--- /dev/null
+; usbdux_firmware.asm
+; Copyright (C) 2003 Bernd Porr, Bernd.Porr@cn.stir.ac.uk
+;
+; This program is free software; you can redistribute it and/or modify
+; it under the terms of the GNU General Public License as published by
+; the Free Software Foundation; either version 2 of the License, or
+; (at your option) any later version.
+;
+; This program is distributed in the hope that it will be useful,
+; but WITHOUT ANY WARRANTY; without even the implied warranty of
+; MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+; GNU General Public License for more details.
+;
+; You should have received a copy of the GNU General Public License
+; along with this program; if not, write to the Free Software
+; Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
+;
+;
+; Firmware: usbdux_firmware.asm for usbdux.c
+; Description: University of Stirling USB DAQ & INCITE Technology Limited
+; Devices: [ITL] USB-DUX (usbdux.o)
+; Author: Bernd Porr <Bernd.Porr@cn.stir.ac.uk>
+; Updated: Thu Oct 16
+; Status: testing
+;
+;;;
+;;;
+;;;
+
+ .inc fx2-include.asm
+
+ .equ CHANNELLIST,80h ; channellist in indirect memory
+
+ .equ DIOFLAG,90h ; flag if next IN transf is DIO
+
+ .org 0000h ; after reset the processor starts here
+ ljmp main ; jump to the main loop
+
+ .org 0043h ; the IRQ2-vector
+ ljmp jmptbl ; irq service-routine
+
+ .org 0100h ; start of the jump table
+
+jmptbl: ljmp sudav_isr
+ nop
+ ljmp sof_isr
+ nop
+ ljmp sutok_isr
+ nop
+ ljmp suspend_isr
+ nop
+ ljmp usbreset_isr
+ nop
+ ljmp hispeed_isr
+ nop
+ ljmp ep0ack_isr
+ nop
+ ljmp spare_isr
+ nop
+ ljmp ep0in_isr
+ nop
+ ljmp ep0out_isr
+ nop
+ ljmp ep1in_isr
+ nop
+ ljmp ep1out_isr
+ nop
+ ljmp ep2_isr
+ nop
+ ljmp ep4_isr
+ nop
+ ljmp ep6_isr
+ nop
+ ljmp ep8_isr
+ nop
+ ljmp ibn_isr
+ nop
+ ljmp spare_isr
+ nop
+ ljmp ep0ping_isr
+ nop
+ ljmp ep1ping_isr
+ nop
+ ljmp ep2ping_isr
+ nop
+ ljmp ep4ping_isr
+ nop
+ ljmp ep6ping_isr
+ nop
+ ljmp ep8ping_isr
+ nop
+ ljmp errlimit_isr
+ nop
+ ljmp spare_isr
+ nop
+ ljmp spare_isr
+ nop
+ ljmp spare_isr
+ nop
+ ljmp ep2isoerr_isr
+ nop
+ ljmp ep4isoerr_isr
+ nop
+ ljmp ep6isoerr_isr
+ nop
+ ljmp ep8isoerr_isr
+
+
+ ;; dummy isr
+sudav_isr:
+sutok_isr:
+suspend_isr:
+usbreset_isr:
+hispeed_isr:
+ep0ack_isr:
+spare_isr:
+ep0in_isr:
+ep0out_isr:
+ep1in_isr:
+ep1out_isr:
+ibn_isr:
+ep0ping_isr:
+ep1ping_isr:
+ep2ping_isr:
+ep4ping_isr:
+ep6ping_isr:
+ep8ping_isr:
+errlimit_isr:
+ep2isoerr_isr:
+ep4isoerr_isr:
+ep6isoerr_isr:
+ep8isoerr_isr:
+
+ push dps
+ push dpl
+ push dph
+ push dpl1
+ push dph1
+ push acc
+ push psw
+
+ ;; clear the USB2 irq bit and return
+ mov a,EXIF
+ clr acc.4
+ mov EXIF,a
+
+ pop psw
+ pop acc
+ pop dph1
+ pop dpl1
+ pop dph
+ pop dpl
+ pop dps
+
+ reti
+
+
+;;; main program
+;;; basically only initialises the processor and
+;;; then engages in an endless loop
+main:
+ mov DPTR,#CPUCS ; CPU control register
+ mov a,#000010100b ; 48MHz clock
+ movx @DPTR,a ; do it
+
+ mov dptr,#INTSETUP ; IRQ setup register
+ mov a,#08h ; enable autovector
+ movx @DPTR,a ; do it
+
+ lcall initAD ; init the ports to the converters
+
+ mov dptr,#USBCS ; USB status
+ movx a,@dptr ; get it
+ anl a,#80H ; mask out high speed
+
+ jnz inihi ; high speed
+
+ lcall inieplo ; init the isochronous data-transfer
+ sjmp mloop2
+inihi:
+ lcall iniephi ; init the irq transfer
+
+mloop2: nop
+
+ sjmp mloop2 ; do nothing. The rest is done by the IRQs
+
+
+;;; initialise the ports for the AD-converter
+initAD:
+ mov OEA,#27H ;PortA0,A1,A2,A5 Outputs
+ mov IOA,#22H ;/CS = 1, disable transfers to the converters
+ ret
+
+
+
+
+;;; from here it's only IRQ handling...
+
+;;; A/D-conversion:
+;;; control-byte in a,
+;;; result in r3(low) and r4(high)
+;;; this routine is optimised for speed
+readAD: ; mask the control byte
+ anl a,#01111100b ; only the channel, gain+pol are left
+ orl a,#10000001b ; start bit, external clock
+ ;; set CS to low
+ clr IOA.1 ; set /CS to zero
+ ;; send the control byte to the AD-converter
+ mov R2,#8 ; bit-counter
+S1: jnb ACC.7,bitzero ; jump if Bit7 = 0?
+ setb IOA.2 ; set the DIN bit
+ sjmp clock ; continue with the clock
+bitzero:clr IOA.2 ; clear the DIN bit
+clock: setb IOA.0 ; SCLK = 1
+ clr IOA.0 ; SCLK = 0
+ rl a ; next Bit
+ djnz R2,S1
+
+ ;; continue the aquisition (already started)
+ clr IOA.2 ; clear the DIN bit
+ mov R2,#5 ; five steps for the aquision
+clockaq:setb IOA.0 ; SCLK = 1
+ clr IOA.0 ; SCLK = 0
+ djnz R2,clockaq ; loop
+
+ ;; read highbyte from the A/D-converter
+ ;; and do the conversion
+ mov r4,#0 ; Highbyte goes into R4
+ mov R2,#4 ; COUNTER 4 data bits in the MSB
+ mov r5,#08h ; create bit-mask
+gethi: ; loop get the 8 highest bits from MSB downw
+ setb IOA.0 ; SCLK = 1
+ clr IOA.0 ; SCLK = 0
+ mov a,IOA ; from port A
+ jnb ACC.4,zerob ; the in-bit is zero
+ mov a,r4 ; get the byte
+ orl a,r5 ; or the bit to the result
+ mov r4,a ; save it again in r4
+zerob: mov a,r5 ; get r5 in order to shift the mask
+ rr a ; rotate right
+ mov r5,a ; back to r5
+ djnz R2,gethi
+ ;; read the lowbyte from the A/D-converter
+ mov r3,#0 ; Lowbyte goes into R3
+ mov r2,#8 ; COUNTER 8 data-bits in the LSB
+ mov r5,#80h ; create bit-mask
+getlo: ; loop get the 8 highest bits from MSB downw
+ setb IOA.0 ; SCLK = 1
+ clr IOA.0 ; SCLK = 0
+ mov a,IOA ; from port A
+ jnb ACC.4,zerob2 ; the in-bit is zero
+ mov a,r3 ; get the result-byte
+ orl a,r5 ; or the bit to the result
+ mov r3,a ; save it again in r4
+zerob2: mov a,r5 ; get r5 in order to shift the mask
+ rr a ; rotate right
+ mov r5,a ; back to r5
+ djnz R2,getlo
+ setb IOA.1 ; set /CS to one
+ ;;
+ ret
+
+
+
+;;; aquires data from all 8 channels and stores it in the EP6 buffer
+convlo: ;;
+ mov AUTOPTRH1,#0F8H ; EP6
+ mov AUTOPTRL1,#00H
+ mov AUTOPTRSETUP,#7
+ mov r0,#CHANNELLIST ; points to the channellist
+ mov a,@r0 ;Ch0
+ lcall readAD
+ mov a,R3 ;
+ mov DPTR,#XAUTODAT1
+ movx @DPTR,A
+ mov a,R4 ;
+ movx @DPTR,A
+
+ inc r0 ; next channel
+ mov a,@r0 ;Ch1
+ lcall readAD
+ mov a,R3 ;
+ mov DPTR,#XAUTODAT1
+ movx @DPTR,A
+ mov a,R4 ;
+ movx @DPTR,A
+
+ inc r0
+ mov a,@r0 ;Ch2
+ lcall readAD
+ mov a,R3 ;
+ mov DPTR,#XAUTODAT1
+ movx @DPTR,A
+ mov a,R4 ;
+ movx @DPTR,A
+
+ inc r0
+ mov a,@r0 ;Ch3
+ lcall readAD
+ mov a,R3 ;
+ mov DPTR,#XAUTODAT1
+ movx @DPTR,A
+ mov a,R4 ;
+ movx @DPTR,A
+
+ inc r0
+ mov a,@r0 ;Ch4
+ lcall readAD
+ mov a,R3 ;
+ mov DPTR,#XAUTODAT1
+ movx @DPTR,A
+ mov a,R4 ;
+ movx @DPTR,A
+
+ inc r0
+ mov a,@r0 ;Ch5
+ lcall readAD
+ mov a,R3 ;
+ mov DPTR,#XAUTODAT1
+ movx @DPTR,A
+ mov a,R4 ;
+ movx @DPTR,A
+
+ inc r0
+ mov a,@r0 ;Ch6
+ lcall readAD
+ mov a,R3 ;
+ mov DPTR,#XAUTODAT1
+ movx @DPTR,A
+ mov a,R4 ;
+ movx @DPTR,A
+
+ inc r0
+ mov a,@r0 ;Ch7
+ lcall readAD
+ mov a,R3 ;
+ mov DPTR,#XAUTODAT1
+ movx @DPTR,A
+ mov a,R4 ;
+ movx @DPTR,A
+ ret
+
+
+
+
+;;; initilise the transfer for full speed
+;;; It is assumed that the USB interface is in alternate setting 3
+inieplo:
+ mov dptr,#FIFORESET
+ mov a,#0fh
+ movx @dptr,a ; reset all fifos
+ mov a,#00h
+ movx @dptr,a ; normal operat
+
+ mov DPTR,#EP2CFG
+ mov a,#10010010b ; valid, out, double buff, iso
+ movx @DPTR,a
+
+ mov dptr,#EP2FIFOCFG
+ mov a,#00000000b ; manual
+ movx @dptr,a
+
+ mov dptr,#EP2BCL ; "arm" it
+ mov a,#80h
+ movx @DPTR,a ; can receive data
+ movx @DPTR,a ; can receive data
+ movx @DPTR,a ; can receive data
+
+ mov DPTR,#EP4CFG
+ mov a,#10100000b ; valid
+ movx @dptr,a
+
+ mov dptr,#EP4FIFOCFG
+ mov a,#00000000b ; manual
+ movx @dptr,a
+
+ mov dptr,#EP4BCL ; "arm" it
+ mov a,#80h
+ movx @DPTR,a ; can receive data
+ movx @dptr,a ; make shure its really empty
+
+ mov DPTR,#EP6CFG ; ISO data from here to the host
+ mov a,#11010010b ; Valid
+ movx @DPTR,a ; ISO transfer, double buffering
+
+ mov DPTR,#EP8CFG ; EP8
+ mov a,#11100000b ; BULK data from here to the host
+ movx @DPTR,a ;
+
+ mov dptr,#EPIE ; interrupt enable
+ mov a,#10100000b ; enable irq for ep4,8
+ movx @dptr,a ; do it
+
+ mov dptr,#EPIRQ ; clear IRQs
+ mov a,#10100000b
+ movx @dptr,a
+
+ ;; enable interrups
+ mov DPTR,#USBIE ; USB int enables register
+ mov a,#2 ; enables SOF (1ms/125us interrupt)
+ movx @DPTR,a ;
+
+ mov EIE,#00000001b ; enable INT2 in the 8051's SFR
+ mov IE,#80h ; IE, enable all interrupts
+
+ lcall ep8_arm ;
+
+ ret
+
+
+;;; initilise the IRQ transfer
+iniephi:
+ mov dptr,#FIFORESET
+ mov a,#0fh
+ movx @dptr,a ; reset all fifos
+ mov a,#00h
+ movx @dptr,a ; normal operat
+
+ mov DPTR,#EP2CFG
+ mov a,#10110010b ; valid, out, double buff, irq
+ movx @DPTR,a
+
+ mov dptr,#EP2FIFOCFG
+ mov a,#00000000b ; manual
+ movx @dptr,a
+
+ mov dptr,#EP2BCL ; "arm" it
+ mov a,#80h
+ movx @DPTR,a ; can receive data
+ movx @DPTR,a ; can receive data
+ movx @DPTR,a ; can receive data
+
+ mov DPTR,#EP4CFG
+ mov a,#10100000b ; valid
+ movx @dptr,a
+
+ mov dptr,#EP4FIFOCFG
+ mov a,#00000000b ; manual
+ movx @dptr,a
+
+ mov dptr,#EP4BCL ; "arm" it
+ mov a,#80h
+ movx @DPTR,a ; can receive data
+ movx @dptr,a ; make shure its really empty
+
+ mov DPTR,#EP6CFG ; IRQ data from here to the host
+ mov a,#11110010b ; Valid
+ movx @DPTR,a ; IRQ transfer, double buffering
+
+ mov DPTR,#EP8CFG ; EP8
+ mov a,#11100000b ; BULK data from here to the host
+ movx @DPTR,a ;
+
+ mov dptr,#EPIE ; interrupt enable
+ mov a,#11110000b ; enable irq for ep2,ep4,ep6,ep8
+ movx @dptr,a ; do it
+
+ mov dptr,#EPIRQ
+ mov a,#11110000b ; clear irq bits
+ movx @dptr,a
+
+ ;; enable interrups
+ mov DPTR,#USBIE ; USB int enables register
+ mov a,#0 ; disables SOF (1ms/125ms interrupt)
+ movx @DPTR,a ;
+
+ mov EIE,#00000001b ; enable INT2 in the 8051's SFR
+ mov IE,#80h ; IE, enable all interrupts
+
+ lcall ep8_arm ; put dummy data into ep8
+ lcall ep6_arm ; put dummy data into ep6
+
+ ret
+
+
+
+;;; interrupt-routine for SOF
+;;; is for full speed
+sof_isr:
+ push dps
+ push dpl
+ push dph
+ push dpl1
+ push dph1
+ push acc
+ push psw
+ push 00h ; R0
+ push 01h ; R1
+ push 02h ; R2
+ push 03h ; R3
+ push 04h ; R4
+ push 05h ; R5
+ push 06h ; R6
+ push 07h ; R7
+
+ mov dptr,#USBCS ; USB status
+ movx a,@dptr ; get it
+ anl a,#80H ; mask out high speed
+
+ jnz hispeed ; do nothing here
+
+ mov a,EP2468STAT
+ anl a,#20H ; full?
+ jnz epfull ; EP6-buffer is full
+
+ lcall convlo ; conversion
+
+ mov DPTR,#EP6BCH ; byte count H
+ mov a,#0 ; is zero
+ movx @DPTR,a
+
+ mov DPTR,#EP6BCL ; byte count L
+ mov a,#10H ; is 8x word = 16 bytes
+ movx @DPTR,a
+
+epfull:
+ ;; do the D/A conversion
+ mov a,EP2468STAT
+ anl a,#01H ; empty
+ jnz epempty ; nothing to get
+
+ mov dptr,#0F000H ; EP2 fifo buffer
+ lcall dalo ; conversion
+
+ mov dptr,#EP2BCL ; "arm" it
+ mov a,#80h
+ movx @DPTR,a ; can receive data
+ movx @dptr,a
+
+hispeed:
+epempty:
+ ;; clear INT2
+ mov a,EXIF ; FIRST clear the USB (INT2) interrupt request
+ clr acc.4
+ mov EXIF,a ; Note: EXIF reg is not 8051 bit-addressable
+
+ mov DPTR,#USBIRQ ; points to the SOF
+ mov a,#2 ; clear the SOF
+ movx @DPTR,a
+
+nosof:
+ pop 07h
+ pop 06h
+ pop 05h
+ pop 04h ; R4
+ pop 03h ; R3
+ pop 02h ; R2
+ pop 01h ; R1
+ pop 00h ; R0
+ pop psw
+ pop acc
+ pop dph1
+ pop dpl1
+ pop dph
+ pop dpl
+ pop dps
+ reti
+
+
+
+
+
+;;; interrupt-routine for ep4
+;;; receives the channel list and other commands
+ep4_isr:
+ push dps
+ push dpl
+ push dph
+ push dpl1
+ push dph1
+ push acc
+ push psw
+ push 00h ; R0
+ push 01h ; R1
+ push 02h ; R2
+ push 03h ; R3
+ push 04h ; R4
+ push 05h ; R5
+ push 06h ; R6
+ push 07h ; R7
+
+ mov dptr,#0f400h ; FIFO buffer of EP4
+ movx a,@dptr ; get the first byte
+
+ mov dptr,#ep4_jmp ; jump table for the different functions
+ rl a ; multiply by 2: sizeof sjmp
+ jmp @a+dptr ; jump to the jump table
+ep4_jmp:
+ sjmp storechannellist; a=0
+ sjmp single_da ; a=1
+ sjmp config_digital_b; a=2
+ sjmp write_digital_b ; a=3
+
+
+;;; Channellist:
+;;; the first byte is zero:
+;;; we've just received the channel list
+;;; the channel list is stored in the addresses from 80H which
+;;; are _only_ reachable by indirect addressing
+storechannellist:
+ mov r0,#CHANNELLIST ; the conversion bytes are now stored in 80h
+ mov r2,#8 ; counter
+ mov dptr,#0f401h ; FIFO buffer of EP4
+chanlloop:
+ movx a,@dptr ;
+ mov @r0,a
+ inc dptr
+ inc r0
+ djnz r2,chanlloop
+ clr a ; announce analogue transaction
+ mov r0,#DIOFLAG ; pointer to the command byte
+ mov @r0,a ; set the command byte
+ sjmp over_da
+
+;;; Single DA conversion. The 2 bytes are in the FIFO buffer
+single_da:
+ mov dptr,#0f401h ; FIFO buffer of EP4
+ lcall dalo ; conversion
+ sjmp over_da
+
+;;; configure the port B
+config_digital_b:
+ mov dptr,#0f401h ; FIFO buffer of EP4
+ movx a,@dptr ; get the second byte
+ mov OEB,a ; set the output enable bits
+ sjmp over_da
+
+;;; Write one byte to the external digital port B
+;;; and prepare for digital read
+write_digital_b:
+ mov dptr,#0f401h ; FIFO buffer of EP4
+ movx a,@dptr ; get the second byte
+ mov OEB,a ; output enable
+ inc dptr ; next byte
+ movx a,@dptr ; bits
+ mov IOB,a ; send the byte to the I/O port
+ mov a,#0ffh ; announce DIO transaction
+ mov r0,#DIOFLAG ; pointer to the command byte
+ mov @r0,a ; set the command byte
+ sjmp over_da
+
+;;; more things here to come...
+
+over_da:
+ mov dptr,#EP4BCL
+ mov a,#80h
+ movx @DPTR,a ; arm it
+ movx @DPTR,a ; arm it
+ movx @DPTR,a ; arm it
+
+ ;; clear INT2
+ mov a,EXIF ; FIRST clear the USB (INT2) interrupt request
+ clr acc.4
+ mov EXIF,a ; Note: EXIF reg is not 8051 bit-addressable
+
+ mov DPTR,#EPIRQ ;
+ mov a,#00100000b ; clear the ep4irq
+ movx @DPTR,a
+
+ pop 07h
+ pop 06h
+ pop 05h
+ pop 04h ; R4
+ pop 03h ; R3
+ pop 02h ; R2
+ pop 01h ; R1
+ pop 00h ; R0
+ pop psw
+ pop acc
+ pop dph1
+ pop dpl1
+ pop dph
+ pop dpl
+ pop dps
+ reti
+
+
+
+;;; all channels
+dalo:
+ movx a,@dptr ; number of channels
+ inc dptr ; pointer to the first channel
+ mov r0,a ; 4 channels
+nextDA:
+ movx a,@dptr ; get the first low byte
+ mov r3,a ; store in r3 (see below)
+ inc dptr ; point to the high byte
+ movx a,@dptr ; get the high byte
+ mov r4,a ; store in r4 (for writeDA)
+ inc dptr ; point to the channel number
+ movx a,@dptr ; get the channel number
+ inc dptr ; get ready for the next channel
+ lcall writeDA ; write value to the DAC
+ djnz r0,nextDA ; next channel
+ ret
+
+
+
+;;; D/A-conversion:
+;;; control-byte in a,
+;;; value in r3(low) and r4(high)
+writeDA: ; mask the control byte
+ anl a,#11000000b ; only the channel is left
+ orl a,#00110000b ; internal clock, bipolar mode, +/-5V
+ orl a,r4 ; or the value of R4 to it
+ ;; set CS to low
+ clr IOA.5 ; set /CS to zero
+ ;; send the first byte to the DA-converter
+ mov R2,#8 ; bit-counter
+DA1: jnb ACC.7,zeroda ; jump if Bit7 = 0?
+ setb IOA.2 ; set the DIN bit
+ sjmp clkda ; continue with the clock
+zeroda: clr IOA.2 ; clear the DIN bit
+clkda: setb IOA.0 ; SCLK = 1
+ clr IOA.0 ; SCLK = 0
+ rl a ; next Bit
+ djnz R2,DA1
+
+
+ ;; send the second byte to the DA-converter
+ mov a,r3 ; low byte
+ mov R2,#8 ; bit-counter
+DA2: jnb ACC.7,zeroda2 ; jump if Bit7 = 0?
+ setb IOA.2 ; set the DIN bit
+ sjmp clkda2 ; continue with the clock
+zeroda2:clr IOA.2 ; clear the DIN bit
+clkda2: setb IOA.0 ; SCLK = 1
+ clr IOA.0 ; SCLK = 0
+ rl a ; next Bit
+ djnz R2,DA2
+ ;;
+ setb IOA.5 ; set /CS to one
+ ;;
+noDA: ret
+
+
+
+;;; arm ep6
+ep6_arm:
+ lcall convlo
+
+ mov DPTR,#EP6BCH ; byte count H
+ mov a,#0 ; is zero
+ movx @DPTR,a
+
+ mov DPTR,#EP6BCL ; byte count L
+ mov a,#10H ; is one
+ movx @DPTR,a
+ ret
+
+
+
+;;; get all 8 channels in the high speed mode
+ep6_isr:
+ push dps
+ push dpl
+ push dph
+ push dpl1
+ push dph1
+ push acc
+ push psw
+ push 00h ; R0
+ push 01h ; R1
+ push 02h ; R2
+ push 03h ; R3
+ push 04h ; R4
+ push 05h ; R5
+ push 06h ; R6
+ push 07h ; R7
+
+ lcall convlo ; conversion
+
+ mov DPTR,#EP6BCH ; byte count H
+ mov a,#0 ; is zero
+ movx @DPTR,a
+
+ mov DPTR,#EP6BCL ; byte count L
+ mov a,#10H ; is 8x word = 16 bytes
+ movx @DPTR,a
+
+ ;; clear INT2
+ mov a,EXIF ; FIRST clear the USB (INT2) interrupt request
+ clr acc.4
+ mov EXIF,a ; Note: EXIF reg is not 8051 bit-addressable
+
+ mov DPTR,#EPIRQ ;
+ mov a,#01000000b ; clear the ep6irq
+ movx @DPTR,a
+
+ pop 07h
+ pop 06h
+ pop 05h
+ pop 04h ; R4
+ pop 03h ; R3
+ pop 02h ; R2
+ pop 01h ; R1
+ pop 00h ; R0
+ pop psw
+ pop acc
+ pop dph1
+ pop dpl1
+ pop dph
+ pop dpl
+ pop dps
+ reti
+
+
+
+;;; converts one analog/digital channel and stores it in EP8
+;;; also gets the content of the digital ports B and D
+ep8_adc:
+ mov r0,#DIOFLAG ; pointer to the DIO flag
+ mov a,@r0 ; get the flag
+ jnz ep8_dio ; nonzero means DIO
+
+ mov r0,#CHANNELLIST ; points to the channellist
+ mov a,@r0 ; Ch0
+
+ lcall readAD ; start the conversion
+
+ mov DPTR,#0fc00h ; EP8 FIFO
+ mov a,R3 ; get low byte
+ movx @DPTR,A ; store in FIFO
+ inc dptr ; next fifo entry
+ mov a,R4 ; get high byte
+ movx @DPTR,A ; store in FIFO
+
+ sjmp ep8_send ; send the data
+
+ep8_dio:
+ mov DPTR,#0fc00h ; store the contents of port B
+ mov a,IOB ; in the next
+ movx @dptr,a ; entry of the buffer
+
+ inc dptr
+ clr a ; high byte is zero
+ movx @dptr,a ; next byte of the EP
+
+ep8_send:
+ mov DPTR,#EP8BCH ; byte count H
+ mov a,#0 ; is zero
+ movx @DPTR,a
+
+ mov DPTR,#EP8BCL ; byte count L
+ mov a,#10H ; 16 bytes
+ movx @DPTR,a ; send the data over to the host
+ ret
+
+
+
+;;; arms EP8 with one byte. This signals the Linux driver that
+;;; the EP has been armed only with a dummy byte to make the
+;;; IRQ work. The byte is not processed by the driver.
+ep8_arm:
+ mov DPTR,#EP8BCH ; byte count H
+ mov a,#0 ; is zero
+ movx @DPTR,a
+
+ mov DPTR,#EP8BCL ; byte count L
+ mov a,#1 ; 1 byte
+ movx @DPTR,a
+ ret
+
+
+
+;;; EP8 interrupt: gets one measurement from the AD converter and
+;;; sends it via EP8. The channel # is stored in address 80H.
+;;; It also gets the state of the digital registers B and D.
+ep8_isr:
+ push dps
+ push dpl
+ push dph
+ push dpl1
+ push dph1
+ push acc
+ push psw
+ push 00h ; R0
+ push 01h ; R1
+ push 02h ; R2
+ push 03h ; R3
+ push 04h ; R4
+ push 05h ; R5
+ push 06h ; R6
+ push 07h ; R7
+
+ lcall ep8_adc
+
+ ;; clear INT2
+ mov a,EXIF ; FIRST clear the USB (INT2) interrupt request
+ clr acc.4
+ mov EXIF,a ; Note: EXIF reg is not 8051 bit-addressable
+
+ mov DPTR,#EPIRQ ;
+ mov a,#10000000b ; clear the ep8irq
+ movx @DPTR,a
+
+ pop 07h
+ pop 06h
+ pop 05h
+ pop 04h ; R4
+ pop 03h ; R3
+ pop 02h ; R2
+ pop 01h ; R1
+ pop 00h ; R0
+ pop psw
+ pop acc
+ pop dph1
+ pop dpl1
+ pop dph
+ pop dpl
+ pop dps
+ reti
+
+
+
+
+
+
+;;; high speed mode, IRQ mode. Asynchronous transmission.
+ep2_isr:
+ push dps
+ push dpl
+ push dph
+ push dpl1
+ push dph1
+ push acc
+ push psw
+ push 00h ; R0
+ push 01h ; R1
+ push 02h ; R2
+ push 03h ; R3
+ push 04h ; R4
+ push 05h ; R5
+ push 06h ; R6
+ push 07h ; R7
+
+ mov dptr,#0F000H ; EP2 fifo buffer
+ lcall dalo ; conversion
+
+ mov dptr,#EP2BCL ; "arm" it
+ mov a,#80h
+ movx @DPTR,a ; can receive data
+ movx @dptr,a
+
+ ;; clear INT2
+ mov a,EXIF ; FIRST clear the USB (INT2) interrupt request
+ clr acc.4
+ mov EXIF,a ; Note: EXIF reg is not 8051 bit-addressable
+
+ mov DPTR,#EPIRQ ; points to the usbirq
+ mov a,#00010000b ; clear the usbirq of ep 2
+ movx @DPTR,a
+
+ pop 07h
+ pop 06h
+ pop 05h
+ pop 04h ; R4
+ pop 03h ; R3
+ pop 02h ; R2
+ pop 01h ; R1
+ pop 00h ; R0
+ pop psw
+ pop acc
+ pop dph1
+ pop dpl1
+ pop dph
+ pop dpl
+ pop dps
+ reti
+
+
+
+
+
+
+
+
+
+.End
+
+
--- /dev/null
+ ; usbdux_firmware.asm
+ ; Copyright (C) 2003 Bernd Porr, bp1@cn.stir.ac.uk
+ ;
+ ; This program is free software; you can redistribute it a
+ ; it under the terms of the GNU General Public License as
+ ; the Free Software Foundation; either version 2 of the Li
+ ; (at your option) any later version.
+ ;
+ ; This program is distributed in the hope that it will be
+ ; but WITHOUT ANY WARRANTY; without even the implied warra
+ ; MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. Se
+ ; GNU General Public License for more details.
+ ;
+ ; You should have received a copy of the GNU General Publi
+ ; along with this program; if not, write to the Free Softw
+ ; Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA
+ ;
+ ;
+ ; Firmware: usbdux_firmware.asm for usbdux.c
+ ; Description: University of Stirling USB DAQ & INCITE Techn
+ ; Devices: [ITL] USB-DUX (usbdux.o)
+ ; Author: Bernd Porr <Bernd.Porr@cn.stir.ac.uk>
+ ; Updated: Thu Oct 16
+ ; Status: testing
+ ;
+ ;;;
+ ;;;
+ ;;;
+
+ ; rev 0.9
+ ; (c) Bernd Porr, Bernd.Porr@cn.stir.ac.uk
+ ; GPL, GNU public license
+ ;
+ ; This program is free software; you can redistribute it a
+ ; it under the terms of the GNU General Public License as
+ ; the Free Software Foundation; either version 2 of the Li
+ ; (at your option) any later version.
+ ;
+ ; This program is distributed in the hope that it will be
+ ; but WITHOUT ANY WARRANTY; without even the implied warra
+ ; MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. Se
+ ; GNU General Public License for more details.
+ ;
+ ; You should have received a copy of the GNU General Publi
+ ; along with this program; if not, write to the Free Softw
+ ; Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA
+ ;
+ ; In conjunction with the as31.
+ ; Include-file for the FX2 by Cypress. The rest of the regs
+ ; by the as31 itself.
+ ;
+ ; from the TRM of the FX2:
+ ;
+ ;; CPU control
+0000: .equ CPUCS,0E600H
+ ;; interface config
+0000: .equ IFCONFIG,0E601H
+0000: .equ FIFORESET,0E604H
+ ;; Endpoint configs
+0000: .equ EP1OUTCFG,0E610H
+0000: .equ EP1INCFG,0E611H
+0000: .equ EP2CFG,0E612H
+0000: .equ EP4CFG,0E613H
+0000: .equ EP6CFG,0E614H
+0000: .equ EP8CFG,0E615H
+ ;; packets per frame, always one for USB 1.1
+0000: .equ EP2ISOINPKTS,0E640H
+0000: .equ EP4ISOINPKTS,0E641H
+0000: .equ EP6ISOINPKTS,0E642H
+0000: .equ EP8ISOINPKTS,0E643H
+ ;; endpoint byte counts
+0000: .equ EP1OUTBC,0E68DH
+0000: .equ EP2BCH,0E690H
+0000: .equ EP2BCL,0E691H
+0000: .equ EP4BCH,0E694H
+0000: .equ EP4BCL,0E695H
+0000: .equ EP6BCH,0E698H
+0000: .equ EP6BCL,0E699H
+0000: .equ EP8BCH,0E69CH
+0000: .equ EP8BCL,0E69DH
+ ;;
+0000: .equ EP4AUTOINLENH,0E622H
+0000: .equ EP4AUTOINLENL,0E623H
+0000: .equ EP2FIFOCFG,0E618H
+0000: .equ EP4FIFOCFG,0E619H
+0000: .equ EP6FIFOCFG,0E61AH
+0000: .equ EP8FIFOCFG,0E61BH
+ ;;
+0000: .equ INPKTEND,0E648H
+ ;;
+ ;; endpoint control
+0000: .equ EP2CS,0E6A3H
+0000: .equ EP4CS,0E6A4H
+0000: .equ EP6CS,0E6A5H
+0000: .equ EP8CS,0E6A6H
+ ;; endpoint buffers
+0000: .equ EP2FIFOBUF,0F000H
+0000: .equ EP4FIFOBUF,0F400H
+0000: .equ EP6FIFOBUF,0F800H
+0000: .equ EP8FIFOBUF,0FC00H
+ ;; IRQ enable for bulk NAK
+0000: .equ IBNIE,0E658H
+ ;; interrupt requ for NAK
+0000: .equ IBNIRQ,0E659H
+ ;; USB INT enables
+0000: .equ USBIE,0E65CH
+ ;; USB interrupt request
+0000: .equ USBIRQ,0E65DH
+ ;; endpoint IRQ enable
+0000: .equ EPIE,0E65EH
+ ;; endpoint IRQ requests
+0000: .equ EPIRQ,0E65FH
+ ;; USB error IRQ requests
+0000: .equ USBERRIE,0E662H
+ ;; USB error IRQ request
+0000: .equ USBERRIRQ,0E663H
+ ;; USB interrupt 2 autovector
+0000: .equ INT2IVEC,0E666H
+ ;; autovector enable
+0000: .equ INTSETUP,0E668H
+ ;; port cfg
+0000: .equ PORTACFG,0E670H
+0000: .equ PORTCCFG,0E671H
+0000: .equ PORTECFG,0E672H
+ ;; I2C bus
+0000: .equ I2CS,0E678H
+0000: .equ I2DAT,0E679H
+0000: .equ I2CTL,0E67AH
+ ;; auto pointers, read/write is directed to the poi
+0000: .equ XAUTODAT1,0E67BH
+0000: .equ XAUTODAT2,0E67CH
+ ;; USB-control
+0000: .equ USBCS,0E680H
+
+0000: .equ IOA,80H
+0000: .equ DPL1,84H
+0000: .equ DPH1,85H
+0000: .equ DPS,86H
+0000: .equ CKCON,8Eh
+0000: .equ IOB,90H
+0000: .equ EXIF,91h
+0000: .equ MPAGE,92h
+0000: .equ AUTOPTRH1,9AH
+0000: .equ AUTOPTRL1,9BH
+0000: .equ AUTOPTRH2,9DH
+0000: .equ AUTOPTRL2,9EH
+0000: .equ IOC,0A0H
+0000: .equ INT2CLR,0A1H
+0000: .equ INT4CLR,0A2H
+0000: .equ EP2468STAT,0AAH
+0000: .equ EP24FIFOFLGS,0ABH
+0000: .equ EP68FIFOFLGS,0ACH
+0000: .equ AUTOPTRSETUP,0AFH
+0000: .equ IOD,0B0H
+0000: .equ IOE,0B1H
+0000: .equ OEA,0B2H
+0000: .equ OEB,0B3H
+0000: .equ OEC,0B4H
+0000: .equ OED,0B5H
+0000: .equ OEE,0B6H
+0000: .equ EIE,0E8h
+
+
+ ;;; end of file
+
+
+
+0000: .equ CHANNELLIST,80h ; channellist in in
+
+0000: .equ DIOFLAG,90h ; flag if next IN transf is
+
+0000: .org 0000h ; after reset the processor
+0000: 02 01 A2 ljmp main ; jump to the main loop
+
+0043: .org 0043h ; the IRQ2-vector
+0043: 02 01 00 ljmp jmptbl ; irq service-routine
+
+0100: .org 0100h ; start of the jump table
+
+0100: 02 01 7F jmptbl: ljmp sudav_isr
+0103: 00 nop
+0104: 02 03 3C ljmp sof_isr
+0107: 00 nop
+0108: 02 01 7F ljmp sutok_isr
+010B: 00 nop
+010C: 02 01 7F ljmp suspend_isr
+010F: 00 nop
+0110: 02 01 7F ljmp usbreset_isr
+0113: 00 nop
+0114: 02 01 7F ljmp hispeed_isr
+0117: 00 nop
+0118: 02 01 7F ljmp ep0ack_isr
+011B: 00 nop
+011C: 02 01 7F ljmp spare_isr
+011F: 00 nop
+0120: 02 01 7F ljmp ep0in_isr
+0123: 00 nop
+0124: 02 01 7F ljmp ep0out_isr
+0127: 00 nop
+0128: 02 01 7F ljmp ep1in_isr
+012B: 00 nop
+012C: 02 01 7F ljmp ep1out_isr
+012F: 00 nop
+0130: 02 05 77 ljmp ep2_isr
+0133: 00 nop
+0134: 02 03 B5 ljmp ep4_isr
+0137: 00 nop
+0138: 02 04 9B ljmp ep6_isr
+013B: 00 nop
+013C: 02 05 2B ljmp ep8_isr
+013F: 00 nop
+0140: 02 01 7F ljmp ibn_isr
+0143: 00 nop
+0144: 02 01 7F ljmp spare_isr
+0147: 00 nop
+0148: 02 01 7F ljmp ep0ping_isr
+014B: 00 nop
+014C: 02 01 7F ljmp ep1ping_isr
+014F: 00 nop
+0150: 02 01 7F ljmp ep2ping_isr
+0153: 00 nop
+0154: 02 01 7F ljmp ep4ping_isr
+0157: 00 nop
+0158: 02 01 7F ljmp ep6ping_isr
+015B: 00 nop
+015C: 02 01 7F ljmp ep8ping_isr
+015F: 00 nop
+0160: 02 01 7F ljmp errlimit_isr
+0163: 00 nop
+0164: 02 01 7F ljmp spare_isr
+0167: 00 nop
+0168: 02 01 7F ljmp spare_isr
+016B: 00 nop
+016C: 02 01 7F ljmp spare_isr
+016F: 00 nop
+0170: 02 01 7F ljmp ep2isoerr_isr
+0173: 00 nop
+0174: 02 01 7F ljmp ep4isoerr_isr
+0177: 00 nop
+0178: 02 01 7F ljmp ep6isoerr_isr
+017B: 00 nop
+017C: 02 01 7F ljmp ep8isoerr_isr
+
+
+ ;; dummy isr
+ sudav_isr:
+ sutok_isr:
+ suspend_isr:
+ usbreset_isr:
+ hispeed_isr:
+ ep0ack_isr:
+ spare_isr:
+ ep0in_isr:
+ ep0out_isr:
+ ep1in_isr:
+ ep1out_isr:
+ ibn_isr:
+ ep0ping_isr:
+ ep1ping_isr:
+ ep2ping_isr:
+ ep4ping_isr:
+ ep6ping_isr:
+ ep8ping_isr:
+ errlimit_isr:
+ ep2isoerr_isr:
+ ep4isoerr_isr:
+ ep6isoerr_isr:
+ ep8isoerr_isr:
+
+017F: C0 86 push dps
+0181: C0 82 push dpl
+0183: C0 83 push dph
+0185: C0 84 push dpl1
+0187: C0 85 push dph1
+0189: C0 E0 push acc
+018B: C0 D0 push psw
+
+ ;; clear the USB2 irq bit and return
+018D: E5 91 mov a,EXIF
+018F: C2 E4 clr acc.4
+0191: F5 91 mov EXIF,a
+
+0193: D0 D0 pop psw
+0195: D0 E0 pop acc
+0197: D0 85 pop dph1
+0199: D0 84 pop dpl1
+019B: D0 83 pop dph
+019D: D0 82 pop dpl
+019F: D0 86 pop dps
+
+01A1: 32 reti
+
+
+ ;;; main program
+ ;;; basically only initialises the processor and
+ ;;; then engages in an endless loop
+ main:
+01A2: 90 E6 00 mov DPTR,#CPUCS ; CPU control register
+01A5: 74 14 mov a,#000010100b ; 48MHz clock
+01A7: F0 movx @DPTR,a ; do it
+
+01A8: 90 E6 68 mov dptr,#INTSETUP ; IRQ setup register
+01AB: 74 08 mov a,#08h ; enable autovector
+01AD: F0 movx @DPTR,a ; do it
+
+01AE: 12 01 C4 lcall initAD ; init the ports to the con
+
+01B1: 90 E6 80 mov dptr,#USBCS ; USB status
+01B4: E0 movx a,@dptr ; get it
+01B5: 54 80 anl a,#80H ; mask out high speed
+
+01B7: 70 05 jnz inihi ; high speed
+
+01B9: 12 02 89 lcall inieplo ; init the isochron
+01BC: 80 03 sjmp mloop2
+ inihi:
+01BE: 12 02 E1 lcall iniephi ; init the irq tran
+
+01C1: 00 mloop2: nop
+
+01C2: 80 FD sjmp mloop2 ; do nothing. The rest is d
+
+
+ ;;; initialise the ports for the AD-converter
+ initAD:
+01C4: 75 B2 27 mov OEA,#27H ;PortA0,A1,A2,A5 Outputs
+01C7: 75 80 22 mov IOA,#22H ;/CS = 1, disable transfers
+01CA: 22 ret
+
+
+
+
+ ;;; from here it's only IRQ handling...
+
+ ;;; A/D-conversion:
+ ;;; control-byte in a,
+ ;;; result in r3(low) and r4(high)
+ ;;; this routine is optimised for speed
+ readAD: ; mask the control byte
+01CB: 54 7C anl a,#01111100b ; only the channel, gain+po
+01CD: 44 81 orl a,#10000001b ; start bit, external clock
+ ;; set CS to low
+01CF: C2 81 clr IOA.1 ; set /CS to zero
+ ;; send the control byte to the AD-converter
+01D1: 7A 08 mov R2,#8 ; bit-counter
+01D3: 30 E7 04 S1: jnb ACC.7,bitzero ; jump if Bit7 = 0?
+01D6: D2 82 setb IOA.2 ; set the DIN bit
+01D8: 80 02 sjmp clock ; continue with the clock
+01DA: C2 82 bitzero:clr IOA.2 ; clear the DIN bit
+01DC: D2 80 clock: setb IOA.0 ; SCLK = 1
+01DE: C2 80 clr IOA.0 ; SCLK = 0
+01E0: 23 rl a ; next Bit
+01E1: DA F0 djnz R2,S1
+
+ ;; continue the aquisition (already started)
+01E3: C2 82 clr IOA.2 ; clear the DIN bit
+01E5: 7A 05 mov R2,#5 ; five steps for the aquisi
+01E7: D2 80 clockaq:setb IOA.0 ; SCLK = 1
+01E9: C2 80 clr IOA.0 ; SCLK = 0
+01EB: DA FA djnz R2,clockaq ; loop
+
+ ;; read highbyte from the A/D-converter
+ ;; and do the conversion
+01ED: 7C 00 mov r4,#0 ; Highbyte goes into R4
+01EF: 7A 04 mov R2,#4 ; COUNTER 4 data bits in th
+01F1: 7D 08 mov r5,#08h ; create bit-mask
+ gethi: ; loop get the 8 highest bi
+01F3: D2 80 setb IOA.0 ; SCLK = 1
+01F5: C2 80 clr IOA.0 ; SCLK = 0
+01F7: E5 80 mov a,IOA ; from port A
+01F9: 30 E4 03 jnb ACC.4,zerob ; the in-bit is zero
+01FC: EC mov a,r4 ; get the byte
+01FD: 4D orl a,r5 ; or the bit to the result
+01FE: FC mov r4,a ; save it again in r4
+01FF: ED zerob: mov a,r5 ; get r5 in order to shift
+0200: 03 rr a ; rotate right
+0201: FD mov r5,a ; back to r5
+0202: DA EF djnz R2,gethi
+ ;; read the lowbyte from the A/D-converter
+0204: 7B 00 mov r3,#0 ; Lowbyte goes into R3
+0206: 7A 08 mov r2,#8 ; COUNTER 8 data-bits in th
+0208: 7D 80 mov r5,#80h ; create bit-mask
+ getlo: ; loop get the 8 highest bi
+020A: D2 80 setb IOA.0 ; SCLK = 1
+020C: C2 80 clr IOA.0 ; SCLK = 0
+020E: E5 80 mov a,IOA ; from port A
+0210: 30 E4 03 jnb ACC.4,zerob2 ; the in-bit is zero
+0213: EB mov a,r3 ; get the result-byte
+0214: 4D orl a,r5 ; or the bit to the result
+0215: FB mov r3,a ; save it again in r4
+0216: ED zerob2: mov a,r5 ; get r5 in order to shift
+0217: 03 rr a ; rotate right
+0218: FD mov r5,a ; back to r5
+0219: DA EF djnz R2,getlo
+021B: D2 81 setb IOA.1 ; set /CS to one
+ ;;
+021D: 22 ret
+
+
+
+ ;;; aquires data from all 8 channels and stores it in the EP
+ convlo: ;;
+021E: 75 9A F8 mov AUTOPTRH1,#0F8H ; EP6
+0221: 75 9B 00 mov AUTOPTRL1,#00H
+0224: 75 AF 07 mov AUTOPTRSETUP,#7
+0227: 78 80 mov r0,#CHANNELLIST ; points to the cha
+0229: E6 mov a,@r0 ;Ch0
+022A: 12 01 CB lcall readAD
+022D: EB mov a,R3 ;
+022E: 90 E6 7B mov DPTR,#XAUTODAT1
+0231: F0 movx @DPTR,A
+0232: EC mov a,R4 ;
+0233: F0 movx @DPTR,A
+
+0234: 08 inc r0 ; next channel
+0235: E6 mov a,@r0 ;Ch1
+0236: 12 01 CB lcall readAD
+0239: EB mov a,R3 ;
+023A: 90 E6 7B mov DPTR,#XAUTODAT1
+023D: F0 movx @DPTR,A
+023E: EC mov a,R4 ;
+023F: F0 movx @DPTR,A
+
+0240: 08 inc r0
+0241: E6 mov a,@r0 ;Ch2
+0242: 12 01 CB lcall readAD
+0245: EB mov a,R3 ;
+0246: 90 E6 7B mov DPTR,#XAUTODAT1
+0249: F0 movx @DPTR,A
+024A: EC mov a,R4 ;
+024B: F0 movx @DPTR,A
+
+024C: 08 inc r0
+024D: E6 mov a,@r0 ;Ch3
+024E: 12 01 CB lcall readAD
+0251: EB mov a,R3 ;
+0252: 90 E6 7B mov DPTR,#XAUTODAT1
+0255: F0 movx @DPTR,A
+0256: EC mov a,R4 ;
+0257: F0 movx @DPTR,A
+
+0258: 08 inc r0
+0259: E6 mov a,@r0 ;Ch4
+025A: 12 01 CB lcall readAD
+025D: EB mov a,R3 ;
+025E: 90 E6 7B mov DPTR,#XAUTODAT1
+0261: F0 movx @DPTR,A
+0262: EC mov a,R4 ;
+0263: F0 movx @DPTR,A
+
+0264: 08 inc r0
+0265: E6 mov a,@r0 ;Ch5
+0266: 12 01 CB lcall readAD
+0269: EB mov a,R3 ;
+026A: 90 E6 7B mov DPTR,#XAUTODAT1
+026D: F0 movx @DPTR,A
+026E: EC mov a,R4 ;
+026F: F0 movx @DPTR,A
+
+0270: 08 inc r0
+0271: E6 mov a,@r0 ;Ch6
+0272: 12 01 CB lcall readAD
+0275: EB mov a,R3 ;
+0276: 90 E6 7B mov DPTR,#XAUTODAT1
+0279: F0 movx @DPTR,A
+027A: EC mov a,R4 ;
+027B: F0 movx @DPTR,A
+
+027C: 08 inc r0
+027D: E6 mov a,@r0 ;Ch7
+027E: 12 01 CB lcall readAD
+0281: EB mov a,R3 ;
+0282: 90 E6 7B mov DPTR,#XAUTODAT1
+0285: F0 movx @DPTR,A
+0286: EC mov a,R4 ;
+0287: F0 movx @DPTR,A
+0288: 22 ret
+
+
+
+
+ ;;; initilise the transfer for full speed
+ ;;; It is assumed that the USB interface is in alternate set
+ inieplo:
+0289: 90 E6 04 mov dptr,#FIFORESET
+028C: 74 0F mov a,#0fh
+028E: F0 movx @dptr,a ; reset all fifos
+028F: 74 00 mov a,#00h
+0291: F0 movx @dptr,a ; normal operat
+
+0292: 90 E6 12 mov DPTR,#EP2CFG
+0295: 74 92 mov a,#10010010b ; valid, out, double buff,
+0297: F0 movx @DPTR,a
+
+0298: 90 E6 18 mov dptr,#EP2FIFOCFG
+029B: 74 00 mov a,#00000000b ; manual
+029D: F0 movx @dptr,a
+
+029E: 90 E6 91 mov dptr,#EP2BCL ; "arm" it
+02A1: 74 80 mov a,#80h
+02A3: F0 movx @DPTR,a ; can receive data
+02A4: F0 movx @DPTR,a ; can receive data
+02A5: F0 movx @DPTR,a ; can receive data
+
+02A6: 90 E6 13 mov DPTR,#EP4CFG
+02A9: 74 A0 mov a,#10100000b ; valid
+02AB: F0 movx @dptr,a
+
+02AC: 90 E6 19 mov dptr,#EP4FIFOCFG
+02AF: 74 00 mov a,#00000000b ; manual
+02B1: F0 movx @dptr,a
+
+02B2: 90 E6 95 mov dptr,#EP4BCL ; "arm" it
+02B5: 74 80 mov a,#80h
+02B7: F0 movx @DPTR,a ; can receive data
+02B8: F0 movx @dptr,a ; make shure its re
+
+02B9: 90 E6 14 mov DPTR,#EP6CFG ; ISO data from here to the
+02BC: 74 D2 mov a,#11010010b ; Valid
+02BE: F0 movx @DPTR,a ; ISO transfer, dou
+
+02BF: 90 E6 15 mov DPTR,#EP8CFG ; EP8
+02C2: 74 E0 mov a,#11100000b ; BULK data from here to th
+02C4: F0 movx @DPTR,a ;
+
+02C5: 90 E6 5E mov dptr,#EPIE ; interrupt enable
+02C8: 74 A0 mov a,#10100000b ; enable irq for ep4,8
+02CA: F0 movx @dptr,a ; do it
+
+02CB: 90 E6 5F mov dptr,#EPIRQ ; clear IRQs
+02CE: 74 A0 mov a,#10100000b
+02D0: F0 movx @dptr,a
+
+ ;; enable interrups
+02D1: 90 E6 5C mov DPTR,#USBIE ; USB int enables register
+02D4: 74 02 mov a,#2 ; enables SOF (1ms/125us int
+02D6: F0 movx @DPTR,a ;
+
+02D7: 75 E8 01 mov EIE,#00000001b ; enable INT2 in the 8051's
+02DA: 75 A8 80 mov IE,#80h ; IE, enable all in
+
+02DD: 12 05 1E lcall ep8_arm ;
+
+02E0: 22 ret
+
+
+ ;;; initilise the IRQ transfer
+ iniephi:
+02E1: 90 E6 04 mov dptr,#FIFORESET
+02E4: 74 0F mov a,#0fh
+02E6: F0 movx @dptr,a ; reset all fifos
+02E7: 74 00 mov a,#00h
+02E9: F0 movx @dptr,a ; normal operat
+
+02EA: 90 E6 12 mov DPTR,#EP2CFG
+02ED: 74 B2 mov a,#10110010b ; valid, out, double buff,
+02EF: F0 movx @DPTR,a
+
+02F0: 90 E6 18 mov dptr,#EP2FIFOCFG
+02F3: 74 00 mov a,#00000000b ; manual
+02F5: F0 movx @dptr,a
+
+02F6: 90 E6 91 mov dptr,#EP2BCL ; "arm" it
+02F9: 74 80 mov a,#80h
+02FB: F0 movx @DPTR,a ; can receive data
+02FC: F0 movx @DPTR,a ; can receive data
+02FD: F0 movx @DPTR,a ; can receive data
+
+02FE: 90 E6 13 mov DPTR,#EP4CFG
+0301: 74 A0 mov a,#10100000b ; valid
+0303: F0 movx @dptr,a
+
+0304: 90 E6 19 mov dptr,#EP4FIFOCFG
+0307: 74 00 mov a,#00000000b ; manual
+0309: F0 movx @dptr,a
+
+030A: 90 E6 95 mov dptr,#EP4BCL ; "arm" it
+030D: 74 80 mov a,#80h
+030F: F0 movx @DPTR,a ; can receive data
+0310: F0 movx @dptr,a ; make shure its re
+
+0311: 90 E6 14 mov DPTR,#EP6CFG ; IRQ data from here to the
+0314: 74 F2 mov a,#11110010b ; Valid
+0316: F0 movx @DPTR,a ; IRQ transfer, dou
+
+0317: 90 E6 15 mov DPTR,#EP8CFG ; EP8
+031A: 74 E0 mov a,#11100000b ; BULK data from here to th
+031C: F0 movx @DPTR,a ;
+
+031D: 90 E6 5E mov dptr,#EPIE ; interrupt enable
+0320: 74 F0 mov a,#11110000b ; enable irq for ep2,ep4,ep
+0322: F0 movx @dptr,a ; do it
+
+0323: 90 E6 5F mov dptr,#EPIRQ
+0326: 74 F0 mov a,#11110000b ; clear irq bits
+0328: F0 movx @dptr,a
+
+ ;; enable interrups
+0329: 90 E6 5C mov DPTR,#USBIE ; USB int enables register
+032C: 74 00 mov a,#0 ; disables SOF (1ms/125ms in
+032E: F0 movx @DPTR,a ;
+
+032F: 75 E8 01 mov EIE,#00000001b ; enable INT2 in the 8051's
+0332: 75 A8 80 mov IE,#80h ; IE, enable all in
+
+0335: 12 05 1E lcall ep8_arm ; put dummy data in
+0338: 12 04 8B lcall ep6_arm ; put dummy data in
+
+033B: 22 ret
+
+
+
+ ;;; interrupt-routine for SOF
+ ;;; is for full speed
+ sof_isr:
+033C: C0 86 push dps
+033E: C0 82 push dpl
+0340: C0 83 push dph
+0342: C0 84 push dpl1
+0344: C0 85 push dph1
+0346: C0 E0 push acc
+0348: C0 D0 push psw
+034A: C0 00 push 00h ; R0
+034C: C0 01 push 01h ; R1
+034E: C0 02 push 02h ; R2
+0350: C0 03 push 03h ; R3
+0352: C0 04 push 04h ; R4
+0354: C0 05 push 05h ; R5
+0356: C0 06 push 06h ; R6
+0358: C0 07 push 07h ; R7
+
+035A: 90 E6 80 mov dptr,#USBCS ; USB status
+035D: E0 movx a,@dptr ; get it
+035E: 54 80 anl a,#80H ; mask out high speed
+
+0360: 70 28 jnz hispeed ; do nothing here
+
+0362: E5 AA mov a,EP2468STAT
+0364: 54 20 anl a,#20H ; full?
+0366: 70 0F jnz epfull ; EP6-buffer is full
+
+0368: 12 02 1E lcall convlo ; conversion
+
+036B: 90 E6 98 mov DPTR,#EP6BCH ; byte count H
+036E: 74 00 mov a,#0 ; is zero
+0370: F0 movx @DPTR,a
+
+0371: 90 E6 99 mov DPTR,#EP6BCL ; byte count L
+0374: 74 10 mov a,#10H ; is 8x word = 16 bytes
+0376: F0 movx @DPTR,a
+
+ epfull:
+ ;; do the D/A conversion
+0377: E5 AA mov a,EP2468STAT
+0379: 54 01 anl a,#01H ; empty
+037B: 70 0D jnz epempty ; nothing to get
+
+037D: 90 F0 00 mov dptr,#0F000H ; EP2 fifo buffer
+0380: 12 04 4B lcall dalo ; conversion
+
+0383: 90 E6 91 mov dptr,#EP2BCL ; "arm" it
+0386: 74 80 mov a,#80h
+0388: F0 movx @DPTR,a ; can receive data
+0389: F0 movx @dptr,a
+
+ hispeed:
+ epempty:
+ ;; clear INT2
+038A: E5 91 mov a,EXIF ; FIRST clear the USB (INT2
+038C: C2 E4 clr acc.4
+038E: F5 91 mov EXIF,a ; Note: EXIF reg is not 805
+
+0390: 90 E6 5D mov DPTR,#USBIRQ ; points to the SOF
+0393: 74 02 mov a,#2 ; clear the SOF
+0395: F0 movx @DPTR,a
+
+ nosof:
+0396: D0 07 pop 07h
+0398: D0 06 pop 06h
+039A: D0 05 pop 05h
+039C: D0 04 pop 04h ; R4
+039E: D0 03 pop 03h ; R3
+03A0: D0 02 pop 02h ; R2
+03A2: D0 01 pop 01h ; R1
+03A4: D0 00 pop 00h ; R0
+03A6: D0 D0 pop psw
+03A8: D0 E0 pop acc
+03AA: D0 85 pop dph1
+03AC: D0 84 pop dpl1
+03AE: D0 83 pop dph
+03B0: D0 82 pop dpl
+03B2: D0 86 pop dps
+03B4: 32 reti
+
+
+
+
+
+ ;;; interrupt-routine for ep4
+ ;;; receives the channel list and other commands
+ ep4_isr:
+03B5: C0 86 push dps
+03B7: C0 82 push dpl
+03B9: C0 83 push dph
+03BB: C0 84 push dpl1
+03BD: C0 85 push dph1
+03BF: C0 E0 push acc
+03C1: C0 D0 push psw
+03C3: C0 00 push 00h ; R0
+03C5: C0 01 push 01h ; R1
+03C7: C0 02 push 02h ; R2
+03C9: C0 03 push 03h ; R3
+03CB: C0 04 push 04h ; R4
+03CD: C0 05 push 05h ; R5
+03CF: C0 06 push 06h ; R6
+03D1: C0 07 push 07h ; R7
+
+03D3: 90 F4 00 mov dptr,#0f400h ; FIFO buffer of EP4
+03D6: E0 movx a,@dptr ; get the first byt
+
+03D7: 90 03 DC mov dptr,#ep4_jmp ; jump table for the differ
+03DA: 23 rl a ; multiply by 2: sizeof sjm
+03DB: 73 jmp @a+dptr ; jump to the jump
+ ep4_jmp:
+03DC: 80 06 sjmp storechannellist; a=0
+03DE: 80 17 sjmp single_da ; a=1
+03E0: 80 1D sjmp config_digital_b; a=2
+03E2: 80 23 sjmp write_digital_b ; a=3
+
+
+ ;;; Channellist:
+ ;;; the first byte is zero:
+ ;;; we've just received the channel list
+ ;;; the channel list is stored in the addresses from 80H whi
+ ;;; are _only_ reachable by indirect addressing
+ storechannellist:
+03E4: 78 80 mov r0,#CHANNELLIST ; the conversion by
+03E6: 7A 08 mov r2,#8 ; counter
+03E8: 90 F4 01 mov dptr,#0f401h ; FIFO buffer of EP4
+ chanlloop:
+03EB: E0 movx a,@dptr ;
+03EC: F6 mov @r0,a
+03ED: A3 inc dptr
+03EE: 08 inc r0
+03EF: DA FA djnz r2,chanlloop
+03F1: E4 clr a ; announce analogue transac
+03F2: 78 90 mov r0,#DIOFLAG ; pointer to the command by
+03F4: F6 mov @r0,a ; set the command byte
+03F5: 80 21 sjmp over_da
+
+ ;;; Single DA conversion. The 2 bytes are in the FIFO buffer
+ single_da:
+03F7: 90 F4 01 mov dptr,#0f401h ; FIFO buffer of EP4
+03FA: 12 04 4B lcall dalo ; conversion
+03FD: 80 19 sjmp over_da
+
+ ;;; configure the port B
+ config_digital_b:
+03FF: 90 F4 01 mov dptr,#0f401h ; FIFO buffer of EP4
+0402: E0 movx a,@dptr ; get the second by
+0403: F5 B3 mov OEB,a ; set the output enable bit
+0405: 80 11 sjmp over_da
+
+ ;;; Write one byte to the external digital port B
+ ;;; and prepare for digital read
+ write_digital_b:
+0407: 90 F4 01 mov dptr,#0f401h ; FIFO buffer of EP4
+040A: E0 movx a,@dptr ; get the second by
+040B: F5 B3 mov OEB,a ; output enable
+040D: A3 inc dptr ; next byte
+040E: E0 movx a,@dptr ; bits
+040F: F5 90 mov IOB,a ; send the byte to the I/O
+0411: 74 FF mov a,#0ffh ; announce DIO tran
+0413: 78 90 mov r0,#DIOFLAG ; pointer to the command by
+0415: F6 mov @r0,a ; set the command byte
+0416: 80 00 sjmp over_da
+
+ ;;; more things here to come...
+
+ over_da:
+0418: 90 E6 95 mov dptr,#EP4BCL
+041B: 74 80 mov a,#80h
+041D: F0 movx @DPTR,a ; arm it
+041E: F0 movx @DPTR,a ; arm it
+041F: F0 movx @DPTR,a ; arm it
+
+ ;; clear INT2
+0420: E5 91 mov a,EXIF ; FIRST clear the USB (INT2
+0422: C2 E4 clr acc.4
+0424: F5 91 mov EXIF,a ; Note: EXIF reg is not 805
+
+0426: 90 E6 5F mov DPTR,#EPIRQ ;
+0429: 74 20 mov a,#00100000b ; clear the ep4irq
+042B: F0 movx @DPTR,a
+
+042C: D0 07 pop 07h
+042E: D0 06 pop 06h
+0430: D0 05 pop 05h
+0432: D0 04 pop 04h ; R4
+0434: D0 03 pop 03h ; R3
+0436: D0 02 pop 02h ; R2
+0438: D0 01 pop 01h ; R1
+043A: D0 00 pop 00h ; R0
+043C: D0 D0 pop psw
+043E: D0 E0 pop acc
+0440: D0 85 pop dph1
+0442: D0 84 pop dpl1
+0444: D0 83 pop dph
+0446: D0 82 pop dpl
+0448: D0 86 pop dps
+044A: 32 reti
+
+
+
+ ;;; all channels
+ dalo:
+044B: E0 movx a,@dptr ; number of channel
+044C: A3 inc dptr ; pointer to the first chan
+044D: F8 mov r0,a ; 4 channels
+ nextDA:
+044E: E0 movx a,@dptr ; get the first low
+044F: FB mov r3,a ; store in r3 (see below)
+0450: A3 inc dptr ; point to the high byte
+0451: E0 movx a,@dptr ; get the high byte
+0452: FC mov r4,a ; store in r4 (for writeDA)
+0453: A3 inc dptr ; point to the channel numb
+0454: E0 movx a,@dptr ; get the channel n
+0455: A3 inc dptr ; get ready for the next ch
+0456: 12 04 5C lcall writeDA ; write value to th
+0459: D8 F3 djnz r0,nextDA ; next channel
+045B: 22 ret
+
+
+
+ ;;; D/A-conversion:
+ ;;; control-byte in a,
+ ;;; value in r3(low) and r4(high)
+ writeDA: ; mask the control byte
+045C: 54 C0 anl a,#11000000b ; only the channel is left
+045E: 44 30 orl a,#00110000b ; internal clock, bipolar m
+0460: 4C orl a,r4 ; or the value of R4 to it
+ ;; set CS to low
+0461: C2 85 clr IOA.5 ; set /CS to zero
+ ;; send the first byte to the DA-converter
+0463: 7A 08 mov R2,#8 ; bit-counter
+0465: 30 E7 04 DA1: jnb ACC.7,zeroda ; jump if Bit7 = 0?
+0468: D2 82 setb IOA.2 ; set the DIN bit
+046A: 80 02 sjmp clkda ; continue with the clock
+046C: C2 82 zeroda: clr IOA.2 ; clear the DIN bit
+046E: D2 80 clkda: setb IOA.0 ; SCLK = 1
+0470: C2 80 clr IOA.0 ; SCLK = 0
+0472: 23 rl a ; next Bit
+0473: DA F0 djnz R2,DA1
+
+
+ ;; send the second byte to the DA-converter
+0475: EB mov a,r3 ; low byte
+0476: 7A 08 mov R2,#8 ; bit-counter
+0478: 30 E7 04 DA2: jnb ACC.7,zeroda2 ; jump if Bit7 = 0?
+047B: D2 82 setb IOA.2 ; set the DIN bit
+047D: 80 02 sjmp clkda2 ; continue with the clock
+047F: C2 82 zeroda2:clr IOA.2 ; clear the DIN bit
+0481: D2 80 clkda2: setb IOA.0 ; SCLK = 1
+0483: C2 80 clr IOA.0 ; SCLK = 0
+0485: 23 rl a ; next Bit
+0486: DA F0 djnz R2,DA2
+ ;;
+0488: D2 85 setb IOA.5 ; set /CS to one
+ ;;
+048A: 22 noDA: ret
+
+
+
+ ;;; arm ep6
+ ep6_arm:
+048B: 12 02 1E lcall convlo
+
+048E: 90 E6 98 mov DPTR,#EP6BCH ; byte count H
+0491: 74 00 mov a,#0 ; is zero
+0493: F0 movx @DPTR,a
+
+0494: 90 E6 99 mov DPTR,#EP6BCL ; byte count L
+0497: 74 10 mov a,#10H ; is one
+0499: F0 movx @DPTR,a
+049A: 22 ret
+
+
+
+ ;;; get all 8 channels in the high speed mode
+ ep6_isr:
+049B: C0 86 push dps
+049D: C0 82 push dpl
+049F: C0 83 push dph
+04A1: C0 84 push dpl1
+04A3: C0 85 push dph1
+04A5: C0 E0 push acc
+04A7: C0 D0 push psw
+04A9: C0 00 push 00h ; R0
+04AB: C0 01 push 01h ; R1
+04AD: C0 02 push 02h ; R2
+04AF: C0 03 push 03h ; R3
+04B1: C0 04 push 04h ; R4
+04B3: C0 05 push 05h ; R5
+04B5: C0 06 push 06h ; R6
+04B7: C0 07 push 07h ; R7
+
+04B9: 12 02 1E lcall convlo ; conversion
+
+04BC: 90 E6 98 mov DPTR,#EP6BCH ; byte count H
+04BF: 74 00 mov a,#0 ; is zero
+04C1: F0 movx @DPTR,a
+
+04C2: 90 E6 99 mov DPTR,#EP6BCL ; byte count L
+04C5: 74 10 mov a,#10H ; is 8x word = 16 bytes
+04C7: F0 movx @DPTR,a
+
+ ;; clear INT2
+04C8: E5 91 mov a,EXIF ; FIRST clear the USB (INT2
+04CA: C2 E4 clr acc.4
+04CC: F5 91 mov EXIF,a ; Note: EXIF reg is not 805
+
+04CE: 90 E6 5F mov DPTR,#EPIRQ ;
+04D1: 74 40 mov a,#01000000b ; clear the ep6irq
+04D3: F0 movx @DPTR,a
+
+04D4: D0 07 pop 07h
+04D6: D0 06 pop 06h
+04D8: D0 05 pop 05h
+04DA: D0 04 pop 04h ; R4
+04DC: D0 03 pop 03h ; R3
+04DE: D0 02 pop 02h ; R2
+04E0: D0 01 pop 01h ; R1
+04E2: D0 00 pop 00h ; R0
+04E4: D0 D0 pop psw
+04E6: D0 E0 pop acc
+04E8: D0 85 pop dph1
+04EA: D0 84 pop dpl1
+04EC: D0 83 pop dph
+04EE: D0 82 pop dpl
+04F0: D0 86 pop dps
+04F2: 32 reti
+
+
+
+ ;;; converts one analog/digital channel and stores it in EP8
+ ;;; also gets the content of the digital ports B and D
+ ep8_adc:
+04F3: 78 90 mov r0,#DIOFLAG ; pointer to the DIO flag
+04F5: E6 mov a,@r0 ; get the flag
+04F6: 70 10 jnz ep8_dio ; nonzero means DIO
+
+04F8: 78 80 mov r0,#CHANNELLIST ; points to the cha
+04FA: E6 mov a,@r0 ; Ch0
+
+04FB: 12 01 CB lcall readAD ; start the conversion
+
+04FE: 90 FC 00 mov DPTR,#0fc00h ; EP8 FIFO
+0501: EB mov a,R3 ; get low byte
+0502: F0 movx @DPTR,A ; store in FIFO
+0503: A3 inc dptr ; next fifo entry
+0504: EC mov a,R4 ; get high byte
+0505: F0 movx @DPTR,A ; store in FIFO
+
+0506: 80 09 sjmp ep8_send ; send the data
+
+ ep8_dio:
+0508: 90 FC 00 mov DPTR,#0fc00h ; store the contents of por
+050B: E5 90 mov a,IOB ; in the next
+050D: F0 movx @dptr,a ; entry of the buff
+
+050E: A3 inc dptr
+050F: E4 clr a ; high byte is zero
+0510: F0 movx @dptr,a ; next byte of the
+
+ ep8_send:
+0511: 90 E6 9C mov DPTR,#EP8BCH ; byte count H
+0514: 74 00 mov a,#0 ; is zero
+0516: F0 movx @DPTR,a
+
+0517: 90 E6 9D mov DPTR,#EP8BCL ; byte count L
+051A: 74 10 mov a,#10H ; 16 bytes
+051C: F0 movx @DPTR,a ; send the data ove
+051D: 22 ret
+
+
+
+ ;;; arms EP8 with one byte. This signals the Linux driver th
+ ;;; the EP has been armed only with a dummy byte to make the
+ ;;; IRQ work. The byte is not processed by the driver.
+ ep8_arm:
+051E: 90 E6 9C mov DPTR,#EP8BCH ; byte count H
+0521: 74 00 mov a,#0 ; is zero
+0523: F0 movx @DPTR,a
+
+0524: 90 E6 9D mov DPTR,#EP8BCL ; byte count L
+0527: 74 01 mov a,#1 ; 1 byte
+0529: F0 movx @DPTR,a
+052A: 22 ret
+
+
+
+ ;;; EP8 interrupt: gets one measurement from the AD converte
+ ;;; sends it via EP8. The channel # is stored in address 80H
+ ;;; It also gets the state of the digital registers B and D.
+ ep8_isr:
+052B: C0 86 push dps
+052D: C0 82 push dpl
+052F: C0 83 push dph
+0531: C0 84 push dpl1
+0533: C0 85 push dph1
+0535: C0 E0 push acc
+0537: C0 D0 push psw
+0539: C0 00 push 00h ; R0
+053B: C0 01 push 01h ; R1
+053D: C0 02 push 02h ; R2
+053F: C0 03 push 03h ; R3
+0541: C0 04 push 04h ; R4
+0543: C0 05 push 05h ; R5
+0545: C0 06 push 06h ; R6
+0547: C0 07 push 07h ; R7
+
+0549: 12 04 F3 lcall ep8_adc
+
+ ;; clear INT2
+054C: E5 91 mov a,EXIF ; FIRST clear the USB (INT2
+054E: C2 E4 clr acc.4
+0550: F5 91 mov EXIF,a ; Note: EXIF reg is not 805
+
+0552: 90 E6 5F mov DPTR,#EPIRQ ;
+0555: 74 80 mov a,#10000000b ; clear the ep8irq
+0557: F0 movx @DPTR,a
+
+0558: D0 07 pop 07h
+055A: D0 06 pop 06h
+055C: D0 05 pop 05h
+055E: D0 04 pop 04h ; R4
+0560: D0 03 pop 03h ; R3
+0562: D0 02 pop 02h ; R2
+0564: D0 01 pop 01h ; R1
+0566: D0 00 pop 00h ; R0
+0568: D0 D0 pop psw
+056A: D0 E0 pop acc
+056C: D0 85 pop dph1
+056E: D0 84 pop dpl1
+0570: D0 83 pop dph
+0572: D0 82 pop dpl
+0574: D0 86 pop dps
+0576: 32 reti
+
+
+
+
+
+
+ ;;; high speed mode, IRQ mode. Asynchronous transmission.
+ ep2_isr:
+0577: C0 86 push dps
+0579: C0 82 push dpl
+057B: C0 83 push dph
+057D: C0 84 push dpl1
+057F: C0 85 push dph1
+0581: C0 E0 push acc
+0583: C0 D0 push psw
+0585: C0 00 push 00h ; R0
+0587: C0 01 push 01h ; R1
+0589: C0 02 push 02h ; R2
+058B: C0 03 push 03h ; R3
+058D: C0 04 push 04h ; R4
+058F: C0 05 push 05h ; R5
+0591: C0 06 push 06h ; R6
+0593: C0 07 push 07h ; R7
+
+0595: 90 F0 00 mov dptr,#0F000H ; EP2 fifo buffer
+0598: 12 04 4B lcall dalo ; conversion
+
+059B: 90 E6 91 mov dptr,#EP2BCL ; "arm" it
+059E: 74 80 mov a,#80h
+05A0: F0 movx @DPTR,a ; can receive data
+05A1: F0 movx @dptr,a
+
+ ;; clear INT2
+05A2: E5 91 mov a,EXIF ; FIRST clear the USB (INT2
+05A4: C2 E4 clr acc.4
+05A6: F5 91 mov EXIF,a ; Note: EXIF reg is not 805
+
+05A8: 90 E6 5F mov DPTR,#EPIRQ ; points to the usbirq
+05AB: 74 10 mov a,#00010000b ; clear the usbirq of ep 2
+05AD: F0 movx @DPTR,a
+
+05AE: D0 07 pop 07h
+05B0: D0 06 pop 06h
+05B2: D0 05 pop 05h
+05B4: D0 04 pop 04h ; R4
+05B6: D0 03 pop 03h ; R3
+05B8: D0 02 pop 02h ; R2
+05BA: D0 01 pop 01h ; R1
+05BC: D0 00 pop 00h ; R0
+05BE: D0 D0 pop psw
+05C0: D0 E0 pop acc
+05C2: D0 85 pop dph1
+05C4: D0 84 pop dpl1
+05C6: D0 83 pop dph
+05C8: D0 82 pop dpl
+05CA: D0 86 pop dps
+05CC: 32 reti
+
+
+
+
+
+
+
+
+
+05CD: .End
+
+
+