mirror of
https://github.com/betaflight/betaflight.git
synced 2025-07-23 16:25:31 +03:00
Add support for LED thrust ring. (St7ven)
This commit includes various fixed not included in the original pull request.
This commit is contained in:
parent
d2536e3792
commit
ddc7a39fa2
3 changed files with 179 additions and 35 deletions
|
@ -55,6 +55,7 @@ static failsafe_t* failsafe;
|
|||
static void ledStripDisable(void);
|
||||
|
||||
//#define USE_LED_ANIMATION
|
||||
//#define USE_LED_RING_DEFAULT_CONFIG
|
||||
|
||||
// timers
|
||||
#ifdef USE_LED_ANIMATION
|
||||
|
@ -63,6 +64,7 @@ static uint32_t nextAnimationUpdateAt = 0;
|
|||
|
||||
static uint32_t nextIndicatorFlashAt = 0;
|
||||
static uint32_t nextWarningFlashAt = 0;
|
||||
static uint32_t nextRotationUpdateAt = 0;
|
||||
|
||||
#define LED_STRIP_20HZ ((1000 * 1000) / 20)
|
||||
#define LED_STRIP_10HZ ((1000 * 1000) / 10)
|
||||
|
@ -225,23 +227,44 @@ static const modeColorIndexes_t baroModeColors = {
|
|||
uint8_t ledGridWidth;
|
||||
uint8_t ledGridHeight;
|
||||
uint8_t ledCount;
|
||||
uint8_t ledsInRingCount;
|
||||
|
||||
ledConfig_t *ledConfigs;
|
||||
hsvColor_t *colors;
|
||||
|
||||
|
||||
#ifdef USE_LED_RING_DEFAULT_CONFIG
|
||||
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_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_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_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 },
|
||||
{ CALCULATE_LED_XY( 2, 2), 3, LED_FUNCTION_THRUST_RING},
|
||||
{ CALCULATE_LED_XY( 2, 1), 3, LED_FUNCTION_THRUST_RING},
|
||||
{ CALCULATE_LED_XY( 2, 0), 3, LED_FUNCTION_THRUST_RING},
|
||||
{ CALCULATE_LED_XY( 1, 0), 3, LED_FUNCTION_THRUST_RING},
|
||||
{ CALCULATE_LED_XY( 0, 0), 3, LED_FUNCTION_THRUST_RING},
|
||||
{ CALCULATE_LED_XY( 0, 1), 3, LED_FUNCTION_THRUST_RING},
|
||||
{ CALCULATE_LED_XY( 0, 2), 3, LED_FUNCTION_THRUST_RING},
|
||||
{ CALCULATE_LED_XY( 1, 2), 3, LED_FUNCTION_THRUST_RING},
|
||||
{ CALCULATE_LED_XY( 1, 1), 3, LED_FUNCTION_THRUST_RING},
|
||||
{ CALCULATE_LED_XY( 1, 1), 3, LED_FUNCTION_THRUST_RING},
|
||||
{ CALCULATE_LED_XY( 1, 1), 3, LED_FUNCTION_THRUST_RING},
|
||||
{ CALCULATE_LED_XY( 1, 1), 3, LED_FUNCTION_THRUST_RING},
|
||||
};
|
||||
#else
|
||||
const ledConfig_t defaultLedStripConfig[] = {
|
||||
{ CALCULATE_LED_XY( 2, 2), 0, LED_DIRECTION_SOUTH | LED_DIRECTION_EAST | LED_FUNCTION_INDICATOR | LED_FUNCTION_ARM_STATE },
|
||||
{ CALCULATE_LED_XY( 2, 1), 0, LED_DIRECTION_EAST | LED_FUNCTION_FLIGHT_MODE | LED_FUNCTION_WARNING },
|
||||
{ CALCULATE_LED_XY( 2, 0), 0, LED_DIRECTION_NORTH | LED_DIRECTION_EAST | LED_FUNCTION_INDICATOR | LED_FUNCTION_ARM_STATE },
|
||||
{ CALCULATE_LED_XY( 1, 0), 0, LED_DIRECTION_NORTH | LED_FUNCTION_FLIGHT_MODE },
|
||||
{ CALCULATE_LED_XY( 0, 0), 0, LED_DIRECTION_NORTH | LED_DIRECTION_WEST | LED_FUNCTION_INDICATOR | LED_FUNCTION_ARM_STATE },
|
||||
{ CALCULATE_LED_XY( 0, 1), 0, LED_DIRECTION_WEST | LED_FUNCTION_FLIGHT_MODE | LED_FUNCTION_WARNING },
|
||||
{ CALCULATE_LED_XY( 0, 2), 0, LED_DIRECTION_SOUTH | LED_DIRECTION_WEST | LED_FUNCTION_INDICATOR | LED_FUNCTION_ARM_STATE },
|
||||
{ CALCULATE_LED_XY( 1, 2), 0, LED_DIRECTION_SOUTH | LED_FUNCTION_FLIGHT_MODE | LED_FUNCTION_WARNING },
|
||||
{ CALCULATE_LED_XY( 1, 1), 0, LED_DIRECTION_UP | LED_FUNCTION_FLIGHT_MODE | LED_FUNCTION_WARNING },
|
||||
{ CALCULATE_LED_XY( 1, 1), 0, LED_DIRECTION_UP | LED_FUNCTION_FLIGHT_MODE | LED_FUNCTION_WARNING },
|
||||
{ CALCULATE_LED_XY( 1, 1), 0, LED_DIRECTION_DOWN | LED_FUNCTION_FLIGHT_MODE | LED_FUNCTION_WARNING },
|
||||
{ CALCULATE_LED_XY( 1, 1), 0, LED_DIRECTION_DOWN | LED_FUNCTION_FLIGHT_MODE | LED_FUNCTION_WARNING },
|
||||
};
|
||||
#endif
|
||||
|
||||
|
||||
|
||||
/*
|
||||
|
@ -258,12 +281,13 @@ typedef enum {
|
|||
X_COORDINATE,
|
||||
Y_COORDINATE,
|
||||
DIRECTIONS,
|
||||
FUNCTIONS
|
||||
FUNCTIONS,
|
||||
RING_COLORS
|
||||
} parseState_e;
|
||||
|
||||
#define PARSE_STATE_COUNT 4
|
||||
#define PARSE_STATE_COUNT 5
|
||||
|
||||
static const char chunkSeparators[PARSE_STATE_COUNT] = {',', ':', ':', '\0' };
|
||||
static const char chunkSeparators[PARSE_STATE_COUNT] = {',', ':', ':',':', '\0' };
|
||||
|
||||
static const char directionCodes[] = { 'N', 'E', 'S', 'W', 'U', 'D' };
|
||||
#define DIRECTION_COUNT (sizeof(directionCodes) / sizeof(directionCodes[0]))
|
||||
|
@ -276,14 +300,15 @@ static const uint8_t directionMappings[DIRECTION_COUNT] = {
|
|||
LED_DIRECTION_DOWN
|
||||
};
|
||||
|
||||
static const char functionCodes[] = { 'I', 'W', 'F', 'A', 'T' };
|
||||
static const char functionCodes[] = { 'I', 'W', 'F', 'A', 'T', 'R' };
|
||||
#define FUNCTION_COUNT (sizeof(functionCodes) / sizeof(functionCodes[0]))
|
||||
static const uint16_t functionMappings[FUNCTION_COUNT] = {
|
||||
LED_FUNCTION_INDICATOR,
|
||||
LED_FUNCTION_WARNING,
|
||||
LED_FUNCTION_FLIGHT_MODE,
|
||||
LED_FUNCTION_ARM_STATE,
|
||||
LED_FUNCTION_THROTTLE
|
||||
LED_FUNCTION_THROTTLE,
|
||||
LED_FUNCTION_THRUST_RING
|
||||
};
|
||||
|
||||
// grid offsets
|
||||
|
@ -327,13 +352,24 @@ void determineOrientationLimits(void)
|
|||
|
||||
void updateLedCount(void)
|
||||
{
|
||||
const ledConfig_t *ledConfig;
|
||||
uint8_t ledIndex;
|
||||
ledCount = 0;
|
||||
ledsInRingCount = 0;
|
||||
|
||||
for (ledIndex = 0; ledIndex < MAX_LED_STRIP_LENGTH; ledIndex++) {
|
||||
if (ledConfigs[ledIndex].flags == 0 && ledConfigs[ledIndex].xy == 0) {
|
||||
|
||||
ledConfig = &ledConfigs[ledIndex];
|
||||
|
||||
if (ledConfig->flags == 0 && ledConfig->xy == 0) {
|
||||
break;
|
||||
}
|
||||
|
||||
ledCount++;
|
||||
|
||||
if ((ledConfig->flags & LED_FUNCTION_THRUST_RING)) {
|
||||
ledsInRingCount++;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -410,6 +446,15 @@ bool parseLedStripConfig(uint8_t ledIndex, const char *config)
|
|||
}
|
||||
}
|
||||
break;
|
||||
case RING_COLORS:
|
||||
if (atoi(chunk) < CONFIGURABLE_COLOR_COUNT) {
|
||||
ledConfig->color = atoi(chunk);
|
||||
} else {
|
||||
ledConfig->color = 0;
|
||||
}
|
||||
break;
|
||||
default :
|
||||
break;
|
||||
}
|
||||
|
||||
parseState++;
|
||||
|
@ -433,11 +478,13 @@ void generateLedConfig(uint8_t ledIndex, char *ledConfigBuffer, size_t bufferSiz
|
|||
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));
|
||||
//memset(&ringColors, 0 ,sizeof(ringColors));
|
||||
|
||||
for (mappingIndex = 0, index = 0; mappingIndex < FUNCTION_COUNT; mappingIndex++) {
|
||||
if (ledConfig->flags & functionMappings[mappingIndex]) {
|
||||
|
@ -451,7 +498,7 @@ void generateLedConfig(uint8_t ledIndex, char *ledConfigBuffer, size_t bufferSiz
|
|||
}
|
||||
}
|
||||
|
||||
sprintf(ledConfigBuffer, "%u,%u:%s:%s", GET_LED_X(ledConfig), GET_LED_Y(ledConfig), directions, functions);
|
||||
sprintf(ledConfigBuffer, "%u,%u:%s:%s:%u", GET_LED_X(ledConfig), GET_LED_Y(ledConfig), directions, functions, ledConfig->color);
|
||||
}
|
||||
|
||||
void applyDirectionalModeColor(const uint8_t ledIndex, const ledConfig_t *ledConfig, const modeColorIndexes_t *modeColors)
|
||||
|
@ -529,7 +576,9 @@ void applyLedModeLayer(void)
|
|||
|
||||
ledConfig = &ledConfigs[ledIndex];
|
||||
|
||||
setLedHsv(ledIndex, &hsv_black);
|
||||
if (!(ledConfig->flags & LED_FUNCTION_THRUST_RING)) {
|
||||
setLedHsv(ledIndex, &hsv_black);
|
||||
}
|
||||
|
||||
if (!(ledConfig->flags & LED_FUNCTION_FLIGHT_MODE)) {
|
||||
if (ledConfig->flags & LED_FUNCTION_ARM_STATE) {
|
||||
|
@ -682,7 +731,7 @@ void applyLedThrottleLayer()
|
|||
uint8_t ledIndex;
|
||||
for (ledIndex = 0; ledIndex < ledCount; ledIndex++) {
|
||||
ledConfig = &ledConfigs[ledIndex];
|
||||
if(!(ledConfig->flags & LED_FUNCTION_THROTTLE)) {
|
||||
if (!(ledConfig->flags & LED_FUNCTION_THROTTLE)) {
|
||||
continue;
|
||||
}
|
||||
|
||||
|
@ -695,15 +744,77 @@ void applyLedThrottleLayer()
|
|||
}
|
||||
}
|
||||
|
||||
#ifdef USE_LED_ANIMATION
|
||||
static uint8_t frameCounter = 0;
|
||||
|
||||
static uint8_t previousRow;
|
||||
static uint8_t currentRow;
|
||||
static uint8_t nextRow;
|
||||
|
||||
static void updateLedAnimationState(void)
|
||||
int applyLedThrustRingLayer(void)
|
||||
{
|
||||
uint8_t oppositeLedIndex = ledsInRingCount >> 1;
|
||||
uint8_t ledIndex;
|
||||
int returnedValue = 1;
|
||||
int throttleScaled = scaleRange(rcData[THROTTLE], PWM_RANGE_MIN, PWM_RANGE_MAX, 1, 10);
|
||||
static uint8_t rotationPhase = 0;
|
||||
static bool nextLedOn = false;
|
||||
hsvColor_t ringColor;
|
||||
const ledConfig_t *ledConfig;
|
||||
|
||||
|
||||
for (ledIndex = 0; ledIndex < ledCount; ledIndex++) {
|
||||
|
||||
ledConfig = &ledConfigs[ledIndex];
|
||||
|
||||
ringColor = colors[ledConfig->color];
|
||||
|
||||
if ((ledConfig->flags & LED_FUNCTION_THRUST_RING)) {
|
||||
|
||||
if (!ARMING_FLAG(ARMED)) {
|
||||
|
||||
if (nextLedOn == false) {
|
||||
nextLedOn = true;
|
||||
}
|
||||
else {
|
||||
nextLedOn = false;
|
||||
ringColor = hsv_black;
|
||||
}
|
||||
|
||||
returnedValue = 1;
|
||||
}
|
||||
else {
|
||||
if (rotationPhase == ((oppositeLedIndex) - 1)) {
|
||||
if (!((ledIndex == rotationPhase) || (ledIndex == (rotationPhase + oppositeLedIndex))
|
||||
|| (ledIndex == (rotationPhase +1)) || (ledIndex == 0))) {
|
||||
ringColor = hsv_black;
|
||||
}
|
||||
}
|
||||
else if (!((ledIndex == rotationPhase) || (ledIndex == (rotationPhase + oppositeLedIndex))
|
||||
|| (ledIndex == (rotationPhase +1)) || (ledIndex == (rotationPhase + oppositeLedIndex +1 )))) {
|
||||
ringColor = hsv_black;
|
||||
}
|
||||
else {
|
||||
// Led stay on
|
||||
}
|
||||
|
||||
returnedValue = throttleScaled;
|
||||
}
|
||||
setLedHsv(ledIndex, &ringColor);
|
||||
}
|
||||
}
|
||||
|
||||
if (rotationPhase >= (oppositeLedIndex - 1)) {
|
||||
rotationPhase = 0;
|
||||
}
|
||||
else {
|
||||
rotationPhase++;
|
||||
}
|
||||
|
||||
return returnedValue;
|
||||
}
|
||||
|
||||
#ifdef USE_LED_ANIMATION
|
||||
void updateLedAnimationState(void)
|
||||
{
|
||||
static uint8_t frameCounter = 0;
|
||||
|
||||
static uint8_t previousRow;
|
||||
static uint8_t currentRow;
|
||||
static uint8_t nextRow;
|
||||
uint8_t animationFrames = ledGridHeight;
|
||||
|
||||
previousRow = (frameCounter + animationFrames - 1) % animationFrames;
|
||||
|
@ -741,7 +852,8 @@ static void applyLedAnimationLayer(void)
|
|||
|
||||
void updateLedStrip(void)
|
||||
{
|
||||
if (!(ledStripInitialised && isWS2811LedStripReady())) {
|
||||
|
||||
if (!(ledStripInitialised && isWS2811LedStripReady())) {
|
||||
return;
|
||||
}
|
||||
|
||||
|
@ -762,12 +874,14 @@ void updateLedStrip(void)
|
|||
uint32_t now = micros();
|
||||
|
||||
bool indicatorFlashNow = indicatorFlashNow = (int32_t)(now - nextIndicatorFlashAt) >= 0L;
|
||||
bool warningFlashNow =warningFlashNow = (int32_t)(now - nextWarningFlashAt) >= 0L;
|
||||
bool warningFlashNow = warningFlashNow = (int32_t)(now - nextWarningFlashAt) >= 0L;
|
||||
bool rotationUpdateNow = (int32_t)(now - nextRotationUpdateAt) >= 0L;
|
||||
#ifdef USE_LED_ANIMATION
|
||||
bool animationUpdateNow = animationUpdateNow = (int32_t)(now - nextAnimationUpdateAt) >= 0L;
|
||||
#endif
|
||||
if (!(
|
||||
indicatorFlashNow ||
|
||||
rotationUpdateNow ||
|
||||
warningFlashNow
|
||||
#ifdef USE_LED_ANIMATION
|
||||
|| animationUpdateNow
|
||||
|
@ -812,10 +926,16 @@ void updateLedStrip(void)
|
|||
nextAnimationUpdateAt = now + LED_STRIP_20HZ;
|
||||
updateLedAnimationState();
|
||||
}
|
||||
|
||||
applyLedAnimationLayer();
|
||||
#endif
|
||||
|
||||
if (rotationUpdateNow) {
|
||||
|
||||
int animationSpeedScaled = applyLedThrustRingLayer();
|
||||
|
||||
nextRotationUpdateAt = now + LED_STRIP_5HZ/animationSpeedScaled; // TODO will be changed with more specifics animation
|
||||
}
|
||||
|
||||
ws2811UpdateStrip();
|
||||
}
|
||||
|
||||
|
@ -835,6 +955,7 @@ bool parseColor(uint8_t index, const char *colorConfig)
|
|||
if (val > HSV_HUE_MAX) {
|
||||
ok = false;
|
||||
continue;
|
||||
|
||||
}
|
||||
colors[index].h = val;
|
||||
break;
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue