Created
August 9, 2014 20:16
-
-
Save ozzieg/372449b1d900ed31c81d to your computer and use it in GitHub Desktop.
Electric Imp Device code utilizing the Firmata protocol based on Firmata implementation in Javascript from http://jgautier.github.com/firmata/. Utilizes the UART to talk to an Arduino.
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
server.log("Device started, impee_id " + hardware.getimpeeid() + " and mac = " + imp.getmacaddress() ); | |
//------------------------------------------------------------------------------------------------------------------------------ | |
// Uart57 for TX/RX | |
SERIAL <- hardware.uart57; | |
// FIRMATA CONSTANTS | |
const PIN_MODE = 0xF4; | |
const REPORT_DIGITAL = 0xD0; | |
const REPORT_ANALOG = 0xC0; | |
const DIGITAL_MESSAGE = 0x90; | |
const START_SYSEX = 0xF0; | |
const END_SYSEX = 0xF7; | |
const QUERY_FIRMWARE = 0x79; | |
const REPORT_VERSION = 0xF9; | |
const ANALOG_MESSAGE = 0xE0; | |
const EXTENDED_ANALOG = 0x6F; | |
const CAPABILITY_QUERY = 0x6B; | |
const CAPABILITY_RESPONSE = 0x6C; | |
const PIN_STATE_QUERY = 0x6D; | |
const PIN_STATE_RESPONSE = 0x6E; | |
const ANALOG_MAPPING_QUERY = 0x69; | |
const ANALOG_MAPPING_RESPONSE = 0x6A; | |
const I2C_REQUEST = 0x76; | |
const I2C_REPLY = 0x77; | |
const I2C_CONFIG = 0x78; | |
const STRING_DATA = 0x71; | |
const SYSTEM_RESET = 0xFF; | |
const PULSE_OUT = 0x73; | |
const PULSE_IN = 0x74; | |
const SAMPLING_INTERVAL = 0x7A; | |
const STEPPER = 0x72; | |
const ONEWIRE_DATA = 0x73; | |
MIDI_RESPONSE <- {}; | |
SYSEX_RESPONSE <- {}; | |
MIDI_RESPONSE[REPORT_VERSION] <- function(board) { | |
board.version.major = board.currentBuffer[1]; | |
board.version.minor = board.currentBuffer[2]; | |
board.emit("report-version"); | |
}; | |
MIDI_RESPONSE[ANALOG_MESSAGE] <- function(board) { | |
local value = board.currentBuffer[1] | (board.currentBuffer[2] << 7); | |
local port = board.currentBuffer[0] & 0x0F; | |
if (board.pins[board.analogPins[port]]) { | |
board.pins[board.analogPins[port]].value = value; | |
} | |
board.emit("analog-read-" + port, value); | |
board.emit("analog-read", { | |
pin= port, | |
value= value | |
}); | |
}; | |
MIDI_RESPONSE[DIGITAL_MESSAGE] <- function (board) { | |
local port = (board.currentBuffer[0] & 0x0F); | |
local portValue = board.currentBuffer[1] | (board.currentBuffer[2] << 7); | |
server.log("digital message: port: " + port + " value: " + portValue); | |
for (local i = 0; i < 8; i++) { | |
local pinNumber = 8 * port + i; | |
local pin = board.pins[pinNumber]; | |
if (pin && (pin.mode == board.MODES.INPUT)) { | |
pin.value = (portValue >> (i & 0x07)) & 0x01; | |
this.MODES.emit("digital-read-" + pinNumber, pin.value); | |
board.emit("digital-read", { | |
pin= pinNumber, | |
value= pin.value | |
}); | |
} | |
} | |
}; | |
SYSEX_RESPONSE[CAPABILITY_RESPONSE] <- function(board) { | |
server.log("capability response received."); | |
}; | |
SYSEX_RESPONSE[ANALOG_MAPPING_RESPONSE] <- function(board) { | |
server.log("analog mapping response received."); | |
local pin = 0; | |
local currentValue; | |
for (local i = 2; i < board.currentBuffer.length - 1; i++) { | |
currentValue = board.currentBuffer[i]; | |
board.pins[pin].analogChannel = currentValue; | |
if (currentValue != 127) { | |
board.analogPins.push(pin); | |
} | |
pin++; | |
} | |
board.emit("analog-mapping-query"); | |
}; | |
SYSEX_RESPONSE[PIN_STATE_RESPONSE] <- function(board) { | |
server.log("analog mapping response received."); | |
}; | |
SYSEX_RESPONSE[STRING_DATA] <- function(board) { | |
local str = format("%s", board.currentBuffer.slice(2, -1)); | |
board.emit("string", str); | |
server.log("debug msg: " + str); | |
}; | |
SYSEX_RESPONSE[QUERY_FIRMWARE] <- function (board) { | |
local firmwareBuf; | |
board.firmware.version.major = board.currentBuffer[2]; | |
board.firmware.version.minor = board.currentBuffer[3]; | |
for (local i = 4, length = board.currentBuffer.len() - 2; i < length; i += 2) { | |
firmwareBuf += format("%c", ((board.currentBuffer[i] & 0x7F) | ((board.currentBuffer[i + 1] & 0x7F) << 7))); | |
} | |
board.firmware.name = firmwareBuf; | |
board.emit("query-firmware"); | |
}; | |
board <- { | |
currentBuffer = [], | |
MODES = { | |
INPUT= 0x00, | |
OUTPUT= 0x01, | |
ANALOG= 0x02, | |
PWM= 0x03, | |
SERVO= 0x04, | |
SHIFT= 0x05, | |
I2C= 0x06, | |
ONEWIRE= 0x07, | |
STEPPER= 0x08, | |
IGNORE= 0x7F, | |
UNKOWN= 0x10 | |
}, | |
pins = [ | |
{ report = 0, value = 0, mode = 0 }, | |
{ report = 0, value = 0, mode = 0 }, | |
{ report = 0, value = 0, mode = 0 }, | |
{ report = 0, value = 0, mode = 0 }, | |
{ report = 0, value = 0, mode = 0 }, | |
{ report = 0, value = 0, mode = 0 }, | |
{ report = 0, value = 0, mode = 0 }, | |
{ report = 0, value = 0, mode = 0 }, | |
{ report = 0, value = 0, mode = 0 }, | |
{ report = 0, value = 0, mode = 0 }, | |
{ report = 0, value = 0, mode = 0 }, | |
{ report = 0, value = 0, mode = 0 }, | |
{ report = 0, value = 0, mode = 0 }, | |
{ report = 0, value = 0, mode = 0 }, | |
{ report = 0, value = 0, mode = 0, analogChannel = 0 }, | |
{ report = 0, value = 0, mode = 0, analogChannel = 0 }, | |
{ report = 0, value = 0, mode = 0, analogChannel = 0 }, | |
{ report = 0, value = 0, mode = 0, analogChannel = 0 }, | |
{ report = 0, value = 0, mode = 0, analogChannel = 0 }, | |
{ report = 0, value = 0, mode = 0, analogChannel = 0 }, | |
], | |
analogPins = [ 14, 15, 16, 17, 18, 19 ], | |
listeners = {}, | |
sp = {}, | |
version = { major = 0, minor = 0 }, | |
firmware = { name = "", version = { major = 0, minor = 0 }}, | |
function emit(event, data = null) { | |
//server.log("Event: " + event); | |
//server.log("Data: " + data); | |
if( event in listeners ) { | |
if( data != null ) { | |
listeners[event](board, data); | |
} else { | |
listeners[event](board); | |
} | |
} | |
}, | |
function pinMode(pin, mode) { | |
board.pins[pin].mode = mode; | |
board.sp.write(format("%c%c%c", PIN_MODE, pin, mode)); | |
}, | |
function digitalWrite(pin, value) { | |
local port = math.abs(math.floor(pin / 8)); | |
local portValue = 0; | |
board.pins[pin].value = value; | |
for (local i = 0; i < 8; i++) { | |
if (board.pins[8 * port + i].value) { | |
portValue = portValue | (1 << i); | |
} | |
} | |
board.sp.write(format("%c%c%c", DIGITAL_MESSAGE | port, portValue & 0x7F, (portValue >> 7) & 0x7F)); | |
}, | |
function analogRead(pin, callback) { | |
listeners["analog-read-" + pin] <- callback; | |
}, | |
function digitalRead(pin, callback) { | |
listeners["digital-read-" + pin] <- callback; | |
}, | |
function reportAnalogPin(pin, value) { | |
if(value == 0 || value == 1) { | |
board.pins[board.analogPins[pin]].report = value; | |
board.sp.write(format("%c%c", REPORT_ANALOG | pin, value)); | |
} | |
}, | |
function reportDigitalPin(pin, value) { | |
if(value == 0 || value == 1) { | |
board.pins[pin].report = value; | |
board.sp.write(format("%c%c", REPORT_DIGITAL | pin, value)); | |
} | |
}, | |
function reset() { | |
board.sp.write(format("%c", SYSTEM_RESET)); | |
}, | |
function queryCapabilities(callback) { | |
board.sp.write(format("%c%c%c", START_SYSEX, CAPABILITY_QUERY, END_SYSEX)); | |
}, | |
function queryAnalogMapping(callback) { | |
listeners["analog-mapping-query"] <- callback; | |
board.sp.write(format("%c%c%c", START_SYSEX, ANALOG_MAPPING_QUERY, END_SYSEX)); | |
}, | |
function queryFirmware(callback) { | |
listeners["query-firmware"] <- callback; | |
board.sp.write(format("%c%c%c", START_SYSEX, QUERY_FIRMWARE, END_SYSEX)); | |
}, | |
function queryPinState(pin, callback) { | |
board.sp.write(format("%c%c%c", START_SYSEX, PIN_STATE_QUERY, pin, END_SYSEX)); | |
}, | |
function reportVersion(callback) { | |
listeners["report-version"] <- callback; | |
board.sp.write(format("%c", REPORT_VERSION)); | |
}, | |
function setSamplingInterval(interval) { | |
local safeint = interval < 10 ? 10 : (interval > 65535 ? 65535 : interval); // constrained | |
board.sp.write(format("%c%c%c%c%c", START_SYSEX, SAMPLING_INTERVAL, (safeint & 0xFF),((safeint >> 8) & 0xFF), END_SYSEX)); | |
}, | |
function serialData() { | |
//server.log("received serial data"); | |
local ch = board.sp.read(); | |
local str = ""; | |
while( ch != -1 ) { | |
board.currentBuffer.push(ch); | |
str += format("%c", ch); | |
ch = board.sp.read(); | |
} | |
//server.log(str); | |
local cmd; | |
if( board.currentBuffer.len() > 0 ) { | |
if( board.currentBuffer[0] == START_SYSEX && | |
SYSEX_RESPONSE[board.currentBuffer[1]] && | |
board.currentBuffer[board.currentBuffer.len() - 1] == END_SYSEX ) { | |
SYSEX_RESPONSE[board.currentBuffer[1]](board); | |
board.currentBuffer.clear(); | |
} | |
if( board.currentBuffer.len() == 3 && board.currentBuffer[0] != START_SYSEX ) { | |
cmd = board.currentBuffer[0] < 240 ? board.currentBuffer[0] & 0xF0 : board.currentBuffer[0]; | |
if( MIDI_RESPONSE[cmd] ) { | |
MIDI_RESPONSE[cmd](board); | |
board.currentBuffer.clear(); | |
} else { | |
board.currentBuffer.clear(); | |
} | |
} | |
} | |
}, | |
function init() { | |
board.reportVersion(function(board) { | |
server.log("board version: " + board.version.major + "." + board.version.minor); | |
board.queryFirmware(function(board) { | |
server.log("firmware: " + board.firmware.name); | |
}); | |
}); | |
} | |
}; | |
//------------------------------------------------------------------------------------------------------------------------------ | |
board.sp = SERIAL; | |
SERIAL.configure(57600, 8, PARITY_NONE, 1, NO_CTSRTS, board.serialData); | |
board.init(); | |
//Example Usage: | |
board.setSamplingInterval(100); | |
board.reportAnalogPin(0, 1); | |
board.pinMode(6, board.MODES.OUTPUT); | |
board.pinMode(7, board.MODES.OUTPUT); | |
board.digitalWrite(6, 0); | |
board.digitalWrite(7. 0); | |
analogValues <- []; | |
analogValueIndex <- 0; | |
analogReady <- false; | |
board.analogRead(0, function(board, data) { | |
//server.log("value: " + data); | |
//save off last 30 values | |
if( analogValues.len() < 30 ) { | |
analogValues.push(data); //build up the array | |
} else { | |
analogReady = true; | |
analogValues[analogValueIndex] = data; | |
analogValueIndex++; | |
if( analogValueIndex == 30 ) { | |
analogValueIndex = 0; | |
} | |
} | |
}); |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment