Skip to content
Snippets Groups Projects
Commit d7fbe4bd authored by Micah Elizabeth Scott's avatar Micah Elizabeth Scott
Browse files

Move color correction command to SysEx

After discussing with Ping, changed the format of the color correction command to use a MIDI-style SysEx command in OPC.
parent 257a3287
No related branches found
No related tags found
No related merge requests found
...@@ -18,7 +18,7 @@ print "Connected to OPC server" ...@@ -18,7 +18,7 @@ print "Connected to OPC server"
def setGlobalColorCorrection(**obj): def setGlobalColorCorrection(**obj):
msg = json.dumps(obj) msg = json.dumps(obj)
s.send(struct.pack(">BBH", 0, 0xF0, len(msg)) + msg) s.send(struct.pack(">BBHHH", 0, 0xFF, len(msg) + 4, 0x0001, 0x0001) + msg)
def update(_): def update(_):
setGlobalColorCorrection( setGlobalColorCorrection(
......
...@@ -16,10 +16,39 @@ Supported hardware devices: ...@@ -16,10 +16,39 @@ Supported hardware devices:
OPC Commands OPC Commands
------------ ------------
* Set pixel colors (0x00) All OPC commands follow the same general format. All multi-byte values in Open Pixel Control are in network byte order, high byte followed by low byte.
* Standard OPC message. Data block is an array of 24-bit pixel colors.
* Set global color correction (0xF0) Channel | Command | Length (N) | Data
* Unofficial OPC message. Data block is JSON text, identical to the contents of the 'color' configuration key. ---------- | --------- | ---------- | --------------------------
1 byte | 1 byte | 2 bytes | N bytes of message data
Video data arrives in a **Set Pixel Colors** command:
Byte | **Set Pixel Colors** command
------ | --------------------------------
0 | Channel Number
1 | Command (0x01)
2 - 3 | Data length
4 | Pixel #0, Red
5 | Pixel #0, Green
6 | Pixel #0, Blue
7 | Pixel #1, Red
8 | Pixel #1, Green
9 | Pixel #1, Blue
… | …
As soon as a complete Set Pixel Colors command is received, a new frame of video will be broadcast simultaneously to all attached Fadecandy devices.
The color correction data (from the 'color' configuration key) can also be changed at runtime, by sending a new blob of JSON text in a Fadecandy-specific command. Fadecandy's 16-bit System ID for Open Pixel Control's System Exclusive (0xFF) command is **0x0001**.
Byte | **Set Global Color Correction** command
------ | ------------------------------------------
0 | Channel Number (0x00, reserved)
1 | Command (0xFF, System Exclusive)
2 - 3 | Data length (JSON Length + 4)
4 - 5 | System ID (0x0001, Fadecandy)
6 - 7 | SysEx ID (0x0001, Set Global Color Correction)
8 - … | JSON Text
Configuration Configuration
......
...@@ -287,16 +287,40 @@ void FCDevice::writeMessage(const OPCSink::Message &msg) ...@@ -287,16 +287,40 @@ void FCDevice::writeMessage(const OPCSink::Message &msg)
writeFramebuffer(); writeFramebuffer();
return; return;
case OPCSink::SetGlobalColorCorrection: case OPCSink::SystemExclusive:
opcSetGlobalColorCorrection(msg); opcSysEx(msg);
return; return;
} }
if (mVerbose) { if (mVerbose) {
std::clog << "Unsupported OPC command: " << msg.command << "\n"; std::clog << "Unsupported OPC command: " << unsigned(msg.command) << "\n";
} }
} }
void FCDevice::opcSysEx(const OPCSink::Message &msg)
{
if (msg.length() < 4) {
if (mVerbose) {
std::clog << "SysEx message too short!\n";
}
return;
}
unsigned id = (unsigned(msg.data[0]) << 24) |
(unsigned(msg.data[1]) << 16) |
(unsigned(msg.data[2]) << 8) |
unsigned(msg.data[3]) ;
switch (id) {
case OPCSink::FCSetGlobalColorCorrection:
return opcSetGlobalColorCorrection(msg);
}
// Quietly ignore unhandled SysEx messages.
}
void FCDevice::opcSetPixelColors(const OPCSink::Message &msg) void FCDevice::opcSetPixelColors(const OPCSink::Message &msg)
{ {
/* /*
...@@ -382,7 +406,10 @@ void FCDevice::opcSetGlobalColorCorrection(const OPCSink::Message &msg) ...@@ -382,7 +406,10 @@ void FCDevice::opcSetGlobalColorCorrection(const OPCSink::Message &msg)
*/ */
// Mutable NUL-terminated copy of the message string // Mutable NUL-terminated copy of the message string
std::string text((char*)msg.data, msg.length()); std::string text((char*)msg.data + 4, msg.length() - 4);
if (mVerbose) {
std::clog << "New global color correction settings: " << text << "\n";
}
// Parse it in-place // Parse it in-place
rapidjson::Document doc; rapidjson::Document doc;
......
...@@ -99,6 +99,7 @@ private: ...@@ -99,6 +99,7 @@ private:
static void completeTransfer(struct libusb_transfer *transfer); static void completeTransfer(struct libusb_transfer *transfer);
void opcSetPixelColors(const OPCSink::Message &msg); void opcSetPixelColors(const OPCSink::Message &msg);
void opcSysEx(const OPCSink::Message &msg);
void opcSetGlobalColorCorrection(const OPCSink::Message &msg); void opcSetGlobalColorCorrection(const OPCSink::Message &msg);
void opcMapPixelColors(const OPCSink::Message &msg, const Value &inst); void opcMapPixelColors(const OPCSink::Message &msg, const Value &inst);
}; };
...@@ -33,7 +33,12 @@ class OPCSink { ...@@ -33,7 +33,12 @@ class OPCSink {
public: public:
enum Command { enum Command {
SetPixelColors = 0x00, SetPixelColors = 0x00,
SetGlobalColorCorrection = 0xF0, SystemExclusive = 0xFF,
};
// SysEx system and command IDs
enum SysEx {
FCSetGlobalColorCorrection = 0x00010001,
}; };
struct Message struct Message
......
0% Loading or .
You are about to add 0 people to the discussion. Proceed with caution.
Please register or to comment