Hello,
I'm trying to achieve a rather simple program with three steps.
- I initialize the SAADC to sample three channels (currently I only have one setup)
- I "arm/prepare" the ADC and a timer to control the SAADC samples via PPI
- SAADC samples n times until buffer is full, driven by the timer.
This setup seems to work if I first trigger a sample manually during the init phase, which I do not want to do.
Here is the initialization code, where adc_end_cb just prints the ADC event.
When I uncomment the nrfx_saadc_mode_trigger(); command, the PPI seems to work and collect samples. If it's commented, the callback is never invoked, as the ADC was disabled or similar.
int hw_adc_init(void (*cb)(void), uint16_t *buffer, size_t buffer_size){
nrfx_err_t err;
adc_end_cb_ptr = cb;
err = nrfx_saadc_init(5);
if(err != NRFX_SUCCESS){
LOG_ERR("Failed to initialize SAADC");
return err;
}
IRQ_CONNECT(DT_IRQN(SAADC_NODE), DT_IRQ(SAADC_NODE, priority), nrfx_isr, nrfx_saadc_irq_handler, 0);
nrfx_saadc_adv_config_t channel_config = NRFX_SAADC_DEFAULT_ADV_CONFIG;
channel_config.oversampling = NRF_SAADC_OVERSAMPLE_DISABLED;
channel_config.burst = NRF_SAADC_BURST_DISABLED;
channel_config.internal_timer_cc = 0; // if set to 0, TASK_SAMPLE must be triggered manually
channel_config.start_on_end = true; // seems to be a "restart" task a the end of sampling
// todo get pins from dts
nrfx_saadc_channel_t config = NRFX_SAADC_DEFAULT_CHANNEL_SE(NRF_SAADC_INPUT_AIN0, 0);
config.channel_config.reference = NRF_SAADC_REFERENCE_VDD4;
config.channel_config.gain = NRF_SAADC_GAIN1_4;
err = nrfx_saadc_channel_config(&config);
if(err != NRFX_SUCCESS){
LOG_ERR("Failed to configure SAADC channel");
return err;
}
err = nrfx_saadc_advanced_mode_set(0x01,
NRF_SAADC_RESOLUTION_10BIT,
&channel_config,
adc_end_cb);
if(err != NRFX_SUCCESS){
LOG_ERR("Failed to set SAADC advanced mode");
return err;
}
err = nrfx_saadc_buffer_set((nrf_saadc_value_t*)buffer, buffer_size);
if(err != NRFX_SUCCESS){
LOG_ERR("Failed to set SAADC buffer");
return err;
}
// err = nrfx_saadc_mode_trigger();
// if(err != NRFX_SUCCESS){
// LOG_ERR("Failed to trigger SAADC");
// return err;
// }
return 0;
}
Then I trigger the START task in software while preparing the timers etc
nrf_saadc_task_trigger(NRF_SAADC, NRF_SAADC_TASK_START);The PPI channel is connected with the SAMPLE task
err = nrfx_ppi_channel_assign(ppi_ch_adc_trigger,
nrfx_timer_event_address_get(&timer, NRF_TIMER_EVENT_COMPARE4),
nrf_saadc_task_address_get(NRF_SAADC, NRF_SAADC_TASK_SAMPLE));Maybe I have some confusion about the TASK and SAMPLE tasks? I thought the START would "prepare" the ADC for sampling, and the SAMPLE actually triggers one sample. Is this assumption wrong? Maybe I'm also mixing APIs a bit but the nrfx does not seem to have a good way of doing this.