<< >>

Programmers guide to module_i2c_single_port

This I2C module comprises three functions that implement I2C master. It is a small and simple version of the protocol with limitations (described below), and expects SCL and SDA on the same port.

The four restrictions of this module are:

  1. It does not implement clock-stretching: it should only be used when slaves do not attempt to stretch the clock.
  2. It does not implement register read at present.
  3. It does not implement multi-master: it should only be used when the XCore is the only master on the I2C bus.
  4. The speed of the bus is defined using a compile-time define (I2C_BIT_TIME).

Note that on a single port it is impossible to implement clock stretching or multi-master.

Any constants that are to be overridden should be defined in an include file i2c_conf.h.

Symbolic constants

I2C_BIT_TIME

This constant defines the time in clock ticks between successive bits.

By default set to 1000 for 100 Kbit devices, but it can be overriden to 250 for 400 Kbit devices.

SCL_HIGH

This constant defines the bit value of a high clock on the I2C port.

The default value is 2, meaning that this is on bit 1 of the port. Set to 1, 4, 8, ... for other bits of the port.

SDA_HIGH

This constant defines the bit value of a high data bit on the I2C port.

The default value is 1, meaning that this is on bit 0 of the port. Set to 2, 4, 8, ... for other bits of the port.

S_REST

This constant defines the bit value of the other bits of the I2C port.

The default value is 0xC, meaning that bits 2 and 3 are kept high. Note that on occassions the other bits are left to float, so external resistors shall be used to reinforce the default value

API

void i2c_master_init(struct r_i2c &i2c)

Function that initialises the ports on an I2C device.

Parameters:
  • i2c_master – struct containing the clock and data ports. Both should be declared as unbuffered bidirectional ports.
int i2c_master_rx(int device, unsigned char data[], int nbytes, struct r_i2c &i2c)

Function that reads data from an I2C device.

Parameters:
  • device – Bus address of device, even number between 0x00 and 0xFE.
  • data – Array where data is stored.
  • nbytes – Number of bytes to read and store in data. This parameter must be set to ‘1’ and is ignored in this module. This parameter is provided for compatibililty with module_i2c_master.
  • i2c – struct containing the clock and data ports. Both should be declared as unbuffered bidirectional ports.
int i2c_master_write_reg(int device, int reg_addr, unsigned char data[], int nbytes, struct r_i2c &i2c_master)

Function that writes to a register on an I2C device.

Note that this function uses the same interface as module_i2c but that the fields master_num and clock_mul are ignored by this function.

Parameters:
  • device – Bus address of device, even number between 0x00 and 0xFE.
  • reg_addr – Address of register to write to, value between 0x00 and 0x7F.
  • data – Array where data is stored.
  • nbytes – Number of bytes to read and store in data. This parameter must be set to ‘1’ and is ignored in this module. This parameter is provided for compatibililty with module_i2c_master.
  • i2c_master – struct containing the clock and data ports. Both should be declared as unbuffered bidirectional ports.

Example

An example program is shown below. Two unbuffered undirectional ports must be declared. Neither should be configured. In this example, SDA and SCL are connected to the lowest two bits of port 4A:

#include <stdio.h>
#include <xs1.h>
#include "i2c.h"

port i2c = XS1_PORT_4F;
port gpio = XS1_PORT_4E;

The main program calls _write_reg as appropriate:

int main(void)
{
  unsigned char data[1];
  int x;
  int i;

  i2c_master_init(i2c);

  gpio <: 0xF;

  data[0] = 0xFF;
  for(int j = 0; j < 1000000; j++) {
      for(i = 0x90; i < 0x9E; i += 2) {
          if (i == 0x94) i = 0x9C;
          data[0] = ~i;
          x = i2c_master_write_reg(i, 7, data, 1, i2c);
      }
      for(i = 0x90; i < 0x9E; i += 2) {
          if (i == 0x94) i = 0x9C;
          data[0] = i;
          x = i2c_master_write_reg(i, 8, data, 1, i2c);
      }
  }
  return 0;
}