Appiko
hw_testing_app.c
1 /*
2  * hw_testing_app.c : Tests for SensePi Board level testing
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 
19 #include <stdint.h>
20 #include "nrf.h"
21 #include "boards.h"
22 #include "nrf_util.h"
23 
24 #include "hal_pin_analog_input.h"
25 #include "hal_nop_delay.h"
26 #include "hal_gpio.h"
27 #include "hal_clocks.h"
28 #include "hal_gpio.h"
29 #include "hal_nop_delay.h"
30 
31 #include "pir_sense.h"
32 #include "ms_timer.h"
33 #include "profiler_timer.h"
34 #include "simple_adc.h"
35 #include "mcp4012_x.h"
36 #include "uart_printf.h"
37 #include "tinyprintf.h"
38 #include "mcp4012_x.h"
39 #include "log.h"
40 
41 #include "hw_testing_app.h"
42 
43 
44 #define TIMER_INIT_VALUE (read_time_us())
45 #define CALC_TIMER_VAL 1000000
46 #define MAX_FREQ 10
47 
49 #define CALC_OFFSET simple_adc_get_value(SIMPLE_ADC_GAIN1_5, PIN_TO_ANALOG_INPUT(BATT_VOLTAGE_SENSE))/2
50 
56 static uint32_t my_sqrt(uint32_t num);
57 
65 static uint32_t compare_percent(uint32_t data, uint32_t ref, float per);
66 
72 static uint32_t hw_test_obs_sig();
73 
81 static uint32_t hw_test_obs_freq();
82 
85 typedef enum {
86  MY_LFCLK_SRC_RC = CLOCK_LFCLKSRC_SRC_RC,
87  MY_LFCLK_SRC_Xtal = CLOCK_LFCLKSRC_SRC_Xtal,
88  MY_LFCLK_SRC_Synth = CLOCK_LFCLKSRC_SRC_Synth
89 } my_lfclk_src_t;
90 
95 static uint32_t my_lfclk_init(my_lfclk_src_t my_lfclk_src);
96 
100 void capture_lfclk_test(void);
101 
102 
103 static uint32_t timer_val_us;
104 
105 
106 
107 //Supporting mathematical funcs
108 
109 uint32_t compare_percent(uint32_t data, uint32_t ref, float per)
110 {
111  if((ref-(ref*per/100))<=data && data<=(ref+(ref*per/100)))
112  {
113  return 1;
114  }
115  else
116  {
117  return 0;
118  }
119 }
120 
121 static uint32_t my_sqrt(uint32_t num)
122 {
123  float xn,xm,flag, temp;
124  xn = 0; xm = 800; flag = 0;
125  while(flag == 0)
126  {
127  xn = (xm + (num/xm))/2;
128  if(xn == xm)
129  {
130  flag = 1;
131  }
132  else
133  {
134  xm = xn;
135  }
136  }
137  temp = xn * 1000;
138  return (uint32_t) temp;
139 }
140 
141 
142 //Funtions for actual tests.
143 // Power Test
144 uint32_t power_test(void)
145 {
146  hal_gpio_pin_set(LED_RED);
147  log_printf("Power_test : 1\n");
148  hal_nop_delay_ms(100);
149  hal_gpio_pin_clear(LED_RED);
150  return 1;
151 }
152 // DC/DC Test
153 uint32_t dc_dc_test(void)
154 {
155  NRF_POWER->DCDCEN = POWER_DCDCEN_DCDCEN_Enabled << POWER_DCDCEN_DCDCEN_Pos;
156  if(NRF_POWER->DCDCEN == (POWER_DCDCEN_DCDCEN_Enabled << POWER_DCDCEN_DCDCEN_Pos))
157  {
158  log_printf("DC_DC_test : 1\n");
159  return 1;
160  }
161  else
162  {
163  log_printf("DC_DC_test : 0\n");
164  return 0;
165  }
166 }
167 // LED test
168 uint32_t led_test(void)
169 {
170  for(uint32_t led_cnt; led_cnt < 15; led_cnt ++)
171  {
172  hal_gpio_pin_set(LED_GREEN);
173  hal_nop_delay_ms(500);
174  hal_gpio_pin_clear(LED_GREEN);
175  hal_gpio_pin_set(LED_RED);
176  hal_nop_delay_ms(500);
177  hal_gpio_pin_clear(LED_RED);
178  log_printf("LED_test : 1\n");
179  }
180  return 1;
181 }
182 
183 //Crystal test
188 static uint32_t my_lfclk_init(my_lfclk_src_t my_lfclk_src)
189 {
190  uint32_t my_xtal_flag = 0;
191  if((NRF_CLOCK->LFCLKSTAT & //Clock is running
192  (CLOCK_LFCLKSTAT_STATE_Running << CLOCK_LFCLKSTAT_STATE_Pos)) &&
193  //Correct source is already set
194  ((NRF_CLOCK->LFCLKSTAT & CLOCK_LFCLKSTAT_SRC_Msk) == my_lfclk_src))
195  {
196  //Already in the required configuration
197  my_xtal_flag = 1;
198  return my_xtal_flag;
199  }
200 
201  NRF_CLOCK->LFCLKSRC = (my_lfclk_src << CLOCK_LFCLKSRC_SRC_Pos);
202  NRF_CLOCK->INTENSET = CLOCK_INTENSET_LFCLKSTARTED_Msk;
203  NVIC_ClearPendingIRQ(POWER_CLOCK_IRQn);
204 
205  // Enable wake-up on any event or interrupt (even disabled)
206  SCB->SCR |= SCB_SCR_SEVONPEND_Msk;
207 
208  NRF_CLOCK->EVENTS_LFCLKSTARTED = 0;
209  (void)NRF_CLOCK->EVENTS_LFCLKSTARTED;
210  NRF_CLOCK->TASKS_LFCLKSTART = 1;
211  hal_nop_delay_ms(500);
212  /* Wait for the external oscillator to start up. */
213  if (NRF_CLOCK->EVENTS_LFCLKSTARTED == 1)
214  {
215  my_xtal_flag = 1;
216  }
217  /* Clear the event and the pending interrupt */
218  NRF_CLOCK->EVENTS_LFCLKSTARTED = 0;
219  (void)NRF_CLOCK->EVENTS_LFCLKSTARTED;
220  NVIC_ClearPendingIRQ(POWER_CLOCK_IRQn);
221  NRF_CLOCK->INTENCLR = CLOCK_INTENCLR_LFCLKSTARTED_Msk;
222 
223  return my_xtal_flag;
224 
225 }
226 
227 uint32_t crystal_test()
228 {
229  uint32_t flag = 0;
230  uint32_t check_status_xtal = 0;
231  ms_timer_init(1);
232  check_status_xtal = my_lfclk_init(MY_LFCLK_SRC_Xtal);
233  ms_timer_start(MS_TIMER0,MS_SINGLE_CALL,32768,capture_lfclk_test);
235  hal_nop_delay_ms(1020);
236  flag = compare_percent(timer_val_us, CALC_TIMER_VAL, 1);
237  ms_timer_stop(1);
238  if (check_status_xtal)
239  {
240  log_printf("Crystal : 1\n");
241  }
242  else
243  {
244  log_printf("Crystal : 0\n");
245  }
246  if (flag && check_status_xtal)
247  {
248  log_printf("Crystal_test : 1\n");
249  return 1;
250  }
251  else
252  {
253  log_printf("Crystal_test : 0\n");
254  return 0;
255  }
256 
257 }
258 
259 void capture_lfclk_test (void)
260 {
261  timer_val_us = read_time_us();
262  log_printf("Timer_XTAL : %d\n", timer_val_us);
263  log_printf("Timer_TIMER : %d\n", CALC_TIMER_VAL);
265 }
266 
267 
268 // RC test
269 uint32_t rc_test(void)
270 {
271  uint32_t obs_offset = 0, avg_offset = 0, i = 0, temp_sum = 0;
274  while(read_time_us() < 1200000)
275  {
276  obs_offset = simple_adc_get_value(SIMPLE_ADC_GAIN1_5, PIN_TO_ANALOG_INPUT(PIR_AMP_OFFSET_PIN));
277  temp_sum = temp_sum + obs_offset;
278  i++;
279  }
280  avg_offset = temp_sum / i;
282  log_printf("CALC_OFFSET : %lu\n", CALC_OFFSET);
283  log_printf("Avg_Offset : %lu\n", avg_offset);
284  if(compare_percent(avg_offset, CALC_OFFSET, 5))
285  {
286  log_printf("RC_test : 1\n");
287  return 1;
288  }
289  else
290  {
291  log_printf("RC_test : 0\n");
292  return 0;
293  }
294 }
295 
296 // Freq filter test
297 uint32_t freq_filter_test(void)
298 {
299  uint32_t obs_freq = hw_test_obs_freq();
300  if(obs_freq == MAX_FREQ)
301  {
302  log_printf("Freq_filter_test : 1\n");
303  return 1;
304  }
305  else
306  {
307  log_printf("Freq_filter_test : 0\n");
308  return 0;
309  }
310 }
311 
312 static uint32_t hw_test_obs_freq()
313 {
314  uint32_t temp_signal = 0, cnt_cross = 0, freq = 0;
315  const uint32_t temp_offset = CALC_OFFSET;
316  do{
317  temp_signal = simple_adc_get_value(SIMPLE_ADC_GAIN1_5, PIN_TO_ANALOG_INPUT(PIR_AMP_SIGNAL_PIN));
318 
319  }while(!(compare_percent(temp_signal, temp_offset, 0.1) &&((int)(temp_signal - temp_offset) <= 0)));
321  while(read_time_us() < 1010000)
322  {
323  temp_signal = simple_adc_get_value(SIMPLE_ADC_GAIN1_5, PIN_TO_ANALOG_INPUT(PIR_AMP_SIGNAL_PIN));
324 
325  if(compare_percent(temp_offset,temp_signal,0.2))
326  {
327  cnt_cross++;
328  hal_nop_delay_ms(5);
329  }
330  }
332  freq = cnt_cross/2;
333  log_printf("Frequency : %d\n", freq);
334  return freq;
335 }
336 
337 // POT test
338 uint32_t pot_test(void)
339 {
340  uint32_t read1 = 0;
341  uint32_t read2 = 0;
342 
343  mcp4012_set_value(45);
344  hal_nop_delay_ms(10);
345  read1 = hw_test_obs_sig();
346  log_printf("POT_test_Read1 : %d\n", read1);
347 
349  hal_nop_delay_ms(10);
350  read2 = hw_test_obs_sig();
351  log_printf("POT_test_Read2 : %d\n", read2);
352  log_printf("ratio_Read1_Read2 : %d\n", ((read1*1000)/read2));
353 
354  if(!compare_percent(read1, read2, 100))
355  {
356  log_printf("POT_test : 1\n");
357  return 1;
358  }
359  else
360  {
361  log_printf("POT_test : 0\n");
362  return 0;
363  }
364 }
365 
366 static uint32_t hw_test_obs_sig()
367 {
368  uint32_t temp_signal, avg_signal, rms, i;
369  uint64_t temp_sum;
370  temp_signal = 0; avg_signal = 0; temp_sum = 0, i = 0;
371  const uint32_t temp_offset = CALC_OFFSET;
372  do{
373  temp_signal = simple_adc_get_value(SIMPLE_ADC_GAIN1_5, PIN_TO_ANALOG_INPUT(PIR_AMP_SIGNAL_PIN));
374  }while((!compare_percent(temp_signal, temp_offset, 0.1)) && (((int)(temp_signal - temp_offset)) > 0));
376  while(read_time_us() < 1000000)
377  {
378  temp_signal = simple_adc_get_value(SIMPLE_ADC_GAIN1_5, PIN_TO_ANALOG_INPUT(PIR_AMP_SIGNAL_PIN));
379  temp_sum = (temp_sum + (((int)(temp_signal-temp_offset))*((int)(temp_signal-temp_offset))));
380  i++;
381  }
383  avg_signal = temp_sum / i;
384  rms = my_sqrt(avg_signal);
385  return rms;
386 }
387 
388 
#define PIR_AMP_OFFSET_PIN
Definition: sensepi_rev2.h:72
void profiler_timer_init(void)
uint32_t simple_adc_get_value(simple_adc_gain_t gain, simple_adc_input_t pin)
This function initializes the SAADC peripheral, gets an ADC value and then deinitializes The function...
Definition: simple_adc.c:25
uint32_t freq_filter_test(void)
This fucntion is used to check output filter designed for f(max)=10Hz This test will detect if any ot...
uint32_t power_test(void)
This function is used to check power on the board If program execution starts properly,...
void profiler_timer_deinit()
Fully stop the profiling timer to save power. profiler_timer_init needs to be called again before usi...
Gain factor 1/5.
Definition: simple_adc.h:71
uint32_t dc_dc_test(void)
This fucntion is used to check DC/DC converter. If DC/DC circuit is present at input supply,...
uint32_t rc_test(void)
This fucntion is used to check output RC very low frequency filter. This function will actully check ...
#define PIR_AMP_SIGNAL_PIN
Definition: sensepi_rev2.h:70
void ms_timer_init(uint32_t irq_priority)
Definition: ms_timer.c:111
Millisecond Timer 0.
Definition: ms_timer.h:69
uint32_t led_test(void)
This fucntion is used to check on board LEDs. Operator has to be there to check if LEDs are blinking ...
void mcp4012_set_value(uint32_t value_sent_by_user)
This function is used to set the value of MCP4012 wiper value.
Definition: mcp4012_x.c:79
void ms_timer_start(ms_timer_num id, ms_timer_mode mode, uint64_t ticks, void(*handler)(void))
Definition: ms_timer.c:134
uint32_t pot_test(void)
This fucntion is used to check MCP4012 pot. In this function we will check an ratio between two signa...
void ms_timer_stop(ms_timer_num id)
Definition: ms_timer.c:173
One shot call of the timer.
Definition: ms_timer.h:82
uint32_t crystal_test()
This fucntion is used to check on low frequency crystal. Without LF-XTAL we cannot use RTC....
uint32_t read_time_us(void)