Prashant Vaibhav / Mbed 2 deprecated FileTransferExample

Dependencies:   BLE_API mbed nRF51822

Files at this revision

API Documentation at this revision

Comitter:
pvaibhav
Date:
Thu Aug 14 14:13:53 2014 +0000
Commit message:
Minimal program to demo slow throughput/callback latency

Changed in this revision

BLE_API.lib Show annotated file Show diff for this revision Revisions of this file
Configuration.h Show annotated file Show diff for this revision Revisions of this file
Logger.h Show annotated file Show diff for this revision Revisions of this file
TransferService.cpp Show annotated file Show diff for this revision Revisions of this file
TransferService.h 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
mbed.bld Show annotated file Show diff for this revision Revisions of this file
nRF51822.lib Show annotated file Show diff for this revision Revisions of this file
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/BLE_API.lib	Thu Aug 14 14:13:53 2014 +0000
@@ -0,0 +1,1 @@
+http://mbed.org/teams/Bluetooth-Low-Energy/code/BLE_API/#189ff241dae1
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/Configuration.h	Thu Aug 14 14:13:53 2014 +0000
@@ -0,0 +1,28 @@
+#ifndef _H_CONFIGURATION_H
+#define _H_CONFIGURATION_H
+
+/*
+ * Configuration.h
+ * Prashant Vaibhav, TobyRich GmbH
+ *
+ * This file defines default configuration parameters like device name, connection parameters etc.
+ */
+
+namespace Config
+{
+
+const uint8_t deviceName[] = "Transfer PRO";
+
+const int advertisingInterval   = 160; // (0.625 ms units)
+
+// default connection parameters conforming to Apple recommendations
+const int minConnectionInterval = 16; // (1.25 ms units)
+const int maxConnectionInterval = 40; // (1.25 ms units)
+const int slaveLatency          = 0;
+const int supervisionTimeout    = 500; // (10 ms units)
+
+const int blockSize = 16; // in bytes
+
+};
+
+#endif//_H_CONFIGURATION_H
\ No newline at end of file
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/Logger.h	Thu Aug 14 14:13:53 2014 +0000
@@ -0,0 +1,13 @@
+#ifndef _H_LOGGER_H
+#define _H_LOGGER_H
+
+#define NEED_CONSOLE_OUTPUT 1 /* Set this if you need debug messages on the console;
+                               * it will have an impact on code-size and power consumption. */
+
+#if NEED_CONSOLE_OUTPUT
+#define DEBUG(...) { printf(__VA_ARGS__); }
+#else
+#define DEBUG(...) /* nothing */
+#endif /* #if NEED_CONSOLE_OUTPUT */
+
+#endif//_H_LOGGER_H
\ No newline at end of file
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/TransferService.cpp	Thu Aug 14 14:13:53 2014 +0000
@@ -0,0 +1,218 @@
+#include "TransferService.h"
+#include "Logger.h"
+#include "Configuration.h"
+
+namespace Transfer
+{
+
+// Transfer base UUID: ADC710C2-xxxx-4BF5-8244-3CEAAA0F87F5
+#define transfer_UUID(x)   { 0xAD, 0xC7, 0x10, 0xC2, (((x) & 0xFF00) >> 8), ((x) & 0xFF), 0x4B, 0xF5, 0x82, 0x44, 0x3C, 0xEA, 0xAA, 0x0F, 0x87, 0xF5 }
+
+// UUID byte arrays
+static const uint8_t transferServiceUUID[]   = transfer_UUID(0xACDC);
+static const uint8_t transferFileInfoUUID[]  = transfer_UUID(0xACDF);
+static const uint8_t transferFileBlocksUUID[6][16] =
+{
+    transfer_UUID(0xACE0), 
+    transfer_UUID(0xACE1), 
+    transfer_UUID(0xACE2), 
+    transfer_UUID(0xACE3), 
+    transfer_UUID(0xACE4), 
+    transfer_UUID(0xACE5),
+};
+
+// UUID objects used to initialise Bluetooth API
+static UUID transferServiceUUID_   = UUID(transferServiceUUID);
+static UUID transferFileInfoUUID_  = UUID(transferFileInfoUUID);
+static UUID transferFileBlocksUUID_[6] =
+{
+    UUID(transferFileBlocksUUID[0]), 
+    UUID(transferFileBlocksUUID[1]), 
+    UUID(transferFileBlocksUUID[2]), 
+    UUID(transferFileBlocksUUID[3]), 
+    UUID(transferFileBlocksUUID[4]), 
+    UUID(transferFileBlocksUUID[5]), 
+};
+
+// Storage for the value of the characteristics
+struct fileInfo_t {
+    uint16_t length;
+    uint16_t crc16;
+};
+static struct fileInfo_t            fileInfo;
+struct fileBlock_t {
+    uint16_t blockNumber;
+    uint8_t data[16];
+};
+static struct fileBlock_t           fileBlocks[6]; // 6 blocks
+
+// Other things needed for operation
+static BLEDevice*                   ble;
+static Timer                        downloadTimer;
+
+static uint16_t expectingBlock = 0;
+
+static bool acceptFile = true; // additional condition whether to accept a file upload or not, currently always accept
+static bool downloadInProgress = false; // indicates if we are downloading a file from the phone
+
+static GattCharacteristic transferFileInfo(transferFileInfoUUID_,
+                                        (uint8_t*) &fileInfo,
+                                        sizeof(fileInfo),
+                                        sizeof(fileInfo),
+                                        GattCharacteristic::BLE_GATT_CHAR_PROPERTIES_WRITE
+                                        | GattCharacteristic::BLE_GATT_CHAR_PROPERTIES_NOTIFY);
+
+static uint8_t fileBlockProperties =
+        GattCharacteristic::BLE_GATT_CHAR_PROPERTIES_WRITE
+        | GattCharacteristic::BLE_GATT_CHAR_PROPERTIES_WRITE_WITHOUT_RESPONSE;
+        
+static GattCharacteristic transferFileBlocks[6] = {
+        GattCharacteristic(transferFileBlocksUUID_[0], (uint8_t*) &fileBlocks[0], sizeof(fileBlock_t), sizeof(fileBlock_t), fileBlockProperties),
+        GattCharacteristic(transferFileBlocksUUID_[1], (uint8_t*) &fileBlocks[1], sizeof(fileBlock_t), sizeof(fileBlock_t), fileBlockProperties),
+        GattCharacteristic(transferFileBlocksUUID_[2], (uint8_t*) &fileBlocks[2], sizeof(fileBlock_t), sizeof(fileBlock_t), fileBlockProperties),
+        GattCharacteristic(transferFileBlocksUUID_[3], (uint8_t*) &fileBlocks[3], sizeof(fileBlock_t), sizeof(fileBlock_t), fileBlockProperties),
+        GattCharacteristic(transferFileBlocksUUID_[4], (uint8_t*) &fileBlocks[4], sizeof(fileBlock_t), sizeof(fileBlock_t), fileBlockProperties),
+        GattCharacteristic(transferFileBlocksUUID_[5], (uint8_t*) &fileBlocks[5], sizeof(fileBlock_t), sizeof(fileBlock_t), fileBlockProperties),
+    };
+        
+static GattCharacteristic* allChars[] = 
+{ 
+    &transferFileInfo,
+    &transferFileBlocks[0], 
+    &transferFileBlocks[1], 
+    &transferFileBlocks[2], 
+    &transferFileBlocks[3], 
+    &transferFileBlocks[4], 
+    &transferFileBlocks[5],  
+};
+
+static GattService transferService(transferServiceUUID_, allChars, sizeof(allChars) / sizeof(GattCharacteristic*));
+
+void init(BLEDevice &bleDevice)
+{
+    downloadInProgress = false;
+    ble = &bleDevice;
+    ble->addService(transferService);
+    DEBUG("Added transfer service\r\n");
+}
+
+void reset()
+{
+    // reset internal state on new connection
+    downloadInProgress = false;
+}
+
+const uint8_t* getServiceUUIDp()
+{
+    return transferServiceUUID;
+}
+
+void requestBlock(uint16_t); // prototype declaration
+void sendFileInfo();
+void refuseFile();
+void sendFileDownloadedSuccessfully();
+
+void handleDataWritten(uint16_t handle)
+{
+    if (!ble)
+        return;
+        
+    int channel = expectingBlock % 6;
+
+    if (handle == transferFileInfo.getHandle()) {
+
+        uint16_t len = sizeof(fileInfo);
+        ble->readCharacteristicValue(handle, (uint8_t*) &fileInfo, &len);
+
+        if (fileInfo.length == 0 && fileInfo.crc16 == 0) {
+            // signal to cancel pending upload
+            downloadInProgress = false;
+            downloadTimer.reset();
+            expectingBlock = 0;
+            DEBUG("Download RESET\r\n");
+            return;
+        }
+
+        DEBUG("Offered file len=%d, crc=0x%04x, acceptFile=%d, downloadInProgress=%d\r\n", fileInfo.length, fileInfo.crc16, acceptFile, downloadInProgress);
+
+        // Now we must decide whether to accept it or not
+        if (acceptFile && !downloadInProgress) {
+            downloadTimer.reset();
+            downloadTimer.start();
+            downloadInProgress = true;
+            requestBlock(0);
+        } else
+            refuseFile();
+
+    } else if (handle == transferFileBlocks[channel].getHandle()) {
+
+        uint16_t len = sizeof(fileBlocks[channel]);
+        ble->readCharacteristicValue(handle, (uint8_t*) &fileBlocks[channel], &len);
+
+        //DEBUG("blk %d on ch %d (total %d)", fileBlocks[channel].blockNumber, channel, ++blk)
+        //DEBUG(".");
+        /*
+        uint8_t byte;
+        for (int i = 2; i < len; i++) {
+            byte = *(((uint8_t*) &fileBlock) + i);
+            DEBUG("%c", byte, byte);
+        }
+        */
+        
+        if (fileBlocks[channel].blockNumber != expectingBlock) {
+            DEBUG("Channel %d ok but expected blk %d, not %d!\r\n", channel, expectingBlock, fileBlocks[channel].blockNumber);
+            requestBlock(expectingBlock);
+            return;
+        } else {
+            // DEBUG("."); // one dot = one successfully received packet
+        }
+
+        if (fileBlocks[channel].blockNumber > (fileInfo.length / Config::blockSize)) {
+            DEBUG("Error: block %d is out of range\r\n", fileBlocks[channel].blockNumber);
+            return;
+        }
+
+        // "processing" step disabled
+        //uint16_t offset = fileBlock.blockNumber * Config::blockSize;
+        //memcpy(downloadLocation, fileBlock[0].data, Config::blockSize);
+
+        // request next block if needed
+        uint16_t nextBlock = fileBlocks[channel].blockNumber + 1;
+        if (nextBlock <= fileInfo.length / Config::blockSize)
+            requestBlock(nextBlock);
+        else {
+            sendFileDownloadedSuccessfully();
+        }
+    } else {
+        DEBUG("Got data on ch %d, but expected on ch %d!\r\n", handle - 1, channel);
+    }
+}
+
+void requestBlock(uint16_t blockNumber)
+{
+    // Requesting a block by sending notification is disabled for speed
+    //ble->updateCharacteristicValue(transferFileBlocks[0].getHandle(), (uint8_t*) &blockNumber, sizeof(blockNumber), false);
+    //DEBUG("BlockReq %d --> PHONE\r\n", blockNumber);
+    expectingBlock = blockNumber;
+}
+
+void sendFileInfo(uint32_t value)
+{
+    // refusal is indicated by sending a fileInfo with all zeros
+    ble->updateCharacteristicValue(transferFileInfo.getHandle(), (uint8_t*) &value, sizeof(value), false);
+}
+
+void refuseFile()
+{
+    sendFileInfo(0);
+}
+
+void sendFileDownloadedSuccessfully()
+{
+    sendFileInfo(1);
+    downloadInProgress = false;
+    downloadTimer.stop();
+    DEBUG("File transfer took %0.1f sec\r\n", downloadTimer.read());
+}
+
+} // namespace transfer
\ No newline at end of file
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/TransferService.h	Thu Aug 14 14:13:53 2014 +0000
@@ -0,0 +1,16 @@
+#ifndef _H_TRANSFERSERVICE_H
+#define _H_TRANSFERSERVICE_H
+
+#include "BLEDevice.h"
+
+namespace Transfer
+{
+
+void init(BLEDevice &ble);
+void reset();
+void handleDataWritten(uint16_t handle);
+const uint8_t* getServiceUUIDp();
+
+};
+
+#endif//_H_TRANSFERSERVICE_H
\ No newline at end of file
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/main.cpp	Thu Aug 14 14:13:53 2014 +0000
@@ -0,0 +1,114 @@
+/* mbed Microcontroller Library
+ * Copyright (c) 2006-2013 ARM Limited
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *     http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#include "mbed.h"
+#include "Logger.h"
+#include "Configuration.h"
+#include "BLEDevice.h"
+#include "TransferService.h"
+
+BLEDevice  ble;
+
+static Gap::ConnectionParams_t connectionParams;
+
+static const uint8_t* uuidlist = Transfer::getServiceUUIDp();
+static uint8_t uuidlistrev[16];
+
+void bluetoothInit();
+
+void disconnectionCallback(Gap::Handle_t handle)
+{
+    DEBUG("Disconnected\n\r");
+    ble.startAdvertising();
+    DEBUG("Advertising...\r\n");
+}
+
+void onConnectionCallback(Gap::Handle_t handle)
+{
+    DEBUG("____[ Connected ]______________________________________\r\n");
+
+    connectionParams.minConnectionInterval = Config::minConnectionInterval;
+    connectionParams.maxConnectionInterval = Config::maxConnectionInterval;
+    connectionParams.slaveLatency          = Config::slaveLatency;
+    connectionParams.connectionSupervisionTimeout = Config::supervisionTimeout;
+    if (ble.updateConnectionParams(handle, &connectionParams) != BLE_ERROR_NONE) {
+        DEBUG("failed to update connection paramter\r\n");
+    } else {
+
+    }
+
+    Transfer::reset();
+}
+
+void onUpdatesEnabled(Gap::Handle_t handle)
+{
+    DEBUG("Notifications enabled for %d\r\n", handle);
+}
+
+void onDataWritten(Gap::Handle_t handle)
+{
+    // bubble up to services, they will emit callbacks if handle matches
+    Transfer::handleDataWritten(handle);
+}
+
+void bluetoothInit()
+{
+    DEBUG("Bluetooth initialising...\r\n");
+    ble.init();
+    ble.setDeviceName(Config::deviceName);
+    ble.onDisconnection(disconnectionCallback);
+    ble.onConnection(onConnectionCallback);
+    ble.onDataWritten(onDataWritten);
+    ble.onUpdatesEnabled(onUpdatesEnabled);
+    
+    // Make sure we use our preferred conn. parameters
+    connectionParams.minConnectionInterval = Config::minConnectionInterval;
+    connectionParams.maxConnectionInterval = Config::maxConnectionInterval;
+    connectionParams.slaveLatency          = Config::slaveLatency;
+    connectionParams.connectionSupervisionTimeout = Config::supervisionTimeout;
+    ble.setPreferredConnectionParams(&connectionParams);
+    ble.getPreferredConnectionParams(&connectionParams);
+    DEBUG("Conn. params => min=%d, max=%d, slave=%d, supervision=%d\r\n", connectionParams.minConnectionInterval,
+          connectionParams.maxConnectionInterval,
+          connectionParams.slaveLatency,
+          connectionParams.connectionSupervisionTimeout);
+    
+    // Initialise transfer service
+    Transfer::init(ble);
+
+    /* setup advertising */
+    ble.accumulateAdvertisingPayload(GapAdvertisingData::BREDR_NOT_SUPPORTED | GapAdvertisingData::LE_GENERAL_DISCOVERABLE);
+    ble.accumulateAdvertisingPayload(GapAdvertisingData::COMPLETE_LIST_128BIT_SERVICE_IDS, uuidlistrev, 16);
+    ble.setAdvertisingType(GapAdvertisingParams::ADV_CONNECTABLE_UNDIRECTED);
+    ble.setAdvertisingInterval(Config::advertisingInterval);
+    ble.startAdvertising();
+    DEBUG("Ready. Advertising.\r\n");
+}
+
+int main(void)
+{
+    DEBUG("Initialising TRANSFER PRO | Built %s %s\n\r", __DATE__, __TIME__);
+
+    for (int i = 0; i < 16; i++) {
+        uuidlistrev[15 - i] = uuidlist[i];
+    }
+    
+    bluetoothInit();
+
+    while (true) {
+        ble.waitForEvent();
+    }
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/mbed.bld	Thu Aug 14 14:13:53 2014 +0000
@@ -0,0 +1,1 @@
+http://mbed.org/users/mbed_official/code/mbed/builds/6213f644d804
\ No newline at end of file
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/nRF51822.lib	Thu Aug 14 14:13:53 2014 +0000
@@ -0,0 +1,1 @@
+http://mbed.org/teams/Nordic-Semiconductor/code/nRF51822/#1e5c300cec7f