-
Notifications
You must be signed in to change notification settings - Fork 21
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
SPI #3
Comments
FWIW, here's the documentation for SPI in the C++ library I use for raspi-io: http://wiringpi.com/reference/spi-library/. Specifically, you specify a channel and a clock rate in initialization, and reading/writing is batched together (since SPI slaves can only write while the master is also sending data) |
xref: rwaldron/johnny-five#624 (comment) Also, you could check out my https://github.com/natevw/pi-spi as an example simple wrapper around the Linux spidev interface if that's relevant for such a backend. |
I'm also looking into this spi module for Linux: https://www.npmjs.com/package/spi. I'll try both once I get a compatible board. |
One of the bigger issues I'm facing in defining a protocol is how to handle the CS pin and any secondary CS-type pins. On the Firmata side there is an advantage to specifying the CS pin and any CS-like pins in the config message, then managing them on the firmware side to avoid having to send too many messages over Serial (especially for SPI devices that require toggling CS between every byte read - not yet sure if that's even a case worth supporting). However for Linux implementations (Pi, BeagleBone, Galileo, etc) it may be better to handle the CS pin separately since there is far less latency involved (I'm assuming). |
Yes, another thing to consider along with related pins is transactions that need to hold the SPI bus. I forget the exact situation but there was an avoidable need with https://github.com/tessel/sdcard to "lock out" SPI communications with other chips during some operations (i.e. a CSN pin had to remain down even between individual SPI transfers) — there are likely other types of devices that are are SPI "compatible" but need similar coddling. This is how Tessel ended up exposing such a feature at the API level: https://github.com/tessel/docs/blob/master/tutorials/raw-spi.md (via https://tessel.io/docs/hardwareAPI#api-spi-lock-callback) |
I remember in college doing some SPI work where I had something like 4 SS pins (ne CS, ne CSN, ne why the hell are there so many names for this pin) on the master that would essentially "toggle" between slaves to avoid needing more than one SPI port. If we want to support these types of use cases, would it make sense to start by having the SS just be "automagic" for now and handled on the firmata side, and provide a flag for saying "no, I'm going to handle SS myself"? |
Right, sharing a bus is the usual SPI situation (see http://www.dorkbotpdx.org/blog/paul/better_spi_bus_design_in_3_steps for "protips" on the hardware side) but there's some devices (SD Card for one I'm familiar with) that are mostly SPI-compatible but don't really follow that "standard" and use the select pin for signaling more than just "I am talking with you via the other three pins". In the SD case, after you issue a read/write request you need to hold its CSN equivalent "active" (i.e. low) and during that time you want to make sure no other SPI usage happens. That's what the "lock" is for, so that you can reserve the SPI bus against other traffic. A more mundane use case is when you run out of hardware pins and start using random other GPIO pins for CSN…that pin state needs to be coordinated with the SPI transfer the same sort of mutex/fifo can facilitate that. |
TIL |
My current thoughts (incorporating feedback from Nate and Bryan): configuration options
methods// the idea here is that each device would have its own SPI instance
// someone please correct me if I'm wrong but it seems this is already the case for
// many Linux SPI interfaces. Otherwise if there is only a single SPI instance (per SPI
// port on a device if multiple) then options will need to be set on the spi object
// instance before each transaction with a different device
// constructor (see options above)
// a setter could also be provided for each option
var spi = new SPI(options)
// when you need to write and read in a single transaction (most common use case)
// The implementation must ensure that the number of words written equals the
// number of words received. If a written word does not return data, 0 should be returned
spi.transfer(txBuffer, cb(err, rxBuffer))
// writes 0 for each byte requested
// length is number of words (see words option above)
spi.read(length, cb(err, rxBuffer))
// for write only transactions
spi.write(txBuffer, cb(err)) |
For node-firmata applications we'll also need |
Just a thought: what do you think about making txBuffer optional in spi.transfer? This way, read and write are just direct aliases to transfer, and can be literally implemented as:
|
The separation is necessary for the following reasons:
spi.write and spi.transfer could be consolidated but it would take an additional parameter to specify whether or not to return data. I think having separate write and transfer methods is cleaner. |
I see, so spi.write/spi.read are convenience methods, essentially, right? SPI works by reading/writing simultaneously, and write/read essentially handles the case where you don't care about one or the other but still have to provide something, correct? In that case, you're right, it does make sense to have them separate. |
That is correct. |
@soundanalogous Hello! I have some bandwidth this week to begin working on this as well-- I'm going to start with the edison wrapper, maybe add Galileo if there's time this week. Let me know if there's a branch I can look at to see where you're at, or have any further ideas :). |
@nodebotanist that's great news! I haven't done any on an implementation yet for Edison or Galileo yet. My effort so far has been on trying to nail down the SPI protocol for Firmata and coming up with a high level API for johnny-five (this thread) that will work for both Linux and Arduino/Firmata based SPI implementations. If you want to take on the Linux side (at least for Edison and maybe Galileo for now) that would be great actually since I don't have much experience with those platforms. I plan to work on the Arduino implementation. Let's sync up on the high level API for johnny-five. |
I'm finally making some progress here on the Arduino and firmata.js front: Feedback is welcome. |
Wow, rad! I will try to have a look as soon as I can :) |
Another potential candidate for Linux IO Plugins would be https://github.com/fivdi/spi-device |
@soundanalogous @rwaldron Very cool! It looks like the SPI proposal was merged upstream, does that mean we're go for SPI in johnny-five? |
The Firmata SPI proposal is not yet final. It will still be a while before it is finalized due to the limited amount of feedback on the proposal. |
Define a generic API for SPI that can be implemented across all platforms
The text was updated successfully, but these errors were encountered: