diff --git a/src/dali/commands_dt8.hpp b/src/dali/commands_dt8.hpp new file mode 100644 index 0000000..dbefbdc --- /dev/null +++ b/src/dali/commands_dt8.hpp @@ -0,0 +1,55 @@ +/* + * Copyright (c) 2015-2016, Arkadiusz Materek (arekmat@poczta.fm) + * + * Licensed under GNU General Public License 3.0 or later. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. + */ + +#ifndef DALI_COMMANDS_DT8_HPP_ +#define DALI_COMMANDS_DT8_HPP_ + +#include + +namespace dali { + +enum class CommandDT8 { + SET_TEMPORARY_X_COORDINATE_WORD = 224, + SET_TEMPORARY_Y_COORDINATE_WORD = 225, + ACTIVATE = 226, + X_COORDINATE_STEP_UP = 227, + X_COORDINATE_STEP_DOWN = 228, + Y_COORDINATE_STEP_UP = 229, + Y_COORDINATE_STEP_DOWN = 230, + SET_TEMPORARY_COLOUR_TEMPERATURE = 231, + COLOUR_TEMPERATURE_STEP_COOLER = 232, + COLOUR_TEMPERATURE_STEP_WARMER = 233, + SET_TEMPORARY_PRIMARY_N_DIMLEVEL = 234, + SET_TEMPORARY_RGB_DIMLEVEL = 235, + SET_TEMPORARY_WAF_DIMLEVEL = 236, + SET_TEMPORARY_RGBWAF_CONTROL = 237, + COPY_REPORT_TO_TEMPORARY = 238, + + STORE_TY_PRIMARY_N = 240, + STORE_XY_COORDINATE_PRIMARY_N = 241, + STORE_COLOUR_TEMPERATURE_LIMIT = 242, + STORE_GEAR_FEATURES_STATUS = 243, + + ASSIGN_COLOUR_TO_LINKED_CHANNEL = 245, + START_AUTO_CALIBRATION = 246, + QUERY_GEAR_FEATURES_STATUS = 247, + QUERY_COLOUR_STATUS = 248, + QUERY_COLOUR_TYPE_FEATURES = 249, + QUERY_COLOUR_VALUE = 250, + QUERY_RGBWAF_CONTROL = 251, + QUERY_ASSIGNED_COLOUR = 252, + + QUERY_EXTENDED_VERSION_NUMBER = 255, +}; + +} +// namespace dali + +#endif // DALI_COMMANDS_DT8_HPP_ diff --git a/src/dali/config.hpp b/src/dali/config.hpp index d84351e..fc58991 100644 --- a/src/dali/config.hpp +++ b/src/dali/config.hpp @@ -14,11 +14,13 @@ #define DALI_VERSION 1 #define DALI_DEVICE_TYPE 8 -#define DALI_BANKS 3 +#define DALI_BANKS 5 #define DALI_BANK0_ADDR 0 // Bank 0 (16 bytes) according to 62386-102 #define DALI_BANK1_ADDR 16 // Bank 1 (16 bytes) according to 62386-102 #define DALI_BANK2_ADDR 32 // Bank 2 (28 bytes) data 62386-102 (26 bytes) -#define DALI_BANK3_ADDR 60 +#define DALI_BANK3_ADDR 60 // Bank 3 (44 bytes) configuration DT8 62386-209 +#define DALI_BANK4_ADDR 104 // Bank 4 (148 bytes) data DT8 62386-209 +#define DALI_BANK5_ADDR 252 #define DALI_PHISICAL_MIN_LEVEL 1 diff --git a/src/dali/config_dt8.hpp b/src/dali/config_dt8.hpp new file mode 100644 index 0000000..b2b82d3 --- /dev/null +++ b/src/dali/config_dt8.hpp @@ -0,0 +1,33 @@ +/* + * Copyright (c) 2015-2016, Arkadiusz Materek (arekmat@poczta.fm) + * + * All right reversed. Usage for commercial on not commercial + * purpose without written permission is not allowed. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. + */ + +#ifndef DALI_CONFIG_DT8_H_ +#define DALI_CONFIG_DT8_H_ + +#include "config.hpp" + +#if DALI_DEVICE_TYPE == 8 + +# define DALI_DT8 + +# define DALI_DT8_SUPPORT_XY +# define DALI_DT8_SUPPORT_TC +# define DALI_DT8_SUPPORT_PRIMARY_N +// # define DALI_DT8_SUPPORT_RGBWAF // TODO + +#define DALI_DT8_NUMBER_OF_PRIMARIES 3 + +# define DEFAULT_RGBWAF_CONTROL (DALI_DT8_RGBWAF_CONTROL_CANNELS_MASK | (DALI_DT8_RGBWAF_CONTROL_COLOR << 6)) + + +#endif // DALI_DEVICE_TYPE == 8 + +#endif // DALI_CONFIG_DT8_H_ diff --git a/src/dali/controller/color_dt8.cpp b/src/dali/controller/color_dt8.cpp new file mode 100644 index 0000000..000ed1d --- /dev/null +++ b/src/dali/controller/color_dt8.cpp @@ -0,0 +1,311 @@ +/* + * Copyright (c) 2015-2016, Arkadiusz Materek (arekmat@poczta.fm) + * + * Licensed under GNU General Public License 3.0 or later. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. + */ + +#include "color_dt8.hpp" + +#include +#include + +// TC values in mired +#define TC_MIN 50 +#define TC_MAX 1000 +#define TC_STEP 50 + +namespace dali { +namespace controller { +namespace { + +const PointXY tc2xy[] = { + { 16807, 16884 }, // 0 - minimal possible TC + { 18392, 18893 }, // 1 + { 20382, 21047 }, // 2 + { 22617, 23043 }, // 3 + { 24933, 24691 }, // 4 + { 27200, 25910 }, // 5 + { 29325, 26700 }, // 6 + { 31261, 27111 }, // 7 + { 32992, 27214 }, // 8 + { 34517, 27086 }, // 9 + { 35859, 26793 }, // 10 + { 37031, 26394 }, // 11 + { 38073, 25925 }, // 12 + { 38980, 25430 }, // 13 + { 39799, 24916 }, // 14 + { 40521, 24411 }, // 15 + { 41177, 23916 }, // 16 + { 41762, 23446 }, // 17 + { 42291, 23001 }, // 18 + { 42779, 22574 }, // 19 - maximal possible TC +}; + +const Float kZero(0); +const Float kOne(65536); + +bool isCalibrated(const Primary& p) { + return (p.ty <= DALI_DT8_PRIMARY_TY_MAX) && (p.xy.x != DALI_DT8_MASK16) && (p.xy.x != DALI_DT8_MASK16); +} + +bool xyToPrimary1(PointXY p, const PointXY prim_xy[], Float out[]) { + out[0] = kOne; + return (prim_xy[0].x != p.x) || (prim_xy[0].y != p.y); +} + +Float float_abs(Float x) { + if (x < kZero) { + return kZero - x; + } + return x; +} + +bool xyToPrimary2(PointXY p, const PointXY prim_xy[], Float out[]) { + bool limitError = false; + Float x1(prim_xy[0].x); + Float x2(prim_xy[1].x); + Float y1(prim_xy[0].y); + Float y2(prim_xy[1].y); + Float tmpx = x1 - x2; + Float tmpy = y1 - y2; + + Float l1, l2; + if (float_abs(tmpx) >= float_abs(tmpy)) { + Float x = Float(p.x); + l1 = (x - x2) / tmpx; + l2 = (x1 - x) / tmpx; + } else { + Float y = Float(p.y); + l1 = (y - y2) / tmpy; + l2 = (y1 - y) / tmpy; + } + + if (l1 < kZero) { + l1 = kZero; + limitError = true; + } else if (l1 > kOne) { + l1 = kOne; + limitError = true; + } + + if (l2 < kZero) { + l2 = kZero; + limitError = true; + } else if (l2 > kOne) { + l2 = kOne; + limitError = true; + } + + out[0] = l1; + out[1] = l2; + + return limitError; +} + +bool xyToPrimary3(PointXY p, const PointXY prim_xy[], Float out[]) { + bool limitError = false; + Float x(p.x); + Float y(p.y); + Float x1(prim_xy[0].x); + Float y1(prim_xy[0].y); + Float x2(prim_xy[1].x); + Float y2(prim_xy[1].y); + Float x3(prim_xy[2].x); + Float y3(prim_xy[2].y); + Float tmp = (x1 * (y2 - y3) + x2 * (y3 - y1) + x3 * (y1 - y2)); + + if (tmp == Float(0)) { + return true; + } + + Float l1 = (x * (y2 - y3) + y * (x3 - x2) + x2 * y3 - x3 * y2) / tmp; + if (l1 < kZero) { + l1 = kZero; + limitError = true; + } else if (l1 > kOne) { + l1 = kOne; + limitError = true; + } + + Float l2 = kZero - (x * (y1 - y3) + y * (x3 - x1) + x1 * y3 - x3 * y1) / tmp; + if (l2 < kZero) { + l2 = kZero; + limitError = true; + } else if (l2 > kOne) { + l2 = kOne; + limitError = true; + } + + Float l3 = (x * (y1 - y2) + y * (x2 - x1) + x1 * y2 - x2 * y1) / tmp; + if (l3 < kZero) { + l3 = kZero; + limitError = true; + } else if (l3 > kOne) { + l3 = kOne; + limitError = true; + } + out[0] = l1; + out[1] = l2; + out[2] = l3; + return limitError; +} + +} // namespace + +// static +uint16_t ColorDT8::primaryToTc(const Float level[], const Primary primary[], uint16_t nrOfPrimaries) { + PointXY p = ColorDT8::primaryToXY(level, primary, nrOfPrimaries); + + uint16_t x = p.x; + if (x <= tc2xy[0].x) { + return TC_MIN; + } + if (x >= tc2xy[19].x) { + return TC_MAX; + } + + uint16_t a = 0; + uint16_t b = 19; + while (a + 1 < b) { + uint16_t m = (a + b) / 2; + uint16_t xx = tc2xy[m].x; + if (x == xx) { + a = b = m; + } else if (x < xx) { + b = m; + } else { + a = m; + } + } + + if (a == b) { + return (a + 1) * TC_STEP; + } else { + uint16_t xx = x - tc2xy[a].x; + uint16_t dx = tc2xy[b].x - tc2xy[a].x; + return (a + 1) * TC_STEP + (xx * TC_STEP + dx / 2) / dx; + } +} + +// static +PointXY ColorDT8::tcToXY(uint16_t tc) { + if (tc <= TC_MIN) { + return tc2xy[0]; + } + if (tc >= TC_MAX) { + return tc2xy[19]; + } + uint16_t i = tc / TC_STEP - 1; + + // linear approximation + PointXY a = tc2xy[i]; + PointXY b = tc2xy[i + 1]; + int32_t r = tc % TC_STEP; + PointXY result = a; + result.x += (((int32_t)b.x - a.x) * r + TC_STEP / 2) / TC_STEP; + result.y += (((int32_t)b.y - a.y) * r + TC_STEP / 2) / TC_STEP; + return result; +} + +// static +PointXY ColorDT8::primaryToXY(const Float level[], const Primary primary[], uint16_t nrOfPrimaries) { + Float x(0); + Float y(0); + Float l(0); + uint16_t min_ty = 65535; + for (uint16_t i = 0; i < nrOfPrimaries; ++ i) { + if (primary[i].ty < min_ty) { + min_ty = primary[i].ty; + } + } + + for (uint16_t i = 0; i < nrOfPrimaries; ++ i) { + const Primary& p = primary[i]; + if (isCalibrated(p)) { + Float ty = level[i] * Float(primary[i].ty) / Float(min_ty); + l += ty; + x += Float(p.xy.x) * ty; + y += Float(p.xy.y) * ty; + } + } + PointXY result; + if (l != kZero) { + int32_t tx = x / l; + result.x = tx <= 65535 ? tx : 65535; + int32_t ty = y / l; + result.y = ty <= 65535 ? ty : 65535; + } else { + // TODO how to handle this case + result.x = 0; + result.y = 0; + } + return result; +} + +uint16_t findValidPrimaries(const Primary primary[], uint16_t nrOfPrimaries, PointXY primaryXY[], uint16_t primaryNr[]) { + uint16_t n = 0; + for (uint16_t i = 0; i < nrOfPrimaries; ++ i) { + const Primary& p = primary[i]; + if (isCalibrated(p)) { + primaryXY[n].x = p.xy.x; + primaryXY[n].y = p.xy.y; + primaryNr[n] = i; + n++; + } + } + return n; +} + +// static +bool ColorDT8::xyToPrimary(PointXY xy, const Primary primary[], uint16_t nrOfPrimaries, Float level[]) { + PointXY primaryXY[nrOfPrimaries]; + uint16_t primaryNr[nrOfPrimaries]; + uint16_t n = findValidPrimaries(primary, nrOfPrimaries, primaryXY, primaryNr); + + memset(level, 0, sizeof(uint16_t) * nrOfPrimaries); + + bool limitError = false; + Float out[n]; + switch (n) { + case 0: + // no calibrated primary found + break; + + case 1: + limitError = xyToPrimary1(xy, primaryXY, out); + break; + + case 2: + limitError = xyToPrimary2(xy, primaryXY, out); + break; + + case 3: + limitError = xyToPrimary3(xy, primaryXY, out); + break; + + default: + // TODO find better solution ex. find nearest points + n = 3; + limitError =xyToPrimary3(xy, primaryXY, out); + break; + } + + uint16_t min_ty = 65535; + for (uint16_t i = 0; i < nrOfPrimaries; ++ i) { + if (primary[i].ty < min_ty) { + min_ty = primary[i].ty; + } + } + for (uint16_t i = 0; i < n; ++i) { + uint16_t j = primaryNr[i]; + level[j] = (out[i] * Float(min_ty)) / Float(primary[j].ty); + } + return limitError; +} + +} // controller +} // namespace dali diff --git a/src/dali/controller/color_dt8.hpp b/src/dali/controller/color_dt8.hpp new file mode 100644 index 0000000..c1c91bf --- /dev/null +++ b/src/dali/controller/color_dt8.hpp @@ -0,0 +1,78 @@ +/* + * Copyright (c) 2015-2016, Arkadiusz Materek (arekmat@poczta.fm) + * + * Licensed under GNU General Public License 3.0 or later. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. + */ + +#ifndef DALI_CONTROLLER_COLOR_HPP_ +#define DALI_CONTROLLER_COLOR_HPP_ + +#include + +#ifdef DALI_DT8 + +#include + +namespace dali { +namespace controller { + +typedef struct __attribute__((__packed__)) ColorDT8 { + + ColorDT8() { + reset(); + } + + void reset() { + type = DALI_MASK; + memset(&value, 0xff, sizeof(value)); + } + + bool isReset() const { + if (type != DALI_MASK) + return false; + return true; + } + + void setType(uint8_t type) { + if (this->type != type) { + reset(); + this->type = type; + } + } + +#ifdef DALI_DT8_SUPPORT_PRIMARY_N + typedef uint16_t Primaries[DALI_DT8_NUMBER_OF_PRIMARIES]; +#endif // DALI_DT8_SUPPORT_PRIMARY_N + union { + +#ifdef DALI_DT8_SUPPORT_XY + PointXY xy; +#endif // DALI_DT8_SUPPORT_XY + +#ifdef DALI_DT8_SUPPORT_TC + uint16_t tc; +#endif // DALI_DT8_SUPPORT_TC + +#ifdef DALI_DT8_SUPPORT_PRIMARY_N + Primaries primary; +#endif // DALI_DT8_SUPPORT_PRIMARY_N + } value; + + uint8_t type; + + static uint16_t primaryToTc(const Float level[], const Primary primary[], uint16_t nrOfPrimaries); + static PointXY tcToXY(uint16_t tc); + static PointXY primaryToXY(const Float level[], const Primary primary[], uint16_t nrOfPrimaries); + static bool xyToPrimary(PointXY xy, const Primary primary[], uint16_t nrOfPrimaries, Float level[]); +} ColorDT8; + +} // controller +} // dali + +#endif // DALI_DT8 + +#endif // DALI_CONTROLLER_COLOR_HPP_ diff --git a/src/dali/controller/lamp_dt8.cpp b/src/dali/controller/lamp_dt8.cpp new file mode 100644 index 0000000..54233d2 --- /dev/null +++ b/src/dali/controller/lamp_dt8.cpp @@ -0,0 +1,453 @@ +/* + * Copyright (c) 2015-2016, Arkadiusz Materek (arekmat@poczta.fm) + * + * Licensed under GNU General Public License 3.0 or later. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. + */ + +#include "lamp_dt8.hpp" + +#ifdef DALI_DT8 + +#include "color_dt8.hpp" +#include "lamp_helper.hpp" + +namespace dali { +namespace controller { + +LampDT8::LampDT8(ILamp* lamp, MemoryDT8* memoryController) : + Lamp(lamp, memoryController), mXYCoordinateLimitError(false), mTemeratureLimitError(false) { + for (uint16_t i = 0; i < DALI_DT8_NUMBER_OF_PRIMARIES; ++i) { + mActualPrimary[i] = 0; + } + calculatePowerOnColor(); // update mActualColor to initial value + setColor(mActualColor, 0); +} + +const ColorDT8& LampDT8::getActualColor() { + if (getLampDT8()->isColorChanging()) { + updateActualColor(); + return mActualColor; + } + return mActualColor; +} + +bool LampDT8::isColorChanging() { + return getLampDT8()->isColorChanging(); +} + +bool LampDT8::isAutomaticActivationEnabled() { + return (getMemoryDT8()->getFeaturesStatus() & 0x01) != 0; +} + +bool LampDT8::isXYCoordinateLimitError() { + return mXYCoordinateLimitError; +} + +bool LampDT8::isTemeratureLimitError() { + return mTemeratureLimitError; +} + +Status LampDT8::powerDirect(uint8_t level, uint64_t time) { + if (isAutomaticActivationEnabled()) { + activateColor(getFadeTime()); + } else if (level == DALI_MASK) { + abortColorChanging(); + } + return Lamp::powerDirect(level, time); +} + +Status LampDT8::powerOff() { + if (isAutomaticActivationEnabled()) { + activateColor(0); + } + return Lamp::powerOff(); +} + +Status LampDT8::powerScene(uint8_t scene) { + const ColorDT8& color = getMemoryDT8()->getColorForScene(scene); + getMemoryDT8()->setTemporaryColor(color); + if (isAutomaticActivationEnabled()) { + activateColor(getFadeTime()); + } + return Lamp::powerScene(scene); +} + +Status LampDT8::powerUp() { + if (isAutomaticActivationEnabled()) { + activateColor(getFadeRate()); + } + return Lamp::powerUp(); +} + +Status LampDT8::powerDown() { + if (isAutomaticActivationEnabled()) { + activateColor(getFadeRate()); + } + return Lamp::powerDown(); +} + +Status LampDT8::powerStepUp() { + if (isAutomaticActivationEnabled()) { + activateColor(0); + } + return Lamp::powerStepUp(); +} + +Status LampDT8::powerStepDown() { + if (isAutomaticActivationEnabled()) { + activateColor(0); + } + return Lamp::powerStepDown(); +} + +Status LampDT8::powerOnAndStepUp() { + if (isAutomaticActivationEnabled()) { + activateColor(0); + } + return Lamp::powerOnAndStepUp(); +} + +Status LampDT8::powerStepDownAndOff() { + if (isAutomaticActivationEnabled()) { + activateColor(0); + } + return Lamp::powerStepDownAndOff(); +} + +Status LampDT8::powerRecallMinLevel() { + if (isAutomaticActivationEnabled()) { + activateColor(0); + } + return Lamp::powerRecallMinLevel(); +} + +Status LampDT8::powerRecallMaxLevel() { + if (isAutomaticActivationEnabled()) { + activateColor(0); + } + return Lamp::powerRecallMaxLevel(); +} + +Status LampDT8::powerRecallOnLevel() { + setColor(getMemoryDT8()->getPowerOnColor(), 0); + return Lamp::powerRecallOnLevel(); +} + +Status LampDT8::powerRecallFaliureLevel() { + setColor(getMemoryDT8()->getFaliureColor(), 0); + return Lamp::powerRecallFaliureLevel(); +} + +Status LampDT8::activate() { + // shall stop a running fade if a fade is running, + // and start a new fade for color only. + // See 9.12.5 for details. + Lamp::abortFading(); + return activateColor(getFadeTime()); +} + +#ifdef DALI_DT8_SUPPORT_XY +Status LampDT8::coordinateStepUpX() { + ColorDT8 color = getActualColor(); + if (color.type != DALI_DT8_COLOR_TYPE_XY) { + return Status::INVALID; + } + if (color.value.xy.x < 65535 - 256) { + color.value.xy.x += 256; + } + return setColor(color, 0); +} + +Status LampDT8::coordinateStepUpY() { + ColorDT8 color = getActualColor(); + if (color.type != DALI_DT8_COLOR_TYPE_XY) { + return Status::INVALID; + } + if (color.value.xy.y < 65535 - 256) { + color.value.xy.y += 256; + } + return setColor(color, 0); +} + +Status LampDT8::coordinateStepDownX() { + ColorDT8 color = getActualColor(); + if (color.type != DALI_DT8_COLOR_TYPE_XY) { + return Status::INVALID; + } + if (color.value.xy.x > 256) { + color.value.xy.x -= 256; + } + return setColor(color, 0); +} + +Status LampDT8::coordinateStepDownY() { + ColorDT8 color = getActualColor(); + if (color.type != DALI_DT8_COLOR_TYPE_XY) { + return Status::INVALID; + } + if (color.value.xy.y > 256) { + color.value.xy.y -= 256; + } + return setColor(color, 0); +} +#endif // DALI_DT8_SUPPORT_XY + +#ifdef DALI_DT8_SUPPORT_TC +Status LampDT8::colorTemperatureStepCooler() { + ColorDT8 color = getActualColor(); + if (color.type != DALI_DT8_COLOR_TYPE_TC) { + return Status::INVALID; + } + uint16_t colorTemperatureCoolest = getMemoryDT8()->getColorTemperatureCoolest(); + if (color.value.tc <= colorTemperatureCoolest) { + mTemeratureLimitError = true; + return Status::OK; + } else { + color.value.tc--; + } + return setColor(color, 0); +} + +Status LampDT8::colorTemperatureStepWarmer() { + ColorDT8 color = getActualColor(); + if (color.type != DALI_DT8_COLOR_TYPE_TC) { + return Status::INVALID; + } + uint16_t colorTemperatureWarmest = getMemoryDT8()->getColorTemperatureWarmest(); + if (color.value.tc >= colorTemperatureWarmest) { + mTemeratureLimitError = true; + return Status::OK; + } else { + color.value.tc++; + } + return setColor(color, 0); +} +#endif // DALI_DT8_SUPPORT_TC + +Status LampDT8::activateColor(uint32_t changeTime) { + Status status = Status::INVALID; + + ColorDT8 color = getMemoryDT8()->getTemporaryColor(); + switch (color.type) { + +#ifdef DALI_DT8_SUPPORT_XY + case DALI_DT8_COLOR_TYPE_XY: +#endif // DALI_DT8_SUPPORT_XY + +#ifdef DALI_DT8_SUPPORT_TC + case DALI_DT8_COLOR_TYPE_TC: +#endif // DALI_DT8_SUPPORT_TC + +#ifdef DALI_DT8_SUPPORT_PRIMARY_N + case DALI_DT8_COLOR_TYPE_PRIMARY_N: +#endif // DALI_DT8_SUPPORT_PRIMARY_N + + getLampDT8()->abortColorChanging(); + status = setColor(color, changeTime); + getMemoryDT8()->resetTemporaryColor(); + break; + + case DALI_MASK: + abortColorChanging(); + status = Status::OK; + break; + + default: + status = Status::ERROR; + break; + } + return status; +} + +Status LampDT8::setColor(const ColorDT8& color, uint32_t changeTime) { + mXYCoordinateLimitError = false; + mTemeratureLimitError = false; + + switch (color.type) { +#ifdef DALI_DT8_SUPPORT_XY + case DALI_DT8_COLOR_TYPE_XY: + Lamp::setMode(Mode::NORMAL, DALI_MASK, changeTime); + return setColorXY(color, changeTime); +#endif // DALI_DT8_SUPPORT_XY + +#ifdef DALI_DT8_SUPPORT_TC + case DALI_DT8_COLOR_TYPE_TC: + Lamp::setMode(Mode::NORMAL, DALI_MASK, changeTime); + return setColorTemperature(color, changeTime); +#endif // DALI_DT8_SUPPORT_TC + +#ifdef DALI_DT8_SUPPORT_PRIMARY_N + case DALI_DT8_COLOR_TYPE_PRIMARY_N: { + Status status = setColorPrimary(color, changeTime); + Lamp::setMode(Mode::CONSTANT_POWER, DALI_LEVEL_MAX, changeTime); + return status; + } +#endif // DALI_DT8_SUPPORT_PRIMARY_N + + default: + return Status::INVALID; + } +} + +#ifdef DALI_DT8_SUPPORT_XY +Status LampDT8::setColorXY(const ColorDT8& color, uint32_t changeTime) { + const Primary* primaries = getMemoryDT8()->getPrimaries(); + mActualColor = color; + if ((mActualColor.value.xy.x == DALI_DT8_MASK16) || (mActualColor.value.xy.y == DALI_DT8_MASK16)) { + PointXY xy = ColorDT8::primaryToXY(mActualPrimary, primaries, DALI_DT8_NUMBER_OF_PRIMARIES); + if (mActualColor.value.xy.x == DALI_DT8_MASK16) { + mActualColor.value.xy.x = xy.x; + } + if (mActualColor.value.xy.y == DALI_DT8_MASK16) { + mActualColor.value.xy.y = xy.y; + } + } + if (ColorDT8::xyToPrimary(mActualColor.value.xy, primaries, DALI_DT8_NUMBER_OF_PRIMARIES, mActualPrimary)) { + mXYCoordinateLimitError = true; + mActualColor.value.xy = ColorDT8::primaryToXY(mActualPrimary, primaries, DALI_DT8_NUMBER_OF_PRIMARIES); + } + updateLampDriver(changeTime); + return getMemoryDT8()->setActualColor(mActualColor); +} +#endif // DALI_DT8_SUPPORT_XY + +#ifdef DALI_DT8_SUPPORT_TC +Status LampDT8::setColorTemperature(const ColorDT8& color, uint32_t changeTime) { + const Primary* primaries = getMemoryDT8()->getPrimaries(); + mActualColor = color; + if (mActualColor.value.tc != DALI_DT8_MASK16) { + uint16_t colorTemperaturePhisicalCoolest = getMemoryDT8()->getColorTemperaturePhisicalCoolest(); + uint16_t colorTemperaturePhisicalWarmest = getMemoryDT8()->getColorTemperaturePhisicalWarmest(); + + if (colorTemperaturePhisicalCoolest == DALI_DT8_MASK16) { + colorTemperaturePhisicalCoolest = DALI_DT8_TC_COOLEST; + } + if (colorTemperaturePhisicalWarmest == DALI_DT8_MASK16) { + colorTemperaturePhisicalWarmest = DALI_DT8_TC_WARMESR; + } + + uint16_t colorTemperatureCoolest = getMemoryDT8()->getColorTemperatureCoolest(); + uint16_t colorTemperatureWarmest = getMemoryDT8()->getColorTemperatureWarmest(); + + if (colorTemperatureCoolest == DALI_DT8_MASK16) { + colorTemperatureCoolest = colorTemperaturePhisicalCoolest; + } + if (colorTemperatureWarmest == DALI_DT8_MASK16) { + colorTemperatureWarmest = colorTemperaturePhisicalWarmest; + } + + if (mActualColor.value.tc < colorTemperatureCoolest) { + mTemeratureLimitError = true; + mActualColor.value.tc = colorTemperatureCoolest; + } + if (mActualColor.value.tc > colorTemperatureWarmest) { + mTemeratureLimitError = true; + mActualColor.value.tc = colorTemperatureWarmest; + } + + PointXY xy = ColorDT8::tcToXY(mActualColor.value.tc); + ColorDT8::xyToPrimary(xy, primaries, DALI_DT8_NUMBER_OF_PRIMARIES, mActualPrimary); + + updateLampDriver(changeTime); + } else { + mActualColor.value.tc = ColorDT8::primaryToTc(mActualPrimary, primaries, DALI_DT8_NUMBER_OF_PRIMARIES); + } + return getMemoryDT8()->setActualColor(mActualColor); +} +#endif // DALI_DT8_SUPPORT_TC + +#ifdef DALI_DT8_SUPPORT_PRIMARY_N + +Status LampDT8::setColorPrimary(const ColorDT8& color, uint32_t changeTime) { + uint16_t primary[DALI_DT8_NUMBER_OF_PRIMARIES]; + getLampDT8()->getPrimary(primary, DALI_DT8_NUMBER_OF_PRIMARIES); + mActualColor = color; + for (uint8_t i = 0; i < DALI_DT8_NUMBER_OF_PRIMARIES; ++i) { + if (mActualColor.value.primary[i] == DALI_DT8_MASK16) { + mActualColor.value.primary[i] = primary[i]; // no change + } + mActualPrimary[i] = mActualColor.value.primary[i]; + } + updateLampDriver(changeTime); + return getMemoryDT8()->setActualColor(mActualColor); +} +#endif // DALI_DT8_SUPPORT_PRIMARY_N + +void LampDT8::abortColorChanging() { + if (getLampDT8()->isColorChanging()) { + getLampDT8()->abortColorChanging(); + updateActualColor(); + getMemoryDT8()->setActualColor(mActualColor); + } +} + +void LampDT8::calculatePowerOnColor() { + mActualColor = getMemoryDT8()->getPowerOnColor(); + const ColorDT8& actualColor = getMemoryDT8()->getActualColor(); + switch (mActualColor.type) { + +#ifdef DALI_DT8_SUPPORT_XY + case DALI_DT8_COLOR_TYPE_XY: + if (mActualColor.value.xy.x == DALI_DT8_MASK16) { + mActualColor.value.xy.x = actualColor.value.xy.x == DALI_DT8_MASK16 ? getMemoryDT8()->getDefaults()->xCoordinate : actualColor.value.xy.x; + } + if (mActualColor.value.xy.y == DALI_DT8_MASK16) { + mActualColor.value.xy.y = actualColor.value.xy.y == DALI_DT8_MASK16 ? getMemoryDT8()->getDefaults()->yCoordinate : actualColor.value.xy.y; + } + break; +#endif // DALI_DT8_SUPPORT_XY + +#ifdef DALI_DT8_SUPPORT_TC + case DALI_DT8_COLOR_TYPE_TC: + if (mActualColor.value.tc == DALI_DT8_MASK16) { + mActualColor.value.tc = actualColor.value.tc == DALI_DT8_MASK16 ? getMemoryDT8()->getDefaults()->tc : actualColor.value.tc; + } + break; +#endif // DALI_DT8_SUPPORT_TC + + default: + break; + } +} + +void LampDT8::updateLampDriver(uint32_t changeTime) { + uint16_t primary[DALI_DT8_NUMBER_OF_PRIMARIES]; + for (uint16_t i = 0; i < DALI_DT8_NUMBER_OF_PRIMARIES; ++i) { + int32_t level = mActualPrimary[i]; + primary[i] = level < DALI_DT8_MASK16 ? level : DALI_DT8_MASK16; + } + getLampDT8()->setPrimary(primary, DALI_DT8_NUMBER_OF_PRIMARIES, changeTime); +} + +void LampDT8::updateActualColor() { + uint16_t primary[DALI_DT8_NUMBER_OF_PRIMARIES]; + getLampDT8()->getPrimary(primary, DALI_DT8_NUMBER_OF_PRIMARIES); + for (uint8_t i = 0; i < DALI_DT8_NUMBER_OF_PRIMARIES; ++i) { + mActualPrimary[i] = primary[i]; + } + + mActualColor = getMemoryDT8()->getActualColor(); + switch (mActualColor.type) { + +#ifdef DALI_DT8_SUPPORT_XY + case DALI_DT8_COLOR_TYPE_XY: + mActualColor.value.xy = ColorDT8::primaryToXY(mActualPrimary, getMemoryDT8()->getPrimaries(), DALI_DT8_NUMBER_OF_PRIMARIES); + break; +#endif // DALI_DT8_SUPPORT_XY + +#ifdef DALI_DT8_SUPPORT_TC + case DALI_DT8_COLOR_TYPE_TC: + mActualColor.value.tc = ColorDT8::primaryToTc(mActualPrimary, getMemoryDT8()->getPrimaries(), DALI_DT8_NUMBER_OF_PRIMARIES); + break; +#endif // DALI_DT8_SUPPORT_TC + } // switch +} + +} // namespace controller +} // namespace dali + +#endif // DALI_DT8 diff --git a/src/dali/controller/lamp_dt8.hpp b/src/dali/controller/lamp_dt8.hpp new file mode 100644 index 0000000..41c4a28 --- /dev/null +++ b/src/dali/controller/lamp_dt8.hpp @@ -0,0 +1,113 @@ +/* + * Copyright (c) 2015-2016, Arkadiusz Materek (arekmat@poczta.fm) + * + * Licensed under GNU General Public License 3.0 or later. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. + */ + +#ifndef DALI_LAMP_DT8_CONTROLLER_HPP_ +#define DALI_LAMP_DT8_CONTROLLER_HPP_ + +#include + +#ifdef DALI_DT8 + +#include "color_dt8.hpp" +#include "lamp.hpp" +#include "memory_dt8.hpp" + +#include + +namespace dali { +namespace controller { + +class LampDT8: public Lamp { +public: + + explicit LampDT8(ILamp* lamp, MemoryDT8* memoryController); + +// >>> used only in controller namespace + + const ColorDT8& getActualColor(); + + bool isColorChanging(); + bool isAutomaticActivationEnabled(); + bool isXYCoordinateLimitError(); + bool isTemeratureLimitError(); +// <<< used only in controller namespace + + Status powerDirect(uint8_t level, uint64_t time) override; + Status powerOff() override; + Status powerScene(uint8_t scene) override; + Status powerUp() override; + Status powerDown() override; + Status powerStepUp() override; + Status powerStepDown() override; + Status powerOnAndStepUp() override; + Status powerStepDownAndOff() override; + Status powerRecallMinLevel() override; + Status powerRecallMaxLevel() override; + Status powerRecallOnLevel() override; + Status powerRecallFaliureLevel() override; + + Status activate(); + +#ifdef DALI_DT8_SUPPORT_XY + Status coordinateStepUpX(); + Status coordinateStepUpY(); + Status coordinateStepDownX(); + Status coordinateStepDownY(); +#endif // DALI_DT8_SUPPORT_XY + +#ifdef DALI_DT8_SUPPORT_TC + Status colorTemperatureStepCooler(); + Status colorTemperatureStepWarmer(); +#endif // DALI_DT8_SUPPORT_TC + +private: + LampDT8(const LampDT8& other) = delete; + LampDT8& operator=(const LampDT8&) = delete; + + ILampDT8* getLampDT8() { + return (ILampDT8*) getLamp(); + } + + MemoryDT8* getMemoryDT8() { + return (MemoryDT8*) getMemoryController(); + } + + Status activateColor(uint32_t changeTime); + Status setColor(const ColorDT8& color, uint32_t changeTime); + +#ifdef DALI_DT8_SUPPORT_XY + Status setColorXY(const ColorDT8& color, uint32_t changeTime); +#endif // DALI_DT8_SUPPORT_XY + +#ifdef DALI_DT8_SUPPORT_TC + Status setColorTemperature(const ColorDT8& color, uint32_t changeTime); +#endif // DALI_DT8_SUPPORT_TC + +#ifdef DALI_DT8_SUPPORT_PRIMARY_N + Status setColorPrimary(const ColorDT8& color, uint32_t changeTime); +#endif // DALI_DT8_SUPPORT_PRIMARY_N + + void abortColorChanging(); + void calculatePowerOnColor(); + void updateLampDriver(uint32_t changeTime); + void updateActualColor(); + + bool mXYCoordinateLimitError; + bool mTemeratureLimitError; + ColorDT8 mActualColor; + Float mActualPrimary[DALI_DT8_NUMBER_OF_PRIMARIES]; +}; + +} // namespace controller +}// namespace dali + +#endif // DALI_DT8 + +#endif // DALI_LAMP_DT8_CONTROLLER_HPP_ diff --git a/src/dali/controller/memory.cpp b/src/dali/controller/memory.cpp index 0ecf397..74af7f5 100644 --- a/src/dali/controller/memory.cpp +++ b/src/dali/controller/memory.cpp @@ -317,6 +317,10 @@ size_t Memory::getBankSize(uint8_t bank) { return DALI_BANK2_ADDR - DALI_BANK1_ADDR; case 2: return DALI_BANK3_ADDR - DALI_BANK2_ADDR; + case 3: + return DALI_BANK4_ADDR - DALI_BANK3_ADDR; + case 4: + return DALI_BANK5_ADDR - DALI_BANK4_ADDR; default: return 0; } @@ -330,6 +334,10 @@ uintptr_t Memory::getBankAddr(uint8_t bank) { return DALI_BANK1_ADDR; case 2: return DALI_BANK2_ADDR; + case 3: + return DALI_BANK3_ADDR; + case 4: + return DALI_BANK4_ADDR; default: return INVALID_BANK_ADDR; } diff --git a/src/dali/controller/memory_dt8.cpp b/src/dali/controller/memory_dt8.cpp new file mode 100644 index 0000000..ed1dadb --- /dev/null +++ b/src/dali/controller/memory_dt8.cpp @@ -0,0 +1,610 @@ +/* + * Copyright (c) 2015-2016, Arkadiusz Materek (arekmat@poczta.fm) + * + * Licensed under GNU General Public License 3.0 or later. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. + */ + +#include "memory_dt8.hpp" + +#ifdef DALI_DT8 + +#define DATA_FIELD_OFFSET(type, field) ((uintptr_t) &(((type *) 0)->field)) +#define TEMP_FIELD_OFFSET(type, field) (sizeof(Temp) + (uintptr_t) &(((type *) 0)->field)) + +#define CONFIG_VERSION 1 + +namespace dali { +namespace controller { + +MemoryDT8::MemoryDT8(IMemory* memory, const DefaultsDT8* defaults) : + Memory(memory), + mDefaults(defaults), + mConfigDT8((ConfigDT8*)memory->data(DALI_BANK3_ADDR, sizeof(ConfigDT8))), + mDataDT8((DataDT8*)memory->data(DALI_BANK4_ADDR, sizeof(DataDT8))), + mTempDT8((TempDT8*)memory->tempData(sizeof(Temp), sizeof(TempDT8))){ + + resetRamDT8(true); + + if (mConfigDT8 != nullptr) { + if (!isValidConfigDT8()) { + resetConfigDT8(); + } + } + if (mDataDT8 != nullptr) { + if (!isValidDataDT8()) { + resetDataDT8(true); + } + } + if (mTempDT8 != nullptr) { + if (!isValidTempDT8()) { + resetTempDT8(true); + } + } +} + +Status MemoryDT8::setPowerOnColor(const ColorDT8& color) { + return writeDataColor(DATA_FIELD_OFFSET(DataDT8, powerOnColor), &color); +} + +const ColorDT8& MemoryDT8::getPowerOnColor() { + return mDataDT8->powerOnColor; +} + +Status MemoryDT8::setFaliureColor(const ColorDT8& color) { + return writeDataColor(DATA_FIELD_OFFSET(DataDT8, failureColor), &color); +} + +const ColorDT8& MemoryDT8::getFaliureColor() { + return mDataDT8->failureColor; +} + +Status MemoryDT8::setColorForScene(uint8_t scene, const ColorDT8& color) { + if (scene > DALI_SCENE_MAX) { + return Status::ERROR; + } + return writeDataColor(DATA_FIELD_OFFSET(DataDT8, sceneColor[scene]), &color); +} + +const ColorDT8& MemoryDT8::getColorForScene(uint8_t scene) { + static const ColorDT8 kInvalidColor; + if (scene > DALI_SCENE_MAX) { + return kInvalidColor; + } + return mDataDT8->sceneColor[scene]; +} + +Status MemoryDT8::setTemporaryColor(const ColorDT8& color) { + mRamDT8.temporaryColor = color; + return Status::OK; +} + +const ColorDT8& MemoryDT8::getTemporaryColor() { + return mRamDT8.temporaryColor; +} + +Status MemoryDT8::resetTemporaryColor() { + mRamDT8.temporaryColor.reset(); + return Status::OK; +} + +Status MemoryDT8::setReportColor(const ColorDT8& color) { + mRamDT8.reportColor = color; + return Status::OK; +} + +const ColorDT8& MemoryDT8::getReportColor() { + return mRamDT8.reportColor; +} + +Status MemoryDT8::resetReportColor() { + mRamDT8.reportColor.reset(); + return Status::OK; +} + +Status MemoryDT8::copyReportToTemporary() { + mRamDT8.temporaryColor = mRamDT8.reportColor; + return Status::OK; +} + +const ColorDT8& MemoryDT8::getActualColor() { + return mTempDT8->actualColor; +} + +Status MemoryDT8::setActualColor(const ColorDT8& color) { + return writeTempColor(TEMP_FIELD_OFFSET(TempDT8, actualColor), &color); +} + +uint8_t MemoryDT8::getFeaturesStatus() { + return mRamDT8.featuresStatus; +} + +Status MemoryDT8::setFeaturesStatus(uint8_t value) { + mRamDT8.featuresStatus = value; + return Status::OK; +} + +bool MemoryDT8::isReset() { + if (mRamDT8.featuresStatus != 0x01) { + return false; + } +#if !defined(DALI_DT8_SUPPORT_XY) && defined(DALI_DT8_SUPPORT_PRIMARY_N) + if (mRamDT8.temporaryX != DALI_DT8_MASK16) + return false; + if (mRamDT8.temporaryY != DALI_DT8_MASK16) + return false; +#endif + + + if (!mRamDT8.temporaryColor.isReset()) + return false; + + if (mDataDT8->powerOnColor.type != mDefaults->colorType) + return false; + +#ifdef DALI_DT8_SUPPORT_XY + if (mDefaults->colorType == DALI_DT8_COLOR_TYPE_XY) { + if (mDataDT8->powerOnColor.value.xy.x != mDefaults->xCoordinate) + return false; + if (mDataDT8->powerOnColor.value.xy.y != mDefaults->yCoordinate) + return false; + } +#endif // DALI_DT8_SUPPORT_XY + +#ifdef DALI_DT8_SUPPORT_TC + if (mDefaults->colorType == DALI_DT8_COLOR_TYPE_TC) { + if (mDataDT8->powerOnColor.value.tc != mDefaults->tc) + return false; + } +#endif // DALI_DT8_SUPPORT_TC + +#ifdef DALI_DT8_SUPPORT_PRIMARY_N + if (mDefaults->colorType == DALI_DT8_COLOR_TYPE_PRIMARY_N) { + for (uint8_t i = 0; i < DALI_DT8_NUMBER_OF_PRIMARIES; ++i) { + if (mDataDT8->powerOnColor.value.primary[i] != mDefaults->primary[i]) { + return false; + } + } + } +#endif // DALI_DT8_SUPPORT_PRIMARY_N + + if (mDataDT8->failureColor.type != mDefaults->colorType) + return false; + +#ifdef DALI_DT8_SUPPORT_XY + if (mDefaults->colorType == DALI_DT8_COLOR_TYPE_XY) { + if (mDataDT8->failureColor.value.xy.x != mDefaults->xCoordinate) + return false; + if (mDataDT8->failureColor.value.xy.y != mDefaults->yCoordinate) + return false; + } +#endif // DALI_DT8_SUPPORT_XY + +#ifdef DALI_DT8_SUPPORT_TC + if (mDefaults->colorType == DALI_DT8_COLOR_TYPE_TC) { + if (mDataDT8->failureColor.value.tc != mDefaults->tc) + return false; + } +#endif // DALI_DT8_SUPPORT_TC + +#ifdef DALI_DT8_SUPPORT_PRIMARY_N + if (mDefaults->colorType == DALI_DT8_COLOR_TYPE_PRIMARY_N) { + for (uint8_t i = 0; i < DALI_DT8_NUMBER_OF_PRIMARIES; ++i) { + if (mDataDT8->failureColor.value.primary[i] != mDefaults->primary[i]) { + return false; + } + } + } +#endif // DALI_DT8_SUPPORT_PRIMARY_N + + for (size_t i = 0; i <= DALI_SCENE_MAX; i++) { + if (!mDataDT8->sceneColor[i].isReset()) + return false; + } + +#ifdef DALI_DT8_SUPPORT_TC + if (mDataDT8->colorTemperatureCoolest != getColorTemperaturePhisicalCoolest()) + return false; + if (mDataDT8->colorTemperatureWarmest != getColorTemperaturePhisicalWarmest()) + return false; +#endif // DALI_DT8_SUPPORT_TC + + return Memory::isReset(); +} + +Status MemoryDT8::reset() { + resetDataDT8(false); + resetTempDT8(false); + resetRamDT8(false); + return Memory::reset(); +} + +#if defined(DALI_DT8_SUPPORT_XY) || defined(DALI_DT8_SUPPORT_PRIMARY_N) +Status MemoryDT8::setTemporaryCoordinateX(uint16_t value) { +#ifdef DALI_DT8_SUPPORT_XY + mRamDT8.temporaryColor.setType(DALI_DT8_COLOR_TYPE_XY); + mRamDT8.temporaryColor.value.xy.x = value; + return Status::OK; +#else + mRamDT8.temporaryColor.setType(DALI_DT8_COLOR_TYPE_XY); + mRamDT8.temporaryX = value; + return Status::OK; +#endif // DALI_DT8_SUPPORT_XY +} + +Status MemoryDT8::setTemporaryCoordinateY(uint16_t value) { +#ifdef DALI_DT8_SUPPORT_XY + mRamDT8.temporaryColor.setType(DALI_DT8_COLOR_TYPE_XY); + mRamDT8.temporaryColor.value.xy.y = value; + return Status::OK; +#else + mRamDT8.temporaryColor.setType(DALI_DT8_COLOR_TYPE_XY); + mRamDT8.temporaryY = value; + return Status::OK; +#endif // DALI_DT8_SUPPORT_XY +} + +# if !defined(DALI_DT8_SUPPORT_XY) +uint16_t MemoryDT8::getTemporaryCooridanateX() { + return mRamDT8.temporaryX; +} + +uint16_t MemoryDT8::getTemporaryCooridanateY() { + return mRamDT8.temporaryY; +} +# endif // !defined(DALI_DT8_SUPPORT_XY) +#endif // defined(DALI_DT8_SUPPORT_XY) || defined(DALI_DT8_SUPPORT_PRIMARY_N) + +#ifdef DALI_DT8_SUPPORT_TC +Status MemoryDT8::setTemporaryColorTemperature(uint16_t temperature) { + mRamDT8.temporaryColor.setType(DALI_DT8_COLOR_TYPE_TC); + mRamDT8.temporaryColor.value.tc = temperature; + return Status::OK; +} + +Status MemoryDT8::setColorTemperatureCoolest(uint16_t temperature) { + return writeData16(DATA_FIELD_OFFSET(DataDT8, colorTemperatureCoolest), temperature); +} + +uint16_t MemoryDT8::getColorTemperatureCoolest() { + return mDataDT8->colorTemperatureCoolest; +} + +Status MemoryDT8::setColorTemperatureWarmest(uint16_t temperature) { + return writeData16(DATA_FIELD_OFFSET(DataDT8, colorTemperatureWarmest), temperature); +} + +uint16_t MemoryDT8::getColorTemperatureWarmest() { + return mDataDT8->colorTemperatureWarmest; +} + +Status MemoryDT8::setColorTemperaturePhisicalCoolest(uint16_t temperature) { + return writeConfig16(DATA_FIELD_OFFSET(ConfigDT8, colorTemperaturePhisicalCoolest), temperature); +} + +uint16_t MemoryDT8::getColorTemperaturePhisicalCoolest() { + return mConfigDT8->colorTemperaturePhisicalCoolest; +} + +Status MemoryDT8::setColorTemperaturePhisicalWarmest(uint16_t temperature) { + return writeConfig16(DATA_FIELD_OFFSET(ConfigDT8, colorTemperaturePhisicalWarmest), temperature); +} + +uint16_t MemoryDT8::getColorTemperaturePhisicalWarmest() { + return mConfigDT8->colorTemperaturePhisicalWarmest; +} +#endif // DALI_DT8_SUPPORT_TC + +Status MemoryDT8::storePrimaryTy(uint8_t n, uint16_t ty) { + if (n < DALI_DT8_NUMBER_OF_PRIMARIES) { + return writeConfig16(DATA_FIELD_OFFSET(ConfigDT8, primary[n].ty), ty); + } else { + return Status::ERROR; + } + return Status::OK; +} + +Status MemoryDT8::storePrimaryCoordinate(uint8_t n, uint16_t x, uint16_t y) { + Status status = Status::OK; + if (n < DALI_DT8_NUMBER_OF_PRIMARIES) { + if (writeConfig16(DATA_FIELD_OFFSET(ConfigDT8, primary[n].xy.x), x) != Status::OK) { + status = Status::ERROR; + } + if (writeConfig16(DATA_FIELD_OFFSET(ConfigDT8, primary[n].xy.y), y) != Status::OK) { + status = Status::ERROR; + } + } else { + status = Status::ERROR; + } + return status; +} + +#ifdef DALI_DT8_SUPPORT_PRIMARY_N +Status MemoryDT8::setTemporaryPrimaryLevel(uint8_t n, uint16_t level) { + if (n < DALI_DT8_NUMBER_OF_PRIMARIES) { + mRamDT8.temporaryColor.setType(DALI_DT8_COLOR_TYPE_PRIMARY_N); + mRamDT8.temporaryColor.value.primary[n] = level; + return Status::OK; + } else { + return Status::ERROR; + } +} + +uint16_t MemoryDT8::getPrimaryTy(uint8_t n) { + return mConfigDT8->primary[n].ty; +} + +uint16_t MemoryDT8::getPrimaryCoordinateX(uint8_t n) { + return mConfigDT8->primary[n].xy.x; +} + +uint16_t MemoryDT8::getPrimaryCoordinateY(uint8_t n) { + return mConfigDT8->primary[n].xy.y; +} +#endif // DALI_DT8_SUPPORT_PRIMARY_N + +bool MemoryDT8::isColorValid(const ColorDT8& color, bool canTypeBeMask) { + switch (color.type) { + case DALI_DT8_COLOR_TYPE_XY: +#ifdef DALI_DT8_SUPPORT_XY + if (color.value.xy.x == 0 || color.value.xy.y == 0) { + return false; + } + break; +#else + return false; +#endif // DALI_DT8_SUPPORT_XY + case DALI_DT8_COLOR_TYPE_TC: +#ifdef DALI_DT8_SUPPORT_TC + if ((color.value.tc != DALI_DT8_MASK16) && ((color.value.tc < DALI_DT8_TC_COOLEST) || (color.value.tc > DALI_DT8_TC_WARMESR))) { + return false; + } + break; +#else + return false; +#endif // DALI_DT8_SUPPORT_TC + case DALI_DT8_COLOR_TYPE_PRIMARY_N: +#ifdef DALI_DT8_SUPPORT_PRIMARY_N + // Nothing to do + break; +#else + return false; +#endif // DALI_DT8_SUPPORT_PRIMARY_N + + case DALI_MASK: + return canTypeBeMask ? true : false; + + default: + return false; + } + + return true; +} + +bool MemoryDT8::isValidConfigDT8() { + if (mConfigDT8->version != CONFIG_VERSION) { + return false; + } + +#ifdef DALI_DT8_SUPPORT_TC + if (mConfigDT8->colorTemperaturePhisicalCoolest == 0) { + return false; + } + if (mConfigDT8->colorTemperaturePhisicalWarmest == 0) { + return false; + } + if (mConfigDT8->colorTemperaturePhisicalCoolest > mConfigDT8->colorTemperaturePhisicalWarmest) { + return false; + } +#endif // DALI_DT8_SUPPORT_TC + +#ifdef DALI_DT8_SUPPORT_PRIMARY_N + for (uint8_t i = 0; i < DALI_DT8_NUMBER_OF_PRIMARIES; ++i) { + Primary prim = mConfigDT8->primary[i]; + if (prim.xy.x == 0) { + return false; + } + if (prim.xy.y == 0) { + return false; + } + if ((prim.ty != DALI_DT8_MASK16) && (prim.ty > DALI_DT8_PRIMARY_TY_MAX)) { + return false; + } + } +#endif // DALI_DT8_SUPPORT_PRIMARY_N + + return true; +} + +bool MemoryDT8::isValidDataDT8() { + if (!isColorValid(mDataDT8->powerOnColor, false)) { + return false; + } + if (!isColorValid(mDataDT8->failureColor, false)) { + return false; + } +#ifdef DALI_DT8_SUPPORT_TC + uint16_t colorTemperaturePhisicalCoolest = getColorTemperaturePhisicalCoolest(); + uint16_t colorTemperaturePhisicalWarmest = getColorTemperaturePhisicalWarmest(); + + uint16_t colorTemperatureCoolest = mDataDT8->colorTemperatureCoolest; + uint16_t colorTemperatureWarmest = mDataDT8->colorTemperatureWarmest; + if (colorTemperaturePhisicalCoolest != DALI_DT8_MASK16) { + if (colorTemperaturePhisicalCoolest > colorTemperaturePhisicalWarmest) + return false; + if (colorTemperaturePhisicalCoolest < DALI_DT8_TC_COOLEST) + return false; + + if (colorTemperatureCoolest != DALI_DT8_MASK16 && colorTemperatureCoolest < colorTemperaturePhisicalCoolest) + return false; + } + if (colorTemperaturePhisicalWarmest != DALI_DT8_MASK16) { + if (colorTemperaturePhisicalWarmest > DALI_DT8_TC_WARMESR) + return false; + + if (colorTemperatureWarmest != DALI_DT8_MASK16 && colorTemperatureWarmest > colorTemperaturePhisicalWarmest) + return false; + } + if (colorTemperatureCoolest != DALI_DT8_MASK16 && colorTemperatureWarmest != DALI_DT8_MASK16 + && colorTemperatureCoolest > colorTemperatureWarmest) + return false; +#endif // DALI_DT8_SUPPORT_TC + + for (uint16_t i = 0; i <= DALI_SCENE_MAX; i++) { + const ColorDT8& color = mDataDT8->sceneColor[i]; + if (color.type != DALI_MASK) { + if (!isColorValid(color, true)) { + return false; + } + } + } + return true; +} + +bool MemoryDT8::isValidTempDT8() { + switch (mTempDT8->actualColor.type) { + case DALI_DT8_COLOR_TYPE_XY: +#ifdef DALI_DT8_SUPPORT_XY + if (mTempDT8->actualColor.value.xy.x == 0 || mTempDT8->actualColor.value.xy.y == 0) { + return false; + } + break; +#else + return false; +#endif // DALI_DT8_SUPPORT_XY + case DALI_DT8_COLOR_TYPE_TC: +#ifdef DALI_DT8_SUPPORT_TC + if (mTempDT8->actualColor.value.tc == 0) { + return false; + } + break; +#else + return false; +#endif // DALI_DT8_SUPPORT_TC + case DALI_DT8_COLOR_TYPE_PRIMARY_N: +#ifdef DALI_DT8_SUPPORT_PRIMARY_N + for (uint8_t i = 0; i < DALI_DT8_NUMBER_OF_PRIMARIES; ++i) { + uint16_t value = mTempDT8->actualColor.value.primary[i]; + if (value == DALI_DT8_MASK16) { + return false; + } + } + break; +#else + return false; +#endif // DALI_DT8_SUPPORT_PRIMARY_N + break; + + case DALI_MASK: + break; + + default: + return false; + } + + return true; +} + +void MemoryDT8::resetRamDT8(bool initialize) { + mRamDT8.temporaryColor.reset(); +#if !defined(DALI_DT8_SUPPORT_XY) && defined(DALI_DT8_SUPPORT_PRIMARY_N) + mRamDT8.temporaryX = DALI_DT8_MASK16; + mRamDT8.temporaryY = DALI_DT8_MASK16; +#endif + mRamDT8.reportColor.reset(); + mRamDT8.featuresStatus = 0x01; +} + +void MemoryDT8::resetConfigDT8() { + writeConfig8(DATA_FIELD_OFFSET(ConfigDT8, version), CONFIG_VERSION); + +#ifdef DALI_DT8_SUPPORT_TC + setColorTemperaturePhisicalCoolest(mDefaults->tcCoolest); + setColorTemperaturePhisicalWarmest(mDefaults->tcWarmest); +#endif // DALI_DT8_SUPPORT_TC + + for (uint8_t i = 0; i < DALI_DT8_NUMBER_OF_PRIMARIES; ++i) { + Primary primary = getDefaults()->primaryConfig[i]; + storePrimaryTy(i, primary.ty); + storePrimaryCoordinate(i, primary.xy.x, primary.xy.y); + } +} + +void MemoryDT8::resetDataDT8(bool initialize) { + ColorDT8 temp; + temp.setType(mDefaults->colorType); + +#ifdef DALI_DT8_SUPPORT_XY + if (mDefaults->colorType == DALI_DT8_COLOR_TYPE_XY) { + temp.value.xy.x = mDefaults->xCoordinate; + temp.value.xy.y = mDefaults->yCoordinate; + } +#endif // DALI_DT8_SUPPORT_XY + +#ifdef DALI_DT8_SUPPORT_TC + if (mDefaults->colorType == DALI_DT8_COLOR_TYPE_TC) { + temp.value.tc = mDefaults->tc; + } +#endif // DALI_DT8_SUPPORT_TC + +#ifdef DALI_DT8_SUPPORT_PRIMARY_N + if (mDefaults->colorType == DALI_DT8_COLOR_TYPE_PRIMARY_N) { + for (uint8_t i = 0; i < DALI_DT8_NUMBER_OF_PRIMARIES; ++ i) { + temp.value.primary[i] = mDefaults->primary[i]; + } + } +#endif // DALI_DT8_SUPPORT_PRIMARY_N + + setPowerOnColor(temp); + + temp.setType(mDefaults->colorType); + +#ifdef DALI_DT8_SUPPORT_XY + if (mDefaults->colorType == DALI_DT8_COLOR_TYPE_XY) { + temp.value.xy.x = mDefaults->xCoordinate; + temp.value.xy.y = mDefaults->yCoordinate; + } +#endif // DALI_DT8_SUPPORT_XY + +#ifdef DALI_DT8_SUPPORT_TC + if (mDefaults->colorType == DALI_DT8_COLOR_TYPE_TC) { + temp.value.tc = mDefaults->tc; + } +#endif // DALI_DT8_SUPPORT_TC + +#ifdef DALI_DT8_SUPPORT_PRIMARY_N + if (mDefaults->colorType == DALI_DT8_COLOR_TYPE_PRIMARY_N) { + for (uint8_t i = 0; i < DALI_DT8_NUMBER_OF_PRIMARIES; ++ i) { + temp.value.primary[i] = mDefaults->primary[i]; + } + } +#endif // DALI_DT8_SUPPORT_PRIMARY_N + + setFaliureColor(temp); + + temp.reset(); + for (size_t i = 0; i <= DALI_SCENE_MAX; i++) { + setColorForScene(i, temp); + } + +#ifdef DALI_DT8_SUPPORT_TC + setColorTemperatureCoolest(getColorTemperaturePhisicalCoolest()); + setColorTemperatureWarmest(getColorTemperaturePhisicalWarmest()); +#endif //DALI_DT8_SUPPORT_TC + +} + +void MemoryDT8::resetTempDT8(bool initialize) { + ColorDT8 color; + if (initialize) { + writeTempColor(TEMP_FIELD_OFFSET(TempDT8, actualColor), &color); + } +} + +} // namespace controller +} // namespace dali + +#endif // DALI_DT8 diff --git a/src/dali/controller/memory_dt8.hpp b/src/dali/controller/memory_dt8.hpp new file mode 100644 index 0000000..3e4d0d9 --- /dev/null +++ b/src/dali/controller/memory_dt8.hpp @@ -0,0 +1,186 @@ +/* + * Copyright (c) 2015-2016, Arkadiusz Materek (arekmat@poczta.fm) + * + * Licensed under GNU General Public License 3.0 or later. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. + */ + +#ifndef DALI_MEMORY_DT8_CONTROLLER_HPP_ +#define DALI_MEMORY_DT8_CONTROLLER_HPP_ + +#include + +#ifdef DALI_DT8 + +#include "color_dt8.hpp" +#include "memory.hpp" + +namespace dali { +namespace controller { + +class MemoryDT8: public Memory { +public: + explicit MemoryDT8(IMemory* memory, const DefaultsDT8* defaults); + + Status setPowerOnColor(const ColorDT8& color); + const ColorDT8& getPowerOnColor(); + Status setFaliureColor(const ColorDT8& color); + const ColorDT8& getFaliureColor(); + Status setColorForScene(uint8_t scene, const ColorDT8& color); + const ColorDT8& getColorForScene(uint8_t scene); + uint8_t getFeaturesStatus(); + Status setFeaturesStatus(uint8_t value); + Status setTemporaryColor(const ColorDT8& color); + const ColorDT8& getTemporaryColor(); + Status resetTemporaryColor(); + Status setReportColor(const ColorDT8& color); + const ColorDT8& getReportColor(); + Status resetReportColor(); + Status copyReportToTemporary(); + const ColorDT8& getActualColor(); + Status setActualColor(const ColorDT8& color); + + bool isValid() override { + return Memory::isValid() && isValidDataDT8() && isValidTempDT8(); + } + + bool isReset() override; + Status reset() override; + + const Primary* getPrimaries() { + return mConfigDT8->primary; + } + +#if defined(DALI_DT8_SUPPORT_XY) || defined(DALI_DT8_SUPPORT_PRIMARY_N) + Status setTemporaryCoordinateX(uint16_t value); + Status setTemporaryCoordinateY(uint16_t value); + +#if !defined(DALI_DT8_SUPPORT_XY) + uint16_t getTemporaryCooridanateX(); + uint16_t getTemporaryCooridanateY(); +#endif // !defined(DALI_DT8_SUPPORT_XY) +#endif // defined(DALI_DT8_SUPPORT_XY) || defined(DALI_DT8_SUPPORT_PRIMARY_N) + +#ifdef DALI_DT8_SUPPORT_TC + Status setTemporaryColorTemperature(uint16_t temperature); + Status setColorTemperatureCoolest(uint16_t temperature); + uint16_t getColorTemperatureCoolest(); + Status setColorTemperatureWarmest(uint16_t temperature); + uint16_t getColorTemperatureWarmest(); + Status setColorTemperaturePhisicalCoolest(uint16_t temperature); + uint16_t getColorTemperaturePhisicalCoolest(); + Status setColorTemperaturePhisicalWarmest(uint16_t temperature); + uint16_t getColorTemperaturePhisicalWarmest(); +#endif // DALI_DT8_SUPPORT_TC + + Status storePrimaryTy(uint8_t n, uint16_t ty); + Status storePrimaryCoordinate(uint8_t n, uint16_t x, uint16_t y); + +#ifdef DALI_DT8_SUPPORT_PRIMARY_N + Status setTemporaryPrimaryLevel(uint8_t n, uint16_t level); + uint16_t getPrimaryTy(uint8_t n); + uint16_t getPrimaryCoordinateX(uint8_t n); + uint16_t getPrimaryCoordinateY(uint8_t n); +#endif // DALI_DT8_SUPPORT_PRIMARY_N + + const DefaultsDT8* getDefaults() { + return mDefaults; + } + +private: + MemoryDT8(const MemoryDT8& other) = delete; + MemoryDT8& operator=(const MemoryDT8&) = delete; + + bool isColorValid(const ColorDT8& color, bool canTypeBeMask); + + bool isValidConfigDT8(); + bool isValidDataDT8(); + bool isValidTempDT8(); + void resetRamDT8(bool initialize); + void resetConfigDT8(); + void resetDataDT8(bool initialize); + void resetTempDT8(bool initialize); + + Status writeConfig8(uintptr_t addr, uint8_t data) { + return internalBankWrite(3, addr, &data, sizeof(uint8_t)); + } + + Status writeConfig16(uintptr_t addr, uint16_t data) { + return internalBankWrite(3, addr, (uint8_t*)&data, sizeof(uint16_t)); + } + + Status writeData8(uintptr_t addr, uint8_t data) { + return internalBankWrite(4, addr, &data, sizeof(uint8_t)); + } + + Status writeData16(uintptr_t addr, uint16_t data) { + return internalBankWrite(4, addr, (uint8_t*)&data, sizeof(uint16_t)); + } + + Status writeData32(uintptr_t addr, uint32_t data) { + return internalBankWrite(4, addr, (uint8_t*)&data, sizeof(uint16_t)); + } + + Status writeDataColor(uintptr_t addr, const ColorDT8* color) { + return internalBankWrite(4, addr, (uint8_t*) color, sizeof(ColorDT8)); + } + + Status writeTempColor(uintptr_t addr, const ColorDT8* color) { + return writeTemp(addr, (uint8_t*) color, sizeof(ColorDT8)); + } + + typedef struct __attribute__((__packed__)) { + uint8_t size; // BANK mandatory field + uint8_t crc; // BANK mandatory field + uint8_t protection; + uint8_t version; + uint16_t colorTemperaturePhisicalCoolest; + uint16_t colorTemperaturePhisicalWarmest; + + Primary primary[6]; + } ConfigDT8; + + typedef struct __attribute__((__packed__)) { + uint8_t size; // BANK mandatory field + uint8_t crc; // BANK mandatory field + ColorDT8 powerOnColor; + ColorDT8 failureColor; + ColorDT8 sceneColor[16]; + +#ifdef DALI_DT8_SUPPORT_TC + uint16_t colorTemperatureCoolest; + uint16_t colorTemperatureWarmest; +#endif + + } DataDT8; + + typedef struct { + ColorDT8 actualColor; + } TempDT8; + + typedef struct { + ColorDT8 temporaryColor; +#if !defined(DALI_DT8_SUPPORT_XY) && defined(DALI_DT8_SUPPORT_PRIMARY_N) + uint16_t temporaryX; + uint16_t temporaryY; +#endif + ColorDT8 reportColor; + uint8_t featuresStatus; + } RamDT8; + + RamDT8 mRamDT8; + const DefaultsDT8* mDefaults; + const ConfigDT8* mConfigDT8; + const DataDT8* mDataDT8; + const TempDT8* mTempDT8; +}; + +} // namespace controller +} // namespace dali + +#endif // DALI_DT8 + +#endif // DALI_MEMORY_DT8_CONTROLLER_HPP_ diff --git a/src/dali/controller/query_store_dt8.cpp b/src/dali/controller/query_store_dt8.cpp new file mode 100644 index 0000000..7432d17 --- /dev/null +++ b/src/dali/controller/query_store_dt8.cpp @@ -0,0 +1,733 @@ +/* + * Copyright (c) 2015-2016, Arkadiusz Materek (arekmat@poczta.fm) + * + * All right reversed. Usage for commercial on not commercial + * purpose without written permission is not allowed. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. + */ + +#include "query_store_dt8.hpp" + +#ifdef DALI_DT8 + +namespace dali { +namespace controller { + +QueryStoreDT8::QueryStoreDT8(MemoryDT8* memory, LampDT8* lamp) : + QueryStore(memory, lamp) { +} + +bool QueryStoreDT8::queryIsFading() { + if (getLampControllerDT8()->isColorChanging()) { + return true; + } + return QueryStore::queryIsFading(); +} + +Status QueryStoreDT8::storeActualLevelInDtr() { + const ColorDT8& color = getLampControllerDT8()->getActualColor(); + getMemoryControllerDT8()->setReportColor(color); + return QueryStore::storeActualLevelInDtr(); +} + +Status QueryStoreDT8::storeDtrAsFailureLevel() { + const ColorDT8& color = getMemoryControllerDT8()->getTemporaryColor(); + switch (color.type) { +#ifdef DALI_DT8_SUPPORT_XY + case DALI_DT8_COLOR_TYPE_XY: +#endif + +#ifdef DALI_DT8_SUPPORT_TC + case DALI_DT8_COLOR_TYPE_TC: +#endif + +#ifdef DALI_DT8_SUPPORT_PRIMARY_N + case DALI_DT8_COLOR_TYPE_PRIMARY_N: +#endif + + getMemoryControllerDT8()->setFaliureColor(color); + break; + } + getMemoryControllerDT8()->resetTemporaryColor(); + return QueryStore::storeDtrAsFailureLevel(); +} + +Status QueryStoreDT8::storePowerOnLevel() { + const ColorDT8& color = getMemoryControllerDT8()->getTemporaryColor(); + switch (color.type) { + +#ifdef DALI_DT8_SUPPORT_XY + case DALI_DT8_COLOR_TYPE_XY: +#endif + +#ifdef DALI_DT8_SUPPORT_TC + case DALI_DT8_COLOR_TYPE_TC: +#endif + +#ifdef DALI_DT8_SUPPORT_PRIMARY_N + case DALI_DT8_COLOR_TYPE_PRIMARY_N: +#endif + getMemoryControllerDT8()->setPowerOnColor(color); + break; + } + getMemoryControllerDT8()->resetTemporaryColor(); + return QueryStore::storePowerOnLevel(); +} + +Status QueryStoreDT8::storeDtrAsScene(uint8_t scene) { + const ColorDT8& color = getMemoryControllerDT8()->getTemporaryColor(); + switch (color.type) { + +#ifdef DALI_DT8_SUPPORT_XY + case DALI_DT8_COLOR_TYPE_XY: +#endif + +#ifdef DALI_DT8_SUPPORT_TC + case DALI_DT8_COLOR_TYPE_TC: +#endif + +#ifdef DALI_DT8_SUPPORT_PRIMARY_N + case DALI_DT8_COLOR_TYPE_PRIMARY_N: +#endif + getMemoryControllerDT8()->setColorForScene(scene, color); + break; + } + getMemoryControllerDT8()->resetTemporaryColor(); // TODO reset if color type is invalid? + return QueryStore::storeDtrAsScene(scene); +} + +Status QueryStoreDT8::removeFromScene(uint8_t scene) { + ColorDT8 color; + getMemoryControllerDT8()->setColorForScene(scene, color); + return QueryStore::removeFromScene(scene); +} + +uint8_t QueryStoreDT8::queryActualLevel() { + getMemoryControllerDT8()->setReportColor(getLampControllerDT8()->getActualColor()); + return QueryStore::queryActualLevel(); +} + +uint8_t QueryStoreDT8::queryPowerOnLevel() { + getMemoryControllerDT8()->setReportColor(getMemoryControllerDT8()->getPowerOnColor()); + return QueryStore::queryPowerOnLevel(); +} + +uint8_t QueryStoreDT8::queryFaliureLevel() { + getMemoryControllerDT8()->setReportColor(getMemoryControllerDT8()->getFaliureColor()); + return QueryStore::queryFaliureLevel(); +} + +uint8_t QueryStoreDT8::queryLevelForScene(uint8_t scene) { + getMemoryControllerDT8()->setReportColor(getMemoryControllerDT8()->getColorForScene(scene)); + return QueryStore::queryLevelForScene(scene); +} + +Status QueryStoreDT8::storeGearFeatures() { + uint8_t featuresStatus = getMemoryController()->getDTR(); + return getMemoryControllerDT8()->setFeaturesStatus(featuresStatus & 0x01); +} + +uint8_t QueryStoreDT8::queryGearFeatures() { + uint8_t featuresStatus = getMemoryControllerDT8()->getFeaturesStatus(); + return featuresStatus; +} + +uint8_t QueryStoreDT8::queryColorStatus() { + uint8_t status = 0; + if (getLampControllerDT8()->isXYCoordinateLimitError()) { + status |= (1 << DALI_DT8_COLOR_TYPE_XY); + } + if (getLampControllerDT8()->isTemeratureLimitError()) { + status |= (1 << DALI_DT8_COLOR_TYPE_TC); + } + switch (getLampControllerDT8()->getActualColor().type) { + case DALI_DT8_COLOR_TYPE_XY: + status |= (0x10 << DALI_DT8_COLOR_TYPE_XY); + break; + case DALI_DT8_COLOR_TYPE_TC: + status |= (0x10 << DALI_DT8_COLOR_TYPE_TC); + break; + case DALI_DT8_COLOR_TYPE_PRIMARY_N: + status |= (0x10 << DALI_DT8_COLOR_TYPE_PRIMARY_N); + break; + case DALI_DT8_COLOR_TYPE_RGBWAF: + status |= (0x10 << DALI_DT8_COLOR_TYPE_RGBWAF); + break; + } + return status; +} + +uint8_t QueryStoreDT8::queryColorTypes() { + uint8_t colorTypes = 0; + +#ifdef DALI_DT8_SUPPORT_XY + colorTypes |= DALI_DT8_COLOUR_TYPE_FEATURES_XY; +#endif // DALI_DT8_SUPPORT_XY + +#ifdef DALI_DT8_SUPPORT_TC + colorTypes |= DALI_DT8_COLOUR_TYPE_FEATURES_TC; +#endif // DALI_DT8_SUPPORT_TC + +#ifdef DALI_DT8_SUPPORT_PRIMARY_N + colorTypes |= (DALI_DT8_NUMBER_OF_PRIMARIES << 2) & DALI_DT8_COLOUR_TYPE_FEATURES_PRIMARY_N; +#endif // DALI_DT8_SUPPORT_PRIMARY_N + + return colorTypes; +} + +Status QueryStoreDT8::queryColorValue() { + Status status = Status::OK; + uint16_t value = DALI_DT8_MASK16; + uint8_t type = getMemoryController()->getDTR(); + + switch (type) { +#ifdef DALI_DT8_SUPPORT_XY + case 0: // x-COORDINATE + value = queryCoordinateX(getLampControllerDT8()->getActualColor()); + break; + + case 1: // y-COORDINATE + value = queryCoordinateY(getLampControllerDT8()->getActualColor()); + break; +#endif + +#ifdef DALI_DT8_SUPPORT_TC + case 2: // COLOUR TEMPERATURE TC + value = queryColorTemperature(getLampControllerDT8()->getActualColor()); + break; +#endif + +#ifdef DALI_DT8_SUPPORT_PRIMARY_N + case 3: // PRIMARY N DIMLEVEL 0 + value = queryPrimaryLevel(getLampControllerDT8()->getActualColor(), 0); + break; + + case 4: // PRIMARY N DIMLEVEL 1 + value = queryPrimaryLevel(getLampControllerDT8()->getActualColor(), 1); + break; + + case 5: // PRIMARY N DIMLEVEL 2 + value = queryPrimaryLevel(getLampControllerDT8()->getActualColor(), 2); + break; + + case 6: // PRIMARY N DIMLEVEL 3 + value = queryPrimaryLevel(getLampControllerDT8()->getActualColor(), 3); + break; + + case 7: // PRIMARY N DIMLEVEL 4 + value = queryPrimaryLevel(getLampControllerDT8()->getActualColor(), 4); + break; + + case 8: // PRIMARY N DIMLEVEL 5 + value = queryPrimaryLevel(getLampControllerDT8()->getActualColor(), 5); + break; +#endif + +#ifdef DALI_DT8_SUPPORT_PRIMARY_N + case 64: // x-COORDINATE PRIMARY N 0 + value = getMemoryControllerDT8()->getPrimaryCoordinateX(0); + break; + case 65: // y-COORDINATE PRIMARY N 0 + value = getMemoryControllerDT8()->getPrimaryCoordinateY(0); + break; + + case 66: // TY PRIMARY N 0 + value = getMemoryControllerDT8()->getPrimaryTy(0); + break; + + case 67: // x-COORDINATE PRIMARY N 1 + value = getMemoryControllerDT8()->getPrimaryCoordinateX(1); + break; + + case 68: // y-COORDINATE PRIMARY N 1 + value = getMemoryControllerDT8()->getPrimaryCoordinateY(1); + break; + + case 69: // TY PRIMARY N 1 + value = getMemoryControllerDT8()->getPrimaryTy(1); + break; + + case 70: // x-COORDINATE PRIMARY N 2 + value = getMemoryControllerDT8()->getPrimaryCoordinateX(2); + break; + + case 71: // y-COORDINATE PRIMARY N 2 + value = getMemoryControllerDT8()->getPrimaryCoordinateY(2); + break; + + case 72: // TY PRIMARY N 2 + value = getMemoryControllerDT8()->getPrimaryTy(2); + break; + + case 73: // x-COORDINATE PRIMARY N 3 + value = getMemoryControllerDT8()->getPrimaryCoordinateX(3); + break; + + case 74: // y-COORDINATE PRIMARY N 3 + value = getMemoryControllerDT8()->getPrimaryCoordinateY(3); + break; + + case 75: // TY PRIMARY N 3 + value = getMemoryControllerDT8()->getPrimaryTy(3); + break; + + case 76: // x-COORDINATE PRIMARY N 4 + value = getMemoryControllerDT8()->getPrimaryCoordinateX(4); + break; + + case 77: // y-COORDINATE PRIMARY N 4 + value = getMemoryControllerDT8()->getPrimaryCoordinateY(4); + break; + + case 78: // TY PRIMARY N 4 + value = getMemoryControllerDT8()->getPrimaryTy(3); + break; + + case 79: // x-COORDINATE PRIMARY N 5 + value = getMemoryControllerDT8()->getPrimaryCoordinateX(5); + break; + + case 80: // y-COORDINATE PRIMARY N 5 + value = getMemoryControllerDT8()->getPrimaryCoordinateY(5); + break; + + case 81: // TY PRIMARY N 5 + value = getMemoryControllerDT8()->getPrimaryTy(5); + break; + + case 82: // NUMBER OF PRIMARIES + value = DALI_DT8_NUMBER_OF_PRIMARIES << 8; + break; +#else // DALI_DT8_SUPPORT_PRIMARY_N + case 64: // x-COORDINATE PRIMARY N 0 + case 65: // y-COORDINATE PRIMARY N 0 + case 66: // TY PRIMARY N 0 + case 67: // x-COORDINATE PRIMARY N 1 + case 68: // y-COORDINATE PRIMARY N 1 + case 69: // TY PRIMARY N 1 + case 70: // x-COORDINATE PRIMARY N 2 + case 71: // y-COORDINATE PRIMARY N 2 + case 72: // TY PRIMARY N 2 + case 73: // x-COORDINATE PRIMARY N 3 + case 74: // y-COORDINATE PRIMARY N 3 + case 75: // TY PRIMARY N 3 + case 76: // x-COORDINATE PRIMARY N 4 + case 77: // y-COORDINATE PRIMARY N 4 + case 78: // TY PRIMARY N 4 + case 79: // x-COORDINATE PRIMARY N 5 + case 80: // y-COORDINATE PRIMARY N 5 + case 81: // TY PRIMARY N 5 + case 82: // NUMBER OF PRIMARIES + value = DALI_DT8_MASK16; + break; +#endif // DALI_DT8_SUPPORT_PRIMARY_N + +#ifdef DALI_DT8_SUPPORT_TC + case 128: // COLOUR TEMPERATURE TC COOLEST + value = getMemoryControllerDT8()->getColorTemperatureCoolest(); + break; + + case 129: // COLOUR TEMPERATURE TC PHYSICAL COOLEST + value = getMemoryControllerDT8()->getColorTemperaturePhisicalCoolest(); + break; + + case 130: // COLOUR TEMPERATURE TC WARMEST + value = getMemoryControllerDT8()->getColorTemperatureWarmest(); + break; + + case 131: // COLOUR TEMPERATURE TC PHYSICAL WARMEST + value = getMemoryControllerDT8()->getColorTemperaturePhisicalWarmest(); + break; +#endif + +#if defined(DALI_DT8_SUPPORT_XY) || defined(DALI_DT8_SUPPORT_PRIMARY_N) + case 192: // TEMPORARY x-COORDINATE +# ifndef DALI_DT8_SUPPORT_XY + value = getMemoryControllerDT8()->getTemporaryCooridanateX(); +# else + value = queryCoordinateX(getMemoryControllerDT8()->getTemporaryColor()); +#endif + break; + + case 193: // TEMPORARY y-COORDINATE +# ifndef DALI_DT8_SUPPORT_XY + value = getMemoryControllerDT8()->getTemporaryCooridanateY(); +# else + value = queryCoordinateY(getMemoryControllerDT8()->getTemporaryColor()); +#endif + break; +#endif + +#ifdef DALI_DT8_SUPPORT_TC + case 194: // TEMPORARY COLOUR TEMPERATURE TC + value = queryColorTemperature(getMemoryControllerDT8()->getTemporaryColor()); + break; +#endif + +#ifdef DALI_DT8_SUPPORT_PRIMARY_N + case 195: // TEMPORARY PRIMARY N DIMLEVEL 0 + value = queryPrimaryLevel(getMemoryControllerDT8()->getTemporaryColor(), 0); + break; + + case 196: // TEMPORARY PRIMARY N DIMLEVEL 1 + value = queryPrimaryLevel(getMemoryControllerDT8()->getTemporaryColor(), 1); + break; + + case 197: // TEMPORARY PRIMARY N DIMLEVEL 2 + value = queryPrimaryLevel(getMemoryControllerDT8()->getTemporaryColor(), 2); + break; + + case 198: // TEMPORARY PRIMARY N DIMLEVEL 3 + value = queryPrimaryLevel(getMemoryControllerDT8()->getTemporaryColor(), 3); + break; + + case 199: // TEMPORARY PRIMARY N DIMLEVEL 4 + value = queryPrimaryLevel(getMemoryControllerDT8()->getTemporaryColor(), 4); + break; + + case 200: // TEMPORARY PRIMARY N DIMLEVEL 5 + value = queryPrimaryLevel(getMemoryControllerDT8()->getTemporaryColor(), 5); + break; +#endif + + case 208: // TEMPORARY COLOUR TYPE + value = queryColorType(getMemoryControllerDT8()->getTemporaryColor()); + break; + +#ifdef DALI_DT8_SUPPORT_XY + case 224: // REPORT x-COORDINATE + value = queryCoordinateX(getMemoryControllerDT8()->getReportColor()); + break; + + case 225: // REPORT y-COORDINATE + value = queryCoordinateY(getMemoryControllerDT8()->getReportColor()); + break; +#endif + +#ifdef DALI_DT8_SUPPORT_TC + case 226: // REPORT COLOUR TEMPERATURE TC + value = queryColorTemperature(getMemoryControllerDT8()->getReportColor()); + break; +#endif + +#ifdef DALI_DT8_SUPPORT_PRIMARY_N + case 227: // REPORT PRIMARY N DIMLEVEL 0 + value = queryPrimaryLevel(getMemoryControllerDT8()->getReportColor(), 0); + break; + + case 228: // REPORT PRIMARY N DIMLEVEL 1 + value = queryPrimaryLevel(getMemoryControllerDT8()->getReportColor(), 1); + break; + + case 229: // REPORT PRIMARY N DIMLEVEL 2 + value = queryPrimaryLevel(getMemoryControllerDT8()->getReportColor(), 2); + break; + + case 230: // REPORT PRIMARY N DIMLEVEL 3 + value = queryPrimaryLevel(getMemoryControllerDT8()->getReportColor(), 3); + break; + + case 231: // REPORT PRIMARY N DIMLEVEL 4 + value = queryPrimaryLevel(getMemoryControllerDT8()->getReportColor(), 4); + break; + + case 232: // REPORT PRIMARY N DIMLEVEL 5 + value = queryPrimaryLevel(getMemoryControllerDT8()->getReportColor(), 5); + break; +#endif + + case 240: // REPORT COLOUR TYPE + value = queryColorType(getMemoryControllerDT8()->getReportColor()); + break; + + default: // Not supported + status = Status::INVALID; + break; + } + + if (status == Status::OK) { + getMemoryController()->setDTR1(value >> 8); + getMemoryController()->setDTR(value & 0xff); + } + + return status; +} + +Status QueryStoreDT8::setTemporaryCoordinateX() { +#if defined(DALI_DT8_SUPPORT_XY) || defined(DALI_DT8_SUPPORT_PRIMARY_N) + return getMemoryControllerDT8()->setTemporaryCoordinateX(uint16FromDtrAndDtr1()); +#else + return getMemoryControllerDT8()->resetTemporaryColor(); +#endif +} + +Status QueryStoreDT8::setTemporaryCoordinateY() { +#if defined(DALI_DT8_SUPPORT_XY) || defined(DALI_DT8_SUPPORT_PRIMARY_N) + return getMemoryControllerDT8()->setTemporaryCoordinateY(uint16FromDtrAndDtr1()); +#else + return getMemoryControllerDT8()->resetTemporaryColor(); +#endif +} + +Status QueryStoreDT8::setTemporaryColorTemperature() { +#ifdef DALI_DT8_SUPPORT_TC + return getMemoryControllerDT8()->setTemporaryColorTemperature(uint16FromDtrAndDtr1()); +#else + return getMemoryControllerDT8()->resetTemporaryColor(); +#endif +} + +Status QueryStoreDT8::setTemporaryPrimaryLevel() { +#ifdef DALI_DT8_SUPPORT_PRIMARY_N + return getMemoryControllerDT8()->setTemporaryPrimaryLevel(getMemoryController()->getDTR2(), uint16FromDtrAndDtr1()); +#else + return getMemoryControllerDT8()->resetTemporaryColor(); +#endif // DALI_DT8_SUPPORT_PRIMARY_N + +} + +Status QueryStoreDT8::setTemporaryRGB() { + return getMemoryControllerDT8()->resetTemporaryColor(); +} + +Status QueryStoreDT8::setTemporaryWAF() { + return getMemoryControllerDT8()->resetTemporaryColor(); +} + +Status QueryStoreDT8::setTemporaryRGBWAFControl() { + return getMemoryControllerDT8()->resetTemporaryColor(); +} + +#ifdef DALI_DT8_SUPPORT_TC + +Status QueryStoreDT8::storeColourTemperatureCoolest(uint16_t temperature) { + MemoryDT8* memory = getMemoryControllerDT8(); + uint16_t colorTemperaturePhisicalCoolest = memory->getColorTemperaturePhisicalCoolest(); + if (temperature < colorTemperaturePhisicalCoolest) { + temperature = colorTemperaturePhisicalCoolest; + } + Status status = Status::OK; + if (temperature > memory->getColorTemperatureWarmest()) { + status = storeColourTemperatureWarmest(temperature); + uint16_t colorTemperatureWarmest = memory->getColorTemperatureWarmest(); + if (temperature > colorTemperatureWarmest) { + temperature = colorTemperatureWarmest; + } + } + if (memory->setColorTemperatureCoolest(temperature) != Status::OK) { + status = Status::ERROR; + } + return status; +} + +Status QueryStoreDT8::storeColourTemperatureWarmest(uint16_t temperature) { + MemoryDT8* memory = getMemoryControllerDT8(); + uint16_t colorTemperaturePhisicalWarmest = memory->getColorTemperaturePhisicalWarmest(); + if (temperature > colorTemperaturePhisicalWarmest) { + temperature = colorTemperaturePhisicalWarmest; + } + Status status = Status::OK; + if (temperature < getMemoryControllerDT8()->getColorTemperatureCoolest()) { + status = storeColourTemperatureCoolest(temperature); + uint16_t colorTemperatureCoolest = memory->getColorTemperatureCoolest(); + if (temperature < colorTemperatureCoolest) { + temperature = colorTemperatureCoolest; + } + } + if (memory->setColorTemperatureWarmest(temperature) != Status::OK) { + status = Status::ERROR; + } + return status; +} + +Status QueryStoreDT8::storeColourTemperaturePhisicalCoolest(uint16_t temperature) { + MemoryDT8* memory = getMemoryControllerDT8(); + Status status = Status::OK; + if (temperature == DALI_DT8_MASK16) { + if (memory->setColorTemperatureCoolest(DALI_DT8_MASK16) != Status::OK) + status = Status::ERROR; + if (memory->setColorTemperatureWarmest(DALI_DT8_MASK16) != Status::OK) + status = Status::ERROR; + if (memory->setColorTemperaturePhisicalCoolest(DALI_DT8_MASK16) != Status::OK) + status = Status::ERROR; + if (memory->setColorTemperaturePhisicalWarmest(DALI_DT8_MASK16) != Status::OK) + status = Status::ERROR; + } else { + if (temperature < DALI_DT8_TC_COOLEST) { + temperature = DALI_DT8_TC_COOLEST; + } + uint16_t colorTemperaturePhisicalWarmest = memory->getColorTemperaturePhisicalWarmest(); + if (colorTemperaturePhisicalWarmest != DALI_DT8_MASK16 && temperature > colorTemperaturePhisicalWarmest) { + if (memory->setColorTemperaturePhisicalWarmest(temperature) != Status::OK) + status = Status::ERROR; + uint16_t colorTemperatureWarmest = memory->getColorTemperatureWarmest(); + if (temperature > colorTemperatureWarmest) { + if (memory->setColorTemperatureWarmest(temperature) != Status::OK) + status = Status::ERROR; + } + } + uint16_t colorTemperatureCoolest = memory->getColorTemperatureCoolest(); + if (colorTemperatureCoolest == DALI_DT8_MASK16 || colorTemperatureCoolest < temperature) { + if (memory->setColorTemperatureCoolest(temperature) != Status::OK) + status = Status::ERROR; + } + if (memory->setColorTemperaturePhisicalCoolest(temperature) != Status::OK) + status = Status::ERROR; + } + return status; +} + +Status QueryStoreDT8::storeColourTemperaturePhisicalWarmest(uint16_t temperature) { + MemoryDT8* memory = getMemoryControllerDT8(); + Status status = Status::OK; + if (temperature == DALI_DT8_MASK16) { + if (memory->setColorTemperatureCoolest(DALI_DT8_MASK16) != Status::OK) + status = Status::ERROR; + if (memory->setColorTemperatureWarmest(DALI_DT8_MASK16) != Status::OK) + status = Status::ERROR; + if (memory->setColorTemperaturePhisicalCoolest(DALI_DT8_MASK16) != Status::OK) + status = Status::ERROR; + if (memory->setColorTemperaturePhisicalWarmest(DALI_DT8_MASK16) != Status::OK) + status = Status::ERROR; + } else { + if (temperature > DALI_DT8_TC_WARMESR) { + temperature = DALI_DT8_TC_WARMESR; + } + uint16_t colorTemperaturePhisicalCoolest = memory->getColorTemperaturePhisicalCoolest(); + if (colorTemperaturePhisicalCoolest != DALI_DT8_MASK16 && temperature < colorTemperaturePhisicalCoolest) { + if (memory->setColorTemperaturePhisicalCoolest(temperature) != Status::OK) + status = Status::ERROR; + uint16_t colorTemperatureCoolest = memory->getColorTemperatureCoolest(); + if (temperature < colorTemperatureCoolest) { + if (memory->setColorTemperatureCoolest(temperature) != Status::OK) + status = Status::ERROR; + } + } + uint16_t colorTemperatureWarmest = memory->getColorTemperatureWarmest(); + if (colorTemperatureWarmest == DALI_DT8_MASK16 || colorTemperatureWarmest > temperature) { + if (memory->setColorTemperatureWarmest(temperature) != Status::OK) + status = Status::ERROR; + } + if (memory->setColorTemperaturePhisicalWarmest(temperature) != Status::OK) + status = Status::ERROR; + } + return status; +} + +Status QueryStoreDT8::storeColourTemperatureLimit() { + uint8_t limitType = getMemoryController()->getDTR2(); + uint16_t temperature = uint16FromDtrAndDtr1(); + switch (limitType) { + case 0: // coolest + return storeColourTemperatureCoolest(temperature); + case 1: // warmest + return storeColourTemperatureWarmest(temperature); + case 2: // physical coolest + return storeColourTemperaturePhisicalCoolest(temperature); + case 3: // physical warmest + return storeColourTemperaturePhisicalWarmest(temperature); + } + return Status::INVALID; +} + +#endif // DALI_DT8_SUPPORT_TC + +#ifdef DALI_DT8_SUPPORT_PRIMARY_N +Status QueryStoreDT8::storePrimaryTY() { + uint8_t n = getMemoryController()->getDTR2(); + uint16_t ty = uint16FromDtrAndDtr1(); + if (n < DALI_DT8_NUMBER_OF_PRIMARIES) { + return getMemoryControllerDT8()->storePrimaryTy(n, ty); + } else { + return Status::ERROR; + } +} + +Status QueryStoreDT8::storePrimaryCoordinate() { + uint8_t n = getMemoryController()->getDTR2(); + if (n < DALI_DT8_NUMBER_OF_PRIMARIES) { + const ColorDT8& color = getMemoryControllerDT8()->getTemporaryColor(); + if (color.type != DALI_DT8_COLOR_TYPE_XY) { + return Status::ERROR; + } + uint16_t x; + uint16_t y; +#ifdef DALI_DT8_SUPPORT_XY + x = color.value.xy.x; + y = color.value.xy.y; +#else + x = getMemoryControllerDT8()->getTemporaryCooridanateX(); + y = getMemoryControllerDT8()->getTemporaryCooridanateY(); +#endif + return getMemoryControllerDT8()->storePrimaryCoordinate(n, x, y); + } + return Status::ERROR; +} +#endif // DALI_DT8_SUPPORT_PRIMARY_N + +uint16_t QueryStoreDT8::queryColorType(const ColorDT8& color) { + switch (color.type) { + +#ifdef DALI_DT8_SUPPORT_XY + case DALI_DT8_COLOR_TYPE_XY: +#endif + +#ifdef DALI_DT8_SUPPORT_TC + case DALI_DT8_COLOR_TYPE_TC: +#endif + +#ifdef DALI_DT8_SUPPORT_PRIMARY_N + case DALI_DT8_COLOR_TYPE_PRIMARY_N: +#endif + + return ((0x10 << (uint16_t)(color.type)) << 8) | 0x00ff; + default: + return DALI_DT8_MASK16; + } +} + +#ifdef DALI_DT8_SUPPORT_XY +uint16_t QueryStoreDT8::queryCoordinateX(const ColorDT8& color) { + if (color.type == DALI_DT8_COLOR_TYPE_XY) { + return color.value.xy.x; + } else { + return DALI_DT8_MASK16; + } +} + +uint16_t QueryStoreDT8::queryCoordinateY(const ColorDT8& color) { + if (color.type == DALI_DT8_COLOR_TYPE_XY) { + return color.value.xy.y; + } else { + return DALI_DT8_MASK16; + } +} +#endif // DALI_DT8_SUPPORT_XY + +#ifdef DALI_DT8_SUPPORT_TC +uint16_t QueryStoreDT8::queryColorTemperature(const ColorDT8& color) { + if (color.type == DALI_DT8_COLOR_TYPE_TC) { + return color.value.tc; + } else { + return DALI_DT8_MASK16; + } +} +#endif // DALI_DT8_SUPPORT_TC + +#ifdef DALI_DT8_SUPPORT_PRIMARY_N +uint16_t QueryStoreDT8::queryPrimaryLevel(const ColorDT8& color, uint8_t n) { + if ((n < DALI_DT8_NUMBER_OF_PRIMARIES) && (color.type == DALI_DT8_COLOR_TYPE_PRIMARY_N)) { + return color.value.primary[n]; + } else { + return DALI_DT8_MASK16; + } +} +#endif // DALI_DT8_SUPPORT_PRIMARY_N + +} // namespace controller +} // namespace dali + +#endif // DALI_DT8 diff --git a/src/dali/controller/query_store_dt8.hpp b/src/dali/controller/query_store_dt8.hpp new file mode 100644 index 0000000..d20d1dd --- /dev/null +++ b/src/dali/controller/query_store_dt8.hpp @@ -0,0 +1,108 @@ +/* + * Copyright (c) 2015-2016, Arkadiusz Materek (arekmat@poczta.fm) + * + * All right reversed. Usage for commercial on not commercial + * purpose without written permission is not allowed. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. + */ + +#ifndef DALI_CONTROLLER_QUERY_DT8_HPP_ +#define DALI_CONTROLLER_QUERY_DT8_HPP_ + +#include + +#ifdef DALI_DT8 + +#include "lamp_dt8.hpp" +#include "memory_dt8.hpp" +#include "query_store.hpp" + +namespace dali { +namespace controller { + +class QueryStoreDT8: public QueryStore { + +public: + explicit QueryStoreDT8(MemoryDT8* memory, LampDT8* lamp); + + bool queryIsFading() override; + + Status storeActualLevelInDtr() override; + Status storeDtrAsFailureLevel() override; + Status storePowerOnLevel() override; + Status storeDtrAsScene(uint8_t scene) override; + Status removeFromScene(uint8_t scene) override; + uint8_t queryActualLevel() override; + uint8_t queryPowerOnLevel() override; + uint8_t queryFaliureLevel() override; + uint8_t queryLevelForScene(uint8_t scene) override; + + Status storeGearFeatures(); + uint8_t queryGearFeatures(); + uint8_t queryColorStatus(); + uint8_t queryColorTypes(); + Status queryColorValue(); + + Status setTemporaryCoordinateX(); + Status setTemporaryCoordinateY(); + Status setTemporaryColorTemperature(); + Status setTemporaryPrimaryLevel(); + Status setTemporaryRGB(); + Status setTemporaryWAF(); + Status setTemporaryRGBWAFControl(); + +#ifdef DALI_DT8_SUPPORT_TC + Status storeColourTemperatureLimit(); +#endif + +#ifdef DALI_DT8_SUPPORT_PRIMARY_N + Status storePrimaryTY(); + Status storePrimaryCoordinate(); +#endif // DALI_DT8_SUPPORT_PRIMARY_N + +private: + QueryStoreDT8(const QueryStoreDT8& other) = delete; + QueryStoreDT8& operator=(const QueryStoreDT8&) = delete; + + MemoryDT8* getMemoryControllerDT8() { + return (MemoryDT8*) getMemoryController(); + } + + LampDT8* getLampControllerDT8() { + return (LampDT8*) getLampController(); + } + + uint16_t uint16FromDtrAndDtr1() { + return getMemoryController()->uint16FromDtrAndDtr1(); + } + + uint16_t queryColorType(const ColorDT8& color); + +#ifdef DALI_DT8_SUPPORT_XY + uint16_t queryCoordinateX(const ColorDT8& color); + uint16_t queryCoordinateY(const ColorDT8& color); +#endif + +#ifdef DALI_DT8_SUPPORT_TC + Status storeColourTemperatureCoolest(uint16_t temperature); + Status storeColourTemperatureWarmest(uint16_t temperature); + Status storeColourTemperaturePhisicalCoolest(uint16_t temperature); + Status storeColourTemperaturePhisicalWarmest(uint16_t temperature); + + uint16_t queryColorTemperature(const ColorDT8& color); +#endif + +#ifdef DALI_DT8_SUPPORT_PRIMARY_N + uint16_t queryPrimaryLevel(const ColorDT8& color, uint8_t n); +#endif +}; + +} // namespace controller +} // namespace dali + +#endif // DALI_DT8 + +#endif // DALI_CONTROLLER_QUERY_DT8_HPP_ diff --git a/src/dali/dali_dt8.hpp b/src/dali/dali_dt8.hpp new file mode 100644 index 0000000..ddb292e --- /dev/null +++ b/src/dali/dali_dt8.hpp @@ -0,0 +1,98 @@ +/* + * Copyright (c) 2015-2016, Arkadiusz Materek (arekmat@poczta.fm) + * + * All right reversed. Usage for commercial on not commercial + * purpose without written permission is not allowed. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. + */ + +#ifndef DALI_DALI_DT8_HPP_ +#define DALI_DALI_DT8_HPP_ + +#include "config_dt8.hpp" + +#ifdef DALI_DT8 + +#include "commands_dt8.hpp" +#include "dali.hpp" + +#define DALI_DT8_COLOR_TYPE_XY 0 +#define DALI_DT8_COLOR_TYPE_TC 1 +#define DALI_DT8_COLOR_TYPE_PRIMARY_N 2 +#define DALI_DT8_COLOR_TYPE_RGBWAF 3 + +#define DALI_DT8_COLOUR_TYPE_FEATURES_XY 0x01 +#define DALI_DT8_COLOUR_TYPE_FEATURES_TC 0x02 +#define DALI_DT8_COLOUR_TYPE_FEATURES_PRIMARY_N 0x1C +#define DALI_DT8_COLOUR_TYPE_FEATURES_RGBWAF 0xE0 + +#define DALI_DT8_FEATURES_AUTO_ACTIVATION 0x01 +#define DALI_DT8_FEATURES_AUTO_CALIBRATION 0x40 +#define DALI_DT8_FEATURES_AUTO_CALIBRATION_RECOVERY 0x80 + +#define DALI_DT8_STATUS_XY_OUT_OF_RANGE 0x01 +#define DALI_DT8_STATUS_TC_OUT_OF_RANGE 0x02 +#define DALI_DT8_STATUS_AUTO_CALIBRATION_RUNNING 0x04 +#define DALI_DT8_STATUS_AUTO_CALIBRATION_SUCCESSFUL 0x08 + +#define DALI_DT8_TC_COOLEST 1 +#define DALI_DT8_TC_WARMESR 65534 +#define DALI_DT8_PRIMARY_TY_MAX 32767 +#define DALI_DT8_RGBWAF_MAX 254 +#define DALI_DT8_MASK16 65535 + +#define DALI_DT8_RGBWAF_CONTROL_CHANNEL 0 +#define DALI_DT8_RGBWAF_CONTROL_COLOR 1 +#define DALI_DT8_RGBWAF_CONTROL_NORMALIZED 2 + +#define DALI_DT8_RGBWAF_CONTROL_CANNELS_MASK ((1 << DALI_DT8_NUMBER_OF_PRIMARIES) - 1) + +namespace dali { + +typedef struct { + uint16_t x; + uint16_t y; +} PointXY; + +typedef struct { + uint16_t ty; + PointXY xy; +} Primary; + +class ILampDT8 : public ILamp { +public: + virtual void setPrimary(const uint16_t primary[], uint8_t size, uint32_t changeTime) = 0; + virtual void getPrimary(uint16_t primary[], uint8_t size) = 0; + virtual bool isColorChanging() = 0; + virtual void abortColorChanging() = 0; +}; + +typedef struct { +public: + Primary primaryConfig[6]; + uint8_t colorType; +#ifdef DALI_DT8_SUPPORT_XY + uint16_t xCoordinate; + uint16_t yCoordinate; +#endif // DALI_DT8_SUPPORT_XY +#ifdef DALI_DT8_SUPPORT_TC + uint16_t tcCoolest; + uint16_t tcWarmest; + uint16_t tc; +#endif // DALI_DT8_SUPPORT_TC +#ifdef DALI_DT8_SUPPORT_PRIMARY_N + uint16_t primary[6]; +#endif // DALI_DT8_SUPPORT_PRIMARY_N +} DefaultsDT8; + +extern const DefaultsDT8 kDefaultsDT8; + +} // namespace dali + +#endif // DALI_DT8 + +#endif // DALI_DALI_DT8_HPP_ + diff --git a/src/dali/float_dt8.cpp b/src/dali/float_dt8.cpp new file mode 100644 index 0000000..84bcf06 --- /dev/null +++ b/src/dali/float_dt8.cpp @@ -0,0 +1,15 @@ +/* + * Copyright (c) 2015-2016, Arkadiusz Materek (arekmat@poczta.fm) + * + * Licensed under GNU General Public License 3.0 or later. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. + */ + +#include "float_dt8.hpp" + +namespace dali { + +} // namespace dali diff --git a/src/dali/float_dt8.hpp b/src/dali/float_dt8.hpp new file mode 100644 index 0000000..28e18a7 --- /dev/null +++ b/src/dali/float_dt8.hpp @@ -0,0 +1,131 @@ +/* + * Copyright (c) 2015-2016, Arkadiusz Materek (arekmat@poczta.fm) + * + * Licensed under GNU General Public License 3.0 or later. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. + */ + +#ifndef DALI_FLOAT_DT8_HPP_ +#define DALI_FLOAT_DT8_HPP_ + +#ifdef HW_FLOATING_POINT + +typedef float Float; + +#else + +#include + +#define BASE_PRECISION_SH 16 +#define BASE_PRECISION (1 << BASE_PRECISION_SH) +#define EXTRA_PRECISION_SH 13 +#define EXTRA_PRECISION (1 << EXTRA_PRECISION_SH) +#define PRECISION_SH (BASE_PRECISION_SH + EXTRA_PRECISION_SH) +#define PRECISION (BASE_PRECISION * EXTRA_PRECISION) + +namespace dali { + +class Float { +public: + + Float() { + } + + explicit Float(int32_t value) : mValue(value << EXTRA_PRECISION_SH) { + } + + Float(const Float& value) : mValue(value.mValue) { + } + + operator int32_t () const { + return (mValue + EXTRA_PRECISION / 2) >> EXTRA_PRECISION_SH; + } + + Float& operator = (const Float& r) { + mValue = r.mValue; + return *this; + } + + Float& operator = (int32_t value) { + mValue = value << EXTRA_PRECISION_SH; + return *this; + } + + bool operator == (const Float& r) const { + return mValue == r.mValue; + } + + bool operator != (const Float& r) const { + return mValue != r.mValue; + } + + bool operator < (const Float& r) const { + return mValue < r.mValue; + } + + bool operator <= (const Float& r) const { + return mValue <= r.mValue; + } + + bool operator > (const Float& r) const { + return mValue > r.mValue; + } + + bool operator >= (const Float& r) const { + return mValue >= r.mValue; + } + + Float operator + (const Float& r) const { + Float result = r; + result.mValue += mValue; + return result; + } + + void operator += (const Float& r) { + mValue += r.mValue; + } + + Float operator - (const Float& r) const { + Float result = *this; + result.mValue -= r.mValue; + return result; + } + + void operator -= (const Float& r) { + mValue -= r.mValue; + } + + Float operator * (const Float& r) const { + Float result; + result.mValue = ((int64_t) mValue * r.mValue + PRECISION / 2) >> PRECISION_SH; + return result; + } + + void operator *= (const Float& r) { + mValue = ((int64_t) mValue * r.mValue + PRECISION / 2) >> PRECISION_SH; + } + + Float operator / (Float r) const { + Float result; + result.mValue = (((int64_t) mValue << PRECISION_SH) + r.mValue / 2) / r.mValue; + return result; + } + + void operator /= (const Float& r) { + mValue = (((int64_t) mValue << PRECISION_SH) + r.mValue / 2) / r.mValue; + } + + friend Float operator + (Float value); + friend Float operator - (Float value); + +private: + int32_t mValue; +}; + +} // namespace dali + +#endif // HW_FLOATING_POINT +#endif // DALI_FLOAT_DT8_HPP_ diff --git a/src/dali/slave_dt8.cpp b/src/dali/slave_dt8.cpp new file mode 100644 index 0000000..c65636c --- /dev/null +++ b/src/dali/slave_dt8.cpp @@ -0,0 +1,152 @@ +/* + * Copyright (c) 2015-2016, Arkadiusz Materek (arekmat@poczta.fm) + * + * Licensed under GNU General Public License 3.0 or later. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. + */ + +#include "slave_dt8.hpp" + +#ifdef DALI_DT8 + +namespace dali { + +// static +Slave* SlaveDT8::create(IMemory* memoryDriver, ILamp* lampDriver, IBus* busDriver, ITimer* timer) { + controller::MemoryDT8* memory = new controller::MemoryDT8(memoryDriver, &kDefaultsDT8); + controller::LampDT8* lamp = new controller::LampDT8(lampDriver, memory); + controller::QueryStoreDT8* queryStore = new controller::QueryStoreDT8(memory, lamp); + controller::Bus* bus = new controller::Bus(busDriver); + controller::Initialization* initialization = new controller::Initialization(timer, memory); + + return new SlaveDT8(memory, lamp, queryStore, bus, initialization); +} + +SlaveDT8::SlaveDT8(controller::Memory* memory, controller::Lamp* lamp, controller::QueryStore* queryStore, + controller::Bus* bus, controller::Initialization* initialization) : + Slave(memory, lamp, queryStore, bus, initialization) { +} + +Status SlaveDT8::handleHandleDaliDeviceTypeCommand(uint16_t repeatCount, Command cmd, uint8_t param, + uint8_t device_type) { + if (device_type != 8) { + return Status::INVALID; + } + + CommandDT8 cmdDT8 = (CommandDT8)cmd; + + switch (cmdDT8) { + case CommandDT8::SET_TEMPORARY_X_COORDINATE_WORD: + return getQueryStoreControllerDT8()->setTemporaryCoordinateX(); + + case CommandDT8::SET_TEMPORARY_Y_COORDINATE_WORD: + return getQueryStoreControllerDT8()->setTemporaryCoordinateY(); + + case CommandDT8::ACTIVATE: + return getLampControllerDT8()->activate(); + +#ifdef DALI_DT8_SUPPORT_XY + case CommandDT8::X_COORDINATE_STEP_UP: + return getLampControllerDT8()->coordinateStepUpX(); + + case CommandDT8::X_COORDINATE_STEP_DOWN: + return getLampControllerDT8()->coordinateStepDownX(); + + case CommandDT8::Y_COORDINATE_STEP_UP: + return getLampControllerDT8()->coordinateStepUpY(); + + case CommandDT8::Y_COORDINATE_STEP_DOWN: + return getLampControllerDT8()->coordinateStepDownY(); +#endif // DALI_DT8_SUPPORT_XY + + case CommandDT8::SET_TEMPORARY_COLOUR_TEMPERATURE: + return getQueryStoreControllerDT8()->setTemporaryColorTemperature(); + +#ifdef DALI_DT8_SUPPORT_TC + case CommandDT8::COLOUR_TEMPERATURE_STEP_COOLER: + return getLampControllerDT8()->colorTemperatureStepCooler(); + + case CommandDT8::COLOUR_TEMPERATURE_STEP_WARMER: + return getLampControllerDT8()->colorTemperatureStepWarmer(); +#endif // DALI_DT8_SUPPORT_TC + + case CommandDT8::SET_TEMPORARY_PRIMARY_N_DIMLEVEL: + return getQueryStoreControllerDT8()->setTemporaryPrimaryLevel(); + + case CommandDT8::SET_TEMPORARY_RGB_DIMLEVEL: + return getQueryStoreControllerDT8()->setTemporaryRGB(); + + case CommandDT8::SET_TEMPORARY_WAF_DIMLEVEL: + return getQueryStoreControllerDT8()->setTemporaryWAF(); + + case CommandDT8::SET_TEMPORARY_RGBWAF_CONTROL: + return getQueryStoreControllerDT8()->setTemporaryRGBWAFControl(); + + case CommandDT8::COPY_REPORT_TO_TEMPORARY: + return getMemoryControllerDT8()->copyReportToTemporary(); + +#ifdef DALI_DT8_SUPPORT_PRIMARY_N + case CommandDT8::STORE_TY_PRIMARY_N: + if (repeatCount == 0) { + return Status::REPEAT_REQUIRED; + } + return getQueryStoreControllerDT8()->storePrimaryTY(); + + case CommandDT8::STORE_XY_COORDINATE_PRIMARY_N: + if (repeatCount == 0) { + return Status::REPEAT_REQUIRED; + } + return getQueryStoreControllerDT8()->storePrimaryCoordinate(); +#endif // DALI_DT8_SUPPORT_PRIMARY_N + +#ifdef DALI_DT8_SUPPORT_TC + case CommandDT8::STORE_COLOUR_TEMPERATURE_LIMIT: + if (repeatCount == 0) { + return Status::REPEAT_REQUIRED; + } + return getQueryStoreControllerDT8()->storeColourTemperatureLimit(); +#endif // DALI_DT8_SUPPORT_TC + + case CommandDT8::STORE_GEAR_FEATURES_STATUS: + if (repeatCount == 0) { + return Status::REPEAT_REQUIRED; + } + return getQueryStoreControllerDT8()->storeGearFeatures(); + + case CommandDT8::START_AUTO_CALIBRATION: + if (repeatCount == 0) { + return Status::REPEAT_REQUIRED; + } + // TODO Implement in the future + return Status::INVALID; + + case CommandDT8::QUERY_GEAR_FEATURES_STATUS: + return sendAck(getQueryStoreControllerDT8()->queryGearFeatures()); + + case CommandDT8::QUERY_COLOUR_STATUS: + return sendAck(getQueryStoreControllerDT8()->queryColorStatus()); + + case CommandDT8::QUERY_COLOUR_TYPE_FEATURES: + return sendAck(getQueryStoreControllerDT8()->queryColorTypes()); + + case CommandDT8::QUERY_COLOUR_VALUE: { + if (getQueryStoreControllerDT8()->queryColorValue() == Status::OK) { + return sendAck(getMemoryController()->getDTR1()); + } + return Status::INVALID; + } + + case CommandDT8::QUERY_EXTENDED_VERSION_NUMBER: + return sendAck(2); + + default: + return Status::INVALID; + } +} + +} // namespace dali + +#endif // DALI_DT8 diff --git a/src/dali/slave_dt8.hpp b/src/dali/slave_dt8.hpp new file mode 100644 index 0000000..a2a8ffd --- /dev/null +++ b/src/dali/slave_dt8.hpp @@ -0,0 +1,58 @@ +/* + * Copyright (c) 2015-2016, Arkadiusz Materek (arekmat@poczta.fm) + * + * Licensed under GNU General Public License 3.0 or later. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. + */ + +#ifndef DALI_SLAVE_DT8_H_ +#define DALI_SLAVE_DT8_H_ + +#include + +#ifdef DALI_DT8 + +#include +#include +#include +#include +#include +#include + +namespace dali { + +class SlaveDT8: public Slave { +public: + static Slave* create(IMemory* memoryDriver, ILamp* lampDriver, IBus* busDriver, ITimer* timer); + +protected: + SlaveDT8(controller::Memory* memory, controller::Lamp* lamp, controller::QueryStore* queryStore, + controller::Bus* busDriver, controller::Initialization* initializationController); + + Status handleHandleDaliDeviceTypeCommand(uint16_t repeat, Command cmd, uint8_t param, uint8_t device_type) override; + +private: + SlaveDT8(const SlaveDT8& other) = delete; + SlaveDT8& operator=(const SlaveDT8&) = delete; + + controller::MemoryDT8* getMemoryControllerDT8() { + return (controller::MemoryDT8*) getMemoryController(); + } + + controller::LampDT8* getLampControllerDT8() { + return (controller::LampDT8*) getLampController(); + } + + controller::QueryStoreDT8* getQueryStoreControllerDT8() { + return (controller::QueryStoreDT8*) getQueryStoreController(); + } +}; + +} // namespace dali + +#endif // DALI_DT8 + +#endif // DALI_SLAVE_DT8_H_ diff --git a/src/xmc1200/dali/lamp.cpp b/src/xmc1200/dali/lamp.cpp index 9c3e04b..04feb93 100644 --- a/src/xmc1200/dali/lamp.cpp +++ b/src/xmc1200/dali/lamp.cpp @@ -117,6 +117,44 @@ void LampRGB::waitForFade() { } } + +void LampRGB::setPrimary(const uint16_t primary[], uint8_t size, uint32_t changeTime) { + for (uint8_t i = 0; i < 3; ++i) { + mPrimary[i] = primary[i]; + } + mLamp.setColor(dali2driver(primary[0]), dali2driver(primary[1]), dali2driver(primary[2]), changeTime); +} + +void LampRGB::getPrimary(uint16_t primary[], uint8_t size) { + if (isColorChanging()) { + primary[0] = driver2dali(mLamp.getColorR()); + primary[1] = driver2dali(mLamp.getColorG()); + primary[2] = driver2dali(mLamp.getColorB()); + } else { + for (uint8_t i = 0; i < 3; ++i) { + mPrimary[i] = mPrimary[i]; + } + } +} + +bool LampRGB::isColorChanging() { + return mLamp.isColorChanging(); +} + +void LampRGB::abortColorChanging() { + if (mLamp.isColorChanging()) { + mLamp.abortColorChanging(); + mPrimary[0] = driver2dali(mLamp.getColorR()); + mPrimary[1] = driver2dali(mLamp.getColorG()); + mPrimary[2] = driver2dali(mLamp.getColorB()); + } +} + +void LampRGB::waitForColorChange() { + while (mLamp.isColorChanging()) { + } +} + void LampRGB::onLampStateChnaged(ILampState state) { for (uint16_t i = 0; i < kMaxClients; ++i) { if (mClients[i] != nullptr) { diff --git a/src/xmc1200/dali/lamp.hpp b/src/xmc1200/dali/lamp.hpp index bd134c2..67eea2c 100644 --- a/src/xmc1200/dali/lamp.hpp +++ b/src/xmc1200/dali/lamp.hpp @@ -11,13 +11,13 @@ #ifndef XMC_DALI_LAMP_HPP_ #define XMC_DALI_LAMP_HPP_ -#include +#include #include namespace dali { namespace xmc { -class LampRGB: public dali::ILamp { +class LampRGB: public dali::ILampDT8 { public: static LampRGB* getInstance(); @@ -30,6 +30,12 @@ public: void abortFading() override; void waitForFade(); + void setPrimary(const uint16_t primary[], uint8_t size, uint32_t changeTime) override; + void getPrimary(uint16_t primary[], uint8_t size) override; + bool isColorChanging() override; + void abortColorChanging() override; + void waitForColorChange(); + bool isOff() { return getLevel() == 0; } @@ -48,6 +54,7 @@ private: ILampClient* mClients[kMaxClients]; ::xmc::BccuLampRGB mLamp; uint16_t mLevel; + uint16_t mPrimary[3]; }; diff --git a/src/xmc1200/dali_defaults_dt8.cpp b/src/xmc1200/dali_defaults_dt8.cpp new file mode 100644 index 0000000..d1cb40f --- /dev/null +++ b/src/xmc1200/dali_defaults_dt8.cpp @@ -0,0 +1,42 @@ +/* + * Copyright (c) 2015-2016, Arkadiusz Materek (arekmat@poczta.fm) + * + * Licensed under GNU General Public License 3.0 or later. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. + */ + +#include + +namespace dali { + +const dali::DefaultsDT8 kDefaultsDT8 = { + primaryConfig: { + {32767, {48149, 17387}}, + {32767, {17944, 47016}}, + {32767, {10918, 583}}, + {65535, {65535, 65535}}, + {65535, {65535, 65535}}, + {65535, {65535, 65535}}, + }, + colorType: DALI_DT8_COLOR_TYPE_TC, +#ifdef DALI_DT8_SUPPORT_XY + xCoordinate: 21845, + yCoordinate: 21846, +#endif // DALI_DT8_SUPPORT_XY +#ifdef DALI_DT8_SUPPORT_TC + tcCoolest: 50, + tcWarmest: 1000, + tc: 500, +#endif /// DALI_DT8_SUPPORT_TC +#ifdef DALI_DT8_SUPPORT_PRIMARY_N + primary: { 10920, 10921, 10922, 10923, 10924, 10925}, +#endif // DALI_DT8_SUPPORT_PRIMARY_N +#ifdef DALI_DT8_SUPPORT_RGBWAF + color: {128, 253, 200, 129, 150, 201}, +#endif // DALI_DT8_SUPPORT_RGBWAF +}; + +} // namespace dali diff --git a/src/xmc1200/main.cpp b/src/xmc1200/main.cpp index 834849d..7c3f82b 100644 --- a/src/xmc1200/main.cpp +++ b/src/xmc1200/main.cpp @@ -10,13 +10,11 @@ #if (CPU_CLOCK == 32000000) #define XMC_CPU_FREQ xmc::Clock::FREQ_32MHZ -#elif (CPU_CLOCK == 16000000) -#define XMC_CPU_FREQ xmc::Clock::FREQ_16MHZ #else #error Unsupported CPU clock #endif -#include +#include #include #include @@ -78,7 +76,7 @@ int main(void) { dali::xmc::Memory* daliMemory1 = dali::xmc::Memory::getInstance(); dali::xmc::LampRGB* daliLamp1 = dali::xmc::LampRGB::getInstance(); - gSlave = dali::Slave::create(daliMemory1, daliLamp1, daliBus, daliTimer); + gSlave = dali::SlaveDT8::create(daliMemory1, daliLamp1, daliBus, daliTimer); daliTimer->schedule(&gPowerOnTimerTask, 600, 0);