Firmware SDK
 All Data Structures Functions Variables Typedefs Enumerations Enumerator Groups Pages
bc_pyq1648.c
1 #include <bc_pyq1648.h>
2 #include <bc_irq.h>
3 #include <bc_gpio.h>
4 #include <bc_system.h>
5 #include <bc_timer.h>
6 #include <stm32l0xx.h>
7 
8 #define BC_PYQ1648_BPF 0x00
9 #define BC_PYQ1648_LPF 0x01
10 #define BC_PYQ1648_WAKE_UP_MODE 0x02
11 
12 #define BC_PYQ1648_DELAY_RUN 50
13 #define BC_PYQ1648_DELAY_INITIALIZATION 10
14 #define BC_PYQ1648_UPDATE_INTERVAL 100
15 
16 static inline void _bc_pyq1648_msp_init(bc_gpio_channel_t gpio_channel_serin, bc_gpio_channel_t gpio_channel_dl);
17 static inline void _bc_pyq1648_dev_init(bc_pyq1648_t *self);
18 static inline void _bc_pyq1648_compose_event_unit_config(bc_pyq1648_t *self);
19 static void _bc_pyq1648_task(void *param);
20 
21 static const uint8_t _bc_pyq1648_sensitivity_table[4] =
22 {
27 };
28 
29 extern GPIO_TypeDef * bc_gpio_port[];
30 extern uint16_t bc_gpio_16_bit_mask[];
31 extern uint32_t bc_gpio_32_bit_upper_mask[];
32 
33 static GPIO_TypeDef **_pyq1648_gpiox_table = bc_gpio_port;
34 static uint16_t *_pyq1648_set_mask = bc_gpio_16_bit_mask;
35 static uint32_t *_pyq1648_reset_mask = bc_gpio_32_bit_upper_mask;
36 
37 void bc_pyq1648_init(bc_pyq1648_t *self, bc_gpio_channel_t gpio_channel_serin, bc_gpio_channel_t gpio_channel_dl)
38 {
39  // Initialize structure
40  memset(self, 0, sizeof(*self));
41 
42  // Initialize default values
43  self->_sensitivity = _bc_pyq1648_sensitivity_table[BC_PYQ1648_SENSITIVITY_HIGH];
44  self->_blank_period = 1000;
45 
46  // Initialize actually used pins
47  self->_gpio_channel_serin = gpio_channel_serin;
48  self->_gpio_channel_dl = gpio_channel_dl;
49 
50  // Initialize event_unit_configuration register value
51  // _bc_pyq1648_compose_event_unit_config(self);
52 
53  // Register task
54  self->_task_id = bc_scheduler_register(_bc_pyq1648_task, self, BC_PYQ1648_DELAY_RUN);
55 
56  bc_timer_init();
57 }
58 
59 void bc_pyq1648_set_event_handler(bc_pyq1648_t *self, void (*event_handler)(bc_pyq1648_t *, bc_pyq1648_event_t, void *), void *event_param)
60 {
61  // Set event handler
62  self->_event_handler = event_handler;
63 
64  // Set event param
65  self->_event_param = event_param;
66 }
67 
69 {
70  // Set sensitivity to desired value
71  self->_sensitivity = _bc_pyq1648_sensitivity_table[sensitivity];
72 
73  self->_state = BC_PYQ1648_STATE_INITIALIZE;
74 
75  bc_scheduler_plan_now(self->_task_id);
76 }
77 
79 {
80  // Set blank period
81  self->_blank_period = blank_period;
82 }
83 
84 void _bc_pyq1648_compose_event_unit_config(bc_pyq1648_t *self)
85 {
86  // --------------------------------------------------------------------------------------------------------------------------------------
87  // | Event unit configuration |
88  // --------------------------------------------------------------------------------------------------------------------------------------
89  // | 7bit sensitivity | 4bit blind time | 2bit pulse counter | 2bit window time | 2bit operatin mode | 2bit filter source | 5bit reserved |
90  // --------------------------------------------------------------------------------------------------------------------------------------
91  // | from self | handled by SW | 0x00 | 0x00 | wake up mode | Band pass filter | has to be 16 |
92  // --------------------------------------------------------------------------------------------------------------------------------------
93 
94  self->_config = 0x00000000;
95  self->_config |= (self->_sensitivity << 17) | (BC_PYQ1648_WAKE_UP_MODE << 7) | (BC_PYQ1648_BPF << 5) |0x10;
96 }
97 
98 static inline void _bc_pyq1648_msp_init(bc_gpio_channel_t gpio_channel_serin, bc_gpio_channel_t gpio_channel_dl)
99 {
100  // Initialize SerialIn (SERIN) GPIO pin
101  bc_gpio_init(gpio_channel_serin);
102  bc_gpio_set_mode(gpio_channel_serin, BC_GPIO_MODE_OUTPUT);
103 
104  // Initialize DirectLink (DL) GPIO pin
105  bc_gpio_init(gpio_channel_dl);
106  bc_gpio_set_mode(gpio_channel_dl, BC_GPIO_MODE_INPUT);
107  bc_gpio_set_pull(gpio_channel_dl, BC_GPIO_PULL_DOWN);
108 }
109 
110 static void _bc_pyq1648_clear_event(bc_pyq1648_t *self)
111 {
112  // Clear event by pull down DL
113  bc_gpio_set_mode(self->_gpio_channel_dl, BC_GPIO_MODE_OUTPUT);
114  bc_gpio_set_output(self->_gpio_channel_dl, 0);
115  bc_gpio_set_mode(self->_gpio_channel_dl, BC_GPIO_MODE_INPUT);
116 }
117 
118 // TODO Consider using "OneWire"
119 static inline void _bc_pyq1648_dev_init(bc_pyq1648_t *self)
120 {
121  // Disable interrupts
122  bc_irq_disable();
123 
124  // Enable PLL
125  bc_system_pll_enable();
126 
127  // Load desired event unit configuration
128  uint32_t regval = self->_config;
129  uint32_t regmask = 0x1000000;
130  bool next_bit;
131 
132  // Prepare fast GPIO access
133  uint32_t bsrr_mask[2] =
134  {
135  [0] = _pyq1648_reset_mask[self->_gpio_channel_serin],
136  [1] = _pyq1648_set_mask[self->_gpio_channel_serin]
137  };
138  GPIO_TypeDef *GPIOx = _pyq1648_gpiox_table[self->_gpio_channel_serin];
139  volatile uint32_t *GPIOx_BSRR = &GPIOx->BSRR;
140 
141  // Low level pin initialization
142  _bc_pyq1648_msp_init(self->_gpio_channel_serin, self->_gpio_channel_dl);
143 
144  // Transmit event unit configuration
145  for (int i = 0; i < 25; i++)
146  {
147  next_bit = (regval & regmask) != 0 ? true : false;
148  regmask >>= 1;
149 
150  bc_timer_start();
151 
152  *GPIOx_BSRR = bsrr_mask[0];
153 
154  while (bc_timer_get_microseconds() < 1)
155  {
156  continue;
157  }
158 
159  *GPIOx_BSRR = bsrr_mask[1];
160 
161  while (bc_timer_get_microseconds() < 2)
162  {
163  continue;
164  }
165 
166  *GPIOx_BSRR = bsrr_mask[next_bit];
167 
168  while (bc_timer_get_microseconds() < 83)
169  {
170  continue;
171  }
172 
173  bc_timer_stop();
174  }
175 
176  bc_gpio_set_output(self->_gpio_channel_serin, 0);
177 
178  // Disable PLL
179  bc_system_pll_disable();
180 
181  // Enable interrupts
182  bc_irq_enable();
183 }
184 
185 static void _bc_pyq1648_task(void *param)
186 {
187  bc_pyq1648_t *self = param;
188 
189 start:
190 
191  switch (self->_state)
192  {
193  case BC_PYQ1648_STATE_ERROR:
194  {
195  if (self->_event_handler != NULL)
196  {
197  self->_event_handler(self, BC_PYQ1648_EVENT_ERROR, self->_event_param);
198  }
199 
200  self->_state = BC_PYQ1648_STATE_INITIALIZE;
201 
202  bc_scheduler_plan_current_relative(BC_PYQ1648_UPDATE_INTERVAL);
203 
204  return;
205  }
206  case BC_PYQ1648_STATE_INITIALIZE:
207  {
208  self->_state = BC_PYQ1648_STATE_ERROR;
209 
210  _bc_pyq1648_compose_event_unit_config(self);
211 
212  _bc_pyq1648_dev_init(self);
213 
214  self->_state = BC_PYQ1648_STATE_IGNORE;
215 
216  bc_scheduler_plan_current_relative(BC_PYQ1648_DELAY_INITIALIZATION);
217 
218  return;
219  }
220  case BC_PYQ1648_STATE_IGNORE:
221  {
222  self->_state = BC_PYQ1648_STATE_ERROR;
223 
224  if (self->_ignore_untill == 0)
225  {
226  // TODO ... acquire !!!
227  self->_ignore_untill = bc_tick_get() + (75000 / 15);
228  }
229 
230  if (bc_gpio_get_input(self->_gpio_channel_dl) != 0)
231  {
232  _bc_pyq1648_clear_event(self);
233  }
234 
235  if (bc_tick_get() >= self->_ignore_untill)
236  {
237  self->_state = BC_PYQ1648_STATE_CHECK;
238  }
239  else
240  {
241  self->_state = BC_PYQ1648_STATE_IGNORE;
242  }
243 
244  bc_scheduler_plan_current_relative(BC_PYQ1648_UPDATE_INTERVAL);
245 
246  return;
247  }
248  case BC_PYQ1648_STATE_CHECK:
249  {
250  bc_tick_t tick_now = bc_tick_get();
251 
252  self->_state = BC_PYQ1648_STATE_ERROR;
253 
254  if (bc_gpio_get_input(self->_gpio_channel_dl) != 0)
255  {
256  if (tick_now >= self->_aware_time)
257  {
258  if (self->_event_handler != NULL)
259  {
260  self->_event_handler(self, BC_PYQ1648_EVENT_MOTION, self->_event_param);
261  }
262 
263  self->_aware_time = tick_now + self->_blank_period;
264  }
265  _bc_pyq1648_clear_event(self);
266  }
267 
268  self->_state = BC_PYQ1648_STATE_CHECK;
269 
270  bc_scheduler_plan_current_relative(BC_PYQ1648_UPDATE_INTERVAL);
271 
272  return;
273  }
274  default:
275  {
276  self->_state = BC_PYQ1648_STATE_ERROR;
277 
278  goto start;
279  }
280  }
281 }
uint64_t bc_tick_t
Timestamp data type.
Definition: bc_tick.h:16
void bc_irq_enable(void)
Enable interrupt requests globally (call can be nested)
Definition: bc_irq.c:21
Update event.
Definition: bc_pyq1648.h:20
void bc_timer_start(void)
Start timer.
Definition: bc_timer.c:24
bc_scheduler_task_id_t bc_scheduler_register(void(*task)(void *), void *param, bc_tick_t tick)
Register task in scheduler.
Definition: bc_scheduler.c:56
void bc_scheduler_plan_now(bc_scheduler_task_id_t task_id)
Schedule specified task for immediate execution.
Definition: bc_scheduler.c:119
void bc_gpio_set_output(bc_gpio_channel_t channel, int state)
Set output state for GPIO channel.
Definition: bc_gpio.c:442
void bc_pyq1648_set_blank_period(bc_pyq1648_t *self, bc_tick_t blank_period)
Set blank period (for how long alarm events will be ignored)
Definition: bc_pyq1648.c:78
void bc_pyq1648_set_event_handler(bc_pyq1648_t *self, void(*event_handler)(bc_pyq1648_t *, bc_pyq1648_event_t, void *), void *event_param)
Set callback function.
Definition: bc_pyq1648.c:59
void bc_gpio_set_mode(bc_gpio_channel_t channel, bc_gpio_mode_t mode)
Set mode of operation for GPIO channel.
Definition: bc_gpio.c:340
Error event.
Definition: bc_pyq1648.h:17
void bc_gpio_set_pull(bc_gpio_channel_t channel, bc_gpio_pull_t pull)
Set pull-up/pull-down configuration for GPIO channel.
Definition: bc_gpio.c:313
bc_tick_t bc_tick_get(void)
Get absolute timestamp since start of program.
Definition: bc_tick.c:7
void bc_scheduler_plan_current_relative(bc_tick_t tick)
Schedule current task to tick relative from current spin.
Definition: bc_scheduler.c:149
void bc_timer_stop(void)
Stop timer.
Definition: bc_timer.c:55
void bc_pyq1648_init(bc_pyq1648_t *self, bc_gpio_channel_t gpio_channel_serin, bc_gpio_channel_t gpio_channel_dl)
Initialize PYQ1648 driver.
Definition: bc_pyq1648.c:37
Medium sensitivity.
Definition: bc_pyq1648.h:32
int bc_gpio_get_input(bc_gpio_channel_t channel)
Get input state for GPIO channel.
Definition: bc_gpio.c:436
bc_pyq1648_sensitivity_t
Possible sensitivities.
Definition: bc_pyq1648.h:26
GPIO channel operates as input.
Definition: bc_gpio.h:99
High sensitivity.
Definition: bc_pyq1648.h:35
struct bc_pyq1648_t bc_pyq1648_t
PYQ1648 instance.
Definition: bc_pyq1648.h:44
uint16_t bc_timer_get_microseconds(void)
Get actual tick of timer.
Definition: bc_timer.c:35
Low sensitivity.
Definition: bc_pyq1648.h:29
void bc_pyq1648_set_sensitivity(bc_pyq1648_t *self, bc_pyq1648_sensitivity_t sensitivity)
Set PYQ1648 sensitivity.
Definition: bc_pyq1648.c:68
GPIO channel has pull-down.
Definition: bc_gpio.h:90
bc_gpio_channel_t
GPIO channels.
Definition: bc_gpio.h:12
void bc_irq_disable(void)
Disable interrupt requests globally (call can be nested)
Definition: bc_irq.c:7
Very high sensitivity.
Definition: bc_pyq1648.h:38
void bc_timer_init(void)
Initialize timer.
Definition: bc_timer.c:18
void bc_gpio_init(bc_gpio_channel_t channel)
Initialize GPIO channel.
Definition: bc_gpio.c:301
GPIO channel operates as output.
Definition: bc_gpio.h:102
bc_pyq1648_event_t
Callback events.
Definition: bc_pyq1648.h:14