Tag Archives: i2c

HiFiBerry DSP Light: Prototyping started

hifiberry-dsp-debuggingOur DSP project for the Raspberry Pi has reached the next milestone: hardware prototyping. The digital part of the circuits is working. There was still a minor bug (wrong pinout of a transistor) that was easy to correct by soldering the transistor on its back. The rest of the circuit worked well. As you can see on the picture, the analog part is not assembled yet. First I want to be able to upload the software to the chip.

Unfortunately, the simple approach to upload the program did not work. The chip simply did not acknowledge any I2S requests. Soldering some cables and connecting the I2S bus to the logic analyzer showed some unexpected behavior. While I2C read requests did not work, there was no problem with write requests. What happened? I had a look at the datasheet again and I think, I found the problem. Before every read request, the chip expects a write request with the address to read. However, both requests have to be in the same I2C transaction. The chip expects multiple start bits. Unfortunately, the Python I2C library that I wanted to use does not support multiple starts. It seems that I have to use the lower-level device driver of the operating system to upload the software to the chip.

Raspberry Pi I2C experiments

eeprom-bugAfter soldering so many 0602 packages and 0.65mm pitch circuits, it is really nice to do some soldering on 1.25mm pitch ICs. You can even solder cables to these ICs. Why should one do this? I have to do some tests with I2C communication on the Raspberry Pi. The Raspberry should program an I2C EEPROM.

That does not look like an audio project, but it is. This is the first step for our DSP project (the DSP will run standalone and has an integrated EEPROM for its program).

The default Raspian distribution does not come with the necessary tools installed. Therefore we first had to install them:

sudo apt-get install python-smbus
sudo apt-get install i2c-tools

Then, the I2C modules have to be added to /etc/modules:

i2c-bcm2708
i2c-dev

An they also have to be removed from the /etc/modprobe.d/raspi-blacklist.conf file (just comment them out).

After a reboot I2C communication should work:

pi@raspbian ~ $ sudo i2cdetect -y 1
...
40: -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- --
50: 50 -- -- -- -- -- -- -- -- -- -- -- -- -- -- --
60: -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- --
...

The EEPROM has the I2C address 0x50 – correct.

Now we have to write data to it and read it. There is a Python library SMBus, that has a very simple API. Unfortunately there are two issues:

  • there is almost no documentation
  • it is optimized for command-based I2C devices, where all command are single-byte command

With the 16kB EEPROM used here, this does not work very well, because addresses use 2 bytes. Therefore we need an additional abstraction layer to read and write data. Note, that the following program code is not final and only shown as an example.

# Simple I2C EEPROM routines
# works with 16-bit addressable EEPROMs (up to 64kB)

from smbus import SMBus

smb=SMBus(1);
slaveaddr=0x50;

def eeprom_set_current_address(addr):
  a1=addr/256;
  a0=addr%256;
  smb.write_i2c_block_data(slaveaddr,a1,[a0]);

def eeprom_write_block(addr,data):
  a1=addr/256;
  a0=addr%256;
  data.insert(0,a0);
  smb.write_i2c_block_data(slaveaddr,a1,data);

def eeprom_read_byte(addr):
  eeprom_set_current_address(addr);
  return smb.read_byte(slaveaddr);

eeprom_set_current_address(0);
#eeprom_write_block(1024,[3,1,4,1,5])

for x in range(0,10):
  print eeprom_read_byte(x);

for x in range(1024,1030):
  print eeprom_read_byte(x);