diff --git a/src/LedStrips/DotStarLedStrip.cpp b/src/LedStrips/DotStarLedStrip.cpp index 736cf3be15..764460e92c 100644 --- a/src/LedStrips/DotStarLedStrip.cpp +++ b/src/LedStrips/DotStarLedStrip.cpp @@ -6,11 +6,16 @@ */ #include +#include + +#if SUPPORT_REMOTE_COMMANDS +# include +#endif #if SUPPORT_LED_STRIPS && SUPPORT_DMA_DOTSTAR DotStarLedStrip::DotStarLedStrip() noexcept - : LocalLedStrip(LedStripType::DotStar, DefaultDotStarSpiClockFrequency) + : LocalLedStrip(LedStripType::DotStar, DefaultDotStarSpiClockFrequency), colorOrder(ColorOrder::BGR) { } @@ -19,6 +24,14 @@ GCodeResult DotStarLedStrip::Configure(GCodeBuffer& gb, const StringRef& reply, { bool seen = false; GCodeResult rslt = CommonConfigure(gb, reply, pinName, seen); + + if (gb.Seen('K')) + { + uint32_t order; + gb.TryGetLimitedUIValue('K', order, seen, (uint32_t)ColorOrder::count); + colorOrder = (ColorOrder)order; + } + if (seen) { if (!UsesDma()) @@ -39,6 +52,19 @@ GCodeResult DotStarLedStrip::Configure(CanMessageGenericParser& parser, const St { bool seen = false; GCodeResult rslt = CommonConfigure(parser, reply, seen, extra); + + uint32_t order; + if (parser.GetUintParam('K', order)) + { + if (order >= (uint32_t)ColorOrder::count) + { + reply.printf("Invalid color order K=%lu", order); + return GCodeResult::warning; + } + colorOrder = (ColorOrder)order; + seen = true; + } + if (seen) { if (!UsesDma()) @@ -73,11 +99,55 @@ GCodeResult DotStarLedStrip::HandleM150(CanMessageGenericParser& parser, const S params.numLeds = numRemaining; } + uint32_t data; # if USE_16BIT_SPI // Swap bytes for 16-bit SPI - const uint32_t data = ((params.brightness & 0xF8) << 5) | (0xE0 << 8) | ((params.blue & 255)) | ((params.green & 255) << 24) | ((params.red & 255) << 16); + switch (colorOrder) + { + case ColorOrder::BRG: + data = ((params.brightness & 0xF8) << 5) | (0xE0 << 8) | ((params.blue & 255)) | ((params.red & 255) << 24) | ((params.green & 255) << 16); + break; + case ColorOrder::RGB: + data = ((params.brightness & 0xF8) << 5) | (0xE0 << 8) | ((params.red & 255)) | ((params.green & 255) << 24) | ((params.blue & 255) << 16); + break; + case ColorOrder::GRB: // no idea why but RBG and GRB behave the wrong way round in testing with 2 different LED strips so have just swapped them so it works in practice. + data = ((params.brightness & 0xF8) << 5) | (0xE0 << 8) | ((params.red & 255)) | ((params.blue & 255) << 24) | ((params.green & 255) << 16); + break; + case ColorOrder::GBR: + data = ((params.brightness & 0xF8) << 5) | (0xE0 << 8) | ((params.green & 255)) | ((params.blue & 255) << 24) | ((params.red & 255) << 16); + break; + case ColorOrder::RBG: // see above note about GRB + data = ((params.brightness & 0xF8) << 5) | (0xE0 << 8) | ((params.green & 255)) | ((params.red & 255) << 24) | ((params.blue & 255) << 16); + break; + case ColorOrder::BGR: + default: + data = ((params.brightness & 0xF8) << 5) | (0xE0 << 8) | ((params.blue & 255)) | ((params.green & 255) << 24) | ((params.red & 255) << 16); + break; + } # else - const uint32_t data = (params.brightness >> 3) | 0xE0 | ((params.blue & 255) << 8) | ((params.green & 255) << 16) | ((params.red & 255) << 24); + // Untested, might suffer from same RBG/GRB issue as above + switch (colorOrder) + { + case ColorOrder::BRG: + data = (params.brightness >> 3) | 0xE0 | ((params.blue & 255) << 8) | ((params.red & 255) << 16) | ((params.green & 255) << 24); + break; + case ColorOrder::RGB: + data = (params.brightness >> 3) | 0xE0 | ((params.red & 255) << 8) | ((params.green & 255) << 16) | ((params.blue & 255) << 24); + break; + case ColorOrder::RBG: + data = (params.brightness >> 3) | 0xE0 | ((params.red & 255) << 8) | ((params.blue & 255) << 16) | ((params.green & 255) << 24); + break; + case ColorOrder::GBR: + data = (params.brightness >> 3) | 0xE0 | ((params.green & 255) << 8) | ((params.blue & 255) << 16) | ((params.red & 255) << 24); + break; + case ColorOrder::GRB: + data = (params.brightness >> 3) | 0xE0 | ((params.green & 255) << 8) | ((params.red & 255) << 16) | ((params.blue & 255) << 24); + break; + case ColorOrder::BGR: + default: + data = (params.brightness >> 3) | 0xE0 | ((params.blue & 255) << 8) | ((params.green & 255) << 16) | ((params.red & 255) << 24); + break; + } # endif return SendDotStarData(data, params.numLeds, params.following); } @@ -105,11 +175,55 @@ GCodeResult DotStarLedStrip::HandleM150(GCodeBuffer &gb, const StringRef &reply) params.numLeds = numRemaining; } + uint32_t data; # if USE_16BIT_SPI // Swap bytes for 16-bit SPI - const uint32_t data = ((params.brightness & 0xF8) << 5) | (0xE0 << 8) | ((params.blue & 255)) | ((params.green & 255) << 24) | ((params.red & 255) << 16); + switch (colorOrder) + { + case ColorOrder::BRG: + data = ((params.brightness & 0xF8) << 5) | (0xE0 << 8) | ((params.blue & 255)) | ((params.red & 255) << 24) | ((params.green & 255) << 16); + break; + case ColorOrder::RGB: + data = ((params.brightness & 0xF8) << 5) | (0xE0 << 8) | ((params.red & 255)) | ((params.green & 255) << 24) | ((params.blue & 255) << 16); + break; + case ColorOrder::GRB: // no idea why but RBG and GRB behave the wrong way round in testing with 2 different LED strips so have just swapped them so it works in practice. + data = ((params.brightness & 0xF8) << 5) | (0xE0 << 8) | ((params.red & 255)) | ((params.blue & 255) << 24) | ((params.green & 255) << 16); + break; + case ColorOrder::GBR: + data = ((params.brightness & 0xF8) << 5) | (0xE0 << 8) | ((params.green & 255)) | ((params.blue & 255) << 24) | ((params.red & 255) << 16); + break; + case ColorOrder::RBG: // see above note about GRB + data = ((params.brightness & 0xF8) << 5) | (0xE0 << 8) | ((params.green & 255)) | ((params.red & 255) << 24) | ((params.blue & 255) << 16); + break; + case ColorOrder::BGR: + default: + data = ((params.brightness & 0xF8) << 5) | (0xE0 << 8) | ((params.blue & 255)) | ((params.green & 255) << 24) | ((params.red & 255) << 16); + break; + } # else - const uint32_t data = (params.brightness >> 3) | 0xE0 | ((params.blue & 255) << 8) | ((params.green & 255) << 16) | ((params.red & 255) << 24); + // Untested, might suffer from same RBG/GRB issue as above + switch (colorOrder) + { + case ColorOrder::BRG: + data = (params.brightness >> 3) | 0xE0 | ((params.blue & 255) << 8) | ((params.red & 255) << 16) | ((params.green & 255) << 24); + break; + case ColorOrder::RGB: + data = (params.brightness >> 3) | 0xE0 | ((params.red & 255) << 8) | ((params.green & 255) << 16) | ((params.blue & 255) << 24); + break; + case ColorOrder::RBG: + data = (params.brightness >> 3) | 0xE0 | ((params.red & 255) << 8) | ((params.blue & 255) << 16) | ((params.green & 255) << 24); + break; + case ColorOrder::GBR: + data = (params.brightness >> 3) | 0xE0 | ((params.green & 255) << 8) | ((params.blue & 255) << 16) | ((params.red & 255) << 24); + break; + case ColorOrder::GRB: + data = (params.brightness >> 3) | 0xE0 | ((params.green & 255) << 8) | ((params.red & 255) << 16) | ((params.blue & 255) << 24); + break; + case ColorOrder::BGR: + default: + data = (params.brightness >> 3) | 0xE0 | ((params.blue & 255) << 8) | ((params.green & 255) << 16) | ((params.red & 255) << 24); + break; + } # endif return SendDotStarData(data, params.numLeds, params.following); } diff --git a/src/LedStrips/DotStarLedStrip.h b/src/LedStrips/DotStarLedStrip.h index f38d8a1206..dc5f848955 100644 --- a/src/LedStrips/DotStarLedStrip.h +++ b/src/LedStrips/DotStarLedStrip.h @@ -15,6 +15,17 @@ class DotStarLedStrip : public LocalLedStrip { public: + enum class ColorOrder : uint8_t + { + BGR = 0, + BRG, + RGB, + RBG, + GBR, + GRB, + count + }; + DotStarLedStrip() noexcept; GCodeResult Configure(GCodeBuffer& gb, const StringRef& reply, const char *_ecv_array pinName) THROWS(GCodeException) override; @@ -36,6 +47,7 @@ class DotStarLedStrip : public LocalLedStrip unsigned int numRemaining = 0; // how much of the current request remains after the current transfer unsigned int totalSent = 0; // total amount of data sent since the start frame bool needStartFrame = true; + ColorOrder colorOrder; }; #endif