ΣSigmaStudio Ask AI Русский Log in

ADAU1401 I2C communication after Self-Boot

SigmaDSP & SigmaStudio xStSx Jan 9, 2019 00:00 4 replies Original on forum ↗
Subscribe
xStSx Question
Jan 9, 2019 00:00

Hello,

I'm a little bit stuck after reading datasheets,ez, and googling...

My goal to get ADAU1401 selfbooting and control volume gain from RaspberryPI(RPi) over I2C.

I have ADAU1401 board configured to work in Self-Boot mode with EEPROM attached to it (SELFBOOT pin connected to 3.3V, SDA and SCLK pulled high).

I designed simple system for tests in SigmaStudio 4.2 (I2S in/out , LED blinking at GPIO2), And got (RPi) write the selfboot image to the board's EEPROM. System is working I have audio out and LED blinking.

But I still unable to get control over ADAU1401 on I2C bus. After booting there is no 0x68/0x69 addresses on bus. Only 0x50 of EEPROM.

According to datasheet page28 (Self-Boot), after booting ADAU1401 becomes slave to receive commands. But it's never happening.. or I'm doing something completely wrong.

I's there some pin configuration that can prevent ADAU1401 to get slave on I2C ? or maybe some system design?

Thank you.

StS

Edit Notes
filling tags

[edited by: xStSx at 7:13 PM (GMT 0) on 9 Jan 2019]

Audio Signal Processors

adau1401

i2c

eeprom

microcontroller

raspberrypi

SigmaDSP Audio Processors

selfboot

Show More

5706.Untitled.png
5706.Untitled.png
xStSx Reply
Jan 17, 2019 00:00

Will answer my self.

Just found a solution, decided to try communicate with MCU (stm32f103/stm32f407) with both I can read and write the Param RAM space.

Strange that RPi can't do it.

Can be closed.

DaveThib Reply
Jan 18, 2019 00:00

Hello StS,

Sorry, been really busy the last couple of weeks.

The part can be "talked to" after it completes the bootup. So there is something happening that would explain your issues.

One thing is that the CLATCH/WP pin. Are you switching the state of that pin between high and low? If it switches three times then it will enter the SPI mode and then I2C messages will be ignored. It has to be powered down to revert back to I2C. So that is one possible issue that I can think of. After that I would suggest putting a scope on the SCL and SDA pins to see what is actually is being sent and if the part gives an "Ack".

A scope may also reveal what the issue is.

But, it sounds like you have worked through the issue.

Dave T

xStSx Reply
Feb 5, 2019 00:00

Thank you Dave for the reply. Got it working.

The problem was in low level wrong signaling at I2C bus, that's why adau1401 "get lost".

All the tools I have used and python scripts, tried to put stop condition (P) after sending Address of register, that was making everything stuck.

Anyway I successfully managed to communicate with the DSP , and to see the right parameters (PARAM,DATA). Just had to write it from scratch the right way.

#include <string.h>
#include <stdio.h>
#include <stdlib.h>
#include <linux/i2c.h>
#include <linux/i2c-dev.h>
#include <sys/ioctl.h>
#include <sys/types.h>
#include <sys/stat.h>
#include <inttypes.h>
#include <fcntl.h>
#include <errno.h>

#define ADAU_1401_ADDR 0x34
#define REG_ADDR 0x081c //DSP control reg

uint16_t read_reg_16 (int *dev, uint16_t reg)
{
uint8_t in_buff[2] = {0};
uint8_t out_buff[2] = {0};

out_buff[0] = reg >> 8;
out_buff[1] = reg & 0xFF;

struct i2c_msg msgs[2];
struct i2c_rdwr_ioctl_data msgset[1];

msgs[0].addr = ADAU_1401_ADDR;
msgs[0].flags = 0;
msgs[0].len = 2;
msgs[0].buf = out_buff;

msgs[1].addr = ADAU_1401_ADDR;
msgs[1].flags = I2C_M_RD;
msgs[1].len = 2;
msgs[1].buf = in_buff;

msgset[0].msgs = msgs;
msgset[0].nmsgs = 2;

if(ioctl(*dev, I2C_RDWR, &msgset) < 0)
{
printf("Failed to send message: %s\n", strerror(errno));
}

return (uint16_t)(in_buff[0]<<8 | in_buff[1]);

}

int main (int argc, char *argv[])
{
int i2c_dev;
char filename[40];

sprintf(filename, "/dev/i2c-1");
if((i2c_dev = open(filename, O_RDWR)) < 0)
{
printf("Failed to open I2C: %s\n", strerror(errno));
exit(1);
}

if(ioctl(i2c_dev, I2C_SLAVE, ADAU_1401_ADDR) < 0)
{
printf("Failed to get bus access: %s\n", strerror(errno));
close(i2c_dev);
exit(1);
}

printf("REG_ADDR: 0x%x - DATA: 0x%x\n", REG_ADDR, read_reg_16(&i2c_dev, REG_ADDR));

close(i2c_dev);

return 0;
}

I will leave it here if somebody will look for example :)

Thank you,

Sts.

DaveThib Reply
Feb 6, 2019 00:00

Hello Sts,

Thanks for the reply and the info.

I also have had to resort to custom routines with some compilers for embedded micros. It seems the stock built in functions do not always behave the way you would like. I recall one compiler that would sit around and wait for the SPI message to finish sending or to come in. That is an eternity to a uC and that is why god invented interrupts!

It was Ok for writing "Hello World" but not for any real application.

Have a great day!

Dave T