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:
1:c3d7e673cdd2
Parent:
0:0d5ac2fd4620
Child:
2:9090120e2656
--- a/main.cpp	Tue Mar 10 15:29:07 2015 +0000
+++ b/main.cpp	Tue Mar 10 16:50:59 2015 +0000
@@ -11,107 +11,59 @@
 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;
+// Device name
+const static char     DEVICE_NAME[] = "JOESALARM";
+
+// UUID for CurTimeService & TimeBlockCharacteristic
+const uint16_t UUID_CUR_TIME_SERVICE = 0xA000;
+const uint16_t UUID_TIME_BLOCK_CHARACTERISTIC = 0xA001;
+
+// List of supported service UUIDs
+static const uint16_t uuid16_list[] = {UUID_CUR_TIME_SERVICE};
 
+// Time is packed in an array of bytes
+const int SIZE_OF_TIME_BLOCK = 7;
+uint8_t timeBlockInitValue[SIZE_OF_TIME_BLOCK];
+uint8_t curTimeBlock[SIZE_OF_TIME_BLOCK];
+
+// GATT Characteristic for time block
+ReadWriteGattCharacteristic<uint8_t> timeBlockCharacteristic(UUID_TIME_BLOCK_CHARACTERISTIC, timeBlockInitValue);
+
+// Callback when connection lost
 void disconnectionCallback(Gap::Handle_t handle, Gap::DisconnectionReason_t reason)
 {
     ble.startAdvertising(); // restart advertising
 }
 
+// Callback for ticker
+int tickCount = 0;
+bool showInfo = false;
+int writeSinceLast = 0;
 void periodicCallback(void)
 {
     ledIndicator = !ledIndicator; /* Do blinky on LED1 while we're waiting for BLE events */
     testOut = !testOut;
+    tickCount++;
+    if (tickCount > 100)
+    {
+        showInfo = true;
+        tickCount = 0;
+    }
 }
 
+// Data written callback
+void onDataWrittenCallback(const GattCharacteristicWriteCBParams *params) 
+{
+    if ((params->charHandle == timeBlockCharacteristic.getValueHandle())) 
+    {
+//        && (params->len == SIZE_OF_TIME_BLOCK)
+        writeSinceLast = params->len;
+        memcpy(curTimeBlock, params->data, SIZE_OF_TIME_BLOCK);
+    }
+    writeSinceLast = true;
+}
+
+// Main
 int main(void)
 {
     ledIndicator = 0;
@@ -121,9 +73,18 @@
     Ticker ticker;
     ticker.attach_us(periodicCallback, 100000);
 
-    // Init BLE
+    // Initial value for the time block characteristic
+    memset(timeBlockInitValue, 0, sizeof(timeBlockInitValue));
+
+    // Init BLE and register callbacks
     ble.init();
     ble.onDisconnection(disconnectionCallback);
+    ble.onDataWritten(onDataWrittenCallback);
+
+    // Add the time setting service
+    GattCharacteristic *charTable[] = {&timeBlockCharacteristic};
+    GattService timeBlockService(UUID_CUR_TIME_SERVICE, charTable, sizeof(charTable) / sizeof(GattCharacteristic *));
+    ble.addService(timeBlockService);
     
     // Setup advertising
     /* BREDR_NOT_SUPPORTED means classic bluetooth not supported;
@@ -131,6 +92,9 @@
     * discovered by any BLE scanner--i.e. any phone. */
     ble.accumulateAdvertisingPayload(GapAdvertisingData::BREDR_NOT_SUPPORTED | GapAdvertisingData::LE_GENERAL_DISCOVERABLE);
     
+    // Add services to payload
+    ble.accumulateAdvertisingPayload(GapAdvertisingData::COMPLETE_LIST_16BIT_SERVICE_IDS, (uint8_t *)uuid16_list, sizeof(uuid16_list));
+    
     /* 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));
     
@@ -150,6 +114,18 @@
     while (true) 
     {
         ble.waitForEvent();
+        
+        if (showInfo)
+        {
+            printf("Time info: ");
+            for (int i = 0; i < SIZE_OF_TIME_BLOCK; i++)
+            {
+                printf("%02d", curTimeBlock[i]);
+            }
+            printf(" - writeSinceLast %d\r\n", writeSinceLast);
+            showInfo = false;
+            writeSinceLast = 0;
+        }
     }    
 //    /* Setup primary service. */
 //    uint8_t hrmCounter = 100; // init HRM to 100bps