Open
Description
I had started work on the interface a while back: firmata/protocol#27.
And a thread here: firmata/protocol#26.
The tricky part is there are a lot of edge cases to cover. A decision needs to be made on where to draw the line regarding what is in and what is out in terms of support. Ideally this can be done in a way that the interface can scale if it becomes apparent that more functionality is needed.
Activity
overdamped commentedon Sep 19, 2017
Has anyone attempted implementation of this yet? If not, I have a definite and immediate need that I'd like to try to implement the proposal towards.
soundanalogous commentedon Sep 19, 2017
There is an implementation. Still needs a few tweaks but would be great to have people start testing it to see where or if it falls short. See this thread: #341.
The implementation is in this branch: https://github.com/firmata/arduino/tree/spi-alpha.
There were a couple of changes I had not yet made in the spi-alpha branch yet that were discussed here: firmata/protocol#88.
overdamped commentedon Sep 19, 2017
Excellent! I'll give it a spin and give some feedback. Thanks!
soundanalogous commentedon Sep 24, 2017
@overdamped I've updated the SPI implementation in the spi-alpha branch to match the firmata SPI protocol proposal.
Please try this version and provide any feedback you may have. I have an example client-side nodeJS implementation as well in the firmata.js spi-alpha branch.
I have only been able to test on an old LIS3LV02DQ accelerometer as that is the only SPI component I have. I'd love to see this tested on SPI components require sending and receiving more than 64 bytes at a time (this will test the multi-packet transfer case). Because Firmata sends data in 7-bit chunks, this means a 32 byte data packet would require 64 bytes to send. A SPI LCD screen is probably a good test case.
The part of the Firmata SPI proposal that I still think is kinda ugly, but don't have a better solution for is the [csPinControl] byte required with every SPI_TRANSFER, SPI_WRITE, or SPI_READ message. This is to allow the firmware to control the CS pin while still allowing multi-packet or streaming transfers (necessary if the packet length exceeds the transport (Serial, TCP, BLE) buffer size, which is 64 bytes for Serial for most architectures). However, this is the most efficient method I've found, the main advantage is that most simple SPI transfers (transfer, write or read) only require a single Firmata message. The 2 less efficient alternatives are:
Alternate 1: Requiring the user to frame every transfer with SPI_BEGIN_TRANSACTION and SPI_END_TRANSACTION messages (requires sending 3 Firmata messages for even simple transfers). In this case the SPI_BEGIN_TRANSACTION and SPI_END_TRANSACTION would handle toggling the CS pin appropriately. It would probably be the best approach semantically, but is not as efficient as what is currently proposed and implemented.
Alternate 2: Require the user to manually control the CS pin. This would also require sending 3 Firmata messages even for simple transfers.
@zfields FYI
soundanalogous commentedon Sep 24, 2017
I figure it's easier to understand if I attempt to explain the 3 different options for CS pin handling with a concrete example. To read the x, y, and z axis data from the LIS3LV02DQ accelerometer, the following steps are required:
There are at least 3 different ways this could be implemented in Firmata.
Option 1 (current implementation)
2 Firmata messages required to read the accelerometer data:
In option 1 SPI_BEGIN_TRANSACTION only needs to be sent once per device or when switching to another device on the same SPI bus.
Option 2 (frame every transfer as a transaction)
4 Firmata messages are required to read the accel data:
Option 3 (manual control of CS pin)
4 Firmata messages are required to read the accel data:
In option 3 SPI_BEGIN_TRANSACTION only needs to be sent once per device or when switching to another device on the same SPI bus.
soundanalogous commentedon Sep 30, 2017
A client library could also provide helper functions to mask some of the complexity in managing the CS pin. For example:
This enables our LIS3LV02DQ accelerometer example to use more familiar syntax:
soundanalogous commentedon Sep 30, 2017
Also, as a convenience when using more than one device on a single SPI bus,
SPI_BEGIN_TRANSACTION
could allow everything after the 4th byte (deviceId | channel) to be optional. That way only the firstSPI_BEGIN_TRANSACTION
for a specific device would need to send the full configuration, but subsequent messages would only need to send the deviceId, which would be used to lookup the settings for that device in stored in the firmware.