I2C Slave...Get Data Address

12 Feb 2012

Hey Guys,

Quick question regarding the I2C Slave library that was not immediately apparent. I understand that the receive method returns a status to check regarding if there is a read/write request from the master. I would like to set up my slave program to have multiple readable and writable registers like most slave devices. I have not, however, seen a way to get the data address that the master is trying to access.

Ex. My device address is 0x10 and should implement the following table:

NamePermissionsData AddressRead ResponseWrite Action
WhoamiR0x00Device IDN/A
Control1RW0x01Actual ValueSet Setpoint
Control2RW0x02Actual ValueSet Setpoint
SensorR0x03Sensor DataN/A

So, in this case, the program pattern should go something like:

...
int i = slave.receive();
switch(i) {
    case I2CSlave::ReadAddressed:
        //SOMEHOW GET THE DATA ADDRESS
        //STORE IN SOME VARIABLE v
        switch(v) {
            case 0x00: //This is the whoami register, return device id
                buf[0] = 0x10;
                slave.write(buf,1);
                break;
            ...
        }
        break;
   ...
}
...

Can anyone point me in the right diection?

12 Feb 2012

The master needs to write a single byte indicating the registeraddress. Any following byte will be written to the selected register. The slave will autoincrement the registeraddress when the master sends more than one byte of data. Reading from the registers is done by first writing the selected registeraddress. The master then ends the I2C write transmission and restarts reading the slave. The slave then sends the data from the selected register and again autoincrements when the master wants more data. Below is some example code which is not complete yet.

... 
int i = slave.receive(); 
int v = 0; // selected slave register;
switch(i) { 

case I2CSlave::WriteAddressed: 
  slave.read(buf, 2); // assume we only accept address and max of one databyte
  
  v = buf[0];  // buff[0] is the registeraddress
               // note: you need more code to handle the
               // one byte registerselection transfer for a follow on read.

  // test here to make sure we did receive a databyte before overwriting
  switch (v) {
     case 0:
             //This is the whoami register, ignore 
             v = 1; //autoincrement   
             break; 

     case 1:
             //This is the setpoint register 
             setpoint = buf[1];
             v = 2; //autoincrement   
             break; 

        ......
  }

  break;


case I2CSlave::ReadAddressed: 
   switch (v) {
     case 0:
             //This is the whoami register, return device id 
             buf[0] = 0x10;
             slave.write(buf,1); 
             v = 1; //autoincrement   
             break; 

     case 1:
             //This is the setpoint register 
             buf[0] = setpoint;
             slave.write(buf,1); 
             v = 2; //autoincrement   
             break; 

        ......
   } 
   Break;
 ... } 

...

12 Feb 2012

Ah, thanks...I was working on it pretty late at night and the fact that the master writes the register it wants to read first completely escaped me. I got it going now.

Thanks again