New command: digital read port (A, B)
Opened this issue · 6 comments
To make digital pin reading more efficient:
- allowing a client to request the values of the entire port, encoded as an 8-bit unsigned int byte
- "port value" is determined by these parameters:
- 0 for pins that are enabled for I2C, SPI or UART use
- 0 for pins that are input or output and currently "low"
- 1 for pins that are input or output and currently "high"
Pins correspond to bits as:
B7 | B6 | B5 | B4 | B3 | B2 | B1 | B0 |
---|---|---|---|---|---|---|---|
7 | 6 | 5 | 4 | 3 | 2 | 1 | 0 |
For example, if all pins on a given port were in use as digital i/o pins and currently pin 7 is "high" and pins 0-6 are "low", then the port value would be 128
:
B7 | B6 | B5 | B4 | B3 | B2 | B1 | B0 |
---|---|---|---|---|---|---|---|
1 | 0 | 0 | 0 | 0 | 0 | 0 | 0 |
I don't understand– can you give an example scenario for using this?
This is actually an optimization taken from the Firmata protocol, it allows client code to get the current value/state of all pins in a given port (port = set of 8 pins) at once, instead of requiring 8 separate reads with 8 corresponding responses. This is also how most IO expansion chips are designed, 8 pins = 1 (8-bit unsigned int) byte. It's a cheap (and very efficient) way to see the state of all 8 pins in a port at once.
I'm going to work on a draft patch
You could accomplish this without firmware changes by doing a batched sequence of 8 commands to read the 8 pins, which would be one round-trip instead of 8. It would still involve 16 bytes in each direction and dispatching 8 instructions, but that's negligible compared to latency and bridge overhead.
Note that with cork
/uncork
nonfunctional on domain sockets in the current io.js you can't guarantee that it will go out as a single batch.
I'll try both ways and see which results in the best end-to-end performance
As part of a larger effort to exploit the async IO potential of an onboard co-processor, I'm going to start working on this again, with a slight change to the plan: it should not be necessary to constantly send requests for pin values or port state. Realistically, a program should be able to send a one time request for any or all of the following:
- send me the entire port state every N milliseconds.
- send me the analog input value of pin P, every N milliseconds
- send me K bytes read from I2C register at address, every N milliseconds
My original plan was to do this with macro-like sequences that execute multiple times, by adding opcodes like:
BEGIN: start recording a macro. subsequent commands until LOOP are buffered as they are executed.
LOOP: jump back to the preceding BEGIN
CANCEL: the only command legal to be sent after LOOP, makes the loop exit
PERIOD: delays until the specified time has elapsed since the start of this iteration of the loop
GPIO_WAIT: delays until the pin is high/low (to wait for interrupt / "data ready" pins)
with that, you can accomplish all of those and more.