a56: Add manpage for keybld by Thorsten Alteholz
[linux-libre-firmware.git] / usbdux / usbduxfast_firmware.asm
1 ;   usbduxfast_firmware.asm
2 ;   Copyright (C) 2004,2009 Bernd Porr, Bernd.Porr@f2s.com
3 ;
4 ;   This program is free software; you can redistribute it and/or modify
5 ;   it under the terms of the GNU General Public License as published by
6 ;   the Free Software Foundation; either version 2 of the License, or
7 ;   (at your option) any later version.
8 ;
9 ;   This program is distributed in the hope that it will be useful,
10 ;   but WITHOUT ANY WARRANTY; without even the implied warranty of
11 ;   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
12 ;   GNU General Public License for more details.
13 ;
14 ;   You should have received a copy of the GNU General Public License
15 ;   along with this program; if not, write to the Free Software
16 ;   Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
17 ;
18 ;
19 ; Firmware: usbduxfast_firmware.asm for usbdux.c
20 ; Description: Firmware for usbduxfast
21 ; Devices: [ITL] USB-DUX (usbdux.o)
22 ; Author: Bernd Porr <Bernd.Porr@f2s.com>
23 ; Updated: 17 Apr 2009
24 ; Status: stable
25 ;
26 ;;;
27 ;;;
28 ;;;
29
30         .inc    fx2-include.asm
31
32         .equ    WFLOADED,70H    ; waveform is loaded
33
34         .org    0000h           ; after reset the processor starts here
35         ljmp    main            ; jump to the main loop
36
37         .org    0043h           ; the IRQ2-vector
38         ljmp    jmptbl          ; irq service-routine
39
40         .org    0100h           ; start of the jump table
41
42 jmptbl: ljmp    sudav_isr
43         nop
44         ljmp    sof_isr
45         nop
46         ljmp    sutok_isr
47         nop
48         ljmp    suspend_isr
49         nop
50         ljmp    usbreset_isr
51         nop
52         ljmp    hispeed_isr
53         nop
54         ljmp    ep0ack_isr
55         nop
56         ljmp    spare_isr
57         nop
58         ljmp    ep0in_isr
59         nop
60         ljmp    ep0out_isr
61         nop
62         ljmp    ep1in_isr
63         nop
64         ljmp    ep1out_isr
65         nop
66         ljmp    ep2_isr
67         nop
68         ljmp    ep4_isr
69         nop
70         ljmp    ep6_isr
71         nop
72         ljmp    ep8_isr
73         nop
74         ljmp    ibn_isr
75         nop
76         ljmp    spare_isr
77         nop
78         ljmp    ep0ping_isr
79         nop
80         ljmp    ep1ping_isr
81         nop
82         ljmp    ep2ping_isr
83         nop
84         ljmp    ep4ping_isr
85         nop
86         ljmp    ep6ping_isr
87         nop
88         ljmp    ep8ping_isr
89         nop
90         ljmp    errlimit_isr
91         nop
92         ljmp    spare_isr
93         nop
94         ljmp    spare_isr
95         nop
96         ljmp    spare_isr
97         nop
98         ljmp    ep2isoerr_isr
99         nop
100         ljmp    ep4isoerr_isr
101         nop
102         ljmp    ep6isoerr_isr
103         nop
104         ljmp    ep8isoerr_isr
105
106         
107         ;; dummy isr
108 sof_isr:
109 sudav_isr:      
110 sutok_isr:      
111 suspend_isr:    
112 usbreset_isr:   
113 hispeed_isr:    
114 ep0ack_isr:     
115 spare_isr:      
116 ep0in_isr:      
117 ep0out_isr:     
118 ep1out_isr:
119 ep1in_isr:      
120 ibn_isr:        
121 ep0ping_isr:    
122 ep1ping_isr:    
123 ep2ping_isr:    
124 ep4ping_isr:    
125 ep6ping_isr:    
126 ep8ping_isr:    
127 errlimit_isr:   
128 ep2isoerr_isr:  
129 ep4isoerr_isr:  
130 ep6isoerr_isr:  
131 ep8isoerr_isr:
132 ep6_isr:
133 ep2_isr:
134 ep8_isr:
135
136         push    dps
137         push    dpl
138         push    dph
139         push    dpl1
140         push    dph1
141         push    acc
142         push    psw
143
144         ;; clear the USB2 irq bit and return
145         mov     a,EXIF
146         clr     acc.4
147         mov     EXIF,a
148
149         pop     psw
150         pop     acc 
151         pop     dph1 
152         pop     dpl1
153         pop     dph 
154         pop     dpl 
155         pop     dps
156         
157         reti
158
159                 
160 ;;; main program
161 ;;; basically only initialises the processor and
162 ;;; then engages in an endless loop
163 main:
164         mov     dptr,#REVCTL
165         mov     a,#00000011b    ; allows skip
166         lcall   syncdelaywr
167
168         mov     DPTR,#CPUCS     ; CPU control register
169         mov     a,#00010000b    ; 48Mhz
170         lcall   syncdelaywr
171
172         mov     dptr,#IFCONFIG  ; switch on IFCLK signal
173         mov     a,#10100010b    ; gpif, 30MHz
174         lcall   syncdelaywr
175
176         mov     dptr,#FIFORESET
177         mov     a,#80h
178         lcall   syncdelaywr
179         mov     a,#8
180         lcall   syncdelaywr
181         mov     a,#2            
182         lcall   syncdelaywr
183         mov     a,#4            
184         lcall   syncdelaywr
185         mov     a,#6            
186         lcall   syncdelaywr
187         mov     a,#0            
188         lcall   syncdelaywr
189
190         mov     dptr,#INTSETUP  ; IRQ setup register
191         mov     a,#08h          ; enable autovector
192         lcall   syncdelaywr
193
194         lcall   initeps         ; init the isochronous data-transfer
195
196         lcall   initGPIF
197
198 ;;; main loop
199
200 mloop2:
201         lcall   gpif_run
202         sjmp    mloop2          ; do nothing. The rest is done by the IRQs
203
204
205 gpif_run:
206         mov     a,WFLOADED
207         jz      no_trig         ; do not trigger
208         mov     a,GPIFTRIG      ; GPIF status
209         anl     a,#80h          ; done bit
210         jz      no_trig         ; GPIF busy
211
212 ;;; gpif has stopped
213         mov     a,#06h          ; RD,EP6
214         mov     GPIFTRIG,a
215 no_trig:
216         ret
217
218         
219
220 initGPIF:
221         mov     DPTR,#EP6CFG    ; BLK data from here to the host
222         mov     a,#11100000b    ; Valid, quad buffering
223         lcall   syncdelaywr     ; write
224
225         mov     dptr,#EP6FIFOCFG
226         mov     a,#00001001b    ; autoin, wordwide
227         lcall   syncdelaywr
228
229         mov     dptr,#EP6AUTOINLENH
230         mov     a,#00000010b    ; 512 bytes
231         lcall   syncdelaywr     ; write
232
233         mov     dptr,#EP6AUTOINLENL
234         mov     a,#00000000b    ; 0
235         lcall   syncdelaywr     ; write
236
237         mov     dptr,#GPIFWFSELECT
238         mov     a,#11111100b    ; waveform 0 for FIFO RD
239         lcall   syncdelaywr
240
241         mov     dptr,#GPIFCTLCFG
242         mov     a,#10000000b    ; tri state for CTRL
243         lcall   syncdelaywr
244
245         mov     dptr,#GPIFIDLECTL
246         mov     a,#11111111b    ; all CTL outputs high
247         lcall   syncdelaywr
248         mov     a,#11111101b    ; reset counter
249         lcall   syncdelaywr
250         mov     a,#11111111b    ; reset to high again
251         lcall   syncdelaywr
252
253         mov     a,#00000010b    ; abort when full
254         mov     dptr,#EP6GPIFFLGSEL
255         lcall   syncdelaywr
256
257         mov     a,#00000001b    ; stop when buffer overfl
258         mov     dptr,#EP6GPIFPDFSTOP
259         lcall   syncdelaywr
260
261         mov     a,#0
262         mov     dptr,#GPIFREADYCFG
263         lcall   syncdelaywr
264
265         mov     a,#0
266         mov     dptr,#GPIFIDLECS
267         lcall   syncdelaywr
268
269 ; waveform 1
270 ; this is a dummy waveform which is used
271 ; during the upload of another waveform into
272 ; wavefrom 0
273 ; it branches directly into the IDLE state
274         mov     dptr,#0E420H
275         mov     a,#00111111b    ; branch to IDLE
276         lcall   syncdelaywr
277
278         mov     dptr,#0E428H    ; opcode
279         mov     a,#00000001b    ; deceision point
280         lcall   syncdelaywr
281
282         mov     dptr,#0E430H
283         mov     a,#0FFH         ; output is high
284         lcall   syncdelaywr
285
286         mov     dptr,#0E438H
287         mov     a,#0FFH         ; logic function
288         lcall   syncdelaywr
289
290 ; signals that no waveform 0 is loaded so far
291         mov     WFLOADED,#0     ; waveform flag
292
293         ret
294
295
296
297 ;;; initilise the transfer
298 ;;; It is assumed that the USB interface is in alternate setting 1
299 initeps:
300         mov     DPTR,#EP4CFG
301         mov     a,#10100000b    ; valid, bulk, out
302         lcall   syncdelaywr
303
304         mov     dptr,#EP4BCL    ; "arm" it
305         mov     a,#00h
306         lcall   syncdelaywr     ; wait until we can write again
307         lcall   syncdelaywr     ; wait
308         lcall   syncdelaywr     ; wait
309
310         mov     DPTR,#EP8CFG
311         mov     a,#0            ; disable EP8, it overlaps with EP6!!
312         lcall   syncdelaywr
313
314         mov     dptr,#EPIE      ; interrupt enable
315         mov     a,#00100000b    ; enable irq for ep4
316         lcall   syncdelaywr     ; do it
317
318         mov     dptr,#EPIRQ     ; clear IRQs
319         mov     a,#00100100b
320         movx    @dptr,a
321
322         mov     DPTR,#USBIE     ; USB int enable register
323         mov     a,#0            ; SOF etc
324         movx    @DPTR,a         ;
325
326         mov     DPTR,#GPIFIE    ; GPIF int enable register
327         mov     a,#0            ; done IRQ
328         movx    @DPTR,a         ;
329
330         mov     EIE,#00000001b  ; enable INT2 in the 8051's SFR
331         mov     IE,#80h         ; IE, enable all interrupts
332
333         ret
334
335
336 ;;; interrupt-routine for ep4
337 ;;; receives the channel list and other commands
338 ep4_isr:
339         push    dps
340         push    dpl
341         push    dph
342         push    dpl1
343         push    dph1
344         push    acc
345         push    psw
346         push    00h             ; R0
347         push    01h             ; R1
348         push    02h             ; R2
349         push    03h             ; R3
350         push    04h             ; R4
351         push    05h             ; R5
352         push    06h             ; R6
353         push    07h             ; R7
354                 
355         mov     dptr,#0f400h    ; FIFO buffer of EP4
356         movx    a,@dptr         ; get the first byte
357
358         mov     dptr,#ep4_jmp   ; jump table for the different functions
359         rl      a               ; multiply by 2: sizeof sjmp
360         jmp     @a+dptr         ; jump to the jump table
361
362 ep4_jmp:
363         sjmp    storewaveform   ; a=0
364         sjmp    init_ep6        ; a=1
365         
366 init_ep6:
367         ; stop ep6
368         ; just now do nothing
369
370         ljmp    over_wf
371
372
373 storewaveform:
374         mov     WFLOADED,#0     ; waveform flag
375
376         mov     dptr,#EP6FIFOCFG
377         mov     a,#00000000b    ;
378         lcall   syncdelaywr
379
380         mov     dptr,#GPIFABORT
381         mov     a,#0ffh         ; abort all transfers
382         lcall   syncdelaywr
383
384 wait_f_abort:
385         mov     a,GPIFTRIG      ; GPIF status
386         anl     a,#80h          ; done bit
387         jz      wait_f_abort    ; GPIF busy
388
389         mov     dptr,#GPIFWFSELECT
390         mov     a,#11111101b    ; select dummy waveform
391         movx    @dptr,a
392         lcall   syncdelay
393
394         mov     dptr,#FIFORESET
395         mov     a,#80h          ; NAK
396         lcall   syncdelaywr
397         mov     a,#6            ; reset EP6
398         lcall   syncdelaywr
399         mov     a,#0            ; normal op
400         lcall   syncdelaywr
401
402 ; change to dummy waveform 1
403         mov     a,#06h          ; RD,EP6
404         mov     GPIFTRIG,a
405
406 ; wait a bit
407         mov     r2,255
408 loopx:
409         djnz    r2,loopx
410
411 ; abort waveform if not already so
412         mov     dptr,#GPIFABORT
413         mov     a,#0ffh         ; abort all transfers
414         lcall   syncdelaywr
415
416 ; wait again
417         mov     r2,255
418 loopx2:
419         djnz    r2,loopx2
420
421 ; check for DONE
422 wait_f_abort2:
423         mov     a,GPIFTRIG      ; GPIF status
424         anl     a,#80h          ; done bit
425         jz      wait_f_abort2   ; GPIF busy
426
427 ; upload the new waveform into waveform 0
428         mov     AUTOPTRH2,#0E4H ; XDATA0H
429         lcall   syncdelay
430         mov     AUTOPTRL2,#00H  ; XDATA0L
431         lcall   syncdelay
432
433         mov     AUTOPTRH1,#0F4H ; EP4 high
434         lcall   syncdelay
435         mov     AUTOPTRL1,#01H  ; EP4 low
436         lcall   syncdelay
437
438         mov     AUTOPTRSETUP,#7 ; autoinc and enable
439         lcall   syncdelay
440
441         mov     r2,#20H         ; 32 bytes to transfer
442
443 wavetr:
444         mov     dptr,#XAUTODAT1
445         movx    a,@dptr
446         lcall   syncdelay
447         mov     dptr,#XAUTODAT2
448         movx    @dptr,a
449         lcall   syncdelay
450         djnz    r2,wavetr
451
452         mov     dptr,#EP6FIFOCFG
453         mov     a,#00001001b    ; autoin, wordwide
454         lcall   syncdelaywr
455
456         mov     dptr,#GPIFWFSELECT
457         mov     a,#11111100b
458         movx    @dptr,a
459         lcall   syncdelay
460
461         mov     dptr,#FIFORESET
462         mov     a,#80h          ; NAK
463         lcall   syncdelaywr
464         mov     a,#6            ; reset EP6
465         lcall   syncdelaywr
466         mov     a,#0            ; normal op
467         lcall   syncdelaywr
468
469         mov     dptr,#0E400H+10H; waveform 0: first CTL byte
470         movx    a,@dptr         ; get it
471         orl     a,#11111011b    ; force all bits to one except the range bit
472         mov     dptr,#GPIFIDLECTL
473         lcall   syncdelaywr
474
475         mov     WFLOADED,#1     ; waveform flag
476
477 ; do the common things here     
478 over_wf:        
479         mov     dptr,#EP4BCL
480         mov     a,#00h
481         movx    @DPTR,a         ; arm it
482         lcall   syncdelay       ; wait
483         movx    @DPTR,a         ; arm it
484         lcall   syncdelay       ; wait
485
486         ;; clear INT2
487         mov     a,EXIF          ; FIRST clear the USB (INT2) interrupt request
488         clr     acc.4
489         mov     EXIF,a          ; Note: EXIF reg is not 8051 bit-addressable
490
491         mov     DPTR,#EPIRQ     ; 
492         mov     a,#00100000b    ; clear the ep4irq
493         movx    @DPTR,a
494
495         pop     07h
496         pop     06h
497         pop     05h
498         pop     04h             ; R4
499         pop     03h             ; R3
500         pop     02h             ; R2
501         pop     01h             ; R1
502         pop     00h             ; R0
503         pop     psw
504         pop     acc 
505         pop     dph1 
506         pop     dpl1
507         pop     dph 
508         pop     dpl 
509         pop     dps
510         reti
511
512
513 ;; need to delay every time the byte counters
514 ;; for the EPs have been changed.
515
516 syncdelay:
517         nop
518         nop
519         nop
520         nop
521         nop
522         nop
523         nop
524         nop
525         nop
526         ret
527
528
529 syncdelaywr:
530         lcall   syncdelay
531         movx    @dptr,a
532         ret
533
534
535 .End
536
537
538
539
540
541
542
543
544
545
546
547