Unudge / Mbed 2 deprecated BLE_HeartRate

Dependencies:   BLE_API mbed nRF51822 X_NUCLEO_IDB0XA1

Fork of BLE_HeartRate by Bluetooth Low Energy

Revision:
80:a2573ce708e2
Parent:
75:8128a06c0a21
Child:
81:fd97c70abbd8
diff -r 8b7c8c240540 -r a2573ce708e2 main.cpp
--- a/main.cpp	Tue Sep 20 12:36:16 2016 +0100
+++ b/main.cpp	Mon Jun 05 09:13:27 2017 +0000
@@ -13,30 +13,116 @@
  * See the License for the specific language governing permissions and
  * limitations under the License.
  */
+ 
 
 #include "mbed.h"
 #include "ble/BLE.h"
 #include "ble/services/HeartRateService.h"
 #include "ble/services/BatteryService.h"
 #include "ble/services/DeviceInformationService.h"
+#include "ble/services/UARTService.h"               // Not explictly used, I have just added this in.
 
+//** From Simple Chat example **//
+#define BLE_UUID_TXRX_SERVICE            0x0000 /**< The UUID of the Nordic UART Service. */
+#define BLE_UUID_TX_CHARACTERISTIC       0x0002 /**< The UUID of the TX Characteristic. */
+#define BLE_UUIDS_RX_CHARACTERISTIC      0x0003 /**< The UUID of the RX Characteristic. */
+
+#define TXRX_BUF_LEN                     20
+
+ /* SimpleChat */ BLE  ble; // Commented out to prevent conflict
+ /* HeartRate */ /* BLE &ble = params->ble; // Defined in scope of "bleInitComplete"
+                  * ble_error_t error = params->error; */
+                  
+Serial pc(USBTX, USBRX); // USBTX, USBRX origin unclear
+
+// The Nordic UART Service
+static const uint8_t uart_base_uuid[] = {0x71, 0x3D, 0, 0, 0x50, 0x3E, 0x4C, 0x75, 0xBA, 0x94, 0x31, 0x48, 0xF1, 0x8D, 0x94, 0x1E};
+static const uint8_t uart_tx_uuid[]   = {0x71, 0x3D, 0, 3, 0x50, 0x3E, 0x4C, 0x75, 0xBA, 0x94, 0x31, 0x48, 0xF1, 0x8D, 0x94, 0x1E};
+static const uint8_t uart_rx_uuid[]   = {0x71, 0x3D, 0, 2, 0x50, 0x3E, 0x4C, 0x75, 0xBA, 0x94, 0x31, 0x48, 0xF1, 0x8D, 0x94, 0x1E};
+static const uint8_t uart_base_uuid_rev[] = {0x1E, 0x94, 0x8D, 0xF1, 0x48, 0x31, 0x94, 0xBA, 0x75, 0x4C, 0x3E, 0x50, 0, 0, 0x3D, 0x71};
+
+uint8_t txPayload[TXRX_BUF_LEN] = {0,};
+uint8_t rxPayload[TXRX_BUF_LEN] = {0,};
+
+static uint8_t rx_buf[TXRX_BUF_LEN];
+static uint8_t rx_len=0;
+
+GattCharacteristic  txCharacteristic (uart_tx_uuid, txPayload, 1, TXRX_BUF_LEN, GattCharacteristic::BLE_GATT_CHAR_PROPERTIES_WRITE | GattCharacteristic::BLE_GATT_CHAR_PROPERTIES_WRITE_WITHOUT_RESPONSE);
+GattCharacteristic  rxCharacteristic (uart_rx_uuid, rxPayload, 1, TXRX_BUF_LEN, GattCharacteristic::BLE_GATT_CHAR_PROPERTIES_NOTIFY);
+GattCharacteristic *uartChars[] = {&txCharacteristic, &rxCharacteristic};
+GattService         uartService(uart_base_uuid, uartChars, sizeof(uartChars) / sizeof(GattCharacteristic *));
+
+void WrittenHandler(const GattWriteCallbackParams *Handler)
+{   
+    uint8_t buf[TXRX_BUF_LEN];
+    uint16_t bytesRead, index;
+    
+    if (Handler->handle == txCharacteristic.getValueAttribute().getHandle()) 
+    {
+        ble.readCharacteristicValue(txCharacteristic.getValueAttribute().getHandle(), buf, &bytesRead);
+        memset(txPayload, 0, TXRX_BUF_LEN);
+        memcpy(txPayload, buf, TXRX_BUF_LEN);       
+        pc.printf("WriteHandler \r\n");
+        pc.printf("Length: ");
+        pc.putc(bytesRead);
+        pc.printf("\r\n");
+        pc.printf("Data: ");
+        for(index=0; index<bytesRead; index++)
+        {
+            pc.putc(txPayload[index]);        
+        }
+        pc.printf("\r\n");
+    }
+}
+
+void uartCB(void)
+{   
+    while(pc.readable())    
+    {
+        rx_buf[rx_len++] = pc.getc();    
+        if(rx_len>=20 || rx_buf[rx_len-1]=='\0' || rx_buf[rx_len-1]=='\n')
+        {
+            ble.updateCharacteristicValue(rxCharacteristic.getValueAttribute().getHandle(), rx_buf, rx_len); 
+            pc.printf("RecHandler \r\n");
+            pc.printf("Length: ");
+            pc.putc(rx_len);
+            pc.printf("\r\n");
+            rx_len = 0;
+            break;
+        }
+    }
+}
+//** From Heart Rate example **//
 DigitalOut led1(LED1);
 
-const static char     DEVICE_NAME[]        = "HRM1";
+const static char     DEVICE_NAME[]        = "Unudge_Prototype";
 static const uint16_t uuid16_list[]        = {GattService::UUID_HEART_RATE_SERVICE,
                                               GattService::UUID_DEVICE_INFORMATION_SERVICE};
+
+// Alternately to include the UART , I could use a different unit size ("uint128_list[]" rather than "uuid16_list[]")
+
 static volatile bool  triggerSensorPolling = false;
 
 uint8_t hrmCounter = 100; // init HRM to 100bps
 
+// These services are classes: "HeartRateService" and "DeviceInformationService" are defined in the BLE_API library under classes
+// The names of the objects are brought in as pointers
 HeartRateService         *hrService;
 DeviceInformationService *deviceInfo;
 
+// Specifics not understood, purpose clear: When the device is disconnected,
+// start advertising again immediately
 void disconnectionCallback(const Gap::DisconnectionCallbackParams_t *params)
 {
-    BLE::Instance(BLE::DEFAULT_INSTANCE).gap().startAdvertising(); // restart advertising
+    BLE::Instance(BLE::DEFAULT_INSTANCE).startAdvertising(); // restart advertising
+    // Alternate Content
+    /*pc.printf("Disconnected \r\n");
+    pc.printf("Restart advertising \r\n");
+    ble.startAdvertising();*/
 }
 
+// This function switches the led ON/OFF and
+// sets a flag value which is used in int main ()
 void periodicCallback(void)
 {
     led1 = !led1; /* Do blinky on LED1 while we're waiting for BLE events */
@@ -44,10 +130,37 @@
     /* Note that the periodicCallback() executes in interrupt context, so it is safer to do
      * heavy-weight sensor polling from the main thread. */
     triggerSensorPolling = true;
+    
+    // ".available" is guesswork. I need something to check
+    // If there's any incoming message - onDataWritten?
+    /*
+    if(ble.getGapState().available) {
+        // I anticipate using a single char input to flag
+        // The intended purpose of the communication
+        
+        // read in "someFlag" and store
+        string someFlag = /syntax for reading ble input/
+        
+        switch(someFlag){
+            case 'S':
+            inBoundSettingChange = true;
+            break;
+            case 'R':
+            inBoundRhythm = true;
+            break;
+            default:
+            break;
+        }
+        //Flush someFlag
+        someFlag = '';
+    }
+    */
 }
 
 void bleInitComplete(BLE::InitializationCompleteCallbackContext *params)
 {
+    // BLE is the class, &ble is the address of the declared object
+    // "params->" purpose unknown
     BLE &ble          = params->ble;
     ble_error_t error = params->error;
 
@@ -55,26 +168,50 @@
         return;
     }
 
-    ble.gap().onDisconnection(disconnectionCallback);
+    ble.onDisconnection(disconnectionCallback);
 
     /* Setup primary service. */
     hrService = new HeartRateService(ble, hrmCounter, HeartRateService::LOCATION_FINGER);
 
     /* Setup auxiliary service. */
-    deviceInfo = new DeviceInformationService(ble, "ARM", "Model1", "SN1", "hw-rev1", "fw-rev1", "soft-rev1");
+    // 2nd parameter - the manufacturer's name // rev - revision
+    deviceInfo = new DeviceInformationService(ble, "ARM", "Model1", "SerialNo#", "hw-rev1", "fw-rev1", "soft-rev1");
 
     /* Setup advertising. */
-    ble.gap().accumulateAdvertisingPayload(GapAdvertisingData::BREDR_NOT_SUPPORTED | GapAdvertisingData::LE_GENERAL_DISCOVERABLE);
-    ble.gap().accumulateAdvertisingPayload(GapAdvertisingData::COMPLETE_LIST_16BIT_SERVICE_IDS, (uint8_t *)uuid16_list, sizeof(uuid16_list));
-    ble.gap().accumulateAdvertisingPayload(GapAdvertisingData::GENERIC_HEART_RATE_SENSOR);
-    ble.gap().accumulateAdvertisingPayload(GapAdvertisingData::COMPLETE_LOCAL_NAME, (uint8_t *)DEVICE_NAME, sizeof(DEVICE_NAME));
-    ble.gap().setAdvertisingType(GapAdvertisingParams::ADV_CONNECTABLE_UNDIRECTED);
-    ble.gap().setAdvertisingInterval(1000); /* 1000ms */
-    ble.gap().startAdvertising();
+    // This line below is mandatory for bluetooth smart
+    // It indicates the device only supports Bluetooth Low Energy
+    ble.accumulateAdvertisingPayload(GapAdvertisingData::BREDR_NOT_SUPPORTED | GapAdvertisingData::LE_GENERAL_DISCOVERABLE);
+    // I believe this advertises the service list
+    ble.accumulateAdvertisingPayload(GapAdvertisingData::COMPLETE_LIST_16BIT_SERVICE_IDS, (uint8_t *)uuid16_list, sizeof(uuid16_list));
+    
+    // I realise that this isn't efficient but I would rather keep the code as
+    // Is for now, so that it actually works. Hence why a 2nd "COMPLETE_LIST"
+    /* SimpleChat */ ble.accumulateAdvertisingPayload(GapAdvertisingData::COMPLETE_LIST_128BIT_SERVICE_IDS,
+                     (const uint8_t *)uart_base_uuid_rev, sizeof(uart_base_uuid));
+    
+    ble.accumulateAdvertisingPayload(GapAdvertisingData::GENERIC_HEART_RATE_SENSOR);
+    // Advertise the device name
+    ble.accumulateAdvertisingPayload(GapAdvertisingData::COMPLETE_LOCAL_NAME, (uint8_t *)DEVICE_NAME, sizeof(DEVICE_NAME));
+    // Appears in all examples I have seen
+    ble.setAdvertisingType(GapAdvertisingParams::ADV_CONNECTABLE_UNDIRECTED);
+    
+    // Setup Advertising Interval
+    ble.setAdvertisingInterval(1000); /* 1000ms */
+    
+    /* SimpleChat */ ble.addService(uartService);
+    // Start Advertising
+    ble.startAdvertising();
+    
+    /* SimpleChat */ pc.printf("Advertising Start \r\n");
 }
 
 int main(void)
 {
+    pc.baud(9600);
+    pc.printf("Baud Rate set to 9600 \r\n");
+    
+    pc.attach( uartCB , pc.RxIrq);
+    
     led1 = 1;
     Ticker ticker;
     ticker.attach(periodicCallback, 1); // blink LED every second
@@ -86,6 +223,9 @@
      * BLE object is used in the main loop below. */
     while (ble.hasInitialized()  == false) { /* spin loop */ }
 
+    /* SimpleChat */ // Places nothing in the while (1) {} loop
+                     // It's relying on interrupts rather than
+                     // a periodic callback via a Ticker
     // infinite loop
     while (1) {
         // check for trigger from periodicCallback()
@@ -98,8 +238,28 @@
             if (hrmCounter == 175) { //  100 <= HRM bps <=175
                 hrmCounter = 100;
             }
-
             hrService->updateHeartRate(hrmCounter);
+        // Code relating to storing/playing inbound rhythm
+        // Into "Rhythm" Class (Yet to be defined)
+        /*} else if (inBoundRhythm && ble.getGapState().connected) {
+            inBoundRhythm = false;
+            Rhythm inRhythm;
+            inRythm += syntax for getting the incoming string
+            inRhythm.play(); // Create Member function which 
+                             // Plays Rhythms
+            
+        */
+        // Code relating to storing/sending outbound rhythm
+        /*} else if (inBoundRhythm && ble.getGapState().connected) {
+            inBoundRhythm = false;
+            Rhythm inRhythm;
+            inRythm += syntax for getting the incoming string
+            inRhythm.play(); // Create Member function which 
+                             // Plays Rhythms
+            
+        */
+        
+        // How will I set inBoundRhythm = true; ?
         } else {
             ble.waitForEvent(); // low power wait for event
         }