Redbear Nano firmware using Sandroide and showing how to send custom strings and parameters to the Android application

Dependencies:   BLE_API MbedJSONValue mbed nRF51822

Fork of BLE_RedBearNano-SAndroidEDevice by gio wild

Revision:
0:8d3dd6e411bf
Child:
1:ff6ec7837f46
diff -r 000000000000 -r 8d3dd6e411bf main.cpp
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/main.cpp	Mon Nov 28 10:58:38 2016 +0000
@@ -0,0 +1,271 @@
+/*
+
+Copyright (c) 2016 Giovanni Lenzi
+
+*/
+
+/*
+ *    This firmware is a port the RedBear BLE Shield Arduino Sketch(https://github.com/RedBearLab/nRF8001/blob/master/examples/BLEControllerSketch/BLEControllerSketch.ino), 
+ *    to Redbear Nano (http://redbearlab.com/blenano/).
+ *    After connection of Nano to PC using the provided MK20 USB board, 
+ *    you need to download the compiled firmware to your local disk 
+ *    and drag and drop it to the newly created MBED drive. 
+ *    Once flashed, you may access your Nano device with the NanoChat test application 
+ *    or from any SAndroidE powered application (http://es3.unibs.it/SAndroidE/)
+ */
+
+#include "mbed.h"
+#include "ble/BLE.h"
+
+#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
+
+// pin modes
+#define PIN_INPUT                 0 // digital input pin
+#define PIN_OUTPUT                1 // digital output pin
+#define PIN_ANALOG                2 // analog pin in analogInput mode
+#define PIN_PWM                   3 // digital pin in PWM output mode
+#define PIN_SERVO                 4 // digital pin in Servo output mode
+#define PIN_NOTSET                5 // pin not set
+
+BLE  ble;
+
+// 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 payloadTicker[TXRX_BUF_LEN] = {0,};
+uint8_t txPayload[TXRX_BUF_LEN] = {0,};
+uint8_t rxPayload[TXRX_BUF_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 *));
+
+static const int maxPins = 30;
+uint8_t pinTypes[maxPins];
+uint16_t prevValues[maxPins];
+
+DigitalInOut digitals[] = {P0_0,P0_7,P0_15,P0_19,P0_28,P0_29};
+int mapDigitals[] = { 0,-1,-1,-1,-1,-1,-1, 1,-1,-1,-1,-1,-1,-1,-1, 2,-1,-1,-1, 3,-1,-1,-1,-1,-1,-1,-1,-1, 4, 5,-1};
+AnalogIn analogs[] = {P0_1, P0_2, P0_3, P0_4, P0_5, P0_6};
+int mapAnalogs[] =  {-1, 0, 1, 2, 3, 4, 5,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1};
+
+
+void disconnectionCallback(const Gap::DisconnectionCallbackParams_t *params)
+{
+    //pc.printf("Disconnected \r\n");
+    //pc.printf("Restart advertising \r\n");
+    ble.startAdvertising();
+}
+
+bool initPin(int pin, uint8_t type){
+    bool ret=false;
+    if (pin>=0 && pin<31) {       // "initPin(): Pin number out of bounds"
+        if ((type==PIN_INPUT||type==PIN_OUTPUT) && mapDigitals[pin]>=0) {
+            if (type==PIN_INPUT) digitals[mapDigitals[pin]].input();  // initialize as input
+            if (type==PIN_OUTPUT) digitals[mapDigitals[pin]].output(); // initialize as input
+            pinTypes[pin] = type; // mark the pin as initialized
+            ret =true;
+        } else if (type==PIN_ANALOG && mapAnalogs[pin]>=0) {
+            pinTypes[pin] = type; // mark the pin as initialized
+            ret =true;
+        }
+    }
+    return ret;
+}
+
+uint16_t readPin(int pin) {
+    uint8_t mode = pinTypes[pin];
+    if (mode==PIN_INPUT) { // exists and is initialized as digital output
+        mode = 0;
+        return (((uint16_t)mode)<<8 | (uint16_t)(digitals[mapDigitals[pin]].read()));
+    } else if (mode==PIN_OUTPUT) { // exists and is initialized as digital output
+        mode = 1;
+        return (((uint16_t)mode)<<8 | (uint16_t)(digitals[mapDigitals[pin]].read()));
+    } else if (mode==PIN_ANALOG) { // exists and is initialized as digital output
+        mode = 2;
+        uint16_t value = analogs[mapAnalogs[pin]].read_u16();
+        uint8_t value_lo = value;
+        uint8_t value_hi = value>>8;
+        mode = (value_hi << 4) | mode;
+        return (((uint16_t)mode)<<8) | (uint16_t)value_lo;
+    }
+    return 0;
+}
+
+void sendPinValue(int pin, uint16_t value) {
+    uint8_t buf[TXRX_BUF_LEN];
+    buf[0]='G';
+    buf[1]=pin;
+    buf[2]=(uint8_t)(value>>8); buf[3]=(uint8_t)value;
+    ble.updateCharacteristicValue(rxCharacteristic.getValueAttribute().getHandle(), buf, 4);
+    prevValues[pin] = value;
+}
+
+void parseRedBearCmd(){
+    uint8_t buf[TXRX_BUF_LEN];
+    memset(buf, 0, TXRX_BUF_LEN);
+    
+    uint8_t startOffset = txPayload[0]==0?1:0;
+    uint8_t index = startOffset;
+    uint8_t cmd = txPayload[index++], pin=txPayload[index++], mode=PIN_NOTSET;
+    pin = pin>=48?pin-48:pin;
+
+    switch (cmd) {
+        case 'Z':sendPinValue(pin,readPin(pin));
+            break;
+        case 'X':initPin(7, PIN_OUTPUT);
+            break;
+        case 'Y':uint8_t value2write = txPayload[index++]-48;
+                    if (mapDigitals[pin]>=0) {
+                        digitals[mapDigitals[pin]].write(value2write==0?0:1);
+                        sendPinValue(pin,readPin(pin));
+                    }
+            break;
+
+        case 'M': //pc.printf("Querying pin %u mode\n",pin);
+            buf[0]=cmd;
+            buf[1]=pin;
+            buf[2]=pinTypes[pin];
+            ble.updateCharacteristicValue(rxCharacteristic.getValueAttribute().getHandle(), buf, 3);
+            break;
+            
+        case 'S': // set pin mode
+            mode = txPayload[index++];
+            mode = mode>=48?mode-48:mode;
+            if (initPin(pin, mode)) { // analogs are already initialized
+                sendPinValue(pin,readPin(pin));
+            }
+            break;
+            
+        case 'G': //pc.printf("Reading pin %u\n",pin);
+            switch (pinTypes[pin]) {
+                case PIN_INPUT:
+                case PIN_ANALOG:
+                    sendPinValue(pin,readPin(pin));
+                    break;
+                case PIN_OUTPUT: // TODO: send warning pin not readable (is an output)
+                default:  // TODO: send warning pin not initialized
+                    buf[0]=PIN_NOTSET;
+                    buf[1]=PIN_NOTSET;
+                    buf[2]=PIN_NOTSET;
+                    ble.updateCharacteristicValue(rxCharacteristic.getValueAttribute().getHandle(), buf, 3);
+                    break; 
+            }
+            break; 
+            
+        case 'T':
+            switch (pinTypes[pin]) {
+                case PIN_OUTPUT:
+                    uint8_t value2write = txPayload[index++];
+                    if (mapDigitals[pin]>=0) {
+                        digitals[mapDigitals[pin]].write(value2write==0?0:1);
+                        sendPinValue(pin,readPin(pin));
+                    }
+                    break;
+                case PIN_INPUT: // TODO: send warning pin not writable (is an input) 
+                case PIN_ANALOG: // TODO: send warning pin not writable (is an input) 
+                default:  // TODO: send warning pin not initialized
+                    buf[0]='T';
+                    buf[1]='T';
+                    buf[2]='T';
+                    ble.updateCharacteristicValue(rxCharacteristic.getValueAttribute().getHandle(), buf, 3);
+                    break; 
+            }
+            break; 
+            
+        default:
+            // echo received buffer
+            ble.updateCharacteristicValue(rxCharacteristic.getValueAttribute().getHandle(), &txPayload[startOffset], strlen((char *)&txPayload[startOffset])); // FIXME
+            break;
+    }   
+}
+
+
+void WrittenHandler(const GattWriteCallbackParams *Handler)
+{   
+    uint8_t buf[TXRX_BUF_LEN];
+    uint16_t bytesRead;
+    
+    if (Handler->handle == txCharacteristic.getValueAttribute().getHandle()) //only if empty
+    {
+        ble.readCharacteristicValue(txCharacteristic.getValueAttribute().getHandle(), buf, &bytesRead);
+        memset(txPayload, 0, TXRX_BUF_LEN);
+        memcpy(txPayload, buf, TXRX_BUF_LEN); 
+        
+        ble.updateCharacteristicValue(rxCharacteristic.getValueAttribute().getHandle(), buf, bytesRead);
+        parseRedBearCmd();
+    }
+}
+
+void m_status_check_handle(void)
+{   
+    for (int pin=0; pin<maxPins;pin++){
+        if (pinTypes[pin]==PIN_INPUT||pinTypes[pin]==PIN_ANALOG) {
+            uint16_t value = readPin(pin);
+            //uint16_t prevValue = 33;
+            if (prevValues[pin] != value) {
+                sendPinValue(pin,value);
+            }
+        }
+    }
+}
+
+int main(void)
+{
+    for (int i=0;i<maxPins;i++) {
+        pinTypes[i] = PIN_NOTSET;
+        prevValues[i] = 0;
+    }
+    
+    //memset(txPayload, 0, TXRX_BUF_LEN);
+
+    ble.init();
+    ble.onDisconnection(disconnectionCallback);
+    ble.onDataWritten(WrittenHandler);  
+    
+   // setup advertising 
+    ble.accumulateAdvertisingPayload(GapAdvertisingData::BREDR_NOT_SUPPORTED);
+    ble.setAdvertisingType(GapAdvertisingParams::ADV_CONNECTABLE_UNDIRECTED);
+    ble.accumulateAdvertisingPayload(GapAdvertisingData::SHORTENED_LOCAL_NAME,
+                                    (const uint8_t *)"MyNano", sizeof("MyNano") - 1);
+    ble.accumulateAdvertisingPayload(GapAdvertisingData::COMPLETE_LIST_128BIT_SERVICE_IDS,
+                                    (const uint8_t *)uart_base_uuid_rev, sizeof(uart_base_uuid));
+    // 100ms; in multiples of 0.625ms. 
+    ble.setAdvertisingInterval(160);
+
+    ble.addService(uartService);
+    
+    ble.startAdvertising(); 
+
+    Ticker ticker;
+    ticker.attach(m_status_check_handle, 0.2);
+    
+    while(1)
+    {
+        ble.waitForEvent();
+    }
+}
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+