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:
0:0d5ac2fd4620
Child:
1:c3d7e673cdd2

File content as of revision 0:0d5ac2fd4620:

// 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);

const static char     DEVICE_NAME[]        = "ALMW";
//static const uint16_t uuid16_list[]        = {GattService::UUID_ALARM_WATCH_SERVICE,
//                                              GattService::UUID_DEVICE_INFORMATION_SERVICE};
//                                              
                                              
///*
//* Define a custom UUID, first as an array of uint8_t and then convert to
//* a proper UUID later. The UUID must be 16 bytes (128-bits, 16 letters)
//* long - here we have padded out to 16 bytes by adding an extra '0' at
//* the end. Make sure you fill more than 4 bytes otherwise it will count
//* as a 'short' code and you could end up using a predefined value from
//* the BLE spec.
//*/
//uint8_t raw_characteristic_uuid[16] = {
//    'M', 'Y', '_', 'T',
//    'E', 'S', 'T', '_',
//    'C', 'H', 'A', 'R',
//    0, 0, 0, 0
//};
//// Create a proper UUID - use the built in function to do this correctly
//UUID characteristic_uuid = UUID(raw_characteristic_uuid);
//// Setup some dummy properties for our characteristic
//static uint8_t my_char_values[2] = { 15, 10 };
///*
//* Here we create our Characteristic adding in the dummy parameter values
//* we just setup, we also make it readable and writeable meaning that a
//* central can read and update the parameters we have stored.
//*/
//GattCharacteristic pattern(
//    characteristic_uuid,
//    my_char_values,
//    sizeof(my_char_values),
//    sizeof(my_char_values),
//    GattCharacteristic::BLE_GATT_CHAR_PROPERTIES_READ | GattCharacteristic::BLE_GATT_CHAR_PROPERTIES_WRITE
//);
///* 
//* List the Characteristics of our custom Service, can have one or more
//* of these each with a custom UUID and parameter values.
//*/
//GattCharacteristic *my_service_chars[] = {
//    &new_alert,
//};
//// Now setup a custom Service UUID, in the same fashion as for the Characteristic
//uint8_t raw_service_uuid[16] = {
//    'M', 'Y', '_', 'T',
//    'E', 'S', 'T', '_',
//    'S', 'E', 'R', 'V',
//    'I', 'C', 'E', 0
//};
//UUID service_uuid = UUID(raw_service_uuid);
//// Setup the Service with the UUID and all of the Characteristics
//GattService my_service(
//    service_uuid,
//    my_service_chars,
//    sizeof(my_service_chars) / sizeof(GattCharacteristic *)
//);
///* 
//* Now list the long UUIDs of the services we offer, these will be bundled into the
//* advertisement. It may look like repetition of 'raw_service_uuid' but here you can
//* list multiple UUIDs one after another.
//*/
//static const uint8_t uuid128_list[] = {
//    'M', 'Y', '_', 'T', 'E', 'S', 'T', '_', 'S', 'E', 'R', 'V', 'I', 'C', 'E', 0
//    // List more long UUIDs below...
//};
// 
//...
// 
///*
//* Now we change from using short (16-bit) UUIDs to long (128-bit) UUIDs, comment out
//* the old section of the payload and add the new 128-bit section.
//*/
///*bluetooth->accumulateAdvertisingPayload(
//    GapAdvertisingData::COMPLETE_LIST_16BIT_SERVICE_IDS, 
//    (uint8_t *)uuid16_list, 
//    sizeof(uuid16_list)
//);*/
//bluetooth->accumulateAdvertisingPayload(
//    GapAdvertisingData::INCOMPLETE_LIST_128BIT_SERVICE_IDS,
//    (uint8_t *)uuid128_list,
//    sizeof(uuid128_list)
//);                                              
//                                              
//                                              
//                                              
//                                              
//                                              
                                              
static volatile bool  triggerSensorPolling = false;

void disconnectionCallback(Gap::Handle_t handle, Gap::DisconnectionReason_t reason)
{
    ble.startAdvertising(); // restart advertising
}

void periodicCallback(void)
{
    ledIndicator = !ledIndicator; /* Do blinky on LED1 while we're waiting for BLE events */
    testOut = !testOut;
}

int main(void)
{
    ledIndicator = 0;
    testOut = 0;

    // Ticker is interrupt driven
    Ticker ticker;
    ticker.attach_us(periodicCallback, 100000);

    // Init BLE
    ble.init();
    ble.onDisconnection(disconnectionCallback);
    
    // 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);
    
    /* 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();
    }    
//    /* 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
//        }
//    }
}