This post is older than 2 years and might not be relevant anymore
More Info: Consider searching for newer posts

SAADC is not scanning

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?

Related