From 439a2078ba4cd6665a258a062efd4b9c9216784c Mon Sep 17 00:00:00 2001 From: Tony Date: Wed, 3 Jun 2026 15:45:38 +0800 Subject: [PATCH] Enhance DaliDT8: add support for preferred color type handling and temporary color operations Signed-off-by: Tony --- include/dt8.hpp | 16 +++++++++- src/dt8.cpp | 80 ++++++++++++++++++++++++++++++++++++++++++------- 2 files changed, 84 insertions(+), 12 deletions(-) diff --git a/include/dt8.hpp b/include/dt8.hpp index e8c32fb..811b55e 100644 --- a/include/dt8.hpp +++ b/include/dt8.hpp @@ -91,6 +91,11 @@ enum class Dt8SceneStoreColorMode { rgbcw, }; +enum class Dt8PreferredColorType { + xy, + rgbwaf, +}; + class DaliDT8 { public: explicit DaliDT8(DaliBase& base); @@ -139,6 +144,10 @@ class DaliDT8 { std::optional getColourRaw(int a, int type); std::vector getColour(int a); bool setColourRGB(int addr, int r, int g, int b); + bool setTemporaryColourRGBPreferred(int addr, int r, int g, int b, + Dt8PreferredColorType preferredColorType = Dt8PreferredColorType::xy); + bool setColourRGBPreferred(int addr, int r, int g, int b, + Dt8PreferredColorType preferredColorType = Dt8PreferredColorType::xy); bool setColourRGBW(int addr, int r, int g, int b, int w); bool setColourRGBCW(int addr, int r, int g, int b, int coolWhite, int warmWhite); bool setColourRGBWAF(int addr, int r, int g, int b, int w, int amber, int freecolour, @@ -203,11 +212,15 @@ class DaliDT8 { bool storeSceneSnapshot(int address, int scene, int brightness, Dt8SceneStoreColorMode colorMode = Dt8SceneStoreColorMode::disabled, int colorTemperature = 0, int red = 0, int green = 0, int blue = 0, - int white = 0, int amber = 0, int freecolour = 255, + int white = 0, int amber = 0, int freecolour = 254, int rgbwafControl = -1, int gateway = -1); bool storePowerOnLevelSnapshot(int address, int level); + bool storePowerOnLevelColorSnapshot(int address, int level, int r, int g, int b, + Dt8PreferredColorType preferredColorType = Dt8PreferredColorType::xy); bool storeSystemFailureLevelSnapshot(int address, int level); + bool storeSystemFailureLevelColorSnapshot(int address, int level, int r, int g, int b, + Dt8PreferredColorType preferredColorType = Dt8PreferredColorType::xy); std::optional getPowerOnLevelColorReport(int a); std::optional getSystemFailureLevelColorReport(int a); bool storeColourTempLimitRaw(int a, int limitType, int mirek); @@ -223,6 +236,7 @@ class DaliDT8 { std::optional getExtendedVersion(int a); private: + Dt8PreferredColorType resolvePreferredColorType(int address, Dt8PreferredColorType preferredColorType); std::optional buildLevelColorReport(int a, std::optional level); std::vector getReportRGBWAF(int a); diff --git a/src/dt8.cpp b/src/dt8.cpp index 656e61f..7bbc052 100644 --- a/src/dt8.cpp +++ b/src/dt8.cpp @@ -6,6 +6,7 @@ #include namespace { +constexpr int kRgbControl = 0x07; constexpr int kRgbWControl = 0x0F; constexpr int kRgbCwControl = 0x1F; constexpr int kRgbWafControl = 0x3F; @@ -33,6 +34,25 @@ std::optional kelvinFromMirek(std::optional mirek) { DaliDT8::DaliDT8(DaliBase& base) : base_(base) {} +Dt8PreferredColorType DaliDT8::resolvePreferredColorType( + int address, Dt8PreferredColorType preferredColorType) { + if (address < 0 || address > 63) return preferredColorType; + const auto features = getColorTypeFeature(address); + if (!features.has_value()) return preferredColorType; + + switch (preferredColorType) { + case Dt8PreferredColorType::rgbwaf: + if (features->rgbwafCapable()) return Dt8PreferredColorType::rgbwaf; + if (features->xyCapable()) return Dt8PreferredColorType::xy; + break; + case Dt8PreferredColorType::xy: + if (features->xyCapable()) return Dt8PreferredColorType::xy; + if (features->rgbwafCapable()) return Dt8PreferredColorType::rgbwaf; + break; + } + return preferredColorType; +} + bool DaliDT8::enableDT8() { return base_.dtSelect(8); } std::optional DaliDT8::getColorTypeFeature(int a) { @@ -203,26 +223,27 @@ bool DaliDT8::setTemporaryPrimaryDimLevel(int a, int n, double level) { } bool DaliDT8::setTemporaryRGBDimLevels(int a, int r, int g, int b) { - const int R = std::clamp(r, 0, 255); - const int G = std::clamp(g, 0, 255); - const int B = std::clamp(b, 0, 255); + const int R = std::clamp(r, 0, 254); + const int G = std::clamp(g, 0, 254); + const int B = std::clamp(b, 0, 254); const int addr = a * 2 + 1; return base_.setDTR(R) && base_.setDTR1(G) && base_.setDTR2(B) && base_.dtSelect(8) && base_.sendExtCmd(addr, DALI_CMD_DT8_SET_TEMPORARY_RGB_DIM_LEVELS); } bool DaliDT8::setTemporaryWAFDimLevels(int a, int w, int amber, int freecolour) { - const int W = std::clamp(w, 0, 255); - const int A = std::clamp(amber, 0, 255); - const int F = std::clamp(freecolour, 0, 255); + const int W = std::clamp(w, 0, 254); + const int A = std::clamp(amber, 0, 254); + const int F = std::clamp(freecolour, 0, 254); const int addr = a * 2 + 1; return base_.setDTR(W) && base_.setDTR1(A) && base_.setDTR2(F) && base_.dtSelect(8) && base_.sendExtCmd(addr, DALI_CMD_DT8_SET_TEMPORARY_WAF_DIM_LEVELS); } bool DaliDT8::setTemporaryRGBWAFControl(int a, int control) { + const int storedControl = std::clamp(control, 0, 254); const int addr = a * 2 + 1; - return base_.setDTR(control & 0xFF) && base_.dtSelect(8) && + return base_.setDTR(storedControl) && base_.dtSelect(8) && base_.sendExtCmd(addr, DALI_CMD_DT8_SET_TEMPORARY_RGBWAF_CONTROL); } @@ -233,7 +254,6 @@ bool DaliDT8::setTemporaryRGBWAFDimLevels(int a, int r, int g, int b, int w, int } bool DaliDT8::setTemporaryColourMask(int a) { - if (setTemporaryRGBDimLevels(a, 255, 255, 255)) return true; if (base_.setDTR(0xFF) && base_.setDTR1(0xFF) && base_.dtSelect(8) && base_.setDTRAsColourTemp(a)) { return true; } @@ -345,12 +365,38 @@ bool DaliDT8::setColourRGB(int addr, int r, int g, int b) { return setColour(addr, xy[0], xy[1]); } +bool DaliDT8::setTemporaryColourRGBPreferred(int addr, int r, int g, int b, + Dt8PreferredColorType preferredColorType) { + const int R = std::clamp(r, 0, 255); + const int G = std::clamp(g, 0, 255); + const int B = std::clamp(b, 0, 255); + const auto resolved = resolvePreferredColorType(addr, preferredColorType); + + switch (resolved) { + case Dt8PreferredColorType::rgbwaf: + return setTemporaryRGBDimLevels(addr, R, G, B) && setTemporaryRGBWAFControl(addr, kRgbControl); + case Dt8PreferredColorType::xy: { + const auto xy = DaliColor::rgb2xy(static_cast(R) / 255.0, + static_cast(G) / 255.0, + static_cast(B) / 255.0); + return setTemporaryColourXY(addr, xy[0], xy[1]); + } + } + return false; +} + +bool DaliDT8::setColourRGBPreferred(int addr, int r, int g, int b, + Dt8PreferredColorType preferredColorType) { + return setTemporaryColourRGBPreferred(addr, r, g, b, preferredColorType) && + activateTemporaryColour(addr); +} + bool DaliDT8::setColourRGBW(int addr, int r, int g, int b, int w) { - return setColourRGBWAF(addr, r, g, b, w, 255, 255, kRgbWControl); + return setColourRGBWAF(addr, r, g, b, w, 254, 254, kRgbWControl); } bool DaliDT8::setColourRGBCW(int addr, int r, int g, int b, int coolWhite, int warmWhite) { - return setColourRGBWAF(addr, r, g, b, coolWhite, warmWhite, 255, kRgbCwControl); + return setColourRGBWAF(addr, r, g, b, coolWhite, warmWhite, 254, kRgbCwControl); } bool DaliDT8::setColourRGBWAF(int addr, int r, int g, int b, int w, int amber, int freecolour, @@ -391,7 +437,7 @@ bool DaliDT8::storeSceneSnapshot(int address, int scene, int brightness, } case Dt8SceneStoreColorMode::rgbw: { const int control = rgbwafControl < 0 ? kRgbWControl : rgbwafControl; - if (!setTemporaryRGBWAFDimLevels(address, red, green, blue, white, 255, 255, control)) return false; + if (!setTemporaryRGBWAFDimLevels(address, red, green, blue, white, 254, 254, control)) return false; break; } case Dt8SceneStoreColorMode::rgbcw: { @@ -416,6 +462,12 @@ bool DaliDT8::storePowerOnLevelSnapshot(int address, int level) { return base_.setDTR(storedLevel) && base_.dtSelect(8) && base_.storeDTRAsPoweredBright(address); } +bool DaliDT8::storePowerOnLevelColorSnapshot(int address, int level, int r, int g, int b, + Dt8PreferredColorType preferredColorType) { + return setTemporaryColourRGBPreferred(address, r, g, b, preferredColorType) && + storePowerOnLevelSnapshot(address, level); +} + bool DaliDT8::storeSystemFailureLevelSnapshot(int address, int level) { const int storedLevel = std::clamp(level, 0, 254); // DT SELECT is one-shot and SET DTR consumes any earlier selection. @@ -423,6 +475,12 @@ bool DaliDT8::storeSystemFailureLevelSnapshot(int address, int level) { base_.storeDTRAsSystemFailureLevel(address); } +bool DaliDT8::storeSystemFailureLevelColorSnapshot(int address, int level, int r, int g, int b, + Dt8PreferredColorType preferredColorType) { + return setTemporaryColourRGBPreferred(address, r, g, b, preferredColorType) && + storeSystemFailureLevelSnapshot(address, level); +} + bool DaliDT8::activateTemporaryColour(int a) { return base_.dtSelect(8) && base_.activate(a); } std::optional DaliDT8::getPrimaryDimLevel(int a, int n) {