From 485922d898a9ae660f3f8d1500241810555d23b7 Mon Sep 17 00:00:00 2001 From: William Clark Date: Sat, 6 Jan 2024 00:52:37 +0000 Subject: [PATCH] SPI working! when using SPI, the order of writing out ctrl_reg's matters....but seemingly not when using i2c --- README.md | 5 ++- i2c.c | 19 ++++++----- lis3dh.c | 22 +++++++++---- main.c | 98 ++++++++++++++++--------------------------------------- spi.c | 70 +++++++++++++++++++-------------------- 5 files changed, 93 insertions(+), 121 deletions(-) diff --git a/README.md b/README.md index 468bf6e..947341b 100644 --- a/README.md +++ b/README.md @@ -21,7 +21,7 @@ See the `examples/` dir for complete code examples ## Implementation This driver requires the user to implement the following interface functions: -This project has example interface code for I2C and SPI (broken) used on Raspberry Pi 4. +This project has example interface code for I2C and SPI used on Raspberry Pi 4. ```c /* initialise the "interface" */ int init(void); @@ -52,6 +52,9 @@ int i2c_write(uint8_t reg, uint8_t value) { } int i2c_read(uint8_t reg, uint8_t *dst, uint32_t size) { + if (size > 1) { + reg |= 0x80; /* auto-increment bit */ + } uint8_t send[2] = { reg, 0x00 }; HAL_I2C_Master_Transmit(&hi2c2, LIS3DH_I2C_ADDR << 1, send, 2, HAL_MAX_DELAY); HAL_I2C_Master_Receive(&hi2c2, LIS3DH_I2C_ADDR << 1, dst, size, HAL_MAX_DELAY); diff --git a/i2c.c b/i2c.c index a32361b..6f6a080 100644 --- a/i2c.c +++ b/i2c.c @@ -24,19 +24,19 @@ Example I2C use on linux/raspberry pi */ #define I2C_DEVICE "/dev/i2c-1" -#define I2C_LIS3DH_ADDRESS 0x18 +#define I2C_LIS3DH_ADDRESS 0x18 /* Can also be 0x19 */ static int fd; int i2c_init(void) { fd = open(I2C_DEVICE, O_RDWR); if (fd < 0) { - fprintf(stderr, "[i2c] could not open device: %s\n", I2C_DEVICE); + fprintf(stderr, "i2c_init(): could not open device: %s\n", I2C_DEVICE); return 1; } if (ioctl(fd, I2C_SLAVE, I2C_LIS3DH_ADDRESS) < 0) { - fprintf(stderr, "[i2c] failed to acquire bus/talk to slave\n"); + fprintf(stderr, "i2c_init(): failed to acquire bus/talk to slave\n"); close(fd); return 1; } @@ -44,7 +44,6 @@ int i2c_init(void) { return 0; } - int i2c_read(uint8_t reg, uint8_t *dst, uint32_t size) { uint8_t cmd[2]; @@ -55,10 +54,13 @@ int i2c_read(uint8_t reg, uint8_t *dst, uint32_t size) { cmd[0] = reg; cmd[1] = 0x00; - write(fd, cmd, 2); + if (write(fd, cmd, 2) != 2) { + fprintf(stderr, "i2c_read(): error write()\n"); + return 1; + } - if (read(fd, dst, size) != (ssize_t)size) { - fprintf(stderr, "[i2c] error read()\n"); + if (read(fd, dst, size) != (int)size) { + fprintf(stderr, "i2c_read(): error read()\n"); return 1; } @@ -66,7 +68,6 @@ int i2c_read(uint8_t reg, uint8_t *dst, uint32_t size) { return 0; } - int i2c_write(uint8_t reg, uint8_t value) { uint8_t cmd[2]; @@ -74,7 +75,7 @@ int i2c_write(uint8_t reg, uint8_t value) { cmd[1] = value; if (write(fd, cmd, 2) != 2) { - fprintf(stderr, "[i2c] error write()\n"); + fprintf(stderr, "i2c_write(): error write()\n"); return 1; } diff --git a/lis3dh.c b/lis3dh.c index c042fee..0b2c5e4 100644 --- a/lis3dh.c +++ b/lis3dh.c @@ -175,7 +175,9 @@ int lis3dh_configure(lis3dh_t *lis3dh) { ctrl_reg0 |= 0x10; ctrl_reg0 |= (lis3dh->cfg.sdo_pullup & 1) << 7; - /* write these before the control regs that start the device */ + err |= lis3dh->dev.write(REG_CTRL_REG4, ctrl_reg4); + err |= lis3dh->dev.write(REG_CTRL_REG5, ctrl_reg5); + err |= lis3dh->dev.write(REG_FIFO_CTRL_REG, fifo_ctrl_reg); err |= lis3dh->dev.write(REG_INT1_CFG, int1_cfg); err |= lis3dh->dev.write(REG_INT1_THS, int1_ths); @@ -193,16 +195,15 @@ int lis3dh_configure(lis3dh_t *lis3dh) { err |= lis3dh->dev.write(REG_TEMP_CFG_REG, temp_cfg_reg); err |= lis3dh->dev.write(REG_REFERENCE, lis3dh->cfg.reference); - err |= lis3dh->dev.write(REG_CTRL_REG0, ctrl_reg0); err |= lis3dh->dev.write(REG_CTRL_REG1, ctrl_reg1); + + err |= lis3dh->dev.write(REG_CTRL_REG6, ctrl_reg6); + err |= lis3dh->dev.write(REG_CTRL_REG0, ctrl_reg0); err |= lis3dh->dev.write(REG_CTRL_REG2, ctrl_reg2); err |= lis3dh->dev.write(REG_CTRL_REG3, ctrl_reg3); - err |= lis3dh->dev.write(REG_CTRL_REG4, ctrl_reg4); - err |= lis3dh->dev.write(REG_CTRL_REG5, ctrl_reg5); - err |= lis3dh->dev.write(REG_CTRL_REG6, ctrl_reg6); /* sleep for a period TBD ~ ODR */ - lis3dh->dev.sleep(50000); /* 50 ms */ + lis3dh->dev.sleep(1000); /* 50 ms */ return err; } @@ -335,6 +336,9 @@ int lis3dh_reset(lis3dh_t *lis3dh) { /* set BOOT bit so device reloads internal trim parameters */ err |= lis3dh->dev.write(REG_CTRL_REG5, 0x80); + /* wait 30 ms */ + lis3dh->dev.sleep(30000); + /* write default values to rw regs */ err |= lis3dh->dev.write(REG_CTRL_REG0, 0x10); err |= lis3dh->dev.write(REG_CTRL_REG1, 0x07); @@ -357,6 +361,12 @@ int lis3dh_reset(lis3dh_t *lis3dh) { err |= lis3dh->dev.write(REG_TIME_WINDOW, 0x00); err |= lis3dh->dev.write(REG_ACT_THS, 0x00); err |= lis3dh->dev.write(REG_ACT_DUR, 0x00); + + /* set BOOT bit again so device reloads internal trim parameters */ + err |= lis3dh->dev.write(REG_CTRL_REG5, 0x80); + + /* wait 30 ms */ + lis3dh->dev.sleep(30000); return err; } diff --git a/main.c b/main.c index dd12326..7a8a30b 100644 --- a/main.c +++ b/main.c @@ -1,107 +1,65 @@ #define _GNU_SOURCE -#include -#include #include -#include +#include #include "lis3dh.h" -#include "interrupt.h" #include "i2c.h" - -/* GPIO 12 or Pin 32 */ -#define GPIO_INTERRUPT_PIN 12 - -static void quit(const char *msg, lis3dh_t *lis) { - lis->dev.deinit(); - fprintf(stderr, "%s\n", msg); - exit(1); -} - -static float mag(float x, float y, float z) { - return (float) sqrt(x*x + y*y + z*z); -} +#include "spi.h" int main() { lis3dh_t lis; - struct lis3dh_fifo_data fifo; - int k; + struct lis3dh_fifo_data data; + int i; - lis.dev.init = i2c_init; - lis.dev.read = i2c_read; - lis.dev.write = i2c_write; + lis.dev.init = spi_init; + lis.dev.read = spi_read; + lis.dev.write = spi_write; lis.dev.sleep = usleep; - lis.dev.deinit = i2c_deinit; + lis.dev.deinit = spi_deinit; - /* initalise LIS3DH struct */ + /* initialise LIS3DH struct */ if (lis3dh_init(&lis)) { - quit("init()", &lis); + puts("init()"); } /* reset device just in case */ if (lis3dh_reset(&lis)) { - quit("reset()", &lis); - } - - /* register interrupt */ - if (int_register(GPIO_INTERRUPT_PIN)) { - quit("int_register()", &lis); + puts("reset()"); } lis.cfg.mode = LIS3DH_MODE_HR; lis.cfg.range = LIS3DH_FS_2G; lis.cfg.rate = LIS3DH_ODR_400_HZ; - lis.cfg.fifo.mode = LIS3DH_FIFO_MODE_STREAM_TO_FIFO; - lis.cfg.fifo.trig = LIS3DH_FIFO_TRIG_INT1; /* trigger interrupt into int pin1 */ - lis.cfg.pin1.wtm = 1; /* trigger upon FIFO watermark level reached */ + lis.cfg.fifo.size = 20; - lis.cfg.en_adc =1; - lis.cfg.en_temp = 1; - /* write device config */ if (lis3dh_configure(&lis)) { - quit("configure()", &lis); + puts("configure()"); } - - /* wait for interrupt from LIS3DH */ - if (int_poll(GPIO_INTERRUPT_PIN)) { - - quit("int_poll()", &lis); + +A: + /* poll fifo register until it reports that the watermark level has + been reached, or that it has overwritten old data, whichever + happens first. */ + if (lis3dh_poll_fifo(&lis)) { + puts("poll_fifo()"); } /* read as many [x y z] sets as specified by watermark level (fth) */ /* copy them to the fifo data struct given below as `fifo' */ - if (lis3dh_read_fifo(&lis, &fifo)) { - quit("read_fifo()", &lis); + if (lis3dh_read_fifo(&lis, &data)) { + puts("read_fifo()"); } - /* above function also writes out the qty of [x y z] sets stored in `fifo' */ - for(k=0; k LIS3DH "SDA" or "SDI" * MISO - GPIO 9 (physical pin 21) => LIS3DH "SDO" - * SCLK - GPIO 11 (physical pin 23) => LIS3DH "SCK" + * SCLK - GPIO 11 (physical pin 23) => LIS3DH "SCL" * CE0 - GPIO 8 (physical pin 24) => LIS3DH "!CS" - * - * Broken for unknown reason on Pi 4 * */ -#define SPI_SPEED 500 * 1000 /* 500 KHz */ - static int fd; -static uint8_t rx[256]; -static uint8_t tx[256]; int spi_init(void) { - uint8_t mode = SPI_MODE_3; + uint8_t mode = SPI_MODE_0; uint8_t bits = 8; uint32_t speed = SPI_SPEED; if ((fd = open(SPI_DEVICE, O_RDWR)) < 0) { - fprintf(stderr, "spi open(%s)\n", SPI_DEVICE); + fprintf(stderr, "spi_init(): open(%s)\n", SPI_DEVICE); return 1; } if (ioctl(fd, SPI_IOC_RD_MODE, &mode) == -1) { - fprintf(stderr, "SPI_IOC_RD_MODE\n"); + fprintf(stderr, "spi_init(): SPI_IOC_RD_MODE\n"); return 1; } if (ioctl(fd, SPI_IOC_WR_MODE, &mode) == -1) { - fprintf(stderr, "SPI_IOC_WR_MODE\n"); + fprintf(stderr, "spi_init(): SPI_IOC_WR_MODE\n"); return 1; } if (ioctl(fd, SPI_IOC_WR_BITS_PER_WORD, &bits) == -1) { - fprintf(stderr, "SPI_IOC_WR_BITS_PER_WORD\n"); + fprintf(stderr, "spi_init(): SPI_IOC_WR_BITS_PER_WORD\n"); return 1; } if (ioctl(fd, SPI_IOC_RD_BITS_PER_WORD, &bits) == -1) { - fprintf(stderr, "SPI_IOC_RD_BITS_PER_WORD\n"); + fprintf(stderr, "spi_init(): SPI_IOC_RD_BITS_PER_WORD\n"); return 1; } if (ioctl(fd, SPI_IOC_WR_MAX_SPEED_HZ, &speed) == -1) { - fprintf(stderr, "SPI_IOC_WR_MAX_SPEED_HZ\n"); + fprintf(stderr, "spi_init(): SPI_IOC_WR_MAX_SPEED_HZ\n"); return 1; } if (ioctl(fd, SPI_IOC_RD_MAX_SPEED_HZ, &speed) == -1) { - fprintf(stderr, "SPI_IOC_RD_MAX_SPEED_HZ\n"); + fprintf(stderr, "spi_init(): SPI_IOC_RD_MAX_SPEED_HZ\n"); return 1; } return 0; } -static int spi_transaction(uint8_t *tx, uint8_t *rx, uint32_t size) { - struct spi_ioc_transfer tr = {0}; - - tr.tx_buf = (unsigned long) tx; - tr.rx_buf = (unsigned long) rx; - tr.len = size; - - return ioctl(fd, SPI_IOC_MESSAGE(1), &tr); -} - int spi_read(uint8_t reg, uint8_t *dst, uint32_t size) { + uint8_t send[2]; + struct spi_ioc_transfer tr[2] = {0}; + /* clear 2 MSbits */ reg &= 0x3F; @@ -102,28 +89,41 @@ int spi_read(uint8_t reg, uint8_t *dst, uint32_t size) { reg |= 0x40; } - tx[0] = reg; + send[0] = reg; + send[1] = 0x00; - if (spi_transaction(tx, rx, size + 1) < 0) { - fprintf(stderr, "spi_read()\n"); + tr[0].tx_buf = (unsigned long) send; + tr[0].rx_buf = (unsigned long) 0; + tr[0].len = 2; + + tr[1].tx_buf = (unsigned long) 0; + tr[1].rx_buf = (unsigned long) dst; + tr[1].len = size; + + if (ioctl(fd, SPI_IOC_MESSAGE(2), tr) < 0) { + fprintf(stderr, "spi_read(): error ioctl()\n"); return 1; } - memcpy(dst, rx + 1, size); - return 0; } int spi_write(uint8_t reg, uint8_t value) { + struct spi_ioc_transfer tr[2] = {0}; /* clear 2 MSbits */ reg &= 0x3F; - tx[0] = reg; - tx[1] = value; + tr[0].tx_buf = (unsigned long) ® + tr[0].rx_buf = (unsigned long) 0; + tr[0].len = 1; - if (spi_transaction(tx, rx, 2) < 0) { - fprintf(stderr, "spi_write()\n"); + tr[1].tx_buf = (unsigned long) &value; + tr[1].rx_buf = (unsigned long) 0; + tr[1].len = 1; + + if (ioctl(fd, SPI_IOC_MESSAGE(2), tr) < 0) { + fprintf(stderr, "spi_write(): error ioctl()\n"); return 1; }