![](/media/cache/img/default_profile.jpg.50x50_q85.jpg)
run this here
Dependencies: Hexi_KW40Z Hexi_OLED_SSD1351
main.cpp@3:f34bbdea0786, 2018-06-12 (annotated)
- Committer:
- trhackett
- Date:
- Tue Jun 12 00:27:26 2018 +0000
- Revision:
- 3:f34bbdea0786
- Parent:
- 2:75253a344332
- Child:
- 4:1ae9f76749b9
initial commit, can't get more than one hexiwear at once
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 | 3:f34bbdea0786 | 23 | float timingError = 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 | // pc.printf("main started!!\r\n"); |
trhackett | 3:f34bbdea0786 | 46 | |
trhackett | 3:f34bbdea0786 | 47 | kw40z_device.attach_alert(&AlertReceived); |
trhackett | 3:f34bbdea0786 | 48 | |
trhackett | 3:f34bbdea0786 | 49 | // thread that displays the time for us |
trhackett | 3:f34bbdea0786 | 50 | Thread displayThread; |
trhackett | 3:f34bbdea0786 | 51 | displayThread.start(callback(&displayQueue, &EventQueue::dispatch_forever)); |
trhackett | 3:f34bbdea0786 | 52 | |
trhackett | 3:f34bbdea0786 | 53 | // thread that responds to pi's time updates |
trhackett | 3:f34bbdea0786 | 54 | Thread receiveTimeThread; |
trhackett | 3:f34bbdea0786 | 55 | receiveTimeThread.start(callback(&receiveTimeQueue, &EventQueue::dispatch_forever)); |
trhackett | 3:f34bbdea0786 | 56 | |
trhackett | 3:f34bbdea0786 | 57 | // initialize the screen to blank |
trhackett | 3:f34bbdea0786 | 58 | displayQueue.call(&clearScreen); |
trhackett | 3:f34bbdea0786 | 59 | displayQueue.call(&displayTimeToScreen); |
trhackett | 3:f34bbdea0786 | 60 | |
trhackett | 3:f34bbdea0786 | 61 | // ticker that increments the time |
trhackett | 3:f34bbdea0786 | 62 | Ticker updateTimeTicker; |
trhackett | 3:f34bbdea0786 | 63 | updateTimeTicker.attach(receiveTimeQueue.event(&updateDisplayString), interval); |
trhackett | 3:f34bbdea0786 | 64 | |
trhackett | 3:f34bbdea0786 | 65 | // start toggling bluetooth so you can connect |
trhackett | 3:f34bbdea0786 | 66 | txThread.start(txTask); |
trhackett | 3:f34bbdea0786 | 67 | |
trhackett | 3:f34bbdea0786 | 68 | wait(osWaitForever); |
trhackett | 0:2b94f7017e4e | 69 | } |
trhackett | 0:2b94f7017e4e | 70 | |
trhackett | 3:f34bbdea0786 | 71 | /******************************End of Main*************************************/ |
trhackett | 3:f34bbdea0786 | 72 | |
trhackett | 3:f34bbdea0786 | 73 | // initialize the screen to black |
trhackett | 3:f34bbdea0786 | 74 | void clearScreen() { |
trhackett | 3:f34bbdea0786 | 75 | oled.FillScreen(COLOR_BLACK); |
trhackett | 0:2b94f7017e4e | 76 | } |
trhackett | 0:2b94f7017e4e | 77 | |
trhackett | 3:f34bbdea0786 | 78 | void displayTimeToScreen() { |
trhackett | 3:f34bbdea0786 | 79 | /* Get OLED Class Default Text Properties */ |
trhackett | 3:f34bbdea0786 | 80 | oled_text_properties_t textProperties = {0}; |
trhackett | 3:f34bbdea0786 | 81 | oled.GetTextProperties(&textProperties); |
trhackett | 0:2b94f7017e4e | 82 | |
trhackett | 3:f34bbdea0786 | 83 | /* Change font color to Blue */ |
trhackett | 3:f34bbdea0786 | 84 | textProperties.fontColor = COLOR_BLUE; |
trhackett | 3:f34bbdea0786 | 85 | oled.SetTextProperties(&textProperties); |
trhackett | 3:f34bbdea0786 | 86 | |
trhackett | 3:f34bbdea0786 | 87 | if (secondsAreEven(displayTime)) { |
trhackett | 3:f34bbdea0786 | 88 | pwm = 0 ; |
trhackett | 3:f34bbdea0786 | 89 | } else { |
trhackett | 3:f34bbdea0786 | 90 | pwm = 1; |
trhackett | 0:2b94f7017e4e | 91 | } |
trhackett | 0:2b94f7017e4e | 92 | |
trhackett | 3:f34bbdea0786 | 93 | /* Display time Label at x=20,y=40 */ |
trhackett | 3:f34bbdea0786 | 94 | strcpy((char *) text, displayTime); |
trhackett | 3:f34bbdea0786 | 95 | oled.Label((uint8_t *)text,20,40); |
trhackett | 0:2b94f7017e4e | 96 | } |
trhackett | 0:2b94f7017e4e | 97 | |
trhackett | 3:f34bbdea0786 | 98 | // the alert that we've received is always the updated time from raspberry pi |
trhackett | 3:f34bbdea0786 | 99 | // so we should put that in display time, calculate the new interval, and |
trhackett | 3:f34bbdea0786 | 100 | // display the new time |
trhackett | 3:f34bbdea0786 | 101 | void AlertReceived(uint8_t *data, uint8_t length) { |
trhackett | 3:f34bbdea0786 | 102 | |
trhackett | 3:f34bbdea0786 | 103 | char buf[10]; |
trhackett | 3:f34bbdea0786 | 104 | for (int i = 0; i < 10; ++i) { |
trhackett | 3:f34bbdea0786 | 105 | buf[i] = data[i]; |
trhackett | 3:f34bbdea0786 | 106 | } |
trhackett | 0:2b94f7017e4e | 107 | |
trhackett | 3:f34bbdea0786 | 108 | // copy in the new data, storing the old only if there is old to store |
trhackett | 3:f34bbdea0786 | 109 | for (int i = 0; i < 10; i++) { |
trhackett | 3:f34bbdea0786 | 110 | if (!firstSync) { |
trhackett | 3:f34bbdea0786 | 111 | prevTime[i] = displayTime[i]; |
trhackett | 3:f34bbdea0786 | 112 | } |
trhackett | 3:f34bbdea0786 | 113 | |
trhackett | 3:f34bbdea0786 | 114 | else { |
trhackett | 3:f34bbdea0786 | 115 | prevTime[i] = buf[i]; |
trhackett | 3:f34bbdea0786 | 116 | |
trhackett | 3:f34bbdea0786 | 117 | // if you get here, then you've synced once |
trhackett | 3:f34bbdea0786 | 118 | if (!syncedTwice) { |
trhackett | 3:f34bbdea0786 | 119 | syncedTwice = true; |
trhackett | 3:f34bbdea0786 | 120 | } |
trhackett | 3:f34bbdea0786 | 121 | } |
trhackett | 3:f34bbdea0786 | 122 | displayTime[i] = buf[i]; |
trhackett | 0:2b94f7017e4e | 123 | } |
trhackett | 0:2b94f7017e4e | 124 | |
trhackett | 3:f34bbdea0786 | 125 | // reset numTicks |
trhackett | 3:f34bbdea0786 | 126 | prevNumTicks = numTicks; |
trhackett | 3:f34bbdea0786 | 127 | numTicks = 0; |
trhackett | 3:f34bbdea0786 | 128 | |
trhackett | 3:f34bbdea0786 | 129 | // update the error as long as it isn't your first sync ... need two times |
trhackett | 3:f34bbdea0786 | 130 | if (!firstSync && syncedTwice) { |
trhackett | 3:f34bbdea0786 | 131 | receiveTimeQueue.call(&updateError); |
trhackett | 0:2b94f7017e4e | 132 | } |
trhackett | 0:2b94f7017e4e | 133 | |
trhackett | 3:f34bbdea0786 | 134 | firstSync = false; |
trhackett | 3:f34bbdea0786 | 135 | } |
trhackett | 3:f34bbdea0786 | 136 | |
trhackett | 3:f34bbdea0786 | 137 | // error is the total amount that hexiwear was off by |
trhackett | 3:f34bbdea0786 | 138 | // averaged over all of the ticks ... moving forward we |
trhackett | 3:f34bbdea0786 | 139 | // can add the error into out calculation of the current |
trhackett | 3:f34bbdea0786 | 140 | // time and hopefully it will be more accurate. |
trhackett | 3:f34bbdea0786 | 141 | void updateError() { |
trhackett | 0:2b94f7017e4e | 142 | |
trhackett | 3:f34bbdea0786 | 143 | float secsToAdd = interval * prevNumTicks + timingError; |
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 | 3:f34bbdea0786 | 148 | timingError += (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 | 3:f34bbdea0786 | 159 | float offset = interval * numTicks + timingError; |
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 | } |