Smart Button

Dependencies:   BLE_API mbed nRF51822

Revision:
0:d7ba2329a303
Child:
1:795c0e3fbd4e
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/main.cpp	Sun Oct 16 14:18:27 2016 +0000
@@ -0,0 +1,271 @@
+/*
+
+#define BUTTON_SERVICE_UUID     0xA000
+#define BUTTON_STATE_CHAR_UUID  0xA001
+
+#define LED_SERVICE_UUID        0xB000
+#define LED_STATE_CHAR_UUID     0xB001
+#define LED_STATUS_CHAR_UUID    0xB002
+ 
+const static char     DEVICE_NAME[] = "Button";
+static const uint16_t uuid16_list[] = {BUTTON_SERVICE_UUID, LED_SERVICE_UUID};
+ 
+bool buttonPressed = false;
+
+ReadOnlyGattCharacteristic<bool> buttonState(BUTTON_STATE_CHAR_UUID, &buttonPressed, GattCharacteristic::BLE_GATT_CHAR_PROPERTIES_NOTIFY);
+
+//static uint8_t readValue[10] = {0};
+//ReadOnlyArrayGattCharacteristic<uint8_t, sizeof(readValue)> readChar(LED_STATUS_CHAR_UUID, readValue);
+ 
+static uint8_t writeValue[10] = {0};
+WriteOnlyArrayGattCharacteristic<uint8_t, sizeof(writeValue)> writeChar(LED_STATE_CHAR_UUID, writeValue);
+
+
+
+
+void writeCharCallback(const GattWriteCallbackParams* params)
+{
+    // check to see what characteristic was written, by handle
+    if(params->handle == writeChar.getValueHandle()) {
+        // toggle LED if only 1 byte is written
+        if(params->len == 1) {
+            led2 = params->data[0] ? false : true;
+        }
+        // update the readChar with the value of writeChar
+        //ble.updateCharacteristicValue(readChar.getValueHandle(),params->data,params->len);
+    }
+}
+
+
+
+void buttonPressedCallback(void)
+{
+    buttonPressed = true;
+    ble.updateCharacteristicValue(buttonState.getValueHandle(), (uint8_t *)&buttonPressed, sizeof(bool));
+    //led2 = false;
+}
+ 
+void buttonReleasedCallback(void)
+{
+    buttonPressed = false;
+    ble.updateCharacteristicValue(buttonState.getValueHandle(), (uint8_t *)&buttonPressed, sizeof(bool));
+    //led2 = true;
+}
+ 
+void disconnectionCallback(const Gap::DisconnectionCallbackParams_t* reason)
+{
+    ble.startAdvertising();
+    led1 = 1;
+    led2 = 1;
+}
+ 
+void periodicCallback(void)
+{
+    led1 = !led1; // Do blinky on LED1 to indicate system aliveness. 
+}
+ 
+int main(void)
+{
+    led1 = 1;
+    led2 = 1;
+    Ticker ticker;
+    ticker.attach(periodicCallback, 1);
+    button.fall(buttonPressedCallback);
+    button.rise(buttonReleasedCallback);
+ 
+    ble.init();
+    ble.onDisconnection(disconnectionCallback);
+    ble.onDataWritten(writeCharCallback);
+ 
+    GattCharacteristic *btnChars[] = {&buttonState};
+    GattService         buttonService(BUTTON_SERVICE_UUID, btnChars, sizeof(btnChars) / sizeof(GattCharacteristic *));
+    ble.addService(buttonService);
+
+    // Set up custom service
+    GattCharacteristic *ledChars[] = { &writeChar}; //&readChar,
+    GattService        ledService(LED_SERVICE_UUID, ledChars, sizeof(ledChars) / sizeof(GattCharacteristic *));
+    ble.addService(ledService);
+    
+    // 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::COMPLETE_LOCAL_NAME, (uint8_t *)DEVICE_NAME, sizeof(DEVICE_NAME));
+    ble.setAdvertisingType(GapAdvertisingParams::ADV_CONNECTABLE_UNDIRECTED);
+    ble.setAdvertisingInterval(Gap::MSEC_TO_GAP_DURATION_UNITS(1000)); // 1000ms.
+    ble.startAdvertising();
+ 
+    while (true) {
+        ble.waitForEvent();
+    }
+}
+*/
+
+#include "mbed.h"
+#include "BLE.h"
+
+class ButtonService {
+public:
+    const static uint16_t BUTTON_SERVICE_UUID              = 0xA000;
+    const static uint16_t BUTTON_STATE_CHARACTERISTIC_UUID = 0xA001;
+ 
+    ButtonService(BLEDevice &_ble, bool buttonPressedInitial) :
+        ble(_ble), buttonState(BUTTON_STATE_CHARACTERISTIC_UUID, &buttonPressedInitial, GattCharacteristic::BLE_GATT_CHAR_PROPERTIES_NOTIFY)
+    {
+        GattCharacteristic *charTable[] = {&buttonState};
+        GattService         buttonService(ButtonService::BUTTON_SERVICE_UUID, charTable, sizeof(charTable) / sizeof(GattCharacteristic *));
+        ble.gattServer().addService(buttonService);
+    }
+ 
+    void updateButtonState(bool newState)
+    {
+        ble.gattServer().write(buttonState.getValueHandle(), (uint8_t *)&newState, sizeof(bool));
+    }
+ 
+private:
+    BLEDevice &ble;
+    ReadOnlyGattCharacteristic<bool> buttonState;
+};
+
+class LEDService {
+public:
+    const static uint16_t LED_SERVICE_UUID              = 0xB000;
+    const static uint16_t LED_STATE_CHARACTERISTIC_UUID = 0xB001;
+ 
+    LEDService(BLEDevice &_ble, bool initialValueForLEDCharacteristic = false) :
+        ble(_ble), ledState(LED_STATE_CHARACTERISTIC_UUID, &initialValueForLEDCharacteristic)
+    {
+        GattCharacteristic *charTable[] = {&ledState};
+        GattService         ledService(LED_SERVICE_UUID, charTable, sizeof(charTable) / sizeof(GattCharacteristic *));
+        ble.gattServer().addService(ledService);
+    }
+ 
+    GattAttribute::Handle_t getValueHandle() const
+    {
+        return ledState.getValueHandle();
+    }
+ 
+private:
+    BLEDevice &ble;
+    ReadWriteGattCharacteristic<bool> ledState;
+};
+
+class BuzzerService {
+public:
+    const static uint16_t BUZZ_SERVICE_UUID              = 0xC000;
+    const static uint16_t BUZZ_STATE_CHARACTERISTIC_UUID = 0xC001;
+ 
+    BuzzerService(BLEDevice &_ble, uint16_t initialValue = 0) :
+        ble(_ble), buzzState(BUZZ_STATE_CHARACTERISTIC_UUID, &initialValue)
+    {
+        GattCharacteristic *charTable[] = {&buzzState};
+        GattService         buzzService(BUZZ_SERVICE_UUID, charTable, sizeof(charTable) / sizeof(GattCharacteristic *));
+        ble.gattServer().addService(buzzService);
+    }
+ 
+    GattAttribute::Handle_t getValueHandle() const
+    {
+        return buzzState.getValueHandle();
+    }
+ 
+private:
+    BLEDevice &ble;
+    ReadWriteGattCharacteristic<uint16_t> buzzState;
+};
+
+DigitalOut  led1(p14);
+DigitalOut  led2(p15);
+InterruptIn button(p16);
+PwmOut*     buzzer = NULL;
+
+void setBuzzer(uint16_t value) {
+    if (value) {
+        if (!buzzer) {
+            buzzer = new PwmOut(p30);
+        }
+        buzzer->period(1.0/value);
+        buzzer->write(0.5);
+    } else {
+        if (buzzer) {
+            buzzer->write(0);
+            delete buzzer;
+            buzzer = NULL;
+        }
+    }
+}
+
+static const uint8_t device_name[] = "Nut2";
+static const uint16_t uuid16_list[] = {
+    ButtonService::BUTTON_SERVICE_UUID,
+    LEDService::LED_SERVICE_UUID
+};
+
+BLEDevice      ble;
+ButtonService *svcButton;
+LEDService    *svcLed1;
+LEDService    *svcLed2;
+BuzzerService *svcBuzzer;
+ 
+void buttonPressedCallback(void)
+{
+    svcButton->updateButtonState(true);
+}
+ 
+void buttonReleasedCallback(void)
+{
+    svcButton->updateButtonState(false);
+}
+
+void disconnectionCallback(const Gap::DisconnectionCallbackParams_t* reason)
+{
+    ble.startAdvertising();
+    led1 = 1;
+    led2 = 1;
+    setBuzzer(0);
+}
+
+void onDataWrittenCallback(const GattWriteCallbackParams *params)
+{
+    if ((params->handle == svcLed1->getValueHandle()) && (params->len == 1)) {
+        led1 = !*(params->data);
+    } else if ((params->handle == svcLed2->getValueHandle()) && (params->len == 1)) {
+        led2 = !*(params->data);
+    } else if ((params->handle == svcBuzzer->getValueHandle()) && (params->len == 2)) {
+        setBuzzer(*(uint16_t*)(params->data));
+    }
+}
+ 
+int main(void)
+{
+    led1 = 1;
+    led2 = 1;
+    setBuzzer(0);
+    //Ticker ticker;
+    //ticker.attach([] { led1 = !led1; }, 1.0);
+    button.fall(buttonPressedCallback);
+    button.rise(buttonReleasedCallback);
+ 
+    ble.init();
+    ble.onDisconnection(disconnectionCallback);
+    ble.gattServer().onDataWritten(onDataWrittenCallback);
+ 
+    svcButton = new ButtonService(ble, false);
+    svcLed1 = new LEDService(ble);
+    svcLed2 = new LEDService(ble);
+    svcBuzzer = new BuzzerService(ble);
+ 
+    // 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::COMPLETE_LOCAL_NAME, device_name, sizeof(device_name));
+
+    ble.gap().setDeviceName(device_name);
+    ble.gap().setTxPower(4);
+    ble.gap().setAdvertisingType(GapAdvertisingParams::ADV_CONNECTABLE_UNDIRECTED);
+    ble.gap().setAdvertisingInterval(Gap::MSEC_TO_GAP_DURATION_UNITS(1000));
+    ble.gap().setAdvertisingTimeout(0);
+    ble.startAdvertising();
+ 
+    while (true) {
+        ble.waitForEvent();
+    }
+}
\ No newline at end of file