Skip to content

Commit

Permalink
finished refactoring and tested
Browse files Browse the repository at this point in the history
  • Loading branch information
jgautier committed Sep 5, 2011
1 parent 5e439fe commit 8b7b1e1
Show file tree
Hide file tree
Showing 5 changed files with 205 additions and 200 deletions.
2 changes: 2 additions & 0 deletions .gitignore
@@ -0,0 +1,2 @@
node_modules
.DS_Store
87 changes: 52 additions & 35 deletions lib/firmata.js
Expand Up @@ -14,22 +14,40 @@ var SerialPort = require('serialport').SerialPort,
* constants
*/

const PIN_MODE = 0xF4, REPORT_DIGITAL = 0xD0, REPORT_ANALOG = 0xC0, DIGITAL_MESSAGE = 0x90, START_SYSEX = 0xF0, END_SYSEX = 0xF7, QUERY_FIRMWARE = 0x79, REPORT_VERSION = 0xF9, ANALOG_MESSAGE = 0xE0, CAPABILITY_QUERY = 0x6B, CAPABILITY_RESPONSE = 0x6C, PIN_STATE_QUERY = 0x6D, PIN_STATE_RESPONSE = 0x6E, ANALOG_MAPPING_QUERY = 0x69, ANALOG_MAPPING_RESPONSE = 0x6A, I2C_REQUEST = 0x76, I2C_REPLY = 0x77, I2C_CONFIG = 0x78, STRING_DATA = 0x71

/**
* MIDI_RESPONSE contains functions to be called when we receive a MIDI message from the arduino.
* used as a switch object as seen here http://james.padolsey.com/javascript/how-to-avoid-switch-case-syndrome/
*/

var MIDI_RESPONSE={};
var PIN_MODE = 0xF4,
REPORT_DIGITAL = 0xD0,
REPORT_ANALOG = 0xC0,
DIGITAL_MESSAGE = 0x90,
START_SYSEX = 0xF0,
END_SYSEX = 0xF7,
QUERY_FIRMWARE = 0x79,
REPORT_VERSION = 0xF9,
ANALOG_MESSAGE = 0xE0,
CAPABILITY_QUERY = 0x6B,
CAPABILITY_RESPONSE = 0x6C,
PIN_STATE_QUERY = 0x6D,
PIN_STATE_RESPONSE = 0x6E,
ANALOG_MAPPING_QUERY = 0x69,
ANALOG_MAPPING_RESPONSE = 0x6A,
I2C_REQUEST = 0x76,
I2C_REPLY = 0x77,
I2C_CONFIG = 0x78,
STRING_DATA = 0x71

/**
* MIDI_RESPONSE contains functions to be called when we receive a MIDI message from the arduino.
* used as a switch object as seen here http://james.padolsey.com/javascript/how-to-avoid-switch-case-syndrome/
*/

var MIDI_RESPONSE = {};

/**
* Handles a REPORT_VERSION response and emits the reportversion event. Also turns on all pins to start reporting
* @private
* @param {Board} board the current arduino board we are working with.
*/

MIDI_RESPONSE[REPORT_VERSION]=function(board){
MIDI_RESPONSE[REPORT_VERSION] = function(board) {
board.version.major = board.currentBuffer[1];
board.version.minor = board.currentBuffer[2];
board.emit('reportversion');
Expand All @@ -44,8 +62,8 @@ MIDI_RESPONSE[REPORT_VERSION]=function(board){
* @private
* @param {Board} board the current arduino board we are working with.
*/
MIDI_RESPONSE[ANALOG_MESSAGE]=function(board){

MIDI_RESPONSE[ANALOG_MESSAGE] = function(board) {
var value = board.currentBuffer[1] | (board.currentBuffer[2] << 7);
var port = board.currentBuffer[0] & 0x0F;
if (board.pins[board.analogPins[port]]) {
Expand All @@ -63,14 +81,14 @@ MIDI_RESPONSE[ANALOG_MESSAGE]=function(board){
* @private
* @param {Board} board the current arduino board we are working with.
*/
MIDI_RESPONSE[DIGITAL_MESSAGE]=function(board){

MIDI_RESPONSE[DIGITAL_MESSAGE] = function(board) {
var port = (board.currentBuffer[0] & 0x0F);
var portValue = board.currentBuffer[1] | (board.currentBuffer[2] << 7);
for (var i = 0; i < 8; i++) {
var pinNumber = 8 * port + i;
var pin = board.pins[pinNumber];
if (pin.mode == board.MODES.INPUT) {
if (pin && (pin.mode == board.MODES.INPUT)) {
pin.value = (portValue >> (i & 0x07)) & 0x01;
board.emit('digital-read-' + pinNumber, pin.value);
board.emit('digital-read', {
Expand All @@ -85,7 +103,7 @@ MIDI_RESPONSE[DIGITAL_MESSAGE]=function(board){
* SYSEX_RESPONSE contains functions to be called when we receive a SYSEX message from the arduino.
* used as a switch object as seen here http://james.padolsey.com/javascript/how-to-avoid-switch-case-syndrome/
*/

var SYSEX_RESPONSE = {};

/**
Expand Down Expand Up @@ -131,7 +149,7 @@ SYSEX_RESPONSE[CAPABILITY_RESPONSE] = function(board) {
n = 0;
continue;
}
if (n == 0) {
if (n === 0) {
supportedModes |= (1 << board.currentBuffer[i]);
}
n ^= 1;
Expand All @@ -145,12 +163,12 @@ SYSEX_RESPONSE[CAPABILITY_RESPONSE] = function(board) {
* @param {Board} board the current arduino board we are working with.
*/

SYSEX_RESPONSE[PIN_STATE] = function(board) {
SYSEX_RESPONSE[PIN_STATE_RESPONSE] = function(board) {
var pin = board.currentBuffer[2];
board.pins[pin].mode = board.currentBuffer[3];
board.pins[pin].value = board.currentBuffer[4];
if (board.currentBuffer.length > 6) {
board.pins[pin].value |= (board.currentBuffer[5] << 7)
board.pins[pin].value |= (board.currentBuffer[5] << 7);
}
if (board.currentBuffer.length > 7) {
board.pins[pin].value |= (board.currentBuffer[6] << 14);
Expand Down Expand Up @@ -185,7 +203,7 @@ SYSEX_RESPONSE[ANALOG_MAPPING_RESPONSE] = function(board) {
* @param {Board} board the current arduino board we are working with.
*/

SYSEX_RESPONSE[I2C_REPLY] = function(board){
SYSEX_RESPONSE[I2C_REPLY] = function(board) {
var replyBuffer = [];
var slaveAddress = (board.currentBuffer[2] & 0x7F) | ((board.currentBuffer[3] & 0x7F) << 7);
var register = (board.currentBuffer[4] & 0x7F) | ((board.currentBuffer[5] & 0x7F) << 7);
Expand All @@ -201,8 +219,8 @@ SYSEX_RESPONSE[I2C_REPLY] = function(board){
* @param {Board} board the current arduino board we are working with.
*/

SYSEX_RESPONSE[STRING_DATA] = function(board){
console.log(new Buffer(board.currentBuffer.slice(1, -1)).toString('utf8'));
SYSEX_RESPONSE[STRING_DATA] = function(board) {
board.emit('string',new Buffer(board.currentBuffer.slice(1, -1)).toString('utf8'));
};

/**
Expand All @@ -221,7 +239,6 @@ SYSEX_RESPONSE[STRING_DATA] = function(board){
* @property currentBuffer An array holding the current bytes received from the arduino.
* @property {SerialPort} sp The serial port object used to communicate with the arduino.
*/

var Board = function(port, callback) {
events.EventEmitter.call(this);
var board = this;
Expand All @@ -237,7 +254,7 @@ var Board = function(port, callback) {
READ: 1,
CONTINUOUS_READ: 2,
STOP_READING: 3
}
};
this.HIGH = 1;
this.LOW = 0;
this.pins = [];
Expand All @@ -251,26 +268,27 @@ var Board = function(port, callback) {
});
this.sp.on('data', function(data) {
//we dont want to push 0 as the first byte on our buffer
if ((board.currentBuffer.length == 0 && data[0] != 0 || board.currentBuffer.length)) {
if ((board.currentBuffer.length === 0 && data[0] !== 0 || board.currentBuffer.length)) {
board.currentBuffer.push(data[0]);
}
//a MIDI or SYSEX command function we are going to call
var cmdFunc;
var cmd;
//if the first byte is START_SYSEX and last byte is END_SYSEX we have a SYSEX command.
if (board.currentBuffer[0] == START_SYSEX && board.currentBuffer[board.currentBuffer.length - 1] == END_SYSEX) {
cmdFunc = SYSEX_RESPONSE[board.currentBuffer[1]];
//if the first byte is not a START_SYSEX and we have 3 bytes we might have a MIDI Command
}else if(board.currentBuffer.length == 3 && board.currentBuffer[0] != START_SYSEX){
//if the first byte is not a START_SYSEX and we have 3 bytes we might have a MIDI Command
} else if (board.currentBuffer.length == 3 && board.currentBuffer[0] != START_SYSEX) {
//commands under 0xF0 we have a multi byte command
if(board.currentBuffer[0] < 240){
var cmd = board.currentBuffer[0] & 0xF0;
}else{
var cmd = board.currentBuffer[0];
if (board.currentBuffer[0] < 240) {
cmd = board.currentBuffer[0] & 0xF0;
} else {
cmd = board.currentBuffer[0];
}
cmdFunc = MIDI_RESPONSE[cmd];
}
//if a function is found we will call it
if(cmdFunc){
if (cmdFunc) {
//call function with board object
cmdFunc(board);
//reset currentBuffer so we can receive the next command
Expand All @@ -283,7 +301,7 @@ var Board = function(port, callback) {
this.reportVersion(function() {
board.queryCapabilities(function() {
board.queryAnalogMapping(function() {
var pinsToQuery = []
var pinsToQuery = [];
for (i = 0; i < board.pins.length; i++) {
pinsToQuery[i] = i;
}
Expand All @@ -292,15 +310,14 @@ var Board = function(port, callback) {
board.queryPinState(pinsToQuery[i], function() {
callback();
});
}
else {
} else {
board.queryPinState(pinsToQuery[i], function() {});
}
}
});
});
});
}
};
sys.inherits(Board, events.EventEmitter);

/**
Expand Down
43 changes: 18 additions & 25 deletions package.json
@@ -1,25 +1,18 @@
{ "name" : "firmata"
, "description" : "A library to control an arduino running firmata"
, "version" : "0.1.3"
, "author" : "Julian Gautier"
, "homepage" : "http://www.github.com/jgautier/firmata"
, "repository" :
{
"type" : "git"
,"url" : "git://github.com/jgautier/firmata.git"
}
, "main" : "lib/firmata"
, "bin" :
{
"firmata" : "./repl.js"
}
, "dependencies" :
{
"serialport" : ">=0.2.0"
}
, "engines" :
{
"node" : "v0.5.0-pre"
}

}
{
"name": "firmata",
"description": "A library to control an arduino running firmata",
"version": "0.1.3",
"author": "Julian Gautier",
"homepage": "http://www.github.com/jgautier/firmata",
"repository": {
"type": "git",
"url": "git://github.com/jgautier/firmata.git"
},
"main": "lib/firmata",
"bin": {
"firmata": "./repl.js"
},
"dependencies": {
"serialport": ">=0.2.0"
}
}
15 changes: 8 additions & 7 deletions repl.js
@@ -1,13 +1,14 @@
#!/usr/bin/env node
var firmata=require('./lib/firmata.js')
,repl = require('repl');

var firmata = require('./lib/firmata.js'),
repl = require('repl');
console.log('Enter USB Port and press enter:');
process.stdin.resume();
process.stdin.setEncoding('utf8');
process.stdin.once('data',function(chunk){
var port = chunk.replace('\n','');
var board = new firmata.Board(port,function(){
console.log('Successfully Connected to ')+port;
repl.start('firmata>').context.board=board;
process.stdin.once('data', function(chunk) {
var port = chunk.replace('\n', '');
var board = new firmata.Board(port, function() {
console.log('Successfully Connected to ' + port);
repl.start('firmata>').context.board = board;
});
});

0 comments on commit 8b7b1e1

Please sign in to comment.