https://toitlang.org/ logo
Driver for CS5529 SPI
# help
e
I'm trying to write a driver for this chip, but it seems the spi library is not meant for soemthing like this. Should I use the serial library instead? I'm a bit confused about the times, and chip select because when I look a the actual output it seems to something else. Chip select is activated later than miso, and there is no manual way to set chio select to active. https://cdn.discordapp.com/attachments/1342884960125845546/1342884960310263861/CS5529_F5.pdf?ex=67bb4294&is=67b9f114&hm=a90c9ebde585effd594b704b9b650661b88743af340745bf92b389dc63186944&
f
We are using the ESP-IDF under the hood, so it should be suitable and work. Could it be that the CS is activated after the MISO, because the MISO is brought into its idle state first? Fundamentally, it shouldn't even matter when the MISO is changed as long as the CLK is only activated when the data is set correctly. From looking at the datasheet I believe that the sensor runs with CPOL=0, CPHA=0, thus
--mode=0
(the default). If you don't trust the CS, you can just toggle the CS yourself (
gpio.Pin --output
and then just
pin.set ...
). Since your sensor has 24-bit registers you can't use the
Device.Registers
facility, but you can just read and write by yourself. However in that case you might need to keep the CS active yourself between the write and read. For example:
Copy code
/**
Sends a command to the SPI-device stored in the $device_ field.

Example:
``  // Note this should be 3 '`', but my Discord response doesn't allow that.
send-command_ 0b1100_0000  // Perform single conversion.
``  // Should be 3 '`', but due to Discord...
*/
send-command_ command/int -> none:
  device_.write #[command]

/**
Reads a 24-bit register from the SPI-device stored in
  $device_ field.
*/
read-register_ register/int -> int:
  // The CS5529_F5 only seems to have 5 registers.  
  assert: 0 <= register <= 4

  device_.with-reserved-bus:
    read-command := 0b1001_0000 | (register << 1)
    device_.write #[register] --keep-cs-active
    bytes := device_.read 3
    return (bytes[0] << 16) | (bytes[1] << 8) | bytes[2]
  unreachable
e
Thank you. I got it to work, but I'm still a bit confused with some things. Not that I want to waste you time with any of this, just mentioning this here... I couldn't make the oscillator work, maybe because I'm operating the logic part of the chip with 3.3V. I'm doing that to avoid adding a level shifter. So, I'm making a clock with the ESP32, and feeding it to the chip. Not sure if that is the reason, or just my inexperience with these kind of things. I reset the chip, and it seems to work ok. However, in the datasheet it says that after a single shot conversion it will signal ready, and after sending 8-bit 00s it should send back the reading. I tried doing that, but no luck, so I ended just reading the registers.
f
I will have a look tomorrow, but a short scan of the code looked good.
I would probably sweet the constants as hex (unless the datasheet uses decimal). But that doesn't really change anything.
Can you show me the code for the oscillator that didn't work? Is it committed?
When you say you couldn't make the oscillator work, what was the intention? I will look at the datasheet in more detail tomorrow, but I got the impression the chip has xtal pins for a crystal and not for an external clock
My understanding of the single conversion with PF=1 is that the sensor makes the miso (SDO) into an interrupt pin. That is, the Toit code would need to reconfigure the pin into input (and not SPI anymore). Then wait for the pin to trigger. Switch back to SPI. Send out the Null-Bytes to make the SDO again into a miso pin, and finally read the value. Unless the conversions take a long time I would not bother with that and use PF=0 instead.
It's a pull request, but it shouldn't be committed.