tidying and testing new functions

This commit is contained in:
William Clark 2023-12-29 23:24:15 +00:00
parent 9c3f912d1a
commit 30508a8378
4 changed files with 62 additions and 93 deletions

View File

@ -1,7 +1,8 @@
CC=gcc CC=gcc
CFLAGS=-O2 -std=c89 -W -Werror -Wall -Wextra -pedantic -I. CFLAGS=-O0 -g3 -ggdb -std=c89 -W -Werror -Wall -Wextra -Wpedantic -pedantic-errors -Wformat-signedness -I.
CFLAGS+=-Wlogical-op -Wmissing-declarations -Wswitch-default -Wundef -Wformat=2
LFLAGS=-lm LFLAGS=-lm
CFILES=$(wildcard ./*.c) CFILES=$(wildcard *.c)
all: all:
$(CC) $(CFLAGS) $(CFILES) -o lis3dh $(LFLAGS) $(CC) $(CFLAGS) $(CFILES) -o lis3dh $(LFLAGS)

View File

@ -30,6 +30,8 @@ int deinit(void);
``` ```
All above functions return `0` on success. All above functions return `0` on success.
The `init` and `deinit` pointers can both be set to `NULL` and they won't be run.
## Usage ## Usage
Simple example: Simple example:
```c ```c
@ -146,6 +148,7 @@ x: 0.518000, y: -0.846000, z: -0.100000
Instead of polling for every single [x y z] set, a FIFO with programmable capacity ("watermark") can be used like such: Instead of polling for every single [x y z] set, a FIFO with programmable capacity ("watermark") can be used like such:
All FIFO readings use 10-bit resolution regardless of the mode set in `lis.cfg.mode`. All FIFO readings use 10-bit resolution regardless of the mode set in `lis.cfg.mode`.
The watermark level can also be adjusted to a value [0-31] inclusive by modifying the `lis.cfg.fifo.fth` property before calling configure(). The watermark level can also be adjusted to a value [0-31] inclusive by modifying the `lis.cfg.fifo.fth` property before calling configure().
```c ```c
#define _GNU_SOURCE #define _GNU_SOURCE

105
lis3dh.c
View File

@ -1,3 +1,5 @@
#include <stddef.h>
#include <string.h>
#include "lis3dh.h" #include "lis3dh.h"
#include "registers.h" #include "registers.h"
@ -38,8 +40,11 @@ int lis3dh_init(lis3dh_t *lis3dh) {
uint8_t result; uint8_t result;
int err = 0; int err = 0;
if (lis3dh->dev.init() != 0) { /* if init has been given, check it */
return 1; if (lis3dh->dev.init != NULL) {
if (lis3dh->dev.init() != 0) {
return 1;
}
} }
err |= lis3dh->dev.read(REG_WHO_AM_I, &result, 1); err |= lis3dh->dev.read(REG_WHO_AM_I, &result, 1);
@ -97,10 +102,10 @@ int lis3dh_configure(lis3dh_t *lis3dh) {
int err = 0; int err = 0;
/* the 0x07 enables Z, Y and X axis in that order */ /* the 0x07 enables Z, Y and X axis in that order */
ctrl_reg1 = 0 | (lis3dh->cfg.rate << 4) | 0x07; ctrl_reg1 = (lis3dh->cfg.rate << 4) | 0x07;
ctrl_reg2 = 0; ctrl_reg2 = 0;
ctrl_reg3 = 0; ctrl_reg3 = 0;
ctrl_reg4 = 0 | (lis3dh->cfg.range << 4); ctrl_reg4 = (lis3dh->cfg.range << 4);
ctrl_reg5 = 0; ctrl_reg5 = 0;
ctrl_reg6 = 0; ctrl_reg6 = 0;
fifo_ctrl_reg = 0; fifo_ctrl_reg = 0;
@ -204,77 +209,36 @@ int lis3dh_poll_fifo(lis3dh_t *lis3dh) {
/* the real size of the int you get back from reading the acc u16 /* the real size of the int you get back from reading the acc u16
depends on the power mode. depends on the power mode.
shift down the 16 bit word by this amount: */ shift down the 16 bit word by this amount: */
static uint8_t acc_shift(lis3dh_t *lis3dh) { static uint8_t acc_shift(uint8_t mode) {
switch (lis3dh->cfg.mode) { switch (mode) {
case LIS3DH_MODE_HR: case LIS3DH_MODE_HR: return 4; /* i12 */
return 4; /* i12 */ case LIS3DH_MODE_NORMAL: return 6; /* i10 */
case LIS3DH_MODE_NORMAL: case LIS3DH_MODE_LP: return 8; /* i8 */
return 6; /* i10 */ default: return 0;
case LIS3DH_MODE_LP:
return 8; /* i8 */
} }
return 0;
} }
/* returns a scalar that when multiplied with axis reading /* returns a scalar that when multiplied with axis reading
turns it to a multiple of mg. */ turns it to a multiple of mg. */
static uint8_t acc_sensitivity(lis3dh_t *lis3dh) { static uint8_t acc_sensitivity(uint8_t mode, uint8_t range) {
uint8_t mode = lis3dh->cfg.mode; switch (range) {
case LIS3DH_FS_2G: return (mode == LIS3DH_MODE_LP) ? 16 : (mode == LIS3DH_MODE_NORMAL) ? 4 : 1;
switch (lis3dh->cfg.range) { case LIS3DH_FS_4G: return (mode == LIS3DH_MODE_LP) ? 32 : (mode == LIS3DH_MODE_NORMAL) ? 8 : 2;
case LIS3DH_FS_2G: case LIS3DH_FS_8G: return (mode == LIS3DH_MODE_LP) ? 64 : (mode == LIS3DH_MODE_NORMAL) ? 16 : 4;
if (mode == LIS3DH_MODE_LP) { case LIS3DH_FS_16G: return (mode == LIS3DH_MODE_LP) ? 192 : (mode == LIS3DH_MODE_NORMAL) ? 48 : 12;
return 16; default: return 0;
} else if (mode == LIS3DH_MODE_NORMAL) {
return 4;
} else {
return 1;
}
break;
case LIS3DH_FS_4G:
if (mode == LIS3DH_MODE_LP) {
return 32;
} else if (mode == LIS3DH_MODE_NORMAL) {
return 8;
} else {
return 2;
}
break;
case LIS3DH_FS_8G:
if (mode == LIS3DH_MODE_LP) {
return 64;
} else if (mode == LIS3DH_MODE_NORMAL) {
return 16;
} else {
return 4;
}
break;
case LIS3DH_FS_16G:
if (mode == LIS3DH_MODE_LP) {
return 192;
} else if (mode == LIS3DH_MODE_NORMAL) {
return 48;
} else {
return 12;
}
break;
} }
return 0;
} }
int lis3dh_read(lis3dh_t *lis3dh) { int lis3dh_read(lis3dh_t *lis3dh) {
uint8_t data[6]; uint8_t data[6];
int32_t x, y, z; int32_t x, y, z;
uint8_t scale, sens; uint8_t scale, sens;
int err = 0; int err = 0;
scale = acc_shift(lis3dh); scale = acc_shift(lis3dh->cfg.mode);
sens = acc_sensitivity(lis3dh); sens = acc_sensitivity(lis3dh->cfg.mode, lis3dh->cfg.range);
/* must set MSbit of the address to multi-read and /* must set MSbit of the address to multi-read and
have the device auto-increment the address. */ have the device auto-increment the address. */
@ -301,17 +265,7 @@ int lis3dh_read_fifo(lis3dh_t *lis3dh, struct lis3dh_fifo_data *fifo) {
/* FIFO is always 10-bit */ /* FIFO is always 10-bit */
scale = 6; scale = 6;
sens = acc_sensitivity(lis3dh->cfg.mode, lis3dh->cfg.range);
/* normal mode */
if (lis3dh->cfg.range == LIS3DH_FS_2G) {
sens = 4;
} else if (lis3dh->cfg.range == LIS3DH_FS_4G) {
sens = 8;
} else if (lis3dh->cfg.range == LIS3DH_FS_8G) {
sens = 16;
} else { /* 16G */
sens = 48;
}
/* fifo buffer is max 32 */ /* fifo buffer is max 32 */
fifo->size = lis3dh->cfg.fifo.fth > 32 ? 32 : lis3dh->cfg.fifo.fth; fifo->size = lis3dh->cfg.fifo.fth > 32 ? 32 : lis3dh->cfg.fifo.fth;
@ -334,8 +288,13 @@ int lis3dh_read_fifo(lis3dh_t *lis3dh, struct lis3dh_fifo_data *fifo) {
return err; return err;
} }
/* if NULL, this function doesn't have to be called */
int lis3dh_deinit(lis3dh_t *lis3dh) { int lis3dh_deinit(lis3dh_t *lis3dh) {
return lis3dh->dev.deinit(); if (lis3dh->dev.deinit != NULL) {
return lis3dh->dev.deinit();
}
return 0;
} }
/* read INT1_SRC to clear latched INT1 irq */ /* read INT1_SRC to clear latched INT1 irq */

42
main.c
View File

@ -10,12 +10,12 @@
#define GPIO_INTERRUPT_PIN 12 #define GPIO_INTERRUPT_PIN 12
/* calc magnitude of accel [x y z] vector */ /* calc magnitude of accel [x y z] vector */
float mag(float x, float y, float z) { static float mag(float x, float y, float z) {
return sqrt( powf(x, 2) + powf(y, 2) + powf(z, 2) ); return sqrt( powf(x, 2) + powf(y, 2) + powf(z, 2) );
} }
/* print message then exit */ /* print message then exit */
void quit(const char *msg, lis3dh_t *lis) { static void quit(const char *msg, lis3dh_t *lis) {
lis->dev.deinit(); lis->dev.deinit();
fprintf(stderr, "%s\n", msg); fprintf(stderr, "%s\n", msg);
exit(1); exit(1);
@ -25,7 +25,7 @@ int main() {
lis3dh_t lis; lis3dh_t lis;
struct lis3dh_fifo_data fifo; struct lis3dh_fifo_data fifo;
int k; int i, k;
/* set fn ptrs to rw on bus (i2c or SPI) */ /* set fn ptrs to rw on bus (i2c or SPI) */
lis.dev.init = i2c_init; lis.dev.init = i2c_init;
@ -53,6 +53,8 @@ int main() {
lis.cfg.fifo.trig = LIS3DH_FIFO_TRIG_INT1; lis.cfg.fifo.trig = LIS3DH_FIFO_TRIG_INT1;
lis.cfg.int1.wtm = 1; lis.cfg.int1.wtm = 1;
lis.cfg.int1.latch = 1; lis.cfg.int1.latch = 1;
lis.cfg.filter.mode = LIS3DH_FILTER_MODE_REFERENCE;
lis.cfg.filter.cutoff = LIS3DH_FILTER_CUTOFF_8;
/* write device config */ /* write device config */
@ -60,24 +62,28 @@ int main() {
quit("configure()", &lis); quit("configure()", &lis);
} }
/* wait for interrupt from LIS3DH */ for(i=0; i<50; i++) {
if (int_poll(GPIO_INTERRUPT_PIN)) { /* wait for interrupt from LIS3DH */
quit("int_poll()", &lis); if (int_poll(GPIO_INTERRUPT_PIN)) {
} quit("int_poll()", &lis);
}
if (lis3dh_clear_int1(&lis)) { if (lis3dh_clear_int1(&lis)) {
quit("clear_int1()", &lis); quit("clear_int1()", &lis);
} }
/* read stored fifo data into `fifo' struct */ /* read stored fifo data into `fifo' struct */
if (lis3dh_read_fifo(&lis, &fifo)) { if (lis3dh_read_fifo(&lis, &fifo)) {
quit("read_fifo()", &lis); quit("read_fifo()", &lis);
} }
for(k=0; k<fifo.size; k++) { for(k=0; k<fifo.size; k++) {
printf("%04.04f %04.04f %04.04f %04.04f\n", printf("%04.04f %04.04f %04.04f %04.04f\n",
fifo.x[k], fifo.y[k], fifo.z[k], fifo.x[k], fifo.y[k], fifo.z[k],
mag(fifo.x[k], fifo.y[k], fifo.z[k])); mag(fifo.x[k], fifo.y[k], fifo.z[k]));
}
lis3dh_reference(&lis);
} }
/* unregister interrupt */ /* unregister interrupt */