comedilib support for new usbdux driver
authorFrank Mori Hess <fmhess@speakeasy.net>
Sun, 30 Nov 2003 15:41:14 +0000 (15:41 +0000)
committerFrank Mori Hess <fmhess@speakeasy.net>
Sun, 30 Nov 2003 15:41:14 +0000 (15:41 +0000)
etc/Makefile.am
etc/hotplug/Makefile.am [new file with mode: 0644]
etc/hotplug/usb/Makefile.am [new file with mode: 0644]
etc/hotplug/usb/usbdux/Makefile.am [new file with mode: 0644]
etc/hotplug/usb/usbdux/Makefile_asm [new file with mode: 0644]
etc/hotplug/usb/usbdux/README [new file with mode: 0644]
etc/hotplug/usb/usbdux/fx2-include.asm [new file with mode: 0644]
etc/hotplug/usb/usbdux/usbdux [new file with mode: 0755]
etc/hotplug/usb/usbdux/usbdux_firmware.asm [new file with mode: 0644]
etc/hotplug/usb/usbdux/usbdux_firmware.hex [new file with mode: 0644]
etc/hotplug/usb/usbdux/usbdux_firmware.lst [new file with mode: 0644]

index c4ab91afef96c6955505d57f024334ec9a03032e..8f862e4b78f501b8999d43f26d1a9c57d335134a 100644 (file)
@@ -1,5 +1,5 @@
 
-SUBDIRS = pcmcia
+SUBDIRS = pcmcia hotplug
 
 pkgdata_DATA = das1600.conf dt282x.conf modules.conf
 
diff --git a/etc/hotplug/Makefile.am b/etc/hotplug/Makefile.am
new file mode 100644 (file)
index 0000000..feb8d0a
--- /dev/null
@@ -0,0 +1 @@
+SUBDIRS = usb
diff --git a/etc/hotplug/usb/Makefile.am b/etc/hotplug/usb/Makefile.am
new file mode 100644 (file)
index 0000000..88108a4
--- /dev/null
@@ -0,0 +1,2 @@
+SUBDIRS = usbdux
+
diff --git a/etc/hotplug/usb/usbdux/Makefile.am b/etc/hotplug/usb/usbdux/Makefile.am
new file mode 100644 (file)
index 0000000..4a79249
--- /dev/null
@@ -0,0 +1,6 @@
+
+usbhotplug_SCRIPTS = usbdux
+
+usbfirmware_DATA = usbdux_firmware.hex
+
+EXTRA_DIST = usbdux usbdux_firmware.hex
diff --git a/etc/hotplug/usb/usbdux/Makefile_asm b/etc/hotplug/usb/usbdux/Makefile_asm
new file mode 100644 (file)
index 0000000..d7310f5
--- /dev/null
@@ -0,0 +1,27 @@
+# (c) Bernd Porr
+# GNU public license
+# no warranty
+#
+
+all: as31 usbdux_firmware.hex
+
+as31:
+       make -C as31-2.1
+
+#deprecated
+usbdux_firmware.bin: fx2-include.asm usbdux_firmware.asm as31
+       as31-2.1/as31 -Fbin usbdux_firmware.asm
+
+usbdux_firmware.hex: fx2-include.asm usbdux_firmware.asm as31
+       as31-2.1/as31 -l usbdux_firmware.asm
+
+clean:
+       rm -f *.bin *~ *.lst *.bin *.hex
+       make -C as31-2.1 clean
+
+install:
+       mkdir -p /usr/share/usb/
+       install usbdux_firmware.hex /usr/share/usb/usbdux_firmware.hex
+       mkdir -p /etc/hotplug/usb
+       install hotplug/usbdux /etc/hotplug/usb/usbdux
+
diff --git a/etc/hotplug/usb/usbdux/README b/etc/hotplug/usb/usbdux/README
new file mode 100644 (file)
index 0000000..d87cb0d
--- /dev/null
@@ -0,0 +1,33 @@
+Remarks to the hotplug script "usbdux":
+---------------------------------------
+
+The script /etc/hotplug/usb/usbdux uploads the
+firmware into the usb device after it has been
+plugged in.
+
+It assumes that you have installed the firmware
+under /usr/share/usb (recommended by the usb hotplug team) and that
+usbdux shall be connected to comedi0.
+
+Please modify the script if needed.
+
+
+
+To compile the firmware:
+------------------------
+Download the as31 from:
+
+http://www.cn.stir.ac.uk/linux-daq/as31/
+
+(this is a patched version of as31 which supports an
+include directive).
+
+Install it in this directory.
+
+Then run "make -f Makefile_asm".
+
+
+
+Feedback:
+Bernd.Porr@cn.stir.ac.uk
+
diff --git a/etc/hotplug/usb/usbdux/fx2-include.asm b/etc/hotplug/usb/usbdux/fx2-include.asm
new file mode 100644 (file)
index 0000000..8d79025
--- /dev/null
@@ -0,0 +1,136 @@
+; 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 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.
+;
+; In conjunction with the as31.
+; Include-file for the FX2 by Cypress. The rest of the regs is defined
+; by the as31 itself.
+;
+; from the TRM of the FX2:
+;
+       ;;  CPU control
+       .equ    CPUCS,0E600H
+       ;; interface config
+       .equ    IFCONFIG,0E601H
+       .equ    FIFORESET,0E604H
+       ;; Endpoint configs
+       .equ    EP1OUTCFG,0E610H
+       .equ    EP1INCFG,0E611H
+       .equ    EP2CFG,0E612H
+       .equ    EP4CFG,0E613H
+       .equ    EP6CFG,0E614H
+       .equ    EP8CFG,0E615H
+       ;; packets per frame, always one for USB 1.1
+       .equ    EP2ISOINPKTS,0E640H
+       .equ    EP4ISOINPKTS,0E641H
+       .equ    EP6ISOINPKTS,0E642H
+       .equ    EP8ISOINPKTS,0E643H
+       ;; endpoint byte counts
+       .equ    EP1OUTBC,0E68DH
+       .equ    EP2BCH,0E690H
+       .equ    EP2BCL,0E691H
+       .equ    EP4BCH,0E694H
+       .equ    EP4BCL,0E695H
+       .equ    EP6BCH,0E698H
+       .equ    EP6BCL,0E699H
+       .equ    EP8BCH,0E69CH
+       .equ    EP8BCL,0E69DH
+       ;;
+       .equ    EP4AUTOINLENH,0E622H
+       .equ    EP4AUTOINLENL,0E623H
+       .equ    EP2FIFOCFG,0E618H
+       .equ    EP4FIFOCFG,0E619H
+       .equ    EP6FIFOCFG,0E61AH
+       .equ    EP8FIFOCFG,0E61BH
+       ;; 
+       .equ    INPKTEND,0E648H
+       ;; 
+       ;; endpoint control
+       .equ    EP2CS,0E6A3H
+       .equ    EP4CS,0E6A4H
+       .equ    EP6CS,0E6A5H
+       .equ    EP8CS,0E6A6H
+       ;; endpoint buffers
+       .equ    EP2FIFOBUF,0F000H
+       .equ    EP4FIFOBUF,0F400H
+       .equ    EP6FIFOBUF,0F800H
+       .equ    EP8FIFOBUF,0FC00H
+       ;; IRQ enable for bulk NAK
+       .equ    IBNIE,0E658H
+       ;; interrupt requ for NAK
+       .equ    IBNIRQ,0E659H
+       ;; USB INT enables
+       .equ    USBIE,0E65CH
+       ;; USB interrupt request
+       .equ    USBIRQ,0E65DH
+       ;; endpoint IRQ enable
+       .equ    EPIE,0E65EH
+       ;; endpoint IRQ requests
+       .equ    EPIRQ,0E65FH
+       ;; USB error IRQ requests
+       .equ    USBERRIE,0E662H
+       ;; USB error IRQ request
+       .equ    USBERRIRQ,0E663H
+       ;; USB interrupt 2 autovector
+       .equ    INT2IVEC,0E666H
+       ;; autovector enable
+       .equ    INTSETUP,0E668H
+       ;; port cfg
+       .equ    PORTACFG,0E670H
+       .equ    PORTCCFG,0E671H
+       .equ    PORTECFG,0E672H
+       ;; I2C bus
+       .equ    I2CS,0E678H
+       .equ    I2DAT,0E679H
+       .equ    I2CTL,0E67AH
+       ;; auto pointers, read/write is directed to the pointed address
+       .equ    XAUTODAT1,0E67BH
+       .equ    XAUTODAT2,0E67CH
+       ;; USB-control
+       .equ    USBCS,0E680H
+
+       .equ    IOA,80H
+       .equ    DPL1,84H
+       .equ    DPH1,85H
+       .equ    DPS,86H
+       .equ    CKCON,8Eh
+       .equ    IOB,90H
+       .equ    EXIF,91h
+       .equ    MPAGE,92h
+       .equ    AUTOPTRH1,9AH
+       .equ    AUTOPTRL1,9BH
+       .equ    AUTOPTRH2,9DH
+       .equ    AUTOPTRL2,9EH
+       .equ    IOC,0A0H
+       .equ    INT2CLR,0A1H
+       .equ    INT4CLR,0A2H
+       .equ    EP2468STAT,0AAH
+       .equ    EP24FIFOFLGS,0ABH
+       .equ    EP68FIFOFLGS,0ACH
+       .equ    AUTOPTRSETUP,0AFH
+       .equ    IOD,0B0H
+       .equ    IOE,0B1H
+       .equ    OEA,0B2H
+       .equ    OEB,0B3H
+       .equ    OEC,0B4H
+       .equ    OED,0B5H
+       .equ    OEE,0B6H
+       .equ    EIE,0E8h
+
+
+       ;;; end of file
+       
diff --git a/etc/hotplug/usb/usbdux/usbdux b/etc/hotplug/usb/usbdux/usbdux
new file mode 100755 (executable)
index 0000000..fd16b84
--- /dev/null
@@ -0,0 +1,38 @@
+#!/bin/sh
+#
+# hotplug script for USBDUX. Mon Oct 20 10:08:09 BST 2003. 
+# Bernd.Porr@cn.stir.ac.uk
+#
+#
+#
+#look for comedi config
+COMEDI_CONFIG=
+#
+if [ -e /usr/local/sbin/comedi_config ]; then
+       COMEDI_CONFIG=/usr/local/sbin/comedi_config
+fi
+if [ -e /usr/sbin/comedi_config ]; then 
+        COMEDI_CONFIG=/usr/sbin/comedi_config
+fi
+if [ -e /sbin/comedi_config ]; then 
+        COMEDI_CONFIG=/sbin/comedi_config
+fi
+#
+#
+#look for the firmware
+USBDUX_FIRMWARE=
+if [ -e /usr/share/usb/usbdux_firmware.hex ]; then 
+        USBDUX_FIRMWARE=/usr/share/usb/usbdux_firmware.hex
+fi
+if [ -e /usr/local/share/usb/usbdux_firmware.hex ]; then
+        USBDUX_FIRMWARE=/usr/local/share/usb/usbdux_firmware.hex
+fi
+#
+#
+# please modify if needed
+#
+echo "$COMEDI_CONFIG -i $USBDUX_FIRMWARE /dev/comedi0 usbdux"
+$COMEDI_CONFIG -i $USBDUX_FIRMWARE /dev/comedi0 usbdux
+#
+#
+#
diff --git a/etc/hotplug/usb/usbdux/usbdux_firmware.asm b/etc/hotplug/usb/usbdux/usbdux_firmware.asm
new file mode 100644 (file)
index 0000000..ea5a896
--- /dev/null
@@ -0,0 +1,981 @@
+;   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
+
+
diff --git a/etc/hotplug/usb/usbdux/usbdux_firmware.hex b/etc/hotplug/usb/usbdux/usbdux_firmware.hex
new file mode 100644 (file)
index 0000000..e1dc621
--- /dev/null
@@ -0,0 +1,80 @@
+:030000000201A258
+:03004300020100B7
+:1001000002017F0002033C0002017F0002017F0028
+:1001100002017F0002017F0002017F0002017F00D7
+:1001200002017F0002017F0002017F0002017F00C7
+:10013000020577000203B50002049B0002052B00B4
+:1001400002017F0002017F0002017F0002017F00A7
+:1001500002017F0002017F0002017F0002017F0097
+:1001600002017F0002017F0002017F0002017F0087
+:1001700002017F0002017F0002017F0002017FC0B7
+:1001800086C082C083C084C085C0E0C0D0E591C273
+:10019000E4F591D0D0D0E0D085D084D083D082D087
+:1001A000863290E6007414F090E6687408F012014C
+:1001B000C490E680E0548070051202898003120228
+:1001C000E10080FD75B22775802222547C4481C2F3
+:1001D000817A0830E704D2828002C282D280C28053
+:1001E00023DAF0C2827A05D280C280DAFA7C007A01
+:1001F000047D08D280C280E58030E403EC4DFCED44
+:1002000003FDDAEF7B007A087D80D280C280E58032
+:1002100030E403EB4DFBED03FDDAEFD28122759A5A
+:10022000F8759B0075AF077880E61201CBEB90E67E
+:100230007BF0ECF008E61201CBEB90E67BF0ECF003
+:1002400008E61201CBEB90E67BF0ECF008E6120139
+:10025000CBEB90E67BF0ECF008E61201CBEB90E6FE
+:100260007BF0ECF008E61201CBEB90E67BF0ECF0D3
+:1002700008E61201CBEB90E67BF0ECF008E6120109
+:10028000CBEB90E67BF0ECF02290E604740FF07478
+:1002900000F090E6127492F090E6187400F090E688
+:1002A000917480F0F0F090E61374A0F090E6197469
+:1002B00000F090E6957480F0F090E61474D2F0901F
+:1002C000E61574E0F090E65E74A0F090E65F74A02E
+:1002D000F090E65C7402F075E80175A88012051EC6
+:1002E0002290E604740FF07400F090E61274B2F0FD
+:1002F00090E6187400F090E6917480F0F0F090E6CB
+:100300001374A0F090E6197400F090E6957480F0F4
+:10031000F090E61474F2F090E61574E0F090E65E6A
+:1003200074F0F090E65F74F0F090E65C7400F075A5
+:10033000E80175A88012051E12048B22C086C082B7
+:10034000C083C084C085C0E0C0D0C000C001C0026E
+:10035000C003C004C005C006C00790E680E054801A
+:100360007028E5AA5420700F12021E90E6987400BF
+:10037000F090E6997410F0E5AA5401700D90F00029
+:1003800012044B90E6917480F0F0E591C2E4F5918F
+:1003900090E65D7402F0D007D006D005D004D003FB
+:1003A000D002D001D000D0D0D0E0D085D084D0838E
+:1003B000D082D08632C086C082C083C084C085C04F
+:1003C000E0C0D0C000C001C002C003C004C005C06E
+:1003D00006C00790F400E09003DC237380068017CA
+:1003E000801D802378807A0890F401E0F6A308DA73
+:1003F000FAE47890F6802190F40112044B80199071
+:10040000F401E0F5B3801190F401E0F5B3A3E0F559
+:100410009074FF7890F6800090E6957480F0F0F08C
+:10042000E591C2E4F59190E65F7420F0D007D00624
+:10043000D005D004D003D002D001D000D0D0D0E07D
+:10044000D085D084D083D082D08632E0A3F8E0FB80
+:10045000A3E0FCA3E0A312045CD8F32254C0443010
+:100460004CC2857A0830E704D2828002C282D280F0
+:10047000C28023DAF0EB7A0830E704D2828002C22D
+:1004800082D280C28023DAF0D2852212021E90E648
+:10049000987400F090E6997410F022C086C082C073
+:1004A00083C084C085C0E0C0D0C000C001C002C00D
+:1004B00003C004C005C006C00712021E90E698746F
+:1004C00000F090E6997410F0E591C2E4F59190E6A1
+:1004D0005F7440F0D007D006D005D004D003D0021E
+:1004E000D001D000D0D0D0E0D085D084D083D082CD
+:1004F000D086327890E670107880E61201CB90FCBE
+:1005000000EBF0A3ECF0800990FC00E590F0A3E490
+:10051000F090E69C7400F090E69D7410F02290E656
+:100520009C7400F090E69D7401F022C086C082C0E9
+:1005300083C084C085C0E0C0D0C000C001C002C07C
+:1005400003C004C005C006C0071204F3E591C2E46D
+:10055000F59190E65F7480F0D007D006D005D00406
+:10056000D003D002D001D000D0D0D0E0D085D0844C
+:10057000D083D082D08632C086C082C083C084C07F
+:1005800085C0E0C0D0C000C001C002C003C004C02C
+:1005900005C006C00790F00012044B90E6917480ED
+:1005A000F0F0E591C2E4F59190E65F7410F0D007A9
+:1005B000D006D005D004D003D002D001D000D0D0D6
+:0D05C000D0E0D085D084D083D082D08632A8
+:00000001FF
diff --git a/etc/hotplug/usb/usbdux/usbdux_firmware.lst b/etc/hotplug/usb/usbdux/usbdux_firmware.lst
new file mode 100644 (file)
index 0000000..01cd32c
--- /dev/null
@@ -0,0 +1,1118 @@
+                   ;   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
+                   
+                   
+