Auto updating alarm watch - accepts alarm settings from a BLE device like a Raspberry Pi and buzzes at the appropriate time - also displays binary time

Dependencies:   BLE_API mbed-src nRF51822 nrf51_rtc

Committer:
Bobty
Date:
Tue Mar 10 15:29:07 2015 +0000
Revision:
0:0d5ac2fd4620
Child:
1:c3d7e673cdd2
First rev based on code at http://ble-intros.readthedocs.org/en/latest/AdvSamples/LEDReadWrite/

Who changed what in which revision?

UserRevisionLine numberNew contents of line
Bobty 0:0d5ac2fd4620 1 // BLE Alarm Watch
Bobty 0:0d5ac2fd4620 2 // Based on BLE heart-rate-monitor from MBED team
Bobty 0:0d5ac2fd4620 3 // Rob Dobson, 2015
Bobty 0:0d5ac2fd4620 4
Bobty 0:0d5ac2fd4620 5 #include "mbed.h"
Bobty 0:0d5ac2fd4620 6 #include "BLEDevice.h"
Bobty 0:0d5ac2fd4620 7 #include "DeviceInformationService.h"
Bobty 0:0d5ac2fd4620 8
Bobty 0:0d5ac2fd4620 9 // BLE Device etc
Bobty 0:0d5ac2fd4620 10 BLEDevice ble;
Bobty 0:0d5ac2fd4620 11 DigitalOut ledIndicator(LED1);
Bobty 0:0d5ac2fd4620 12 DigitalOut testOut(p1);
Bobty 0:0d5ac2fd4620 13
Bobty 0:0d5ac2fd4620 14 const static char DEVICE_NAME[] = "ALMW";
Bobty 0:0d5ac2fd4620 15 //static const uint16_t uuid16_list[] = {GattService::UUID_ALARM_WATCH_SERVICE,
Bobty 0:0d5ac2fd4620 16 // GattService::UUID_DEVICE_INFORMATION_SERVICE};
Bobty 0:0d5ac2fd4620 17 //
Bobty 0:0d5ac2fd4620 18
Bobty 0:0d5ac2fd4620 19 ///*
Bobty 0:0d5ac2fd4620 20 //* Define a custom UUID, first as an array of uint8_t and then convert to
Bobty 0:0d5ac2fd4620 21 //* a proper UUID later. The UUID must be 16 bytes (128-bits, 16 letters)
Bobty 0:0d5ac2fd4620 22 //* long - here we have padded out to 16 bytes by adding an extra '0' at
Bobty 0:0d5ac2fd4620 23 //* the end. Make sure you fill more than 4 bytes otherwise it will count
Bobty 0:0d5ac2fd4620 24 //* as a 'short' code and you could end up using a predefined value from
Bobty 0:0d5ac2fd4620 25 //* the BLE spec.
Bobty 0:0d5ac2fd4620 26 //*/
Bobty 0:0d5ac2fd4620 27 //uint8_t raw_characteristic_uuid[16] = {
Bobty 0:0d5ac2fd4620 28 // 'M', 'Y', '_', 'T',
Bobty 0:0d5ac2fd4620 29 // 'E', 'S', 'T', '_',
Bobty 0:0d5ac2fd4620 30 // 'C', 'H', 'A', 'R',
Bobty 0:0d5ac2fd4620 31 // 0, 0, 0, 0
Bobty 0:0d5ac2fd4620 32 //};
Bobty 0:0d5ac2fd4620 33 //// Create a proper UUID - use the built in function to do this correctly
Bobty 0:0d5ac2fd4620 34 //UUID characteristic_uuid = UUID(raw_characteristic_uuid);
Bobty 0:0d5ac2fd4620 35 //// Setup some dummy properties for our characteristic
Bobty 0:0d5ac2fd4620 36 //static uint8_t my_char_values[2] = { 15, 10 };
Bobty 0:0d5ac2fd4620 37 ///*
Bobty 0:0d5ac2fd4620 38 //* Here we create our Characteristic adding in the dummy parameter values
Bobty 0:0d5ac2fd4620 39 //* we just setup, we also make it readable and writeable meaning that a
Bobty 0:0d5ac2fd4620 40 //* central can read and update the parameters we have stored.
Bobty 0:0d5ac2fd4620 41 //*/
Bobty 0:0d5ac2fd4620 42 //GattCharacteristic pattern(
Bobty 0:0d5ac2fd4620 43 // characteristic_uuid,
Bobty 0:0d5ac2fd4620 44 // my_char_values,
Bobty 0:0d5ac2fd4620 45 // sizeof(my_char_values),
Bobty 0:0d5ac2fd4620 46 // sizeof(my_char_values),
Bobty 0:0d5ac2fd4620 47 // GattCharacteristic::BLE_GATT_CHAR_PROPERTIES_READ | GattCharacteristic::BLE_GATT_CHAR_PROPERTIES_WRITE
Bobty 0:0d5ac2fd4620 48 //);
Bobty 0:0d5ac2fd4620 49 ///*
Bobty 0:0d5ac2fd4620 50 //* List the Characteristics of our custom Service, can have one or more
Bobty 0:0d5ac2fd4620 51 //* of these each with a custom UUID and parameter values.
Bobty 0:0d5ac2fd4620 52 //*/
Bobty 0:0d5ac2fd4620 53 //GattCharacteristic *my_service_chars[] = {
Bobty 0:0d5ac2fd4620 54 // &new_alert,
Bobty 0:0d5ac2fd4620 55 //};
Bobty 0:0d5ac2fd4620 56 //// Now setup a custom Service UUID, in the same fashion as for the Characteristic
Bobty 0:0d5ac2fd4620 57 //uint8_t raw_service_uuid[16] = {
Bobty 0:0d5ac2fd4620 58 // 'M', 'Y', '_', 'T',
Bobty 0:0d5ac2fd4620 59 // 'E', 'S', 'T', '_',
Bobty 0:0d5ac2fd4620 60 // 'S', 'E', 'R', 'V',
Bobty 0:0d5ac2fd4620 61 // 'I', 'C', 'E', 0
Bobty 0:0d5ac2fd4620 62 //};
Bobty 0:0d5ac2fd4620 63 //UUID service_uuid = UUID(raw_service_uuid);
Bobty 0:0d5ac2fd4620 64 //// Setup the Service with the UUID and all of the Characteristics
Bobty 0:0d5ac2fd4620 65 //GattService my_service(
Bobty 0:0d5ac2fd4620 66 // service_uuid,
Bobty 0:0d5ac2fd4620 67 // my_service_chars,
Bobty 0:0d5ac2fd4620 68 // sizeof(my_service_chars) / sizeof(GattCharacteristic *)
Bobty 0:0d5ac2fd4620 69 //);
Bobty 0:0d5ac2fd4620 70 ///*
Bobty 0:0d5ac2fd4620 71 //* Now list the long UUIDs of the services we offer, these will be bundled into the
Bobty 0:0d5ac2fd4620 72 //* advertisement. It may look like repetition of 'raw_service_uuid' but here you can
Bobty 0:0d5ac2fd4620 73 //* list multiple UUIDs one after another.
Bobty 0:0d5ac2fd4620 74 //*/
Bobty 0:0d5ac2fd4620 75 //static const uint8_t uuid128_list[] = {
Bobty 0:0d5ac2fd4620 76 // 'M', 'Y', '_', 'T', 'E', 'S', 'T', '_', 'S', 'E', 'R', 'V', 'I', 'C', 'E', 0
Bobty 0:0d5ac2fd4620 77 // // List more long UUIDs below...
Bobty 0:0d5ac2fd4620 78 //};
Bobty 0:0d5ac2fd4620 79 //
Bobty 0:0d5ac2fd4620 80 //...
Bobty 0:0d5ac2fd4620 81 //
Bobty 0:0d5ac2fd4620 82 ///*
Bobty 0:0d5ac2fd4620 83 //* Now we change from using short (16-bit) UUIDs to long (128-bit) UUIDs, comment out
Bobty 0:0d5ac2fd4620 84 //* the old section of the payload and add the new 128-bit section.
Bobty 0:0d5ac2fd4620 85 //*/
Bobty 0:0d5ac2fd4620 86 ///*bluetooth->accumulateAdvertisingPayload(
Bobty 0:0d5ac2fd4620 87 // GapAdvertisingData::COMPLETE_LIST_16BIT_SERVICE_IDS,
Bobty 0:0d5ac2fd4620 88 // (uint8_t *)uuid16_list,
Bobty 0:0d5ac2fd4620 89 // sizeof(uuid16_list)
Bobty 0:0d5ac2fd4620 90 //);*/
Bobty 0:0d5ac2fd4620 91 //bluetooth->accumulateAdvertisingPayload(
Bobty 0:0d5ac2fd4620 92 // GapAdvertisingData::INCOMPLETE_LIST_128BIT_SERVICE_IDS,
Bobty 0:0d5ac2fd4620 93 // (uint8_t *)uuid128_list,
Bobty 0:0d5ac2fd4620 94 // sizeof(uuid128_list)
Bobty 0:0d5ac2fd4620 95 //);
Bobty 0:0d5ac2fd4620 96 //
Bobty 0:0d5ac2fd4620 97 //
Bobty 0:0d5ac2fd4620 98 //
Bobty 0:0d5ac2fd4620 99 //
Bobty 0:0d5ac2fd4620 100 //
Bobty 0:0d5ac2fd4620 101
Bobty 0:0d5ac2fd4620 102 static volatile bool triggerSensorPolling = false;
Bobty 0:0d5ac2fd4620 103
Bobty 0:0d5ac2fd4620 104 void disconnectionCallback(Gap::Handle_t handle, Gap::DisconnectionReason_t reason)
Bobty 0:0d5ac2fd4620 105 {
Bobty 0:0d5ac2fd4620 106 ble.startAdvertising(); // restart advertising
Bobty 0:0d5ac2fd4620 107 }
Bobty 0:0d5ac2fd4620 108
Bobty 0:0d5ac2fd4620 109 void periodicCallback(void)
Bobty 0:0d5ac2fd4620 110 {
Bobty 0:0d5ac2fd4620 111 ledIndicator = !ledIndicator; /* Do blinky on LED1 while we're waiting for BLE events */
Bobty 0:0d5ac2fd4620 112 testOut = !testOut;
Bobty 0:0d5ac2fd4620 113 }
Bobty 0:0d5ac2fd4620 114
Bobty 0:0d5ac2fd4620 115 int main(void)
Bobty 0:0d5ac2fd4620 116 {
Bobty 0:0d5ac2fd4620 117 ledIndicator = 0;
Bobty 0:0d5ac2fd4620 118 testOut = 0;
Bobty 0:0d5ac2fd4620 119
Bobty 0:0d5ac2fd4620 120 // Ticker is interrupt driven
Bobty 0:0d5ac2fd4620 121 Ticker ticker;
Bobty 0:0d5ac2fd4620 122 ticker.attach_us(periodicCallback, 100000);
Bobty 0:0d5ac2fd4620 123
Bobty 0:0d5ac2fd4620 124 // Init BLE
Bobty 0:0d5ac2fd4620 125 ble.init();
Bobty 0:0d5ac2fd4620 126 ble.onDisconnection(disconnectionCallback);
Bobty 0:0d5ac2fd4620 127
Bobty 0:0d5ac2fd4620 128 // Setup advertising
Bobty 0:0d5ac2fd4620 129 /* BREDR_NOT_SUPPORTED means classic bluetooth not supported;
Bobty 0:0d5ac2fd4620 130 * LE_GENERAL_DISCOVERABLE means that this peripheral can be
Bobty 0:0d5ac2fd4620 131 * discovered by any BLE scanner--i.e. any phone. */
Bobty 0:0d5ac2fd4620 132 ble.accumulateAdvertisingPayload(GapAdvertisingData::BREDR_NOT_SUPPORTED | GapAdvertisingData::LE_GENERAL_DISCOVERABLE);
Bobty 0:0d5ac2fd4620 133
Bobty 0:0d5ac2fd4620 134 /* This is where we're collecting the device name into the advertisement payload. */
Bobty 0:0d5ac2fd4620 135 ble.accumulateAdvertisingPayload(GapAdvertisingData::COMPLETE_LOCAL_NAME, (uint8_t *)DEVICE_NAME, sizeof(DEVICE_NAME));
Bobty 0:0d5ac2fd4620 136
Bobty 0:0d5ac2fd4620 137 /* We'd like for this BLE peripheral to be connectable. */
Bobty 0:0d5ac2fd4620 138 ble.setAdvertisingType(GapAdvertisingParams::ADV_CONNECTABLE_UNDIRECTED);
Bobty 0:0d5ac2fd4620 139
Bobty 0:0d5ac2fd4620 140 /* set the interval at which advertisements are sent out; this has
Bobty 0:0d5ac2fd4620 141 * an implication power consumption--radio activity being a
Bobty 0:0d5ac2fd4620 142 * biggest draw on average power. The other software controllable
Bobty 0:0d5ac2fd4620 143 * parameter which influences power is the radio's TX power
Bobty 0:0d5ac2fd4620 144 * level--there's an API to adjust that. */
Bobty 0:0d5ac2fd4620 145 ble.setAdvertisingInterval(Gap::MSEC_TO_ADVERTISEMENT_DURATION_UNITS(1000)); /* 1000ms. */
Bobty 0:0d5ac2fd4620 146
Bobty 0:0d5ac2fd4620 147 /* we're finally good to go with advertisements. */
Bobty 0:0d5ac2fd4620 148 ble.startAdvertising();
Bobty 0:0d5ac2fd4620 149
Bobty 0:0d5ac2fd4620 150 while (true)
Bobty 0:0d5ac2fd4620 151 {
Bobty 0:0d5ac2fd4620 152 ble.waitForEvent();
Bobty 0:0d5ac2fd4620 153 }
Bobty 0:0d5ac2fd4620 154 // /* Setup primary service. */
Bobty 0:0d5ac2fd4620 155 // uint8_t hrmCounter = 100; // init HRM to 100bps
Bobty 0:0d5ac2fd4620 156 // HeartRateService hrService(ble, hrmCounter, HeartRateService::LOCATION_FINGER);
Bobty 0:0d5ac2fd4620 157 //
Bobty 0:0d5ac2fd4620 158 // /* Setup auxiliary service. */
Bobty 0:0d5ac2fd4620 159 // DeviceInformationService deviceInfo(ble, "ARM", "Model1", "SN1", "hw-rev1", "fw-rev1", "soft-rev1");
Bobty 0:0d5ac2fd4620 160 //
Bobty 0:0d5ac2fd4620 161 // /* Setup advertising. */
Bobty 0:0d5ac2fd4620 162 // ble.accumulateAdvertisingPayload(GapAdvertisingData::BREDR_NOT_SUPPORTED | GapAdvertisingData::LE_GENERAL_DISCOVERABLE);
Bobty 0:0d5ac2fd4620 163 // ble.accumulateAdvertisingPayload(GapAdvertisingData::COMPLETE_LIST_16BIT_SERVICE_IDS, (uint8_t *)uuid16_list, sizeof(uuid16_list));
Bobty 0:0d5ac2fd4620 164 // ble.accumulateAdvertisingPayload(GapAdvertisingData::GENERIC_HEART_RATE_SENSOR);
Bobty 0:0d5ac2fd4620 165 // ble.accumulateAdvertisingPayload(GapAdvertisingData::COMPLETE_LOCAL_NAME, (uint8_t *)DEVICE_NAME, sizeof(DEVICE_NAME));
Bobty 0:0d5ac2fd4620 166 // ble.setAdvertisingType(GapAdvertisingParams::ADV_CONNECTABLE_UNDIRECTED);
Bobty 0:0d5ac2fd4620 167 // ble.setAdvertisingInterval(Gap::MSEC_TO_ADVERTISEMENT_DURATION_UNITS(1000));
Bobty 0:0d5ac2fd4620 168 // ble.startAdvertising();
Bobty 0:0d5ac2fd4620 169 //
Bobty 0:0d5ac2fd4620 170 // // infinite loop
Bobty 0:0d5ac2fd4620 171 // while (1) {
Bobty 0:0d5ac2fd4620 172 // // check for trigger from periodicCallback()
Bobty 0:0d5ac2fd4620 173 // if (triggerSensorPolling && ble.getGapState().connected) {
Bobty 0:0d5ac2fd4620 174 // triggerSensorPolling = false;
Bobty 0:0d5ac2fd4620 175 //
Bobty 0:0d5ac2fd4620 176 // // Do blocking calls or whatever is necessary for sensor polling.
Bobty 0:0d5ac2fd4620 177 // // In our case, we simply update the HRM measurement.
Bobty 0:0d5ac2fd4620 178 // hrmCounter++;
Bobty 0:0d5ac2fd4620 179 //
Bobty 0:0d5ac2fd4620 180 // // 100 <= HRM bps <=175
Bobty 0:0d5ac2fd4620 181 // if (hrmCounter == 175) {
Bobty 0:0d5ac2fd4620 182 // hrmCounter = 100;
Bobty 0:0d5ac2fd4620 183 // }
Bobty 0:0d5ac2fd4620 184 //
Bobty 0:0d5ac2fd4620 185 // // update bps
Bobty 0:0d5ac2fd4620 186 // hrService.updateHeartRate(hrmCounter);
Bobty 0:0d5ac2fd4620 187 // } else {
Bobty 0:0d5ac2fd4620 188 // ble.waitForEvent(); // low power wait for event
Bobty 0:0d5ac2fd4620 189 // }
Bobty 0:0d5ac2fd4620 190 // }
Bobty 0:0d5ac2fd4620 191 }