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.
Dependencies: BLE_API mbed nRF51822
Revision 1:2e474d4e7092, committed 2016-10-17
- Comitter:
- javiervelasco
- Date:
- Mon Oct 17 07:41:30 2016 +0000
- Branch:
- INTELLIGENT_LUMEN_BEACON
- Parent:
- 0:720b1ee20d33
- Commit message:
- First release
Changed in this revision
| BLE_API.lib | Show annotated file Show diff for this revision Revisions of this file |
| main.cpp | Show annotated file Show diff for this revision Revisions of this file |
--- a/BLE_API.lib Thu Sep 15 14:43:08 2016 +0000 +++ b/BLE_API.lib Mon Oct 17 07:41:30 2016 +0000 @@ -1,1 +1,1 @@ -http://mbed.org/teams/Bluetooth-Low-Energy/code/BLE_API/#65474dc93927 +https://developer.mbed.org/users/javiervelasco/code/BLE_API/#1cdc132601a3
--- a/main.cpp Thu Sep 15 14:43:08 2016 +0000
+++ b/main.cpp Mon Oct 17 07:41:30 2016 +0000
@@ -15,48 +15,217 @@
*/
#include "mbed.h"
+#include <string.h>
+#include <stddef.h>
+#include <Serial.h>
#include "ble/services/iBeacon.h"
#include "ble/services/UARTService.h"
+#include "ble/services/DFUService.h"
+#include "nrf.h"
+#include "nrf_sdm.h"
+extern "C" {
+ #include "pstorage.h"
+}
+#include "nrf_error.h"
+
+#define _DEBUG
+
BLE ble;
-
-void bleInitComplete(BLE::InitializationCompleteCallbackContext *params)
-{
- BLE &ble = params->ble;
- ble_error_t error = params->error;
+UARTService *uarts;
+DFUService *dfus;
+iBeacon *ibeacon;
+pstorage_handle_t pstorageHandle;
+#ifdef _DEBUG
+Serial pc(USBTX, USBRX);
+#endif
+Ticker ticker;
- if (error != BLE_ERROR_NONE) {
- return;
+// Struct to hold persistent data across power cycles
+typedef struct PersistentData_t {
+ char name[32];
+ uint16_t majorNumber;
+ uint16_t minorNumber;
+ uint16_t txPower;
+} __attribute__ ((aligned (4)));
+PersistentData_t persistentData;
+static const int PERSISTENT_DATA_ALIGNED_SIZE = sizeof(PersistentData_t);
+
+/* Dummy callback handler needed by Nordic's pstorage module. */
+void pstorageNotificationCallback(
+ pstorage_handle_t *p_handle,
+ uint8_t op_code,
+ uint32_t result,
+ uint8_t * p_data,
+ uint32_t data_len){
+ /* APP_ERROR_CHECK(result); */
+}
+
+void pstorageLoad(){
+ if (pstorage_init()!=NRF_SUCCESS) {
}
- /**
- * The Beacon payload has the following composition:
- * 128-Bit / 16byte UUID = E2 0A 39 F4 73 F5 4B C4 A1 2F 17 D1 AD 07 A9 61
- * Major/Minor = 0x1122 / 0x3344
- * Tx Power = 0xC8 = 200, 2's compliment is 256-200 = (-56dB)
- *
- * Note: please remember to calibrate your beacons TX Power for more accurate results.
- */
- const uint8_t uuid[] = {0xE2, 0x0A, 0x39, 0xF4, 0x73, 0xF5, 0x4B, 0xC4,
- 0xA1, 0x2F, 0x17, 0xD1, 0xAD, 0x07, 0xA9, 0x61};
- uint16_t majorNumber = 1122;
- uint16_t minorNumber = 3344;
- uint16_t txPower = 0x40;
- iBeacon *ibeacon = new iBeacon(ble, uuid, majorNumber, minorNumber, txPower);
+ pstorage_module_param_t pstorageParams = {
+ .cb = pstorageNotificationCallback,
+ .block_size = PERSISTENT_DATA_ALIGNED_SIZE,
+ .block_count = 1
+ };
+ pstorage_register(&pstorageParams, &pstorageHandle);
+ if (pstorage_load(
+ reinterpret_cast<uint8_t *>(&persistentData),
+ &pstorageHandle, PERSISTENT_DATA_ALIGNED_SIZE, 0
+ ) != NRF_SUCCESS) {
+ // On failure zero out and let the service reset to defaults
+ sprintf(persistentData.name,"INTELLIGENTLUMEN");
+ persistentData.majorNumber=1234;
+ persistentData.minorNumber=5678;
+ persistentData.txPower=54;
+ }
+}
+
+
+
+void pstorageSave() {
+ pstorage_store(
+ &pstorageHandle,
+ reinterpret_cast<uint8_t *>(&persistentData),
+ sizeof(PersistentData_t),
+ 0 /* offset */
+ );
+ wait(2);
+}
+
+
- ble.gap().setAdvertisingInterval(1000); /* 1000ms. */
- ble.gap().startAdvertising();
+/* BLE UART data received callback */
+void onDataWritten(const GattWriteCallbackParams *params)
+{
+ char *bp = (char*)params->data;
+ bp[params->len]=0; //Fix string end with zero.
+ #ifdef _DEBUG
+ pc.printf("%s\r\n",bp);
+ #endif
+ char *token;
+ token = strtok(bp," ,");
+ if (token!=NULL) {
+ #ifdef _DEBUG
+ pc.printf("Recv: %s\r\n",token);
+ #endif
+ if (strcmp(token,"name")==0) {
+ token = strtok(NULL," ,");
+ if (token==NULL) {
+ #ifdef _DEBUG
+ pc.printf("Cfg error: invalid name \r\n");
+ #endif
+ return;
+ }
+ sprintf((char *)persistentData.name,"%s",token);
+ } else if (strcmp(token,"major")==0) {
+ token = strtok(NULL," ,");
+ if (token==NULL) {
+ #ifdef _DEBUG
+ pc.printf("Cfg error: invalid majorNumber \r\n");
+ #endif
+ return;
+ }
+ persistentData.majorNumber=atoi(token);
+ } else if (strcmp(token,"minor")==0) {
+ token = strtok(NULL," ,");
+ if (token==NULL) {
+ #ifdef _DEBUG
+ pc.printf("Cfg error: invalid minorNumber \r\n");
+ #endif
+ return;
+ }
+ persistentData.minorNumber=atoi(token);
+ } else if (strcmp(token,"rssi")==0) {
+ token = strtok(NULL," ,");
+ if (token==NULL) {
+ #ifdef _DEBUG
+ pc.printf("Cfg error: invalid txPower \r\n");
+ #endif
+ return;
+ }
+ persistentData.txPower=atoi(token);
+ #ifdef _DEBUG
+ pc.printf("Cfg txPower:%i\r\n",persistentData.txPower);
+ #endif
+ } else if (strcmp(token,"save")==0) {
+ pstorageSave();
+ #ifdef _DEBUG
+ pc.printf("Config name:%s major:%i minor:%i tx:%i\r\n",persistentData.name,persistentData.majorNumber,persistentData.minorNumber,persistentData.txPower);
+ #endif
+ NVIC_SystemReset();
+ } else if (strcmp(token,"dfu")==0) {
+ sd_power_gpregret_set(BOOTLOADER_DFU_START);
+ sd_softdevice_disable();
+ sd_softdevice_vector_table_base_set(NRF_UICR->BOOTLOADERADDR);
+ NVIC_SystemReset();
+ }
+ }
}
+
+
+void connectionCallback(const Gap::ConnectionCallbackParams_t *params)
+{
+ #ifdef _DEBUG
+ pc.printf("Connected!\n");
+ #endif
+}
+
+void disconnectionCallback(const Gap::DisconnectionCallbackParams_t *cbParams)
+{
+ #ifdef _DEBUG
+ pc.printf("Disconnected!\n");
+ pc.printf("Restarting the advertising process\n");
+ #endif
+ ble.startAdvertising();
+}
+
+
int main(void)
{
- ble.init(bleInitComplete);
+ const uint8_t uuid[] = {0xE2, 0x0A, 0x39, 0xF4, 0x73, 0xF5, 0x4B, 0xC4,
+ 0xA1, 0x2F, 0x17, 0xD1, 0xAD, 0x07, 0xA9, 0x61};
+ #ifdef _DEBUG
+ pc.baud(9600);
+ pc.printf("INTELLIGENT LUMEN BEACON DFU v1.1\r\n");
+ #endif
+
+ /* Load mayor minor and txpower from storage */
+ pstorageLoad();
+ #ifdef _DEBUG
+ pc.printf("Storage size:%i\r\n",PERSISTENT_DATA_ALIGNED_SIZE);
+ pc.printf("Config name:%s mayor:%i minor:%i tx:%i\r\n",persistentData.name,persistentData.majorNumber,persistentData.minorNumber,persistentData.txPower);
+ #endif
+
+ ble.init();
+ while (!ble.hasInitialized()) { wait(0.5);/* wait for BLE initialization */ }
- /* SpinWait for initialization to complete. This is necessary because the
- * BLE object is used in the main loop below. */
- while (!ble.hasInitialized()) { /* spin loop */ }
+ ble.gap().onDisconnection(disconnectionCallback);
+ ble.gap().onConnection(connectionCallback);
+ ble.accumulateAdvertisingPayload(GapAdvertisingData::SHORTENED_LOCAL_NAME,
+ (const uint8_t*)persistentData.name, strlen((const char*)persistentData.name));
+
+ UARTService uartService(ble);
+ uarts = &uartService;
+ DFUService dfu(ble);
+ dfus = &dfu;
+ ibeacon = new iBeacon(ble, uuid, persistentData.majorNumber, persistentData.minorNumber, persistentData.txPower);
+ ble.onDataWritten(onDataWritten);
+
+ /* setup advertising */
+ ble.accumulateAdvertisingPayload(GapAdvertisingData::BREDR_NOT_SUPPORTED);
+ ble.setAdvertisingType(GapAdvertisingParams::ADV_CONNECTABLE_UNDIRECTED);
+ ble.accumulateAdvertisingPayload(GapAdvertisingData::COMPLETE_LIST_128BIT_SERVICE_IDS,
+ (const uint8_t *)UARTServiceUUID_reversed, sizeof(UARTServiceUUID_reversed));
+ ble.setAdvertisingInterval(100); /* 100ms; in multiples of 0.625ms. */
+ ble.gap().startAdvertising();
+
+
while (true) {
ble.waitForEvent(); // allows or low power operation
}