Appiko
main.c
1 /*
2  * main.c : Application to log ADC values
3  * Copyright (C) 2019 Appiko
4  *
5  * This program is free software: you can redistribute it and/or modify
6  * it under the terms of the GNU General Public License as published by
7  * the Free Software Foundation, either version 3 of the License, or
8  * (at your option) any later version.
9  *
10  * This program is distributed in the hope that it will be useful,
11  * but WITHOUT ANY WARRANTY; without even the implied warranty of
12  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
13  * GNU General Public License for more details.
14  *
15  * You should have received a copy of the GNU General Public License
16  * along with this program. If not, see <https://www.gnu.org/licenses/>.
17  */
18 
54 #include <stdbool.h>
55 #include <stdint.h>
56 
57 #include "nrf.h"
58 
59 #include "boards.h"
60 #include "hal_saadc.h"
61 #include "hal_clocks.h"
62 #include "hal_nop_delay.h"
63 #include "hal_gpio.h"
64 #include "nrf_assert.h"
65 #include "hal_nop_delay.h"
66 #include "ms_timer.h"
67 #include "common_util.h"
68 #include "nrf_util.h"
69 #include "log.h"
70 
71 /* Defines */
73 #define LOGGER_INTERVAL_MS 50
74 
76 #define SAADC_NUMBER_OF_CHANNELS 1
77 
81 #if 0
82 #define SAADC_RC_CHANNEL_CONFIG \
83  { \
84  .resistor_p = NRF_SAADC_RESISTOR_DISABLED, \
85  .resistor_n = NRF_SAADC_RESISTOR_DISABLED, \
86  .gain = NRF_SAADC_GAIN4, \
87  .reference = NRF_SAADC_REFERENCE_INTERNAL, \
88  .acq_time = NRF_SAADC_ACQTIME_10US, \
89  .mode = NRF_SAADC_MODE_DIFFERENTIAL, \
90  .burst = NRF_SAADC_BURST_ENABLED, \
91  .pin_p = PIN_TO_ANALOG_INPUT(PIR_RC_SIGNAL_PIN), \
92  .pin_n = PIN_TO_ANALOG_INPUT(PIR_RC_OFFSET_PIN) \
93  }
94 #else
95 #define SAADC_AMP_CHANNEL_CONFIG \
96  { \
97  .resistor_p = NRF_SAADC_RESISTOR_DISABLED, \
98  .resistor_n = NRF_SAADC_RESISTOR_DISABLED, \
99  .gain = NRF_SAADC_GAIN1, \
100  .reference = NRF_SAADC_REFERENCE_INTERNAL, \
101  .acq_time = NRF_SAADC_ACQTIME_10US, \
102  .mode = NRF_SAADC_MODE_DIFFERENTIAL, \
103  .burst = NRF_SAADC_BURST_DISABLED, \
104  .pin_p = PIN_TO_ANALOG_INPUT(PIR_AMP_SIGNAL_PIN), \
105  .pin_n = PIN_TO_ANALOG_INPUT(PIR_AMP_OFFSET_PIN) \
106  }
107 
108 #endif
109 
113 #define PIR_RC_CHANNEL_UPPER_LIMIT (32767)
114 #define PIR_RC_CHANNEL_LOWER_LIMIT (-32768)
115 
116 #define PIR_AMP_CHANNEL_UPPER_LIMIT (100)
117 #define PIR_AMP_CHANNEL_LOWER_LIMIT (-100)
118 
121 #define APPLN_SAADC_RESOLUTION NRF_SAADC_RESOLUTION_12BIT
122 
123 #define APPLN_SAADC_OVERSAMPLING NRF_SAADC_OVERSAMPLE_DISABLED
124 
125 #define APPLN_SAADC_IRQ_PRIORITY APP_IRQ_PRIORITY_LOW
126 
129 {
130  int16_t upper_limit;
131  int16_t lower_limit;
132 };
133 
134 
135 /* Global constants in flash */
137 static const struct saadc_limit saadc_limit_config[SAADC_NUMBER_OF_CHANNELS] =
138 {
139 // { PIR_RC_CHANNEL_UPPER_LIMIT, PIR_RC_CHANNEL_LOWER_LIMIT }
140  { PIR_AMP_CHANNEL_UPPER_LIMIT, PIR_AMP_CHANNEL_LOWER_LIMIT }
141 };
142 
144 static const nrf_saadc_channel_config_t saadc_ch_config[SAADC_NUMBER_OF_CHANNELS] =
145  {
146 // SAADC_RC_CHANNEL_CONFIG
147  SAADC_AMP_CHANNEL_CONFIG
148  };
149 
150 /* Globals */
152 static int16_t saadc_result[1];
153 
154 /* Function declarations */
158 static void saadc_init(void);
159 
160 
161 void trigger_handler(void)
162 {
163  log_printf("RTC handlers\n");
164  hal_gpio_pin_toggle(LED_RED);
165 }
166 
167 
168 /* Function definitions */
171 {
172 #if 0
173  if(nrf_saadc_event_check(NRF_SAADC_EVENT_STARTED))
174  {
175  nrf_saadc_event_clear(NRF_SAADC_EVENT_STARTED);
176  SEGGER_RTT_printf(0, "STARTED: %d\n", saadc_result);
177  }
178 
179 #endif
180 #if 1
181  if (nrf_saadc_event_check(NRF_SAADC_EVENT_END))
182  {
183  nrf_saadc_event_clear(NRF_SAADC_EVENT_END);
184 
185  log_printf("END: %d [%d%d]\n", saadc_result[0], NRF_SAADC->EVENTS_CH[0].LIMITH, NRF_SAADC->EVENTS_CH[0].LIMITL
186 // ,saadc_result[1], NRF_SAADC->EVENTS_CH[1].LIMITH, NRF_SAADC->EVENTS_CH[1].LIMITL
187  );
188 // if(NRF_SAADC->EVENTS_CH[0].LIMITH){
189 // SEGGER_RTT_printf(0, "END 0: %d\n", saadc_result[0]);
190 // } else if (NRF_SAADC->EVENTS_CH[1].LIMITH){
191 // SEGGER_RTT_printf(0, "END 1: %d\n", saadc_result[0]);
192 // }
193 
194  NRF_SAADC->EVENTS_CH[0].LIMITH = NRF_SAADC->EVENTS_CH[0].LIMITL = 0;
195  NRF_SAADC->EVENTS_CH[1].LIMITH = NRF_SAADC->EVENTS_CH[1].LIMITL = 0;
196  }
197 #endif
198 #if 0
199 
200  if(nrf_saadc_event_check(NRF_SAADC_EVENT_DONE))
201  {
202  nrf_saadc_event_clear(NRF_SAADC_EVENT_DONE);
203  SEGGER_RTT_printf(0, "DONE: %d\n", saadc_result);
204  }
205 
206  if(nrf_saadc_event_check(NRF_SAADC_EVENT_RESULTDONE))
207  {
208  nrf_saadc_event_clear(NRF_SAADC_EVENT_RESULTDONE);
209  SEGGER_RTT_printf(0, "RESULTDONE: %d\n", saadc_result);
210  }
211 
212  if(nrf_saadc_event_check(NRF_SAADC_EVENT_STOPPED))
213  {
214  nrf_saadc_event_clear(NRF_SAADC_EVENT_STOPPED);
215  SEGGER_RTT_printf(0, "STOPPED: %d %d\n", saadc_result[0], saadc_result[1]);
216  nrf_saadc_disable();
217  }
218 #endif
219 #if 1
220  if(nrf_saadc_event_check(NRF_SAADC_EVENT_CH0_LIMITH))
221  {
222  nrf_saadc_event_clear(NRF_SAADC_EVENT_CH0_LIMITH);
223  log_printf("CH0_LIMITH: %d\n", saadc_result[0]);
224 // SEGGER_RTT_printf(0, "CH0_LIMITH: %d\n", saadc_result[0]);
225 // ms_timer_start(MS_TIMER3,MS_SINGLE_CALL, RTC_TICKS_MS(49), trigger_handler);
226 // hal_gpio_pin_write(LED_RED, LEDS_ACTIVE_STATE);
227  }
228  if(nrf_saadc_event_check(NRF_SAADC_EVENT_CH0_LIMITL))
229  {
230  nrf_saadc_event_clear(NRF_SAADC_EVENT_CH0_LIMITL);
231  log_printf("CH0_LIMITL: %d\n", saadc_result[0]);
232 // SEGGER_RTT_printf(0, "CH0_LIMITL: %d\n", saadc_result[0]);
233 // ms_timer_start(MS_TIMER3,MS_SINGLE_CALL, RTC_TICKS_MS(49), trigger_handler);
234 // hal_gpio_pin_write(LED_RED, LEDS_ACTIVE_STATE);
235  }
236 #endif
237 #if 0
238  if(nrf_saadc_event_check(NRF_SAADC_EVENT_CH1_LIMITH))
239  {
240  nrf_saadc_event_clear(NRF_SAADC_EVENT_CH1_LIMITH);
241  SEGGER_RTT_printf(0, "CH1_LIMITH: %d %d\n", saadc_result[0], saadc_result[1]);
242  }
243 
244  if(nrf_saadc_event_check(NRF_SAADC_EVENT_CH1_LIMITL))
245  {
246  nrf_saadc_event_clear(NRF_SAADC_EVENT_CH1_LIMITL);
247  SEGGER_RTT_printf(0, "CH1_LIMITL: %d %d\n", saadc_result[0], saadc_result[1]);
248  }
249 #endif
250 }
251 
252 
253 static void saadc_init(void)
254 {
255  static_assert((SAADC_NUMBER_OF_CHANNELS > 0) && (SAADC_NUMBER_OF_CHANNELS <= 8),
256  "The number of SAADC channels is between 1 and 8");
257  static_assert((PIR_AMP_CHANNEL_LOWER_LIMIT >= -32768) && (PIR_AMP_CHANNEL_LOWER_LIMIT <= 32767),
258  "The channel limit of SAADC is between -32768 and 32767");
259  static_assert((PIR_AMP_CHANNEL_UPPER_LIMIT >= -32768) && (PIR_AMP_CHANNEL_UPPER_LIMIT <= 32767),
260  "The channel limit of SAADC is between -32768 and 32767");
261  static_assert((PIR_RC_CHANNEL_LOWER_LIMIT >= -32768) && (PIR_RC_CHANNEL_LOWER_LIMIT <= 32767),
262  "The channel limit of SAADC is between -32768 and 32767");
263  static_assert((PIR_RC_CHANNEL_UPPER_LIMIT >= -32768) && (PIR_RC_CHANNEL_UPPER_LIMIT <= 32767),
264  "The channel limit of SAADC is between -32768 and 32767");
265 
266  nrf_saadc_resolution_set(APPLN_SAADC_RESOLUTION);
268  nrf_saadc_buffer_init(saadc_result, ARRAY_SIZE(saadc_result));
269  NVIC_SetPriority(SAADC_IRQn, APPLN_SAADC_IRQ_PRIORITY);
270  NVIC_EnableIRQ(SAADC_IRQn);
271  NVIC_ClearPendingIRQ(SAADC_IRQn);
272  nrf_saadc_oversample_set(APPLN_SAADC_OVERSAMPLING);
273 
274  for (uint32_t i = 0; i < SAADC_NUMBER_OF_CHANNELS; i++)
275  {
276  saadc_channel_init(i, &saadc_ch_config[i]);
277  nrf_saadc_channel_limits_set(i,
278  saadc_limit_config[i].lower_limit,
279  saadc_limit_config[i].upper_limit);
280  }
281 
282  nrf_saadc_int_enable(
283  NRF_SAADC_INT_END |
284  NRF_SAADC_INT_CH0LIMITH |
285  NRF_SAADC_INT_CH0LIMITL
286 // NRF_SAADC_INT_CH1LIMITH |
287 // NRF_SAADC_INT_CH1LIMITL
288  );
289 
290  NRF_PPI->CH[PPI_CHEN_CH0_Pos].EEP = (uint32_t) &(NRF_SAADC->EVENTS_STARTED);
291  NRF_PPI->CH[PPI_CHEN_CH0_Pos].TEP = (uint32_t) &(NRF_SAADC->TASKS_SAMPLE);
292  NRF_PPI->CHENSET = PPI_CHENSET_CH0_Set << PPI_CHEN_CH0_Pos;
293 
294 // nrf_ppi_channel_endpoint_setup(NRF_PPI_CHANNEL0,
295 // nrf_saadc_event_address_get(NRF_SAADC_EVENT_STARTED),
296 // nrf_saadc_task_address_get(NRF_SAADC_TASK_SAMPLE));
297 // nrf_ppi_channel_enable(NRF_PPI_CHANNEL0);
298 
299  NRF_PPI->CH[PPI_CHEN_CH1_Pos].EEP = (uint32_t) &(NRF_RTC0->EVENTS_COMPARE[0]);
300  NRF_PPI->CH[PPI_CHEN_CH1_Pos].TEP = (uint32_t) &(NRF_SAADC->TASKS_START);
301  NRF_PPI->FORK[PPI_CHEN_CH1_Pos].TEP = (uint32_t) &(NRF_RTC0->TASKS_CLEAR);
302  NRF_PPI->CHENSET = PPI_CHENSET_CH1_Set << PPI_CHEN_CH1_Pos;
303 
304 // nrf_ppi_channel_endpoint_setup(NRF_PPI_CHANNEL1,
305 // nrf_rtc_event_address_get(NRF_RTC0, NRF_RTC_EVENT_COMPARE_0),
306 // nrf_saadc_task_address_get(NRF_SAADC_TASK_START));
307 // nrf_ppi_fork_endpoint_setup(NRF_PPI_CHANNEL1,
308 // nrf_rtc_task_address_get(NRF_RTC0, NRF_RTC_TASK_CLEAR));
309 // nrf_ppi_channel_enable(NRF_PPI_CHANNEL1);
310 
311  NRF_PPI->CH[PPI_CHEN_CH2_Pos].EEP = (uint32_t) &(NRF_SAADC->EVENTS_END);
312  NRF_PPI->CH[PPI_CHEN_CH2_Pos].TEP = (uint32_t) &(NRF_SAADC->TASKS_STOP);
313  NRF_PPI->CHENSET = PPI_CHENSET_CH2_Set << PPI_CHEN_CH2_Pos;
314 
315 // nrf_ppi_channel_endpoint_setup(NRF_PPI_CHANNEL2,
316 // nrf_saadc_event_address_get(NRF_SAADC_EVENT_END),
317 // nrf_saadc_task_address_get(NRF_SAADC_TASK_STOP));
318 // nrf_ppi_channel_enable(NRF_PPI_CHANNEL2);
319 
320  NRF_RTC0->TASKS_STOP = 1;
321  NRF_RTC0->PRESCALER = 0;
322  NRF_RTC0->CC[0] = RTC_TICKS_MS(LOGGER_INTERVAL_MS);
323  NRF_RTC0->EVTENSET = (RTC_EVTENSET_COMPARE0_Enabled << RTC_EVTENSET_COMPARE0_Pos);
324  NRF_RTC0->EVENTS_COMPARE[0] = 0;
325  NRF_RTC0->TASKS_START = 1;
326  nrf_saadc_enable();
327 }
328 
329 
333 int main(void)
334 {
335  /* Mandatory welcome message */
336  log_init();
337  log_printf("\n\nHello World!\n");
338 
340 
341  saadc_init();
342 
343  while (true)
344  {
345  __WFI();
346  }
347 }
348 
#define SAADC_NUMBER_OF_CHANNELS
Macro that defines the number of channels of ADC to sample.
Definition: main.c:76
#define APPLN_SAADC_RESOLUTION
The ADC converstion resolution used in this application.
Definition: main.c:121
Configuration structure of the SAADC limit for a channel.
Definition: main.c:128
#define APPLN_SAADC_OVERSAMPLING
The number of samples used to average to get the result.
Definition: main.c:123
void lfclk_init(lfclk_src_t lfclk_src)
Function to initialize the LF clock.
Definition: hal_clocks.c:23
#define APPLN_SAADC_IRQ_PRIORITY
The interrupt priority of the SAADC peripheral.
Definition: main.c:125
#define LOGGER_INTERVAL_MS
Macro that defines the data sampling frequency.
Definition: main.c:73
#define ARRAY_SIZE(arr)
Definition: common_util.h:70
#define saadc_channel_init
To be consistent with the saadc naming for the function here. The function definition is in the SDK H...
Definition: hal_saadc.h:45
__STATIC_INLINE void saadc_sampling_task_mode_set(void)
Function that sets the sampling to be started with SAMPLING task.
Definition: hal_saadc.h:64
int main(void)
Function for application main entry.
Definition: main.c:90
External crystal.
Definition: hal_clocks.h:38
void SAADC_IRQHandler(void)
Implementation of the SAADC interrupt handler.
Definition: main.c:170