]> git.proxmox.com Git - mirror_linux-firmware.git/commitdiff
usbdux: usbduxsigma: fixed timing issues between ADC and DAC
authorBernd Porr <mail@berndporr.me.uk>
Wed, 22 Jul 2015 08:27:55 +0000 (09:27 +0100)
committerKyle McMartin <kyle@kernel.org>
Wed, 22 Jul 2015 17:40:55 +0000 (13:40 -0400)
When sync ADC and the DAC was running at the same time the ADC
showed spikes in the signal. This happened when just before the
DRDY from the ADC was triggered a DAC interrupt was dealt with.
ADC and DAC share the same SPI bus and priority is now given the
ADC. The DAC values are now first stored in a buffer and
are only send to the DAC once the ADC has finished
converting all channels (start = 0) so that the SPI bus is
definitely quiet for about 100us.

Signed-off-by: Bernd Porr <mail@berndporr.me.uk>
Signed-off-by: Kyle McMartin <kyle@kernel.org>
usbdux/usbduxsigma_firmware.asm

index 0bdadc2f27cddde078da7f058ecbe8f771a7fd73..38f5f0e84008d76628bb90a65afee8b1385680c9 100644 (file)
        
        .inc    fx2-include.asm
 
-;;; a couple of flags
+;;; a couple of flags in high memory
        .equ    CMD_FLAG,80h    ; flag for the next in transfer
        .equ    PWMFLAG,81h     ; PWM on or off?
        .equ    MAXSMPL,82H     ; maximum number of samples, n channellist
        .equ    MUXSG0,83H      ; content of the MUXSG0 register
-       .equ    SMPLCTR,84h
-       .equ    DPTRL,85H
-       .equ    DPTRH,86h
-       .equ    ASYNC_ON,87h
        .equ    INTERVAL,88h    ; uframe/frame interval
        .equ    INTCTR,89h      ; interval counter
+       .equ    DABUFFER,0F0h   ; buffer with DA values
+
+;;; in precious low memory but accessible within one clock cycle
+       .equ    DPTRL,70H
+       .equ    DPTRH,71h
+       .equ    ASYNC_ON,72h
+       .equ    SMPLCTR,73h
 
 ;;; actual code
        .org    0000h           ; after reset the processor starts here
@@ -229,31 +232,24 @@ isr0:
        push    06h             ; R6
        push    07h             ; R7
 
-       mov     r0,#ASYNC_ON
-       mov     a,@r0
+       mov     a,ASYNC_ON
        jz      noepsubmit
 
        mov     DPS,#0
-       mov     r0,#DPTRL
-       mov     dpl,@r0
-       inc     r0
-       mov     dph,@r0
+       mov     dpl,DPTRL
+       mov     dph,DPTRH
 
        lcall   readADCch       ; read one channel
 
-       mov     r0,#DPTRL
-       mov     @r0,dpl
-       inc     r0
-       mov     @r0,dph
+       mov     DPTRL,dpl
+       mov     DPTRH,dph
 
-       mov     r0,#SMPLCTR
-       mov     a,@r0
+       mov     a,SMPLCTR
        dec     a
-       mov     @r0,a
+       mov     SMPLCTR,a
        jnz     noepsubmit
 
-       mov     r0,#ASYNC_ON
-       mov     @r0,#0
+       mov     ASYNC_ON,#0
 
        clr     IOA.7           ; START = 0
        
@@ -303,9 +299,6 @@ main:
         mov     a,#00000011b    ; allows skip
         lcall   syncdelaywr
 
-       mov     IP,#0           ; all std 8051 int have low priority
-       mov     EIP,#0FFH       ; all FX2 interrupts have high priority
-       
        mov     dptr,#INTSETUP  ; IRQ setup register
        mov     a,#08h          ; enable autovector
        lcall   syncdelaywr
@@ -314,6 +307,9 @@ main:
        mov     a,#0
        lcall   syncdelaywr
 
+       mov     IP,#01H         ; int0 has highest interrupt priority
+       mov     EIP,#0          ; all USB interrupts have low priority
+
        lcall   initAD          ; init the ports to the converters
 
        lcall   initeps         ; init the isochronous data-transfer
@@ -341,8 +337,10 @@ initAD:
        mov     r0,#MAXSMPL     ; length of channellist
        mov     @r0,#0          ; we don't want to accumlate samples
 
-       mov     r0,#ASYNC_ON    ; async enable
-       mov     @r0,#0          ; we don't want to accumlate samples
+       mov     ASYNC_ON,#0     ; async enable
+
+       mov     r0,#DABUFFER
+       mov     @r0,#0
 
        mov     OEA,#11100000b  ; PortA7,A6,A5 Outputs
        mov     IOA,#01100000b  ; /CS = 1 and START = 0
@@ -589,8 +587,6 @@ sof_isr:
        push    06h             ; R6
        push    07h             ; R7
 
-       clr     IE.7            ; make sure that no other int's disturbe us
-
        mov     r0,#INTCTR      ; interval counter
        mov     a,@r0           ; get the value
        dec     a               ; decrement
@@ -631,18 +627,14 @@ sof_adc:
        mov     a,#0            ; just zero
        movx    @dptr,a         ; pad it up
        inc     dptr            ; algin along a 32 bit word
-       mov     r0,#DPTRL
-       mov     @r0,dpl
-       inc     r0
-       mov     @r0,dph
+       mov     DPTRL,dpl
+       mov     DPTRH,dph
 
        mov     r0,#MAXSMPL
        mov     a,@r0
-       mov     r0,#SMPLCTR
-       mov     @r0,a
+       mov     SMPLCTR,a
 
-       mov     r0,#ASYNC_ON
-       mov     @r0,#1          ; enable data collection
+       mov     ASYNC_ON,#1
 
 epfull:
        ;; do the D/A conversion
@@ -658,7 +650,13 @@ epfull:
        lcall   syncdelaywr     ; wait for the rec to sync
        lcall   syncdelaywr     ; wait for the rec to sync
 
-epempty:       
+epempty:
+       mov     a,IOA           ; conversion running?
+       jb      ACC.7,sofend
+
+       lcall   DAsend
+
+sofend:        
        ;; clear INT2
        mov     a,EXIF          ; FIRST clear the USB (INT2) interrupt request
        clr     acc.4
@@ -669,8 +667,6 @@ epempty:
        movx    @DPTR,a
 
 nosof:
-       setb    IE.7            ; re-enable global interrupts
-       
        pop     07h
        pop     06h
        pop     05h
@@ -795,8 +791,6 @@ ep1out_isr:
        push    06h             ; R6
        push    07h             ; R7
 
-       clr     IE.7            ; block other interrupts
-               
        mov     dptr,#0E780h    ; FIFO buffer of EP1OUT
        movx    a,@dptr         ; get the first byte
        mov     r0,#CMD_FLAG    ; pointer to the command byte
@@ -831,8 +825,7 @@ pwm_off:
        sjmp    over_da
 
 initsgADchannel:
-       mov     r0,#ASYNC_ON
-       mov     @r0,#0          ; make sure that no async activity is on
+       mov     ASYNC_ON,#0
        
        mov     dptr,#0e781h    ; FIFO buffer of EP1OUT
        lcall   configADC       ; configures the ADC esp sel the channel
@@ -869,13 +862,11 @@ startadc2:
        inc     dptr
        mov     r0,#MAXSMPL
        mov     @r0,a           ; length of the channel list
-       mov     r0,#SMPLCTR
-       mov     @r0,a
+       mov     SMPLCTR,a
 
        lcall   configADC       ; configures all registers
 
-       mov     r0,#ASYNC_ON    ; async enable
-       mov     @r0,#1          ; enable it
+       mov     ASYNC_ON,#1     ; async enable
 
        lcall   reset_ep6       ; reset FIFO
        
@@ -958,8 +949,6 @@ over_da:
        mov     a,#00001000b    ; clear the ep1outirq
        movx    @DPTR,a
 
-       setb    IE.7            ; re-enable interrupts
-
        pop     07h
        pop     06h
        pop     05h
@@ -979,19 +968,45 @@ over_da:
 
 
        
-;;; all channels
+;;; save all DA channels from the endpoint buffer in a local buffer
 dalo:
        movx    a,@dptr         ; number of bytes to send out
        inc     dptr            ; pointer to the first byte
+       mov     r1,#DABUFFER    ; buffer for DA values
+       mov     @r1,a           ; save it
+       inc     r1              ; inc pointer to local buffer
        mov     r0,a            ; counter
-nextDA:        
+nextDAlo:      
        movx    a,@dptr         ; get the byte
        inc     dptr            ; point to the high byte
-       mov     r3,a            ; store in r3 for writeDA
+       mov     @r1,a           ; save it in the buffer
+       inc     r1
        movx    a,@dptr         ; get the channel number
        inc     dptr            ; get ready for the next channel
+       mov     @r1,a           ; save it
+       inc     r1
+       djnz    r0,nextDAlo     ; next channel
+       ret
+
+
+;;; write to the DA converter
+DAsend:
+       mov     r1,#DABUFFER    ; buffer of the DA values
+       mov     a,@r1           ; get the channel count
+       jz      DAret           ; nothing to do
+       inc     r1              ; pointer to the first byte
+       mov     r0,a            ; counter
+nextDA:        
+       mov     a,@r1           ; get the byte
+       inc     r1              ; point to the high byte
+       mov     r3,a            ; store in r3 for writeDA
+       mov     a,@r1           ; get the channel number
+       inc     r1              ; get ready for the next channel
+       push    1               ; is modified in the subroutine
        lcall   writeDA         ; write value to the DAC
+       pop     1               ; get the pointer back
        djnz    r0,nextDA       ; next channel
+DAret: 
        ret
 
 
@@ -1014,7 +1029,7 @@ writeDA3:
        rr      a               ; shift to the upper to the lower
        djnz    r1,writeDA3
        orl     a,r2            ; merge with the channel info
-       clr     IOA.6           ; /SYNC of the DA to 0
+       clr     IOA.6           ; /SYNC (/CS) of the DA to 0
        lcall   sendSPI         ; send it out to the SPI
        mov     a,r3            ; get data again
        anl     a,#00001111b    ; get the lower nibble
@@ -1024,7 +1039,7 @@ writeDA4:
        djnz    r1,writeDA4
        anl     a,#11110000b    ; make sure that's empty
        lcall   sendSPI
-       setb    IOA.6           ; /SYNC of the DA to 1
+       setb    IOA.6           ; /SYNC (/CS) of the DA to 1
 noDA:  ret