LIS3DH & BLE broadcast example for VTT Node V3 & mbed

Dependencies:   BLE_API TMP_nrf51 mbed nRF51822

Committer:
jejuho
Date:
Mon Jan 25 13:27:15 2016 +0000
Revision:
1:bd7fd35251ab
Parent:
0:de3e4a57ebe0
Initial version.

Who changed what in which revision?

UserRevisionLine numberNew contents of line
jejuho 1:bd7fd35251ab 1 /**
jejuho 1:bd7fd35251ab 2 * LIS3DH & BLE broadcast example for VTT Node V3 & mbed
jejuho 1:bd7fd35251ab 3 * broadcasts accelerometer xyz values.
jejuho 1:bd7fd35251ab 4 * Also generates LIS3DH interrupt on position change and lights up leds based on that interrupt.
jejuho 1:bd7fd35251ab 5 * As a bonus, read temperature values from SOC and transmit those as well.
jejuho 1:bd7fd35251ab 6 * Juho Eskeli, VTT
jejuho 1:bd7fd35251ab 7 */
jejuho 1:bd7fd35251ab 8
jejuho 1:bd7fd35251ab 9
jejuho 1:bd7fd35251ab 10 #include "NodeV3PinNames.h" //This should come before mbed.h to override pin configuration
jejuho 0:de3e4a57ebe0 11 #include "mbed.h"
jejuho 0:de3e4a57ebe0 12 #include "ble/BLE.h"
jejuho 0:de3e4a57ebe0 13
jejuho 0:de3e4a57ebe0 14 #define USE_DFU
jejuho 0:de3e4a57ebe0 15
jejuho 0:de3e4a57ebe0 16 #ifdef USE_DFU
jejuho 0:de3e4a57ebe0 17 #include "DFUService.h"
jejuho 0:de3e4a57ebe0 18 #endif
jejuho 0:de3e4a57ebe0 19
jejuho 0:de3e4a57ebe0 20 #include "AT45.h"
jejuho 0:de3e4a57ebe0 21 #include "LIS3DH.h"
jejuho 1:bd7fd35251ab 22 #include "TMP_nrf51.h"
jejuho 0:de3e4a57ebe0 23
jejuho 0:de3e4a57ebe0 24 //interrupt /gpio configuration
jejuho 0:de3e4a57ebe0 25 #include "nrf_gpio.h"
jejuho 0:de3e4a57ebe0 26 #include "nrf_gpiote.h"
jejuho 0:de3e4a57ebe0 27 #include "nrf_soc.h"
jejuho 0:de3e4a57ebe0 28
jejuho 0:de3e4a57ebe0 29 //const static char DEVICE_NAME[] = "BAc0N";
jejuho 0:de3e4a57ebe0 30 //static const uint16_t uuid16_list[] = {GattService::UUID_STREAMING_SERVICE};
jejuho 0:de3e4a57ebe0 31
jejuho 0:de3e4a57ebe0 32 BLE ble;
jejuho 0:de3e4a57ebe0 33
jejuho 1:bd7fd35251ab 34 #define MOSI SPI_PSELMOSI0
jejuho 1:bd7fd35251ab 35 #define MISO SPI_PSELMISO0
jejuho 1:bd7fd35251ab 36 #define CS SPI_PSELSS0
jejuho 1:bd7fd35251ab 37 #define SCLK SPI_PSELSCK0
jejuho 0:de3e4a57ebe0 38 static LIS3DH lis(MOSI, MISO, CS, SCLK);
jejuho 1:bd7fd35251ab 39 static TMP_nrf51 tempSensor;
jejuho 0:de3e4a57ebe0 40
jejuho 1:bd7fd35251ab 41 DigitalOut myled1(LED1);
jejuho 1:bd7fd35251ab 42 DigitalOut myled2(LED2);
jejuho 0:de3e4a57ebe0 43
jejuho 1:bd7fd35251ab 44 DigitalOut LIS_CS_0(CS); //LIS3DH CS
jejuho 1:bd7fd35251ab 45 DigitalOut AT_CS(p5); //Dataflash CS
jejuho 1:bd7fd35251ab 46 DigitalOut AT_RS(p6); //Dataflash reset
jejuho 0:de3e4a57ebe0 47
jejuho 0:de3e4a57ebe0 48 /** @brief Function for initializing the GPIO Tasks/Events peripheral.
jejuho 0:de3e4a57ebe0 49 */
jejuho 0:de3e4a57ebe0 50 static void gpiote_init(void)
jejuho 0:de3e4a57ebe0 51 {
jejuho 1:bd7fd35251ab 52 // Configure accelerometer interrupt pin
jejuho 0:de3e4a57ebe0 53 nrf_gpio_cfg_input(3, NRF_GPIO_PIN_PULLDOWN);
jejuho 0:de3e4a57ebe0 54 //nrf_gpio_cfg_input(4, NRF_GPIO_PIN_PULLDOWN);
jejuho 0:de3e4a57ebe0 55
jejuho 0:de3e4a57ebe0 56 // Configure GPIOTE channel 0 to generate event when MOTION_INTERRUPT_PIN_NUMBER goes from Low to High
jejuho 0:de3e4a57ebe0 57 nrf_gpiote_event_config(0, 3, NRF_GPIOTE_POLARITY_LOTOHI); //accelerometer int1
jejuho 0:de3e4a57ebe0 58 //nrf_gpiote_event_config(1, 4, NRF_GPIOTE_POLARITY_LOTOHI); //accelerometer int2
jejuho 0:de3e4a57ebe0 59
jejuho 0:de3e4a57ebe0 60 // Enable interrupt for NRF_GPIOTE->EVENTS_IN[0] event
jejuho 0:de3e4a57ebe0 61 NRF_GPIOTE->INTENSET = GPIOTE_INTENSET_IN0_Msk;
jejuho 1:bd7fd35251ab 62 //NRF_GPIOTE->INTENSET |= GPIOTE_INTENSET_IN1_Msk;
jejuho 0:de3e4a57ebe0 63 }
jejuho 0:de3e4a57ebe0 64
jejuho 0:de3e4a57ebe0 65 extern "C"
jejuho 0:de3e4a57ebe0 66 void GPIOTE_IRQHandler(void)
jejuho 0:de3e4a57ebe0 67 {
jejuho 0:de3e4a57ebe0 68 // Event causing the interrupt must be cleared
jejuho 0:de3e4a57ebe0 69 NRF_GPIOTE->EVENTS_IN[0] = 0;
jejuho 0:de3e4a57ebe0 70 //NRF_GPIOTE->EVENTS_IN[1] = 0;
jejuho 0:de3e4a57ebe0 71 lis.LIS3DH_ResetInt1Latch();
jejuho 0:de3e4a57ebe0 72
jejuho 0:de3e4a57ebe0 73 myled1 = !myled1;
jejuho 0:de3e4a57ebe0 74 myled2 = !myled2;
jejuho 0:de3e4a57ebe0 75 }
jejuho 0:de3e4a57ebe0 76
jejuho 0:de3e4a57ebe0 77 void disconnect_input_buffers()
jejuho 0:de3e4a57ebe0 78 {
jejuho 0:de3e4a57ebe0 79 for(uint8_t i = 0; i < 3; i++)
jejuho 0:de3e4a57ebe0 80 {
jejuho 0:de3e4a57ebe0 81 NRF_GPIO->PIN_CNF[i] = (GPIO_PIN_CNF_SENSE_Disabled << GPIO_PIN_CNF_SENSE_Pos)
jejuho 0:de3e4a57ebe0 82 | (GPIO_PIN_CNF_DRIVE_S0S1 << GPIO_PIN_CNF_DRIVE_Pos)
jejuho 0:de3e4a57ebe0 83 | (GPIO_PIN_CNF_PULL_Disabled << GPIO_PIN_CNF_PULL_Pos)
jejuho 0:de3e4a57ebe0 84 | (GPIO_PIN_CNF_INPUT_Disconnect << GPIO_PIN_CNF_INPUT_Pos)
jejuho 0:de3e4a57ebe0 85 | (GPIO_PIN_CNF_DIR_Output << GPIO_PIN_CNF_DIR_Pos);
jejuho 0:de3e4a57ebe0 86 }
jejuho 0:de3e4a57ebe0 87 //Omit accelerometer interrupt pins (3&4)
jejuho 0:de3e4a57ebe0 88 for(uint8_t i = 5; i < 21; i++)
jejuho 0:de3e4a57ebe0 89 {
jejuho 0:de3e4a57ebe0 90 NRF_GPIO->PIN_CNF[i] = (GPIO_PIN_CNF_SENSE_Disabled << GPIO_PIN_CNF_SENSE_Pos)
jejuho 0:de3e4a57ebe0 91 | (GPIO_PIN_CNF_DRIVE_S0S1 << GPIO_PIN_CNF_DRIVE_Pos)
jejuho 0:de3e4a57ebe0 92 | (GPIO_PIN_CNF_PULL_Disabled << GPIO_PIN_CNF_PULL_Pos)
jejuho 0:de3e4a57ebe0 93 | (GPIO_PIN_CNF_INPUT_Disconnect << GPIO_PIN_CNF_INPUT_Pos)
jejuho 0:de3e4a57ebe0 94 | (GPIO_PIN_CNF_DIR_Output << GPIO_PIN_CNF_DIR_Pos);
jejuho 0:de3e4a57ebe0 95 }
jejuho 0:de3e4a57ebe0 96 //Omit I2C pins (21 & 22)
jejuho 0:de3e4a57ebe0 97 for(uint8_t i = 23; i < 31; i++)
jejuho 0:de3e4a57ebe0 98 {
jejuho 0:de3e4a57ebe0 99 NRF_GPIO->PIN_CNF[i] = (GPIO_PIN_CNF_SENSE_Disabled << GPIO_PIN_CNF_SENSE_Pos)
jejuho 0:de3e4a57ebe0 100 | (GPIO_PIN_CNF_DRIVE_S0S1 << GPIO_PIN_CNF_DRIVE_Pos)
jejuho 0:de3e4a57ebe0 101 | (GPIO_PIN_CNF_PULL_Disabled << GPIO_PIN_CNF_PULL_Pos)
jejuho 0:de3e4a57ebe0 102 | (GPIO_PIN_CNF_INPUT_Disconnect << GPIO_PIN_CNF_INPUT_Pos)
jejuho 0:de3e4a57ebe0 103 | (GPIO_PIN_CNF_DIR_Output << GPIO_PIN_CNF_DIR_Pos);
jejuho 0:de3e4a57ebe0 104 }
jejuho 0:de3e4a57ebe0 105 }
jejuho 0:de3e4a57ebe0 106
jejuho 0:de3e4a57ebe0 107 __packed struct ApplicationData_t {
jejuho 0:de3e4a57ebe0 108 uint16_t applicationSpecificId; /* An ID used to identify temperature value in the manufacture specific AD data field */
jejuho 1:bd7fd35251ab 109 TMP_nrf51::tmpSensorValue_t tmpSensorValue; /* User defined application data */
jejuho 1:bd7fd35251ab 110 int8_t accel_temp;
jejuho 0:de3e4a57ebe0 111 AxesRaw_t accel_raw;
jejuho 0:de3e4a57ebe0 112 };
jejuho 0:de3e4a57ebe0 113
jejuho 0:de3e4a57ebe0 114 void setupApplicationData(ApplicationData_t &appData)
jejuho 0:de3e4a57ebe0 115 {
jejuho 0:de3e4a57ebe0 116 static const uint16_t APP_SPECIFIC_ID_TEST = 0xFEFE;
jejuho 0:de3e4a57ebe0 117 appData.applicationSpecificId = APP_SPECIFIC_ID_TEST;
jejuho 1:bd7fd35251ab 118 appData.tmpSensorValue = tempSensor.get();
jejuho 0:de3e4a57ebe0 119 lis.LIS3DH_GetAccAxesRaw(&appData.accel_raw);
jejuho 1:bd7fd35251ab 120 lis.LIS3DH_GetTempRaw(&appData.accel_temp);
jejuho 0:de3e4a57ebe0 121 }
jejuho 0:de3e4a57ebe0 122
jejuho 0:de3e4a57ebe0 123 void disconnectionCallback(const Gap::DisconnectionCallbackParams_t *params)
jejuho 0:de3e4a57ebe0 124 {
jejuho 0:de3e4a57ebe0 125 ble.gap().startAdvertising();
jejuho 0:de3e4a57ebe0 126 }
jejuho 0:de3e4a57ebe0 127
jejuho 0:de3e4a57ebe0 128 void senseCallback(void)
jejuho 0:de3e4a57ebe0 129 {
jejuho 0:de3e4a57ebe0 130 ApplicationData_t appData;
jejuho 0:de3e4a57ebe0 131 setupApplicationData(appData);
jejuho 0:de3e4a57ebe0 132 ble.gap().updateAdvertisingPayload(GapAdvertisingData::MANUFACTURER_SPECIFIC_DATA, (uint8_t *)&appData, sizeof(ApplicationData_t));
jejuho 0:de3e4a57ebe0 133 }
jejuho 0:de3e4a57ebe0 134
jejuho 1:bd7fd35251ab 135 void setup_CS_LIS3DH()
jejuho 0:de3e4a57ebe0 136 {
jejuho 1:bd7fd35251ab 137 //Without this setup CS lines of AT45 & LIS3DH are in conflict, causing huge current consumption
jejuho 0:de3e4a57ebe0 138 LIS_CS_0 = 1; //not selected
jejuho 0:de3e4a57ebe0 139 AT_CS = 1; //not selected
jejuho 0:de3e4a57ebe0 140 AT_RS = 0; //asserted == reset state
jejuho 0:de3e4a57ebe0 141 wait_ms(100);
jejuho 0:de3e4a57ebe0 142 AT_RS = 1;
jejuho 1:bd7fd35251ab 143 }
jejuho 1:bd7fd35251ab 144
jejuho 1:bd7fd35251ab 145 int main()
jejuho 1:bd7fd35251ab 146 {
jejuho 1:bd7fd35251ab 147 //LEDS off
jejuho 1:bd7fd35251ab 148 myled1 = 0;
jejuho 1:bd7fd35251ab 149 myled2 = 0;
jejuho 1:bd7fd35251ab 150
jejuho 1:bd7fd35251ab 151 setup_CS_LIS3DH();
jejuho 0:de3e4a57ebe0 152
jejuho 0:de3e4a57ebe0 153 //Initialize SPI interface
jejuho 0:de3e4a57ebe0 154 SPI spi(MOSI, MISO, SCLK); // mosi, miso, sclk
jejuho 0:de3e4a57ebe0 155 spi.format(8,3);
jejuho 0:de3e4a57ebe0 156 spi.frequency(8000000);
jejuho 0:de3e4a57ebe0 157 //setup AT45 dataflash to powersaving mode
jejuho 0:de3e4a57ebe0 158 AT45* flash = new AT45(spi, p5);
jejuho 0:de3e4a57ebe0 159 flash->ultra_deep_power_down(true);
jejuho 0:de3e4a57ebe0 160
jejuho 0:de3e4a57ebe0 161 //Accelerometer interrupt pin configuration
jejuho 0:de3e4a57ebe0 162 gpiote_init();
jejuho 0:de3e4a57ebe0 163
jejuho 0:de3e4a57ebe0 164 //Disconnect input buffers to save power
jejuho 1:bd7fd35251ab 165 disconnect_input_buffers();
jejuho 0:de3e4a57ebe0 166
jejuho 0:de3e4a57ebe0 167 //Initialize LIS3DH driver
jejuho 0:de3e4a57ebe0 168 lis.InitLIS3DH(LIS3DH_NORMAL, LIS3DH_ODR_100Hz, LIS3DH_FULLSCALE_2); //Init Acc-sensor
jejuho 0:de3e4a57ebe0 169 //enable threshold to generate interrupt
jejuho 1:bd7fd35251ab 170 lis.SetLIS3DHActivityDetection(3, LIS3DH_INT_MODE_6D_POSITION, 1);
jejuho 0:de3e4a57ebe0 171
jejuho 0:de3e4a57ebe0 172 // Enable GPIOTE interrupt in Nested Vector Interrupt Controller.
jejuho 0:de3e4a57ebe0 173 NVIC_ClearPendingIRQ(GPIOTE_IRQn);
jejuho 0:de3e4a57ebe0 174 NRF_GPIOTE->INTENSET = GPIOTE_INTENSET_PORT_Set << GPIOTE_INTENSET_PORT_Pos;
jejuho 0:de3e4a57ebe0 175 NVIC_SetPriority(GPIOTE_IRQn, 1);
jejuho 0:de3e4a57ebe0 176 NVIC_EnableIRQ(GPIOTE_IRQn);
jejuho 1:bd7fd35251ab 177 //sd_nvic_EnableIRQ(GPIOTE_IRQn);
jejuho 0:de3e4a57ebe0 178
jejuho 0:de3e4a57ebe0 179 //Initialize BLE stuff
jejuho 0:de3e4a57ebe0 180 ble.init();
jejuho 0:de3e4a57ebe0 181 ble.gap().onDisconnection(disconnectionCallback);
jejuho 0:de3e4a57ebe0 182
jejuho 0:de3e4a57ebe0 183 #ifdef USE_DFU
jejuho 0:de3e4a57ebe0 184 DFUService dfu(ble);
jejuho 0:de3e4a57ebe0 185 #endif
jejuho 0:de3e4a57ebe0 186
jejuho 0:de3e4a57ebe0 187 /* Setup advertising. */
jejuho 0:de3e4a57ebe0 188 ble.gap().accumulateAdvertisingPayload(GapAdvertisingData::BREDR_NOT_SUPPORTED | GapAdvertisingData::LE_GENERAL_DISCOVERABLE);
jejuho 0:de3e4a57ebe0 189 ble.gap().accumulateAdvertisingPayload(GapAdvertisingData::GENERIC_THERMOMETER);
jejuho 0:de3e4a57ebe0 190 ApplicationData_t appData;
jejuho 0:de3e4a57ebe0 191 setupApplicationData(appData);
jejuho 0:de3e4a57ebe0 192 //ble.gap().accumulateAdvertisingPayload(GapAdvertisingData::COMPLETE_LIST_16BIT_SERVICE_IDS, (uint8_t *)uuid16_list, sizeof(uuid16_list));
jejuho 0:de3e4a57ebe0 193 //ble.gap().accumulateAdvertisingPayload(GapAdvertisingData::COMPLETE_LOCAL_NAME, (uint8_t *)DEVICE_NAME, sizeof(DEVICE_NAME));
jejuho 0:de3e4a57ebe0 194 ble.gap().accumulateAdvertisingPayload(GapAdvertisingData::MANUFACTURER_SPECIFIC_DATA, (uint8_t *)&appData, sizeof(ApplicationData_t));
jejuho 0:de3e4a57ebe0 195
jejuho 0:de3e4a57ebe0 196 ble.gap().setAdvertisingType(GapAdvertisingParams::ADV_CONNECTABLE_UNDIRECTED);
jejuho 0:de3e4a57ebe0 197 //ble.gap().setAdvertisingType(GapAdvertisingParams::ADV_NON_CONNECTABLE_UNDIRECTED);
jejuho 0:de3e4a57ebe0 198 ble.gap().setAdvertisingInterval(100); /* 1000ms. */
jejuho 0:de3e4a57ebe0 199 ble.gap().startAdvertising();
jejuho 0:de3e4a57ebe0 200
jejuho 0:de3e4a57ebe0 201 Ticker ticker;
jejuho 0:de3e4a57ebe0 202 ticker.attach(senseCallback, 0.1);
jejuho 0:de3e4a57ebe0 203
jejuho 0:de3e4a57ebe0 204 ///Could have main loop here doing something
jejuho 0:de3e4a57ebe0 205 while(true) {
jejuho 0:de3e4a57ebe0 206 ble.waitForEvent();
jejuho 0:de3e4a57ebe0 207 }
jejuho 0:de3e4a57ebe0 208 }
jejuho 0:de3e4a57ebe0 209