Firmware SDK
twr_led.c
1 #include <twr_led.h>
2 
3 #define _TWR_LED_DEFAULT_SLOT_INTERVAL 100
4 
5 static void _twr_led_gpio_init(twr_led_t *self)
6 {
7  twr_gpio_init(self->_channel.gpio);
8 }
9 
10 static void _twr_led_gpio_on(twr_led_t *self)
11 {
12  twr_gpio_set_output(self->_channel.gpio, self->_idle_state ? 0 : 1);
13 }
14 
15 static void _twr_led_gpio_off(twr_led_t *self)
16 {
17  twr_gpio_set_output(self->_channel.gpio, self->_idle_state ? 1 : 0);
18 }
19 
20 static const twr_led_driver_t _twr_led_driver_gpio =
21 {
22  .init = _twr_led_gpio_init,
23  .on = _twr_led_gpio_on,
24  .off = _twr_led_gpio_off
25 };
26 
27 static void _twr_led_task(void *param)
28 {
29  twr_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  twr_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  twr_scheduler_plan_current_relative(self->_slot_interval);
73 }
74 
75 void twr_led_init(twr_led_t *self, twr_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 = &_twr_led_driver_gpio;
86  self->_driver->init(self);
87  self->_driver->off(self);
88 
89  if (self->_open_drain_output)
90  {
91  twr_gpio_set_mode(self->_channel.gpio, TWR_GPIO_MODE_OUTPUT_OD);
92  }
93  else
94  {
95  twr_gpio_set_mode(self->_channel.gpio, TWR_GPIO_MODE_OUTPUT);
96  }
97 
98  self->_slot_interval = _TWR_LED_DEFAULT_SLOT_INTERVAL;
99 
100  self->_task_id = twr_scheduler_register(_twr_led_task, self, TWR_TICK_INFINITY);
101 }
102 
103 void twr_led_init_virtual(twr_led_t *self, int channel, const twr_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 = _TWR_LED_DEFAULT_SLOT_INTERVAL;
116 
117  self->_task_id = twr_scheduler_register(_twr_led_task, self, TWR_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 TWR_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 TWR_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 TWR_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 TWR_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 TWR_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  twr_scheduler_plan_now(self->_task_id);
215 }
216 
217 void twr_led_set_pattern(twr_led_t *self, uint32_t pattern)
218 {
219  self->_pattern = pattern;
220  self->_selector = 0;
221 
222  twr_scheduler_plan_now(self->_task_id);
223 }
224 
225 void twr_led_set_count(twr_led_t *self, int count)
226 {
227  self->_count = count;
228 }
229 
230 void twr_led_blink(twr_led_t *self, int count)
231 {
232  self->_pattern = 0xf0f0f0f0;
233  self->_selector = 0;
234  self->_count = count * 8;
235 
236  twr_scheduler_plan_now(self->_task_id);
237 }
238 
239 void twr_led_pulse(twr_led_t *self, twr_tick_t duration)
240 {
241  if (!self->_pulse_active)
242  {
243  self->_driver->on(self);
244 
245  self->_pulse_active = true;
246  }
247 
248  twr_scheduler_plan_from_now(self->_task_id, duration);
249 }
250 
252 {
253  return self->_pulse_active;
254 }
void twr_gpio_set_output(twr_gpio_channel_t channel, int state)
Set output state for GPIO channel.
Definition: twr_gpio.c:471
void twr_gpio_init(twr_gpio_channel_t channel)
Initialize GPIO channel.
Definition: twr_gpio.c:325
twr_gpio_channel_t
GPIO channels.
Definition: twr_gpio.h:13
void twr_gpio_set_mode(twr_gpio_channel_t channel, twr_gpio_mode_t mode)
Set mode of operation for GPIO channel.
Definition: twr_gpio.c:367
@ TWR_GPIO_MODE_OUTPUT
GPIO channel operates as output.
Definition: twr_gpio.h:108
@ TWR_GPIO_MODE_OUTPUT_OD
GPIO channel operates as open-drain output.
Definition: twr_gpio.h:117
bool twr_led_is_pulse(twr_led_t *self)
Check if there is ongoing LED pulse.
Definition: twr_led.c:251
void twr_led_set_slot_interval(twr_led_t *self, twr_tick_t interval)
Set slot interval for pattern processing.
Definition: twr_led.c:120
void twr_led_set_pattern(twr_led_t *self, uint32_t pattern)
Set custom blinking pattern.
Definition: twr_led.c:217
void twr_led_init_virtual(twr_led_t *self, int channel, const twr_led_driver_t *driver, int idle_state)
Initialize virtual LED.
Definition: twr_led.c:103
struct twr_led_t twr_led_t
LED instance.
Definition: twr_led.h:52
void twr_led_init(twr_led_t *self, twr_gpio_channel_t gpio_channel, bool open_drain_output, int idle_state)
Initialize LED.
Definition: twr_led.c:75
void twr_led_blink(twr_led_t *self, int count)
LED blink.
Definition: twr_led.c:230
twr_led_mode_t
LED modes.
Definition: twr_led.h:26
void twr_led_pulse(twr_led_t *self, twr_tick_t duration)
Turn on LED for the specified duration of time.
Definition: twr_led.c:239
void twr_led_set_count(twr_led_t *self, int count)
Set count for blinking pattern executed.
Definition: twr_led.c:225
void twr_led_set_mode(twr_led_t *self, twr_led_mode_t mode)
Set LED mode.
Definition: twr_led.c:125
@ TWR_LED_MODE_TOGGLE
LED toggles between on/off state (this has no effect while processing alternating patterns)
Definition: twr_led.h:28
@ TWR_LED_MODE_BLINK
LED blinks.
Definition: twr_led.h:37
@ TWR_LED_MODE_BLINK_FAST
LED blinks quickly.
Definition: twr_led.h:43
@ TWR_LED_MODE_FLASH
LED flashes repeatedly.
Definition: twr_led.h:46
@ TWR_LED_MODE_BLINK_SLOW
LED blinks slowly.
Definition: twr_led.h:40
@ TWR_LED_MODE_ON
LED has steady on state.
Definition: twr_led.h:34
@ TWR_LED_MODE_OFF
LED has steady off state.
Definition: twr_led.h:31
void twr_scheduler_plan_current_relative(twr_tick_t tick)
Schedule current task to tick relative from current spin.
void twr_scheduler_plan_from_now(twr_scheduler_task_id_t task_id, twr_tick_t tick)
Schedule specified task to tick relative from now.
void twr_scheduler_plan_now(twr_scheduler_task_id_t task_id)
Schedule specified task for immediate execution.
twr_scheduler_task_id_t twr_scheduler_register(void(*task)(void *), void *param, twr_tick_t tick)
Register task in scheduler.
Definition: twr_scheduler.c:53
#define TWR_TICK_INFINITY
Maximum timestamp value.
Definition: twr_tick.h:12
uint64_t twr_tick_t
Timestamp data type.
Definition: twr_tick.h:16
LED driver interface.
Definition: twr_led.h:57
void(* init)(twr_led_t *self)
Callback for initialization.
Definition: twr_led.h:59
bool(* init)(void)
Callback for initialization.
Definition: twr_lp8.h:56