Browse Source

usbdux: usbduxsigma: fixed timing issues between ADC and DAC

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>
main
Bernd Porr 9 years ago committed by Kyle McMartin
parent
commit
75cc3ef8ba
  1. 119
      usbdux/usbduxsigma_firmware.asm

119
usbdux/usbduxsigma_firmware.asm

@ -30,17 +30,20 @@
.inc fx2-include.asm .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 CMD_FLAG,80h ; flag for the next in transfer
.equ PWMFLAG,81h ; PWM on or off? .equ PWMFLAG,81h ; PWM on or off?
.equ MAXSMPL,82H ; maximum number of samples, n channellist .equ MAXSMPL,82H ; maximum number of samples, n channellist
.equ MUXSG0,83H ; content of the MUXSG0 register .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 INTERVAL,88h ; uframe/frame interval
.equ INTCTR,89h ; interval counter .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 ;;; actual code
.org 0000h ; after reset the processor starts here .org 0000h ; after reset the processor starts here
@ -229,31 +232,24 @@ isr0:
push 06h ; R6 push 06h ; R6
push 07h ; R7 push 07h ; R7


mov r0,#ASYNC_ON mov a,ASYNC_ON
mov a,@r0
jz noepsubmit jz noepsubmit


mov DPS,#0 mov DPS,#0
mov r0,#DPTRL mov dpl,DPTRL
mov dpl,@r0 mov dph,DPTRH
inc r0
mov dph,@r0


lcall readADCch ; read one channel lcall readADCch ; read one channel


mov r0,#DPTRL mov DPTRL,dpl
mov @r0,dpl mov DPTRH,dph
inc r0
mov @r0,dph


mov r0,#SMPLCTR mov a,SMPLCTR
mov a,@r0
dec a dec a
mov @r0,a mov SMPLCTR,a
jnz noepsubmit jnz noepsubmit


mov r0,#ASYNC_ON mov ASYNC_ON,#0
mov @r0,#0


clr IOA.7 ; START = 0 clr IOA.7 ; START = 0
@ -303,9 +299,6 @@ main:
mov a,#00000011b ; allows skip mov a,#00000011b ; allows skip
lcall syncdelaywr 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 dptr,#INTSETUP ; IRQ setup register
mov a,#08h ; enable autovector mov a,#08h ; enable autovector
lcall syncdelaywr lcall syncdelaywr
@ -314,6 +307,9 @@ main:
mov a,#0 mov a,#0
lcall syncdelaywr 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 initAD ; init the ports to the converters


lcall initeps ; init the isochronous data-transfer lcall initeps ; init the isochronous data-transfer
@ -341,8 +337,10 @@ initAD:
mov r0,#MAXSMPL ; length of channellist mov r0,#MAXSMPL ; length of channellist
mov @r0,#0 ; we don't want to accumlate samples mov @r0,#0 ; we don't want to accumlate samples


mov r0,#ASYNC_ON ; async enable mov ASYNC_ON,#0 ; async enable
mov @r0,#0 ; we don't want to accumlate samples
mov r0,#DABUFFER
mov @r0,#0


mov OEA,#11100000b ; PortA7,A6,A5 Outputs mov OEA,#11100000b ; PortA7,A6,A5 Outputs
mov IOA,#01100000b ; /CS = 1 and START = 0 mov IOA,#01100000b ; /CS = 1 and START = 0
@ -589,8 +587,6 @@ sof_isr:
push 06h ; R6 push 06h ; R6
push 07h ; R7 push 07h ; R7


clr IE.7 ; make sure that no other int's disturbe us

mov r0,#INTCTR ; interval counter mov r0,#INTCTR ; interval counter
mov a,@r0 ; get the value mov a,@r0 ; get the value
dec a ; decrement dec a ; decrement
@ -631,18 +627,14 @@ sof_adc:
mov a,#0 ; just zero mov a,#0 ; just zero
movx @dptr,a ; pad it up movx @dptr,a ; pad it up
inc dptr ; algin along a 32 bit word inc dptr ; algin along a 32 bit word
mov r0,#DPTRL mov DPTRL,dpl
mov @r0,dpl mov DPTRH,dph
inc r0
mov @r0,dph


mov r0,#MAXSMPL mov r0,#MAXSMPL
mov a,@r0 mov a,@r0
mov r0,#SMPLCTR mov SMPLCTR,a
mov @r0,a


mov r0,#ASYNC_ON mov ASYNC_ON,#1
mov @r0,#1 ; enable data collection


epfull: epfull:
;; do the D/A conversion ;; do the D/A conversion
@ -659,6 +651,12 @@ 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 ;; clear INT2
mov a,EXIF ; FIRST clear the USB (INT2) interrupt request mov a,EXIF ; FIRST clear the USB (INT2) interrupt request
clr acc.4 clr acc.4
@ -669,8 +667,6 @@ epempty:
movx @DPTR,a movx @DPTR,a


nosof: nosof:
setb IE.7 ; re-enable global interrupts
pop 07h pop 07h
pop 06h pop 06h
pop 05h pop 05h
@ -795,8 +791,6 @@ ep1out_isr:
push 06h ; R6 push 06h ; R6
push 07h ; R7 push 07h ; R7


clr IE.7 ; block other interrupts
mov dptr,#0E780h ; FIFO buffer of EP1OUT mov dptr,#0E780h ; FIFO buffer of EP1OUT
movx a,@dptr ; get the first byte movx a,@dptr ; get the first byte
mov r0,#CMD_FLAG ; pointer to the command byte mov r0,#CMD_FLAG ; pointer to the command byte
@ -831,8 +825,7 @@ pwm_off:
sjmp over_da sjmp over_da


initsgADchannel: initsgADchannel:
mov r0,#ASYNC_ON mov ASYNC_ON,#0
mov @r0,#0 ; make sure that no async activity is on
mov dptr,#0e781h ; FIFO buffer of EP1OUT mov dptr,#0e781h ; FIFO buffer of EP1OUT
lcall configADC ; configures the ADC esp sel the channel lcall configADC ; configures the ADC esp sel the channel
@ -869,13 +862,11 @@ startadc2:
inc dptr inc dptr
mov r0,#MAXSMPL mov r0,#MAXSMPL
mov @r0,a ; length of the channel list mov @r0,a ; length of the channel list
mov r0,#SMPLCTR mov SMPLCTR,a
mov @r0,a


lcall configADC ; configures all registers lcall configADC ; configures all registers


mov r0,#ASYNC_ON ; async enable mov ASYNC_ON,#1 ; async enable
mov @r0,#1 ; enable it


lcall reset_ep6 ; reset FIFO lcall reset_ep6 ; reset FIFO
@ -958,8 +949,6 @@ over_da:
mov a,#00001000b ; clear the ep1outirq mov a,#00001000b ; clear the ep1outirq
movx @DPTR,a movx @DPTR,a


setb IE.7 ; re-enable interrupts

pop 07h pop 07h
pop 06h pop 06h
pop 05h pop 05h
@ -979,19 +968,45 @@ over_da:




;;; all channels ;;; save all DA channels from the endpoint buffer in a local buffer
dalo: dalo:
movx a,@dptr ; number of bytes to send out movx a,@dptr ; number of bytes to send out
inc dptr ; pointer to the first byte 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 mov r0,a ; counter
nextDA: nextDAlo:
movx a,@dptr ; get the byte movx a,@dptr ; get the byte
inc dptr ; point to the high 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 movx a,@dptr ; get the channel number
inc dptr ; get ready for the next channel 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 lcall writeDA ; write value to the DAC
pop 1 ; get the pointer back
djnz r0,nextDA ; next channel djnz r0,nextDA ; next channel
DAret:
ret ret




@ -1014,7 +1029,7 @@ writeDA3:
rr a ; shift to the upper to the lower rr a ; shift to the upper to the lower
djnz r1,writeDA3 djnz r1,writeDA3
orl a,r2 ; merge with the channel info 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 lcall sendSPI ; send it out to the SPI
mov a,r3 ; get data again mov a,r3 ; get data again
anl a,#00001111b ; get the lower nibble anl a,#00001111b ; get the lower nibble
@ -1024,7 +1039,7 @@ writeDA4:
djnz r1,writeDA4 djnz r1,writeDA4
anl a,#11110000b ; make sure that's empty anl a,#11110000b ; make sure that's empty
lcall sendSPI lcall sendSPI
setb IOA.6 ; /SYNC of the DA to 1 setb IOA.6 ; /SYNC (/CS) of the DA to 1
noDA: ret noDA: ret



Loading…
Cancel
Save