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.