I have made an ADC driver that (should) scan 5 inputs into a sample buffer using EasyDMA. On the END event the 5 samples are transferred to 5 ring buffers read by the client using an os_read() function.
The sample time pr. channel is 12kHz.
I get the correct amount of samples, so the setup seems right.
However, each sample buffer, which I expected to hold 1 sample pr. each of the 5 channels, only holds samples for CH[0].
ADC initialization:
bool_t driver_adc_init( void )
{
adc_client = PID_INVALID;
// Analog input mapping - setup to fit board
SAADC_CH[0].PSELP = AIN1;
SAADC_CH[1].PSELP = AIN2;
SAADC_CH[2].PSELP = AIN3;
SAADC_CH[3].PSELP = AIN4;
SAADC_CH[4].PSELP = AIN0;
// Analog input configuration
SAADC_CH[0].CONFIG = RESP_PULLDOWN | RESN_BYPASS | GAIN1_4 | REFSEL_VDD1_4 | TACQ_10US | MODE_SE | BURST_DISABLED;
SAADC_CH[1].CONFIG = RESP_PULLDOWN | RESN_BYPASS | GAIN1_4 | REFSEL_VDD1_4 | TACQ_10US | MODE_SE | BURST_DISABLED;
SAADC_CH[2].CONFIG = RESP_PULLDOWN | RESN_BYPASS | GAIN1_4 | REFSEL_VDD1_4 | TACQ_10US | MODE_SE | BURST_DISABLED;
SAADC_CH[3].CONFIG = RESP_PULLDOWN | RESN_BYPASS | GAIN1_4 | REFSEL_VDD1_4 | TACQ_10US | MODE_SE | BURST_DISABLED;
SAADC_CH[4].CONFIG = RESP_PULLDOWN | RESN_BYPASS | GAIN1_4 | REFSEL_VDD1_4 | TACQ_10US | MODE_SE | BURST_DISABLED;
return true;
}
START ADC:
void driver_adc_set_ioctl( ioctl_id_t id, ioctl_t ioctl )
{
switch( id )
{
case DRIVER_ADC_IOCTL_START:
if( ioctl )
{
memset( dma_sample_buf, 0, sizeof( dma_sample_buf ));
memset( read_ring_buf, 0, sizeof( read_ring_buf ));
ovfl_mask = 0;
current_dma_buffer = 0;
read_since_event = 1;
SAADC_RESULT->PTR = ( uint32_t *)&dma_sample_buf[current_dma_buffer][0];
SAADC_RESULT->MAXCNT = NOF_SCAN_CHANNELS;
SAADC_INTENSET = INT_STARTED | INT_END | INT_STOPPED | INT_CALIBRATEDONE;
SAADC_SAMPLERATE = ( 1 << 12 ) | 266; // Sample rate 16 MHz / ( 5 x 266) = 12030 Hz.
SAADC_ENABLE = 1;
NVIC_SetPriority( SAADC_IRQ_NO, SAADC_IRQ_LEVEL );
NVIC_ClearPendingIRQ( SAADC_IRQ_NO );
NVIC_EnableIRQ( SAADC_IRQ_NO );
//SAADC_TASKS_CALIBRATEOFFSE = 1;
SAADC_TASKS_START = 1;
adc_client = os_get_pid();
}
else
{
SAADC_TASKS_STOP = 1;
}
break;
case DRIVER_ADC_IOCTL_OVERFLOW_MASK:
ovfl_mask = ioctl;
break;
default:
break;
}
}
IRQ HANDLER:
void SAADC_IRQHandler( void )
{
if( SAADC_EVENTS_STARTED > 0 )
{
SAADC_EVENTS_STARTED = 0;
uint8_t next_buf = current_dma_buffer + 1 >= NOF_DMA_BUFFERS ?
0 : current_dma_buffer + 1; // Next DMA buffer
SAADC_RESULT->PTR = ( uint32_t *)&dma_sample_buf[next_buf][0];
// We only want to handle start event the first time
SAADC_INTENCLR = INT_STARTED;
// If CALIBRATEDDON event is enabled - we are just starting
if( SAADC_INTEN & INT_CALIBRATEDONE )
{
SAADC_TASKS_SAMPLE = 1;
SAADC_INTENCLR = INT_CALIBRATEDONE;
}
}
if( SAADC_EVENTS_END > 0 )
{
SAADC_EVENTS_END = 0;
if( read_since_event )
{
os_isr_status_bits_set( DEVHDL_ADC, ISR_STATUS_SAMPLES_READY );
read_since_event = 0;
}
// Transfer samples to read buffers
uint8_t ch;
for( ch = 0; ch < NOF_SCAN_CHANNELS; ch++ )
{
uint8_t nextwp = read_ring_buf[ch].wp + 1 == NOF_READ_SAMPLES ?
0 : read_ring_buf[ch].wp + 1;
if( nextwp == read_ring_buf[ch].rp )
{
if( ( ovfl_mask & ( 1 << ch )) == 0 )
{
// Overflow was not signalled for this channel - so do it
ovfl_mask |= ( 1 << ch );
os_isr_status_bits_set( DEVHDL_ADC, ISR_STATUS_BUFFER_OVERFLOW );
}
}
else
{
read_ring_buf[ch].sample_buf[nextwp] = dma_sample_buf[current_dma_buffer][ch];
read_ring_buf[ch].wp = nextwp;
}
}
current_dma_buffer = current_dma_buffer + 1 == NOF_DMA_BUFFERS ? 0 : current_dma_buffer + 1;
SAADC_TASKS_START = 1;
}
if( SAADC_EVENTS_CALIBRATEDON > 0 )
{
SAADC_EVENTS_CALIBRATEDON = 0;
SAADC_TASKS_START = 1;
}
if( SAADC_EVENTS_STOPPED > 0 )
{
SAADC_EVENTS_STOPPED = 0;
SAADC_ENABLE = 0;
NVIC_DisableIRQ( SAADC_IRQ_NO );
}
}
What am I not getting?