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
main.cpp
- Committer:
- Bobty
- Date:
- 2015-03-10
- Revision:
- 1:c3d7e673cdd2
- Parent:
- 0:0d5ac2fd4620
- Child:
- 2:9090120e2656
File content as of revision 1:c3d7e673cdd2:
// BLE Alarm Watch // Based on BLE heart-rate-monitor from MBED team // Rob Dobson, 2015 #include "mbed.h" #include "BLEDevice.h" #include "DeviceInformationService.h" // BLE Device etc BLEDevice ble; DigitalOut ledIndicator(LED1); DigitalOut testOut(p1); // Device name const static char DEVICE_NAME[] = "JOESALARM"; // UUID for CurTimeService & TimeBlockCharacteristic const uint16_t UUID_CUR_TIME_SERVICE = 0xA000; const uint16_t UUID_TIME_BLOCK_CHARACTERISTIC = 0xA001; // List of supported service UUIDs static const uint16_t uuid16_list[] = {UUID_CUR_TIME_SERVICE}; // Time is packed in an array of bytes const int SIZE_OF_TIME_BLOCK = 7; uint8_t timeBlockInitValue[SIZE_OF_TIME_BLOCK]; uint8_t curTimeBlock[SIZE_OF_TIME_BLOCK]; // GATT Characteristic for time block ReadWriteGattCharacteristic<uint8_t> timeBlockCharacteristic(UUID_TIME_BLOCK_CHARACTERISTIC, timeBlockInitValue); // Callback when connection lost void disconnectionCallback(Gap::Handle_t handle, Gap::DisconnectionReason_t reason) { ble.startAdvertising(); // restart advertising } // Callback for ticker int tickCount = 0; bool showInfo = false; int writeSinceLast = 0; void periodicCallback(void) { ledIndicator = !ledIndicator; /* Do blinky on LED1 while we're waiting for BLE events */ testOut = !testOut; tickCount++; if (tickCount > 100) { showInfo = true; tickCount = 0; } } // Data written callback void onDataWrittenCallback(const GattCharacteristicWriteCBParams *params) { if ((params->charHandle == timeBlockCharacteristic.getValueHandle())) { // && (params->len == SIZE_OF_TIME_BLOCK) writeSinceLast = params->len; memcpy(curTimeBlock, params->data, SIZE_OF_TIME_BLOCK); } writeSinceLast = true; } // Main int main(void) { ledIndicator = 0; testOut = 0; // Ticker is interrupt driven Ticker ticker; ticker.attach_us(periodicCallback, 100000); // Initial value for the time block characteristic memset(timeBlockInitValue, 0, sizeof(timeBlockInitValue)); // Init BLE and register callbacks ble.init(); ble.onDisconnection(disconnectionCallback); ble.onDataWritten(onDataWrittenCallback); // Add the time setting service GattCharacteristic *charTable[] = {&timeBlockCharacteristic}; GattService timeBlockService(UUID_CUR_TIME_SERVICE, charTable, sizeof(charTable) / sizeof(GattCharacteristic *)); ble.addService(timeBlockService); // Setup advertising /* BREDR_NOT_SUPPORTED means classic bluetooth not supported; * LE_GENERAL_DISCOVERABLE means that this peripheral can be * discovered by any BLE scanner--i.e. any phone. */ ble.accumulateAdvertisingPayload(GapAdvertisingData::BREDR_NOT_SUPPORTED | GapAdvertisingData::LE_GENERAL_DISCOVERABLE); // Add services to payload ble.accumulateAdvertisingPayload(GapAdvertisingData::COMPLETE_LIST_16BIT_SERVICE_IDS, (uint8_t *)uuid16_list, sizeof(uuid16_list)); /* This is where we're collecting the device name into the advertisement payload. */ ble.accumulateAdvertisingPayload(GapAdvertisingData::COMPLETE_LOCAL_NAME, (uint8_t *)DEVICE_NAME, sizeof(DEVICE_NAME)); /* We'd like for this BLE peripheral to be connectable. */ ble.setAdvertisingType(GapAdvertisingParams::ADV_CONNECTABLE_UNDIRECTED); /* set the interval at which advertisements are sent out; this has * an implication power consumption--radio activity being a * biggest draw on average power. The other software controllable * parameter which influences power is the radio's TX power * level--there's an API to adjust that. */ ble.setAdvertisingInterval(Gap::MSEC_TO_ADVERTISEMENT_DURATION_UNITS(1000)); /* 1000ms. */ /* we're finally good to go with advertisements. */ ble.startAdvertising(); while (true) { ble.waitForEvent(); if (showInfo) { printf("Time info: "); for (int i = 0; i < SIZE_OF_TIME_BLOCK; i++) { printf("%02d", curTimeBlock[i]); } printf(" - writeSinceLast %d\r\n", writeSinceLast); showInfo = false; writeSinceLast = 0; } } // /* Setup primary service. */ // uint8_t hrmCounter = 100; // init HRM to 100bps // HeartRateService hrService(ble, hrmCounter, HeartRateService::LOCATION_FINGER); // // /* Setup auxiliary service. */ // DeviceInformationService deviceInfo(ble, "ARM", "Model1", "SN1", "hw-rev1", "fw-rev1", "soft-rev1"); // // /* Setup advertising. */ // ble.accumulateAdvertisingPayload(GapAdvertisingData::BREDR_NOT_SUPPORTED | GapAdvertisingData::LE_GENERAL_DISCOVERABLE); // ble.accumulateAdvertisingPayload(GapAdvertisingData::COMPLETE_LIST_16BIT_SERVICE_IDS, (uint8_t *)uuid16_list, sizeof(uuid16_list)); // ble.accumulateAdvertisingPayload(GapAdvertisingData::GENERIC_HEART_RATE_SENSOR); // ble.accumulateAdvertisingPayload(GapAdvertisingData::COMPLETE_LOCAL_NAME, (uint8_t *)DEVICE_NAME, sizeof(DEVICE_NAME)); // ble.setAdvertisingType(GapAdvertisingParams::ADV_CONNECTABLE_UNDIRECTED); // ble.setAdvertisingInterval(Gap::MSEC_TO_ADVERTISEMENT_DURATION_UNITS(1000)); // ble.startAdvertising(); // // // infinite loop // while (1) { // // check for trigger from periodicCallback() // if (triggerSensorPolling && ble.getGapState().connected) { // triggerSensorPolling = false; // // // Do blocking calls or whatever is necessary for sensor polling. // // In our case, we simply update the HRM measurement. // hrmCounter++; // // // 100 <= HRM bps <=175 // if (hrmCounter == 175) { // hrmCounter = 100; // } // // // update bps // hrService.updateHeartRate(hrmCounter); // } else { // ble.waitForEvent(); // low power wait for event // } // } }