run this here
Dependencies: Hexi_KW40Z Hexi_OLED_SSD1351
main.cpp
- Committer:
- trhackett
- Date:
- 2018-06-14
- Revision:
- 4:1ae9f76749b9
- Parent:
- 3:f34bbdea0786
File content as of revision 4:1ae9f76749b9:
#include "mbed.h"
#include "Hexi_KW40Z.h"
#include "Hexi_OLED_SSD1351.h"
#include "Ticker.h"
#include "timeHelp.h"
void AlertReceived(uint8_t *data, uint8_t length);
void displayTimeToScreen();
void clearScreen();
void updateError();
void updateDisplayString();
void txTask();
KW40Z kw40z_device(PTE24, PTE25);
// oled driver and its text buffer
SSD1351 oled(PTB22,PTB21,PTC13,PTB20,PTE6, PTD15);
char text[20];
const float interval = 0.1;
int numTicks = 0;
int prevNumTicks = 0;
float intervalError = 0.0;
char prevTime[11] = "00:00:00.0";
char displayTime[11] = "00:00:00.0";
// important to know whether or not we've synced at least once with pi
// because we don't have an initial time until we hear from pi
bool firstSync = true;
bool syncedTwice = false;
DigitalOut pwm(PTA10);
// bluetooth thread
Thread txThread;
// event queue for displaying the time
EventQueue displayQueue;
// event queue for receiving the time
EventQueue receiveTimeQueue;
int main() {
kw40z_device.attach_alert(&AlertReceived);
// thread that displays the time for us
Thread displayThread;
displayThread.start(callback(&displayQueue, &EventQueue::dispatch_forever));
// thread that responds to pi's time updates
Thread receiveTimeThread;
receiveTimeThread.start(callback(&receiveTimeQueue, &EventQueue::dispatch_forever));
// initialize the screen to blank
displayQueue.call(&clearScreen);
displayQueue.call(&displayTimeToScreen);
// ticker that increments the time
Ticker updateTimeTicker;
updateTimeTicker.attach(receiveTimeQueue.event(&updateDisplayString), interval);
// start toggling bluetooth so you can connect
txThread.start(txTask);
wait(osWaitForever);
}
/******************************End of Main*************************************/
// initialize the screen to black
void clearScreen() {
oled.FillScreen(COLOR_BLACK);
}
void displayTimeToScreen() {
/* Get OLED Class Default Text Properties */
oled_text_properties_t textProperties = {0};
oled.GetTextProperties(&textProperties);
/* Change font color to Blue */
textProperties.fontColor = COLOR_BLUE;
oled.SetTextProperties(&textProperties);
if (secondsAreEven(displayTime)) {
pwm = 0 ;
} else {
pwm = 1;
}
/* Display time Label at x=20,y=40 */
strcpy((char *) text, displayTime);
oled.Label((uint8_t *)text,20,40);
}
// the alert that we've received is always the updated time from raspberry pi
// so we should put that in display time, calculate the new interval, and
// display the new time
void AlertReceived(uint8_t *data, uint8_t length) {
char buf[10];
for (int i = 0; i < 10; ++i) {
buf[i] = data[i];
}
// copy in the new data, storing the old only if there is old to store
for (int i = 0; i < 10; i++) {
if (!firstSync) {
prevTime[i] = displayTime[i];
}
else {
prevTime[i] = buf[i];
// if you get here, then you've synced once
if (!syncedTwice) {
syncedTwice = true;
}
}
displayTime[i] = buf[i];
}
// reset numTicks
prevNumTicks = numTicks;
numTicks = 0;
// update the error as long as it isn't your first sync ... need two times
if (!firstSync && syncedTwice) {
receiveTimeQueue.call(&updateError);
}
firstSync = false;
}
// error is the total amount that hexiwear was off by
// averaged over all of the ticks ... moving forward we
// can add the error into out calculation of the current
// time and hopefully it will be more accurate.
void updateError() {
//
float secsToAdd = prevNumTicks * (interval + intervalError);
float T1 = currTimeSecs(displayTime);
float T0 = currTimeSecs(prevTime);
intervalError = (T1 - (T0+secsToAdd)) / prevNumTicks;
}
int numPrints = 20;
// you update the display string every 0.1 seconds, to add to the
// number of ticks, calculate the offset from the previous time,
// and display it
void updateDisplayString() {
numTicks++;
float offset = numTicks * (interval + intervalError);
addSecondsToCurrentTime(prevTime, displayTime, offset);
displayQueue.call(&displayTimeToScreen);
}
// take care of the bluetooth toggling so that it can conect
void txTask(){
while (true)
{
// there is about a half second delay before the hexiwear
// realizes that the link state is down, so if you ever
// do realize that, you should toggle the advertisement
// state right away, I think. NO what you should do it, if
// you ever realize that the link is down, wait a half a second
// and then toggle advertisement mode to let it refresh
// it seems like this doesn't perform quite as well, but I think
// it is more robust...
if (kw40z_device.GetLinkState() == 0) {
Thread::wait(2500);
if (kw40z_device.GetLinkState() == 0) {
kw40z_device.ToggleAdvertisementMode();
}
}
Thread::wait(5000);
}
}