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

Committer:
Bobty
Date:
Mon Jul 27 19:30:11 2015 +0000
Revision:
4:f0b030a3223f
Parent:
3:a4b8d67de1b1
Child:
5:2682353a8c32
Now using nrf51_rtc library by Francis Schumacher

Who changed what in which revision?

UserRevisionLine numberNew contents of line
Bobty 0:0d5ac2fd4620 1 // BLE Alarm Watch
Bobty 2:9090120e2656 2 // Based on BLE examples on MBED
Bobty 0:0d5ac2fd4620 3 // Rob Dobson, 2015
Bobty 0:0d5ac2fd4620 4
Bobty 0:0d5ac2fd4620 5 #include "mbed.h"
Bobty 2:9090120e2656 6 #include "BLE.h"
Bobty 2:9090120e2656 7 #include "ButtonService.h"
Bobty 3:a4b8d67de1b1 8 #include "WatchTimeService.h"
Bobty 4:f0b030a3223f 9 #include "nrf51_rtc.h"
Bobty 2:9090120e2656 10
Bobty 2:9090120e2656 11 // BLE platform
Bobty 2:9090120e2656 12 BLE ble;
Bobty 2:9090120e2656 13
Bobty 2:9090120e2656 14 // Indicator LEDs
Bobty 2:9090120e2656 15 DigitalOut led1(LED1);
Bobty 2:9090120e2656 16
Bobty 2:9090120e2656 17 // Button press to show time
Bobty 2:9090120e2656 18 InterruptIn button(D8);
Bobty 2:9090120e2656 19
Bobty 2:9090120e2656 20 // Device name - this is the visible name of device on BLE
Bobty 3:a4b8d67de1b1 21 const static char DEVICE_NAME[] = "JoesAlarm";
Bobty 3:a4b8d67de1b1 22
Bobty 3:a4b8d67de1b1 23 // UUIDs of services offered
Bobty 3:a4b8d67de1b1 24 static const uint16_t uuid16_list[] = {ButtonService::BUTTON_SERVICE_UUID, WatchTimeService::WATCHTIME_SERVICE_UUID};
Bobty 3:a4b8d67de1b1 25
Bobty 3:a4b8d67de1b1 26 // Service offering to read and set the time on the watch
Bobty 3:a4b8d67de1b1 27 WatchTimeService *pWatchTimeService;
Bobty 2:9090120e2656 28
Bobty 2:9090120e2656 29 // TEST CODE
Bobty 3:a4b8d67de1b1 30 int callbackCount = 0;
Bobty 3:a4b8d67de1b1 31 uint8_t testbuf[WatchTimeService::WatchTime_BlockSize];
Bobty 3:a4b8d67de1b1 32 time_t retval = 0;
Bobty 3:a4b8d67de1b1 33 int servcode = 0;
Bobty 3:a4b8d67de1b1 34 int buflen = 0;
Bobty 3:a4b8d67de1b1 35 int mycode = 0;
Bobty 3:a4b8d67de1b1 36 int offs = 0;
Bobty 3:a4b8d67de1b1 37 int butcode = 0;
Bobty 2:9090120e2656 38 ButtonService *buttonServicePtr;
Bobty 2:9090120e2656 39
Bobty 2:9090120e2656 40 // Handle button press to read watch
Bobty 2:9090120e2656 41 void buttonPressedCallback(void)
Bobty 2:9090120e2656 42 {
Bobty 2:9090120e2656 43 // TEST CODE
Bobty 2:9090120e2656 44 buttonServicePtr->updateButtonState(true);
Bobty 2:9090120e2656 45 }
Bobty 2:9090120e2656 46
Bobty 2:9090120e2656 47 // TEST CODE
Bobty 2:9090120e2656 48 void buttonReleasedCallback(void)
Bobty 2:9090120e2656 49 {
Bobty 2:9090120e2656 50 // TEST CODE
Bobty 2:9090120e2656 51 buttonServicePtr->updateButtonState(false);
Bobty 2:9090120e2656 52 }
Bobty 2:9090120e2656 53
Bobty 2:9090120e2656 54 // Handle BLE disconnection - restart advertising
Bobty 2:9090120e2656 55 void disconnectionCallback(Gap::Handle_t handle, Gap::DisconnectionReason_t reason)
Bobty 2:9090120e2656 56 {
Bobty 2:9090120e2656 57 ble.gap().startAdvertising();
Bobty 2:9090120e2656 58 }
Bobty 2:9090120e2656 59
Bobty 2:9090120e2656 60 // TEST CODE
Bobty 2:9090120e2656 61 void periodicCallback(void)
Bobty 2:9090120e2656 62 {
Bobty 2:9090120e2656 63 led1 = !led1; /* Do blinky on LED1 to indicate system aliveness. */
Bobty 4:f0b030a3223f 64
Bobty 4:f0b030a3223f 65 // Update the rtc library time (it says in the notes on the rtc lib that this needs to happen
Bobty 4:f0b030a3223f 66 // more than once every few hundred seconds to avoid a rollover
Bobty 4:f0b030a3223f 67 rtc.time();
Bobty 2:9090120e2656 68 }
Bobty 2:9090120e2656 69
Bobty 3:a4b8d67de1b1 70 time_t watchTimeToUnix(const uint8_t* pWatchTime)
Bobty 3:a4b8d67de1b1 71 {
Bobty 3:a4b8d67de1b1 72 struct tm tminfo;
Bobty 3:a4b8d67de1b1 73 tminfo.tm_year = int(pWatchTime[0])*256 + pWatchTime[1] - 1900;
Bobty 3:a4b8d67de1b1 74 tminfo.tm_mon = pWatchTime[2] - 1;
Bobty 3:a4b8d67de1b1 75 tminfo.tm_mday = pWatchTime[3];
Bobty 3:a4b8d67de1b1 76 tminfo.tm_hour = pWatchTime[4];
Bobty 3:a4b8d67de1b1 77 tminfo.tm_min = pWatchTime[5];
Bobty 3:a4b8d67de1b1 78 tminfo.tm_sec = pWatchTime[6];
Bobty 3:a4b8d67de1b1 79 tminfo.tm_isdst = -1;
Bobty 3:a4b8d67de1b1 80 time_t timest = mktime(&tminfo);
Bobty 3:a4b8d67de1b1 81 return timest;
Bobty 3:a4b8d67de1b1 82 }
Bobty 3:a4b8d67de1b1 83
Bobty 3:a4b8d67de1b1 84 void onDataWrittenCallback(const GattWriteCallbackParams *params)
Bobty 3:a4b8d67de1b1 85 {
Bobty 3:a4b8d67de1b1 86 // TEST code
Bobty 3:a4b8d67de1b1 87 callbackCount++;
Bobty 3:a4b8d67de1b1 88 memcpy(testbuf, params->data, WatchTimeService::WatchTime_BlockSize);
Bobty 3:a4b8d67de1b1 89 servcode = params->handle;
Bobty 3:a4b8d67de1b1 90 buflen = params->len;
Bobty 3:a4b8d67de1b1 91 mycode = pWatchTimeService->getValueHandle();
Bobty 3:a4b8d67de1b1 92 butcode = buttonServicePtr->getValueHandle();
Bobty 3:a4b8d67de1b1 93 offs = params->offset;
Bobty 3:a4b8d67de1b1 94
Bobty 3:a4b8d67de1b1 95 // Check if this is time setting
Bobty 3:a4b8d67de1b1 96 if (pWatchTimeService->getValueHandle() == params->handle)
Bobty 3:a4b8d67de1b1 97 {
Bobty 3:a4b8d67de1b1 98 if (params->len == WatchTimeService::WatchTime_BlockSize)
Bobty 3:a4b8d67de1b1 99 {
Bobty 3:a4b8d67de1b1 100 time_t timest = watchTimeToUnix(params->data);
Bobty 3:a4b8d67de1b1 101 retval = timest;
Bobty 3:a4b8d67de1b1 102 if (timest != -1)
Bobty 4:f0b030a3223f 103 rtc.set_time(timest);
Bobty 3:a4b8d67de1b1 104 }
Bobty 3:a4b8d67de1b1 105 }
Bobty 3:a4b8d67de1b1 106 }
Bobty 3:a4b8d67de1b1 107
Bobty 4:f0b030a3223f 108 // TEST CODE
Bobty 4:f0b030a3223f 109 void print_time()
Bobty 4:f0b030a3223f 110 {
Bobty 4:f0b030a3223f 111 time_t rawtime=rtc.time();
Bobty 4:f0b030a3223f 112
Bobty 4:f0b030a3223f 113 // massage the time into a human-friendly format for printing
Bobty 4:f0b030a3223f 114 struct tm * timeinfo;
Bobty 4:f0b030a3223f 115 timeinfo = localtime(&rawtime);
Bobty 4:f0b030a3223f 116 char date[24];
Bobty 4:f0b030a3223f 117 strftime(date,sizeof(date),"%H:%M:%S on %m/%d/%G",timeinfo);
Bobty 4:f0b030a3223f 118 printf("The current time is %s.\r\n",date);
Bobty 4:f0b030a3223f 119 }
Bobty 4:f0b030a3223f 120
Bobty 2:9090120e2656 121 int main(void)
Bobty 2:9090120e2656 122 {
Bobty 3:a4b8d67de1b1 123 printf("AlarmWatch\r\n");
Bobty 3:a4b8d67de1b1 124
Bobty 2:9090120e2656 125 // TEST CODE
Bobty 3:a4b8d67de1b1 126 memset(testbuf, 0, WatchTimeService::WatchTime_BlockSize);
Bobty 3:a4b8d67de1b1 127 int loopCount = 0;
Bobty 2:9090120e2656 128 led1 = 1;
Bobty 2:9090120e2656 129 Ticker ticker;
Bobty 2:9090120e2656 130 ticker.attach(periodicCallback, 1);
Bobty 2:9090120e2656 131 button.fall(buttonPressedCallback);
Bobty 2:9090120e2656 132 button.rise(buttonReleasedCallback);
Bobty 2:9090120e2656 133
Bobty 2:9090120e2656 134 // BLE init
Bobty 2:9090120e2656 135 ble.init();
Bobty 2:9090120e2656 136 ble.gap().onDisconnection(disconnectionCallback);
Bobty 3:a4b8d67de1b1 137 ble.onDataWritten(onDataWrittenCallback);
Bobty 3:a4b8d67de1b1 138
Bobty 2:9090120e2656 139 // TEST CODE
Bobty 2:9090120e2656 140 ButtonService buttonService(ble, false /* initial value for button pressed */);
Bobty 2:9090120e2656 141 buttonServicePtr = &buttonService;
Bobty 3:a4b8d67de1b1 142
Bobty 3:a4b8d67de1b1 143 // Watch Time Service
Bobty 3:a4b8d67de1b1 144 uint8_t initialTime[] = { uint8_t(2015/256), uint8_t(2015%256), 7, 26, 12, 8, 0 };
Bobty 3:a4b8d67de1b1 145 WatchTimeService watchTimeService(ble, initialTime);
Bobty 3:a4b8d67de1b1 146 pWatchTimeService = &watchTimeService;
Bobty 2:9090120e2656 147
Bobty 2:9090120e2656 148 // Setup advertising
Bobty 2:9090120e2656 149 ble.gap().accumulateAdvertisingPayload(GapAdvertisingData::BREDR_NOT_SUPPORTED | GapAdvertisingData::LE_GENERAL_DISCOVERABLE);
Bobty 2:9090120e2656 150 ble.gap().accumulateAdvertisingPayload(GapAdvertisingData::COMPLETE_LIST_16BIT_SERVICE_IDS, (uint8_t *)uuid16_list, sizeof(uuid16_list));
Bobty 2:9090120e2656 151 ble.gap().accumulateAdvertisingPayload(GapAdvertisingData::COMPLETE_LOCAL_NAME, (uint8_t *)DEVICE_NAME, sizeof(DEVICE_NAME));
Bobty 2:9090120e2656 152 ble.gap().setAdvertisingType(GapAdvertisingParams::ADV_CONNECTABLE_UNDIRECTED);
Bobty 2:9090120e2656 153 ble.gap().setAdvertisingInterval(1000); /* 1000ms. */
Bobty 2:9090120e2656 154 ble.gap().startAdvertising();
Bobty 2:9090120e2656 155
Bobty 2:9090120e2656 156 while (true) {
Bobty 2:9090120e2656 157 ble.waitForEvent();
Bobty 3:a4b8d67de1b1 158
Bobty 3:a4b8d67de1b1 159 loopCount++;
Bobty 3:a4b8d67de1b1 160 if (loopCount < 5)
Bobty 3:a4b8d67de1b1 161 continue;
Bobty 3:a4b8d67de1b1 162 loopCount = 0;
Bobty 3:a4b8d67de1b1 163
Bobty 3:a4b8d67de1b1 164 time_t rawtime;
Bobty 3:a4b8d67de1b1 165 struct tm * timeinfo;
Bobty 3:a4b8d67de1b1 166 time (&rawtime);
Bobty 3:a4b8d67de1b1 167 timeinfo = localtime (&rawtime);
Bobty 3:a4b8d67de1b1 168 printf ("Current local time and date: %s callbacks %d retval %d\r\n", asctime(timeinfo), callbackCount, retval);
Bobty 3:a4b8d67de1b1 169 printf ("Timest %02x %02x %02x %02x %02x %02x %02x %ld\r\n", testbuf[0],
Bobty 3:a4b8d67de1b1 170 testbuf[1], testbuf[2], testbuf[3], testbuf[4], testbuf[5], testbuf[6], retval);
Bobty 3:a4b8d67de1b1 171 printf ("serv %d buflen %d mycode %d offs %d butcode %d\r\n", servcode, buflen, mycode, offs, butcode);
Bobty 3:a4b8d67de1b1 172 printf ("val %ld\r\n", watchTimeService.getValueHandle());
Bobty 4:f0b030a3223f 173 print_time();
Bobty 2:9090120e2656 174 }
Bobty 2:9090120e2656 175 }
Bobty 2:9090120e2656 176
Bobty 2:9090120e2656 177 /*
Bobty 2:9090120e2656 178
Bobty 2:9090120e2656 179 #include "mbed.h"
Bobty 0:0d5ac2fd4620 180 #include "BLEDevice.h"
Bobty 0:0d5ac2fd4620 181 #include "DeviceInformationService.h"
Bobty 0:0d5ac2fd4620 182
Bobty 0:0d5ac2fd4620 183 // BLE Device etc
Bobty 0:0d5ac2fd4620 184 BLEDevice ble;
Bobty 0:0d5ac2fd4620 185 DigitalOut ledIndicator(LED1);
Bobty 0:0d5ac2fd4620 186 DigitalOut testOut(p1);
Bobty 0:0d5ac2fd4620 187
Bobty 1:c3d7e673cdd2 188 // Device name
Bobty 1:c3d7e673cdd2 189 const static char DEVICE_NAME[] = "JOESALARM";
Bobty 1:c3d7e673cdd2 190
Bobty 1:c3d7e673cdd2 191 // UUID for CurTimeService & TimeBlockCharacteristic
Bobty 1:c3d7e673cdd2 192 const uint16_t UUID_CUR_TIME_SERVICE = 0xA000;
Bobty 1:c3d7e673cdd2 193 const uint16_t UUID_TIME_BLOCK_CHARACTERISTIC = 0xA001;
Bobty 1:c3d7e673cdd2 194
Bobty 1:c3d7e673cdd2 195 // List of supported service UUIDs
Bobty 1:c3d7e673cdd2 196 static const uint16_t uuid16_list[] = {UUID_CUR_TIME_SERVICE};
Bobty 0:0d5ac2fd4620 197
Bobty 1:c3d7e673cdd2 198 // Time is packed in an array of bytes
Bobty 1:c3d7e673cdd2 199 const int SIZE_OF_TIME_BLOCK = 7;
Bobty 1:c3d7e673cdd2 200 uint8_t timeBlockInitValue[SIZE_OF_TIME_BLOCK];
Bobty 1:c3d7e673cdd2 201 uint8_t curTimeBlock[SIZE_OF_TIME_BLOCK];
Bobty 1:c3d7e673cdd2 202
Bobty 1:c3d7e673cdd2 203 // GATT Characteristic for time block
Bobty 2:9090120e2656 204 GattCharacteristic timeBlockCharacteristic(UUID_TIME_BLOCK_CHARACTERISTIC, timeBlockInitValue, SIZE_OF_TIME_BLOCK, SIZE_OF_TIME_BLOCK,
Bobty 2:9090120e2656 205 GattCharacteristic::BLE_GATT_CHAR_PROPERTIES_WRITE | GattCharacteristic::BLE_GATT_CHAR_PROPERTIES_WRITE_WITHOUT_RESPONSE | GattCharacteristic::BLE_GATT_CHAR_PROPERTIES_READ);
Bobty 1:c3d7e673cdd2 206
Bobty 1:c3d7e673cdd2 207 // Callback when connection lost
Bobty 0:0d5ac2fd4620 208 void disconnectionCallback(Gap::Handle_t handle, Gap::DisconnectionReason_t reason)
Bobty 0:0d5ac2fd4620 209 {
Bobty 0:0d5ac2fd4620 210 ble.startAdvertising(); // restart advertising
Bobty 0:0d5ac2fd4620 211 }
Bobty 0:0d5ac2fd4620 212
Bobty 1:c3d7e673cdd2 213 // Callback for ticker
Bobty 1:c3d7e673cdd2 214 int tickCount = 0;
Bobty 1:c3d7e673cdd2 215 bool showInfo = false;
Bobty 1:c3d7e673cdd2 216 int writeSinceLast = 0;
Bobty 0:0d5ac2fd4620 217 void periodicCallback(void)
Bobty 0:0d5ac2fd4620 218 {
Bobty 2:9090120e2656 219 ledIndicator = !ledIndicator;
Bobty 0:0d5ac2fd4620 220 testOut = !testOut;
Bobty 1:c3d7e673cdd2 221 tickCount++;
Bobty 1:c3d7e673cdd2 222 if (tickCount > 100)
Bobty 1:c3d7e673cdd2 223 {
Bobty 1:c3d7e673cdd2 224 showInfo = true;
Bobty 1:c3d7e673cdd2 225 tickCount = 0;
Bobty 1:c3d7e673cdd2 226 }
Bobty 0:0d5ac2fd4620 227 }
Bobty 0:0d5ac2fd4620 228
Bobty 1:c3d7e673cdd2 229 // Data written callback
Bobty 1:c3d7e673cdd2 230 void onDataWrittenCallback(const GattCharacteristicWriteCBParams *params)
Bobty 1:c3d7e673cdd2 231 {
Bobty 1:c3d7e673cdd2 232 if ((params->charHandle == timeBlockCharacteristic.getValueHandle()))
Bobty 1:c3d7e673cdd2 233 {
Bobty 2:9090120e2656 234 // Validate time
Bobty 2:9090120e2656 235 int year = params->data[0] * 100 + params->data[1];
Bobty 2:9090120e2656 236 int month = params->data[2];
Bobty 2:9090120e2656 237 int day = params->data[3];
Bobty 1:c3d7e673cdd2 238 // && (params->len == SIZE_OF_TIME_BLOCK)
Bobty 1:c3d7e673cdd2 239 writeSinceLast = params->len;
Bobty 1:c3d7e673cdd2 240 memcpy(curTimeBlock, params->data, SIZE_OF_TIME_BLOCK);
Bobty 1:c3d7e673cdd2 241 }
Bobty 1:c3d7e673cdd2 242 writeSinceLast = true;
Bobty 1:c3d7e673cdd2 243 }
Bobty 1:c3d7e673cdd2 244
Bobty 1:c3d7e673cdd2 245 // Main
Bobty 0:0d5ac2fd4620 246 int main(void)
Bobty 0:0d5ac2fd4620 247 {
Bobty 0:0d5ac2fd4620 248 ledIndicator = 0;
Bobty 0:0d5ac2fd4620 249 testOut = 0;
Bobty 0:0d5ac2fd4620 250
Bobty 0:0d5ac2fd4620 251 // Ticker is interrupt driven
Bobty 0:0d5ac2fd4620 252 Ticker ticker;
Bobty 0:0d5ac2fd4620 253 ticker.attach_us(periodicCallback, 100000);
Bobty 0:0d5ac2fd4620 254
Bobty 1:c3d7e673cdd2 255 // Initial value for the time block characteristic
Bobty 1:c3d7e673cdd2 256 memset(timeBlockInitValue, 0, sizeof(timeBlockInitValue));
Bobty 1:c3d7e673cdd2 257
Bobty 1:c3d7e673cdd2 258 // Init BLE and register callbacks
Bobty 0:0d5ac2fd4620 259 ble.init();
Bobty 0:0d5ac2fd4620 260 ble.onDisconnection(disconnectionCallback);
Bobty 1:c3d7e673cdd2 261 ble.onDataWritten(onDataWrittenCallback);
Bobty 1:c3d7e673cdd2 262
Bobty 1:c3d7e673cdd2 263 // Add the time setting service
Bobty 1:c3d7e673cdd2 264 GattCharacteristic *charTable[] = {&timeBlockCharacteristic};
Bobty 1:c3d7e673cdd2 265 GattService timeBlockService(UUID_CUR_TIME_SERVICE, charTable, sizeof(charTable) / sizeof(GattCharacteristic *));
Bobty 1:c3d7e673cdd2 266 ble.addService(timeBlockService);
Bobty 0:0d5ac2fd4620 267
Bobty 0:0d5ac2fd4620 268 // Setup advertising
Bobty 2:9090120e2656 269 // BREDR_NOT_SUPPORTED means classic bluetooth not supported;
Bobty 2:9090120e2656 270 // LE_GENERAL_DISCOVERABLE means that this peripheral can be
Bobty 2:9090120e2656 271 // discovered by any BLE scanner--i.e. any phone.
Bobty 0:0d5ac2fd4620 272 ble.accumulateAdvertisingPayload(GapAdvertisingData::BREDR_NOT_SUPPORTED | GapAdvertisingData::LE_GENERAL_DISCOVERABLE);
Bobty 0:0d5ac2fd4620 273
Bobty 1:c3d7e673cdd2 274 // Add services to payload
Bobty 1:c3d7e673cdd2 275 ble.accumulateAdvertisingPayload(GapAdvertisingData::COMPLETE_LIST_16BIT_SERVICE_IDS, (uint8_t *)uuid16_list, sizeof(uuid16_list));
Bobty 1:c3d7e673cdd2 276
Bobty 2:9090120e2656 277 // This is where we're collecting the device name into the advertisement payload.
Bobty 0:0d5ac2fd4620 278 ble.accumulateAdvertisingPayload(GapAdvertisingData::COMPLETE_LOCAL_NAME, (uint8_t *)DEVICE_NAME, sizeof(DEVICE_NAME));
Bobty 0:0d5ac2fd4620 279
Bobty 2:9090120e2656 280 // We'd like for this BLE peripheral to be connectable.
Bobty 0:0d5ac2fd4620 281 ble.setAdvertisingType(GapAdvertisingParams::ADV_CONNECTABLE_UNDIRECTED);
Bobty 0:0d5ac2fd4620 282
Bobty 2:9090120e2656 283 // set the interval at which advertisements are sent out; this has
Bobty 2:9090120e2656 284 // an implication power consumption--radio activity being a
Bobty 2:9090120e2656 285 // biggest draw on average power. The other software controllable
Bobty 2:9090120e2656 286 // parameter which influences power is the radio's TX power
Bobty 2:9090120e2656 287 // level--there's an API to adjust that.
Bobty 2:9090120e2656 288 ble.setAdvertisingInterval(Gap::MSEC_TO_ADVERTISEMENT_DURATION_UNITS(1000));
Bobty 0:0d5ac2fd4620 289
Bobty 2:9090120e2656 290
Bobty 0:0d5ac2fd4620 291 ble.startAdvertising();
Bobty 0:0d5ac2fd4620 292
Bobty 0:0d5ac2fd4620 293 while (true)
Bobty 0:0d5ac2fd4620 294 {
Bobty 0:0d5ac2fd4620 295 ble.waitForEvent();
Bobty 1:c3d7e673cdd2 296
Bobty 1:c3d7e673cdd2 297 if (showInfo)
Bobty 1:c3d7e673cdd2 298 {
Bobty 1:c3d7e673cdd2 299 printf("Time info: ");
Bobty 1:c3d7e673cdd2 300 for (int i = 0; i < SIZE_OF_TIME_BLOCK; i++)
Bobty 1:c3d7e673cdd2 301 {
Bobty 1:c3d7e673cdd2 302 printf("%02d", curTimeBlock[i]);
Bobty 1:c3d7e673cdd2 303 }
Bobty 1:c3d7e673cdd2 304 printf(" - writeSinceLast %d\r\n", writeSinceLast);
Bobty 1:c3d7e673cdd2 305 showInfo = false;
Bobty 1:c3d7e673cdd2 306 writeSinceLast = 0;
Bobty 1:c3d7e673cdd2 307 }
Bobty 0:0d5ac2fd4620 308 }
Bobty 0:0d5ac2fd4620 309 }
Bobty 2:9090120e2656 310 */