1 /*
2  * Copyright (c) 2019 Vestas Wind Systems A/S
3  *
4  * SPDX-License-Identifier: Apache-2.0
5  */
6 
7 #include <CANopen.h>
8 #include <canopennode.h>
9 
10 struct canopen_leds_state {
11 	CO_NMT_t *nmt;
12 	canopen_led_callback_t green_cb;
13 	void *green_arg;
14 	canopen_led_callback_t red_cb;
15 	void *red_arg;
16 	bool green : 1;
17 	bool red : 1;
18 	bool program_download : 1;
19 };
20 
21 static struct canopen_leds_state canopen_leds;
22 
canopen_leds_update(struct k_timer * timer_id)23 static void canopen_leds_update(struct k_timer *timer_id)
24 {
25 	bool green = false;
26 	bool red = false;
27 
28 	ARG_UNUSED(timer_id);
29 
30 	CO_NMT_blinkingProcess50ms(canopen_leds.nmt);
31 
32 	if (canopen_leds.program_download) {
33 		green = LED_TRIPLE_FLASH(canopen_leds.nmt);
34 	} else {
35 		green = LED_GREEN_RUN(canopen_leds.nmt);
36 	}
37 
38 	red = LED_RED_ERROR(canopen_leds.nmt);
39 
40 #ifdef CONFIG_CANOPENNODE_LEDS_BICOLOR
41 	if (red && canopen_leds.red_cb) {
42 		green = false;
43 	}
44 #endif
45 
46 	if (canopen_leds.green_cb) {
47 		if (green != canopen_leds.green) {
48 			canopen_leds.green_cb(green, canopen_leds.green_arg);
49 			canopen_leds.green = green;
50 		}
51 	}
52 
53 	if (canopen_leds.red_cb) {
54 		if (red != canopen_leds.red) {
55 			canopen_leds.red_cb(red, canopen_leds.red_arg);
56 			canopen_leds.red = red;
57 		}
58 	}
59 }
60 
61 K_TIMER_DEFINE(canopen_leds_timer, canopen_leds_update, NULL);
62 
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)63 void canopen_leds_init(CO_NMT_t *nmt,
64 		       canopen_led_callback_t green_cb, void *green_arg,
65 		       canopen_led_callback_t red_cb, void *red_arg)
66 {
67 	k_timer_stop(&canopen_leds_timer);
68 
69 	canopen_leds.nmt = nmt;
70 
71 	/* Call existing callbacks to turn off LEDs */
72 	if (canopen_leds.green_cb) {
73 		canopen_leds.green_cb(false, canopen_leds.green_arg);
74 	}
75 	if (canopen_leds.red_cb) {
76 		canopen_leds.red_cb(false, canopen_leds.red_arg);
77 	}
78 
79 	canopen_leds.green_cb = green_cb;
80 	canopen_leds.green_arg = green_arg;
81 	canopen_leds.green = false;
82 	canopen_leds.red_cb = red_cb;
83 	canopen_leds.red_arg = red_arg;
84 	canopen_leds.red = false;
85 
86 	/* Call new callbacks to turn off LEDs */
87 	if (canopen_leds.green_cb) {
88 		canopen_leds.green_cb(false, canopen_leds.green_arg);
89 	}
90 	if (canopen_leds.red_cb) {
91 		canopen_leds.red_cb(false, canopen_leds.red_arg);
92 	}
93 
94 	if (nmt && (green_cb || red_cb)) {
95 		k_timer_start(&canopen_leds_timer, K_MSEC(50), K_MSEC(50));
96 	}
97 }
98 
canopen_leds_program_download(bool in_progress)99 void canopen_leds_program_download(bool in_progress)
100 {
101 	canopen_leds.program_download = in_progress;
102 }
103