![](/media/cache/img/default_profile.jpg.50x50_q85.jpg)
run this here
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 | } |