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

Files at this revision

API Documentation at this revision

Comitter:
Bobty
Date:
Mon Dec 14 22:58:31 2015 +0000
Parent:
4:f0b030a3223f
Child:
6:4a12e0f03381
Commit message:
Works reliably - time only (no alarm functions) - doesn't display on binary digits as yet

Changed in this revision

WatchTimeService.h Show annotated file Show diff for this revision Revisions of this file
main.cpp Show annotated file Show diff for this revision Revisions of this file
mbed-src.lib Show annotated file Show diff for this revision Revisions of this file
mbed.bld Show diff for this revision Revisions of this file
--- a/WatchTimeService.h	Mon Jul 27 19:30:11 2015 +0000
+++ b/WatchTimeService.h	Mon Dec 14 22:58:31 2015 +0000
@@ -4,6 +4,8 @@
 #ifndef __BLE_WATCHTIME_SERVICE_H__
 #define __BLE_WATCHTIME_SERVICE_H__
 
+//typedef void (*GetCurTimeCallbackFn)(uint8_t* curWatchTime)
+
 class WatchTimeService {
 public:
 
@@ -11,26 +13,29 @@
     const static uint16_t WATCHTIME_SERVICE_UUID              = 0xFE32;
     const static uint16_t WATCHTIME_STATE_CHARACTERISTIC_UUID = 0xFE33;
 
-    WatchTimeService(BLE &_ble, uint8_t* pInitialWatchTime) :
-        ble(_ble), watchTimeVal(WATCHTIME_STATE_CHARACTERISTIC_UUID, pInitialWatchTime, GattCharacteristic::BLE_GATT_CHAR_PROPERTIES_NOTIFY)
+    WatchTimeService(BLE &ble, uint8_t* pInitialWatchTime) :
+        _ble(ble), 
+        _watchTimeVal(WATCHTIME_STATE_CHARACTERISTIC_UUID, pInitialWatchTime, GattCharacteristic::BLE_GATT_CHAR_PROPERTIES_NOTIFY)
     {
-        GattCharacteristic *charTable[] = {&watchTimeVal};
+        GattCharacteristic *charTable[] = {&_watchTimeVal};
         GattService watchTimeService(WatchTimeService::WATCHTIME_SERVICE_UUID, charTable, sizeof(charTable) / sizeof(GattCharacteristic *));
-        ble.gattServer().addService(watchTimeService);
+        _ble.gattServer().addService(watchTimeService);
     }
 
-    void sendWatchTime(uint8_t* pWatchTime) {
-        ble.gattServer().write(watchTimeVal.getValueHandle(), pWatchTime, WatchTime_BlockSize);
+    void writeWatchTime(uint8_t* pWatchTime)
+    {
+        _ble.gattServer().write(_watchTimeVal.getValueHandle(), pWatchTime, WatchTime_BlockSize);
     }
 
     GattAttribute::Handle_t getValueHandle()
     {
-        return watchTimeVal.getValueHandle();
+        return _watchTimeVal.getValueHandle();
     }
 
 private:
-    BLE &ble;
-    ReadWriteArrayGattCharacteristic<uint8_t, WatchTime_BlockSize> watchTimeVal;
+    BLE &_ble;
+    ReadWriteArrayGattCharacteristic<uint8_t, WatchTime_BlockSize> _watchTimeVal;
+//    GetCurTimeCallbackFn _pGetCurTimeCallback;
 };
 
 #endif /* #ifndef __BLE_WATCHTIME_SERVICE_H__ */
--- a/main.cpp	Mon Jul 27 19:30:11 2015 +0000
+++ b/main.cpp	Mon Dec 14 22:58:31 2015 +0000
@@ -1,6 +1,6 @@
 // BLE Alarm Watch
 // Based on BLE examples on MBED
-// Rob Dobson, 2015
+// Rob Dobson, (c) 2015
 
 #include "mbed.h"
 #include "BLE.h"
@@ -11,14 +11,17 @@
 // BLE platform
 BLE ble;
 
-// Indicator LEDs
-DigitalOut  led1(LED1);
+// Hour LEDs
+DigitalOut hourPins[5] = { p0, p1, p2, p3, p4 };
+
+// Minute LEDs
+DigitalOut minPins[6] = { p23, p24, p25, p28, p29, p30 };
 
 // Button press to show time
-InterruptIn button(D8);
+InterruptIn button(p5);
 
 // Device name - this is the visible name of device on BLE
-const static char     DEVICE_NAME[] = "JoesAlarm";
+const static char DEVICE_NAME[] = "JoesAlarm";
 
 // UUIDs of services offered
 static const uint16_t uuid16_list[] = {ButtonService::BUTTON_SERVICE_UUID, WatchTimeService::WATCHTIME_SERVICE_UUID};
@@ -26,6 +29,19 @@
 // Service offering to read and set the time on the watch
 WatchTimeService *pWatchTimeService;
 
+// Time display state variables
+const int timeDisplayState_None = 0;
+const int timeDisplayState_ShowTime = 1;
+const int timeDisplayState_ShowAlarm = 2;
+int timeDisplayState = timeDisplayState_None;
+uint8_t curBinaryLedDisplayVal[WatchTimeService::WatchTime_BlockSize];
+int timeDisplayLastButtonTime = 0;
+const int timeDisplayShowTimeSecs = 10;
+const int timeDisplayMoveToShowAlarmSecs = 5;
+
+// Cur time disp info
+int curTimeLEDBitPos = 0;
+
 // TEST CODE
 int callbackCount = 0;
 uint8_t testbuf[WatchTimeService::WatchTime_BlockSize];
@@ -36,36 +52,8 @@
 int offs = 0;
 int butcode = 0;
 ButtonService *buttonServicePtr;
-
-// Handle button press to read watch
-void buttonPressedCallback(void)
-{
-// TEST CODE
-    buttonServicePtr->updateButtonState(true);
-}
-
-// TEST CODE
-void buttonReleasedCallback(void)
-{
-// TEST CODE
-    buttonServicePtr->updateButtonState(false);
-}
-
-// Handle BLE disconnection - restart advertising
-void disconnectionCallback(Gap::Handle_t handle, Gap::DisconnectionReason_t reason)
-{
-    ble.gap().startAdvertising();
-}
-
-// TEST CODE
-void periodicCallback(void)
-{
-    led1 = !led1; /* Do blinky on LED1 to indicate system aliveness. */
-    
-    // Update the rtc library time (it says in the notes on the rtc lib that this needs to happen
-    // more than once every few hundred seconds to avoid a rollover
-    rtc.time();
-}
+Ticker periodicCallbackToKeepTimerGoing;
+Timeout timerForLEDMuxing;
 
 time_t watchTimeToUnix(const uint8_t* pWatchTime)
 {
@@ -81,6 +69,150 @@
     return timest;
 }
 
+void unixTimeToWatchTime(time_t unixTime, uint8_t* pWatchTime)
+{
+    // Convert to localtime
+    struct tm * timeinfo;     
+    timeinfo = localtime (&unixTime);
+    pWatchTime[0] = (timeinfo->tm_year + 1900) / 256;
+    pWatchTime[1] = (timeinfo->tm_year + 1900) % 256;
+    pWatchTime[2] = timeinfo->tm_mon + 1;
+    pWatchTime[3] = timeinfo->tm_mday;
+    pWatchTime[4] = timeinfo->tm_hour;
+    pWatchTime[5] = timeinfo->tm_min;
+    pWatchTime[6] = timeinfo->tm_sec;
+}
+
+int watchTimeToBCD(const uint8_t* pWatchTime)
+{
+    // Simply combine the hour and minute values in a 4 digit BCD number
+    int bcdHourMin = pWatchTime[4] / 10;
+    bcdHourMin = (bcdHourMin << 4) + pWatchTime[4] % 10;
+    bcdHourMin = (bcdHourMin << 4) + pWatchTime[5] / 10;
+    bcdHourMin = (bcdHourMin << 4) + pWatchTime[5] % 10;
+    return bcdHourMin;
+}
+
+void callbackForLEDMuxing();
+
+void clearTimeLEDs()
+{
+    for (int i = 0; i < 5; i++)
+        hourPins[i] = 0;
+    for (int i = 0; i < 6; i++)
+        minPins[i] = 0;
+}
+
+//uint8_t* GetCurTimeAsWatchTime()
+//{
+//    // Get current time and convert to displayable time
+//    time_t rawtime=rtc.time();
+//    unixTimeToWatchTime(rawtime, curBinaryLedDisplayVal);
+//}
+    
+void nextShowingTimeLEDs()
+{
+    // Get current time and convert to displayable time
+    time_t rawtime=rtc.time();
+    unixTimeToWatchTime(rawtime, curBinaryLedDisplayVal);
+    
+    // Clear LEDs
+    clearTimeLEDs();
+    
+    // Stop displaying time after a certain number of seconds
+    if (rawtime - timeDisplayLastButtonTime >= timeDisplayShowTimeSecs)
+        return;
+
+    // Display binary time
+    int hours = curBinaryLedDisplayVal[4];
+    int mins = curBinaryLedDisplayVal[5];
+    int mask = 1 << curTimeLEDBitPos;
+    if ((curTimeLEDBitPos < 5) && ((hours & mask) != 0))
+        hourPins[curTimeLEDBitPos] = 1;
+    if ((mins & mask) != 0)
+        minPins[curTimeLEDBitPos] = 1;
+    curTimeLEDBitPos++;
+    if (curTimeLEDBitPos > 5)
+        curTimeLEDBitPos = 0;
+
+    // Set for another callback
+    timerForLEDMuxing.attach(callbackForLEDMuxing, 0.001);
+}
+
+void callbackForLEDMuxing()
+{
+    nextShowingTimeLEDs();
+}
+    
+void startShowingTimeLEDs()
+{
+    curTimeLEDBitPos = 0;
+    timerForLEDMuxing.attach(callbackForLEDMuxing, 0.001);
+}
+
+void stopShowingTimeLEDs()
+{
+    clearTimeLEDs();
+}
+
+// Handle button press to read watch
+void buttonPressedCallback(void)
+{
+    // Get the time to display
+    time_t rawtime=rtc.time();
+    
+    // Check if we should display current time or alarm time
+    if (rawtime - timeDisplayLastButtonTime > timeDisplayMoveToShowAlarmSecs)
+    {
+        timeDisplayState = timeDisplayState_ShowTime;
+    }
+    else
+    {
+        // TO BE DONE 
+        // - move alarm time value to the curBinaryLedDisplayVal
+        timeDisplayState = timeDisplayState_ShowAlarm;
+    }
+    startShowingTimeLEDs();
+    
+    // Remember when button last pressed
+    timeDisplayLastButtonTime = rawtime;
+
+    // Update the button-state service
+    buttonServicePtr->updateButtonState(true);
+}
+
+// TEST CODE
+void buttonReleasedCallback(void)
+{
+    // Update the button-state service
+    buttonServicePtr->updateButtonState(false);
+}
+
+// Handle BLE disconnection - restart advertising
+void disconnectionCallback(Gap::Handle_t handle, Gap::DisconnectionReason_t reason)
+{
+    ble.gap().startAdvertising();
+}
+
+// TEST CODE
+void periodicCallback(void)
+{
+    // Update the rtc library time (it says in the notes on the rtc lib that this needs to happen
+    // more than once every few hundred seconds to avoid a rollover
+    rtc.time();
+}
+
+void setRTCfromWatchTime(const uint8_t* pWatchTime)
+{
+    time_t timest = watchTimeToUnix(pWatchTime);
+    retval = timest;
+    if ((int)timest != -1)
+    {
+        rtc.set_time(timest);
+        minPins[5] = !minPins[5];
+    }
+}
+
 void onDataWrittenCallback(const GattWriteCallbackParams *params) 
 {
     // TEST code
@@ -97,10 +229,7 @@
     {
         if (params->len == WatchTimeService::WatchTime_BlockSize)
         {
-            time_t timest = watchTimeToUnix(params->data);
-            retval = timest;
-            if (timest != -1)
-                rtc.set_time(timest);
+            setRTCfromWatchTime(params->data);
         }
     }
 }
@@ -125,12 +254,13 @@
     // TEST CODE
     memset(testbuf, 0, WatchTimeService::WatchTime_BlockSize);
     int loopCount = 0;
-    led1 = 1;
-    Ticker ticker;
-    ticker.attach(periodicCallback, 1);
+    periodicCallbackToKeepTimerGoing.attach(periodicCallback, 1);
     button.fall(buttonPressedCallback);
     button.rise(buttonReleasedCallback);
 
+    // Clear display
+    clearTimeLEDs();
+    
     // BLE init
     ble.init();
     ble.gap().onDisconnection(disconnectionCallback);
@@ -143,8 +273,9 @@
     // Watch Time Service
     uint8_t initialTime[] = { uint8_t(2015/256), uint8_t(2015%256), 7, 26, 12, 8, 0 };    
     WatchTimeService watchTimeService(ble, initialTime);
+    setRTCfromWatchTime(initialTime);
     pWatchTimeService = &watchTimeService;
-
+    
     // Setup advertising
     ble.gap().accumulateAdvertisingPayload(GapAdvertisingData::BREDR_NOT_SUPPORTED | GapAdvertisingData::LE_GENERAL_DISCOVERABLE);
     ble.gap().accumulateAdvertisingPayload(GapAdvertisingData::COMPLETE_LIST_16BIT_SERVICE_IDS, (uint8_t *)uuid16_list, sizeof(uuid16_list));
@@ -153,24 +284,41 @@
     ble.gap().setAdvertisingInterval(1000); /* 1000ms. */
     ble.gap().startAdvertising();
 
-    while (true) {
+    uint8_t curWatchTime[WatchTimeService::WatchTime_BlockSize];
+    while (true) 
+    {
         ble.waitForEvent();
         
+        // TEST CODE    
         loopCount++;
         if (loopCount < 5)
             continue;
         loopCount = 0;
         
-        time_t rawtime;
-        struct tm * timeinfo;        
-        time (&rawtime);
-        timeinfo = localtime (&rawtime);
-        printf ("Current local time and date: %s callbacks %d retval %d\r\n", asctime(timeinfo), callbackCount, retval);
-        printf ("Timest %02x %02x %02x %02x %02x %02x %02x %ld\r\n", testbuf[0],
+        print_time();
+        // Get current time and convert to watch time
+        time_t rawtime=rtc.time();
+        unixTimeToWatchTime(rawtime, curWatchTime);
+        pWatchTimeService->writeWatchTime(curWatchTime);
+
+        
+/*        printf ("Timest %02x %02x %02x %02x %02x %02x %02x %ld\r\n", testbuf[0],
                 testbuf[1], testbuf[2], testbuf[3], testbuf[4], testbuf[5], testbuf[6], retval); 
         printf ("serv %d buflen %d mycode %d offs %d butcode %d\r\n", servcode, buflen, mycode, offs, butcode);
         printf ("val %ld\r\n", watchTimeService.getValueHandle());
         print_time();
+        
+        if (timeDisplayState != timeDisplayState_None)
+        {
+            int watchLedTime = watchTimeToBCD(curBinaryLedDisplayVal);
+            printf("watchTime %04x = ", watchLedTime);
+            for (int i = 15; i >= 0; i--)
+            {
+                printf("%d", (watchLedTime >> i) % 2);
+            }
+            printf("\r\n");
+        }
+        */
     }
 }
 
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/mbed-src.lib	Mon Dec 14 22:58:31 2015 +0000
@@ -0,0 +1,1 @@
+http://mbed.org/users/mbed_official/code/mbed-src/#a11c0372f0ba
--- a/mbed.bld	Mon Jul 27 19:30:11 2015 +0000
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,1 +0,0 @@
-http://mbed.org/users/mbed_official/code/mbed/builds/bad568076d81
\ No newline at end of file