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

Committer:
giowild
Date:
Mon Mar 27 12:04:16 2017 +0000
Revision:
1:ff6ec7837f46
Parent:
0:8d3dd6e411bf
Child:
2:6c45738bba43
added digital pins p0_8,p0_9,p0_10,p0_11

Who changed what in which revision?

UserRevisionLine numberNew contents of line
giowild 0:8d3dd6e411bf 1 /*
giowild 0:8d3dd6e411bf 2
giowild 0:8d3dd6e411bf 3 Copyright (c) 2016 Giovanni Lenzi
giowild 0:8d3dd6e411bf 4
giowild 0:8d3dd6e411bf 5 */
giowild 0:8d3dd6e411bf 6
giowild 0:8d3dd6e411bf 7 /*
giowild 0:8d3dd6e411bf 8 * This firmware is a port the RedBear BLE Shield Arduino Sketch(https://github.com/RedBearLab/nRF8001/blob/master/examples/BLEControllerSketch/BLEControllerSketch.ino),
giowild 0:8d3dd6e411bf 9 * to Redbear Nano (http://redbearlab.com/blenano/).
giowild 0:8d3dd6e411bf 10 * After connection of Nano to PC using the provided MK20 USB board,
giowild 0:8d3dd6e411bf 11 * you need to download the compiled firmware to your local disk
giowild 0:8d3dd6e411bf 12 * and drag and drop it to the newly created MBED drive.
giowild 0:8d3dd6e411bf 13 * Once flashed, you may access your Nano device with the NanoChat test application
giowild 0:8d3dd6e411bf 14 * or from any SAndroidE powered application (http://es3.unibs.it/SAndroidE/)
giowild 0:8d3dd6e411bf 15 */
giowild 0:8d3dd6e411bf 16
giowild 0:8d3dd6e411bf 17 #include "mbed.h"
giowild 0:8d3dd6e411bf 18 #include "ble/BLE.h"
giowild 0:8d3dd6e411bf 19
giowild 0:8d3dd6e411bf 20 #define BLE_UUID_TXRX_SERVICE 0x0000 /**< The UUID of the Nordic UART Service. */
giowild 0:8d3dd6e411bf 21 #define BLE_UUID_TX_CHARACTERISTIC 0x0002 /**< The UUID of the TX Characteristic. */
giowild 0:8d3dd6e411bf 22 #define BLE_UUIDS_RX_CHARACTERISTIC 0x0003 /**< The UUID of the RX Characteristic. */
giowild 0:8d3dd6e411bf 23
giowild 0:8d3dd6e411bf 24 #define TXRX_BUF_LEN 20
giowild 0:8d3dd6e411bf 25
giowild 0:8d3dd6e411bf 26 // pin modes
giowild 0:8d3dd6e411bf 27 #define PIN_INPUT 0 // digital input pin
giowild 0:8d3dd6e411bf 28 #define PIN_OUTPUT 1 // digital output pin
giowild 0:8d3dd6e411bf 29 #define PIN_ANALOG 2 // analog pin in analogInput mode
giowild 0:8d3dd6e411bf 30 #define PIN_PWM 3 // digital pin in PWM output mode
giowild 0:8d3dd6e411bf 31 #define PIN_SERVO 4 // digital pin in Servo output mode
giowild 0:8d3dd6e411bf 32 #define PIN_NOTSET 5 // pin not set
giowild 0:8d3dd6e411bf 33
giowild 0:8d3dd6e411bf 34 BLE ble;
giowild 0:8d3dd6e411bf 35
giowild 0:8d3dd6e411bf 36 // The Nordic UART Service
giowild 0:8d3dd6e411bf 37 static const uint8_t uart_base_uuid[] = {0x71, 0x3D, 0, 0, 0x50, 0x3E, 0x4C, 0x75, 0xBA, 0x94, 0x31, 0x48, 0xF1, 0x8D, 0x94, 0x1E};
giowild 0:8d3dd6e411bf 38 static const uint8_t uart_tx_uuid[] = {0x71, 0x3D, 0, 3, 0x50, 0x3E, 0x4C, 0x75, 0xBA, 0x94, 0x31, 0x48, 0xF1, 0x8D, 0x94, 0x1E};
giowild 0:8d3dd6e411bf 39 static const uint8_t uart_rx_uuid[] = {0x71, 0x3D, 0, 2, 0x50, 0x3E, 0x4C, 0x75, 0xBA, 0x94, 0x31, 0x48, 0xF1, 0x8D, 0x94, 0x1E};
giowild 0:8d3dd6e411bf 40 static const uint8_t uart_base_uuid_rev[] = {0x1E, 0x94, 0x8D, 0xF1, 0x48, 0x31, 0x94, 0xBA, 0x75, 0x4C, 0x3E, 0x50, 0, 0, 0x3D, 0x71};
giowild 0:8d3dd6e411bf 41
giowild 0:8d3dd6e411bf 42 uint8_t payloadTicker[TXRX_BUF_LEN] = {0,};
giowild 0:8d3dd6e411bf 43 uint8_t txPayload[TXRX_BUF_LEN] = {0,};
giowild 0:8d3dd6e411bf 44 uint8_t rxPayload[TXRX_BUF_LEN] = {0,};
giowild 0:8d3dd6e411bf 45
giowild 0:8d3dd6e411bf 46 GattCharacteristic txCharacteristic (uart_tx_uuid, txPayload, 1, TXRX_BUF_LEN, GattCharacteristic::BLE_GATT_CHAR_PROPERTIES_WRITE | GattCharacteristic::BLE_GATT_CHAR_PROPERTIES_WRITE_WITHOUT_RESPONSE);
giowild 0:8d3dd6e411bf 47 GattCharacteristic rxCharacteristic (uart_rx_uuid, rxPayload, 1, TXRX_BUF_LEN, GattCharacteristic::BLE_GATT_CHAR_PROPERTIES_NOTIFY);
giowild 0:8d3dd6e411bf 48 GattCharacteristic *uartChars[] = {&txCharacteristic, &rxCharacteristic};
giowild 0:8d3dd6e411bf 49 GattService uartService(uart_base_uuid, uartChars, sizeof(uartChars) / sizeof(GattCharacteristic *));
giowild 0:8d3dd6e411bf 50
giowild 0:8d3dd6e411bf 51 static const int maxPins = 30;
giowild 0:8d3dd6e411bf 52 uint8_t pinTypes[maxPins];
giowild 0:8d3dd6e411bf 53 uint16_t prevValues[maxPins];
giowild 0:8d3dd6e411bf 54
giowild 1:ff6ec7837f46 55 DigitalInOut digitals[] = {P0_0,P0_7,P0_8,P0_9,P0_10,P0_11,P0_15,P0_19,P0_28,P0_29};
giowild 1:ff6ec7837f46 56 int mapDigitals[] = { 0,-1,-1,-1,-1,-1,-1, 1,2,3,4,5,-1,-1,-1, 6,-1,-1,-1, 7,-1,-1,-1,-1,-1,-1,-1,-1, 8, 9,-1};
giowild 0:8d3dd6e411bf 57 AnalogIn analogs[] = {P0_1, P0_2, P0_3, P0_4, P0_5, P0_6};
giowild 0:8d3dd6e411bf 58 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};
giowild 0:8d3dd6e411bf 59
giowild 0:8d3dd6e411bf 60
giowild 0:8d3dd6e411bf 61 void disconnectionCallback(const Gap::DisconnectionCallbackParams_t *params)
giowild 0:8d3dd6e411bf 62 {
giowild 0:8d3dd6e411bf 63 //pc.printf("Disconnected \r\n");
giowild 0:8d3dd6e411bf 64 //pc.printf("Restart advertising \r\n");
giowild 0:8d3dd6e411bf 65 ble.startAdvertising();
giowild 0:8d3dd6e411bf 66 }
giowild 0:8d3dd6e411bf 67
giowild 0:8d3dd6e411bf 68 bool initPin(int pin, uint8_t type){
giowild 0:8d3dd6e411bf 69 bool ret=false;
giowild 0:8d3dd6e411bf 70 if (pin>=0 && pin<31) { // "initPin(): Pin number out of bounds"
giowild 0:8d3dd6e411bf 71 if ((type==PIN_INPUT||type==PIN_OUTPUT) && mapDigitals[pin]>=0) {
giowild 0:8d3dd6e411bf 72 if (type==PIN_INPUT) digitals[mapDigitals[pin]].input(); // initialize as input
giowild 0:8d3dd6e411bf 73 if (type==PIN_OUTPUT) digitals[mapDigitals[pin]].output(); // initialize as input
giowild 0:8d3dd6e411bf 74 pinTypes[pin] = type; // mark the pin as initialized
giowild 0:8d3dd6e411bf 75 ret =true;
giowild 0:8d3dd6e411bf 76 } else if (type==PIN_ANALOG && mapAnalogs[pin]>=0) {
giowild 0:8d3dd6e411bf 77 pinTypes[pin] = type; // mark the pin as initialized
giowild 0:8d3dd6e411bf 78 ret =true;
giowild 0:8d3dd6e411bf 79 }
giowild 0:8d3dd6e411bf 80 }
giowild 0:8d3dd6e411bf 81 return ret;
giowild 0:8d3dd6e411bf 82 }
giowild 0:8d3dd6e411bf 83
giowild 0:8d3dd6e411bf 84 uint16_t readPin(int pin) {
giowild 0:8d3dd6e411bf 85 uint8_t mode = pinTypes[pin];
giowild 0:8d3dd6e411bf 86 if (mode==PIN_INPUT) { // exists and is initialized as digital output
giowild 0:8d3dd6e411bf 87 mode = 0;
giowild 0:8d3dd6e411bf 88 return (((uint16_t)mode)<<8 | (uint16_t)(digitals[mapDigitals[pin]].read()));
giowild 0:8d3dd6e411bf 89 } else if (mode==PIN_OUTPUT) { // exists and is initialized as digital output
giowild 0:8d3dd6e411bf 90 mode = 1;
giowild 0:8d3dd6e411bf 91 return (((uint16_t)mode)<<8 | (uint16_t)(digitals[mapDigitals[pin]].read()));
giowild 0:8d3dd6e411bf 92 } else if (mode==PIN_ANALOG) { // exists and is initialized as digital output
giowild 0:8d3dd6e411bf 93 mode = 2;
giowild 0:8d3dd6e411bf 94 uint16_t value = analogs[mapAnalogs[pin]].read_u16();
giowild 0:8d3dd6e411bf 95 uint8_t value_lo = value;
giowild 0:8d3dd6e411bf 96 uint8_t value_hi = value>>8;
giowild 0:8d3dd6e411bf 97 mode = (value_hi << 4) | mode;
giowild 0:8d3dd6e411bf 98 return (((uint16_t)mode)<<8) | (uint16_t)value_lo;
giowild 0:8d3dd6e411bf 99 }
giowild 0:8d3dd6e411bf 100 return 0;
giowild 0:8d3dd6e411bf 101 }
giowild 0:8d3dd6e411bf 102
giowild 0:8d3dd6e411bf 103 void sendPinValue(int pin, uint16_t value) {
giowild 0:8d3dd6e411bf 104 uint8_t buf[TXRX_BUF_LEN];
giowild 0:8d3dd6e411bf 105 buf[0]='G';
giowild 0:8d3dd6e411bf 106 buf[1]=pin;
giowild 0:8d3dd6e411bf 107 buf[2]=(uint8_t)(value>>8); buf[3]=(uint8_t)value;
giowild 0:8d3dd6e411bf 108 ble.updateCharacteristicValue(rxCharacteristic.getValueAttribute().getHandle(), buf, 4);
giowild 0:8d3dd6e411bf 109 prevValues[pin] = value;
giowild 0:8d3dd6e411bf 110 }
giowild 0:8d3dd6e411bf 111
giowild 0:8d3dd6e411bf 112 void parseRedBearCmd(){
giowild 0:8d3dd6e411bf 113 uint8_t buf[TXRX_BUF_LEN];
giowild 0:8d3dd6e411bf 114 memset(buf, 0, TXRX_BUF_LEN);
giowild 0:8d3dd6e411bf 115
giowild 0:8d3dd6e411bf 116 uint8_t startOffset = txPayload[0]==0?1:0;
giowild 0:8d3dd6e411bf 117 uint8_t index = startOffset;
giowild 0:8d3dd6e411bf 118 uint8_t cmd = txPayload[index++], pin=txPayload[index++], mode=PIN_NOTSET;
giowild 0:8d3dd6e411bf 119 pin = pin>=48?pin-48:pin;
giowild 0:8d3dd6e411bf 120
giowild 0:8d3dd6e411bf 121 switch (cmd) {
giowild 0:8d3dd6e411bf 122 case 'Z':sendPinValue(pin,readPin(pin));
giowild 0:8d3dd6e411bf 123 break;
giowild 0:8d3dd6e411bf 124 case 'X':initPin(7, PIN_OUTPUT);
giowild 0:8d3dd6e411bf 125 break;
giowild 0:8d3dd6e411bf 126 case 'Y':uint8_t value2write = txPayload[index++]-48;
giowild 0:8d3dd6e411bf 127 if (mapDigitals[pin]>=0) {
giowild 0:8d3dd6e411bf 128 digitals[mapDigitals[pin]].write(value2write==0?0:1);
giowild 0:8d3dd6e411bf 129 sendPinValue(pin,readPin(pin));
giowild 0:8d3dd6e411bf 130 }
giowild 0:8d3dd6e411bf 131 break;
giowild 0:8d3dd6e411bf 132
giowild 0:8d3dd6e411bf 133 case 'M': //pc.printf("Querying pin %u mode\n",pin);
giowild 0:8d3dd6e411bf 134 buf[0]=cmd;
giowild 0:8d3dd6e411bf 135 buf[1]=pin;
giowild 0:8d3dd6e411bf 136 buf[2]=pinTypes[pin];
giowild 0:8d3dd6e411bf 137 ble.updateCharacteristicValue(rxCharacteristic.getValueAttribute().getHandle(), buf, 3);
giowild 0:8d3dd6e411bf 138 break;
giowild 0:8d3dd6e411bf 139
giowild 0:8d3dd6e411bf 140 case 'S': // set pin mode
giowild 0:8d3dd6e411bf 141 mode = txPayload[index++];
giowild 0:8d3dd6e411bf 142 mode = mode>=48?mode-48:mode;
giowild 0:8d3dd6e411bf 143 if (initPin(pin, mode)) { // analogs are already initialized
giowild 0:8d3dd6e411bf 144 sendPinValue(pin,readPin(pin));
giowild 0:8d3dd6e411bf 145 }
giowild 0:8d3dd6e411bf 146 break;
giowild 0:8d3dd6e411bf 147
giowild 0:8d3dd6e411bf 148 case 'G': //pc.printf("Reading pin %u\n",pin);
giowild 0:8d3dd6e411bf 149 switch (pinTypes[pin]) {
giowild 0:8d3dd6e411bf 150 case PIN_INPUT:
giowild 0:8d3dd6e411bf 151 case PIN_ANALOG:
giowild 0:8d3dd6e411bf 152 sendPinValue(pin,readPin(pin));
giowild 0:8d3dd6e411bf 153 break;
giowild 0:8d3dd6e411bf 154 case PIN_OUTPUT: // TODO: send warning pin not readable (is an output)
giowild 0:8d3dd6e411bf 155 default: // TODO: send warning pin not initialized
giowild 0:8d3dd6e411bf 156 buf[0]=PIN_NOTSET;
giowild 0:8d3dd6e411bf 157 buf[1]=PIN_NOTSET;
giowild 0:8d3dd6e411bf 158 buf[2]=PIN_NOTSET;
giowild 0:8d3dd6e411bf 159 ble.updateCharacteristicValue(rxCharacteristic.getValueAttribute().getHandle(), buf, 3);
giowild 0:8d3dd6e411bf 160 break;
giowild 0:8d3dd6e411bf 161 }
giowild 0:8d3dd6e411bf 162 break;
giowild 0:8d3dd6e411bf 163
giowild 0:8d3dd6e411bf 164 case 'T':
giowild 0:8d3dd6e411bf 165 switch (pinTypes[pin]) {
giowild 0:8d3dd6e411bf 166 case PIN_OUTPUT:
giowild 0:8d3dd6e411bf 167 uint8_t value2write = txPayload[index++];
giowild 0:8d3dd6e411bf 168 if (mapDigitals[pin]>=0) {
giowild 0:8d3dd6e411bf 169 digitals[mapDigitals[pin]].write(value2write==0?0:1);
giowild 0:8d3dd6e411bf 170 sendPinValue(pin,readPin(pin));
giowild 0:8d3dd6e411bf 171 }
giowild 0:8d3dd6e411bf 172 break;
giowild 0:8d3dd6e411bf 173 case PIN_INPUT: // TODO: send warning pin not writable (is an input)
giowild 0:8d3dd6e411bf 174 case PIN_ANALOG: // TODO: send warning pin not writable (is an input)
giowild 0:8d3dd6e411bf 175 default: // TODO: send warning pin not initialized
giowild 0:8d3dd6e411bf 176 buf[0]='T';
giowild 0:8d3dd6e411bf 177 buf[1]='T';
giowild 0:8d3dd6e411bf 178 buf[2]='T';
giowild 0:8d3dd6e411bf 179 ble.updateCharacteristicValue(rxCharacteristic.getValueAttribute().getHandle(), buf, 3);
giowild 0:8d3dd6e411bf 180 break;
giowild 0:8d3dd6e411bf 181 }
giowild 0:8d3dd6e411bf 182 break;
giowild 0:8d3dd6e411bf 183
giowild 0:8d3dd6e411bf 184 default:
giowild 0:8d3dd6e411bf 185 // echo received buffer
giowild 0:8d3dd6e411bf 186 ble.updateCharacteristicValue(rxCharacteristic.getValueAttribute().getHandle(), &txPayload[startOffset], strlen((char *)&txPayload[startOffset])); // FIXME
giowild 0:8d3dd6e411bf 187 break;
giowild 0:8d3dd6e411bf 188 }
giowild 0:8d3dd6e411bf 189 }
giowild 0:8d3dd6e411bf 190
giowild 0:8d3dd6e411bf 191
giowild 0:8d3dd6e411bf 192 void WrittenHandler(const GattWriteCallbackParams *Handler)
giowild 0:8d3dd6e411bf 193 {
giowild 0:8d3dd6e411bf 194 uint8_t buf[TXRX_BUF_LEN];
giowild 0:8d3dd6e411bf 195 uint16_t bytesRead;
giowild 0:8d3dd6e411bf 196
giowild 0:8d3dd6e411bf 197 if (Handler->handle == txCharacteristic.getValueAttribute().getHandle()) //only if empty
giowild 0:8d3dd6e411bf 198 {
giowild 0:8d3dd6e411bf 199 ble.readCharacteristicValue(txCharacteristic.getValueAttribute().getHandle(), buf, &bytesRead);
giowild 0:8d3dd6e411bf 200 memset(txPayload, 0, TXRX_BUF_LEN);
giowild 0:8d3dd6e411bf 201 memcpy(txPayload, buf, TXRX_BUF_LEN);
giowild 0:8d3dd6e411bf 202
giowild 0:8d3dd6e411bf 203 ble.updateCharacteristicValue(rxCharacteristic.getValueAttribute().getHandle(), buf, bytesRead);
giowild 0:8d3dd6e411bf 204 parseRedBearCmd();
giowild 0:8d3dd6e411bf 205 }
giowild 0:8d3dd6e411bf 206 }
giowild 0:8d3dd6e411bf 207
giowild 0:8d3dd6e411bf 208 void m_status_check_handle(void)
giowild 0:8d3dd6e411bf 209 {
giowild 0:8d3dd6e411bf 210 for (int pin=0; pin<maxPins;pin++){
giowild 0:8d3dd6e411bf 211 if (pinTypes[pin]==PIN_INPUT||pinTypes[pin]==PIN_ANALOG) {
giowild 0:8d3dd6e411bf 212 uint16_t value = readPin(pin);
giowild 0:8d3dd6e411bf 213 //uint16_t prevValue = 33;
giowild 0:8d3dd6e411bf 214 if (prevValues[pin] != value) {
giowild 0:8d3dd6e411bf 215 sendPinValue(pin,value);
giowild 0:8d3dd6e411bf 216 }
giowild 0:8d3dd6e411bf 217 }
giowild 0:8d3dd6e411bf 218 }
giowild 0:8d3dd6e411bf 219 }
giowild 0:8d3dd6e411bf 220
giowild 0:8d3dd6e411bf 221 int main(void)
giowild 0:8d3dd6e411bf 222 {
giowild 0:8d3dd6e411bf 223 for (int i=0;i<maxPins;i++) {
giowild 0:8d3dd6e411bf 224 pinTypes[i] = PIN_NOTSET;
giowild 0:8d3dd6e411bf 225 prevValues[i] = 0;
giowild 0:8d3dd6e411bf 226 }
giowild 0:8d3dd6e411bf 227
giowild 0:8d3dd6e411bf 228 //memset(txPayload, 0, TXRX_BUF_LEN);
giowild 0:8d3dd6e411bf 229
giowild 0:8d3dd6e411bf 230 ble.init();
giowild 0:8d3dd6e411bf 231 ble.onDisconnection(disconnectionCallback);
giowild 0:8d3dd6e411bf 232 ble.onDataWritten(WrittenHandler);
giowild 0:8d3dd6e411bf 233
giowild 0:8d3dd6e411bf 234 // setup advertising
giowild 0:8d3dd6e411bf 235 ble.accumulateAdvertisingPayload(GapAdvertisingData::BREDR_NOT_SUPPORTED);
giowild 0:8d3dd6e411bf 236 ble.setAdvertisingType(GapAdvertisingParams::ADV_CONNECTABLE_UNDIRECTED);
giowild 0:8d3dd6e411bf 237 ble.accumulateAdvertisingPayload(GapAdvertisingData::SHORTENED_LOCAL_NAME,
giowild 0:8d3dd6e411bf 238 (const uint8_t *)"MyNano", sizeof("MyNano") - 1);
giowild 0:8d3dd6e411bf 239 ble.accumulateAdvertisingPayload(GapAdvertisingData::COMPLETE_LIST_128BIT_SERVICE_IDS,
giowild 0:8d3dd6e411bf 240 (const uint8_t *)uart_base_uuid_rev, sizeof(uart_base_uuid));
giowild 0:8d3dd6e411bf 241 // 100ms; in multiples of 0.625ms.
giowild 0:8d3dd6e411bf 242 ble.setAdvertisingInterval(160);
giowild 0:8d3dd6e411bf 243
giowild 0:8d3dd6e411bf 244 ble.addService(uartService);
giowild 0:8d3dd6e411bf 245
giowild 0:8d3dd6e411bf 246 ble.startAdvertising();
giowild 0:8d3dd6e411bf 247
giowild 0:8d3dd6e411bf 248 Ticker ticker;
giowild 0:8d3dd6e411bf 249 ticker.attach(m_status_check_handle, 0.2);
giowild 0:8d3dd6e411bf 250
giowild 0:8d3dd6e411bf 251 while(1)
giowild 0:8d3dd6e411bf 252 {
giowild 0:8d3dd6e411bf 253 ble.waitForEvent();
giowild 0:8d3dd6e411bf 254 }
giowild 0:8d3dd6e411bf 255 }
giowild 0:8d3dd6e411bf 256
giowild 0:8d3dd6e411bf 257
giowild 0:8d3dd6e411bf 258
giowild 0:8d3dd6e411bf 259
giowild 0:8d3dd6e411bf 260
giowild 0:8d3dd6e411bf 261
giowild 0:8d3dd6e411bf 262
giowild 0:8d3dd6e411bf 263
giowild 0:8d3dd6e411bf 264
giowild 0:8d3dd6e411bf 265
giowild 0:8d3dd6e411bf 266
giowild 0:8d3dd6e411bf 267
giowild 0:8d3dd6e411bf 268
giowild 0:8d3dd6e411bf 269
giowild 0:8d3dd6e411bf 270
giowild 0:8d3dd6e411bf 271