The BERG Cloud connection library for mbed. This works in conjunction with the BERG Cloud Devshield available via http://bergcloud.com/platform/devkit/
Dependents: LittleCounter-Example
BERGCloudBase.cpp
00001 /* 00002 00003 BERGCloud library common API 00004 00005 Copyright (c) 2013 BERG Cloud Ltd. http://bergcloud.com/ 00006 00007 Permission is hereby granted, free of charge, to any person obtaining a copy 00008 of this software and associated documentation files (the "Software"), to deal 00009 in the Software without restriction, including without limitation the rights 00010 to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 00011 copies of the Software, and to permit persons to whom the Software is 00012 furnished to do so, subject to the following conditions: 00013 00014 The above copyright notice and this permission notice shall be included in 00015 all copies or substantial portions of the Software. 00016 00017 THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 00018 IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 00019 FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 00020 AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 00021 LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 00022 OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN 00023 THE SOFTWARE. 00024 00025 */ 00026 00027 00028 #define __STDC_LIMIT_MACROS /* Include C99 stdint defines in C++ code */ 00029 #include <stdint.h> 00030 #include <stddef.h> 00031 #include <string.h> /* For memset() */ 00032 00033 #include "BERGCloudBase.h" 00034 00035 #define SPI_POLL_TIMEOUT_MS 1000 00036 #define SPI_SYNC_TIMEOUT_MS 10000 00037 00038 #define CONNECT_POLL_RATE_MS 250 00039 00040 /* MessagePack for named commands and events */ 00041 #define _MP_FIXRAW_MIN 0xa0 00042 #define _MP_FIXRAW_MAX 0xbf 00043 #define _MAX_FIXRAW (_MP_FIXRAW_MAX - _MP_FIXRAW_MIN) 00044 00045 uint8_t BERGCloudBase::nullKey[BC_KEY_SIZE_BYTES] = {0}; 00046 00047 bool BERGCloudBase::_transaction(_BC_SPI_TRANSACTION *tr) 00048 { 00049 uint16_t i, j; 00050 uint8_t rxByte; 00051 bool timeout; 00052 uint8_t dataSize; 00053 uint16_t groupSize; 00054 uint16_t dataCRC; 00055 uint16_t calcCRC; 00056 uint8_t header[SPI_HEADER_SIZE_BYTES]; 00057 uint8_t footer[SPI_FOOTER_SIZE_BYTES]; 00058 00059 /* Check synchronisation */ 00060 if (!synced) 00061 { 00062 timerReset(); 00063 00064 do { 00065 rxByte = SPITransaction(SPI_PROTOCOL_PAD, true); 00066 timeout = timerRead_mS() > SPI_SYNC_TIMEOUT_MS; 00067 00068 } while ((rxByte != SPI_PROTOCOL_RESET) && !timeout); 00069 00070 if (timeout) 00071 { 00072 _LOG("Timeout, sync (BERGCloudBase::transaction)\r\n"); 00073 return false; 00074 } 00075 00076 /* Resynchronisation successful */ 00077 synced = true; 00078 } 00079 00080 /* Calculate total data size */ 00081 dataSize = 0; 00082 00083 for (i=0; i<_TX_GROUPS; i++) 00084 { 00085 dataSize += tr->tx[i].dataSize; 00086 } 00087 00088 /* Initialise CRC */ 00089 calcCRC = 0xffff; 00090 00091 /* Create header */ 00092 header[0] = tr->command; 00093 header[1] = 0x00; /* Reserved */ 00094 header[2] = 0x00; /* Reserved */ 00095 header[3] = dataSize; 00096 00097 /* Send header */ 00098 for (i=0; i<sizeof(header); i++) 00099 { 00100 00101 calcCRC = Crc16(header[i], calcCRC); 00102 rxByte = SPITransaction(header[i], false); 00103 00104 if (rxByte == SPI_PROTOCOL_RESET) 00105 { 00106 _LOG("Reset, send header (BERGCloudBase::transaction)\r\n"); 00107 return false; 00108 } 00109 00110 if (rxByte != SPI_PROTOCOL_PAD) 00111 { 00112 _LOG("SyncErr, send header (BERGCloudBase::transaction)\r\n"); 00113 synced = false; 00114 return false; 00115 } 00116 } 00117 00118 /* Send data groups */ 00119 for (i=0; i<_TX_GROUPS; i++) 00120 { 00121 for (j=0; j<tr->tx[i].dataSize; j++) 00122 { 00123 calcCRC = Crc16(tr->tx[i].buffer[j], calcCRC); 00124 rxByte = SPITransaction(tr->tx[i].buffer[j], false); 00125 00126 if (rxByte == SPI_PROTOCOL_RESET) 00127 { 00128 _LOG("Reset, send data (BERGCloudBase::transaction)\r\n"); 00129 return false; 00130 } 00131 00132 if (rxByte != SPI_PROTOCOL_PAD) 00133 { 00134 _LOG("SyncErr, send data (BERGCloudBase::transaction)\r\n"); 00135 synced = false; 00136 return false; 00137 } 00138 } 00139 } 00140 00141 /* Create footer */ 00142 footer[0] = calcCRC >> 8; 00143 footer[1] = calcCRC & 0xff; 00144 00145 /* Send footer */ 00146 for (i=0; i<sizeof(footer); i++) 00147 { 00148 rxByte = SPITransaction(footer[i], false); 00149 00150 if (rxByte == SPI_PROTOCOL_RESET) 00151 { 00152 _LOG("Reset, send footer (BERGCloudBase::transaction)\r\n"); 00153 return false; 00154 } 00155 00156 if (rxByte != SPI_PROTOCOL_PAD) 00157 { 00158 _LOG("SyncErr, send footer (BERGCloudBase::transaction)\r\n"); 00159 synced = false; 00160 return false; 00161 } 00162 } 00163 00164 /* Poll for response */ 00165 timerReset(); 00166 00167 do { 00168 rxByte = SPITransaction(SPI_PROTOCOL_PAD, false); 00169 00170 if (rxByte == SPI_PROTOCOL_RESET) 00171 { 00172 _LOG("Reset, poll (BERGCloudBase::transaction)\r\n"); 00173 return false; 00174 } 00175 00176 if (rxByte == SPI_PROTOCOL_PENDING) 00177 { 00178 /* Waiting for data; reset timeout */ 00179 timerReset(); 00180 } 00181 00182 timeout = timerRead_mS() > SPI_POLL_TIMEOUT_MS; 00183 00184 } while (((rxByte == SPI_PROTOCOL_PAD) || (rxByte == SPI_PROTOCOL_PENDING)) && !timeout); 00185 00186 if (timeout) 00187 { 00188 _LOG("Timeout, poll (BERGCloudBase::transaction)\r\n"); 00189 synced = false; 00190 return false; 00191 } 00192 00193 /* Initialise CRC */ 00194 calcCRC = 0xffff; 00195 00196 /* Read header, we already have the first byte */ 00197 header[0] = rxByte; 00198 calcCRC = Crc16(header[0], calcCRC); 00199 00200 for (i=1; i < SPI_HEADER_SIZE_BYTES; i++) 00201 { 00202 header[i] = SPITransaction(SPI_PROTOCOL_PAD, false); 00203 calcCRC = Crc16(header[i], calcCRC); 00204 } 00205 00206 /* Get data size */ 00207 dataSize = header[3]; 00208 00209 /* Read data groups */ 00210 for (i=0; i<_RX_GROUPS; i++) 00211 { 00212 groupSize = tr->rx[i].bufferSize; 00213 j = 0; /* Start of the group buffer */ 00214 00215 while((dataSize > 0) && (groupSize > 0)) 00216 { 00217 tr->rx[i].buffer[j] = SPITransaction(SPI_PROTOCOL_PAD, false); 00218 calcCRC = Crc16(tr->rx[i].buffer[j], calcCRC); 00219 00220 /* Next */ 00221 j++; 00222 00223 /* Update the total data remaining and the space remaining in this group. */ 00224 dataSize--; 00225 groupSize--; 00226 } 00227 00228 if (tr->rx[i].dataSize != NULL) 00229 { 00230 /* Return the number of bytes used in this buffer */ 00231 *tr->rx[i].dataSize = tr->rx[i].bufferSize - groupSize; 00232 } 00233 } 00234 00235 if (dataSize > 0) 00236 { 00237 /* Too much data sent */ 00238 _LOG("SizeErr, read data (BERGCloudBase::transaction)\r\n"); 00239 synced = false; 00240 return false; 00241 } 00242 00243 /* Read CRC; set nCS high */ 00244 dataCRC = SPITransaction(SPI_PROTOCOL_PAD, false); /* MSByte */ 00245 dataCRC <<= 8; 00246 dataCRC |= SPITransaction(SPI_PROTOCOL_PAD, true /* nCS -> high */); /* LSByte */ 00247 00248 /* Compare with calculated CRC */ 00249 if (calcCRC != dataCRC) 00250 { 00251 /* Invalid CRC */ 00252 _LOG("CRCErr, read data (BERGCloudBase::transaction)\r\n"); 00253 synced = false; 00254 return false; 00255 } 00256 00257 /* Get reponse code */ 00258 lastResponse = header[0]; 00259 00260 return (lastResponse == SPI_RSP_SUCCESS); 00261 } 00262 00263 bool BERGCloudBase::transaction(_BC_SPI_TRANSACTION *tr) 00264 { 00265 bool result; 00266 00267 /* For thread synchronisation */ 00268 lockTake(); 00269 result = _transaction(tr); 00270 lockRelease(); 00271 00272 return result; 00273 } 00274 00275 void BERGCloudBase::initTransaction(_BC_SPI_TRANSACTION *tr) 00276 { 00277 memset(tr, 0x00, sizeof(_BC_SPI_TRANSACTION)); 00278 } 00279 00280 bool BERGCloudBase::pollForCommand(uint8_t *commandBuffer, uint16_t commandBufferSize, uint16_t& commandSize, uint8_t& commandID) 00281 { 00282 /* Returns TRUE if a valid command has been received */ 00283 00284 _LOG("pollForCommand() methods returning a command ID number have been deprecated.\r\n"); 00285 00286 _BC_SPI_TRANSACTION tr; 00287 uint8_t cmdID[2] = {0}; 00288 uint16_t cmdIDSize = 0; 00289 00290 initTransaction(&tr); 00291 00292 tr.command = SPI_CMD_POLL_FOR_COMMAND; 00293 00294 tr.rx[0].buffer = cmdID; 00295 tr.rx[0].bufferSize = sizeof(cmdID); 00296 tr.rx[0].dataSize = &cmdIDSize; 00297 00298 tr.rx[1].buffer = commandBuffer; 00299 tr.rx[1].bufferSize = commandBufferSize; 00300 tr.rx[1].dataSize = &commandSize; 00301 00302 if (transaction(&tr)) 00303 { 00304 commandID = cmdID[1]; 00305 return true; 00306 } 00307 00308 commandID = 0; 00309 commandSize = 0; 00310 return false; 00311 } 00312 00313 bool BERGCloudBase::pollForCommand(uint8_t *commandBuffer, uint16_t commandBufferSize, uint16_t& commandSize, char *commandName, uint8_t commandNameMaxSize) 00314 { 00315 /* Returns TRUE if a valid command has been received */ 00316 00317 _BC_SPI_TRANSACTION tr; 00318 uint8_t cmdID[2] = {0}; 00319 uint16_t cmdIDSize = 0; 00320 uint8_t commandNameSize; 00321 uint8_t originalCommandNameSize; 00322 uint8_t msgPackByte; 00323 uint16_t command; 00324 00325 if ((commandName == NULL) || (commandNameMaxSize < 2)) 00326 { 00327 return false; 00328 } 00329 00330 initTransaction(&tr); 00331 00332 tr.command = SPI_CMD_POLL_FOR_COMMAND; 00333 00334 tr.rx[0].buffer = cmdID; 00335 tr.rx[0].bufferSize = sizeof(cmdID); 00336 tr.rx[0].dataSize = &cmdIDSize; 00337 00338 tr.rx[1].buffer = commandBuffer; 00339 tr.rx[1].bufferSize = commandBufferSize; 00340 tr.rx[1].dataSize = &commandSize; 00341 00342 if (transaction(&tr)) 00343 { 00344 command = (cmdID[0] << 8) | cmdID[1]; 00345 if (command == BC_COMMAND_NAMED_PACKED) 00346 { 00347 /* Get command name string size */ 00348 msgPackByte = *commandBuffer; 00349 00350 if ((msgPackByte <_MP_FIXRAW_MIN) || (msgPackByte > _MP_FIXRAW_MAX)) 00351 { 00352 /* Invalid */ 00353 return false; 00354 } 00355 00356 commandNameSize = originalCommandNameSize = msgPackByte - _MP_FIXRAW_MIN; 00357 00358 /* Limit to the size of the buffer provided */ 00359 if (commandNameSize > (commandNameMaxSize-1)) /* -1 for null terminator */ 00360 { 00361 commandNameSize = (commandNameMaxSize-1); 00362 } 00363 00364 /* Copy command name string as a null-terminated C string */ 00365 bytecpy((uint8_t *)commandName, (commandBuffer+1), commandNameSize); /* +1 for messagePack fixraw byte */ 00366 commandName[commandNameSize] = '\0'; 00367 00368 /* Move up remaining packed data, update size */ 00369 commandSize -= (originalCommandNameSize + 1); /* +1 for messagePack fixraw byte */ 00370 bytecpy(commandBuffer, commandBuffer + (originalCommandNameSize + 1), commandSize); 00371 return true; 00372 } 00373 } 00374 00375 *commandName = '\0'; 00376 commandSize = 0; 00377 return false; 00378 } 00379 00380 #ifdef BERGCLOUD_PACK_UNPACK 00381 bool BERGCloudBase::pollForCommand(BERGCloudMessageBuffer& buffer, uint8_t& commandID) 00382 { 00383 /* Returns TRUE if a valid command has been received */ 00384 00385 _LOG("pollForCommand() methods returning a command ID number have been deprecated.\r\n"); 00386 00387 _BC_SPI_TRANSACTION tr; 00388 uint8_t cmdID[2] = {0}; 00389 uint16_t cmdIDSize = 0; 00390 uint16_t dataSize = 0; 00391 00392 initTransaction(&tr); 00393 buffer.clear(); 00394 00395 tr.command = SPI_CMD_POLL_FOR_COMMAND; 00396 00397 tr.rx[0].buffer = cmdID; 00398 tr.rx[0].bufferSize = sizeof(cmdID); 00399 tr.rx[0].dataSize = &cmdIDSize; 00400 00401 tr.rx[1].buffer = buffer.ptr(); 00402 tr.rx[1].bufferSize = buffer.size(); 00403 tr.rx[1].dataSize = &dataSize; 00404 00405 if (transaction(&tr)) 00406 { 00407 commandID = cmdID[1]; 00408 buffer.used(dataSize); 00409 return true; 00410 } 00411 00412 commandID = 0; 00413 buffer.used(0); 00414 return false; 00415 } 00416 00417 bool BERGCloudBase::pollForCommand(BERGCloudMessageBuffer& buffer, char *commandName, uint8_t commandNameMaxSize) 00418 { 00419 /* Returns TRUE if a valid command has been received */ 00420 00421 _BC_SPI_TRANSACTION tr; 00422 uint8_t cmdID[2] = {0}; 00423 uint16_t cmdIDSize = 0; 00424 uint16_t dataSize = 0; 00425 uint8_t commandNameSize; 00426 uint8_t originalCommandNameSize; 00427 uint8_t msgPackByte; 00428 uint16_t command; 00429 00430 if ((commandName == NULL) || (commandNameMaxSize < 2)) 00431 { 00432 return false; 00433 } 00434 00435 initTransaction(&tr); 00436 buffer.clear(); 00437 00438 tr.command = SPI_CMD_POLL_FOR_COMMAND; 00439 00440 tr.rx[0].buffer = cmdID; 00441 tr.rx[0].bufferSize = sizeof(cmdID); 00442 tr.rx[0].dataSize = &cmdIDSize; 00443 00444 tr.rx[1].buffer = buffer.ptr(); 00445 tr.rx[1].bufferSize = buffer.size(); 00446 tr.rx[1].dataSize = &dataSize; 00447 00448 if (transaction(&tr)) 00449 { 00450 command = (cmdID[0] << 8) | cmdID[1]; 00451 if (command == BC_COMMAND_NAMED_PACKED) 00452 { 00453 /* Get command name string size */ 00454 msgPackByte = *buffer.ptr(); 00455 00456 if ((msgPackByte <_MP_FIXRAW_MIN) || (msgPackByte > _MP_FIXRAW_MAX)) 00457 { 00458 /* Invalid */ 00459 return false; 00460 } 00461 00462 commandNameSize = originalCommandNameSize = msgPackByte - _MP_FIXRAW_MIN; 00463 00464 /* Limit to the size of the buffer provided */ 00465 if (commandNameSize > (commandNameMaxSize-1)) /* -1 for null terminator */ 00466 { 00467 commandNameSize = (commandNameMaxSize-1); 00468 } 00469 00470 /* Copy command name string as a null-terminated C string */ 00471 bytecpy((uint8_t *)commandName, (buffer.ptr()+1), commandNameSize); /* +1 for messagePack fixraw byte */ 00472 commandName[commandNameSize] = '\0'; 00473 00474 /* Move up remaining packed data, update size */ 00475 dataSize -= (originalCommandNameSize + 1); /* +1 for messagePack fixraw byte */ 00476 bytecpy(buffer.ptr(), buffer.ptr() + (originalCommandNameSize + 1), dataSize); 00477 00478 buffer.used(dataSize); 00479 return true; 00480 } 00481 } 00482 00483 buffer.used(0); 00484 *commandName = '\0'; 00485 return false; 00486 } 00487 #endif 00488 00489 bool BERGCloudBase::_sendEvent(uint8_t eventCode, uint8_t *eventBuffer, uint16_t eventSize, uint8_t command) 00490 { 00491 /* Returns TRUE if the event is sent successfully */ 00492 00493 _LOG("sendEvent() methods using an eventCode number have been deprecated.\r\n"); 00494 00495 _BC_SPI_TRANSACTION tr; 00496 uint8_t header[4] = {0}; 00497 00498 if (eventSize > (SPI_MAX_PAYLOAD_SIZE_BYTES - sizeof(header))) 00499 { 00500 /* Too big */ 00501 return false; 00502 } 00503 00504 header[0] = eventCode; 00505 00506 initTransaction(&tr); 00507 00508 tr.command = command; 00509 tr.tx[0].buffer = (uint8_t *)header; 00510 tr.tx[0].dataSize = sizeof(header); 00511 tr.tx[1].buffer = eventBuffer; 00512 tr.tx[1].dataSize = (uint8_t)eventSize; 00513 00514 return transaction(&tr); 00515 } 00516 00517 bool BERGCloudBase::sendEvent(uint8_t eventCode, uint8_t *eventBuffer, uint16_t eventSize, bool packed) 00518 { 00519 00520 return _sendEvent(eventCode, eventBuffer, eventSize, packed ? SPI_CMD_SEND_EVENT_PACKED : SPI_CMD_SEND_EVENT_RAW); 00521 } 00522 00523 bool BERGCloudBase::sendEvent(const char *eventName, uint8_t *eventBuffer, uint16_t eventSize, bool packed) 00524 { 00525 /* Returns TRUE if the event is sent successfully */ 00526 00527 _BC_SPI_TRANSACTION tr; 00528 uint8_t headerSize = 5; /* Four bytes of SPI header, one byte of messagePack type */ 00529 uint8_t header[5 + _MAX_FIXRAW] = {0}; /* Header size plus maximum name string size */ 00530 00531 if (!packed) 00532 { 00533 /* We only support packed data now */ 00534 return false; 00535 } 00536 00537 if ((eventName == NULL) || (eventName[0] == '\0')) 00538 { 00539 _LOG("Event name must be at least one character.\r\n"); 00540 return false; 00541 } 00542 00543 /* Create SPI header */ 00544 header[0] = BC_EVENT_NAMED_PACKED & BC_EVENT_ID_MASK; 00545 header[1] = 0; 00546 header[2] = 0; 00547 header[3] = 0; 00548 00549 /* Create string header in messagePack format */ 00550 header[4] = _MP_FIXRAW_MIN; 00551 while ((*eventName != '\0') && (headerSize < sizeof(header))) 00552 { 00553 /* Copy string, update messagePack byte */ 00554 header[4]++; 00555 header[headerSize++] = *eventName++; 00556 } 00557 00558 if (eventSize > ((uint16_t)SPI_MAX_PAYLOAD_SIZE_BYTES - headerSize)) 00559 { 00560 _LOG("Event is too big.\r\n"); 00561 return false; 00562 } 00563 00564 initTransaction(&tr); 00565 00566 tr.command = SPI_CMD_SEND_EVENT_PACKED; 00567 tr.tx[0].buffer = (uint8_t *)header; 00568 tr.tx[0].dataSize = headerSize; 00569 tr.tx[1].buffer = eventBuffer; 00570 tr.tx[1].dataSize = eventSize; 00571 00572 return transaction(&tr); 00573 } 00574 00575 #ifdef BERGCLOUD_PACK_UNPACK 00576 bool BERGCloudBase::sendEvent(uint8_t eventCode, BERGCloudMessageBuffer& buffer) 00577 { 00578 bool result; 00579 00580 result = _sendEvent(eventCode, buffer.ptr(), buffer.used(), SPI_CMD_SEND_EVENT_PACKED); 00581 00582 buffer.clear(); 00583 return result; 00584 } 00585 00586 bool BERGCloudBase::sendEvent(const char *eventName, BERGCloudMessageBuffer& buffer) 00587 { 00588 /* Returns TRUE if the event is sent successfully */ 00589 00590 _BC_SPI_TRANSACTION tr; 00591 uint8_t headerSize = 5; /* Four bytes of SPI header, one byte of messagePack type */ 00592 uint8_t header[5 + _MAX_FIXRAW] = {0}; /* Header size plus maximum name string size */ 00593 00594 if ((eventName == NULL) || (eventName[0] == '\0')) 00595 { 00596 _LOG("Event name must be at least one character.\r\n"); 00597 return false; 00598 } 00599 00600 /* Create SPI header */ 00601 header[0] = BC_EVENT_NAMED_PACKED & BC_EVENT_ID_MASK; 00602 header[1] = 0; 00603 header[2] = 0; 00604 header[3] = 0; 00605 00606 /* Create string header in messagePack format */ 00607 header[4] = _MP_FIXRAW_MIN; 00608 while ((*eventName != '\0') && (headerSize < sizeof(header))) 00609 { 00610 /* Copy string, update messagePack byte */ 00611 header[4]++; 00612 header[headerSize++] = *eventName++; 00613 } 00614 00615 if (buffer.used() > ((uint16_t)SPI_MAX_PAYLOAD_SIZE_BYTES - headerSize)) 00616 { 00617 _LOG("Event is too big.\r\n"); 00618 return false; 00619 } 00620 00621 initTransaction(&tr); 00622 00623 tr.command = SPI_CMD_SEND_EVENT_PACKED; 00624 tr.tx[0].buffer = (uint8_t *)header; 00625 tr.tx[0].dataSize = headerSize; 00626 tr.tx[1].buffer = buffer.ptr(); 00627 tr.tx[1].dataSize = buffer.used(); 00628 00629 return transaction(&tr); 00630 } 00631 #endif 00632 00633 bool BERGCloudBase::getConnectionState(uint8_t& state) 00634 { 00635 _BC_SPI_TRANSACTION tr; 00636 00637 initTransaction(&tr); 00638 00639 tr.command = SPI_CMD_GET_CONNECT_STATE; 00640 tr.rx[0].buffer = &state; 00641 tr.rx[0].bufferSize = sizeof(state); 00642 00643 return transaction(&tr); 00644 } 00645 00646 bool BERGCloudBase::getSignalQuality(int8_t& rssi, uint8_t& lqi) 00647 { 00648 _BC_SPI_TRANSACTION tr; 00649 00650 initTransaction(&tr); 00651 00652 tr.command = SPI_CMD_GET_SIGNAL_QUALITY; 00653 tr.rx[0].buffer = (uint8_t *)&rssi; 00654 tr.rx[0].bufferSize = sizeof(rssi); 00655 tr.rx[1].buffer = &lqi; 00656 tr.rx[1].bufferSize = sizeof(lqi); 00657 00658 return transaction(&tr); 00659 } 00660 00661 bool BERGCloudBase::connect(const uint8_t (&key)[BC_KEY_SIZE_BYTES], uint16_t version, bool waitForConnected) 00662 { 00663 _BC_SPI_TRANSACTION tr; 00664 uint16_t hostType = BC_HOST_UNKNOWN; 00665 uint8_t connectData [sizeof(version) + sizeof(hostType)]; 00666 00667 uint8_t lastState = BC_CONNECT_STATE_DISCONNECTED; 00668 uint8_t state; 00669 00670 #ifndef BERGCLOUD_NO_HOST_TYPE 00671 /* Get host type */ 00672 hostType = getHostType(); 00673 #endif 00674 00675 initTransaction(&tr); 00676 00677 connectData[0] = hostType; 00678 connectData[1] = hostType >> 8; 00679 connectData[2] = version; 00680 connectData[3] = version >> 8; 00681 00682 tr.command = SPI_CMD_SEND_ANNOUNCE; 00683 tr.tx[0].buffer = (uint8_t *)key; 00684 tr.tx[0].dataSize = sizeof(key); 00685 tr.tx[1].buffer = connectData; 00686 tr.tx[1].dataSize = sizeof(connectData); 00687 00688 if (!transaction(&tr)) 00689 { 00690 return false; 00691 } 00692 00693 if (waitForConnected) 00694 { 00695 /* Poll until connected */ 00696 do { 00697 timerReset(); 00698 while (timerRead_mS() < CONNECT_POLL_RATE_MS); 00699 00700 if (!getConnectionState(state)) 00701 { 00702 return false; 00703 } 00704 00705 if (state != lastState) 00706 { 00707 switch (state) 00708 { 00709 case BC_CONNECT_STATE_CONNECTED: 00710 _LOG("connect: Connected\r\n"); 00711 break; 00712 case BC_CONNECT_STATE_CONNECTING: 00713 _LOG("connect: Connecting...\r\n"); 00714 break; 00715 default: 00716 case BC_CONNECT_STATE_DISCONNECTED: 00717 _LOG("connect: Disconnected\r\n"); 00718 break; 00719 } 00720 00721 lastState = state; 00722 } 00723 00724 } while (state != BC_CONNECT_STATE_CONNECTED); 00725 } 00726 00727 return true; 00728 } 00729 00730 bool BERGCloudBase::connect(const char *key, uint16_t version, bool waitForConnected) 00731 { 00732 unsigned int tmp_key[BC_KEY_SIZE_BYTES] = {0}; 00733 uint8_t _key[BC_KEY_SIZE_BYTES] = {0}; 00734 uint8_t i; 00735 00736 /* Convert key from ASCII */ 00737 if (key != NULL) 00738 { 00739 if (sscanf(key, "%2x%2x%2x%2x%2x%2x%2x%2x%2x%2x%2x%2x%2x%2x%2x%2x", 00740 &tmp_key[0], &tmp_key[1], &tmp_key[2], &tmp_key[3], 00741 &tmp_key[4], &tmp_key[5], &tmp_key[6], &tmp_key[7], 00742 &tmp_key[8], &tmp_key[9], &tmp_key[10], &tmp_key[11], 00743 &tmp_key[12], &tmp_key[13], &tmp_key[14], &tmp_key[15]) == 16) 00744 { 00745 for (i=0; i<sizeof(_key); i++) 00746 { 00747 _key[i] = (uint8_t)tmp_key[i]; 00748 } 00749 } 00750 } 00751 00752 return connect(_key, version, waitForConnected); 00753 } 00754 00755 bool BERGCloudBase::getClaimingState(uint8_t& state) 00756 { 00757 _BC_SPI_TRANSACTION tr; 00758 00759 initTransaction(&tr); 00760 00761 tr.command = SPI_CMD_GET_CLAIM_STATE; 00762 tr.rx[0].buffer = &state; 00763 tr.rx[0].bufferSize = sizeof(state); 00764 00765 return transaction(&tr); 00766 } 00767 00768 bool BERGCloudBase::getClaimcode(const char (&claimcode)[BC_CLAIMCODE_SIZE_BYTES]) 00769 { 00770 _BC_SPI_TRANSACTION tr; 00771 00772 initTransaction(&tr); 00773 00774 tr.command = SPI_CMD_GET_CLAIMCODE; 00775 tr.rx[0].buffer = (uint8_t *)claimcode; 00776 tr.rx[0].bufferSize = sizeof(claimcode); 00777 00778 return transaction(&tr); 00779 } 00780 00781 bool BERGCloudBase::getEUI64(uint8_t type, uint8_t (&eui64)[BC_EUI64_SIZE_BYTES]) 00782 { 00783 _BC_SPI_TRANSACTION tr; 00784 00785 initTransaction(&tr); 00786 00787 tr.command = SPI_CMD_GET_EUI64; 00788 tr.tx[0].buffer = &type; 00789 tr.tx[0].dataSize = sizeof(uint8_t); 00790 tr.rx[0].buffer = eui64; 00791 tr.rx[0].bufferSize = sizeof(eui64); 00792 00793 return transaction(&tr); 00794 } 00795 00796 bool BERGCloudBase::getDeviceAddress(uint8_t (&address)[BC_ADDRESS_SIZE_BYTES]) 00797 { 00798 _BC_SPI_TRANSACTION tr; 00799 00800 initTransaction(&tr); 00801 00802 tr.command = SPI_CMD_GET_ADDRESS; 00803 tr.rx[0].buffer = address; 00804 tr.rx[0].bufferSize = sizeof(address); 00805 00806 return transaction(&tr); 00807 } 00808 00809 bool BERGCloudBase::setDisplayStyle(uint8_t style) 00810 { 00811 _BC_SPI_TRANSACTION tr; 00812 00813 initTransaction(&tr); 00814 00815 tr.command = SPI_CMD_SET_DISPLAY_STYLE; 00816 tr.tx[0].buffer = &style; 00817 tr.tx[0].dataSize = sizeof(style); 00818 00819 return transaction(&tr); 00820 } 00821 00822 bool BERGCloudBase::clearDisplay(void) 00823 { 00824 return setDisplayStyle(BC_DISPLAY_CLEAR); 00825 } 00826 00827 bool BERGCloudBase::display(const char *text) 00828 { 00829 _BC_SPI_TRANSACTION tr; 00830 uint8_t strLen = 0; 00831 const char *tmp = text; 00832 00833 if (text == NULL) 00834 { 00835 return false; 00836 } 00837 00838 initTransaction(&tr); 00839 00840 /* Get string length excluding terminator */ 00841 while ((*tmp++ != '\0') && (strLen < UINT8_MAX)) 00842 { 00843 strLen++; 00844 } 00845 00846 tr.command = SPI_CMD_DISPLAY_PRINT; 00847 tr.tx[0].buffer = (uint8_t *)text; 00848 tr.tx[0].dataSize = strLen; 00849 00850 return transaction(&tr); 00851 } 00852 00853 uint16_t BERGCloudBase::Crc16(uint8_t data, uint16_t crc) 00854 { 00855 /* CRC16 CCITT (0x1021) */ 00856 00857 uint8_t s; 00858 uint16_t t; 00859 00860 s = data ^ (crc >> 8); 00861 t = s ^ (s >> 4); 00862 return (crc << 8) ^ t ^ (t << 5) ^ (t << 12); 00863 } 00864 00865 uint8_t BERGCloudBase::SPITransaction(uint8_t dataOut, bool finalCS) 00866 { 00867 uint8_t dataIn = 0; 00868 00869 SPITransaction(&dataOut, &dataIn, (uint16_t)1, finalCS); 00870 00871 return dataIn; 00872 } 00873 00874 void BERGCloudBase::lockTake(void) 00875 { 00876 } 00877 00878 void BERGCloudBase::lockRelease(void) 00879 { 00880 } 00881 00882 void BERGCloudBase::begin(void) 00883 { 00884 synced = false; 00885 lastResponse = SPI_RSP_SUCCESS; 00886 00887 /* Print library version */ 00888 _LOG("\r\nBERGCloud library version "); 00889 _LOG_HEX(BERGCLOUD_LIB_VERSION >> 8); 00890 _LOG("."); 00891 _LOG_HEX(BERGCLOUD_LIB_VERSION & 0xff); 00892 _LOG("\r\n"); 00893 } 00894 00895 void BERGCloudBase::end(void) 00896 { 00897 } 00898 00899 void BERGCloudBase::bytecpy(uint8_t *dst, uint8_t *src, uint16_t size) 00900 { 00901 /* memcpy() cannot be used when buffers overlap */ 00902 while (size-- > 0) 00903 { 00904 *dst++ = *src++; 00905 } 00906 } 00907
Generated on Sun Jul 17 2022 20:45:26 by
1.7.2
BERG Cloud


