diff --git a/doc/fc_server_config.md b/doc/fc_server_config.md index cca6eb1eeb3c6d3c5fff08e65f5b419a44c3e936..ad7852d8b54cd0bdcdf2d76f1a3307b2012b041f 100644 --- a/doc/fc_server_config.md +++ b/doc/fc_server_config.md @@ -102,6 +102,8 @@ Supported mapping objects for Fadecandy devices: * The "Color channels" must be a 3-letter string, where each letter corresponds to one of the WS2811 outputs. * Each letter can be "r", "g", or "b" to choose the red, green, or blue channel respectively, or "l" to use the average luminosity. +If the pixel count is negative, the output pixels are mapped in reverse order starting at the first output pixel index and decrementing the index for each successive pixel up to the absolute value of the pixel count. + Other settings for Fadecandy devices: Name | Values | Default | Description @@ -110,7 +112,7 @@ led | true / false / null | null | Is the LED on, off, or under aut dither | true / false | true | Is dithering enabled? interpolate | true / false | true | Is inter-frame interpolation enabled? -The following example config file supports two Fadecandy devices with distinct serial numbers. They both receive data from OPC channel #0. The first 512 pixels map to the first Fadecandy device. The next 64 pixels map to the entire first strand of the second Fadecandy device, and the next 32 pixels map to the beginning of the third strand with the color channels in Blue, Green, Red order. +The following example config file supports two Fadecandy devices with distinct serial numbers. They both receive data from OPC channel #0. The first 512 pixels map to the first Fadecandy device. The next 64 pixels map to the entire first strand of the second Fadecandy device, the next 32 pixels map to the beginning of the third strand with the color channels in Blue, Green, Red order, and the next 32 pixels map to the end of the third strand in reverse order. { "listen": ["127.0.0.1", 7890], @@ -136,6 +138,7 @@ The following example config file supports two Fadecandy devices with distinct s "map": [ [ 0, 512, 0, 64 ], [ 0, 576, 128, 32, "bgr" ] + [ 0, 608, 191, -32 ] ] } ] diff --git a/server/src/fcdevice.cpp b/server/src/fcdevice.cpp index ee1956e86f62841efc501b9f634fe172b52d83b2..8347fa4218f1075a3399cd33cedf1268f8001e4a 100644 --- a/server/src/fcdevice.cpp +++ b/server/src/fcdevice.cpp @@ -539,11 +539,19 @@ void FCDevice::opcMapPixelColors(const OPC::Message &msg, const Value &inst) const Value &vFirstOut = inst[2]; const Value &vCount = inst[3]; - if (vChannel.IsUint() && vFirstOPC.IsUint() && vFirstOut.IsUint() && vCount.IsUint()) { + if (vChannel.IsUint() && vFirstOPC.IsUint() && vFirstOut.IsUint() && vCount.IsInt()) { unsigned channel = vChannel.GetUint(); unsigned firstOPC = vFirstOPC.GetUint(); unsigned firstOut = vFirstOut.GetUint(); - unsigned count = vCount.GetUint(); + unsigned count; + int direction; + if (vCount.GetInt() >= 0) { + count = vCount.GetInt(); + direction = 1; + } else { + count = -vCount.GetInt(); + direction = -1; + } if (channel != msg.channel) { return; @@ -553,14 +561,15 @@ void FCDevice::opcMapPixelColors(const OPC::Message &msg, const Value &inst) firstOPC = std::min<unsigned>(firstOPC, msgPixelCount); firstOut = std::min<unsigned>(firstOut, unsigned(NUM_PIXELS)); count = std::min<unsigned>(count, msgPixelCount - firstOPC); - count = std::min<unsigned>(count, NUM_PIXELS - firstOut); + count = std::min<unsigned>(count, + direction > 0 ? NUM_PIXELS - firstOut : firstOut + 1); // Copy pixels const uint8_t *inPtr = msg.data + (firstOPC * 3); unsigned outIndex = firstOut; - while (count--) { - uint8_t *outPtr = fbPixel(outIndex++); + uint8_t *outPtr = fbPixel(outIndex); + outIndex += direction; outPtr[0] = inPtr[0]; outPtr[1] = inPtr[1]; outPtr[2] = inPtr[2]; @@ -580,13 +589,21 @@ void FCDevice::opcMapPixelColors(const OPC::Message &msg, const Value &inst) const Value &vCount = inst[3]; const Value &vColorChannels = inst[4]; - if (vChannel.IsUint() && vFirstOPC.IsUint() && vFirstOut.IsUint() && vCount.IsUint() + if (vChannel.IsUint() && vFirstOPC.IsUint() && vFirstOut.IsUint() && vCount.IsInt() && vColorChannels.IsString() && vColorChannels.GetStringLength() == 3) { unsigned channel = vChannel.GetUint(); unsigned firstOPC = vFirstOPC.GetUint(); unsigned firstOut = vFirstOut.GetUint(); - unsigned count = vCount.GetUint(); + unsigned count; + int direction; + if (vCount.GetInt() >= 0) { + count = vCount.GetInt(); + direction = 1; + } else { + count = -vCount.GetInt(); + direction = -1; + } const char *colorChannels = vColorChannels.GetString(); if (channel != msg.channel) { @@ -597,15 +614,16 @@ void FCDevice::opcMapPixelColors(const OPC::Message &msg, const Value &inst) firstOPC = std::min<unsigned>(firstOPC, msgPixelCount); firstOut = std::min<unsigned>(firstOut, unsigned(NUM_PIXELS)); count = std::min<unsigned>(count, msgPixelCount - firstOPC); - count = std::min<unsigned>(count, NUM_PIXELS - firstOut); + count = std::min<unsigned>(count, + direction > 0 ? NUM_PIXELS - firstOut : firstOut + 1); // Copy pixels const uint8_t *inPtr = msg.data + (firstOPC * 3); unsigned outIndex = firstOut; bool success = true; - while (count--) { - uint8_t *outPtr = fbPixel(outIndex++); + uint8_t *outPtr = fbPixel(outIndex); + outIndex += direction; for (int channel = 0; channel < 3; channel++) { if (!OPC::pickColorChannel(outPtr[channel], colorChannels[channel], inPtr)) {