Merge pull request #7303 from pkruger/4278-LED-profiles-switchable-via-OSD
Add LED strip profile feature
This commit is contained in:
commit
dfb438cc5b
103
docs/LedStrip.md
103
docs/LedStrip.md
|
@ -1,13 +1,20 @@
|
|||
# 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.
|
||||
Betaflight supports the use of addressable LED strips. Addressable LED strips allow each LED in the strip to be programmed with a unique and independent 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.
|
||||
## LED Strip Profiles
|
||||
|
||||
The LED strip feature supports 3 LED strip profiles, STATUS, RACE and BEACON. The selected profile can be changed from the CLI, OSD LED strip menu or from an adjustment channel, i.e. switch on your radio. Take note that the adjustment channel from your radio overrides all other LED strip profile selection options.
|
||||
|
||||
|
||||
### STATUS Profile
|
||||
|
||||
The STATUS profile is used to display all the information mentioned below, i.e. warning indications, larsen scanner etc.
|
||||
|
||||
Addressable LED strips can be used to show information from the flight controller system, the current implementation supports the following:
|
||||
|
||||
* Up to 32 LEDs. (Support for more than 32 LEDs is possible, it just requires additional development.)
|
||||
* Indicators showing pitch/roll stick positions.
|
||||
* Heading/Orientation lights.
|
||||
* Flight mode specific color schemes.
|
||||
|
@ -17,12 +24,58 @@ supports the following:
|
|||
* RSSI level.
|
||||
* Battery level.
|
||||
|
||||
Support for more than 32 LEDs is possible, it just requires additional development.
|
||||
|
||||
### RACE Profile
|
||||
|
||||
The RACE profile is used to set ALL strip LEDs to the selected color for racing, i.e. to identify quads based on LED color. The LED color is fixed and no other information is displayed.
|
||||
|
||||
|
||||
### BEACON Profile
|
||||
|
||||
The BEACON profile is used to find a lost quad, it flashes all LEDs white once per second. Again in this profile no other information is displayed on the LEDs.
|
||||
|
||||
|
||||
### LED Profile Configuration
|
||||
|
||||
###### OPTION 1: Configure an adjustment range to change the LED strip profile from your radio
|
||||
1. Turn on Expert mode - see top right of configurator screen "Enable Expert Mode".
|
||||
2. The LED strip profile selection is performed using an adjustment configured via the Adjustments tab.
|
||||
- Enable an adjustment. ("If enabled")
|
||||
- Select the AUX channel to be used to change the LED strip profile. ("when channel")
|
||||
- Set the range to cover the entire range of the selected AUX channel. ("is in ranges")
|
||||
- For the action select "RC Rate Adjustment". ("then apply") This will be configured in the CLI since LED strip profiles is not supported by Configurator 10.4.0 and earlier. "RC Rate Adjustment" is only selected to make the configuration in the CLI a little easier below.
|
||||
- Select slot 1. ("using slot") (the slot number does not matter, pick any free number)
|
||||
- Select the "via channel" to match the selected AUX channel of above. ("when channel").
|
||||
- Save
|
||||
3. Open the CLI and type ```adjrange``` followed by enter.
|
||||
4. Copy the adjrange configured in step 2. above and paste it in the command window. Change the '1' following the range of the channel to '30' and press enter. Type ```save``` and press enter. The configured adjrange will now be saved and the FC will reboot.
|
||||
5. Configure the AUX channel on your radio. When this channel is changed the selected LED strip profile will change between STATUS, RACE and BEACON, you should see the LED function change as you do this.
|
||||
|
||||
|
||||
###### OPTION 2: Use the CLI to select the LED strip profile (i.e. not selecting the LED strip profile with your radio)
|
||||
1. Open the CLI.
|
||||
2. Type ```get ledstrip_profile``` followed by enter to display the currently selected LED strip profile.
|
||||
3. Type ```set ledstrip_profile=x``` where x is the profile STATUS, RACE or BEACON and press enter.
|
||||
4. Type ```save``` followed by enter to save the selected LED strip profile.
|
||||
|
||||
|
||||
###### OPTION 3: By using the OSD
|
||||
1. Open the OSD menu by yawing left and pitching forward on your radio.
|
||||
2. Using the pitch stick, move down to the LED Strip menu and roll right to enter the menu.
|
||||
3. The profile and race color can be configured using the left stick to go back and the right stick to navigate up/down and to change the selected value.
|
||||
4. Use the left stick to go to the top level menu and select save & reboot to complete.
|
||||
|
||||
|
||||
###### RACE COLOR: The Race color can be configured using the CLI:
|
||||
1. Open the CLI.
|
||||
2. Type ```get ledstrip_race_color``` followed by enter to display the currently selected race color number.
|
||||
3. Type ```set ledstrip_race_color=x``` where x is the required color.
|
||||
4. Type ```save``` followed by enter to save the race color to be used.
|
||||
|
||||
|
||||
## Supported hardware
|
||||
|
||||
Only strips of 32 WS2811/WS2812 LEDs are supported currently. If the strip is longer than 32 LEDs it does not matter,
|
||||
but only the first 32 are used.
|
||||
Only strips of 32 WS2811/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.
|
||||
|
||||
|
@ -62,11 +115,7 @@ Then confirm the required setting by simply setting an LED to be green. If it li
|
|||
|
||||
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.
|
||||
|
||||
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 |
|
||||
| --------------------- | ---- | --------- | -------|
|
||||
|
@ -75,15 +124,9 @@ from another BEC. Just ensure that the GROUND is the same for all BEC outputs a
|
|||
| ChebuzzF3/F3Discovery | PB8 | Data In | PB8 |
|
||||
| Sparky | PWM5 | Data In | PA6 |
|
||||
|
||||
Since RC5 is also used for SoftSerial on the Naze 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.
|
||||
Since RC5 is also used for SoftSerial on the Naze 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.
|
||||
|
||||
If you have LEDs that are intermittent, flicker or show the wrong colors then drop the VIN to less than 4.7v, e.g. by using an inline
|
||||
diode on the VIN to the LED strip. The problem occurs because of the difference in voltage between the data signal and the power
|
||||
signal. The WS2811 LED's require the data signal (Din) to be between 0.3 * Vin (Max) and 0.7 * VIN (Min) to register valid logic
|
||||
low/high signals. The LED pin on the CPU will always be between 0v to ~3.3v, so the Vin should be 4.7v (3.3v / 0.7 = 4.71v).
|
||||
Some LEDs are more tolerant of this than others.
|
||||
If you have LEDs that are intermittent, flicker or show the wrong colors then drop the VIN to less than 4.7v, e.g. by using an inline diode on the VIN to the LED strip. The problem occurs because of the difference in voltage between the data signal and the power signal. The WS2811 LED's require the data signal (Din) to be between 0.3 * Vin (Max) and 0.7 * VIN (Min) to register valid logic low/high signals. The LED pin on the CPU will always be between 0v to ~3.3v, so the Vin should be 4.7v (3.3v / 0.7 = 4.71v). Some LEDs are more tolerant of this than others.
|
||||
|
||||
The datasheet can be found here: http://www.adafruit.com/datasheets/WS2812.pdf
|
||||
|
||||
|
@ -313,9 +356,7 @@ Note: Armed State cannot be used with Flight Mode.
|
|||
|
||||
#### Thrust state
|
||||
|
||||
This mode fades the LED current LED color to the previous/next color in the HSB color space depending on throttle stick position. When the
|
||||
throttle is in the middle position the color is unaffected, thus it can be mixed with orientation colors to indicate orientation and throttle at
|
||||
the same time. Thrust should normally be combined with Color or Mode/Orientation.
|
||||
This mode fades the LED current LED color to the previous/next color in the HSB color space depending on throttle stick position. When the throttle is in the middle position the color is unaffected, thus it can be mixed with orientation colors to indicate orientation and throttle at the same time. Thrust should normally be combined with Color or Mode/Orientation.
|
||||
|
||||
#### Thrust ring state
|
||||
|
||||
|
@ -452,8 +493,7 @@ Examples (using the default colors):
|
|||
|
||||
## 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.
|
||||
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.
|
||||
|
||||
|
@ -615,10 +655,7 @@ This configuration is specifically designed for the [Alien Spider AQ50D PRO 250m
|
|||
|
||||
## 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. Most 5050 LEDs will draw 0.3 Watts a piece.
|
||||
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.
|
||||
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. Most 5050 LEDs will draw 0.3 Watts a piece.
|
||||
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.
|
||||
|
||||
After a short delay the LEDs will show the unarmed color sequence and or low-battery warning sequence.
|
||||
|
||||
Also check that the feature `LED_STRIP` was correctly enabled and that it does not conflict with other features, as above.
|
||||
Also check that the feature `LED_STRIP` was correctly enabled and that it does not conflict with other features, as above.
|
||||
|
|
|
@ -39,32 +39,55 @@
|
|||
|
||||
#include "fc/config.h"
|
||||
|
||||
#include "io/ledstrip.h"
|
||||
|
||||
#include "interface/settings.h"
|
||||
|
||||
#ifdef USE_LED_STRIP
|
||||
|
||||
static bool featureRead = false;
|
||||
static uint8_t cmsx_FeatureLedstrip;
|
||||
static uint8_t cmsx_LedProfile;
|
||||
static uint8_t cmsx_RaceColor;
|
||||
const char * const ledProfileNames[LED_PROFILE_COUNT] = {
|
||||
"RACE",
|
||||
"BEACON",
|
||||
#ifdef USE_LED_STRIP_STATUS_MODE
|
||||
"STATUS"
|
||||
#endif
|
||||
};
|
||||
|
||||
static long cmsx_Ledstrip_FeatureRead(void)
|
||||
static long cmsx_Ledstrip_OnEnter(void)
|
||||
{
|
||||
if (!featureRead) {
|
||||
cmsx_FeatureLedstrip = featureIsEnabled(FEATURE_LED_STRIP) ? 1 : 0;
|
||||
featureRead = true;
|
||||
}
|
||||
|
||||
#ifdef USE_LED_STRIP
|
||||
cmsx_LedProfile = getLedProfile();
|
||||
cmsx_RaceColor = getLedRaceColor();
|
||||
#endif
|
||||
return 0;
|
||||
}
|
||||
|
||||
static long cmsx_Ledstrip_FeatureWriteback(const OSD_Entry *self)
|
||||
static long cmsx_Ledstrip_OnExit(const OSD_Entry *self)
|
||||
{
|
||||
UNUSED(self);
|
||||
if (featureRead) {
|
||||
if (cmsx_FeatureLedstrip)
|
||||
featureEnable(FEATURE_LED_STRIP);
|
||||
else
|
||||
else {
|
||||
ledStripDisable();
|
||||
featureDisable(FEATURE_LED_STRIP);
|
||||
}
|
||||
}
|
||||
|
||||
#ifdef USE_LED_STRIP
|
||||
setLedProfile(cmsx_LedProfile);
|
||||
setLedRaceColor(cmsx_RaceColor);
|
||||
#endif
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
@ -72,7 +95,8 @@ static OSD_Entry cmsx_menuLedstripEntries[] =
|
|||
{
|
||||
{ "-- LED STRIP --", OME_Label, NULL, NULL, 0 },
|
||||
{ "ENABLED", OME_Bool, NULL, &cmsx_FeatureLedstrip, 0 },
|
||||
|
||||
{ "PROFILE", OME_TAB, NULL, &(OSD_TAB_t){ &cmsx_LedProfile, LED_PROFILE_COUNT-1, ledProfileNames }, 0 },
|
||||
{ "RACE COLOR", OME_TAB, NULL, &(OSD_TAB_t){ &cmsx_RaceColor, COLOR_COUNT-1, lookupTableLEDRaceColors }, 0 },
|
||||
{ "BACK", OME_Back, NULL, NULL, 0 },
|
||||
{ NULL, OME_END, NULL, NULL, 0 }
|
||||
};
|
||||
|
@ -82,8 +106,8 @@ CMS_Menu cmsx_menuLedstrip = {
|
|||
.GUARD_text = "MENULED",
|
||||
.GUARD_type = OME_MENU,
|
||||
#endif
|
||||
.onEnter = cmsx_Ledstrip_FeatureRead,
|
||||
.onExit = cmsx_Ledstrip_FeatureWriteback,
|
||||
.onEnter = cmsx_Ledstrip_OnEnter,
|
||||
.onExit = cmsx_Ledstrip_OnExit,
|
||||
.entries = cmsx_menuLedstripEntries
|
||||
};
|
||||
#endif // LED_STRIP
|
||||
|
|
|
@ -42,6 +42,7 @@
|
|||
#include "flight/pid.h"
|
||||
|
||||
#include "io/beeper.h"
|
||||
#include "io/ledstrip.h"
|
||||
#include "io/motors.h"
|
||||
#include "io/pidaudio.h"
|
||||
#include "io/osd.h"
|
||||
|
@ -242,6 +243,10 @@ static const adjustmentConfig_t defaultAdjustmentConfigs[ADJUSTMENT_FUNCTION_COU
|
|||
.adjustmentFunction = ADJUSTMENT_OSD_PROFILE,
|
||||
.mode = ADJUSTMENT_MODE_SELECT,
|
||||
.data = { .switchPositions = 3 }
|
||||
}, {
|
||||
.adjustmentFunction = ADJUSTMENT_LED_PROFILE,
|
||||
.mode = ADJUSTMENT_MODE_SELECT,
|
||||
.data = { .switchPositions = 3 }
|
||||
}
|
||||
};
|
||||
|
||||
|
@ -665,11 +670,20 @@ static uint8_t applySelectAdjustment(adjustmentFunction_e adjustmentFunction, ui
|
|||
}
|
||||
#endif
|
||||
break;
|
||||
#ifdef USE_OSD_PROFILES
|
||||
case ADJUSTMENT_OSD_PROFILE:
|
||||
#ifdef USE_OSD_PROFILES
|
||||
if (getCurrentOsdProfileIndex() != (position + 1)) {
|
||||
changeOsdProfileIndex(position+1);
|
||||
}
|
||||
#endif
|
||||
break;
|
||||
case ADJUSTMENT_LED_PROFILE:
|
||||
#ifdef USE_LED_STRIP
|
||||
#ifndef UNIT_TEST
|
||||
if (getLedProfile() != position) {
|
||||
setLedProfile(position);
|
||||
}
|
||||
#endif
|
||||
#endif
|
||||
break;
|
||||
|
||||
|
@ -793,6 +807,9 @@ void processRcAdjustments(controlRateConfig_t *controlRateConfig)
|
|||
&& adjustmentState->config->adjustmentFunction != ADJUSTMENT_RATE_PROFILE // Rate profile already has an OSD element
|
||||
#ifdef USE_OSD_PROFILES
|
||||
&& adjustmentState->config->adjustmentFunction != ADJUSTMENT_OSD_PROFILE
|
||||
#endif
|
||||
#ifdef USE_LED_STRIP
|
||||
&& adjustmentState->config->adjustmentFunction != ADJUSTMENT_LED_PROFILE
|
||||
#endif
|
||||
) {
|
||||
adjustmentRangeNameIndex = adjustmentFunction;
|
||||
|
|
|
@ -59,6 +59,7 @@ typedef enum {
|
|||
ADJUSTMENT_ROLL_F,
|
||||
ADJUSTMENT_YAW_F,
|
||||
ADJUSTMENT_OSD_PROFILE,
|
||||
ADJUSTMENT_LED_PROFILE,
|
||||
ADJUSTMENT_FUNCTION_COUNT
|
||||
} adjustmentFunction_e;
|
||||
|
||||
|
|
|
@ -1579,7 +1579,7 @@ static void cliRxRange(char *cmdline)
|
|||
}
|
||||
}
|
||||
|
||||
#ifdef USE_LED_STRIP
|
||||
#ifdef USE_LED_STRIP_STATUS_MODE
|
||||
static void printLed(uint8_t dumpMask, const ledConfig_t *ledConfigs, const ledConfig_t *defaultLedConfigs)
|
||||
{
|
||||
const char *format = "led %u %s";
|
||||
|
@ -4657,7 +4657,7 @@ static void printConfig(char *cmdline, bool doDiff)
|
|||
cliPrintHashLine("serial");
|
||||
printSerial(dumpMask, &serialConfig_Copy, serialConfig());
|
||||
|
||||
#ifdef USE_LED_STRIP
|
||||
#ifdef USE_LED_STRIP_STATUS_MODE
|
||||
cliPrintHashLine("led");
|
||||
printLed(dumpMask, ledStripConfig_Copy.ledConfigs, ledStripConfig()->ledConfigs);
|
||||
|
||||
|
@ -4818,8 +4818,8 @@ const clicmd_t cmdTable[] = {
|
|||
#if defined(USE_BOARD_INFO)
|
||||
CLI_COMMAND_DEF("board_name", "get / set the name of the board model", "[board name]", cliBoardName),
|
||||
#endif
|
||||
#ifdef USE_LED_STRIP
|
||||
CLI_COMMAND_DEF("color", "configure colors", NULL, cliColor),
|
||||
#ifdef USE_LED_STRIP_STATUS_MODE
|
||||
CLI_COMMAND_DEF("color", "configure colors", NULL, cliColor),
|
||||
#endif
|
||||
CLI_COMMAND_DEF("defaults", "reset to defaults and reboot", "[nosave]", cliDefaults),
|
||||
CLI_COMMAND_DEF("diff", "list configuration changes from default", "[master|profile|rates|all] {defaults}", cliDiff),
|
||||
|
@ -4857,8 +4857,8 @@ const clicmd_t cmdTable[] = {
|
|||
CLI_COMMAND_DEF("gyroregisters", "dump gyro config registers contents", NULL, cliDumpGyroRegisters),
|
||||
#endif
|
||||
CLI_COMMAND_DEF("help", NULL, NULL, cliHelp),
|
||||
#ifdef USE_LED_STRIP
|
||||
CLI_COMMAND_DEF("led", "configure leds", NULL, cliLed),
|
||||
#ifdef USE_LED_STRIP_STATUS_MODE
|
||||
CLI_COMMAND_DEF("led", "configure leds", NULL, cliLed),
|
||||
#endif
|
||||
#if defined(USE_BOARD_INFO)
|
||||
CLI_COMMAND_DEF("manufacturer_id", "get / set the id of the board manufacturer", "[manufacturer id]", cliManufacturerId),
|
||||
|
@ -4869,7 +4869,7 @@ const clicmd_t cmdTable[] = {
|
|||
CLI_COMMAND_DEF("mixer", "configure mixer", "list\r\n\t<name>", cliMixer),
|
||||
#endif
|
||||
CLI_COMMAND_DEF("mmix", "custom motor mixer", NULL, cliMotorMix),
|
||||
#ifdef USE_LED_STRIP
|
||||
#ifdef USE_LED_STRIP_STATUS_MODE
|
||||
CLI_COMMAND_DEF("mode_color", "configure mode and special colors", NULL, cliModeColor),
|
||||
#endif
|
||||
CLI_COMMAND_DEF("motor", "get/set motor", "<index> [<value>]", cliMotor),
|
||||
|
|
|
@ -1185,7 +1185,7 @@ static bool mspProcessOutCommand(uint8_t cmdMSP, sbuf_t *dst)
|
|||
}
|
||||
break;
|
||||
|
||||
#ifdef USE_LED_STRIP
|
||||
#ifdef USE_LED_STRIP_STATUS_MODE
|
||||
case MSP_LED_COLORS:
|
||||
for (int i = 0; i < LED_CONFIGURABLE_COLOR_COUNT; i++) {
|
||||
const hsvColor_t *color = &ledStripConfig()->colors[i];
|
||||
|
@ -2259,7 +2259,7 @@ static mspResult_e mspProcessInCommand(uint8_t cmdMSP, sbuf_t *src)
|
|||
}
|
||||
break;
|
||||
|
||||
#ifdef USE_LED_STRIP
|
||||
#ifdef USE_LED_STRIP_STATUS_MODE
|
||||
case MSP_SET_LED_COLORS:
|
||||
for (int i = 0; i < LED_CONFIGURABLE_COLOR_COUNT; i++) {
|
||||
hsvColor_t *color = &ledStripConfigMutable()->colors[i];
|
||||
|
|
|
@ -341,7 +341,7 @@ static const char * const lookupOverclock[] = {
|
|||
};
|
||||
#endif
|
||||
|
||||
#ifdef USE_LED_STRIP
|
||||
#ifdef USE_LED_STRIP_STATUS_MODE
|
||||
static const char * const lookupLedStripFormatRGB[] = {
|
||||
"GRB", "RGB"
|
||||
};
|
||||
|
@ -424,6 +424,35 @@ static const char * const lookupTableTpaMode[] = {
|
|||
};
|
||||
#endif
|
||||
|
||||
#ifdef USE_LED_STRIP
|
||||
#ifdef USE_LED_STRIP_STATUS_MODE
|
||||
static const char * const lookupTableLEDProfile[] = {
|
||||
"RACE", "BEACON", "STATUS"
|
||||
};
|
||||
#else
|
||||
static const char * const lookupTableLEDProfile[] = {
|
||||
"RACE", "BEACON"
|
||||
};
|
||||
#endif
|
||||
#endif
|
||||
|
||||
const char * const lookupTableLEDRaceColors[COLOR_COUNT] = {
|
||||
"BLACK",
|
||||
"WHITE",
|
||||
"RED",
|
||||
"ORANGE",
|
||||
"YELLOW",
|
||||
"LIME_GREEN",
|
||||
"GREEN",
|
||||
"MINT_GREEN",
|
||||
"CYAN",
|
||||
"LIGHT_BLUE",
|
||||
"BLUE",
|
||||
"DARK_VIOLET",
|
||||
"MAGENTA",
|
||||
"DEEP_PINK"
|
||||
};
|
||||
|
||||
#define LOOKUP_TABLE_ENTRY(name) { name, ARRAYLEN(name) }
|
||||
|
||||
const lookupTableEntry_t lookupTables[] = {
|
||||
|
@ -493,7 +522,7 @@ const lookupTableEntry_t lookupTables[] = {
|
|||
#ifdef USE_OVERCLOCK
|
||||
LOOKUP_TABLE_ENTRY(lookupOverclock),
|
||||
#endif
|
||||
#ifdef USE_LED_STRIP
|
||||
#ifdef USE_LED_STRIP_STATUS_MODE
|
||||
LOOKUP_TABLE_ENTRY(lookupLedStripFormatRGB),
|
||||
#endif
|
||||
#ifdef USE_MULTI_GYRO
|
||||
|
@ -532,6 +561,10 @@ const lookupTableEntry_t lookupTables[] = {
|
|||
#ifdef USE_TPA_MODE
|
||||
LOOKUP_TABLE_ENTRY(lookupTableTpaMode),
|
||||
#endif
|
||||
#ifdef USE_LED_STRIP
|
||||
LOOKUP_TABLE_ENTRY(lookupTableLEDProfile),
|
||||
LOOKUP_TABLE_ENTRY(lookupTableLEDRaceColors),
|
||||
#endif
|
||||
};
|
||||
|
||||
#undef LOOKUP_TABLE_ENTRY
|
||||
|
@ -1037,6 +1070,8 @@ const clivalue_t valueTable[] = {
|
|||
#ifdef USE_LED_STRIP
|
||||
{ "ledstrip_visual_beeper", VAR_UINT8 | MASTER_VALUE | MODE_LOOKUP, .config.lookup = { TABLE_OFF_ON }, PG_LED_STRIP_CONFIG, offsetof(ledStripConfig_t, ledstrip_visual_beeper) },
|
||||
{ "ledstrip_grb_rgb", VAR_UINT8 | MASTER_VALUE | MODE_LOOKUP, .config.lookup = { TABLE_RGB_GRB }, PG_LED_STRIP_CONFIG, offsetof(ledStripConfig_t, ledstrip_grb_rgb) },
|
||||
{ "ledstrip_profile", VAR_UINT8 | MASTER_VALUE | MODE_LOOKUP, .config.lookup = { TABLE_LED_PROFILE }, PG_LED_STRIP_CONFIG, offsetof(ledStripConfig_t, ledstrip_profile) },
|
||||
{ "ledstrip_race_color", VAR_UINT8 | MASTER_VALUE | MODE_LOOKUP, .config.lookup = { TABLE_LED_RACE_COLOR }, PG_LED_STRIP_CONFIG, offsetof(ledStripConfig_t, ledRaceColor) },
|
||||
#endif
|
||||
|
||||
// PG_SDCARD_CONFIG
|
||||
|
|
|
@ -92,7 +92,7 @@ typedef enum {
|
|||
#ifdef USE_OVERCLOCK
|
||||
TABLE_OVERCLOCK,
|
||||
#endif
|
||||
#ifdef USE_LED_STRIP
|
||||
#ifdef USE_LED_STRIP_STATUS_MODE
|
||||
TABLE_RGB_GRB,
|
||||
#endif
|
||||
#ifdef USE_MULTI_GYRO
|
||||
|
@ -130,6 +130,10 @@ typedef enum {
|
|||
#endif
|
||||
#ifdef USE_TPA_MODE
|
||||
TABLE_TPA_MODE,
|
||||
#endif
|
||||
#ifdef USE_LED_STRIP
|
||||
TABLE_LED_PROFILE,
|
||||
TABLE_LED_RACE_COLOR,
|
||||
#endif
|
||||
LOOKUP_TABLE_COUNT
|
||||
} lookupTableIndex_e;
|
||||
|
@ -218,3 +222,5 @@ extern const char * const lookupTableMagHardware[];
|
|||
//extern const uint8_t lookupTableMagHardwareEntryCount;
|
||||
|
||||
extern const char * const lookupTableRangefinderHardware[];
|
||||
|
||||
extern const char * const lookupTableLEDRaceColors[];
|
||||
|
|
|
@ -44,6 +44,7 @@
|
|||
|
||||
#include "drivers/light_ws2811strip.h"
|
||||
#include "drivers/serial.h"
|
||||
#include "drivers/time.h"
|
||||
#include "drivers/vtx_common.h"
|
||||
|
||||
#include "fc/config.h"
|
||||
|
@ -83,35 +84,21 @@ const modeColorIndexes_t *modeColors;
|
|||
specialColorIndexes_t specialColors;
|
||||
|
||||
static bool ledStripInitialised = false;
|
||||
static bool ledStripEnabled = true;
|
||||
static volatile bool ledStripEnabled = true;
|
||||
|
||||
static void ledStripDisable(void);
|
||||
void ledStripDisable(void);
|
||||
|
||||
#define HZ_TO_US(hz) ((int32_t)((1000 * 1000) / (hz)))
|
||||
|
||||
#define MAX_TIMER_DELAY (5 * 1000 * 1000)
|
||||
|
||||
#define BEACON_FLASH_PERIOD_MS 1000 // 1000ms
|
||||
#define BEACON_FLASH_ON_TIME 100 // 100ms
|
||||
|
||||
#if LED_MAX_STRIP_LENGTH > WS2811_LED_STRIP_LENGTH
|
||||
# error "Led strip length must match driver"
|
||||
#endif
|
||||
|
||||
typedef enum {
|
||||
COLOR_BLACK = 0,
|
||||
COLOR_WHITE,
|
||||
COLOR_RED,
|
||||
COLOR_ORANGE,
|
||||
COLOR_YELLOW,
|
||||
COLOR_LIME_GREEN,
|
||||
COLOR_GREEN,
|
||||
COLOR_MINT_GREEN,
|
||||
COLOR_CYAN,
|
||||
COLOR_LIGHT_BLUE,
|
||||
COLOR_BLUE,
|
||||
COLOR_DARK_VIOLET,
|
||||
COLOR_MAGENTA,
|
||||
COLOR_DEEP_PINK
|
||||
} colorId_e;
|
||||
|
||||
const hsvColor_t hsv[] = {
|
||||
// H S V
|
||||
[COLOR_BLACK] = { 0, 0, 0},
|
||||
|
@ -175,7 +162,12 @@ void pgResetFn_ledStripConfig(ledStripConfig_t *ledStripConfig)
|
|||
memcpy_fn(&ledStripConfig->specialColors, &defaultSpecialColors, sizeof(defaultSpecialColors));
|
||||
ledStripConfig->ledstrip_visual_beeper = 0;
|
||||
ledStripConfig->ledstrip_aux_channel = THROTTLE;
|
||||
|
||||
#ifdef USE_LED_STRIP_STATUS_MODE
|
||||
ledStripConfig->ledstrip_profile = LED_PROFILE_STATUS;
|
||||
#else
|
||||
ledStripConfig->ledstrip_profile = LED_PROFILE_RACE;
|
||||
#endif
|
||||
ledStripConfig->ledRaceColor = COLOR_ORANGE;
|
||||
#ifndef UNIT_TEST
|
||||
ledStripConfig->ioTag = timerioTagGetByUsage(TIM_USE_LED, 0);
|
||||
#endif
|
||||
|
@ -183,8 +175,9 @@ void pgResetFn_ledStripConfig(ledStripConfig_t *ledStripConfig)
|
|||
|
||||
static int scaledThrottle;
|
||||
static int auxInput;
|
||||
|
||||
#ifdef USE_LED_STRIP_STATUS_MODE
|
||||
static void updateLedRingCounts(void);
|
||||
#endif
|
||||
|
||||
STATIC_UNIT_TESTED void updateDimensions(void)
|
||||
{
|
||||
|
@ -251,10 +244,13 @@ void reevaluateLedConfig(void)
|
|||
{
|
||||
updateLedCount();
|
||||
updateDimensions();
|
||||
#ifdef USE_LED_STRIP_STATUS_MODE
|
||||
updateLedRingCounts();
|
||||
updateRequiredOverlay();
|
||||
#endif
|
||||
}
|
||||
|
||||
#ifdef USE_LED_STRIP_STATUS_MODE
|
||||
// get specialColor by index
|
||||
static const hsvColor_t* getSC(ledSpecialColorIds_e index)
|
||||
{
|
||||
|
@ -264,9 +260,10 @@ static const hsvColor_t* getSC(ledSpecialColorIds_e index)
|
|||
static const char directionCodes[LED_DIRECTION_COUNT] = { 'N', 'E', 'S', 'W', 'U', 'D' };
|
||||
static const char baseFunctionCodes[LED_BASEFUNCTION_COUNT] = { 'C', 'F', 'A', 'L', 'S', 'G', 'R' };
|
||||
static const char overlayCodes[LED_OVERLAY_COUNT] = { 'T', 'O', 'B', 'V', 'I', 'W' };
|
||||
#endif
|
||||
|
||||
#define CHUNK_BUFFER_SIZE 11
|
||||
|
||||
#ifdef USE_LED_STRIP_STATUS_MODE
|
||||
bool parseLedStripConfig(int ledIndex, const char *config)
|
||||
{
|
||||
if (ledIndex >= LED_MAX_STRIP_LENGTH)
|
||||
|
@ -781,11 +778,12 @@ static void applyLedGpsLayer(bool updateNow, timeUs_t *timer)
|
|||
|
||||
applyLedHsv(LED_MOV_FUNCTION(LED_FUNCTION_GPS), gpsColor);
|
||||
}
|
||||
|
||||
#endif
|
||||
#endif
|
||||
|
||||
#define INDICATOR_DEADBAND 25
|
||||
|
||||
#ifdef USE_LED_STRIP_STATUS_MODE
|
||||
static void applyLedIndicatorLayer(bool updateNow, timeUs_t *timer)
|
||||
{
|
||||
static bool flash = 0;
|
||||
|
@ -992,6 +990,7 @@ static uint16_t disabledTimerMask;
|
|||
|
||||
STATIC_ASSERT(timTimerCount <= sizeof(disabledTimerMask) * 8, disabledTimerMask_too_small);
|
||||
|
||||
#ifdef USE_LED_STRIP_STATUS_MODE
|
||||
// function to apply layer.
|
||||
// function must replan self using timer pointer
|
||||
// when updateNow is true (timer triggered), state must be updated first,
|
||||
|
@ -1014,6 +1013,7 @@ static applyLayerFn_timed* layerTable[] = {
|
|||
[timIndicator] = &applyLedIndicatorLayer,
|
||||
[timRing] = &applyLedThrustRingLayer
|
||||
};
|
||||
#endif
|
||||
|
||||
bool isOverlayTypeUsed(ledOverlayId_e overlayType)
|
||||
{
|
||||
|
@ -1038,23 +1038,9 @@ void updateRequiredOverlay(void)
|
|||
disabledTimerMask |= !isOverlayTypeUsed(LED_OVERLAY_INDICATOR) << timIndicator;
|
||||
}
|
||||
|
||||
void ledStripUpdate(timeUs_t currentTimeUs)
|
||||
{
|
||||
if (!(ledStripInitialised && isWS2811LedStripReady())) {
|
||||
return;
|
||||
}
|
||||
|
||||
if (IS_RC_MODE_ACTIVE(BOXLEDLOW) && !(ledStripConfig()->ledstrip_visual_beeper && isBeeperOn())) {
|
||||
if (ledStripEnabled) {
|
||||
ledStripDisable();
|
||||
ledStripEnabled = false;
|
||||
}
|
||||
return;
|
||||
}
|
||||
ledStripEnabled = true;
|
||||
|
||||
const uint32_t now = currentTimeUs;
|
||||
static void applyStatusProfile(uint32_t now) {
|
||||
|
||||
// apply all layers; triggered timed functions has to update timers
|
||||
// test all led timers, setting corresponding bits
|
||||
uint32_t timActive = 0;
|
||||
for (timId_e timId = 0; timId < timTimerCount; timId++) {
|
||||
|
@ -1074,19 +1060,67 @@ void ledStripUpdate(timeUs_t currentTimeUs)
|
|||
if (!timActive)
|
||||
return; // no change this update, keep old state
|
||||
|
||||
// apply all layers; triggered timed functions has to update timers
|
||||
|
||||
scaledThrottle = ARMING_FLAG(ARMED) ? scaleRange(rcData[THROTTLE], PWM_RANGE_MIN, PWM_RANGE_MAX, 0, 100) : 0;
|
||||
auxInput = rcData[ledStripConfig()->ledstrip_aux_channel];
|
||||
|
||||
applyLedFixedLayers();
|
||||
|
||||
for (timId_e timId = 0; timId < ARRAYLEN(layerTable); timId++) {
|
||||
uint32_t *timer = &timerVal[timId];
|
||||
bool updateNow = timActive & (1 << timId);
|
||||
(*layerTable[timId])(updateNow, timer);
|
||||
}
|
||||
ws2811UpdateStrip((ledStripFormatRGB_e)ledStripConfig()->ledstrip_grb_rgb);
|
||||
}
|
||||
#endif
|
||||
|
||||
static void applyBeaconProfile(void) {
|
||||
|
||||
bool ledsBlink = millis() % (BEACON_FLASH_PERIOD_MS) < BEACON_FLASH_ON_TIME;
|
||||
if (ledsBlink) {
|
||||
setStripColor(&HSV(WHITE));
|
||||
} else {
|
||||
setStripColor(&HSV(BLACK));
|
||||
}
|
||||
}
|
||||
|
||||
void ledStripUpdate(timeUs_t currentTimeUs)
|
||||
{
|
||||
#ifndef USE_LED_STRIP_STATUS_MODE
|
||||
UNUSED(currentTimeUs);
|
||||
#endif
|
||||
|
||||
if (!(ledStripInitialised && isWS2811LedStripReady())) {
|
||||
return;
|
||||
}
|
||||
|
||||
if (((true == ledStripEnabled)
|
||||
|| (ledStripConfig()->ledstrip_visual_beeper && isBeeperOn()))
|
||||
&& !IS_RC_MODE_ACTIVE(BOXLEDLOW)) {
|
||||
|
||||
scaledThrottle = ARMING_FLAG(ARMED) ? scaleRange(rcData[THROTTLE], PWM_RANGE_MIN, PWM_RANGE_MAX, 0, 100) : 0;
|
||||
auxInput = rcData[ledStripConfig()->ledstrip_aux_channel];
|
||||
|
||||
switch (ledStripConfig()->ledstrip_profile) {
|
||||
#ifdef USE_LED_STRIP_STATUS_MODE
|
||||
case LED_PROFILE_STATUS: {
|
||||
applyStatusProfile(currentTimeUs);
|
||||
break;
|
||||
}
|
||||
#endif
|
||||
case LED_PROFILE_RACE: {
|
||||
setStripColor(&hsv[ledStripConfig()->ledRaceColor]);
|
||||
break;
|
||||
}
|
||||
case LED_PROFILE_BEACON: {
|
||||
applyBeaconProfile();
|
||||
break;
|
||||
}
|
||||
default:
|
||||
break;
|
||||
}
|
||||
ws2811UpdateStrip((ledStripFormatRGB_e) ledStripConfig()->ledstrip_grb_rgb);
|
||||
}
|
||||
else
|
||||
{
|
||||
setStripColor(&HSV(BLACK));
|
||||
ws2811UpdateStrip((ledStripFormatRGB_e)ledStripConfig()->ledstrip_grb_rgb);
|
||||
}
|
||||
}
|
||||
|
||||
bool parseColor(int index, const char *colorConfig)
|
||||
|
@ -1135,6 +1169,7 @@ bool parseColor(int index, const char *colorConfig)
|
|||
return result;
|
||||
}
|
||||
|
||||
#ifdef USE_LED_STRIP_STATUS_MODE
|
||||
/*
|
||||
* Redefine a color in a mode.
|
||||
* */
|
||||
|
@ -1160,6 +1195,7 @@ bool setModeColor(ledModeIndex_e modeIndex, int modeColorIndex, int colorIndex)
|
|||
}
|
||||
return true;
|
||||
}
|
||||
#endif
|
||||
|
||||
void ledStripInit(void)
|
||||
{
|
||||
|
@ -1175,12 +1211,39 @@ void ledStripEnable(void)
|
|||
ledStripInitialised = true;
|
||||
|
||||
ws2811LedStripInit(ledStripConfig()->ioTag);
|
||||
ledStripEnabled = true;
|
||||
}
|
||||
|
||||
static void ledStripDisable(void)
|
||||
void ledStripDisable(void)
|
||||
{
|
||||
ledStripEnabled = false;
|
||||
setStripColor(&HSV(BLACK));
|
||||
|
||||
ws2811UpdateStrip((ledStripFormatRGB_e)ledStripConfig()->ledstrip_grb_rgb);
|
||||
}
|
||||
|
||||
|
||||
uint8_t getLedProfile(void)
|
||||
{
|
||||
return ledStripConfig()->ledstrip_profile;
|
||||
}
|
||||
|
||||
void setLedProfile(uint8_t profile)
|
||||
{
|
||||
if (profile < LED_PROFILE_COUNT) {
|
||||
ledStripConfigMutable()->ledstrip_profile = profile;
|
||||
}
|
||||
}
|
||||
|
||||
uint8_t getLedRaceColor(void)
|
||||
{
|
||||
return ledStripConfig()->ledRaceColor;
|
||||
}
|
||||
|
||||
void setLedRaceColor(uint8_t color)
|
||||
{
|
||||
if (color <= COLOR_DEEP_PINK) {
|
||||
ledStripConfigMutable()->ledRaceColor = color;
|
||||
}
|
||||
}
|
||||
#endif
|
||||
|
|
|
@ -77,6 +77,24 @@
|
|||
#define LED_XY_MASK 0x0F
|
||||
#define CALCULATE_LED_XY(x, y) ((((x) & LED_XY_MASK) << LED_X_BIT_OFFSET) | (((y) & LED_XY_MASK) << LED_Y_BIT_OFFSET))
|
||||
|
||||
typedef enum {
|
||||
COLOR_BLACK = 0,
|
||||
COLOR_WHITE,
|
||||
COLOR_RED,
|
||||
COLOR_ORANGE,
|
||||
COLOR_YELLOW,
|
||||
COLOR_LIME_GREEN,
|
||||
COLOR_GREEN,
|
||||
COLOR_MINT_GREEN,
|
||||
COLOR_CYAN,
|
||||
COLOR_LIGHT_BLUE,
|
||||
COLOR_BLUE,
|
||||
COLOR_DARK_VIOLET,
|
||||
COLOR_MAGENTA,
|
||||
COLOR_DEEP_PINK,
|
||||
COLOR_COUNT
|
||||
} colorId_e;
|
||||
|
||||
typedef enum {
|
||||
LED_MODE_ORIENTATION = 0,
|
||||
LED_MODE_HEADFREE,
|
||||
|
@ -127,6 +145,15 @@ typedef enum {
|
|||
LED_OVERLAY_WARNING
|
||||
} ledOverlayId_e;
|
||||
|
||||
typedef enum {
|
||||
LED_PROFILE_RACE = 0,
|
||||
LED_PROFILE_BEACON,
|
||||
#ifdef USE_LED_STRIP_STATUS_MODE
|
||||
LED_PROFILE_STATUS,
|
||||
#endif
|
||||
LED_PROFILE_COUNT
|
||||
} ledProfile_e;
|
||||
|
||||
typedef struct modeColorIndexes_s {
|
||||
uint8_t color[LED_DIRECTION_COUNT];
|
||||
} modeColorIndexes_t;
|
||||
|
@ -153,6 +180,9 @@ typedef struct ledStripConfig_s {
|
|||
uint8_t ledstrip_aux_channel;
|
||||
ioTag_t ioTag;
|
||||
ledStripFormatRGB_e ledstrip_grb_rgb;
|
||||
ledProfile_e ledstrip_profile;
|
||||
colorId_e ledRaceColor;
|
||||
|
||||
} ledStripConfig_t;
|
||||
|
||||
PG_DECLARE(ledStripConfig_t, ledStripConfig);
|
||||
|
@ -186,6 +216,7 @@ void reevaluateLedConfig(void);
|
|||
|
||||
void ledStripInit(void);
|
||||
void ledStripEnable(void);
|
||||
void ledStripDisable(void);
|
||||
void ledStripUpdate(timeUs_t currentTimeUs);
|
||||
|
||||
bool setModeColor(ledModeIndex_e modeIndex, int modeColorIndex, int colorIndex);
|
||||
|
@ -196,3 +227,8 @@ void applyDefaultModeColors(modeColorIndexes_t *modeColors);
|
|||
void applyDefaultSpecialColors(specialColorIndexes_t *specialColors);
|
||||
|
||||
void updateRequiredOverlay(void);
|
||||
|
||||
uint8_t getLedProfile(void);
|
||||
void setLedProfile(uint8_t profile);
|
||||
uint8_t getLedRaceColor(void);
|
||||
void setLedRaceColor(uint8_t color);
|
||||
|
|
|
@ -238,6 +238,10 @@
|
|||
#define USE_SERIAL_4WAY_BLHELI_BOOTLOADER
|
||||
#endif
|
||||
|
||||
#if !defined(USE_LED_STRIP)
|
||||
#undef USE_LED_STRIP_STATUS_MODE
|
||||
#endif
|
||||
|
||||
#if defined(SIMULATOR_BUILD) || defined(UNIT_TEST)
|
||||
// This feature uses 'arm_math.h', which does not exist for x86.
|
||||
#undef USE_GYRO_DATA_ANALYSE
|
||||
|
|
|
@ -270,6 +270,7 @@
|
|||
#define USE_ABSOLUTE_CONTROL
|
||||
#define USE_HOTT_TEXTMODE
|
||||
#define USE_LED_STRIP
|
||||
#define USE_LED_STRIP_STATUS_MODE
|
||||
#define USE_VARIO
|
||||
#define USE_RX_LINK_QUALITY_INFO
|
||||
#define USE_ESC_SENSOR_TELEMETRY
|
||||
|
|
|
@ -1,4 +1,5 @@
|
|||
# A sample Makefile for building Google Test and using it in user
|
||||
# A sample Makefile for building Google Test and using it in user
|
||||
# tests. Please tweak it to suit your environment and project. You
|
||||
# may want to move it to your project's root directory.
|
||||
#
|
||||
|
@ -156,7 +157,10 @@ ledstrip_unittest_SRC := \
|
|||
$(USER_DIR)/fc/rc_modes.c \
|
||||
$(USER_DIR)/io/ledstrip.c
|
||||
|
||||
|
||||
ledstrip_unittest_DEFINES := \
|
||||
USE_LED_STRIP=
|
||||
|
||||
|
||||
maths_unittest_SRC := \
|
||||
$(USER_DIR)/common/maths.c
|
||||
|
||||
|
@ -187,7 +191,7 @@ rc_controls_unittest_SRC := \
|
|||
$(USER_DIR)/common/bitarray.c \
|
||||
$(USER_DIR)/common/maths.c \
|
||||
$(USER_DIR)/fc/rc_adjustments.c \
|
||||
$(USER_DIR)/fc/rc_modes.c \
|
||||
$(USER_DIR)/fc/rc_modes.c
|
||||
|
||||
|
||||
rx_crsf_unittest_SRC := \
|
||||
|
|
|
@ -351,6 +351,9 @@ void delay(uint32_t ms)
|
|||
}
|
||||
|
||||
uint32_t micros(void) { return 0; }
|
||||
|
||||
uint32_t millis(void) { return 0; }
|
||||
|
||||
bool shouldSoundBatteryAlarm(void) { return false; }
|
||||
bool featureIsEnabled(uint32_t mask) {
|
||||
UNUSED(mask);
|
||||
|
|
|
@ -49,6 +49,7 @@
|
|||
#define USE_TELEMETRY_MAVLINK
|
||||
#define USE_TELEMETRY_SMARTPORT
|
||||
#define USE_LED_STRIP
|
||||
#define USE_LED_STRIP_STATUS_MODE
|
||||
#define USE_SERVOS
|
||||
#define USE_TRANSPONDER
|
||||
#define USE_VCP
|
||||
|
|
Loading…
Reference in New Issue