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
// }
// }
}