The ongoing discussion in the K66 beta test thread reveals a serious shortcoming of the DMASPI library's design. It was designed with just one SPI in mind and evolved from "somewhat working" to "usable for others" to what it is now - but still only for one SPI. The problems revolve around the following procedure:
the DMASPI library provides the class ActiveLowChipSelect, which is hardcoded to use SPI, without any way to sneak in SPI1 or SPI2. The only way to change the SPI object is to write the correct one in ActiveLowChipSelect or another class that derives from AbstractChipSelect, or to somehow change the interface to allow passing in a reference to an SPI object. However - and I pointed this out when I first worked on DMASPI - SPI, SPI1 and SPI2 don't derive from a common base class. They cannot be passed as the same reference type.
My suggestions for workarounds or changes to the interface:
Any more suggestions or wishes? What would you do? If breaking changes are necessary, I'd rewrite the chip select interface and call it DMASPI_v2 or something like that, to clearly indicate that it's a different library.
Regards
Christoph
- A transfer object is created, which describes the desired transfer. It has an optional chip select object which can used to set up the SPI bus (SPISettings) when the transfer is started and ended, and to correctly assert and deassert a chip select signal.
- the transfer object is registered with the desired DMASPI object
- eventually the DMASPI object starts the transfer and calls transfer::select(), which has no arguments
- transfer::select() may call SPI.beginTransaction to set up the bus
- the DMASPI transfer is executed
- transfer::deselect() is called, and if a transaction was started in select(), it must be ended now
the DMASPI library provides the class ActiveLowChipSelect, which is hardcoded to use SPI, without any way to sneak in SPI1 or SPI2. The only way to change the SPI object is to write the correct one in ActiveLowChipSelect or another class that derives from AbstractChipSelect, or to somehow change the interface to allow passing in a reference to an SPI object. However - and I pointed this out when I first worked on DMASPI - SPI, SPI1 and SPI2 don't derive from a common base class. They cannot be passed as the same reference type.
My suggestions for workarounds or changes to the interface:
- Create an independent chip select class that uses SPI1. Tedious, and error-prone when code is moved from one SPI to the other
- Modify ActiveLowChipSelect to accept a template parameter to choose the correct SPI. Error-prone as the previous suggestion
- Add beginTransaction() and endTransaction() methods to DMASPI. Add an AbstractDmaSpi reference parameter to AbstractChipSelect::select and ::deselect, so that the chip select object can use the abstract interface provided by DMASPI to control SPI transactions. The AbstractDmaSpi reference would need to be passed to the transfer object, and on to the chip select object. Con: breaking change to existing code, because a new argument is introduced. Pro: the chip select object can't work on the wrong SPI object
- Instead of passing an AbstractDmaSpi reference to AbstractChipSelect::select() and ::deselect(), set a pointer in registerTransfer(). Feels awkward, but would probably work as well.
Any more suggestions or wishes? What would you do? If breaking changes are necessary, I'd rewrite the chip select interface and call it DMASPI_v2 or something like that, to clearly indicate that it's a different library.
Regards
Christoph