Refactor I2C SMBUS

Add SI7021 chipset, partially done.
This commit is contained in:
Pim van Pelt
2018-04-02 20:38:26 +02:00
parent 5d92a45b58
commit 5b0fcadd9f
4 changed files with 78 additions and 130 deletions

View File

@ -122,6 +122,5 @@ void mgos_i2c_close(struct mgos_i2c *conn);
struct mgos_i2c *mgos_i2c_get_global(void); struct mgos_i2c *mgos_i2c_get_global(void);
// User contributed! // User contributed!
int get_i2c_register(struct mgos_i2c *i2c, uint8_t addr, uint8_t reg, uint8_t *val);
bool mgos_i2c_open(int busnr); bool mgos_i2c_open(int busnr);

View File

@ -23,15 +23,19 @@ void i2c_scanner(struct mgos_i2c *i2c) {
} }
bool i2c_dumpregs(struct mgos_i2c *i2c, uint8_t i2caddr) { bool i2c_dumpregs(struct mgos_i2c *i2c, uint8_t i2caddr) {
uint8_t reg, value; uint16_t reg;
int value;
for(reg=0; reg<255; reg++) { for(reg=0; reg<256; reg++) {
if (0 != get_i2c_register(i2c, i2caddr, reg, &value)) { value=mgos_i2c_read_reg_b(i2c, i2caddr, reg);
LOG(LL_ERROR, ("Could not read register")); if (value<0) {
printf(" XX");
} else { } else {
LOG(LL_INFO, ("reg=%u value=%u", reg, value)); printf(" %02x", value);
} }
if (reg%16==15) printf("\n");
} }
printf("\n");
return true; return true;
} }
@ -82,9 +86,12 @@ int main() {
} }
i2c_scanner(i2c); i2c_scanner(i2c);
// i2c_dumpregs(i2c, 0x76);
for (;;) { for (;;) {
sht31(i2c, 0x44); sht31(i2c, 0x44);
si7021(i2c, 0x44);
// i2c_dumpregs(i2c, 0x40);
si7021(i2c, 0x40);
sleep(1); sleep(1);
} }

View File

@ -89,151 +89,37 @@ bool mgos_i2c_set_freq(struct mgos_i2c *i2c, int freq) {
} }
int mgos_i2c_read_reg_b(struct mgos_i2c *i2c, uint16_t addr, uint8_t reg) { int mgos_i2c_read_reg_b(struct mgos_i2c *i2c, uint16_t addr, uint8_t reg) {
uint8_t data; uint8_t value;
if (!i2c) { if (!mgos_i2c_read_reg_n(i2c, addr, reg, 1, &value))
LOG(LL_ERROR, ("No I2C bus"));
return -1; return -1;
} return value;
if (ioctl(i2c->fd,I2C_SLAVE,addr) < 0) {
LOG(LL_ERROR, ("Cannot select slave 0x%04x on I2C bus: %s", addr, strerror(errno)));
return -1;
}
if (1 != write(i2c->fd, &reg, 1)) {
LOG(LL_ERROR, ("Cannot select register 0x%02x on device 0x%04x: %s", reg, addr, strerror(errno)));
return -1;
}
if (1 != i2c_read_timeout(i2c, &data, 1)) {
LOG(LL_ERROR, ("Cannot read register 0x%02x on device 0x%04x: %s", reg, addr, strerror(errno)));
return -1;
}
return data;
} }
int mgos_i2c_read_reg_w(struct mgos_i2c *i2c, uint16_t addr, uint8_t reg) { int mgos_i2c_read_reg_w(struct mgos_i2c *i2c, uint16_t addr, uint8_t reg) {
uint16_t data; uint16_t value;
uint8_t data[2];
if (!i2c) { if (!mgos_i2c_read_reg_n(i2c, addr, reg, 2, data))
LOG(LL_ERROR, ("No I2C bus"));
return -1; return -1;
} value=(data[1]<<8)+data[0];
return value;
if (ioctl(i2c->fd,I2C_SLAVE,addr) < 0) {
LOG(LL_ERROR, ("Cannot select slave 0x%04x on I2C bus: %s", addr, strerror(errno)));
return -1;
}
if (1 != write(i2c->fd, &reg, 1)) {
LOG(LL_ERROR, ("Cannot select register 0x%02x on device 0x%04x: %s", reg, addr, strerror(errno)));
return -1;
}
if (2 != i2c_read_timeout(i2c, &data, 2)) {
LOG(LL_ERROR, ("Cannot read register 0x%02x on device 0x%04x: %s", reg, addr, strerror(errno)));
return -1;
}
return data;
} }
bool mgos_i2c_read_reg_n(struct mgos_i2c *i2c, uint16_t addr, uint8_t reg, size_t n, uint8_t *buf) { bool mgos_i2c_read_reg_n(struct mgos_i2c *i2c, uint16_t addr, uint8_t reg, size_t n, uint8_t *buf) {
if (!i2c) { uint8_t outbuf;
LOG(LL_ERROR, ("No I2C bus"));
return false;
}
if (ioctl(i2c->fd,I2C_SLAVE,addr) < 0) {
LOG(LL_ERROR, ("Cannot select slave 0x%04x on I2C bus: %s", addr, strerror(errno)));
return false;
}
if (1 != write(i2c->fd, &reg, 1)) {
LOG(LL_ERROR, ("Cannot select register 0x%02x on device 0x%04x: %s", reg, addr, strerror(errno)));
return false;
}
if (n != i2c_read_timeout(i2c, buf, n)) {
LOG(LL_ERROR, ("Cannot read %lu bytes at register 0x%02x on device 0x%04x: %s", n, reg, addr, strerror(errno)));
return false;
}
return true;
}
bool mgos_i2c_write_reg_b(struct mgos_i2c *i2c, uint16_t addr, uint8_t reg, uint8_t value) {
uint8_t data[2];
if (!i2c) {
LOG(LL_ERROR, ("No I2C bus"));
return false;
}
if (ioctl(i2c->fd,I2C_SLAVE,addr) < 0) {
LOG(LL_ERROR, ("Cannot select slave 0x%04x on I2C bus: %s", addr, strerror(errno)));
return false;
}
data[0]=reg;
data[1]=value;
if (2 != write(i2c->fd, data, 2)) {
LOG(LL_ERROR, ("Cannot write to register 0x%02x on device 0x%04x: %s", reg, addr, strerror(errno)));
return false;
}
return true;
}
bool mgos_i2c_write_reg_w(struct mgos_i2c *i2c, uint16_t addr, uint8_t reg, uint16_t value) {
uint8_t data[3];
if (!i2c) {
LOG(LL_ERROR, ("No I2C bus"));
return false;
}
if (ioctl(i2c->fd,I2C_SLAVE,addr) < 0) {
LOG(LL_ERROR, ("Cannot select slave 0x%04x on I2C bus: %s", addr, strerror(errno)));
return false;
}
data[0]=reg;
data[1]=(uint8_t)(0xFF & (value >> 0));
data[2]=(uint8_t)(0xFF & (value >> 8));
if (3 != write(i2c->fd, data, 3)) {
LOG(LL_ERROR, ("Cannot write to register 0x%02x on device 0x%04x: %s", reg, addr, strerror(errno)));
return false;
}
return true;
}
bool mgos_i2c_write_reg_n(struct mgos_i2c *i2c, uint16_t addr, uint8_t reg, size_t n, const uint8_t *buf) {
if (!i2c) {
LOG(LL_ERROR, ("No I2C bus"));
return false;
}
if (ioctl(i2c->fd,I2C_SLAVE,addr) < 0) {
LOG(LL_ERROR, ("Cannot select slave 0x%04x on I2C bus: %s", addr, strerror(errno)));
return false;
}
if (1 != write(i2c->fd, &reg, 1)) {
LOG(LL_ERROR, ("Cannot select register 0x%02x on device 0x%04x: %s", reg, addr, strerror(errno)));
return false;
}
if (n != write(i2c->fd, buf, n)) {
LOG(LL_ERROR, ("Cannot write to register 0x%02x on device 0x%04x: %s", reg, addr, strerror(errno)));
return false;
}
return true;
}
void mgos_i2c_close(struct mgos_i2c *i2c) {
return;
}
struct mgos_i2c *mgos_i2c_get_global(void) {
return s_global_i2c_bus;
}
int get_i2c_register(struct mgos_i2c *i2c, uint8_t addr, uint8_t reg, uint8_t *val) {
unsigned char inbuf, outbuf;
struct i2c_rdwr_ioctl_data packets; struct i2c_rdwr_ioctl_data packets;
struct i2c_msg messages[2]; struct i2c_msg messages[2];
if (!i2c) {
LOG(LL_ERROR, ("No I2C bus"));
return -1;
}
if (ioctl(i2c->fd,I2C_SLAVE,addr) < 0) {
LOG(LL_ERROR, ("Cannot select slave 0x%04x on I2C bus: %s", addr, strerror(errno)));
return -1;
}
/* /*
* In order to read a register, we first do a "dummy write" by writing * In order to read a register, we first do a "dummy write" by writing
* 0 bytes to the register we want to read from. This is similar to * 0 bytes to the register we want to read from. This is similar to
@ -248,22 +134,68 @@ int get_i2c_register(struct mgos_i2c *i2c, uint8_t addr, uint8_t reg, uint8_t *v
/* The data will get returned in this structure */ /* The data will get returned in this structure */
messages[1].addr = addr; messages[1].addr = addr;
messages[1].flags = I2C_M_RD/* | I2C_M_NOSTART*/; messages[1].flags = I2C_M_RD/* | I2C_M_NOSTART*/;
messages[1].len = sizeof(inbuf); messages[1].len = n;
messages[1].buf = &inbuf; messages[1].buf = buf;
/* Send the request to the kernel and get the result back */ /* Send the request to the kernel and get the result back */
packets.msgs = messages; packets.msgs = messages;
packets.nmsgs = 2; packets.nmsgs = 2;
if(ioctl(i2c->fd, I2C_RDWR, &packets) < 0)
return false;
return true;
}
bool mgos_i2c_write_reg_w(struct mgos_i2c *i2c, uint16_t addr, uint8_t reg, uint16_t value) {
uint8_t data[2];
data[0]=value>>8;
data[1]=value&0xFF;
return mgos_i2c_write_reg_n(i2c, addr, reg, 2, data);
}
bool mgos_i2c_write_reg_b(struct mgos_i2c *i2c, uint16_t addr, uint8_t reg, uint8_t value) {
return mgos_i2c_write_reg_n(i2c, addr, reg, 1, &value);
}
bool mgos_i2c_write_reg_n(struct mgos_i2c *i2c, uint16_t addr, uint8_t reg, size_t n, const uint8_t *buf) {
unsigned char outbuf[n+1];
struct i2c_rdwr_ioctl_data packets;
struct i2c_msg messages[1];
if (!i2c) {
LOG(LL_ERROR, ("No I2C bus"));
return false;
}
if (ioctl(i2c->fd,I2C_SLAVE,addr) < 0) {
LOG(LL_ERROR, ("Cannot select slave 0x%04x on I2C bus: %s", addr, strerror(errno)));
return false;
}
messages[0].addr=addr;
messages[0].flags=0;
messages[0].len=sizeof(outbuf);
messages[0].buf=outbuf;
outbuf[0]=reg;
memcpy(outbuf+1, buf, n);
packets.msgs = messages;
packets.nmsgs = 1;
if(ioctl(i2c->fd, I2C_RDWR, &packets) < 0) { if(ioctl(i2c->fd, I2C_RDWR, &packets) < 0) {
LOG(LL_ERROR, ("Unable to send data")); return false;
return 1;
} }
*val = inbuf; return true;
return 0;
} }
void mgos_i2c_close(struct mgos_i2c *i2c) {
return;
}
struct mgos_i2c *mgos_i2c_get_global(void) {
return s_global_i2c_bus;
}
// User provided function to interface with Linux I2C driver // User provided function to interface with Linux I2C driver
bool mgos_i2c_open(int busnr) { bool mgos_i2c_open(int busnr) {

View File

@ -24,14 +24,24 @@
// Public functions follow // Public functions follow
struct mgos_si7021 *mgos_si7021_create(struct mgos_i2c *i2c, uint8_t i2caddr) { struct mgos_si7021 *mgos_si7021_create(struct mgos_i2c *i2c, uint8_t i2caddr) {
struct mgos_si7021 *sensor; struct mgos_si7021 *sensor;
int ret;
if (!i2c) return NULL; if (!i2c) return NULL;
// Reset and query register
ret=mgos_i2c_read_reg_b(i2c, i2caddr, MGOS_SI7021_READRHT_REG_CMD);
if (ret!=0x3A) {
LOG(LL_ERROR, ("Chip ID register invalid, expected 0x3A got 0x%02x (%d)", ret, ret));
return NULL;
}
LOG(LL_INFO, ("SI7021 found at I2C 0x%02x", i2caddr));
sensor=calloc(1, sizeof(struct mgos_si7021)); sensor=calloc(1, sizeof(struct mgos_si7021));
if (!sensor) return NULL; if (!sensor) return NULL;
sensor->i2caddr=i2caddr; sensor->i2caddr=i2caddr;
sensor->i2c=i2c; sensor->i2c=i2c;
sensor->last_read_time=0; sensor->last_read_time=0;
return sensor; return sensor;
} }