Arun Raj / Mbed OS MAXREFDES101_SOURCE

Dependencies:   max32630fthr Adafruit_FeatherOLED USBDevice

Embed: (wiki syntax)

« Back to documentation index

Show/hide line numbers BLE_ICARUS.cpp Source File

BLE_ICARUS.cpp

00001 /*******************************************************************************
00002 * Copyright (C) Maxim Integrated Products, Inc., All rights Reserved.
00003 * 
00004 * This software is protected by copyright laws of the United States and
00005 * of foreign countries. This material may also be protected by patent laws
00006 * and technology transfer regulations of the United States and of foreign
00007 * countries. This software is furnished under a license agreement and/or a
00008 * nondisclosure agreement and may only be used or reproduced in accordance
00009 * with the terms of those agreements. Dissemination of this information to
00010 * any party or parties not specified in the license agreement and/or
00011 * nondisclosure agreement is expressly prohibited.
00012 *
00013 * The above copyright notice and this permission notice shall be included
00014 * in all copies or substantial portions of the Software.
00015 *
00016 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
00017 * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
00018 * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
00019 * IN NO EVENT SHALL MAXIM INTEGRATED BE LIABLE FOR ANY CLAIM, DAMAGES
00020 * OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE,
00021 * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
00022 * OTHER DEALINGS IN THE SOFTWARE.
00023 *
00024 * Except as contained in this notice, the name of Maxim Integrated
00025 * Products, Inc. shall not be used except as stated in the Maxim Integrated
00026 * Products, Inc. Branding Policy.
00027 *
00028 * The mere transfer of this software does not imply any licenses
00029 * of trade secrets, proprietary technology, copyrights, patents,
00030 * trademarks, maskwork rights, or any other form of intellectual
00031 * property whatsoever. Maxim Integrated Products, Inc. retains all
00032 * ownership rights.
00033 *******************************************************************************
00034 */
00035 
00036 #include "BLE_ICARUS.h"
00037 
00038 #include "../../Utilities/mxm_assert.h"
00039 #include "queue.h"
00040 #include "Peripherals.h"
00041 #include "../../version.h"
00042 
00043 
00044 UUID customServiceUUID("00001523-1212-efde-1523-785feabcd123");
00045 UUID notifyCharUUID(  "00001011-1212-efde-1523-785feabcd123");
00046 UUID configRWCharUUID("00001027-1212-efde-1523-785feabcd123");
00047 
00048 const static char     DEVICE_NAME[]        = FIRMWARE_VERSION;
00049 static const uint16_t uuid16_list[]        = {0xFFFF}; //Custom UUID, FFFF is reserved for development
00050 
00051 // BLE defines
00052 #define BLE_TICKER_PERIOD   0.050           //Ticker period in order of seconds
00053 #define BLE_CONN_INT_PACKET 2               //Ticker period in order of seconds
00054 #define BLE_NOTIFY_CHAR_ARR_SIZE    20
00055 #define BLE_READWRITE_CHAR_ARR_SIZE 16
00056 #define MAX_BLE_QUEUE 128
00057 // end of BLE defines
00058 
00059 #if defined(USE_BLE_TICKER_TO_CHECK_TRANSFER)
00060 Ticker TICKER_BLE;
00061 static volatile unsigned char BLE_CAN_TRANSFER = 0;
00062 
00063 static void Ble_Can_Transfer_Toggle(){
00064     BLE_CAN_TRANSFER = true;
00065 }
00066 
00067 static inline char Ble_Can_Transfer_Check(){
00068     return BLE_CAN_TRANSFER;
00069 }
00070 
00071 static inline void Ble_Can_Transfer_Set(unsigned char en){
00072     BLE_CAN_TRANSFER = en;
00073 }
00074 
00075 #endif
00076 
00077 /* Set Up custom Characteristics */
00078 static uint8_t notifyValue[BLE_NOTIFY_CHAR_ARR_SIZE] = {0};
00079 GattCharacteristic notifyChar(notifyCharUUID, notifyValue, BLE_NOTIFY_CHAR_ARR_SIZE, BLE_NOTIFY_CHAR_ARR_SIZE, GattCharacteristic::BLE_GATT_CHAR_PROPERTIES_NOTIFY);
00080 
00081 static uint8_t configValue[BLE_READWRITE_CHAR_ARR_SIZE] = {3,0,254,37};
00082 ReadWriteArrayGattCharacteristic<uint8_t, sizeof(configValue)> writeChar(configRWCharUUID, configValue);
00083 
00084 /* Set up custom service */
00085 GattCharacteristic *characteristics[] = {&writeChar,&notifyChar};
00086 GattService        customService(customServiceUUID, characteristics, sizeof(characteristics) / sizeof(GattCharacteristic *));
00087 
00088 // Temporary Fixes to be removed
00089 volatile BLE_State bleState = BLE_STARTING;
00090 
00091 // end of Temporary Fixes to be removed
00092 
00093 // sc...
00094 struct queue_t BLEQUEUE;
00095 static uint8_t BLEOutBuffer[BLE_NOTIFY_CHAR_ARR_SIZE * MAX_BLE_QUEUE];
00096 
00097 static DSInterface *BLE_DS_INTERFACE;
00098 
00099 
00100 /*
00101  *  Handle writes to writeCharacteristic
00102  */
00103 void writeCharCallback(const GattWriteCallbackParams *params)
00104 {
00105     uint8_t data[BLE_READWRITE_CHAR_ARR_SIZE] = {0};
00106     /* Check to see what characteristic was written, by handle */
00107     printf("writeCharCallback %p\r\n", Thread::gettid());
00108     if(params->handle == writeChar.getValueHandle()) {
00109         printf("Data received: length = %d, data = 0x",params->len);
00110         for(int x=0; x < params->len; x++) {
00111             if ((BLE_DS_INTERFACE != NULL) && (params->data[x] != 0)) {
00112                 BLE_DS_INTERFACE->build_command((char)params->data[x]);
00113             }
00114             printf("%x-", params->data[x]);
00115         }
00116         printf("\n\r");
00117     }
00118     /* Update the notifyChar with the value of writeChar */
00119     BLE::Instance(BLE::DEFAULT_INSTANCE).gattServer().write(writeChar.getValueHandle(), data, BLE_READWRITE_CHAR_ARR_SIZE);
00120 }
00121 
00122 /**
00123  * This function is called when the ble initialization process has failed
00124  */
00125 void onBleInitError(BLE &ble, ble_error_t error)
00126 {
00127     printf("errro %d\r\n", __LINE__);
00128     /* Avoid compiler warnings */
00129     (void) ble;
00130     (void) error;
00131     /* Initialization error handling should go here */
00132 }
00133 
00134 /* Restart Advertising on disconnection*/
00135 void disconnectionCallback(const Gap::DisconnectionCallbackParams_t *params)
00136 {
00137     pr_debug("disconnectionCallback %p\r\n", Thread::gettid());
00138 #if defined(USE_BLE_TICKER_TO_CHECK_TRANSFER)
00139     TICKER_BLE.detach();
00140     pr_debug("detached disconnectionCallback\r\n");
00141     Ble_Can_Transfer_Set(false);
00142 #endif
00143     bleState = BLE_DISCONNECTED;
00144     BLE::Instance().gap().startAdvertising();
00145     BLE_DS_INTERFACE->ds_set_ble_status(false);
00146     queue_reset(&BLEQUEUE);
00147 }
00148 
00149 /* Connection */
00150 void connectionCallback(const Gap::ConnectionCallbackParams_t *params)
00151 {
00152     pr_err("connectionCallback %p\r\n", Thread::gettid());
00153 
00154     Gap::ConnectionParams_t newParams = {
00155         .minConnectionInterval = 6,         /**< Minimum Connection Interval in 1.25 ms units, see BLE_GAP_CP_LIMITS.*/
00156         .maxConnectionInterval = 9,         /**< Maximum Connection Interval in 1.25 ms units, see BLE_GAP_CP_LIMITS.*/
00157         .slaveLatency = 0,                  /**< Slave Latency in number of connection events, see BLE_GAP_CP_LIMITS.*/
00158         .connectionSupervisionTimeout = 600 /**< Connection Supervision Timeout in 10 ms units, see BLE_GAP_CP_LIMITS.*/
00159     };
00160 
00161     BLE::Instance().gap().updateConnectionParams(params->handle, &newParams);
00162     BLE::Instance().gap().stopAdvertising();
00163     BLE_DS_INTERFACE->ds_set_ble_status(true);
00164 #if defined(USE_BLE_TICKER_TO_CHECK_TRANSFER)
00165     TICKER_BLE.attach(&Ble_Can_Transfer_Toggle, BLE_TICKER_PERIOD);
00166     pr_debug("Attached connectionCallback\r\n");
00167 #endif
00168     //m.sensor_enable(1);
00169     bleState = BLE_CONNECTED;
00170 }
00171 
00172 /**
00173  * Callback triggered when the ble initialization process has finished
00174  */
00175 void bleInitComplete(BLE::InitializationCompleteCallbackContext *params)
00176 {
00177     int ret;
00178     BLE&        ble   = params->ble;
00179     ble_error_t error = params->error;
00180 
00181     if (error != BLE_ERROR_NONE) {
00182         printf("errro %d\r\n", __LINE__);
00183         /* In case of error, forward the error handling to onBleInitError */
00184         onBleInitError(ble, error);
00185         printf("errro %d\r\n", __LINE__);
00186         return;
00187     }
00188     /* Ensure that it is the default instance of BLE */
00189     if (ble.getInstanceID() != BLE::DEFAULT_INSTANCE) {
00190         printf("errro %d\r\n", __LINE__);
00191         return;
00192     }
00193     ble.gap().onDisconnection(disconnectionCallback);
00194     ble.gap().onConnection(connectionCallback);
00195     ble.gattServer().onDataWritten(writeCharCallback);
00196     /* Setup advertising */
00197     ble.gap().accumulateAdvertisingPayload(GapAdvertisingData::BREDR_NOT_SUPPORTED | GapAdvertisingData::LE_GENERAL_DISCOVERABLE); // BLE only, no classic BT
00198     ble.gap().setAdvertisingType(GapAdvertisingParams::ADV_CONNECTABLE_UNDIRECTED); // advertising type
00199     ble.gap().accumulateAdvertisingPayload(GapAdvertisingData::COMPLETE_LOCAL_NAME, (uint8_t *)DEVICE_NAME, sizeof(DEVICE_NAME)); // add name
00200     ble.gap().accumulateAdvertisingPayload(GapAdvertisingData::COMPLETE_LIST_16BIT_SERVICE_IDS, (uint8_t *)uuid16_list, sizeof(uuid16_list)); // UUID's broadcast in advertising packet
00201     ble.gap().accumulateAdvertisingPayload(GapAdvertisingData::GENERIC_TAG);
00202     ble.gap().setAdvertisingInterval(100); // 100ms.
00203     /* Add our custom service */
00204     ble.gattServer().addService(customService);
00205     printf("bleInitComplete\n");
00206     ble.gap().startAdvertising();
00207 
00208     ret = queue_init(&BLEQUEUE, BLEOutBuffer, BLE_NOTIFY_CHAR_ARR_SIZE, BLE_NOTIFY_CHAR_ARR_SIZE * MAX_BLE_QUEUE);
00209     if(ret != 0)
00210         printf("queue_init has failed\r\n");
00211 }
00212 
00213 int BLE_Icarus_TransferData(uint8_t data_transfer[20]){
00214     int ret;
00215     ret = BLE::Instance(BLE::DEFAULT_INSTANCE).gattServer().write(notifyChar.getValueHandle(), data_transfer, 20);
00216     return ret;
00217 }
00218 
00219 int BLE_Icarus_TransferDataFromQueue(){
00220     int ret;
00221     uint8_t data_transfer[20];
00222     unsigned char i;
00223 
00224     if (BLEQUEUE.num_item >= 1) {
00225 #if defined(USE_BLE_TICKER_TO_CHECK_TRANSFER)
00226         if(!Ble_Can_Transfer_Check())
00227             return 0;
00228 #endif
00229         for(i = 0; i < BLE_CONN_INT_PACKET; ++i){
00230             ret = dequeue(&BLEQUEUE, data_transfer);
00231             if(ret < 0)
00232                 break;
00233             pr_debug("dequeued data for tx, %d remain\r\n", BLEQUEUE.num_item);
00234             BLE::Instance(BLE::DEFAULT_INSTANCE).gattServer().write(notifyChar.getValueHandle(), data_transfer, 20);
00235         }
00236 #if defined(USE_BLE_TICKER_TO_CHECK_TRANSFER)
00237         TICKER_BLE.attach(&Ble_Can_Transfer_Toggle, BLE_TICKER_PERIOD);
00238         Ble_Can_Transfer_Set(false);
00239 #endif
00240     }
00241 
00242     return 0;
00243 }
00244 
00245 
00246 //TODO: check that function for memory safety (no overflow should occur)
00247 int BLE_Icarus_AddtoQueue(uint8_t *data_transfer, int32_t buf_size, int32_t data_size) {
00248     int ret = 0;
00249     //printf("size is: %d\r\n", size);
00250     // TODO: Append a known character to the byte array in case size is
00251     // less than 20 bytes
00252     while ((data_size % BLE_NOTIFY_CHAR_ARR_SIZE) && data_size < buf_size)
00253         data_transfer[data_size++] = 0;
00254     mxm_assert_msg(!(data_size % 20), "BLE packet size must be multiple of 20 bytes");
00255 
00256     while(data_size > 0){
00257         ret = enqueue(&BLEQUEUE, data_transfer);
00258         data_size -= BLE_NOTIFY_CHAR_ARR_SIZE;
00259         data_transfer += BLE_NOTIFY_CHAR_ARR_SIZE;
00260     }
00261 
00262     if(ret != 0)
00263         printf("BLE_Icarus_AddtoQueue has failed\r\n");
00264 
00265     return ret;
00266 }
00267 
00268 
00269 int BLE_Icarus_SetDSInterface(DSInterface *comm_obj) {
00270     BLE_DS_INTERFACE = comm_obj;
00271     return 0;
00272 }
00273 
00274 bool BLE_Icarus_Interface_Exists()
00275 {
00276     return (bleState == BLE_CONNECTED);
00277 }
00278 
00279 int BLE_ICARUS_Get_Mac_Address(char MacAdress[6]){
00280     /* Print out device MAC address to the console*/
00281     Gap::AddressType_t addr_type;
00282     Gap::Address_t address;
00283     if(BLE::Instance().gap().getAddress(&addr_type, address) != 0)
00284         return -1;
00285     for (int i = 5; i >= 0; i--){
00286         MacAdress[5-i] = address[i];
00287     }
00288     pr_info("BLE_ADV_NAME:%s", DEVICE_NAME);
00289     return 0;
00290 }