e9aa88bd3258b5bfc475f169886ed05df6b54c80
[comedilib.git] / etc / hotplug / usb / usbdux / usbdux_firmware.asm
1 ;   usbdux_firmware.asm
2 ;   Copyright (C) 2004 Bernd Porr, Bernd.Porr@cn.stir.ac.uk
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: usbdux_firmware.asm for usbdux.c
20 ; Description: University of Stirling USB DAQ & INCITE Technology Limited
21 ; Devices: [ITL] USB-DUX (usbdux.o)
22 ; Author: Bernd Porr <Bernd.Porr@cn.stir.ac.uk>
23 ; Updated: 25 Jan 2004
24 ; Status: testing
25 ;
26 ;;;
27 ;;;
28 ;;;
29
30         .inc    fx2-include.asm
31
32         .equ    CHANNELLIST,80h ; channellist in indirect memory
33         
34         .equ    DIOFLAG,90h     ; flag if next IN transf is DIO
35                 
36         .org    0000h           ; after reset the processor starts here
37         ljmp    main            ; jump to the main loop
38
39         .org    0043h           ; the IRQ2-vector
40         ljmp    jmptbl          ; irq service-routine
41         
42         .org    0100h           ; start of the jump table
43
44 jmptbl: ljmp    sudav_isr
45         nop
46         ljmp    sof_isr
47         nop
48         ljmp    sutok_isr
49         nop
50         ljmp    suspend_isr
51         nop
52         ljmp    usbreset_isr
53         nop
54         ljmp    hispeed_isr
55         nop
56         ljmp    ep0ack_isr
57         nop
58         ljmp    spare_isr
59         nop
60         ljmp    ep0in_isr
61         nop
62         ljmp    ep0out_isr
63         nop
64         ljmp    ep1in_isr
65         nop
66         ljmp    ep1out_isr
67         nop
68         ljmp    ep2_isr
69         nop
70         ljmp    ep4_isr
71         nop
72         ljmp    ep6_isr
73         nop
74         ljmp    ep8_isr
75         nop
76         ljmp    ibn_isr
77         nop
78         ljmp    spare_isr
79         nop
80         ljmp    ep0ping_isr
81         nop
82         ljmp    ep1ping_isr
83         nop
84         ljmp    ep2ping_isr
85         nop
86         ljmp    ep4ping_isr
87         nop
88         ljmp    ep6ping_isr
89         nop
90         ljmp    ep8ping_isr
91         nop
92         ljmp    errlimit_isr
93         nop
94         ljmp    spare_isr
95         nop
96         ljmp    spare_isr
97         nop
98         ljmp    spare_isr
99         nop
100         ljmp    ep2isoerr_isr
101         nop
102         ljmp    ep4isoerr_isr
103         nop
104         ljmp    ep6isoerr_isr
105         nop
106         ljmp    ep8isoerr_isr
107
108         
109         ;; dummy isr
110 sudav_isr:      
111 sutok_isr:      
112 suspend_isr:    
113 usbreset_isr:   
114 hispeed_isr:    
115 ep0ack_isr:     
116 spare_isr:      
117 ep0in_isr:      
118 ep0out_isr:     
119 ep1in_isr:      
120 ep1out_isr:     
121 ibn_isr:        
122 ep0ping_isr:    
123 ep1ping_isr:    
124 ep2ping_isr:    
125 ep4ping_isr:    
126 ep6ping_isr:    
127 ep8ping_isr:    
128 errlimit_isr:   
129 ep2isoerr_isr:  
130 ep4isoerr_isr:  
131 ep6isoerr_isr:  
132 ep8isoerr_isr:
133 ep6_isr:
134 ep2_isr:
135
136
137         push    dps
138         push    dpl
139         push    dph
140         push    dpl1
141         push    dph1
142         push    acc
143         push    psw
144
145         ;; clear the USB2 irq bit and return
146         mov     a,EXIF
147         clr     acc.4
148         mov     EXIF,a
149
150         pop     psw
151         pop     acc 
152         pop     dph1 
153         pop     dpl1
154         pop     dph 
155         pop     dpl 
156         pop     dps
157         
158         reti
159
160                 
161 ;;; main program
162 ;;; basically only initialises the processor and
163 ;;; then engages in an endless loop
164 main:
165         mov     DPTR,#CPUCS     ; CPU control register
166         mov     a,#00010000b    ; 48Mhz
167         movx    @DPTR,a         ; do it
168         lcall   syncdelay
169
170         mov     dptr,#INTSETUP  ; IRQ setup register
171         mov     a,#08h          ; enable autovector
172         movx    @DPTR,a         ; do it
173         lcall   syncdelay
174
175         lcall   initAD          ; init the ports to the converters
176
177         lcall   initeps         ; init the isochronous data-transfer
178
179 mloop2: nop
180         nop
181         nop
182         nop
183         nop
184         nop
185         nop
186
187         sjmp    mloop2          ; do nothing. The rest is done by the IRQs
188
189
190 ;;; initialise the ports for the AD-converter
191 initAD:
192         mov     OEA,#27H        ;PortA0,A1,A2,A5 Outputs
193         mov     IOA,#22H        ;/CS = 1, disable transfers to the converters
194         ret
195
196
197
198
199 ;;; from here it's only IRQ handling...
200         
201 ;;; A/D-conversion:
202 ;;; control-byte in a,
203 ;;; result in r3(low) and r4(high)
204 ;;; this routine is optimised for speed
205 readAD:                         ; mask the control byte
206         anl     a,#01111100b    ; only the channel, gain+pol are left
207         orl     a,#10000001b    ; start bit, external clock
208         ;; set CS to low
209         clr     IOA.1           ; set /CS to zero
210         ;; send the control byte to the AD-converter
211         mov     R2,#8           ; bit-counter
212 bitlp:  jnb     ACC.7,bitzero   ; jump if Bit7 = 0?
213         setb    IOA.2           ; set the DIN bit
214         sjmp    clock           ; continue with the clock
215 bitzero:clr     IOA.2           ; clear the DIN bit
216 clock:  setb    IOA.0           ; SCLK = 1
217         clr     IOA.0           ; SCLK = 0
218         rl      a               ; next Bit
219         djnz    R2,bitlp
220
221         ;; continue the aquisition (already started)
222         clr     IOA.2           ; clear the DIN bit
223         mov     R2,#5           ; five steps for the aquision
224 clockaq:setb    IOA.0           ; SCLK = 1
225         clr     IOA.0           ; SCLK = 0
226         djnz    R2,clockaq      ; loop
227         
228         ;; read highbyte from the A/D-converter
229         ;; and do the conversion
230         mov     r4,#0           ; Highbyte goes into R4
231         mov     R2,#4           ; COUNTER 4 data bits in the MSB
232         mov     r5,#08h         ; create bit-mask
233 gethi:                          ; loop get the 8 highest bits from MSB downw
234         setb    IOA.0           ; SCLK = 1
235         clr     IOA.0           ; SCLK = 0
236         mov     a,IOA           ; from port A
237         jnb     ACC.4,zerob     ; the in-bit is zero
238         mov     a,r4            ; get the byte
239         orl     a,r5            ; or the bit to the result
240         mov     r4,a            ; save it again in r4
241 zerob:  mov     a,r5            ; get r5 in order to shift the mask
242         rr      a               ; rotate right
243         mov     r5,a            ; back to r5
244         djnz    R2,gethi
245         ;; read the lowbyte from the A/D-converter
246         mov     r3,#0           ; Lowbyte goes into R3
247         mov     r2,#8           ; COUNTER 8 data-bits in the LSB
248         mov     r5,#80h         ; create bit-mask
249 getlo:                          ; loop get the 8 highest bits from MSB downw
250         setb    IOA.0           ; SCLK = 1
251         clr     IOA.0           ; SCLK = 0
252         mov     a,IOA           ; from port A
253         jnb     ACC.4,zerob2    ; the in-bit is zero
254         mov     a,r3            ; get the result-byte
255         orl     a,r5            ; or the bit to the result
256         mov     r3,a            ; save it again in r4
257 zerob2: mov     a,r5            ; get r5 in order to shift the mask
258         rr      a               ; rotate right
259         mov     r5,a            ; back to r5
260         djnz    R2,getlo
261         setb    IOA.1           ; set /CS to one
262         ;;
263         ret
264         
265
266         
267 ;;; aquires data from all 8 channels and stores it in the EP6 buffer
268 convlo: ;;
269         mov     AUTOPTRH1,#0F8H ; EP6
270         mov     AUTOPTRL1,#00H
271         mov     AUTOPTRSETUP,#7
272         mov     r0,#CHANNELLIST ; points to the channellist
273         mov     a,@r0           ;Ch0
274         lcall   readAD
275         mov     a,R3            ;
276         mov     DPTR,#XAUTODAT1
277         movx    @DPTR,A
278         mov     a,R4            ;
279         movx    @DPTR,A
280
281         inc     r0              ; next channel
282         mov     a,@r0           ;Ch1
283         lcall   readAD
284         mov     a,R3            ;
285         mov     DPTR,#XAUTODAT1
286         movx    @DPTR,A
287         mov     a,R4            ;
288         movx    @DPTR,A
289
290         inc     r0
291         mov     a,@r0           ;Ch2
292         lcall   readAD
293         mov     a,R3            ;
294         mov     DPTR,#XAUTODAT1
295         movx    @DPTR,A
296         mov     a,R4            ;
297         movx    @DPTR,A
298
299         inc     r0
300         mov     a,@r0           ;Ch3
301         lcall   readAD
302         mov     a,R3            ;
303         mov     DPTR,#XAUTODAT1
304         movx    @DPTR,A
305         mov     a,R4            ;
306         movx    @DPTR,A
307
308         inc     r0
309         mov     a,@r0           ;Ch4
310         lcall   readAD
311         mov     a,R3            ;
312         mov     DPTR,#XAUTODAT1
313         movx    @DPTR,A
314         mov     a,R4            ;
315         movx    @DPTR,A
316
317         inc     r0
318         mov     a,@r0           ;Ch5
319         lcall   readAD
320         mov     a,R3            ;
321         mov     DPTR,#XAUTODAT1
322         movx    @DPTR,A
323         mov     a,R4            ;
324         movx    @DPTR,A
325
326         inc     r0
327         mov     a,@r0           ;Ch6
328         lcall   readAD
329         mov     a,R3            ;
330         mov     DPTR,#XAUTODAT1
331         movx    @DPTR,A
332         mov     a,R4            ;
333         movx    @DPTR,A
334
335         inc     r0
336         mov     a,@r0           ;Ch7
337         lcall   readAD
338         mov     a,R3            ;
339         mov     DPTR,#XAUTODAT1
340         movx    @DPTR,A
341         mov     a,R4            ;
342         movx    @DPTR,A
343         ret
344
345
346
347
348 ;;; initilise the transfer
349 ;;; It is assumed that the USB interface is in alternate setting 3
350 initeps:
351         mov     dptr,#FIFORESET
352         mov     a,#0fh          
353         movx    @dptr,a         ; reset all fifos
354         mov     a,#00h          
355         movx    @dptr,a         ; normal operat
356         
357         mov     DPTR,#EP2CFG
358         mov     a,#10010010b    ; valid, out, double buff, iso
359         movx    @DPTR,a
360
361         mov     dptr,#EP2FIFOCFG
362         mov     a,#00000000b    ; manual
363         movx    @dptr,a
364
365         mov     dptr,#EP2BCL    ; "arm" it
366         mov     a,#80h
367         movx    @DPTR,a         ; can receive data
368         lcall   syncdelay       ; wait to sync
369         movx    @DPTR,a         ; can receive data
370         lcall   syncdelay       ; wait to sync
371         movx    @DPTR,a         ; can receive data
372         lcall   syncdelay       ; wait to sync
373         
374         mov     DPTR,#EP4CFG
375         mov     a,#10100000b    ; valid
376         movx    @dptr,a
377
378         mov     dptr,#EP4FIFOCFG
379         mov     a,#00000000b    ; manual
380         movx    @dptr,a
381
382         mov     dptr,#EP4BCL    ; "arm" it
383         mov     a,#80h
384         movx    @DPTR,a         ; can receive data
385         lcall   syncdelay       ; wait until we can write again
386         movx    @dptr,a         ; make shure its really empty
387         lcall   syncdelay       ; wait
388
389         mov     DPTR,#EP6CFG    ; ISO data from here to the host
390         mov     a,#11010010b    ; Valid
391         movx    @DPTR,a         ; ISO transfer, double buffering
392
393         mov     DPTR,#EP8CFG    ; EP8
394         mov     a,#11100000b    ; BULK data from here to the host
395         movx    @DPTR,a         ;
396
397         mov     dptr,#EPIE      ; interrupt enable
398         mov     a,#10100000b    ; enable irq for ep4,8
399         movx    @dptr,a         ; do it
400
401         mov     dptr,#EPIRQ     ; clear IRQs
402         mov     a,#10100000b
403         movx    @dptr,a
404
405         ;; enable interrups
406         mov     DPTR,#USBIE     ; USB int enables register
407         mov     a,#2            ; enables SOF (1ms/125us interrupt)
408         movx    @DPTR,a         ; 
409
410         mov     EIE,#00000001b  ; enable INT2 in the 8051's SFR
411         mov     IE,#80h         ; IE, enable all interrupts
412
413         lcall   ep8_arm         ; 
414         
415         ret
416
417
418 ;;; interrupt-routine for SOF
419 ;;; is for full speed
420 sof_isr:
421         push    dps
422         push    dpl
423         push    dph
424         push    dpl1
425         push    dph1
426         push    acc
427         push    psw
428         push    00h             ; R0
429         push    01h             ; R1
430         push    02h             ; R2
431         push    03h             ; R3
432         push    04h             ; R4
433         push    05h             ; R5
434         push    06h             ; R6
435         push    07h             ; R7
436                 
437         mov     a,EP2468STAT
438         anl     a,#20H          ; full?
439         jnz     epfull          ; EP6-buffer is full
440
441         lcall   convlo          ; conversion
442
443         mov     DPTR,#EP6BCH    ; byte count H
444         mov     a,#0            ; is zero
445         movx    @DPTR,a
446         lcall   syncdelay       ; wait until we can write again
447         
448         mov     DPTR,#EP6BCL    ; byte count L
449         mov     a,#10H          ; is 8x word = 16 bytes
450         movx    @DPTR,a
451         lcall   syncdelay       ; wait until we can write again
452         
453 epfull:
454         ;; do the D/A conversion
455         mov     a,EP2468STAT
456         anl     a,#01H          ; empty
457         jnz     epempty         ; nothing to get
458
459         mov     dptr,#0F000H    ; EP2 fifo buffer
460         lcall   dalo            ; conversion
461
462         mov     dptr,#EP2BCL    ; "arm" it
463         mov     a,#80h
464         movx    @DPTR,a         ; can receive data
465         lcall   syncdelay       ; wait for the rec to sync
466         movx    @dptr,a         ; just to make sure that it's empty
467         lcall   syncdelay       ; wait for the rec to sync
468
469 epempty:        
470         ;; clear INT2
471         mov     a,EXIF          ; FIRST clear the USB (INT2) interrupt request
472         clr     acc.4
473         mov     EXIF,a          ; Note: EXIF reg is not 8051 bit-addressable
474         
475         mov     DPTR,#USBIRQ    ; points to the SOF
476         mov     a,#2            ; clear the SOF
477         movx    @DPTR,a
478
479 nosof:  
480         pop     07h
481         pop     06h
482         pop     05h
483         pop     04h             ; R4
484         pop     03h             ; R3
485         pop     02h             ; R2
486         pop     01h             ; R1
487         pop     00h             ; R0
488         pop     psw
489         pop     acc 
490         pop     dph1 
491         pop     dpl1
492         pop     dph 
493         pop     dpl 
494         pop     dps
495         reti
496
497
498
499
500
501 ;;; interrupt-routine for ep4
502 ;;; receives the channel list and other commands
503 ep4_isr:
504         push    dps
505         push    dpl
506         push    dph
507         push    dpl1
508         push    dph1
509         push    acc
510         push    psw
511         push    00h             ; R0
512         push    01h             ; R1
513         push    02h             ; R2
514         push    03h             ; R3
515         push    04h             ; R4
516         push    05h             ; R5
517         push    06h             ; R6
518         push    07h             ; R7
519                 
520         mov     dptr,#0f400h    ; FIFO buffer of EP4
521         movx    a,@dptr         ; get the first byte
522
523         mov     dptr,#ep4_jmp   ; jump table for the different functions
524         rl      a               ; multiply by 2: sizeof sjmp
525         jmp     @a+dptr         ; jump to the jump table
526 ep4_jmp:
527         sjmp    storechannellist; a=0
528         sjmp    single_da       ; a=1
529         sjmp    config_digital_b; a=2
530         sjmp    write_digital_b ; a=3
531
532
533 ;;; Channellist:        
534 ;;; the first byte is zero:
535 ;;; we've just received the channel list
536 ;;; the channel list is stored in the addresses from 80H which
537 ;;; are _only_ reachable by indirect addressing
538 storechannellist:
539         mov     r0,#CHANNELLIST ; the conversion bytes are now stored in 80h
540         mov     r2,#8           ; counter
541         mov     dptr,#0f401h    ; FIFO buffer of EP4
542 chanlloop:      
543         movx    a,@dptr         ; 
544         mov     @r0,a
545         inc     dptr
546         inc     r0
547         djnz    r2,chanlloop
548         clr     a               ; announce analogue transaction
549         mov     r0,#DIOFLAG     ; pointer to the command byte
550         mov     @r0,a           ; set the command byte
551         sjmp    over_da
552
553 ;;; Single DA conversion. The 2 bytes are in the FIFO buffer
554 single_da:
555         mov     dptr,#0f401h    ; FIFO buffer of EP4
556         lcall   dalo            ; conversion
557         sjmp    over_da
558
559 ;;; configure the port B
560 config_digital_b:
561         mov     dptr,#0f401h    ; FIFO buffer of EP4
562         movx    a,@dptr         ; get the second byte
563         mov     OEB,a           ; set the output enable bits
564         sjmp    over_da
565         
566 ;;; Write one byte to the external digital port B
567 ;;; and prepare for digital read
568 write_digital_b:
569         mov     dptr,#0f401h    ; FIFO buffer of EP4
570         movx    a,@dptr         ; get the second byte
571         mov     OEB,a           ; output enable
572         inc     dptr            ; next byte
573         movx    a,@dptr         ; bits
574         mov     IOB,a           ; send the byte to the I/O port
575         mov     a,#0ffh         ; announce DIO transaction
576         mov     r0,#DIOFLAG     ; pointer to the command byte
577         mov     @r0,a           ; set the command byte
578         sjmp    over_da
579
580 ;;; more things here to come...
581         
582 over_da:        
583         mov     dptr,#EP4BCL
584         mov     a,#80h
585         movx    @DPTR,a         ; arm it
586         lcall   syncdelay       ; wait
587         movx    @DPTR,a         ; arm it
588         lcall   syncdelay       ; wait
589         movx    @DPTR,a         ; arm it
590         lcall   syncdelay       ; wait
591
592         ;; clear INT2
593         mov     a,EXIF          ; FIRST clear the USB (INT2) interrupt request
594         clr     acc.4
595         mov     EXIF,a          ; Note: EXIF reg is not 8051 bit-addressable
596
597         mov     DPTR,#EPIRQ     ; 
598         mov     a,#00100000b    ; clear the ep4irq
599         movx    @DPTR,a
600
601         pop     07h
602         pop     06h
603         pop     05h
604         pop     04h             ; R4
605         pop     03h             ; R3
606         pop     02h             ; R2
607         pop     01h             ; R1
608         pop     00h             ; R0
609         pop     psw
610         pop     acc 
611         pop     dph1 
612         pop     dpl1
613         pop     dph 
614         pop     dpl 
615         pop     dps
616         reti
617
618
619         
620 ;;; all channels
621 dalo:
622         movx    a,@dptr         ; number of channels
623         inc     dptr            ; pointer to the first channel
624         mov     r0,a            ; 4 channels
625 nextDA: 
626         movx    a,@dptr         ; get the first low byte
627         mov     r3,a            ; store in r3 (see below)
628         inc     dptr            ; point to the high byte
629         movx    a,@dptr         ; get the high byte
630         mov     r4,a            ; store in r4 (for writeDA)
631         inc     dptr            ; point to the channel number
632         movx    a,@dptr         ; get the channel number
633         inc     dptr            ; get ready for the next channel
634         lcall   writeDA         ; write value to the DAC
635         djnz    r0,nextDA       ; next channel
636         ret
637
638
639
640 ;;; D/A-conversion:
641 ;;; control-byte in a,
642 ;;; value in r3(low) and r4(high)
643 writeDA:                        ; mask the control byte
644         anl     a,#11000000b    ; only the channel is left
645         orl     a,#00110000b    ; internal clock, bipolar mode, +/-5V
646         orl     a,r4            ; or the value of R4 to it
647         ;; set CS to low
648         clr     IOA.5           ; set /CS to zero
649         ;; send the first byte to the DA-converter
650         mov     R2,#8           ; bit-counter
651 DA1:    jnb     ACC.7,zeroda    ; jump if Bit7 = 0?
652         setb    IOA.2           ; set the DIN bit
653         sjmp    clkda           ; continue with the clock
654 zeroda: clr     IOA.2           ; clear the DIN bit
655 clkda:  setb    IOA.0           ; SCLK = 1
656         clr     IOA.0           ; SCLK = 0
657         rl      a               ; next Bit
658         djnz    R2,DA1
659
660         
661         ;; send the second byte to the DA-converter
662         mov     a,r3            ; low byte
663         mov     R2,#8           ; bit-counter
664 DA2:    jnb     ACC.7,zeroda2   ; jump if Bit7 = 0?
665         setb    IOA.2           ; set the DIN bit
666         sjmp    clkda2          ; continue with the clock
667 zeroda2:clr     IOA.2           ; clear the DIN bit
668 clkda2: setb    IOA.0           ; SCLK = 1
669         clr     IOA.0           ; SCLK = 0
670         rl      a               ; next Bit
671         djnz    R2,DA2
672         ;; 
673         setb    IOA.5           ; set /CS to one
674         ;; 
675 noDA:   ret
676         
677
678
679 ;;; arm ep6
680 ep6_arm:
681         lcall   convlo
682         
683         mov     DPTR,#EP6BCH    ; byte count H
684         mov     a,#0            ; is zero
685         movx    @DPTR,a
686         lcall   syncdelay       ; wait until the length has arrived
687         
688         mov     DPTR,#EP6BCL    ; byte count L
689         mov     a,#10H          ; is one
690         movx    @DPTR,a
691         lcall   syncdelay       ; wait until the length has been proc
692         ret
693         
694
695
696 ;;; converts one analog/digital channel and stores it in EP8
697 ;;; also gets the content of the digital ports B and D
698 ep8_adc:
699         mov     r0,#DIOFLAG     ; pointer to the DIO flag
700         mov     a,@r0           ; get the flag
701         jnz     ep8_dio         ; nonzero means DIO
702
703         mov     r0,#CHANNELLIST ; points to the channellist
704         mov     a,@r0           ; Ch0
705         
706         lcall   readAD          ; start the conversion
707                 
708         mov     DPTR,#0fc00h    ; EP8 FIFO 
709         mov     a,R3            ; get low byte
710         movx    @DPTR,A         ; store in FIFO
711         inc     dptr            ; next fifo entry
712         mov     a,R4            ; get high byte
713         movx    @DPTR,A         ; store in FIFO
714
715         sjmp    ep8_send        ; send the data
716
717 ep8_dio:        
718         mov     DPTR,#0fc00h    ; store the contents of port B
719         mov     a,IOB           ; in the next
720         movx    @dptr,a         ; entry of the buffer
721
722         inc     dptr
723         clr     a               ; high byte is zero
724         movx    @dptr,a         ; next byte of the EP
725         
726 ep8_send:       
727         mov     DPTR,#EP8BCH    ; byte count H
728         mov     a,#0            ; is zero
729         movx    @DPTR,a
730         
731         mov     DPTR,#EP8BCL    ; byte count L
732         mov     a,#10H          ; 16 bytes
733         movx    @DPTR,a         ; send the data over to the host
734         ret
735
736
737         
738 ;;; arms EP8 with one byte. This signals the Linux driver that
739 ;;; the EP has been armed only with a dummy byte to make the
740 ;;; IRQ work. The byte is not processed by the driver.
741 ep8_arm:        
742         mov     DPTR,#EP8BCH    ; byte count H
743         mov     a,#0            ; is zero
744         movx    @DPTR,a
745         
746         mov     DPTR,#EP8BCL    ; byte count L
747         mov     a,#1            ; 1 byte
748         movx    @DPTR,a
749         ret     
750
751
752
753 ;;; EP8 interrupt: gets one measurement from the AD converter and
754 ;;; sends it via EP8. The channel # is stored in address 80H.
755 ;;; It also gets the state of the digital registers B and D.
756 ep8_isr:        
757         push    dps
758         push    dpl
759         push    dph
760         push    dpl1
761         push    dph1
762         push    acc
763         push    psw
764         push    00h             ; R0
765         push    01h             ; R1
766         push    02h             ; R2
767         push    03h             ; R3
768         push    04h             ; R4
769         push    05h             ; R5
770         push    06h             ; R6
771         push    07h             ; R7
772                 
773         lcall   ep8_adc
774         
775         ;; clear INT2
776         mov     a,EXIF          ; FIRST clear the USB (INT2) interrupt request
777         clr     acc.4
778         mov     EXIF,a          ; Note: EXIF reg is not 8051 bit-addressable
779
780         mov     DPTR,#EPIRQ     ; 
781         mov     a,#10000000b    ; clear the ep8irq
782         movx    @DPTR,a
783
784         pop     07h
785         pop     06h
786         pop     05h
787         pop     04h             ; R4
788         pop     03h             ; R3
789         pop     02h             ; R2
790         pop     01h             ; R1
791         pop     00h             ; R0
792         pop     psw
793         pop     acc 
794         pop     dph1 
795         pop     dpl1
796         pop     dph 
797         pop     dpl 
798         pop     dps
799         reti
800
801
802 ;; need to delay every time the byte counters
803 ;; for the EPs have been changed.
804
805 syncdelay:
806         nop
807         nop
808         nop
809         nop
810         ret
811
812
813 .End
814
815