ruuvi.drivers.c  ${PROJECT_VERSION}
Drivers for external sensors and peripherals on embedded systems.
ruuvi_task_led.c
Go to the documentation of this file.
1 
12 #if RT_LED_ENABLED
13 #include "ruuvi_task_led.h"
14 #include "ruuvi_driver_error.h"
15 #include "ruuvi_interface_gpio.h"
16 #include "ruuvi_interface_timer.h"
17 #include <stddef.h>
18 
19 static uint16_t m_activity_led;
20 static uint16_t m_blink_led;
21 static bool m_initialized;
22 static ri_gpio_id_t m_led_list[RT_MAX_LED_CFG];
23 static ri_gpio_state_t m_led_active_state[RT_MAX_LED_CFG];
24 //Store user configured led number in case there's extra space in array.
25 static size_t m_num_leds;
26 // Timer instance for LED timer
27 #ifndef CEEDLING
28 static
29 #endif
30 ri_timer_id_t m_timer;
31 
32 #ifndef CEEDLING
33 static
34 #endif
35 int8_t is_led (const ri_gpio_id_t led)
36 {
37  int8_t led_valid = -1;
38 
39  for (size_t ii = 0U;
40  (ii < m_num_leds) && (0 > led_valid);
41  ii++)
42  {
43  if (led == m_led_list[ii])
44  {
45  led_valid = ii;
46  }
47  }
48 
49  return led_valid;
50 }
51 
52 static inline ri_gpio_state_t led_to_pin_state (ri_gpio_id_t led, bool active)
53 {
55  int8_t index = is_led (led);
56 
57  if (index > -1)
58  {
59  if (RI_GPIO_HIGH == m_led_active_state[index])
60  {
61  state = active ? RI_GPIO_HIGH : RI_GPIO_LOW;
62  }
63  else
64  {
65  state = active ? RI_GPIO_LOW : RI_GPIO_HIGH;
66  }
67  }
68 
69  return state;
70 }
71 
72 rd_status_t rt_led_init (const ri_gpio_id_t * const leds,
73  const ri_gpio_state_t * const active_states,
74  const size_t num_leds)
75 {
76  rd_status_t err_code = RD_SUCCESS;
77 
78  if (m_initialized)
79  {
80  err_code |= RD_ERROR_INVALID_STATE;
81  }
82  else
83  {
84  if (!ri_gpio_is_init())
85  {
86  err_code |= ri_gpio_init();
87  }
88  }
89 
90  if (RD_SUCCESS == err_code)
91  {
92  for (size_t ii = 0u; ii < num_leds; ii++)
93  {
94  m_led_list[ii] = leds[ii];
95  m_led_active_state[ii] = active_states[ii];
96  err_code |= ri_gpio_configure (m_led_list[ii],
98  err_code |= ri_gpio_write (m_led_list[ii], !m_led_active_state[ii]);
99  }
100 
101  m_activity_led = RI_GPIO_ID_UNUSED;
102  m_blink_led = RI_GPIO_ID_UNUSED;
103  m_num_leds = num_leds;
104  m_initialized = true;
105  }
106 
107  return err_code;
108 }
109 
111 {
112  rd_status_t err_code = RD_SUCCESS;
113 
114  for (size_t ii = 0U; ii < m_num_leds; ii++)
115  {
116  err_code |= ri_gpio_configure (m_led_list[ii], RI_GPIO_MODE_HIGH_Z);
117  }
118 
119  m_activity_led = RI_GPIO_ID_UNUSED;
120  m_blink_led = RI_GPIO_ID_UNUSED;
121  m_initialized = false;
122  m_num_leds = 0;
123  return err_code;
124 }
125 
126 rd_status_t rt_led_write (const ri_gpio_id_t led, const bool active)
127 {
128  rd_status_t err_code = RD_SUCCESS;
129 
130  if (!m_initialized)
131  {
132  err_code |= RD_ERROR_INVALID_STATE;
133  }
134  else if (0 > is_led (led))
135  {
136  err_code |= RD_ERROR_INVALID_PARAM;
137  }
138  else
139  {
140  const ri_gpio_state_t state = led_to_pin_state (led, active);
141  err_code |= ri_gpio_write (led, state);
142  }
143 
144  return err_code;
145 }
146 
147 void rt_led_activity_indicate (const bool active)
148 {
149  // Error code cannot be returned, ignore
150  (void) rt_led_write (m_activity_led, active);
151 }
152 
154 {
155  rd_status_t err_code = RD_SUCCESS;
156 
157  if (RI_GPIO_ID_UNUSED == led)
158  {
159  m_activity_led = RI_GPIO_ID_UNUSED;
160  }
161  else if (0 > is_led (led))
162  {
163  err_code |= RD_ERROR_INVALID_PARAM;
164  }
165  else
166  {
167  m_activity_led = led;
168  }
169 
170  return err_code;
171 }
172 
173 uint16_t rt_led_activity_led_get (void)
174 {
175  return m_activity_led;
176 }
177 
178 #ifndef CEEDLING
179 static
180 #endif
181 void rt_led_blink_isr (void * const p_context)
182 {
183  static bool active = true;
184  rt_led_write (m_blink_led, active);
185  active = !active;
186 }
187 
188 #ifndef CEEDLING
189 static
190 #endif
191 void rt_led_blink_once_isr (void * const p_context)
192 {
193  rt_led_blink_stop (m_blink_led);
194 }
195 
196 rd_status_t rt_led_blink_start (const ri_gpio_id_t led, const uint16_t interval_ms)
197 {
198  rd_status_t err_code = RD_SUCCESS;
199 
200  if (!ri_timer_is_init())
201  {
202  err_code |= ri_timer_init();
203  }
204 
205  if (!m_timer)
206  {
207  err_code |= ri_timer_create (&m_timer, RI_TIMER_MODE_REPEATED, &rt_led_blink_isr);
208  }
209 
210  if (RI_GPIO_ID_UNUSED != m_blink_led)
211  {
212  err_code |= RD_ERROR_INVALID_STATE;
213  }
214 
215  if (0 > is_led (led))
216  {
217  err_code |= RD_ERROR_INVALID_PARAM;
218  }
219 
220  if (RD_SUCCESS == err_code)
221  {
222  err_code |= ri_timer_start (m_timer, interval_ms, NULL);
223  }
224 
225  if (RD_SUCCESS == err_code)
226  {
227  m_blink_led = led;
228  }
229 
230  return err_code;
231 }
232 
233 rd_status_t rt_led_blink_once (const ri_gpio_id_t led, const uint16_t interval_ms)
234 {
235  rd_status_t err_code = RD_SUCCESS;
236 
237  if (!ri_timer_is_init())
238  {
239  err_code |= ri_timer_init();
240  }
241 
242  if (!m_timer)
243  {
244  err_code |= ri_timer_create (&m_timer, RI_TIMER_MODE_SINGLE_SHOT, &rt_led_blink_once_isr);
245  }
246 
247  if (RI_GPIO_ID_UNUSED != m_blink_led)
248  {
249  err_code |= RD_ERROR_INVALID_STATE;
250  }
251 
252  if (0 > is_led (led))
253  {
254  err_code |= RD_ERROR_INVALID_PARAM;
255  }
256 
257  if (RD_SUCCESS == err_code)
258  {
259  err_code |= ri_timer_start (m_timer, interval_ms, NULL);
260  }
261 
262  if (RD_SUCCESS == err_code)
263  {
264  m_blink_led = led;
265  err_code |= rt_led_write (m_blink_led, true);
266  }
267 
268  return err_code;
269 }
270 
272 {
273  rd_status_t err_code = RD_SUCCESS;
274 
275  if (led != m_blink_led)
276  {
277  err_code |= RD_ERROR_INVALID_STATE;
278  }
279  else
280  {
281  ri_timer_stop (m_timer);
282  m_blink_led = RI_GPIO_ID_UNUSED;
283  rt_led_write (led, false);
284  }
285 
286  return err_code;
287 }
288 
289 bool rt_led_is_init (void)
290 {
291  return m_initialized;
292 }
293 
294 #endif
#define RD_ERROR_INVALID_PARAM
Invalid Parameter.
uint32_t rd_status_t
bitfield for representing errors
#define RD_SUCCESS
Internal Error.
#define RD_ERROR_INVALID_STATE
Invalid state, operation disallowed in this state.
bool ri_gpio_is_init(void)
return true if GPIO is init, false otherwise.
rd_status_t ri_gpio_configure(const ri_gpio_id_t pin, const ri_gpio_mode_t mode)
Configure a pin of a port into a mode. If there are several ports the platform driver must implement ...
rd_status_t ri_gpio_init(void)
Initializes GPIO module. Call this before other GPIO functions. After initialization all GPIO pins sh...
rd_status_t ri_gpio_write(const ri_gpio_id_t pin, const ri_gpio_state_t state)
Write a pin of a port into given state If there are several ports the platform driver must implement ...
bool ri_timer_is_init(void)
Check if timer is initialized.
rd_status_t ri_timer_start(ri_timer_id_t timer_id, uint32_t ms, void *const context)
Start given timer at a mode defined in ri_timer_create.
rd_status_t ri_timer_create(ri_timer_id_t *p_timer_id, ri_timer_mode_t mode, ruuvi_timer_timeout_handler_t timeout_handler)
rd_status_t ri_timer_init(void)
rd_status_t ri_timer_stop(ri_timer_id_t timer_id)
void * ri_timer_id_t
Pointer to timer data.
@ RI_TIMER_MODE_REPEATED
@ RI_TIMER_MODE_SINGLE_SHOT
Header to enable and disable module compilation.
#define RT_MAX_LED_CFG
Conserve RAM for led task variables.
Ruuvi error codes and error check function.
uint16_t ri_gpio_id_t
port<<8 + pin
#define RI_GPIO_ID_UNUSED
Enable implementation selected by application.
@ RI_GPIO_MODE_OUTPUT_HIGHDRIVE
Push-pull output, can be written. Higher current drive than standard.
@ RI_GPIO_MODE_HIGH_Z
High-impedance mode, electrically disconnected.
ri_gpio_state_t
States of GPIO pins.
@ RI_GPIO_LOW
GPIO electrically low.
@ RI_GPIO_HIGH
GPIO electrically high.
Interface functions to timer.
rd_status_t rt_led_init(const ri_gpio_id_t *const leds, const ri_gpio_state_t *const active_states, const size_t num_leds)
LED initialization function.
rd_status_t rt_led_blink_once(const ri_gpio_id_t led, const uint16_t interval_ms)
Function to blink led once.
rd_status_t rt_led_activity_led_set(const ri_gpio_id_t led)
Set LED which is used to indicate activity.
uint16_t rt_led_activity_led_get(void)
Get LED which is used to indicate activity.
bool rt_led_is_init(void)
Check if LED task has been initialized.
rd_status_t rt_led_blink_start(const ri_gpio_id_t led, const uint16_t interval_ms)
Start blinking led at 50 % duty cycle at given interval.
rd_status_t rt_led_blink_stop(const ri_gpio_id_t led)
Stop blinking led and leave the pin as high-drive output in inactive state.
rd_status_t rt_led_write(const ri_gpio_id_t led, const bool state)
LED write function. Set given LED ON or OFF.
void rt_led_activity_indicate(const bool state)
Function to indicate activity in program. Led is turned on while program is active and off while in s...
rd_status_t rt_led_uninit(void)
LED uninitialization function.