mirror of
https://github.com/betaflight/betaflight.git
synced 2025-07-24 00:35:39 +03:00
Update LED strip code to allow configurable LED strips.
See documentation for details.
This commit is contained in:
parent
3ef769bf7b
commit
6ce5736990
17 changed files with 983 additions and 236 deletions
|
@ -18,14 +18,23 @@
|
|||
#include <stdbool.h>
|
||||
#include <stdlib.h>
|
||||
#include <stdint.h>
|
||||
#include <string.h>
|
||||
#include <stdarg.h>
|
||||
|
||||
#include <platform.h>
|
||||
|
||||
#include <build_config.h>
|
||||
|
||||
#ifdef LED_STRIP
|
||||
#include <common/maths.h>
|
||||
|
||||
#include "drivers/light_ws2811strip.h"
|
||||
#include "drivers/system.h"
|
||||
#include "drivers/serial.h"
|
||||
|
||||
#include <common/maths.h>
|
||||
#include <common/printf.h>
|
||||
#include <common/typeconversion.h>
|
||||
|
||||
|
||||
#include "sensors/battery.h"
|
||||
|
||||
|
@ -36,142 +45,99 @@
|
|||
|
||||
#include "io/ledstrip.h"
|
||||
|
||||
#define LED_WHITE {255, 255, 255}
|
||||
#define LED_BLACK {0, 0, 0 }
|
||||
#define LED_RED {255, 0, 0 }
|
||||
#define LED_GREEN {0, 255, 0 }
|
||||
#define LED_BLUE {0, 0, 255}
|
||||
#define LED_CYAN {0, 255, 255}
|
||||
#define LED_YELLOW {255, 255, 0 }
|
||||
#define LED_ORANGE {255, 128, 0 }
|
||||
#define LED_PINK {255, 0, 128}
|
||||
#define LED_PURPLE {192, 64, 255}
|
||||
#if MAX_LED_STRIP_LENGTH > WS2811_LED_STRIP_LENGTH
|
||||
#error "Led strip length must match driver"
|
||||
#endif
|
||||
|
||||
//#define USE_LED_ANIMATION
|
||||
|
||||
#define LED_WHITE {255, 255, 255}
|
||||
#define LED_BLACK {0, 0, 0 }
|
||||
|
||||
#define LED_RED {255, 0, 0 }
|
||||
#define LED_ORANGE {255, 128, 0 }
|
||||
#define LED_YELLOW {255, 255, 0 }
|
||||
#define LED_LIME_GREEN {128, 255, 0 }
|
||||
#define LED_CYAN {0, 255, 255}
|
||||
#define LED_GREEN {0, 255, 0 }
|
||||
#define LED_LIGHT_BLUE {0, 128, 255}
|
||||
#define LED_BLUE {0, 0, 255}
|
||||
#define LED_DARK_MAGENTA {128, 0, 128}
|
||||
#define LED_PINK {255, 0, 255}
|
||||
#define LED_DARK_VIOLET {128, 0, 255}
|
||||
#define LED_DEEP_PINK {255, 0, 128}
|
||||
|
||||
const rgbColor24bpp_t black = { LED_BLACK };
|
||||
const rgbColor24bpp_t white = { LED_WHITE };
|
||||
|
||||
const rgbColor24bpp_t red = { LED_RED };
|
||||
const rgbColor24bpp_t orange = { LED_ORANGE };
|
||||
const rgbColor24bpp_t white = { LED_WHITE };
|
||||
const rgbColor24bpp_t green = { LED_GREEN };
|
||||
const rgbColor24bpp_t blue = { LED_BLUE };
|
||||
|
||||
|
||||
uint8_t ledGridWidth;
|
||||
uint8_t ledGridHeight;
|
||||
uint8_t ledCount;
|
||||
|
||||
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, 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( 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, 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 },
|
||||
};
|
||||
|
||||
|
||||
/*
|
||||
* 0..5 - rear right cluster, 0..2 rear 3..5 right
|
||||
* 6..11 - front right cluster, 6..8 rear, 9..11 front
|
||||
* 12..15 - front center cluster
|
||||
* 16..21 - front left cluster, 16..18 front, 19..21 rear
|
||||
* 22..27 - rear left cluster, 22..24 left, 25..27 rear
|
||||
* 6 coords @nn,nn
|
||||
* 4 direction @##
|
||||
* 6 modes @####
|
||||
* = 16 bytes per led
|
||||
* 16 * 32 leds = 512 bytes storage needed worst case.
|
||||
* = not efficient to store led configs as strings in flash.
|
||||
* = becomes a problem to send all the data via cli due to serial/cli buffers
|
||||
*/
|
||||
|
||||
typedef enum {
|
||||
LED_DISABLED = 0,
|
||||
LED_DIRECTION_NORTH = (1 << 0),
|
||||
LED_DIRECTION_EAST = (1 << 1),
|
||||
LED_DIRECTION_SOUTH = (1 << 2),
|
||||
LED_DIRECTION_WEST = (1 << 3),
|
||||
LED_DIRECTION_UP = (1 << 4),
|
||||
LED_DIRECTION_DOWN = (1 << 5),
|
||||
LED_FUNCTION_INDICATOR = (1 << 6),
|
||||
LED_FUNCTION_BATTERY = (1 << 7),
|
||||
LED_FUNCTION_MODE = (1 << 8),
|
||||
LED_FUNCTION_ARM_STATE = (1 << 9)
|
||||
} ledFlag_e;
|
||||
X_COORDINATE,
|
||||
Y_COORDINATE,
|
||||
DIRECTIONS,
|
||||
FUNCTIONS
|
||||
} parseState_e;
|
||||
|
||||
#define LED_X_BIT_OFFSET 4
|
||||
#define LED_Y_BIT_OFFSET 0
|
||||
#define PARSE_STATE_COUNT 4
|
||||
|
||||
#define LED_XY_MASK (0x0F)
|
||||
static const char chunkSeparators[PARSE_STATE_COUNT] = {',', ':', ':', '\0' };
|
||||
|
||||
#define LED_X(ledConfig) ((ledConfig->xy >> LED_X_BIT_OFFSET) & LED_XY_MASK)
|
||||
#define LED_Y(ledConfig) ((ledConfig->xy >> LED_Y_BIT_OFFSET) & LED_XY_MASK)
|
||||
|
||||
#define LED_XY(x,y) (((x & LED_XY_MASK) << LED_X_BIT_OFFSET) | ((y & LED_XY_MASK) << LED_Y_BIT_OFFSET))
|
||||
|
||||
typedef struct ledConfig_s {
|
||||
uint8_t xy; // see LED_X/Y_MASK defines
|
||||
uint16_t flags; // see ledFlag_e
|
||||
} ledConfig_t;
|
||||
|
||||
static uint8_t ledGridWidth;
|
||||
static uint8_t ledGridHeight;
|
||||
|
||||
#ifdef USE_ALTERNATE_LED_LAYOUT
|
||||
static const ledConfig_t ledConfigs[WS2811_LED_STRIP_LENGTH] = {
|
||||
{ LED_XY( 1, 14), LED_DIRECTION_SOUTH | LED_FUNCTION_MODE | LED_FUNCTION_INDICATOR | LED_FUNCTION_ARM_STATE },
|
||||
|
||||
{ LED_XY( 0, 13), LED_DIRECTION_WEST | LED_FUNCTION_INDICATOR | LED_FUNCTION_ARM_STATE },
|
||||
{ LED_XY( 0, 12), LED_DIRECTION_WEST | LED_FUNCTION_INDICATOR | LED_FUNCTION_ARM_STATE },
|
||||
|
||||
{ LED_XY( 0, 11), LED_DIRECTION_WEST | LED_FUNCTION_MODE },
|
||||
{ LED_XY( 0, 10), LED_DIRECTION_WEST | LED_FUNCTION_MODE },
|
||||
{ LED_XY( 0, 9), LED_DIRECTION_WEST | LED_FUNCTION_MODE },
|
||||
{ LED_XY( 0, 8), LED_DIRECTION_WEST | LED_FUNCTION_MODE | LED_FUNCTION_BATTERY },
|
||||
{ LED_XY( 0, 7), LED_DIRECTION_WEST | LED_FUNCTION_MODE | LED_FUNCTION_BATTERY },
|
||||
{ LED_XY( 0, 6), LED_DIRECTION_WEST | LED_FUNCTION_MODE | LED_FUNCTION_BATTERY },
|
||||
{ LED_XY( 0, 5), LED_DIRECTION_WEST | LED_FUNCTION_MODE },
|
||||
{ LED_XY( 0, 4), LED_DIRECTION_WEST | LED_FUNCTION_MODE },
|
||||
{ LED_XY( 0, 3), LED_DIRECTION_WEST | LED_FUNCTION_MODE },
|
||||
|
||||
{ LED_XY( 0, 2), LED_DIRECTION_WEST | LED_FUNCTION_INDICATOR | LED_FUNCTION_ARM_STATE },
|
||||
{ LED_XY( 0, 1), LED_DIRECTION_WEST | LED_FUNCTION_INDICATOR | LED_FUNCTION_ARM_STATE },
|
||||
|
||||
{ LED_XY( 1, 0), LED_DIRECTION_NORTH | LED_FUNCTION_MODE | LED_FUNCTION_INDICATOR | LED_FUNCTION_ARM_STATE },
|
||||
{ LED_XY( 2, 0), LED_DIRECTION_NORTH | LED_FUNCTION_MODE | LED_FUNCTION_ARM_STATE },
|
||||
{ LED_XY( 3, 0), LED_DIRECTION_NORTH | LED_FUNCTION_MODE | LED_FUNCTION_INDICATOR | LED_FUNCTION_ARM_STATE },
|
||||
|
||||
{ LED_XY( 4, 1), LED_DIRECTION_EAST | LED_FUNCTION_INDICATOR | LED_FUNCTION_ARM_STATE },
|
||||
{ LED_XY( 4, 2), LED_DIRECTION_EAST | LED_FUNCTION_INDICATOR | LED_FUNCTION_ARM_STATE },
|
||||
|
||||
{ LED_XY( 4, 3), LED_DIRECTION_EAST | LED_FUNCTION_MODE },
|
||||
{ LED_XY( 4, 4), LED_DIRECTION_EAST | LED_FUNCTION_MODE },
|
||||
{ LED_XY( 4, 5), LED_DIRECTION_EAST | LED_FUNCTION_MODE },
|
||||
{ LED_XY( 4, 6), LED_DIRECTION_EAST | LED_FUNCTION_MODE | LED_FUNCTION_BATTERY },
|
||||
{ LED_XY( 4, 7), LED_DIRECTION_EAST | LED_FUNCTION_MODE | LED_FUNCTION_BATTERY },
|
||||
{ LED_XY( 4, 8), LED_DIRECTION_EAST | LED_FUNCTION_MODE | LED_FUNCTION_BATTERY },
|
||||
{ LED_XY( 4, 9), LED_DIRECTION_EAST | LED_FUNCTION_MODE },
|
||||
{ LED_XY( 4, 10), LED_DIRECTION_EAST | LED_FUNCTION_MODE },
|
||||
{ LED_XY( 4, 11), LED_DIRECTION_EAST | LED_FUNCTION_MODE },
|
||||
|
||||
{ LED_XY( 4, 12), LED_DIRECTION_EAST | LED_FUNCTION_INDICATOR | LED_FUNCTION_ARM_STATE },
|
||||
{ LED_XY( 4, 13), LED_DIRECTION_EAST | LED_FUNCTION_INDICATOR | LED_FUNCTION_ARM_STATE },
|
||||
|
||||
{ LED_XY( 3, 14), LED_DIRECTION_SOUTH | LED_FUNCTION_MODE | LED_FUNCTION_INDICATOR | LED_FUNCTION_ARM_STATE },
|
||||
static const char directionCodes[] = { 'N', 'E', 'S', 'W', 'U', 'D' };
|
||||
#define DIRECTION_COUNT (sizeof(directionCodes) / sizeof(directionCodes[0]))
|
||||
static const uint8_t directionMappings[DIRECTION_COUNT] = {
|
||||
LED_DIRECTION_NORTH,
|
||||
LED_DIRECTION_EAST,
|
||||
LED_DIRECTION_SOUTH,
|
||||
LED_DIRECTION_WEST,
|
||||
LED_DIRECTION_UP,
|
||||
LED_DIRECTION_DOWN
|
||||
};
|
||||
#else
|
||||
static const ledConfig_t ledConfigs[WS2811_LED_STRIP_LENGTH] = {
|
||||
{ LED_XY( 9, 9), LED_DIRECTION_SOUTH | LED_FUNCTION_MODE | LED_FUNCTION_BATTERY },
|
||||
{ LED_XY(10, 10), LED_DIRECTION_SOUTH | LED_FUNCTION_MODE | LED_FUNCTION_BATTERY },
|
||||
{ LED_XY(11, 11), LED_DIRECTION_SOUTH | LED_FUNCTION_INDICATOR | LED_FUNCTION_ARM_STATE },
|
||||
{ LED_XY(11, 11), LED_DIRECTION_EAST | LED_FUNCTION_INDICATOR | LED_FUNCTION_ARM_STATE },
|
||||
{ LED_XY(10, 10), LED_DIRECTION_EAST | LED_FUNCTION_MODE },
|
||||
{ LED_XY( 9, 9), LED_DIRECTION_EAST | LED_FUNCTION_MODE },
|
||||
|
||||
{ LED_XY(10, 5), LED_DIRECTION_SOUTH | LED_FUNCTION_MODE },
|
||||
{ LED_XY(11, 4), LED_DIRECTION_SOUTH | LED_FUNCTION_MODE },
|
||||
{ LED_XY(12, 3), LED_DIRECTION_SOUTH | LED_FUNCTION_INDICATOR | LED_FUNCTION_ARM_STATE },
|
||||
{ LED_XY(12, 2), LED_DIRECTION_NORTH | LED_FUNCTION_INDICATOR | LED_FUNCTION_ARM_STATE },
|
||||
{ LED_XY(11, 1), LED_DIRECTION_NORTH | LED_FUNCTION_MODE },
|
||||
{ LED_XY(10, 0), LED_DIRECTION_NORTH | LED_FUNCTION_MODE },
|
||||
|
||||
{ LED_XY( 7, 0), LED_DIRECTION_NORTH | LED_FUNCTION_MODE | LED_FUNCTION_BATTERY },
|
||||
{ LED_XY( 6, 0), LED_DIRECTION_NORTH | LED_FUNCTION_MODE | LED_FUNCTION_BATTERY },
|
||||
{ LED_XY( 5, 0), LED_DIRECTION_NORTH | LED_FUNCTION_MODE | LED_FUNCTION_BATTERY },
|
||||
{ LED_XY( 4, 0), LED_DIRECTION_NORTH | LED_FUNCTION_MODE | LED_FUNCTION_BATTERY },
|
||||
|
||||
{ LED_XY( 2, 0), LED_DIRECTION_NORTH | LED_FUNCTION_MODE },
|
||||
{ LED_XY( 1, 1), LED_DIRECTION_NORTH | LED_FUNCTION_MODE },
|
||||
{ LED_XY( 0, 2), LED_DIRECTION_NORTH | LED_FUNCTION_INDICATOR | LED_FUNCTION_ARM_STATE },
|
||||
{ LED_XY( 0, 3), LED_DIRECTION_WEST | LED_FUNCTION_INDICATOR | LED_FUNCTION_ARM_STATE },
|
||||
{ LED_XY( 1, 4), LED_DIRECTION_WEST | LED_FUNCTION_MODE },
|
||||
{ LED_XY( 2, 5), LED_DIRECTION_WEST | LED_FUNCTION_MODE },
|
||||
|
||||
{ LED_XY( 2, 9), LED_DIRECTION_WEST | LED_FUNCTION_MODE },
|
||||
{ LED_XY( 1, 10), LED_DIRECTION_WEST | LED_FUNCTION_MODE },
|
||||
{ LED_XY( 0, 11), LED_DIRECTION_WEST | LED_FUNCTION_INDICATOR | LED_FUNCTION_ARM_STATE },
|
||||
{ LED_XY( 0, 11), LED_DIRECTION_SOUTH | LED_FUNCTION_INDICATOR | LED_FUNCTION_ARM_STATE },
|
||||
{ LED_XY( 1, 10), LED_DIRECTION_SOUTH | LED_FUNCTION_MODE | LED_FUNCTION_BATTERY },
|
||||
{ LED_XY( 2, 9), LED_DIRECTION_SOUTH | LED_FUNCTION_MODE | LED_FUNCTION_BATTERY }
|
||||
static const char functionCodes[] = { 'I', 'B', '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_FLIGHT_MODE,
|
||||
LED_FUNCTION_ARM_STATE
|
||||
};
|
||||
#endif
|
||||
|
||||
// grid offsets
|
||||
uint8_t highestYValueForNorth;
|
||||
|
@ -179,6 +145,168 @@ uint8_t lowestYValueForSouth;
|
|||
uint8_t highestXValueForWest;
|
||||
uint8_t lowestXValueForEast;
|
||||
|
||||
void determineLedStripDimensions(void)
|
||||
{
|
||||
ledGridWidth = 0;
|
||||
ledGridHeight = 0;
|
||||
|
||||
uint8_t ledIndex;
|
||||
const ledConfig_t *ledConfig;
|
||||
|
||||
for (ledIndex = 0; ledIndex < ledCount; ledIndex++) {
|
||||
ledConfig = &ledConfigs[ledIndex];
|
||||
|
||||
if (GET_LED_X(ledConfig) >= ledGridWidth) {
|
||||
ledGridWidth = GET_LED_X(ledConfig) + 1;
|
||||
}
|
||||
if (GET_LED_Y(ledConfig) >= ledGridHeight) {
|
||||
ledGridHeight = GET_LED_Y(ledConfig) + 1;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void determineOrientationLimits(void)
|
||||
{
|
||||
bool isOddHeight = (ledGridHeight & 1);
|
||||
bool isOddWidth = (ledGridWidth & 1);
|
||||
uint8_t heightModifier = isOddHeight ? 1 : 0;
|
||||
uint8_t widthModifier = isOddWidth ? 1 : 0;
|
||||
|
||||
highestYValueForNorth = (ledGridHeight / 2) - 1;
|
||||
lowestYValueForSouth = (ledGridHeight / 2) + heightModifier;
|
||||
highestXValueForWest = (ledGridWidth / 2) - 1;
|
||||
lowestXValueForEast = (ledGridWidth / 2) + widthModifier;
|
||||
}
|
||||
|
||||
void updateLedCount(void)
|
||||
{
|
||||
uint8_t ledIndex;
|
||||
ledCount = 0;
|
||||
for (ledIndex = 0; ledIndex < MAX_LED_STRIP_LENGTH; ledIndex++) {
|
||||
if (ledConfigs[ledIndex].flags == 0 && ledConfigs[ledIndex].xy == 0) {
|
||||
break;
|
||||
}
|
||||
ledCount++;
|
||||
}
|
||||
}
|
||||
|
||||
static void reevalulateLedConfig(void)
|
||||
{
|
||||
updateLedCount();
|
||||
determineLedStripDimensions();
|
||||
determineOrientationLimits();
|
||||
}
|
||||
|
||||
#define CHUNK_BUFFER_SIZE 10
|
||||
|
||||
#define NEXT_PARSE_STATE(parseState) ((parseState + 1) % PARSE_STATE_COUNT)
|
||||
|
||||
|
||||
bool parseLedStripConfig(uint8_t ledIndex, const char *config)
|
||||
{
|
||||
char chunk[CHUNK_BUFFER_SIZE];
|
||||
uint8_t chunkIndex;
|
||||
uint8_t val;
|
||||
|
||||
uint8_t parseState = X_COORDINATE;
|
||||
bool ok = true;
|
||||
|
||||
if (ledIndex >= MAX_LED_STRIP_LENGTH) {
|
||||
return !ok;
|
||||
}
|
||||
|
||||
ledConfig_t *ledConfig = &ledConfigs[ledIndex];
|
||||
memset(ledConfig, 0, sizeof(ledConfig_t));
|
||||
|
||||
while (ok) {
|
||||
|
||||
char chunkSeparator = chunkSeparators[parseState];
|
||||
|
||||
memset(&chunk, 0, sizeof(chunk));
|
||||
chunkIndex = 0;
|
||||
|
||||
while (*config && chunkIndex < CHUNK_BUFFER_SIZE && *config != chunkSeparator) {
|
||||
chunk[chunkIndex++] = *config++;
|
||||
}
|
||||
|
||||
if (*config++ != chunkSeparator) {
|
||||
ok = false;
|
||||
break;
|
||||
}
|
||||
|
||||
switch((parseState_e)parseState) {
|
||||
case X_COORDINATE:
|
||||
val = atoi(chunk);
|
||||
ledConfig->xy |= CALCULATE_LED_X(val);
|
||||
break;
|
||||
case Y_COORDINATE:
|
||||
val = atoi(chunk);
|
||||
ledConfig->xy |= CALCULATE_LED_Y(val);
|
||||
break;
|
||||
case DIRECTIONS:
|
||||
for (chunkIndex = 0; chunk[chunkIndex] && chunkIndex < CHUNK_BUFFER_SIZE; chunkIndex++) {
|
||||
for (uint8_t mappingIndex = 0; mappingIndex < DIRECTION_COUNT; mappingIndex++) {
|
||||
if (directionCodes[mappingIndex] == chunk[chunkIndex]) {
|
||||
ledConfig->flags |= directionMappings[mappingIndex];
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
break;
|
||||
case FUNCTIONS:
|
||||
for (chunkIndex = 0; chunk[chunkIndex] && chunkIndex < CHUNK_BUFFER_SIZE; chunkIndex++) {
|
||||
for (uint8_t mappingIndex = 0; mappingIndex < FUNCTION_COUNT; mappingIndex++) {
|
||||
if (functionCodes[mappingIndex] == chunk[chunkIndex]) {
|
||||
ledConfig->flags |= functionMappings[mappingIndex];
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
break;
|
||||
}
|
||||
|
||||
parseState++;
|
||||
if (parseState >= PARSE_STATE_COUNT) {
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
if (!ok) {
|
||||
memset(ledConfig, 0, sizeof(ledConfig_t));
|
||||
}
|
||||
|
||||
reevalulateLedConfig();
|
||||
|
||||
return ok;
|
||||
}
|
||||
|
||||
void generateLedConfig(uint8_t ledIndex, char *ledConfigBuffer, size_t bufferSize)
|
||||
{
|
||||
char functions[FUNCTION_COUNT];
|
||||
char directions[DIRECTION_COUNT];
|
||||
uint8_t index;
|
||||
uint8_t mappingIndex;
|
||||
ledConfig_t *ledConfig = &ledConfigs[ledIndex];
|
||||
|
||||
memset(ledConfigBuffer, 0, bufferSize);
|
||||
memset(&functions, 0, sizeof(functions));
|
||||
memset(&directions, 0, sizeof(directions));
|
||||
|
||||
for (mappingIndex = 0, index = 0; mappingIndex < FUNCTION_COUNT; mappingIndex++) {
|
||||
if (ledConfig->flags & functionMappings[mappingIndex]) {
|
||||
functions[index++] = functionCodes[mappingIndex];
|
||||
}
|
||||
}
|
||||
|
||||
for (mappingIndex = 0, index = 0; mappingIndex < DIRECTION_COUNT; mappingIndex++) {
|
||||
if (ledConfig->flags & directionMappings[mappingIndex]) {
|
||||
directions[index++] = directionCodes[mappingIndex];
|
||||
}
|
||||
}
|
||||
|
||||
sprintf(ledConfigBuffer, "%u,%u:%s:%s", GET_LED_X(ledConfig), GET_LED_Y(ledConfig), directions, functions);
|
||||
}
|
||||
|
||||
// timers
|
||||
uint32_t nextAnimationUpdateAt = 0;
|
||||
uint32_t nextIndicatorFlashAt = 0;
|
||||
|
@ -207,69 +335,97 @@ typedef union {
|
|||
static const modeColors_t orientationModeColors = {
|
||||
.raw = {
|
||||
{LED_WHITE},
|
||||
{LED_BLUE},
|
||||
{LED_DARK_VIOLET},
|
||||
{LED_RED},
|
||||
{LED_GREEN},
|
||||
{LED_PURPLE},
|
||||
{LED_CYAN}
|
||||
{LED_DEEP_PINK},
|
||||
{LED_BLUE},
|
||||
{LED_ORANGE}
|
||||
}
|
||||
};
|
||||
|
||||
static const modeColors_t headfreeModeColors = {
|
||||
.raw = {
|
||||
{LED_PINK},
|
||||
{LED_BLACK},
|
||||
{LED_LIME_GREEN},
|
||||
{LED_DARK_VIOLET},
|
||||
{LED_ORANGE},
|
||||
{LED_BLACK},
|
||||
{LED_BLACK},
|
||||
{LED_BLACK}
|
||||
{LED_DEEP_PINK},
|
||||
{LED_BLUE},
|
||||
{LED_ORANGE}
|
||||
}
|
||||
};
|
||||
|
||||
static const modeColors_t horizonModeColors = {
|
||||
.raw = {
|
||||
{LED_BLUE},
|
||||
{LED_BLACK},
|
||||
{LED_DARK_VIOLET},
|
||||
{LED_YELLOW},
|
||||
{LED_BLACK},
|
||||
{LED_BLACK},
|
||||
{LED_BLACK}
|
||||
{LED_DEEP_PINK},
|
||||
{LED_BLUE},
|
||||
{LED_ORANGE}
|
||||
}
|
||||
};
|
||||
|
||||
static const modeColors_t angleModeColors = {
|
||||
.raw = {
|
||||
{LED_CYAN},
|
||||
{LED_BLACK},
|
||||
{LED_DARK_VIOLET},
|
||||
{LED_YELLOW},
|
||||
{LED_BLACK},
|
||||
{LED_BLACK},
|
||||
{LED_BLACK}
|
||||
{LED_DEEP_PINK},
|
||||
{LED_BLUE},
|
||||
{LED_ORANGE}
|
||||
}
|
||||
};
|
||||
|
||||
static const modeColors_t magModeColors = {
|
||||
.raw = {
|
||||
{LED_PURPLE},
|
||||
{LED_BLACK},
|
||||
{LED_PINK},
|
||||
{LED_DARK_VIOLET},
|
||||
{LED_ORANGE},
|
||||
{LED_BLACK},
|
||||
{LED_BLACK},
|
||||
{LED_BLACK}
|
||||
{LED_DEEP_PINK},
|
||||
{LED_BLUE},
|
||||
{LED_ORANGE}
|
||||
}
|
||||
};
|
||||
|
||||
static const modeColors_t baroModeColors = {
|
||||
.raw = {
|
||||
{LED_LIGHT_BLUE},
|
||||
{LED_DARK_VIOLET},
|
||||
{LED_RED},
|
||||
{LED_DEEP_PINK},
|
||||
{LED_BLUE},
|
||||
{LED_ORANGE}
|
||||
}
|
||||
};
|
||||
|
||||
void applyDirectionalModeColor(const uint8_t ledIndex, const ledConfig_t *ledConfig, const modeColors_t *modeColors)
|
||||
{
|
||||
if (ledConfig->flags & LED_DIRECTION_NORTH && LED_Y(ledConfig) < highestYValueForNorth) {
|
||||
setLedColor(ledIndex, &modeColors->colors.north);
|
||||
return;
|
||||
// apply up/down colors regardless of quadrant.
|
||||
if ((ledConfig->flags & LED_DIRECTION_UP)) {
|
||||
setLedColor(ledIndex, &modeColors->colors.up);
|
||||
}
|
||||
|
||||
if (ledConfig->flags & LED_DIRECTION_SOUTH && LED_Y(ledConfig) >= lowestYValueForSouth) {
|
||||
setLedColor(ledIndex, &modeColors->colors.south);
|
||||
return;
|
||||
if ((ledConfig->flags & LED_DIRECTION_DOWN)) {
|
||||
setLedColor(ledIndex, &modeColors->colors.down);
|
||||
}
|
||||
|
||||
// override with n/e/s/w colors to each n/s e/w half - bail at first match.
|
||||
if ((ledConfig->flags & LED_DIRECTION_WEST) && GET_LED_X(ledConfig) <= highestXValueForWest) {
|
||||
setLedColor(ledIndex, &modeColors->colors.west);
|
||||
}
|
||||
|
||||
if ((ledConfig->flags & LED_DIRECTION_EAST) && GET_LED_X(ledConfig) >= lowestXValueForEast) {
|
||||
setLedColor(ledIndex, &modeColors->colors.east);
|
||||
}
|
||||
|
||||
if ((ledConfig->flags & LED_DIRECTION_NORTH) && GET_LED_Y(ledConfig) <= highestYValueForNorth) {
|
||||
setLedColor(ledIndex, &modeColors->colors.north);
|
||||
}
|
||||
|
||||
if ((ledConfig->flags & LED_DIRECTION_SOUTH) && GET_LED_Y(ledConfig) >= lowestYValueForSouth) {
|
||||
setLedColor(ledIndex, &modeColors->colors.south);
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
typedef enum {
|
||||
|
@ -283,25 +439,25 @@ void applyQuadrantColor(const uint8_t ledIndex, const ledConfig_t *ledConfig, co
|
|||
{
|
||||
switch (quadrant) {
|
||||
case QUADRANT_NORTH_EAST:
|
||||
if (LED_Y(ledConfig) <= highestYValueForNorth && LED_X(ledConfig) >= lowestXValueForEast) {
|
||||
if (GET_LED_Y(ledConfig) <= highestYValueForNorth && GET_LED_X(ledConfig) >= lowestXValueForEast) {
|
||||
setLedColor(ledIndex, color);
|
||||
}
|
||||
return;
|
||||
|
||||
case QUADRANT_SOUTH_EAST:
|
||||
if (LED_Y(ledConfig) >= lowestYValueForSouth && LED_X(ledConfig) >= lowestXValueForEast) {
|
||||
if (GET_LED_Y(ledConfig) >= lowestYValueForSouth && GET_LED_X(ledConfig) >= lowestXValueForEast) {
|
||||
setLedColor(ledIndex, color);
|
||||
}
|
||||
return;
|
||||
|
||||
case QUADRANT_SOUTH_WEST:
|
||||
if (LED_Y(ledConfig) >= lowestYValueForSouth && LED_X(ledConfig) <= highestXValueForWest) {
|
||||
if (GET_LED_Y(ledConfig) >= lowestYValueForSouth && GET_LED_X(ledConfig) <= highestXValueForWest) {
|
||||
setLedColor(ledIndex, color);
|
||||
}
|
||||
return;
|
||||
|
||||
case QUADRANT_NORTH_WEST:
|
||||
if (LED_Y(ledConfig) <= highestYValueForNorth && LED_X(ledConfig) <= highestXValueForWest) {
|
||||
if (GET_LED_Y(ledConfig) <= highestYValueForNorth && GET_LED_X(ledConfig) <= highestXValueForWest) {
|
||||
setLedColor(ledIndex, color);
|
||||
}
|
||||
return;
|
||||
|
@ -313,13 +469,13 @@ void applyLedModeLayer(void)
|
|||
const ledConfig_t *ledConfig;
|
||||
|
||||
uint8_t ledIndex;
|
||||
for (ledIndex = 0; ledIndex < WS2811_LED_STRIP_LENGTH; ledIndex++) {
|
||||
for (ledIndex = 0; ledIndex < ledCount; ledIndex++) {
|
||||
|
||||
ledConfig = &ledConfigs[ledIndex];
|
||||
|
||||
setLedColor(ledIndex, &black);
|
||||
|
||||
if (!(ledConfig->flags & LED_FUNCTION_MODE)) {
|
||||
if (!(ledConfig->flags & LED_FUNCTION_FLIGHT_MODE)) {
|
||||
if (ledConfig->flags & LED_FUNCTION_ARM_STATE) {
|
||||
if (!ARMING_FLAG(ARMED)) {
|
||||
setLedColor(ledIndex, &green);
|
||||
|
@ -337,6 +493,10 @@ void applyLedModeLayer(void)
|
|||
#ifdef MAG
|
||||
} else if (FLIGHT_MODE(MAG_MODE)) {
|
||||
applyDirectionalModeColor(ledIndex, ledConfig, &magModeColors);
|
||||
#endif
|
||||
#ifdef BARO
|
||||
} else if (FLIGHT_MODE(BARO_MODE)) {
|
||||
applyDirectionalModeColor(ledIndex, ledConfig, &baroModeColors);
|
||||
#endif
|
||||
} else if (FLIGHT_MODE(HORIZON_MODE)) {
|
||||
applyDirectionalModeColor(ledIndex, ledConfig, &horizonModeColors);
|
||||
|
@ -351,7 +511,7 @@ void applyLedLowBatteryLayer(uint8_t batteryFlashState)
|
|||
const ledConfig_t *ledConfig;
|
||||
|
||||
uint8_t ledIndex;
|
||||
for (ledIndex = 0; ledIndex < WS2811_LED_STRIP_LENGTH; ledIndex++) {
|
||||
for (ledIndex = 0; ledIndex < ledCount; ledIndex++) {
|
||||
|
||||
ledConfig = &ledConfigs[ledIndex];
|
||||
|
||||
|
@ -381,7 +541,7 @@ void applyLedIndicatorLayer(uint8_t indicatorFlashState)
|
|||
|
||||
|
||||
uint8_t ledIndex;
|
||||
for (ledIndex = 0; ledIndex < WS2811_LED_STRIP_LENGTH; ledIndex++) {
|
||||
for (ledIndex = 0; ledIndex < ledCount; ledIndex++) {
|
||||
|
||||
ledConfig = &ledConfigs[ledIndex];
|
||||
|
||||
|
@ -428,6 +588,7 @@ static void updateLedAnimationState(void)
|
|||
frameCounter = (frameCounter + 1) % animationFrames;
|
||||
}
|
||||
|
||||
#ifdef USE_LED_ANIMATION
|
||||
static void applyLedAnimationLayer(void)
|
||||
{
|
||||
const ledConfig_t *ledConfig;
|
||||
|
@ -437,21 +598,22 @@ static void applyLedAnimationLayer(void)
|
|||
}
|
||||
|
||||
uint8_t ledIndex;
|
||||
for (ledIndex = 0; ledIndex < WS2811_LED_STRIP_LENGTH; ledIndex++) {
|
||||
for (ledIndex = 0; ledIndex < ledCount; ledIndex++) {
|
||||
|
||||
ledConfig = &ledConfigs[ledIndex];
|
||||
|
||||
if (LED_Y(ledConfig) == previousRow) {
|
||||
if (GET_LED_Y(ledConfig) == previousRow) {
|
||||
setLedColor(ledIndex, &white);
|
||||
setLedBrightness(ledIndex, 50);
|
||||
|
||||
} else if (LED_Y(ledConfig) == currentRow) {
|
||||
} else if (GET_LED_Y(ledConfig) == currentRow) {
|
||||
setLedColor(ledIndex, &white);
|
||||
} else if (LED_Y(ledConfig) == nextRow) {
|
||||
} else if (GET_LED_Y(ledConfig) == nextRow) {
|
||||
setLedBrightness(ledIndex, 50);
|
||||
}
|
||||
}
|
||||
}
|
||||
#endif
|
||||
|
||||
void updateLedStrip(void)
|
||||
{
|
||||
|
@ -519,57 +681,22 @@ void updateLedStrip(void)
|
|||
updateLedAnimationState();
|
||||
}
|
||||
|
||||
#ifdef USE_LED_ANIMATION
|
||||
applyLedAnimationLayer();
|
||||
|
||||
#endif
|
||||
ws2811UpdateStrip();
|
||||
}
|
||||
|
||||
void determineLedStripDimensions()
|
||||
void applyDefaultLedStripConfig(ledConfig_t *ledConfigs)
|
||||
{
|
||||
ledGridWidth = 0;
|
||||
ledGridHeight = 0;
|
||||
|
||||
uint8_t ledIndex;
|
||||
const ledConfig_t *ledConfig;
|
||||
|
||||
for (ledIndex = 0; ledIndex < WS2811_LED_STRIP_LENGTH; ledIndex++) {
|
||||
ledConfig = &ledConfigs[ledIndex];
|
||||
|
||||
if (LED_X(ledConfig) >= ledGridWidth) {
|
||||
ledGridWidth = LED_X(ledConfig) + 1;
|
||||
}
|
||||
if (LED_Y(ledConfig) >= ledGridHeight) {
|
||||
ledGridHeight = LED_Y(ledConfig) + 1;
|
||||
}
|
||||
}
|
||||
memset(ledConfigs, 0, MAX_LED_STRIP_LENGTH * sizeof(ledConfig_t));
|
||||
memcpy(ledConfigs, &defaultLedStripConfig, sizeof(defaultLedStripConfig));
|
||||
reevalulateLedConfig();
|
||||
}
|
||||
|
||||
void determineOrientationLimits(void)
|
||||
void ledStripInit(ledConfig_t *ledConfigsToUse)
|
||||
{
|
||||
highestYValueForNorth = (ledGridHeight / 2) - 1;
|
||||
if (highestYValueForNorth > 1) { // support small grid (e.g. gridwidth 5)
|
||||
highestYValueForNorth &= ~(1 << 0); // make even
|
||||
}
|
||||
|
||||
lowestYValueForSouth = (ledGridHeight / 2) - 1;
|
||||
if (lowestYValueForSouth & 1) {
|
||||
lowestYValueForSouth = min(lowestYValueForSouth + 1, ledGridHeight - 1);
|
||||
}
|
||||
|
||||
highestXValueForWest = (ledGridWidth / 2) - 1;
|
||||
if (highestXValueForWest > 1) { // support small grid (e.g. gridwidth 5)
|
||||
highestXValueForWest &= ~(1 << 0); // make even
|
||||
}
|
||||
|
||||
lowestXValueForEast = (ledGridWidth / 2) - 1;
|
||||
if (lowestXValueForEast & 1) {
|
||||
lowestXValueForEast = min(lowestXValueForEast + 1, ledGridWidth - 1);
|
||||
}
|
||||
}
|
||||
|
||||
void ledStripInit(void)
|
||||
{
|
||||
determineLedStripDimensions();
|
||||
determineOrientationLimits();
|
||||
ledConfigs = ledConfigsToUse;
|
||||
reevalulateLedConfig();
|
||||
}
|
||||
#endif
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue