|  | /* | 
|  | * Copyright (c) 2019 Vestas Wind Systems A/S | 
|  | * | 
|  | * SPDX-License-Identifier: Apache-2.0 | 
|  | */ | 
|  |  | 
|  | #include <CANopen.h> | 
|  | #include <canopennode.h> | 
|  |  | 
|  | struct canopen_leds_state { | 
|  | CO_NMT_t *nmt; | 
|  | canopen_led_callback_t green_cb; | 
|  | void *green_arg; | 
|  | canopen_led_callback_t red_cb; | 
|  | void *red_arg; | 
|  | bool green : 1; | 
|  | bool red : 1; | 
|  | bool program_download : 1; | 
|  | }; | 
|  |  | 
|  | static struct canopen_leds_state canopen_leds; | 
|  |  | 
|  | static void canopen_leds_update(struct k_timer *timer_id) | 
|  | { | 
|  | bool green = false; | 
|  | bool red = false; | 
|  |  | 
|  | ARG_UNUSED(timer_id); | 
|  |  | 
|  | CO_NMT_blinkingProcess50ms(canopen_leds.nmt); | 
|  |  | 
|  | if (canopen_leds.program_download) { | 
|  | green = LED_TRIPLE_FLASH(canopen_leds.nmt); | 
|  | } else { | 
|  | green = LED_GREEN_RUN(canopen_leds.nmt); | 
|  | } | 
|  |  | 
|  | red = LED_RED_ERROR(canopen_leds.nmt); | 
|  |  | 
|  | #ifdef CONFIG_CANOPENNODE_LEDS_BICOLOR | 
|  | if (red && canopen_leds.red_cb) { | 
|  | green = false; | 
|  | } | 
|  | #endif | 
|  |  | 
|  | if (canopen_leds.green_cb) { | 
|  | if (green != canopen_leds.green) { | 
|  | canopen_leds.green_cb(green, canopen_leds.green_arg); | 
|  | canopen_leds.green = green; | 
|  | } | 
|  | } | 
|  |  | 
|  | if (canopen_leds.red_cb) { | 
|  | if (red != canopen_leds.red) { | 
|  | canopen_leds.red_cb(red, canopen_leds.red_arg); | 
|  | canopen_leds.red = red; | 
|  | } | 
|  | } | 
|  | } | 
|  |  | 
|  | K_TIMER_DEFINE(canopen_leds_timer, canopen_leds_update, NULL); | 
|  |  | 
|  | void canopen_leds_init(CO_NMT_t *nmt, | 
|  | canopen_led_callback_t green_cb, void *green_arg, | 
|  | canopen_led_callback_t red_cb, void *red_arg) | 
|  | { | 
|  | k_timer_stop(&canopen_leds_timer); | 
|  |  | 
|  | canopen_leds.nmt = nmt; | 
|  |  | 
|  | /* Call existing callbacks to turn off LEDs */ | 
|  | if (canopen_leds.green_cb) { | 
|  | canopen_leds.green_cb(false, canopen_leds.green_arg); | 
|  | } | 
|  | if (canopen_leds.red_cb) { | 
|  | canopen_leds.red_cb(false, canopen_leds.red_arg); | 
|  | } | 
|  |  | 
|  | canopen_leds.green_cb = green_cb; | 
|  | canopen_leds.green_arg = green_arg; | 
|  | canopen_leds.green = false; | 
|  | canopen_leds.red_cb = red_cb; | 
|  | canopen_leds.red_arg = red_arg; | 
|  | canopen_leds.red = false; | 
|  |  | 
|  | /* Call new callbacks to turn off LEDs */ | 
|  | if (canopen_leds.green_cb) { | 
|  | canopen_leds.green_cb(false, canopen_leds.green_arg); | 
|  | } | 
|  | if (canopen_leds.red_cb) { | 
|  | canopen_leds.red_cb(false, canopen_leds.red_arg); | 
|  | } | 
|  |  | 
|  | if (nmt && (green_cb || red_cb)) { | 
|  | k_timer_start(&canopen_leds_timer, K_MSEC(50), K_MSEC(50)); | 
|  | } | 
|  | } | 
|  |  | 
|  | void canopen_leds_program_download(bool in_progress) | 
|  | { | 
|  | canopen_leds.program_download = in_progress; | 
|  | } |