4
4
* SPDX-License-Identifier: Apache-2.0
5
5
*/
6
6
7
- #define ADC_CONTEXT_USES_KERNEL_TIMER
8
7
#include "adc_context.h"
9
8
#include <nrfx_saadc.h>
10
9
#include <zephyr/dt-bindings/adc/nrf-saadc-v3.h>
@@ -104,15 +103,20 @@ struct driver_data {
104
103
uint8_t active_channel_cnt ;
105
104
void * mem_reg ;
106
105
void * user_buffer ;
106
+ struct k_timer timer ;
107
+ bool internal_timer_enabled ;
107
108
};
108
109
109
110
static struct driver_data m_data = {
110
- ADC_CONTEXT_INIT_TIMER (m_data , ctx ),
111
111
ADC_CONTEXT_INIT_LOCK (m_data , ctx ),
112
112
ADC_CONTEXT_INIT_SYNC (m_data , ctx ),
113
113
.mem_reg = DMM_DEV_TO_REG (DT_NODELABEL (adc )),
114
+ .internal_timer_enabled = false,
114
115
};
115
116
117
+ /* Maximum value of the internal timer interval in microseconds. */
118
+ #define ADC_INTERNAL_TIMER_INTERVAL_MAX_US 128U
119
+
116
120
/* Forward declaration */
117
121
static void event_handler (const nrfx_saadc_evt_t * event );
118
122
@@ -385,22 +389,57 @@ static void adc_context_start_sampling(struct adc_context *ctx)
385
389
386
390
static void adc_context_update_buffer_pointer (struct adc_context * ctx , bool repeat )
387
391
{
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
+ }
399
+
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
+ }
389
407
390
- if (!repeat ) {
391
- m_data .user_buffer = (uint16_t * )m_data .user_buffer + m_data .active_channel_cnt ;
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
+ }
392
414
}
415
+ }
393
416
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
+ }
401
428
}
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
+ }
437
+
438
+ static void adc_context_on_timer_expired (struct k_timer * timer_id )
439
+ {
440
+ ARG_UNUSED (timer_id );
402
441
403
- nrfx_saadc_buffer_set ( samples_buffer , m_data .active_channel_cnt );
442
+ adc_context_request_next_sampling ( & m_data .ctx );
404
443
}
405
444
406
445
static int get_resolution (const struct adc_sequence * sequence , nrf_saadc_resolution_t * resolution )
@@ -490,31 +529,68 @@ static int check_buffer_size(const struct adc_sequence *sequence, uint8_t active
490
529
return 0 ;
491
530
}
492
531
532
+ static inline void single_ended_channel_cut_negative_sample (uint16_t channel_bit ,
533
+ uint8_t single_ended_channels ,
534
+ int16_t * * sample )
535
+ {
536
+ if ((channel_bit & single_ended_channels ) && (* sample < 0 )) {
537
+ * * sample = 0 ;
538
+ }
539
+
540
+ (* sample )++ ;
541
+ }
542
+
493
543
static bool has_single_ended (const struct adc_sequence * sequence )
494
544
{
495
545
return sequence -> channels & m_data .single_ended_channels ;
496
546
}
497
547
498
- static void correct_single_ended (const struct adc_sequence * sequence , nrf_saadc_value_t * buffer )
548
+ static void correct_single_ended (const struct adc_sequence * sequence , nrf_saadc_value_t * buffer ,
549
+ uint16_t buffer_size )
499
550
{
500
- uint16_t channel_bit = BIT (0 );
501
551
uint8_t selected_channels = sequence -> channels ;
502
552
uint8_t single_ended_channels = m_data .single_ended_channels ;
503
553
int16_t * sample = (int16_t * )buffer ;
504
554
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 ;
555
+ for (uint16_t channel_bit = BIT (0 ); channel_bit <= single_ended_channels ;
556
+ channel_bit <<= 1 ) {
557
+ if (!(channel_bit & selected_channels )) {
558
+ continue ;
559
+ }
560
+
561
+ if (m_data .internal_timer_enabled ) {
562
+ if (!(channel_bit & single_ended_channels )) {
563
+ continue ;
509
564
}
510
565
511
- sample ++ ;
566
+ for (int i = 0 ; i < buffer_size ; i ++ ) {
567
+ if (sample [i ] < 0 ) {
568
+ sample [i ] = 0 ;
569
+ }
570
+ }
571
+ } else {
572
+ single_ended_channel_cut_negative_sample (channel_bit , single_ended_channels ,
573
+ & sample );
512
574
}
513
-
514
- channel_bit <<= 1 ;
515
575
}
516
576
}
517
577
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
+
518
594
static int start_read (const struct device * dev ,
519
595
const struct adc_sequence * sequence )
520
596
{
@@ -562,10 +638,28 @@ static int start_read(const struct device *dev,
562
638
return error ;
563
639
}
564
640
565
- nrfx_err = nrfx_saadc_simple_mode_set (selected_channels ,
566
- resolution ,
567
- oversampling ,
568
- event_handler );
641
+ if ((active_channel_cnt == 1 ) && (sequence -> options != NULL ) &&
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 , resolution , & adv_config ,
655
+ event_handler );
656
+ } else {
657
+ m_data .internal_timer_enabled = false;
658
+
659
+ nrfx_err = nrfx_saadc_simple_mode_set (selected_channels , resolution , oversampling ,
660
+ event_handler );
661
+ }
662
+
569
663
if (nrfx_err != NRFX_SUCCESS ) {
570
664
return - EINVAL ;
571
665
}
@@ -578,9 +672,11 @@ static int start_read(const struct device *dev,
578
672
m_data .active_channel_cnt = active_channel_cnt ;
579
673
m_data .user_buffer = sequence -> buffer ;
580
674
581
- error = dmm_buffer_in_prepare (m_data .mem_reg ,
582
- m_data .user_buffer ,
583
- NRFX_SAADC_SAMPLES_TO_BYTES (active_channel_cnt ),
675
+ error = dmm_buffer_in_prepare (m_data .mem_reg , m_data .user_buffer ,
676
+ (m_data .internal_timer_enabled
677
+ ? (NRFX_SAADC_SAMPLES_TO_BYTES (active_channel_cnt ) *
678
+ (1 + sequence -> options -> extra_samplings ))
679
+ : NRFX_SAADC_SAMPLES_TO_BYTES (active_channel_cnt )),
584
680
& samples_buffer );
585
681
if (error != 0 ) {
586
682
LOG_ERR ("DMM buffer allocation failed err=%d" , error );
@@ -590,7 +686,15 @@ static int start_read(const struct device *dev,
590
686
/* Buffer is filled in chunks, each chunk composed of number of samples equal to number
591
687
* of active channels. Buffer pointer is advanced and reloaded after each chunk.
592
688
*/
593
- nrfx_saadc_buffer_set (samples_buffer , active_channel_cnt );
689
+ nrfx_err = nrfx_saadc_buffer_set (
690
+ samples_buffer ,
691
+ (m_data .internal_timer_enabled
692
+ ? (active_channel_cnt * (1 + sequence -> options -> extra_samplings ))
693
+ : active_channel_cnt ));
694
+ if (nrfx_err != NRFX_SUCCESS ) {
695
+ LOG_ERR ("Failed to set buffer: %08x" , nrfx_err );
696
+ return - EINVAL ;
697
+ }
594
698
595
699
adc_context_start_read (& m_data .ctx , sequence );
596
700
@@ -633,11 +737,15 @@ static void event_handler(const nrfx_saadc_evt_t *event)
633
737
if (event -> type == NRFX_SAADC_EVT_DONE ) {
634
738
dmm_buffer_in_release (
635
739
m_data .mem_reg , m_data .user_buffer ,
636
- NRFX_SAADC_SAMPLES_TO_BYTES (m_data .active_channel_cnt ),
740
+ (m_data .internal_timer_enabled
741
+ ? (NRFX_SAADC_SAMPLES_TO_BYTES (m_data .active_channel_cnt ) *
742
+ (1 + m_data .ctx .sequence .options -> extra_samplings ))
743
+ : NRFX_SAADC_SAMPLES_TO_BYTES (m_data .active_channel_cnt )),
637
744
event -> data .done .p_buffer );
638
745
639
746
if (has_single_ended (& m_data .ctx .sequence )) {
640
- correct_single_ended (& m_data .ctx .sequence , m_data .user_buffer );
747
+ correct_single_ended (& m_data .ctx .sequence , m_data .user_buffer ,
748
+ event -> data .done .size );
641
749
}
642
750
adc_context_on_sampling_done (& m_data .ctx , DEVICE_DT_INST_GET (0 ));
643
751
} else if (event -> type == NRFX_SAADC_EVT_CALIBRATEDONE ) {
@@ -646,13 +754,17 @@ static void event_handler(const nrfx_saadc_evt_t *event)
646
754
LOG_ERR ("Cannot start sampling: 0x%08x" , err );
647
755
adc_context_complete (& m_data .ctx , - EIO );
648
756
}
757
+ } else if (event -> type == NRFX_SAADC_EVT_FINISHED ) {
758
+ adc_context_complete (& m_data .ctx , 0 );
649
759
}
650
760
}
651
761
652
762
static int init_saadc (const struct device * dev )
653
763
{
654
764
nrfx_err_t err ;
655
765
766
+ k_timer_init (& m_data .timer , adc_context_on_timer_expired , NULL );
767
+
656
768
/* The priority value passed here is ignored (see nrfx_glue.h). */
657
769
err = nrfx_saadc_init (0 );
658
770
if (err != NRFX_SUCCESS ) {
0 commit comments