-
-
@gordon is it possible to wire up buttons to trigger button 1 / the rest button? With the espruino being upside down, it makes it tricky to push the buttons, so would be good if I could add some custom buttons on the edge to trigger them.
From the reference diagram, it looks like Btn1 is pin B12 is that correct? I couldn't find anything for reset.
Any pointers?
Matt
-
Hey @Gordon
Regarding switching the callbacks for an array buffer, can you suggest a way to handle the bit of code at line 40? Basically, I wire the LED matrix on the opposite side you are supposed to (the chip is meant to be on the back, but I make it so it sits under the LED matrix leaving me a flat back to mount easily) which means I have to do some shifting.
Basically what happens is, think of the image being in for segments, top left, top right, bottom right and bottom left, well with this wiring, the top left square swaps with bottom right, and top right swaps with bottom left. So you end up with 4 lots of 4x4 squares rendering correctly, but in the wrong order. In my original code then, I just shift things by 4 pixels, however once it's been converted to a uintarray, I don't know the right way to do this? I'm assuming it'll use some bitshifting, but after playing around with it before, I couldn't come up with the right shift (especially when you take the colours into account aswell).
You got any suggestions? (Likewise for the rotation too)
Matt
-
@Gordon thanks for the tips. A few things:
1) Weirdly, if I just had the clear override, that would work, so I don't think that is the reason for it failing.
2) When I left off fillRect callback, it didn't render any of my calls to fillRect so I assumed it needed supplying (I've raised an issue on Github)
3) What exactly is a
flip
function? The function to make it display on screen? Got any examples of something that would be more efficient? -
@Gordon it already is, see my other post regarding "trying to assign to an un-named type" :) (I always like to get as close to the original to work first, then make better)
Is there a github repo we can submit new libraries to?
Matt
-
-
@JumJum I'm playing around with the Adafruit bi-color 8x8 matrix which is pretty cool. About £16 here in the UK, so not overly expensive. I've written a library for it for the Espruino on my other thread, so should be pretty easy to get going.
-
Strange! If I use dictionary notation when defining my additional methods, everything seems to work. Does this mean the first way of doing it has a bug?
// Define global constants var LED_OFF = 0; var LED_RED = 1; var LED_YELLOW = 2; var LED_GREEN = 3; var HT16K33_BLINK_CMD = 0x80; var HT16K33_BLINK_DISPLAYON = 0x01; var HT16K33_BLINK_OFF = 0; var HT16K33_BLINK_2HZ = 1; var HT16K33_BLINK_HALFHZ = 3; var HT16K33_BRIGHTNESS_CMD = 0xE0; var HT16K33_ENABLE_OSCILLATOR_CMD = 0x21; var exports = {}; exports.connect = function(i2c, address, callback){ // Private methods function drawPixel(x,y,col){ // Handle rotation switch (rotation) { case 1: var t1 = x; x = 8 - y - 1; y = t1; break; case 2: x = 8 - x - 1; y = 8 - y - 1; break; case 3: var t2 = x; x = y; y = 8 - t2 - 1; break; } // Handle backwards wiring if(x < 4){ x += 4; } else { x -= 4; } if(y < 4){ y += 4; } else { y -= 4; } // We wamt colours to override // so turn the current pixel off by default // then set it's colour again displaybuffer[y] &= ~(1 << x) & ~(1 << (x+8)); if (col == LED_GREEN) { displaybuffer[y] |= (1 << x) & ~(1 << (x+8)); } else if (col == LED_RED) { displaybuffer[y] |= ~(1 << x) & (1 << (x+8)); } else if (col == LED_YELLOW) { displaybuffer[y] |= (1 << x) | (1 << (x+8)); } } function drawRect(x1,y1,x2,y2,col){ for(var x=x1;x<=x2;x++){ for(var y=y1;y<=y2;y++){ drawPixel(x,y,col); } } } // Create buffer var display = Graphics.createCallback(8,8,8,{setPixel:drawPixel,fillRect:drawRect}); var displaybuffer = new Uint16Array(8); var rotation = 0; display["setRotation"] = function(rot){ rotation = rot; }; display["getRotation"] = function(){ return rotation; }; display["setBlinkRate"] = function(b) { if (b > 3) b = 0; // turn off if not sure i2c.writeTo(address, HT16K33_BLINK_CMD | HT16K33_BLINK_DISPLAYON | (b << 1)); }; display["setBrightness"] = function(b) { if (b > 15) b = 15; // Don't go over max i2c.writeTo(address, HT16K33_BRIGHTNESS_CMD | b); }; display["updateDisplay"] = function(){ var tmp = new Uint8Array(17); tmp[0] = 0x00; for (var i=0; i<16; i+=2) { tmp[i+1] = displaybuffer[i/2] & 0xFF; tmp[i+2] = displaybuffer[i/2] >> 8; } i2c.writeTo(address, tmp); }; display["clearDisplay"] = function(){ for (var i=0; i<8; i++) { displaybuffer[i] = 0; } display.updateDisplay(); }; // Turn on oscillator i2c.writeTo(address, HT16K33_ENABLE_OSCILLATOR_CMD); // Set blink rate display.setBlinkRate(HT16K33_BLINK_OFF); // Set to full brightness display.setBrightness(15); // Trigger callback if (callback!==undefined){ setTimeout(callback, 100); } return display; }; // Setup I2C I2C2.setup({ scl: B10, sda: B11 }); var matrix = exports.connect(I2C2, 0x70, function(){ var counter = 1; setInterval(function(){ matrix.clear(); matrix.setRotation(counter - 1); matrix.setColor(counter); matrix.fillRect(0,0,7,1); matrix.fillRect(0,3,7,4); matrix.fillRect(0,6,7,7); matrix.fillRect(0,0,1,7); matrix.updateDisplay(); counter = (counter == 3) ? 1 : counter + 1; }, 2000); });
-
Hey Guys,
I'm trying to write a library for my Adafruit Bi-color 8x8 matrix so that I can release it for others to use. As it is a display and so involves drawing shapes and such, I thought a good idea would be to extend off of the Graphics object and some custom methods to that and return that as my modules API, like so:
// Define global constants var LED_OFF = 0; var LED_RED = 1; var LED_YELLOW = 2; var LED_GREEN = 3; var HT16K33_BLINK_CMD = 0x80; var HT16K33_BLINK_DISPLAYON = 0x01; var HT16K33_BLINK_OFF = 0; var HT16K33_BLINK_2HZ = 1; var HT16K33_BLINK_HALFHZ = 3; var HT16K33_BRIGHTNESS_CMD = 0xE0; var HT16K33_ENABLE_OSCILLATOR_CMD = 0x21; var exports = {}; exports.connect = function(i2c, address, callback){ // Private methods function drawPixel(x,y,col){ // Handle rotation switch (rotation) { case 1: var t1 = x; x = 8 - y - 1; y = t1; break; case 2: x = 8 - x - 1; y = 8 - y - 1; break; case 3: var t2 = x; x = y; y = 8 - t2 - 1; break; } // Handle backwards wiring if(x < 4){ x += 4; } else { x -= 4; } if(y < 4){ y += 4; } else { y -= 4; } // We wamt colours to override // so turn the current pixel off by default // then set it's colour again displaybuffer[y] &= ~(1 << x) & ~(1 << (x+8)); if (col == LED_GREEN) { displaybuffer[y] |= (1 << x) & ~(1 << (x+8)); } else if (col == LED_RED) { displaybuffer[y] |= ~(1 << x) & (1 << (x+8)); } else if (col == LED_YELLOW) { displaybuffer[y] |= (1 << x) | (1 << (x+8)); } } function drawRect(x1,y1,x2,y2,col){ for(var x=x1;x<=x2;x++){ for(var y=y1;y<=y2;y++){ drawPixel(x,y,col); } } } // Create buffer var display = Graphics.createCallback(8,8,8,{setPixel:drawPixel,fillRect:drawRect}); var displaybuffer = new Uint16Array(8); var rotation = 0; display.setRotation = function(rot){ rotation = rot; }; display.getRotation = function(){ return rotation; }; display.setBlinkRate = function(b) { if (b > 3) b = 0; // turn off if not sure i2c.writeTo(address, HT16K33_BLINK_CMD | HT16K33_BLINK_DISPLAYON | (b << 1)); }; display.setBrightness = function(b) { if (b > 15) b = 15; // Don't go over max i2c.writeTo(address, HT16K33_BRIGHTNESS_CMD | b); }; display.clear = function(){ for (var i=0; i<8; i++) { displaybuffer[i] = 0; } display.write(); }; display.write = function(){ var tmp = new Uint8Array(17); tmp[0] = 0x00; for (var i=0; i<16; i+=2) { tmp[i+1] = displaybuffer[i/2] & 0xFF; tmp[i+2] = displaybuffer[i/2] >> 8; } i2c.writeTo(address, tmp); }; // Turn on oscillator i2c.writeTo(address, HT16K33_ENABLE_OSCILLATOR_CMD); // Set blink rate display.setBlinkRate(HT16K33_BLINK_OFF); // Set to full brightness display.setBrightness(15); // Trigger callback if (callback!==undefined){ setTimeout(callback, 100); } return display; }; // Setup I2C I2C2.setup({ scl: B10, sda: B11 }); var matrix = exports.connect(I2C2, 0x70, function(){ var counter = 1; setInterval(function(){ matrix.clear(); matrix.setRotation(counter - 1); matrix.setColor(counter); matrix.fillRect(0,0,7,1); matrix.fillRect(0,3,7,4); matrix.fillRect(0,6,7,7); matrix.fillRect(0,0,1,7); matrix.write(); counter = (counter == 3) ? 1 : counter + 1; }, 2000); });
The problem is, I keep getting errors when I try to add additional methods to my
display
object. If I extend theGraphics
class viaprototype
then everything works, however I don't won't my methods available to all Graphics objects, just ones returned from my module. Anyone know what I'm doing wrong (I'm sure I saw @Gordon do this kind of thing in the 123-LED demo video).Matt
-
Typical, write a post and find the answer :) Turns out I needed some other methods to be called first to setup the device. The following works:
// Variables var address = 0x70; var displaybuffer = new Uint16Array(8); var LED_OFF = 0; var LED_RED = 1; var LED_YELLOW = 2; var LED_GREEN = 3; var HT16K33_BLINK_CMD = 0x80; var HT16K33_BLINK_DISPLAYON = 0x01; var HT16K33_BLINK_OFF = 0; var HT16K33_BLINK_2HZ = 1; var HT16K33_BLINK_HALFHZ = 3; // Setup I2C I2C1.setup({ scl: B6, sda: B7 }); function clearDisplay(){ for (var i=0; i<8; i++) { displaybuffer[i] = 0; } } function setBrightness(lvl) { if (lvl > 15) { lvl = 15; } I2C1.writeTo(address, 0xE0 | lvl); } function blinkRate(b) { if (b > 3) b = 0; // turn off if not sure I2C1.writeTo(address, HT16K33_BLINK_CMD | HT16K33_BLINK_DISPLAYON | (b << 1)); } function drawPixel(x,y,color){ if(x < 4){ x += 4; } else { x -= 4; } if(y < 4){ y += 4; } else { y -= 4; } if (color == LED_GREEN) { displaybuffer[y] |= 1 << x; } else if (color == LED_RED) { displaybuffer[y] |= 1 << (x+8); } else if (color == LED_YELLOW) { displaybuffer[y] |= (1 << (x+8)) | (1 << x); } else if (color == LED_OFF) { displaybuffer[y] &= ~(1 << x) & ~(1 << (x+8)); } } function writeDisplay(){ var tmp = new Uint8Array(17); tmp[0] = 0x00; for (var i=0; i<16; i+=2) { tmp[i+1] = displaybuffer[i/2] & 0xFF; tmp[i+2] = displaybuffer[i/2] >> 8; } console.log(tmp); I2C1.writeTo(address, tmp); } // Turn on oscillator I2C1.writeTo(address, 0x21); // Set blink rate blinkRate(HT16K33_BLINK_OFF); // Set to full brightness setBrightness(15); // Draw pixels drawPixel(0,0,LED_GREEN); drawPixel(1,1,LED_RED); drawPixel(2,2,LED_YELLOW); // Update display writeDisplay();
-
Hi Guys,
I've been spending the last couple of hours trying to convert some Adafruit code to work with the Espruino, but am struggling to get it to work. Can anyone offer any advice?
The code from adafruit is as follows (just the methods I'm bothered about):
void Adafruit_BicolorMatrix::drawPixel(int16_t x, int16_t y, uint16_t color) { if ((y < 0) || (y >= 8)) return; if ((x < 0) || (x >= 8)) return; switch (getRotation()) { case 1: swap(x, y); x = 8 - x - 1; break; case 2: x = 8 - x - 1; y = 8 - y - 1; break; case 3: swap(x, y); y = 8 - y - 1; break; } if(x < 4){ x += 4; } else { x -= 4; } if(y < 4){ y += 4; } else { y -= 4; } if (color == LED_GREEN) { displaybuffer[y] |= 1 << x; } else if (color == LED_RED) { displaybuffer[y] |= 1 << (x+8); } else if (color == LED_YELLOW) { displaybuffer[y] |= (1 << (x+8)) | (1 << x); } else if (color == LED_OFF) { displaybuffer[y] &= ~(1 << x) & ~(1 << (x+8)); } } void Adafruit_LEDBackpack::writeDisplay(void) { Wire.beginTransmission(i2c_addr); Wire.write((uint8_t)0x00); // start at address $00 for (uint8_t i=0; i<8; i++) { Wire.write((displaybuffer[i]) & 0xFF); Wire.write((displaybuffer[i]) >> 8); } Wire.endTransmission(); }
And I have currently got the following javascript for the Espruino:
// Variables var address = 0x70; var displaybuffer = new Uint16Array(8); var LED_OFF = 0; var LED_RED = 1; var LED_YELLOW = 2; var LED_GREEN = 3; // Setup I2C I2C1.setup({ scl: B6, sda: B7 }); function clearDisplay(){ for (var i=0; i<8; i++) { displaybuffer[i] = 0; } } function drawPixel(x,y,color){ // Not bothered about rotation yet if(x < 4){ x += 4; } else { x -= 4; } if(y < 4){ y += 4; } else { y -= 4; } if (color == LED_GREEN) { displaybuffer[y] |= 1 << x; } else if (color == LED_RED) { displaybuffer[y] |= 1 << (x+8); } else if (color == LED_YELLOW) { displaybuffer[y] |= (1 << (x+8)) | (1 << x); } else if (color == LED_OFF) { displaybuffer[y] &= ~(1 << x) & ~(1 << (x+8)); } } function writeDisplay(){ var tmp = new Uint8Array(17); tmp[0] = 0x00; for (var i=0; i<16; i+=2) { tmp[i+1] = displaybuffer[i] & 0xFF; tmp[i+2] = displaybuffer[i] >> 8; } console.log(tmp); I2C1.writeTo(address, tmp); } drawPixel(0,0,LED_GREEN); drawPixel(1,1,LED_RED); drawPixel(2,2,LED_YELLOW); writeDisplay();
The problem is, I just don't get any lights lighting up. Have I converted the code incorrectly? Or am I miss-understanding how you work with I2C on the Espruino?
Matt
-
Hey @Gordon, I thought that's what you meant, unfortunately it still struggles a bit :( It keeps a constant steady colour, but they you just get the odd moment where it just struggles and you get flickering (like an old tv in and out of reception).
I've got some other LED matrix screens on order so I'll see how they perform and maybe have a go at creating my own board. If you do have any other suggestions though, I'd be glad to hear them (you've been really helpful already).
Matt
-
-
-
cheers @gordon, that works a treat.
Just playing with some simple logic (capturing button presses) at the moment, and currently hitting what I feared, that the additional logic affects the display loop and so causes stuttering / flickering as it has stuff to compute.
Not sure what can be done here though as ultimately I guess it's coming down to computations and without uber optimizing everything, the fact we have to refresh the screen the way we do means this is always going to be the case isn't it?
Matt
-
Hi @Gordon, I'm playing with the graphics library now. If I want to keep two graphics objects (one for the user to update, and internal one that is being rendered to the screen currently) is the best way to copy one to the other by iterating over the
.buffer
and copying the values over? -
Thanks @Gordon. I'll give those a try too. I've actually just tried it running off battery (was previously USB) and that seems to stabilize a bit more of the flickering, so I think I'll just go with these and see what happens when I start adding game logic :)
Thanks for all the tips. It's good to know how you can optimize things :)
Matt
-
Hmm, playing around with
.set();
and passing the LAT into send doesn't seem to be making much of a difference. And I've already moved all the logic from updateRow into the setInterval function so no more gain to be had there :)Out of interest, what is that's the main issue here? the length of time it take to convert the JS into runtime + execution? or something else?
Wouldn't unraveling updateRow just be the same though? You can only update one row at a time with the bitshifter + led driver compo right?
Also, if I want to make the matrix run off 5v, where would the pullup resistor need go?
Matt
-
Hey @Gordon, thanks for the suggestions (kinda feels like we are mechanics tweaking the max horse power out of an engine :)), I'll give them a go later this evening.
RE the graphics lib, it's on my todo list, I was just porting their code over as close to original right now to get something working, but will defo look at using these once I'm happy with how it's running.
Matt
-
-
Cool, thanks @Gordon. I've inlined the two methods, and got rid of updateRow and moved all the logic within the setInterval function itself and it's a lot better. I think it could do with being a tiny bit faster (it does look solid now, but it's kinda like the old days of low res monitors, we you move your eyes, it looks a bit stuttery) but I'd say it's workable now at least.
I wondered the same about the MAX7129, but I'm guessing it was more about the looks than the functionality. It's fun to have a limitation though and try to work round it :)
Matt
-
So, this is much faster and I actually get a solid image being drawn now, but will need to try a few more speed tweaks as it's just not quite fast enough (like a monitor in too low a refresh rate, you see slight flickering in the corner of your eye).
Other than inlining the methods in update row, is there anything else you can suggest? (currently got setInterval at 0.05)
PS The image rendering out now seems to be backwards (compared to what I had before) is this something to do with config? or should I just compensate in my code?
Matt
-
Ok, I'm confused :)
I must confess, this stuff doesn't come naturally to me, but if you look at my drawPixel method, and how it handles colours, this is how I currently understand this, see attached (correct me if I'm wrong).
So I believe it builds up a matrix where for every Y position, it stores a 16byte value, the bits in that value dictate whether an LED should be on or off. I think the first 8 bytes are for green, and the second 8 are for red, or maybe the other way, I can't tell :) if they are both on at the same time thought, you get yellow. Now when I'm talking segments getting mixed up, see the black lines on the picture, each 4x4 square renders as it should, but each black square is in the wrong location, so the top left green one, is in the bottom right green one and vica-versa for the other opposite corner / colours.
So, is that how you understood me? and do your examples hold true for this? and also, looking at my code, is my assumption of how this work correct? :)
Cheers
Matt