GPS Device
Loading...
Searching...
No Matches
Button Public APIs

Functions

ERR_te button_init_subsys (void)
 Initializes the button subsystem.
ERR_te button_deinit_subsys (void)
 Deinitializes the button subsystem.
ERR_te button_start_subsys (void)
 Starts the button subsystem.
ERR_te button_stop_subsys (void)
 Stops the button subsystem.
ERR_te button_init_handle (BUTTON_CFG_ts *button_cfg, BUTTON_HANDLE_ts **button_handle_o)
 Initializes and registers a button handle.
ERR_te button_deinit_handle (BUTTON_HANDLE_ts const *button_handle)
 Deinitializes a button handle.
ERR_te button_run_handle (BUTTON_HANDLE_ts *button_handle)
 Runs the state machine for a single button handle.
ERR_te button_run_handle_all (void)
 Runs the state machine for all registered button handles.
ERR_te button_get_pushed_state (BUTTON_HANDLE_ts const *button_handle, bool *pushed_state_o)
 Retrieves the pushed state of a button.
ERR_te button_get_held_state (BUTTON_HANDLE_ts const *button_handle, bool *held_state_o)
 Retrieves the held state of a button.

Detailed Description

Function Documentation

◆ button_init_subsys()

ERR_te button_init_subsys ( void )

Initializes the button subsystem.

See also
button_init_subsys

Definition at line 159 of file button.c.

159 {
160 ERR_te err;
161
162 if(internal_state.initialized) {
164 }
165
166 internal_state = (struct internal_state_s){ 0 };
167
168 internal_state.log_level = LOG_LEVEL_INFO;
170 internal_state.initialized = true;
171 internal_state.started = false;
172
173 init_log();
174 init_systick();
175
177 if(err != ERR_OK) {
178 LOG_ERROR(
179 internal_state.subsys,
180 internal_state.log_level,
181 "button_init_subsys: cmd_register error"
182 );
183
184 return err;
185 }
186 LOG_INFO(
187 internal_state.subsys,
188 internal_state.log_level,
189 "button_init_subsys: subsys initialized"
190 );
191
192 return ERR_OK;
193}
static struct internal_state_s internal_state
Singleton instance of the SysTick driver internal state.
static CMD_CLIENT_INFO_ts button_cmd_client_info
Registration descriptor passed to the command subsystem.
Definition button.c:146
ERR_te cmd_register(CMD_CLIENT_INFO_ts *cmd_client_info)
Registers a client with the command subsystem.
Definition cmd.c:51
ERR_te
Standard return type used by all public API functions.
Definition err.h:35
@ ERR_OK
Definition err.h:36
@ ERR_INITIALIZATION_FAILURE
Definition err.h:43
ERR_te init_log(void)
Initializes the logging subsystem.
Definition init.c:25
ERR_te init_systick(void)
Initializes the SysTick timer.
Definition init.c:40
#define LOG_ERROR(subsys, lvl, fmt,...)
Definition log.h:258
#define LOG_INFO(subsys, lvl, fmt,...)
Definition log.h:255
@ LOG_LEVEL_INFO
Definition log.h:64
@ MODULES_BUTTON
Definition modules.h:47
Internal state of the SysTick driver.
Here is the call graph for this function:
Here is the caller graph for this function:

◆ button_deinit_subsys()

ERR_te button_deinit_subsys ( void )

Deinitializes the button subsystem.

See also
button_deinit_subsys

Definition at line 196 of file button.c.

196 {
197 if(internal_state.initialized && !internal_state.started) {
198 internal_state = (struct internal_state_s){ 0 };
199
201 }
202 else {
203 LOG_ERROR(
204 internal_state.subsys,
205 internal_state.log_level,
206 "button_deinit_subsys: subsys is not initialized or not stopped"
207 );
208
210 }
211 LOG_INFO(
212 internal_state.subsys,
213 internal_state.log_level,
214 "button_deinit_subsys: subsys deinitialized"
215 );
216
217 return ERR_OK;
218}
ERR_te cmd_deregister(CMD_CLIENT_INFO_ts const *cmd_client_info)
Deregisters a client from the command subsystem.
Definition cmd.c:66
@ ERR_DEINITIALIZATION_FAILURE
Definition err.h:44
Here is the call graph for this function:

◆ button_start_subsys()

ERR_te button_start_subsys ( void )

Starts the button subsystem.

See also
button_start_subsys

Definition at line 221 of file button.c.

221 {
222 if(internal_state.initialized && !internal_state.started) {
223 internal_state.started = true;
224
225 LOG_INFO(
226 internal_state.subsys,
227 internal_state.log_level,
228 "button_start_subsys: subsys started"
229 );
230 }
231 else {
232 LOG_ERROR(
233 internal_state.subsys,
234 internal_state.log_level,
235 "button_start_subsys: subsys not initialized or already started"
236 );
237
238 return ERR_UNKNOWN;
239 }
240
241 return ERR_OK;
242}
@ ERR_UNKNOWN
Definition err.h:37
Here is the caller graph for this function:

◆ button_stop_subsys()

ERR_te button_stop_subsys ( void )

Stops the button subsystem.

See also
button_stop_subsys

Definition at line 245 of file button.c.

245 {
246 if(internal_state.initialized && internal_state.started) {
247 internal_state.started = false;
248
249 LOG_INFO(
250 internal_state.subsys,
251 internal_state.log_level,
252 "button_stop_subsys: subsys stopped"
253 );
254 }
255 else {
256 LOG_ERROR(
257 internal_state.subsys,
258 internal_state.log_level,
259 "button_stop_subsys: subsys not initialized or already already stopped"
260 );
261
262 return ERR_UNKNOWN;
263 }
264
265 return ERR_OK;
266}

◆ button_init_handle()

ERR_te button_init_handle ( BUTTON_CFG_ts * button_cfg,
BUTTON_HANDLE_ts ** button_handle_o )

Initializes and registers a button handle.

See also
button_init_handle

Definition at line 269 of file button.c.

269 {
270 if(!internal_state.initialized) {
271 LOG_INFO(
272 internal_state.subsys,
273 internal_state.log_level,
274 "button_init_handle: subsys not initialized"
275 );
276
278 }
279
280 if(internal_state.button_num == CONFIG_BUTTON_MAX_OBJECTS) {
281 LOG_ERROR(
282 internal_state.subsys,
283 internal_state.log_level,
284 "button_init_handle: subsystem out of memory space"
285 );
286
288 }
289
290 if(!button_cfg) {
291 LOG_ERROR(
292 internal_state.subsys,
293 internal_state.log_level,
294 "button_init_handle: invalid argument"
295 );
297 }
298
299 GPIO_CFG_ts gpio = { 0 };
300 gpio.port = button_cfg->gpio_port;
301 gpio.pin = button_cfg->gpio_pin;
303 gpio.mode = GPIO_MODE_INPUT;
304
305 gpio_init(&gpio);
306
307 for(uint32_t i = 0; i < CONFIG_BUTTON_MAX_OBJECTS; i++) {
308 if(internal_state.buttons[i].in_use == false) {
309 str_cpy(
310 internal_state.buttons[i].name,
311 button_cfg->name,
312 get_str_len(button_cfg->name) + 1
313 );
314
315 internal_state.buttons[i].debounce_limit_ms = button_cfg->debounce_limit_ms;
316 internal_state.buttons[i].gpio_port = button_cfg->gpio_port;
317 internal_state.buttons[i].gpio_pin = button_cfg->gpio_pin;
318 internal_state.buttons[i].pushed_type = button_cfg->pushed_type;
319 internal_state.buttons[i].held_limit_ms = button_cfg->held_limit_ms;
320 internal_state.buttons[i].held = false;
321 internal_state.buttons[i].held_started_ms = 0;
322 internal_state.buttons[i].debounce_started = false;
323 internal_state.buttons[i].held_started = false;
324 internal_state.buttons[i].pushed = false;
325 internal_state.buttons[i].debounce_started_ms = 0;
326 internal_state.buttons[i].in_use = true;
327
328 *button_handle_o = &internal_state.buttons[i];
329
330 internal_state.button_num++;
331
332 LOG_INFO(
333 internal_state.subsys,
334 internal_state.log_level,
335 "button_init_handle: button handle %s initialized",
336 internal_state.buttons[i].name
337 );
338
339 break;
340 }
341 }
342
343 return ERR_OK;
344}
int str_cpy(char *str_to, const char *str_from, uint32_t len)
Copies a null-terminated string into a destination buffer.
Definition common.c:333
uint32_t get_str_len(char const *str)
Returns the length of a string, excluding the null terminator.
Definition common.c:22
@ ERR_UNINITIALZIED_OBJECT
Definition err.h:42
@ ERR_NOT_ENOUGH_SPACE
Definition err.h:49
@ ERR_INVALID_ARGUMENT
Definition err.h:38
void gpio_init(GPIO_CFG_ts *gpio_cfg)
Initializes a GPIO pin according to the given configuration.
@ GPIO_OUTPUT_TYPE_PUSHPULL
@ GPIO_MODE_INPUT
uint32_t debounce_limit_ms
Definition button.h:94
uint32_t held_limit_ms
Definition button.h:97
char name[CONFIG_BUTTON_MAX_NAME_LEN]
Definition button.h:78
GPIO_PIN_te gpio_pin
Definition button.h:84
GPIO_REGDEF_ts * gpio_port
Definition button.h:81
BUTTON_PUSHED_TYPE_te pushed_type
Definition button.h:91
Configuration structure for initializing a GPIO pin.
GPIO_REGDEF_ts * port
GPIO_OUTPUT_TYPE_te output_type
GPIO_PIN_te pin
GPIO_MODE_te mode
Here is the call graph for this function:
Here is the caller graph for this function:

◆ button_deinit_handle()

ERR_te button_deinit_handle ( BUTTON_HANDLE_ts const * button_handle)

Deinitializes a button handle.

See also
button_deinit_handle

Definition at line 347 of file button.c.

347 {
348 if(internal_state.started) {
349 LOG_INFO(
350 internal_state.subsys,
351 internal_state.log_level,
352 "button_deinit_handle: subsys not stopped"
353 );
354 return ERR_ILLEGAL_ACTION;
355 }
356
357 if(internal_state.button_num == 0) {
358 LOG_ERROR(
359 internal_state.subsys,
360 internal_state.log_level,
361 "button_deinit_handle: no such handle to deinitialize"
362 );
363
365 }
366
367 for(uint32_t i = 0; i < CONFIG_BUTTON_MAX_OBJECTS; i++) {
368 if(&internal_state.buttons[i] == button_handle) {
369 uint8_t name_len = get_str_len(internal_state.buttons[i].name) + 1;
370 char name[name_len];
371 str_cpy(name, internal_state.buttons[i].name, name_len);
372
373 internal_state.buttons[i] = (BUTTON_HANDLE_ts){ 0 };
374
375 internal_state.button_num--;
376
377 LOG_INFO(
378 internal_state.subsys,
379 internal_state.log_level,
380 "button_deinit_handle: io handle %s deinitialized",
381 name
382 );
383
384 break;
385 }
386
387 if(i == CONFIG_BUTTON_MAX_OBJECTS - 1) {
388 LOG_ERROR(
389 internal_state.subsys,
390 internal_state.log_level,
391 "button_deinit_handle: no such handle to deinitialize"
392 );
393
395 }
396 }
397
398 return ERR_OK;
399}
struct button_handle_s BUTTON_HANDLE_ts
Opaque handle representing a button instance.
Definition button.h:110
@ ERR_ILLEGAL_ACTION
Definition err.h:50
Here is the call graph for this function:

◆ button_run_handle()

ERR_te button_run_handle ( BUTTON_HANDLE_ts * button_handle)

Runs the state machine for a single button handle.

Executes the state machine for a single button.

See also
button_run_handle

Definition at line 402 of file button.c.

402 {
403 if(!internal_state.initialized || !internal_state.started) {
404 LOG_ERROR(
405 internal_state.subsys,
406 internal_state.log_level,
407 "button_run_handle: subsystem not initialized or started"
408 );
409
410 return ERR_UNKNOWN;
411 }
412
413 PIN_STATUS_te pin_status = gpio_read(button_handle->gpio_port, button_handle->gpio_pin);
414
415 // If the debounce has not yet been completed, complete it (if it's enabled)
416 if(button_handle->pushed == false) {
417 if((button_handle->pushed_type == BUTTON_PUSHED_TYPE_HIGH &&
418 pin_status == HIGH) ||
419 (button_handle->pushed_type == BUTTON_PUSHED_TYPE_LOW &&
420 pin_status == LOW)) {
421 uint32_t current_ms = systick_get_ms();
422
423 if(!button_handle->debounce_started) {
424 button_handle->debounce_started = true;
425 button_handle->debounce_started_ms = current_ms;
426 }
427
428 if(button_handle->debounce_started &&
429 current_ms - button_handle->debounce_started_ms >= button_handle->debounce_limit_ms) {
430 button_handle->pushed = true;
431 button_handle->debounce_started = false;
432 }
433 }
434 else {
435 if(button_handle->debounce_started) {
436 button_handle->debounce_started = false;
437 button_handle->debounce_started_ms = 0;
438 }
439 }
440 }
441
442 // If the held property is enabled, check if button is held for long enough
443 if(button_handle->pushed == true && button_handle->held == false) {
444 if((button_handle->pushed_type == BUTTON_PUSHED_TYPE_HIGH &&
445 pin_status == HIGH) ||
446 (button_handle->pushed_type == BUTTON_PUSHED_TYPE_LOW &&
447 pin_status == LOW)) {
448 uint32_t current_ms = systick_get_ms();
449
450 if(!button_handle->held_started) {
451 button_handle->held_started = true;
452 button_handle->held_started_ms = current_ms;
453 }
454
455 if(button_handle->held_started &&
456 current_ms - button_handle->held_started_ms >= button_handle->held_limit_ms) {
457 button_handle->held = true;
458 button_handle->held_started = false;
459 }
460 }
461 else {
462 if(button_handle->held_started) {
463 button_handle->held_started = false;
464 button_handle->held_started_ms = 0;
465 }
466 }
467 }
468
469 // If the button has been pushed, check for button release then restore states and counters
470 if(button_handle->pushed == true) {
471 if((button_handle->pushed_type == BUTTON_PUSHED_TYPE_HIGH &&
472 pin_status == LOW) ||
473 (button_handle->pushed_type == BUTTON_PUSHED_TYPE_LOW &&
474 pin_status == HIGH)) {
475 uint32_t current_ms = systick_get_ms();
476
477 if(!button_handle->debounce_started) {
478 button_handle->debounce_started = true;
479 button_handle->debounce_started_ms = current_ms;
480 }
481
482 if(button_handle->debounce_started &&
483 current_ms - button_handle->debounce_started_ms >= button_handle->debounce_limit_ms) {
484 button_handle->pushed = false;
485 button_handle->held = false;
486 button_handle->debounce_started = false;
487 button_handle->held_started = false;
488 }
489 }
490 else {
491 if(button_handle->debounce_started) {
492 button_handle->debounce_started = false;
493 button_handle->debounce_started_ms = 0;
494 }
495 }
496 }
497
498 return ERR_OK;
499}
@ BUTTON_PUSHED_TYPE_HIGH
Definition button.h:64
@ BUTTON_PUSHED_TYPE_LOW
Definition button.h:61
PIN_STATUS_te
Represents the logical level of a GPIO pin.
Definition common.h:84
@ HIGH
Definition common.h:89
@ LOW
Definition common.h:86
uint32_t systick_get_ms(void)
Returns the number of milliseconds elapsed since SysTick was initialized.
PIN_STATUS_te gpio_read(GPIO_REGDEF_ts const *gpio_port, uint8_t gpio_pin)
Reads the current logic level of a GPIO input pin.
bool held_started
Definition button.c:63
BUTTON_PUSHED_TYPE_te pushed_type
Definition button.c:45
uint32_t debounce_started_ms
Definition button.c:54
GPIO_REGDEF_ts * gpio_port
Definition button.c:39
uint32_t held_started_ms
Definition button.c:57
bool debounce_started
Definition button.c:60
GPIO_PIN_te gpio_pin
Definition button.c:42
uint32_t debounce_limit_ms
Definition button.c:48
uint32_t held_limit_ms
Definition button.c:51
Here is the call graph for this function:
Here is the caller graph for this function:

◆ button_run_handle_all()

ERR_te button_run_handle_all ( void )

Runs the state machine for all registered button handles.

Runs the state machine for all registered buttons.

See also
button_run_handle_all

Definition at line 502 of file button.c.

502 {
503 for(uint32_t i = 0; i < CONFIG_BUTTON_MAX_OBJECTS; i++) {
504 if(internal_state.buttons[i].in_use == true) {
505 ERR_te err = button_run_handle(&internal_state.buttons[i]);
506 if(err != ERR_OK) {
507 return err;
508 }
509 }
510 }
511
512 return ERR_OK;
513}
ERR_te button_run_handle(BUTTON_HANDLE_ts *button_handle)
Runs the state machine for a single button handle.
Definition button.c:402
Here is the call graph for this function:
Here is the caller graph for this function:

◆ button_get_pushed_state()

ERR_te button_get_pushed_state ( BUTTON_HANDLE_ts const * button_handle,
bool * pushed_state_o )

Retrieves the pushed state of a button.

Retrieves the pushed (pressed) state of a button.

See also
button_get_pushed_state

Definition at line 516 of file button.c.

516 {
517 if(!internal_state.initialized || !internal_state.started) {
518 LOG_ERROR(
519 internal_state.subsys,
520 internal_state.log_level,
521 "button_get_pushed_state: handle not initialized or subsystem not started"
522 );
523
524 return ERR_ILLEGAL_ACTION;
525 }
526
527 *pushed_state_o = button_handle->pushed;
528
529 return ERR_OK;
530}
Here is the caller graph for this function:

◆ button_get_held_state()

ERR_te button_get_held_state ( BUTTON_HANDLE_ts const * button_handle,
bool * held_state_o )

Retrieves the held state of a button.

See also
button_get_held_state

Definition at line 533 of file button.c.

533 {
534 if(!internal_state.initialized || !internal_state.started) {
535 LOG_ERROR(
536 internal_state.subsys,
537 internal_state.log_level,
538 "button_get_held_state: handle not initialized or subsystem not started"
539 );
540
541 return ERR_ILLEGAL_ACTION;
542 }
543
544 *held_state_o = button_handle->held;
545
546 return ERR_OK;
547}
Here is the caller graph for this function: