mirror of
https://github.com/betaflight/betaflight.git
synced 2025-07-19 22:35:23 +03:00
Added single colour mode to WS2811 driver for RAM savings.
This commit is contained in:
parent
7393d5fdac
commit
37d0d402c8
6 changed files with 52 additions and 63 deletions
|
@ -57,8 +57,9 @@ volatile uint8_t ws2811LedDataTransferInProgress = 0;
|
|||
uint16_t BIT_COMPARE_1 = 0;
|
||||
uint16_t BIT_COMPARE_0 = 0;
|
||||
|
||||
static hsvColor_t ledColorBuffer[WS2811_LED_STRIP_LENGTH];
|
||||
static hsvColor_t ledColorBuffer[WS2811_DATA_BUFFER_SIZE];
|
||||
|
||||
#if !defined(USE_WS2811_SINGLE_COLOUR)
|
||||
void setLedHsv(uint16_t index, const hsvColor_t *color)
|
||||
{
|
||||
ledColorBuffer[index] = *color;
|
||||
|
@ -78,19 +79,20 @@ void scaleLedValue(uint16_t index, const uint8_t scalePercent)
|
|||
{
|
||||
ledColorBuffer[index].v = ((uint16_t)ledColorBuffer[index].v * scalePercent / 100);
|
||||
}
|
||||
#endif
|
||||
|
||||
void setStripColor(const hsvColor_t *color)
|
||||
{
|
||||
uint16_t index;
|
||||
for (index = 0; index < WS2811_LED_STRIP_LENGTH; index++) {
|
||||
setLedHsv(index, color);
|
||||
for (index = 0; index < WS2811_DATA_BUFFER_SIZE; index++) {
|
||||
ledColorBuffer[index] = *color;
|
||||
}
|
||||
}
|
||||
|
||||
void setStripColors(const hsvColor_t *colors)
|
||||
{
|
||||
uint16_t index;
|
||||
for (index = 0; index < WS2811_LED_STRIP_LENGTH; index++) {
|
||||
for (index = 0; index < WS2811_DATA_BUFFER_SIZE; index++) {
|
||||
setLedHsv(index, colors++);
|
||||
}
|
||||
}
|
||||
|
@ -114,10 +116,7 @@ bool isWS2811LedStripReady(void)
|
|||
STATIC_UNIT_TESTED uint16_t dmaBufferOffset;
|
||||
static int16_t ledIndex;
|
||||
|
||||
#define USE_FAST_DMA_BUFFER_IMPL
|
||||
#ifdef USE_FAST_DMA_BUFFER_IMPL
|
||||
|
||||
STATIC_UNIT_TESTED void fastUpdateLEDDMABuffer(ledStripFormatRGB_e ledFormat, rgbColor24bpp_t *color)
|
||||
STATIC_UNIT_TESTED void updateLEDDMABuffer(ledStripFormatRGB_e ledFormat, rgbColor24bpp_t *color)
|
||||
{
|
||||
uint32_t packed_colour;
|
||||
|
||||
|
@ -136,25 +135,6 @@ STATIC_UNIT_TESTED void fastUpdateLEDDMABuffer(ledStripFormatRGB_e ledFormat, rg
|
|||
ledStripDMABuffer[dmaBufferOffset++] = (packed_colour & (1 << index)) ? BIT_COMPARE_1 : BIT_COMPARE_0;
|
||||
}
|
||||
}
|
||||
#else
|
||||
STATIC_UNIT_TESTED void updateLEDDMABuffer(uint8_t componentValue)
|
||||
{
|
||||
uint8_t bitIndex;
|
||||
|
||||
for (bitIndex = 0; bitIndex < 8; bitIndex++)
|
||||
{
|
||||
if ((componentValue << bitIndex) & 0x80 ) // data sent MSB first, j = 0 is MSB j = 7 is LSB
|
||||
{
|
||||
ledStripDMABuffer[dmaBufferOffset] = BIT_COMPARE_1;
|
||||
}
|
||||
else
|
||||
{
|
||||
ledStripDMABuffer[dmaBufferOffset] = BIT_COMPARE_0; // compare value for logical 0
|
||||
}
|
||||
dmaBufferOffset++;
|
||||
}
|
||||
}
|
||||
#endif
|
||||
|
||||
/*
|
||||
* This method is non-blocking unless an existing LED update is in progress.
|
||||
|
@ -174,28 +154,11 @@ void ws2811UpdateStrip(ledStripFormatRGB_e ledFormat)
|
|||
|
||||
// fill transmit buffer with correct compare values to achieve
|
||||
// correct pulse widths according to color values
|
||||
while (ledIndex < WS2811_LED_STRIP_LENGTH)
|
||||
while (ledIndex < WS2811_DATA_BUFFER_SIZE)
|
||||
{
|
||||
rgb24 = hsvToRgb24(&ledColorBuffer[ledIndex]);
|
||||
|
||||
#ifdef USE_FAST_DMA_BUFFER_IMPL
|
||||
fastUpdateLEDDMABuffer(ledFormat, rgb24);
|
||||
#else
|
||||
switch (ledFormat) {
|
||||
case LED_RGB: // WS2811 drivers use RGB format
|
||||
updateLEDDMABuffer(rgb24->rgb.r);
|
||||
updateLEDDMABuffer(rgb24->rgb.g);
|
||||
break;
|
||||
|
||||
case LED_GRB: // WS2812 drivers use GRB format
|
||||
default:
|
||||
updateLEDDMABuffer(rgb24->rgb.g);
|
||||
updateLEDDMABuffer(rgb24->rgb.r);
|
||||
break;
|
||||
}
|
||||
|
||||
updateLEDDMABuffer(rgb24->rgb.b);
|
||||
#endif
|
||||
updateLEDDMABuffer(ledFormat, rgb24);
|
||||
|
||||
ledIndex++;
|
||||
}
|
||||
|
|
|
@ -20,16 +20,26 @@
|
|||
|
||||
#pragma once
|
||||
|
||||
#include "platform.h"
|
||||
|
||||
#include "drivers/io_types.h"
|
||||
|
||||
#define WS2811_LED_STRIP_LENGTH 32
|
||||
|
||||
#define WS2811_BITS_PER_LED 24
|
||||
|
||||
#if defined(USE_WS2811_SINGLE_COLOUR)
|
||||
#define WS2811_DATA_BUFFER_SIZE 1
|
||||
#define WS2811_DMA_BUFFER_SIZE (WS2811_DATA_BUFFER_SIZE * WS2811_BITS_PER_LED)
|
||||
// Do 2 extra iterations of the DMA transfer with the ouptut set to low to generate the > 50us delay.
|
||||
#define WS2811_DELAY_ITERATIONS 2
|
||||
#else
|
||||
#define WS2811_DATA_BUFFER_SIZE WS2811_LED_STRIP_LENGTH
|
||||
// for 50us delay
|
||||
#define WS2811_DELAY_BUFFER_LENGTH 42
|
||||
|
||||
#define WS2811_DATA_BUFFER_SIZE (WS2811_BITS_PER_LED * WS2811_LED_STRIP_LENGTH)
|
||||
// number of bytes needed is #LEDs * 24 bytes + 42 trailing bytes)
|
||||
#define WS2811_DMA_BUFFER_SIZE (WS2811_DATA_BUFFER_SIZE + WS2811_DELAY_BUFFER_LENGTH)
|
||||
#define WS2811_DMA_BUFFER_SIZE (WS2811_DATA_BUFFER_SIZE * WS2811_BITS_PER_LED + WS2811_DELAY_BUFFER_LENGTH)
|
||||
#endif
|
||||
|
||||
#define WS2811_TIMER_MHZ 48
|
||||
#define WS2811_CARRIER_HZ 800000
|
||||
|
|
|
@ -20,6 +20,7 @@
|
|||
|
||||
#include <stdbool.h>
|
||||
#include <stdint.h>
|
||||
#include <string.h>
|
||||
|
||||
#include "platform.h"
|
||||
|
||||
|
@ -50,9 +51,26 @@ static TIM_TypeDef *timer = NULL;
|
|||
|
||||
static void WS2811_DMA_IRQHandler(dmaChannelDescriptor_t *descriptor)
|
||||
{
|
||||
#if defined(USE_WS2811_SINGLE_COLOUR)
|
||||
static uint32_t counter = 0;
|
||||
#endif
|
||||
|
||||
if (DMA_GET_FLAG_STATUS(descriptor, DMA_IT_TCIF)) {
|
||||
#if defined(USE_WS2811_SINGLE_COLOUR)
|
||||
counter++;
|
||||
if (counter == WS2811_LED_STRIP_LENGTH) {
|
||||
// Output low for 50us delay
|
||||
memset(ledStripDMABuffer, 0, sizeof(ledStripDMABuffer));
|
||||
} else if (counter == (WS2811_LED_STRIP_LENGTH + WS2811_DELAY_ITERATIONS)) {
|
||||
counter = 0;
|
||||
ws2811LedDataTransferInProgress = 0;
|
||||
DMA_Cmd(descriptor->ref, DISABLE);
|
||||
}
|
||||
#else
|
||||
ws2811LedDataTransferInProgress = 0;
|
||||
DMA_Cmd(descriptor->ref, DISABLE);
|
||||
#endif
|
||||
|
||||
DMA_CLEAR_FLAG(descriptor, DMA_IT_TCIF);
|
||||
}
|
||||
}
|
||||
|
@ -162,7 +180,7 @@ void ws2811LedStripHardwareInit(ioTag_t ioTag)
|
|||
DMA_InitStructure.DMA_Priority = DMA_Priority_High;
|
||||
DMA_InitStructure.DMA_M2M = DMA_M2M_Disable;
|
||||
#endif
|
||||
DMA_InitStructure.DMA_Mode = DMA_Mode_Normal;
|
||||
DMA_InitStructure.DMA_Mode = DMA_Mode_Circular;
|
||||
|
||||
DMA_Init(dmaRef, &DMA_InitStructure);
|
||||
TIM_DMACmd(timer, timerDmaSource(timerHardware->channel), ENABLE);
|
||||
|
|
|
@ -94,10 +94,6 @@ static uint8_t previousProfileColorIndex = COLOR_UNDEFINED;
|
|||
#define BEACON_FAILSAFE_PERIOD_US 250 // 2Hz
|
||||
#define BEACON_FAILSAFE_ON_PERCENT 50 // 50% duty cycle
|
||||
|
||||
#if LED_MAX_STRIP_LENGTH > WS2811_LED_STRIP_LENGTH
|
||||
# error "Led strip length must match driver"
|
||||
#endif
|
||||
|
||||
const hsvColor_t hsv[] = {
|
||||
// H S V
|
||||
[COLOR_BLACK] = { 0, 0, 0},
|
||||
|
@ -140,6 +136,11 @@ void pgResetFn_ledStripConfig(ledStripConfig_t *ledStripConfig)
|
|||
}
|
||||
|
||||
#ifdef USE_LED_STRIP_STATUS_MODE
|
||||
|
||||
#if LED_MAX_STRIP_LENGTH > WS2811_LED_STRIP_LENGTH
|
||||
# error "Led strip length must match driver"
|
||||
#endif
|
||||
|
||||
const hsvColor_t *colors;
|
||||
const modeColorIndexes_t *modeColors;
|
||||
specialColorIndexes_t specialColors;
|
||||
|
|
|
@ -244,6 +244,10 @@
|
|||
#undef USE_LED_STRIP_STATUS_MODE
|
||||
#endif
|
||||
|
||||
#if defined(USE_LED_STRIP) && !defined(USE_LED_STRIP_STATUS_MODE)
|
||||
#define USE_WS2811_SINGLE_COLOUR
|
||||
#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
|
||||
|
|
|
@ -33,8 +33,7 @@ extern "C" {
|
|||
extern "C" {
|
||||
STATIC_UNIT_TESTED extern uint16_t dmaBufferOffset;
|
||||
|
||||
STATIC_UNIT_TESTED void fastUpdateLEDDMABuffer(rgbColor24bpp_t *color);
|
||||
STATIC_UNIT_TESTED void updateLEDDMABuffer(uint8_t componentValue);
|
||||
STATIC_UNIT_TESTED void updateLEDDMABuffer(rgbColor24bpp_t *color);
|
||||
}
|
||||
|
||||
TEST(WS2812, updateDMABuffer) {
|
||||
|
@ -45,13 +44,7 @@ TEST(WS2812, updateDMABuffer) {
|
|||
dmaBufferOffset = 0;
|
||||
|
||||
// when
|
||||
#if 0
|
||||
updateLEDDMABuffer(color1.rgb.g);
|
||||
updateLEDDMABuffer(color1.rgb.r);
|
||||
updateLEDDMABuffer(color1.rgb.b);
|
||||
#else
|
||||
fastUpdateLEDDMABuffer(&color1);
|
||||
#endif
|
||||
updateLEDDMABuffer(&color1);
|
||||
|
||||
// then
|
||||
EXPECT_EQ(24, dmaBufferOffset);
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue