44 * SPDX-License-Identifier: Apache-2.0
55 */
66
7- #define ADC_CONTEXT_USES_KERNEL_TIMER
87#include "adc_context.h"
98#include <nrfx_saadc.h>
109#include <zephyr/dt-bindings/adc/nrf-saadc-v3.h>
@@ -104,15 +103,20 @@ struct driver_data {
104103 uint8_t active_channel_cnt ;
105104 void * mem_reg ;
106105 void * user_buffer ;
106+ struct k_timer timer ;
107+ bool internal_timer_enabled ;
107108};
108109
109110static struct driver_data m_data = {
110- ADC_CONTEXT_INIT_TIMER (m_data , ctx ),
111111 ADC_CONTEXT_INIT_LOCK (m_data , ctx ),
112112 ADC_CONTEXT_INIT_SYNC (m_data , ctx ),
113113 .mem_reg = DMM_DEV_TO_REG (DT_NODELABEL (adc )),
114+ .internal_timer_enabled = false,
114115};
115116
117+ /* Maximum value of the internal timer interval in microseconds. */
118+ #define ADC_INTERNAL_TIMER_INTERVAL_MAX_US 128U
119+
116120/* Forward declaration */
117121static void event_handler (const nrfx_saadc_evt_t * event );
118122
@@ -385,22 +389,55 @@ static void adc_context_start_sampling(struct adc_context *ctx)
385389
386390static void adc_context_update_buffer_pointer (struct adc_context * ctx , bool repeat )
387391{
388- void * samples_buffer ;
392+ if (!m_data .internal_timer_enabled ) {
393+ void * samples_buffer ;
394+
395+ if (!repeat ) {
396+ m_data .user_buffer =
397+ (uint16_t * )m_data .user_buffer + m_data .active_channel_cnt ;
398+ }
389399
390- if (!repeat ) {
391- m_data .user_buffer = (uint16_t * )m_data .user_buffer + m_data .active_channel_cnt ;
400+ int error = dmm_buffer_in_prepare (
401+ m_data .mem_reg , m_data .user_buffer ,
402+ NRFX_SAADC_SAMPLES_TO_BYTES (m_data .active_channel_cnt ), & samples_buffer );
403+ if (error != 0 ) {
404+ LOG_ERR ("DMM buffer allocation failed err=%d" , error );
405+ adc_context_complete (ctx , - EIO );
406+ }
407+
408+ nrfx_err_t nrfx_err =
409+ nrfx_saadc_buffer_set (samples_buffer , m_data .active_channel_cnt );
410+ if (nrfx_err != NRFX_SUCCESS ) {
411+ LOG_ERR ("Failed to set buffer: %08x" , nrfx_err );
412+ adc_context_complete (ctx , - EIO );
413+ }
392414 }
415+ }
393416
394- int error = dmm_buffer_in_prepare (
395- m_data .mem_reg , m_data .user_buffer ,
396- NRFX_SAADC_SAMPLES_TO_BYTES (m_data .active_channel_cnt ),
397- & samples_buffer );
398- if (error != 0 ) {
399- LOG_ERR ("DMM buffer allocation failed err=%d" , error );
400- adc_context_complete (ctx , - EIO );
417+ static inline void adc_context_enable_timer (struct adc_context * ctx )
418+ {
419+ if (!m_data .internal_timer_enabled ) {
420+ k_timer_start (& m_data .timer , K_NO_WAIT , K_USEC (ctx -> options .interval_us ));
421+ } else {
422+ nrfx_err_t ret = nrfx_saadc_mode_trigger ();
423+
424+ if (ret != NRFX_SUCCESS ) {
425+ LOG_ERR ("Cannot start sampling: %d" , ret );
426+ adc_context_complete (& m_data .ctx , - EIO );
427+ }
401428 }
429+ }
430+
431+ static inline void adc_context_disable_timer (struct adc_context * ctx )
432+ {
433+ if (!m_data .internal_timer_enabled ) {
434+ k_timer_stop (& m_data .timer );
435+ }
436+ }
402437
403- nrfx_saadc_buffer_set (samples_buffer , m_data .active_channel_cnt );
438+ static void adc_context_on_timer_expired (struct k_timer * timer_id )
439+ {
440+ adc_context_request_next_sampling (& m_data .ctx );
404441}
405442
406443static int get_resolution (const struct adc_sequence * sequence , nrf_saadc_resolution_t * resolution )
@@ -490,31 +527,70 @@ static int check_buffer_size(const struct adc_sequence *sequence, uint8_t active
490527 return 0 ;
491528}
492529
530+ static inline void single_ended_channel_cut_negative_sample (uint16_t channel_bit ,
531+ uint8_t single_ended_channels ,
532+ int16_t * * sample )
533+ {
534+ if ((channel_bit & single_ended_channels ) && (* sample < 0 )) {
535+ * * sample = 0 ;
536+ }
537+
538+ (* sample )++ ;
539+ }
540+
493541static bool has_single_ended (const struct adc_sequence * sequence )
494542{
495543 return sequence -> channels & m_data .single_ended_channels ;
496544}
497545
498- static void correct_single_ended (const struct adc_sequence * sequence , nrf_saadc_value_t * buffer )
546+ static void correct_single_ended (const struct adc_sequence * sequence ,
547+ nrf_saadc_value_t * buffer ,
548+ uint16_t buffer_size )
499549{
500- uint16_t channel_bit = BIT (0 );
501550 uint8_t selected_channels = sequence -> channels ;
502551 uint8_t single_ended_channels = m_data .single_ended_channels ;
503552 int16_t * sample = (int16_t * )buffer ;
504553
505- while (channel_bit <= single_ended_channels ) {
506- if (channel_bit & selected_channels ) {
507- if ((channel_bit & single_ended_channels ) && (* sample < 0 )) {
508- * sample = 0 ;
554+ for (uint16_t channel_bit = BIT (0 ); channel_bit <= single_ended_channels ;
555+ channel_bit <<= 1 ) {
556+ if (!(channel_bit & selected_channels )) {
557+ continue ;
558+ }
559+
560+ if (m_data .internal_timer_enabled ) {
561+ if (!(channel_bit & single_ended_channels )) {
562+ continue ;
509563 }
510564
511- sample ++ ;
565+ for (int i = 0 ; i < buffer_size ; i ++ ) {
566+ if (sample [i ] < 0 ) {
567+ sample [i ] = 0 ;
568+ }
569+ }
570+ } else {
571+ single_ended_channel_cut_negative_sample (channel_bit ,
572+ single_ended_channels ,
573+ & sample );
512574 }
513-
514- channel_bit <<= 1 ;
515575 }
516576}
517577
578+ /* The internal timer runs at 16 MHz, so to convert the interval in microseconds
579+ * to the internal timer CC value, we can use the formula:
580+ * interval_cc = interval_us * 16 MHz
581+ * where 16 MHz is the frequency of the internal timer.
582+ *
583+ * The maximum value for interval_cc is 2047, which corresponds to
584+ * approximately 7816 Hz ~ 128us.
585+ * The minimum value for interval_cc is depends on the SoC.
586+ */
587+ static inline uint16_t interval_to_cc (uint16_t interval_us )
588+ {
589+ NRFX_ASSERT ((interval_us <= ADC_INTERNAL_TIMER_INTERVAL_MAX_US ) && (interval_us > 0 ));
590+
591+ return (interval_us * 16 ) - 1 ;
592+ }
593+
518594static int start_read (const struct device * dev ,
519595 const struct adc_sequence * sequence )
520596{
@@ -562,10 +638,32 @@ static int start_read(const struct device *dev,
562638 return error ;
563639 }
564640
565- nrfx_err = nrfx_saadc_simple_mode_set (selected_channels ,
566- resolution ,
567- oversampling ,
568- event_handler );
641+ if ((active_channel_cnt == 1 ) &&
642+ (sequence -> options -> interval_us <= ADC_INTERNAL_TIMER_INTERVAL_MAX_US ) &&
643+ (sequence -> options -> interval_us > 0 )) {
644+
645+ nrfx_saadc_adv_config_t adv_config = {
646+ .oversampling = oversampling ,
647+ .burst = NRF_SAADC_BURST_DISABLED ,
648+ .internal_timer_cc = interval_to_cc (sequence -> options -> interval_us ),
649+ .start_on_end = true,
650+ };
651+
652+ m_data .internal_timer_enabled = true;
653+
654+ nrfx_err = nrfx_saadc_advanced_mode_set (selected_channels ,
655+ resolution ,
656+ & adv_config ,
657+ event_handler );
658+ } else {
659+ m_data .internal_timer_enabled = false;
660+
661+ nrfx_err = nrfx_saadc_simple_mode_set (selected_channels ,
662+ resolution ,
663+ oversampling ,
664+ event_handler );
665+ }
666+
569667 if (nrfx_err != NRFX_SUCCESS ) {
570668 return - EINVAL ;
571669 }
@@ -578,9 +676,11 @@ static int start_read(const struct device *dev,
578676 m_data .active_channel_cnt = active_channel_cnt ;
579677 m_data .user_buffer = sequence -> buffer ;
580678
581- error = dmm_buffer_in_prepare (m_data .mem_reg ,
582- m_data .user_buffer ,
583- NRFX_SAADC_SAMPLES_TO_BYTES (active_channel_cnt ),
679+ error = dmm_buffer_in_prepare (m_data .mem_reg , m_data .user_buffer ,
680+ (m_data .internal_timer_enabled
681+ ? (NRFX_SAADC_SAMPLES_TO_BYTES (active_channel_cnt ) *
682+ (1 + sequence -> options -> extra_samplings ))
683+ : NRFX_SAADC_SAMPLES_TO_BYTES (active_channel_cnt )),
584684 & samples_buffer );
585685 if (error != 0 ) {
586686 LOG_ERR ("DMM buffer allocation failed err=%d" , error );
@@ -590,7 +690,15 @@ static int start_read(const struct device *dev,
590690 /* Buffer is filled in chunks, each chunk composed of number of samples equal to number
591691 * of active channels. Buffer pointer is advanced and reloaded after each chunk.
592692 */
593- nrfx_saadc_buffer_set (samples_buffer , active_channel_cnt );
693+ nrfx_err = nrfx_saadc_buffer_set (
694+ samples_buffer ,
695+ (m_data .internal_timer_enabled
696+ ? (active_channel_cnt * (1 + sequence -> options -> extra_samplings ))
697+ : active_channel_cnt ));
698+ if (nrfx_err != NRFX_SUCCESS ) {
699+ LOG_ERR ("Failed to set buffer: %08x" , nrfx_err );
700+ return - EINVAL ;
701+ }
594702
595703 adc_context_start_read (& m_data .ctx , sequence );
596704
@@ -633,11 +741,17 @@ static void event_handler(const nrfx_saadc_evt_t *event)
633741 if (event -> type == NRFX_SAADC_EVT_DONE ) {
634742 dmm_buffer_in_release (
635743 m_data .mem_reg , m_data .user_buffer ,
636- NRFX_SAADC_SAMPLES_TO_BYTES (m_data .active_channel_cnt ),
744+ (m_data .internal_timer_enabled
745+ ? (NRFX_SAADC_SAMPLES_TO_BYTES (
746+ m_data .active_channel_cnt ) *
747+ (1 + m_data .ctx .sequence .options -> extra_samplings ))
748+ : NRFX_SAADC_SAMPLES_TO_BYTES (
749+ m_data .active_channel_cnt )),
637750 event -> data .done .p_buffer );
638751
639752 if (has_single_ended (& m_data .ctx .sequence )) {
640- correct_single_ended (& m_data .ctx .sequence , m_data .user_buffer );
753+ correct_single_ended (& m_data .ctx .sequence , m_data .user_buffer ,
754+ event -> data .done .size );
641755 }
642756 adc_context_on_sampling_done (& m_data .ctx , DEVICE_DT_INST_GET (0 ));
643757 } else if (event -> type == NRFX_SAADC_EVT_CALIBRATEDONE ) {
@@ -646,13 +760,17 @@ static void event_handler(const nrfx_saadc_evt_t *event)
646760 LOG_ERR ("Cannot start sampling: 0x%08x" , err );
647761 adc_context_complete (& m_data .ctx , - EIO );
648762 }
763+ } else if (event -> type == NRFX_SAADC_EVT_FINISHED ) {
764+ adc_context_complete (& m_data .ctx , 0 );
649765 }
650766}
651767
652768static int init_saadc (const struct device * dev )
653769{
654770 nrfx_err_t err ;
655771
772+ k_timer_init (& m_data .timer , adc_context_on_timer_expired , NULL );
773+
656774 /* The priority value passed here is ignored (see nrfx_glue.h). */
657775 err = nrfx_saadc_init (0 );
658776 if (err != NRFX_SUCCESS ) {
0 commit comments