Firmware SDK
 All Data Structures Functions Variables Typedefs Enumerations Enumerator Groups Pages
bc_switch.c
1 #include <bc_switch.h>
2 #include <bc_timer.h>
3 
4 #define _BC_SWITCH_SCAN_INTERVAL 50
5 #define _BC_SWITCH_DEBOUNCE_TIME 20
6 #define _BC_SWITCH_PULL_ADVANCE_TIME_US 50
7 
8 static void _bc_switch_task(void *param);
9 
10 static const bc_gpio_pull_t _bc_switch_pull_lut[5] = {
16 };
17 
19 {
20  memset(self, 0, sizeof(&self));
21  self->_channel = channel;
22  self->_type = type;
23  self->_pull = pull;
24  self->_scan_interval = _BC_SWITCH_SCAN_INTERVAL;
25  self->_debounce_time = _BC_SWITCH_DEBOUNCE_TIME;
26  self->_pull_advance_time = _BC_SWITCH_PULL_ADVANCE_TIME_US;
27 
28  bc_gpio_init(channel);
29 
31 
32  self->_task_id = bc_scheduler_register(_bc_switch_task, self, 0);
33 
34  if ((self->_pull == BC_SWITCH_PULL_UP_DYNAMIC) || (self->_pull == BC_SWITCH_PULL_DOWN_DYNAMIC))
35  {
36  if (self->_pull_advance_time > 1000)
37  {
38  self->_task_state = BC_SWITCH_TASK_STATE_SET_PULL;
39  }
40 
41  bc_gpio_set_pull(self->_channel, BC_GPIO_PULL_NONE);
42 
43  bc_timer_init();
44  }
45  else
46  {
47  bc_gpio_set_pull(self->_channel, _bc_switch_pull_lut[self->_pull]);
48  }
49 }
50 
52 {
53  return self->_pin_state != 0 ? BC_SWITCH_OPEN : BC_SWITCH_CLOSE;
54 }
55 
56 void bc_switch_set_event_handler(bc_switch_t *self, void (*event_handler)(bc_switch_t *, bc_switch_event_t, void*), void *event_param)
57 {
58  self->_event_handler = event_handler;
59  self->_event_param = event_param;
60 }
61 
63 {
64  self->_scan_interval = scan_interval;
65 }
66 
68 {
69  self->_debounce_time = debounce_time;
70 }
71 
72 void bc_switch_set_pull_advance_time(bc_switch_t *self, uint16_t pull_advance_time_us)
73 {
74  self->_pull_advance_time = pull_advance_time_us;
75 }
76 
77 static void _bc_switch_task(void *param)
78 {
79  bc_switch_t *self = (bc_switch_t *) param;
80 
81  switch (self->_task_state)
82  {
83  case BC_SWITCH_TASK_STATE_MEASURE:
84  {
85  bool dynamic = (self->_pull == BC_SWITCH_PULL_UP_DYNAMIC) || (self->_pull == BC_SWITCH_PULL_DOWN_DYNAMIC);
86 
87  if (dynamic)
88  {
89  if (self->_pull_advance_time < 1000)
90  {
91  bc_gpio_set_pull(self->_channel, _bc_switch_pull_lut[self->_pull]);
92 
94 
95  bc_timer_delay(self->_pull_advance_time);
96 
97  bc_timer_stop();
98  }
99  }
100 
101  int pin_state = bc_gpio_get_input(self->_channel);
102 
103  if (dynamic)
104  {
105  bc_gpio_set_pull(self->_channel, BC_GPIO_PULL_NONE);
106 
107  if (self->_pull_advance_time > 1000)
108  {
109  self->_task_state = BC_SWITCH_TASK_STATE_SET_PULL;
110  }
111  }
112 
113  if (self->_type == BC_SWITCH_TYPE_NC)
114  {
115  pin_state = pin_state == 0 ? 1 : 0;
116  }
117 
119 
120  if (self->_pin_state != pin_state)
121  {
122  if (self->_tick_debounce == BC_TICK_INFINITY)
123  {
124  self->_tick_debounce = tick_now + self->_debounce_time;
125 
126  bc_scheduler_plan_current_relative(self->_debounce_time);
127 
128  return;
129  }
130 
131  if (tick_now >= self->_tick_debounce)
132  {
133  self->_pin_state = pin_state;
134 
135  if (self->_event_handler != NULL)
136  {
137  if (self->_pin_state != 0)
138  {
139  self->_event_handler(self, BC_SWITCH_EVENT_CLOSED, self->_event_param);
140  }
141  else
142  {
143  self->_event_handler(self, BC_SWITCH_EVENT_OPENED, self->_event_param);
144  }
145  }
146  }
147  }
148  else
149  {
150  self->_tick_debounce = BC_TICK_INFINITY;
151  }
152 
153  bc_scheduler_plan_current_relative(self->_scan_interval);
154 
155  return;
156 
157  }
158  case BC_SWITCH_TASK_STATE_SET_PULL:
159  {
160  bc_gpio_set_pull(self->_channel, _bc_switch_pull_lut[self->_pull]);
161 
162  bc_scheduler_plan_current_relative(self->_pull_advance_time / 1000);
163 
164  self->_task_state = BC_SWITCH_TASK_STATE_MEASURE;
165 
166  return;
167  }
168  default:
169  {
170  return;
171  }
172  }
173 }
void bc_switch_set_scan_interval(bc_switch_t *self, bc_tick_t scan_interval)
Set scan interval (period of button input sampling), default 50ms.
Definition: bc_switch.c:62
uint64_t bc_tick_t
Timestamp data type.
Definition: bc_tick.h:16
Pull Up.
Definition: bc_switch.h:47
GPIO channel has no pull-up/pull-down.
Definition: bc_gpio.h:84
struct bc_switch_t bc_switch_t
State.
Definition: bc_switch.h:62
bc_tick_t bc_scheduler_get_spin_tick(void)
Get current tick of spin in which task has been run.
Definition: bc_scheduler.c:104
bool bc_switch_get_state(bc_switch_t *self)
Get state.
Definition: bc_switch.c:51
GPIO channel has pull-up.
Definition: bc_gpio.h:87
bc_switch_pull_t
Pull.
Definition: bc_switch.h:41
void bc_timer_start(void)
Start timer.
Definition: bc_timer.c:24
bc_switch_type_t
Type.
Definition: bc_switch.h:29
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_timer_delay(uint16_t microseconds)
Relative delay.
Definition: bc_timer.c:40
void bc_switch_set_debounce_time(bc_switch_t *self, bc_tick_t debounce_time)
Set debounce time (minimum sampling interval during which input cannot change to toggle its state)...
Definition: bc_switch.c:67
Pull Down dynamic (Turns pull only for measurement)
Definition: bc_switch.h:56
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
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_gpio_pull_t
GPIO pull-up/pull-down setting.
Definition: bc_gpio.h:81
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
Event Opened.
Definition: bc_switch.h:20
int bc_gpio_get_input(bc_gpio_channel_t channel)
Get input state for GPIO channel.
Definition: bc_gpio.c:436
GPIO channel operates as input.
Definition: bc_gpio.h:99
void bc_switch_set_event_handler(bc_switch_t *self, void(*event_handler)(bc_switch_t *, bc_switch_event_t, void *), void *event_param)
Set callback function.
Definition: bc_switch.c:56
GPIO channel has pull-down.
Definition: bc_gpio.h:90
void bc_switch_init(bc_switch_t *self, bc_gpio_channel_t channel, bc_switch_type_t type, bc_switch_pull_t pull)
Initialize button.
Definition: bc_switch.c:18
void bc_switch_set_pull_advance_time(bc_switch_t *self, uint16_t pull_advance_time_us)
Set pull advance time (work only with dynamic pull up/down), default 50us, for time bigger than 1000u...
Definition: bc_switch.c:72
Pull None.
Definition: bc_switch.h:44
#define BC_TICK_INFINITY
Maximum timestamp value.
Definition: bc_tick.h:12
bc_gpio_channel_t
GPIO channels.
Definition: bc_gpio.h:12
bc_switch_event_t
Callback events.
Definition: bc_switch.h:17
void bc_timer_init(void)
Initialize timer.
Definition: bc_timer.c:18
Pull Down.
Definition: bc_switch.h:53
void bc_gpio_init(bc_gpio_channel_t channel)
Initialize GPIO channel.
Definition: bc_gpio.c:301
Type Normally Closed.
Definition: bc_switch.h:35
Event Closed.
Definition: bc_switch.h:23
Pull Up dynamic (Turns pull only for measurement)
Definition: bc_switch.h:50