9 constexpr uint8_t LEDSEQ_RADIO_FAILED
[] = { 20, 100 }; // 200ms on, 1000ms off
10 constexpr uint8_t LEDSEQ_DISCONNECTED
[] = { 50, 50 }; // 500ms on, 500ms off
11 constexpr uint8_t LEDSEQ_WIFI_UPDATE
[] = { 2, 3 }; // 20ms on, 30ms off
12 constexpr uint8_t LEDSEQ_BINDING
[] = { 10, 10, 10, 100 }; // 2x 100ms blink, 1s pause
13 constexpr uint8_t LEDSEQ_MODEL_MISMATCH
[] = { 10, 10, 10, 10, 10, 100 }; // 3x 100ms blink, 1s pause
14 constexpr uint8_t LEDSEQ_UPDATE
[] = { 20, 5, 5, 5, 5, 40 }; // 200ms on, 2x 50ms off/on, 400ms off
16 static int8_t _pin
= -1;
17 static uint8_t _pin_inverted
;
18 static const uint8_t *_durations
;
19 static uint8_t _count
;
20 static uint8_t _counter
= 0;
21 static bool hasRGBLeds
= false;
22 static bool hasGBLeds
= false;
24 static uint16_t updateLED()
26 if (_pin
== UNDEF_PIN
)
28 return DURATION_NEVER
;
31 digitalWrite(_pin
, LOW
^ _pin_inverted
);
33 digitalWrite(_pin
, HIGH
^ _pin_inverted
);
34 if (_counter
>= _count
)
38 return _durations
[_counter
++] * 10;
41 static uint16_t flashLED(int8_t pin
, uint8_t pin_inverted
, const uint8_t durations
[], uint8_t count
)
45 _pin_inverted
= pin_inverted
;
46 _durations
= durations
;
51 static bool initialize()
54 if (GPIO_PIN_LED_BLUE
!= UNDEF_PIN
)
56 pinMode(GPIO_PIN_LED_BLUE
, OUTPUT
);
57 digitalWrite(GPIO_PIN_LED_BLUE
, LOW
^ GPIO_LED_BLUE_INVERTED
);
60 if (GPIO_PIN_LED_GREEN
!= UNDEF_PIN
)
62 pinMode(GPIO_PIN_LED_GREEN
, OUTPUT
);
63 digitalWrite(GPIO_PIN_LED_GREEN
, HIGH
^ GPIO_LED_GREEN_INVERTED
);
66 if (GPIO_PIN_LED_RED
!= UNDEF_PIN
)
68 pinMode(GPIO_PIN_LED_RED
, OUTPUT
);
69 digitalWrite(GPIO_PIN_LED_RED
, LOW
^ GPIO_LED_RED_INVERTED
);
72 if (GPIO_PIN_LED_BLUE
!= UNDEF_PIN
&& GPIO_PIN_LED_GREEN
!= UNDEF_PIN
&& GPIO_PIN_LED_RED
!= UNDEF_PIN
)
75 digitalWrite(GPIO_PIN_LED_GREEN
, LOW
);
76 digitalWrite(GPIO_PIN_LED_RED
, HIGH
);
77 digitalWrite(GPIO_PIN_LED_BLUE
, LOW
);
79 else if (GPIO_PIN_LED_BLUE
!= UNDEF_PIN
&& GPIO_PIN_LED_GREEN
!= UNDEF_PIN
&& GPIO_PIN_LED_RED
== UNDEF_PIN
)
83 return hasLED
|| hasRGBLeds
|| hasGBLeds
;
91 #if defined(TARGET_TX)
92 static void setPowerLEDs()
96 switch (POWERMGNT::currPower())
99 digitalWrite(GPIO_PIN_LED_BLUE
, HIGH
);
100 digitalWrite(GPIO_PIN_LED_GREEN
, HIGH
);
103 digitalWrite(GPIO_PIN_LED_BLUE
, LOW
);
104 digitalWrite(GPIO_PIN_LED_GREEN
, HIGH
);
111 digitalWrite(GPIO_PIN_LED_BLUE
, HIGH
);
112 digitalWrite(GPIO_PIN_LED_GREEN
, LOW
);
121 #if defined(TARGET_TX)
124 if (InBindingMode
&& GPIO_PIN_LED_RED
!= UNDEF_PIN
)
126 return flashLED(GPIO_PIN_LED_RED
, GPIO_LED_RED_INVERTED
, LEDSEQ_BINDING
, sizeof(LEDSEQ_BINDING
));
129 switch (connectionState
)
134 digitalWrite(GPIO_PIN_LED_GREEN
, HIGH
);
135 digitalWrite(GPIO_PIN_LED_RED
, LOW
);
136 digitalWrite(GPIO_PIN_LED_BLUE
, LOW
);
138 else if (GPIO_PIN_LED_GREEN
!= UNDEF_PIN
)
140 digitalWrite(GPIO_PIN_LED_GREEN
, HIGH
^ GPIO_LED_GREEN_INVERTED
);
142 if (GPIO_PIN_LED_RED
!= UNDEF_PIN
)
144 if (!connectionHasModelMatch
|| !teamraceHasModelMatch
)
146 return flashLED(GPIO_PIN_LED_RED
, GPIO_LED_RED_INVERTED
, LEDSEQ_MODEL_MISMATCH
, sizeof(LEDSEQ_MODEL_MISMATCH
));
148 else if (!hasRGBLeds
)
150 digitalWrite(GPIO_PIN_LED_RED
, HIGH
^ GPIO_LED_RED_INVERTED
); // turn on led
153 return DURATION_NEVER
;
157 digitalWrite(GPIO_PIN_LED_GREEN
, LOW
);
158 digitalWrite(GPIO_PIN_LED_BLUE
, LOW
);
159 return flashLED(GPIO_PIN_LED_RED
, GPIO_LED_RED_INVERTED
, LEDSEQ_DISCONNECTED
, sizeof(LEDSEQ_DISCONNECTED
));
161 else if (GPIO_PIN_LED_GREEN
!= UNDEF_PIN
&& GPIO_PIN_LED_RED
!= UNDEF_PIN
)
163 digitalWrite(GPIO_PIN_LED_GREEN
, LOW
^ GPIO_LED_GREEN_INVERTED
);
164 digitalWrite(GPIO_PIN_LED_RED
, LOW
^ GPIO_LED_RED_INVERTED
);
166 else if (GPIO_PIN_LED_RED
!= UNDEF_PIN
)
168 return flashLED(GPIO_PIN_LED_RED
, GPIO_LED_RED_INVERTED
, LEDSEQ_DISCONNECTED
, sizeof(LEDSEQ_DISCONNECTED
));
170 else if (GPIO_PIN_LED_GREEN
!= UNDEF_PIN
)
172 return flashLED(GPIO_PIN_LED_GREEN
, GPIO_LED_GREEN_INVERTED
, LEDSEQ_DISCONNECTED
, sizeof(LEDSEQ_DISCONNECTED
));
174 return DURATION_NEVER
;
178 digitalWrite(GPIO_PIN_LED_GREEN
, LOW
);
179 digitalWrite(GPIO_PIN_LED_RED
, LOW
);
180 return flashLED(GPIO_PIN_LED_BLUE
, GPIO_LED_BLUE_INVERTED
, LEDSEQ_WIFI_UPDATE
, sizeof(LEDSEQ_WIFI_UPDATE
));
182 else if (GPIO_PIN_LED_RED
!= UNDEF_PIN
)
184 return flashLED(GPIO_PIN_LED_RED
, GPIO_LED_RED_INVERTED
, LEDSEQ_WIFI_UPDATE
, sizeof(LEDSEQ_WIFI_UPDATE
));
186 return DURATION_NEVER
;
190 digitalWrite(GPIO_PIN_LED_GREEN
, LOW
);
191 digitalWrite(GPIO_PIN_LED_BLUE
, LOW
);
192 return flashLED(GPIO_PIN_LED_RED
, GPIO_LED_RED_INVERTED
, LEDSEQ_RADIO_FAILED
, sizeof(LEDSEQ_RADIO_FAILED
));
194 else if (GPIO_PIN_LED_GREEN
!= UNDEF_PIN
)
196 digitalWrite(GPIO_PIN_LED_GREEN
, LOW
^ GPIO_LED_GREEN_INVERTED
);
198 if (GPIO_PIN_LED_RED
!= UNDEF_PIN
)
200 return flashLED(GPIO_PIN_LED_RED
, GPIO_LED_RED_INVERTED
, LEDSEQ_RADIO_FAILED
, sizeof(LEDSEQ_RADIO_FAILED
));
202 return DURATION_NEVER
;
204 if (GPIO_PIN_LED_RED
!= UNDEF_PIN
)
206 // technically nocrossfire is {10,100} but {20,100} is close enough
207 return flashLED(GPIO_PIN_LED_RED
, GPIO_LED_RED_INVERTED
, LEDSEQ_RADIO_FAILED
, sizeof(LEDSEQ_RADIO_FAILED
));
210 if (GPIO_PIN_LED_RED
!= UNDEF_PIN
)
212 return flashLED(GPIO_PIN_LED_RED
, GPIO_LED_RED_INVERTED
, LEDSEQ_UPDATE
, sizeof(LEDSEQ_UPDATE
));
215 return DURATION_NEVER
;
224 device_t LED_device
= {
225 .initialize
= initialize
,
229 .subscribe
= EVENT_CONNECTION_CHANGED
| EVENT_ENTER_BIND_MODE
| EVENT_EXIT_BIND_MODE