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
38 #define NRFX_LOG_MODULE EXAMPLE
39 #define NRFX_EXAMPLE_CONFIG_LOG_ENABLED 1
40 #define NRFX_EXAMPLE_CONFIG_LOG_LEVEL 3
41 #include <nrfx_log.h>
42
43 /**
44 * @defgroup nrfx_saadc_simple_blocking_example Simple blocking SAADC example
45 * @{
46 * @ingroup nrfx_saadc_examples
47 *
48 * @brief Example showing simple functionality of nrfx_saadc driver operating in the blocking mode.
49 *
50 * @details Application initializes nrfx_saadc driver and starts operating in the blocking mode.
51 * Program works as a simple state machine and starts in state @ref m_current_state == STATE_SINGLE_CONFIG.
52 * In the state ( @ref m_current_state ):
53 * - STATE_SINGLE_CONFIG - SAADC driver is configured to work with only one channel ( @ref m_single_channel )
54 * in the blocking mode. @ref m_current_state is changed to STATE_SINGLE_SAMPLING afterward.
55 * - STATE_SINGLE_SAMPLING - sampling on a single channel ( @ref m_single_channel ) is performed specified
56 * number of times ( @ref SAMPLING_ITERATIONS ), after that @ref m_current_state is changed to STATE_MULTIPLE_CONFIG.
57 * - STATE_MULTIPLE_CONFIG - SAADC driver is configured to work with multiple channels ( @ref m_multiple_channels )
58 * in the blocking mode. @ref m_current_state is changed to STATE_MULTIPLE_SAMPLING afterward.
59 * - STATE_MULTIPLE_SAMPLING - sampling on multiple channels ( @ref m_multiple_channels ) is performed specified
60 * number of times ( @ref SAMPLING_ITERATIONS ).
61 * Before every sampling, calibration in a blocking manner is performed. After it, sampling is invoked
62 * by @p nrfx_saadc_mode_trigger() function.
63 *
64 * In the example there are GPIOTE tasks configured to toggle specified ( @ref m_out_pins ) loopback pins. Those tasks
65 * are being triggered between successive samplings to verify the functionality of the SAADC on the non-constant analog signal.
66 */
67
68 /** @brief Symbol specifying analog input to be observed by SAADC channel 0. */
69 #define CH0_AIN ANALOG_INPUT_TO_SAADC_AIN(ANALOG_INPUT_A0)
70
71 /** @brief Symbol specifying analog input to be observed by SAADC channel 1. */
72 #define CH1_AIN ANALOG_INPUT_TO_SAADC_AIN(ANALOG_INPUT_A1)
73
74 /** @brief Symbol specifying analog input to be observed by SAADC channel 2. */
75 #define CH2_AIN ANALOG_INPUT_TO_SAADC_AIN(ANALOG_INPUT_A2)
76
77 /** @brief Declaration of enum containing a set of states for the simple state machine. */
78 typedef enum
79 {
80 STATE_SINGLE_CONFIG, ///< Configure a single SAADC channel and set the SAADC driver in the simple mode.
81 STATE_SINGLE_SAMPLING, ///< Trigger SAADC sampling on the single channel.
82 STATE_MULTIPLE_CONFIG, ///< Configure multiple SAADC channels and set the SAADC driver in the simple mode.
83 STATE_MULTIPLE_SAMPLING, ///< Trigger SAADC sampling on multiple channels.
84 } state_t;
85
86 /** @brief SAADC channel configuration structure for single channel use. */
87 static const nrfx_saadc_channel_t m_single_channel = NRFX_SAADC_DEFAULT_CHANNEL_SE(CH0_AIN, 0);
88
89 /** @brief SAADC channel configuration structure for multiple channel use. */
90 static const nrfx_saadc_channel_t m_multiple_channels[] =
91 {
92 NRFX_SAADC_DEFAULT_CHANNEL_SE(CH0_AIN, 0),
93 NRFX_SAADC_DEFAULT_CHANNEL_SE(CH1_AIN, 1),
94 NRFX_SAADC_DEFAULT_CHANNEL_SE(CH2_AIN, 2),
95 };
96
97 /** @brief Symbol specifying numbers of multiple channels ( @ref m_multiple_channels) used by SAADC. */
98 #define CHANNEL_COUNT NRFX_ARRAY_SIZE(m_multiple_channels)
99
100 /** @brief Symbol specifying the number of SAADC samplings to trigger. */
101 #define SAMPLING_ITERATIONS 8
102
103 /** @brief Symbol specifying the resolution of the SAADC. */
104 #define RESOLUTION NRF_SAADC_RESOLUTION_8BIT
105
106 /** @brief Symbol specifying GPIOTE instance to be used. */
107 #define GPIOTE_INST_IDX 0
108
109 /** @brief Array specifying GPIO pins used to test the functionality of SAADC. */
110 static uint8_t m_out_pins[CHANNEL_COUNT] = {LOOPBACK_PIN_1B, LOOPBACK_PIN_2B, LOOPBACK_PIN_3B};
111
112 /** @brief Samples buffer defined with the size of @ref CHANNEL_COUNT symbol to store values from each channel ( @ref m_multiple_channels). */
113 #if (NRF_SAADC_8BIT_SAMPLE_WIDTH == 8) && (RESOLUTION == NRF_SAADC_RESOLUTION_8BIT)
114 static uint8_t samples_buffer[CHANNEL_COUNT];
115 #else
116 static uint16_t samples_buffer[CHANNEL_COUNT];
117 #endif
118
119 /** @brief Enum with the current state of the simple state machine. */
120 static state_t m_current_state = STATE_SINGLE_CONFIG;
121
122 /**
123 * @brief Function for application main entry.
124 *
125 * @return Nothing.
126 */
main(void)127 int main(void)
128 {
129 nrfx_err_t status;
130 (void)status;
131
132 #if defined(__ZEPHYR__)
133 IRQ_CONNECT(NRFX_IRQ_NUMBER_GET(NRF_GPIOTE_INST_GET(GPIOTE_INST_IDX)), IRQ_PRIO_LOWEST,
134 NRFX_GPIOTE_INST_HANDLER_GET(GPIOTE_INST_IDX), 0, 0);
135 #endif
136
137 NRFX_EXAMPLE_LOG_INIT();
138 NRFX_LOG_INFO("Starting nrfx_saadc simple blocking example.");
139 NRFX_EXAMPLE_LOG_PROCESS();
140
141 status = nrfx_saadc_init(NRFX_SAADC_DEFAULT_CONFIG_IRQ_PRIORITY);
142 NRFX_ASSERT(status == NRFX_SUCCESS);
143
144 nrfx_gpiote_t const gpiote_inst = NRFX_GPIOTE_INSTANCE(GPIOTE_INST_IDX);
145 status = nrfx_gpiote_init(&gpiote_inst, NRFX_GPIOTE_DEFAULT_CONFIG_IRQ_PRIORITY);
146 NRFX_ASSERT(status == NRFX_SUCCESS);
147 NRFX_LOG_INFO("GPIOTE status: %s",
148 nrfx_gpiote_init_check(&gpiote_inst) ? "initialized" : "not initialized");
149
150 uint8_t i;
151 for (i = 0; i < CHANNEL_COUNT; i++)
152 {
153 gpiote_pin_toggle_task_setup(&gpiote_inst, m_out_pins[i]);
154 }
155
156 uint32_t sampling_index = 0;
157 uint32_t channels_mask = 0;
158 while (1)
159 {
160 switch (m_current_state)
161 {
162 case STATE_SINGLE_CONFIG:
163 NRFX_LOG_INFO("Single channel SAADC test.");
164
165 status = nrfx_saadc_channel_config(&m_single_channel);
166 NRFX_ASSERT(status == NRFX_SUCCESS);
167
168 channels_mask = nrfx_saadc_channels_configured_get();
169 status = nrfx_saadc_simple_mode_set(channels_mask,
170 RESOLUTION,
171 NRF_SAADC_OVERSAMPLE_DISABLED,
172 NULL);
173 NRFX_ASSERT(status == NRFX_SUCCESS);
174
175 status = nrfx_saadc_buffer_set(samples_buffer, 1);
176 NRFX_ASSERT(status == NRFX_SUCCESS);
177
178 m_current_state = STATE_SINGLE_SAMPLING;
179 break;
180
181 case STATE_SINGLE_SAMPLING:
182 if (sampling_index++ < SAMPLING_ITERATIONS)
183 {
184 nrfx_gpiote_out_task_trigger(&gpiote_inst, m_out_pins[0]);
185
186 status = nrfx_saadc_offset_calibrate(NULL);
187 NRFX_ASSERT(status == NRFX_SUCCESS);
188 NRFX_LOG_INFO("Calibration in the blocking manner finished successfully.");
189
190 NRFX_LOG_INFO("Sampling %d / %d", sampling_index, SAMPLING_ITERATIONS);
191 NRFX_EXAMPLE_LOG_PROCESS();
192
193 status = nrfx_saadc_mode_trigger();
194 NRFX_ASSERT(status == NRFX_SUCCESS);
195
196 NRFX_LOG_INFO("[CHANNEL %u] Sampled value == %d",
197 m_multiple_channels[0].channel_index,
198 NRFX_SAADC_SAMPLE_GET(RESOLUTION, samples_buffer, 0));
199 }
200 else
201 {
202 m_current_state = STATE_MULTIPLE_CONFIG;
203 sampling_index = 0;
204 }
205 break;
206
207 case STATE_MULTIPLE_CONFIG:
208 NRFX_LOG_INFO("Multiple channels SAADC test.");
209
210 status = nrfx_saadc_channels_config(m_multiple_channels, CHANNEL_COUNT);
211 NRFX_ASSERT(status == NRFX_SUCCESS);
212
213 channels_mask = nrfx_saadc_channels_configured_get();
214 status = nrfx_saadc_simple_mode_set(channels_mask,
215 RESOLUTION,
216 NRF_SAADC_OVERSAMPLE_DISABLED,
217 NULL);
218 NRFX_ASSERT(status == NRFX_SUCCESS);
219
220 status = nrfx_saadc_buffer_set(samples_buffer, CHANNEL_COUNT);
221 NRFX_ASSERT(status == NRFX_SUCCESS);
222
223 m_current_state = STATE_MULTIPLE_SAMPLING;
224 break;
225
226 case STATE_MULTIPLE_SAMPLING:
227 if (sampling_index++ < SAMPLING_ITERATIONS)
228 {
229 for (i = 0; i < CHANNEL_COUNT; i++)
230 {
231 nrfx_gpiote_out_task_trigger(&gpiote_inst, m_out_pins[i]);
232 }
233
234 status = nrfx_saadc_offset_calibrate(NULL);
235 NRFX_ASSERT(status == NRFX_SUCCESS);
236 NRFX_LOG_INFO("Calibration in the blocking manner finished successfully.");
237
238 NRFX_LOG_INFO("Sampling %d / %d", sampling_index, SAMPLING_ITERATIONS);
239 NRFX_EXAMPLE_LOG_PROCESS();
240
241 status = nrfx_saadc_mode_trigger();
242 NRFX_ASSERT(status == NRFX_SUCCESS);
243
244 for (i = 0; i < CHANNEL_COUNT; i++)
245 {
246 NRFX_LOG_INFO("[CHANNEL %u] Sampled value == %d",
247 m_multiple_channels[i].channel_index,
248 NRFX_SAADC_SAMPLE_GET(RESOLUTION, samples_buffer, i));
249 }
250 }
251 break;
252
253 default:
254 break;
255 }
256 NRFX_EXAMPLE_LOG_PROCESS();
257 }
258 }
259
260 /** @} */
261