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 5:2682353a8c32, committed 2015-12-14
- 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
--- 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