Port of RedBear BLE Shield Arduino Sketch to RedBear Nano. This firmware enables BLE clients to initialize, read and write Nano pins over the air via Bluetooth, using the same protocol used by Redbear BLE Shield. This enables working with Nano devices from any SAndroidE powered application (http://es3.unibs.it/SAndroidE/).

Dependencies:   BLE_API mbed nRF51822 MbedJSONValue

Committer:
giowild
Date:
Mon Jul 24 09:36:09 2017 +0000
Revision:
2:6c45738bba43
Parent:
1:ff6ec7837f46
initial working version includes:; - changing sampling interval  for each pin; - changing delta thresold for each pin; - set pin to group

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 2:6c45738bba43 19 //#include "UARTService.h"
giowild 2:6c45738bba43 20 #include "Queue.h"
giowild 2:6c45738bba43 21
giowild 2:6c45738bba43 22
giowild 2:6c45738bba43 23 //#define MAX_REPLY_LEN (UARTService::BLE_UART_SERVICE_MAX_DATA_LEN)
giowild 0:8d3dd6e411bf 24
giowild 0:8d3dd6e411bf 25 #define BLE_UUID_TXRX_SERVICE 0x0000 /**< The UUID of the Nordic UART Service. */
giowild 0:8d3dd6e411bf 26 #define BLE_UUID_TX_CHARACTERISTIC 0x0002 /**< The UUID of the TX Characteristic. */
giowild 0:8d3dd6e411bf 27 #define BLE_UUIDS_RX_CHARACTERISTIC 0x0003 /**< The UUID of the RX Characteristic. */
giowild 0:8d3dd6e411bf 28
giowild 0:8d3dd6e411bf 29 #define TXRX_BUF_LEN 20
giowild 0:8d3dd6e411bf 30
giowild 0:8d3dd6e411bf 31 // pin modes
giowild 0:8d3dd6e411bf 32 #define PIN_INPUT 0 // digital input pin
giowild 0:8d3dd6e411bf 33 #define PIN_OUTPUT 1 // digital output pin
giowild 0:8d3dd6e411bf 34 #define PIN_ANALOG 2 // analog pin in analogInput mode
giowild 0:8d3dd6e411bf 35 #define PIN_PWM 3 // digital pin in PWM output mode
giowild 0:8d3dd6e411bf 36 #define PIN_SERVO 4 // digital pin in Servo output mode
giowild 0:8d3dd6e411bf 37 #define PIN_NOTSET 5 // pin not set
giowild 0:8d3dd6e411bf 38
giowild 2:6c45738bba43 39 #define NO_GROUP 0 // no_group means that current pin is sampled and transmitted individually
giowild 2:6c45738bba43 40
giowild 2:6c45738bba43 41
giowild 2:6c45738bba43 42 #define ANALOG_MAX_VALUE 1024 // this is uint16 max value: 65535
giowild 2:6c45738bba43 43 #define DEFAULT_SAMPLING_INTERVAL 1000 // 1 second
giowild 2:6c45738bba43 44 #define DEFAULT_DELTA 10 // this is uint16 in range [0-65535], 655 is 1% delta
giowild 2:6c45738bba43 45
giowild 0:8d3dd6e411bf 46 BLE ble;
giowild 2:6c45738bba43 47 Queue *recvQueue = NULL, *toSendQueue =NULL;
giowild 0:8d3dd6e411bf 48
giowild 0:8d3dd6e411bf 49 // The Nordic UART Service
giowild 0:8d3dd6e411bf 50 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 51 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 52 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 53 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 54
giowild 0:8d3dd6e411bf 55 uint8_t payloadTicker[TXRX_BUF_LEN] = {0,};
giowild 0:8d3dd6e411bf 56 uint8_t txPayload[TXRX_BUF_LEN] = {0,};
giowild 0:8d3dd6e411bf 57 uint8_t rxPayload[TXRX_BUF_LEN] = {0,};
giowild 0:8d3dd6e411bf 58
giowild 0:8d3dd6e411bf 59 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 60 GattCharacteristic rxCharacteristic (uart_rx_uuid, rxPayload, 1, TXRX_BUF_LEN, GattCharacteristic::BLE_GATT_CHAR_PROPERTIES_NOTIFY);
giowild 0:8d3dd6e411bf 61 GattCharacteristic *uartChars[] = {&txCharacteristic, &rxCharacteristic};
giowild 0:8d3dd6e411bf 62 GattService uartService(uart_base_uuid, uartChars, sizeof(uartChars) / sizeof(GattCharacteristic *));
giowild 2:6c45738bba43 63 //UARTService *m_uart_service_ptr;
giowild 2:6c45738bba43 64
giowild 0:8d3dd6e411bf 65
giowild 0:8d3dd6e411bf 66 static const int maxPins = 30;
giowild 0:8d3dd6e411bf 67 uint8_t pinTypes[maxPins];
giowild 2:6c45738bba43 68 uint8_t pinGroups[maxPins];
giowild 0:8d3dd6e411bf 69 uint16_t prevValues[maxPins];
giowild 0:8d3dd6e411bf 70
giowild 2:6c45738bba43 71 int pinSamplingIntervals[maxPins];
giowild 2:6c45738bba43 72 int pinTimers[maxPins];
giowild 2:6c45738bba43 73 uint16_t pinDelta[maxPins];
giowild 2:6c45738bba43 74
giowild 1:ff6ec7837f46 75 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 76 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 77 AnalogIn analogs[] = {P0_1, P0_2, P0_3, P0_4, P0_5, P0_6};
giowild 0:8d3dd6e411bf 78 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 79
giowild 0:8d3dd6e411bf 80
giowild 2:6c45738bba43 81
giowild 2:6c45738bba43 82 void enqueueItem(Queue *queue, uint8_t *buf, int len) {
giowild 2:6c45738bba43 83 NODE *item = NULL;
giowild 2:6c45738bba43 84 item = (NODE*) malloc(sizeof (NODE));
giowild 2:6c45738bba43 85 memcpy(item->data.payload, buf, len);
giowild 2:6c45738bba43 86 item->data.length = len;
giowild 2:6c45738bba43 87 Enqueue(queue, item);
giowild 2:6c45738bba43 88 }
giowild 2:6c45738bba43 89
giowild 0:8d3dd6e411bf 90 void disconnectionCallback(const Gap::DisconnectionCallbackParams_t *params)
giowild 0:8d3dd6e411bf 91 {
giowild 0:8d3dd6e411bf 92 //pc.printf("Disconnected \r\n");
giowild 0:8d3dd6e411bf 93 //pc.printf("Restart advertising \r\n");
giowild 0:8d3dd6e411bf 94 ble.startAdvertising();
giowild 0:8d3dd6e411bf 95 }
giowild 0:8d3dd6e411bf 96
giowild 2:6c45738bba43 97
giowild 2:6c45738bba43 98 NODE *enqItem = NULL;
giowild 2:6c45738bba43 99 int bytesCmd = 0;
giowild 2:6c45738bba43 100 bool endsOnNewLine = true;
giowild 2:6c45738bba43 101 #define NOT_FOUND -1
giowild 2:6c45738bba43 102
giowild 2:6c45738bba43 103 void WrittenHandler(const GattWriteCallbackParams *params)
giowild 2:6c45738bba43 104 {
giowild 2:6c45738bba43 105 uint8_t buf[TXRX_BUF_LEN];
giowild 2:6c45738bba43 106 uint16_t bytesRead, i;
giowild 2:6c45738bba43 107
giowild 2:6c45738bba43 108 if (params->handle == txCharacteristic.getValueAttribute().getHandle()) {
giowild 2:6c45738bba43 109 ble.readCharacteristicValue(params->handle, buf, &bytesRead);
giowild 2:6c45738bba43 110
giowild 2:6c45738bba43 111 if (enqItem == NULL){
giowild 2:6c45738bba43 112 endsOnNewLine = buf[0]=='{';
giowild 0:8d3dd6e411bf 113 }
giowild 2:6c45738bba43 114
giowild 2:6c45738bba43 115 if (!endsOnNewLine) {
giowild 2:6c45738bba43 116 enqueueItem(recvQueue, buf, bytesRead);
giowild 2:6c45738bba43 117 } else {
giowild 2:6c45738bba43 118 for (i=0; i<bytesRead; i++) {
giowild 2:6c45738bba43 119 if (endsOnNewLine && (buf[i]=='\n' || bytesCmd>QUEUE_STRING_LENGTH)) {
giowild 2:6c45738bba43 120 if (enqItem != NULL && enqItem->data.length>0) {
giowild 2:6c45738bba43 121 // push string to queue
giowild 2:6c45738bba43 122 Enqueue(recvQueue, enqItem);
giowild 2:6c45738bba43 123 }
giowild 2:6c45738bba43 124 enqItem = NULL;
giowild 2:6c45738bba43 125 } else {
giowild 2:6c45738bba43 126 // enqueue character
giowild 2:6c45738bba43 127 if (enqItem == NULL) {
giowild 2:6c45738bba43 128 enqItem = (NODE*) malloc(sizeof (NODE));
giowild 2:6c45738bba43 129 bytesCmd = 0;
giowild 2:6c45738bba43 130 }
giowild 2:6c45738bba43 131 enqItem->data.payload[bytesCmd++]=buf[i];
giowild 2:6c45738bba43 132 enqItem->data.length = bytesCmd;
giowild 2:6c45738bba43 133 }
giowild 2:6c45738bba43 134 }
giowild 2:6c45738bba43 135 }
giowild 2:6c45738bba43 136 }
giowild 0:8d3dd6e411bf 137 }
giowild 0:8d3dd6e411bf 138
giowild 2:6c45738bba43 139 uint16_t readPin(uint8_t pin) {
giowild 2:6c45738bba43 140 uint8_t mode = pinTypes[pin];
giowild 2:6c45738bba43 141 if (mode==PIN_INPUT) { // exists and is initialized as digital output
giowild 2:6c45738bba43 142 return digitals[mapDigitals[pin]].read()==0?0:ANALOG_MAX_VALUE;
giowild 2:6c45738bba43 143 } else if (mode==PIN_OUTPUT) { // exists and is initialized as digital output
giowild 2:6c45738bba43 144 return digitals[mapDigitals[pin]].read()==0?0:ANALOG_MAX_VALUE;
giowild 2:6c45738bba43 145 } else if (mode==PIN_ANALOG) { // exists and is initialized as digital output
giowild 2:6c45738bba43 146 return analogs[mapAnalogs[pin]].read_u16(); // 10 bits only
giowild 2:6c45738bba43 147 }
giowild 2:6c45738bba43 148 return 0;
giowild 2:6c45738bba43 149 }
giowild 2:6c45738bba43 150
giowild 2:6c45738bba43 151 uint16_t readPinOld(int pin) {
giowild 0:8d3dd6e411bf 152 uint8_t mode = pinTypes[pin];
giowild 0:8d3dd6e411bf 153 if (mode==PIN_INPUT) { // exists and is initialized as digital output
giowild 0:8d3dd6e411bf 154 mode = 0;
giowild 0:8d3dd6e411bf 155 return (((uint16_t)mode)<<8 | (uint16_t)(digitals[mapDigitals[pin]].read()));
giowild 0:8d3dd6e411bf 156 } else if (mode==PIN_OUTPUT) { // exists and is initialized as digital output
giowild 0:8d3dd6e411bf 157 mode = 1;
giowild 0:8d3dd6e411bf 158 return (((uint16_t)mode)<<8 | (uint16_t)(digitals[mapDigitals[pin]].read()));
giowild 0:8d3dd6e411bf 159 } else if (mode==PIN_ANALOG) { // exists and is initialized as digital output
giowild 0:8d3dd6e411bf 160 mode = 2;
giowild 0:8d3dd6e411bf 161 uint16_t value = analogs[mapAnalogs[pin]].read_u16();
giowild 0:8d3dd6e411bf 162 uint8_t value_lo = value;
giowild 0:8d3dd6e411bf 163 uint8_t value_hi = value>>8;
giowild 0:8d3dd6e411bf 164 mode = (value_hi << 4) | mode;
giowild 0:8d3dd6e411bf 165 return (((uint16_t)mode)<<8) | (uint16_t)value_lo;
giowild 0:8d3dd6e411bf 166 }
giowild 0:8d3dd6e411bf 167 return 0;
giowild 0:8d3dd6e411bf 168 }
giowild 0:8d3dd6e411bf 169
giowild 2:6c45738bba43 170 void sendPinValue(uint8_t pin, uint16_t value) {
giowild 0:8d3dd6e411bf 171 uint8_t buf[TXRX_BUF_LEN];
giowild 0:8d3dd6e411bf 172 buf[0]='G';
giowild 0:8d3dd6e411bf 173 buf[1]=pin;
giowild 2:6c45738bba43 174 buf[2]=(uint8_t)(value>>8);
giowild 2:6c45738bba43 175 buf[3]= (uint8_t) ((value<<8)>>8);
giowild 2:6c45738bba43 176 enqueueItem(toSendQueue, buf, 4);
giowild 2:6c45738bba43 177 /*int len = sprintf((char *)buf,"{\"pin\":%d,\"v\":%4.3f}",pin,(float)value/(float)ANALOG_MAX_VALUE);
giowild 2:6c45738bba43 178 enqueueItem(toSendQueue,buf, len);*/
giowild 2:6c45738bba43 179
giowild 0:8d3dd6e411bf 180 prevValues[pin] = value;
giowild 0:8d3dd6e411bf 181 }
giowild 0:8d3dd6e411bf 182
giowild 0:8d3dd6e411bf 183
giowild 2:6c45738bba43 184 void sendGroup(uint8_t groupno) {
giowild 2:6c45738bba43 185 uint8_t buf[TXRX_BUF_LEN], i=0;
giowild 2:6c45738bba43 186 buf[i++]='G';
giowild 2:6c45738bba43 187 for (uint8_t pin=0; pin<maxPins;pin++){
giowild 2:6c45738bba43 188 if (pinGroups[pin]==groupno) {
giowild 2:6c45738bba43 189 uint16_t value = readPin(pin);
giowild 2:6c45738bba43 190 buf[i++] = pin;
giowild 2:6c45738bba43 191 buf[i++] = (uint8_t)(value>>8);
giowild 2:6c45738bba43 192 buf[i++] = (uint8_t) ((value<<8)>>8);
giowild 2:6c45738bba43 193 prevValues[pin] = value;
giowild 2:6c45738bba43 194 }
giowild 2:6c45738bba43 195 }
giowild 2:6c45738bba43 196 if (i>1) { // at least 1 pin value to send
giowild 2:6c45738bba43 197 enqueueItem(toSendQueue, buf, i);
giowild 2:6c45738bba43 198 }
giowild 0:8d3dd6e411bf 199 }
giowild 0:8d3dd6e411bf 200
giowild 2:6c45738bba43 201 bool isInputPin(uint8_t pin) {
giowild 2:6c45738bba43 202 if (pin<maxPins){
giowild 2:6c45738bba43 203 uint8_t type = pinTypes[pin];
giowild 2:6c45738bba43 204 return type==PIN_INPUT||type==PIN_ANALOG;
giowild 0:8d3dd6e411bf 205 }
giowild 2:6c45738bba43 206 return false;
giowild 0:8d3dd6e411bf 207 }
giowild 0:8d3dd6e411bf 208
giowild 0:8d3dd6e411bf 209 void m_status_check_handle(void)
giowild 0:8d3dd6e411bf 210 {
giowild 0:8d3dd6e411bf 211 for (int pin=0; pin<maxPins;pin++){
giowild 0:8d3dd6e411bf 212 if (pinTypes[pin]==PIN_INPUT||pinTypes[pin]==PIN_ANALOG) {
giowild 0:8d3dd6e411bf 213 uint16_t value = readPin(pin);
giowild 0:8d3dd6e411bf 214 //uint16_t prevValue = 33;
giowild 0:8d3dd6e411bf 215 if (prevValues[pin] != value) {
giowild 0:8d3dd6e411bf 216 sendPinValue(pin,value);
giowild 0:8d3dd6e411bf 217 }
giowild 0:8d3dd6e411bf 218 }
giowild 0:8d3dd6e411bf 219 }
giowild 0:8d3dd6e411bf 220 }
giowild 0:8d3dd6e411bf 221
giowild 2:6c45738bba43 222
giowild 2:6c45738bba43 223 static volatile int gcd=-1;
giowild 2:6c45738bba43 224 Ticker *pTicker;
giowild 2:6c45738bba43 225 //Timeout timeout;
giowild 2:6c45738bba43 226 static volatile bool recalcTimer = false;
giowild 2:6c45738bba43 227 static volatile bool triggerSensorPolling = false;
giowild 2:6c45738bba43 228 static volatile bool gcdChanged =false;
giowild 2:6c45738bba43 229
giowild 2:6c45738bba43 230 int calc_gcd(int n1,int n2) {
giowild 2:6c45738bba43 231 int lgcd=1;
giowild 2:6c45738bba43 232 for(int i=2; i <= n1 && i <= n2; ++i)
giowild 2:6c45738bba43 233 {
giowild 2:6c45738bba43 234 // Checks if i is factor of both integers
giowild 2:6c45738bba43 235 if(n1%i==0 && n2%i==0)
giowild 2:6c45738bba43 236 lgcd = i;
giowild 2:6c45738bba43 237 }
giowild 2:6c45738bba43 238 return lgcd;
giowild 2:6c45738bba43 239 }
giowild 2:6c45738bba43 240
giowild 2:6c45738bba43 241 void check_pin_changed(void)
giowild 2:6c45738bba43 242 {
giowild 2:6c45738bba43 243 uint8_t buf[QUEUE_STRING_LENGTH];
giowild 2:6c45738bba43 244 if (gcd>0) {
giowild 2:6c45738bba43 245 for (int pin=0; pin<maxPins;pin++){
giowild 2:6c45738bba43 246 if (isInputPin(pin)) {
giowild 2:6c45738bba43 247 if (pinTimers[pin] < 0) {
giowild 2:6c45738bba43 248 pinTimers[pin] = pinSamplingIntervals[pin];
giowild 2:6c45738bba43 249 } else {
giowild 2:6c45738bba43 250 pinTimers[pin]-=gcd;
giowild 2:6c45738bba43 251 }
giowild 2:6c45738bba43 252 if (pinTimers[pin]==0) {
giowild 2:6c45738bba43 253 pinTimers[pin] = pinSamplingIntervals[pin];
giowild 2:6c45738bba43 254 uint16_t value = readPin(pin);
giowild 2:6c45738bba43 255 if (abs(prevValues[pin]-value) >= pinDelta[pin]) {
giowild 2:6c45738bba43 256 if (pinGroups[pin]!=NO_GROUP) { // enqueue sending operation for group
giowild 2:6c45738bba43 257 int len = sprintf((char *)buf,"R%c",pinGroups[pin]);
giowild 2:6c45738bba43 258 enqueueItem(recvQueue, buf, len);
giowild 2:6c45738bba43 259 } else { // send the pin
giowild 2:6c45738bba43 260 sendPinValue(pin,value);
giowild 2:6c45738bba43 261 }
giowild 2:6c45738bba43 262 }
giowild 2:6c45738bba43 263 }
giowild 2:6c45738bba43 264 }
giowild 2:6c45738bba43 265 }
giowild 2:6c45738bba43 266 }
giowild 2:6c45738bba43 267 }
giowild 2:6c45738bba43 268
giowild 2:6c45738bba43 269 void calc_timer_interval()
giowild 2:6c45738bba43 270 {
giowild 2:6c45738bba43 271 gcd = -1;
giowild 2:6c45738bba43 272 for (int pin=0; pin<maxPins;pin++){
giowild 2:6c45738bba43 273 if (isInputPin(pin) && pinSamplingIntervals[pin]>0) {
giowild 2:6c45738bba43 274 uint8_t buf[TXRX_BUF_LEN];
giowild 2:6c45738bba43 275 int len = sprintf((char *)buf,"TIMER %d@%d",pin,pinSamplingIntervals[pin]);
giowild 2:6c45738bba43 276 //int len = sprintf((char *)buf,"check-gcd");
giowild 2:6c45738bba43 277 enqueueItem(toSendQueue, buf, len);
giowild 2:6c45738bba43 278
giowild 2:6c45738bba43 279 if (gcd==-1) {
giowild 2:6c45738bba43 280 gcd = pinSamplingIntervals[pin];
giowild 2:6c45738bba43 281 } else {
giowild 2:6c45738bba43 282 gcd = calc_gcd(gcd,pinSamplingIntervals[pin]);
giowild 2:6c45738bba43 283 }
giowild 2:6c45738bba43 284 }
giowild 2:6c45738bba43 285 }
giowild 2:6c45738bba43 286 }
giowild 2:6c45738bba43 287
giowild 2:6c45738bba43 288 bool initPin(uint8_t pin, uint8_t type){
giowild 2:6c45738bba43 289 bool ret=false,wasset=true,armTimer=false;
giowild 2:6c45738bba43 290
giowild 2:6c45738bba43 291 //uint8_t buf[TXRX_BUF_LEN];
giowild 2:6c45738bba43 292 //buf[0]='Y';buf[1]=pin;buf[2]=type;
giowild 2:6c45738bba43 293 //int len = sprintf((char *)buf,"ASD%d-%c",pin,pin);
giowild 2:6c45738bba43 294 //enqueueItem(toSendQueue, buf, 3);
giowild 2:6c45738bba43 295
giowild 2:6c45738bba43 296 if (pin<maxPins) { // "initPin(): Pin number out of bounds"
giowild 2:6c45738bba43 297 wasset = pinTypes[pin]!=PIN_NOTSET;
giowild 2:6c45738bba43 298 if ((type==PIN_INPUT||type==PIN_OUTPUT) && mapDigitals[pin]>=0) {
giowild 2:6c45738bba43 299 if (type==PIN_INPUT) digitals[mapDigitals[pin]].input(); // initialize as input
giowild 2:6c45738bba43 300 if (type==PIN_OUTPUT) digitals[mapDigitals[pin]].output(); // initialize as input
giowild 2:6c45738bba43 301 pinTypes[pin] = type; // mark the pin as initialized
giowild 2:6c45738bba43 302 ret =true;
giowild 2:6c45738bba43 303 } else if (type==PIN_ANALOG && mapAnalogs[pin]>=0) {
giowild 2:6c45738bba43 304 pinTypes[pin] = type; // mark the pin as initialized
giowild 2:6c45738bba43 305 ret =true;
giowild 2:6c45738bba43 306 }
giowild 2:6c45738bba43 307 if (!wasset && ret && (type==PIN_INPUT||type==PIN_ANALOG)) armTimer=true;
giowild 2:6c45738bba43 308 }
giowild 2:6c45738bba43 309 if (armTimer) {
giowild 2:6c45738bba43 310 pinSamplingIntervals[pin] = DEFAULT_SAMPLING_INTERVAL;
giowild 2:6c45738bba43 311 //pinTimers[pin]=pinSamplingIntervals[pin];
giowild 2:6c45738bba43 312 recalcTimer = true;
giowild 2:6c45738bba43 313 }
giowild 2:6c45738bba43 314
giowild 2:6c45738bba43 315 return ret;
giowild 2:6c45738bba43 316 }
giowild 2:6c45738bba43 317
giowild 2:6c45738bba43 318 bool initPin(uint8_t pin, uint8_t type, uint8_t group){
giowild 2:6c45738bba43 319 bool ret = initPin(pin, type);
giowild 2:6c45738bba43 320 if (ret){
giowild 2:6c45738bba43 321 pinGroups[pin]=group;
giowild 2:6c45738bba43 322 }
giowild 2:6c45738bba43 323 return ret;
giowild 2:6c45738bba43 324 }
giowild 2:6c45738bba43 325
giowild 2:6c45738bba43 326 void changeDelta(uint8_t pin, uint16_t delta) {
giowild 2:6c45738bba43 327 uint8_t buf[TXRX_BUF_LEN];
giowild 2:6c45738bba43 328 int len = sprintf((char *)buf,"DELTA %d@%d",pin,delta);
giowild 2:6c45738bba43 329 enqueueItem(toSendQueue, buf, len);
giowild 2:6c45738bba43 330
giowild 2:6c45738bba43 331 //float fdelta = delta / ANALOG_MAX_VALUE;
giowild 2:6c45738bba43 332 if (delta > ANALOG_MAX_VALUE) delta=ANALOG_MAX_VALUE;
giowild 2:6c45738bba43 333 if (isInputPin(pin)) {
giowild 2:6c45738bba43 334 pinDelta[pin] = delta;
giowild 2:6c45738bba43 335 }
giowild 2:6c45738bba43 336 }
giowild 2:6c45738bba43 337
giowild 2:6c45738bba43 338 void changeDeltaPercent(uint8_t pin, float fdelta) {
giowild 2:6c45738bba43 339 changeDelta(pin, (uint16_t)(fdelta*ANALOG_MAX_VALUE));
giowild 2:6c45738bba43 340 }
giowild 2:6c45738bba43 341 void changeSamplingInterval(uint8_t pin, int interval) {
giowild 2:6c45738bba43 342 if (isInputPin(pin)) {
giowild 2:6c45738bba43 343 pinSamplingIntervals[pin]= interval;
giowild 2:6c45738bba43 344 recalcTimer = true;
giowild 2:6c45738bba43 345 }
giowild 2:6c45738bba43 346 }
giowild 2:6c45738bba43 347
giowild 2:6c45738bba43 348 bool writeDigital(uint8_t pin, bool value){
giowild 2:6c45738bba43 349 if (mapDigitals[pin]>=0) {
giowild 2:6c45738bba43 350 digitals[mapDigitals[pin]].write(value?1:0);
giowild 2:6c45738bba43 351 //sendPinValue(pin,readPin(pin));
giowild 2:6c45738bba43 352 }
giowild 2:6c45738bba43 353 }
giowild 2:6c45738bba43 354
giowild 2:6c45738bba43 355 void parseRedBearCmd(uint8_t* cmdString){
giowild 2:6c45738bba43 356 uint8_t buf[TXRX_BUF_LEN];
giowild 2:6c45738bba43 357 memset(buf, 0, TXRX_BUF_LEN);
giowild 2:6c45738bba43 358 int len=0, scanned=-1, sampling=-1;
giowild 2:6c45738bba43 359 float fdelta=-1;
giowild 2:6c45738bba43 360
giowild 2:6c45738bba43 361 uint8_t startOffset = cmdString[0]==0?1:0;
giowild 2:6c45738bba43 362 uint8_t index = startOffset;
giowild 2:6c45738bba43 363 uint8_t cmd = cmdString[index++], pin=cmdString[index++], mode=PIN_NOTSET, group=NO_GROUP;
giowild 2:6c45738bba43 364 pin = pin>=48?pin-48:pin;
giowild 2:6c45738bba43 365
giowild 2:6c45738bba43 366 switch (cmd) {
giowild 2:6c45738bba43 367 case '{':
giowild 2:6c45738bba43 368 //snprintf((char*) buf, MAX_REPLY_LEN, "ERROR: Unknown char\n");
giowild 2:6c45738bba43 369 //m_uart_service_ptr->writeString((char*)buf);
giowild 2:6c45738bba43 370 break;
giowild 2:6c45738bba43 371 case 'Y':
giowild 2:6c45738bba43 372 uint8_t value2write = cmdString[index++]-48;
giowild 2:6c45738bba43 373 value2write = value2write>=48?value2write-48:value2write;
giowild 2:6c45738bba43 374 writeDigital(pin,value2write!=0);
giowild 2:6c45738bba43 375 break;
giowild 2:6c45738bba43 376
giowild 2:6c45738bba43 377 case 'M': //pc.printf("Querying pin %u mode\n",pin);
giowild 2:6c45738bba43 378 buf[0]=cmd;buf[1]=pin;buf[2]=pinTypes[pin];
giowild 2:6c45738bba43 379 enqueueItem(toSendQueue, buf, 3);
giowild 2:6c45738bba43 380 break;
giowild 2:6c45738bba43 381
giowild 2:6c45738bba43 382 case 'S': // set pin mode
giowild 2:6c45738bba43 383 mode = cmdString[index++];
giowild 2:6c45738bba43 384 mode = mode>=48?mode-48:mode;
giowild 2:6c45738bba43 385 group = cmdString[index++];
giowild 2:6c45738bba43 386 if (initPin(pin, mode, group)) { // analogs are already initialized
giowild 2:6c45738bba43 387 //if (initPin(pin, mode)) { // analogs are already initialized
giowild 2:6c45738bba43 388 sendPinValue(pin,readPin(pin));
giowild 2:6c45738bba43 389 }
giowild 2:6c45738bba43 390 break;
giowild 2:6c45738bba43 391
giowild 2:6c45738bba43 392 case 'D': // delta to consider value changed (as percentage [0-1] of Voltage range)
giowild 2:6c45738bba43 393 scanned = sscanf( (char *)&cmdString[2], "%f", &fdelta);
giowild 2:6c45738bba43 394
giowild 2:6c45738bba43 395 if (scanned==1 && fdelta>=0 && fdelta<=1) {
giowild 2:6c45738bba43 396 len = sprintf((char *)buf,"DELTA%d@%f",(int)pin,fdelta);
giowild 2:6c45738bba43 397 enqueueItem(toSendQueue, buf, len);
giowild 2:6c45738bba43 398 changeDeltaPercent(pin, fdelta);
giowild 2:6c45738bba43 399 /*changeDelta ( pin,((uint16_t)cmdString[index+0]) << 8 |
giowild 2:6c45738bba43 400 ((uint16_t)cmdString[index+1]) );*/
giowild 2:6c45738bba43 401 } else {
giowild 2:6c45738bba43 402 len = sprintf((char *)buf,"DELTA%d@ERR",(int)pin);
giowild 2:6c45738bba43 403 enqueueItem(toSendQueue, buf, len);
giowild 2:6c45738bba43 404 }
giowild 2:6c45738bba43 405 break;
giowild 2:6c45738bba43 406
giowild 2:6c45738bba43 407 case 'I': // sampling interval
giowild 2:6c45738bba43 408 scanned = sscanf( (char *)&cmdString[2], "%d", &sampling);
giowild 2:6c45738bba43 409
giowild 2:6c45738bba43 410 if (scanned==1 && sampling>=0) {
giowild 2:6c45738bba43 411 len = sprintf((char *)buf,"SAMPL%d@%d",(int)pin,sampling);
giowild 2:6c45738bba43 412 enqueueItem(toSendQueue, buf, len);
giowild 2:6c45738bba43 413 changeSamplingInterval( pin, sampling);
giowild 2:6c45738bba43 414 /*changeSamplingInterval( pin,((int)cmdString[index+0]) << 24 |
giowild 2:6c45738bba43 415 ((int)cmdString[index+1]) << 16 |
giowild 2:6c45738bba43 416 ((int)cmdString[index+2]) << 8 |
giowild 2:6c45738bba43 417 ((int)cmdString[index+3]) );*/
giowild 2:6c45738bba43 418 } else {
giowild 2:6c45738bba43 419 len = sprintf((char *)buf,"SAMPL%d@ERR",(int)pin);
giowild 2:6c45738bba43 420 enqueueItem(toSendQueue, buf, len);
giowild 2:6c45738bba43 421 }
giowild 2:6c45738bba43 422 break;
giowild 2:6c45738bba43 423
giowild 2:6c45738bba43 424 case 'G': //pc.printf("Reading pin %u\n",pin);
giowild 2:6c45738bba43 425 switch (pinTypes[pin]) {
giowild 2:6c45738bba43 426 case PIN_INPUT:
giowild 2:6c45738bba43 427 case PIN_ANALOG:
giowild 2:6c45738bba43 428 sendPinValue(pin,readPin(pin));
giowild 2:6c45738bba43 429 break;
giowild 2:6c45738bba43 430 case PIN_OUTPUT: // TODO: send warning pin not readable (is an output)
giowild 2:6c45738bba43 431 default: // TODO: send warning pin not initialized
giowild 2:6c45738bba43 432 buf[0]=PIN_NOTSET;buf[1]=PIN_NOTSET;buf[2]=PIN_NOTSET;
giowild 2:6c45738bba43 433 enqueueItem(toSendQueue, buf, 3);
giowild 2:6c45738bba43 434 break;
giowild 2:6c45738bba43 435 }
giowild 2:6c45738bba43 436 break;
giowild 2:6c45738bba43 437
giowild 2:6c45738bba43 438 case 'T':
giowild 2:6c45738bba43 439 switch (pinTypes[pin]) {
giowild 2:6c45738bba43 440 case PIN_OUTPUT:
giowild 2:6c45738bba43 441 uint8_t value2write = cmdString[index++];
giowild 2:6c45738bba43 442 if (mapDigitals[pin]>=0) {
giowild 2:6c45738bba43 443 digitals[mapDigitals[pin]].write(value2write==0?0:1);
giowild 2:6c45738bba43 444 sendPinValue(pin,readPin(pin));
giowild 2:6c45738bba43 445 }
giowild 2:6c45738bba43 446 break;
giowild 2:6c45738bba43 447 case PIN_INPUT: // TODO: send warning pin not writable (is an input)
giowild 2:6c45738bba43 448 case PIN_ANALOG: // TODO: send warning pin not writable (is an input)
giowild 2:6c45738bba43 449 default: // TODO: send warning pin not initialized
giowild 2:6c45738bba43 450 buf[0]='T';buf[1]='T';buf[2]='T';
giowild 2:6c45738bba43 451 enqueueItem(toSendQueue, buf, 3);
giowild 2:6c45738bba43 452 break;
giowild 2:6c45738bba43 453 }
giowild 2:6c45738bba43 454 break;
giowild 2:6c45738bba43 455 case 'R':
giowild 2:6c45738bba43 456 // pin variable contains the group, not the pin number
giowild 2:6c45738bba43 457 sendGroup(pin);
giowild 2:6c45738bba43 458 break;
giowild 2:6c45738bba43 459 default:
giowild 2:6c45738bba43 460 // echo received buffer
giowild 2:6c45738bba43 461 enqueueItem(toSendQueue, &cmdString[startOffset], strlen((char *)&cmdString[startOffset]));
giowild 2:6c45738bba43 462 break;
giowild 2:6c45738bba43 463 }
giowild 2:6c45738bba43 464 }
giowild 2:6c45738bba43 465
giowild 2:6c45738bba43 466
giowild 2:6c45738bba43 467 void triggerSensor(){
giowild 2:6c45738bba43 468 triggerSensorPolling=true;
giowild 2:6c45738bba43 469 }
giowild 2:6c45738bba43 470
giowild 2:6c45738bba43 471
giowild 2:6c45738bba43 472 void changeGcdTiming(){
giowild 2:6c45738bba43 473 /*if (gcdChanged) {
giowild 2:6c45738bba43 474 gcdChanged =false;
giowild 2:6c45738bba43 475 if (gcd>0) {
giowild 2:6c45738bba43 476 pTicker->attach(NULL,5);
giowild 2:6c45738bba43 477 pTicker->attach(triggerSensor, 0.001*gcd);
giowild 2:6c45738bba43 478 } else {
giowild 2:6c45738bba43 479 pTicker->attach(NULL,5);
giowild 2:6c45738bba43 480 }
giowild 2:6c45738bba43 481 }*/
giowild 2:6c45738bba43 482
giowild 2:6c45738bba43 483 uint8_t buf[TXRX_BUF_LEN];
giowild 2:6c45738bba43 484 int len = sprintf((char *)buf,"check-gcd %d",gcd);
giowild 2:6c45738bba43 485 enqueueItem(toSendQueue, buf, len);
giowild 2:6c45738bba43 486 }
giowild 2:6c45738bba43 487
giowild 2:6c45738bba43 488
giowild 0:8d3dd6e411bf 489 int main(void)
giowild 0:8d3dd6e411bf 490 {
giowild 2:6c45738bba43 491
giowild 0:8d3dd6e411bf 492 for (int i=0;i<maxPins;i++) {
giowild 0:8d3dd6e411bf 493 pinTypes[i] = PIN_NOTSET;
giowild 0:8d3dd6e411bf 494 prevValues[i] = 0;
giowild 2:6c45738bba43 495 pinSamplingIntervals[i] = -1;
giowild 2:6c45738bba43 496 pinTimers[i]=-1;
giowild 2:6c45738bba43 497 pinDelta[i]=DEFAULT_DELTA;
giowild 2:6c45738bba43 498 pinGroups[i]=NO_GROUP;
giowild 0:8d3dd6e411bf 499 }
giowild 2:6c45738bba43 500
giowild 2:6c45738bba43 501 initPin(7,PIN_OUTPUT);
giowild 2:6c45738bba43 502 initPin(28,PIN_OUTPUT);
giowild 2:6c45738bba43 503 writeDigital(7,true);
giowild 2:6c45738bba43 504 writeDigital(28,false);
giowild 0:8d3dd6e411bf 505
giowild 0:8d3dd6e411bf 506 ble.init();
giowild 0:8d3dd6e411bf 507 ble.onDisconnection(disconnectionCallback);
giowild 0:8d3dd6e411bf 508 ble.onDataWritten(WrittenHandler);
giowild 0:8d3dd6e411bf 509
giowild 0:8d3dd6e411bf 510 // setup advertising
giowild 0:8d3dd6e411bf 511 ble.accumulateAdvertisingPayload(GapAdvertisingData::BREDR_NOT_SUPPORTED);
giowild 0:8d3dd6e411bf 512 ble.setAdvertisingType(GapAdvertisingParams::ADV_CONNECTABLE_UNDIRECTED);
giowild 0:8d3dd6e411bf 513 ble.accumulateAdvertisingPayload(GapAdvertisingData::SHORTENED_LOCAL_NAME,
giowild 0:8d3dd6e411bf 514 (const uint8_t *)"MyNano", sizeof("MyNano") - 1);
giowild 0:8d3dd6e411bf 515 ble.accumulateAdvertisingPayload(GapAdvertisingData::COMPLETE_LIST_128BIT_SERVICE_IDS,
giowild 0:8d3dd6e411bf 516 (const uint8_t *)uart_base_uuid_rev, sizeof(uart_base_uuid));
giowild 0:8d3dd6e411bf 517 // 100ms; in multiples of 0.625ms.
giowild 0:8d3dd6e411bf 518 ble.setAdvertisingInterval(160);
giowild 0:8d3dd6e411bf 519
giowild 0:8d3dd6e411bf 520 ble.addService(uartService);
giowild 0:8d3dd6e411bf 521
giowild 0:8d3dd6e411bf 522 ble.startAdvertising();
giowild 0:8d3dd6e411bf 523
giowild 2:6c45738bba43 524 //ticker.attach(m_status_check_handle, 0.2);
giowild 2:6c45738bba43 525
giowild 2:6c45738bba43 526 // Create a UARTService object (GATT stuff).
giowild 2:6c45738bba43 527 //UARTService myUartService(ble);
giowild 2:6c45738bba43 528 //m_uart_service_ptr = &myUartService;
giowild 2:6c45738bba43 529
giowild 0:8d3dd6e411bf 530 Ticker ticker;
giowild 2:6c45738bba43 531 //pTicker = &ticker;
giowild 2:6c45738bba43 532
giowild 2:6c45738bba43 533 //Ticker pinTicker;
giowild 2:6c45738bba43 534 //pinTicker.attach(triggerSensor, 5);
giowild 2:6c45738bba43 535
giowild 2:6c45738bba43 536 Ticker gcdTicker;
giowild 2:6c45738bba43 537 gcdTicker.attach(changeGcdTiming, 5);
giowild 2:6c45738bba43 538
giowild 2:6c45738bba43 539 recvQueue = ConstructQueue(40);
giowild 2:6c45738bba43 540 toSendQueue = ConstructQueue(40);
giowild 2:6c45738bba43 541
giowild 2:6c45738bba43 542 uint8_t buf[QUEUE_STRING_LENGTH];
giowild 2:6c45738bba43 543 NODE *deqItem = NULL;
giowild 2:6c45738bba43 544 /*
giowild 2:6c45738bba43 545 // set pin 7 as VCC and pin 28 as GND
giowild 2:6c45738bba43 546 int len = sprintf((char *)buf,"S%c%c",7,1);
giowild 2:6c45738bba43 547 enqueueItem(recvQueue, buf, len);
giowild 2:6c45738bba43 548 len = sprintf((char *)buf,"S%c%c",28,1);
giowild 2:6c45738bba43 549 enqueueItem(recvQueue, buf, len);
giowild 2:6c45738bba43 550 len = sprintf((char *)buf,"Y%c%c",7,'1');
giowild 2:6c45738bba43 551 enqueueItem(recvQueue, buf, len);
giowild 2:6c45738bba43 552 len = sprintf((char *)buf,"Y%c%c",28,'0');
giowild 2:6c45738bba43 553 enqueueItem(recvQueue, buf, len);*/
giowild 0:8d3dd6e411bf 554
giowild 0:8d3dd6e411bf 555 while(1)
giowild 0:8d3dd6e411bf 556 {
giowild 2:6c45738bba43 557 if (ble.getGapState().connected) {
giowild 2:6c45738bba43 558 if (recalcTimer) {
giowild 2:6c45738bba43 559 recalcTimer =false;
giowild 2:6c45738bba43 560 calc_timer_interval();
giowild 2:6c45738bba43 561 //gcdChanged =true;
giowild 2:6c45738bba43 562 if (gcd>0) {
giowild 2:6c45738bba43 563 ticker.attach(NULL,5);
giowild 2:6c45738bba43 564 ticker.attach(triggerSensor, 0.001*gcd);
giowild 2:6c45738bba43 565 } else {
giowild 2:6c45738bba43 566 ticker.attach(NULL,5);
giowild 2:6c45738bba43 567 }
giowild 2:6c45738bba43 568 } else if (!isEmpty(toSendQueue)) {
giowild 2:6c45738bba43 569 //while (!isEmpty(toSendQueue)) {
giowild 2:6c45738bba43 570 deqItem = Dequeue(toSendQueue);
giowild 2:6c45738bba43 571 //memset(buf, 0, QUEUE_STRING_LENGTH); // useless
giowild 2:6c45738bba43 572 memcpy(buf, (uint8_t *)deqItem->data.payload, deqItem->data.length);
giowild 2:6c45738bba43 573 ble.updateCharacteristicValue(rxCharacteristic.getValueAttribute().getHandle(), buf, deqItem->data.length);
giowild 2:6c45738bba43 574 //ble.updateCharacteristicValue(m_uart_service_ptr->getRXCharacteristicHandle(), buf, deqItem->data.length);
giowild 2:6c45738bba43 575 free(deqItem);
giowild 2:6c45738bba43 576 //}
giowild 2:6c45738bba43 577 } else if (!isEmpty(recvQueue)) {
giowild 2:6c45738bba43 578 //if (!isEmpty(recvQueue)) {
giowild 2:6c45738bba43 579 deqItem = Dequeue(recvQueue);
giowild 2:6c45738bba43 580 memset(buf, 0, QUEUE_STRING_LENGTH); // maybe useless: TO CHECK its handling in parseRedBearCmd
giowild 2:6c45738bba43 581 memcpy(buf, (uint8_t *)deqItem->data.payload, deqItem->data.length);
giowild 2:6c45738bba43 582 //ble.updateCharacteristicValue(m_uart_service_ptr->getRXCharacteristicHandle(), buf, deqItem->data.length);
giowild 2:6c45738bba43 583 //ble.updateCharacteristicValue(rxCharacteristic.getValueAttribute().getHandle(), buf, deqItem->data.length);
giowild 2:6c45738bba43 584 parseRedBearCmd(buf);
giowild 2:6c45738bba43 585 free(deqItem);
giowild 2:6c45738bba43 586 //}
giowild 2:6c45738bba43 587 //} else if (!isEmpty(toSendQueue)) {
giowild 2:6c45738bba43 588 } else if (triggerSensorPolling) {
giowild 2:6c45738bba43 589 triggerSensorPolling = false;
giowild 2:6c45738bba43 590 check_pin_changed();
giowild 2:6c45738bba43 591 } else {
giowild 2:6c45738bba43 592 ble.waitForEvent();
giowild 2:6c45738bba43 593 }
giowild 2:6c45738bba43 594 } else {
giowild 2:6c45738bba43 595 ble.waitForEvent();
giowild 2:6c45738bba43 596 }
giowild 2:6c45738bba43 597
giowild 2:6c45738bba43 598
giowild 0:8d3dd6e411bf 599 }
giowild 0:8d3dd6e411bf 600 }
giowild 0:8d3dd6e411bf 601
giowild 0:8d3dd6e411bf 602
giowild 0:8d3dd6e411bf 603
giowild 0:8d3dd6e411bf 604
giowild 0:8d3dd6e411bf 605
giowild 0:8d3dd6e411bf 606
giowild 0:8d3dd6e411bf 607
giowild 0:8d3dd6e411bf 608
giowild 0:8d3dd6e411bf 609
giowild 0:8d3dd6e411bf 610
giowild 0:8d3dd6e411bf 611
giowild 0:8d3dd6e411bf 612
giowild 0:8d3dd6e411bf 613
giowild 0:8d3dd6e411bf 614
giowild 0:8d3dd6e411bf 615
giowild 0:8d3dd6e411bf 616