BERG Cloud / BERGCloud

Dependents:   LittleCounter-Example

Committer:
nickludlam
Date:
Tue Nov 26 17:45:12 2013 +0000
Revision:
5:2e04a8b3fc25
Parent:
4:5a04c00b5b6f
Child:
6:79100379d4b4
Update to v1.1.; ; This fixes an issue with unpacking data which required a promotion of container size. It also includes a template for threading, and a fresh implementation of the CRC16 code.

Who changed what in which revision?

UserRevisionLine numberNew contents of line
nickludlam 0:b4ccb530b9eb 1 /*
nickludlam 0:b4ccb530b9eb 2
nickludlam 0:b4ccb530b9eb 3 BERGCloud library common API
nickludlam 0:b4ccb530b9eb 4
nickludlam 0:b4ccb530b9eb 5 Copyright (c) 2013 BERG Cloud Ltd. http://bergcloud.com/
nickludlam 0:b4ccb530b9eb 6
nickludlam 0:b4ccb530b9eb 7 Permission is hereby granted, free of charge, to any person obtaining a copy
nickludlam 0:b4ccb530b9eb 8 of this software and associated documentation files (the "Software"), to deal
nickludlam 0:b4ccb530b9eb 9 in the Software without restriction, including without limitation the rights
nickludlam 0:b4ccb530b9eb 10 to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
nickludlam 0:b4ccb530b9eb 11 copies of the Software, and to permit persons to whom the Software is
nickludlam 0:b4ccb530b9eb 12 furnished to do so, subject to the following conditions:
nickludlam 0:b4ccb530b9eb 13
nickludlam 0:b4ccb530b9eb 14 The above copyright notice and this permission notice shall be included in
nickludlam 0:b4ccb530b9eb 15 all copies or substantial portions of the Software.
nickludlam 0:b4ccb530b9eb 16
nickludlam 0:b4ccb530b9eb 17 THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
nickludlam 0:b4ccb530b9eb 18 IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
nickludlam 0:b4ccb530b9eb 19 FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
nickludlam 0:b4ccb530b9eb 20 AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
nickludlam 0:b4ccb530b9eb 21 LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
nickludlam 0:b4ccb530b9eb 22 OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
nickludlam 0:b4ccb530b9eb 23 THE SOFTWARE.
nickludlam 0:b4ccb530b9eb 24
nickludlam 0:b4ccb530b9eb 25 */
nickludlam 0:b4ccb530b9eb 26
nickludlam 0:b4ccb530b9eb 27
nickludlam 0:b4ccb530b9eb 28 #define __STDC_LIMIT_MACROS /* Include C99 stdint defines in C++ code */
nickludlam 0:b4ccb530b9eb 29 #include <stdint.h>
nickludlam 0:b4ccb530b9eb 30 #include <stddef.h>
nickludlam 0:b4ccb530b9eb 31 #include <string.h> /* For memcpy() */
nickludlam 0:b4ccb530b9eb 32
nickludlam 0:b4ccb530b9eb 33 #include "BERGCloudBase.h"
nickludlam 0:b4ccb530b9eb 34
nickludlam 0:b4ccb530b9eb 35 #define SPI_POLL_TIMEOUT_MS 1000
nickludlam 0:b4ccb530b9eb 36 #define SPI_SYNC_TIMEOUT_MS 10000
nickludlam 0:b4ccb530b9eb 37
nickludlam 0:b4ccb530b9eb 38 #define CONNECT_POLL_RATE_MS 250
nickludlam 0:b4ccb530b9eb 39
nickludlam 4:5a04c00b5b6f 40 uint8_t BERGCloudBase::nullKey[BC_KEY_SIZE_BYTES] = {0};
nickludlam 0:b4ccb530b9eb 41
nickludlam 5:2e04a8b3fc25 42 bool BERGCloudBase::_transaction(_BC_SPI_TRANSACTION *tr)
nickludlam 0:b4ccb530b9eb 43 {
nickludlam 0:b4ccb530b9eb 44 uint16_t i, j;
nickludlam 0:b4ccb530b9eb 45 uint8_t rxByte;
nickludlam 0:b4ccb530b9eb 46 bool timeout;
nickludlam 0:b4ccb530b9eb 47 uint8_t dataSize;
nickludlam 0:b4ccb530b9eb 48 uint16_t groupSize;
nickludlam 0:b4ccb530b9eb 49 uint16_t dataCRC;
nickludlam 0:b4ccb530b9eb 50 uint16_t calcCRC;
nickludlam 0:b4ccb530b9eb 51 uint8_t header[SPI_HEADER_SIZE_BYTES];
nickludlam 0:b4ccb530b9eb 52 uint8_t footer[SPI_FOOTER_SIZE_BYTES];
nickludlam 0:b4ccb530b9eb 53
nickludlam 0:b4ccb530b9eb 54 /* Check synchronisation */
nickludlam 0:b4ccb530b9eb 55 if (!synced)
nickludlam 0:b4ccb530b9eb 56 {
nickludlam 0:b4ccb530b9eb 57 timerReset();
nickludlam 0:b4ccb530b9eb 58
nickludlam 0:b4ccb530b9eb 59 do {
nickludlam 0:b4ccb530b9eb 60 rxByte = SPITransaction(SPI_PROTOCOL_PAD, true);
nickludlam 0:b4ccb530b9eb 61 timeout = timerRead_mS() > SPI_SYNC_TIMEOUT_MS;
nickludlam 0:b4ccb530b9eb 62
nickludlam 0:b4ccb530b9eb 63 } while ((rxByte != SPI_PROTOCOL_RESET) && !timeout);
nickludlam 0:b4ccb530b9eb 64
nickludlam 0:b4ccb530b9eb 65 if (timeout)
nickludlam 0:b4ccb530b9eb 66 {
nickludlam 0:b4ccb530b9eb 67 _LOG("Timeout, sync (BERGCloudBase::transaction)\r\n");
nickludlam 0:b4ccb530b9eb 68 return false;
nickludlam 0:b4ccb530b9eb 69 }
nickludlam 0:b4ccb530b9eb 70
nickludlam 0:b4ccb530b9eb 71 /* Resynchronisation successful */
nickludlam 0:b4ccb530b9eb 72 synced = true;
nickludlam 0:b4ccb530b9eb 73 }
nickludlam 0:b4ccb530b9eb 74
nickludlam 0:b4ccb530b9eb 75 /* Calculate total data size */
nickludlam 0:b4ccb530b9eb 76 dataSize = 0;
nickludlam 0:b4ccb530b9eb 77
nickludlam 0:b4ccb530b9eb 78 for (i=0; i<_TX_GROUPS; i++)
nickludlam 0:b4ccb530b9eb 79 {
nickludlam 0:b4ccb530b9eb 80 dataSize += tr->tx[i].dataSize;
nickludlam 0:b4ccb530b9eb 81 }
nickludlam 0:b4ccb530b9eb 82
nickludlam 0:b4ccb530b9eb 83 /* Initialise CRC */
nickludlam 0:b4ccb530b9eb 84 calcCRC = 0xffff;
nickludlam 0:b4ccb530b9eb 85
nickludlam 0:b4ccb530b9eb 86 /* Create header */
nickludlam 0:b4ccb530b9eb 87 header[0] = tr->command;
nickludlam 0:b4ccb530b9eb 88 header[1] = 0x00; /* Reserved */
nickludlam 0:b4ccb530b9eb 89 header[2] = 0x00; /* Reserved */
nickludlam 0:b4ccb530b9eb 90 header[3] = dataSize;
nickludlam 0:b4ccb530b9eb 91
nickludlam 0:b4ccb530b9eb 92 /* Send header */
nickludlam 0:b4ccb530b9eb 93 for (i=0; i<sizeof(header); i++)
nickludlam 0:b4ccb530b9eb 94 {
nickludlam 0:b4ccb530b9eb 95
nickludlam 0:b4ccb530b9eb 96 calcCRC = Crc16(header[i], calcCRC);
nickludlam 0:b4ccb530b9eb 97 rxByte = SPITransaction(header[i], false);
nickludlam 0:b4ccb530b9eb 98
nickludlam 0:b4ccb530b9eb 99 if (rxByte == SPI_PROTOCOL_RESET)
nickludlam 0:b4ccb530b9eb 100 {
nickludlam 0:b4ccb530b9eb 101 _LOG("Reset, send header (BERGCloudBase::transaction)\r\n");
nickludlam 0:b4ccb530b9eb 102 return false;
nickludlam 0:b4ccb530b9eb 103 }
nickludlam 0:b4ccb530b9eb 104
nickludlam 0:b4ccb530b9eb 105 if (rxByte != SPI_PROTOCOL_PAD)
nickludlam 0:b4ccb530b9eb 106 {
nickludlam 0:b4ccb530b9eb 107 _LOG("SyncErr, send header (BERGCloudBase::transaction)\r\n");
nickludlam 0:b4ccb530b9eb 108 synced = false;
nickludlam 0:b4ccb530b9eb 109 return false;
nickludlam 0:b4ccb530b9eb 110 }
nickludlam 0:b4ccb530b9eb 111 }
nickludlam 0:b4ccb530b9eb 112
nickludlam 0:b4ccb530b9eb 113 /* Send data groups */
nickludlam 0:b4ccb530b9eb 114 for (i=0; i<_TX_GROUPS; i++)
nickludlam 0:b4ccb530b9eb 115 {
nickludlam 0:b4ccb530b9eb 116 for (j=0; j<tr->tx[i].dataSize; j++)
nickludlam 0:b4ccb530b9eb 117 {
nickludlam 0:b4ccb530b9eb 118 calcCRC = Crc16(tr->tx[i].buffer[j], calcCRC);
nickludlam 0:b4ccb530b9eb 119 rxByte = SPITransaction(tr->tx[i].buffer[j], false);
nickludlam 0:b4ccb530b9eb 120
nickludlam 0:b4ccb530b9eb 121 if (rxByte == SPI_PROTOCOL_RESET)
nickludlam 0:b4ccb530b9eb 122 {
nickludlam 0:b4ccb530b9eb 123 _LOG("Reset, send data (BERGCloudBase::transaction)\r\n");
nickludlam 0:b4ccb530b9eb 124 return false;
nickludlam 0:b4ccb530b9eb 125 }
nickludlam 0:b4ccb530b9eb 126
nickludlam 0:b4ccb530b9eb 127 if (rxByte != SPI_PROTOCOL_PAD)
nickludlam 0:b4ccb530b9eb 128 {
nickludlam 0:b4ccb530b9eb 129 _LOG("SyncErr, send data (BERGCloudBase::transaction)\r\n");
nickludlam 0:b4ccb530b9eb 130 synced = false;
nickludlam 0:b4ccb530b9eb 131 return false;
nickludlam 0:b4ccb530b9eb 132 }
nickludlam 0:b4ccb530b9eb 133 }
nickludlam 0:b4ccb530b9eb 134 }
nickludlam 0:b4ccb530b9eb 135
nickludlam 0:b4ccb530b9eb 136 /* Create footer */
nickludlam 0:b4ccb530b9eb 137 footer[0] = calcCRC >> 8;
nickludlam 0:b4ccb530b9eb 138 footer[1] = calcCRC & 0xff;
nickludlam 0:b4ccb530b9eb 139
nickludlam 0:b4ccb530b9eb 140 /* Send footer */
nickludlam 0:b4ccb530b9eb 141 for (i=0; i<sizeof(footer); i++)
nickludlam 0:b4ccb530b9eb 142 {
nickludlam 0:b4ccb530b9eb 143 rxByte = SPITransaction(footer[i], false);
nickludlam 0:b4ccb530b9eb 144
nickludlam 0:b4ccb530b9eb 145 if (rxByte == SPI_PROTOCOL_RESET)
nickludlam 0:b4ccb530b9eb 146 {
nickludlam 0:b4ccb530b9eb 147 _LOG("Reset, send footer (BERGCloudBase::transaction)\r\n");
nickludlam 0:b4ccb530b9eb 148 return false;
nickludlam 0:b4ccb530b9eb 149 }
nickludlam 0:b4ccb530b9eb 150
nickludlam 0:b4ccb530b9eb 151 if (rxByte != SPI_PROTOCOL_PAD)
nickludlam 0:b4ccb530b9eb 152 {
nickludlam 0:b4ccb530b9eb 153 _LOG("SyncErr, send footer (BERGCloudBase::transaction)\r\n");
nickludlam 0:b4ccb530b9eb 154 synced = false;
nickludlam 0:b4ccb530b9eb 155 return false;
nickludlam 0:b4ccb530b9eb 156 }
nickludlam 0:b4ccb530b9eb 157 }
nickludlam 0:b4ccb530b9eb 158
nickludlam 0:b4ccb530b9eb 159 /* Poll for response */
nickludlam 0:b4ccb530b9eb 160 timerReset();
nickludlam 0:b4ccb530b9eb 161
nickludlam 0:b4ccb530b9eb 162 do {
nickludlam 0:b4ccb530b9eb 163 rxByte = SPITransaction(SPI_PROTOCOL_PAD, false);
nickludlam 0:b4ccb530b9eb 164
nickludlam 0:b4ccb530b9eb 165 if (rxByte == SPI_PROTOCOL_RESET)
nickludlam 0:b4ccb530b9eb 166 {
nickludlam 0:b4ccb530b9eb 167 _LOG("Reset, poll (BERGCloudBase::transaction)\r\n");
nickludlam 0:b4ccb530b9eb 168 return false;
nickludlam 0:b4ccb530b9eb 169 }
nickludlam 0:b4ccb530b9eb 170
nickludlam 0:b4ccb530b9eb 171 if (rxByte == SPI_PROTOCOL_PENDING)
nickludlam 0:b4ccb530b9eb 172 {
nickludlam 0:b4ccb530b9eb 173 /* Waiting for data; reset timeout */
nickludlam 0:b4ccb530b9eb 174 timerReset();
nickludlam 0:b4ccb530b9eb 175 }
nickludlam 0:b4ccb530b9eb 176
nickludlam 0:b4ccb530b9eb 177 timeout = timerRead_mS() > SPI_POLL_TIMEOUT_MS;
nickludlam 0:b4ccb530b9eb 178
nickludlam 0:b4ccb530b9eb 179 } while (((rxByte == SPI_PROTOCOL_PAD) || (rxByte == SPI_PROTOCOL_PENDING)) && !timeout);
nickludlam 0:b4ccb530b9eb 180
nickludlam 0:b4ccb530b9eb 181 if (timeout)
nickludlam 0:b4ccb530b9eb 182 {
nickludlam 0:b4ccb530b9eb 183 _LOG("Timeout, poll (BERGCloudBase::transaction)\r\n");
nickludlam 0:b4ccb530b9eb 184 synced = false;
nickludlam 0:b4ccb530b9eb 185 return false;
nickludlam 0:b4ccb530b9eb 186 }
nickludlam 0:b4ccb530b9eb 187
nickludlam 0:b4ccb530b9eb 188 /* Initialise CRC */
nickludlam 0:b4ccb530b9eb 189 calcCRC = 0xffff;
nickludlam 0:b4ccb530b9eb 190
nickludlam 0:b4ccb530b9eb 191 /* Read header, we already have the first byte */
nickludlam 0:b4ccb530b9eb 192 header[0] = rxByte;
nickludlam 0:b4ccb530b9eb 193 calcCRC = Crc16(header[0], calcCRC);
nickludlam 0:b4ccb530b9eb 194
nickludlam 0:b4ccb530b9eb 195 for (i=1; i < SPI_HEADER_SIZE_BYTES; i++)
nickludlam 0:b4ccb530b9eb 196 {
nickludlam 0:b4ccb530b9eb 197 header[i] = SPITransaction(SPI_PROTOCOL_PAD, false);
nickludlam 0:b4ccb530b9eb 198 calcCRC = Crc16(header[i], calcCRC);
nickludlam 0:b4ccb530b9eb 199 }
nickludlam 0:b4ccb530b9eb 200
nickludlam 0:b4ccb530b9eb 201 /* Get data size */
nickludlam 0:b4ccb530b9eb 202 dataSize = header[3];
nickludlam 0:b4ccb530b9eb 203
nickludlam 0:b4ccb530b9eb 204 /* Read data groups */
nickludlam 0:b4ccb530b9eb 205 for (i=0; i<_RX_GROUPS; i++)
nickludlam 0:b4ccb530b9eb 206 {
nickludlam 0:b4ccb530b9eb 207 groupSize = tr->rx[i].bufferSize;
nickludlam 0:b4ccb530b9eb 208 j = 0; /* Start of the group buffer */
nickludlam 0:b4ccb530b9eb 209
nickludlam 0:b4ccb530b9eb 210 while((dataSize > 0) && (groupSize > 0))
nickludlam 0:b4ccb530b9eb 211 {
nickludlam 0:b4ccb530b9eb 212 tr->rx[i].buffer[j] = SPITransaction(SPI_PROTOCOL_PAD, false);
nickludlam 0:b4ccb530b9eb 213 calcCRC = Crc16(tr->rx[i].buffer[j], calcCRC);
nickludlam 0:b4ccb530b9eb 214
nickludlam 0:b4ccb530b9eb 215 /* Next */
nickludlam 0:b4ccb530b9eb 216 j++;
nickludlam 0:b4ccb530b9eb 217
nickludlam 0:b4ccb530b9eb 218 /* Update the total data remaining and the space remaining in this group. */
nickludlam 0:b4ccb530b9eb 219 dataSize--;
nickludlam 0:b4ccb530b9eb 220 groupSize--;
nickludlam 0:b4ccb530b9eb 221 }
nickludlam 0:b4ccb530b9eb 222
nickludlam 0:b4ccb530b9eb 223 if (tr->rx[i].dataSize != NULL)
nickludlam 0:b4ccb530b9eb 224 {
nickludlam 0:b4ccb530b9eb 225 /* Return the number of bytes used in this buffer */
nickludlam 0:b4ccb530b9eb 226 *tr->rx[i].dataSize = tr->rx[i].bufferSize - groupSize;
nickludlam 0:b4ccb530b9eb 227 }
nickludlam 0:b4ccb530b9eb 228 }
nickludlam 0:b4ccb530b9eb 229
nickludlam 0:b4ccb530b9eb 230 if (dataSize > 0)
nickludlam 0:b4ccb530b9eb 231 {
nickludlam 0:b4ccb530b9eb 232 /* Too much data sent */
nickludlam 0:b4ccb530b9eb 233 _LOG("SizeErr, read data (BERGCloudBase::transaction)\r\n");
nickludlam 0:b4ccb530b9eb 234 synced = false;
nickludlam 0:b4ccb530b9eb 235 return false;
nickludlam 0:b4ccb530b9eb 236 }
nickludlam 0:b4ccb530b9eb 237
nickludlam 0:b4ccb530b9eb 238 /* Read CRC; set nCS high */
nickludlam 0:b4ccb530b9eb 239 dataCRC = SPITransaction(SPI_PROTOCOL_PAD, false); /* MSByte */
nickludlam 0:b4ccb530b9eb 240 dataCRC <<= 8;
nickludlam 0:b4ccb530b9eb 241 dataCRC |= SPITransaction(SPI_PROTOCOL_PAD, true /* nCS -> high */); /* LSByte */
nickludlam 0:b4ccb530b9eb 242
nickludlam 0:b4ccb530b9eb 243 /* Compare with calculated CRC */
nickludlam 0:b4ccb530b9eb 244 if (calcCRC != dataCRC)
nickludlam 0:b4ccb530b9eb 245 {
nickludlam 0:b4ccb530b9eb 246 /* Invalid CRC */
nickludlam 0:b4ccb530b9eb 247 _LOG("CRCErr, read data (BERGCloudBase::transaction)\r\n");
nickludlam 0:b4ccb530b9eb 248 synced = false;
nickludlam 0:b4ccb530b9eb 249 return false;
nickludlam 0:b4ccb530b9eb 250 }
nickludlam 0:b4ccb530b9eb 251
nickludlam 0:b4ccb530b9eb 252 /* Get reponse code */
nickludlam 0:b4ccb530b9eb 253 lastResponse = header[0];
nickludlam 0:b4ccb530b9eb 254
nickludlam 0:b4ccb530b9eb 255 return (lastResponse == SPI_RSP_SUCCESS);
nickludlam 0:b4ccb530b9eb 256 }
nickludlam 0:b4ccb530b9eb 257
nickludlam 5:2e04a8b3fc25 258 bool BERGCloudBase::transaction(_BC_SPI_TRANSACTION *tr)
nickludlam 5:2e04a8b3fc25 259 {
nickludlam 5:2e04a8b3fc25 260 bool result;
nickludlam 5:2e04a8b3fc25 261
nickludlam 5:2e04a8b3fc25 262 /* For thread synchronisation */
nickludlam 5:2e04a8b3fc25 263 lockTake();
nickludlam 5:2e04a8b3fc25 264 result = _transaction(tr);
nickludlam 5:2e04a8b3fc25 265 lockRelease();
nickludlam 5:2e04a8b3fc25 266
nickludlam 5:2e04a8b3fc25 267 return result;
nickludlam 5:2e04a8b3fc25 268 }
nickludlam 5:2e04a8b3fc25 269
nickludlam 0:b4ccb530b9eb 270 void BERGCloudBase::initTransaction(_BC_SPI_TRANSACTION *tr)
nickludlam 0:b4ccb530b9eb 271 {
nickludlam 0:b4ccb530b9eb 272 memset(tr, 0x00, sizeof(_BC_SPI_TRANSACTION));
nickludlam 0:b4ccb530b9eb 273 }
nickludlam 0:b4ccb530b9eb 274
nickludlam 0:b4ccb530b9eb 275 bool BERGCloudBase::pollForCommand(uint8_t *commandBuffer, uint16_t commandBufferSize, uint16_t& commandSize, uint8_t& commandID)
nickludlam 0:b4ccb530b9eb 276 {
nickludlam 0:b4ccb530b9eb 277 /* Returns TRUE if a valid command has been received */
nickludlam 0:b4ccb530b9eb 278
nickludlam 0:b4ccb530b9eb 279 _BC_SPI_TRANSACTION tr;
nickludlam 0:b4ccb530b9eb 280 uint8_t cmdID[2] = {0};
nickludlam 0:b4ccb530b9eb 281 uint16_t cmdIDSize = 0;
nickludlam 0:b4ccb530b9eb 282
nickludlam 0:b4ccb530b9eb 283 initTransaction(&tr);
nickludlam 0:b4ccb530b9eb 284
nickludlam 0:b4ccb530b9eb 285 tr.command = SPI_CMD_POLL_FOR_COMMAND;
nickludlam 0:b4ccb530b9eb 286
nickludlam 0:b4ccb530b9eb 287 tr.rx[0].buffer = cmdID;
nickludlam 0:b4ccb530b9eb 288 tr.rx[0].bufferSize = sizeof(cmdID);
nickludlam 0:b4ccb530b9eb 289 tr.rx[0].dataSize = &cmdIDSize;
nickludlam 0:b4ccb530b9eb 290
nickludlam 0:b4ccb530b9eb 291 tr.rx[1].buffer = commandBuffer;
nickludlam 0:b4ccb530b9eb 292 tr.rx[1].bufferSize = commandBufferSize;
nickludlam 0:b4ccb530b9eb 293 tr.rx[1].dataSize = &commandSize;
nickludlam 0:b4ccb530b9eb 294
nickludlam 0:b4ccb530b9eb 295 if (transaction(&tr))
nickludlam 0:b4ccb530b9eb 296 {
nickludlam 0:b4ccb530b9eb 297 commandID = cmdID[1];
nickludlam 0:b4ccb530b9eb 298 return true;
nickludlam 0:b4ccb530b9eb 299 }
nickludlam 0:b4ccb530b9eb 300
nickludlam 0:b4ccb530b9eb 301 commandID = 0;
nickludlam 0:b4ccb530b9eb 302 commandSize = 0;
nickludlam 0:b4ccb530b9eb 303 return false;
nickludlam 0:b4ccb530b9eb 304 }
nickludlam 0:b4ccb530b9eb 305
nickludlam 0:b4ccb530b9eb 306 #ifdef BERGCLOUD_PACK_UNPACK
nickludlam 0:b4ccb530b9eb 307 bool BERGCloudBase::pollForCommand(BERGCloudMessageBuffer& buffer, uint8_t& commandID)
nickludlam 0:b4ccb530b9eb 308 {
nickludlam 0:b4ccb530b9eb 309 /* Returns TRUE if a valid command has been received */
nickludlam 0:b4ccb530b9eb 310
nickludlam 0:b4ccb530b9eb 311 _BC_SPI_TRANSACTION tr;
nickludlam 0:b4ccb530b9eb 312 uint8_t cmdID[2] = {0};
nickludlam 0:b4ccb530b9eb 313 uint16_t cmdIDSize = 0;
nickludlam 0:b4ccb530b9eb 314 uint16_t dataSize = 0;
nickludlam 0:b4ccb530b9eb 315
nickludlam 0:b4ccb530b9eb 316 initTransaction(&tr);
nickludlam 0:b4ccb530b9eb 317 buffer.clear();
nickludlam 0:b4ccb530b9eb 318
nickludlam 0:b4ccb530b9eb 319 tr.command = SPI_CMD_POLL_FOR_COMMAND;
nickludlam 0:b4ccb530b9eb 320
nickludlam 0:b4ccb530b9eb 321 tr.rx[0].buffer = cmdID;
nickludlam 0:b4ccb530b9eb 322 tr.rx[0].bufferSize = sizeof(cmdID);
nickludlam 0:b4ccb530b9eb 323 tr.rx[0].dataSize = &cmdIDSize;
nickludlam 0:b4ccb530b9eb 324
nickludlam 0:b4ccb530b9eb 325 tr.rx[1].buffer = buffer.ptr();
nickludlam 0:b4ccb530b9eb 326 tr.rx[1].bufferSize = buffer.size();
nickludlam 0:b4ccb530b9eb 327 tr.rx[1].dataSize = &dataSize;
nickludlam 0:b4ccb530b9eb 328
nickludlam 0:b4ccb530b9eb 329 if (transaction(&tr))
nickludlam 0:b4ccb530b9eb 330 {
nickludlam 0:b4ccb530b9eb 331 commandID = cmdID[1];
nickludlam 0:b4ccb530b9eb 332 buffer.used(dataSize);
nickludlam 0:b4ccb530b9eb 333 return true;
nickludlam 0:b4ccb530b9eb 334 }
nickludlam 0:b4ccb530b9eb 335
nickludlam 0:b4ccb530b9eb 336 commandID = 0;
nickludlam 0:b4ccb530b9eb 337 buffer.used(0);
nickludlam 0:b4ccb530b9eb 338 return false;
nickludlam 0:b4ccb530b9eb 339 }
nickludlam 0:b4ccb530b9eb 340 #endif
nickludlam 0:b4ccb530b9eb 341
nickludlam 0:b4ccb530b9eb 342 bool BERGCloudBase::_sendEvent(uint8_t eventCode, uint8_t *eventBuffer, uint16_t eventSize, uint8_t command)
nickludlam 0:b4ccb530b9eb 343 {
nickludlam 0:b4ccb530b9eb 344 /* Returns TRUE if the event is sent successfully */
nickludlam 0:b4ccb530b9eb 345
nickludlam 0:b4ccb530b9eb 346 _BC_SPI_TRANSACTION tr;
nickludlam 0:b4ccb530b9eb 347 uint8_t header[4] = {0};
nickludlam 0:b4ccb530b9eb 348
nickludlam 0:b4ccb530b9eb 349 if (eventSize > (SPI_MAX_PAYLOAD_SIZE_BYTES - sizeof(header)))
nickludlam 0:b4ccb530b9eb 350 {
nickludlam 0:b4ccb530b9eb 351 /* Too big */
nickludlam 0:b4ccb530b9eb 352 return false;
nickludlam 0:b4ccb530b9eb 353 }
nickludlam 0:b4ccb530b9eb 354
nickludlam 0:b4ccb530b9eb 355 header[0] = eventCode;
nickludlam 0:b4ccb530b9eb 356
nickludlam 0:b4ccb530b9eb 357 initTransaction(&tr);
nickludlam 0:b4ccb530b9eb 358
nickludlam 0:b4ccb530b9eb 359 tr.command = command;
nickludlam 0:b4ccb530b9eb 360 tr.tx[0].buffer = (uint8_t *)header;
nickludlam 0:b4ccb530b9eb 361 tr.tx[0].dataSize = sizeof(header);
nickludlam 0:b4ccb530b9eb 362 tr.tx[1].buffer = eventBuffer;
nickludlam 0:b4ccb530b9eb 363 tr.tx[1].dataSize = (uint8_t)eventSize;
nickludlam 0:b4ccb530b9eb 364
nickludlam 0:b4ccb530b9eb 365 return transaction(&tr);
nickludlam 0:b4ccb530b9eb 366 }
nickludlam 0:b4ccb530b9eb 367
nickludlam 4:5a04c00b5b6f 368 bool BERGCloudBase::sendEvent(uint8_t eventCode, uint8_t *eventBuffer, uint16_t eventSize, bool packed)
nickludlam 0:b4ccb530b9eb 369 {
nickludlam 4:5a04c00b5b6f 370 return _sendEvent(eventCode, eventBuffer, eventSize, packed ? SPI_CMD_SEND_EVENT_PACKED : SPI_CMD_SEND_EVENT_RAW);
nickludlam 0:b4ccb530b9eb 371 }
nickludlam 0:b4ccb530b9eb 372
nickludlam 0:b4ccb530b9eb 373 #ifdef BERGCLOUD_PACK_UNPACK
nickludlam 0:b4ccb530b9eb 374 bool BERGCloudBase::sendEvent(uint8_t eventCode, BERGCloudMessageBuffer& buffer)
nickludlam 0:b4ccb530b9eb 375 {
nickludlam 0:b4ccb530b9eb 376 bool result;
nickludlam 0:b4ccb530b9eb 377
nickludlam 0:b4ccb530b9eb 378 result = _sendEvent(eventCode, buffer.ptr(), buffer.used(), SPI_CMD_SEND_EVENT_PACKED);
nickludlam 0:b4ccb530b9eb 379
nickludlam 0:b4ccb530b9eb 380 buffer.clear();
nickludlam 0:b4ccb530b9eb 381 return result;
nickludlam 0:b4ccb530b9eb 382 }
nickludlam 0:b4ccb530b9eb 383 #endif
nickludlam 0:b4ccb530b9eb 384
nickludlam 0:b4ccb530b9eb 385 bool BERGCloudBase::getConnectionState(uint8_t& state)
nickludlam 0:b4ccb530b9eb 386 {
nickludlam 0:b4ccb530b9eb 387 _BC_SPI_TRANSACTION tr;
nickludlam 0:b4ccb530b9eb 388
nickludlam 0:b4ccb530b9eb 389 initTransaction(&tr);
nickludlam 0:b4ccb530b9eb 390
nickludlam 0:b4ccb530b9eb 391 tr.command = SPI_CMD_GET_CONNECT_STATE;
nickludlam 0:b4ccb530b9eb 392 tr.rx[0].buffer = &state;
nickludlam 0:b4ccb530b9eb 393 tr.rx[0].bufferSize = sizeof(state);
nickludlam 0:b4ccb530b9eb 394
nickludlam 0:b4ccb530b9eb 395 return transaction(&tr);
nickludlam 0:b4ccb530b9eb 396 }
nickludlam 0:b4ccb530b9eb 397
nickludlam 0:b4ccb530b9eb 398 bool BERGCloudBase::getSignalQuality(int8_t& rssi, uint8_t& lqi)
nickludlam 0:b4ccb530b9eb 399 {
nickludlam 0:b4ccb530b9eb 400 _BC_SPI_TRANSACTION tr;
nickludlam 0:b4ccb530b9eb 401
nickludlam 0:b4ccb530b9eb 402 initTransaction(&tr);
nickludlam 0:b4ccb530b9eb 403
nickludlam 0:b4ccb530b9eb 404 tr.command = SPI_CMD_GET_SIGNAL_QUALITY;
nickludlam 0:b4ccb530b9eb 405 tr.rx[0].buffer = (uint8_t *)&rssi;
nickludlam 0:b4ccb530b9eb 406 tr.rx[0].bufferSize = sizeof(rssi);
nickludlam 0:b4ccb530b9eb 407 tr.rx[1].buffer = &lqi;
nickludlam 0:b4ccb530b9eb 408 tr.rx[1].bufferSize = sizeof(lqi);
nickludlam 0:b4ccb530b9eb 409
nickludlam 0:b4ccb530b9eb 410 return transaction(&tr);
nickludlam 0:b4ccb530b9eb 411 }
nickludlam 0:b4ccb530b9eb 412
nickludlam 4:5a04c00b5b6f 413 bool BERGCloudBase::connect(const uint8_t (&key)[BC_KEY_SIZE_BYTES], uint16_t version, bool waitForConnected)
nickludlam 0:b4ccb530b9eb 414 {
nickludlam 0:b4ccb530b9eb 415 _BC_SPI_TRANSACTION tr;
nickludlam 0:b4ccb530b9eb 416 uint16_t hostType = BC_HOST_UNKNOWN;
nickludlam 0:b4ccb530b9eb 417 uint8_t connectData [sizeof(version) + sizeof(hostType)];
nickludlam 0:b4ccb530b9eb 418
nickludlam 0:b4ccb530b9eb 419 uint8_t lastState = BC_CONNECT_STATE_DISCONNECTED;
nickludlam 0:b4ccb530b9eb 420 uint8_t state;
nickludlam 0:b4ccb530b9eb 421
nickludlam 0:b4ccb530b9eb 422 #ifndef BERGCLOUD_NO_HOST_TYPE
nickludlam 0:b4ccb530b9eb 423 /* Get host type */
nickludlam 0:b4ccb530b9eb 424 hostType = getHostType();
nickludlam 0:b4ccb530b9eb 425 #endif
nickludlam 0:b4ccb530b9eb 426
nickludlam 0:b4ccb530b9eb 427 initTransaction(&tr);
nickludlam 0:b4ccb530b9eb 428
nickludlam 0:b4ccb530b9eb 429 connectData[0] = hostType;
nickludlam 0:b4ccb530b9eb 430 connectData[1] = hostType >> 8;
nickludlam 0:b4ccb530b9eb 431 connectData[2] = version;
nickludlam 0:b4ccb530b9eb 432 connectData[3] = version >> 8;
nickludlam 0:b4ccb530b9eb 433
nickludlam 4:5a04c00b5b6f 434 tr.command = SPI_CMD_SEND_ANNOUNCE;
nickludlam 4:5a04c00b5b6f 435 tr.tx[0].buffer = (uint8_t *)key;
nickludlam 4:5a04c00b5b6f 436 tr.tx[0].dataSize = sizeof(key);
nickludlam 0:b4ccb530b9eb 437 tr.tx[1].buffer = connectData;
nickludlam 0:b4ccb530b9eb 438 tr.tx[1].dataSize = sizeof(connectData);
nickludlam 0:b4ccb530b9eb 439
nickludlam 0:b4ccb530b9eb 440 if (!transaction(&tr))
nickludlam 0:b4ccb530b9eb 441 {
nickludlam 0:b4ccb530b9eb 442 return false;
nickludlam 0:b4ccb530b9eb 443 }
nickludlam 0:b4ccb530b9eb 444
nickludlam 0:b4ccb530b9eb 445 if (waitForConnected)
nickludlam 0:b4ccb530b9eb 446 {
nickludlam 0:b4ccb530b9eb 447 /* Poll until connected */
nickludlam 0:b4ccb530b9eb 448 do {
nickludlam 0:b4ccb530b9eb 449 timerReset();
nickludlam 0:b4ccb530b9eb 450 while (timerRead_mS() < CONNECT_POLL_RATE_MS);
nickludlam 0:b4ccb530b9eb 451
nickludlam 0:b4ccb530b9eb 452 if (!getConnectionState(state))
nickludlam 0:b4ccb530b9eb 453 {
nickludlam 0:b4ccb530b9eb 454 return false;
nickludlam 0:b4ccb530b9eb 455 }
nickludlam 0:b4ccb530b9eb 456
nickludlam 0:b4ccb530b9eb 457 if (state != lastState)
nickludlam 0:b4ccb530b9eb 458 {
nickludlam 0:b4ccb530b9eb 459 switch (state)
nickludlam 0:b4ccb530b9eb 460 {
nickludlam 0:b4ccb530b9eb 461 case BC_CONNECT_STATE_CONNECTED:
nickludlam 0:b4ccb530b9eb 462 _LOG("connect: Connected\r\n");
nickludlam 0:b4ccb530b9eb 463 break;
nickludlam 0:b4ccb530b9eb 464 case BC_CONNECT_STATE_CONNECTING:
nickludlam 0:b4ccb530b9eb 465 _LOG("connect: Connecting...\r\n");
nickludlam 0:b4ccb530b9eb 466 break;
nickludlam 0:b4ccb530b9eb 467 default:
nickludlam 0:b4ccb530b9eb 468 case BC_CONNECT_STATE_DISCONNECTED:
nickludlam 0:b4ccb530b9eb 469 _LOG("connect: Disconnected\r\n");
nickludlam 0:b4ccb530b9eb 470 break;
nickludlam 0:b4ccb530b9eb 471 }
nickludlam 0:b4ccb530b9eb 472
nickludlam 0:b4ccb530b9eb 473 lastState = state;
nickludlam 0:b4ccb530b9eb 474 }
nickludlam 0:b4ccb530b9eb 475
nickludlam 0:b4ccb530b9eb 476 } while (state != BC_CONNECT_STATE_CONNECTED);
nickludlam 0:b4ccb530b9eb 477 }
nickludlam 0:b4ccb530b9eb 478
nickludlam 0:b4ccb530b9eb 479 return true;
nickludlam 0:b4ccb530b9eb 480 }
nickludlam 0:b4ccb530b9eb 481
nickludlam 0:b4ccb530b9eb 482 bool BERGCloudBase::getClaimingState(uint8_t& state)
nickludlam 0:b4ccb530b9eb 483 {
nickludlam 0:b4ccb530b9eb 484 _BC_SPI_TRANSACTION tr;
nickludlam 0:b4ccb530b9eb 485
nickludlam 0:b4ccb530b9eb 486 initTransaction(&tr);
nickludlam 0:b4ccb530b9eb 487
nickludlam 0:b4ccb530b9eb 488 tr.command = SPI_CMD_GET_CLAIM_STATE;
nickludlam 0:b4ccb530b9eb 489 tr.rx[0].buffer = &state;
nickludlam 0:b4ccb530b9eb 490 tr.rx[0].bufferSize = sizeof(state);
nickludlam 0:b4ccb530b9eb 491
nickludlam 0:b4ccb530b9eb 492 return transaction(&tr);
nickludlam 0:b4ccb530b9eb 493 }
nickludlam 0:b4ccb530b9eb 494
nickludlam 0:b4ccb530b9eb 495 bool BERGCloudBase::getClaimcode(const char (&claimcode)[BC_CLAIMCODE_SIZE_BYTES])
nickludlam 0:b4ccb530b9eb 496 {
nickludlam 0:b4ccb530b9eb 497 _BC_SPI_TRANSACTION tr;
nickludlam 0:b4ccb530b9eb 498
nickludlam 0:b4ccb530b9eb 499 initTransaction(&tr);
nickludlam 0:b4ccb530b9eb 500
nickludlam 0:b4ccb530b9eb 501 tr.command = SPI_CMD_GET_CLAIMCODE;
nickludlam 0:b4ccb530b9eb 502 tr.rx[0].buffer = (uint8_t *)claimcode;
nickludlam 0:b4ccb530b9eb 503 tr.rx[0].bufferSize = sizeof(claimcode);
nickludlam 0:b4ccb530b9eb 504
nickludlam 0:b4ccb530b9eb 505 return transaction(&tr);
nickludlam 0:b4ccb530b9eb 506 }
nickludlam 0:b4ccb530b9eb 507
nickludlam 0:b4ccb530b9eb 508 bool BERGCloudBase::getEUI64(uint8_t type, uint8_t (&eui64)[BC_EUI64_SIZE_BYTES])
nickludlam 0:b4ccb530b9eb 509 {
nickludlam 0:b4ccb530b9eb 510 _BC_SPI_TRANSACTION tr;
nickludlam 0:b4ccb530b9eb 511
nickludlam 0:b4ccb530b9eb 512 initTransaction(&tr);
nickludlam 0:b4ccb530b9eb 513
nickludlam 0:b4ccb530b9eb 514 tr.command = SPI_CMD_GET_EUI64;
nickludlam 0:b4ccb530b9eb 515 tr.tx[0].buffer = &type;
nickludlam 0:b4ccb530b9eb 516 tr.tx[0].dataSize = sizeof(uint8_t);
nickludlam 0:b4ccb530b9eb 517 tr.rx[0].buffer = eui64;
nickludlam 0:b4ccb530b9eb 518 tr.rx[0].bufferSize = sizeof(eui64);
nickludlam 0:b4ccb530b9eb 519
nickludlam 0:b4ccb530b9eb 520 return transaction(&tr);
nickludlam 0:b4ccb530b9eb 521 }
nickludlam 0:b4ccb530b9eb 522
nickludlam 0:b4ccb530b9eb 523 bool BERGCloudBase::getDeviceAddress(uint8_t (&address)[BC_ADDRESS_SIZE_BYTES])
nickludlam 0:b4ccb530b9eb 524 {
nickludlam 0:b4ccb530b9eb 525 _BC_SPI_TRANSACTION tr;
nickludlam 0:b4ccb530b9eb 526
nickludlam 0:b4ccb530b9eb 527 initTransaction(&tr);
nickludlam 0:b4ccb530b9eb 528
nickludlam 0:b4ccb530b9eb 529 tr.command = SPI_CMD_GET_ADDRESS;
nickludlam 0:b4ccb530b9eb 530 tr.rx[0].buffer = address;
nickludlam 0:b4ccb530b9eb 531 tr.rx[0].bufferSize = sizeof(address);
nickludlam 0:b4ccb530b9eb 532
nickludlam 0:b4ccb530b9eb 533 return transaction(&tr);
nickludlam 0:b4ccb530b9eb 534 }
nickludlam 0:b4ccb530b9eb 535
nickludlam 0:b4ccb530b9eb 536 bool BERGCloudBase::setDisplayStyle(uint8_t style)
nickludlam 0:b4ccb530b9eb 537 {
nickludlam 0:b4ccb530b9eb 538 _BC_SPI_TRANSACTION tr;
nickludlam 0:b4ccb530b9eb 539
nickludlam 0:b4ccb530b9eb 540 initTransaction(&tr);
nickludlam 0:b4ccb530b9eb 541
nickludlam 0:b4ccb530b9eb 542 tr.command = SPI_CMD_SET_DISPLAY_STYLE;
nickludlam 0:b4ccb530b9eb 543 tr.tx[0].buffer = &style;
nickludlam 0:b4ccb530b9eb 544 tr.tx[0].dataSize = sizeof(style);
nickludlam 0:b4ccb530b9eb 545
nickludlam 0:b4ccb530b9eb 546 return transaction(&tr);
nickludlam 0:b4ccb530b9eb 547 }
nickludlam 0:b4ccb530b9eb 548
nickludlam 0:b4ccb530b9eb 549 bool BERGCloudBase::clearDisplay(void)
nickludlam 0:b4ccb530b9eb 550 {
nickludlam 0:b4ccb530b9eb 551 return setDisplayStyle(BC_DISPLAY_CLEAR);
nickludlam 0:b4ccb530b9eb 552 }
nickludlam 0:b4ccb530b9eb 553
nickludlam 0:b4ccb530b9eb 554 bool BERGCloudBase::display(const char *text)
nickludlam 0:b4ccb530b9eb 555 {
nickludlam 0:b4ccb530b9eb 556 _BC_SPI_TRANSACTION tr;
nickludlam 0:b4ccb530b9eb 557 uint8_t strLen = 0;
nickludlam 0:b4ccb530b9eb 558 const char *tmp = text;
nickludlam 0:b4ccb530b9eb 559
nickludlam 0:b4ccb530b9eb 560 if (text == NULL)
nickludlam 0:b4ccb530b9eb 561 {
nickludlam 0:b4ccb530b9eb 562 return false;
nickludlam 0:b4ccb530b9eb 563 }
nickludlam 0:b4ccb530b9eb 564
nickludlam 0:b4ccb530b9eb 565 initTransaction(&tr);
nickludlam 0:b4ccb530b9eb 566
nickludlam 0:b4ccb530b9eb 567 /* Get string length excluding terminator */
nickludlam 0:b4ccb530b9eb 568 while ((*tmp++ != '\0') && (strLen < UINT8_MAX))
nickludlam 0:b4ccb530b9eb 569 {
nickludlam 0:b4ccb530b9eb 570 strLen++;
nickludlam 0:b4ccb530b9eb 571 }
nickludlam 0:b4ccb530b9eb 572
nickludlam 0:b4ccb530b9eb 573 tr.command = SPI_CMD_DISPLAY_PRINT;
nickludlam 0:b4ccb530b9eb 574 tr.tx[0].buffer = (uint8_t *)text;
nickludlam 0:b4ccb530b9eb 575 tr.tx[0].dataSize = strLen;
nickludlam 0:b4ccb530b9eb 576
nickludlam 0:b4ccb530b9eb 577 return transaction(&tr);
nickludlam 0:b4ccb530b9eb 578 }
nickludlam 0:b4ccb530b9eb 579
nickludlam 0:b4ccb530b9eb 580 uint16_t BERGCloudBase::Crc16(uint8_t data, uint16_t crc)
nickludlam 0:b4ccb530b9eb 581 {
nickludlam 5:2e04a8b3fc25 582 /* CRC16 CCITT (0x1021) */
nickludlam 0:b4ccb530b9eb 583
nickludlam 5:2e04a8b3fc25 584 uint8_t s;
nickludlam 5:2e04a8b3fc25 585 uint16_t t;
nickludlam 0:b4ccb530b9eb 586
nickludlam 5:2e04a8b3fc25 587 s = data ^ (crc >> 8);
nickludlam 5:2e04a8b3fc25 588 t = s ^ (s >> 4);
nickludlam 5:2e04a8b3fc25 589 return (crc << 8) ^ t ^ (t << 5) ^ (t << 12);
nickludlam 0:b4ccb530b9eb 590 }
nickludlam 0:b4ccb530b9eb 591
nickludlam 0:b4ccb530b9eb 592 uint8_t BERGCloudBase::SPITransaction(uint8_t dataOut, bool finalCS)
nickludlam 0:b4ccb530b9eb 593 {
nickludlam 0:b4ccb530b9eb 594 uint8_t dataIn = 0;
nickludlam 0:b4ccb530b9eb 595
nickludlam 0:b4ccb530b9eb 596 SPITransaction(&dataOut, &dataIn, (uint16_t)1, finalCS);
nickludlam 0:b4ccb530b9eb 597
nickludlam 0:b4ccb530b9eb 598 return dataIn;
nickludlam 0:b4ccb530b9eb 599 }
nickludlam 0:b4ccb530b9eb 600
nickludlam 5:2e04a8b3fc25 601 void BERGCloudBase::lockTake(void)
nickludlam 5:2e04a8b3fc25 602 {
nickludlam 5:2e04a8b3fc25 603 }
nickludlam 5:2e04a8b3fc25 604
nickludlam 5:2e04a8b3fc25 605 void BERGCloudBase::lockRelease(void)
nickludlam 5:2e04a8b3fc25 606 {
nickludlam 5:2e04a8b3fc25 607 }
nickludlam 5:2e04a8b3fc25 608
nickludlam 0:b4ccb530b9eb 609 void BERGCloudBase::begin(void)
nickludlam 0:b4ccb530b9eb 610 {
nickludlam 0:b4ccb530b9eb 611 synced = false;
nickludlam 0:b4ccb530b9eb 612 lastResponse = SPI_RSP_SUCCESS;
nickludlam 0:b4ccb530b9eb 613 }
nickludlam 0:b4ccb530b9eb 614
nickludlam 0:b4ccb530b9eb 615 void BERGCloudBase::end(void)
nickludlam 0:b4ccb530b9eb 616 {
nickludlam 0:b4ccb530b9eb 617 }
nickludlam 0:b4ccb530b9eb 618