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 0:ab775bf55fe4, committed 2014-08-14
- 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
--- /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