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

Revision:
0:0d5ac2fd4620
Child:
1:c3d7e673cdd2
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/main.cpp	Tue Mar 10 15:29:07 2015 +0000
@@ -0,0 +1,191 @@
+// BLE Alarm Watch
+// Based on BLE heart-rate-monitor from MBED team
+// Rob Dobson, 2015
+
+#include "mbed.h"
+#include "BLEDevice.h"
+#include "DeviceInformationService.h"
+
+// BLE Device etc
+BLEDevice  ble;
+DigitalOut ledIndicator(LED1);
+DigitalOut testOut(p1);
+
+const static char     DEVICE_NAME[]        = "ALMW";
+//static const uint16_t uuid16_list[]        = {GattService::UUID_ALARM_WATCH_SERVICE,
+//                                              GattService::UUID_DEVICE_INFORMATION_SERVICE};
+//                                              
+                                              
+///*
+//* Define a custom UUID, first as an array of uint8_t and then convert to
+//* a proper UUID later. The UUID must be 16 bytes (128-bits, 16 letters)
+//* long - here we have padded out to 16 bytes by adding an extra '0' at
+//* the end. Make sure you fill more than 4 bytes otherwise it will count
+//* as a 'short' code and you could end up using a predefined value from
+//* the BLE spec.
+//*/
+//uint8_t raw_characteristic_uuid[16] = {
+//    'M', 'Y', '_', 'T',
+//    'E', 'S', 'T', '_',
+//    'C', 'H', 'A', 'R',
+//    0, 0, 0, 0
+//};
+//// Create a proper UUID - use the built in function to do this correctly
+//UUID characteristic_uuid = UUID(raw_characteristic_uuid);
+//// Setup some dummy properties for our characteristic
+//static uint8_t my_char_values[2] = { 15, 10 };
+///*
+//* Here we create our Characteristic adding in the dummy parameter values
+//* we just setup, we also make it readable and writeable meaning that a
+//* central can read and update the parameters we have stored.
+//*/
+//GattCharacteristic pattern(
+//    characteristic_uuid,
+//    my_char_values,
+//    sizeof(my_char_values),
+//    sizeof(my_char_values),
+//    GattCharacteristic::BLE_GATT_CHAR_PROPERTIES_READ | GattCharacteristic::BLE_GATT_CHAR_PROPERTIES_WRITE
+//);
+///* 
+//* List the Characteristics of our custom Service, can have one or more
+//* of these each with a custom UUID and parameter values.
+//*/
+//GattCharacteristic *my_service_chars[] = {
+//    &new_alert,
+//};
+//// Now setup a custom Service UUID, in the same fashion as for the Characteristic
+//uint8_t raw_service_uuid[16] = {
+//    'M', 'Y', '_', 'T',
+//    'E', 'S', 'T', '_',
+//    'S', 'E', 'R', 'V',
+//    'I', 'C', 'E', 0
+//};
+//UUID service_uuid = UUID(raw_service_uuid);
+//// Setup the Service with the UUID and all of the Characteristics
+//GattService my_service(
+//    service_uuid,
+//    my_service_chars,
+//    sizeof(my_service_chars) / sizeof(GattCharacteristic *)
+//);
+///* 
+//* Now list the long UUIDs of the services we offer, these will be bundled into the
+//* advertisement. It may look like repetition of 'raw_service_uuid' but here you can
+//* list multiple UUIDs one after another.
+//*/
+//static const uint8_t uuid128_list[] = {
+//    'M', 'Y', '_', 'T', 'E', 'S', 'T', '_', 'S', 'E', 'R', 'V', 'I', 'C', 'E', 0
+//    // List more long UUIDs below...
+//};
+// 
+//...
+// 
+///*
+//* Now we change from using short (16-bit) UUIDs to long (128-bit) UUIDs, comment out
+//* the old section of the payload and add the new 128-bit section.
+//*/
+///*bluetooth->accumulateAdvertisingPayload(
+//    GapAdvertisingData::COMPLETE_LIST_16BIT_SERVICE_IDS, 
+//    (uint8_t *)uuid16_list, 
+//    sizeof(uuid16_list)
+//);*/
+//bluetooth->accumulateAdvertisingPayload(
+//    GapAdvertisingData::INCOMPLETE_LIST_128BIT_SERVICE_IDS,
+//    (uint8_t *)uuid128_list,
+//    sizeof(uuid128_list)
+//);                                              
+//                                              
+//                                              
+//                                              
+//                                              
+//                                              
+                                              
+static volatile bool  triggerSensorPolling = false;
+
+void disconnectionCallback(Gap::Handle_t handle, Gap::DisconnectionReason_t reason)
+{
+    ble.startAdvertising(); // restart advertising
+}
+
+void periodicCallback(void)
+{
+    ledIndicator = !ledIndicator; /* Do blinky on LED1 while we're waiting for BLE events */
+    testOut = !testOut;
+}
+
+int main(void)
+{
+    ledIndicator = 0;
+    testOut = 0;
+
+    // Ticker is interrupt driven
+    Ticker ticker;
+    ticker.attach_us(periodicCallback, 100000);
+
+    // Init BLE
+    ble.init();
+    ble.onDisconnection(disconnectionCallback);
+    
+    // Setup advertising
+    /* BREDR_NOT_SUPPORTED means classic bluetooth not supported;
+    * LE_GENERAL_DISCOVERABLE means that this peripheral can be
+    * discovered by any BLE scanner--i.e. any phone. */
+    ble.accumulateAdvertisingPayload(GapAdvertisingData::BREDR_NOT_SUPPORTED | GapAdvertisingData::LE_GENERAL_DISCOVERABLE);
+    
+    /* This is where we're collecting the device name into the advertisement payload. */
+    ble.accumulateAdvertisingPayload(GapAdvertisingData::COMPLETE_LOCAL_NAME, (uint8_t *)DEVICE_NAME, sizeof(DEVICE_NAME));
+    
+    /* We'd like for this BLE peripheral to be connectable. */
+    ble.setAdvertisingType(GapAdvertisingParams::ADV_CONNECTABLE_UNDIRECTED);
+    
+    /* set the interval at which advertisements are sent out; this has
+    * an implication power consumption--radio activity being a
+    * biggest draw on average power. The other software controllable
+    * parameter which influences power is the radio's TX power
+    * level--there's an API to adjust that. */
+    ble.setAdvertisingInterval(Gap::MSEC_TO_ADVERTISEMENT_DURATION_UNITS(1000)); /* 1000ms. */
+    
+    /* we're finally good to go with advertisements. */
+    ble.startAdvertising();
+    
+    while (true) 
+    {
+        ble.waitForEvent();
+    }    
+//    /* Setup primary service. */
+//    uint8_t hrmCounter = 100; // init HRM to 100bps
+//    HeartRateService hrService(ble, hrmCounter, HeartRateService::LOCATION_FINGER);
+//
+//    /* Setup auxiliary service. */
+//    DeviceInformationService deviceInfo(ble, "ARM", "Model1", "SN1", "hw-rev1", "fw-rev1", "soft-rev1");
+//
+//    /* Setup advertising. */
+//    ble.accumulateAdvertisingPayload(GapAdvertisingData::BREDR_NOT_SUPPORTED | GapAdvertisingData::LE_GENERAL_DISCOVERABLE);
+//    ble.accumulateAdvertisingPayload(GapAdvertisingData::COMPLETE_LIST_16BIT_SERVICE_IDS, (uint8_t *)uuid16_list, sizeof(uuid16_list));
+//    ble.accumulateAdvertisingPayload(GapAdvertisingData::GENERIC_HEART_RATE_SENSOR);
+//    ble.accumulateAdvertisingPayload(GapAdvertisingData::COMPLETE_LOCAL_NAME, (uint8_t *)DEVICE_NAME, sizeof(DEVICE_NAME));
+//    ble.setAdvertisingType(GapAdvertisingParams::ADV_CONNECTABLE_UNDIRECTED);
+//    ble.setAdvertisingInterval(Gap::MSEC_TO_ADVERTISEMENT_DURATION_UNITS(1000));
+//    ble.startAdvertising();
+//
+//    // infinite loop
+//    while (1) {
+//        // check for trigger from periodicCallback()
+//        if (triggerSensorPolling && ble.getGapState().connected) {
+//            triggerSensorPolling = false;
+//
+//            // Do blocking calls or whatever is necessary for sensor polling.
+//            // In our case, we simply update the HRM measurement. 
+//            hrmCounter++;
+//            
+//            //  100 <= HRM bps <=175
+//            if (hrmCounter == 175) {
+//                hrmCounter = 100;
+//            }
+//            
+//            // update bps
+//            hrService.updateHeartRate(hrmCounter);
+//        } else {
+//            ble.waitForEvent(); // low power wait for event
+//        }
+//    }
+}