Post Go back to editing

Rasp Pi SPI Initial Settings

Thread Summary

The user was unable to establish SPI communication with an ADAU1467 DSP on a Raspberry Pi. The solution involved using SPI mode 0 or 3, ensuring the correct pin connections on J1 (slave control port), and toggling the CS line to switch from I2C to SPI mode. The user also confirmed that a readback cell can be used to monitor the status of a logic gate in the DSP flow.
AI Generated Content
Category: Software
Product Number: ADAU1467
Software Version: 4.7

I am doing initial interface to a R-pi using J1 on the board.  MISO, SS, MOSI, and SCLK are all verified.  Can't seem to establish com with the board and read the registers. Couple questions.

1) Do I need to buffer the SS line with the Pi?

2) Do I need to change the DIP or boot switches on the board?

3) Are there any configuration options in SS that need to be changed/set for these lines?

Any reference examples would be appreciated.  

Thanks!

 

  • ADI North America will be on winter shutdown starting December 24, 2024; perhaps another community member can assist you until our return on January 2, 2025.
  • Just additional data, I can read the registers, but I cannot write to them.  Do I need to supply power to any of the header pins?  Thanks again and HAPPY NEW YEAR!

  • Here is the code I am using to try and write to the registers...

    #!/usr/bin/env python3
    """
    Test ADAU1467 using I2C instead of SPI
    """
    import smbus2
    import time

    # ADAU1467 default I2C address (7-bit)
    I2C_ADDR = 0x38 # Try 0x38 first, then 0x70 if that fails

    bus = smbus2.SMBus(1) # I2C bus 1

    print("=" * 60)
    print("ADAU1467 I2C Test")
    print("=" * 60)

    # Try to read a register via I2C
    CLOCK_REG = 0xF026

    try:
    # I2C protocol: write register address, then read data
    # Split 16-bit address into 2 bytes
    addr_high = (CLOCK_REG >> 8) & 0xFF
    addr_low = CLOCK_REG & 0xFF

    # Write address
    bus.write_i2c_block_data(I2C_ADDR, addr_high, [addr_low])
    time.sleep(0.01)

    # Read 2 bytes
    data = bus.read_i2c_block_data(I2C_ADDR, 0, 2)
    value = (data[0] << 8) | data[1]

    print(f"✓ I2C Read succeeded!")
    print(f" Address: 0x{I2C_ADDR:02X}")
    print(f" Register 0xF026 = 0x{value:04X}")

    except Exception as e:
    print(f"✗ I2C failed: {e}")
    print("\nTrying alternate address 0x70...")

    try:
    I2C_ADDR = 0x70
    bus.write_i2c_block_data(I2C_ADDR, addr_high, [addr_low])
    time.sleep(0.01)
    data = bus.read_i2c_block_data(I2C_ADDR, 0, 2)
    value = (data[0] << 8) | data[1]
    print(f"✓ I2C Read succeeded with address 0x70!")
    print(f" Register 0xF026 = 0x{value:04X}")
    except Exception as e2:
    print(f"✗ Also failed: {e2}")

    print("=" * 60)

    *****This is the result of that test code****

    ============================================================
    ADAU1467 Hardware Register Test
    Testing register 0xF026 (Clock Gen 3 Input Reference)
    ============================================================

    Step 1: Read default value
    Register 0xF026 = 0x00DD (expected 0x000E)

    Step 2: Write new value 0x0005
    Read back: 0x00DD

    ✗ Failed (expected 0x0005, got 0x00DD)
    ============================================================

  • Disregard that code, that was an I2C test that I have not yet run... Here is the SPI test....

    #!/usr/bin/env python3
    """
    Test ADAU1467 hardware register read/write
    Based on DaveThib's advice from Analog Devices forum
    """
    import spidev
    import time
    import RPi.GPIO as GPIO

    RESET_PIN = 26

    class ADAU1467:
    def __init__(self):
    GPIO.setwarnings(False)
    GPIO.setmode(GPIO.BCM)
    GPIO.setup(RESET_PIN, GPIO.OUT, initial=GPIO.HIGH)

    self.spi = spidev.SpiDev()
    self.spi.open(0, 0)
    self.spi.max_speed_hz = 1000000
    self.spi.mode = 0
    time.sleep(0.1)

    def write_register_16bit(self, addr, value):
    """Write 16-bit value to hardware register"""
    addr_high = (addr >> 8) & 0xFF
    addr_low = addr & 0xFF
    val_high = (value >> 8) & 0xFF
    val_low = value & 0xFF

    packet = [addr_high, addr_low, val_high, val_low]
    self.spi.xfer2(packet)
    time.sleep(0.01)

    def read_register_16bit(self, addr):
    """Read 16-bit value from hardware register"""
    addr_high = ((addr >> 8) & 0xFF) | 0x01 # Set read bit
    addr_low = addr & 0xFF

    packet = [addr_high, addr_low, 0x00, 0x00]
    result = self.spi.xfer2(packet)

    # Return 16-bit value from bytes 2 and 3
    return (result[2] << 8) | result[3]

    def close(self):
    self.spi.close()
    GPIO.cleanup()

    # Test as Dave suggested
    print("=" * 60)
    print("ADAU1467 Hardware Register Test")
    print("Testing register 0xF026 (Clock Gen 3 Input Reference)")
    print("=" * 60)

    CLOCK_REG = 0xF026

    dsp = ADAU1467()

    # Step 1: Read default value
    print("\nStep 1: Read default value")
    default = dsp.read_register_16bit(CLOCK_REG)
    print(f" Register 0xF026 = 0x{default:04X} (expected 0x000E)")

    # Step 2: Write new value
    new_value = 0x0005 # Valid 5-bit value
    print(f"\nStep 2: Write new value 0x{new_value:04X}")
    dsp.write_register_16bit(CLOCK_REG, new_value)
    time.sleep(0.05)

    # Step 3: Read back
    verify = dsp.read_register_16bit(CLOCK_REG)
    print(f" Read back: 0x{verify:04X}")

    if verify == new_value:
    print("\n✓✓✓ SUCCESS! Hardware register write works!")
    else:
    print(f"\n✗ Failed (expected 0x{new_value:04X}, got 0x{verify:04X})")

    dsp.close()
    print("=" * 60)

    ****And the result....****

    ============================================================
    ADAU1467 Hardware Register Test
    Testing register 0xF026 (Clock Gen 3 Input Reference)
    ============================================================

    Step 1: Read default value
    Register 0xF026 = 0x00DD (expected 0x000E)

    Step 2: Write new value 0x0005
    Read back: 0x00DD

    ✗ Failed (expected 0x0005, got 0x00DD)
    ============================================================

  • Hello ElsaDog,

    Please note that when the DSP is powered on or comes out of reset, by default the slave control port will be an I2C port, so you have to put it in SPI mode to read/write via SPI.

    Please add this code snippet and try again.

    If it still doesn't work, please attach your hardware schematic and probe the SPI port and send us the scope shots.

    Regards,

    Harish

  • Thanks for the answer, Harish!  It does not seem to change.  I also did an I2C address scan on pins 1 and 3 and see nothing (I am on the  Peripheral Cntl port, J6, btw).  I see SPI echos from the chip when in SPI mode.  Also running MODE 3 per datasheet. Still cant seem to access the registers.  Just FYI, I have a working schematic loaded and it is sending status back to Sig Studio.  When I connect on J1 to the USBi, I see constant updates streaming over the MISO lines on an SPI decode scope.  I was trying to identify the polling protocol but no luck, so far.  The pi is also very particular about seizing the CS line once SPI is running, so I moved it to another GPIO, did the pulse, then moved it back to CE0.  Still no luck.  I am hardware connected MISO on Pi to pin 5, MOSI to pin 8, CLK to pin 7, CEO/SS/CS to pin 9.   Is there a simple handshake code I can execute in the proper format so that I know I have syntax correct?  Thanks!

  • OK,. I have managed to get I2C working on J1, Master Header, by shorting pins 1-7 and 3-5.  I can now read and write registers! 

    1) Can you advise on if I can move this to the slave port?  so far no luck on that interface. 

    2) I still would like to get SPI working, but will fight that more, but should I be able to control this with my Pi on J6 and leave the master open for Sigma Studio program changes?  That workflow would be best for me.

    3) When I disconnect SS, and reset and reestablish com with the DSP, will my existing program continue to run?  Do I need to do any configuration with Self Boot to run the SS program and simply read and write registers with the controller?

    Thanks for your help!

  • I hope you read this one, first!  I have the self boot issue figured out, so now I only need to see if I can get I2C working on the Peripheral Control Port, and hopefully move to SPI.  So if you could please help me with question 1 and 2 from previous post.  Thanks!!

  • Hello ElsaDog,

    I think you have been using the wrong port, if you want to communicate with the DSP from your uC/uP/USBi, you must use the slave control port. It's always slave and only it allows the uC/uP/SS to program, read/write the DSP.

    The master control port (named as peripheral port in the eval board) is always master, it is used to program the self-boot EEPROM, program ADC/DAC, SPI flash etc.

    So, you have to use the port J1 (slave control port) in order to program the DSP.

    Regards,

    Harish

  • Great, thank you!  I am still working on SPI, can you sent me a quick diagram to validate pin connections, there are many variations I see out there, some with pins shorted, others not.  So to control via J1 using SPI, can you validate those connections and series resistors.  Also, I am doing some programming and have a question, can I read the status of a logic gate that is working as an OR gate in the flow? I do not see a reference to that gate in my export XML file.  If I cannot, do I insert a readback and poll it, or......  Thanks again!