From dba12691ae605787b2bad5e5b0f00ac4c8da3f12 Mon Sep 17 00:00:00 2001 From: Bernd Porr Date: Wed, 22 Jul 2015 09:26:32 +0100 Subject: usbdux: usbduxsigma: changed firmware from ADC polling to IRQ processing In order to prepare the firmware to work with the EHCI driver the ADC data acquisition is now done by triggering the acquisition with a start of frame interrupt (SOF) and then the collection of the data is done via "data ready" interrupts until all data has been received. Once this has happend then the whole packet is dispatched and at the next SOF the next packet is dispatched. If there are SOF interrupts happening during the data acquisiton it is no longer interupted and only send out the next ISO packet once it has comleted its job. Also now the USBDUXSIGMA has now plenty of time to deal with other interrupts between ADC data readouts so that for example the DIO can now be handled much quicker. Signed-off-by: Bernd Porr Signed-off-by: Kyle McMartin --- usbdux/usbduxsigma_firmware.asm | 160 +++++++++++++++++++++++++++++++--------- 1 file changed, 125 insertions(+), 35 deletions(-) (limited to 'usbdux') diff --git a/usbdux/usbduxsigma_firmware.asm b/usbdux/usbduxsigma_firmware.asm index e363991..a8094f2 100644 --- a/usbdux/usbduxsigma_firmware.asm +++ b/usbdux/usbduxsigma_firmware.asm @@ -1,5 +1,5 @@ ; usbdux_firmware.asm -; Copyright (C) 2010,2011,2015 Bernd Porr, mail@berndporr.me.uk +; Copyright (C) 2010,2011 Bernd Porr, Bernd.Porr@f2s.com ; For usbduxsigma.c 0.5+ ; ; This program is free software; you can redistribute it and/or modify @@ -20,8 +20,8 @@ ; Firmware: usbduxsigma_firmware.asm for usbduxsigma.c ; Description: University of Stirling USB DAQ & INCITE Technology Limited ; Devices: [ITL] USB-DUX-SIGMA (usbduxsigma.ko) -; Author: Bernd Porr -; Updated: 25 Jun 2015 +; Author: Bernd Porr +; Updated: 24 Jul 2011 ; Status: testing ; ;;; @@ -35,14 +35,21 @@ .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 ;;; actual code .org 0000h ; after reset the processor starts here ljmp main ; jump to the main loop + .org 0003h + ljmp isr0 ; external interrupt 0: /DRY + .org 0043h ; the IRQ2-vector ljmp jmptbl ; irq service-routine - + .org 0100h ; start of the jump table jmptbl: ljmp sudav_isr @@ -160,6 +167,85 @@ ep4_isr: reti +;;; this is triggered when DRY goes low +isr0: + 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 r0,#ASYNC_ON + mov a,@r0 + jz noepsubmit + + mov DPS,#0 + mov r0,#DPTRL + mov dpl,@r0 + inc r0 + mov dph,@r0 + + lcall readADCch ; read one channel + + mov r0,#DPTRL + mov @r0,dpl + inc r0 + mov @r0,dph + + mov r0,#SMPLCTR + mov a,@r0 + dec a + mov @r0,a + jnz noepsubmit + + mov r0,#ASYNC_ON + mov @r0,#0 + + clr IOA.7 ; START = 0 + + ;; arm the endpoint and send off the data + mov DPTR,#EP6BCH ; byte count H + mov a,#0 ; is zero + lcall syncdelaywr ; wait until we can write again + + mov r0,#MAXSMPL ; number of samples to transmit + mov a,@r0 ; get them + rl a ; a=a*2 + rl a ; a=a*2 + add a,#4 ; four bytes for DIO + mov DPTR,#EP6BCL ; byte count L + lcall syncdelaywr ; wait until we can write again + +noepsubmit: + 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 + + ;;; main program ;;; basically only initialises the processor and @@ -211,6 +297,9 @@ 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 OEA,#11100000b ; PortA7,A6,A5 Outputs mov IOA,#01100000b ; /CS = 1 and START = 0 mov dptr,#IFCONFIG ; switch on clock on IFCLK pin @@ -379,6 +468,10 @@ initeps: mov a,#11100000b ; BULK data from here to the host movx @DPTR,a ; + mov dptr,#PORTACFG + mov a,#1 ; interrupt on pin A0 + lcall syncdelaywr + ;; enable interrupts mov dptr,#EPIE ; interrupt enable mov a,#10001000b ; enable irq for ep1out,8 @@ -392,8 +485,10 @@ initeps: mov a,#2 ; enables SOF (1ms/125us interrupt) movx @DPTR,a ; + setb TCON.0 ; make INT0 edge triggered, falling edge + mov EIE,#00000001b ; enable INT2/USBINT in the 8051's SFR - mov IE,#80h ; IE, enable all interrupts + mov IE,#81h ; IE, enable all interrupts and INT0 ret @@ -401,10 +496,6 @@ initeps: ;;; Reads one ADC channel from the converter and stores ;;; the result at dptr readADCch: - ;; we do polling: we wait until DATA READY is zero - mov a,IOA ; get /DRDY - jb ACC.0,readADCch ; wait until data ready (DRDY=0) - ;; reading data is done by just dropping /CS and start reading and ;; while keeping the IN signal to the ADC inactive clr IOA.5 ; /cs to 0 @@ -460,7 +551,8 @@ sof_isr: anl a,#20H ; full? jnz epfull ; EP6-buffer is full - clr IOA.7 ; stop converter, START = 0 + mov a,IOA ; conversion running? + jb ACC.7,epfull ;; make sure that we are starting with the first channel mov r0,#MUXSG0 ; @@ -471,8 +563,6 @@ sof_isr: setb IOA.7 ; start converter, START = 1 - ;; get the data from the ADC as fast as possible and transfer it - ;; to the EP buffer mov dptr,#0f800h ; EP6 buffer mov a,IOD ; get DIO D movx @dptr,a ; store it @@ -486,30 +576,18 @@ sof_isr: 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 r0,#MAXSMPL ; number of samples to transmit - mov a,@r0 ; get them - mov r1,a ; counter - - ;; main loop, get all the data -eptrans: - lcall readADCch ; get one reading - djnz r1,eptrans ; do until we have all content transf'd + mov r0,#MAXSMPL + mov a,@r0 + mov r0,#SMPLCTR + mov @r0,a - clr IOA.7 ; stop converter, START = 0 - - ;; arm the endpoint and send off the data - mov DPTR,#EP6BCH ; byte count H - mov a,#0 ; is zero - lcall syncdelaywr ; wait until we can write again - - mov r0,#MAXSMPL ; number of samples to transmit - mov a,@r0 ; get them - rl a ; a=a*2 - rl a ; a=a*2 - add a,#4 ; four bytes for DIO - mov DPTR,#EP6BCL ; byte count L - lcall syncdelaywr ; wait until we can write again + mov r0,#ASYNC_ON + mov @r0,#1 ; enable data collection epfull: ;; do the D/A conversion @@ -697,6 +775,9 @@ pwm_off: sjmp over_da initsgADchannel: + mov r0,#ASYNC_ON + mov @r0,#0 ; make sure that no async activity is on + mov dptr,#0e781h ; FIFO buffer of EP1OUT lcall configADC ; configures the ADC esp sel the channel @@ -719,9 +800,14 @@ startadc: inc dptr mov r0,#MAXSMPL mov @r0,a ; length of the channel list + mov r0,#SMPLCTR + mov @r0,a lcall configADC ; configures all registers + mov r0,#ASYNC_ON ; async enable + mov @r0,#1 ; enable it + lcall reset_ep6 ; reset FIFO ;; load new A/D data into EP6 @@ -915,8 +1001,12 @@ ep8_jmp: ;; read one A/D channel ep8_sglchannel: - mov DPTR,#0fc01h ; EP8 FIFO setb IOA.7 ; start converter, START = 1 + ;; we do polling: we wait until DATA READY is zero +sglchwait: + mov a,IOA ; get /DRDY + jb ACC.0,sglchwait ; wait until data ready (DRDY=0) + mov DPTR,#0fc01h ; EP8 FIFO lcall readADCch ; get one reading clr IOA.7 ; stop the converter, START = 0 -- cgit v1.2.1