Seeking some advice on how best to convert this Arduino library.
I wondered whether Electric Imp could offer up a more elegant GPIO digitalWrite solution than what this library uses, via the Imp pin output configure options.
Not really, no - this appears to be a custom protocol they’ve come up with themselves, talking to a microcontroller on the board. eg they send data on both edges of the clock, do a weird data only thing to latch, etc.
They could have just done i2c given that they have two wires… sigh.
Working through the library but could not get it to work… any clues
`
class Grove_LED_Bar {
// Avoid name conflict
static GLB_CMDMODE = 0x00; // Work on 8-bit mode
static GLB_ON = 0xff; // 8-bit 1 data
static GLB_OFF = 0x00; // 8-bit 0 data
static version = [1,0,0];
// Class properties; those defined in the Constructor must be null
__pinClock = 0; // Clock pin
__pinData = 0; // Data pin
__greenToRed = 0; // Orientation (0 = red to green, 1 = green to red)
__state = null; // Led state, brightness for each LED
constructor(pinClock = 0, pinData = 0, greenToRed = 0) {
__pinClock = pinClock;
__pinData = pinData;
__greenToRed = greenToRed;
__state = [0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00];
__pinClock.configure(DIGITAL_OUT,1);
__pinData.configure(DIGITAL_OUT,1);
}
// Send the latch command
function latchData() {
__pinData.write(0);
imp.sleep(0.00001);
for (local i = 0; i < 4; i++) {
__pinData.write(1);
__pinData.write(0);
}
}
// Send 16 bits of data
function sendData(data) {
for (local i = 0; i < 16; i++) {
local state = (data & 0x8000) ? 1 : 0;
__pinData.write (state);
state = __pinClock.read() ? 1 : 0;
__pinClock.write(state);
data = data << 1;
}
}
// Change the orientation
// Green to red, or red to green
function setGreenToRed(greenToRed) {
__greenToRed = greenToRed;
setData(__state);
}
// Set level (0-10)
// Level 0 means all leds off
// Level 10 means all leds on
// Level 4.5 means 4 LEDs on and the 5th LED's half on
function setLevel(level = 0.0) {
local minLevel = (10.0 < level) ? 10.0 : level;
level = (0.0 > minLevel) ? 0.0 : minLevel;
level *= 8; // there are 8 (noticable) levels of brightness on each segment
// Place number of 'level' of 1-bits on __state
for (local i = 0; i < 10; i++) {
__state[i] = (level > 8) ? ~0 : (level > 0) ? ~(~0 << (level).tointeger()) : 0;
level -= 8;
}
setData(__state);
}
// Set a single led
// led (1-10)
// brightness (0-1)
function setLed(led = 0, brightness = 0.0) {
local minLed = (10 < led) ? 10 : led;
led = (1 > minLed) ? 1 : minLed;
local minBright = (1.0 < brightness) ? 1.0 : brightness;
brightness = (0.0 > minBright) ? 0.0 : minBright;
// Zero based index 0-9 for bitwise operations
led--;
// 8 (noticable) levels of brightness
// 00000000 darkest
// 00000011 brighter
// ........
// 11111111 brightest
__state[led] = ~(~0 << (brightness*8).tointeger());
setData(__state);
}
// Toggle a single led
// led (1-10)
function toggleLed(led = 0) {
local minLed = (10 < led) ? 10 : led;
led = (1 > minLed) ? 1: minLed;
// Zero based index 0-9 for bitwise operations
led--;
__state[led] = __state[led] ? 0 : ~0;
setData(__state);
}
// each element in the state will hold the brightness level
// 00000000 darkest
// 00000011 brighter
// ........
// 11111111 brightest
function setData(__state) {
sendData(GLB_CMDMODE);
for (local i = 0; i < 10; i++) {
if (__greenToRed) {
// Go backward on __state
sendData(__state[10-i-1]);
}
else {
// Go forward on __state
sendData(__state[i]);
}
}
// Two extra empty bits for padding the command to the correct length
sendData(0x00);
sendData(0x00);
latchData();
}
function setBits(bits = 0) {
for (local i = 0; i < 10; i++) {
if ((bits % 2) == 1) __state[i] = 0xFF;
else __state[i] = 0x00;
bits /= 2;
}
setData(__state);
}
// Return the current bits
function getBits() {
local __bits = 0x00;
for (local i = 0; i < 10; i++) {
if (__state[i] != 0x0) __bits = __bits || (0x1 << i);
}
return __bits;
}
Having reviewed what I quickly stuck together, I see the main problem lies in my total lack of use of blobs (and in the use of blob.writen methods) as well as a few errors here and there.
I’m also hoping that as this is not a huge coding job it could quickly morph into a standard imp library (@smittytone is this probable/possible).
Turns out the code works, after I corrected one small error.
state = __pinClock.read() ? 1 : 0; should read state = __pinClock.read() ? 0 : 1;
Tested class with a simple script:
first assign LEDBar <- Grove_LED_Bar(yourLEDclockPin, yourLEDdataPin, true);
Then ran this test code // Start as green to red // Walk through the 10 levels LEDBar.setGreenToRed(1); for (local i = 0; i <= 10; i++) { LEDBar.setLevel(i); imp.sleep(0.2); } LEDBar.setLevel(0); // Now start as red to green & repeat LEDBar.setGreenToRed(0); imp.sleep(0.2); for (local i = 0; i <= 10; i++) { LEDBar.setLevel(i); imp.sleep(0.2); } LEDBar.setLevel(0);