Hey guys,
While working on my Dataflash library, I noticed a few things were missing from libmaple's spi implementation, and wirish's HardwareSPI
class.
For starters, when using HardwareSPI
there is no easy way to change the clock speed, bit order, or mode without calling end
and begin
in sequence. This is acceptable if you are changing two or more parameters, however if you only need to change one parameter (clock speed, for example) it's unnecessary to have to supply the other parameters since they don't change. In addition, libmaple's spi implementation has no way of changing these corresponding settings without applying an entire new configuration to the control register.
I propose the following changes:
1) Add new setFrequency
, setBitOrder
, and setMode
methods to the HardwareSPI
class.
2) Add a new low-level c helper function to libmaple's spi implementation that only changes affected bits in the CR1 register (based on a passed-in mask).
3) Using the new helper function, add corresponding low-level c functions to libmaple's spi implementation that allow only desired parameters to be changed.
The low-level c changes to libmaple are required in order to make the HardwareSPI
changes as efficient as possibly -- even though wirish/wiring has some overhead we all accept, it's still a good idea to minimize it. With these additions we'll still have to stop the spi peripheral before applying any changes to its configuration but these convenience methods will make the process simpler, but the actual changes will be easier to make. For example:
If you currently want to switch between two frequencies without manually controlling the CR1 registers yourself you must:
// Configure SPI to 1.125MHz, MSB first with mode of 0.
SPI.begin(SPI_1_125MHZ, MSBFIRST, 0);
// select some low-speed spi device, like a touchscreen controller
// ... Do some transferring at low-speeds
// deselect the device
SPI.end();
// Enable high-speed 18MHz transfers
SPI.begin(SPI_18MHZ, MSBFIRST, 0);
// select some high-speed spi device, like dataflash (hint hint)
// .. crazy fast transfers!
// deselect the device
SPI.end();
// go back to lower-speed for touchscreen controller
SPI.begin(SPI_1_125MHZ, MSBFIRST, 0);
// ...
As you can see, currently it's a pain to switch between multiple frequencies. If you're using two or more devices that depend on different frequencies (for highest possible performance) you'll be doing this a lot. While there are two SPI peripherals on the Maple, they are shared with other peripherals including GPIO and may not always be available for use. With the proposed changes you'll simply have to do:
// Configure SPI to 1.125MHz, MSB first with mode of 0.
SPI.begin(SPI_1_125MHZ, MSBFIRST, 0);
// select some low-speed spi device, like a touchscreen controller
// ... Do some transferring at low-speeds
// deselect the device
// Only change the SPI frequency to 18MHz, then restart the peripheral
SPI.setFrequency(SPI_18MHZ);
// select some high-speed spi device, like dataflash (hint hint)
// .. crazy fast transfers!
// deselect the device
//go back to lower-speed for touchscreen controller
SPI.setFrequency(SPI_1_125MHZ);
// ...
I am aware that Marti and the rest of the LeafLabs crew are busy working on things (like usb, oak, native *cough*, etc.). I would not mind working on these proposed changes and submit a pull request. Heck, I may even implement interrupt-based receiving for free as well.
Either way, I would love to hear what you think about these proposed changes and how they can be improved even further.
Cheers,
-robodude666