aboutsummaryrefslogtreecommitdiffhomepage
diff options
context:
space:
mode:
authorcbdev <cb@cbcdn.com>2020-03-06 23:46:43 +0100
committercbdev <cb@cbcdn.com>2020-03-06 23:46:43 +0100
commit1b3f7610d47ba5464e7aa2e16b5b1a27b7d0f5a3 (patch)
treeaec459da2711aa92082d6d9b03928a9a7ad7aca6
parentf12fb1e2f88e29c8060dfe673b65a315a84c1b29 (diff)
downloadmidimonster-1b3f7610d47ba5464e7aa2e16b5b1a27b7d0f5a3.tar.gz
midimonster-1b3f7610d47ba5464e7aa2e16b5b1a27b7d0f5a3.tar.bz2
midimonster-1b3f7610d47ba5464e7aa2e16b5b1a27b7d0f5a3.zip
Implement openpixelcontrol broadcast (strip 0) input
-rw-r--r--backends/openpixelcontrol.c191
-rw-r--r--backends/openpixelcontrol.md3
2 files changed, 131 insertions, 63 deletions
diff --git a/backends/openpixelcontrol.c b/backends/openpixelcontrol.c
index 62cdb68..ca395d3 100644
--- a/backends/openpixelcontrol.c
+++ b/backends/openpixelcontrol.c
@@ -1,4 +1,5 @@
#define BACKEND_NAME "openpixelcontrol"
+#define DEBUG
#include <string.h>
@@ -115,7 +116,7 @@ static ssize_t openpixel_buffer_find(openpixel_instance_data* data, uint8_t stri
static int openpixel_buffer_extend(openpixel_instance_data* data, uint8_t strip, uint8_t input, uint16_t length){
ssize_t buffer = openpixel_buffer_find(data, strip, input);
-
+
//length is in component-channels, round it to the nearest rgb-triplet
//this guarantees that any allocated buffer has at least three bytes, which is important to parts of the receive handler
length = (length % 3) ? ((length / 3) + 1) * 3 : length;
@@ -340,12 +341,86 @@ static int openpixel_client_new(instance* inst, int fd){
return mm_manage_fd(fd, BACKEND_NAME, 1, inst);
}
-static ssize_t openpixel_client_pixeldata(instance* inst, openpixel_client* client, uint8_t* buffer, size_t bytes_left){
- openpixel_instance_data* data = (openpixel_instance_data*) inst->impl;
+static size_t openpixel_strip_pixeldata8(instance* inst, openpixel_client* client, uint8_t* data, openpixel_buffer* buffer, size_t bytes_left){
+ channel* chan = NULL;
+ channel_value val;
size_t u;
+
+ for(u = 0; u < bytes_left; u++){
+ //if over buffer length, ignore
+ if(u + client->offset >= buffer->bytes){
+ client->buffer = -2;
+ break;
+ }
+
+ //FIXME if at start of trailing non-multiple of 3, ignore
+
+ //update changed channels
+ if(buffer->data.u8[u + client->offset] != data[u]){
+ buffer->data.u8[u + client->offset] = data[u];
+ chan = mm_channel(inst, ((uint64_t) buffer->strip << 32) | (u + client->offset + 1), 0);
+ if(chan){
+ //push event
+ val.raw.u64 = data[u];
+ val.normalised = (double) data[u] / 255.0;
+ if(mm_channel_event(chan, val)){
+ LOG("Failed to push channel event to core");
+ }
+ }
+ }
+ }
+ return u;
+}
+
+static size_t openpixel_strip_pixeldata16(instance* inst, openpixel_client* client, uint8_t* data, openpixel_buffer* buffer, size_t bytes_left){
channel* chan = NULL;
channel_value val;
+ size_t u;
+ for(u = 0; u < bytes_left; u++){
+ //if over buffer length, ignore
+ if(u + client->offset >= buffer->bytes){
+ client->buffer = -2;
+ break;
+ }
+
+ //if at start of trailing non-multiple of 6, ignore
+ if((client->offset + u) >= (client->offset + client->left) - ((client->offset + client->left) % 6)){
+ client->buffer = -2;
+ break;
+ }
+
+ //byte-order conversion may be on message boundary, do it via a buffer
+ client->boundary.u8[(client->offset + u) % 2] = data[u];
+
+ //detect and update changed channels
+ if((client->offset + u) % 2
+ && buffer->data.u16[(u + client->offset) / 2] != be16toh(client->boundary.u16)){
+ buffer->data.u16[(u + client->offset) / 2] = be16toh(client->boundary.u16);
+ chan = mm_channel(inst, ((uint64_t) buffer->strip << 32) | ((u + client->offset) / 2 + 1), 0);
+ if(chan){
+ //push event
+ val.raw.u64 = be16toh(client->boundary.u16);;
+ val.normalised = (double) val.raw.u64 / 65535.0;
+ if(mm_channel_event(chan, val)){
+ LOG("Failed to push channel event to core");
+ }
+ }
+
+ }
+ }
+ return u;
+}
+
+static ssize_t openpixel_client_pixeldata(instance* inst, openpixel_client* client, uint8_t* buffer, size_t bytes_left){
+ openpixel_instance_data* data = (openpixel_instance_data*) inst->impl;
+ openpixel_client temp_client = {
+ .fd = -1
+ };
+ ssize_t u, p;
+ uint8_t processing_done = 1;
+
+ //ignore data
if(client->buffer == -2){
//ignore data
u = min(client->left, bytes_left);
@@ -353,71 +428,55 @@ static ssize_t openpixel_client_pixeldata(instance* inst, openpixel_client* clie
client->left -= u;
return u;
}
- else{
- if(data->mode == rgb8){
- for(u = 0; u < bytes_left; u++){
- //if over buffer length, ignore
- if(u + client->offset >= data->buffer[client->buffer].bytes){
- client->buffer = -2;
- break;
+ //handle broadcast data
+ else if(client->buffer == -3){
+ //iterate all input strips
+ for(p = 0; p < data->buffers; p++){
+ if(data->buffer[p].flags & OPENPIXEL_INPUT){
+ //prepare temporary client
+ temp_client.buffer = p;
+ temp_client.hdr = client->hdr;
+ temp_client.hdr.strip = data->buffer[p].strip;
+ temp_client.offset = client->offset;
+ temp_client.left = client->left;
+
+ //run processing on strip
+ if(data->mode == rgb8){
+ openpixel_strip_pixeldata8(inst, &temp_client, buffer, data->buffer + p, bytes_left);
}
-
- //FIXME if at start of trailing non-multiple of 3, ignore
-
- //update changed channels
- if(data->buffer[client->buffer].data.u8[u + client->offset] != buffer[u]){
- data->buffer[client->buffer].data.u8[u + client->offset] = buffer[u];
- chan = mm_channel(inst, ((uint64_t) client->hdr.strip << 32) | (u + client->offset + 1), 0);
- if(chan){
- //push event
- val.raw.u64 = buffer[u];
- val.normalised = (double) buffer[u] / 255.0;
- if(mm_channel_event(chan, val)){
- LOG("Failed to push channel event to core");
- }
- }
+ else{
+ openpixel_strip_pixeldata16(inst, &temp_client, buffer, data->buffer + p, bytes_left);
+ }
+ if(temp_client.buffer != -2){
+ processing_done = 0;
}
}
-
- //update offsets
- client->offset += u;
- client->left -= u;
- return u;
}
- else{
- for(u = 0; u < bytes_left; u++){
- //if over buffer length, ignore
- if(u + client->offset >= data->buffer[client->buffer].bytes){
- client->buffer = -2;
- break;
- }
-
- //if at start of trailing non-multiple of 6, ignore
- if((client->offset + u) >= (client->offset + client->left) - ((client->offset + client->left) % 6)){
- client->buffer = -2;
- break;
- }
- //byte-order conversion may be on message boundary, do it via a buffer
- client->boundary.u8[(client->offset + u) % 2] = buffer[u];
-
- //detect and update changed channels
- if((client->offset + u) % 2
- && data->buffer[client->buffer].data.u16[(u + client->offset) / 2] != be16toh(client->boundary.u16)){
- data->buffer[client->buffer].data.u16[(u + client->offset) / 2] = be16toh(client->boundary.u16);
- chan = mm_channel(inst, ((uint64_t) client->hdr.strip << 32) | ((u + client->offset) / 2 + 1), 0);
- if(chan){
- //push event
- val.raw.u64 = be16toh(client->boundary.u16);;
- val.normalised = (double) val.raw.u64 / 65535.0;
- if(mm_channel_event(chan, val)){
- LOG("Failed to push channel event to core");
- }
- }
+ //if all strips report being done, ignore the rest of the data
+ if(processing_done){
+ client->buffer = -2;
+ }
- }
- }
+ //remove data
+ u = min(client->left, bytes_left);
+ client->offset += u;
+ client->left -= u;
+ return u;
+ }
+ //process data
+ else{
+ if(data->mode == rgb8){
+ u = openpixel_strip_pixeldata8(inst, client, buffer, data->buffer + client->buffer, bytes_left);
+ }
+ else{
+ u = openpixel_strip_pixeldata16(inst, client, buffer, data->buffer + client->buffer, bytes_left);
}
+
+ //update offsets
+ client->offset += u;
+ client->left -= u;
+ return u;
}
return -1;
}
@@ -431,8 +490,14 @@ static ssize_t openpixel_client_headerdata(instance* inst, openpixel_client* cli
//if done, resolve buffer
if(sizeof(openpixel_header) - client->offset <= bytes_left){
- client->buffer = openpixel_buffer_find(data, client->hdr.strip, 1);
- //TODO handle broadcast strip input
+ //if broadcast strip, mark broadcast
+ if(client->hdr.strip == 0
+ && data->mode == client->hdr.mode){
+ client->buffer = -3;
+ }
+ else{
+ client->buffer = openpixel_buffer_find(data, client->hdr.strip, 1);
+ }
//if no buffer or mode mismatch, ignore data
if(client->buffer < 0
|| data->mode != client->hdr.mode){
diff --git a/backends/openpixelcontrol.md b/backends/openpixelcontrol.md
index 5a8686f..d09d412 100644
--- a/backends/openpixelcontrol.md
+++ b/backends/openpixelcontrol.md
@@ -50,3 +50,6 @@ This behaviour may be changed in future releases.
While acting as an OpenPixelControl server, the backend allows multiple clients to connect.
This may lead to confusing data output when multiple clients are trying to control the same strip.
+
+When acting as a 16bit OpenPixelControl server, input on the broadcast strip (strip 0) may cause erratic
+value events on a few channels, especially with longer strips and inputs.