diff --git a/libsrc/leddevice/LedDeviceFactory.cpp b/libsrc/leddevice/LedDeviceFactory.cpp index 9c1a259a..33bd7f7a 100755 --- a/libsrc/leddevice/LedDeviceFactory.cpp +++ b/libsrc/leddevice/LedDeviceFactory.cpp @@ -305,10 +305,7 @@ LedDevice * LedDeviceFactory::construct(const Json::Value & deviceConfig) } else if (type == "fadecandy") { - const std::string host = deviceConfig.get("output", "127.0.0.1").asString(); - const uint16_t port = deviceConfig.get("port", 7890).asInt(); - const uint16_t channel = deviceConfig.get("channel", 0).asInt(); - device = new LedDeviceFadeCandy(host, port, channel); + device = new LedDeviceFadeCandy(deviceConfig); } else if (type == "udp") { diff --git a/libsrc/leddevice/LedDeviceFadeCandy.cpp b/libsrc/leddevice/LedDeviceFadeCandy.cpp index 183e97b8..29b9d0e9 100644 --- a/libsrc/leddevice/LedDeviceFadeCandy.cpp +++ b/libsrc/leddevice/LedDeviceFadeCandy.cpp @@ -2,17 +2,20 @@ static const signed MAX_NUM_LEDS = 10000; // OPC can handle 21845 leds - in theory, fadecandy device should handle 10000 leds static const unsigned OPC_SET_PIXELS = 0; // OPC command codes +static const unsigned OPC_SYS_EX = 255; // OPC command codes static const unsigned OPC_HEADER_SIZE = 4; // OPC header size -LedDeviceFadeCandy::LedDeviceFadeCandy(const std::string& host, const uint16_t port, const unsigned channel) : - _host(host), _port(port), _channel(channel) +LedDeviceFadeCandy::LedDeviceFadeCandy(const Json::Value &deviceConfig) { + setConfig(deviceConfig); _opc_data.resize( OPC_HEADER_SIZE ); - _opc_data[0] = channel; + _opc_data[0] = _channel; _opc_data[1] = OPC_SET_PIXELS; _opc_data[2] = 0; _opc_data[3] = 0; + + } @@ -21,6 +24,31 @@ LedDeviceFadeCandy::~LedDeviceFadeCandy() _client.close(); } +bool LedDeviceFadeCandy::setConfig(const Json::Value &deviceConfig) +{ + _host = deviceConfig.get("output", "127.0.0.1").asString(); + _port = deviceConfig.get("port", 7890).asInt(); + _channel = deviceConfig.get("channel", 0).asInt(); + _gamma = deviceConfig.get("gamma", 1.0).asDouble(); + _noDither = ! deviceConfig.get("dither", false).asBool(); + _noInterp = ! deviceConfig.get("interpolation", false).asBool(); + _manualLED = deviceConfig.get("manualLed", false).asBool(); + _ledOnOff = deviceConfig.get("ledOn", false).asBool(); + + _whitePoint_r = 1.0; + _whitePoint_g = 1.0; + _whitePoint_b = 1.0; + + const Json::Value whitePointConfig = deviceConfig["whitePoint"]; + if ( whitePointConfig.isArray() && whitePointConfig.size() == 3 ) + { + _whitePoint_r = whitePointConfig[0].asDouble(); + _whitePoint_g = whitePointConfig[1].asDouble(); + _whitePoint_b = whitePointConfig[2].asDouble(); + } + + return true; +} bool LedDeviceFadeCandy::isConnected() { @@ -33,7 +61,10 @@ bool LedDeviceFadeCandy::tryConnect() if ( _client.state() == QAbstractSocket::UnconnectedState ) { _client.connectToHost( _host.c_str(), _port); if ( _client.waitForConnected(1000) ) + { + sendFadeCandyConfiguration(); Info(_log,"fadecandy/opc: connected to %s:%i on channel %i", _host.c_str(), _port, _channel); + } } return isConnected(); @@ -88,3 +119,35 @@ int LedDeviceFadeCandy::switchOff() return ( transferData()<0 ? -1 : 0 ); } +int LedDeviceFadeCandy::sendSysEx(uint8_t systemId, uint8_t commandId, QByteArray msg) +{ + if ( isConnected() ) + { + QByteArray sysExData; + ssize_t data_size = msg.size() + 4; + sysExData.resize( 4 + OPC_HEADER_SIZE ); + + sysExData[0] = 0; + sysExData[1] = OPC_SYS_EX; + sysExData[2] = data_size >>8; + sysExData[3] = data_size &0xff; + sysExData[4] = systemId >>8; + sysExData[5] = systemId &0xff; + sysExData[6] = commandId >>8; + sysExData[7] = commandId &0xff; + + sysExData += msg; + + return _client.write( sysExData, sysExData.size() ); + } + return -1; +} + +void LedDeviceFadeCandy::sendFadeCandyConfiguration() +{ + QString data = "{\"gamma\": "+QString::number(_gamma,'g',4)+", \"whitepoint\": ["+QString::number(_whitePoint_r,'g',4)+", "+QString::number(_whitePoint_g,'g',4)+", "+QString::number(_whitePoint_b,'g',4)+"]}"; + sendSysEx(1, 1, data.toLocal8Bit() ); + + char firmware_data = ((uint8_t)_noDither | ((uint8_t)_noInterp << 1) | ((uint8_t)_manualLED << 2) | ((uint8_t)_ledOnOff << 3) ); + sendSysEx(1, 2, QByteArray(1,firmware_data) ); +} diff --git a/libsrc/leddevice/LedDeviceFadeCandy.h b/libsrc/leddevice/LedDeviceFadeCandy.h index ebcd85d9..4b837545 100644 --- a/libsrc/leddevice/LedDeviceFadeCandy.h +++ b/libsrc/leddevice/LedDeviceFadeCandy.h @@ -7,6 +7,7 @@ // Leddevice includes #include +#include /// /// Implementation of the LedDevice interface for sending to @@ -20,16 +21,39 @@ public: /// /// Constructs the LedDevice for fadecandy/opc server /// - /// @param host The ip address/host name of fadecandy/opc server - /// @param port The port to use (fadecandy default is 7890) + /// following code shows all config options + /// @code + /// "device" : + /// { + /// "name" : "MyPi", + /// "type" : "fadecandy", + /// "output" : "localhost", + /// "colorOrder" : "rgb", + /// "gamma" : 1.0, + /// "whitepoint" : [1.0, 1.0, 1.0], + /// "dither" : false, + /// "interpolation" : false, + /// "manualLed" : false, + /// "ledOn" : false + /// }, + ///@endcode /// - LedDeviceFadeCandy(const std::string& host, const uint16_t port, const unsigned channel); + /// @param deviceConfig json config for fadecandy + /// + LedDeviceFadeCandy(const Json::Value &deviceConfig); /// /// Destructor of the LedDevice; closes the tcp client /// virtual ~LedDeviceFadeCandy(); + /// + /// Sets configuration + /// + /// @param deviceConfig the json device config + /// @return true if success + bool setConfig(const Json::Value &deviceConfig); + /// /// Writes the led color values to the led-device /// @@ -43,11 +67,21 @@ public: private: - QTcpSocket _client; - const std::string _host; - const uint16_t _port; - const unsigned _channel; - QByteArray _opc_data; + QTcpSocket _client; + std::string _host; + uint16_t _port; + unsigned _channel; + QByteArray _opc_data; + + // fadecandy sysEx + double _gamma; + double _whitePoint_r; + double _whitePoint_g; + double _whitePoint_b; + bool _noDither; + bool _noInterp; + bool _manualLED; + bool _ledOnOff; /// try to establish connection to opc server, if not connected yet /// @@ -61,11 +95,21 @@ private: /// bool isConnected(); - /// transfer current opc_data buffer to opc server /// /// @return amount of transfered bytes. -1 error while transfering, -2 error while connecting /// int transferData(); + /// send system exclusive commands + /// + /// @param systemId fadecandy device identifier (for standard fadecandy always: 1) + /// @param commandId id of command + /// @param msg the sysEx message + /// @return amount bytes written, -1 if fail + int sendSysEx(uint8_t systemId, uint8_t commandId, QByteArray msg); + + /// sends the configuration to fcserver + void sendFadeCandyConfiguration(); + };