diff --git a/.gitattributes b/.gitattributes
new file mode 100644
index 0000000000..ce84c76420
--- /dev/null
+++ b/.gitattributes
@@ -0,0 +1,2 @@
+*.md eol=crlf
+
diff --git a/docs/LedStrip.md b/docs/LedStrip.md
index 849e3bf23c..7bea700ade 100644
--- a/docs/LedStrip.md
+++ b/docs/LedStrip.md
@@ -1,290 +1,293 @@
-# Led Strip
-
-Cleanflight supports the use of addressable LED strips. Addressable LED strips allow each LED in the strip to
-be programmed with a unique and independant color. This is far more advanced than the normal RGB strips which
-require that all the LEDs in the strip show the same color.
-
-Addressable LED strips can be used to show information from the flight controller system, the current implementation
-supports the following:
-
-* Up to 32 LEDs.
-* Indicators showing pitch/roll stick positions.
-* Heading/Orientation lights.
-* Flight mode specific color schemes.
-* Low battery warning.
-
-The function and orientation configuration is fixed for now but later it should be able to be set via the UI or CLI..
-
-In the future, if someone codes it, they could be used to show GPS navigation status, thrust levels, RSSI, etc.
-Lots of scope for ideas and improvements.
-
-Likewise, support for more than 32 LEDs is possible, it just requires additional development.
-
-## Supported hardware
-
-Only strips of 32 WS2812 LEDs are supported currently. If the strip is longer than 32 leds it does not matter,
-but only the first 32 are used.
-
-WS2812 LEDs require an 800khz signal and precise timings and thus requires the use of a dedicated hardware timer.
-
-Note: The initial code may work with WS2801 + External LEDs since the protocol is the same, WS2811/WS2812B should also work but
-may require very simple timing adjustments to be made in the source.
-Not all WS2812 ICs use the same timings, some batches use different timings.
-
-It could be possible to be able to specify the timings required via CLI if users request it.
-
-## Connections
-
-WS2812 LED strips generally require a single data line, 5V and GND.
-
-WS2812 LEDs on full brightness can consume quite a bit of current. It is recommended to verify the current draw and ensure your
-supply can cope with the load. On a multirotor that uses multiple BEC ESC's you can try use a different BEC to the one the FC
-uses. e.g. ESC1/BEC1 -> FC, ESC2/BEC2 -> LED strip. It's also possible to power one half of the strip from one BEC and the other half
-from another BEC. Just ensure that the GROUND is the same for all BEC outputs and LEDs.
-
-
-| Target | Pin | Led Strip | Signal |
-| --------------------- | --- | --------- | -------|
-| Naze/Olimexino | RC5 | Data In | PA6 |
-| CC3D | ??? | Data In | PB4 |
-| ChebuzzF3/F3Discovery | PB8 | Data In | PB8 |
-
-
-Since RC5 is also used for SoftSerial on the Naze/Olimexino it means that you cannot use softserial and led strips at the same time.
-Additionally, since RC5 is also used for Parallel PWM RC input on both the Naze, Chebuzz and STM32F3Discovery targets, led strips
-can not be used at the same time at Parallel PWM.
-
-
-## Configuration
-
-Enable the `LED_STRIP` feature via the cli:
-
-```
-feature LED_STRIP
-```
-
-If you enable LED_STRIP feature and the feature is turned off again after a reboot then check your config does not conflict with other features, as above.
-
-Configure the LEDs using the `led` command.
-
-The `led` command takes either zero or two arguments - an zero-based led number and a pair of coordinates, direction flags and mode flags.
-
-If used with zero arguments it prints out the led configuration which can be copied for future reference.
-
-Each led is configured using the following template: `x,y:ddd:mmm`
-
-`x` and `y` are grid coordinates of a 0 based 16x16 grid, north west is 0,0, south east is 15,15
-`ddd` specifies the directions, since an led can face in any direction it can have multiple directions. Directions are:
-
- `N` - North
- `E` - East
- `S` - South
- `W` - West
- `U` - Up
- `D` - Down
-
-For instance, an LED that faces South-east at a 45 degree downwards angle could be configured as `SED`.
-
-Note: It is perfectly possible to configure an LED to have all directions `NESWUD` but probably doesn't make sense.
-
-`mmm` specifies the modes that should be applied an LED. Modes are:
-
-* `B` - `B`attery warning.
-* `F` - `F`light mode & Orientation
-* `I` - `I`ndicator.
-* `A` - `A`rmed state.
-
-Example:
-
-```
-led 0 0,15:SD:IAB
-led 1 15,0:ND:IAB
-led 2 0,0:ND:IAB
-led 3 0,15:SD:IAB
-```
-
-to erase an led, and to mark the end of the chain, use `0,0::` as the second argument, like this:
-
-```
-led 4 0,0::
-```
-
-
-### Modes
-
-#### Battery Warning
-
-This mode simply flashes the LED RED when the battery is low if battery monitoring is enabled.
-
-#### Flight Mode & Orientation
-
-This mode shows the flight mode and orientation.
-
-When flight modes are active then the leds are updated to show different colors depending on the mode, placement on the grid and direction.
-
-Leds are set in a specific order:
- * Leds that marked as facing up or down.
- * Leds that marked as facing west or east AND are on the west or east side of the grid.
- * Leds that marked as facing north or south AND are on the north or south side of the grid.
-
-That is, south facing leds have priority.
-
-#### Indicator
-
-This mode flashes LEDs that correspond to roll and pitch stick positions. i.e. they indicate the direction the craft is going to turn.
-
-#### Armed state
-
-This mode toggles LEDs between green and blue when disarmed and armed, respectively.
-
-Note: Armed State cannot be used with Flight Mode.
-
-## Positioning
-
-Cut the strip into sections as per diagrams below. When the strips are cut ensure you reconnect each output to each input with cable where the break is made.
-e.g. connect 5V out to 5V in, GND to GND and Data Out to Data In.
-
-Orientation is when viewed with the front of the aircraft facing away from you and viewed from above.
-
-### Example 12 LED config
-
-The default configuration is as follows
-```
-led 0 2,2:ES:IA
-led 1 2,1:E:BF
-led 2 2,0:NE:IA
-led 3 1,0:N:F
-led 4 0,0:NW:IA
-led 5 0,1:W:BF
-led 6 0,2:SW:IA
-led 7 1,2:S:BF
-led 8 1,1:U:BF
-led 9 1,1:U:BF
-led 10 1,1:D:BF
-led 11 1,1:D:BF
-```
-
-Which translates into the following positions:
-
-```
- 5 3
- \ /
- \ 4 /
- \ FRONT /
- 6 | 9-12 | 2
- / BACK \
- / 8 \
- / \
- 7 1
-```
-
-LEDs 1,3,5 and 7 should be placed underneath the quad, facing downwards.
-LEDs 2, 4, 6 and 8 should be positioned so the face east/north/west/south, respectively.
-LEDs 9-10 should be placed facing down, in the middle
-LEDs 11-12 should be placed facing up, in the middle
-
-This is the default so that if you don't want to place LEDs top and bottom in the middle just connect the first 8 leds.
-
-### Example 16 LED config
-
-```
-15,15:SD:IA
-8,8:E:FB
-8,7:E:FB
-15,0:ND:IA
-7,7:N:FB
-8,7:N:FB
-0,0:ND:IA
-7,7:W:FB
-7,8:W:FB
-0,15:SD:IA
-7,8:S:FB
-8,8:S:FB
-7,7:D:FB
-8,7:D:FB
-7,7:U:FB
-8,7:U:FB
-```
-
-Which translates into the following positions:
-
-```
- 7 4
- \ /
- \ 6-5 /
- 8 \ FRONT / 3
- | 13-16 |
- 9 / BACK \ 2
- / 11-12 \
- / \
- 10 1
-```
-
-LEDs 1,4,7 and 10 should be placed underneath the quad, facing downwards.
-LEDs 2-3, 6-5, 8-9 and 11-12 should be positioned so the face east/north/west/south, respectively.
-LEDs 13-14 should be placed facing down, in the middle
-LEDs 15-16 should be placed facing up, in the middle
-
-### Exmple 28 LED config
-
-```
-9,9:S:FB
-10,10:S:FB
-11,11:S:IA
-11,11:E:IA
-10,10:E:F
-9,9:E:F
-10,5:S:F
-11,4:S:F
-12,3:S:IA
-12,2:N:IA
-11,1:N:F
-10,0:N:F
-7,0:N:FB
-6,0:N:FB
-5,0:N:FB
-4,0:N:FB
-2,0:N:F
-1,1:N:F
-0,2:N:IA
-0,3:W:IA
-1,4:W:F
-2,5:W:F
-2,9:W:F
-1,10:W:F
-0,11:W:IA
-0,11:S:IA
-1,10:S:FB
-2,9:S:FB
-```
-
-```
- 17-19 10-12
-20-22 \ / 7-9
- \ 13-16 /
- \ FRONT /
- / BACK \
- / \
-23-25 / \ 4-6
- 26-28 1-3
-```
-
-All LEDs should face outwards from the chassis in this configuration.
-
-Note:
-This configuration is specifically designed for the Alien Spider AQ50D PRO 250mm frame.
-
-http://www.goodluckbuy.com/alien-spider-aq50d-pro-250mm-mini-quadcopter-carbon-fiber-micro-multicopter-frame.html
-
-## Troubleshooting
-
-On initial power up the LEDs on the strip will be set to WHITE. This means you can attach a current meter to verify
-the current draw if your measurement equipment is fast enough. This also means that you can make sure that each R,G and B LED
-in each LED module on the strip is also functioning.
-
-After a short delay the LEDs will show the unarmed color sequence and or low-battery warning sequence.
-
-If the LEDs flash intermittently or do not show the correct colors verify all connections and check the specifications of the
-LEDs you have against the supported timings (for now, you'll have to look in the source).
-
-Also check that the feature `LED_STRIP` was correctly enabled and that it does not conflict with other features, as above.
+# Led Strip
+
+Cleanflight supports the use of addressable LED strips. Addressable LED strips allow each LED in the strip to
+be programmed with a unique and independant color. This is far more advanced than the normal RGB strips which
+require that all the LEDs in the strip show the same color.
+
+Addressable LED strips can be used to show information from the flight controller system, the current implementation
+supports the following:
+
+* Up to 32 LEDs.
+* Indicators showing pitch/roll stick positions.
+* Heading/Orientation lights.
+* Flight mode specific color schemes.
+* Low battery warning.
+
+The function and orientation configuration is fixed for now but later it should be able to be set via the UI or CLI..
+
+In the future, if someone codes it, they could be used to show GPS navigation status, thrust levels, RSSI, etc.
+Lots of scope for ideas and improvements.
+
+Likewise, support for more than 32 LEDs is possible, it just requires additional development.
+
+## Supported hardware
+
+Only strips of 32 WS2812 LEDs are supported currently. If the strip is longer than 32 leds it does not matter,
+but only the first 32 are used.
+
+WS2812 LEDs require an 800khz signal and precise timings and thus requires the use of a dedicated hardware timer.
+
+Note: The initial code may work with WS2801 + External LEDs since the protocol is the same, WS2811/WS2812B should also work but
+may require very simple timing adjustments to be made in the source.
+Not all WS2812 ICs use the same timings, some batches use different timings.
+
+It could be possible to be able to specify the timings required via CLI if users request it.
+
+## Connections
+
+WS2812 LED strips generally require a single data line, 5V and GND.
+
+WS2812 LEDs on full brightness can consume quite a bit of current. It is recommended to verify the current draw and ensure your
+supply can cope with the load. On a multirotor that uses multiple BEC ESC's you can try use a different BEC to the one the FC
+uses. e.g. ESC1/BEC1 -> FC, ESC2/BEC2 -> LED strip. It's also possible to power one half of the strip from one BEC and the other half
+from another BEC. Just ensure that the GROUND is the same for all BEC outputs and LEDs.
+
+
+| Target | Pin | Led Strip | Signal |
+| --------------------- | --- | --------- | -------|
+| Naze/Olimexino | RC5 | Data In | PA6 |
+| CC3D | ??? | Data In | PB4 |
+| ChebuzzF3/F3Discovery | PB8 | Data In | PB8 |
+
+
+Since RC5 is also used for SoftSerial on the Naze/Olimexino it means that you cannot use softserial and led strips at the same time.
+Additionally, since RC5 is also used for Parallel PWM RC input on both the Naze, Chebuzz and STM32F3Discovery targets, led strips
+can not be used at the same time at Parallel PWM.
+
+
+## Configuration
+
+Enable the `LED_STRIP` feature via the cli:
+
+```
+feature LED_STRIP
+```
+
+If you enable LED_STRIP feature and the feature is turned off again after a reboot then check your config does not conflict with other features, as above.
+
+Configure the LEDs using the `led` command.
+
+The `led` command takes either zero or two arguments - an zero-based led number and a pair of coordinates, direction flags and mode flags.
+
+If used with zero arguments it prints out the led configuration which can be copied for future reference.
+
+Each led is configured using the following template: `x,y:ddd:mmm`
+
+`x` and `y` are grid coordinates of a 0 based 16x16 grid, north west is 0,0, south east is 15,15
+`ddd` specifies the directions, since an led can face in any direction it can have multiple directions. Directions are:
+
+ `N` - North
+ `E` - East
+ `S` - South
+ `W` - West
+ `U` - Up
+ `D` - Down
+
+For instance, an LED that faces South-east at a 45 degree downwards angle could be configured as `SED`.
+
+Note: It is perfectly possible to configure an LED to have all directions `NESWUD` but probably doesn't make sense.
+
+`mmm` specifies the modes that should be applied an LED. Modes are:
+
+* `W` - `W`warnings.
+* `F` - `F`light mode & Orientation
+* `I` - `I`ndicator.
+* `A` - `A`rmed state.
+
+Example:
+
+```
+led 0 0,15:SD:IAW
+led 1 15,0:ND:IAW
+led 2 0,0:ND:IAW
+led 3 0,15:SD:IAW
+```
+
+to erase an led, and to mark the end of the chain, use `0,0::` as the second argument, like this:
+
+```
+led 4 0,0::
+```
+
+
+### Modes
+
+#### Warning
+
+This mode simply uses the leds to flash when warnings occur.
+
+* Battery warning flashes the LEDs between red and off when the battery is low if battery monitoring is enabled.
+* Failsafe warning flashes the LEDs between light blue and lime green when failsafe is active.
+
+#### Flight Mode & Orientation
+
+This mode shows the flight mode and orientation.
+
+When flight modes are active then the leds are updated to show different colors depending on the mode, placement on the grid and direction.
+
+Leds are set in a specific order:
+ * Leds that marked as facing up or down.
+ * Leds that marked as facing west or east AND are on the west or east side of the grid.
+ * Leds that marked as facing north or south AND are on the north or south side of the grid.
+
+That is, south facing leds have priority.
+
+#### Indicator
+
+This mode flashes LEDs that correspond to roll and pitch stick positions. i.e. they indicate the direction the craft is going to turn.
+
+#### Armed state
+
+This mode toggles LEDs between green and blue when disarmed and armed, respectively.
+
+Note: Armed State cannot be used with Flight Mode.
+
+## Positioning
+
+Cut the strip into sections as per diagrams below. When the strips are cut ensure you reconnect each output to each input with cable where the break is made.
+e.g. connect 5V out to 5V in, GND to GND and Data Out to Data In.
+
+Orientation is when viewed with the front of the aircraft facing away from you and viewed from above.
+
+### Example 12 LED config
+
+The default configuration is as follows
+```
+led 0 2,2:ES:IA
+led 1 2,1:E:WF
+led 2 2,0:NE:IA
+led 3 1,0:N:F
+led 4 0,0:NW:IA
+led 5 0,1:W:WF
+led 6 0,2:SW:IA
+led 7 1,2:S:WF
+led 8 1,1:U:WF
+led 9 1,1:U:WF
+led 10 1,1:D:WF
+led 11 1,1:D:WF
+```
+
+Which translates into the following positions:
+
+```
+ 5 3
+ \ /
+ \ 4 /
+ \ FRONT /
+ 6 | 9-12 | 2
+ / BACK \
+ / 8 \
+ / \
+ 7 1
+```
+
+LEDs 1,3,5 and 7 should be placed underneath the quad, facing downwards.
+LEDs 2, 4, 6 and 8 should be positioned so the face east/north/west/south, respectively.
+LEDs 9-10 should be placed facing down, in the middle
+LEDs 11-12 should be placed facing up, in the middle
+
+This is the default so that if you don't want to place LEDs top and bottom in the middle just connect the first 8 leds.
+
+### Example 16 LED config
+
+```
+15,15:SD:IA
+8,8:E:FW
+8,7:E:FW
+15,0:ND:IA
+7,7:N:FW
+8,7:N:FW
+0,0:ND:IA
+7,7:W:FW
+7,8:W:FW
+0,15:SD:IA
+7,8:S:FW
+8,8:S:FW
+7,7:D:FW
+8,7:D:FW
+7,7:U:FW
+8,7:U:FW
+```
+
+Which translates into the following positions:
+
+```
+ 7 4
+ \ /
+ \ 6-5 /
+ 8 \ FRONT / 3
+ | 13-16 |
+ 9 / BACK \ 2
+ / 11-12 \
+ / \
+ 10 1
+```
+
+LEDs 1,4,7 and 10 should be placed underneath the quad, facing downwards.
+LEDs 2-3, 6-5, 8-9 and 11-12 should be positioned so the face east/north/west/south, respectively.
+LEDs 13-14 should be placed facing down, in the middle
+LEDs 15-16 should be placed facing up, in the middle
+
+### Exmple 28 LED config
+
+```
+9,9:S:FW
+10,10:S:FW
+11,11:S:IA
+11,11:E:IA
+10,10:E:F
+9,9:E:F
+10,5:S:F
+11,4:S:F
+12,3:S:IA
+12,2:N:IA
+11,1:N:F
+10,0:N:F
+7,0:N:FW
+6,0:N:FW
+5,0:N:FW
+4,0:N:FW
+2,0:N:F
+1,1:N:F
+0,2:N:IA
+0,3:W:IA
+1,4:W:F
+2,5:W:F
+2,9:W:F
+1,10:W:F
+0,11:W:IA
+0,11:S:IA
+1,10:S:FW
+2,9:S:FW
+```
+
+```
+ 17-19 10-12
+20-22 \ / 7-9
+ \ 13-16 /
+ \ FRONT /
+ / BACK \
+ / \
+23-25 / \ 4-6
+ 26-28 1-3
+```
+
+All LEDs should face outwards from the chassis in this configuration.
+
+Note:
+This configuration is specifically designed for the Alien Spider AQ50D PRO 250mm frame.
+
+http://www.goodluckbuy.com/alien-spider-aq50d-pro-250mm-mini-quadcopter-carbon-fiber-micro-multicopter-frame.html
+
+## Troubleshooting
+
+On initial power up the LEDs on the strip will be set to WHITE. This means you can attach a current meter to verify
+the current draw if your measurement equipment is fast enough. This also means that you can make sure that each R,G and B LED
+in each LED module on the strip is also functioning.
+
+After a short delay the LEDs will show the unarmed color sequence and or low-battery warning sequence.
+
+If the LEDs flash intermittently or do not show the correct colors verify all connections and check the specifications of the
+LEDs you have against the supported timings (for now, you'll have to look in the source).
+
+Also check that the feature `LED_STRIP` was correctly enabled and that it does not conflict with other features, as above.
diff --git a/src/main/io/ledstrip.c b/src/main/io/ledstrip.c
index 8c23177080..b3a05cfcd5 100644
--- a/src/main/io/ledstrip.c
+++ b/src/main/io/ledstrip.c
@@ -42,9 +42,12 @@
#include "config/config.h"
#include "rx/rx.h"
#include "io/rc_controls.h"
+#include "flight/failsafe.h"
#include "io/ledstrip.h"
+static failsafe_t* failsafe;
+
#if MAX_LED_STRIP_LENGTH > WS2811_LED_STRIP_LENGTH
#error "Led strip length must match driver"
#endif
@@ -74,6 +77,8 @@ const rgbColor24bpp_t red = { LED_RED };
const rgbColor24bpp_t orange = { LED_ORANGE };
const rgbColor24bpp_t green = { LED_GREEN };
const rgbColor24bpp_t blue = { LED_BLUE };
+const rgbColor24bpp_t lightBlue = { LED_LIGHT_BLUE };
+const rgbColor24bpp_t limeGreen = { LED_LIME_GREEN };
uint8_t ledGridWidth;
@@ -84,17 +89,17 @@ ledConfig_t *ledConfigs;
const ledConfig_t defaultLedStripConfig[] = {
{ CALCULATE_LED_XY( 2, 2), LED_DIRECTION_SOUTH | LED_DIRECTION_EAST | LED_FUNCTION_INDICATOR | LED_FUNCTION_ARM_STATE },
- { CALCULATE_LED_XY( 2, 1), LED_DIRECTION_EAST | LED_FUNCTION_FLIGHT_MODE | LED_FUNCTION_BATTERY },
+ { CALCULATE_LED_XY( 2, 1), LED_DIRECTION_EAST | LED_FUNCTION_FLIGHT_MODE | LED_FUNCTION_WARNING },
{ CALCULATE_LED_XY( 2, 0), LED_DIRECTION_NORTH | LED_DIRECTION_EAST | LED_FUNCTION_INDICATOR | LED_FUNCTION_ARM_STATE },
{ CALCULATE_LED_XY( 1, 0), LED_DIRECTION_NORTH | LED_FUNCTION_FLIGHT_MODE },
{ CALCULATE_LED_XY( 0, 0), LED_DIRECTION_NORTH | LED_DIRECTION_WEST | LED_FUNCTION_INDICATOR | LED_FUNCTION_ARM_STATE },
- { CALCULATE_LED_XY( 0, 1), LED_DIRECTION_WEST | LED_FUNCTION_FLIGHT_MODE | LED_FUNCTION_BATTERY },
+ { CALCULATE_LED_XY( 0, 1), LED_DIRECTION_WEST | LED_FUNCTION_FLIGHT_MODE | LED_FUNCTION_WARNING },
{ CALCULATE_LED_XY( 0, 2), LED_DIRECTION_SOUTH | LED_DIRECTION_WEST | LED_FUNCTION_INDICATOR | LED_FUNCTION_ARM_STATE },
- { CALCULATE_LED_XY( 1, 2), LED_DIRECTION_SOUTH | LED_FUNCTION_FLIGHT_MODE | LED_FUNCTION_BATTERY },
- { CALCULATE_LED_XY( 1, 1), LED_DIRECTION_UP | LED_FUNCTION_FLIGHT_MODE | LED_FUNCTION_BATTERY },
- { CALCULATE_LED_XY( 1, 1), LED_DIRECTION_UP | LED_FUNCTION_FLIGHT_MODE | LED_FUNCTION_BATTERY },
- { CALCULATE_LED_XY( 1, 1), LED_DIRECTION_DOWN | LED_FUNCTION_FLIGHT_MODE | LED_FUNCTION_BATTERY },
- { CALCULATE_LED_XY( 1, 1), LED_DIRECTION_DOWN | LED_FUNCTION_FLIGHT_MODE | LED_FUNCTION_BATTERY },
+ { CALCULATE_LED_XY( 1, 2), LED_DIRECTION_SOUTH | LED_FUNCTION_FLIGHT_MODE | LED_FUNCTION_WARNING },
+ { CALCULATE_LED_XY( 1, 1), LED_DIRECTION_UP | LED_FUNCTION_FLIGHT_MODE | LED_FUNCTION_WARNING },
+ { CALCULATE_LED_XY( 1, 1), LED_DIRECTION_UP | LED_FUNCTION_FLIGHT_MODE | LED_FUNCTION_WARNING },
+ { CALCULATE_LED_XY( 1, 1), LED_DIRECTION_DOWN | LED_FUNCTION_FLIGHT_MODE | LED_FUNCTION_WARNING },
+ { CALCULATE_LED_XY( 1, 1), LED_DIRECTION_DOWN | LED_FUNCTION_FLIGHT_MODE | LED_FUNCTION_WARNING },
};
@@ -130,11 +135,11 @@ static const uint8_t directionMappings[DIRECTION_COUNT] = {
LED_DIRECTION_DOWN
};
-static const char functionCodes[] = { 'I', 'B', 'F', 'A' };
+static const char functionCodes[] = { 'I', 'W', 'F', 'A' };
#define FUNCTION_COUNT (sizeof(functionCodes) / sizeof(functionCodes[0]))
static const uint16_t functionMappings[FUNCTION_COUNT] = {
LED_FUNCTION_INDICATOR,
- LED_FUNCTION_BATTERY,
+ LED_FUNCTION_WARNING,
LED_FUNCTION_FLIGHT_MODE,
LED_FUNCTION_ARM_STATE
};
@@ -310,7 +315,7 @@ void generateLedConfig(uint8_t ledIndex, char *ledConfigBuffer, size_t bufferSiz
// timers
uint32_t nextAnimationUpdateAt = 0;
uint32_t nextIndicatorFlashAt = 0;
-uint32_t nextBatteryFlashAt = 0;
+uint32_t nextWarningFlashAt = 0;
#define LED_STRIP_20HZ ((1000 * 1000) / 20)
#define LED_STRIP_10HZ ((1000 * 1000) / 10)
@@ -506,23 +511,45 @@ void applyLedModeLayer(void)
}
}
-void applyLedLowBatteryLayer(uint8_t batteryFlashState)
+typedef enum {
+ WARNING_FLAG_NONE = 0,
+ WARNING_FLAG_LOW_BATTERY = (1 << 0),
+ WARNING_FLAG_FAILSAFE = (1 << 1)
+} warningFlags_e;
+
+void applyLedWarningLayer(uint8_t warningState, uint8_t warningFlags)
{
const ledConfig_t *ledConfig;
+ static uint8_t warningFlashCounter = 0;
+
+ if (warningState) {
+ warningFlashCounter++;
+ warningFlashCounter = warningFlashCounter % 4;
+ }
uint8_t ledIndex;
for (ledIndex = 0; ledIndex < ledCount; ledIndex++) {
ledConfig = &ledConfigs[ledIndex];
- if (!(ledConfig->flags & LED_FUNCTION_BATTERY)) {
+ if (!(ledConfig->flags & LED_FUNCTION_WARNING)) {
continue;
}
- if (batteryFlashState == 0) {
- setLedColor(ledIndex, &red);
+ if (warningState == 0) {
+ if (warningFlashCounter == 0 && warningFlags & WARNING_FLAG_LOW_BATTERY) {
+ setLedColor(ledIndex, &red);
+ }
+ if (warningFlashCounter > 1 && warningFlags & WARNING_FLAG_FAILSAFE) {
+ setLedColor(ledIndex, &lightBlue);
+ }
} else {
- setLedColor(ledIndex, &black);
+ if (warningFlashCounter == 0 && warningFlags & WARNING_FLAG_LOW_BATTERY) {
+ setLedColor(ledIndex, &black);
+ }
+ if (warningFlashCounter > 1 && warningFlags & WARNING_FLAG_FAILSAFE) {
+ setLedColor(ledIndex, &limeGreen);
+ }
}
}
}
@@ -625,15 +652,15 @@ void updateLedStrip(void)
bool animationUpdateNow = (int32_t)(now - nextAnimationUpdateAt) >= 0L;
bool indicatorFlashNow = (int32_t)(now - nextIndicatorFlashAt) >= 0L;
- bool batteryFlashNow = (int32_t)(now - nextBatteryFlashAt) >= 0L;
+ bool warningFlashNow = (int32_t)(now - nextWarningFlashAt) >= 0L;
- if (!(batteryFlashNow || indicatorFlashNow || animationUpdateNow)) {
+ if (!(warningFlashNow || indicatorFlashNow || animationUpdateNow)) {
return;
}
static uint8_t indicatorFlashState = 0;
- static uint8_t batteryFlashState = 0;
- static bool batteryWarningEnabled = false;
+ static uint8_t warningState = 0;
+ static uint8_t warningFlags;
// LAYER 1
@@ -641,21 +668,27 @@ void updateLedStrip(void)
// LAYER 2
- if (batteryFlashNow) {
- nextBatteryFlashAt = now + LED_STRIP_10HZ;
+ if (warningFlashNow) {
+ nextWarningFlashAt = now + LED_STRIP_10HZ;
- if (batteryFlashState == 0) {
- batteryFlashState = 1;
+ if (warningState == 0) {
+ warningState = 1;
+
+ warningFlags = WARNING_FLAG_NONE;
+ if (feature(FEATURE_VBAT) && shouldSoundBatteryAlarm()) {
+ warningFlags |= WARNING_FLAG_LOW_BATTERY;
+ }
+ if (failsafe->vTable->hasTimerElapsed()) {
+ warningFlags |= WARNING_FLAG_FAILSAFE;
+ }
- batteryWarningEnabled = feature(FEATURE_VBAT) && shouldSoundBatteryAlarm();
} else {
- batteryFlashState = 0;
-
+ warningState = 0;
}
}
- if (batteryWarningEnabled) {
- applyLedLowBatteryLayer(batteryFlashState);
+ if (warningFlags) {
+ applyLedWarningLayer(warningState, warningFlags);
}
// LAYER 3
@@ -694,9 +727,10 @@ void applyDefaultLedStripConfig(ledConfig_t *ledConfigs)
reevalulateLedConfig();
}
-void ledStripInit(ledConfig_t *ledConfigsToUse)
+void ledStripInit(ledConfig_t *ledConfigsToUse, failsafe_t* failsafeToUse)
{
ledConfigs = ledConfigsToUse;
+ failsafe = failsafeToUse;
reevalulateLedConfig();
}
#endif
diff --git a/src/main/io/ledstrip.h b/src/main/io/ledstrip.h
index 9ce3e00823..27828c40ba 100644
--- a/src/main/io/ledstrip.h
+++ b/src/main/io/ledstrip.h
@@ -41,7 +41,7 @@ typedef enum {
LED_DIRECTION_UP = (1 << 4),
LED_DIRECTION_DOWN = (1 << 5),
LED_FUNCTION_INDICATOR = (1 << 6),
- LED_FUNCTION_BATTERY = (1 << 7),
+ LED_FUNCTION_WARNING = (1 << 7),
LED_FUNCTION_FLIGHT_MODE = (1 << 8),
LED_FUNCTION_ARM_STATE = (1 << 9)
} ledFlag_e;
diff --git a/src/main/main.c b/src/main/main.c
index b3f87890ea..2446659415 100755
--- a/src/main/main.c
+++ b/src/main/main.c
@@ -89,8 +89,7 @@ void gpsInit(serialConfig_t *serialConfig, gpsConfig_t *initialGpsConfig);
void navigationInit(gpsProfile_t *initialGpsProfile, pidProfile_t *pidProfile);
bool sensorsAutodetect(sensorAlignmentConfig_t *sensorAlignmentConfig, uint16_t gyroLpf, uint8_t accHardwareToUse, int16_t magDeclinationFromConfig);
void imuInit(void);
-void ledStripInit(ledConfig_t *ledConfigs);
-
+void ledStripInit(ledConfig_t *ledConfigsToUse, failsafe_t* failsafeToUse);
void loop(void);
// FIXME bad naming - this appears to be for some new board that hasn't been made available yet.
@@ -238,7 +237,7 @@ void init(void)
#ifdef LED_STRIP
if (feature(FEATURE_LED_STRIP)) {
ws2811LedStripInit();
- ledStripInit(masterConfig.ledConfigs);
+ ledStripInit(masterConfig.ledConfigs, failsafe);
}
#endif
diff --git a/src/test/unit/ledstrip_unittest.cc b/src/test/unit/ledstrip_unittest.cc
index 9d711cfd01..f34c355a19 100644
--- a/src/test/unit/ledstrip_unittest.cc
+++ b/src/test/unit/ledstrip_unittest.cc
@@ -15,6 +15,7 @@
* along with Cleanflight. If not, see .
*/
#include
+#include
#include
@@ -56,8 +57,8 @@ TEST(LedStripTest, parseLedStripConfig)
// given
static const ledConfig_t expectedLedStripConfig[WS2811_LED_STRIP_LENGTH] = {
- { CALCULATE_LED_XY( 9, 9), LED_DIRECTION_SOUTH | LED_FUNCTION_FLIGHT_MODE | LED_FUNCTION_BATTERY },
- { CALCULATE_LED_XY(10, 10), LED_DIRECTION_SOUTH | LED_FUNCTION_FLIGHT_MODE | LED_FUNCTION_BATTERY },
+ { CALCULATE_LED_XY( 9, 9), LED_DIRECTION_SOUTH | LED_FUNCTION_FLIGHT_MODE | LED_FUNCTION_WARNING },
+ { CALCULATE_LED_XY(10, 10), LED_DIRECTION_SOUTH | LED_FUNCTION_FLIGHT_MODE | LED_FUNCTION_WARNING },
{ CALCULATE_LED_XY(11, 11), LED_DIRECTION_SOUTH | LED_FUNCTION_INDICATOR | LED_FUNCTION_ARM_STATE },
{ CALCULATE_LED_XY(11, 11), LED_DIRECTION_EAST | LED_FUNCTION_INDICATOR | LED_FUNCTION_ARM_STATE },
{ CALCULATE_LED_XY(10, 10), LED_DIRECTION_EAST | LED_FUNCTION_FLIGHT_MODE },
@@ -70,10 +71,10 @@ TEST(LedStripTest, parseLedStripConfig)
{ CALCULATE_LED_XY(11, 1), LED_DIRECTION_NORTH | LED_FUNCTION_FLIGHT_MODE },
{ CALCULATE_LED_XY(10, 0), LED_DIRECTION_NORTH | LED_FUNCTION_FLIGHT_MODE },
- { CALCULATE_LED_XY( 7, 0), LED_DIRECTION_NORTH | LED_FUNCTION_FLIGHT_MODE | LED_FUNCTION_BATTERY },
- { CALCULATE_LED_XY( 6, 0), LED_DIRECTION_NORTH | LED_FUNCTION_FLIGHT_MODE | LED_FUNCTION_BATTERY },
- { CALCULATE_LED_XY( 5, 0), LED_DIRECTION_NORTH | LED_FUNCTION_FLIGHT_MODE | LED_FUNCTION_BATTERY },
- { CALCULATE_LED_XY( 4, 0), LED_DIRECTION_NORTH | LED_FUNCTION_FLIGHT_MODE | LED_FUNCTION_BATTERY },
+ { CALCULATE_LED_XY( 7, 0), LED_DIRECTION_NORTH | LED_FUNCTION_FLIGHT_MODE | LED_FUNCTION_WARNING },
+ { CALCULATE_LED_XY( 6, 0), LED_DIRECTION_NORTH | LED_FUNCTION_FLIGHT_MODE | LED_FUNCTION_WARNING },
+ { CALCULATE_LED_XY( 5, 0), LED_DIRECTION_NORTH | LED_FUNCTION_FLIGHT_MODE | LED_FUNCTION_WARNING },
+ { CALCULATE_LED_XY( 4, 0), LED_DIRECTION_NORTH | LED_FUNCTION_FLIGHT_MODE | LED_FUNCTION_WARNING },
{ CALCULATE_LED_XY( 2, 0), LED_DIRECTION_NORTH | LED_FUNCTION_FLIGHT_MODE },
{ CALCULATE_LED_XY( 1, 1), LED_DIRECTION_NORTH | LED_FUNCTION_FLIGHT_MODE },
@@ -86,8 +87,8 @@ TEST(LedStripTest, parseLedStripConfig)
{ CALCULATE_LED_XY( 1, 10), LED_DIRECTION_WEST | LED_FUNCTION_FLIGHT_MODE },
{ CALCULATE_LED_XY( 0, 11), LED_DIRECTION_WEST | LED_FUNCTION_INDICATOR | LED_FUNCTION_ARM_STATE },
{ CALCULATE_LED_XY( 0, 11), LED_DIRECTION_SOUTH | LED_FUNCTION_INDICATOR | LED_FUNCTION_ARM_STATE },
- { CALCULATE_LED_XY( 1, 10), LED_DIRECTION_SOUTH | LED_FUNCTION_FLIGHT_MODE | LED_FUNCTION_BATTERY },
- { CALCULATE_LED_XY( 2, 9), LED_DIRECTION_SOUTH | LED_FUNCTION_FLIGHT_MODE | LED_FUNCTION_BATTERY },
+ { CALCULATE_LED_XY( 1, 10), LED_DIRECTION_SOUTH | LED_FUNCTION_FLIGHT_MODE | LED_FUNCTION_WARNING },
+ { CALCULATE_LED_XY( 2, 9), LED_DIRECTION_SOUTH | LED_FUNCTION_FLIGHT_MODE | LED_FUNCTION_WARNING },
{ 0, 0 },
{ 0, 0 },
@@ -100,8 +101,8 @@ TEST(LedStripTest, parseLedStripConfig)
// Spider quad
// right rear cluster
- "9,9:S:FB",
- "10,10:S:FB",
+ "9,9:S:FW",
+ "10,10:S:FW",
"11,11:S:IA",
"11,11:E:IA",
"10,10:E:F",
@@ -116,10 +117,10 @@ TEST(LedStripTest, parseLedStripConfig)
"10,0:N:F",
// center front cluster
- "7,0:N:FB",
- "6,0:N:FB",
- "5,0:N:FB",
- "4,0:N:FB",
+ "7,0:N:FW",
+ "6,0:N:FW",
+ "5,0:N:FW",
+ "4,0:N:FW",
// left front cluster
"2,0:N:F",
@@ -134,8 +135,8 @@ TEST(LedStripTest, parseLedStripConfig)
"1,10:W:F",
"0,11:W:IA",
"0,11:S:IA",
- "1,10:S:FB",
- "2,9:S:FB"
+ "1,10:S:FW",
+ "2,9:S:FW"
};
// and
memset(&systemLedConfigs, 0, sizeof(systemLedConfigs));
@@ -182,13 +183,13 @@ TEST(LedStripTest, smallestGridWithCenter)
// and
static const ledConfig_t testLedConfigs[] = {
{ CALCULATE_LED_XY( 2, 2), LED_DIRECTION_SOUTH | LED_DIRECTION_EAST | LED_FUNCTION_INDICATOR | LED_FUNCTION_ARM_STATE },
- { CALCULATE_LED_XY( 2, 1), LED_DIRECTION_EAST | LED_FUNCTION_FLIGHT_MODE | LED_FUNCTION_BATTERY },
+ { CALCULATE_LED_XY( 2, 1), LED_DIRECTION_EAST | LED_FUNCTION_FLIGHT_MODE | LED_FUNCTION_WARNING },
{ CALCULATE_LED_XY( 2, 0), LED_DIRECTION_NORTH | LED_DIRECTION_EAST | LED_FUNCTION_INDICATOR | LED_FUNCTION_ARM_STATE },
- { CALCULATE_LED_XY( 1, 0), LED_DIRECTION_NORTH | LED_FUNCTION_FLIGHT_MODE | LED_FUNCTION_BATTERY },
+ { CALCULATE_LED_XY( 1, 0), LED_DIRECTION_NORTH | LED_FUNCTION_FLIGHT_MODE | LED_FUNCTION_WARNING },
{ CALCULATE_LED_XY( 0, 0), LED_DIRECTION_NORTH | LED_DIRECTION_WEST | LED_FUNCTION_INDICATOR | LED_FUNCTION_ARM_STATE },
- { CALCULATE_LED_XY( 0, 1), LED_DIRECTION_WEST | LED_FUNCTION_FLIGHT_MODE | LED_FUNCTION_BATTERY },
+ { CALCULATE_LED_XY( 0, 1), LED_DIRECTION_WEST | LED_FUNCTION_FLIGHT_MODE | LED_FUNCTION_WARNING },
{ CALCULATE_LED_XY( 0, 2), LED_DIRECTION_SOUTH | LED_DIRECTION_WEST | LED_FUNCTION_INDICATOR | LED_FUNCTION_ARM_STATE },
- { CALCULATE_LED_XY( 1, 2), LED_DIRECTION_SOUTH | LED_FUNCTION_FLIGHT_MODE | LED_FUNCTION_BATTERY }
+ { CALCULATE_LED_XY( 1, 2), LED_DIRECTION_SOUTH | LED_FUNCTION_FLIGHT_MODE | LED_FUNCTION_WARNING }
};
memcpy(&systemLedConfigs, &testLedConfigs, sizeof(testLedConfigs));
@@ -250,9 +251,9 @@ TEST(LedStripTest, smallestGrid)
{ CALCULATE_LED_XY( 0, 11), LED_DIRECTION_WEST | LED_FUNCTION_FLIGHT_MODE },
{ CALCULATE_LED_XY( 0, 10), LED_DIRECTION_WEST | LED_FUNCTION_FLIGHT_MODE },
{ CALCULATE_LED_XY( 0, 9), LED_DIRECTION_WEST | LED_FUNCTION_FLIGHT_MODE },
- { CALCULATE_LED_XY( 0, 8), LED_DIRECTION_WEST | LED_FUNCTION_FLIGHT_MODE | LED_FUNCTION_BATTERY },
- { CALCULATE_LED_XY( 0, 7), LED_DIRECTION_WEST | LED_FUNCTION_FLIGHT_MODE | LED_FUNCTION_BATTERY },
- { CALCULATE_LED_XY( 0, 6), LED_DIRECTION_WEST | LED_FUNCTION_FLIGHT_MODE | LED_FUNCTION_BATTERY },
+ { CALCULATE_LED_XY( 0, 8), LED_DIRECTION_WEST | LED_FUNCTION_FLIGHT_MODE | LED_FUNCTION_WARNING },
+ { CALCULATE_LED_XY( 0, 7), LED_DIRECTION_WEST | LED_FUNCTION_FLIGHT_MODE | LED_FUNCTION_WARNING },
+ { CALCULATE_LED_XY( 0, 6), LED_DIRECTION_WEST | LED_FUNCTION_FLIGHT_MODE | LED_FUNCTION_WARNING },
{ CALCULATE_LED_XY( 0, 5), LED_DIRECTION_WEST | LED_FUNCTION_FLIGHT_MODE },
{ CALCULATE_LED_XY( 0, 4), LED_DIRECTION_WEST | LED_FUNCTION_FLIGHT_MODE },
{ CALCULATE_LED_XY( 0, 3), LED_DIRECTION_WEST | LED_FUNCTION_FLIGHT_MODE },
@@ -270,9 +271,9 @@ TEST(LedStripTest, smallestGrid)
{ CALCULATE_LED_XY( 4, 3), LED_DIRECTION_EAST | LED_FUNCTION_FLIGHT_MODE },
{ CALCULATE_LED_XY( 4, 4), LED_DIRECTION_EAST | LED_FUNCTION_FLIGHT_MODE },
{ CALCULATE_LED_XY( 4, 5), LED_DIRECTION_EAST | LED_FUNCTION_FLIGHT_MODE },
- { CALCULATE_LED_XY( 4, 6), LED_DIRECTION_EAST | LED_FUNCTION_FLIGHT_MODE | LED_FUNCTION_BATTERY },
- { CALCULATE_LED_XY( 4, 7), LED_DIRECTION_EAST | LED_FUNCTION_FLIGHT_MODE | LED_FUNCTION_BATTERY },
- { CALCULATE_LED_XY( 4, 8), LED_DIRECTION_EAST | LED_FUNCTION_FLIGHT_MODE | LED_FUNCTION_BATTERY },
+ { CALCULATE_LED_XY( 4, 6), LED_DIRECTION_EAST | LED_FUNCTION_FLIGHT_MODE | LED_FUNCTION_WARNING },
+ { CALCULATE_LED_XY( 4, 7), LED_DIRECTION_EAST | LED_FUNCTION_FLIGHT_MODE | LED_FUNCTION_WARNING },
+ { CALCULATE_LED_XY( 4, 8), LED_DIRECTION_EAST | LED_FUNCTION_FLIGHT_MODE | LED_FUNCTION_WARNING },
{ CALCULATE_LED_XY( 4, 9), LED_DIRECTION_EAST | LED_FUNCTION_FLIGHT_MODE },
{ CALCULATE_LED_XY( 4, 10), LED_DIRECTION_EAST | LED_FUNCTION_FLIGHT_MODE },
{ CALCULATE_LED_XY( 4, 11), LED_DIRECTION_EAST | LED_FUNCTION_FLIGHT_MODE },