Firmware SDK
 All Data Structures Functions Variables Typedefs Enumerations Enumerator Groups Pages
bc_led.c
1 #include <bc_led.h>
2 
3 #define _BC_LED_DEFAULT_SLOT_INTERVAL 100
4 
5 static void _bc_led_gpio_init(bc_led_t *self)
6 {
7  bc_gpio_init(self->_channel.gpio);
8 }
9 
10 static void _bc_led_gpio_on(bc_led_t *self)
11 {
12  bc_gpio_set_output(self->_channel.gpio, self->_idle_state ? 0 : 1);
13 }
14 
15 static void _bc_led_gpio_off(bc_led_t *self)
16 {
17  bc_gpio_set_output(self->_channel.gpio, self->_idle_state ? 1 : 0);
18 }
19 
20 static const bc_led_driver_t _bc_led_driver_gpio =
21 {
22  .init = _bc_led_gpio_init,
23  .on = _bc_led_gpio_on,
24  .off = _bc_led_gpio_off
25 };
26 
27 static void _bc_led_task(void *param)
28 {
29  bc_led_t *self = param;
30 
31  if (self->_pulse_active)
32  {
33  self->_driver->off(self);
34 
35  self->_pulse_active = false;
36  self->_selector = 0;
37 
38  bc_scheduler_plan_current_relative(self->_slot_interval);
39 
40  return;
41  }
42 
43  if (self->_pattern == 0 || self->_pattern == 0xffffffff)
44  {
45  return;
46  }
47 
48  if (self->_selector == 0)
49  {
50  self->_selector = 0x80000000;
51  }
52 
53  if ((self->_pattern & self->_selector) != 0)
54  {
55  self->_driver->on(self);
56  }
57  else
58  {
59  self->_driver->off(self);
60  }
61 
62  self->_selector >>= 1;
63 
64  if (self->_count != 0)
65  {
66  if (--self->_count == 0)
67  {
68  self->_pattern = 0;
69  }
70  }
71 
72  bc_scheduler_plan_current_relative(self->_slot_interval);
73 }
74 
75 void bc_led_init(bc_led_t *self, bc_gpio_channel_t gpio_channel, bool open_drain_output, int idle_state)
76 {
77  memset(self, 0, sizeof(*self));
78 
79  self->_channel.gpio = gpio_channel;
80 
81  self->_open_drain_output = open_drain_output;
82 
83  self->_idle_state = idle_state;
84 
85  self->_driver = &_bc_led_driver_gpio;
86  self->_driver->init(self);
87  self->_driver->off(self);
88 
89  if (self->_open_drain_output)
90  {
91  bc_gpio_set_mode(self->_channel.gpio, BC_GPIO_MODE_OUTPUT_OD);
92  }
93  else
94  {
95  bc_gpio_set_mode(self->_channel.gpio, BC_GPIO_MODE_OUTPUT);
96  }
97 
98  self->_slot_interval = _BC_LED_DEFAULT_SLOT_INTERVAL;
99 
100  self->_task_id = bc_scheduler_register(_bc_led_task, self, BC_TICK_INFINITY);
101 }
102 
103 void bc_led_init_virtual(bc_led_t *self, int channel, const bc_led_driver_t *driver, int idle_state)
104 {
105  memset(self, 0, sizeof(*self));
106 
107  self->_channel.virtual = channel;
108 
109  self->_idle_state = idle_state;
110 
111  self->_driver = driver;
112  self->_driver->init(self);
113  self->_driver->off(self);
114 
115  self->_slot_interval = _BC_LED_DEFAULT_SLOT_INTERVAL;
116 
117  self->_task_id = bc_scheduler_register(_bc_led_task, self, BC_TICK_INFINITY);
118 }
119 
121 {
122  self->_slot_interval = interval;
123 }
124 
126 {
127  uint32_t pattern = self->_pattern;
128 
129  switch (mode)
130  {
131  case BC_LED_MODE_TOGGLE:
132  {
133  if (pattern == 0)
134  {
135  self->_pattern = 0xffffffff;
136  self->_count = 0;
137 
138  self->_driver->on(self);
139  }
140  else if (pattern == 0xffffffff)
141  {
142  self->_pattern = 0;
143  self->_count = 0;
144 
145  if (!self->_pulse_active)
146  {
147  self->_driver->off(self);
148  }
149  }
150 
151  return;
152  }
153  case BC_LED_MODE_OFF:
154  {
155  self->_pattern = 0x00000000;
156  self->_count = 0;
157 
158  if (!self->_pulse_active)
159  {
160  self->_driver->off(self);
161  }
162 
163  return;
164  }
165  case BC_LED_MODE_ON:
166  {
167  self->_pattern = 0xffffffff;
168  self->_count = 0;
169 
170  if (!self->_pulse_active)
171  {
172  self->_driver->on(self);
173  }
174 
175  return;
176  }
177  case BC_LED_MODE_BLINK:
178  {
179  pattern = 0xf0f0f0f0;
180 
181  break;
182  }
184  {
185  pattern = 0xffff0000;
186 
187  break;
188  }
190  {
191  pattern = 0xaaaaaaaa;
192 
193  break;
194  }
195  case BC_LED_MODE_FLASH:
196  {
197  pattern = 0x80000000;
198 
199  break;
200  }
201  default:
202  {
203  break;
204  }
205  }
206 
207  if (self->_pattern != pattern)
208  {
209  self->_pattern = pattern;
210  self->_selector = 0;
211  self->_count = 0;
212  }
213 
214  bc_scheduler_plan_now(self->_task_id);
215 }
216 
217 void bc_led_set_pattern(bc_led_t *self, uint32_t pattern)
218 {
219  self->_pattern = pattern;
220  self->_selector = 0;
221 
222  bc_scheduler_plan_now(self->_task_id);
223 }
224 
225 void bc_led_set_count(bc_led_t *self, int count)
226 {
227  self->_count = count;
228 }
229 
230 void bc_led_blink(bc_led_t *self, int count)
231 {
232  self->_pattern = 0xf0f0f0f0;
233  self->_selector = 0;
234  self->_count = count * 8;
235 
236  bc_scheduler_plan_now(self->_task_id);
237 }
238 
239 void bc_led_pulse(bc_led_t *self, bc_tick_t duration)
240 {
241  if (!self->_pulse_active)
242  {
243  self->_driver->on(self);
244 
245  self->_pulse_active = true;
246  }
247 
248  bc_scheduler_plan_from_now(self->_task_id, duration);
249 }
250 
252 {
253  return self->_pulse_active;
254 }
bool bc_led_is_pulse(bc_led_t *self)
Check if there is ongoing LED pulse.
Definition: bc_led.c:251
uint64_t bc_tick_t
Timestamp data type.
Definition: bc_tick.h:16
LED toggles between on/off state (this has no effect while processing alternating patterns) ...
Definition: bc_led.h:28
LED driver interface.
Definition: bc_led.h:56
bc_led_mode_t
LED modes.
Definition: bc_led.h:25
void bc_led_set_slot_interval(bc_led_t *self, bc_tick_t interval)
Set slot interval for pattern processing.
Definition: bc_led.c:120
void bc_led_set_count(bc_led_t *self, int count)
Set count for blinking pattern executed.
Definition: bc_led.c:225
LED has steady off state.
Definition: bc_led.h:31
void bc_led_blink(bc_led_t *self, int count)
LED blink.
Definition: bc_led.c:230
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
LED flashes repeatedly.
Definition: bc_led.h:46
struct bc_led_t bc_led_t
LED instance.
Definition: bc_led.h:52
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
LED blinks slowly.
Definition: bc_led.h:40
LED blinks quickly.
Definition: bc_led.h:43
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_led_set_mode(bc_led_t *self, bc_led_mode_t mode)
Set LED mode.
Definition: bc_led.c:125
LED blinks.
Definition: bc_led.h:37
void(* init)(bc_led_t *self)
Callback for initialization.
Definition: bc_led.h:59
void bc_led_init(bc_led_t *self, bc_gpio_channel_t gpio_channel, bool open_drain_output, int idle_state)
Initialize LED.
Definition: bc_led.c:75
void bc_led_set_pattern(bc_led_t *self, uint32_t pattern)
Set custom blinking pattern.
Definition: bc_led.c:217
void bc_scheduler_plan_from_now(bc_scheduler_task_id_t task_id, bc_tick_t tick)
Schedule specified task to tick relative from now.
Definition: bc_scheduler.c:134
#define BC_TICK_INFINITY
Maximum timestamp value.
Definition: bc_tick.h:12
bc_gpio_channel_t
GPIO channels.
Definition: bc_gpio.h:12
LED has steady on state.
Definition: bc_led.h:34
GPIO channel operates as open-drain output.
Definition: bc_gpio.h:111
void bc_led_init_virtual(bc_led_t *self, int channel, const bc_led_driver_t *driver, int idle_state)
Initialize virtual LED.
Definition: bc_led.c:103
void bc_led_pulse(bc_led_t *self, bc_tick_t duration)
Turn on LED for the specified duration of time.
Definition: bc_led.c:239
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