Skip to content

Commit

Permalink
Allow multiple pins to be updated before writing to the board
Browse files Browse the repository at this point in the history
  • Loading branch information
dtex authored and rwaldron committed Aug 24, 2018
1 parent 4df3421 commit e8b9211
Show file tree
Hide file tree
Showing 3 changed files with 86 additions and 3 deletions.
40 changes: 39 additions & 1 deletion lib/firmata.js
Expand Up @@ -10,6 +10,7 @@ var com = require("./com");

// Program specifics
var i2cActive = new Map();
var digitalPortQueue = [];

/**
* constants
Expand Down Expand Up @@ -952,9 +953,26 @@ Board.prototype.pinMode = function(pin, mode) {
* Asks the arduino to write a value to a digital pin
* @param {number} pin The pin you want to write a value to.
* @param {number} value The value you want to write. Must be board.HIGH or board.LOW
* @param {boolean} enqueue When true, the local state is updated but the command is not sent to the Arduino
*/

Board.prototype.digitalWrite = function(pin, value) {
Board.prototype.digitalWrite = function(pin, value, enqueue) {
let port = this.updateDigitalPort(pin, value);

if (enqueue) {
digitalPortQueue[port] = true;
} else {
this.writeDigitalPort(port);
}
};

/**
* Update local store of digital port state
* @param {number} pin The pin you want to write a value to.
* @param {number} value The value you want to write. Must be board.HIGH or board.LOW
*/

Board.prototype.updateDigitalPort = function(pin, value) {
var port = pin >> 3;
var bit = 1 << (pin & 0x07);

Expand All @@ -966,6 +984,26 @@ Board.prototype.digitalWrite = function(pin, value) {
this.ports[port] &= ~bit;
}

return port;
};

/**
* Write queued digital ports
*/

Board.prototype.flushDigitalPorts = function() {
Object.keys(digitalPortQueue).forEach( port => {
this.writeDigitalPort(port);
});
digitalPortQueue = [];
};

/**
* Update a digital port (group of 8 digital pins) on the Arduino
* @param {number} port The port you want to update.
*/

Board.prototype.writeDigitalPort = function(port) {
writeToTransport(this, [
DIGITAL_MESSAGE | port,
this.ports[port] & 0x7F,
Expand Down
8 changes: 6 additions & 2 deletions readme.md
Expand Up @@ -207,9 +207,13 @@ The `Board` constructor creates an instance that represents a physical board.

Set a mode for a pin. pin is the number of the pin and the mode is on of the Board.MODES values. All digital pins are set to board.MODES.OUTPUT by default (because this is what the Firmata firmware running on the board defaults to) and all analog pins are set to board.MODES.ANALOG (analog input) by default.

- `digitalWrite(pin,value)`
- `digitalWrite(pin,value,enqueue)`

Write an output to a digital pin. pin is the number of the pin and the value is either board.HIGH or board.LOW.
Write an output to a digital pin. pin is the number of the pin and the value is either board.HIGH or board.LOW. enqueue is optional and when true will update the local pin value but will not write the data until `writeQueuedDigitalPorts()` is called.

- `writeQueuedDigitalPorts()`

Directs firmata to update all ports whose values have been changed via digitalWrite with the `enqueue` parameter set to true.

- `digitalRead(pin,callback)`

Expand Down
41 changes: 41 additions & 0 deletions test/unit/firmata.test.js
Expand Up @@ -1490,6 +1490,47 @@ describe("Board: lifecycle", function() {
done();
});

it("must be able to enqueue a series of digital writes and then update the ports on demand", function(done) {

var write = sandbox.stub(SerialPort.prototype, "write");
var expect = [
[ 144, 20, 0 ],
[ 145, 5, 0 ]
];

board.digitalWrite(2, board.HIGH, true);
board.digitalWrite(3, board.LOW, true);
board.digitalWrite(4, board.HIGH, true);
board.digitalWrite(5, board.LOW, true);

// Should not call write yet
assert.equal(write.callCount, 0);

board.digitalWrite(8, board.HIGH, true);
board.digitalWrite(9, board.LOW, true);
board.digitalWrite(10, board.HIGH, true);
board.digitalWrite(11, board.LOW, true);

// Should not call write yet
assert.equal(write.callCount, 0);

// Write the ports
board.flushDigitalPorts();

// We are updating both ports 0 and 1
assert.equal(write.callCount, 2);

assert.deepEqual(Array.from(write.getCall(0).args[0]), expect[0]);
assert.deepEqual(Array.from(write.getCall(1).args[0]), expect[1]);

// Reset pins to low
[2, 4, 8, 10].forEach(pin => {
board.digitalWrite(pin, board.LOW);
});

done();
});

it("must be able to track digital writes via ports property", function(done) {
for (var i = 0; i < board.pins.length; i++) {
board.pins[i].mode = board.MODES.UNKNOWN;
Expand Down

0 comments on commit e8b9211

Please sign in to comment.