LIS3DH & BLE broadcast example for VTT Node V3 & mbed
Dependencies: BLE_API TMP_nrf51 mbed nRF51822
main.cpp
- Committer:
- jejuho
- Date:
- 2016-01-25
- Revision:
- 1:bd7fd35251ab
- Parent:
- 0:de3e4a57ebe0
File content as of revision 1:bd7fd35251ab:
/** * LIS3DH & BLE broadcast example for VTT Node V3 & mbed * broadcasts accelerometer xyz values. * Also generates LIS3DH interrupt on position change and lights up leds based on that interrupt. * As a bonus, read temperature values from SOC and transmit those as well. * Juho Eskeli, VTT */ #include "NodeV3PinNames.h" //This should come before mbed.h to override pin configuration #include "mbed.h" #include "ble/BLE.h" #define USE_DFU #ifdef USE_DFU #include "DFUService.h" #endif #include "AT45.h" #include "LIS3DH.h" #include "TMP_nrf51.h" //interrupt /gpio configuration #include "nrf_gpio.h" #include "nrf_gpiote.h" #include "nrf_soc.h" //const static char DEVICE_NAME[] = "BAc0N"; //static const uint16_t uuid16_list[] = {GattService::UUID_STREAMING_SERVICE}; BLE ble; #define MOSI SPI_PSELMOSI0 #define MISO SPI_PSELMISO0 #define CS SPI_PSELSS0 #define SCLK SPI_PSELSCK0 static LIS3DH lis(MOSI, MISO, CS, SCLK); static TMP_nrf51 tempSensor; DigitalOut myled1(LED1); DigitalOut myled2(LED2); DigitalOut LIS_CS_0(CS); //LIS3DH CS DigitalOut AT_CS(p5); //Dataflash CS DigitalOut AT_RS(p6); //Dataflash reset /** @brief Function for initializing the GPIO Tasks/Events peripheral. */ static void gpiote_init(void) { // Configure accelerometer interrupt pin nrf_gpio_cfg_input(3, NRF_GPIO_PIN_PULLDOWN); //nrf_gpio_cfg_input(4, NRF_GPIO_PIN_PULLDOWN); // Configure GPIOTE channel 0 to generate event when MOTION_INTERRUPT_PIN_NUMBER goes from Low to High nrf_gpiote_event_config(0, 3, NRF_GPIOTE_POLARITY_LOTOHI); //accelerometer int1 //nrf_gpiote_event_config(1, 4, NRF_GPIOTE_POLARITY_LOTOHI); //accelerometer int2 // Enable interrupt for NRF_GPIOTE->EVENTS_IN[0] event NRF_GPIOTE->INTENSET = GPIOTE_INTENSET_IN0_Msk; //NRF_GPIOTE->INTENSET |= GPIOTE_INTENSET_IN1_Msk; } extern "C" void GPIOTE_IRQHandler(void) { // Event causing the interrupt must be cleared NRF_GPIOTE->EVENTS_IN[0] = 0; //NRF_GPIOTE->EVENTS_IN[1] = 0; lis.LIS3DH_ResetInt1Latch(); myled1 = !myled1; myled2 = !myled2; } void disconnect_input_buffers() { for(uint8_t i = 0; i < 3; i++) { NRF_GPIO->PIN_CNF[i] = (GPIO_PIN_CNF_SENSE_Disabled << GPIO_PIN_CNF_SENSE_Pos) | (GPIO_PIN_CNF_DRIVE_S0S1 << GPIO_PIN_CNF_DRIVE_Pos) | (GPIO_PIN_CNF_PULL_Disabled << GPIO_PIN_CNF_PULL_Pos) | (GPIO_PIN_CNF_INPUT_Disconnect << GPIO_PIN_CNF_INPUT_Pos) | (GPIO_PIN_CNF_DIR_Output << GPIO_PIN_CNF_DIR_Pos); } //Omit accelerometer interrupt pins (3&4) for(uint8_t i = 5; i < 21; i++) { NRF_GPIO->PIN_CNF[i] = (GPIO_PIN_CNF_SENSE_Disabled << GPIO_PIN_CNF_SENSE_Pos) | (GPIO_PIN_CNF_DRIVE_S0S1 << GPIO_PIN_CNF_DRIVE_Pos) | (GPIO_PIN_CNF_PULL_Disabled << GPIO_PIN_CNF_PULL_Pos) | (GPIO_PIN_CNF_INPUT_Disconnect << GPIO_PIN_CNF_INPUT_Pos) | (GPIO_PIN_CNF_DIR_Output << GPIO_PIN_CNF_DIR_Pos); } //Omit I2C pins (21 & 22) for(uint8_t i = 23; i < 31; i++) { NRF_GPIO->PIN_CNF[i] = (GPIO_PIN_CNF_SENSE_Disabled << GPIO_PIN_CNF_SENSE_Pos) | (GPIO_PIN_CNF_DRIVE_S0S1 << GPIO_PIN_CNF_DRIVE_Pos) | (GPIO_PIN_CNF_PULL_Disabled << GPIO_PIN_CNF_PULL_Pos) | (GPIO_PIN_CNF_INPUT_Disconnect << GPIO_PIN_CNF_INPUT_Pos) | (GPIO_PIN_CNF_DIR_Output << GPIO_PIN_CNF_DIR_Pos); } } __packed struct ApplicationData_t { uint16_t applicationSpecificId; /* An ID used to identify temperature value in the manufacture specific AD data field */ TMP_nrf51::tmpSensorValue_t tmpSensorValue; /* User defined application data */ int8_t accel_temp; AxesRaw_t accel_raw; }; void setupApplicationData(ApplicationData_t &appData) { static const uint16_t APP_SPECIFIC_ID_TEST = 0xFEFE; appData.applicationSpecificId = APP_SPECIFIC_ID_TEST; appData.tmpSensorValue = tempSensor.get(); lis.LIS3DH_GetAccAxesRaw(&appData.accel_raw); lis.LIS3DH_GetTempRaw(&appData.accel_temp); } void disconnectionCallback(const Gap::DisconnectionCallbackParams_t *params) { ble.gap().startAdvertising(); } void senseCallback(void) { ApplicationData_t appData; setupApplicationData(appData); ble.gap().updateAdvertisingPayload(GapAdvertisingData::MANUFACTURER_SPECIFIC_DATA, (uint8_t *)&appData, sizeof(ApplicationData_t)); } void setup_CS_LIS3DH() { //Without this setup CS lines of AT45 & LIS3DH are in conflict, causing huge current consumption LIS_CS_0 = 1; //not selected AT_CS = 1; //not selected AT_RS = 0; //asserted == reset state wait_ms(100); AT_RS = 1; } int main() { //LEDS off myled1 = 0; myled2 = 0; setup_CS_LIS3DH(); //Initialize SPI interface SPI spi(MOSI, MISO, SCLK); // mosi, miso, sclk spi.format(8,3); spi.frequency(8000000); //setup AT45 dataflash to powersaving mode AT45* flash = new AT45(spi, p5); flash->ultra_deep_power_down(true); //Accelerometer interrupt pin configuration gpiote_init(); //Disconnect input buffers to save power disconnect_input_buffers(); //Initialize LIS3DH driver lis.InitLIS3DH(LIS3DH_NORMAL, LIS3DH_ODR_100Hz, LIS3DH_FULLSCALE_2); //Init Acc-sensor //enable threshold to generate interrupt lis.SetLIS3DHActivityDetection(3, LIS3DH_INT_MODE_6D_POSITION, 1); // Enable GPIOTE interrupt in Nested Vector Interrupt Controller. NVIC_ClearPendingIRQ(GPIOTE_IRQn); NRF_GPIOTE->INTENSET = GPIOTE_INTENSET_PORT_Set << GPIOTE_INTENSET_PORT_Pos; NVIC_SetPriority(GPIOTE_IRQn, 1); NVIC_EnableIRQ(GPIOTE_IRQn); //sd_nvic_EnableIRQ(GPIOTE_IRQn); //Initialize BLE stuff ble.init(); ble.gap().onDisconnection(disconnectionCallback); #ifdef USE_DFU DFUService dfu(ble); #endif /* Setup advertising. */ ble.gap().accumulateAdvertisingPayload(GapAdvertisingData::BREDR_NOT_SUPPORTED | GapAdvertisingData::LE_GENERAL_DISCOVERABLE); ble.gap().accumulateAdvertisingPayload(GapAdvertisingData::GENERIC_THERMOMETER); ApplicationData_t appData; setupApplicationData(appData); //ble.gap().accumulateAdvertisingPayload(GapAdvertisingData::COMPLETE_LIST_16BIT_SERVICE_IDS, (uint8_t *)uuid16_list, sizeof(uuid16_list)); //ble.gap().accumulateAdvertisingPayload(GapAdvertisingData::COMPLETE_LOCAL_NAME, (uint8_t *)DEVICE_NAME, sizeof(DEVICE_NAME)); ble.gap().accumulateAdvertisingPayload(GapAdvertisingData::MANUFACTURER_SPECIFIC_DATA, (uint8_t *)&appData, sizeof(ApplicationData_t)); ble.gap().setAdvertisingType(GapAdvertisingParams::ADV_CONNECTABLE_UNDIRECTED); //ble.gap().setAdvertisingType(GapAdvertisingParams::ADV_NON_CONNECTABLE_UNDIRECTED); ble.gap().setAdvertisingInterval(100); /* 1000ms. */ ble.gap().startAdvertising(); Ticker ticker; ticker.attach(senseCallback, 0.1); ///Could have main loop here doing something while(true) { ble.waitForEvent(); } }