1 /*
2  * Copyright (c) 2022 - 2024, Nordic Semiconductor ASA
3  * All rights reserved.
4  *
5  * SPDX-License-Identifier: BSD-3-Clause
6  *
7  * Redistribution and use in source and binary forms, with or without
8  * modification, are permitted provided that the following conditions are met:
9  *
10  * 1. Redistributions of source code must retain the above copyright notice, this
11  *    list of conditions and the following disclaimer.
12  *
13  * 2. Redistributions in binary form must reproduce the above copyright
14  *    notice, this list of conditions and the following disclaimer in the
15  *    documentation and/or other materials provided with the distribution.
16  *
17  * 3. Neither the name of the copyright holder nor the names of its
18  *    contributors may be used to endorse or promote products derived from this
19  *    software without specific prior written permission.
20  *
21  * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
22  * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
23  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
24  * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE
25  * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
26  * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
27  * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
28  * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
29  * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
30  * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
31  * POSSIBILITY OF SUCH DAMAGE.
32  */
33 
34 #include <nrfx_example.h>
35 #include <saadc_examples_common.h>
36 #include <nrfx_saadc.h>
37 #include <nrfx_gpiote.h>
38 
39 #define NRFX_LOG_MODULE                 EXAMPLE
40 #define NRFX_EXAMPLE_CONFIG_LOG_ENABLED 1
41 #define NRFX_EXAMPLE_CONFIG_LOG_LEVEL   3
42 #include <nrfx_log.h>
43 
44 /**
45  * @defgroup nrfx_saadc_advanced_blocking_example Advanced blocking SAADC example
46  * @{
47  * @ingroup nrfx_saadc_examples
48  *
49  * @brief Example showing advanced functionality of nrfx_saadc driver operating in the blocking mode.
50  *
51  * @details Application initializes nrfx_saadc driver and starts operating in the blocking mode.
52  *          In the example, @ref m_single_channel is configured and the SAADC driver is set to the advanced mode.
53  *
54  *          Before every sampling, calibration in a blocking manner is performed. Sampling is invoked
55  *          by @p nrfx_saadc_mode_trigger() function afterwards.
56  *
57  *          In the example there is GPIOTE task configured to toggle specified ( @ref OUT_GPIO_PIN ) pin. This task
58  *          is being triggered between successive samplings to verify the functionality of the SAADC on the non-constant analog signal.
59  */
60 
61 /** @brief Symbol specifying analog input to be observed by SAADC channel 0. */
62 #define CH0_AIN ANALOG_INPUT_TO_SAADC_AIN(ANALOG_INPUT_A0)
63 
64 /** @brief Symbol specifying GPIOTE instance to be used. */
65 #define GPIOTE_INST_IDX 0
66 
67 /** @brief Symbol specifying GPIO pin used to test the functionality of SAADC. */
68 #define OUT_GPIO_PIN LOOPBACK_PIN_1B
69 
70 /** @brief Symbol specifying the size of singular sample buffer ( @ref m_samples_buffer ). */
71 #define BUFFER_SIZE 2UL
72 
73 /** @brief Symbol specifying the number of SAADC samplings to trigger. */
74 #define SAMPLING_ITERATIONS 5UL
75 
76 /** @brief Symbol specifying the resolution of the SAADC. */
77 #define RESOLUTION NRF_SAADC_RESOLUTION_10BIT
78 
79 /** @brief SAADC channel configuration structure for single channel use. */
80 static const nrfx_saadc_channel_t m_single_channel = SAADC_CHANNEL_SE_ACQ_3US(CH0_AIN, 0);
81 
82 /** @brief Samples buffer to store values from a SAADC channel. */
83 #if (NRF_SAADC_8BIT_SAMPLE_WIDTH == 8) && (RESOLUTION == NRF_SAADC_RESOLUTION_8BIT)
84 static uint8_t m_samples_buffer[BUFFER_SIZE];
85 #else
86 static uint16_t m_samples_buffer[BUFFER_SIZE];
87 #endif
88 
89 /**
90  * @brief Function for application main entry.
91  *
92  * @return Nothing.
93  */
main(void)94 int main(void)
95 {
96     nrfx_err_t status;
97     (void)status;
98 
99 #if defined(__ZEPHYR__)
100     IRQ_CONNECT(NRFX_IRQ_NUMBER_GET(NRF_GPIOTE_INST_GET(GPIOTE_INST_IDX)), IRQ_PRIO_LOWEST,
101                 NRFX_GPIOTE_INST_HANDLER_GET(GPIOTE_INST_IDX), 0, 0);
102 #endif
103 
104     NRFX_EXAMPLE_LOG_INIT();
105     NRFX_LOG_INFO("Starting nrfx_saadc advanced blocking example.");
106     NRFX_EXAMPLE_LOG_PROCESS();
107 
108     status = nrfx_saadc_init(NRFX_SAADC_DEFAULT_CONFIG_IRQ_PRIORITY);
109     NRFX_ASSERT(status == NRFX_SUCCESS);
110 
111     nrfx_gpiote_t const gpiote_inst = NRFX_GPIOTE_INSTANCE(GPIOTE_INST_IDX);
112     status = nrfx_gpiote_init(&gpiote_inst, NRFX_GPIOTE_DEFAULT_CONFIG_IRQ_PRIORITY);
113     NRFX_ASSERT(status == NRFX_SUCCESS);
114     NRFX_LOG_INFO("GPIOTE status: %s",
115                   nrfx_gpiote_init_check(&gpiote_inst) ? "initialized" : "not initialized");
116 
117     gpiote_pin_toggle_task_setup(&gpiote_inst, OUT_GPIO_PIN);
118 
119     status = nrfx_saadc_channel_config(&m_single_channel);
120     NRFX_ASSERT(status == NRFX_SUCCESS);
121 
122     nrfx_saadc_adv_config_t adv_config = NRFX_SAADC_DEFAULT_ADV_CONFIG;
123 
124     uint32_t channel_mask = nrfx_saadc_channels_configured_get();
125     status = nrfx_saadc_advanced_mode_set(channel_mask,
126                                           RESOLUTION,
127                                           &adv_config,
128                                           NULL);
129     NRFX_ASSERT(status == NRFX_SUCCESS);
130 
131     status = nrfx_saadc_buffer_set(m_samples_buffer, BUFFER_SIZE);
132     NRFX_ASSERT(status == NRFX_SUCCESS);
133 
134     uint16_t sampling_index = 0;
135     while (1)
136     {
137         if (sampling_index < SAMPLING_ITERATIONS)
138         {
139             nrfx_gpiote_out_task_trigger(&gpiote_inst, OUT_GPIO_PIN);
140 
141             status = nrfx_saadc_offset_calibrate(NULL);
142             NRFX_ASSERT(status == NRFX_SUCCESS);
143             NRFX_LOG_INFO("Calibration in the blocking manner finished successfully.");
144 
145             /*
146              * If function nrfx_saadc_mode_trigger() returns NRFX_ERROR_BUSY it means that the conversion in the advanced
147              * blocking mode is still being performed. Then the function must be called again to continue the conversion.
148              */
149             while ((status = nrfx_saadc_mode_trigger()) == NRFX_ERROR_BUSY)
150             {}
151             NRFX_ASSERT(status == NRFX_SUCCESS);
152             NRFX_LOG_INFO("Sampling %d / %ld", sampling_index + 1, SAMPLING_ITERATIONS);
153 
154             for (uint32_t buffer_index = 0; buffer_index < BUFFER_SIZE; buffer_index++)
155             {
156                 NRFX_LOG_INFO("[Sample %u] value == %d",
157                               buffer_index,
158                               NRFX_SAADC_SAMPLE_GET(RESOLUTION, m_samples_buffer, buffer_index));
159             }
160 
161             status = nrfx_saadc_buffer_set(m_samples_buffer, BUFFER_SIZE);
162             NRFX_ASSERT(status == NRFX_SUCCESS);
163 
164             sampling_index++;
165         }
166         NRFX_EXAMPLE_LOG_PROCESS();
167     }
168 }
169 
170 /** @} */
171