HTM Demo of BLE with Microbit

Dependencies:   microbit

Embed: (wiki syntax)

« Back to documentation index

Show/hide line numbers main.cpp Source File

main.cpp

00001 /*
00002 The MIT License (MIT)
00003 
00004 Copyright (c) 2016 British Broadcasting Corporation.
00005 This software is provided by Lancaster University by arrangement with the BBC.
00006 
00007 Permission is hereby granted, free of charge, to any person obtaining a
00008 copy of this software and associated documentation files (the "Software"),
00009 to deal in the Software without restriction, including without limitation
00010 the rights to use, copy, modify, merge, publish, distribute, sublicense,
00011 and/or sell copies of the Software, and to permit persons to whom the
00012 Software is furnished to do so, subject to the following conditions:
00013 
00014 The above copyright notice and this permission notice shall be included in
00015 all copies or substantial portions of the Software.
00016 
00017 THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
00018 IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
00019 FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
00020 THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
00021 LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
00022 FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
00023 DEALINGS IN THE SOFTWARE.
00024 */
00025 
00026 #include "MicroBit.h"
00027 
00028 const static char  DEVICE_NAME[] = "MY_MICROBIT";
00029 static volatile bool  triggerSensorPolling = false;
00030 
00031 MicroBit uBit;
00032 Ticker ticker;
00033 Serial  pc(USBTX, USBRX);
00034 
00035 bool isConnect = false;
00036 
00037 /* Health Thermometer Service */ 
00038 float temperature = 25.0;
00039 uint8_t             thermTempPayload[5] = { 0, 0, 0, 0, 0 };
00040 
00041 GattCharacteristic  tempChar (GattCharacteristic::UUID_TEMPERATURE_MEASUREMENT_CHAR,
00042                                 thermTempPayload, 5, 5,
00043                                 GattCharacteristic::BLE_GATT_CHAR_PROPERTIES_INDICATE);
00044 
00045 /* Battery Level Service */
00046 uint8_t            batt = 100;     /* Battery level */
00047 GattCharacteristic battLevel ( GattCharacteristic::UUID_BATTERY_LEVEL_CHAR, 
00048                                  (uint8_t *)batt, 1, 1,
00049                                  GattCharacteristic::BLE_GATT_CHAR_PROPERTIES_NOTIFY | GattCharacteristic::BLE_GATT_CHAR_PROPERTIES_READ);
00050 
00051 GattCharacteristic *htmChars[] = {&tempChar, };
00052 GattCharacteristic *battChars[] = {&battLevel, };
00053 
00054 GattService        htmService(GattService::UUID_HEALTH_THERMOMETER_SERVICE, htmChars, 
00055                                 sizeof(htmChars) / sizeof(GattCharacteristic *));
00056 GattService        battService(GattService::UUID_BATTERY_SERVICE, battChars,
00057                                 sizeof(battChars) / sizeof(GattCharacteristic *));
00058 uint16_t             uuid16_list[] = {GattService::UUID_HEALTH_THERMOMETER_SERVICE,
00059                                       GattService::UUID_BATTERY_SERVICE};
00060 
00061 static Gap::ConnectionParams_t connectionParams;
00062 
00063 uint32_t quick_ieee11073_from_float(float temperature);
00064 void updateServiceValues(void);
00065 
00066 void onConnectionCallback(const Gap::ConnectionCallbackParams_t *params)
00067 {
00068     isConnect = true;
00069     pc.printf("connected. Got handle %u\r\n", params->handle);
00070 
00071     connectionParams.slaveLatency = 1;
00072     if (uBit.ble->gap().updateConnectionParams(params->handle, &connectionParams) != BLE_ERROR_NONE) {
00073         pc.printf("failed to update connection paramter\r\n");
00074     }
00075 }
00076 
00077 void disconnectionCallback(const Gap::DisconnectionCallbackParams_t *params)
00078 {
00079     isConnect = false;
00080     pc.printf("Disconnected handle %u, reason %u\r\n", params->handle, params->reason);
00081     pc.printf("Restarting the advertising process\r\n");
00082 
00083     pc.printf("Start Advertising\r\n");
00084     uBit.ble->gap().startAdvertising();
00085 }
00086 
00087 void periodicCallback(void)
00088 {
00089     triggerSensorPolling = true;
00090 }
00091 
00092 int main()
00093 {
00094     // Initialise the micro:bit runtime.
00095     pc.printf("Initialising MicroBit\r\n");
00096     uBit.ble = new BLEDevice();
00097     uBit.init();    
00098     uBit.ble->init();
00099     pc.printf("Init done\r\n");
00100 
00101     uBit.ble->gap().onConnection(onConnectionCallback);
00102     uBit.ble->gap().onDisconnection(disconnectionCallback);
00103 
00104     /* setup advertising */
00105     uBit.ble->gap().accumulateAdvertisingPayload(GapAdvertisingData::BREDR_NOT_SUPPORTED | GapAdvertisingData::LE_GENERAL_DISCOVERABLE);
00106     uBit.ble->gap().accumulateAdvertisingPayload(GapAdvertisingData::COMPLETE_LIST_16BIT_SERVICE_IDS, (uint8_t*)uuid16_list, sizeof(uuid16_list));
00107     uBit.ble->gap().accumulateAdvertisingPayload(GapAdvertisingData::GENERIC_THERMOMETER);
00108     uBit.ble->accumulateAdvertisingPayload(GapAdvertisingData::COMPLETE_LOCAL_NAME, (uint8_t *)DEVICE_NAME, sizeof(DEVICE_NAME));
00109     uBit.ble->gap().setAdvertisingType(GapAdvertisingParams::ADV_CONNECTABLE_UNDIRECTED);
00110     uBit.ble->setAdvertisingInterval(160); /* 100ms; in multiples of 0.625ms. */
00111     uBit.ble->startAdvertising();
00112     pc.printf("Start Advertising\r\n");
00113     
00114     uBit.ble->gattServer().addService(htmService);
00115     uBit.ble->gattServer().addService(battService);
00116     pc.printf("Add Service\r\n");
00117     
00118     ticker.attach(periodicCallback, 1);
00119 
00120     // Insert your code here!
00121     while(1)
00122     {
00123         if(isConnect)
00124         {
00125             uBit.display.printChar('C');
00126         }
00127         else
00128         {
00129             uBit.display.printChar('A');            
00130         }   
00131         
00132         //uBit.display.scroll("ADV");
00133         if (triggerSensorPolling) {
00134             triggerSensorPolling = false;
00135             updateServiceValues();
00136         } else {
00137             uBit.ble->waitForEvent();
00138         }
00139     }
00140     
00141     // If main exits, there may still be other fibers running or registered event handlers etc.
00142     // Simply release this fiber, which will mean we enter the scheduler. Worse case, we then
00143     // sit in the idle task forever, in a power efficient sleep.
00144     //release_fiber();
00145 }
00146 
00147 /**************************************************************************/
00148 /*!
00149     @brief  Ticker callback to switch advertisingStateLed state
00150 */
00151 /**************************************************************************/
00152 void updateServiceValues(void)
00153 {
00154     // Decrement the battery level.
00155     batt <=50 ? batt=100 : batt--;
00156     pc.printf("Batt is %u\r\n", batt);
00157     
00158     /* Update the temperature. Note that we need to convert to an ieee11073 format float. */
00159     temperature >= 30.0 ? temperature = 20.0 : temperature+=0.2;
00160     pc.printf("temp:%f\r\n", temperature);
00161     uint32_t temp_ieee11073 = quick_ieee11073_from_float(temperature);
00162     memcpy(thermTempPayload+1, &temp_ieee11073, 4);
00163     uBit.ble->gattServer().write(tempChar.getValueAttribute().getHandle(), thermTempPayload, sizeof(thermTempPayload));  //Mod
00164     uBit.ble->gattServer().write(battLevel.getValueAttribute().getHandle(), (uint8_t *)&batt, sizeof(batt));             //Mod
00165 }
00166 
00167 /**
00168  * @brief A very quick conversion between a float temperature and 11073-20601 FLOAT-Type.
00169  * @param temperature The temperature as a float.
00170  * @return The temperature in 11073-20601 FLOAT-Type format.
00171  */
00172 uint32_t quick_ieee11073_from_float(float temperature)
00173 {
00174     uint8_t  exponent = 0xFF; //exponent is -1
00175     uint32_t mantissa = (uint32_t)(temperature*10);
00176     
00177     return ( ((uint32_t)exponent) << 24) | mantissa;
00178 }