Merck / Mbed OS SmartCap_OS5

Dependencies:   nRF51822

Committer:
sgetz7908
Date:
Tue Jul 30 19:57:19 2019 +0000
Revision:
32:749e1c060d03
Parent:
30:76b51e525c40
Child:
34:c122d842ad9a
Changed EOL_MAX_USES to 120.; Fixed issue that when the connect inactivity timeout was exceeded, it would lockup.;

Who changed what in which revision?

UserRevisionLine numberNew contents of line
sgetz7908 23:7ca590427f0e 1
sgetz7908 23:7ca590427f0e 2 /// @file BLE_Stuff.cpp
sgetz7908 23:7ca590427f0e 3 #include <events/mbed_events.h>
sgetz7908 23:7ca590427f0e 4 #include <mbed.h>
sgetz7908 23:7ca590427f0e 5 #include "ble/BLE.h"
sgetz7908 23:7ca590427f0e 6 #include "ble/Gap.h"
sgetz7908 23:7ca590427f0e 7 #include "ble/services/UARTService.h"
sgetz7908 23:7ca590427f0e 8
sgetz7908 23:7ca590427f0e 9 #include "BLE_Stuff.h"
sgetz7908 23:7ca590427f0e 10 #include "infoService.h"
sgetz7908 23:7ca590427f0e 11 #include "hw.h"
sgetz7908 23:7ca590427f0e 12 #include "log.h"
sgetz7908 23:7ca590427f0e 13 #include "main.h"
sgetz7908 23:7ca590427f0e 14 #include "log.h"
sgetz7908 23:7ca590427f0e 15 #include "nrf_soc.h"
sgetz7908 23:7ca590427f0e 16
sgetz7908 23:7ca590427f0e 17 extern EventQueue eventQueue; //(/* event count */ 16 * EVENTS_EVENT_SIZE);
sgetz7908 23:7ca590427f0e 18 UARTService *uartServicePtr = NULL;
sgetz7908 23:7ca590427f0e 19
sgetz7908 32:749e1c060d03 20 int timeout_id = 0;
sgetz7908 23:7ca590427f0e 21
sgetz7908 23:7ca590427f0e 22 int adv_timeout_ID = 0;
sgetz7908 23:7ca590427f0e 23
sgetz7908 23:7ca590427f0e 24 int adv_state = false;
sgetz7908 23:7ca590427f0e 25 char dev_name[15] = "";
sgetz7908 23:7ca590427f0e 26
sgetz7908 23:7ca590427f0e 27 volatile int batt_voltage = 0; // actual battery voltage * 100
sgetz7908 23:7ca590427f0e 28
sgetz7908 23:7ca590427f0e 29 bool m_isConnected = false;
sgetz7908 23:7ca590427f0e 30
sgetz7908 23:7ca590427f0e 31 void process_cmd(char * cmd);
sgetz7908 23:7ca590427f0e 32
sgetz7908 32:749e1c060d03 33 void cancel_ble_activity_timeout(void)
sgetz7908 32:749e1c060d03 34 {
sgetz7908 32:749e1c060d03 35 if(timeout_id) { eventQueue.cancel(timeout_id); timeout_id = 0; }
sgetz7908 32:749e1c060d03 36 }
sgetz7908 23:7ca590427f0e 37
sgetz7908 23:7ca590427f0e 38 void disconnect(void)
sgetz7908 23:7ca590427f0e 39 {
sgetz7908 32:749e1c060d03 40 cancel_ble_activity_timeout();
sgetz7908 23:7ca590427f0e 41 #if UART_DEBUGGING==0
sgetz7908 23:7ca590427f0e 42 BLE &ble = BLE::Instance();
sgetz7908 32:749e1c060d03 43 ble.gap().disconnect(Gap::CONNECTION_TIMEOUT ); // force disconnect
sgetz7908 23:7ca590427f0e 44 #endif
sgetz7908 23:7ca590427f0e 45 }
sgetz7908 23:7ca590427f0e 46
sgetz7908 32:749e1c060d03 47 void dis(void)
sgetz7908 23:7ca590427f0e 48 {
sgetz7908 32:749e1c060d03 49 disconnect();
sgetz7908 23:7ca590427f0e 50 }
sgetz7908 23:7ca590427f0e 51
sgetz7908 32:749e1c060d03 52 void ble_activity_timeout(void)
sgetz7908 32:749e1c060d03 53 {
sgetz7908 32:749e1c060d03 54 eventQueue.call(dis);
sgetz7908 32:749e1c060d03 55 }
sgetz7908 32:749e1c060d03 56
sgetz7908 32:749e1c060d03 57 void reset_ble_activity_timer(void)
sgetz7908 32:749e1c060d03 58 {
sgetz7908 32:749e1c060d03 59 cancel_ble_activity_timeout();
sgetz7908 32:749e1c060d03 60 timeout_id = eventQueue.call_in(BLE_INACTIVITY_TIMEOUT*1000UL, ble_activity_timeout);
sgetz7908 32:749e1c060d03 61 }
sgetz7908 32:749e1c060d03 62
sgetz7908 32:749e1c060d03 63 void disconnect_happened()
sgetz7908 23:7ca590427f0e 64 {
sgetz7908 23:7ca590427f0e 65 m_isConnected = false;
sgetz7908 32:749e1c060d03 66 cancel_ble_activity_timeout();
sgetz7908 23:7ca590427f0e 67 BLE &ble = BLE::Instance();
sgetz7908 23:7ca590427f0e 68 ble.gap().setAdvertisingInterval(ADV_INTERVAL);
sgetz7908 23:7ca590427f0e 69 if(adv_state) ble.gap().startAdvertising();
sgetz7908 23:7ca590427f0e 70 }
sgetz7908 32:749e1c060d03 71
sgetz7908 32:749e1c060d03 72 /// Called when the Bluetooth connection is disconnected.
sgetz7908 32:749e1c060d03 73 void disconnectionCallback(const Gap::DisconnectionCallbackParams_t *params)
sgetz7908 32:749e1c060d03 74 {
sgetz7908 32:749e1c060d03 75 eventQueue.call(disconnect_happened);
sgetz7908 32:749e1c060d03 76 }
sgetz7908 23:7ca590427f0e 77
sgetz7908 32:749e1c060d03 78 void connect_happened(void)
sgetz7908 23:7ca590427f0e 79 {
sgetz7908 23:7ca590427f0e 80 m_isConnected = true;
sgetz7908 23:7ca590427f0e 81 BLE &ble = BLE::Instance();
sgetz7908 23:7ca590427f0e 82 ble.gap().setAdvertisingInterval(CONN_INTERVAL);
sgetz7908 32:749e1c060d03 83 reset_ble_activity_timer();
sgetz7908 32:749e1c060d03 84 }
sgetz7908 32:749e1c060d03 85
sgetz7908 32:749e1c060d03 86 void connectionCallback(const Gap::ConnectionCallbackParams_t *params)
sgetz7908 32:749e1c060d03 87 {
sgetz7908 32:749e1c060d03 88 eventQueue.call(connect_happened);
sgetz7908 23:7ca590427f0e 89 }
sgetz7908 23:7ca590427f0e 90
sgetz7908 23:7ca590427f0e 91 bool isConnected(void)
sgetz7908 23:7ca590427f0e 92 {
sgetz7908 23:7ca590427f0e 93 return m_isConnected;
sgetz7908 23:7ca590427f0e 94 }
sgetz7908 23:7ca590427f0e 95
sgetz7908 23:7ca590427f0e 96 /// Called to write a string to the Bluetooth UART.
sgetz7908 23:7ca590427f0e 97 // used for writting to the BLE UART
sgetz7908 23:7ca590427f0e 98 void BLE_UART_xmit(const char * str)
sgetz7908 23:7ca590427f0e 99 {
sgetz7908 23:7ca590427f0e 100 if (uartServicePtr != NULL) {
sgetz7908 23:7ca590427f0e 101 uartServicePtr->writeString(str);
sgetz7908 23:7ca590427f0e 102 }
sgetz7908 23:7ca590427f0e 103 }
sgetz7908 23:7ca590427f0e 104
sgetz7908 23:7ca590427f0e 105 void BLE_UART_xmit(int i)
sgetz7908 23:7ca590427f0e 106 {
sgetz7908 23:7ca590427f0e 107 BLE_UART_xmit(uli2a(i));
sgetz7908 23:7ca590427f0e 108 }
sgetz7908 23:7ca590427f0e 109
sgetz7908 23:7ca590427f0e 110 char cmd_str[21];
sgetz7908 23:7ca590427f0e 111
sgetz7908 23:7ca590427f0e 112 /// Called when data is rcv'd from connected BLE device
sgetz7908 23:7ca590427f0e 113 void onDataWritten(const GattWriteCallbackParams *params)
sgetz7908 23:7ca590427f0e 114 {
sgetz7908 23:7ca590427f0e 115 if ((uartServicePtr != NULL) && (params->handle == uartServicePtr->getTXCharacteristicHandle())) {
sgetz7908 23:7ca590427f0e 116 uint16_t bytesRead = params->len;
sgetz7908 23:7ca590427f0e 117 strncpy(cmd_str, (const char *)params->data, bytesRead);
sgetz7908 24:761c30334cf4 118 cmd_str[bytesRead] = 0; // add end of string char
sgetz7908 23:7ca590427f0e 119
sgetz7908 23:7ca590427f0e 120 // Start process: process_cmd(cmd_str) as regular non-irq routine
sgetz7908 23:7ca590427f0e 121 eventQueue.call(process_cmd, cmd_str);
sgetz7908 23:7ca590427f0e 122 // the dispatch method executes events
sgetz7908 23:7ca590427f0e 123 //queue.dispatch();
sgetz7908 23:7ca590427f0e 124
sgetz7908 23:7ca590427f0e 125 //ble.updateCharacteristicValue(uartServicePtr->getRXCharacteristicHandle(), params->data, bytesRead); // send back whatever is sent to us
sgetz7908 32:749e1c060d03 126 eventQueue.call(reset_ble_activity_timer);
sgetz7908 32:749e1c060d03 127 //reset_ble_activity_timer();
sgetz7908 23:7ca590427f0e 128 }
sgetz7908 23:7ca590427f0e 129 }
sgetz7908 23:7ca590427f0e 130
sgetz7908 27:bb7247a1704e 131
sgetz7908 27:bb7247a1704e 132 /// Called when data is rcv'd from connected BLE device
sgetz7908 27:bb7247a1704e 133 void dataReadCallback(const GattReadCallbackParams *params)
sgetz7908 27:bb7247a1704e 134 {
sgetz7908 27:bb7247a1704e 135 //if ((uartServicePtr != NULL) && (params->handle == uartServicePtr->getRXCharacteristicHandle())) {
sgetz7908 27:bb7247a1704e 136 // Start process: process as regular non-irq routine
sgetz7908 27:bb7247a1704e 137 eventQueue.call(dataWasRead);
sgetz7908 27:bb7247a1704e 138 //}
sgetz7908 27:bb7247a1704e 139 }
sgetz7908 27:bb7247a1704e 140
sgetz7908 27:bb7247a1704e 141
sgetz7908 23:7ca590427f0e 142 /// Turn on or off advertising
sgetz7908 23:7ca590427f0e 143 // When turned on, it will only advertise for a limited time, or until turned off.
sgetz7908 23:7ca590427f0e 144 void set_radio(int state)
sgetz7908 23:7ca590427f0e 145 {
sgetz7908 23:7ca590427f0e 146 BLE &ble = BLE::Instance();
sgetz7908 23:7ca590427f0e 147 adv_state = state;
sgetz7908 23:7ca590427f0e 148
sgetz7908 23:7ca590427f0e 149 if(state) {
sgetz7908 24:761c30334cf4 150 //adv_state = true;
sgetz7908 23:7ca590427f0e 151 ble.gap().setAdvertisingInterval(ADV_INTERVAL);
sgetz7908 23:7ca590427f0e 152 ble.gap().startAdvertising();
sgetz7908 23:7ca590427f0e 153 } else {
sgetz7908 24:761c30334cf4 154 //adv_state = false;
sgetz7908 23:7ca590427f0e 155 ble.gap().stopAdvertising();
sgetz7908 23:7ca590427f0e 156 disconnect();
sgetz7908 23:7ca590427f0e 157 }
sgetz7908 23:7ca590427f0e 158 }
sgetz7908 23:7ca590427f0e 159
sgetz7908 23:7ca590427f0e 160 #if 0
sgetz7908 23:7ca590427f0e 161 void stop_radio_and_wait(void)
sgetz7908 23:7ca590427f0e 162 {
sgetz7908 23:7ca590427f0e 163 set_radio(false);
sgetz7908 23:7ca590427f0e 164
sgetz7908 23:7ca590427f0e 165 // If radio is active, wait for it to become inactive.
sgetz7908 23:7ca590427f0e 166 //wait(0.5);
sgetz7908 23:7ca590427f0e 167 while (isConnected())// || isRadioActive())
sgetz7908 23:7ca590427f0e 168 {
sgetz7908 23:7ca590427f0e 169 // Do nothing (just wait for radio to become inactive).
sgetz7908 23:7ca590427f0e 170 sd_app_evt_wait();
sgetz7908 23:7ca590427f0e 171 }
sgetz7908 23:7ca590427f0e 172 }
sgetz7908 23:7ca590427f0e 173 #endif
sgetz7908 23:7ca590427f0e 174
sgetz7908 27:bb7247a1704e 175 void authorize_client_write(GattWriteAuthCallbackParams *e)
sgetz7908 27:bb7247a1704e 176 {
sgetz7908 27:bb7247a1704e 177 e->authorizationReply = AUTH_CALLBACK_REPLY_SUCCESS;
sgetz7908 27:bb7247a1704e 178 }
sgetz7908 27:bb7247a1704e 179
sgetz7908 23:7ca590427f0e 180 ble_init_status_t ble_init_status = BLE_INIT_IN_PROGRESS;
sgetz7908 23:7ca590427f0e 181
sgetz7908 23:7ca590427f0e 182 /// Called to setup the Bluetooth link.
sgetz7908 23:7ca590427f0e 183 void bleInitComplete(BLE::InitializationCompleteCallbackContext *params)
sgetz7908 23:7ca590427f0e 184 {
sgetz7908 23:7ca590427f0e 185 BLE& ble = params->ble;
sgetz7908 23:7ca590427f0e 186 ble_error_t error = params->error;
sgetz7908 23:7ca590427f0e 187
sgetz7908 23:7ca590427f0e 188 if (error != BLE_ERROR_NONE) {
sgetz7908 23:7ca590427f0e 189 ble_init_status = BLE_INIT_ERROR;
sgetz7908 23:7ca590427f0e 190 return;
sgetz7908 23:7ca590427f0e 191 }
sgetz7908 23:7ca590427f0e 192
sgetz7908 23:7ca590427f0e 193 /* Ensure that it is the default instance of BLE */
sgetz7908 23:7ca590427f0e 194 if(ble.getInstanceID() != BLE::DEFAULT_INSTANCE) {
sgetz7908 23:7ca590427f0e 195 return;
sgetz7908 23:7ca590427f0e 196 }
sgetz7908 23:7ca590427f0e 197
sgetz7908 23:7ca590427f0e 198 ble.gap().onDisconnection(disconnectionCallback);
sgetz7908 23:7ca590427f0e 199 ble.gap().onConnection(connectionCallback);
sgetz7908 23:7ca590427f0e 200 ble.gattServer().onDataWritten(onDataWritten);
sgetz7908 23:7ca590427f0e 201
sgetz7908 23:7ca590427f0e 202 //ble.gattServer().onDataRead( dataReadCallback ); //const DataReadCallback_t & callback)
sgetz7908 23:7ca590427f0e 203 //ble.onDataRead( dataReadCallback);
sgetz7908 23:7ca590427f0e 204
sgetz7908 23:7ca590427f0e 205 strcpy(dev_name, DEV_NAME);
sgetz7908 30:76b51e525c40 206 //strcat(dev_name, char2hex(NRF_FICR->DEVICEADDR[0] & 0xfff, 3));
sgetz7908 30:76b51e525c40 207 strcat(dev_name, char2hex(NRF_FICR->DEVICEADDR[1] | 0xc000, 4));
sgetz7908 30:76b51e525c40 208 strcat(dev_name, char2hex(NRF_FICR->DEVICEADDR[0], 8));
sgetz7908 23:7ca590427f0e 209 int len = strlen(dev_name);
sgetz7908 23:7ca590427f0e 210
sgetz7908 23:7ca590427f0e 211 ble.gap().setDeviceName((std::uint8_t *)dev_name);
sgetz7908 23:7ca590427f0e 212
sgetz7908 23:7ca590427f0e 213 /* Setup primary service */
sgetz7908 23:7ca590427f0e 214 uartServicePtr = new UARTService(ble);
sgetz7908 23:7ca590427f0e 215
sgetz7908 23:7ca590427f0e 216 /* setup advertising */
sgetz7908 23:7ca590427f0e 217 ble.gap().accumulateAdvertisingPayload(GapAdvertisingData::BREDR_NOT_SUPPORTED);
sgetz7908 23:7ca590427f0e 218 ble.gap().setAdvertisingType(GapAdvertisingParams::ADV_CONNECTABLE_UNDIRECTED);
sgetz7908 23:7ca590427f0e 219 ble.gap().accumulateAdvertisingPayload(GapAdvertisingData::SHORTENED_LOCAL_NAME,
sgetz7908 23:7ca590427f0e 220 (const uint8_t *)dev_name, len);
sgetz7908 30:76b51e525c40 221 //ble.gap().accumulateAdvertisingPayload(GapAdvertisingData::COMPLETE_LIST_128BIT_SERVICE_IDS,
sgetz7908 30:76b51e525c40 222 // (const uint8_t *)UARTServiceUUID_reversed, sizeof(UARTServiceUUID_reversed));
sgetz7908 23:7ca590427f0e 223
sgetz7908 23:7ca590427f0e 224
sgetz7908 23:7ca590427f0e 225 ble.gap().setAdvertisingInterval(ADV_INTERVAL);
sgetz7908 23:7ca590427f0e 226 ble.gap().setAdvertisingTimeout(BLE_ADVERTISING_DURATION);
sgetz7908 23:7ca590427f0e 227 ble.gap().setTxPower(-20); // -30, -20, -16, -12, -8, -4, 0, and 4 dBm
sgetz7908 23:7ca590427f0e 228
sgetz7908 23:7ca590427f0e 229 ble_init_status = BLE_INIT_OK;
sgetz7908 23:7ca590427f0e 230
sgetz7908 23:7ca590427f0e 231 set_radio(true);
sgetz7908 23:7ca590427f0e 232 }
sgetz7908 23:7ca590427f0e 233
sgetz7908 23:7ca590427f0e 234 /// Process BLE Events
sgetz7908 23:7ca590427f0e 235 void scheduleBleEventsProcessing(BLE::OnEventsToProcessCallbackContext* context) {
sgetz7908 23:7ca590427f0e 236 BLE &ble = BLE::Instance();
sgetz7908 23:7ca590427f0e 237 eventQueue.call(Callback<void()>(&ble, &BLE::processEvents));
sgetz7908 23:7ca590427f0e 238 }
sgetz7908 23:7ca590427f0e 239
sgetz7908 23:7ca590427f0e 240 /// Initialize the BLE Stack
sgetz7908 23:7ca590427f0e 241 // Returns 0 if OK
sgetz7908 23:7ca590427f0e 242 ble_init_status_t Init_BLE_Stuff(void)
sgetz7908 23:7ca590427f0e 243 {
sgetz7908 23:7ca590427f0e 244 ble_init_status = BLE_INIT_IN_PROGRESS;
sgetz7908 23:7ca590427f0e 245 BLE &ble = BLE::Instance();
sgetz7908 23:7ca590427f0e 246 ble.onEventsToProcess(scheduleBleEventsProcessing);
sgetz7908 23:7ca590427f0e 247 ble.init(bleInitComplete);
sgetz7908 23:7ca590427f0e 248
sgetz7908 23:7ca590427f0e 249 // Wait for initialization to complete. This is necessary because the
sgetz7908 23:7ca590427f0e 250 // BLE object is used after this.
sgetz7908 23:7ca590427f0e 251 while(ble_init_status == BLE_INIT_IN_PROGRESS) { wait(0.05);}
sgetz7908 23:7ca590427f0e 252 // set up BLE Information services in infoService.cpp
sgetz7908 23:7ca590427f0e 253 //ble.gattServer().addService(infoServicePtr);
sgetz7908 23:7ca590427f0e 254 return ble_init_status;
sgetz7908 23:7ca590427f0e 255 }