initial commit

This commit is contained in:
Tony
2026-03-26 12:04:08 +08:00
commit 7e8ac7f566
31 changed files with 4304 additions and 0 deletions
+468
View File
@@ -0,0 +1,468 @@
#include "dt8.hpp"
#include "dali_define.hpp"
#include <algorithm>
#include <cmath>
DaliDT8::DaliDT8(DaliBase& base) : base_(base) {}
bool DaliDT8::enableDT8() { return base_.dtSelect(8); }
std::optional<ColorTypeFeature> DaliDT8::getColorTypeFeature(int a) {
const auto addr = DaliComm::toCmdAddr(a);
base_.dtSelect(8);
const auto result = base_.queryCmd(addr, DALI_CMD_QUERY_COLOR_TYPE);
if (!result.has_value()) return std::nullopt;
return ColorTypeFeature(result.value());
}
std::optional<ColorStatus> DaliDT8::getColorStatus(int a) {
const auto addr = DaliComm::toCmdAddr(a);
base_.dtSelect(8);
const auto result = base_.queryCmd(addr, DALI_CMD_QUERY_COLOR_STATUS);
if (!result.has_value()) return std::nullopt;
return ColorStatus(result.value());
}
std::optional<int> DaliDT8::getColTempRaw(int a, int type) {
int selector;
switch (type) {
case 0:
selector = 128;
break;
case 1:
selector = 130;
break;
case 3:
selector = 129;
break;
case 4:
selector = 131;
break;
case 2:
default:
selector = 2;
break;
}
const auto features = getColorTypeFeature(a);
if (!features.has_value() || !features->ctCapable()) return 0;
const auto v = getColourRaw(a, selector);
if (!v.has_value()) return 0;
return v.value();
}
bool DaliDT8::setColTempRaw(int a, int value) {
int v = value;
if (v < 0) v = 0;
if (v > 65535) v = 65535;
const int dtr = v & 0xFF;
const int dtr1 = (v >> 8) & 0xFF;
if (!base_.setDTR(dtr)) return false;
if (!base_.setDTR1(dtr1)) return false;
if (!base_.dtSelect(8)) return false;
if (!base_.setDTRAsColourTemp(a)) return false;
if (!base_.dtSelect(8)) return false;
return base_.activate(a);
}
bool DaliDT8::setColorTemperature(int addr, int kelvin) {
int v = kelvin == 0 ? 1 : kelvin;
const int mirek = static_cast<int>(std::floor(1000000.0 / static_cast<double>(v)));
return setColTempRaw(addr, mirek);
}
std::optional<int> DaliDT8::getColorTemperature(int a) {
const auto mirek = getColourRaw(a, 2);
if (!mirek.has_value() || mirek.value() == 0) return std::nullopt;
const int kelvin = static_cast<int>(std::floor(1000000.0 / static_cast<double>(mirek.value())));
return kelvin;
}
std::optional<int> DaliDT8::getMinColorTemperature(int a) {
const auto mirek = getColTempRaw(a, 0);
if (!mirek.has_value() || mirek.value() == 0) return std::nullopt;
return static_cast<int>(std::floor(1000000.0 / static_cast<double>(mirek.value())));
}
std::optional<int> DaliDT8::getMaxColorTemperature(int a) {
const auto mirek = getColTempRaw(a, 1);
if (!mirek.has_value() || mirek.value() == 0) return std::nullopt;
return static_cast<int>(std::floor(1000000.0 / static_cast<double>(mirek.value())));
}
std::optional<int> DaliDT8::getPhysicalMinColorTemperature(int a) {
const auto mirek = getColTempRaw(a, 3);
if (!mirek.has_value() || mirek.value() == 0) return std::nullopt;
return static_cast<int>(std::floor(1000000.0 / static_cast<double>(mirek.value())));
}
std::optional<int> DaliDT8::getPhysicalMaxColorTemperature(int a) {
const auto mirek = getColTempRaw(a, 4);
if (!mirek.has_value() || mirek.value() == 0) return std::nullopt;
return static_cast<int>(std::floor(1000000.0 / static_cast<double>(mirek.value())));
}
bool DaliDT8::setColourRaw(int addr, int x1, int y1) {
const int x1L = x1 & 0xFF;
const int y1L = y1 & 0xFF;
const int x1H = (x1 >> 8) & 0xFF;
const int y1H = (y1 >> 8) & 0xFF;
const int a = addr / 2;
if (!base_.setDTR(x1L)) return false;
if (!base_.setDTR1(x1H)) return false;
if (!base_.dtSelect(8)) return false;
if (!base_.setDTRAsColourX(a)) return false;
if (!base_.setDTR(y1L)) return false;
if (!base_.setDTR1(y1H)) return false;
if (!base_.dtSelect(8)) return false;
if (!base_.setDTRAsColourY(a)) return false;
if (!base_.dtSelect(8)) return false;
return base_.activate(a);
}
bool DaliDT8::setTemporaryColourXRaw(int addr, int x1) {
const int x1L = x1 & 0xFF;
const int x1H = (x1 >> 8) & 0xFF;
const int a = addr / 2;
return base_.setDTR(x1L) && base_.setDTR1(x1H) && base_.dtSelect(8) && base_.setDTRAsColourX(a);
}
bool DaliDT8::setTemporaryColourYRaw(int addr, int y1) {
const int y1L = y1 & 0xFF;
const int y1H = (y1 >> 8) & 0xFF;
const int a = addr / 2;
return base_.setDTR(y1L) && base_.setDTR1(y1H) && base_.dtSelect(8) && base_.setDTRAsColourY(a);
}
bool DaliDT8::setTemporaryColourXY(int a, double x, double y) {
double xClamped = std::clamp(x, 0.0, 1.0);
double yClamped = std::clamp(y, 0.0, 1.0);
const int x1 = static_cast<int>(std::round(xClamped * 65535.0));
const int y1 = static_cast<int>(std::round(yClamped * 65535.0));
const int addr = a * 2 + 1;
return setTemporaryColourXRaw(addr, x1) && setTemporaryColourYRaw(addr, y1);
}
bool DaliDT8::setTemporaryColourTemperature(int a, int kelvin) {
int k = kelvin <= 0 ? 1 : kelvin;
const int mirek = static_cast<int>(std::floor(1000000.0 / static_cast<double>(k)));
const int addr = a * 2 + 1;
const int dtr = mirek & 0xFF;
const int dtr1 = (mirek >> 8) & 0xFF;
const int dec = addr / 2;
return base_.setDTR(dtr) && base_.setDTR1(dtr1) && base_.dtSelect(8) && base_.setDTRAsColourTemp(dec);
}
bool DaliDT8::setTemporaryPrimaryDimLevel(int a, int n, double level) {
int idx = std::clamp(n, 0, 5);
double v = std::clamp(level, 0.0, 1.0);
int raw = static_cast<int>(std::round(v * 65535.0));
if (raw > 65534) raw = 65534;
const int lsb = raw & 0xFF;
const int msb = (raw >> 8) & 0xFF;
const int addr = a * 2 + 1;
return base_.setDTR(lsb) && base_.setDTR1(msb) && base_.setDTR2(idx) &&
base_.dtSelect(8) && base_.sendExtCmd(addr, DALI_CMD_DT8_SET_TEMPORARY_PRIMARY_DIM_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 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 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 addr = a * 2 + 1;
return base_.setDTR(control & 0xFF) && base_.dtSelect(8) &&
base_.sendExtCmd(addr, DALI_CMD_DT8_SET_TEMPORARY_RGBWAF_CONTROL);
}
bool DaliDT8::copyReportToTemporary(int a) { return base_.dtSelect(8) && base_.copyReportColourToTemp(a); }
bool DaliDT8::stepXUp(int a) {
return base_.dtSelect(8) && base_.sendExtCmd(a * 2 + 1, DALI_CMD_DT8_STEP_UP_X_COORDINATE);
}
bool DaliDT8::stepXDown(int a) {
return base_.dtSelect(8) && base_.sendExtCmd(a * 2 + 1, DALI_CMD_DT8_STEP_DOWN_X_COORDINATE);
}
bool DaliDT8::stepYUp(int a) {
return base_.dtSelect(8) && base_.sendExtCmd(a * 2 + 1, DALI_CMD_DT8_STEP_UP_Y_COORDINATE);
}
bool DaliDT8::stepYDown(int a) {
return base_.dtSelect(8) && base_.sendExtCmd(a * 2 + 1, DALI_CMD_DT8_STEP_DOWN_Y_COORDINATE);
}
bool DaliDT8::stepTcCooler(int a) {
return base_.dtSelect(8) &&
base_.sendExtCmd(a * 2 + 1, DALI_CMD_DT8_STEP_UP_COLOR_TEMPERATURE);
}
bool DaliDT8::stepTcWarmer(int a) {
return base_.dtSelect(8) &&
base_.sendExtCmd(a * 2 + 1, DALI_CMD_DT8_STEP_DOWN_COLOR_TEMPERATURE);
}
bool DaliDT8::setColourRGBRaw(int addr, int r, int g, int b) {
const int a = addr / 2;
return base_.setDTR(r) && base_.setDTR1(g) && base_.setDTR2(b) && base_.dtSelect(8) && base_.setDTRAsColourRGB(a) && base_.dtSelect(8) && base_.activate(a);
}
bool DaliDT8::setColour(int a, double x, double y) {
double xClamped = std::clamp(x, 0.0, 1.0);
double yClamped = std::clamp(y, 0.0, 1.0);
const int x1 = static_cast<int>(std::round(xClamped * 65535.0));
const int y1 = static_cast<int>(std::round(yClamped * 65535.0));
const int addr = a * 2 + 1;
return setColourRaw(addr, x1, y1);
}
std::optional<int> DaliDT8::getColourRaw(int a, int type) {
const uint8_t code = static_cast<uint8_t>(type & 0xFF);
const auto features = getColorTypeFeature(a);
if (!features.has_value()) return std::nullopt;
if ((code == 2 || code == 128 || code == 129 || code == 130 || code == 131) && !features->ctCapable()) {
return std::nullopt;
}
bool is8bit = false;
if (code == 82 || (code >= 9 && code <= 15) || (code >= 201 && code <= 207) || code == 208 ||
(code >= 233 && code <= 239) || code == 240) {
is8bit = true;
}
if (!base_.setDTR(code)) return std::nullopt;
if (!base_.dtSelect(8)) return std::nullopt;
if (!base_.queryColourValue(a)) return std::nullopt;
const auto dtr = base_.getDTR(a);
const auto dtr1 = base_.getDTR1(a);
if (!dtr.has_value() || !dtr1.has_value()) return std::nullopt;
if (is8bit) {
if (dtr.value() == 0xFF) return std::nullopt;
return dtr.value() & 0xFF;
}
if (dtr.value() == 0xFF && dtr1.value() == 0xFF) return std::nullopt;
return ((dtr1.value() & 0xFF) << 8) | (dtr.value() & 0xFF);
}
std::vector<double> DaliDT8::getColour(int a) {
const auto x = getColourRaw(a, 0);
const auto y = getColourRaw(a, 1);
if (!x.has_value() || !y.has_value()) return {};
return {x.value() / 65535.0, y.value() / 65535.0};
}
bool DaliDT8::setColourRGB(int addr, int r, int g, int b) {
int R = std::clamp(r, 0, 255);
int G = std::clamp(g, 0, 255);
int B = std::clamp(b, 0, 255);
const auto xy = DaliColor::rgb2xy(static_cast<double>(R) / 255.0, static_cast<double>(G) / 255.0,
static_cast<double>(B) / 255.0);
return setColour(addr, xy[0], xy[1]);
}
std::vector<int> DaliDT8::getColourRGB(int a) {
const auto xy = getColour(a);
if (xy.empty()) return {};
const auto rgb = DaliColor::xy2rgb(xy[0], xy[1]);
return {rgb[0], rgb[1], rgb[2]};
}
bool DaliDT8::activateTemporaryColour(int a) { return base_.dtSelect(8) && base_.activate(a); }
std::optional<int> DaliDT8::getPrimaryDimLevel(int a, int n) {
if (n < 0 || n > 5) return std::nullopt;
return getColourRaw(a, 3 + n);
}
std::optional<int> DaliDT8::getRedDimLevel(int a) { return getColourRaw(a, 9); }
std::optional<int> DaliDT8::getGreenDimLevel(int a) { return getColourRaw(a, 10); }
std::optional<int> DaliDT8::getBlueDimLevel(int a) { return getColourRaw(a, 11); }
std::optional<int> DaliDT8::getWhiteDimLevel(int a) { return getColourRaw(a, 12); }
std::optional<int> DaliDT8::getAmberDimLevel(int a) { return getColourRaw(a, 13); }
std::optional<int> DaliDT8::getFreecolourDimLevel(int a) { return getColourRaw(a, 14); }
std::optional<int> DaliDT8::getRGBWAFControl(int a) { return getColourRaw(a, 15); }
std::optional<int> DaliDT8::getTemporaryXRaw(int a) { return getColourRaw(a, 192); }
std::optional<int> DaliDT8::getTemporaryYRaw(int a) { return getColourRaw(a, 193); }
std::optional<int> DaliDT8::getTemporaryColourTemperatureRaw(int a) { return getColourRaw(a, 194); }
std::optional<int> DaliDT8::getTemporaryPrimaryDimLevel(int a, int n) {
if (n < 0 || n > 5) return std::nullopt;
return getColourRaw(a, 195 + n);
}
std::optional<int> DaliDT8::getTemporaryRedDimLevel(int a) { return getColourRaw(a, 201); }
std::optional<int> DaliDT8::getTemporaryGreenDimLevel(int a) { return getColourRaw(a, 202); }
std::optional<int> DaliDT8::getTemporaryBlueDimLevel(int a) { return getColourRaw(a, 203); }
std::optional<int> DaliDT8::getTemporaryWhiteDimLevel(int a) { return getColourRaw(a, 204); }
std::optional<int> DaliDT8::getTemporaryAmberDimLevel(int a) { return getColourRaw(a, 205); }
std::optional<int> DaliDT8::getTemporaryFreecolourDimLevel(int a) { return getColourRaw(a, 206); }
std::optional<int> DaliDT8::getTemporaryRGBWAFControl(int a) { return getColourRaw(a, 207); }
std::optional<int> DaliDT8::getTemporaryColourType(int a) { return getColourRaw(a, 208); }
std::vector<double> DaliDT8::getTemporaryColour(int a) {
const auto x = getTemporaryXRaw(a);
const auto y = getTemporaryYRaw(a);
if (!x.has_value() || !y.has_value()) return {};
return {x.value() / 65535.0, y.value() / 65535.0};
}
std::optional<int> DaliDT8::getTemporaryColorTemperature(int a) {
const auto mirek = getTemporaryColourTemperatureRaw(a);
if (!mirek.has_value() || mirek.value() == 0) return std::nullopt;
return static_cast<int>(std::floor(1000000.0 / static_cast<double>(mirek.value())));
}
std::optional<int> DaliDT8::getReportXRaw(int a) { return getColourRaw(a, 224); }
std::optional<int> DaliDT8::getReportYRaw(int a) { return getColourRaw(a, 225); }
std::optional<int> DaliDT8::getReportColourTemperatureRaw(int a) { return getColourRaw(a, 226); }
std::optional<int> DaliDT8::getReportPrimaryDimLevel(int a, int n) {
if (n < 0 || n > 5) return std::nullopt;
return getColourRaw(a, 227 + n);
}
std::optional<int> DaliDT8::getReportRedDimLevel(int a) { return getColourRaw(a, 233); }
std::optional<int> DaliDT8::getReportGreenDimLevel(int a) { return getColourRaw(a, 234); }
std::optional<int> DaliDT8::getReportBlueDimLevel(int a) { return getColourRaw(a, 235); }
std::optional<int> DaliDT8::getReportWhiteDimLevel(int a) { return getColourRaw(a, 236); }
std::optional<int> DaliDT8::getReportAmberDimLevel(int a) { return getColourRaw(a, 237); }
std::optional<int> DaliDT8::getReportFreecolourDimLevel(int a) { return getColourRaw(a, 238); }
std::optional<int> DaliDT8::getReportRGBWAFControl(int a) { return getColourRaw(a, 239); }
std::optional<int> DaliDT8::getReportColourType(int a) { return getColourRaw(a, 240); }
std::vector<double> DaliDT8::getReportColour(int a) {
const auto x = getReportXRaw(a);
const auto y = getReportYRaw(a);
if (!x.has_value() || !y.has_value()) return {};
return {x.value() / 65535.0, y.value() / 65535.0};
}
std::optional<int> DaliDT8::getReportColorTemperature(int a) {
const auto mirek = getReportColourTemperatureRaw(a);
if (!mirek.has_value() || mirek.value() == 0) return std::nullopt;
return static_cast<int>(std::floor(1000000.0 / static_cast<double>(mirek.value())));
}
std::optional<int> DaliDT8::getNumberOfPrimaries(int a) { return getColourRaw(a, 82); }
std::optional<int> DaliDT8::getPrimaryXRaw(int a, int n) {
if (n < 0 || n > 5) return std::nullopt;
return getColourRaw(a, 64 + 3 * n);
}
std::optional<int> DaliDT8::getPrimaryYRaw(int a, int n) {
if (n < 0 || n > 5) return std::nullopt;
return getColourRaw(a, 65 + 3 * n);
}
std::optional<int> DaliDT8::getPrimaryTy(int a, int n) {
if (n < 0 || n > 5) return std::nullopt;
return getColourRaw(a, 66 + 3 * n);
}
std::vector<double> DaliDT8::getSceneColor(int a, int sense) {
const auto bright = base_.getScene(a, sense);
if (!bright.has_value() || bright.value() == 255) return {};
base_.copyReportColourToTemp(a);
return getColour(a);
}
bool DaliDT8::storePrimaryTy(int a, int n, int ty) {
int idx = std::clamp(n, 0, 5);
int t = std::clamp(ty, 0, 65535);
const int lsb = t & 0xFF;
const int msb = (t >> 8) & 0xFF;
const int addr = a * 2 + 1;
return base_.setDTR(lsb) && base_.setDTR1(msb) && base_.setDTR2(idx) &&
base_.dtSelect(8) && base_.sendExtCmd(addr, DALI_CMD_DT8_STORE_PRIMARY_N_TY);
}
bool DaliDT8::storePrimaryXY(int a, int n, double x, double y) {
int idx = std::clamp(n, 0, 5);
if (!setTemporaryColourXY(a, x, y)) return false;
const int addr = a * 2 + 1;
return base_.setDTR2(idx) && base_.dtSelect(8) &&
base_.sendExtCmd(addr, DALI_CMD_DT8_STORE_PRIMARY_N_XY);
}
bool DaliDT8::storeColourTempLimitRaw(int a, int limitType, int mirek) {
int m = mirek;
if (m < 1) m = 1;
if (m > 65534) m = 65534;
const int lsb = m & 0xFF;
const int msb = (m >> 8) & 0xFF;
const int addr = a * 2 + 1;
return base_.setDTR(lsb) && base_.setDTR1(msb) && base_.setDTR2(limitType & 0xFF) &&
base_.dtSelect(8) && base_.sendExtCmd(addr, DALI_CMD_DT8_STORE_COLOR_TEMPERATURE_LIMIT);
}
bool DaliDT8::storeColourTempLimit(int a, int limitType, int kelvin) {
const int mirek = static_cast<int>(std::floor(1000000.0 / static_cast<double>(kelvin <= 0 ? 1 : kelvin)));
return storeColourTempLimitRaw(a, limitType, mirek);
}
bool DaliDT8::setGearAutoActivate(int a, bool enable) {
const int addr = a * 2 + 1;
const int opts = enable ? 0x01 : 0x00;
return base_.setDTR(opts) && base_.dtSelect(8) &&
base_.sendExtCmd(addr, DALI_CMD_DT8_SET_GEAR_FEATURES);
}
bool DaliDT8::assignColourToLinkedChannels(int a, int colourId) {
const int addr = a * 2 + 1;
const int id = std::clamp(colourId, 0, 6);
return base_.setDTR(id) && base_.dtSelect(8) &&
base_.sendExtCmd(addr, DALI_CMD_DT8_ASSIGN_COLOR_TO_LINKED_CHANNEL);
}
bool DaliDT8::startAutoCalibration(int a) {
const int addr = a * 2 + 1;
return base_.dtSelect(8) && base_.sendExtCmd(addr, DALI_CMD_DT8_START_AUTO_CALIBRATION);
}
std::optional<int> DaliDT8::getGearFeaturesStatus(int a) {
const int addr = a * 2 + 1;
base_.dtSelect(8);
return base_.queryCmd(addr, DALI_CMD_DT8_QUERY_GEAR_FEATURES_STATUS);
}
std::optional<int> DaliDT8::getRGBWAFControlDirect(int a) {
const int addr = a * 2 + 1;
base_.dtSelect(8);
return base_.queryCmd(addr, DALI_CMD_DT8_QUERY_RGBWAF_CONTROL);
}
std::optional<int> DaliDT8::getAssignedColourForChannel(int a, int channelId) {
const int addr = a * 2 + 1;
const int ch = channelId & 0xFF;
if (!base_.setDTR(ch)) return std::nullopt;
if (!base_.dtSelect(8)) return std::nullopt;
return base_.queryCmd(addr, DALI_CMD_DT8_QUERY_ASSIGNED_COLOR);
}
std::optional<int> DaliDT8::getExtendedVersion(int a) {
const int addr = a * 2 + 1;
base_.dtSelect(8);
return base_.queryCmd(addr, DALI_CMD_DT8_QUERY_EXTENDED_VERSION);
}