update unicorn hat node for faster writing of pixels

This commit is contained in:
Dave Conway-Jones 2016-02-26 22:01:00 +00:00
parent 734fbe2adb
commit ea9356a3cc
5 changed files with 95 additions and 68 deletions

View File

@ -34,11 +34,12 @@ A pixel is set by **msg.payload** with a CSV string `x,y,r,g,b` , where x and y
are 0 to 7, and r, g and b are 0 - 255.
If `x` or `y` are set to `*` then the complete row or column can be set.
Setting both `x` and `y` to `*` fills the background.
Multiple pixels can be specified at once by using `x1,y1,r1,g1,b1,x2,y2,r2,g2,b2,...` etc
The background can also be set to a colour by setting **msg.payload** to an r,g,b triple.
Any msg with a **msg.topic** identifies a 'sprite' pixel, which can then be moved
independently of the background. A 'sprite' can be a single pixel or a complete line.
Any msg with a **msg.topic** identifies a 'sprite', which can then be moved
independently of the background. A 'sprite' can be a single pixel, or a group of pixels.
Setting **msg.payload** to `0` will delete the sprite from the list identified by **msg.topic**.

View File

@ -1,6 +1,6 @@
{
"name" : "node-red-node-pi-unicorn-hat",
"version" : "0.0.2",
"version" : "0.0.3",
"description" : "A Node-RED node to output to a Raspberry Pi Unicorn HAT from Pimorini.",
"dependencies" : {
"pngjs": "2.2.*"

View File

@ -33,17 +33,18 @@
<script type="text/x-red" data-help-name="rpi-unicorn">
<p>Raspberry Pi Unicorn HAT Node</p>
<p>The background of the array can be configured using an 8x8 pixel sized
png image, or by specifying a single colour using an r,g,b triple.</p>
<p>A pixel is set by <b>msg.payload</b> with a CSV string <i>x,y,r,g,b</i> .
png image, or by specifying a single colour using an <i>r,g,b</i> triple.</p>
<p>The background colour can also be set by a <code>msg.payload</code> with an <i>r,g,b</i> triple.</p>
<p>A pixel is set by a <code>payload</code> containing a CSV string <i>x,y,r,g,b</i> .
Multiple pixels strings can also be sent as <i>x1,y1,r1,g1,b1,x2,y2,r2,g2,b2,...</i> .
If x or y are set to * then the complete row or column can be set.</p>
<p>The background can be set to a colour by setting msg.payload to an r,g,b triple.</p>
<p>Any msg with a <b>msg.topic</b> identifies a 'sprite' pixel, which can then
be moved independently. A 'sprite' can be a single pixel or a complete row.</p>
<p>Setting msg.payload to 0 will delete the sprite from the list.</p>
<p>Setting msg.payload to "CLS" will clear the display to off and delete any sprites.</p>
<p>Setting msg.payload to "DEL" will delete any sprites, and leave the background.</p>
<p>The brightness may be set by setting msg.payload to <i>brightness,nn</i>, where nn is 0 to 100.</p>
<p>The rotation may be set by setting msg.payload to <i>rotate,rr</i>, where rr is 0, 90, 180 or 270.</p>
<p>Any msg with a <code>topic</code> identifies a 'sprite', which can then
be moved independently. A 'sprite' can be a single pixel or a group of pixels.</p>
<p>Setting <code>payload</code> to 0 will delete the sprite from the list.</p>
<p>Setting <code>payload</code> to "CLS" will clear the display to off and delete any sprites.</p>
<p>Setting <code>payload</code> to "DEL" will delete any sprites, and leave the background.</p>
<p>The brightness may be set by setting <code>payload</code> to <i>brightness,nn</i> where nn is 0 to 100.</p>
<p>The rotation may be set by setting <code>payload</code> to <i>rotate,rr</i> where rr is 0, 90, 180 or 270.</p>
</script>
<script type="text/javascript">

View File

@ -16,9 +16,9 @@
module.exports = function(RED) {
"use strict";
var spawn = require('child_process').spawn;
var fs = require('fs');
var fs = require('fs');
var PNG = require('pngjs').PNG;
var spawn = require('child_process').spawn;
var hatCommand = __dirname+'/unihat';
@ -93,6 +93,7 @@ module.exports = function(RED) {
function inputlistener(msg) {
var s = msg.payload.toUpperCase().split(",");
var doDraw = true;
if (s.length === 1) {
if (s[0] == "CLS") {
//console.log("CLEAR")
@ -123,71 +124,89 @@ module.exports = function(RED) {
i += 2;
}
}
else if (s.length === 5) {
else if (s.length % 5 === 0) { // handles pixel updates
if (msg.topic) {
node.items[msg.topic] = msg.payload;
}
else {
//console.log("PIXEL",b);
if ((s[0] === "*") && (s[1] === "*")) {
for (var c=0; c<192; c++) {
pic[c] = s[2];
pic[c+1] = s[3];
pic[c+2] = s[4];
c += 2;
node.child.stdin.write('P'+msg.payload+'\n');
doDraw = false;
for (var a=0; a<s.length; a++) {
//console.log("PIXELS",a);
if ((s[a] === "*") && (s[a+1] === "*")) {
for (var c=0; c<192; c++) {
pic[c] = s[a+2];
pic[c+1] = s[a+3];
pic[c+2] = s[a+4];
c += 2;
}
}
}
else if (s[0] === "*") {
for (var d=0; d<8; d++) {
pic[d*3+s[1]*24] = s[2];
pic[d*3+s[1]*24+1] = s[3];
pic[d*3+s[1]*24+2] = s[4];
else if (s[a] === "*") {
for (var d=0; d<8; d++) {
pic[d*3+s[1]*24] = s[a+2];
pic[d*3+s[1]*24+1] = s[a+3];
pic[d*3+s[1]*24+2] = s[a+4];
}
}
}
else if (s[1] === "*") {
for (var e=0; e<8; e++) {
pic[s[0]*3+e*24] = s[2];
pic[s[0]*3+e*24+1] = s[3];
pic[s[0]*3+e*24+2] = s[4];
else if (s[a+1] === "*") {
for (var e=0; e<8; e++) {
pic[s[a]*3+e*24] = s[a+2];
pic[s[a]*3+e*24+1] = s[a+3];
pic[s[a]*3+e*24+2] = s[a+4];
}
}
else {
pic[s[a]*3+s[a+1]*24] = s[a+2];
pic[s[a]*3+s[a+1]*24+1] = s[a+3];
pic[s[a]*3+s[a+1]*24+2] = s[a+4];
}
a += 4;
}
else {
pic[s[0]*3+s[1]*24] = s[2];
pic[s[0]*3+s[1]*24+1] = s[3];
pic[s[0]*3+s[1]*24+2] = s[4];
}
}
}
else if (s.length === 192) { // handle complete buffer refresh.
for (var i=0; i<192; i++) {
pic[i] = s[i];
pic[i+1] = s[i+1];
pic[i+2] = s[i+2];
i += 2;
}
}
else {
if (node.items.hasOwnProperty(msg.topic)) { delete node.items[msg.topic]; }
}
var pixels = new Buffer(192);
pic.copy(pixels);
for (var p in node.items) {
var b = node.items[p].split(",");
if (b[0] === "*") {
for (var d=0; d<8; d++) {
pixels[d*3+b[1]*24] = b[2];
pixels[d*3+b[1]*24+1] = b[3];
pixels[d*3+b[1]*24+2] = b[4];
if (doDraw) {
var pixels = new Buffer(192);
pic.copy(pixels);
for (var p in node.items) {
var b = node.items[p].split(",");
for (var a=0; a<b.length; a++) {
if (b[a] === "*") {
for (var d=0; d<8; d++) {
pixels[d*3+b[a+1]*24] = b[a+2];
pixels[d*3+b[a+1]*24+1] = b[a+3];
pixels[d*3+b[a+1]*24+2] = b[a+4];
}
}
else if (b[a+1] === "*") {
for (var e=0; e<8; e++) {
pixels[b[a]*3+e*24] = b[a+2];
pixels[b[a]*3+e*24+1] = b[a+3];
pixels[b[a]*3+e*24+2] = b[a+4];
}
}
else {
pixels[b[a]*3+b[a+1]*24] = b[a+2];
pixels[b[a]*3+b[a+1]*24+1] = b[a+3];
pixels[b[a]*3+b[a+1]*24+2] = b[a+4];
}
a += 4;
}
}
else if (b[1] === "*") {
for (var e=0; e<8; e++) {
pixels[b[0]*3+e*24] = b[2];
pixels[b[0]*3+e*24+1] = b[3];
pixels[b[0]*3+e*24+2] = b[4];
}
}
else {
pixels[b[0]*3+b[1]*24] = b[2];
pixels[b[0]*3+b[1]*24+1] = b[3];
pixels[b[0]*3+b[1]*24+2] = b[4];
}
node.child.stdin.write(pixels);
node.child.stdin.write("\n");
}
node.child.stdin.write(pixels);
node.child.stdin.write("\n");
}
node.child = spawn(hatCommand, [node.bright]);

View File

@ -29,16 +29,22 @@ UH.brightness(brightness)
while True:
try:
data = raw_input()
if len(data) < 20:
if len(data) < 10:
if data[0] == "B":
UH.brightness(float(data[1:])/100)
if data[0] == "R":
UH.rotation(float(data[1:]))
else:
q = 0
for p in range(64):
UH.set_pixel(p%8,int(p/8),ord(data[q]),ord(data[q+1]),ord(data[q+2]))
q+=3
if data[0] == "P":
data = data[1:].strip()
s = data.split(',')
for p in range(0,len(s),5):
UH.set_pixel(int(s[p]),int(s[p+1]),int(s[p+2]),int(s[p+3]),int(s[p+4]))
else:
q = 0
for p in range(64):
UH.set_pixel(p%8,int(p/8),ord(data[q]),ord(data[q+1]),ord(data[q+2]))
q += 3
UH.show()
except (EOFError, SystemExit): # hopefully always caused by us sigint'ing the program
sys.exit(0)