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

Embed: (wiki syntax)

« Back to documentation index

Show/hide line numbers BERGCloudBase.cpp Source File

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