From: Keith Packard Date: Fri, 20 Mar 2015 22:09:20 +0000 (-0700) Subject: altos/stmf0: Have fast ADC ring buffer code use wrap-around X-Git-Tag: 1.6.0.3~94 X-Git-Url: https://git.gag.com/?p=fw%2Faltos;a=commitdiff_plain;h=b1b69c8b73cbffb56c688f6a968d144b642cdff2 altos/stmf0: Have fast ADC ring buffer code use wrap-around Instead of requiring that the whole set of returned values fit precisely in the ring, allow for wrap-around so that we can fetch an odd number of ADC values. The previous version required that the fetch amount always be a factor of the ADC buffer size. Signed-off-by: Keith Packard --- diff --git a/src/drivers/ao_trng.c b/src/drivers/ao_trng.c index db742928..e69cd30b 100644 --- a/src/drivers/ao_trng.c +++ b/src/drivers/ao_trng.c @@ -29,7 +29,8 @@ ao_trng_fetch(void) int usb_buf_id; uint16_t i; uint16_t *buf; - uint32_t *rnd; + uint16_t t; + uint32_t *rnd = (uint32_t *) ao_adc_ring; if (!buffer[0]) { buffer[0] = ao_usb_alloc(); @@ -50,10 +51,12 @@ ao_trng_fetch(void) ao_led_on(AO_LED_TRNG_READ); while (count--) { - rnd = (uint32_t *) ao_adc_get(AO_USB_IN_SIZE); /* one 16-bit value per output byte */ + t = ao_adc_get(AO_USB_IN_SIZE) >> 1; /* one 16-bit value per output byte */ buf = buffer[usb_buf_id]; - for (i = 0; i < AO_USB_IN_SIZE / sizeof (uint16_t); i++) - *buf++ = ao_crc_in_32_out_16(*rnd++); + for (i = 0; i < AO_USB_IN_SIZE / sizeof (uint16_t); i++) { + *buf++ = ao_crc_in_32_out_16(rnd[t]); + t = (t + 1) & ((AO_ADC_RING_SIZE>>1) - 1); + } ao_adc_ack(AO_USB_IN_SIZE); ao_led_toggle(AO_LED_TRNG_READ|AO_LED_TRNG_WRITE); ao_usb_write(buffer[usb_buf_id], AO_USB_IN_SIZE); diff --git a/src/drivers/ao_trng_send.c b/src/drivers/ao_trng_send.c index 34a8a981..bac6035c 100644 --- a/src/drivers/ao_trng_send.c +++ b/src/drivers/ao_trng_send.c @@ -27,7 +27,8 @@ ao_trng_send(void) int usb_buf_id; uint16_t i; uint16_t *buf; - uint32_t *rnd; + uint16_t t; + uint32_t *rnd = (uint32_t *) ao_adc_ring; if (!buffer[0]) { buffer[0] = ao_usb_alloc(); @@ -42,10 +43,12 @@ ao_trng_send(void) for (;;) { ao_led_on(AO_LED_TRNG_ACTIVE); - rnd = (uint32_t *) ao_adc_get(AO_USB_IN_SIZE); /* one 16-bit value per output byte */ + t = ao_adc_get(AO_USB_IN_SIZE) >> 1; /* one 16-bit value per output byte */ buf = buffer[usb_buf_id]; - for (i = 0; i < AO_USB_IN_SIZE / sizeof (uint16_t); i++) - *buf++ = ao_crc_in_32_out_16(*rnd++); + for (i = 0; i < AO_USB_IN_SIZE / sizeof (uint16_t); i++) { + *buf++ = ao_crc_in_32_out_16(rnd[t]); + t = (t + 1) & ((AO_ADC_RING_SIZE>>1) - 1); + } ao_adc_ack(AO_USB_IN_SIZE); ao_led_off(AO_LED_TRNG_ACTIVE); ao_usb_write(buffer[usb_buf_id], AO_USB_IN_SIZE); diff --git a/src/stmf0/ao_adc_fast.c b/src/stmf0/ao_adc_fast.c index 7d2a4fd7..26e6691c 100644 --- a/src/stmf0/ao_adc_fast.c +++ b/src/stmf0/ao_adc_fast.c @@ -23,7 +23,7 @@ uint16_t ao_adc_ring[AO_ADC_RING_SIZE] __attribute__((aligned(4))); /* Maximum number of samples fetched per _ao_adc_start call */ #define AO_ADC_RING_CHUNK (AO_ADC_RING_SIZE >> 1) -uint16_t ao_adc_ring_head, ao_adc_ring_tail; +uint16_t ao_adc_ring_head, ao_adc_ring_remain; uint16_t ao_adc_running; /* @@ -36,6 +36,7 @@ static void ao_adc_dma_done(int index) { (void) index; ao_adc_ring_head += ao_adc_running; + ao_adc_ring_remain += ao_adc_running; if (ao_adc_ring_head == AO_ADC_RING_SIZE) ao_adc_ring_head = 0; ao_adc_running = 0; diff --git a/src/stmf0/ao_adc_fast.h b/src/stmf0/ao_adc_fast.h index ca5f7fb9..c6903e9f 100644 --- a/src/stmf0/ao_adc_fast.h +++ b/src/stmf0/ao_adc_fast.h @@ -31,52 +31,53 @@ extern uint16_t ao_adc_ring[AO_ADC_RING_SIZE]; #define ao_adc_ring_step(pos,inc) (((pos) + (inc)) & (AO_ADC_RING_SIZE - 1)) -extern uint16_t ao_adc_ring_head, ao_adc_ring_tail; +extern uint16_t ao_adc_ring_head, ao_adc_ring_remain; extern uint16_t ao_adc_running; -void -_ao_adc_start(void); - +/* + * Place to start fetching values from + */ static inline uint16_t -_ao_adc_remain(void) +ao_adc_ring_tail(void) { - if (ao_adc_ring_tail > ao_adc_ring_head) - return AO_ADC_RING_SIZE - ao_adc_ring_tail; - return ao_adc_ring_head - ao_adc_ring_tail; + return (ao_adc_ring_head - ao_adc_ring_remain) & (AO_ADC_RING_SIZE - 1); } +void +_ao_adc_start(void); + +/* + * Space available to write ADC values into + */ static inline uint16_t _ao_adc_space(void) { - if (ao_adc_ring_head >= ao_adc_ring_tail) + /* Free to end of buffer? */ + if (ao_adc_ring_remain <= ao_adc_ring_head) return AO_ADC_RING_SIZE - ao_adc_ring_head; - return ao_adc_ring_tail - ao_adc_ring_head; + + /* no, return just the unused entries beyond head */ + return AO_ADC_RING_SIZE - ao_adc_ring_remain; } -static inline uint16_t * +static inline uint16_t ao_adc_get(uint16_t n) { - if (ao_adc_ring_tail + n > AO_ADC_RING_SIZE) - ao_panic(AO_PANIC_ADC); ao_arch_block_interrupts(); - while (_ao_adc_remain() < n) { + while (ao_adc_ring_remain < n) { if (!ao_adc_running) _ao_adc_start(); ao_sleep(&ao_adc_ring_head); } ao_arch_release_interrupts(); - return &ao_adc_ring[ao_adc_ring_tail]; + return ao_adc_ring_tail(); } static inline void ao_adc_ack(uint16_t n) { - if (ao_adc_ring_tail + n > AO_ADC_RING_SIZE) - ao_panic(AO_PANIC_ADC); ao_arch_block_interrupts(); - ao_adc_ring_tail += n; - if (ao_adc_ring_tail == AO_ADC_RING_SIZE) - ao_adc_ring_tail = 0; + ao_adc_ring_remain -= n; if (!ao_adc_running) _ao_adc_start(); ao_arch_release_interrupts();