From 180d984e790fb9658410b327e6e2e7f4f4f9dd33 Mon Sep 17 00:00:00 2001 From: Pete Schwamb Date: Mon, 22 May 2017 16:30:19 -0500 Subject: [PATCH] Jostle (#1) * adding twi/i2c drivers * spi comms to mma8451 working * Jostle detection working and reporting via mesh network * Adding config files --- Makefile | 9 ++- bsp/lesson_tracker.h | 2 + requirements.txt | 1 + src/i2c.c | 77 ++++++++++++++++++++++ src/i2c.h | 18 ++++++ src/jostle_detect.c | 111 ++++++++++++++++++++++++++++++++ src/jostle_detect.h | 12 ++++ src/nrf_drv_config.h | 137 ++++++++++++++++++++++++++++++++++++++++ src/sensor.c | 7 +- src/sensor.h | 2 + src/twi_master_config.h | 18 ++++++ 11 files changed, 391 insertions(+), 3 deletions(-) create mode 100644 src/i2c.c create mode 100644 src/i2c.h create mode 100644 src/jostle_detect.c create mode 100644 src/jostle_detect.h create mode 100644 src/nrf_drv_config.h create mode 100644 src/twi_master_config.h diff --git a/Makefile b/Makefile index e760138..ba09e09 100644 --- a/Makefile +++ b/Makefile @@ -94,7 +94,7 @@ remduplicates = $(strip $(if $1,$(firstword $1) $(call remduplicates,$(filter-ou C_SOURCE_FILES += src/main.c src/config.c src/sensor.c src/app_cmd.c \ src/scheduler.c src/proximity.c src/heartbeat.c src/battery.c src/shoe_accel.c \ - src/app_evt.c src/mesh_control.c bsp/bsp.c + src/app_evt.c src/mesh_control.c bsp/bsp.c src/i2c.c src/jostle_detect.c C_SOURCE_FILES += $(COMPONENTS)/libraries/timer/app_timer.c CXX_SOURCE_FILES += $(SIMBLEE_BASE)/libraries/SimbleeBLE/SimbleeBLE.cpp @@ -134,7 +134,9 @@ C_SOURCE_FILES += $(RBC_MESH)/src/rand.c C_SOURCE_FILES += $(COMPONENTS)/ble/common/ble_advdata.c C_SOURCE_FILES += $(COMPONENTS)/toolchain/system_nrf51.c C_SOURCE_FILES += $(COMPONENTS)/softdevice/common/softdevice_handler/softdevice_handler.c - +C_SOURCE_FILES += $(COMPONENTS)/drivers_nrf/twi_master/incubated/twi_hw_master.c +C_SOURCE_FILES += $(COMPONENTS)/drivers_nrf/gpiote/nrf_drv_gpiote.c +C_SOURCE_FILES += $(COMPONENTS)/drivers_nrf/common/nrf_drv_common.c # assembly files common to all targets #ASM_SOURCE_FILES += $(COMPONENTS)/toolchain/gcc/gcc_startup_nrf51.s @@ -162,8 +164,11 @@ INC_PATHS += -I$(COMPONENTS)/toolchain/gcc INC_PATHS += -I$(COMPONENTS)/libraries/util INC_PATHS += -I$(COMPONENTS)/libraries/timer INC_PATHS += -I$(COMPONENTS)/ble/common +INC_PATHS += -I$(COMPONENTS)/drivers_nrf/common INC_PATHS += -I$(COMPONENTS)/drivers_nrf/hal INC_PATHS += -I$(COMPONENTS)/drivers_nrf/pstorage +INC_PATHS += -I$(COMPONENTS)/drivers_nrf/twi_master/incubated/ +INC_PATHS += -I$(COMPONENTS)/drivers_nrf/gpiote INC_PATHS += -I$(COMPONENTS)/toolchain/gcc INC_PATHS += -I$(COMPONENTS)/toolchain diff --git a/bsp/lesson_tracker.h b/bsp/lesson_tracker.h index 4e2ecf6..a5444d3 100644 --- a/bsp/lesson_tracker.h +++ b/bsp/lesson_tracker.h @@ -7,6 +7,8 @@ extern "C" { #define SIMBLEE +#define MMA8541 + #define LEDS_NUMBER 0 #define BUTTONS_NUMBER 0 diff --git a/requirements.txt b/requirements.txt index ed37b1c..a83c305 100644 --- a/requirements.txt +++ b/requirements.txt @@ -1,3 +1,4 @@ ipython pyyaml sensei_client +pyserial diff --git a/src/i2c.c b/src/i2c.c new file mode 100644 index 0000000..cfbe619 --- /dev/null +++ b/src/i2c.c @@ -0,0 +1,77 @@ +/* Copyright (c) 2013 Microsoft Corporation. All Rights Reserved. + * + */ + +#include +#include +#include "twi_master.h" +#include "i2c.h" + +void i2c_init() { + twi_master_init(); +} + +// read n-bytes from i2c register at the given address where subsequent bytes +// are read from incrementally increasing register addresses. +bool i2c_read_data(uint8_t address, uint8_t reg, uint8_t* data, uint8_t len) +{ + + address = address << 1; + + // initialize data to zero so we don't return random values. + for (int i = 0; i < len; i++) + { + data[i] = 0; + } + + // Write: register address we want to start reading from + if (twi_master_transfer(address, ®, 1, TWI_DONT_ISSUE_STOP)) + { + // Read: the number of bytes requested. + if (twi_master_transfer(address | TWI_READ_BIT, data, len, TWI_ISSUE_STOP)) + { + // Read succeeded. + return true; + } + } + + // read or write failed. + return false; +} + +// read the i2c register at the given address (see table 13 in the LSM9DS0 spec) +// first we write the register address to tell the device to prepare that value +// then we read 1 byte in response from the same i2c device. +uint8_t i2c_read_reg(uint8_t address, uint8_t reg) +{ + uint8_t data = 0; + + if (i2c_read_data(address, reg, &data, 1)) + { + return data; + } + return 0; +} + + +// write 1 byte to the i2c register at the given address (see table 11 in the LSM9DS0 spec) +bool i2c_write_reg(uint8_t address, uint8_t reg, uint8_t value) +{ + uint8_t data[2]; + data[0] = reg; + data[1] = value; + + address = address << 1; + + // Write: register protocol + if (twi_master_transfer(address, data, 2, TWI_ISSUE_STOP)) + { + return true; + } + + // read or write failed. + return false; +} + + +/*lint --flb "Leave library region" */ diff --git a/src/i2c.h b/src/i2c.h new file mode 100644 index 0000000..2596bfa --- /dev/null +++ b/src/i2c.h @@ -0,0 +1,18 @@ +#ifndef _SENSEI_I2C_H +#define _SENSEI_I2C_H + +void i2c_init(); + +// read n-bytes from i2c register at the given address where subsequent bytes +// are read from incrementally increasing register addresses. +bool i2c_read_data(uint8_t address, uint8_t reg, uint8_t* data, uint8_t len); + +// read the i2c register at the given address +// first we write the register address to tell the device to prepare that value +// then we read 1 byte in response from the same i2c device. +uint8_t i2c_read_reg(uint8_t address, uint8_t reg); + +// write 1 byte to the i2c register at the given address +bool i2c_write_reg(uint8_t address, uint8_t reg, uint8_t value); + +#endif // _SENSEI_I2C_H diff --git a/src/jostle_detect.c b/src/jostle_detect.c new file mode 100644 index 0000000..6fe3724 --- /dev/null +++ b/src/jostle_detect.c @@ -0,0 +1,111 @@ + +#include "jostle_detect.h" + +#ifdef MMA8541 + +#include "nrf_drv_gpiote.h" +#include "i2c.h" +#include "app_error.h" + +#define MMA8451_DEFAULT_ADDRESS (0x1C) // if A is GND, it's 0x1C + +#define MMA8451_REG_OUT_X_MSB 0x01 +#define MMA8451_REG_SYSMOD 0x0B +#define MMA8451_REG_WHOAMI 0x0D +#define MMA8451_REG_XYZ_DATA_CFG 0x0E +#define MMA8451_REG_PL_STATUS 0x10 +#define MMA8451_REG_PL_CFG 0x11 +#define MMA8451_REG_FF_MT_CFG 0x15 +#define MMA8451_REG_FF_MT_SRC 0x16 +#define MMA8451_REG_FF_MT_THS 0x17 +#define MMA8451_REG_FF_MT_COUNT 0x18 +#define MMA8451_REG_CTRL_REG1 0x2A +#define MMA8451_REG_CTRL_REG2 0x2B +#define MMA8451_REG_CTRL_REG4 0x2D +#define MMA8451_REG_CTRL_REG5 0x2E + +#define INT_EN_FF_MT (1<<2) +#define INT_EN_PULSE (1<<3) + +#define INT1_GPIO_PIN 24 +#define INT2_GPIO_PIN 22 + +static bool jostle_detected; + +typedef enum +{ + MMA8451_RANGE_8_G = 0b10, // +/- 8g + MMA8451_RANGE_4_G = 0b01, // +/- 4g + MMA8451_RANGE_2_G = 0b00 // +/- 2g (default value) +} mma8451_range_t; + +#define MMA8451_HIGH_PASS_FILTER 0b10000 + +static bool write_register(uint8_t reg, uint8_t value) { + return i2c_write_reg(MMA8451_DEFAULT_ADDRESS, reg, value); +} + +static uint8_t read_register(uint8_t reg) { + return i2c_read_reg(MMA8451_DEFAULT_ADDRESS, reg); +} + +void motion_handler(nrf_drv_gpiote_pin_t pin, nrf_gpiote_polarity_t action) +{ + read_register(MMA8451_REG_FF_MT_SRC); + jostle_detected = true; +} + +void jostle_detect_init() { + i2c_init(); + + ret_code_t err_code; + + err_code = nrf_drv_gpiote_init(); + APP_ERROR_CHECK(err_code); + + nrf_drv_gpiote_in_config_t in_config = GPIOTE_CONFIG_IN_SENSE_TOGGLE(true); + in_config.pull = NRF_GPIO_PIN_PULLUP; + + err_code = nrf_drv_gpiote_in_init(INT1_GPIO_PIN, &in_config, motion_handler); + APP_ERROR_CHECK(err_code); + + nrf_drv_gpiote_in_event_enable(INT1_GPIO_PIN, true); + + // Configure mma8451 + write_register(MMA8451_REG_CTRL_REG2, 0x40); // reset + while (read_register(MMA8451_REG_CTRL_REG2) & 0x40); + + // enable 4G range + write_register(MMA8451_REG_XYZ_DATA_CFG, MMA8451_RANGE_4_G); + // High res + write_register(MMA8451_REG_CTRL_REG2, 0x02); + + // Setup motion detection + write_register(MMA8451_REG_FF_MT_CFG, 0b11111000); // Enable motion, and x,y,z + write_register(MMA8451_REG_FF_MT_THS, 17); // Threshold: 17 * 0.063g = 1.071g + write_register(MMA8451_REG_FF_MT_COUNT, 15); // debounce counter: 15 * 1.25ms = 18.75ms + + // Setup interrupts + write_register(MMA8451_REG_CTRL_REG4, INT_EN_FF_MT | INT_EN_PULSE); // Enable Freefall/Motion int, and pulse + write_register(MMA8451_REG_CTRL_REG5, 0b00000100); // Route motion to INT1 + + // Turn on orientation config + //write_register(MMA8451_REG_PL_CFG, 0x40); + + // ASLP_RATE = 50hz + // ODR = 800hz (1.25ms period) + // LNOISE = 1 + // F_READ = normal + // ACTIVE = active + write_register(MMA8451_REG_CTRL_REG1, 0b00000101); +} + +bool jostle_detect_get_flag() { + return jostle_detected; +} + +void jostle_detect_clear_flag() { + jostle_detected = false; +} + +#endif // MMA8541 diff --git a/src/jostle_detect.h b/src/jostle_detect.h new file mode 100644 index 0000000..ba51f41 --- /dev/null +++ b/src/jostle_detect.h @@ -0,0 +1,12 @@ +#ifndef JOSTLE_DETECT_H +#define JOSTLE_DETECT_H + +#include "stdint.h" +#include "boards.h" + +void jostle_detect_init(); +bool jostle_detect_get_flag(); +void jostle_detect_clear_flag(); + + +#endif // JOSTLE_DETECT_H diff --git a/src/nrf_drv_config.h b/src/nrf_drv_config.h new file mode 100644 index 0000000..4cffefe --- /dev/null +++ b/src/nrf_drv_config.h @@ -0,0 +1,137 @@ +/* Copyright (c) 2015 Nordic Semiconductor. All Rights Reserved. + * + * The information contained herein is property of Nordic Semiconductor ASA. + * Terms and conditions of usage are described in detail in NORDIC + * SEMICONDUCTOR STANDARD SOFTWARE LICENSE AGREEMENT. + * + * Licensees are granted free, non-transferable use of the information. NO + * WARRANTY of ANY KIND is provided. This heading must NOT be removed from + * the file. + * + */ + +#ifndef NRF_DRV_CONFIG_H +#define NRF_DRV_CONFIG_H + +/* CLOCK */ +#define CLOCK_CONFIG_XTAL_FREQ NRF_CLOCK_XTALFREQ_16MHz +#define CLOCK_CONFIG_LF_SRC NRF_CLOCK_LF_SRC_Xtal +#define CLOCK_CONFIG_LF_RC_CAL_INTERVAL RC_2000MS_CALIBRATION_INTERVAL +#define CLOCK_CONFIG_IRQ_PRIORITY APP_IRQ_PRIORITY_LOW + +/* GPIOTE */ +#define GPIOTE_ENABLED 1 + +#if (GPIOTE_ENABLED == 1) +#define GPIOTE_CONFIG_USE_SWI_EGU false +#define GPIOTE_CONFIG_IRQ_PRIORITY APP_IRQ_PRIORITY_HIGH +#define GPIOTE_CONFIG_NUM_OF_LOW_POWER_EVENTS 1 +#endif + +/* TIMER */ +#define TIMER0_ENABLED 0 + +#if (TIMER0_ENABLED == 1) +#define TIMER0_CONFIG_FREQUENCY NRF_TIMER_FREQ_16MHz +#define TIMER0_CONFIG_MODE TIMER_MODE_MODE_Timer +#define TIMER0_CONFIG_BIT_WIDTH TIMER_BITMODE_BITMODE_32Bit +#define TIMER0_CONFIG_IRQ_PRIORITY APP_IRQ_PRIORITY_LOW + +#define TIMER0_INSTANCE_INDEX 0 +#endif + +#define TIMER1_ENABLED 0 + +#if (TIMER1_ENABLED == 1) +#define TIMER1_CONFIG_FREQUENCY NRF_TIMER_FREQ_16MHz +#define TIMER1_CONFIG_MODE TIMER_MODE_MODE_Timer +#define TIMER1_CONFIG_BIT_WIDTH TIMER_BITMODE_BITMODE_16Bit +#define TIMER1_CONFIG_IRQ_PRIORITY APP_IRQ_PRIORITY_LOW + +#define TIMER1_INSTANCE_INDEX (TIMER0_ENABLED) +#endif + +#define TIMER2_ENABLED 0 + +#if (TIMER2_ENABLED == 1) +#define TIMER2_CONFIG_FREQUENCY NRF_TIMER_FREQ_16MHz +#define TIMER2_CONFIG_MODE TIMER_MODE_MODE_Timer +#define TIMER2_CONFIG_BIT_WIDTH TIMER_BITMODE_BITMODE_16Bit +#define TIMER2_CONFIG_IRQ_PRIORITY APP_IRQ_PRIORITY_LOW + +#define TIMER2_INSTANCE_INDEX (TIMER1_ENABLED+TIMER0_ENABLED) +#endif + +#define TIMER_COUNT (TIMER0_ENABLED + TIMER1_ENABLED + TIMER2_ENABLED) + +/* RTC */ +#define RTC0_ENABLED 0 + +#if (RTC0_ENABLED == 1) +#define RTC0_CONFIG_FREQUENCY 32678 +#define RTC0_CONFIG_IRQ_PRIORITY APP_IRQ_PRIORITY_LOW +#define RTC0_CONFIG_RELIABLE false + +#define RTC0_INSTANCE_INDEX 0 +#endif + +#define RTC1_ENABLED 0 + +#if (RTC1_ENABLED == 1) +#define RTC1_CONFIG_FREQUENCY 32768 +#define RTC1_CONFIG_IRQ_PRIORITY APP_IRQ_PRIORITY_LOW +#define RTC1_CONFIG_RELIABLE false + +#define RTC1_INSTANCE_INDEX (RTC0_ENABLED) +#endif + +#define RTC_COUNT (RTC0_ENABLED+RTC1_ENABLED) + +#define NRF_MAXIMUM_LATENCY_US 2000 + +/* RNG */ +#define RNG_ENABLED 0 + +#if (RNG_ENABLED == 1) +#define RNG_CONFIG_ERROR_CORRECTION true +#define RNG_CONFIG_POOL_SIZE 8 +#define RNG_CONFIG_IRQ_PRIORITY APP_IRQ_PRIORITY_LOW +#endif + + +/* QDEC */ +#define QDEC_ENABLED 0 + +#if (QDEC_ENABLED == 1) +#define QDEC_CONFIG_REPORTPER NRF_QDEC_REPORTPER_10 +#define QDEC_CONFIG_SAMPLEPER NRF_QDEC_SAMPLEPER_16384us +#define QDEC_CONFIG_PIO_A 1 +#define QDEC_CONFIG_PIO_B 2 +#define QDEC_CONFIG_PIO_LED 3 +#define QDEC_CONFIG_LEDPRE 511 +#define QDEC_CONFIG_LEDPOL NRF_QDEC_LEPOL_ACTIVE_HIGH +#define QDEC_CONFIG_IRQ_PRIORITY APP_IRQ_PRIORITY_LOW +#define QDEC_CONFIG_DBFEN false +#define QDEC_CONFIG_SAMPLE_INTEN false +#endif + +/* LPCOMP */ +#define LPCOMP_ENABLED 0 + +#if (LPCOMP_ENABLED == 1) +#define LPCOMP_CONFIG_REFERENCE NRF_LPCOMP_REF_SUPPLY_FOUR_EIGHT +#define LPCOMP_CONFIG_DETECTION NRF_LPCOMP_DETECT_DOWN +#define LPCOMP_CONFIG_IRQ_PRIORITY APP_IRQ_PRIORITY_LOW +#define LPCOMP_CONFIG_INPUT NRF_LPCOMP_INPUT_0 +#endif + +/* WDT */ +#define WDT_ENABLED 0 + +#if (WDT_ENABLED == 1) +#define WDT_CONFIG_BEHAVIOUR NRF_WDT_BEHAVIOUR_RUN_SLEEP +#define WDT_CONFIG_RELOAD_VALUE 2000 +#define WDT_CONFIG_IRQ_PRIORITY APP_IRQ_PRIORITY_HIGH +#endif + +#endif // NRF_DRV_CONFIG_H diff --git a/src/sensor.c b/src/sensor.c index 4dd47cd..5cf2811 100644 --- a/src/sensor.c +++ b/src/sensor.c @@ -5,6 +5,7 @@ #include "rbc_mesh.h" #include "scheduler.h" #include "battery.h" +#include "jostle_detect.h" #include "handles.h" #include "shoe_accel.h" #include @@ -16,6 +17,7 @@ void sensor_init() { #ifdef ACCEL_ADXL337 shoe_accel_init(); #endif + jostle_detect_init(); uint32_t error_code; error_code = rbc_mesh_value_enable(SENSOR_HANDLE); @@ -32,7 +34,10 @@ void gather_sensor_data() { memset(&m_value, 0, sizeof(sensor_value_t)); m_value.valid_time = get_clock_time(); m_value.battery = get_battery_adc(); - //m_value.status = ?? + if (jostle_detect_get_flag()) { + m_value.status |= STATUS_FLAG_JOSTLE_DETECTED; + jostle_detect_clear_flag(); + } #ifdef ACCEL_ADXL337 read_shoe_accel(&m_value.accel_x, &m_value.accel_y, &m_value.accel_z); diff --git a/src/sensor.h b/src/sensor.h index 310b6fa..9393fd0 100644 --- a/src/sensor.h +++ b/src/sensor.h @@ -8,6 +8,8 @@ #define MAX_SENSOR_ID = 64 +#define STATUS_FLAG_JOSTLE_DETECTED (1<<0) + typedef __packed_armcc struct { uint8_t proximity_ids[MAX_PROXIMITY_TRACKING_COUNT]; diff --git a/src/twi_master_config.h b/src/twi_master_config.h new file mode 100644 index 0000000..382f629 --- /dev/null +++ b/src/twi_master_config.h @@ -0,0 +1,18 @@ +/* Copyright (c) 2012 Nordic Semiconductor. All Rights Reserved. + * + * The information contained herein is property of Nordic Semiconductor ASA. + * Terms and conditions of usage are described in detail in NORDIC + * SEMICONDUCTOR STANDARD SOFTWARE LICENSE AGREEMENT. + * + * Licensees are granted free, non-transferable use of the information. NO + * WARRANTY of ANY KIND is provided. This heading must NOT be removed from + * the file. + * + */ +#ifndef TWI_MASTER_CONFIG +#define TWI_MASTER_CONFIG + +#define TWI_MASTER_CONFIG_CLOCK_PIN_NUMBER (14U) +#define TWI_MASTER_CONFIG_DATA_PIN_NUMBER (13U) + +#endif