PYNQ: PYTHON PRODUCTIVITY

Question for spi_transfer() function

Pynq Z1
Image Version 2.4

I am trying to code a driver for the Pmod AD5. I am using the example pmod codes for a starting point, specifically the ALS example, for how to code an SPI read device, and the DAC example for how to code an SPI write device. I cannot although find an example where a pmod initiates a write + read in the same spi_transfer() call.

The Pmod AD5 uses the AD7193 chip, which the datasheet states: “All communications to the part must start with a write operation to the communications register.”
So, for example, in order to read the data register, I must write 8 bits to the comms register, and then read 24 bits from the data register.
Screenshot from 2021-04-02 21-22-54

My question is should I put both the write and read buffer arrays of different sizes in the same spi_transfer call? Or is it correct to have separate calls?

Here is part of my code, I am trying to read the state of the configuration register, which defaults to a value of 0x000117 on “Power On” of the device.

u32 get_configuration(){
	/*
	* Sends a read command for the Configuration Register 01010000 
	* Then returns the configuration
	*/
    WriteBuffer[0] = 0x50;
    u8 Configuration[3];
    spi_transfer(device, (char*)WriteBuffer, NULL, 1);
    spi_transfer(device, NULL, (char*)Configuration, 3);
    u32 v = ((Configuration[0] << 16) + (Configuration[1] << 8) + (Configuration[2]));
    return v;
}

I call the function in Jupyter using the following:

conf = adc.read_config()
print(conf)
'{:032b}'.format(conf)

The output I get is not the expected value of 0x000117. (Nor is it a consistent value)
My full code is linked below.

Project Files (C code, Python code, bin file, Jupyter file)
PmodAD5 Reference Manual
AD7193 Datasheet

What you are doing looks good to me. A few thoughts: have you made sure the pins are correctly specified? Also, should you also wait for some time before getting back the response? I checked the datasheet, there should be a 100ms delay before you can get anything?

Hello rock,

The pins should be correct as they follow the pmod specification and I use the standard
device = spi_open(3, 2, 1, 0); command.

From my understanding, the 100ms is the conversion time is for the data register, and I was assuming I can read the configuration register directly. Although, I want to implement this as well, I have two follow-up questions.

  1. To pull the CS-line low for 100ms, before sending/receiving from device, will I have to use some lower-level function, like XSpi_WriteReg()? I don’t see how I can do it with spi_transfer().

I also see this from pg. 12 of AD7193 Datasheet:

DOUT/RDY = Serial Data Output/Data Ready Output.
DOUT/RDY serves a dual purpose. … In addition, DOUT/RDY operates as a data ready pin, going low to indicate the completion of a conversion. If the data is not read after the conversion, the pin goes high before the next update occurs. The DOUT/RDY falling edge can be used as an interrupt to a processor, indicating that valid data is available. …

  1. If I understand, I should put something in my get_configuration() function that waits for the DOUT/RDY pin to go low, before calling the second spi_transfer()? If that is correct, should I again be using another function to monitor the individual line? XSpi_ReadReg()?