Closed ejdp62 closed 1 year ago
I hope my first post is reasonably clear regarding how (based on what information) various SPI parameters should be set. (In my opinion, and please let me know if you agree or not!) So, looking at the code in the Arduino_HWSPI.cpp file, lines 148 to 201, to me it makes no sense to determine the default MODE settings based on a test on architecture (the master). In stead, it would be better to set this parameter based on information owned by the slave (the display controller in this case).
I hope my first post is reasonably clear regarding how (based on what information) various SPI parameters should be set. (In my opinion, and please let me know if you agree or not!) So, looking at the code in the Arduino_HWSPI.cpp file, lines 148 to 201, to me it makes no sense to determine the default MODE settings based on a test on architecture (of the master). In stead, it would be better to set this parameter based on information regarding the slave (the display controller in this case).
As you may know this library is rewritten from Adafruit_GFX, AVR default use SPI mode 2 also inherited from it. Refer to the ST7735 patch, each display driver can override this default. Do you think it is flexible enough? Do you have any design suggestion?
This is not an immediate issue where something that does not work needs to be fixed, but intended as a discussion of how SPI-related controls should be handled by software.
I use the Arduino SPI pages and the wiki on SPI as reference (plus some of my own experience). https://docs.arduino.cc/learn/communication/spi (plus other pages from the same source) https://en.wikipedia.org/wiki/Serial_Peripheral_Interface
A good point of departure is to consider for each control parameter what in the system determines the control value. For example, the MODE settings that need to be used are determined by the slave only. Not the master or anything else, only the slave.
As another example, the speed of the SPI bus is determined by all slaves attached to it, plus the bus itself (the wiring). As corner case, sometimes even the master may be the limiting factor for the speed of the bus.
Another essential difference between MODE and speed parameters is the daisy chain configuration (see wiki): -It does not make sense to hook up two slaves that need different MODE parameters to the same bus -It does make sense to hook up two slaves that need different speed settings to the same bus
In the daisy chain configuration, all slaves share the clock and chain the data line from one slave to the next, so all devices need to have the same transfer MODE. On the other hand, the SPI bus should always clocked at the lowest speed of all devices (including the bus and the master), even if a higher speed slave is targeted.
In the independent slave configuration, devices can be mixed for both mode and speed parameters. And this is where transactions come in. Transactions work particularly well in the independent slave configuration, and they allow to configure the bus optimally each time some data is transmitted to/from a particular slave.
That means that in the independent slave configuration, the SPI bus bus MODE setting should be hands-off for the bus itself, and the slaves can freely determine the transaction parameters without knowing those of other slaves.
The optimal speed parameter that can be used is not known by any slave device, and so the speed parameter must be able to be set by some slave-independent agent. The SPI bus object is a natural candidate.
Summarizing this division of responsibilities: -For each transaction, slaves can each provide their preferred settings, both MODE and speed. -The slave-provided MODE can actually be used in all cases (independent slave or daisy-chain) -The slave-provided speed must always be compared with a centrally stored upper bound, and the minimum is actually used
This centrally stored upper bound is then the minimum of: -The maximum speed of the master, -The maximum speed of the bus, -and in case of a daisy-chain configuration: the maximum speeds of all slave devices.
So it is the slaves that provide in the call to a read or write method of the SPI object: -the MODE parameter, and it should be always be used as-is (so completely hands-off for the bus) -the speed parameter, and that parameter may be overridden by the bus object to set the speed to a safe value
This could be implemented as follows: -Allow a speed parameter for the SPI.begin() and for all slave.begin() methods. -In the slave device code, construct the transaction parameters to the best of the slave's knowledge -In the SPI code, possibly override the speed parameter, but use the mode parameter as given.
Hope this exposition is somewhat clear! Please let me know your questions and remarks. If and when appropriate, we can discuss the current implementation in the library code.