Important changes to repositories hosted on mbed.com
Mbed hosted mercurial repositories are deprecated and are due to be permanently deleted in July 2026.
To keep a copy of this software download the repository Zip archive or clone locally using Mercurial.
It is also possible to export all your personal repositories from the account settings page.
Fork of nRF5-DK-HeartRateDemo by
main.cpp
00001 #include <events/mbed_events.h> 00002 #include <mbed.h> 00003 #include "ble/BLE.h" 00004 #include "ble/Gap.h" 00005 00006 // Uses the provided Service Classes: 00007 // (Local copies with comments are used rather than "ble/services/NAME" versions 00008 #include "DeviceInformationService.h" 00009 #include "HeartRateService.h" 00010 00011 // If debug is "true", include code to print debugging messages to the "console" 00012 #define DEBUG 1 00013 #if DEBUG 00014 #define LOG_PRINTF(...) eventQueue.call(printf, __VA_ARGS__); 00015 #else 00016 #define LOG_PRINTF(...) ; 00017 #endif 00018 00019 /*********************************************************************** 00020 I. Global Variables: 00021 This section declares "global variable" (variables that are used 00022 in multiple functions in this file) 00023 ************************************************************************/ 00024 00025 // A. A way to keep track of the heart rate service object 00026 // Declare a pointer to a heart rate service object. (This variable isn't 00027 // an actual object. It's used like Java Reference Variables --- it can refer 00028 // to a heart rate service object, but doesn't until it is initialized) 00029 // Pointers are used because the heart rate service constructor requires a BLE 00030 // object in its constructors, which isn't available when the program first starts 00031 // The Object won't exist until created with "new" ( 00032 HeartRateService *pHrs; 00033 00034 // B. A way to create new "events" 00035 /* Total size of space for eventQueue = event count * event size */ 00036 EventQueue eventQueue( 16 * 32); 00037 00038 // C. Setup the interrupt pins for any buttons 00039 InterruptIn buttons[4] = { InterruptIn(P0_13), InterruptIn(P0_14), InterruptIn(P0_15), InterruptIn(P0_16) }; 00040 00041 // D. Variable to contain the heart rate value 00042 uint8_t heartRate = 0; 00043 00044 00045 /*********************************************************************** 00046 II. Event "Call backs": 00047 This section contains functions that are called to respond to events. 00048 (Each of these is "set" as a callback somewhere in the following code too) 00049 ************************************************************************/ 00050 00051 // A. Callback for things to do when a device disconnects 00052 void bleDisconnectionCallback(const Gap::DisconnectionCallbackParams_t *params) { 00053 LOG_PRINTF(__func__); // Print the function's name 00054 00055 // Start advertising for a new connection 00056 BLE::Instance().gap().startAdvertising(); 00057 } 00058 00059 00060 // B. Callback for things to do when the BLE object is ready 00061 void bleInitComplete(BLE::InitializationCompleteCallbackContext *params) { 00062 LOG_PRINTF(__func__); // Print the function's name 00063 00064 // Get the BLE object 00065 BLE& ble = BLE::Instance(); 00066 00067 // Create the HeartRateService Object with initial value of 0 and "OTHER" location 00068 // (The object's constructor automatically adds the service) 00069 pHrs = new HeartRateService(ble, heartRate, HeartRateService::LOCATION_OTHER ); 00070 00071 // Add in a Device Information Service object too. 00072 // Argument order: "Manufacturer", "Model No", "Serial No", "Hardware Rev", "Firmware Rev", "Software Rev" 00073 new DeviceInformationService(ble, "Acme", "1A", "123", "v1.1", "r2a", "r3"); 00074 00075 // Setup the "onDisconnection()" callback 00076 // Connection info is handeled by GAP (Generic ACCESS Protocol), hence the ble.gap() part 00077 ble.gap().onDisconnection(bleDisconnectionCallback); 00078 00079 00080 // Setup advertising: Build the "payload" 00081 // Add in the mode (discoverable / low energy only) 00082 ble.gap().accumulateAdvertisingPayload(GapAdvertisingData::BREDR_NOT_SUPPORTED | GapAdvertisingData::LE_GENERAL_DISCOVERABLE); 00083 // Include a list of services in the advertising packet 00084 uint16_t uuid16_list[] = {GattService::UUID_HEART_RATE_SERVICE}; 00085 ble.gap().accumulateAdvertisingPayload(GapAdvertisingData::COMPLETE_LIST_16BIT_SERVICE_IDS, (uint8_t *) uuid16_list, sizeof(uuid16_list)); 00086 00087 // Include the device name in the advertising packet 00088 char DEVICE_NAME[] = "HRM"; 00089 ble.gap().accumulateAdvertisingPayload(GapAdvertisingData::COMPLETE_LOCAL_NAME, (uint8_t *) DEVICE_NAME, sizeof(DEVICE_NAME)); 00090 // Add the fact that it's "connectable" to the advertising packet (and that its not directed to a specific device) 00091 ble.gap().setAdvertisingType(GapAdvertisingParams::ADV_CONNECTABLE_UNDIRECTED); 00092 // Wait 1S between advertising packets. Shorter will lead to faster connections but more power consumption 00093 // Longer will usually lead to slower times-to-connect, but lower power consumption 00094 ble.gap().setAdvertisingInterval(1000); /* 1000ms */ 00095 00096 // Also set the device name in the GAP level 00097 ble.setDeviceName((uint8_t*)DEVICE_NAME); // Set the "GAP Name" too. 00098 00099 // Start advertising 00100 ble.gap().startAdvertising(); 00101 } 00102 00103 void buttonsPress() { 00104 LOG_PRINTF(__func__); // Print the function's name 00105 // Display the buttons that are pressed 00106 00107 // Do NOT use printf() in callbacks. Put all printing on tasks handled by the event queue. 00108 // (This uses the debug macro provided to call printf() with arguments) 00109 for(int i=0;i<sizeof(buttons)/sizeof(InterruptIn);i++) { 00110 if(buttons[i].read()==0) 00111 LOG_PRINTF("\t%d down\r\n",i+1); 00112 } 00113 if(buttons[0].read()==0) { 00114 heartRate++; 00115 pHrs->updateHeartRate(heartRate); 00116 } else 00117 if(buttons[1].read()==0) { 00118 heartRate--; 00119 pHrs->updateHeartRate(heartRate); 00120 } 00121 } 00122 00123 // C. Callback to respond to BLE events. This will add a function call to the 00124 // Event Queue to process the event. 00125 void scheduleBleEventsProcessing(BLE::OnEventsToProcessCallbackContext* context) { 00126 BLE &ble = BLE::Instance(); 00127 eventQueue.call(Callback<void()>(&ble, &BLE::processEvents)); 00128 } 00129 00130 /*********************************************************************** 00131 III. main() thread 00132 This section will run initially and configure/start everything else. 00133 ************************************************************************/ 00134 00135 00136 int main() { 00137 LOG_PRINTF(__func__); // Print the function's name 00138 // Configure the buttons. 00139 for(int i=0;i<sizeof(buttons)/sizeof(InterruptIn); i++) { 00140 // Pull the button voltages "up" to 3v by default 00141 buttons[i].mode(PullUp); 00142 // Callback for when the button falls to a 0 (when the button is pressed) 00143 buttons[i].fall(&buttonsPress); 00144 } 00145 00146 // Get access to the BLE object 00147 BLE &ble = BLE::Instance(); 00148 // Set the BLE object to use the event queue to process any BLE events 00149 // (So when a BLE event occurs, a function to respond to it will be placed in the event queue) 00150 ble.onEventsToProcess(scheduleBleEventsProcessing); 00151 00152 // Initialize the BLE object 00153 ble.init(bleInitComplete); 00154 00155 // Let the "event queue" take over 00156 eventQueue.dispatch_forever(); 00157 00158 return 0; 00159 }
Generated on Wed Jul 13 2022 09:59:17 by
1.7.2
