diff --git a/examples/gpio.c b/examples/gpio.c new file mode 100644 index 0000000..17f3356 --- /dev/null +++ b/examples/gpio.c @@ -0,0 +1,59 @@ +#include +#include +#include +#include +#include +#include +#include +#include + +#define check(e) \ + ({ \ + int ec = (e); \ + if (ec < 0) { \ + perror(#e); \ + exit(1); \ + } \ + ec; \ + }) + +void gpio_info(int gpio_fd) { + struct gpiochip_info chip_info; + check(ioctl(gpio_fd, GPIO_GET_CHIPINFO_IOCTL, &chip_info)); + + printf("Name: %s, Label: %s, %" PRIu32 " lines\n", chip_info.name, + chip_info.label, chip_info.lines); + + for (__u32 i = 0; i != chip_info.lines; ++i) { + struct gpio_v2_line_info line_info = { + .offset = i, + }; + check(ioctl(gpio_fd, GPIO_V2_GET_LINEINFO_IOCTL, &line_info)); + printf("Line %" PRIu32 ": '%s'. Consumer: %s\n", i, line_info.name, + line_info.consumer[0] ? line_info.consumer : ""); + } +} + +int main() { + int gpio0 = check(open("/dev/gpiochip0", O_RDWR)); + + gpio_info(gpio0); + +#if 0 + struct gpio_v2_line_request line_request = { + .offsets = {18}, + .num_lines = 1, + .consumer = "my-super-cool-gpio", + }; + check(ioctl(gpio0, GPIO_V2_GET_LINE_IOCTL, &line_request)); + + struct gpio_v2_line_info line_info = { + .offset = 18, + }; + check(ioctl(gpio0, GPIO_V2_GET_LINEINFO_IOCTL, &line_info)); + printf("Line 18: '%s'. Consumer: '%s'\n", line_info.name, line_info.consumer); + + close(line_request.fd); +#endif + close(gpio0); +} diff --git a/i2c-schedule.py b/examples/i2c-schedule.py similarity index 100% rename from i2c-schedule.py rename to examples/i2c-schedule.py diff --git a/examples/i2c.c b/examples/i2c.c new file mode 100644 index 0000000..ac05ba1 --- /dev/null +++ b/examples/i2c.c @@ -0,0 +1,89 @@ +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#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); +}