thexeno / HardWire-Arduino-Library

A spinoff of the Arduino Wire library, implements a fully controllable I2C slave.
28 stars 4 forks source link

The slave mode does not support word mode reading? #5

Closed mangoalx closed 6 years ago

mangoalx commented 6 years ago

I am using Hardwire library for a project to simulate an I2C slave device. The master will write a byte (register address) then read 1 word (content of the register). Anyway, the data trasferred is always 0x00nn, the second byte is 0 all the time. I wonder if I did anything wrong. I am using a beaglebone as the i2c master and using i2cget command to read data. i2cget -y 2 0x1c 5 w

define SLAVE_ADDRESS 0x1C //slave address,any number from 0x01 to 0x7F

define SLAVE_MASK 0x4 //This value is put in TWAMR, the bit will be ignored, so 0x1E will also

                                    //be accepted as slave address (shifted left for 1 so it is 4 instead of 2)

define REG_MAP_SIZE 18 //9 registers of 2 bytes data, last one Resolution is single byte, check later

define MAX_SENT_BYTES 3 //3 bytes can be written in - reg address, 2 bytes of data maximum

define MANUFACTUREID 0x0054

define DEVICEID 0X0400

define RFU 0x001F

const byte defaultReg[REG_MAP_SIZE] = {0x0,0x1F, //RFU 0x0,0x0, //config 0x0,0x0, //Tupper 0x0,0x0, //Tlower 0x0,0x0, //Tcrit 0x0,0x0, //Ta 0x0,0x54, //ManufactureID 0x04,0x0, //DeviceID 0x03,0x0 //Resolution, 1 byte, fill 0 the last byte };

const byte TaRegister=5; //no.5 register is Temperature ambient, will be used as default pointer value

/* Global Variables ***/

byte registerMap[REG_MAP_SIZE];

byte registerMapTemp[REG_MAP_SIZE];

byte receivedCommands[MAX_SENT_BYTES];

byte regPointer=TaRegister; //write only, to specify the register to access,default to Ta register byte dataReceived=0; //how many byte data received byte mapPointer=2*regPointer; //index for registerMap

include "commandline.h"

void setup()

{

for(byte i=0;i<REG_MAP_SIZE;i++) //copy deault data into registers registerMap[i]=defaultReg[i];

Wire.begin(SLAVE_ADDRESS); Wire.onRequest(requestEvent); Wire.onReceive(receiveEvent); }

void loop()

{ processDataReceved(); //Check if we received data to be written to registers if(getCommandLineFromSerialPort(CommandLine)) //global CommandLine is defined in CommandLine.h DoMyCommand(CommandLine); delay(1);

} //This handler needs to be short,there is just several uS to get ready for sending data. Maybe it holds the scl if not ready void requestEvent()

{

Wire.write(registerMap+regPointer*2, 2); //Send 2 bytes data only

}

//This handler needs to short, cause it hold the i2c until quit void receiveEvent(int bytesReceived)

{ //if only 1 byte is received, it is register address, put it into register pointer if(bytesReceived==1) regPointer=Wire.read();

else{ for (dataReceived = 0; dataReceived < bytesReceived && dataReceived<MAX_SENT_BYTES; dataReceived++)

    receivedCommands[dataReceived] = Wire.read();

// if we receive more data than allowed just throw it away, I just leave them un-read here, should not need to read the rest

if(dataReceived == 1 && (receivedCommands[0] < REG_MAP_SIZE/2)) 

// if only 1 byte received, this is the reg address, and a read operation is coming { regPointer = receivedCommands[0]; //if the reg address is valid, then set the pointer dataReceived = 0; //clear dataReceived, no more process is needed } }

}

void processDataReceved(void) { if(dataReceived != 0){ int i = receivedCommands[0]; if (i>0 && i<5 && dataReceived == 3) { //Register 1 to 4 registerMap[i2]=receivedCommands[1]; registerMap[i2+1]=receivedCommands[2]; } else if (i==8 && dataReceived == 2) { registerMap[i*2]=receivedCommands[1]; //Register 8 resolution, 1 byte } dataReceived=0; //Clear dataReceived } }

thexeno commented 6 years ago

Uhm interesting. I will try with a Rpi, conceptually should be similar. I'll let you know.. Thanks

thexeno commented 6 years ago

My suggestion to make it work with your code, is to try first with a very simple routine. Like getting just one byte back to the BB, then try with 2 or more bytes of a given value, so a very basic code. If that works, you can tell if it is a compatibility with the library or not.