An example program to test data transfer throughput. Exhibits long latency (2 sec) between hardware callbacks on write event.

Dependencies:   BLE_API mbed nRF51822

Committer:
pvaibhav
Date:
Thu Aug 14 14:13:53 2014 +0000
Revision:
0:ab775bf55fe4
Minimal program to demo slow throughput/callback latency

Who changed what in which revision?

UserRevisionLine numberNew contents of line
pvaibhav 0:ab775bf55fe4 1 #include "TransferService.h"
pvaibhav 0:ab775bf55fe4 2 #include "Logger.h"
pvaibhav 0:ab775bf55fe4 3 #include "Configuration.h"
pvaibhav 0:ab775bf55fe4 4
pvaibhav 0:ab775bf55fe4 5 namespace Transfer
pvaibhav 0:ab775bf55fe4 6 {
pvaibhav 0:ab775bf55fe4 7
pvaibhav 0:ab775bf55fe4 8 // Transfer base UUID: ADC710C2-xxxx-4BF5-8244-3CEAAA0F87F5
pvaibhav 0:ab775bf55fe4 9 #define transfer_UUID(x) { 0xAD, 0xC7, 0x10, 0xC2, (((x) & 0xFF00) >> 8), ((x) & 0xFF), 0x4B, 0xF5, 0x82, 0x44, 0x3C, 0xEA, 0xAA, 0x0F, 0x87, 0xF5 }
pvaibhav 0:ab775bf55fe4 10
pvaibhav 0:ab775bf55fe4 11 // UUID byte arrays
pvaibhav 0:ab775bf55fe4 12 static const uint8_t transferServiceUUID[] = transfer_UUID(0xACDC);
pvaibhav 0:ab775bf55fe4 13 static const uint8_t transferFileInfoUUID[] = transfer_UUID(0xACDF);
pvaibhav 0:ab775bf55fe4 14 static const uint8_t transferFileBlocksUUID[6][16] =
pvaibhav 0:ab775bf55fe4 15 {
pvaibhav 0:ab775bf55fe4 16 transfer_UUID(0xACE0),
pvaibhav 0:ab775bf55fe4 17 transfer_UUID(0xACE1),
pvaibhav 0:ab775bf55fe4 18 transfer_UUID(0xACE2),
pvaibhav 0:ab775bf55fe4 19 transfer_UUID(0xACE3),
pvaibhav 0:ab775bf55fe4 20 transfer_UUID(0xACE4),
pvaibhav 0:ab775bf55fe4 21 transfer_UUID(0xACE5),
pvaibhav 0:ab775bf55fe4 22 };
pvaibhav 0:ab775bf55fe4 23
pvaibhav 0:ab775bf55fe4 24 // UUID objects used to initialise Bluetooth API
pvaibhav 0:ab775bf55fe4 25 static UUID transferServiceUUID_ = UUID(transferServiceUUID);
pvaibhav 0:ab775bf55fe4 26 static UUID transferFileInfoUUID_ = UUID(transferFileInfoUUID);
pvaibhav 0:ab775bf55fe4 27 static UUID transferFileBlocksUUID_[6] =
pvaibhav 0:ab775bf55fe4 28 {
pvaibhav 0:ab775bf55fe4 29 UUID(transferFileBlocksUUID[0]),
pvaibhav 0:ab775bf55fe4 30 UUID(transferFileBlocksUUID[1]),
pvaibhav 0:ab775bf55fe4 31 UUID(transferFileBlocksUUID[2]),
pvaibhav 0:ab775bf55fe4 32 UUID(transferFileBlocksUUID[3]),
pvaibhav 0:ab775bf55fe4 33 UUID(transferFileBlocksUUID[4]),
pvaibhav 0:ab775bf55fe4 34 UUID(transferFileBlocksUUID[5]),
pvaibhav 0:ab775bf55fe4 35 };
pvaibhav 0:ab775bf55fe4 36
pvaibhav 0:ab775bf55fe4 37 // Storage for the value of the characteristics
pvaibhav 0:ab775bf55fe4 38 struct fileInfo_t {
pvaibhav 0:ab775bf55fe4 39 uint16_t length;
pvaibhav 0:ab775bf55fe4 40 uint16_t crc16;
pvaibhav 0:ab775bf55fe4 41 };
pvaibhav 0:ab775bf55fe4 42 static struct fileInfo_t fileInfo;
pvaibhav 0:ab775bf55fe4 43 struct fileBlock_t {
pvaibhav 0:ab775bf55fe4 44 uint16_t blockNumber;
pvaibhav 0:ab775bf55fe4 45 uint8_t data[16];
pvaibhav 0:ab775bf55fe4 46 };
pvaibhav 0:ab775bf55fe4 47 static struct fileBlock_t fileBlocks[6]; // 6 blocks
pvaibhav 0:ab775bf55fe4 48
pvaibhav 0:ab775bf55fe4 49 // Other things needed for operation
pvaibhav 0:ab775bf55fe4 50 static BLEDevice* ble;
pvaibhav 0:ab775bf55fe4 51 static Timer downloadTimer;
pvaibhav 0:ab775bf55fe4 52
pvaibhav 0:ab775bf55fe4 53 static uint16_t expectingBlock = 0;
pvaibhav 0:ab775bf55fe4 54
pvaibhav 0:ab775bf55fe4 55 static bool acceptFile = true; // additional condition whether to accept a file upload or not, currently always accept
pvaibhav 0:ab775bf55fe4 56 static bool downloadInProgress = false; // indicates if we are downloading a file from the phone
pvaibhav 0:ab775bf55fe4 57
pvaibhav 0:ab775bf55fe4 58 static GattCharacteristic transferFileInfo(transferFileInfoUUID_,
pvaibhav 0:ab775bf55fe4 59 (uint8_t*) &fileInfo,
pvaibhav 0:ab775bf55fe4 60 sizeof(fileInfo),
pvaibhav 0:ab775bf55fe4 61 sizeof(fileInfo),
pvaibhav 0:ab775bf55fe4 62 GattCharacteristic::BLE_GATT_CHAR_PROPERTIES_WRITE
pvaibhav 0:ab775bf55fe4 63 | GattCharacteristic::BLE_GATT_CHAR_PROPERTIES_NOTIFY);
pvaibhav 0:ab775bf55fe4 64
pvaibhav 0:ab775bf55fe4 65 static uint8_t fileBlockProperties =
pvaibhav 0:ab775bf55fe4 66 GattCharacteristic::BLE_GATT_CHAR_PROPERTIES_WRITE
pvaibhav 0:ab775bf55fe4 67 | GattCharacteristic::BLE_GATT_CHAR_PROPERTIES_WRITE_WITHOUT_RESPONSE;
pvaibhav 0:ab775bf55fe4 68
pvaibhav 0:ab775bf55fe4 69 static GattCharacteristic transferFileBlocks[6] = {
pvaibhav 0:ab775bf55fe4 70 GattCharacteristic(transferFileBlocksUUID_[0], (uint8_t*) &fileBlocks[0], sizeof(fileBlock_t), sizeof(fileBlock_t), fileBlockProperties),
pvaibhav 0:ab775bf55fe4 71 GattCharacteristic(transferFileBlocksUUID_[1], (uint8_t*) &fileBlocks[1], sizeof(fileBlock_t), sizeof(fileBlock_t), fileBlockProperties),
pvaibhav 0:ab775bf55fe4 72 GattCharacteristic(transferFileBlocksUUID_[2], (uint8_t*) &fileBlocks[2], sizeof(fileBlock_t), sizeof(fileBlock_t), fileBlockProperties),
pvaibhav 0:ab775bf55fe4 73 GattCharacteristic(transferFileBlocksUUID_[3], (uint8_t*) &fileBlocks[3], sizeof(fileBlock_t), sizeof(fileBlock_t), fileBlockProperties),
pvaibhav 0:ab775bf55fe4 74 GattCharacteristic(transferFileBlocksUUID_[4], (uint8_t*) &fileBlocks[4], sizeof(fileBlock_t), sizeof(fileBlock_t), fileBlockProperties),
pvaibhav 0:ab775bf55fe4 75 GattCharacteristic(transferFileBlocksUUID_[5], (uint8_t*) &fileBlocks[5], sizeof(fileBlock_t), sizeof(fileBlock_t), fileBlockProperties),
pvaibhav 0:ab775bf55fe4 76 };
pvaibhav 0:ab775bf55fe4 77
pvaibhav 0:ab775bf55fe4 78 static GattCharacteristic* allChars[] =
pvaibhav 0:ab775bf55fe4 79 {
pvaibhav 0:ab775bf55fe4 80 &transferFileInfo,
pvaibhav 0:ab775bf55fe4 81 &transferFileBlocks[0],
pvaibhav 0:ab775bf55fe4 82 &transferFileBlocks[1],
pvaibhav 0:ab775bf55fe4 83 &transferFileBlocks[2],
pvaibhav 0:ab775bf55fe4 84 &transferFileBlocks[3],
pvaibhav 0:ab775bf55fe4 85 &transferFileBlocks[4],
pvaibhav 0:ab775bf55fe4 86 &transferFileBlocks[5],
pvaibhav 0:ab775bf55fe4 87 };
pvaibhav 0:ab775bf55fe4 88
pvaibhav 0:ab775bf55fe4 89 static GattService transferService(transferServiceUUID_, allChars, sizeof(allChars) / sizeof(GattCharacteristic*));
pvaibhav 0:ab775bf55fe4 90
pvaibhav 0:ab775bf55fe4 91 void init(BLEDevice &bleDevice)
pvaibhav 0:ab775bf55fe4 92 {
pvaibhav 0:ab775bf55fe4 93 downloadInProgress = false;
pvaibhav 0:ab775bf55fe4 94 ble = &bleDevice;
pvaibhav 0:ab775bf55fe4 95 ble->addService(transferService);
pvaibhav 0:ab775bf55fe4 96 DEBUG("Added transfer service\r\n");
pvaibhav 0:ab775bf55fe4 97 }
pvaibhav 0:ab775bf55fe4 98
pvaibhav 0:ab775bf55fe4 99 void reset()
pvaibhav 0:ab775bf55fe4 100 {
pvaibhav 0:ab775bf55fe4 101 // reset internal state on new connection
pvaibhav 0:ab775bf55fe4 102 downloadInProgress = false;
pvaibhav 0:ab775bf55fe4 103 }
pvaibhav 0:ab775bf55fe4 104
pvaibhav 0:ab775bf55fe4 105 const uint8_t* getServiceUUIDp()
pvaibhav 0:ab775bf55fe4 106 {
pvaibhav 0:ab775bf55fe4 107 return transferServiceUUID;
pvaibhav 0:ab775bf55fe4 108 }
pvaibhav 0:ab775bf55fe4 109
pvaibhav 0:ab775bf55fe4 110 void requestBlock(uint16_t); // prototype declaration
pvaibhav 0:ab775bf55fe4 111 void sendFileInfo();
pvaibhav 0:ab775bf55fe4 112 void refuseFile();
pvaibhav 0:ab775bf55fe4 113 void sendFileDownloadedSuccessfully();
pvaibhav 0:ab775bf55fe4 114
pvaibhav 0:ab775bf55fe4 115 void handleDataWritten(uint16_t handle)
pvaibhav 0:ab775bf55fe4 116 {
pvaibhav 0:ab775bf55fe4 117 if (!ble)
pvaibhav 0:ab775bf55fe4 118 return;
pvaibhav 0:ab775bf55fe4 119
pvaibhav 0:ab775bf55fe4 120 int channel = expectingBlock % 6;
pvaibhav 0:ab775bf55fe4 121
pvaibhav 0:ab775bf55fe4 122 if (handle == transferFileInfo.getHandle()) {
pvaibhav 0:ab775bf55fe4 123
pvaibhav 0:ab775bf55fe4 124 uint16_t len = sizeof(fileInfo);
pvaibhav 0:ab775bf55fe4 125 ble->readCharacteristicValue(handle, (uint8_t*) &fileInfo, &len);
pvaibhav 0:ab775bf55fe4 126
pvaibhav 0:ab775bf55fe4 127 if (fileInfo.length == 0 && fileInfo.crc16 == 0) {
pvaibhav 0:ab775bf55fe4 128 // signal to cancel pending upload
pvaibhav 0:ab775bf55fe4 129 downloadInProgress = false;
pvaibhav 0:ab775bf55fe4 130 downloadTimer.reset();
pvaibhav 0:ab775bf55fe4 131 expectingBlock = 0;
pvaibhav 0:ab775bf55fe4 132 DEBUG("Download RESET\r\n");
pvaibhav 0:ab775bf55fe4 133 return;
pvaibhav 0:ab775bf55fe4 134 }
pvaibhav 0:ab775bf55fe4 135
pvaibhav 0:ab775bf55fe4 136 DEBUG("Offered file len=%d, crc=0x%04x, acceptFile=%d, downloadInProgress=%d\r\n", fileInfo.length, fileInfo.crc16, acceptFile, downloadInProgress);
pvaibhav 0:ab775bf55fe4 137
pvaibhav 0:ab775bf55fe4 138 // Now we must decide whether to accept it or not
pvaibhav 0:ab775bf55fe4 139 if (acceptFile && !downloadInProgress) {
pvaibhav 0:ab775bf55fe4 140 downloadTimer.reset();
pvaibhav 0:ab775bf55fe4 141 downloadTimer.start();
pvaibhav 0:ab775bf55fe4 142 downloadInProgress = true;
pvaibhav 0:ab775bf55fe4 143 requestBlock(0);
pvaibhav 0:ab775bf55fe4 144 } else
pvaibhav 0:ab775bf55fe4 145 refuseFile();
pvaibhav 0:ab775bf55fe4 146
pvaibhav 0:ab775bf55fe4 147 } else if (handle == transferFileBlocks[channel].getHandle()) {
pvaibhav 0:ab775bf55fe4 148
pvaibhav 0:ab775bf55fe4 149 uint16_t len = sizeof(fileBlocks[channel]);
pvaibhav 0:ab775bf55fe4 150 ble->readCharacteristicValue(handle, (uint8_t*) &fileBlocks[channel], &len);
pvaibhav 0:ab775bf55fe4 151
pvaibhav 0:ab775bf55fe4 152 //DEBUG("blk %d on ch %d (total %d)", fileBlocks[channel].blockNumber, channel, ++blk)
pvaibhav 0:ab775bf55fe4 153 //DEBUG(".");
pvaibhav 0:ab775bf55fe4 154 /*
pvaibhav 0:ab775bf55fe4 155 uint8_t byte;
pvaibhav 0:ab775bf55fe4 156 for (int i = 2; i < len; i++) {
pvaibhav 0:ab775bf55fe4 157 byte = *(((uint8_t*) &fileBlock) + i);
pvaibhav 0:ab775bf55fe4 158 DEBUG("%c", byte, byte);
pvaibhav 0:ab775bf55fe4 159 }
pvaibhav 0:ab775bf55fe4 160 */
pvaibhav 0:ab775bf55fe4 161
pvaibhav 0:ab775bf55fe4 162 if (fileBlocks[channel].blockNumber != expectingBlock) {
pvaibhav 0:ab775bf55fe4 163 DEBUG("Channel %d ok but expected blk %d, not %d!\r\n", channel, expectingBlock, fileBlocks[channel].blockNumber);
pvaibhav 0:ab775bf55fe4 164 requestBlock(expectingBlock);
pvaibhav 0:ab775bf55fe4 165 return;
pvaibhav 0:ab775bf55fe4 166 } else {
pvaibhav 0:ab775bf55fe4 167 // DEBUG("."); // one dot = one successfully received packet
pvaibhav 0:ab775bf55fe4 168 }
pvaibhav 0:ab775bf55fe4 169
pvaibhav 0:ab775bf55fe4 170 if (fileBlocks[channel].blockNumber > (fileInfo.length / Config::blockSize)) {
pvaibhav 0:ab775bf55fe4 171 DEBUG("Error: block %d is out of range\r\n", fileBlocks[channel].blockNumber);
pvaibhav 0:ab775bf55fe4 172 return;
pvaibhav 0:ab775bf55fe4 173 }
pvaibhav 0:ab775bf55fe4 174
pvaibhav 0:ab775bf55fe4 175 // "processing" step disabled
pvaibhav 0:ab775bf55fe4 176 //uint16_t offset = fileBlock.blockNumber * Config::blockSize;
pvaibhav 0:ab775bf55fe4 177 //memcpy(downloadLocation, fileBlock[0].data, Config::blockSize);
pvaibhav 0:ab775bf55fe4 178
pvaibhav 0:ab775bf55fe4 179 // request next block if needed
pvaibhav 0:ab775bf55fe4 180 uint16_t nextBlock = fileBlocks[channel].blockNumber + 1;
pvaibhav 0:ab775bf55fe4 181 if (nextBlock <= fileInfo.length / Config::blockSize)
pvaibhav 0:ab775bf55fe4 182 requestBlock(nextBlock);
pvaibhav 0:ab775bf55fe4 183 else {
pvaibhav 0:ab775bf55fe4 184 sendFileDownloadedSuccessfully();
pvaibhav 0:ab775bf55fe4 185 }
pvaibhav 0:ab775bf55fe4 186 } else {
pvaibhav 0:ab775bf55fe4 187 DEBUG("Got data on ch %d, but expected on ch %d!\r\n", handle - 1, channel);
pvaibhav 0:ab775bf55fe4 188 }
pvaibhav 0:ab775bf55fe4 189 }
pvaibhav 0:ab775bf55fe4 190
pvaibhav 0:ab775bf55fe4 191 void requestBlock(uint16_t blockNumber)
pvaibhav 0:ab775bf55fe4 192 {
pvaibhav 0:ab775bf55fe4 193 // Requesting a block by sending notification is disabled for speed
pvaibhav 0:ab775bf55fe4 194 //ble->updateCharacteristicValue(transferFileBlocks[0].getHandle(), (uint8_t*) &blockNumber, sizeof(blockNumber), false);
pvaibhav 0:ab775bf55fe4 195 //DEBUG("BlockReq %d --> PHONE\r\n", blockNumber);
pvaibhav 0:ab775bf55fe4 196 expectingBlock = blockNumber;
pvaibhav 0:ab775bf55fe4 197 }
pvaibhav 0:ab775bf55fe4 198
pvaibhav 0:ab775bf55fe4 199 void sendFileInfo(uint32_t value)
pvaibhav 0:ab775bf55fe4 200 {
pvaibhav 0:ab775bf55fe4 201 // refusal is indicated by sending a fileInfo with all zeros
pvaibhav 0:ab775bf55fe4 202 ble->updateCharacteristicValue(transferFileInfo.getHandle(), (uint8_t*) &value, sizeof(value), false);
pvaibhav 0:ab775bf55fe4 203 }
pvaibhav 0:ab775bf55fe4 204
pvaibhav 0:ab775bf55fe4 205 void refuseFile()
pvaibhav 0:ab775bf55fe4 206 {
pvaibhav 0:ab775bf55fe4 207 sendFileInfo(0);
pvaibhav 0:ab775bf55fe4 208 }
pvaibhav 0:ab775bf55fe4 209
pvaibhav 0:ab775bf55fe4 210 void sendFileDownloadedSuccessfully()
pvaibhav 0:ab775bf55fe4 211 {
pvaibhav 0:ab775bf55fe4 212 sendFileInfo(1);
pvaibhav 0:ab775bf55fe4 213 downloadInProgress = false;
pvaibhav 0:ab775bf55fe4 214 downloadTimer.stop();
pvaibhav 0:ab775bf55fe4 215 DEBUG("File transfer took %0.1f sec\r\n", downloadTimer.read());
pvaibhav 0:ab775bf55fe4 216 }
pvaibhav 0:ab775bf55fe4 217
pvaibhav 0:ab775bf55fe4 218 } // namespace transfer