diff options
| author | Keith Packard <keithp@keithp.com> | 2015-02-28 15:59:30 -0800 | 
|---|---|---|
| committer | Keith Packard <keithp@keithp.com> | 2015-02-28 16:10:10 -0800 | 
| commit | 27aef593fb4c037fdb65c9fb397829b42d72d0f2 (patch) | |
| tree | 2f486084b10b616ed7b9d12bc949908c5dd7aedc /src | |
| parent | ec2d758844202108b446e6b12ec1da8812ceb265 (diff) | |
altos/stmf0: Fix fast ADC interface
This was configuring the hardware wrong, and wasn't keeping the output
ring full.
Signed-off-by: Keith Packard <keithp@keithp.com>
Diffstat (limited to 'src')
| -rw-r--r-- | src/stmf0/ao_adc_fast.c | 31 | ||||
| -rw-r--r-- | src/stmf0/ao_adc_fast.h | 10 | 
2 files changed, 23 insertions, 18 deletions
diff --git a/src/stmf0/ao_adc_fast.c b/src/stmf0/ao_adc_fast.c index be9b5986..7d2a4fd7 100644 --- a/src/stmf0/ao_adc_fast.c +++ b/src/stmf0/ao_adc_fast.c @@ -18,43 +18,52 @@  #include <ao.h>  #include <ao_adc_fast.h> -uint16_t ao_adc_ring[AO_ADC_RING_SIZE]; +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; -uint8_t ao_adc_running; +uint16_t ao_adc_running;  /*   * Callback from DMA ISR   * - * Mark time in ring, shut down DMA engine + * Wakeup any waiting processes, mark the DMA as done, start the ADC + * if there's still lots of space in the ring   */  static void ao_adc_dma_done(int index)  {  	(void) index; -	ao_adc_ring_head += AO_ADC_RING_CHUNK; +	ao_adc_ring_head += ao_adc_running;  	if (ao_adc_ring_head == AO_ADC_RING_SIZE)  		ao_adc_ring_head = 0;  	ao_adc_running = 0;  	ao_wakeup(&ao_adc_ring_head);  	ao_dma_done_transfer(STM_DMA_INDEX(STM_DMA_CHANNEL_ADC_1)); +	_ao_adc_start();  }  void  _ao_adc_start(void)  {  	uint16_t	*buf; +	uint16_t	count;  	if (ao_adc_running)  		return; -	if (_ao_adc_space() < AO_ADC_RING_CHUNK) +	count = _ao_adc_space(); +	if (count == 0)  		return; -	ao_adc_running = 1; +	if (count > AO_ADC_RING_CHUNK) +		count = AO_ADC_RING_CHUNK; +	ao_adc_running = count;  	buf = ao_adc_ring + ao_adc_ring_head;  	stm_adc.isr = 0;  	ao_dma_set_transfer(STM_DMA_INDEX(STM_DMA_CHANNEL_ADC_1),  			    &stm_adc.dr,  			    buf, -			    AO_ADC_RING_CHUNK, +			    count,  			    (0 << STM_DMA_CCR_MEM2MEM) |  			    (STM_DMA_CCR_PL_HIGH << STM_DMA_CCR_PL) |  			    (STM_DMA_CCR_MSIZE_16 << STM_DMA_CCR_MSIZE) | @@ -140,7 +149,6 @@ ao_adc_init(void)  #if AO_NUM_ADC > 8  #error Need more ADC defines  #endif -	stm_adc.chselr = chselr;  	/* Set the clock */  	stm_adc.cfgr2 = STM_ADC_CFGR2_CKMODE_PCLK_2 << STM_ADC_CFGR2_CKMODE; @@ -160,14 +168,16 @@ ao_adc_init(void)  	while ((stm_adc.isr & (1 << STM_ADC_ISR_ADRDY)) == 0)  		; +	stm_adc.chselr = chselr; +  	stm_adc.cfgr1 = ((0 << STM_ADC_CFGR1_AWDCH) |  			 (0 << STM_ADC_CFGR1_AWDEN) |  			 (0 << STM_ADC_CFGR1_AWDSGL) |  			 (0 << STM_ADC_CFGR1_DISCEN) |  			 (0 << STM_ADC_CFGR1_AUTOOFF) | -			 (1 << STM_ADC_CFGR1_WAIT) | +			 (0 << STM_ADC_CFGR1_WAIT) |  			 (1 << STM_ADC_CFGR1_CONT) | -			 (0 << STM_ADC_CFGR1_OVRMOD) | +			 (1 << STM_ADC_CFGR1_OVRMOD) |  			 (STM_ADC_CFGR1_EXTEN_DISABLE << STM_ADC_CFGR1_EXTEN) |  			 (0 << STM_ADC_CFGR1_ALIGN) |  			 (STM_ADC_CFGR1_RES_12 << STM_ADC_CFGR1_RES) | @@ -186,5 +196,4 @@ ao_adc_init(void)  	stm_syscfg.cfgr1 &= ~(1 << STM_SYSCFG_CFGR1_ADC_DMA_RMP);  	ao_dma_alloc(STM_DMA_INDEX(STM_DMA_CHANNEL_ADC_1)); -	ao_dma_set_isr(STM_DMA_INDEX(STM_DMA_CHANNEL_ADC_1), ao_adc_dma_done);  } diff --git a/src/stmf0/ao_adc_fast.h b/src/stmf0/ao_adc_fast.h index eec45505..ca5f7fb9 100644 --- a/src/stmf0/ao_adc_fast.h +++ b/src/stmf0/ao_adc_fast.h @@ -26,15 +26,13 @@ ao_adc_init(void);  /* Total ring size in samples */  #define AO_ADC_RING_SIZE	256 -/* Number of samples fetched per ao_adc_start call */ -#define AO_ADC_RING_CHUNK	(AO_ADC_RING_SIZE >> 1)  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 uint8_t	ao_adc_running; +extern uint16_t	ao_adc_running;  void  _ao_adc_start(void); @@ -50,9 +48,7 @@ _ao_adc_remain(void)  static inline uint16_t  _ao_adc_space(void)  { -	if (ao_adc_ring_head == ao_adc_ring_tail) -		return AO_ADC_RING_SIZE; -	if (ao_adc_ring_head > ao_adc_ring_tail) +	if (ao_adc_ring_head >= ao_adc_ring_tail)  		return AO_ADC_RING_SIZE - ao_adc_ring_head;  	return ao_adc_ring_tail - ao_adc_ring_head;  } @@ -81,7 +77,7 @@ ao_adc_ack(uint16_t n)  	ao_adc_ring_tail += n;  	if (ao_adc_ring_tail == AO_ADC_RING_SIZE)  		ao_adc_ring_tail = 0; -	if (!ao_adc_running && _ao_adc_space() >= AO_ADC_RING_CHUNK) +	if (!ao_adc_running)  		_ao_adc_start();  	ao_arch_release_interrupts();  }  | 
