I am trying to implement a master Linux driver to communicate with an Omron D6t-PH differential pressure flow-meter slave device.
Reading the manual for this instrument, and the provided sample code (which is for an STM32 uC) it appears I need to increment the slave address following the initial "write to the access address". This will allow me to read measured data from the device.
There IS a function provided within the Linux i2c smbus library here that will do this, although it does not appear to support the address increment that follows the initial "access register write".
Does anyone know a workaround or some advice on how to handle this device address incrementing requirement?
Below is some doc and guides I have been following. First is the device manual;
Address increment requirement is shown on P.7 Table 3. of the D6T... manual
During Write: Set LSB of slave address to “0” to form D8h (1101_1000b).
During Read: Set LSB of slave address to “1” to form D9h (1101_1001b).
Flow chart of the commands required are on P.12,P20-22
Some sample code which outlines the same is on P.28
I2C1_MastrSel(add, 1); /* Slave 7bit => 8bit for RD */
With respect to the master Linux user space driver I am trying to write, how can I alter the "SMBus Block Read" command so i can increment the address following the second "Start" command? Here is the commands structure:
S Addr Wr [A] Comm [A] S Addr Rd [A] [Count] A [Data] A [Data] A ... A [Data] NA P
This is some prototype code which I have written so far its a success up to the point of the block read:
#include <stdio.h>
#include <errno.h>
#include <string.h>
#include <linux/i2c-dev.h>
#include <linux/i2c.h>
// Make sure to link when compiling,... -li2c -o ...
#include <i2c/smbus.h>
#include <fcntl.h>
#include <stdlib.h>
/*******************************************************
Read block will read a block of data from the device
This is a challenge as this device requires that the addres is
incremented by 1 after writing the command to its access register.
The prototype function from smbus doesnt seem to offer this functionality
what i need appears to match the i2c_smbus_read_block_data() function,
although it does not increment the address after writing the initial command.
********************************************************/
void readBlock(file){
char res[2];
int readData = i2c_smbus_read_block_data(file,0x07,res);
if (readData<0){
printf("readDatafailed");
}else{
printf("dataRead, 0x%x",res);
}
}
/*********************************************************
START PROGRAM
********************************************************/
int main () {
/******************************************************
Open the device, as a file... Use adapter i2c-1
*******************************************************/
int file;
int adapter_nr = 1; /* adapter 1 */
char filename[20];
snprintf(filename, 19, "/dev/i2c-%d", adapter_nr);
file = open(filename, O_RDWR);
if (file < 0) {
/* ERROR HANDLING; you can check errno to see what went wrong */
int errnum = errno;
fprintf(stderr, "Value of errno: %d\n", errno);
perror("Error printed by perror");
fprintf(stderr, "Error opening file: %s\n", strerror( errnum ));
exit(1);
}else{
char str[80];
sprintf(str,"Opened the device");
/*Device does open*/
puts(str);
}
/****************************************************************
Next, afer the file is open and using the correct system driver,
Use the system i2c driver to open the correct i2c slave device by referencing
the address 0x6c
*****************************************************************/
int addr = 0x6C; /* The I2C address of this flow meter */
if (ioctl(file, I2C_SLAVE, addr) < 0) {
/* ERROR HANDLING; you can check errno to see what went wrong */
int errnum = errno;
fprintf(stderr, "Value of errno: %d\n", errno);
perror("Error printed by perror");
fprintf(stderr, "Error opening file: %s\n", strerror( errnum ));
exit(1);
}else{
char str[80];
sprintf(str,"Opened the device at address 0x6C");
puts(str);
}
/*************************************************************
Now try and read a conf. register from the Omron flow meter
*************************************************************/
__u8 reg = 0x02; /* Device register to access */
__s32 res;
char buf[10];
/* Using SMBus commands */
res = i2c_smbus_read_byte_data(file, reg);
if (res < 0) {
/* ERROR HANDLING: I2C transaction failed */
}else{
/* res contains the read word */
printf("Data received...Ox%X.\n",res);
/*Receives 0x04 which is correct*/
}
/***************************************************
Now set up the configuration register by writing 00 to 0b
*******************************************************/
char reg1 = 0x0b;
char data1 = 0x00;
__s32 res1;
//write to initialization register
res1 = i2c_smbus_write_byte_data(file,reg1,data1);
//check data and report
if (res1 < 0) {
perror("error writing to Initialization register");
}else{
perror("device initialized");
/*Device is initialized*/
}
//readBlock();
/*This fails as i cannnot increment address*/
/*How to alter the read block function???*/
return 0;
}