From ff4503492c32f17673505f2c975f0b6f648714d4 Mon Sep 17 00:00:00 2001 From: TimMJN <75533580+TimMJN@users.noreply.github.com> Date: Sun, 4 Jun 2023 22:49:33 +0200 Subject: [PATCH 01/32] Update rdm.h type fix --- src/rdm.h | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/rdm.h b/src/rdm.h index 3f6be75..67ed0a0 100644 --- a/src/rdm.h +++ b/src/rdm.h @@ -308,7 +308,7 @@ /* Table A-6: Product Detail Defines */ /********************************************************/ -#define E120_PRODUCT_DETAIL_NOT DECLARED 0x0000 +#define E120_PRODUCT_DETAIL_NOT_DECLARED 0x0000 /* Generally applied to fixtures */ #define E120_PRODUCT_DETAIL_ARC 0x0001 From 6fce9a3b991f39302dee442f61392c5404d842d0 Mon Sep 17 00:00:00 2001 From: TimMJN <75533580+TimMJN@users.noreply.github.com> Date: Sun, 4 Jun 2023 22:50:00 +0200 Subject: [PATCH 02/32] implement parameters --- src/DMXSerial2.cpp | 176 +++++++++++++++++++++++++++++++++++++++++++-- src/DMXSerial2.h | 71 +++++++++++++++++- 2 files changed, 240 insertions(+), 7 deletions(-) diff --git a/src/DMXSerial2.cpp b/src/DMXSerial2.cpp index af42e5d..ac615d5 100644 --- a/src/DMXSerial2.cpp +++ b/src/DMXSerial2.cpp @@ -327,7 +327,15 @@ int random255(); // Initialize or reinitialize the DMX RDM mode. // The other values are stored for later use with the specific commands. -void DMXSerialClass2::init(struct RDMINIT *initData, RDMCallbackFunction func, RDMGetSensorValue sensorFunc, uint8_t modePin, uint8_t modeIn, uint8_t modeOut) +void DMXSerialClass2::init(struct RDMINIT *initData, + RDMCallbackFunction func, + RDMGetSensorValue sensorFunc, + RDMGetParameterValue getParamFunc, + RDMSetParameterValue setParamFunc, + uint8_t modePin, + uint8_t modeIn, + uint8_t modeOut +) { // This structure is defined for mapping the values in the EEPROM struct EEPROMVALUES eeprom; @@ -336,6 +344,8 @@ void DMXSerialClass2::init(struct RDMINIT *initData, RDMCallbackFunction func, R _initData = initData; _rdmFunc = func; _sensorFunc = sensorFunc; + _getParamFunc = getParamFunc; + _setParamFunc = setParamFunc; _dmxModePin = modePin; _dmxModeIn = modeIn; @@ -446,6 +456,13 @@ void DMXSerialClass2::attachSensorCallback(RDMGetSensorValue newFunction) _sensorFunc = newFunction; } // attachSensorCallback +// Register self implemented functions to get/set parameter values +void DMXSerialClass2::attachParameterCallback(RDMGetParameterValue newGetFunction, RDMSetParameterValue newSetFunction) +{ + _getParamFunc = newGetFunction; + _setParamFunc = newSetFunction; +} // attachParameterCallback + // some functions to hide the internal variables from being changed unsigned long DMXSerialClass2::noDataSince() { @@ -612,7 +629,7 @@ void DMXSerialClass2::_processRDMMessage(byte CmdClass, uint16_t Parameter, bool } // if // if not already handled the command: handle it using this implementation - if (! handled ) { + if (! handled) { if (Parameter == SWAPINT(E120_IDENTIFY_DEVICE)) { // 0x1000 if (CmdClass == E120_SET_COMMAND) { // 0x30 @@ -808,7 +825,7 @@ void DMXSerialClass2::_processRDMMessage(byte CmdClass, uint16_t Parameter, bool // E120_DEVICE_INFO // E120_DMX_START_ADDRESS // E120_SOFTWARE_VERSION_LABEL - _rdm.packet.DataLength = 2 * (3 + _initData->additionalCommandsLength); + _rdm.packet.DataLength = 2 * (3 + _initData->additionalCommandsLength + _initData->parametersLength); WRITEINT(_rdm.packet.Data , E120_MANUFACTURER_LABEL); WRITEINT(_rdm.packet.Data+ 2, E120_DEVICE_MODEL_DESCRIPTION); WRITEINT(_rdm.packet.Data+ 4, E120_DEVICE_LABEL); @@ -820,7 +837,12 @@ void DMXSerialClass2::_processRDMMessage(byte CmdClass, uint16_t Parameter, bool WRITEINT(_rdm.packet.Data+ 8, E120_SENSOR_VALUE); } for (uint16_t n = 0; n < _initData->additionalCommandsLength; n++) { - WRITEINT(_rdm.packet.Data+offset+n+n, _initData->additionalCommands[n]); + WRITEINT(_rdm.packet.Data+offset, _initData->additionalCommands[n]); + offset += 2; + } + for (uint16_t n = 0; n < _initData->parametersLength; n++) { + WRITEINT(_rdm.packet.Data+offset, _initData->parameters[n].pid); + offset += 2; } handled = true; } @@ -829,7 +851,95 @@ void DMXSerialClass2::_processRDMMessage(byte CmdClass, uint16_t Parameter, bool nackReason = E120_NR_UNSUPPORTED_COMMAND_CLASS; } -// ADD: PARAMETER_DESCRIPTION + } else if (Parameter == SWAPINT(E120_PARAMETER_DESCRIPTION) && _initData->parametersLength > 0) { // 0x0051 + if (CmdClass == E120_GET_COMMAND) { + if (_rdm.packet.DataLength != 2) { + // Unexpected data + nackReason = E120_NR_FORMAT_ERROR; + } else if (_rdm.packet.SubDev != 0) { + // No sub-devices supported + nackReason = E120_NR_SUB_DEVICE_OUT_OF_RANGE; + } else { + uint16_t requestedPid = READINT(_rdm.packet.Data); + uint16_t parameterNr; + bool8 validPid = false; + for (uint16_t n = 0; n < _initData->parametersLength; n++) { + if (requestedPid == _initData->parameters[n].pid) { + parameterNr = n; + validPid = true; + break; + } + } + if (!validPid) { + // Out of range sensor + nackReason = E120_NR_UNKNOWN_PID; + } else { + _rdm.packet.DataLength = 20 + strnlen(_initData->parameters[parameterNr].description, DMXSERIAL_MAX_RDM_STRING_LENGTH); + WRITEINT(_rdm.packet.Data, _initData->parameters[parameterNr].pid); + _rdm.packet.Data[2] = _initData->parameters[parameterNr].length; + _rdm.packet.Data[3] = _initData->parameters[parameterNr].type; + if (_initData->parameters[parameterNr].getSupported && !_initData->parameters[parameterNr].setSupported) + _rdm.packet.Data[4] = E120_CC_GET; + else if (!_initData->parameters[parameterNr].getSupported && _initData->parameters[parameterNr].setSupported) + _rdm.packet.Data[4] = E120_CC_SET; + else if (_initData->parameters[parameterNr].getSupported && _initData->parameters[parameterNr].setSupported) + _rdm.packet.Data[4] = E120_CC_GET_SET; + _rdm.packet.Data[5] = 0x00; + _rdm.packet.Data[6] = _initData->parameters[parameterNr].unit; + _rdm.packet.Data[7] = _initData->parameters[parameterNr].prefix; + WRITELONG(_rdm.packet.Data + 8, _initData->parameters[parameterNr].rangeMin); + WRITELONG(_rdm.packet.Data + 12, _initData->parameters[parameterNr].rangeMax); + WRITELONG(_rdm.packet.Data + 16, _initData->parameters[parameterNr].defaultValue); + memcpy(_rdm.packet.Data + 20, _initData->parameters[parameterNr].description, _rdm.packet.DataLength - 20); + handled = true; + /////////////////////////////////////////// + } + } + } else if (CmdClass == E120_SET_COMMAND) { + // Unexpected set + nackReason = E120_NR_UNSUPPORTED_COMMAND_CLASS; + } + + } else if (Parameter == SWAPINT(E120_SENSOR_VALUE) && _initData->sensorsLength > 0) { // 0x0201 + if (CmdClass == E120_GET_COMMAND) { + if (_rdm.packet.DataLength != 1) { + // Unexpected data + nackReason = E120_NR_FORMAT_ERROR; + } else if (_rdm.packet.SubDev != 0) { + // No sub-devices supported + nackReason = E120_NR_SUB_DEVICE_OUT_OF_RANGE; + } else { + uint8_t sensorNr = _rdm.packet.Data[0]; + if (sensorNr >= _initData->sensorsLength) { + // Out of range sensor + nackReason = E120_NR_DATA_OUT_OF_RANGE; + } else { + int16_t sensorValue = 0; + int16_t lowestValue = 0; + int16_t highestValue = 0; + int16_t recordedValue = 0; + bool8 res = false; + if (_sensorFunc) { + res = _sensorFunc(sensorNr, &sensorValue, &lowestValue, &highestValue, &recordedValue); + } + if (res) { + _rdm.packet.DataLength = 9; + _rdm.packet.Data[0] = sensorNr; + WRITEINT(_rdm.packet.Data + 1, sensorValue); + WRITEINT(_rdm.packet.Data + 3, lowestValue); + WRITEINT(_rdm.packet.Data + 5, highestValue); + WRITEINT(_rdm.packet.Data + 7, recordedValue); + handled = true; + } else { + nackReason = E120_NR_HARDWARE_FAULT; + } + } + } + } else if (CmdClass == E120_SET_COMMAND) { + // Unhandled set. Set on a sensor is used to reset stats. + // User should process it in own handler when sensor supports high/low or recorded value. + nackReason = E120_NR_UNSUPPORTED_COMMAND_CLASS; + } } else if (Parameter == SWAPINT(E120_SENSOR_DEFINITION) && _initData->sensorsLength > 0) { // 0x0200 if (CmdClass == E120_GET_COMMAND) { @@ -863,6 +973,7 @@ void DMXSerialClass2::_processRDMMessage(byte CmdClass, uint16_t Parameter, bool // Unexpected set nackReason = E120_NR_UNSUPPORTED_COMMAND_CLASS; } + } else if (Parameter == SWAPINT(E120_SENSOR_VALUE) && _initData->sensorsLength > 0) { // 0x0201 if (CmdClass == E120_GET_COMMAND) { if (_rdm.packet.DataLength != 1) { @@ -907,6 +1018,61 @@ void DMXSerialClass2::_processRDMMessage(byte CmdClass, uint16_t Parameter, bool } else { handled = false; + for (uint16_t n = 0; n < _initData->parametersLength; n++) { + if (Parameter == SWAPINT(_initData->parameters[n].pid)) { + if (CmdClass == E120_GET_COMMAND) { + if (!_initData->parameters[n].getSupported) { + // get not supported + nackReason = E120_NR_UNSUPPORTED_COMMAND_CLASS; + } else if (_rdm.packet.DataLength > 0) { + // Unexpected data + nackReason = E120_NR_FORMAT_ERROR; + } else if (_rdm.packet.SubDev != 0) { + // No sub-devices supported + nackReason = E120_NR_SUB_DEVICE_OUT_OF_RANGE; + } else { + uint8_t value[_initData->parameters[n].length]; + bool8 res = false; + if (_getParamFunc) { + res = _getParamFunc(n, value); + } + if (res) { + _rdm.packet.DataLength = _initData->parameters[n].length; + memcpy(_rdm.packet.Data,value,_initData->parameters[n].length); + handled = true; + } else { + nackReason = E120_NR_HARDWARE_FAULT; + } + } + + } else if (CmdClass == E120_SET_COMMAND) { + if (!_initData->parameters[n].setSupported) { + // set not supported + nackReason = E120_NR_UNSUPPORTED_COMMAND_CLASS; + } else if (_rdm.packet.DataLength != _initData->parameters[n].length) { + // Unexpected data + nackReason = E120_NR_FORMAT_ERROR; + } else if (_rdm.packet.SubDev != 0) { + // No sub-devices supported + nackReason = E120_NR_SUB_DEVICE_OUT_OF_RANGE; + } else { + uint8_t value[_initData->parameters[n].length]; + memcpy(value,_rdm.packet.Data,_initData->parameters[n].length); + bool8 res = false; + if (_setParamFunc) { + res = _setParamFunc(n, value); + } + if (res) { + _rdm.packet.DataLength = 0; + handled = true; + } else { + nackReason = E120_NR_HARDWARE_FAULT; + } + } + } // if + break; + } + } // for } // if } // if diff --git a/src/DMXSerial2.h b/src/DMXSerial2.h index 16713bd..06646ac 100644 --- a/src/DMXSerial2.h +++ b/src/DMXSerial2.h @@ -117,6 +117,9 @@ struct RDMDATA { /// write a 16 bit number to a data buffer location #define WRITEINT(p, d) (p)[0] = (d&0xFF00)>>8; (p)[1] = (d&0x00FF); +/// write a 32 bit number to a data buffer location +#define WRITELONG(p, d) (p)[0] = (d&0xFF000000)>>24; (p)[1] = (d&0x00FF0000)>>16; (p)[2] = (d&0x0000FF00)>>8; (p)[3] = (d&0x000000FF); + // ----- Callback function types ----- @@ -133,6 +136,16 @@ extern "C" { * @brief Callback function for RDM sensors. */ typedef bool8 (*RDMGetSensorValue)(uint8_t sensorNr, int16_t *value, int16_t *lowestValue, int16_t *highestValue, int16_t *recordedValue); + + /** + * @brief Callback function for getting RDM parameters. + */ + typedef bool8 (*RDMGetParameterValue)(uint16_t parameterNr, int8_t *value); + + /** + * @brief Callback function for setting RDM parameters. + */ + typedef bool8 (*RDMSetParameterValue)(uint16_t parameterNr, int8_t *value); } // ----- Library Class ----- @@ -158,6 +171,20 @@ struct RDMSENSOR { char *description; }; // struct RDMSENSOR +struct RDMPARAMETER { + uint16_t pid; + uint8_t length; + uint8_t type; + uint8_t unit; + uint8_t prefix; + int32_t rangeMin; + int32_t rangeMax; + int32_t defaultValue; + bool8 getSupported; + bool8 setSupported; + char *description; +}; // struct RDMPARAMETER + struct RDMINIT { const char *manufacturerLabel; // const uint16_t deviceModelId; // @@ -169,6 +196,8 @@ struct RDMINIT { const uint16_t *additionalCommands; const uint8_t sensorsLength; const RDMSENSOR *sensors; + const uint8_t parametersLength; + const RDMPARAMETER *parameters; }; // struct RDMINIT @@ -185,7 +214,7 @@ class DMXSerialClass2 * @param [in] modeOut The level for outbound communication. This parameter is optiona and defaults to 1 = HIGH. */ void init (struct RDMINIT *initData, RDMCallbackFunction func, uint8_t modePin = 2, uint8_t modeIn = 0, uint8_t modeOut = 1) { - init(initData, func, NULL, modePin, modeIn, modeOut); + init(initData, func, NULL, NULL, NULL, modePin, modeIn, modeOut); } /** @@ -197,7 +226,36 @@ class DMXSerialClass2 * @param [in] modeIn The level for inbound communication. This parameter is optiona and defaults to 0 = LOW. * @param [in] modeOut The level for outbound communication. This parameter is optiona and defaults to 1 = HIGH. */ - void init (struct RDMINIT *initData, RDMCallbackFunction func, RDMGetSensorValue sensorFunc, uint8_t modePin = 2, uint8_t modeIn = 0, uint8_t modeOut = 1); + void init (struct RDMINIT *initData, RDMCallbackFunction func, RDMGetSensorValue sensorFunc, uint8_t modePin = 2, uint8_t modeIn = 0, uint8_t modeOut = 1) { + init(initData, func, sensorFunc, NULL, NULL, modePin, modeIn, modeOut); + } + + /** + * @brief Initialize for RDM mode with parameters. + * @param [in] initData Startup parameters. + * @param [in] func Callback function for answering on device specific features. + * @param [in] getParamFunc Callback function for retrieving a parameter value. + * @param [in] setParamFunc Callback function for setting a parameter value. + * @param [in] modePin The pin used to switch the communication direction. This parameter is optiona and defaults to 2. + * @param [in] modeIn The level for inbound communication. This parameter is optiona and defaults to 0 = LOW. + * @param [in] modeOut The level for outbound communication. This parameter is optiona and defaults to 1 = HIGH. + */ + void init (struct RDMINIT *initData, RDMCallbackFunction func, RDMGetParameterValue getParamFunc, RDMSetParameterValue setParamFunc, uint8_t modePin = 2, uint8_t modeIn = 0, uint8_t modeOut = 1) { + init(initData, func, NULL, getParamFunc, setParamFunc, modePin, modeIn, modeOut); + } + + /** + * @brief Initialize for RDM mode with sensor and parameter. + * @param [in] initData Startup parameters. + * @param [in] func Callback function for answering on device specific features. + * @param [in] sensorFunc Callback function for retrieving a sensor value. + * @param [in] getParamFunc Callback function for retrieving a parameter value. + * @param [in] setParamFunc Callback function for setting a parameter value. + * @param [in] modePin The pin used to switch the communication direction. This parameter is optiona and defaults to 2. + * @param [in] modeIn The level for inbound communication. This parameter is optiona and defaults to 0 = LOW. + * @param [in] modeOut The level for outbound communication. This parameter is optiona and defaults to 1 = HIGH. + */ + void init (struct RDMINIT *initData, RDMCallbackFunction func, RDMGetSensorValue sensorFunc, RDMGetParameterValue getParamFunc, RDMSetParameterValue setParamFunc, uint8_t modePin = 2, uint8_t modeIn = 0, uint8_t modeOut = 1); /** * @brief Read the current value of a channel. @@ -246,6 +304,9 @@ class DMXSerialClass2 /// Register a device-specific implemented function for getting sensor values void attachSensorCallback (RDMGetSensorValue newFunction); + /// Register a device-specific implemented function for getting/setting parameter values + void attachParameterCallback(RDMGetParameterValue newGetFunction, RDMSetParameterValue newSetFunction); + /// check for unprocessed RDM Command. void tick(void); @@ -274,6 +335,12 @@ class DMXSerialClass2 /// callback function to get sensor value RDMGetSensorValue _sensorFunc; + /// callback function to get parameter value + RDMGetParameterValue _getParamFunc; + + /// callback function to set parameter value + RDMSetParameterValue _setParamFunc; + /// remember the given manufacturer label and device model strings during init struct RDMINIT *_initData; From 120aa1c06639ef2a43a41caebaf6eb3f417f1e07 Mon Sep 17 00:00:00 2001 From: TimMJN <75533580+TimMJN@users.noreply.github.com> Date: Sun, 4 Jun 2023 22:50:26 +0200 Subject: [PATCH 03/32] move into dir --- examples/{ => RDMIntoDMXOut}/RDMIntoDMXOut.ino | 0 1 file changed, 0 insertions(+), 0 deletions(-) rename examples/{ => RDMIntoDMXOut}/RDMIntoDMXOut.ino (100%) diff --git a/examples/RDMIntoDMXOut.ino b/examples/RDMIntoDMXOut/RDMIntoDMXOut.ino similarity index 100% rename from examples/RDMIntoDMXOut.ino rename to examples/RDMIntoDMXOut/RDMIntoDMXOut.ino From 779518cea0528d8e8cc9e0d1842c30573960af76 Mon Sep 17 00:00:00 2001 From: TimMJN <75533580+TimMJN@users.noreply.github.com> Date: Mon, 5 Jun 2023 21:25:40 +0200 Subject: [PATCH 04/32] integrate sensors example --- .../RDMSerialRecvSensor.ino | 288 ++++++++++++++++++ 1 file changed, 288 insertions(+) create mode 100644 examples/RDMSerialRecvSensor/RDMSerialRecvSensor.ino diff --git a/examples/RDMSerialRecvSensor/RDMSerialRecvSensor.ino b/examples/RDMSerialRecvSensor/RDMSerialRecvSensor.ino new file mode 100644 index 0000000..1557828 --- /dev/null +++ b/examples/RDMSerialRecvSensor/RDMSerialRecvSensor.ino @@ -0,0 +1,288 @@ +// - - - - - +// DmxSerial2 - A hardware supported interface to DMX and RDM. +// RDMSerialRecv.ino: Sample RDM application. +// +// Copyright (c) 2011-2013 by Matthias Hertel, http://www.mathertel.de +// This work is licensed under a BSD style license. See http://www.mathertel.de/License.aspx +// +// This Arduino project is a sample application for the DMXSerial2 library that shows +// how a 3 channel receiving RDM client can be implemented. +// The 3 channels are used for PWM Output: +// address (startAddress) + 0 (red) -> PWM Port 9 +// address (startAddress) + 1 (green) -> PWM Port 6 +// address (startAddress) + 2 (blue) -> PWM Port 5 +// +// This sample shows how Device specific RDM Commands are handled in the processCommand function. +// The following RDM commands are implemented here: +// E120_LAMP_HOURS +// E120_DEVICE_HOURS +// +// More documentation and samples are available at http://www.mathertel.de/Arduino +// 06.12.2012 created from DMXSerialRecv sample. +// 09.12.2012 added first RDM response. +// 22.01.2013 first published version to support RDM +// 03.03.2013 Using DMXSerial2 as a library +// 15.05.2013 Arduino Leonard and Arduino MEGA compatibility +// 15.12.2013 ADD: output information on a LEONARDO board by using the #define SERIAL_DEBUG definition +// If you have to save pgm space you can delete the inner lines of this "#if" blocks +// 24.01.2014 Peter Newman/Sean Sill: Get device specific PIDs returning properly in supportedParameters +// 24.01.2014 Peter Newman: Make the device specific PIDs compliant with the OLA RDM Tests. Add device model ID option +// 12.04.2015 change of using datatype boolean to bool8. +// 25.05.2017 Stefan Krupop: Add support for sensors +// 15.08.2018 Stefan Krupop: Add example for sensors +// 21.08.2018 improvements and typo by Peter Newman +// 31.10.2018 Remove unnecessary #include by Graham Hanson +// 04.06.2023 Tim Nijssen: Add support for device-specific parameters +// 05.06.2023 Tim Nijssen: integrate sensors example +// 05.06.2023 Tim Nijssen: Add example for device-specific parameters +// - - - - - + +#include + +// uncomment this line for enabling information on a LEONARD board. +// #define SERIAL_DEBUG + +// Constants for demo program + +const int RedPin = 9; // PWM output pin for Red Light. +const int GreenPin = 6; // PWM output pin for Green Light. +const int BluePin = 5; // PWM output pin for Blue Light. + +// color: #203050 * 2 +#define RedDefaultLevel 0x20 * 2 +#define GreenDefaultLevel 0x30 * 2 +#define BlueDefaultLevel 0x50 * 2 + +// define the RGB output color +void rgb(byte r, byte g, byte b) +{ + analogWrite(RedPin, r); + analogWrite(GreenPin, g); + analogWrite(BluePin, b); +} // rgb() + +// see DMXSerial2.h for the definition of the fields of this structure +const uint16_t my_pids[] = {E120_DEVICE_HOURS, E120_LAMP_HOURS}; +const RDMSENSOR my_sensors[] = { + {E120_SENS_TEMPERATURE, E120_UNITS_CENTIGRADE, E120_PREFIX_NONE, 0, 80, 10, 30, true, false, "Temperature"} +}; +struct RDMINIT rdmInit = { + "mathertel.de", // Manufacturer Label + 1, // Device Model ID + "Arduino RDM Device", // Device Model Label + 3, // footprint + (sizeof(my_pids)/sizeof(uint16_t)), my_pids, + (sizeof(my_sensors)/sizeof(RDMSENSOR)), my_sensors + //0, NULL +}; + +unsigned long previousMillis = 0; +double temperature = 0.0; +int16_t _lowestValue = 100; +int16_t _highestValue = 0; + +void setup () { + +#if defined(SERIAL_DEBUG) + // The Serial port can be used on Arduino Leonard Boards for debugging purpose + // because it is not mapped to the real serial port of the ATmega32U4 chip but to the USB port. + // Don't use that on Arduino Uno, 2009,... boards based on ATmega328 or ATmega168 chips. + Serial.begin(9600); + while (!Serial) ; + Serial.println("starting..."); +#endif + + // initialize the Serial interface to be used as an RDM Device Node. + // There are several constants that have to be passed to the library so it can reposonse to the + // corresponding commands for itself. + DMXSerial2.init(&rdmInit, processCommand, getSensorValue); + + uint16_t start = DMXSerial2.getStartAddress(); +#if defined(SERIAL_DEBUG) + Serial.print("Listening on DMX address #"); Serial.println(start); +#endif + + // set default values to dark red + // this color will be shown when no signal is present for the first 5 seconds. + DMXSerial2.write(start + 0, 30); + DMXSerial2.write(start + 1, 0); + DMXSerial2.write(start + 2, 0); + + // enable pwm outputs + pinMode(RedPin, OUTPUT); // sets the digital pin as output + pinMode(GreenPin, OUTPUT); + pinMode(BluePin, OUTPUT); + +#if defined(SERIAL_DEBUG) + // output the current DeviceID + + DEVICEID thisDevice; + DMXSerial2.getDeviceID(thisDevice); + + Serial.print("This Device is: "); + if (thisDevice[0] < 0x10) Serial.print('0'); Serial.print(thisDevice[0], HEX); + if (thisDevice[1] < 0x10) Serial.print('0'); Serial.print(thisDevice[1], HEX); + Serial.print(":"); + if (thisDevice[2] < 0x10) Serial.print('0'); Serial.print(thisDevice[2], HEX); + if (thisDevice[3] < 0x10) Serial.print('0'); Serial.print(thisDevice[3], HEX); + if (thisDevice[4] < 0x10) Serial.print('0'); Serial.print(thisDevice[4], HEX); + if (thisDevice[5] < 0x10) Serial.print('0'); Serial.print(thisDevice[5], HEX); + Serial.println(); +#endif + +} // setup() + + +void loop() { + // Calculate how long no data backet was received + unsigned long lastPacket = DMXSerial2.noDataSince(); + + if (DMXSerial2.isIdentifyMode()) { + // RDM command for indentification was sent. + // Blink the device. + unsigned long now = millis(); + if (now % 1000 < 500) { + rgb(200, 200, 200); + } else { + rgb(0, 0, 0); + } // if + + } else if (lastPacket < 30000) { + // read recent DMX values and set pwm levels + analogWrite(RedPin, DMXSerial2.readRelative(0)); + analogWrite(GreenPin, DMXSerial2.readRelative(1)); + analogWrite(BluePin, DMXSerial2.readRelative(2)); + + } else { +#if defined(SERIAL_DEBUG) + Serial.println("no signal since 30 secs."); +#endif + // Show default color, when no data was received since 30 seconds or more. + analogWrite(RedPin, RedDefaultLevel); + analogWrite(GreenPin, GreenDefaultLevel); + analogWrite(BluePin, BlueDefaultLevel); + } // if + + if (millis() - previousMillis >= 1000) { + previousMillis = millis(); + temperature = getTemp(); + if (!isnan(temperature)) { + if (temperature < _lowestValue) { + _lowestValue = temperature; + } + if (temperature > _highestValue) { + _highestValue = temperature; + } + } + } + + // check for unhandled RDM commands + DMXSerial2.tick(); +} // loop() + + +// This function was registered to the DMXSerial2 library in the initRDM call. +// Here device specific RDM Commands are implemented. +bool8 processCommand(struct RDMDATA *rdm, uint16_t *nackReason) +{ + byte CmdClass = rdm->CmdClass; // command class + uint16_t Parameter = rdm->Parameter; // parameter ID + bool8 handled = false; + +// This is a sample of how to return some device specific data + if (Parameter == SWAPINT(E120_DEVICE_HOURS)) { // 0x0400 + if (CmdClass == E120_GET_COMMAND) { + if (rdm->DataLength > 0) { + // Unexpected data + *nackReason = E120_NR_FORMAT_ERROR; + } else if (rdm->SubDev != 0) { + // No sub-devices supported + *nackReason = E120_NR_SUB_DEVICE_OUT_OF_RANGE; + } else { + rdm->DataLength = 4; + rdm->Data[0] = 0; + rdm->Data[1] = 0; + rdm->Data[2] = 2; + rdm->Data[3] = 0; + handled = true; + } + } else if (CmdClass == E120_SET_COMMAND) { + // This device doesn't support set + *nackReason = E120_NR_UNSUPPORTED_COMMAND_CLASS; + } + + } else if (Parameter == SWAPINT(E120_LAMP_HOURS)) { // 0x0401 + if (CmdClass == E120_GET_COMMAND) { + if (rdm->DataLength > 0) { + // Unexpected data + *nackReason = E120_NR_FORMAT_ERROR; + } else if (rdm->SubDev != 0) { + // No sub-devices supported + *nackReason = E120_NR_SUB_DEVICE_OUT_OF_RANGE; + } else { + rdm->DataLength = 4; + rdm->Data[0] = 0; + rdm->Data[1] = 0; + rdm->Data[2] = 0; + rdm->Data[3] = 1; + handled = true; + } + } else if (CmdClass == E120_SET_COMMAND) { + // This device doesn't support set + *nackReason = E120_NR_UNSUPPORTED_COMMAND_CLASS; + } + } // if + + return handled; +} // processCommand + +// This function was registered to the DMXSerial2 library in the initRDM call. +// Here retrieval of sensor values is implemented. +bool8 getSensorValue(uint8_t sensorNr, int16_t *value, int16_t *lowestValue, int16_t *highestValue, int16_t *recordedValue) { + if (sensorNr == 0) { + if (isnan(temperature)) { + return false; + } + *value = temperature; + *lowestValue = _lowestValue; + *highestValue = _highestValue; + return true; + } + return false; +} // getSensorValue + +// Read the ATmega328 internal temperature sensor +// https://theorycircuit.com/arduino-internal-temperature-sensor/ +double getTemp(void) +{ + unsigned int wADC; + double t; + + // The internal temperature has to be used + // with the internal reference of 1.1V. + // Channel 8 can not be selected with + // the analogRead function yet. + + // Set the internal reference and mux. + ADMUX = (_BV(REFS1) | _BV(REFS0) | _BV(MUX3)); + ADCSRA |= _BV(ADEN); // enable the ADC + + delay(20); // wait for voltages to become stable. + + ADCSRA |= _BV(ADSC); // Start the ADC + + // Detect end-of-conversion + while (bit_is_set(ADCSRA,ADSC)); + + // Reading register "ADCW" takes care of how to read ADCL and ADCH. + wADC = ADCW; + + // The offset of 324.31 could be wrong. It is just an indication. + t = (wADC - 324.31 ) / 1.22; + + // The returned temperature is in degrees Celcius. + return (t); +} // getTemp + +// End. + From 33b380d39e6a27953f619ad8f44d9e66dbc25474 Mon Sep 17 00:00:00 2001 From: TimMJN <75533580+TimMJN@users.noreply.github.com> Date: Mon, 5 Jun 2023 21:33:42 +0200 Subject: [PATCH 05/32] Update RDMSerialRecv.ino header --- examples/RDMSerialRecv/RDMSerialRecv.ino | 3 +++ 1 file changed, 3 insertions(+) diff --git a/examples/RDMSerialRecv/RDMSerialRecv.ino b/examples/RDMSerialRecv/RDMSerialRecv.ino index 8c8f142..9099b78 100644 --- a/examples/RDMSerialRecv/RDMSerialRecv.ino +++ b/examples/RDMSerialRecv/RDMSerialRecv.ino @@ -31,6 +31,9 @@ // 25.05.2017 Stefan Krupop: Add support for sensors // 21.08.2018 improvements and typo by Peter Newman // 31.10.2018 Remove unnecessary #include by Graham Hanson +// 04.06.2023 Tim Nijssen: Add support for device-specific parameters +// 05.06.2023 Tim Nijssen: integrate sensors example +// 05.06.2023 Tim Nijssen: Add example for device-specific parameters // - - - - - #include From 206e07bc43bc022bf9bfdfe180369aa843391d11 Mon Sep 17 00:00:00 2001 From: TimMJN <75533580+TimMJN@users.noreply.github.com> Date: Mon, 5 Jun 2023 21:43:20 +0200 Subject: [PATCH 06/32] Create RDMSerialRecvParameter.ino add example for parameters --- .../RDMSerialRecvParameter.ino | 244 ++++++++++++++++++ 1 file changed, 244 insertions(+) create mode 100644 examples/RDMSerialRecvParameter/RDMSerialRecvParameter.ino diff --git a/examples/RDMSerialRecvParameter/RDMSerialRecvParameter.ino b/examples/RDMSerialRecvParameter/RDMSerialRecvParameter.ino new file mode 100644 index 0000000..e9dc936 --- /dev/null +++ b/examples/RDMSerialRecvParameter/RDMSerialRecvParameter.ino @@ -0,0 +1,244 @@ +// - - - - - +// DmxSerial2 - A hardware supported interface to DMX and RDM. +// RDMSerialRecv.ino: Sample RDM application. +// +// Copyright (c) 2011-2013 by Matthias Hertel, http://www.mathertel.de +// This work is licensed under a BSD style license. See http://www.mathertel.de/License.aspx +// +// This Arduino project is a sample application for the DMXSerial2 library that shows +// how a 3 channel receiving RDM client can be implemented. +// The 3 channels are used for PWM Output: +// address (startAddress) + 0 (red) -> PWM Port 9 +// address (startAddress) + 1 (green) -> PWM Port 6 +// address (startAddress) + 2 (blue) -> PWM Port 5 +// +// This sample shows how Device specific RDM Commands are handled in the processCommand function. +// The following RDM commands are implemented here: +// E120_LAMP_HOURS +// E120_DEVICE_HOURS +// +// More documentation and samples are available at http://www.mathertel.de/Arduino +// 06.12.2012 created from DMXSerialRecv sample. +// 09.12.2012 added first RDM response. +// 22.01.2013 first published version to support RDM +// 03.03.2013 Using DMXSerial2 as a library +// 15.05.2013 Arduino Leonard and Arduino MEGA compatibility +// 15.12.2013 ADD: output information on a LEONARDO board by using the #define SERIAL_DEBUG definition +// If you have to save pgm space you can delete the inner lines of this "#if" blocks +// 24.01.2014 Peter Newman/Sean Sill: Get device specific PIDs returning properly in supportedParameters +// 24.01.2014 Peter Newman: Make the device specific PIDs compliant with the OLA RDM Tests. Add device model ID option +// 12.04.2015 change of using datatype boolean to bool8. +// 25.05.2017 Stefan Krupop: Add support for sensors +// 21.08.2018 improvements and typo by Peter Newman +// 31.10.2018 Remove unnecessary #include by Graham Hanson +// 04.06.2023 Tim Nijssen: Add support for device-specific parameters +// 05.06.2023 Tim Nijssen: integrate sensors example +// 05.06.2023 Tim Nijssen: Add example for device-specific parameters +// - - - - - + +//#include +#include "E:\Dropbox\Flierefluiters\DMX\DmxSerial2\src\DMXSerial2.h" +#include "E:\Dropbox\Flierefluiters\DMX\DmxSerial2\src\DMXSerial2.cpp" +#include "E:\Dropbox\Flierefluiters\DMX\DmxSerial2\src\rdm.h" + +// uncomment this line for enabling information on a LEONARD board. +// #define SERIAL_DEBUG + +// Constants for demo program + +const int RedPin = 9; // PWM output pin for Red Light. +const int GreenPin = 6; // PWM output pin for Green Light. +const int BluePin = 5; // PWM output pin for Blue Light. + +// color: #203050 * 2 +#define RedDefaultLevel 0x20 * 2 +#define GreenDefaultLevel 0x30 * 2 +#define BlueDefaultLevel 0x50 * 2 + +// define the RGB output color +void rgb(byte r, byte g, byte b) +{ + analogWrite(RedPin, r); + analogWrite(GreenPin, g); + analogWrite(BluePin, b); +} // rgb() + +// see DMXSerial2.h for the definition of the fields of this structure +const uint16_t my_pids[] = {E120_DEVICE_HOURS, E120_LAMP_HOURS}; +const RDMPARAMETER my_parameters[] = { + {0x8000, 1, E120_DS_UNSIGNED_BYTE, E120_UNITS_NONE, E120_PREFIX_NONE, 0, 255, 128, true, true, "TestParam"} +}; +struct RDMINIT rdmInit = { + "mathertel.de", // Manufacturer Label + 1, // Device Model ID + "Arduino RDM Device", // Device Model Label + 3, // footprint + (sizeof(my_pids)/sizeof(uint16_t)), my_pids, + 0, NULL, + (sizeof(my_parameters)/sizeof(RDMPARAMETER)), my_parameters +}; + +byte parameter = 128; + +void setup () { + +#if defined(SERIAL_DEBUG) + // The Serial port can be used on Arduino Leonard Boards for debugging purpose + // because it is not mapped to the real serial port of the ATmega32U4 chip but to the USB port. + // Don't use that on Arduino Uno, 2009,... boards based on ATmega328 or ATmega168 chips. + Serial.begin(9600); + while (!Serial) ; + Serial.println("starting..."); +#endif + + // initialize the Serial interface to be used as an RDM Device Node. + // There are several constants that have to be passed to the library so it can reposonse to the + // corresponding commands for itself. + DMXSerial2.init(&rdmInit, processCommand, getParameters, setParameters); + + uint16_t start = DMXSerial2.getStartAddress(); +#if defined(SERIAL_DEBUG) + Serial.print("Listening on DMX address #"); Serial.println(start); +#endif + + // set default values to dark red + // this color will be shown when no signal is present for the first 5 seconds. + DMXSerial2.write(start + 0, 30); + DMXSerial2.write(start + 1, 0); + DMXSerial2.write(start + 2, 0); + + // enable pwm outputs + pinMode(RedPin, OUTPUT); // sets the digital pin as output + pinMode(GreenPin, OUTPUT); + pinMode(BluePin, OUTPUT); + +#if defined(SERIAL_DEBUG) + // output the current DeviceID + + DEVICEID thisDevice; + DMXSerial2.getDeviceID(thisDevice); + + Serial.print("This Device is: "); + if (thisDevice[0] < 0x10) Serial.print('0'); Serial.print(thisDevice[0], HEX); + if (thisDevice[1] < 0x10) Serial.print('0'); Serial.print(thisDevice[1], HEX); + Serial.print(":"); + if (thisDevice[2] < 0x10) Serial.print('0'); Serial.print(thisDevice[2], HEX); + if (thisDevice[3] < 0x10) Serial.print('0'); Serial.print(thisDevice[3], HEX); + if (thisDevice[4] < 0x10) Serial.print('0'); Serial.print(thisDevice[4], HEX); + if (thisDevice[5] < 0x10) Serial.print('0'); Serial.print(thisDevice[5], HEX); + Serial.println(); +#endif + +} // setup() + + +void loop() { + // Calculate how long no data backet was received + unsigned long lastPacket = DMXSerial2.noDataSince(); + + if (DMXSerial2.isIdentifyMode()) { + // RDM command for identification was sent. + // Blink the device. + unsigned long now = millis(); + if (now % 1000 < 500) { + rgb(200, 200, 200); + } else { + rgb(0, 0, 0); + } // if + + } else if (lastPacket < 30000) { + // read recent DMX values and set pwm levels + analogWrite(RedPin, DMXSerial2.readRelative(0)); + analogWrite(GreenPin, DMXSerial2.readRelative(1)); + analogWrite(BluePin, DMXSerial2.readRelative(2)); + + } else { +#if defined(SERIAL_DEBUG) + Serial.println("no signal since 30 secs."); +#endif + // Show default color, when no data was received since 30 seconds or more. + analogWrite(RedPin, RedDefaultLevel); + analogWrite(GreenPin, GreenDefaultLevel); + analogWrite(BluePin, BlueDefaultLevel); + } // if + + // check for unhandled RDM commands + DMXSerial2.tick(); +} // loop() + + +// This function was registered to the DMXSerial2 library in the initRDM call. +// Here device specific RDM Commands are implemented. +bool8 processCommand(struct RDMDATA *rdm, uint16_t *nackReason) +{ + byte CmdClass = rdm->CmdClass; // command class + uint16_t Parameter = rdm->Parameter; // parameter ID + bool8 handled = false; + +// This is a sample of how to return some device specific data + if (Parameter == SWAPINT(E120_DEVICE_HOURS)) { // 0x0400 + if (CmdClass == E120_GET_COMMAND) { + if (rdm->DataLength > 0) { + // Unexpected data + *nackReason = E120_NR_FORMAT_ERROR; + } else if (rdm->SubDev != 0) { + // No sub-devices supported + *nackReason = E120_NR_SUB_DEVICE_OUT_OF_RANGE; + } else { + rdm->DataLength = 4; + rdm->Data[0] = 0; + rdm->Data[1] = 0; + rdm->Data[2] = 2; + rdm->Data[3] = 0; + handled = true; + } + } else if (CmdClass == E120_SET_COMMAND) { + // This device doesn't support set + *nackReason = E120_NR_UNSUPPORTED_COMMAND_CLASS; + } + + } else if (Parameter == SWAPINT(E120_LAMP_HOURS)) { // 0x0401 + if (CmdClass == E120_GET_COMMAND) { + if (rdm->DataLength > 0) { + // Unexpected data + *nackReason = E120_NR_FORMAT_ERROR; + } else if (rdm->SubDev != 0) { + // No sub-devices supported + *nackReason = E120_NR_SUB_DEVICE_OUT_OF_RANGE; + } else { + + unsigned long seconds = millis()/1000; + + rdm->DataLength = 4; + rdm->Data[0] = (seconds & 0xff000000) >> 24; + rdm->Data[1] = (seconds & 0x00ff0000) >> 16; + rdm->Data[2] = (seconds & 0x0000ff00) >> 8; + rdm->Data[3] = seconds & 0x000000ff; + handled = true; + } + } else if (CmdClass == E120_SET_COMMAND) { + // This device doesn't support set + *nackReason = E120_NR_UNSUPPORTED_COMMAND_CLASS; + } + } // if + + return handled; +} // processCommand + +// This function was registered to the DMXSerial2 library in the initRDM call. +// Here retrieval of parameter values is implemented. +bool8 getParameters(uint16_t parameterNr, int8_t *value) { + value[0] = parameter; + return true; +} // getParameters + +// This function was registered to the DMXSerial2 library in the initRDM call. +// Here setting of parameter values is implemented. +bool8 setParameters(uint16_t parameterNr, int8_t *value) { + parameter = value[0]; + // do something with the value here, eg store it in eeprom + return true; +} // setParameters + +// End. + From 1b629b071f01688814406aa55940e92583b2a1c7 Mon Sep 17 00:00:00 2001 From: TimMJN <75533580+TimMJN@users.noreply.github.com> Date: Tue, 6 Jun 2023 13:46:46 +0200 Subject: [PATCH 07/32] Update RDMSerialRecvParameter.ino --- examples/RDMSerialRecvParameter/RDMSerialRecvParameter.ino | 7 ++----- 1 file changed, 2 insertions(+), 5 deletions(-) diff --git a/examples/RDMSerialRecvParameter/RDMSerialRecvParameter.ino b/examples/RDMSerialRecvParameter/RDMSerialRecvParameter.ino index e9dc936..9e40e43 100644 --- a/examples/RDMSerialRecvParameter/RDMSerialRecvParameter.ino +++ b/examples/RDMSerialRecvParameter/RDMSerialRecvParameter.ino @@ -36,10 +36,7 @@ // 05.06.2023 Tim Nijssen: Add example for device-specific parameters // - - - - - -//#include -#include "E:\Dropbox\Flierefluiters\DMX\DmxSerial2\src\DMXSerial2.h" -#include "E:\Dropbox\Flierefluiters\DMX\DmxSerial2\src\DMXSerial2.cpp" -#include "E:\Dropbox\Flierefluiters\DMX\DmxSerial2\src\rdm.h" +#include // uncomment this line for enabling information on a LEONARD board. // #define SERIAL_DEBUG @@ -92,7 +89,7 @@ void setup () { #endif // initialize the Serial interface to be used as an RDM Device Node. - // There are several constants that have to be passed to the library so it can reposonse to the + // There are several constants that have to be passed to the library so it can respond to the // corresponding commands for itself. DMXSerial2.init(&rdmInit, processCommand, getParameters, setParameters); From c95a9c2c2885675ac3b7b1bf980901725d93bf15 Mon Sep 17 00:00:00 2001 From: TimMJN <75533580+TimMJN@users.noreply.github.com> Date: Tue, 6 Jun 2023 13:48:11 +0200 Subject: [PATCH 08/32] Update RDMSerialRecvSensor.ino --- examples/RDMSerialRecvSensor/RDMSerialRecvSensor.ino | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/examples/RDMSerialRecvSensor/RDMSerialRecvSensor.ino b/examples/RDMSerialRecvSensor/RDMSerialRecvSensor.ino index 1557828..4763487 100644 --- a/examples/RDMSerialRecvSensor/RDMSerialRecvSensor.ino +++ b/examples/RDMSerialRecvSensor/RDMSerialRecvSensor.ino @@ -93,7 +93,7 @@ void setup () { #endif // initialize the Serial interface to be used as an RDM Device Node. - // There are several constants that have to be passed to the library so it can reposonse to the + // There are several constants that have to be passed to the library so it can respond to the // corresponding commands for itself. DMXSerial2.init(&rdmInit, processCommand, getSensorValue); @@ -138,7 +138,7 @@ void loop() { unsigned long lastPacket = DMXSerial2.noDataSince(); if (DMXSerial2.isIdentifyMode()) { - // RDM command for indentification was sent. + // RDM command for identification was sent. // Blink the device. unsigned long now = millis(); if (now % 1000 < 500) { @@ -280,7 +280,7 @@ double getTemp(void) // The offset of 324.31 could be wrong. It is just an indication. t = (wADC - 324.31 ) / 1.22; - // The returned temperature is in degrees Celcius. + // The returned temperature is in degrees Celsius. return (t); } // getTemp From 89330b86f480c7f595c94699d77b41ff6929058a Mon Sep 17 00:00:00 2001 From: TimMJN <75533580+TimMJN@users.noreply.github.com> Date: Tue, 6 Jun 2023 13:48:52 +0200 Subject: [PATCH 09/32] Update RDMSerialRecv.ino --- examples/RDMSerialRecv/RDMSerialRecv.ino | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/examples/RDMSerialRecv/RDMSerialRecv.ino b/examples/RDMSerialRecv/RDMSerialRecv.ino index 9099b78..35dfee2 100644 --- a/examples/RDMSerialRecv/RDMSerialRecv.ino +++ b/examples/RDMSerialRecv/RDMSerialRecv.ino @@ -84,7 +84,7 @@ void setup () { #endif // initialize the Serial interface to be used as an RDM Device Node. - // There are several constants that have to be passed to the library so it can reposonse to the + // There are several constants that have to be passed to the library so it can respond to the // corresponding commands for itself. DMXSerial2.init(&rdmInit, processCommand); From b676b517d06cd19678750412922b74fed5032020 Mon Sep 17 00:00:00 2001 From: TimMJN <75533580+TimMJN@users.noreply.github.com> Date: Tue, 6 Jun 2023 13:51:30 +0200 Subject: [PATCH 10/32] Update DMXSerial2.h --- src/DMXSerial2.h | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/DMXSerial2.h b/src/DMXSerial2.h index 06646ac..59fa7ed 100644 --- a/src/DMXSerial2.h +++ b/src/DMXSerial2.h @@ -151,7 +151,7 @@ extern "C" { // ----- Library Class ----- // These types are used to pass all the data into the initRDM function. -// The library needs this data to reposonse at the corresponding commands for itself. +// The library needs this data to respond at the corresponding commands for itself. struct RDMPERSONALITY { uint16_t footprint; From 7a04e007368ae4f782f69a580537aa2befa32168 Mon Sep 17 00:00:00 2001 From: TimMJN <75533580+TimMJN@users.noreply.github.com> Date: Tue, 6 Jun 2023 19:31:19 +0200 Subject: [PATCH 11/32] Update src/DMXSerial2.cpp Co-authored-by: Peter Newman --- src/DMXSerial2.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/DMXSerial2.cpp b/src/DMXSerial2.cpp index ac615d5..75a7e0e 100644 --- a/src/DMXSerial2.cpp +++ b/src/DMXSerial2.cpp @@ -628,7 +628,7 @@ void DMXSerialClass2::_processRDMMessage(byte CmdClass, uint16_t Parameter, bool handled = _rdmFunc(&_rdm.packet, &nackReason); } // if - // if not already handled the command: handle it using this implementation + // if this command has not already been handled, handle it using this implementation if (! handled) { if (Parameter == SWAPINT(E120_IDENTIFY_DEVICE)) { // 0x1000 From 7f5dc82de5e45509a9d6e6fc18c42cf5e1754ea1 Mon Sep 17 00:00:00 2001 From: TimMJN <75533580+TimMJN@users.noreply.github.com> Date: Tue, 6 Jun 2023 19:31:35 +0200 Subject: [PATCH 12/32] Update src/DMXSerial2.cpp Co-authored-by: Peter Newman --- src/DMXSerial2.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/DMXSerial2.cpp b/src/DMXSerial2.cpp index 75a7e0e..4fd8500 100644 --- a/src/DMXSerial2.cpp +++ b/src/DMXSerial2.cpp @@ -871,7 +871,7 @@ void DMXSerialClass2::_processRDMMessage(byte CmdClass, uint16_t Parameter, bool } } if (!validPid) { - // Out of range sensor + // Out of range manufacturer specific PID nackReason = E120_NR_UNKNOWN_PID; } else { _rdm.packet.DataLength = 20 + strnlen(_initData->parameters[parameterNr].description, DMXSERIAL_MAX_RDM_STRING_LENGTH); From df163517caadde5cd483b23834f3607978ddb573 Mon Sep 17 00:00:00 2001 From: TimMJN <75533580+TimMJN@users.noreply.github.com> Date: Tue, 6 Jun 2023 19:32:12 +0200 Subject: [PATCH 13/32] Update src/DMXSerial2.h Co-authored-by: Peter Newman --- src/DMXSerial2.h | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/DMXSerial2.h b/src/DMXSerial2.h index 59fa7ed..65aac4d 100644 --- a/src/DMXSerial2.h +++ b/src/DMXSerial2.h @@ -118,7 +118,7 @@ struct RDMDATA { #define WRITEINT(p, d) (p)[0] = (d&0xFF00)>>8; (p)[1] = (d&0x00FF); /// write a 32 bit number to a data buffer location -#define WRITELONG(p, d) (p)[0] = (d&0xFF000000)>>24; (p)[1] = (d&0x00FF0000)>>16; (p)[2] = (d&0x0000FF00)>>8; (p)[3] = (d&0x000000FF); +#define WRITEINT32(p, d) (p)[0] = (d&0xFF000000)>>24; (p)[1] = (d&0x00FF0000)>>16; (p)[2] = (d&0x0000FF00)>>8; (p)[3] = (d&0x000000FF); // ----- Callback function types ----- From d2678fc4381b45025a1d431f5b7b374a30b57319 Mon Sep 17 00:00:00 2001 From: TimMJN <75533580+TimMJN@users.noreply.github.com> Date: Tue, 6 Jun 2023 19:33:37 +0200 Subject: [PATCH 14/32] Update src/DMXSerial2.h Co-authored-by: Peter Newman --- src/DMXSerial2.h | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/src/DMXSerial2.h b/src/DMXSerial2.h index 65aac4d..88b7863 100644 --- a/src/DMXSerial2.h +++ b/src/DMXSerial2.h @@ -251,9 +251,9 @@ class DMXSerialClass2 * @param [in] sensorFunc Callback function for retrieving a sensor value. * @param [in] getParamFunc Callback function for retrieving a parameter value. * @param [in] setParamFunc Callback function for setting a parameter value. - * @param [in] modePin The pin used to switch the communication direction. This parameter is optiona and defaults to 2. - * @param [in] modeIn The level for inbound communication. This parameter is optiona and defaults to 0 = LOW. - * @param [in] modeOut The level for outbound communication. This parameter is optiona and defaults to 1 = HIGH. + * @param [in] modePin The pin used to switch the communication direction. This parameter is optional and defaults to 2. + * @param [in] modeIn The level for inbound communication. This parameter is optional and defaults to 0 = LOW. + * @param [in] modeOut The level for outbound communication. This parameter is optional and defaults to 1 = HIGH. */ void init (struct RDMINIT *initData, RDMCallbackFunction func, RDMGetSensorValue sensorFunc, RDMGetParameterValue getParamFunc, RDMSetParameterValue setParamFunc, uint8_t modePin = 2, uint8_t modeIn = 0, uint8_t modeOut = 1); From bde3c2aeba49477b10353aa84fecb3a59f983a7a Mon Sep 17 00:00:00 2001 From: TimMJN <75533580+TimMJN@users.noreply.github.com> Date: Tue, 6 Jun 2023 19:33:55 +0200 Subject: [PATCH 15/32] Update src/DMXSerial2.h Co-authored-by: Peter Newman --- src/DMXSerial2.h | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/src/DMXSerial2.h b/src/DMXSerial2.h index 88b7863..e862e1c 100644 --- a/src/DMXSerial2.h +++ b/src/DMXSerial2.h @@ -236,9 +236,9 @@ class DMXSerialClass2 * @param [in] func Callback function for answering on device specific features. * @param [in] getParamFunc Callback function for retrieving a parameter value. * @param [in] setParamFunc Callback function for setting a parameter value. - * @param [in] modePin The pin used to switch the communication direction. This parameter is optiona and defaults to 2. - * @param [in] modeIn The level for inbound communication. This parameter is optiona and defaults to 0 = LOW. - * @param [in] modeOut The level for outbound communication. This parameter is optiona and defaults to 1 = HIGH. + * @param [in] modePin The pin used to switch the communication direction. This parameter is optional and defaults to 2. + * @param [in] modeIn The level for inbound communication. This parameter is optional and defaults to 0 = LOW. + * @param [in] modeOut The level for outbound communication. This parameter is optional and defaults to 1 = HIGH. */ void init (struct RDMINIT *initData, RDMCallbackFunction func, RDMGetParameterValue getParamFunc, RDMSetParameterValue setParamFunc, uint8_t modePin = 2, uint8_t modeIn = 0, uint8_t modeOut = 1) { init(initData, func, NULL, getParamFunc, setParamFunc, modePin, modeIn, modeOut); From ee74c82e6daea925510d80a685c8280dc88711ab Mon Sep 17 00:00:00 2001 From: TimMJN <75533580+TimMJN@users.noreply.github.com> Date: Tue, 6 Jun 2023 19:36:17 +0200 Subject: [PATCH 16/32] change WRITELONG to WRITEINT32 --- src/DMXSerial2.cpp | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/src/DMXSerial2.cpp b/src/DMXSerial2.cpp index 4fd8500..1cead51 100644 --- a/src/DMXSerial2.cpp +++ b/src/DMXSerial2.cpp @@ -887,9 +887,9 @@ void DMXSerialClass2::_processRDMMessage(byte CmdClass, uint16_t Parameter, bool _rdm.packet.Data[5] = 0x00; _rdm.packet.Data[6] = _initData->parameters[parameterNr].unit; _rdm.packet.Data[7] = _initData->parameters[parameterNr].prefix; - WRITELONG(_rdm.packet.Data + 8, _initData->parameters[parameterNr].rangeMin); - WRITELONG(_rdm.packet.Data + 12, _initData->parameters[parameterNr].rangeMax); - WRITELONG(_rdm.packet.Data + 16, _initData->parameters[parameterNr].defaultValue); + WRITEINT32(_rdm.packet.Data + 8, _initData->parameters[parameterNr].rangeMin); + WRITEINT32(_rdm.packet.Data + 12, _initData->parameters[parameterNr].rangeMax); + WRITEINT32(_rdm.packet.Data + 16, _initData->parameters[parameterNr].defaultValue); memcpy(_rdm.packet.Data + 20, _initData->parameters[parameterNr].description, _rdm.packet.DataLength - 20); handled = true; /////////////////////////////////////////// From d7e921420b68ce4a8da72090ee377650911e26fc Mon Sep 17 00:00:00 2001 From: TimMJN <75533580+TimMJN@users.noreply.github.com> Date: Tue, 6 Jun 2023 19:37:53 +0200 Subject: [PATCH 17/32] Update src/DMXSerial2.h Co-authored-by: Peter Newman --- src/DMXSerial2.h | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/DMXSerial2.h b/src/DMXSerial2.h index e862e1c..7a4c4f9 100644 --- a/src/DMXSerial2.h +++ b/src/DMXSerial2.h @@ -223,8 +223,8 @@ class DMXSerialClass2 * @param [in] func Callback function for answering on device specific features. * @param [in] sensorFunc Callback function for retrieving a sensor value. * @param [in] modePin The pin used to switch the communication direction. This parameter is optiona and defaults to 2. - * @param [in] modeIn The level for inbound communication. This parameter is optiona and defaults to 0 = LOW. - * @param [in] modeOut The level for outbound communication. This parameter is optiona and defaults to 1 = HIGH. + * @param [in] modeIn The level for inbound communication. This parameter is optional and defaults to 0 = LOW. + * @param [in] modeOut The level for outbound communication. This parameter is optional and defaults to 1 = HIGH. */ void init (struct RDMINIT *initData, RDMCallbackFunction func, RDMGetSensorValue sensorFunc, uint8_t modePin = 2, uint8_t modeIn = 0, uint8_t modeOut = 1) { init(initData, func, sensorFunc, NULL, NULL, modePin, modeIn, modeOut); From 121e6255c92cc0f1cbcf18240056615e45000df9 Mon Sep 17 00:00:00 2001 From: TimMJN <75533580+TimMJN@users.noreply.github.com> Date: Tue, 6 Jun 2023 19:38:09 +0200 Subject: [PATCH 18/32] Update src/DMXSerial2.h Co-authored-by: Peter Newman --- src/DMXSerial2.h | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/DMXSerial2.h b/src/DMXSerial2.h index 7a4c4f9..6534f5a 100644 --- a/src/DMXSerial2.h +++ b/src/DMXSerial2.h @@ -211,7 +211,7 @@ class DMXSerialClass2 * @param [in] func Callback function for answering on device specific features. * @param [in] modePin The pin used to switch the communication direction. This parameter is optiona and defaults to 2. * @param [in] modeIn The level for inbound communication. This parameter is optiona and defaults to 0 = LOW. - * @param [in] modeOut The level for outbound communication. This parameter is optiona and defaults to 1 = HIGH. + * @param [in] modeOut The level for outbound communication. This parameter is optional and defaults to 1 = HIGH. */ void init (struct RDMINIT *initData, RDMCallbackFunction func, uint8_t modePin = 2, uint8_t modeIn = 0, uint8_t modeOut = 1) { init(initData, func, NULL, NULL, NULL, modePin, modeIn, modeOut); From 2e6551a8e2edddf7c5ee4a3d7c0e38ac628e4321 Mon Sep 17 00:00:00 2001 From: TimMJN <75533580+TimMJN@users.noreply.github.com> Date: Tue, 6 Jun 2023 19:38:18 +0200 Subject: [PATCH 19/32] Update src/DMXSerial2.h Co-authored-by: Peter Newman --- src/DMXSerial2.h | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/DMXSerial2.h b/src/DMXSerial2.h index 6534f5a..77357e9 100644 --- a/src/DMXSerial2.h +++ b/src/DMXSerial2.h @@ -151,7 +151,7 @@ extern "C" { // ----- Library Class ----- // These types are used to pass all the data into the initRDM function. -// The library needs this data to respond at the corresponding commands for itself. +// The library needs this data to respond to the corresponding commands for itself. struct RDMPERSONALITY { uint16_t footprint; From fb0c8e1853436b85e507bdbbae2e6fc4fb1f21b6 Mon Sep 17 00:00:00 2001 From: TimMJN <75533580+TimMJN@users.noreply.github.com> Date: Tue, 6 Jun 2023 19:38:57 +0200 Subject: [PATCH 20/32] Update src/DMXSerial2.cpp Co-authored-by: Peter Newman --- src/DMXSerial2.cpp | 7 ++++--- 1 file changed, 4 insertions(+), 3 deletions(-) diff --git a/src/DMXSerial2.cpp b/src/DMXSerial2.cpp index 1cead51..b57db00 100644 --- a/src/DMXSerial2.cpp +++ b/src/DMXSerial2.cpp @@ -878,12 +878,13 @@ void DMXSerialClass2::_processRDMMessage(byte CmdClass, uint16_t Parameter, bool WRITEINT(_rdm.packet.Data, _initData->parameters[parameterNr].pid); _rdm.packet.Data[2] = _initData->parameters[parameterNr].length; _rdm.packet.Data[3] = _initData->parameters[parameterNr].type; - if (_initData->parameters[parameterNr].getSupported && !_initData->parameters[parameterNr].setSupported) + if (_initData->parameters[parameterNr].getSupported && !_initData->parameters[parameterNr].setSupported) { _rdm.packet.Data[4] = E120_CC_GET; - else if (!_initData->parameters[parameterNr].getSupported && _initData->parameters[parameterNr].setSupported) + } else if (!_initData->parameters[parameterNr].getSupported && _initData->parameters[parameterNr].setSupported) { _rdm.packet.Data[4] = E120_CC_SET; - else if (_initData->parameters[parameterNr].getSupported && _initData->parameters[parameterNr].setSupported) + } else if (_initData->parameters[parameterNr].getSupported && _initData->parameters[parameterNr].setSupported) { _rdm.packet.Data[4] = E120_CC_GET_SET; + } _rdm.packet.Data[5] = 0x00; _rdm.packet.Data[6] = _initData->parameters[parameterNr].unit; _rdm.packet.Data[7] = _initData->parameters[parameterNr].prefix; From 10812199082a2e08b520e3d8b111c789de47b209 Mon Sep 17 00:00:00 2001 From: TimMJN <75533580+TimMJN@users.noreply.github.com> Date: Tue, 6 Jun 2023 19:40:12 +0200 Subject: [PATCH 21/32] update nackReason for unknown manufacturer PID --- src/DMXSerial2.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/DMXSerial2.cpp b/src/DMXSerial2.cpp index b57db00..7ecc8ed 100644 --- a/src/DMXSerial2.cpp +++ b/src/DMXSerial2.cpp @@ -872,7 +872,7 @@ void DMXSerialClass2::_processRDMMessage(byte CmdClass, uint16_t Parameter, bool } if (!validPid) { // Out of range manufacturer specific PID - nackReason = E120_NR_UNKNOWN_PID; + nackReason = E120_NR_DATA_OUT_OF_RANGE; } else { _rdm.packet.DataLength = 20 + strnlen(_initData->parameters[parameterNr].description, DMXSERIAL_MAX_RDM_STRING_LENGTH); WRITEINT(_rdm.packet.Data, _initData->parameters[parameterNr].pid); From f4ed6d86ff6071ea024e90397c5e69916d4de0cb Mon Sep 17 00:00:00 2001 From: TimMJN <75533580+TimMJN@users.noreply.github.com> Date: Tue, 6 Jun 2023 23:37:51 +0200 Subject: [PATCH 22/32] change parameterNr to parameterIndex, add pid to callback functions --- .../RDMSerialRecvParameter.ino | 165 ++++++++++-------- src/DMXSerial2.cpp | 34 ++-- src/DMXSerial2.h | 4 +- 3 files changed, 113 insertions(+), 90 deletions(-) diff --git a/examples/RDMSerialRecvParameter/RDMSerialRecvParameter.ino b/examples/RDMSerialRecvParameter/RDMSerialRecvParameter.ino index 9e40e43..bd80acf 100644 --- a/examples/RDMSerialRecvParameter/RDMSerialRecvParameter.ino +++ b/examples/RDMSerialRecvParameter/RDMSerialRecvParameter.ino @@ -4,7 +4,7 @@ // // Copyright (c) 2011-2013 by Matthias Hertel, http://www.mathertel.de // This work is licensed under a BSD style license. See http://www.mathertel.de/License.aspx -// +// // This Arduino project is a sample application for the DMXSerial2 library that shows // how a 3 channel receiving RDM client can be implemented. // The 3 channels are used for PWM Output: @@ -38,53 +38,54 @@ #include -// uncomment this line for enabling information on a LEONARD board. +// uncomment this line for enabling information on a LEONARD board. // #define SERIAL_DEBUG // Constants for demo program -const int RedPin = 9; // PWM output pin for Red Light. -const int GreenPin = 6; // PWM output pin for Green Light. -const int BluePin = 5; // PWM output pin for Blue Light. +const int RedPin = 9; // PWM output pin for Red Light. +const int GreenPin = 6; // PWM output pin for Green Light. +const int BluePin = 5; // PWM output pin for Blue Light. // color: #203050 * 2 -#define RedDefaultLevel 0x20 * 2 +#define RedDefaultLevel 0x20 * 2 #define GreenDefaultLevel 0x30 * 2 -#define BlueDefaultLevel 0x50 * 2 +#define BlueDefaultLevel 0x50 * 2 -// define the RGB output color -void rgb(byte r, byte g, byte b) -{ - analogWrite(RedPin, r); +// define the RGB output color +void rgb(byte r, byte g, byte b) { + analogWrite(RedPin, r); analogWrite(GreenPin, g); - analogWrite(BluePin, b); -} // rgb() + analogWrite(BluePin, b); +} // rgb() // see DMXSerial2.h for the definition of the fields of this structure -const uint16_t my_pids[] = {E120_DEVICE_HOURS, E120_LAMP_HOURS}; +const uint16_t my_pids[] = { E120_DEVICE_HOURS, E120_LAMP_HOURS }; const RDMPARAMETER my_parameters[] = { - {0x8000, 1, E120_DS_UNSIGNED_BYTE, E120_UNITS_NONE, E120_PREFIX_NONE, 0, 255, 128, true, true, "TestParam"} + { 0x8000, 1, E120_DS_UNSIGNED_BYTE, E120_UNITS_NONE, E120_PREFIX_NONE, 0, 255, 128, true, true, "TestParamA" } { 0x8001, 2, E120_DS_UNSIGNED_BYTE, E120_UNITS_NONE, E120_PREFIX_NONE, 0, 255, 128, true, true, "TestParamB" } }; struct RDMINIT rdmInit = { - "mathertel.de", // Manufacturer Label - 1, // Device Model ID - "Arduino RDM Device", // Device Model Label - 3, // footprint - (sizeof(my_pids)/sizeof(uint16_t)), my_pids, + "mathertel.de", // Manufacturer Label + 1, // Device Model ID + "Arduino RDM Device", // Device Model Label + 3, // footprint + (sizeof(my_pids) / sizeof(uint16_t)), my_pids, 0, NULL, - (sizeof(my_parameters)/sizeof(RDMPARAMETER)), my_parameters + (sizeof(my_parameters) / sizeof(RDMPARAMETER)), my_parameters }; -byte parameter = 128; +byte parameterA = 128; +byte parameterB[2] = { 0, 255 }; -void setup () { +void setup() { #if defined(SERIAL_DEBUG) // The Serial port can be used on Arduino Leonard Boards for debugging purpose // because it is not mapped to the real serial port of the ATmega32U4 chip but to the USB port. // Don't use that on Arduino Uno, 2009,... boards based on ATmega328 or ATmega168 chips. - Serial.begin(9600); - while (!Serial) ; + Serial.begin(9600); + while (!Serial) + ; Serial.println("starting..."); #endif @@ -95,19 +96,20 @@ void setup () { uint16_t start = DMXSerial2.getStartAddress(); #if defined(SERIAL_DEBUG) - Serial.print("Listening on DMX address #"); Serial.println(start); + Serial.print("Listening on DMX address #"); + Serial.println(start); #endif // set default values to dark red // this color will be shown when no signal is present for the first 5 seconds. DMXSerial2.write(start + 0, 30); - DMXSerial2.write(start + 1, 0); - DMXSerial2.write(start + 2, 0); - + DMXSerial2.write(start + 1, 0); + DMXSerial2.write(start + 2, 0); + // enable pwm outputs - pinMode(RedPin, OUTPUT); // sets the digital pin as output + pinMode(RedPin, OUTPUT); // sets the digital pin as output pinMode(GreenPin, OUTPUT); - pinMode(BluePin, OUTPUT); + pinMode(BluePin, OUTPUT); #if defined(SERIAL_DEBUG) // output the current DeviceID @@ -116,17 +118,23 @@ void setup () { DMXSerial2.getDeviceID(thisDevice); Serial.print("This Device is: "); - if (thisDevice[0] < 0x10) Serial.print('0'); Serial.print(thisDevice[0], HEX); - if (thisDevice[1] < 0x10) Serial.print('0'); Serial.print(thisDevice[1], HEX); + if (thisDevice[0] < 0x10) Serial.print('0'); + Serial.print(thisDevice[0], HEX); + if (thisDevice[1] < 0x10) Serial.print('0'); + Serial.print(thisDevice[1], HEX); Serial.print(":"); - if (thisDevice[2] < 0x10) Serial.print('0'); Serial.print(thisDevice[2], HEX); - if (thisDevice[3] < 0x10) Serial.print('0'); Serial.print(thisDevice[3], HEX); - if (thisDevice[4] < 0x10) Serial.print('0'); Serial.print(thisDevice[4], HEX); - if (thisDevice[5] < 0x10) Serial.print('0'); Serial.print(thisDevice[5], HEX); + if (thisDevice[2] < 0x10) Serial.print('0'); + Serial.print(thisDevice[2], HEX); + if (thisDevice[3] < 0x10) Serial.print('0'); + Serial.print(thisDevice[3], HEX); + if (thisDevice[4] < 0x10) Serial.print('0'); + Serial.print(thisDevice[4], HEX); + if (thisDevice[5] < 0x10) Serial.print('0'); + Serial.print(thisDevice[5], HEX); Serial.println(); #endif -} // setup() +} // setup() void loop() { @@ -141,39 +149,38 @@ void loop() { rgb(200, 200, 200); } else { rgb(0, 0, 0); - } // if - + } // if + } else if (lastPacket < 30000) { - // read recent DMX values and set pwm levels - analogWrite(RedPin, DMXSerial2.readRelative(0)); + // read recent DMX values and set pwm levels + analogWrite(RedPin, DMXSerial2.readRelative(0)); analogWrite(GreenPin, DMXSerial2.readRelative(1)); - analogWrite(BluePin, DMXSerial2.readRelative(2)); + analogWrite(BluePin, DMXSerial2.readRelative(2)); } else { #if defined(SERIAL_DEBUG) - Serial.println("no signal since 30 secs."); + Serial.println("no signal since 30 secs."); #endif // Show default color, when no data was received since 30 seconds or more. - analogWrite(RedPin, RedDefaultLevel); + analogWrite(RedPin, RedDefaultLevel); analogWrite(GreenPin, GreenDefaultLevel); - analogWrite(BluePin, BlueDefaultLevel); - } // if - + analogWrite(BluePin, BlueDefaultLevel); + } // if + // check for unhandled RDM commands DMXSerial2.tick(); -} // loop() +} // loop() // This function was registered to the DMXSerial2 library in the initRDM call. // Here device specific RDM Commands are implemented. -bool8 processCommand(struct RDMDATA *rdm, uint16_t *nackReason) -{ - byte CmdClass = rdm->CmdClass; // command class - uint16_t Parameter = rdm->Parameter; // parameter ID +bool8 processCommand(struct RDMDATA *rdm, uint16_t *nackReason) { + byte CmdClass = rdm->CmdClass; // command class + uint16_t Parameter = rdm->Parameter; // parameter ID bool8 handled = false; -// This is a sample of how to return some device specific data - if (Parameter == SWAPINT(E120_DEVICE_HOURS)) { // 0x0400 + // This is a sample of how to return some device specific data + if (Parameter == SWAPINT(E120_DEVICE_HOURS)) { // 0x0400 if (CmdClass == E120_GET_COMMAND) { if (rdm->DataLength > 0) { // Unexpected data @@ -194,7 +201,7 @@ bool8 processCommand(struct RDMDATA *rdm, uint16_t *nackReason) *nackReason = E120_NR_UNSUPPORTED_COMMAND_CLASS; } - } else if (Parameter == SWAPINT(E120_LAMP_HOURS)) { // 0x0401 + } else if (Parameter == SWAPINT(E120_LAMP_HOURS)) { // 0x0401 if (CmdClass == E120_GET_COMMAND) { if (rdm->DataLength > 0) { // Unexpected data @@ -204,8 +211,8 @@ bool8 processCommand(struct RDMDATA *rdm, uint16_t *nackReason) *nackReason = E120_NR_SUB_DEVICE_OUT_OF_RANGE; } else { - unsigned long seconds = millis()/1000; - + unsigned long seconds = millis() / 1000; + rdm->DataLength = 4; rdm->Data[0] = (seconds & 0xff000000) >> 24; rdm->Data[1] = (seconds & 0x00ff0000) >> 16; @@ -217,25 +224,41 @@ bool8 processCommand(struct RDMDATA *rdm, uint16_t *nackReason) // This device doesn't support set *nackReason = E120_NR_UNSUPPORTED_COMMAND_CLASS; } - } // if - + } // if + return handled; -} // processCommand +} // processCommand // This function was registered to the DMXSerial2 library in the initRDM call. -// Here retrieval of parameter values is implemented. -bool8 getParameters(uint16_t parameterNr, int8_t *value) { - value[0] = parameter; - return true; -} // getParameters +// Here retrieval of manufacturer-specific parameter values is implemented. +bool8 getParameters(uint16_t pid, uint16_t parameterIndex, int8_t *value) { + if (parameterIndex == 0) { + value[0] = parameterA; + return true; + } else if (parameterIndex == 0) { + value[0] = parameterB[0]; + value[1] = parameterB[1]; + return true; + } else { + return false; + } +} // getParameters // This function was registered to the DMXSerial2 library in the initRDM call. -// Here setting of parameter values is implemented. -bool8 setParameters(uint16_t parameterNr, int8_t *value) { - parameter = value[0]; +// Here setting of manufacturer-specific parameter values is implemented. +bool8 setParameters(uint16_t pid, uint16_t parameterIndex, int8_t *value) { // do something with the value here, eg store it in eeprom + if (parameterIndex == 0) { + parameterA = value[0]; + return true; + } else if (parameterIndex == 0) { + parameterB[0] = value[0]; + parameterB[1] = value[1]; + return true; + } else { + return false; + } return true; -} // setParameters +} // setParameters // End. - diff --git a/src/DMXSerial2.cpp b/src/DMXSerial2.cpp index 7ecc8ed..79bcc45 100644 --- a/src/DMXSerial2.cpp +++ b/src/DMXSerial2.cpp @@ -861,11 +861,11 @@ void DMXSerialClass2::_processRDMMessage(byte CmdClass, uint16_t Parameter, bool nackReason = E120_NR_SUB_DEVICE_OUT_OF_RANGE; } else { uint16_t requestedPid = READINT(_rdm.packet.Data); - uint16_t parameterNr; + uint16_t parameterIndex; bool8 validPid = false; for (uint16_t n = 0; n < _initData->parametersLength; n++) { if (requestedPid == _initData->parameters[n].pid) { - parameterNr = n; + parameterIndex = n; validPid = true; break; } @@ -874,24 +874,24 @@ void DMXSerialClass2::_processRDMMessage(byte CmdClass, uint16_t Parameter, bool // Out of range manufacturer specific PID nackReason = E120_NR_DATA_OUT_OF_RANGE; } else { - _rdm.packet.DataLength = 20 + strnlen(_initData->parameters[parameterNr].description, DMXSERIAL_MAX_RDM_STRING_LENGTH); - WRITEINT(_rdm.packet.Data, _initData->parameters[parameterNr].pid); - _rdm.packet.Data[2] = _initData->parameters[parameterNr].length; - _rdm.packet.Data[3] = _initData->parameters[parameterNr].type; - if (_initData->parameters[parameterNr].getSupported && !_initData->parameters[parameterNr].setSupported) { + _rdm.packet.DataLength = 20 + strnlen(_initData->parameters[parameterIndex].description, DMXSERIAL_MAX_RDM_STRING_LENGTH); + WRITEINT(_rdm.packet.Data, _initData->parameters[parameterIndex].pid); + _rdm.packet.Data[2] = _initData->parameters[parameterIndex].length; + _rdm.packet.Data[3] = _initData->parameters[parameterIndex].type; + if (_initData->parameters[parameterIndex].getSupported && !_initData->parameters[parameterIndex].setSupported) { _rdm.packet.Data[4] = E120_CC_GET; - } else if (!_initData->parameters[parameterNr].getSupported && _initData->parameters[parameterNr].setSupported) { + } else if (!_initData->parameters[parameterIndex].getSupported && _initData->parameters[parameterIndex].setSupported) { _rdm.packet.Data[4] = E120_CC_SET; - } else if (_initData->parameters[parameterNr].getSupported && _initData->parameters[parameterNr].setSupported) { + } else if (_initData->parameters[parameterIndex].getSupported && _initData->parameters[parameterIndex].setSupported) { _rdm.packet.Data[4] = E120_CC_GET_SET; } _rdm.packet.Data[5] = 0x00; - _rdm.packet.Data[6] = _initData->parameters[parameterNr].unit; - _rdm.packet.Data[7] = _initData->parameters[parameterNr].prefix; - WRITEINT32(_rdm.packet.Data + 8, _initData->parameters[parameterNr].rangeMin); - WRITEINT32(_rdm.packet.Data + 12, _initData->parameters[parameterNr].rangeMax); - WRITEINT32(_rdm.packet.Data + 16, _initData->parameters[parameterNr].defaultValue); - memcpy(_rdm.packet.Data + 20, _initData->parameters[parameterNr].description, _rdm.packet.DataLength - 20); + _rdm.packet.Data[6] = _initData->parameters[parameterIndex].unit; + _rdm.packet.Data[7] = _initData->parameters[parameterIndex].prefix; + WRITEINT32(_rdm.packet.Data + 8, _initData->parameters[parameterIndex].rangeMin); + WRITEINT32(_rdm.packet.Data + 12, _initData->parameters[parameterIndex].rangeMax); + WRITEINT32(_rdm.packet.Data + 16, _initData->parameters[parameterIndex].defaultValue); + memcpy(_rdm.packet.Data + 20, _initData->parameters[parameterIndex].description, _rdm.packet.DataLength - 20); handled = true; /////////////////////////////////////////// } @@ -1035,7 +1035,7 @@ void DMXSerialClass2::_processRDMMessage(byte CmdClass, uint16_t Parameter, bool uint8_t value[_initData->parameters[n].length]; bool8 res = false; if (_getParamFunc) { - res = _getParamFunc(n, value); + res = _getParamFunc(_initData->parameters[n].pid, n, value); } if (res) { _rdm.packet.DataLength = _initData->parameters[n].length; @@ -1061,7 +1061,7 @@ void DMXSerialClass2::_processRDMMessage(byte CmdClass, uint16_t Parameter, bool memcpy(value,_rdm.packet.Data,_initData->parameters[n].length); bool8 res = false; if (_setParamFunc) { - res = _setParamFunc(n, value); + res = _setParamFunc(_initData->parameters[n].pid, n, value); } if (res) { _rdm.packet.DataLength = 0; diff --git a/src/DMXSerial2.h b/src/DMXSerial2.h index 77357e9..3c8497e 100644 --- a/src/DMXSerial2.h +++ b/src/DMXSerial2.h @@ -140,12 +140,12 @@ extern "C" { /** * @brief Callback function for getting RDM parameters. */ - typedef bool8 (*RDMGetParameterValue)(uint16_t parameterNr, int8_t *value); + typedef bool8 (*RDMGetParameterValue)(uint16_t pid, uint16_t parameterIndex, int8_t *value); /** * @brief Callback function for setting RDM parameters. */ - typedef bool8 (*RDMSetParameterValue)(uint16_t parameterNr, int8_t *value); + typedef bool8 (*RDMSetParameterValue)(uint16_t pid, uint16_t parameterIndex, int8_t *value); } // ----- Library Class ----- From ec99b3e50ff2ea74451653d0e7522d819b81f21e Mon Sep 17 00:00:00 2001 From: TimMJN <75533580+TimMJN@users.noreply.github.com> Date: Tue, 6 Jun 2023 23:56:54 +0200 Subject: [PATCH 23/32] support sensor (re)set, return 0x0000 for unsupported sensor functions --- src/DMXSerial2.cpp | 43 +++++++++++++++++++++++++++++++++++++------ 1 file changed, 37 insertions(+), 6 deletions(-) diff --git a/src/DMXSerial2.cpp b/src/DMXSerial2.cpp index 79bcc45..68a54d7 100644 --- a/src/DMXSerial2.cpp +++ b/src/DMXSerial2.cpp @@ -927,9 +927,9 @@ void DMXSerialClass2::_processRDMMessage(byte CmdClass, uint16_t Parameter, bool _rdm.packet.DataLength = 9; _rdm.packet.Data[0] = sensorNr; WRITEINT(_rdm.packet.Data + 1, sensorValue); - WRITEINT(_rdm.packet.Data + 3, lowestValue); - WRITEINT(_rdm.packet.Data + 5, highestValue); - WRITEINT(_rdm.packet.Data + 7, recordedValue); + WRITEINT(_rdm.packet.Data + 3, (_initData->sensors[sensorNr].lowHighSupported ? lowestValue : 0)); + WRITEINT(_rdm.packet.Data + 5, (_initData->sensors[sensorNr].lowHighSupported ? highestValue : 0)); + WRITEINT(_rdm.packet.Data + 7, (_initData->sensors[sensorNr].recordedSupported ? recordedValue : 0)); handled = true; } else { nackReason = E120_NR_HARDWARE_FAULT; @@ -937,9 +937,40 @@ void DMXSerialClass2::_processRDMMessage(byte CmdClass, uint16_t Parameter, bool } } } else if (CmdClass == E120_SET_COMMAND) { - // Unhandled set. Set on a sensor is used to reset stats. - // User should process it in own handler when sensor supports high/low or recorded value. - nackReason = E120_NR_UNSUPPORTED_COMMAND_CLASS; + // Set on a sensor is used to reset stats. + if (_rdm.packet.DataLength != 1) { + // Unexpected data + nackReason = E120_NR_FORMAT_ERROR; + } else if (_rdm.packet.SubDev != 0) { + // No sub-devices supported + nackReason = E120_NR_SUB_DEVICE_OUT_OF_RANGE; + } else { + uint8_t sensorNr = _rdm.packet.Data[0]; + if (sensorNr >= _initData->sensorsLength) { + // Out of range sensor + nackReason = E120_NR_DATA_OUT_OF_RANGE; + } else { + int16_t sensorValue = 0; + int16_t lowestValue = 0; + int16_t highestValue = 0; + int16_t recordedValue = 0; + bool8 res = false; + if (_sensorFunc) { + res = _sensorFunc(sensorNr, &sensorValue, &lowestValue, &highestValue, &recordedValue); + } + if (res) { + _rdm.packet.DataLength = 9; + _rdm.packet.Data[0] = sensorNr; + WRITEINT(_rdm.packet.Data + 1, sensorValue); + WRITEINT(_rdm.packet.Data + 3, (_initData->sensors[sensorNr].lowHighSupported ? sensorValue : 0)); + WRITEINT(_rdm.packet.Data + 5, (_initData->sensors[sensorNr].lowHighSupported ? sensorValue : 0)); + WRITEINT(_rdm.packet.Data + 7, (_initData->sensors[sensorNr].recordedSupported ? sensorValue : 0)); + handled = true; + } else { + nackReason = E120_NR_HARDWARE_FAULT; + } + } + } } } else if (Parameter == SWAPINT(E120_SENSOR_DEFINITION) && _initData->sensorsLength > 0) { // 0x0200 From 092aac0ac9df22e0518b21e681ea5ef0c9737df2 Mon Sep 17 00:00:00 2001 From: TimMJN <75533580+TimMJN@users.noreply.github.com> Date: Wed, 7 Jun 2023 22:30:21 +0200 Subject: [PATCH 24/32] bugfixes --- examples/RDMSerialRecvParameter/RDMSerialRecvParameter.ino | 7 ++++--- 1 file changed, 4 insertions(+), 3 deletions(-) diff --git a/examples/RDMSerialRecvParameter/RDMSerialRecvParameter.ino b/examples/RDMSerialRecvParameter/RDMSerialRecvParameter.ino index bd80acf..792723c 100644 --- a/examples/RDMSerialRecvParameter/RDMSerialRecvParameter.ino +++ b/examples/RDMSerialRecvParameter/RDMSerialRecvParameter.ino @@ -62,7 +62,8 @@ void rgb(byte r, byte g, byte b) { // see DMXSerial2.h for the definition of the fields of this structure const uint16_t my_pids[] = { E120_DEVICE_HOURS, E120_LAMP_HOURS }; const RDMPARAMETER my_parameters[] = { - { 0x8000, 1, E120_DS_UNSIGNED_BYTE, E120_UNITS_NONE, E120_PREFIX_NONE, 0, 255, 128, true, true, "TestParamA" } { 0x8001, 2, E120_DS_UNSIGNED_BYTE, E120_UNITS_NONE, E120_PREFIX_NONE, 0, 255, 128, true, true, "TestParamB" } + { 0x8000, 1, E120_DS_UNSIGNED_BYTE, E120_UNITS_NONE, E120_PREFIX_NONE, 0, 255, 128, true, true, "paramA" }, + { 0x8001, 2, E120_DS_UNSIGNED_BYTE, E120_UNITS_NONE, E120_PREFIX_NONE, 0, 255, 128, true, true, "paramB" } }; struct RDMINIT rdmInit = { "mathertel.de", // Manufacturer Label @@ -235,7 +236,7 @@ bool8 getParameters(uint16_t pid, uint16_t parameterIndex, int8_t *value) { if (parameterIndex == 0) { value[0] = parameterA; return true; - } else if (parameterIndex == 0) { + } else if (parameterIndex == 1) { value[0] = parameterB[0]; value[1] = parameterB[1]; return true; @@ -251,7 +252,7 @@ bool8 setParameters(uint16_t pid, uint16_t parameterIndex, int8_t *value) { if (parameterIndex == 0) { parameterA = value[0]; return true; - } else if (parameterIndex == 0) { + } else if (parameterIndex == 1) { parameterB[0] = value[0]; parameterB[1] = value[1]; return true; From 8048876008e11547f6ab2e807506207657ce4a18 Mon Sep 17 00:00:00 2001 From: TimMJN <75533580+TimMJN@users.noreply.github.com> Date: Sat, 10 Jun 2023 14:33:04 +0200 Subject: [PATCH 25/32] added a catch for non-ascii characters in the device label --- src/DMXSerial2.cpp | 21 +++++++++++++++------ 1 file changed, 15 insertions(+), 6 deletions(-) diff --git a/src/DMXSerial2.cpp b/src/DMXSerial2.cpp index 68a54d7..6b53400 100644 --- a/src/DMXSerial2.cpp +++ b/src/DMXSerial2.cpp @@ -734,12 +734,21 @@ void DMXSerialClass2::_processRDMMessage(byte CmdClass, uint16_t Parameter, bool // Oversized data nackReason = E120_NR_FORMAT_ERROR; } else { - memcpy(deviceLabel, _rdm.packet.Data, _rdm.packet.DataLength); - deviceLabel[min(_rdm.packet.DataLength, DMXSERIAL_MAX_RDM_STRING_LENGTH)] = '\0'; - _rdm.packet.DataLength = 0; - // persist in EEPROM - _saveEEPRom(); - handled = true; + bool8 validAsciiStr = true; + for (int i = 0; i<_rdm.packet.DataLength; i++) { + validAsciiStr = validAsciiStr && isAscii(_rdm.packet.Data[i]); + } + if (!validAsciiStr) { + // Not a valid ASCII string + nackReason = E120_NR_FORMAT_ERROR; + } else { + memcpy(deviceLabel, _rdm.packet.Data, _rdm.packet.DataLength); + deviceLabel[min(_rdm.packet.DataLength, DMXSERIAL_MAX_RDM_STRING_LENGTH)] = '\0'; + _rdm.packet.DataLength = 0; + // persist in EEPROM + _saveEEPRom(); + handled = true; + } } } else if (CmdClass == E120_GET_COMMAND) { if (_rdm.packet.DataLength > 0) { From e04ebe47392a92b5f386cff4cc5c840529707e44 Mon Sep 17 00:00:00 2001 From: TimMJN <75533580+TimMJN@users.noreply.github.com> Date: Sat, 10 Jun 2023 14:54:44 +0200 Subject: [PATCH 26/32] move _saveEEPRom after response has been sent --- src/DMXSerial2.cpp | 7 +++++-- 1 file changed, 5 insertions(+), 2 deletions(-) diff --git a/src/DMXSerial2.cpp b/src/DMXSerial2.cpp index 6b53400..41bf68c 100644 --- a/src/DMXSerial2.cpp +++ b/src/DMXSerial2.cpp @@ -622,6 +622,7 @@ void DMXSerialClass2::term(void) void DMXSerialClass2::_processRDMMessage(byte CmdClass, uint16_t Parameter, bool8 handled, bool8 doRespond) { uint16_t nackReason = E120_NR_UNKNOWN_PID; + bool8 updateEEPRom = false; // call the device specific method if ((! handled) && (_rdmFunc)) { @@ -746,7 +747,7 @@ void DMXSerialClass2::_processRDMMessage(byte CmdClass, uint16_t Parameter, bool deviceLabel[min(_rdm.packet.DataLength, DMXSERIAL_MAX_RDM_STRING_LENGTH)] = '\0'; _rdm.packet.DataLength = 0; // persist in EEPROM - _saveEEPRom(); + updateEEPRom = true; handled = true; } } @@ -798,7 +799,7 @@ void DMXSerialClass2::_processRDMMessage(byte CmdClass, uint16_t Parameter, bool _startAddress = newStartAddress; _rdm.packet.DataLength = 0; // persist in EEPROM - _saveEEPRom(); + updateEEPRom = true; handled = true; } } @@ -1119,6 +1120,8 @@ void DMXSerialClass2::_processRDMMessage(byte CmdClass, uint16_t Parameter, bool if (doRespond) respondMessage(handled, nackReason); + if (updateEEPRom) + _saveEEPRom(); } // _processRDMMessage From b55fd586408b51eff6b26b8d984377aa1ec9dd39 Mon Sep 17 00:00:00 2001 From: TimMJN <75533580+TimMJN@users.noreply.github.com> Date: Sun, 11 Jun 2023 22:00:42 +0200 Subject: [PATCH 27/32] Update src/DMXSerial2.h Co-authored-by: Peter Newman --- src/DMXSerial2.h | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/DMXSerial2.h b/src/DMXSerial2.h index 3c8497e..6b2ba50 100644 --- a/src/DMXSerial2.h +++ b/src/DMXSerial2.h @@ -222,7 +222,7 @@ class DMXSerialClass2 * @param [in] initData Startup parameters. * @param [in] func Callback function for answering on device specific features. * @param [in] sensorFunc Callback function for retrieving a sensor value. - * @param [in] modePin The pin used to switch the communication direction. This parameter is optiona and defaults to 2. + * @param [in] modePin The pin used to switch the communication direction. This parameter is optional and defaults to 2. * @param [in] modeIn The level for inbound communication. This parameter is optional and defaults to 0 = LOW. * @param [in] modeOut The level for outbound communication. This parameter is optional and defaults to 1 = HIGH. */ From e05abdcdc8c38660fef2d8cde24917cca5bbc6d4 Mon Sep 17 00:00:00 2001 From: TimMJN <75533580+TimMJN@users.noreply.github.com> Date: Sun, 11 Jun 2023 22:00:55 +0200 Subject: [PATCH 28/32] Update src/DMXSerial2.h Co-authored-by: Peter Newman --- src/DMXSerial2.h | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/DMXSerial2.h b/src/DMXSerial2.h index 6b2ba50..86133a2 100644 --- a/src/DMXSerial2.h +++ b/src/DMXSerial2.h @@ -209,8 +209,8 @@ class DMXSerialClass2 * @brief Initialize for RDM mode. * @param [in] initData Startup parameters. * @param [in] func Callback function for answering on device specific features. - * @param [in] modePin The pin used to switch the communication direction. This parameter is optiona and defaults to 2. - * @param [in] modeIn The level for inbound communication. This parameter is optiona and defaults to 0 = LOW. + * @param [in] modePin The pin used to switch the communication direction. This parameter is optional and defaults to 2. + * @param [in] modeIn The level for inbound communication. This parameter is optional and defaults to 0 = LOW. * @param [in] modeOut The level for outbound communication. This parameter is optional and defaults to 1 = HIGH. */ void init (struct RDMINIT *initData, RDMCallbackFunction func, uint8_t modePin = 2, uint8_t modeIn = 0, uint8_t modeOut = 1) { From 0c924d582294a178344e50b62afec89c5f774236 Mon Sep 17 00:00:00 2001 From: TimMJN <75533580+TimMJN@users.noreply.github.com> Date: Sun, 11 Jun 2023 22:19:44 +0200 Subject: [PATCH 29/32] implement resetting all sensors --- src/DMXSerial2.cpp | 52 +++++++++++++++++++++++++--------------------- 1 file changed, 28 insertions(+), 24 deletions(-) diff --git a/src/DMXSerial2.cpp b/src/DMXSerial2.cpp index 41bf68c..fe6a5b4 100644 --- a/src/DMXSerial2.cpp +++ b/src/DMXSerial2.cpp @@ -921,7 +921,7 @@ void DMXSerialClass2::_processRDMMessage(byte CmdClass, uint16_t Parameter, bool nackReason = E120_NR_SUB_DEVICE_OUT_OF_RANGE; } else { uint8_t sensorNr = _rdm.packet.Data[0]; - if (sensorNr >= _initData->sensorsLength) { + if (sensorNr >= _initData->sensorsLength || sensorNr == 0xFF) { // Out of range sensor nackReason = E120_NR_DATA_OUT_OF_RANGE; } else { @@ -956,32 +956,36 @@ void DMXSerialClass2::_processRDMMessage(byte CmdClass, uint16_t Parameter, bool nackReason = E120_NR_SUB_DEVICE_OUT_OF_RANGE; } else { uint8_t sensorNr = _rdm.packet.Data[0]; - if (sensorNr >= _initData->sensorsLength) { + if (sensorNr >= _initData->sensorsLength && sensorNr != 0xFF) { // Out of range sensor nackReason = E120_NR_DATA_OUT_OF_RANGE; } else { - int16_t sensorValue = 0; - int16_t lowestValue = 0; - int16_t highestValue = 0; - int16_t recordedValue = 0; - bool8 res = false; - if (_sensorFunc) { - res = _sensorFunc(sensorNr, &sensorValue, &lowestValue, &highestValue, &recordedValue); - } - if (res) { - _rdm.packet.DataLength = 9; - _rdm.packet.Data[0] = sensorNr; - WRITEINT(_rdm.packet.Data + 1, sensorValue); - WRITEINT(_rdm.packet.Data + 3, (_initData->sensors[sensorNr].lowHighSupported ? sensorValue : 0)); - WRITEINT(_rdm.packet.Data + 5, (_initData->sensors[sensorNr].lowHighSupported ? sensorValue : 0)); - WRITEINT(_rdm.packet.Data + 7, (_initData->sensors[sensorNr].recordedSupported ? sensorValue : 0)); - handled = true; - } else { - nackReason = E120_NR_HARDWARE_FAULT; - } - } - } - } + for (int i = 0; i<_initData->sensorsLength; i++) { + if (i == sensorNr || sensorNr == 0xFF) { + int16_t sensorValue = 0; + int16_t lowestValue = 0; + int16_t highestValue = 0; + int16_t recordedValue = 0; + bool8 res = false; + if (_sensorFunc) { + res = _sensorFunc(i, &sensorValue, &lowestValue, &highestValue, &recordedValue); + } + if (res) { + _rdm.packet.DataLength = 9; + _rdm.packet.Data[0] = i; + WRITEINT(_rdm.packet.Data + 1, sensorValue); + WRITEINT(_rdm.packet.Data + 3, (_initData->sensors[i].lowHighSupported ? sensorValue : 0)); + WRITEINT(_rdm.packet.Data + 5, (_initData->sensors[i].lowHighSupported ? sensorValue : 0)); + WRITEINT(_rdm.packet.Data + 7, (_initData->sensors[i].recordedSupported ? sensorValue : 0)); + handled = true; + } else { + nackReason = E120_NR_HARDWARE_FAULT; + } + } // if + } // for + } // else + } // else + } // else if } else if (Parameter == SWAPINT(E120_SENSOR_DEFINITION) && _initData->sensorsLength > 0) { // 0x0200 if (CmdClass == E120_GET_COMMAND) { From 79f2c8c9bc904d46c3a737b88e77f121fcaeec75 Mon Sep 17 00:00:00 2001 From: TimMJN <75533580+TimMJN@users.noreply.github.com> Date: Sun, 11 Jun 2023 22:26:17 +0200 Subject: [PATCH 30/32] Update RDMSerialRecvParameter.ino --- .../RDMSerialRecvParameter.ino | 16 ++++++++++------ 1 file changed, 10 insertions(+), 6 deletions(-) diff --git a/examples/RDMSerialRecvParameter/RDMSerialRecvParameter.ino b/examples/RDMSerialRecvParameter/RDMSerialRecvParameter.ino index 792723c..6ac8946 100644 --- a/examples/RDMSerialRecvParameter/RDMSerialRecvParameter.ino +++ b/examples/RDMSerialRecvParameter/RDMSerialRecvParameter.ino @@ -47,6 +47,10 @@ const int RedPin = 9; // PWM output pin for Red Light. const int GreenPin = 6; // PWM output pin for Green Light. const int BluePin = 5; // PWM output pin for Blue Light. +// device-specific PIDs should be in the range 0x8000-0xFFDF +#define PARAM_A_PID 0x8000 +#define PARAM_B_PID 0x8001 + // color: #203050 * 2 #define RedDefaultLevel 0x20 * 2 #define GreenDefaultLevel 0x30 * 2 @@ -62,8 +66,8 @@ void rgb(byte r, byte g, byte b) { // see DMXSerial2.h for the definition of the fields of this structure const uint16_t my_pids[] = { E120_DEVICE_HOURS, E120_LAMP_HOURS }; const RDMPARAMETER my_parameters[] = { - { 0x8000, 1, E120_DS_UNSIGNED_BYTE, E120_UNITS_NONE, E120_PREFIX_NONE, 0, 255, 128, true, true, "paramA" }, - { 0x8001, 2, E120_DS_UNSIGNED_BYTE, E120_UNITS_NONE, E120_PREFIX_NONE, 0, 255, 128, true, true, "paramB" } + { PARAM_A_PID, 1, E120_DS_UNSIGNED_BYTE, E120_UNITS_NONE, E120_PREFIX_NONE, 0, 255, 128, true, true, "paramA" }, + { PARAM_B_PID, 2, E120_DS_UNSIGNED_BYTE, E120_UNITS_NONE, E120_PREFIX_NONE, 0, 255, 128, true, true, "paramB" } }; struct RDMINIT rdmInit = { "mathertel.de", // Manufacturer Label @@ -233,10 +237,10 @@ bool8 processCommand(struct RDMDATA *rdm, uint16_t *nackReason) { // This function was registered to the DMXSerial2 library in the initRDM call. // Here retrieval of manufacturer-specific parameter values is implemented. bool8 getParameters(uint16_t pid, uint16_t parameterIndex, int8_t *value) { - if (parameterIndex == 0) { + if (pid == PARAM_A_PID) { value[0] = parameterA; return true; - } else if (parameterIndex == 1) { + } else if (pid == PARAM_B_PID) { value[0] = parameterB[0]; value[1] = parameterB[1]; return true; @@ -249,10 +253,10 @@ bool8 getParameters(uint16_t pid, uint16_t parameterIndex, int8_t *value) { // Here setting of manufacturer-specific parameter values is implemented. bool8 setParameters(uint16_t pid, uint16_t parameterIndex, int8_t *value) { // do something with the value here, eg store it in eeprom - if (parameterIndex == 0) { + if (pid == PARAM_A_PID) { parameterA = value[0]; return true; - } else if (parameterIndex == 1) { + } else if (pid == PARAM_B_PID) { parameterB[0] = value[0]; parameterB[1] = value[1]; return true; From 05f46d998b606462083a7e410bb1287a7c7885ee Mon Sep 17 00:00:00 2001 From: TimMJN <75533580+TimMJN@users.noreply.github.com> Date: Sun, 11 Jun 2023 22:30:48 +0200 Subject: [PATCH 31/32] correct terminilogy --- examples/RDMSerialRecv/RDMSerialRecv.ino | 4 ++-- examples/RDMSerialRecvParameter/RDMSerialRecvParameter.ino | 6 +++--- examples/RDMSerialRecvSensor/RDMSerialRecvSensor.ino | 4 ++-- src/DMXSerial2.h | 6 +++--- 4 files changed, 10 insertions(+), 10 deletions(-) diff --git a/examples/RDMSerialRecv/RDMSerialRecv.ino b/examples/RDMSerialRecv/RDMSerialRecv.ino index 35dfee2..2086180 100644 --- a/examples/RDMSerialRecv/RDMSerialRecv.ino +++ b/examples/RDMSerialRecv/RDMSerialRecv.ino @@ -31,9 +31,9 @@ // 25.05.2017 Stefan Krupop: Add support for sensors // 21.08.2018 improvements and typo by Peter Newman // 31.10.2018 Remove unnecessary #include by Graham Hanson -// 04.06.2023 Tim Nijssen: Add support for device-specific parameters +// 04.06.2023 Tim Nijssen: Add support for manufacturer-specific parameters // 05.06.2023 Tim Nijssen: integrate sensors example -// 05.06.2023 Tim Nijssen: Add example for device-specific parameters +// 05.06.2023 Tim Nijssen: Add example for manufacturer-specific parameters // - - - - - #include diff --git a/examples/RDMSerialRecvParameter/RDMSerialRecvParameter.ino b/examples/RDMSerialRecvParameter/RDMSerialRecvParameter.ino index 6ac8946..7fd3b28 100644 --- a/examples/RDMSerialRecvParameter/RDMSerialRecvParameter.ino +++ b/examples/RDMSerialRecvParameter/RDMSerialRecvParameter.ino @@ -31,9 +31,9 @@ // 25.05.2017 Stefan Krupop: Add support for sensors // 21.08.2018 improvements and typo by Peter Newman // 31.10.2018 Remove unnecessary #include by Graham Hanson -// 04.06.2023 Tim Nijssen: Add support for device-specific parameters +// 04.06.2023 Tim Nijssen: Add support for manufacturer-specific parameters // 05.06.2023 Tim Nijssen: integrate sensors example -// 05.06.2023 Tim Nijssen: Add example for device-specific parameters +// 05.06.2023 Tim Nijssen: Add example for manufacturer-specific parameters // - - - - - #include @@ -47,7 +47,7 @@ const int RedPin = 9; // PWM output pin for Red Light. const int GreenPin = 6; // PWM output pin for Green Light. const int BluePin = 5; // PWM output pin for Blue Light. -// device-specific PIDs should be in the range 0x8000-0xFFDF +// manufacturer-specific PIDs should be in the range 0x8000-0xFFDF #define PARAM_A_PID 0x8000 #define PARAM_B_PID 0x8001 diff --git a/examples/RDMSerialRecvSensor/RDMSerialRecvSensor.ino b/examples/RDMSerialRecvSensor/RDMSerialRecvSensor.ino index 4763487..f6910bc 100644 --- a/examples/RDMSerialRecvSensor/RDMSerialRecvSensor.ino +++ b/examples/RDMSerialRecvSensor/RDMSerialRecvSensor.ino @@ -32,9 +32,9 @@ // 15.08.2018 Stefan Krupop: Add example for sensors // 21.08.2018 improvements and typo by Peter Newman // 31.10.2018 Remove unnecessary #include by Graham Hanson -// 04.06.2023 Tim Nijssen: Add support for device-specific parameters +// 04.06.2023 Tim Nijssen: Add support for manufacturer-specific parameters // 05.06.2023 Tim Nijssen: integrate sensors example -// 05.06.2023 Tim Nijssen: Add example for device-specific parameters +// 05.06.2023 Tim Nijssen: Add example for manufacturer-specific parameters // - - - - - #include diff --git a/src/DMXSerial2.h b/src/DMXSerial2.h index 86133a2..cf14c06 100644 --- a/src/DMXSerial2.h +++ b/src/DMXSerial2.h @@ -298,13 +298,13 @@ class DMXSerialClass2 /// Return the current DMX footprint, that is the number of DMX addresses used by the device. uint16_t getFootprint(); - /// Register a device-specific implemented function for RDM callbacks + /// Register a manufacturer-specific implemented function for RDM callbacks void attachRDMCallback (RDMCallbackFunction newFunction); - /// Register a device-specific implemented function for getting sensor values + /// Register a manufacturer-specific implemented function for getting sensor values void attachSensorCallback (RDMGetSensorValue newFunction); - /// Register a device-specific implemented function for getting/setting parameter values + /// Register a manufacturer-specific implemented function for getting/setting parameter values void attachParameterCallback(RDMGetParameterValue newGetFunction, RDMSetParameterValue newSetFunction); /// check for unprocessed RDM Command. From 3d5bacdf25da6d8bddecb27b296510bde6c53bae Mon Sep 17 00:00:00 2001 From: TimMJN <75533580+TimMJN@users.noreply.github.com> Date: Sun, 11 Jun 2023 22:47:25 +0200 Subject: [PATCH 32/32] typo --- src/DMXSerial2.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/DMXSerial2.cpp b/src/DMXSerial2.cpp index fe6a5b4..8392f5a 100644 --- a/src/DMXSerial2.cpp +++ b/src/DMXSerial2.cpp @@ -1310,7 +1310,7 @@ void respondMessage(bool8 isHandled, uint16_t nackReason) if (isHandled) { _rdm.packet.ResponseType = E120_RESPONSE_TYPE_ACK; // 0x00 } else { - _rdm.packet.ResponseType = E120_RESPONSE_TYPE_NACK_REASON; // 0x00 + _rdm.packet.ResponseType = E120_RESPONSE_TYPE_NACK_REASON; // 0x02 _rdm.packet.DataLength = 2; _rdm.packet.Data[0] = (nackReason >> 8) & 0xFF; _rdm.packet.Data[1] = nackReason & 0xFF;