-
Notifications
You must be signed in to change notification settings - Fork 4
/
main.c
206 lines (168 loc) · 7.44 KB
/
main.c
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
/*
* Copyright (c) 2024 Nordic Semiconductor ASA
*
* SPDX-License-Identifier: LicenseRef-Nordic-5-Clause
*/
#include <zephyr/kernel.h>
#include <zephyr/logging/log.h>
LOG_MODULE_REGISTER(Lesson6_Exercise3, LOG_LEVEL_DBG);
/* STEP 2 - Include header for nrfx drivers */
#include <nrfx_saadc.h>
#include <nrfx_timer.h>
#include <helpers/nrfx_gppi.h>
#if defined(DPPI_PRESENT)
#include <nrfx_dppi.h>
#else
#include <nrfx_ppi.h>
#endif
/* STEP 3.1 - Define the SAADC sample interval in microseconds */
#define SAADC_SAMPLE_INTERVAL_US 50
/* STEP 4.1 - Define the buffer size for the SAADC */
#define SAADC_BUFFER_SIZE 8000
/* STEP 3.2 - Declaring an instance of nrfx_timer for TIMER2. */
const nrfx_timer_t timer_instance = NRFX_TIMER_INSTANCE(2);
/* STEP 4.2 - Declare the buffers for the SAADC */
static nrf_saadc_value_t saadc_sample_buffer[2][SAADC_BUFFER_SIZE];
/* STEP 4.3 - Declare variable used to keep track of which buffer was last assigned to the SAADC driver */
static uint32_t saadc_current_buffer = 0;
static void configure_timer(void)
{
nrfx_err_t err;
/* STEP 3.3 - Declaring timer config and intialize nrfx_timer instance. */
nrfx_timer_config_t timer_config = NRFX_TIMER_DEFAULT_CONFIG(1000000);
err = nrfx_timer_init(&timer_instance, &timer_config, NULL);
if (err != NRFX_SUCCESS) {
LOG_ERR("nrfx_timer_init error: %08x", err);
return;
}
/* STEP 3.4 - Set compare channel 0 to generate event every SAADC_SAMPLE_INTERVAL_US. */
uint32_t timer_ticks = nrfx_timer_us_to_ticks(&timer_instance, SAADC_SAMPLE_INTERVAL_US);
nrfx_timer_extended_compare(&timer_instance, NRF_TIMER_CC_CHANNEL0, timer_ticks, NRF_TIMER_SHORT_COMPARE0_CLEAR_MASK, false);
}
static void saadc_event_handler(nrfx_saadc_evt_t const * p_event)
{
nrfx_err_t err;
switch (p_event->type)
{
case NRFX_SAADC_EVT_READY:
/* STEP 5.1 - Buffer is ready, timer (and sampling) can be started. */
nrfx_timer_enable(&timer_instance);
break;
case NRFX_SAADC_EVT_BUF_REQ:
/* STEP 5.2 - Set up the next available buffer. Alternate between buffer 0 and 1 */
err = nrfx_saadc_buffer_set(saadc_sample_buffer[(saadc_current_buffer++)%2], SAADC_BUFFER_SIZE);
//err = nrfx_saadc_buffer_set(saadc_sample_buffer[((saadc_current_buffer == 0 )? saadc_current_buffer++ : 0)], SAADC_BUFFER_SIZE);
if (err != NRFX_SUCCESS) {
LOG_ERR("nrfx_saadc_buffer_set error: %08x", err);
return;
}
break;
case NRFX_SAADC_EVT_DONE:
/* STEP 5.3 - Buffer has been filled. Do something with the data and proceed */
int64_t average = 0;
int16_t max = INT16_MIN;
int16_t min = INT16_MAX;
for(int i=0; i < p_event->data.done.size; i++){
average += p_event->data.done.p_buffer[i];
if((int16_t)p_event->data.done.p_buffer[i] > max){
max = p_event->data.done.p_buffer[i];
}
if((int16_t)p_event->data.done.p_buffer[i] < min){
min = p_event->data.done.p_buffer[i];
}
}
average = average/p_event->data.done.size;
LOG_INF("SAADC buffer at 0x%x filled with %d samples", (uint32_t)p_event->data.done.p_buffer, p_event->data.done.size);
LOG_INF("AVG=%d, MIN=%d, MAX=%d", (int16_t)average, min, max);
break;
default:
LOG_INF("Unhandled SAADC evt %d", p_event->type);
break;
}
}
static void configure_saadc(void)
{
nrfx_err_t err;
/* STEP 4.4 - Connect ADC interrupt to nrfx interrupt handler */
IRQ_CONNECT(DT_IRQN(DT_NODELABEL(adc)),
DT_IRQ(DT_NODELABEL(adc), priority),
nrfx_isr, nrfx_saadc_irq_handler, 0);
/* STEP 4.5 - Initialize the nrfx_SAADC driver */
err = nrfx_saadc_init(DT_IRQ(DT_NODELABEL(adc), priority));
if (err != NRFX_SUCCESS) {
LOG_ERR("nrfx_saadc_init error: %08x", err);
return;
}
/* STEP 4.6 - Declare the struct to hold the configuration for the SAADC channel used to sample the battery voltage */
nrfx_saadc_channel_t channel = NRFX_SAADC_DEFAULT_CHANNEL_SE(NRF_SAADC_INPUT_AIN0, 0);
/* STEP 4.7 - Change gain config in default config and apply channel configuration */
channel.channel_config.gain = NRF_SAADC_GAIN1_6;
err = nrfx_saadc_channels_config(&channel, 1);
if (err != NRFX_SUCCESS) {
LOG_ERR("nrfx_saadc_channels_config error: %08x", err);
return;
}
/* STEP 4.8 - Configure channel 0 in advanced mode with event handler (non-blocking mode) */
nrfx_saadc_adv_config_t saadc_adv_config = NRFX_SAADC_DEFAULT_ADV_CONFIG;
err = nrfx_saadc_advanced_mode_set(BIT(0),
NRF_SAADC_RESOLUTION_12BIT,
&saadc_adv_config,
saadc_event_handler);
if (err != NRFX_SUCCESS) {
LOG_ERR("nrfx_saadc_advanced_mode_set error: %08x", err);
return;
}
/* STEP 4.9 - Configure two buffers to make use of double-buffering feature of SAADC */
err = nrfx_saadc_buffer_set(saadc_sample_buffer[0], SAADC_BUFFER_SIZE);
if (err != NRFX_SUCCESS) {
LOG_ERR("nrfx_saadc_buffer_set error: %08x", err);
return;
}
err = nrfx_saadc_buffer_set(saadc_sample_buffer[1], SAADC_BUFFER_SIZE);
if (err != NRFX_SUCCESS) {
LOG_ERR("nrfx_saadc_buffer_set error: %08x", err);
return;
}
/* STEP 4.10 - Trigger the SAADC. This will not start sampling, but will prepare buffer for sampling triggered through PPI */
err = nrfx_saadc_mode_trigger();
if (err != NRFX_SUCCESS) {
LOG_ERR("nrfx_saadc_mode_trigger error: %08x", err);
return;
}
}
static void configure_ppi(void)
{
nrfx_err_t err;
/* STEP 6.1 - Declare variables used to hold the (D)PPI channel number */
uint8_t m_saadc_sample_ppi_channel;
uint8_t m_saadc_start_ppi_channel;
/* STEP 6.2 - Trigger task sample from timer */
err = nrfx_gppi_channel_alloc(&m_saadc_sample_ppi_channel);
if (err != NRFX_SUCCESS) {
LOG_ERR("nrfx_gppi_channel_alloc error: %08x", err);
return;
}
err = nrfx_gppi_channel_alloc(&m_saadc_start_ppi_channel);
if (err != NRFX_SUCCESS) {
LOG_ERR("nrfx_gppi_channel_alloc error: %08x", err);
return;
}
/* STEP 6.3 - Trigger task sample from timer */
nrfx_gppi_channel_endpoints_setup(m_saadc_sample_ppi_channel,
nrfx_timer_compare_event_address_get(&timer_instance, NRF_TIMER_CC_CHANNEL0),
nrf_saadc_task_address_get(NRF_SAADC, NRF_SAADC_TASK_SAMPLE));
/* STEP 6.4 - Trigger task start from end event */
nrfx_gppi_channel_endpoints_setup(m_saadc_start_ppi_channel,
nrf_saadc_event_address_get(NRF_SAADC, NRF_SAADC_EVENT_END),
nrf_saadc_task_address_get(NRF_SAADC, NRF_SAADC_TASK_START));
/* STEP 6.5 - Enable both (D)PPI channels */
nrfx_gppi_channels_enable(BIT(m_saadc_sample_ppi_channel));
nrfx_gppi_channels_enable(BIT(m_saadc_start_ppi_channel));
}
int main(void)
{
configure_timer();
configure_saadc();
configure_ppi();
k_sleep(K_FOREVER);
}