BERG Cloud / BERGCloud

Dependents:   LittleCounter-Example

Committer:
nickludlam
Date:
Tue Nov 12 14:38:30 2013 +0000
Revision:
0:b4ccb530b9eb
Child:
4:5a04c00b5b6f
Initial commit

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 0:b4ccb530b9eb 40 uint8_t BERGCloudBase::nullProductKey[BC_PRODUCT_KEY_SIZE_BYTES] = {0};
nickludlam 0:b4ccb530b9eb 41
nickludlam 0:b4ccb530b9eb 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 0:b4ccb530b9eb 258 void BERGCloudBase::initTransaction(_BC_SPI_TRANSACTION *tr)
nickludlam 0:b4ccb530b9eb 259 {
nickludlam 0:b4ccb530b9eb 260 memset(tr, 0x00, sizeof(_BC_SPI_TRANSACTION));
nickludlam 0:b4ccb530b9eb 261 }
nickludlam 0:b4ccb530b9eb 262
nickludlam 0:b4ccb530b9eb 263 bool BERGCloudBase::pollForCommand(uint8_t *commandBuffer, uint16_t commandBufferSize, uint16_t& commandSize, uint8_t& commandID)
nickludlam 0:b4ccb530b9eb 264 {
nickludlam 0:b4ccb530b9eb 265 /* Returns TRUE if a valid command has been received */
nickludlam 0:b4ccb530b9eb 266
nickludlam 0:b4ccb530b9eb 267 _BC_SPI_TRANSACTION tr;
nickludlam 0:b4ccb530b9eb 268 uint8_t cmdID[2] = {0};
nickludlam 0:b4ccb530b9eb 269 uint16_t cmdIDSize = 0;
nickludlam 0:b4ccb530b9eb 270
nickludlam 0:b4ccb530b9eb 271 initTransaction(&tr);
nickludlam 0:b4ccb530b9eb 272
nickludlam 0:b4ccb530b9eb 273 tr.command = SPI_CMD_POLL_FOR_COMMAND;
nickludlam 0:b4ccb530b9eb 274
nickludlam 0:b4ccb530b9eb 275 tr.rx[0].buffer = cmdID;
nickludlam 0:b4ccb530b9eb 276 tr.rx[0].bufferSize = sizeof(cmdID);
nickludlam 0:b4ccb530b9eb 277 tr.rx[0].dataSize = &cmdIDSize;
nickludlam 0:b4ccb530b9eb 278
nickludlam 0:b4ccb530b9eb 279 tr.rx[1].buffer = commandBuffer;
nickludlam 0:b4ccb530b9eb 280 tr.rx[1].bufferSize = commandBufferSize;
nickludlam 0:b4ccb530b9eb 281 tr.rx[1].dataSize = &commandSize;
nickludlam 0:b4ccb530b9eb 282
nickludlam 0:b4ccb530b9eb 283 if (transaction(&tr))
nickludlam 0:b4ccb530b9eb 284 {
nickludlam 0:b4ccb530b9eb 285 commandID = cmdID[1];
nickludlam 0:b4ccb530b9eb 286 return true;
nickludlam 0:b4ccb530b9eb 287 }
nickludlam 0:b4ccb530b9eb 288
nickludlam 0:b4ccb530b9eb 289 commandID = 0;
nickludlam 0:b4ccb530b9eb 290 commandSize = 0;
nickludlam 0:b4ccb530b9eb 291 return false;
nickludlam 0:b4ccb530b9eb 292 }
nickludlam 0:b4ccb530b9eb 293
nickludlam 0:b4ccb530b9eb 294 #ifdef BERGCLOUD_PACK_UNPACK
nickludlam 0:b4ccb530b9eb 295 bool BERGCloudBase::pollForCommand(BERGCloudMessageBuffer& buffer, uint8_t& commandID)
nickludlam 0:b4ccb530b9eb 296 {
nickludlam 0:b4ccb530b9eb 297 /* Returns TRUE if a valid command has been received */
nickludlam 0:b4ccb530b9eb 298
nickludlam 0:b4ccb530b9eb 299 _BC_SPI_TRANSACTION tr;
nickludlam 0:b4ccb530b9eb 300 uint8_t cmdID[2] = {0};
nickludlam 0:b4ccb530b9eb 301 uint16_t cmdIDSize = 0;
nickludlam 0:b4ccb530b9eb 302 uint16_t dataSize = 0;
nickludlam 0:b4ccb530b9eb 303
nickludlam 0:b4ccb530b9eb 304 initTransaction(&tr);
nickludlam 0:b4ccb530b9eb 305 buffer.clear();
nickludlam 0:b4ccb530b9eb 306
nickludlam 0:b4ccb530b9eb 307 tr.command = SPI_CMD_POLL_FOR_COMMAND;
nickludlam 0:b4ccb530b9eb 308
nickludlam 0:b4ccb530b9eb 309 tr.rx[0].buffer = cmdID;
nickludlam 0:b4ccb530b9eb 310 tr.rx[0].bufferSize = sizeof(cmdID);
nickludlam 0:b4ccb530b9eb 311 tr.rx[0].dataSize = &cmdIDSize;
nickludlam 0:b4ccb530b9eb 312
nickludlam 0:b4ccb530b9eb 313 tr.rx[1].buffer = buffer.ptr();
nickludlam 0:b4ccb530b9eb 314 tr.rx[1].bufferSize = buffer.size();
nickludlam 0:b4ccb530b9eb 315 tr.rx[1].dataSize = &dataSize;
nickludlam 0:b4ccb530b9eb 316
nickludlam 0:b4ccb530b9eb 317 if (transaction(&tr))
nickludlam 0:b4ccb530b9eb 318 {
nickludlam 0:b4ccb530b9eb 319 commandID = cmdID[1];
nickludlam 0:b4ccb530b9eb 320 buffer.used(dataSize);
nickludlam 0:b4ccb530b9eb 321 return true;
nickludlam 0:b4ccb530b9eb 322 }
nickludlam 0:b4ccb530b9eb 323
nickludlam 0:b4ccb530b9eb 324 commandID = 0;
nickludlam 0:b4ccb530b9eb 325 buffer.used(0);
nickludlam 0:b4ccb530b9eb 326 return false;
nickludlam 0:b4ccb530b9eb 327 }
nickludlam 0:b4ccb530b9eb 328 #endif
nickludlam 0:b4ccb530b9eb 329
nickludlam 0:b4ccb530b9eb 330 bool BERGCloudBase::_sendEvent(uint8_t eventCode, uint8_t *eventBuffer, uint16_t eventSize, uint8_t command)
nickludlam 0:b4ccb530b9eb 331 {
nickludlam 0:b4ccb530b9eb 332 /* Returns TRUE if the event is sent successfully */
nickludlam 0:b4ccb530b9eb 333
nickludlam 0:b4ccb530b9eb 334 _BC_SPI_TRANSACTION tr;
nickludlam 0:b4ccb530b9eb 335 uint8_t header[4] = {0};
nickludlam 0:b4ccb530b9eb 336
nickludlam 0:b4ccb530b9eb 337 if (eventSize > (SPI_MAX_PAYLOAD_SIZE_BYTES - sizeof(header)))
nickludlam 0:b4ccb530b9eb 338 {
nickludlam 0:b4ccb530b9eb 339 /* Too big */
nickludlam 0:b4ccb530b9eb 340 return false;
nickludlam 0:b4ccb530b9eb 341 }
nickludlam 0:b4ccb530b9eb 342
nickludlam 0:b4ccb530b9eb 343 header[0] = eventCode;
nickludlam 0:b4ccb530b9eb 344
nickludlam 0:b4ccb530b9eb 345 initTransaction(&tr);
nickludlam 0:b4ccb530b9eb 346
nickludlam 0:b4ccb530b9eb 347 tr.command = command;
nickludlam 0:b4ccb530b9eb 348 tr.tx[0].buffer = (uint8_t *)header;
nickludlam 0:b4ccb530b9eb 349 tr.tx[0].dataSize = sizeof(header);
nickludlam 0:b4ccb530b9eb 350 tr.tx[1].buffer = eventBuffer;
nickludlam 0:b4ccb530b9eb 351 tr.tx[1].dataSize = (uint8_t)eventSize;
nickludlam 0:b4ccb530b9eb 352
nickludlam 0:b4ccb530b9eb 353 return transaction(&tr);
nickludlam 0:b4ccb530b9eb 354 }
nickludlam 0:b4ccb530b9eb 355
nickludlam 0:b4ccb530b9eb 356 bool BERGCloudBase::sendEvent(uint8_t eventCode, uint8_t *eventBuffer, uint16_t eventSize)
nickludlam 0:b4ccb530b9eb 357 {
nickludlam 0:b4ccb530b9eb 358 return _sendEvent(eventCode, eventBuffer, eventSize, SPI_CMD_SEND_EVENT_RAW);
nickludlam 0:b4ccb530b9eb 359 }
nickludlam 0:b4ccb530b9eb 360
nickludlam 0:b4ccb530b9eb 361 #ifdef BERGCLOUD_PACK_UNPACK
nickludlam 0:b4ccb530b9eb 362 bool BERGCloudBase::sendEvent(uint8_t eventCode, BERGCloudMessageBuffer& buffer)
nickludlam 0:b4ccb530b9eb 363 {
nickludlam 0:b4ccb530b9eb 364 bool result;
nickludlam 0:b4ccb530b9eb 365
nickludlam 0:b4ccb530b9eb 366 result = _sendEvent(eventCode, buffer.ptr(), buffer.used(), SPI_CMD_SEND_EVENT_PACKED);
nickludlam 0:b4ccb530b9eb 367
nickludlam 0:b4ccb530b9eb 368 buffer.clear();
nickludlam 0:b4ccb530b9eb 369 return result;
nickludlam 0:b4ccb530b9eb 370 }
nickludlam 0:b4ccb530b9eb 371 #endif
nickludlam 0:b4ccb530b9eb 372
nickludlam 0:b4ccb530b9eb 373 bool BERGCloudBase::getConnectionState(uint8_t& state)
nickludlam 0:b4ccb530b9eb 374 {
nickludlam 0:b4ccb530b9eb 375 _BC_SPI_TRANSACTION tr;
nickludlam 0:b4ccb530b9eb 376
nickludlam 0:b4ccb530b9eb 377 initTransaction(&tr);
nickludlam 0:b4ccb530b9eb 378
nickludlam 0:b4ccb530b9eb 379 tr.command = SPI_CMD_GET_CONNECT_STATE;
nickludlam 0:b4ccb530b9eb 380 tr.rx[0].buffer = &state;
nickludlam 0:b4ccb530b9eb 381 tr.rx[0].bufferSize = sizeof(state);
nickludlam 0:b4ccb530b9eb 382
nickludlam 0:b4ccb530b9eb 383 return transaction(&tr);
nickludlam 0:b4ccb530b9eb 384 }
nickludlam 0:b4ccb530b9eb 385
nickludlam 0:b4ccb530b9eb 386 bool BERGCloudBase::getSignalQuality(int8_t& rssi, uint8_t& lqi)
nickludlam 0:b4ccb530b9eb 387 {
nickludlam 0:b4ccb530b9eb 388 _BC_SPI_TRANSACTION tr;
nickludlam 0:b4ccb530b9eb 389
nickludlam 0:b4ccb530b9eb 390 initTransaction(&tr);
nickludlam 0:b4ccb530b9eb 391
nickludlam 0:b4ccb530b9eb 392 tr.command = SPI_CMD_GET_SIGNAL_QUALITY;
nickludlam 0:b4ccb530b9eb 393 tr.rx[0].buffer = (uint8_t *)&rssi;
nickludlam 0:b4ccb530b9eb 394 tr.rx[0].bufferSize = sizeof(rssi);
nickludlam 0:b4ccb530b9eb 395 tr.rx[1].buffer = &lqi;
nickludlam 0:b4ccb530b9eb 396 tr.rx[1].bufferSize = sizeof(lqi);
nickludlam 0:b4ccb530b9eb 397
nickludlam 0:b4ccb530b9eb 398 return transaction(&tr);
nickludlam 0:b4ccb530b9eb 399 }
nickludlam 0:b4ccb530b9eb 400
nickludlam 0:b4ccb530b9eb 401 bool BERGCloudBase::connect(const uint8_t (&productKey)[BC_PRODUCT_KEY_SIZE_BYTES], uint16_t version, bool waitForConnected)
nickludlam 0:b4ccb530b9eb 402 {
nickludlam 0:b4ccb530b9eb 403 _BC_SPI_TRANSACTION tr;
nickludlam 0:b4ccb530b9eb 404 uint16_t hostType = BC_HOST_UNKNOWN;
nickludlam 0:b4ccb530b9eb 405 uint8_t connectData [sizeof(version) + sizeof(hostType)];
nickludlam 0:b4ccb530b9eb 406
nickludlam 0:b4ccb530b9eb 407 uint8_t lastState = BC_CONNECT_STATE_DISCONNECTED;
nickludlam 0:b4ccb530b9eb 408 uint8_t state;
nickludlam 0:b4ccb530b9eb 409
nickludlam 0:b4ccb530b9eb 410 #ifndef BERGCLOUD_NO_HOST_TYPE
nickludlam 0:b4ccb530b9eb 411 /* Get host type */
nickludlam 0:b4ccb530b9eb 412 hostType = getHostType();
nickludlam 0:b4ccb530b9eb 413 #endif
nickludlam 0:b4ccb530b9eb 414
nickludlam 0:b4ccb530b9eb 415 initTransaction(&tr);
nickludlam 0:b4ccb530b9eb 416
nickludlam 0:b4ccb530b9eb 417 connectData[0] = hostType;
nickludlam 0:b4ccb530b9eb 418 connectData[1] = hostType >> 8;
nickludlam 0:b4ccb530b9eb 419 connectData[2] = version;
nickludlam 0:b4ccb530b9eb 420 connectData[3] = version >> 8;
nickludlam 0:b4ccb530b9eb 421
nickludlam 0:b4ccb530b9eb 422 tr.command = SPI_CMD_SEND_PRODUCT_ANNOUNCE;
nickludlam 0:b4ccb530b9eb 423 tr.tx[0].buffer = (uint8_t *)productKey;
nickludlam 0:b4ccb530b9eb 424 tr.tx[0].dataSize = sizeof(productKey);
nickludlam 0:b4ccb530b9eb 425 tr.tx[1].buffer = connectData;
nickludlam 0:b4ccb530b9eb 426 tr.tx[1].dataSize = sizeof(connectData);
nickludlam 0:b4ccb530b9eb 427
nickludlam 0:b4ccb530b9eb 428 if (!transaction(&tr))
nickludlam 0:b4ccb530b9eb 429 {
nickludlam 0:b4ccb530b9eb 430 return false;
nickludlam 0:b4ccb530b9eb 431 }
nickludlam 0:b4ccb530b9eb 432
nickludlam 0:b4ccb530b9eb 433 if (waitForConnected)
nickludlam 0:b4ccb530b9eb 434 {
nickludlam 0:b4ccb530b9eb 435 /* Poll until connected */
nickludlam 0:b4ccb530b9eb 436 do {
nickludlam 0:b4ccb530b9eb 437 timerReset();
nickludlam 0:b4ccb530b9eb 438 while (timerRead_mS() < CONNECT_POLL_RATE_MS);
nickludlam 0:b4ccb530b9eb 439
nickludlam 0:b4ccb530b9eb 440 if (!getConnectionState(state))
nickludlam 0:b4ccb530b9eb 441 {
nickludlam 0:b4ccb530b9eb 442 return false;
nickludlam 0:b4ccb530b9eb 443 }
nickludlam 0:b4ccb530b9eb 444
nickludlam 0:b4ccb530b9eb 445 if (state != lastState)
nickludlam 0:b4ccb530b9eb 446 {
nickludlam 0:b4ccb530b9eb 447 switch (state)
nickludlam 0:b4ccb530b9eb 448 {
nickludlam 0:b4ccb530b9eb 449 case BC_CONNECT_STATE_CONNECTED:
nickludlam 0:b4ccb530b9eb 450 _LOG("connect: Connected\r\n");
nickludlam 0:b4ccb530b9eb 451 break;
nickludlam 0:b4ccb530b9eb 452 case BC_CONNECT_STATE_CONNECTING:
nickludlam 0:b4ccb530b9eb 453 _LOG("connect: Connecting...\r\n");
nickludlam 0:b4ccb530b9eb 454 break;
nickludlam 0:b4ccb530b9eb 455 default:
nickludlam 0:b4ccb530b9eb 456 case BC_CONNECT_STATE_DISCONNECTED:
nickludlam 0:b4ccb530b9eb 457 _LOG("connect: Disconnected\r\n");
nickludlam 0:b4ccb530b9eb 458 break;
nickludlam 0:b4ccb530b9eb 459 }
nickludlam 0:b4ccb530b9eb 460
nickludlam 0:b4ccb530b9eb 461 lastState = state;
nickludlam 0:b4ccb530b9eb 462 }
nickludlam 0:b4ccb530b9eb 463
nickludlam 0:b4ccb530b9eb 464 } while (state != BC_CONNECT_STATE_CONNECTED);
nickludlam 0:b4ccb530b9eb 465 }
nickludlam 0:b4ccb530b9eb 466
nickludlam 0:b4ccb530b9eb 467 return true;
nickludlam 0:b4ccb530b9eb 468 }
nickludlam 0:b4ccb530b9eb 469
nickludlam 0:b4ccb530b9eb 470 bool BERGCloudBase::getClaimingState(uint8_t& state)
nickludlam 0:b4ccb530b9eb 471 {
nickludlam 0:b4ccb530b9eb 472 _BC_SPI_TRANSACTION tr;
nickludlam 0:b4ccb530b9eb 473
nickludlam 0:b4ccb530b9eb 474 initTransaction(&tr);
nickludlam 0:b4ccb530b9eb 475
nickludlam 0:b4ccb530b9eb 476 tr.command = SPI_CMD_GET_CLAIM_STATE;
nickludlam 0:b4ccb530b9eb 477 tr.rx[0].buffer = &state;
nickludlam 0:b4ccb530b9eb 478 tr.rx[0].bufferSize = sizeof(state);
nickludlam 0:b4ccb530b9eb 479
nickludlam 0:b4ccb530b9eb 480 return transaction(&tr);
nickludlam 0:b4ccb530b9eb 481 }
nickludlam 0:b4ccb530b9eb 482
nickludlam 0:b4ccb530b9eb 483 bool BERGCloudBase::getClaimcode(const char (&claimcode)[BC_CLAIMCODE_SIZE_BYTES])
nickludlam 0:b4ccb530b9eb 484 {
nickludlam 0:b4ccb530b9eb 485 _BC_SPI_TRANSACTION tr;
nickludlam 0:b4ccb530b9eb 486
nickludlam 0:b4ccb530b9eb 487 initTransaction(&tr);
nickludlam 0:b4ccb530b9eb 488
nickludlam 0:b4ccb530b9eb 489 tr.command = SPI_CMD_GET_CLAIMCODE;
nickludlam 0:b4ccb530b9eb 490 tr.rx[0].buffer = (uint8_t *)claimcode;
nickludlam 0:b4ccb530b9eb 491 tr.rx[0].bufferSize = sizeof(claimcode);
nickludlam 0:b4ccb530b9eb 492
nickludlam 0:b4ccb530b9eb 493 return transaction(&tr);
nickludlam 0:b4ccb530b9eb 494 }
nickludlam 0:b4ccb530b9eb 495
nickludlam 0:b4ccb530b9eb 496 bool BERGCloudBase::getEUI64(uint8_t type, uint8_t (&eui64)[BC_EUI64_SIZE_BYTES])
nickludlam 0:b4ccb530b9eb 497 {
nickludlam 0:b4ccb530b9eb 498 _BC_SPI_TRANSACTION tr;
nickludlam 0:b4ccb530b9eb 499
nickludlam 0:b4ccb530b9eb 500 initTransaction(&tr);
nickludlam 0:b4ccb530b9eb 501
nickludlam 0:b4ccb530b9eb 502 tr.command = SPI_CMD_GET_EUI64;
nickludlam 0:b4ccb530b9eb 503 tr.tx[0].buffer = &type;
nickludlam 0:b4ccb530b9eb 504 tr.tx[0].dataSize = sizeof(uint8_t);
nickludlam 0:b4ccb530b9eb 505 tr.rx[0].buffer = eui64;
nickludlam 0:b4ccb530b9eb 506 tr.rx[0].bufferSize = sizeof(eui64);
nickludlam 0:b4ccb530b9eb 507
nickludlam 0:b4ccb530b9eb 508 return transaction(&tr);
nickludlam 0:b4ccb530b9eb 509 }
nickludlam 0:b4ccb530b9eb 510
nickludlam 0:b4ccb530b9eb 511 bool BERGCloudBase::getDeviceAddress(uint8_t (&address)[BC_ADDRESS_SIZE_BYTES])
nickludlam 0:b4ccb530b9eb 512 {
nickludlam 0:b4ccb530b9eb 513 _BC_SPI_TRANSACTION tr;
nickludlam 0:b4ccb530b9eb 514
nickludlam 0:b4ccb530b9eb 515 initTransaction(&tr);
nickludlam 0:b4ccb530b9eb 516
nickludlam 0:b4ccb530b9eb 517 tr.command = SPI_CMD_GET_ADDRESS;
nickludlam 0:b4ccb530b9eb 518 tr.rx[0].buffer = address;
nickludlam 0:b4ccb530b9eb 519 tr.rx[0].bufferSize = sizeof(address);
nickludlam 0:b4ccb530b9eb 520
nickludlam 0:b4ccb530b9eb 521 return transaction(&tr);
nickludlam 0:b4ccb530b9eb 522 }
nickludlam 0:b4ccb530b9eb 523
nickludlam 0:b4ccb530b9eb 524 bool BERGCloudBase::setDisplayStyle(uint8_t style)
nickludlam 0:b4ccb530b9eb 525 {
nickludlam 0:b4ccb530b9eb 526 _BC_SPI_TRANSACTION tr;
nickludlam 0:b4ccb530b9eb 527
nickludlam 0:b4ccb530b9eb 528 initTransaction(&tr);
nickludlam 0:b4ccb530b9eb 529
nickludlam 0:b4ccb530b9eb 530 tr.command = SPI_CMD_SET_DISPLAY_STYLE;
nickludlam 0:b4ccb530b9eb 531 tr.tx[0].buffer = &style;
nickludlam 0:b4ccb530b9eb 532 tr.tx[0].dataSize = sizeof(style);
nickludlam 0:b4ccb530b9eb 533
nickludlam 0:b4ccb530b9eb 534 return transaction(&tr);
nickludlam 0:b4ccb530b9eb 535 }
nickludlam 0:b4ccb530b9eb 536
nickludlam 0:b4ccb530b9eb 537 bool BERGCloudBase::clearDisplay(void)
nickludlam 0:b4ccb530b9eb 538 {
nickludlam 0:b4ccb530b9eb 539 return setDisplayStyle(BC_DISPLAY_CLEAR);
nickludlam 0:b4ccb530b9eb 540 }
nickludlam 0:b4ccb530b9eb 541
nickludlam 0:b4ccb530b9eb 542 bool BERGCloudBase::display(const char *text)
nickludlam 0:b4ccb530b9eb 543 {
nickludlam 0:b4ccb530b9eb 544 _BC_SPI_TRANSACTION tr;
nickludlam 0:b4ccb530b9eb 545 uint8_t strLen = 0;
nickludlam 0:b4ccb530b9eb 546 const char *tmp = text;
nickludlam 0:b4ccb530b9eb 547
nickludlam 0:b4ccb530b9eb 548 if (text == NULL)
nickludlam 0:b4ccb530b9eb 549 {
nickludlam 0:b4ccb530b9eb 550 return false;
nickludlam 0:b4ccb530b9eb 551 }
nickludlam 0:b4ccb530b9eb 552
nickludlam 0:b4ccb530b9eb 553 initTransaction(&tr);
nickludlam 0:b4ccb530b9eb 554
nickludlam 0:b4ccb530b9eb 555 /* Get string length excluding terminator */
nickludlam 0:b4ccb530b9eb 556 while ((*tmp++ != '\0') && (strLen < UINT8_MAX))
nickludlam 0:b4ccb530b9eb 557 {
nickludlam 0:b4ccb530b9eb 558 strLen++;
nickludlam 0:b4ccb530b9eb 559 }
nickludlam 0:b4ccb530b9eb 560
nickludlam 0:b4ccb530b9eb 561 tr.command = SPI_CMD_DISPLAY_PRINT;
nickludlam 0:b4ccb530b9eb 562 tr.tx[0].buffer = (uint8_t *)text;
nickludlam 0:b4ccb530b9eb 563 tr.tx[0].dataSize = strLen;
nickludlam 0:b4ccb530b9eb 564
nickludlam 0:b4ccb530b9eb 565 return transaction(&tr);
nickludlam 0:b4ccb530b9eb 566 }
nickludlam 0:b4ccb530b9eb 567
nickludlam 0:b4ccb530b9eb 568 uint16_t BERGCloudBase::Crc16(uint8_t data, uint16_t crc)
nickludlam 0:b4ccb530b9eb 569 {
nickludlam 0:b4ccb530b9eb 570 /* From Ember's code */
nickludlam 0:b4ccb530b9eb 571 crc = (crc >> 8) | (crc << 8);
nickludlam 0:b4ccb530b9eb 572 crc ^= data;
nickludlam 0:b4ccb530b9eb 573 crc ^= (crc & 0xff) >> 4;
nickludlam 0:b4ccb530b9eb 574 crc ^= (crc << 8) << 4;
nickludlam 0:b4ccb530b9eb 575
nickludlam 0:b4ccb530b9eb 576 crc ^= ( (uint8_t) ( (uint8_t) ( (uint8_t) (crc & 0xff) ) << 5)) |
nickludlam 0:b4ccb530b9eb 577 ((uint16_t) ( (uint8_t) ( (uint8_t) (crc & 0xff)) >> 3) << 8);
nickludlam 0:b4ccb530b9eb 578
nickludlam 0:b4ccb530b9eb 579 return crc;
nickludlam 0:b4ccb530b9eb 580 }
nickludlam 0:b4ccb530b9eb 581
nickludlam 0:b4ccb530b9eb 582 uint8_t BERGCloudBase::SPITransaction(uint8_t dataOut, bool finalCS)
nickludlam 0:b4ccb530b9eb 583 {
nickludlam 0:b4ccb530b9eb 584 uint8_t dataIn = 0;
nickludlam 0:b4ccb530b9eb 585
nickludlam 0:b4ccb530b9eb 586 SPITransaction(&dataOut, &dataIn, (uint16_t)1, finalCS);
nickludlam 0:b4ccb530b9eb 587
nickludlam 0:b4ccb530b9eb 588 return dataIn;
nickludlam 0:b4ccb530b9eb 589 }
nickludlam 0:b4ccb530b9eb 590
nickludlam 0:b4ccb530b9eb 591 void BERGCloudBase::begin(void)
nickludlam 0:b4ccb530b9eb 592 {
nickludlam 0:b4ccb530b9eb 593 synced = false;
nickludlam 0:b4ccb530b9eb 594 lastResponse = SPI_RSP_SUCCESS;
nickludlam 0:b4ccb530b9eb 595 }
nickludlam 0:b4ccb530b9eb 596
nickludlam 0:b4ccb530b9eb 597 void BERGCloudBase::end(void)
nickludlam 0:b4ccb530b9eb 598 {
nickludlam 0:b4ccb530b9eb 599 }
nickludlam 0:b4ccb530b9eb 600