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:
Sun Jul 26 15:38:59 2015 +0000
Revision:
2:9090120e2656
Parent:
1:c3d7e673cdd2
Child:
3:a4b8d67de1b1
Replaced code with RedBear sample BLE code

Who changed what in which revision?

UserRevisionLine numberNew contents of line
Bobty 0:0d5ac2fd4620 1 // BLE Alarm Watch
Bobty 2:9090120e2656 2 // Based on BLE examples on MBED
Bobty 0:0d5ac2fd4620 3 // Rob Dobson, 2015
Bobty 0:0d5ac2fd4620 4
Bobty 0:0d5ac2fd4620 5 #include "mbed.h"
Bobty 2:9090120e2656 6 #include "BLE.h"
Bobty 2:9090120e2656 7 #include "ButtonService.h"
Bobty 2:9090120e2656 8
Bobty 2:9090120e2656 9 // BLE platform
Bobty 2:9090120e2656 10 BLE ble;
Bobty 2:9090120e2656 11
Bobty 2:9090120e2656 12 // Indicator LEDs
Bobty 2:9090120e2656 13 DigitalOut led1(LED1);
Bobty 2:9090120e2656 14
Bobty 2:9090120e2656 15 // Button press to show time
Bobty 2:9090120e2656 16 InterruptIn button(D8);
Bobty 2:9090120e2656 17
Bobty 2:9090120e2656 18 // Device name - this is the visible name of device on BLE
Bobty 2:9090120e2656 19 const static char DEVICE_NAME[] = "Button";
Bobty 2:9090120e2656 20
Bobty 2:9090120e2656 21 // TEST CODE
Bobty 2:9090120e2656 22 static const uint16_t uuid16_list[] = {ButtonService::BUTTON_SERVICE_UUID};
Bobty 2:9090120e2656 23
Bobty 2:9090120e2656 24 // TEST CODE
Bobty 2:9090120e2656 25 ButtonService *buttonServicePtr;
Bobty 2:9090120e2656 26
Bobty 2:9090120e2656 27 // Handle button press to read watch
Bobty 2:9090120e2656 28 void buttonPressedCallback(void)
Bobty 2:9090120e2656 29 {
Bobty 2:9090120e2656 30 // TEST CODE
Bobty 2:9090120e2656 31 buttonServicePtr->updateButtonState(true);
Bobty 2:9090120e2656 32 }
Bobty 2:9090120e2656 33
Bobty 2:9090120e2656 34 // TEST CODE
Bobty 2:9090120e2656 35 void buttonReleasedCallback(void)
Bobty 2:9090120e2656 36 {
Bobty 2:9090120e2656 37 // TEST CODE
Bobty 2:9090120e2656 38 buttonServicePtr->updateButtonState(false);
Bobty 2:9090120e2656 39 }
Bobty 2:9090120e2656 40
Bobty 2:9090120e2656 41 // Handle BLE disconnection - restart advertising
Bobty 2:9090120e2656 42 void disconnectionCallback(Gap::Handle_t handle, Gap::DisconnectionReason_t reason)
Bobty 2:9090120e2656 43 {
Bobty 2:9090120e2656 44 ble.gap().startAdvertising();
Bobty 2:9090120e2656 45 }
Bobty 2:9090120e2656 46
Bobty 2:9090120e2656 47 // TEST CODE
Bobty 2:9090120e2656 48 void periodicCallback(void)
Bobty 2:9090120e2656 49 {
Bobty 2:9090120e2656 50 led1 = !led1; /* Do blinky on LED1 to indicate system aliveness. */
Bobty 2:9090120e2656 51 }
Bobty 2:9090120e2656 52
Bobty 2:9090120e2656 53 int main(void)
Bobty 2:9090120e2656 54 {
Bobty 2:9090120e2656 55 // TEST CODE
Bobty 2:9090120e2656 56 led1 = 1;
Bobty 2:9090120e2656 57 Ticker ticker;
Bobty 2:9090120e2656 58 ticker.attach(periodicCallback, 1);
Bobty 2:9090120e2656 59 button.fall(buttonPressedCallback);
Bobty 2:9090120e2656 60 button.rise(buttonReleasedCallback);
Bobty 2:9090120e2656 61
Bobty 2:9090120e2656 62 // BLE init
Bobty 2:9090120e2656 63 ble.init();
Bobty 2:9090120e2656 64 ble.gap().onDisconnection(disconnectionCallback);
Bobty 2:9090120e2656 65
Bobty 2:9090120e2656 66 // TEST CODE
Bobty 2:9090120e2656 67 ButtonService buttonService(ble, false /* initial value for button pressed */);
Bobty 2:9090120e2656 68 buttonServicePtr = &buttonService;
Bobty 2:9090120e2656 69
Bobty 2:9090120e2656 70 // Setup advertising
Bobty 2:9090120e2656 71 ble.gap().accumulateAdvertisingPayload(GapAdvertisingData::BREDR_NOT_SUPPORTED | GapAdvertisingData::LE_GENERAL_DISCOVERABLE);
Bobty 2:9090120e2656 72 ble.gap().accumulateAdvertisingPayload(GapAdvertisingData::COMPLETE_LIST_16BIT_SERVICE_IDS, (uint8_t *)uuid16_list, sizeof(uuid16_list));
Bobty 2:9090120e2656 73 ble.gap().accumulateAdvertisingPayload(GapAdvertisingData::COMPLETE_LOCAL_NAME, (uint8_t *)DEVICE_NAME, sizeof(DEVICE_NAME));
Bobty 2:9090120e2656 74 ble.gap().setAdvertisingType(GapAdvertisingParams::ADV_CONNECTABLE_UNDIRECTED);
Bobty 2:9090120e2656 75 ble.gap().setAdvertisingInterval(1000); /* 1000ms. */
Bobty 2:9090120e2656 76 ble.gap().startAdvertising();
Bobty 2:9090120e2656 77
Bobty 2:9090120e2656 78 while (true) {
Bobty 2:9090120e2656 79 ble.waitForEvent();
Bobty 2:9090120e2656 80 }
Bobty 2:9090120e2656 81 }
Bobty 2:9090120e2656 82
Bobty 2:9090120e2656 83 /*
Bobty 2:9090120e2656 84
Bobty 2:9090120e2656 85 #include "mbed.h"
Bobty 0:0d5ac2fd4620 86 #include "BLEDevice.h"
Bobty 0:0d5ac2fd4620 87 #include "DeviceInformationService.h"
Bobty 0:0d5ac2fd4620 88
Bobty 0:0d5ac2fd4620 89 // BLE Device etc
Bobty 0:0d5ac2fd4620 90 BLEDevice ble;
Bobty 0:0d5ac2fd4620 91 DigitalOut ledIndicator(LED1);
Bobty 0:0d5ac2fd4620 92 DigitalOut testOut(p1);
Bobty 0:0d5ac2fd4620 93
Bobty 1:c3d7e673cdd2 94 // Device name
Bobty 1:c3d7e673cdd2 95 const static char DEVICE_NAME[] = "JOESALARM";
Bobty 1:c3d7e673cdd2 96
Bobty 1:c3d7e673cdd2 97 // UUID for CurTimeService & TimeBlockCharacteristic
Bobty 1:c3d7e673cdd2 98 const uint16_t UUID_CUR_TIME_SERVICE = 0xA000;
Bobty 1:c3d7e673cdd2 99 const uint16_t UUID_TIME_BLOCK_CHARACTERISTIC = 0xA001;
Bobty 1:c3d7e673cdd2 100
Bobty 1:c3d7e673cdd2 101 // List of supported service UUIDs
Bobty 1:c3d7e673cdd2 102 static const uint16_t uuid16_list[] = {UUID_CUR_TIME_SERVICE};
Bobty 0:0d5ac2fd4620 103
Bobty 1:c3d7e673cdd2 104 // Time is packed in an array of bytes
Bobty 1:c3d7e673cdd2 105 const int SIZE_OF_TIME_BLOCK = 7;
Bobty 1:c3d7e673cdd2 106 uint8_t timeBlockInitValue[SIZE_OF_TIME_BLOCK];
Bobty 1:c3d7e673cdd2 107 uint8_t curTimeBlock[SIZE_OF_TIME_BLOCK];
Bobty 1:c3d7e673cdd2 108
Bobty 1:c3d7e673cdd2 109 // GATT Characteristic for time block
Bobty 2:9090120e2656 110 GattCharacteristic timeBlockCharacteristic(UUID_TIME_BLOCK_CHARACTERISTIC, timeBlockInitValue, SIZE_OF_TIME_BLOCK, SIZE_OF_TIME_BLOCK,
Bobty 2:9090120e2656 111 GattCharacteristic::BLE_GATT_CHAR_PROPERTIES_WRITE | GattCharacteristic::BLE_GATT_CHAR_PROPERTIES_WRITE_WITHOUT_RESPONSE | GattCharacteristic::BLE_GATT_CHAR_PROPERTIES_READ);
Bobty 1:c3d7e673cdd2 112
Bobty 1:c3d7e673cdd2 113 // Callback when connection lost
Bobty 0:0d5ac2fd4620 114 void disconnectionCallback(Gap::Handle_t handle, Gap::DisconnectionReason_t reason)
Bobty 0:0d5ac2fd4620 115 {
Bobty 0:0d5ac2fd4620 116 ble.startAdvertising(); // restart advertising
Bobty 0:0d5ac2fd4620 117 }
Bobty 0:0d5ac2fd4620 118
Bobty 1:c3d7e673cdd2 119 // Callback for ticker
Bobty 1:c3d7e673cdd2 120 int tickCount = 0;
Bobty 1:c3d7e673cdd2 121 bool showInfo = false;
Bobty 1:c3d7e673cdd2 122 int writeSinceLast = 0;
Bobty 0:0d5ac2fd4620 123 void periodicCallback(void)
Bobty 0:0d5ac2fd4620 124 {
Bobty 2:9090120e2656 125 ledIndicator = !ledIndicator;
Bobty 0:0d5ac2fd4620 126 testOut = !testOut;
Bobty 1:c3d7e673cdd2 127 tickCount++;
Bobty 1:c3d7e673cdd2 128 if (tickCount > 100)
Bobty 1:c3d7e673cdd2 129 {
Bobty 1:c3d7e673cdd2 130 showInfo = true;
Bobty 1:c3d7e673cdd2 131 tickCount = 0;
Bobty 1:c3d7e673cdd2 132 }
Bobty 0:0d5ac2fd4620 133 }
Bobty 0:0d5ac2fd4620 134
Bobty 1:c3d7e673cdd2 135 // Data written callback
Bobty 1:c3d7e673cdd2 136 void onDataWrittenCallback(const GattCharacteristicWriteCBParams *params)
Bobty 1:c3d7e673cdd2 137 {
Bobty 1:c3d7e673cdd2 138 if ((params->charHandle == timeBlockCharacteristic.getValueHandle()))
Bobty 1:c3d7e673cdd2 139 {
Bobty 2:9090120e2656 140 // Validate time
Bobty 2:9090120e2656 141 int year = params->data[0] * 100 + params->data[1];
Bobty 2:9090120e2656 142 int month = params->data[2];
Bobty 2:9090120e2656 143 int day = params->data[3];
Bobty 1:c3d7e673cdd2 144 // && (params->len == SIZE_OF_TIME_BLOCK)
Bobty 1:c3d7e673cdd2 145 writeSinceLast = params->len;
Bobty 1:c3d7e673cdd2 146 memcpy(curTimeBlock, params->data, SIZE_OF_TIME_BLOCK);
Bobty 1:c3d7e673cdd2 147 }
Bobty 1:c3d7e673cdd2 148 writeSinceLast = true;
Bobty 1:c3d7e673cdd2 149 }
Bobty 1:c3d7e673cdd2 150
Bobty 1:c3d7e673cdd2 151 // Main
Bobty 0:0d5ac2fd4620 152 int main(void)
Bobty 0:0d5ac2fd4620 153 {
Bobty 0:0d5ac2fd4620 154 ledIndicator = 0;
Bobty 0:0d5ac2fd4620 155 testOut = 0;
Bobty 0:0d5ac2fd4620 156
Bobty 0:0d5ac2fd4620 157 // Ticker is interrupt driven
Bobty 0:0d5ac2fd4620 158 Ticker ticker;
Bobty 0:0d5ac2fd4620 159 ticker.attach_us(periodicCallback, 100000);
Bobty 0:0d5ac2fd4620 160
Bobty 1:c3d7e673cdd2 161 // Initial value for the time block characteristic
Bobty 1:c3d7e673cdd2 162 memset(timeBlockInitValue, 0, sizeof(timeBlockInitValue));
Bobty 1:c3d7e673cdd2 163
Bobty 1:c3d7e673cdd2 164 // Init BLE and register callbacks
Bobty 0:0d5ac2fd4620 165 ble.init();
Bobty 0:0d5ac2fd4620 166 ble.onDisconnection(disconnectionCallback);
Bobty 1:c3d7e673cdd2 167 ble.onDataWritten(onDataWrittenCallback);
Bobty 1:c3d7e673cdd2 168
Bobty 1:c3d7e673cdd2 169 // Add the time setting service
Bobty 1:c3d7e673cdd2 170 GattCharacteristic *charTable[] = {&timeBlockCharacteristic};
Bobty 1:c3d7e673cdd2 171 GattService timeBlockService(UUID_CUR_TIME_SERVICE, charTable, sizeof(charTable) / sizeof(GattCharacteristic *));
Bobty 1:c3d7e673cdd2 172 ble.addService(timeBlockService);
Bobty 0:0d5ac2fd4620 173
Bobty 0:0d5ac2fd4620 174 // Setup advertising
Bobty 2:9090120e2656 175 // BREDR_NOT_SUPPORTED means classic bluetooth not supported;
Bobty 2:9090120e2656 176 // LE_GENERAL_DISCOVERABLE means that this peripheral can be
Bobty 2:9090120e2656 177 // discovered by any BLE scanner--i.e. any phone.
Bobty 0:0d5ac2fd4620 178 ble.accumulateAdvertisingPayload(GapAdvertisingData::BREDR_NOT_SUPPORTED | GapAdvertisingData::LE_GENERAL_DISCOVERABLE);
Bobty 0:0d5ac2fd4620 179
Bobty 1:c3d7e673cdd2 180 // Add services to payload
Bobty 1:c3d7e673cdd2 181 ble.accumulateAdvertisingPayload(GapAdvertisingData::COMPLETE_LIST_16BIT_SERVICE_IDS, (uint8_t *)uuid16_list, sizeof(uuid16_list));
Bobty 1:c3d7e673cdd2 182
Bobty 2:9090120e2656 183 // This is where we're collecting the device name into the advertisement payload.
Bobty 0:0d5ac2fd4620 184 ble.accumulateAdvertisingPayload(GapAdvertisingData::COMPLETE_LOCAL_NAME, (uint8_t *)DEVICE_NAME, sizeof(DEVICE_NAME));
Bobty 0:0d5ac2fd4620 185
Bobty 2:9090120e2656 186 // We'd like for this BLE peripheral to be connectable.
Bobty 0:0d5ac2fd4620 187 ble.setAdvertisingType(GapAdvertisingParams::ADV_CONNECTABLE_UNDIRECTED);
Bobty 0:0d5ac2fd4620 188
Bobty 2:9090120e2656 189 // set the interval at which advertisements are sent out; this has
Bobty 2:9090120e2656 190 // an implication power consumption--radio activity being a
Bobty 2:9090120e2656 191 // biggest draw on average power. The other software controllable
Bobty 2:9090120e2656 192 // parameter which influences power is the radio's TX power
Bobty 2:9090120e2656 193 // level--there's an API to adjust that.
Bobty 2:9090120e2656 194 ble.setAdvertisingInterval(Gap::MSEC_TO_ADVERTISEMENT_DURATION_UNITS(1000));
Bobty 0:0d5ac2fd4620 195
Bobty 2:9090120e2656 196
Bobty 0:0d5ac2fd4620 197 ble.startAdvertising();
Bobty 0:0d5ac2fd4620 198
Bobty 0:0d5ac2fd4620 199 while (true)
Bobty 0:0d5ac2fd4620 200 {
Bobty 0:0d5ac2fd4620 201 ble.waitForEvent();
Bobty 1:c3d7e673cdd2 202
Bobty 1:c3d7e673cdd2 203 if (showInfo)
Bobty 1:c3d7e673cdd2 204 {
Bobty 1:c3d7e673cdd2 205 printf("Time info: ");
Bobty 1:c3d7e673cdd2 206 for (int i = 0; i < SIZE_OF_TIME_BLOCK; i++)
Bobty 1:c3d7e673cdd2 207 {
Bobty 1:c3d7e673cdd2 208 printf("%02d", curTimeBlock[i]);
Bobty 1:c3d7e673cdd2 209 }
Bobty 1:c3d7e673cdd2 210 printf(" - writeSinceLast %d\r\n", writeSinceLast);
Bobty 1:c3d7e673cdd2 211 showInfo = false;
Bobty 1:c3d7e673cdd2 212 writeSinceLast = 0;
Bobty 1:c3d7e673cdd2 213 }
Bobty 0:0d5ac2fd4620 214 }
Bobty 0:0d5ac2fd4620 215 }
Bobty 2:9090120e2656 216 */