Appiko
sensebe_tx_mod.c
1 /*
2  * sensebe_tx_rx_mod.c : Module to handle SenseBe's Tx Rx functionalities
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 
20 #include "sensebe_ble.h"
21 #include "sensebe_tx_mod.h"
22 #include "sensebe_store_config.h"
23 
24 #include "hal_gpio.h"
25 #include "ms_timer.h"
26 #include "log.h"
27 #include "led_ui.h"
28 #include "led_seq.h"
29 #include "tssp_detect.h"
30 #include "device_tick.h"
31 #include "cam_trigger.h"
32 #include "simple_adc.h"
33 #include "string.h"
34 #include "hal_nop_delay.h"
35 #include "tssp_ir_tx.h"
36 #include "radio_trigger.h"
37 
38 /***********MACROS***********/
40 #define DETECT_FEEDBACK_TIMEOUT_TICKS MS_TIMER_TICKS_MS(270000)
41 
42 #define LIGHT_THRESHOLD_MULTIPLY_FACTOR 32
43 
44 #define MAX_ADC_OUTPUT 4096
45 
46 #define LIGHT_SENSE_INTERVAL_TICKS MS_TIMER_TICKS_MS(300000)
47 
48 #define PULSE_REQ_FOR_SYNC 4
49 
50 #define MOTION_SYNC_ON_TIME 200
51 
52 #define MOTION_SYNC_OFF_TIME 800
53 
54 #define RADIO_ON_FREQ_MS 50
55 
56 /***********ENUMS***********/
58 typedef enum
59 {
61  MOD_TIMER,
63  MOD_RADIO,
65  MOD_IR_TX,
67  MAX_MODS,
68 }modules_t;
69 
71 typedef enum
72 {
74  IR_SHORT,
76  IR_MID,
78  IR_LONG,
80  MAX_IR_RANGES,
81 }ir_ranges_t;
82 
84 typedef enum
85 {
87  MOD_FREQ0 = (5),
89  MOD_FREQ1 = (25),
91  MOD_FREQ2 = (50),
93  MOD_FREQ3 = (100),
95  MAX_MOD_FREQ = 4,
96 }module_freq_t;
97 
99 typedef enum
100 {
102  TX_EN = SENSEBE_TX_BOARD,
104  RX_EN = SENSEBE_RX_BOARD
105 }rx_tx_mod_en_t;
106 
107 /***********VARIABLE***********/
109 static uint32_t feedback_timepassed = 0;
111 static sensebe_config_t sensebe_config;
113 static uint32_t arr_module_tick_duration[] = {MOD_FREQ0, MOD_FREQ1, MOD_FREQ2, MOD_FREQ3};
115 static bool arr_is_light_ok [MAX_MODS];
117 static bool arr_is_light_sense_req [MAX_MODS];
119 static bool arr_is_mod_on[MAX_MODS];
121 static uint32_t timer_module_value = 0;
123 static led_sequences arr_range_indicator[] =
124  {LED_SEQ_RED_PULSE, LED_SEQ_ORANGE_PULSE, LED_SEQ_GREEN_PULSE,};
126 static ir_ranges_t tx_range = IR_SHORT;
128 static uint32_t ir_pwr1 = 0, ir_pwr2 =0;
130 static uint32_t light_check_sense_pin = 0;
132 static uint32_t light_check_en_pin = 0;
133 
134 static uint32_t radio_mod_ticks_freq = 0;
135 
136 /***********FUNCTIONS***********/
139 void timer_module_start (void);
141 void timer_module_add_ticks (void);
143 void timer_module_add_mod_ticks (void);
145 void timer_module_stop (void);
146 
148 void timer_trigger_handler ();
149 
150 void radio_module_start ();
151 
152 void radio_module_add_mod_ticks ();
153 
154 void radio_module_stop ();
155 
156 void radio_module_trigger_handler (void * p_trig, uint32_t len);
157 
160 void ir_tx_module_start (void);
162 void ir_tx_module_add_ticks (void);
164 void ir_tx_module_add_mod_ticks (void);
166 void ir_tx_module_stop (void);
167 
169 void ir_range_short (void);
171 void ir_range_mid (void);
173 void ir_range_long (void);
175 void (* arr_ir_range_select[]) () ={
176  ir_range_short,
177  ir_range_mid,
178  ir_range_long,
179 };
180 
182 /***/
189 void light_check (oper_time_t oper_time, uint32_t light_intensity, uint32_t module);
194 void light_sense_add_ticks (uint32_t interval);
195 
201 void camera_unit_handler(uint32_t trigger);
206 void add_ticks_feedback (uint32_t interval);
207 
215 void module_tick_handler ();
216 
217 
218 /*******************Definitions*******************/
219 void add_ticks_feedback (uint32_t interval)
220 {
221  feedback_timepassed += interval;
222  if(feedback_timepassed >= DETECT_FEEDBACK_TIMEOUT_TICKS)
223  {
224  led_ui_stop_seq (LED_UI_LOOP_SEQ, LED_SEQ_DETECT_PULSE);
225  }
226 }
227 
228 void state_change_sync ()
229 {
230  log_printf ("%s\n", __func__);
232 }
233 
234 void state_change_idle ()
235 {
236  log_printf ("%s\n", __func__);
239 }
240 
241 void state_change_stop ()
242 {
243 
244  log_printf ("%s\n", __func__);
247 }
248 
249 void ir_range_short ()
250 {
251  log_printf("%s\n",__func__);
252  hal_gpio_pin_write (ir_pwr1, 0);
253  hal_gpio_pin_write (ir_pwr2, 0);
254 }
255 
256 void ir_range_mid ()
257 {
258  log_printf("%s\n",__func__);
259  hal_gpio_pin_write (ir_pwr1, 1);
260  hal_gpio_pin_write (ir_pwr2, 0);
261 }
262 
263 void ir_range_long ()
264 {
265  log_printf("%s\n",__func__);
266  hal_gpio_pin_write (ir_pwr1, 1);
267  hal_gpio_pin_write (ir_pwr2, 1);
268 }
269 
270 void camera_unit_handler(uint32_t trigger)
271 {
272  log_printf("%s\n", __func__);
273  switch(trigger)
274  {
275  case MOD_TIMER :
276  break;
277  }
278 
279 }
280 
281 void timer_trigger_handler ()
282 {
283  if(cam_trigger_is_on () == false)
284  {
285  cam_trigger (MOD_TIMER);
286  }
287 }
288 
289 void light_check (oper_time_t oper_time, uint32_t light_intensity, uint32_t module)
290 {
291  uint8_t light_sense_config = oper_time.day_or_night;
292  uint32_t light_threshold =
293  (uint32_t)((oper_time.threshold) * LIGHT_THRESHOLD_MULTIPLY_FACTOR);
294 
295  //respective light check
296  //Day and its brighter than the threshold
297  if(((light_sense_config == 1) && (light_intensity >= light_threshold))
298  || //Night and its dimmer than the threshold
299  ((light_sense_config == 0) && (light_intensity <= light_threshold)))
300  //assgin to respective light flag
301  {
302  arr_is_light_ok[module] = true;
303  }
304  else
305  {
306  arr_is_light_ok[module] = false;
307  }
308 }
309 
310 void light_sense_add_ticks (uint32_t interval)
311 {
312  static uint32_t timepassed = 0;
313  timepassed += interval;
314  if(timepassed >= LIGHT_SENSE_INTERVAL_TICKS)
315  {
316  static uint32_t light_intensity;
317  //Enable light sense module
318  hal_gpio_pin_set (light_check_en_pin);
319  //Take light reading
320  hal_nop_delay_ms (3);
321  light_intensity = (MAX_ADC_OUTPUT - simple_adc_get_value (SIMPLE_ADC_GAIN1_6,
322  light_check_sense_pin));
323  //timer light check
324  if(arr_is_light_sense_req[MOD_TIMER])
325  {
326  light_check (sensebe_config.timer_conf.oper_time, light_intensity, MOD_TIMER);
327  }
328 
329  if(arr_is_light_sense_req[MOD_IR_TX])
330  {
331  light_check (sensebe_config.ir_tx_conf.oper_time, light_intensity, MOD_IR_TX);
332  }
333 
334  //Disable light sense module
335  hal_gpio_pin_clear (light_check_en_pin);
336  timepassed = 0;
337  }
338 }
339 
340 void radio_module_start ()
341 {
342  arr_is_mod_on[MOD_RADIO] = 1;
343  radio_trigger_init_t radio_init =
344  {
345  .comm_direction = RADIO_TRIGGER_Rx,
346  .comm_freq = 95,
347  .irq_priority = APP_IRQ_PRIORITY_HIGH,
348  .radio_trigger_rx_callback = radio_module_trigger_handler,
349  .rx_on_time_ms = 2,
350  };
351  radio_trigger_init (&radio_init);
352 
353  cam_trigger_config_t cam_trigg =
354  {
355  .setup_number = MOD_RADIO,
356  .pre_focus_en = sensebe_config.cam_trigs[RADIO_ALL].pre_focus,
357  .trig_duration_100ms = 15,
358  .trig_mode = sensebe_config.cam_trigs[RADIO_ALL].mode,
359  .trig_param1 = sensebe_config.cam_trigs[RADIO_ALL].larger_value,
360  .trig_param2 = sensebe_config.cam_trigs[RADIO_ALL].smaller_value,
361  };
362  cam_trigger_set_trigger (&cam_trigg);
363 
364 }
365 
366 void radio_module_add_mod_ticks ()
367 {
368  static uint32_t radio_cnt = 0;
369  radio_cnt++;
370  if(radio_cnt >= radio_mod_ticks_freq)
371  {
372  radio_trigger_listen ();
373  radio_cnt = 0;
374  }
375 }
376 
377 void radio_module_stop ()
378 {
379  arr_is_mod_on[MOD_RADIO] = 0;
380  radio_trigger_shut ();
381 }
382 
383 void radio_module_trigger_handler (void * p_trig, uint32_t len)
384 {
385  uint32_t * buff = (uint32_t *)p_trig;
386  log_printf("%s : %d\n", __func__, buff[0]);
387  cam_trigger (buff[0]);
388 }
389 
390 void timer_module_start ()
391 {
392  oper_time_t timer_oper_time = sensebe_config.timer_conf.oper_time;
393 
394  if((timer_oper_time.day_or_night == 1 && timer_oper_time.threshold == 0b0000000)||
395  (timer_oper_time.day_or_night == 0 && timer_oper_time.threshold == 0b1111111))
396  {
397  arr_is_light_sense_req[MOD_TIMER] = false;
398  arr_is_light_ok [MOD_TIMER] = true;
399  }
400  else
401  {
402  arr_is_light_sense_req[MOD_TIMER] = true;
403  }
404  cam_trigger_config_t timer_cam_trig_config =
405  {
406  .setup_number = MOD_TIMER,
407  .trig_duration_100ms = 0,
408  .trig_mode = sensebe_config.cam_trigs[TIMER_ALL].mode,
409  .trig_param1 = sensebe_config.cam_trigs[TIMER_ALL].larger_value,
410  .trig_param2 = sensebe_config.cam_trigs[TIMER_ALL].smaller_value,
411  .pre_focus_en = (bool)sensebe_config.cam_trigs[TIMER_ALL].pre_focus,
412  };
413  cam_trigger_set_trigger (&timer_cam_trig_config);
414 
415  timer_module_value = sensebe_config.timer_conf.timer_interval * 100;
416 
417  arr_is_mod_on[MOD_TIMER] = true;
418 
419 }
420 
421 void timer_module_add_ticks ()
422 {
423  if(arr_is_light_ok [MOD_TIMER] == true)
424  {
425  arr_is_mod_on[MOD_TIMER] = true;
426  }
427  else
428  {
429  arr_is_mod_on[MOD_TIMER] = false;
430  }
431 }
432 
433 void timer_module_add_mod_ticks ()
434 {
435  static uint32_t mod_ticks;
436  mod_ticks += arr_module_tick_duration[sensebe_config.ir_tx_conf.ir_tx_speed];
437  if(mod_ticks >= timer_module_value)
438  {
439  timer_trigger_handler ();
440  mod_ticks = 0;
441  }
442 }
443 
444 void timer_module_stop ()
445 {
446  arr_is_mod_on [MOD_TIMER] = false;
447  arr_is_light_sense_req[MOD_TIMER] = false;
448  arr_is_light_ok[MOD_TIMER] = false;
449 }
450 
451 void ir_tx_module_start ()
452 {
453  oper_time_t ir_tx_oper_time = sensebe_config.ir_tx_conf.oper_time;
454 
455  if((ir_tx_oper_time.day_or_night == 1 && ir_tx_oper_time.threshold == 0b0000000)||
456  (ir_tx_oper_time.day_or_night == 0 && ir_tx_oper_time.threshold == 0b1111111))
457  {
458  arr_is_light_sense_req[MOD_IR_TX] = false;
459  arr_is_light_ok [MOD_IR_TX] = true;
460  }
461  else
462  {
463  arr_is_light_sense_req[MOD_IR_TX] = true;
464  }
465 
466  if(sensebe_config.ir_tx_conf.ir_tx_pwr == MAX_IR_RANGES)
467  {
468  sensebe_config.ir_tx_conf.ir_tx_pwr = IR_LONG;
469  }
470 
471  tx_range = sensebe_config.ir_tx_conf.ir_tx_pwr;
472  arr_ir_range_select[tx_range]();
473  led_ui_single_start (arr_range_indicator[tx_range], LED_UI_LOW_PRIORITY, true);
474 
475  arr_is_mod_on[MOD_IR_TX] = true;
476 }
477 
478 void ir_tx_module_add_ticks ()
479 {
480  if(arr_is_light_ok[MOD_IR_TX] == true)
481  {
482  arr_is_mod_on[MOD_IR_TX] = true;
483  }
484  else
485  {
486  arr_is_mod_on[MOD_IR_TX] = false;
487  }
488 }
489 
490 void ir_tx_module_add_mod_ticks ()
491 {
492  tssp_ir_tx_start ();
493 }
494 
495 void ir_tx_module_stop ()
496 {
497  tssp_ir_tx_stop ();
498  arr_is_mod_on[MOD_IR_TX] = false;
499  arr_is_light_sense_req[MOD_IR_TX] = false;
500  arr_is_light_ok[MOD_IR_TX] = false;
501 }
502 
503 void module_tick_handler ()
504 {
505  if(arr_is_mod_on[MOD_TIMER] == true)
506  {
507  timer_module_add_mod_ticks ();
508  }
509  if(arr_is_mod_on[MOD_IR_TX] == true)
510  {
511  ir_tx_module_add_mod_ticks ();
512  }
513  if(arr_is_mod_on[MOD_RADIO] == true)
514  {
515  radio_module_add_mod_ticks ();
516  }
517 }
518 
519 void sensebe_tx_rx_init (sensebe_tx_config_t * sensebe_tx_init)
520 {
521  log_printf("%s\n", __func__);
522 
523  //Assign Enable and sense pins
524  light_check_sense_pin = sensebe_tx_init->light_sense_config.photodiode_pin;
525  hal_gpio_cfg_input (light_check_sense_pin, HAL_GPIO_PULL_DOWN);
526  light_check_en_pin = sensebe_tx_init->light_sense_config.photodiode_en_pin;
527  hal_gpio_cfg_output (light_check_en_pin, 0);
528 
529 
530 
531  memcpy (&sensebe_config, sensebe_tx_init->sensebe_config,
532  sizeof(sensebe_config_t));
533 
534  cam_trigger_setup_t cam_trig_setup =
535  {
536  .cam_trigger_done_handler = camera_unit_handler,
537  .focus_pin = sensebe_tx_init->cam_config.focus_pin_no,
538  .trigger_pin = sensebe_tx_init->cam_config.trigger_pin_no
539  };
540  cam_trigger_init (&cam_trig_setup);
541 
542  tssp_ir_tx_init (sensebe_tx_init->tx_transmit_config.tx_en_pin,
543  sensebe_tx_init->tx_transmit_config.tx_in_pin);
544 
545  ir_pwr1 = sensebe_tx_init->tx_transmit_config.tx_pwr1;
546  ir_pwr2 = sensebe_tx_init->tx_transmit_config.tx_pwr2;
547 
548 
549  hal_gpio_cfg_output (ir_pwr1, 0);
550  hal_gpio_cfg_output (ir_pwr2, 0);
551 
552 }
553 
555 {
556  log_printf("%s\n", __func__);
557  feedback_timepassed = 0;
558  if(memcmp (&sensebe_config, sensebe_store_config_get_last_config(),
559  sizeof(sensebe_config_t)) != 0)
560  {
561  sensebe_store_config_write (&sensebe_config);
562  }
563 
564  //Check if light sense is required
565 
566  log_printf(" Trig Config : %d\n ", sensebe_config.trig_conf);
567 
568  if((sensebe_config.trig_conf != MOTION_ONLY))
569  {
570  timer_module_start ();
571  }
572  else
573  {
574  timer_module_stop ();
575  }
576 
577  if ((sensebe_config.trig_conf != TIMER_ONLY))
578  {
579  radio_module_start ();
580  }
581  else
582  {
583  radio_module_stop ();
584  }
585 
586  if ((sensebe_config.ir_tx_conf.is_enable == 1))
587  {
588  ir_tx_module_start ();
589  }
590  else
591  {
592  ir_tx_module_stop ();
593  }
594 
595  radio_mod_ticks_freq = RADIO_ON_FREQ_MS/
596  arr_module_tick_duration[sensebe_config.ir_tx_conf.ir_tx_speed];
597 
598  ms_timer_start (SENSEBE_OPERATION_MS_TIMER, MS_REPEATED_CALL,
599  MS_TIMER_TICKS_MS(arr_module_tick_duration[sensebe_config.ir_tx_conf.ir_tx_speed])
600  , module_tick_handler);
601 
602  light_sense_add_ticks (LIGHT_SENSE_INTERVAL_TICKS);
603 }
604 
606 {
607  log_printf("%s\n", __func__);
608  cam_trigger_stop ();
609  timer_module_stop ();
610  ir_tx_module_stop ();
611  radio_module_stop ();
612  ms_timer_stop (SENSEBE_OPERATION_MS_TIMER);
613 }
614 
615 void sensebe_tx_rx_add_ticks (uint32_t interval)
616 {
617  add_ticks_feedback (interval);
618 
619  if(arr_is_light_sense_req [MOD_TIMER] == true ||
620  arr_is_light_sense_req [MOD_IR_TX] == true)
621  {
622  light_sense_add_ticks (interval);
623  }
624 
625  if((sensebe_config.trig_conf != MOTION_ONLY))
626  {
627  timer_module_add_ticks ();
628  }
629  if((sensebe_config.ir_tx_conf.is_enable == 1))
630  {
631  ir_tx_module_add_ticks ();
632  }
633 }
634 
635 void sensebe_tx_rx_update_config (sensebe_config_t * update_sensebe_config)
636 {
637  memcpy (&sensebe_config, update_sensebe_config, sizeof(sensebe_config_t));
638 }
639 
640 sensebe_config_t * sensebe_tx_rx_last_config ()
641 {
642  return &sensebe_config;
643 }
644 
646 {
647  tx_range = (tx_range + 1)%MAX_IR_RANGES;
648  led_ui_single_start (arr_range_indicator[tx_range], LED_UI_LOW_PRIORITY, true);
649 
650  arr_ir_range_select[tx_range]();
651  sensebe_config.ir_tx_conf.ir_tx_pwr = tx_range;
652 }
void(* cam_trigger_done_handler)(uint32_t done_state)
Definition: cam_trigger.h:133
void tssp_detect_window_stop(void)
Function to stop IR missed window detection.
Definition: tssp_detect.c:172
sensebe_config_t * sensebe_tx_rx_last_config()
Function to get last config which is being used.
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
LED_UI_LOW_PRIORITY.
Definition: led_ui.h:41
void sensebe_tx_rx_update_config(sensebe_config_t *update_sensebe_config)
Function to update SenseBe Rx configuration to config received over BLE.
void sensebe_tx_rx_init(sensebe_tx_config_t *sensebe_tx_init)
Function to initialize the Rx detect module.
void sensebe_tx_rx_stop(void)
Function to disable detection for SenseBe Rx.
void sensebe_store_config_write(sensebe_config_t *latest_config)
Function to write the sensebe_config_t at address location received from get_next_location().
void sensebe_tx_rx_swicht_range()
Structure to store information corresponding to hardware and application.
Definition: cam_trigger.h:122
void led_ui_single_start(led_sequences seq, led_ui_priority_t priority, bool reset)
Start a sequence to play once.
Definition: led_ui.c:236
void cam_trigger(uint32_t setup_number)
Function to trigger the camera with given setup number.
Definition: cam_trigger.c:524
bool cam_trigger_is_on(void)
Function to check status of cam_trigger module.
Definition: cam_trigger.c:563
void sensebe_tx_rx_start(void)
Function to enable detection for SenseBe Rx.
Repeated call of the timer.
Definition: ms_timer.h:83
#define MS_TIMER_TICKS_MS(ms)
Definition: ms_timer.h:64
sensebe_config_t * sensebe_store_config_get_last_config()
Trigger only on timer.
Definition: sensebe_ble.h:51
void ms_timer_start(ms_timer_num id, ms_timer_mode mode, uint64_t ticks, void(*handler)(void))
Definition: ms_timer.c:134
void cam_trigger_stop(void)
Function to stop camera trigger.
Definition: cam_trigger.c:557
void sensebe_tx_rx_add_ticks(uint32_t interval)
Function to handle add tick event.
void cam_trigger_set_trigger(cam_trigger_config_t *cam_trigger_config)
Function to set a camera trigger.
Definition: cam_trigger.c:483
void tssp_detect_pulse_stop()
Function to stop IR pulse detection.
Definition: tssp_detect.c:156
Gain factor 1/6.
Definition: simple_adc.h:70
void cam_trigger_init(cam_trigger_setup_t *cam_trigger_setup)
Function to initiate output pins.
Definition: cam_trigger.c:469
Structure to store information related to camera trigger.
Definition: cam_trigger.h:86
void tssp_detect_window_detect()
Function to start IR pulse detection.
Definition: tssp_detect.c:131
HAL_GPIO_PULL_DOWN.
Definition: hal_gpio.h:38
void ms_timer_stop(ms_timer_num id)
Definition: ms_timer.c:173
void led_ui_stop_seq(led_ui_seq_t type, led_sequences seq)
Stops a particular sequence of a particular type.
Definition: led_ui.c:283