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

1 Like

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()?
1 Like