Advertisement
cp-pum4

Untitled

Jun 19th, 2012
2,320
0
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
  1. ;   usbdux_firmware.asm
  2. ;   Copyright (C) 2004,2009 Bernd Porr, [email protected]
  3. ;   For usbdux.c
  4. ;
  5. ;   This program is free software; you can redistribute it and/or modify
  6. ;   it under the terms of the GNU General Public License as published by
  7. ;   the Free Software Foundation; either version 2 of the License, or
  8. ;   (at your option) any later version.
  9. ;
  10. ;   This program is distributed in the hope that it will be useful,
  11. ;   but WITHOUT ANY WARRANTY; without even the implied warranty of
  12. ;   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
  13. ;   GNU General Public License for more details.
  14. ;
  15. ;   You should have received a copy of the GNU General Public License
  16. ;   along with this program; if not, write to the Free Software
  17. ;   Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
  18. ;
  19. ;
  20. ; Firmware: usbdux_firmware.asm for usbdux.c
  21. ; Description: University of Stirling USB DAQ & INCITE Technology Limited
  22. ; Devices: [ITL] USB-DUX (usbdux.o)
  23. ; Author: Bernd Porr <[email protected]>
  24. ; Updated: 17 Apr 2009
  25. ; Status: stable
  26. ;
  27. ;;;
  28. ;;;
  29. ;;;
  30.  
  31.     .inc    fx2-include.asm
  32.  
  33.     .equ    CHANNELLIST,80h ; channellist in indirect memory
  34.    
  35.     .equ    CMD_FLAG,90h    ; flag if next IN transf is DIO
  36.     .equ    SGLCHANNEL,91h  ; channel for INSN
  37.     .equ    PWMFLAG,92h ; PWM
  38.    
  39.     .equ    DIOSTAT0,98h    ; last status of the digital port
  40.     .equ    DIOSTAT1,99h    ; same for the second counter
  41.    
  42.     .equ    CTR0,0A0H   ; counter 0
  43.     .equ    CTR1,0A2H   ; counter 1
  44.            
  45.     .org    0000h       ; after reset the processor starts here
  46.     ljmp    main        ; jump to the main loop
  47.  
  48.     .org    000bh       ; timer 0 irq
  49.     ljmp    timer0_isr
  50.  
  51.     .org    0043h       ; the IRQ2-vector
  52.     ljmp    jmptbl      ; irq service-routine
  53.    
  54.     .org    0100h       ; start of the jump table
  55.  
  56. jmptbl: ljmp    sudav_isr
  57.     nop
  58.     ljmp    sof_isr
  59.     nop
  60.     ljmp    sutok_isr
  61.     nop
  62.     ljmp    suspend_isr
  63.     nop
  64.     ljmp    usbreset_isr
  65.     nop
  66.     ljmp    hispeed_isr
  67.     nop
  68.     ljmp    ep0ack_isr
  69.     nop
  70.     ljmp    spare_isr
  71.     nop
  72.     ljmp    ep0in_isr
  73.     nop
  74.     ljmp    ep0out_isr
  75.     nop
  76.     ljmp    ep1in_isr
  77.     nop
  78.     ljmp    ep1out_isr
  79.     nop
  80.     ljmp    ep2_isr
  81.     nop
  82.     ljmp    ep4_isr
  83.     nop
  84.     ljmp    ep6_isr
  85.     nop
  86.     ljmp    ep8_isr
  87.     nop
  88.     ljmp    ibn_isr
  89.     nop
  90.     ljmp    spare_isr
  91.     nop
  92.     ljmp    ep0ping_isr
  93.     nop
  94.     ljmp    ep1ping_isr
  95.     nop
  96.     ljmp    ep2ping_isr
  97.     nop
  98.     ljmp    ep4ping_isr
  99.     nop
  100.     ljmp    ep6ping_isr
  101.     nop
  102.     ljmp    ep8ping_isr
  103.     nop
  104.     ljmp    errlimit_isr
  105.     nop
  106.     ljmp    spare_isr
  107.     nop
  108.     ljmp    spare_isr
  109.     nop
  110.     ljmp    spare_isr
  111.     nop
  112.     ljmp    ep2isoerr_isr
  113.     nop
  114.     ljmp    ep4isoerr_isr
  115.     nop
  116.     ljmp    ep6isoerr_isr
  117.     nop
  118.     ljmp    ep8isoerr_isr
  119.  
  120.    
  121.     ;; dummy isr
  122. sudav_isr: 
  123. sutok_isr: 
  124. suspend_isr:   
  125. usbreset_isr:  
  126. hispeed_isr:   
  127. ep0ack_isr:
  128. spare_isr: 
  129. ep0in_isr: 
  130. ep0out_isr:
  131. ep1in_isr: 
  132. ibn_isr:   
  133. ep0ping_isr:   
  134. ep1ping_isr:   
  135. ep2ping_isr:   
  136. ep4ping_isr:   
  137. ep6ping_isr:   
  138. ep8ping_isr:   
  139. errlimit_isr:  
  140. ep2isoerr_isr: 
  141. ep4isoerr_isr: 
  142. ep6isoerr_isr: 
  143. ep8isoerr_isr:
  144. ep6_isr:
  145. ep2_isr:
  146. ep4_isr:   
  147.  
  148.     push    dps
  149.     push    dpl
  150.     push    dph
  151.     push    dpl1
  152.     push    dph1
  153.     push    acc
  154.     push    psw
  155.  
  156.     ;; clear the USB2 irq bit and return
  157.     mov a,EXIF
  158.     clr acc.4
  159.     mov EXIF,a
  160.  
  161.     pop psw
  162.     pop acc
  163.     pop dph1
  164.     pop dpl1
  165.     pop dph
  166.     pop dpl
  167.     pop dps
  168.    
  169.     reti
  170.  
  171.        
  172. ;;; main program
  173. ;;; basically only initialises the processor and
  174. ;;; then engages in an endless loop
  175. main:
  176.     mov DPTR,#CPUCS ; CPU control register
  177.     mov a,#00010000b    ; 48Mhz
  178.     lcall   syncdelaywr
  179.  
  180.         mov     dptr,#REVCTL
  181.         mov     a,#00000011b    ; allows skip
  182.         lcall   syncdelaywr
  183.  
  184.     mov IP,#0       ; all std 8051 int have low priority
  185.     mov EIP,#0FFH   ; all FX2 interrupts have high priority
  186.    
  187.     mov dptr,#INTSETUP  ; IRQ setup register
  188.     mov a,#08h      ; enable autovector
  189.     lcall   syncdelaywr
  190.  
  191.     lcall   initAD      ; init the ports to the converters
  192.  
  193.     lcall   initeps     ; init the isochronous data-transfer
  194.  
  195.     lcall   init_timer
  196.    
  197. mloop2: nop
  198.  
  199. ;;; pwm
  200.     mov r0,#PWMFLAG ; pwm on?
  201.     mov a,@r0       ; get info
  202.     jz  mloop2      ; it's off
  203.  
  204.     mov a,GPIFTRIG  ; GPIF status
  205.     anl a,#80h      ; done bit
  206.     jz  mloop2      ; GPIF still busy
  207.  
  208.         mov     a,#01h      ; WR,EP4, 01 = EP4
  209.         mov     GPIFTRIG,; restart it
  210.  
  211.     sjmp    mloop2      ; loop for ever
  212.  
  213.  
  214. ;;; GPIF waveform for PWM
  215. waveform:
  216.     ;;      0     1     2     3     4     5     6     7(not used)
  217.     ;; len (gives 50.007Hz)
  218.     .db 195,  195,  195,  195,  195,  195,  1,    1
  219.  
  220.     ;; opcode
  221.     .db 002H, 006H, 002H, 002H, 002H, 002H, 002H, 002H
  222.    
  223.     ;; out
  224.     .db 0ffH, 0ffH, 0ffH, 0ffH, 0ffH, 0ffH, 0ffH, 0ffH
  225.  
  226.     ;; log
  227.     .db 000H, 000H, 000H, 000H, 000H, 000H, 000H, 000H
  228.  
  229.  
  230. stopPWM:
  231.     mov r0,#PWMFLAG ; flag for PWM
  232.     mov a,#0        ; PWM (for the main loop)
  233.     mov @r0,a       ; set it
  234.  
  235.     mov dptr,#IFCONFIG  ; switch off GPIF
  236.     mov a,#10000000b    ; gpif, 30MHz, internal IFCLK
  237.     lcall   syncdelaywr
  238.     ret
  239.    
  240.  
  241. ;;; init PWM
  242. startPWM:
  243.     mov dptr,#IFCONFIG  ; switch on IFCLK signal
  244.     mov a,#10000010b    ; gpif, 30MHz, internal IFCLK
  245.     lcall   syncdelaywr
  246.  
  247.     mov OEB,0FFH    ; output to port B
  248.  
  249.     mov DPTR,#EP4CFG
  250.     mov a,#10100000b    ; valid, out, bulk
  251.     movx    @DPTR,a
  252.  
  253.     ;; reset the endpoint
  254.     mov dptr,#FIFORESET
  255.     mov a,#80h      ; NAK
  256.     lcall   syncdelaywr
  257.     mov a,#84h      ; reset EP4 + NAK
  258.     lcall   syncdelaywr
  259.     mov a,#0        ; normal op
  260.     lcall   syncdelaywr
  261.  
  262.     mov dptr,#EP4BCL
  263.     mov a,#0H       ; discard packets
  264.     lcall   syncdelaywr ; empty FIFO buffer
  265.     lcall   syncdelaywr ; empty FIFO buffer
  266.  
  267.     ;; aborts all transfers by the GPIF
  268.     mov dptr,#GPIFABORT
  269.     mov a,#0ffh     ; abort all transfers
  270.     lcall   syncdelaywr
  271.  
  272.     ;; wait for GPIF to finish
  273. wait_f_abort:
  274.     mov a,GPIFTRIG  ; GPIF status
  275.     anl a,#80h      ; done bit
  276.     jz  wait_f_abort    ; GPIF busy
  277.  
  278.         mov     dptr,#GPIFCTLCFG
  279.         mov     a,#10000000b    ; tri state for CTRL
  280.         lcall   syncdelaywr
  281.  
  282.         mov     dptr,#GPIFIDLECTL
  283.         mov     a,#11110000b    ; all CTL outputs low
  284.         lcall   syncdelaywr
  285.  
  286.     ;; abort if FIFO is empty
  287.         mov     a,#00000001b    ; abort if empty
  288.         mov     dptr,#EP4GPIFFLGSEL
  289.         lcall   syncdelaywr
  290.  
  291.     ;;
  292.         mov     a,#00000001b    ; stop if GPIF flg
  293.         mov     dptr,#EP4GPIFPFSTOP
  294.         lcall   syncdelaywr
  295.  
  296.     ;; transaction counter
  297.     mov a,#0ffH
  298.     mov dptr,#GPIFTCB3
  299.     lcall   syncdelaywr
  300.  
  301.     ;; transaction counter
  302.     mov a,#0ffH
  303.     mov dptr,#GPIFTCB2
  304.     lcall   syncdelaywr
  305.  
  306.     ;; transaction counter
  307.     mov a,#0ffH     ; 512 bytes
  308.     mov dptr,#GPIFTCB1
  309.     lcall   syncdelaywr
  310.  
  311.     ;; transaction counter
  312.     mov a,#0ffH
  313.     mov dptr,#GPIFTCB0
  314.     lcall   syncdelaywr
  315.  
  316.     ;; RDY pins. Not used here.
  317.         mov     a,#0
  318.         mov     dptr,#GPIFREADYCFG
  319.         lcall   syncdelaywr
  320.  
  321.     ;; drives the output in the IDLE state
  322.         mov     a,#1
  323.         mov     dptr,#GPIFIDLECS
  324.         lcall   syncdelaywr
  325.  
  326.     ;; direct data transfer from the EP to the GPIF
  327.     mov dptr,#EP4FIFOCFG
  328.     mov a,#00010000b    ; autoout=1, byte-wide
  329.     lcall   syncdelaywr
  330.  
  331.     ;; waveform 0 is used for FIFO out
  332.     mov dptr,#GPIFWFSELECT
  333.     mov a,#00000000b
  334.     movx    @dptr,a
  335.     lcall   syncdelay
  336.  
  337.     ;; transfer the delay byte from the EP to the waveform
  338.     mov dptr,#0e781h    ; EP1 buffer
  339.     movx    a,@dptr     ; get the delay
  340.     mov dptr,#waveform  ; points to the waveform
  341.     mov r2,#6       ; fill 6 bytes
  342. timloop:
  343.     movx    @dptr,a     ; save timing in a xxx
  344.     inc dptr
  345.     djnz    r2,timloop  ; fill the 6 delay bytes
  346.  
  347.     ;; load waveform
  348.         mov     AUTOPTRH2,#0E4H ; XDATA0H
  349.         lcall   syncdelay
  350.         mov     AUTOPTRL2,#00H  ; XDATA0L
  351.         lcall   syncdelay
  352.  
  353.     mov dptr,#waveform  ; points to the waveform
  354.    
  355.         mov     AUTOPTRSETUP,#7 ; autoinc and enable
  356.         lcall   syncdelay
  357.  
  358.         mov     r2,#20H         ; 32 bytes to transfer
  359.  
  360. wavetr:
  361.         movx    a,@dptr
  362.     inc dptr
  363.     push    dpl
  364.     push    dph
  365.     push    dpl1
  366.     push    dph1
  367.         mov     dptr,#XAUTODAT2
  368.         movx    @dptr,a
  369.         lcall   syncdelay
  370.     pop dph1
  371.     pop dpl1
  372.     pop dph
  373.     pop dpl
  374.         djnz    r2,wavetr
  375.  
  376.     mov dptr,#OUTPKTEND
  377.     mov a,#084H
  378.     lcall   syncdelaywr
  379.     lcall   syncdelaywr
  380.  
  381.     mov r0,#PWMFLAG ; flag for PWM
  382.     mov a,#1        ; PWM (for the main loop)
  383.     mov @r0,a       ; set it
  384.  
  385.     ret
  386.  
  387.  
  388.  
  389. ;;; initialise the ports for the AD-converter
  390. initAD:
  391.     mov OEA,#27H    ;PortA0,A1,A2,A5 Outputs
  392.     mov IOA,#22H    ;/CS = 1, disable transfers to the converters
  393.     ret
  394.  
  395.  
  396. ;;; init the timer for the soft counters
  397. init_timer:
  398.     ;; init the timer for 2ms sampling rate
  399.     mov CKCON,#00000001b; CLKOUT/12 for timer
  400.     mov TL0,#010H   ; 16
  401.     mov TH0,#0H     ; 256
  402.     mov IE,#82H     ; switch on timer interrupt (80H for all IRQs)
  403.     mov TMOD,#00000000b ; 13 bit counters
  404.     setb    TCON.4      ; enable timer 0
  405.     ret
  406.  
  407.  
  408. ;;; from here it's only IRQ handling...
  409.    
  410. ;;; A/D-conversion:
  411. ;;; control-byte in a,
  412. ;;; result in r3(low) and r4(high)
  413. ;;; this routine is optimised for speed
  414. readAD:             ; mask the control byte
  415.     anl a,#01111100b    ; only the channel, gain+pol are left
  416.     orl a,#10000001b    ; start bit, external clock
  417.     ;; set CS to low
  418.     clr IOA.1       ; set /CS to zero
  419.     ;; send the control byte to the AD-converter
  420.     mov     R2,#8       ; bit-counter
  421. bitlp:  jnb     ACC.7,bitzero   ; jump if Bit7 = 0?
  422.     setb    IOA.2       ; set the DIN bit
  423.     sjmp    clock       ; continue with the clock
  424. bitzero:clr IOA.2       ; clear the DIN bit
  425. clock:  setb    IOA.0       ; SCLK = 1
  426.     clr IOA.0       ; SCLK = 0
  427.         rl      a               ; next Bit
  428.         djnz    R2,bitlp
  429.  
  430.     ;; continue the aquisition (already started)
  431.     clr IOA.2       ; clear the DIN bit
  432.     mov     R2,#5       ; five steps for the aquision
  433. clockaq:setb    IOA.0       ; SCLK = 1
  434.     clr IOA.0       ; SCLK = 0
  435.         djnz    R2,clockaq  ; loop
  436.    
  437.     ;; read highbyte from the A/D-converter
  438.     ;; and do the conversion
  439.     mov r4,#0       ; Highbyte goes into R4
  440.     mov R2,#4       ; COUNTER 4 data bits in the MSB
  441.     mov r5,#08h     ; create bit-mask
  442. gethi:              ; loop get the 8 highest bits from MSB downw
  443.     setb    IOA.0       ; SCLK = 1
  444.     clr IOA.0       ; SCLK = 0
  445.     mov a,IOA       ; from port A
  446.     jnb ACC.4,zerob ; the in-bit is zero
  447.     mov a,r4        ; get the byte
  448.     orl a,r5        ; or the bit to the result
  449.     mov r4,a        ; save it again in r4
  450. zerob:  mov a,r5        ; get r5 in order to shift the mask
  451.     rr  a       ; rotate right
  452.     mov r5,a        ; back to r5
  453.     djnz    R2,gethi
  454.     ;; read the lowbyte from the A/D-converter
  455.     mov r3,#0       ; Lowbyte goes into R3
  456.     mov r2,#8       ; COUNTER 8 data-bits in the LSB
  457.     mov r5,#80h     ; create bit-mask
  458. getlo:              ; loop get the 8 highest bits from MSB downw
  459.     setb    IOA.0       ; SCLK = 1
  460.     clr IOA.0       ; SCLK = 0
  461.     mov a,IOA       ; from port A
  462.     jnb ACC.4,zerob2    ; the in-bit is zero
  463.     mov a,r3        ; get the result-byte
  464.     orl a,r5        ; or the bit to the result
  465.     mov r3,a        ; save it again in r4
  466. zerob2: mov a,r5        ; get r5 in order to shift the mask
  467.     rr  a       ; rotate right
  468.     mov r5,a        ; back to r5
  469.     djnz    R2,getlo
  470.     setb    IOA.1       ; set /CS to one
  471.     ;;
  472.     ret
  473.    
  474.  
  475.    
  476. ;;; aquires data from A/D channels and stores them in the EP6 buffer
  477. conv_ad:
  478.     mov AUTOPTRH1,#0F8H ; auto pointer on EP6
  479.     mov AUTOPTRL1,#00H
  480.     mov AUTOPTRSETUP,#7
  481.     mov r0,#CHANNELLIST ; points to the channellist
  482.  
  483.     mov a,@r0       ; number of channels
  484.     mov r1,a        ; counter
  485.  
  486.     mov     DPTR,#XAUTODAT1 ; auto pointer
  487. convloop:
  488.     inc r0
  489.     mov     a,@r0       ; Channel
  490.     lcall   readAD
  491.     mov     a,R3        ;
  492.     movx    @DPTR,A
  493.     mov     a,R4        ;
  494.     movx    @DPTR,A
  495.     djnz    r1,convloop
  496.  
  497.     ret
  498.  
  499.  
  500.  
  501.  
  502. ;;; initilise the transfer
  503. ;;; It is assumed that the USB interface is in alternate setting 3
  504. initeps:
  505.     mov dptr,#FIFORESET
  506.     mov a,#80H     
  507.     movx    @dptr,a     ; reset all fifos
  508.     mov a,#2   
  509.     movx    @dptr,a     ;
  510.     mov a,#4       
  511.     movx    @dptr,a     ;
  512.     mov a,#6       
  513.     movx    @dptr,a     ;
  514.     mov a,#8       
  515.     movx    @dptr,a     ;
  516.     mov a,#0       
  517.     movx    @dptr,a     ; normal operat
  518.    
  519.     mov DPTR,#EP2CFG
  520.     mov a,#10010010b    ; valid, out, double buff, iso
  521.     movx    @DPTR,a
  522.  
  523.     mov dptr,#EP2FIFOCFG
  524.     mov a,#00000000b    ; manual
  525.     movx    @dptr,a
  526.  
  527.     mov dptr,#EP2BCL    ; "arm" it
  528.     mov a,#00h
  529.     movx    @DPTR,a     ; can receive data
  530.     lcall   syncdelay   ; wait to sync
  531.     movx    @DPTR,a     ; can receive data
  532.     lcall   syncdelay   ; wait to sync
  533.     movx    @DPTR,a     ; can receive data
  534.     lcall   syncdelay   ; wait to sync
  535.    
  536.     mov DPTR,#EP1OUTCFG
  537.     mov a,#10100000b    ; valid
  538.     movx    @dptr,a
  539.  
  540.     mov dptr,#EP1OUTBC  ; "arm" it
  541.     mov a,#00h
  542.     movx    @DPTR,a     ; can receive data
  543.     lcall   syncdelay   ; wait until we can write again
  544.     movx    @dptr,a     ; make shure its really empty
  545.     lcall   syncdelay   ; wait
  546.  
  547.     mov DPTR,#EP6CFG    ; ISO data from here to the host
  548.     mov a,#11010010b    ; Valid
  549.     movx    @DPTR,a     ; ISO transfer, double buffering
  550.  
  551.     mov DPTR,#EP8CFG    ; EP8
  552.     mov a,#11100000b    ; BULK data from here to the host
  553.     movx    @DPTR,a     ;
  554.  
  555.     mov dptr,#EPIE  ; interrupt enable
  556.     mov a,#10001000b    ; enable irq for ep1out,8
  557.     movx    @dptr,a     ; do it
  558.  
  559.     mov dptr,#EPIRQ ; clear IRQs
  560.     mov a,#10100000b
  561.     movx    @dptr,a
  562.  
  563.     ;; enable interrups
  564.         mov     DPTR,#USBIE ; USB int enables register
  565.         mov     a,#2            ; enables SOF (1ms/125us interrupt)
  566.         movx    @DPTR,a         ;
  567.  
  568.     mov EIE,#00000001b  ; enable INT2 in the 8051's SFR
  569.     mov IE,#80h     ; IE, enable all interrupts
  570.  
  571.     ret
  572.  
  573.  
  574. ;;; counter
  575. ;;; r0: DIOSTAT
  576. ;;; r1: counter address
  577. ;;; r2: up/down-mask
  578. ;;; r3: reset-mask
  579. ;;; r4: clock-mask
  580. counter:   
  581.     mov a,IOB       ; actual IOB input state
  582.     mov r5,a        ; save in r5
  583.     anl a,r3        ; bit mask for reset
  584.     jz  no_reset    ; reset if one
  585.     clr a       ; set counter to zero
  586.     mov @r1,a
  587.     inc r4
  588.     mov @r1,a
  589.     sjmp    ctr_end
  590. no_reset:  
  591.     mov a,@r0       ; get last state
  592.     xrl a,r5        ; has it changed?
  593.     anl a,r5        ; is it now on?
  594.     anl a,r4        ; mask out the port
  595.     jz  ctr_end     ; no rising edge
  596.     mov a,r5        ; get port B again
  597.     anl a,r2        ; test if up or down
  598.     jnz ctr_up      ; count up
  599.     mov a,@r1
  600.     dec a
  601.     mov @r1,a
  602.     cjne    a,#0ffh,ctr_end ; underflow?
  603.     inc r1      ; high byte
  604.     mov a,@r1
  605.     dec a
  606.     mov @r1,a
  607.     sjmp    ctr_end
  608. ctr_up:             ; count up
  609.     mov a,@r1
  610.     inc a
  611.     mov @r1,a
  612.     jnz ctr_end
  613.     inc r1      ; high byte
  614.     mov a,@r1
  615.     inc a
  616.     mov @r1,a
  617. ctr_end:
  618.     mov a,r5
  619.     mov @r0,a
  620.     ret
  621.  
  622. ;;; implements two soft counters with up/down and reset
  623. timer0_isr:
  624.     push    dps
  625.     push    acc
  626.     push    psw
  627.     push    00h     ; R0
  628.     push    01h     ; R1
  629.     push    02h     ; R2
  630.     push    03h     ; R3
  631.     push    04h     ; R4
  632.     push    05h     ; R5
  633.        
  634.     mov r0,#DIOSTAT0    ; status of port
  635.     mov r1,#CTR0    ; address of counter0
  636.     mov a,#00000001b    ; bit 0
  637.     mov r4,a        ; clock
  638.     rl  a       ; bit 1
  639.     mov r2,a        ; up/down
  640.     rl  a       ; bit 2
  641.     mov r3,a        ; reset mask
  642.     lcall   counter
  643.     inc r0      ; to DISTAT1
  644.     inc r1      ; to CTR1
  645.     inc r1
  646.     mov a,r3
  647.     rl  a       ; bit 3
  648.     rl  a       ; bit 4
  649.     mov r4,a        ; clock
  650.     rl  a       ; bit 5
  651.     mov r2,a        ; up/down
  652.     rl  a       ; bit 6
  653.     mov r3,a        ; reset
  654.     lcall   counter
  655.    
  656.     pop 05h     ; R5
  657.     pop 04h     ; R4
  658.     pop 03h     ; R3
  659.     pop 02h     ; R2
  660.     pop 01h     ; R1
  661.     pop 00h     ; R0
  662.     pop psw
  663.     pop acc
  664.     pop dps
  665.  
  666.     reti
  667.  
  668. ;;; interrupt-routine for SOF
  669. ;;; is for full speed
  670. sof_isr:
  671.     push    dps
  672.     push    dpl
  673.     push    dph
  674.     push    dpl1
  675.     push    dph1
  676.     push    acc
  677.     push    psw
  678.     push    00h     ; R0
  679.     push    01h     ; R1
  680.     push    02h     ; R2
  681.     push    03h     ; R3
  682.     push    04h     ; R4
  683.     push    05h     ; R5
  684.     push    06h     ; R6
  685.     push    07h     ; R7
  686.        
  687.     mov a,EP2468STAT
  688.     anl a,#20H      ; full?
  689.     jnz epfull      ; EP6-buffer is full
  690.  
  691.     lcall   conv_ad     ; conversion
  692.  
  693.     mov DPTR,#EP6BCH    ; byte count H
  694.     mov a,#0        ; is zero
  695.     lcall   syncdelaywr ; wait until we can write again
  696.    
  697.     mov DPTR,#EP6BCL    ; byte count L
  698.     mov a,#10H      ; is 8x word = 16 bytes
  699.     lcall   syncdelaywr ; wait until we can write again
  700.    
  701. epfull:
  702.     ;; do the D/A conversion
  703.     mov a,EP2468STAT
  704.     anl a,#01H      ; empty
  705.     jnz epempty     ; nothing to get
  706.  
  707.     mov dptr,#0F000H    ; EP2 fifo buffer
  708.     lcall   dalo        ; conversion
  709.  
  710.     mov dptr,#EP2BCL    ; "arm" it
  711.     mov a,#00h
  712.     lcall   syncdelaywr ; wait for the rec to sync
  713.     lcall   syncdelaywr ; wait for the rec to sync
  714.  
  715. epempty:   
  716.     ;; clear INT2
  717.     mov a,EXIF      ; FIRST clear the USB (INT2) interrupt request
  718.     clr acc.4
  719.     mov EXIF,a      ; Note: EXIF reg is not 8051 bit-addressable
  720.    
  721.     mov DPTR,#USBIRQ    ; points to the SOF
  722.     mov a,#2        ; clear the SOF
  723.     movx    @DPTR,a
  724.  
  725. nosof: 
  726.     pop 07h
  727.     pop 06h
  728.     pop 05h
  729.     pop 04h     ; R4
  730.     pop 03h     ; R3
  731.     pop 02h     ; R2
  732.     pop 01h     ; R1
  733.     pop 00h     ; R0
  734.     pop psw
  735.     pop acc
  736.     pop dph1
  737.     pop dpl1
  738.     pop dph
  739.     pop dpl
  740.     pop dps
  741.     reti
  742.  
  743.  
  744. reset_ep8:
  745.     ;; erase all data in ep8
  746.     mov dptr,#FIFORESET
  747.     mov a,#80H      ; NAK
  748.     lcall   syncdelaywr
  749.     mov dptr,#FIFORESET
  750.     mov a,#8        ; reset EP8
  751.     lcall   syncdelaywr
  752.     mov dptr,#FIFORESET
  753.     mov a,#0        ; normal operation
  754.     lcall   syncdelaywr
  755.     ret
  756.  
  757.  
  758. reset_ep6:
  759.     ;; throw out old data
  760.     mov dptr,#FIFORESET
  761.     mov a,#80H      ; NAK
  762.     lcall   syncdelaywr
  763.     mov dptr,#FIFORESET
  764.     mov a,#6        ; reset EP6
  765.     lcall   syncdelaywr
  766.     mov dptr,#FIFORESET
  767.     mov a,#0        ; normal operation
  768.     lcall   syncdelaywr
  769.     ret
  770.  
  771. ;;; interrupt-routine for ep1out
  772. ;;; receives the channel list and other commands
  773. ep1out_isr:
  774.     push    dps
  775.     push    dpl
  776.     push    dph
  777.     push    dpl1
  778.     push    dph1
  779.     push    acc
  780.     push    psw
  781.     push    00h     ; R0
  782.     push    01h     ; R1
  783.     push    02h     ; R2
  784.     push    03h     ; R3
  785.     push    04h     ; R4
  786.     push    05h     ; R5
  787.     push    06h     ; R6
  788.     push    07h     ; R7
  789.        
  790.     mov dptr,#0E780h    ; FIFO buffer of EP1OUT
  791.     movx    a,@dptr     ; get the first byte
  792.     mov r0,#CMD_FLAG    ; pointer to the command byte
  793.     mov     @r0,a       ; store the command byte for ep8
  794.  
  795.     mov dptr,#ep1out_jmp; jump table for the different functions
  796.     rl  a       ; multiply by 2: sizeof sjmp
  797.     jmp @a+dptr     ; jump to the jump table
  798.     ;; jump table, corresponds to the command bytes defined
  799.     ;; in usbdux.c
  800. ep1out_jmp:
  801.     sjmp    storechannellist; a=0
  802.     sjmp    single_da   ; a=1
  803.     sjmp    config_digital_b; a=2
  804.     sjmp    write_digital_b ; a=3
  805.     sjmp    storesglchannel ; a=4
  806.     sjmp    readcounter ; a=5
  807.     sjmp    writecounter    ; a=6
  808.     sjmp    pwm_on      ; a=7
  809.     sjmp    pwm_off     ; a=8
  810.  
  811. pwm_on:
  812.     lcall   startPWM
  813.     sjmp    over_da
  814.  
  815. pwm_off:
  816.     lcall   stopPWM
  817.     sjmp    over_da
  818.  
  819.     ;; read the counter
  820. readcounter:
  821.     lcall   reset_ep8   ; reset ep8
  822.     lcall   ep8_ops     ; fill the counter data in there
  823.     sjmp    over_da     ; jump to the end
  824.  
  825.     ;; write zeroes to the counters
  826. writecounter:
  827.     mov dptr,#0e781h    ; buffer
  828.     mov r0,#CTR0    ; r0 points to counter 0
  829.     movx    a,@dptr     ; channel number
  830.     jz  wrctr0      ; first channel
  831.     mov r1,a        ; counter
  832. wrctrl:
  833.     inc r0      ; next counter
  834.     inc r0      ; next counter
  835.     djnz    r1,wrctrl   ; advance to the right counter
  836. wrctr0:
  837.     inc dptr        ; get to the value
  838.     movx    a,@dptr     ; get value
  839.     mov @r0,a       ; save in ctr
  840.     inc r0      ; next byte
  841.     inc dptr
  842.     movx    a,@dptr     ; get value
  843.     mov @r0,a       ; save in ctr
  844.     sjmp    over_da     ; jump to the end
  845.  
  846. storesglchannel:
  847.     mov r0,#SGLCHANNEL  ; the conversion bytes are now stored in 80h
  848.     mov dptr,#0e781h    ; FIFO buffer of EP1OUT
  849.     movx    a,@dptr     ;
  850.     mov @r0,a
  851.  
  852.     lcall   reset_ep8   ; reset FIFO
  853.     ;; Save new A/D data in EP8. This is the first byte
  854.     ;; the host will read during an INSN. If there are
  855.     ;; more to come they will be handled by the ISR of
  856.     ;; ep8.
  857.     lcall   ep8_ops     ; get A/D data
  858.        
  859.     sjmp    over_da
  860.  
  861.    
  862. ;;; Channellist:
  863. ;;; the first byte is zero:
  864. ;;; we've just received the channel list
  865. ;;; the channel list is stored in the addresses from CHANNELLIST which
  866. ;;; are _only_ reachable by indirect addressing
  867. storechannellist:
  868.     mov r0,#CHANNELLIST ; the conversion bytes are now stored in 80h
  869.     mov r2,#9       ; counter
  870.     mov dptr,#0e781h    ; FIFO buffer of EP1OUT
  871. chanlloop: 
  872.     movx    a,@dptr     ;
  873.     mov @r0,a
  874.     inc dptr
  875.     inc r0
  876.     djnz    r2,chanlloop
  877.  
  878.     lcall   reset_ep6   ; reset FIFO
  879.    
  880.     ;; load new A/D data into EP6
  881.     ;; This must be done. Otherwise the ISR is never called.
  882.     ;; The ISR is only called when data has _left_ the
  883.     ;; ep buffer here it has to be refilled.
  884.     lcall   ep6_arm     ; fill with the first data byte
  885.    
  886.     sjmp    over_da
  887.  
  888. ;;; Single DA conversion. The 2 bytes are in the FIFO buffer
  889. single_da:
  890.     mov dptr,#0e781h    ; FIFO buffer of EP1OUT
  891.     lcall   dalo        ; conversion
  892.     sjmp    over_da
  893.  
  894. ;;; configure the port B as input or output (bitwise)
  895. config_digital_b:
  896.     mov dptr,#0e781h    ; FIFO buffer of EP1OUT
  897.     movx    a,@dptr     ; get the second byte
  898.     mov OEB,a       ; set the output enable bits
  899.     sjmp    over_da
  900.    
  901. ;;; Write one byte to the external digital port B
  902. ;;; and prepare for digital read
  903. write_digital_b:
  904.     mov dptr,#0e781h    ; FIFO buffer of EP1OUT
  905.     movx    a,@dptr     ; get the second byte
  906.     mov OEB,a       ; output enable
  907.     inc dptr        ; next byte
  908.     movx    a,@dptr     ; bits
  909.     mov IOB,a       ; send the byte to the I/O port
  910.  
  911.     lcall   reset_ep8   ; reset FIFO of ep 8
  912.  
  913.     ;; fill ep8 with new data from port B
  914.     ;; When the host requests the data it's already there.
  915.     ;; This must be so. Otherwise the ISR is not called.
  916.     ;; The ISR is only called when a packet has been delivered
  917.     ;; to the host. Thus, we need a packet here in the
  918.     ;; first instance.
  919.     lcall   ep8_ops     ; get digital data
  920.  
  921.     ;;
  922.     ;; for all commands the same
  923. over_da:   
  924.     mov dptr,#EP1OUTBC
  925.     mov a,#00h
  926.     lcall   syncdelaywr ; arm
  927.     lcall   syncdelaywr ; arm
  928.     lcall   syncdelaywr ; arm
  929.  
  930.     ;; clear INT2
  931.     mov a,EXIF      ; FIRST clear the USB (INT2) interrupt request
  932.     clr acc.4
  933.     mov EXIF,a      ; Note: EXIF reg is not 8051 bit-addressable
  934.  
  935.     mov DPTR,#EPIRQ ;
  936.     mov a,#00001000b    ; clear the ep1outirq
  937.     movx    @DPTR,a
  938.  
  939.     pop 07h
  940.     pop 06h
  941.     pop 05h
  942.     pop 04h     ; R4
  943.     pop 03h     ; R3
  944.     pop 02h     ; R2
  945.     pop 01h     ; R1
  946.     pop 00h     ; R0
  947.     pop psw
  948.     pop acc
  949.     pop dph1
  950.     pop dpl1
  951.     pop dph
  952.     pop dpl
  953.     pop dps
  954.     reti
  955.  
  956.  
  957.    
  958. ;;; all channels
  959. dalo:
  960.     movx    a,@dptr     ; number of channels
  961.     inc dptr        ; pointer to the first channel
  962.     mov r0,a        ; 4 channels
  963. nextDA:
  964.     movx    a,@dptr     ; get the first low byte
  965.     mov r3,a        ; store in r3 (see below)
  966.     inc dptr        ; point to the high byte
  967.     movx    a,@dptr     ; get the high byte
  968.     mov r4,a        ; store in r4 (for writeDA)
  969.     inc dptr        ; point to the channel number
  970.     movx    a,@dptr     ; get the channel number
  971.     inc dptr        ; get ready for the next channel
  972.     lcall   writeDA     ; write value to the DAC
  973.     djnz    r0,nextDA   ; next channel
  974.     ret
  975.  
  976.  
  977.  
  978. ;;; D/A-conversion:
  979. ;;; control-byte in a,
  980. ;;; value in r3(low) and r4(high)
  981. writeDA:            ; mask the control byte
  982.     anl a,#11000000b    ; only the channel is left
  983.     orl a,#00110000b    ; internal clock, bipolar mode, +/-5V
  984.     orl a,r4        ; or the value of R4 to it
  985.     ;; set CS to low
  986.     clr IOA.5       ; set /CS to zero
  987.     ;; send the first byte to the DA-converter
  988.     mov     R2,#8       ; bit-counter
  989. DA1:    jnb     ACC.7,zeroda    ; jump if Bit7 = 0?
  990.     setb    IOA.2       ; set the DIN bit
  991.     sjmp    clkda       ; continue with the clock
  992. zeroda: clr IOA.2       ; clear the DIN bit
  993. clkda:  setb    IOA.0       ; SCLK = 1
  994.     clr IOA.0       ; SCLK = 0
  995.         rl      a               ; next Bit
  996.         djnz    R2,DA1
  997.  
  998.    
  999.     ;; send the second byte to the DA-converter
  1000.     mov a,r3        ; low byte
  1001.     mov     R2,#8       ; bit-counter
  1002. DA2:    jnb     ACC.7,zeroda2   ; jump if Bit7 = 0?
  1003.     setb    IOA.2       ; set the DIN bit
  1004.     sjmp    clkda2      ; continue with the clock
  1005. zeroda2:clr IOA.2       ; clear the DIN bit
  1006. clkda2: setb    IOA.0       ; SCLK = 1
  1007.     clr IOA.0       ; SCLK = 0
  1008.         rl      a               ; next Bit
  1009.         djnz    R2,DA2
  1010.     ;;
  1011.     setb    IOA.5       ; set /CS to one
  1012.     ;;
  1013. noDA:   ret
  1014.    
  1015.  
  1016.  
  1017. ;;; arm ep6
  1018. ep6_arm:
  1019.     lcall   conv_ad
  1020.    
  1021.     mov DPTR,#EP6BCH    ; byte count H
  1022.     mov a,#0        ; is zero
  1023.     lcall   syncdelaywr ; wait until the length has arrived
  1024.    
  1025.     mov DPTR,#EP6BCL    ; byte count L
  1026.     mov a,#10H      ; is one
  1027.     lcall   syncdelaywr ; wait until the length has been proc
  1028.     ret
  1029.    
  1030.  
  1031.  
  1032. ;;; converts one analog/digital channel and stores it in EP8
  1033. ;;; also gets the content of the digital ports B and D depending on
  1034. ;;; the COMMAND flag
  1035. ep8_ops:
  1036.     mov dptr,#0fc01h    ; ep8 fifo buffer
  1037.     clr a       ; high byte
  1038.     movx    @dptr,a     ; set H=0
  1039.     mov dptr,#0fc00h    ; low byte
  1040.     mov r0,#CMD_FLAG
  1041.     mov a,@r0
  1042.     movx    @dptr,a     ; save command byte
  1043.  
  1044.     mov dptr,#ep8_jmp   ; jump table for the different functions
  1045.     rl  a       ; multiply by 2: sizeof sjmp
  1046.     jmp @a+dptr     ; jump to the jump table
  1047.     ;; jump table, corresponds to the command bytes defined
  1048.     ;; in usbdux.c
  1049. ep8_jmp:
  1050.     sjmp    ep8_err     ; a=0, err
  1051.     sjmp    ep8_err     ; a=1, err
  1052.     sjmp    ep8_err     ; a=2, err
  1053.     sjmp    ep8_dio     ; a=3, digital read
  1054.     sjmp    ep8_sglchannel  ; a=4, analog A/D
  1055.     sjmp    ep8_readctr ; a=5, read counter
  1056.     sjmp    ep8_err     ; a=6, write counter
  1057.  
  1058.     ;; reads all counters
  1059. ep8_readctr:
  1060.     mov r0,#CTR0    ; points to counter0
  1061.     mov dptr,#0fc02h    ; ep8 fifo buffer
  1062.     mov r1,#8       ; transfer 4 16bit counters
  1063. ep8_ctrlp:
  1064.     mov a,@r0       ; get the counter
  1065.     movx    @dptr,a     ; save in the fifo buffer
  1066.     inc r0      ; inc pointer to the counters
  1067.     inc dptr        ; inc pointer to the fifo buffer
  1068.     djnz    r1,ep8_ctrlp    ; loop until ready
  1069.    
  1070.     sjmp    ep8_send    ; send the data
  1071.    
  1072.     ;; read one A/D channel
  1073. ep8_sglchannel:    
  1074.     mov r0,#SGLCHANNEL  ; points to the channel
  1075.     mov     a,@r0       ; Ch0
  1076.    
  1077.     lcall   readAD      ; start the conversion
  1078.        
  1079.     mov     DPTR,#0fc02h    ; EP8 FIFO
  1080.     mov     a,R3        ; get low byte
  1081.     movx    @DPTR,A     ; store in FIFO
  1082.     inc dptr        ; next fifo entry
  1083.     mov     a,R4        ; get high byte
  1084.     movx    @DPTR,A     ; store in FIFO
  1085.  
  1086.     sjmp    ep8_send    ; send the data
  1087.  
  1088.     ;; read the digital lines
  1089. ep8_dio:   
  1090.     mov     DPTR,#0fc02h    ; store the contents of port B
  1091.     mov a,IOB       ; in the next
  1092.     movx    @dptr,a     ; entry of the buffer
  1093.  
  1094.     inc dptr
  1095.     clr a       ; high byte is zero
  1096.     movx    @dptr,a     ; next byte of the EP
  1097.    
  1098. ep8_send:  
  1099.     mov DPTR,#EP8BCH    ; byte count H
  1100.     mov a,#0        ; is zero
  1101.     lcall   syncdelaywr
  1102.    
  1103.     mov DPTR,#EP8BCL    ; byte count L
  1104.     mov a,#10H      ; 16 bytes
  1105.     lcall   syncdelaywr ; send the data over to the host
  1106.  
  1107. ep8_err:   
  1108.     ret
  1109.  
  1110.  
  1111.  
  1112. ;;; EP8 interrupt: gets one measurement from the AD converter and
  1113. ;;; sends it via EP8. The channel # is stored in address 80H.
  1114. ;;; It also gets the state of the digital registers B and D.
  1115. ep8_isr:   
  1116.     push    dps
  1117.     push    dpl
  1118.     push    dph
  1119.     push    dpl1
  1120.     push    dph1
  1121.     push    acc
  1122.     push    psw
  1123.     push    00h     ; R0
  1124.     push    01h     ; R1
  1125.     push    02h     ; R2
  1126.     push    03h     ; R3
  1127.     push    04h     ; R4
  1128.     push    05h     ; R5
  1129.     push    06h     ; R6
  1130.     push    07h     ; R7
  1131.        
  1132.     lcall   ep8_ops
  1133.    
  1134.     ;; clear INT2
  1135.     mov a,EXIF      ; FIRST clear the USB (INT2) interrupt request
  1136.     clr acc.4
  1137.     mov EXIF,a      ; Note: EXIF reg is not 8051 bit-addressable
  1138.  
  1139.     mov DPTR,#EPIRQ ;
  1140.     mov a,#10000000b    ; clear the ep8irq
  1141.     movx    @DPTR,a
  1142.  
  1143.     pop 07h
  1144.     pop 06h
  1145.     pop 05h
  1146.     pop 04h     ; R4
  1147.     pop 03h     ; R3
  1148.     pop 02h     ; R2
  1149.     pop 01h     ; R1
  1150.     pop 00h     ; R0
  1151.     pop psw
  1152.     pop acc
  1153.     pop dph1
  1154.     pop dpl1
  1155.     pop dph
  1156.     pop dpl
  1157.     pop dps
  1158.     reti
  1159.  
  1160.  
  1161. ;; need to delay every time the byte counters
  1162. ;; for the EPs have been changed.
  1163.  
  1164. syncdelay:
  1165.     nop
  1166.     nop
  1167.     nop
  1168.     nop
  1169.     nop
  1170.     nop
  1171.     nop
  1172.     nop
  1173.     nop
  1174.     ret
  1175.  
  1176. syncdelaywr:
  1177.     movx    @dptr,a
  1178.     lcall   syncdelay
  1179.     ret
  1180.  
  1181.  
  1182. .End
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement