90 lines
1.7 KiB
C
90 lines
1.7 KiB
C
#include <linux/i2c.h>
|
|
#include <linux/i2c-dev.h>
|
|
#include <sys/ioctl.h>
|
|
#include <fcntl.h>
|
|
#include <stdio.h>
|
|
#include <unistd.h>
|
|
#include <stdlib.h>
|
|
#include <stdint.h>
|
|
#include <errno.h>
|
|
|
|
#define check(e) ({\
|
|
int ec = (e); \
|
|
if(ec < 0) {\
|
|
perror(#e); \
|
|
exit(1);\
|
|
}\
|
|
ec;\
|
|
})
|
|
|
|
enum BME280Register {
|
|
ID = 0xd0,
|
|
CTRL_MEAS = 0xf4,
|
|
PRESS_MSB = 0xf5,
|
|
};
|
|
|
|
typedef struct {
|
|
int fd;
|
|
} BME280;
|
|
|
|
int i2c_read_register(int fd, uint8_t reg) {
|
|
if(write(fd, ®, 1) < 0)
|
|
return -1;
|
|
uint8_t byte;
|
|
if(read(fd, &byte, 1) < 0)
|
|
return -1;
|
|
return byte;
|
|
}
|
|
|
|
int i2c_read_registers(int fd, uint8_t start_addr, uint8_t* values, size_t n_bytes) {
|
|
if(write(fd, &start_addr, 1) < 0)
|
|
return -1;
|
|
return read(fd, values, n_bytes);
|
|
}
|
|
|
|
int bme280_init(BME280* self, int fd) {
|
|
self->fd = fd;
|
|
|
|
if(i2c_read_register(fd, 0xd0) != 0x60)
|
|
return -ENOTSUP;
|
|
return 0;
|
|
}
|
|
|
|
int main() {
|
|
int bus = check(open("/dev/i2c-1", O_RDWR));
|
|
check(ioctl(bus, I2C_SLAVE, 0x76));
|
|
|
|
#if 0
|
|
// Check I2C driver compatibility
|
|
unsigned long adapter_funcs;
|
|
check(ioctl(bus, I2C_FUNCS, &adapter_funcs));
|
|
for(size_t i = 0; i != (sizeof(funcs)/sizeof(*funcs)); ++i) {
|
|
if(adapter_funcs & funcs[i].bit)
|
|
puts(funcs[i].name);
|
|
}
|
|
#endif
|
|
|
|
BME280 sensor;
|
|
check(bme280_init(&sensor, bus));
|
|
|
|
for(size_t j = 0; j != 10; ++j) {
|
|
uint8_t ctrl_meas = (0b001u << 5) | (0b001 << 2) | 0b11;
|
|
uint8_t bus_data[] = {CTRL_MEAS, ctrl_meas};
|
|
check(write(bus, bus_data, 2));
|
|
|
|
//TODO: should we sleep here? Maybe poll the busy flag?
|
|
|
|
uint8_t sensor_data[8];
|
|
check(i2c_read_registers(bus, PRESS_MSB, sensor_data, 8));
|
|
|
|
for(size_t i = 0; i != sizeof(sensor_data); ++i) {
|
|
printf("%02x ", sensor_data[i]);
|
|
}
|
|
puts("");
|
|
|
|
sleep(1);
|
|
}
|
|
|
|
close(bus);
|
|
}
|