diff --git a/apps/accelerometer-test/app.c b/apps/accelerometer-test/app.c index 1f7803c..1a3acaf 100644 --- a/apps/accelerometer-test/app.c +++ b/apps/accelerometer-test/app.c @@ -24,17 +24,13 @@ static void cb_tick(void) { if (!lis2dw_have_new_data()) return; watch_set_indicator(WATCH_INDICATOR_SIGNAL); - lis2dw_reading raw_reading; - lis2dw_acceleration_measurement measurement = lis2dw_get_acceleration_measurement(&raw_reading); - printf("%f, %f, %f\n", measurement.x, measurement.y, measurement.z); - char buf[128]; - sprintf(buf, "%f, %f, %f\n", measurement.x, measurement.y, measurement.z); - watch_debug_puts(buf); + lis2dw_fifo_t fifo; + bool overrun = lis2dw_read_fifo(&fifo); + printf("FIFO captured %d readings.\n", fifo.count); + if (overrun) printf("\tThere was an overrun!\n\n"); } void app_init(void) { - watch_enable_debug_uart(460800); // this is glitchy now, but this enables a baud rate of 115200 when USB is disabled. - watch_enable_display(); watch_display_string("AC Strean", 0); @@ -45,12 +41,14 @@ void app_init(void) { watch_enable_i2c(); lis2dw_begin(); - lis2dw_set_data_rate(LIS2DW_DATA_RATE_25_HZ); // is this enough for training? - lis2dw_set_low_noise_mode(true); // consumes a little more power lis2dw_set_low_power_mode(LIS2DW_LP_MODE_2); // lowest power 14-bit mode, 25 Hz is 3.5 µA @ 1.8V w/ low noise, 3µA without + lis2dw_set_low_noise_mode(true); // consumes a little more power lis2dw_set_range(LIS2DW_CTRL6_VAL_RANGE_4G); + lis2dw_set_data_rate(LIS2DW_DATA_RATE_25_HZ); // is this enough for training? - watch_rtc_register_periodic_callback(cb_tick, 64); + lis2dw_enable_fifo(); + + watch_rtc_register_periodic_callback(cb_tick, 1); } void app_wake_from_backup(void) { diff --git a/watch-library/shared/driver/lis2dw.c b/watch-library/shared/driver/lis2dw.c index 6e1ac56..fce266b 100644 --- a/watch-library/shared/driver/lis2dw.c +++ b/watch-library/shared/driver/lis2dw.c @@ -50,10 +50,10 @@ bool lis2dw_have_new_data(void) { return retval & LIS2DW_STATUS_VAL_DRDY; } -lis2dw_reading lis2dw_get_raw_reading(void) { +lis2dw_reading_t lis2dw_get_raw_reading(void) { uint8_t buffer[6]; uint8_t reg = LIS2DW_REG_OUT_X_L | 0x80; // set high bit for consecutive reads - lis2dw_reading retval; + lis2dw_reading_t retval; watch_i2c_send(LIS2DW_ADDRESS, ®, 1); watch_i2c_receive(LIS2DW_ADDRESS, (uint8_t *)&buffer, 6); @@ -68,8 +68,8 @@ lis2dw_reading lis2dw_get_raw_reading(void) { return retval; } - lis2dw_acceleration_measurement lis2dw_get_acceleration_measurement(lis2dw_reading *out_reading) { - lis2dw_reading reading = lis2dw_get_raw_reading(); + lis2dw_acceleration_measurement_t lis2dw_get_acceleration_measurement(lis2dw_reading_t *out_reading) { + lis2dw_reading_t reading = lis2dw_get_raw_reading(); uint8_t range = lis2dw_get_range(); if (out_reading != NULL) *out_reading = reading; @@ -82,7 +82,7 @@ lis2dw_reading lis2dw_get_raw_reading(void) { if (range == LIS2DW_RANGE_8_G) lsb_value = 16; if (range == LIS2DW_RANGE_16_G) lsb_value = 48; - lis2dw_acceleration_measurement retval; + lis2dw_acceleration_measurement_t retval; retval.x = lsb_value * ((float)reading.x / 64000.0); retval.y = lsb_value * ((float)reading.y / 64000.0); @@ -104,7 +104,6 @@ lis2dw_range_t lis2dw_get_range(void) { return (lis2dw_range_t)retval; } - void lis2dw_set_data_rate(lis2dw_data_rate_t dataRate) { uint8_t val = watch_i2c_read8(LIS2DW_ADDRESS, LIS2DW_REG_CTRL1) & ~(0b1111 << 4); uint8_t bits = dataRate << 4; @@ -137,3 +136,31 @@ void lis2dw_set_low_noise_mode(bool on) { bool lis2dw_get_low_noise_mode(void) { return (watch_i2c_read8(LIS2DW_ADDRESS, LIS2DW_REG_CTRL1) & LIS2DW_CTRL6_VAL_LOW_NOISE) != 0; } + +inline void lis2dw_disable_fifo(void) { + watch_i2c_write8(LIS2DW_ADDRESS, LIS2DW_REG_FIFO_CTRL, LIS2DW_FIFO_CTRL_MODE_OFF); +} + +inline void lis2dw_enable_fifo(void) { + watch_i2c_write8(LIS2DW_ADDRESS, LIS2DW_REG_FIFO_CTRL, LIS2DW_FIFO_CTRL_MODE_COLLECT_AND_STOP | LIS2DW_FIFO_CTRL_FTH); +} + +bool lis2dw_read_fifo(lis2dw_fifo_t *fifo_data) { + uint8_t temp = watch_i2c_read8(LIS2DW_ADDRESS, LIS2DW_REG_FIFO_SAMPLE); + bool overrun = !!(temp & LIS2DW_FIFO_SAMPLE_OVERRUN); + uint8_t buffer[6]; + + fifo_data->count = temp & LIS2DW_FIFO_SAMPLE_COUNT; + + for(int i = 0; i < fifo_data->count; i++) { + watch_i2c_receive(LIS2DW_ADDRESS, (uint8_t *)&buffer, 6); + fifo_data->readings[i] = lis2dw_get_raw_reading(); + } + + return overrun; +} + +void lis2dw_clear_fifo(void) { + watch_i2c_write8(LIS2DW_ADDRESS, LIS2DW_REG_FIFO_CTRL, LIS2DW_FIFO_CTRL_MODE_OFF); + watch_i2c_write8(LIS2DW_ADDRESS, LIS2DW_REG_FIFO_CTRL, LIS2DW_FIFO_CTRL_MODE_COLLECT_AND_STOP | LIS2DW_FIFO_CTRL_FTH); +} diff --git a/watch-library/shared/driver/lis2dw.h b/watch-library/shared/driver/lis2dw.h index 22b4484..4161117 100644 --- a/watch-library/shared/driver/lis2dw.h +++ b/watch-library/shared/driver/lis2dw.h @@ -32,13 +32,18 @@ typedef struct { int16_t x; int16_t y; int16_t z; -} lis2dw_reading; +} lis2dw_reading_t; typedef struct { float x; float y; float z; -} lis2dw_acceleration_measurement; +} lis2dw_acceleration_measurement_t; + +typedef struct { + int8_t count; + lis2dw_reading_t readings[32]; +} lis2dw_fifo_t; typedef enum { LIS2DW_DATA_RATE_POWERDOWN = 0, @@ -60,6 +65,14 @@ typedef enum { LIS2DW_MODE_ON_DEMAND = 0b10, } lis2dw_mode_t; +typedef enum { + LIS2DW_FIFO_MODE_OFF = 0b000, + LIS2DW_FIFO_MODE_COLLECT_AND_STOP = 0b001, + LIS2DW_FIFO_MODE_CONTINUOUS_TO_FIFO = 0b011, + LIS2DW_FIFO_MODE_BYPASS_TO_CONTINUOUS = 0b100, + LIS2DW_FIFO_MODE_COLLECT_CONTINUOUS = 0b110, +} lis2dw_fifo_mode_t; + typedef enum { LIS2DW_LP_MODE_1 = 0b00, // 12-bit LIS2DW_LP_MODE_2 = 0b01, // 14-bit @@ -177,7 +190,17 @@ typedef enum { #define LIS2DW_REG_OUT_Z_H 0x2D #define LIS2DW_REG_FIFO_CTRL 0x2E -#define LIS2DW_REG_FIFO_SRC 0x2F +#define LIS2DW_FIFO_CTRL_MODE_OFF (LIS2DW_FIFO_MODE_OFF << 5) +#define LIS2DW_FIFO_CTRL_MODE_COLLECT_AND_STOP (LIS2DW_FIFO_MODE_COLLECT_AND_STOP << 5) +#define LIS2DW_FIFO_CTRL_MODE_CONTINUOUS_TO_FIFO (LIS2DW_FIFO_MODE_CONTINUOUS_TO_FIFO << 5) +#define LIS2DW_FIFO_CTRL_MODE_BYPASS_TO_CONTINUOUS (LIS2DW_FIFO_MODE_BYPASS_TO_CONTINUOUS << 5) +#define LIS2DW_FIFO_CTRL_MODE_COLLECT_CONTINUOUS (LIS2DW_FIFO_MODE_COLLECT_CONTINUOUS << 5) +#define LIS2DW_FIFO_CTRL_FTH (0b00011111) + +#define LIS2DW_REG_FIFO_SAMPLE 0x2F +#define LIS2DW_FIFO_SAMPLE_THRESHOLD (1 << 7) +#define LIS2DW_FIFO_SAMPLE_OVERRUN (1 << 6) +#define LIS2DW_FIFO_SAMPLE_COUNT (0b00111111) #define LIS2DW_REG_TAP_THS_X 0x30 #define LIS2DW_REG_TAP_THS_Y 0x31 @@ -242,9 +265,9 @@ uint8_t lis2dw_get_device_id(void); bool lis2dw_have_new_data(void); -lis2dw_reading lis2dw_get_raw_reading(void); +lis2dw_reading_t lis2dw_get_raw_reading(void); -lis2dw_acceleration_measurement lis2dw_get_acceleration_measurement(lis2dw_reading *out_reading); +lis2dw_acceleration_measurement_t lis2dw_get_acceleration_measurement(lis2dw_reading_t *out_reading); void lis2dw_set_range(lis2dw_range_t range); @@ -262,4 +285,12 @@ void lis2dw_set_low_noise_mode(bool on); bool lis2dw_get_low_noise_mode(void); +void lis2dw_disable_fifo(void); + +void lis2dw_enable_fifo(void); + +bool lis2dw_read_fifo(lis2dw_fifo_t *fifo_data); + +void lis2dw_clear_fifo(void); + #endif // LIS2DW_H