Hey all,
I’m trying to build a component for a 3rd party device, where I have no source or firmware for. After analyzing it seems it something resembling SPI closely, but not quite. For arguments sake, lets assume it is an SPI master device, and the ESPHome device would be the slave.
So far I have seen two variants, an older model, that included an interrupt line (very similar to CS of SPI). A newer model seems to abandon CS in favor of ‘encoding’ it in the clock signal (more on this in a moment).
The nice thing of a CS signal for a slave device (assuming it is implemented properly, e.g. asserted on start, de-asserted at end, and not ‘forever on’), is that we know exactly we have to start processing data. Since (for now) we have to rely on bit-banging, a hardware peripherial that reads in the data on CS is not possible.
So then we can either while(digital_read())
the pin (with timeout) until it changes, or trigger an interrupt. I saw esphome certainly supports interrupt driven pins.
Now here is my conundrum. ISR’s should be short and sweet, e.g. inform the main loop to read out the SPI buffer or use it to trigger the mainloop (if it is fast enough) to start reading the pin.
In this case however, esphome will trigger ‘our’ loop()
function every ~16ms. So we’d have to be really lucky to enter our loop()
just after the ISR triggers. Reading the (whole) SPI frame during the ISR is absolutely not something we’d want. Ideally, we’d set a callback function that in the ISR would call (after re-enabling all interrupts again) or some such. But I don’t think ESPHome is setup to handle this cleanly?
Just FYI on the second case, which is not super dissimilar, is that the chip-select is encoded in the clock pin, in that there is a 40ms pause of the clock between a 10ms frame of data. So we could monitor the clock pin like before (with timeout) until it has been asserted for at least 5ms (assuming the time between bits and bytes is shorter then 5ms, or even wait for the full 40ms, but that would be quite wasteful and unnecessary) to ‘sync’ to the end/start of a frame.
Reason I’m mentioning it for now, is just to get some thoughts. My concerns are (for the future) is that if this is SPI, and we can use a hardware SPI periphieral, we’d now have dual ‘role’ of the clock pin, e.g. monitor on the sync moment, to trigger the SPI peripherial to do things. I don’t know how common it is to reconfigure pins at runtime.
Pulling the clock in on two pins is a nother way, use a GPIO to monitor the clock, if the 5ms of assertion have been reached, enable the SPI hardware peripheral and toggle the CS manually, but that ‘costs’ two additional GPIO’s that may not be available, the clock monitor pin, the CS assertion pin, and the actual CS of the peripheral. Where I’m not sure what the consequences are of connecting a clock pin (in my particular case after a level shifter, so it’s not so bad) to two pins …