--- /dev/null
+; 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
+ .equ REVCTL,0E60BH
+ ;; 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 EP1INBC,0E68FH
+ .equ EP1INCS,0E6A2H
+ .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 EP6AUTOINLENH,0E624H
+ .equ EP6AUTOINLENL,0E625H
+ .equ EP2FIFOCFG,0E618H
+ .equ EP4FIFOCFG,0E619H
+ .equ EP6FIFOCFG,0E61AH
+ .equ EP8FIFOCFG,0E61BH
+ ;;
+ .equ INPKTEND,0E648H
+ .equ GPIFCTLCFG,0E6C3H
+ .equ GPIFABORT,0E6F5H
+ .equ GPIFIDLECTL,0E6C2H
+ .equ GPIFWFSELECT,0E6C0H
+ .equ GPIFREADYCFG,0E6F3H
+ .equ GPIFIDLECS,0E6C1H
+ .equ EP6GPIFFLGSEL,0E6E2H
+ .equ EP6GPIFPDFSTOP,0E6E3H
+ .equ EP6GPIFTRIG,0E6E4H
+ .equ GPIFIE,0E660H
+ .equ GPIFIRQ,0E661H
+ ;;
+ ;; 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 GPIFTRIG,0BBH
+ .equ EIE,0E8h
+
+
+ ;;; end of file
+
--- /dev/null
+; usbdux_firmware.asm
+; Copyright (C) 2004 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: xxx
+; Devices: [ITL] USB-DUX (usbdux.o)
+; Author: Bernd Porr <Bernd.Porr@f2s.com>
+; Updated:
+; Status: testing
+;
+;;;
+;;;
+;;;
+
+ .inc fx2-include.asm
+
+ .equ WFLOADED,70H ; waveform is loaded
+
+ .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
+sof_isr:
+sudav_isr:
+sutok_isr:
+suspend_isr:
+usbreset_isr:
+hispeed_isr:
+ep0ack_isr:
+spare_isr:
+ep0in_isr:
+ep0out_isr:
+ep1out_isr:
+ep1in_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:
+ep6_isr:
+ep2_isr:
+ep8_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,#REVCTL
+ mov a,#00000011b ; allows skip
+ lcall syncdelaywr
+
+ mov DPTR,#CPUCS ; CPU control register
+ mov a,#00010000b ; 48Mhz
+ lcall syncdelaywr
+
+ mov dptr,#IFCONFIG ; switch on IFCLK signal
+ mov a,#10110010b ; gpif, 30MHz,
+ lcall syncdelaywr
+
+ mov dptr,#FIFORESET
+ mov a,#80h
+ lcall syncdelaywr
+ mov a,#8
+ lcall syncdelaywr
+ mov a,#2
+ lcall syncdelaywr
+ mov a,#4
+ lcall syncdelaywr
+ mov a,#6
+ lcall syncdelaywr
+ mov a,#0
+ lcall syncdelaywr
+
+ mov dptr,#INTSETUP ; IRQ setup register
+ mov a,#08h ; enable autovector
+ lcall syncdelaywr
+
+ lcall initeps ; init the isochronous data-transfer
+
+ lcall initGPIF
+
+;;; main loop
+
+mloop2:
+ lcall gpif_run
+ sjmp mloop2 ; do nothing. The rest is done by the IRQs
+
+
+gpif_run:
+ mov a,WFLOADED
+ jz no_trig ; do not trigger
+ mov a,GPIFTRIG ; GPIF status
+ anl a,#80h ; done bit
+ jz no_trig ; GPIF busy
+
+ mov a,#06h ; RD,EP6
+ mov GPIFTRIG,a
+no_trig:
+ ret
+
+
+
+initGPIF:
+ mov DPTR,#EP6CFG ; ISO data from here to the host
+ mov a,#11010000b ; Valid, quad buffering
+ lcall syncdelaywr
+
+ mov dptr,#EP6FIFOCFG
+ mov a,#00001001b ; autoin, wordwide
+ lcall syncdelaywr
+
+ mov dptr,#EP6AUTOINLENH
+ mov a,#00000010b ; 512 bytes
+ lcall syncdelaywr
+
+ mov dptr,#EP6AUTOINLENL
+ mov a,#00000000b ; 0
+ lcall syncdelaywr
+
+ mov dptr,#EP6ISOINPKTS
+ mov a,#1 ; 1 packets
+ lcall syncdelaywr
+
+ mov dptr,#GPIFWFSELECT
+ mov a,#11111100b ; waveform 0 for FIFO RD
+ lcall syncdelaywr
+
+ mov dptr,#GPIFCTLCFG
+ mov a,#10000000b ; tri state for CTRL
+ lcall syncdelaywr
+
+ mov dptr,#GPIFIDLECTL
+ mov a,#11111111b ; all CTL outputs high
+ lcall syncdelaywr
+ mov a,#11111101b ; reset counter
+ lcall syncdelaywr
+ mov a,#11111111b ; reset to high again
+ lcall syncdelaywr
+
+ mov a,#00000010b ; abort when full
+ mov dptr,#EP6GPIFFLGSEL
+ lcall syncdelaywr
+
+ mov a,#00000001b ; stop when buffer overfl
+ mov dptr,#EP6GPIFPDFSTOP
+ lcall syncdelaywr
+
+ mov a,#0
+ mov dptr,#GPIFREADYCFG
+ lcall syncdelaywr
+
+ mov a,#0
+ mov dptr,#GPIFIDLECS
+ lcall syncdelaywr
+
+; waveform 1
+; this is a dummy waveform which is used
+; during the upload of another waveform into
+; wavefrom 0
+; it branches directly into the IDLE state
+ mov dptr,#0E420H
+ mov a,#00111111b ; branch to IDLE
+ lcall syncdelaywr
+
+ mov dptr,#0E428H ; opcode
+ mov a,#00000001b ; deceision point
+ lcall syncdelaywr
+
+ mov dptr,#0E430H
+ mov a,#0FFH ; output is high
+ lcall syncdelaywr
+
+ mov dptr,#0E438H
+ mov a,#0FFH ; logic function
+ lcall syncdelaywr
+
+; signals that no waveform 0 is loaded so far
+ mov WFLOADED,#0 ; waveform flag
+
+ ret
+
+
+
+;;; initilise the transfer
+;;; It is assumed that the USB interface is in alternate setting 3
+initeps:
+ mov DPTR,#EP4CFG
+ mov a,#10100000b ; valid, bulk, out
+ movx @dptr,a
+
+ mov dptr,#EP4BCL ; "arm" it
+ mov a,#00h
+ lcall syncdelaywr ; wait until we can write again
+ lcall syncdelaywr ; wait
+ lcall syncdelaywr ; wait
+
+ mov DPTR,#EP8CFG
+ mov a,#0 ; disable EP8, it overlaps with EP6!!
+ movx @dptr,a
+
+ mov dptr,#EPIE ; interrupt enable
+ mov a,#00100000b ; enable irq for ep4
+ movx @dptr,a ; do it
+
+ mov dptr,#EPIRQ ; clear IRQs
+ mov a,#00100100b
+ movx @dptr,a
+
+ mov DPTR,#USBIE ; USB int enable register
+ mov a,#0 ; SOF etc
+ movx @DPTR,a ;
+
+ mov DPTR,#GPIFIE ; GPIF int enable register
+ mov a,#0 ; done IRQ
+ movx @DPTR,a ;
+
+ mov EIE,#00000001b ; enable INT2 in the 8051's SFR
+ mov IE,#80h ; IE, enable all interrupts
+
+ ret
+
+
+;;; 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 storewaveform ; a=0
+ sjmp init_ep6 ; a=1
+
+init_ep6:
+ ; stop ep6
+ ; just now do nothing
+
+ ljmp over_wf
+
+
+storewaveform:
+ mov WFLOADED,#0 ; waveform flag
+
+ mov dptr,#EP6FIFOCFG
+ mov a,#00000000b ;
+ lcall syncdelaywr
+
+ mov dptr,#GPIFABORT
+ mov a,#0ffh ; abort all transfers
+ lcall syncdelaywr
+
+wait_f_abort:
+ mov a,GPIFTRIG ; GPIF status
+ anl a,#80h ; done bit
+ jz wait_f_abort ; GPIF busy
+
+ mov dptr,#GPIFWFSELECT
+ mov a,#11111101b ; select dummy waveform
+ movx @dptr,a
+ lcall syncdelay
+
+ mov dptr,#FIFORESET
+ mov a,#80h ; NAK
+ lcall syncdelaywr
+ mov a,#6 ; reset EP6
+ lcall syncdelaywr
+ mov a,#0 ; normal op
+ lcall syncdelaywr
+
+; change to dummy waveform 1
+ mov a,#06h ; RD,EP6
+ mov GPIFTRIG,a
+
+; wait a bit
+ mov r2,255
+loopx:
+ djnz r2,loopx
+
+; abort waveform if not already so
+ mov dptr,#GPIFABORT
+ mov a,#0ffh ; abort all transfers
+ lcall syncdelaywr
+
+; wait again
+ mov r2,255
+loopx2:
+ djnz r2,loopx2
+
+; check for DONE
+wait_f_abort2:
+ mov a,GPIFTRIG ; GPIF status
+ anl a,#80h ; done bit
+ jz wait_f_abort2 ; GPIF busy
+
+; upload the new waveform into waveform 0
+ mov AUTOPTRH2,#0E4H ; XDATA0H
+ lcall syncdelay
+ mov AUTOPTRL2,#00H ; XDATA0L
+ lcall syncdelay
+
+ mov AUTOPTRH1,#0F4H ; EP4 high
+ lcall syncdelay
+ mov AUTOPTRL1,#01H ; EP4 low
+ lcall syncdelay
+
+ mov AUTOPTRSETUP,#7 ; autoinc and enable
+ lcall syncdelay
+
+ mov r2,#20H ; 32 bytes to transfer
+
+wavetr:
+ mov dptr,#XAUTODAT1
+ movx a,@dptr
+ lcall syncdelay
+ mov dptr,#XAUTODAT2
+ movx @dptr,a
+ lcall syncdelay
+ djnz r2,wavetr
+
+ mov dptr,#EP6FIFOCFG
+ mov a,#00001001b ; autoin, wordwide
+ lcall syncdelaywr
+
+ mov dptr,#GPIFWFSELECT
+ mov a,#11111100b
+ movx @dptr,a
+ lcall syncdelay
+
+ mov dptr,#FIFORESET
+ mov a,#80h ; NAK
+ lcall syncdelaywr
+ mov a,#6 ; reset EP6
+ lcall syncdelaywr
+ mov a,#0 ; normal op
+ lcall syncdelaywr
+
+ mov dptr,#0E400H+10H; waveform 0: first CTL byte
+ movx a,@dptr ; get it
+ orl a,#11111011b ; force all bits to one except the range bit
+ mov dptr,#GPIFIDLECTL
+ lcall syncdelaywr
+
+ mov WFLOADED,#1 ; waveform flag
+
+; do the common things here
+over_wf:
+ mov dptr,#EP4BCL
+ mov a,#00h
+ movx @DPTR,a ; arm it
+ lcall syncdelay ; wait
+ movx @DPTR,a ; arm it
+ lcall syncdelay ; wait
+
+ ;; 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
+
+
+;; need to delay every time the byte counters
+;; for the EPs have been changed.
+
+syncdelay:
+ nop
+ nop
+ nop
+ nop
+ nop
+ nop
+ nop
+ nop
+ nop
+ ret
+
+
+syncdelaywr:
+ lcall syncdelay
+ movx @dptr,a
+ ret
+
+
+.End
+
+
--- /dev/null
+:030000000201A258
+:03004300020100B7
+:1001000002017F0002017F0002017F0002017F00E7
+:1001100002017F0002017F0002017F0002017F00D7
+:1001200002017F0002017F0002017F0002017F00C7
+:1001300002017F000202C40002017F0002017F0071
+:1001400002017F0002017F0002017F0002017F00A7
+:1001500002017F0002017F0002017F0002017F0097
+:1001600002017F0002017F0002017F0002017F0087
+:1001700002017F0002017F0002017F0002017FC0B7
+:1001800086C082C083C084C085C0E0C0D0E591C273
+:10019000E4F591D0D0D0E0D085D084D083D082D087
+:1001A000863290E60B74031203E490E6007410129A
+:1001B00003E490E60174B21203E490E60474801242
+:1001C00003E474081203E474021203E474041203D7
+:1001D000E474061203E474001203E490E668740801
+:1001E0001203E412028B1201FD1201EE80FBE57096
+:1001F000600AE5BB548060047406F5BB2290E614E7
+:1002000074D01203E490E61A74091203E490E62411
+:1002100074021203E490E62574001203E490E642AF
+:1002200074011203E490E6C074FC1203E490E6C388
+:1002300074801203E490E6C274FF1203E474FD12AA
+:1002400003E474FF1203E4740290E6E21203E47420
+:100250000190E6E31203E4740090E6F31203E47401
+:100260000090E6C11203E490E420743F1203E4908E
+:10027000E42874011203E490E43074FF1203E49064
+:10028000E43874FF1203E47570002290E61374A042
+:10029000F090E69574001203E41203E41203E49074
+:1002A000E6157400F090E65E7420F090E65F74242A
+:1002B000F090E65C7400F090E6607400F075E80180
+:1002C00075A88022C086C082C083C084C085C0E07B
+:1002D000C0D0C000C001C002C003C004C005C00639
+:1002E000C00790F400E09002EB23738005800002C9
+:1002F00003A275700090E61A74001203E490E6F50C
+:1003000074FF1203E4E5BB548060FA90E6C074FD0C
+:10031000F01203DA90E60474801203E47406120308
+:10032000E474001203E47406F5BBAAFFDAFE90E65B
+:10033000F574FF1203E4AAFFDAFEE5BB548060FA0D
+:10034000759DE41203DA759E001203DA759AF412B1
+:1003500003DA759B011203DA75AF071203DA7A200C
+:1003600090E67BE01203DA90E67CF01203DADAF032
+:1003700090E61A74091203E490E6C074FCF01203CC
+:10038000DA90E60474801203E474061203E4740045
+:100390001203E490E410E044FB90E6C21203E4751B
+:1003A000700190E6957400F01203DAF01203DAE5BA
+:1003B00091C2E4F59190E65F7420F0D007D006D0AA
+:1003C00005D004D003D002D001D000D0D0D0E0D0EE
+:1003D00085D084D083D082D0863200000000000017
+:0903E000000000221203DAF022F1
+:00000001FF