eblot / pyftdi

FTDI device driver written in pure Python
Other
509 stars 211 forks source link

Missing support for asserting SPI CS# #165

Closed jhol closed 4 years ago

jhol commented 4 years ago

I'm trying to implement a protocol that requires me to assert the CS line for a few milliseconds without transferring any data.

The Windows-based tool that I'm trying to replicate makes calls to FTCSPI.dll SPI_SetGPIOs which has a parameter for setting the chip-select pin: bADBUS3ChipSelectPinState

https://www.ftdichip.com/Support/Documents/AppNotes/AN_111_Programmers_Guide_for_High_Speed_FTCSPI_DLL.pdf

Is such a thing possible in pyftdi?

jhol commented 4 years ago

When asserting CS the FTCSPI SPI_SetGPIOs function calls:

eblot commented 4 years ago

PyFTDI does not let you directly drive /CS (although you can change the code to fit your needs). You can also use a free GPIO (for ex. AD4) as /CS and drive this line the way you like. However this means that you also need to drive it for all SPI transfers.

jhol commented 4 years ago

Sure... this is a question of "ought" versus "is".

Intuitively I would say a high level library like pyftdi should at least match the features of FTDI's FTCSPI.dll, and this seems to be trivial to implement. The main issue seems to be that the gpio_mask just needs a bit clearing for the SPI CS so that this bit can be set/cleared without an error being raised.

eblot commented 4 years ago

Intuitively I would say a high level library like pyftdi should at least match the features of FTDI's FTCSPI.dll

Definitely not the goal sorry :-) but I guess there are Python wrappers for FTDI DLL available out there. It would not be too difficult to implement/add an API to directly drive /CS though. It may be worth considering this addition...

jhol commented 4 years ago

Definitely not the goal sorry :-)

Would it be a problem if pyftdi evolved over time, and after a while it turned out that it now did support all the functions of FTCSPI?

It would not be too difficult to implement/add an API to directly drive /CS though

This would be fine for my needs, and probably a nice user-friendly design. FTCSPI allows the user to set GPIOs and /CS in a single call - though I'm struggling to think of a case where being able to do this would be important.

eblot commented 4 years ago

Well, from the API perspective, I find FTDI material quite ugly; it is backed up by the lack of documentation and their close-source approach (and the numerous, barely documented HW issues and hidden limitations which are buried deep inside application notes). So FTDI way: not a goal :P

Feature-wise the implementation could be equivalent only if it does not preclude readability and ease of use, but definitely not from an interface/API perspective.

There is also a drawback adding more and more feature: to be able to perform real and deep regression tests. As long as I do not have an automated way to perform those, I try not to add too many features that very few people actually use. Having a automated test platform would leverage these limitations, but it requires to write a lot of unit tests, and it also requires to implement a generic slave which is able to cope with that many features...

FTCSPI allows the user to set GPIOs and /CS in a single call

This is one of the feature that easily leads to generating incoherent SPI signalling without even noticing it... I try to keep PyFTDI API simple to use for the most common cases. For those that really want to perform not-so-common calls, it is always possible to use the low-level PyFTDI API, or tweak the SPI high-level implementation. It is a balance between versatility and ease-of-use/robustness. PyFTDI cannot fit all the needs - but fortunately, it is released as open source and under BSD license.

jhol commented 4 years ago

I guess you need an FPGA board with a FT2232H breakout board attached. This is easy enough to do now using open source tools.

eblot commented 4 years ago

Yes, very true, but also to define and implement a test protocol to change the FPGA configuration depending on what (I2C, SPI, JTAG, UART, ...) and how (SPI mode, clock stretching, UART bitrate, ...) to test. Quite a large piece of code to add. I wish I'd have more spare time :-)

jhol commented 4 years ago

I think you could fit all the functionality inside a single FPGA design... just have some (UART?) control interface to switch modes and input and output test data.

Given that this is a Python project, it would probably be appropriate to use a Python-based HDL such as MyHDL or Migen.

But yes, you are right: this is a non-trivial piece of work.

eblot commented 4 years ago

I do agree about this proposal. Any help warmly welcomed!

Back to the original issue, I'll try to add the /CS direct drive whenever I get a chance to work on PyFtdi, hopefully soon.

eblot commented 4 years ago

Hi @jhol,

I've created an experimental branch for this feature, please checkout https://github.com/eblot/pyftdi/tree/spi_cs_direct

The new API is SpiPort.force_select(), you can find some basic doc in the spi.py and the associated unit tests (SpiCsForceTestCase).

Please let me know how it goes.

eblot commented 4 years ago

Hi, any news?

eblot commented 4 years ago

Delivered to master as 25263b00a3c1a7255cfb33b05a56694caae5408b