Important changes to repositories hosted on mbed.com
Mbed hosted mercurial repositories are deprecated and are due to be permanently deleted in July 2026.
To keep a copy of this software download the repository Zip archive or clone locally using Mercurial.
It is also possible to export all your personal repositories from the account settings page.
Dependencies: Hexi_KW40Z Hexi_OLED_SSD1351
main.cpp@4:1ae9f76749b9, 2018-06-14 (annotated)
- Committer:
 - trhackett
 - Date:
 - Thu Jun 14 19:39:23 2018 +0000
 - Revision:
 - 4:1ae9f76749b9
 - Parent:
 - 3:f34bbdea0786
 
current time mbed post comp arch
Who changed what in which revision?
| User | Revision | Line number | New contents of line | 
|---|---|---|---|
| trhackett | 0:2b94f7017e4e | 1 | #include "mbed.h" | 
| trhackett | 3:f34bbdea0786 | 2 | #include "Hexi_KW40Z.h" | 
| trhackett | 3:f34bbdea0786 | 3 | #include "Hexi_OLED_SSD1351.h" | 
| trhackett | 0:2b94f7017e4e | 4 | #include "Ticker.h" | 
| trhackett | 3:f34bbdea0786 | 5 | #include "timeHelp.h" | 
| trhackett | 0:2b94f7017e4e | 6 | |
| trhackett | 3:f34bbdea0786 | 7 | void AlertReceived(uint8_t *data, uint8_t length); | 
| trhackett | 3:f34bbdea0786 | 8 | void displayTimeToScreen(); | 
| trhackett | 3:f34bbdea0786 | 9 | void clearScreen(); | 
| trhackett | 3:f34bbdea0786 | 10 | void updateError(); | 
| trhackett | 3:f34bbdea0786 | 11 | void updateDisplayString(); | 
| trhackett | 3:f34bbdea0786 | 12 | void txTask(); | 
| trhackett | 0:2b94f7017e4e | 13 | |
| trhackett | 3:f34bbdea0786 | 14 | KW40Z kw40z_device(PTE24, PTE25); | 
| trhackett | 0:2b94f7017e4e | 15 | |
| trhackett | 3:f34bbdea0786 | 16 | // oled driver and its text buffer | 
| trhackett | 3:f34bbdea0786 | 17 | SSD1351 oled(PTB22,PTB21,PTC13,PTB20,PTE6, PTD15); | 
| trhackett | 3:f34bbdea0786 | 18 | char text[20]; | 
| trhackett | 3:f34bbdea0786 | 19 | |
| trhackett | 3:f34bbdea0786 | 20 | const float interval = 0.1; | 
| trhackett | 3:f34bbdea0786 | 21 | int numTicks = 0; | 
| trhackett | 3:f34bbdea0786 | 22 | int prevNumTicks = 0; | 
| trhackett | 4:1ae9f76749b9 | 23 | float intervalError = 0.0; | 
| trhackett | 0:2b94f7017e4e | 24 | |
| trhackett | 3:f34bbdea0786 | 25 | char prevTime[11] = "00:00:00.0"; | 
| trhackett | 3:f34bbdea0786 | 26 | char displayTime[11] = "00:00:00.0"; | 
| trhackett | 0:2b94f7017e4e | 27 | |
| trhackett | 3:f34bbdea0786 | 28 | // important to know whether or not we've synced at least once with pi | 
| trhackett | 3:f34bbdea0786 | 29 | // because we don't have an initial time until we hear from pi | 
| trhackett | 3:f34bbdea0786 | 30 | bool firstSync = true; | 
| trhackett | 3:f34bbdea0786 | 31 | bool syncedTwice = false; | 
| trhackett | 3:f34bbdea0786 | 32 | |
| trhackett | 3:f34bbdea0786 | 33 | DigitalOut pwm(PTA10); | 
| trhackett | 0:2b94f7017e4e | 34 | |
| trhackett | 3:f34bbdea0786 | 35 | |
| trhackett | 3:f34bbdea0786 | 36 | // bluetooth thread | 
| trhackett | 3:f34bbdea0786 | 37 | Thread txThread; | 
| trhackett | 0:2b94f7017e4e | 38 | |
| trhackett | 3:f34bbdea0786 | 39 | // event queue for displaying the time | 
| trhackett | 3:f34bbdea0786 | 40 | EventQueue displayQueue; | 
| trhackett | 3:f34bbdea0786 | 41 | // event queue for receiving the time | 
| trhackett | 3:f34bbdea0786 | 42 | EventQueue receiveTimeQueue; | 
| trhackett | 0:2b94f7017e4e | 43 | |
| trhackett | 3:f34bbdea0786 | 44 | int main() { | 
| trhackett | 3:f34bbdea0786 | 45 | |
| trhackett | 3:f34bbdea0786 | 46 | kw40z_device.attach_alert(&AlertReceived); | 
| trhackett | 3:f34bbdea0786 | 47 | |
| trhackett | 3:f34bbdea0786 | 48 | // thread that displays the time for us | 
| trhackett | 3:f34bbdea0786 | 49 | Thread displayThread; | 
| trhackett | 3:f34bbdea0786 | 50 | displayThread.start(callback(&displayQueue, &EventQueue::dispatch_forever)); | 
| trhackett | 3:f34bbdea0786 | 51 | |
| trhackett | 3:f34bbdea0786 | 52 | // thread that responds to pi's time updates | 
| trhackett | 3:f34bbdea0786 | 53 | Thread receiveTimeThread; | 
| trhackett | 3:f34bbdea0786 | 54 | receiveTimeThread.start(callback(&receiveTimeQueue, &EventQueue::dispatch_forever)); | 
| trhackett | 3:f34bbdea0786 | 55 | |
| trhackett | 3:f34bbdea0786 | 56 | // initialize the screen to blank | 
| trhackett | 3:f34bbdea0786 | 57 | displayQueue.call(&clearScreen); | 
| trhackett | 3:f34bbdea0786 | 58 | displayQueue.call(&displayTimeToScreen); | 
| trhackett | 3:f34bbdea0786 | 59 | |
| trhackett | 3:f34bbdea0786 | 60 | // ticker that increments the time | 
| trhackett | 3:f34bbdea0786 | 61 | Ticker updateTimeTicker; | 
| trhackett | 3:f34bbdea0786 | 62 | updateTimeTicker.attach(receiveTimeQueue.event(&updateDisplayString), interval); | 
| trhackett | 3:f34bbdea0786 | 63 | |
| trhackett | 3:f34bbdea0786 | 64 | // start toggling bluetooth so you can connect | 
| trhackett | 3:f34bbdea0786 | 65 | txThread.start(txTask); | 
| trhackett | 3:f34bbdea0786 | 66 | |
| trhackett | 3:f34bbdea0786 | 67 | wait(osWaitForever); | 
| trhackett | 0:2b94f7017e4e | 68 | } | 
| trhackett | 0:2b94f7017e4e | 69 | |
| trhackett | 3:f34bbdea0786 | 70 | /******************************End of Main*************************************/ | 
| trhackett | 3:f34bbdea0786 | 71 | |
| trhackett | 3:f34bbdea0786 | 72 | // initialize the screen to black | 
| trhackett | 3:f34bbdea0786 | 73 | void clearScreen() { | 
| trhackett | 3:f34bbdea0786 | 74 | oled.FillScreen(COLOR_BLACK); | 
| trhackett | 0:2b94f7017e4e | 75 | } | 
| trhackett | 0:2b94f7017e4e | 76 | |
| trhackett | 3:f34bbdea0786 | 77 | void displayTimeToScreen() { | 
| trhackett | 3:f34bbdea0786 | 78 | /* Get OLED Class Default Text Properties */ | 
| trhackett | 3:f34bbdea0786 | 79 | oled_text_properties_t textProperties = {0}; | 
| trhackett | 3:f34bbdea0786 | 80 | oled.GetTextProperties(&textProperties); | 
| trhackett | 0:2b94f7017e4e | 81 | |
| trhackett | 3:f34bbdea0786 | 82 | /* Change font color to Blue */ | 
| trhackett | 3:f34bbdea0786 | 83 | textProperties.fontColor = COLOR_BLUE; | 
| trhackett | 3:f34bbdea0786 | 84 | oled.SetTextProperties(&textProperties); | 
| trhackett | 3:f34bbdea0786 | 85 | |
| trhackett | 3:f34bbdea0786 | 86 | if (secondsAreEven(displayTime)) { | 
| trhackett | 3:f34bbdea0786 | 87 | pwm = 0 ; | 
| trhackett | 3:f34bbdea0786 | 88 | } else { | 
| trhackett | 3:f34bbdea0786 | 89 | pwm = 1; | 
| trhackett | 0:2b94f7017e4e | 90 | } | 
| trhackett | 0:2b94f7017e4e | 91 | |
| trhackett | 3:f34bbdea0786 | 92 | /* Display time Label at x=20,y=40 */ | 
| trhackett | 3:f34bbdea0786 | 93 | strcpy((char *) text, displayTime); | 
| trhackett | 3:f34bbdea0786 | 94 | oled.Label((uint8_t *)text,20,40); | 
| trhackett | 0:2b94f7017e4e | 95 | } | 
| trhackett | 0:2b94f7017e4e | 96 | |
| trhackett | 3:f34bbdea0786 | 97 | // the alert that we've received is always the updated time from raspberry pi | 
| trhackett | 3:f34bbdea0786 | 98 | // so we should put that in display time, calculate the new interval, and | 
| trhackett | 3:f34bbdea0786 | 99 | // display the new time | 
| trhackett | 3:f34bbdea0786 | 100 | void AlertReceived(uint8_t *data, uint8_t length) { | 
| trhackett | 3:f34bbdea0786 | 101 | |
| trhackett | 3:f34bbdea0786 | 102 | char buf[10]; | 
| trhackett | 3:f34bbdea0786 | 103 | for (int i = 0; i < 10; ++i) { | 
| trhackett | 3:f34bbdea0786 | 104 | buf[i] = data[i]; | 
| trhackett | 3:f34bbdea0786 | 105 | } | 
| trhackett | 0:2b94f7017e4e | 106 | |
| trhackett | 3:f34bbdea0786 | 107 | // copy in the new data, storing the old only if there is old to store | 
| trhackett | 3:f34bbdea0786 | 108 | for (int i = 0; i < 10; i++) { | 
| trhackett | 3:f34bbdea0786 | 109 | if (!firstSync) { | 
| trhackett | 3:f34bbdea0786 | 110 | prevTime[i] = displayTime[i]; | 
| trhackett | 3:f34bbdea0786 | 111 | } | 
| trhackett | 3:f34bbdea0786 | 112 | |
| trhackett | 3:f34bbdea0786 | 113 | else { | 
| trhackett | 3:f34bbdea0786 | 114 | prevTime[i] = buf[i]; | 
| trhackett | 3:f34bbdea0786 | 115 | |
| trhackett | 3:f34bbdea0786 | 116 | // if you get here, then you've synced once | 
| trhackett | 3:f34bbdea0786 | 117 | if (!syncedTwice) { | 
| trhackett | 3:f34bbdea0786 | 118 | syncedTwice = true; | 
| trhackett | 3:f34bbdea0786 | 119 | } | 
| trhackett | 3:f34bbdea0786 | 120 | } | 
| trhackett | 3:f34bbdea0786 | 121 | displayTime[i] = buf[i]; | 
| trhackett | 0:2b94f7017e4e | 122 | } | 
| trhackett | 0:2b94f7017e4e | 123 | |
| trhackett | 3:f34bbdea0786 | 124 | // reset numTicks | 
| trhackett | 3:f34bbdea0786 | 125 | prevNumTicks = numTicks; | 
| trhackett | 3:f34bbdea0786 | 126 | numTicks = 0; | 
| trhackett | 3:f34bbdea0786 | 127 | |
| trhackett | 3:f34bbdea0786 | 128 | // update the error as long as it isn't your first sync ... need two times | 
| trhackett | 3:f34bbdea0786 | 129 | if (!firstSync && syncedTwice) { | 
| trhackett | 3:f34bbdea0786 | 130 | receiveTimeQueue.call(&updateError); | 
| trhackett | 0:2b94f7017e4e | 131 | } | 
| trhackett | 0:2b94f7017e4e | 132 | |
| trhackett | 3:f34bbdea0786 | 133 | firstSync = false; | 
| trhackett | 3:f34bbdea0786 | 134 | } | 
| trhackett | 3:f34bbdea0786 | 135 | |
| trhackett | 3:f34bbdea0786 | 136 | // error is the total amount that hexiwear was off by | 
| trhackett | 3:f34bbdea0786 | 137 | // averaged over all of the ticks ... moving forward we | 
| trhackett | 3:f34bbdea0786 | 138 | // can add the error into out calculation of the current | 
| trhackett | 3:f34bbdea0786 | 139 | // time and hopefully it will be more accurate. | 
| trhackett | 3:f34bbdea0786 | 140 | void updateError() { | 
| trhackett | 0:2b94f7017e4e | 141 | |
| trhackett | 4:1ae9f76749b9 | 142 | // | 
| trhackett | 4:1ae9f76749b9 | 143 | float secsToAdd = prevNumTicks * (interval + intervalError); | 
| trhackett | 3:f34bbdea0786 | 144 | |
| trhackett | 3:f34bbdea0786 | 145 | float T1 = currTimeSecs(displayTime); | 
| trhackett | 3:f34bbdea0786 | 146 | float T0 = currTimeSecs(prevTime); | 
| trhackett | 3:f34bbdea0786 | 147 | |
| trhackett | 4:1ae9f76749b9 | 148 | intervalError = (T1 - (T0+secsToAdd)) / prevNumTicks; | 
| trhackett | 0:2b94f7017e4e | 149 | } | 
| trhackett | 0:2b94f7017e4e | 150 | |
| trhackett | 3:f34bbdea0786 | 151 | int numPrints = 20; | 
| trhackett | 3:f34bbdea0786 | 152 | |
| trhackett | 3:f34bbdea0786 | 153 | // you update the display string every 0.1 seconds, to add to the | 
| trhackett | 3:f34bbdea0786 | 154 | // number of ticks, calculate the offset from the previous time, | 
| trhackett | 3:f34bbdea0786 | 155 | // and display it | 
| trhackett | 3:f34bbdea0786 | 156 | void updateDisplayString() { | 
| trhackett | 3:f34bbdea0786 | 157 | numTicks++; | 
| trhackett | 0:2b94f7017e4e | 158 | |
| trhackett | 4:1ae9f76749b9 | 159 | float offset = numTicks * (interval + intervalError); | 
| trhackett | 0:2b94f7017e4e | 160 | |
| trhackett | 3:f34bbdea0786 | 161 | addSecondsToCurrentTime(prevTime, displayTime, offset); | 
| trhackett | 0:2b94f7017e4e | 162 | |
| trhackett | 3:f34bbdea0786 | 163 | displayQueue.call(&displayTimeToScreen); | 
| trhackett | 3:f34bbdea0786 | 164 | } | 
| trhackett | 3:f34bbdea0786 | 165 | |
| trhackett | 3:f34bbdea0786 | 166 | // take care of the bluetooth toggling so that it can conect | 
| trhackett | 3:f34bbdea0786 | 167 | void txTask(){ | 
| trhackett | 3:f34bbdea0786 | 168 | |
| trhackett | 3:f34bbdea0786 | 169 | while (true) | 
| trhackett | 3:f34bbdea0786 | 170 | { | 
| trhackett | 3:f34bbdea0786 | 171 | // there is about a half second delay before the hexiwear | 
| trhackett | 3:f34bbdea0786 | 172 | // realizes that the link state is down, so if you ever | 
| trhackett | 3:f34bbdea0786 | 173 | // do realize that, you should toggle the advertisement | 
| trhackett | 3:f34bbdea0786 | 174 | // state right away, I think. NO what you should do it, if | 
| trhackett | 3:f34bbdea0786 | 175 | // you ever realize that the link is down, wait a half a second | 
| trhackett | 3:f34bbdea0786 | 176 | // and then toggle advertisement mode to let it refresh | 
| trhackett | 3:f34bbdea0786 | 177 | |
| trhackett | 3:f34bbdea0786 | 178 | // it seems like this doesn't perform quite as well, but I think | 
| trhackett | 3:f34bbdea0786 | 179 | // it is more robust... | 
| trhackett | 3:f34bbdea0786 | 180 | if (kw40z_device.GetLinkState() == 0) { | 
| trhackett | 3:f34bbdea0786 | 181 | Thread::wait(2500); | 
| trhackett | 3:f34bbdea0786 | 182 | if (kw40z_device.GetLinkState() == 0) { | 
| trhackett | 3:f34bbdea0786 | 183 | kw40z_device.ToggleAdvertisementMode(); | 
| trhackett | 3:f34bbdea0786 | 184 | } | 
| trhackett | 3:f34bbdea0786 | 185 | } | 
| trhackett | 3:f34bbdea0786 | 186 | |
| trhackett | 3:f34bbdea0786 | 187 | Thread::wait(5000); | 
| trhackett | 3:f34bbdea0786 | 188 | } | 
| trhackett | 2:75253a344332 | 189 | } |