A mbed library for the RN2483. Heavily based on the Sodaq_RN2483 library for Arduino (https://github.com/SodaqMoja/Sodaq_RN2483). This is currently under-going initial testing, but seems to work! Tested on a NRF51 and FRDM K64F.
Dependents: rn2483-TestProgram
Diff: RN2483.cpp
- Revision:
- 1:cf9b0c21907a
- Parent:
- 0:a8609e6f88f3
- Child:
- 2:336a025b82b5
--- a/RN2483.cpp Tue Nov 08 17:11:08 2016 +0000 +++ b/RN2483.cpp Sat Nov 19 23:30:34 2016 +0000 @@ -3,28 +3,31 @@ #include "Utils.h" // Structure for mapping error response strings and error codes. -typedef struct StringEnumPair -{ +typedef struct StringEnumPair { const char* stringValue; uint8_t enumValue; } StringEnumPair_t; - -// Creates a new RN2483 instance. -RN2483::RN2483(PinName tx, PinName rx) : +/** +* @brief Create a new instance of the RN2483. +* @param Serial TX pin name. +* @param Serial RX pin name. +*/ +RN2483::RN2483(PinName tx, PinName rx) : _RN2483(tx, rx, getDefaultBaudRate()), inputBufferSize(DEFAULT_INPUT_BUFFER_SIZE), receivedPayloadBufferSize(DEFAULT_RECEIVED_PAYLOAD_BUFFER_SIZE), packetReceived(false), - isRN2903(false) + isRN2903(false) { #ifdef USE_DYNAMIC_BUFFER this->isBufferInitialized = false; #endif - } - -// Takes care of the init tasks common to both initOTA() and initABP. + +/** +* @brief Takes care of the init tasks common to both initOTA() and initABP. +*/ void RN2483::init() { #ifdef USE_DYNAMIC_BUFFER @@ -36,56 +39,79 @@ } #endif // make sure the module's state is synced and woken up - sleep(); + sleep(259200000); wakeUp(); } -// Initializes the device and connects to the network using Over-The-Air Activation. -// Returns true on successful connection. +/** +* @brief Connect to network using Over The Air activation. +* @param devEUI provided by LoRaWAN Network server registration. +* @param appEUI provided by LoRaWAN Network server registration. +* @param appKey provided by LoRaWAN Network server registration. +* @return Network confirmation if sucessfully connected. +*/ bool RN2483::initOTA(const uint8_t devEUI[8], const uint8_t appEUI[8], const uint8_t appKey[16], bool adr) { init(); return resetDevice() && - setMacParam(STR_DEV_EUI, devEUI, 8) && - setMacParam(STR_APP_EUI, appEUI, 8) && - setMacParam(STR_APP_KEY, appKey, 16) && - setMacParam(STR_ADR, BOOL_TO_ONOFF(adr)) && - joinNetwork(STR_OTAA); + setMacParam(STR_DEV_EUI, devEUI, 8) && + setMacParam(STR_APP_EUI, appEUI, 8) && + setMacParam(STR_APP_KEY, appKey, 16) && + setMacParam(STR_ADR, BOOL_TO_ONOFF(adr)) && + joinNetwork(STR_OTAA); } -// Initializes the device and connects to the network using Activation By Personalization. -// Returns true on successful connection. +/** +* @brief Initializes the device and connects to the network using Activation By Personalization. +* @param devADDR provided by LoRaWAN Network server registration. +* @param appSKey provided by LoRaWAN Network server registration. +* @param nwkSKey provided by LoRaWAN Network server registration. +* @return Returns true if the parameters was valid. +*/ bool RN2483::initABP(const uint8_t devAddr[4], const uint8_t appSKey[16], const uint8_t nwkSKey[16], bool adr) { init(); return resetDevice() && - setMacParam(STR_DEV_ADDR, devAddr, 4) && - setMacParam(STR_APP_SESSION_KEY, appSKey, 16) && - setMacParam(STR_NETWORK_SESSION_KEY, nwkSKey, 16) && - setMacParam(STR_ADR, BOOL_TO_ONOFF(adr)) && - joinNetwork(STR_ABP); + setMacParam(STR_DEV_ADDR, devAddr, 4) && + setMacParam(STR_APP_SESSION_KEY, appSKey, 16) && + setMacParam(STR_NETWORK_SESSION_KEY, nwkSKey, 16) && + setMacParam(STR_ADR, BOOL_TO_ONOFF(adr)) && + joinNetwork(STR_ABP); } - -// Sends the given payload without acknowledgement. -// Returns 0 (NoError) when transmission is successful or one of the MacTransmitErrorCodes otherwise. + +/** +* @brief Sends the given payload without acknowledgement. +* @param Port to use for transmission. +* @param Payload buffer +* @param Payload buffer size +* @return Returns 0 (NoError) when data was sucessfully fowarded to radio, otherwise returns MacTransmitErrorCode. +*/ uint8_t RN2483::send(uint8_t port, const uint8_t* payload, uint8_t size) { return macTransmit(STR_UNCONFIRMED, port, payload, size); } -// Sends the given payload with acknowledgement. -// Returns 0 (NoError) when transmission is successful or one of the MacTransmitErrorCodes otherwise. -uint8_t RN2483::sendReqAck(uint8_t port, const uint8_t* payload, - uint8_t size, uint8_t maxRetries) +/** +* @brief Sends the given payload with acknowledgement. +* @param Port to use for transmission. +* @param Payload buffer +* @param Payload buffer size +* @param Number of transmission retries in event of network transmission failure. +* @return Returns 0 (NoError) when network acks transmission, otherwise returns MacTransmitErrorCode. +*/ +uint8_t RN2483::sendReqAck(uint8_t port, const uint8_t* payload, uint8_t size, uint8_t maxRetries) { return macTransmit(STR_CONFIRMED, port, payload, size); } -// Copies the latest received packet (optionally starting from the "payloadStartPosition" -// position of the payload) into the given "buffer", up to "size" number of bytes. -// Returns the number of bytes written or 0 if no packet is received since last transmission. +/** +* @brief Copies the latest received packet (optionally starting from the "payloadStartPosition" of the payload). +* @param Buffer to read into. +* @param Buffer size. +* @return Returns the number of bytes written or 0 if no packet is received since last transmission. +*/ uint16_t RN2483::receive(uint8_t* buffer, uint16_t size, - uint16_t payloadStartPosition) + uint16_t payloadStartPosition) { if (!this->packetReceived) { @@ -102,12 +128,12 @@ // stop at the first string termination char, or if output buffer is over, or if payload buffer is over while (outputIndex < size - && inputIndex + 1 < this->receivedPayloadBufferSize - && this->receivedPayloadBuffer[inputIndex] != 0 - && this->receivedPayloadBuffer[inputIndex + 1] != 0) { + && inputIndex + 1 < this->receivedPayloadBufferSize + && this->receivedPayloadBuffer[inputIndex] != 0 + && this->receivedPayloadBuffer[inputIndex + 1] != 0) { buffer[outputIndex] = HEX_PAIR_TO_BYTE( - this->receivedPayloadBuffer[inputIndex], - this->receivedPayloadBuffer[inputIndex + 1]); + this->receivedPayloadBuffer[inputIndex], + this->receivedPayloadBuffer[inputIndex + 1]); inputIndex += 2; outputIndex++; @@ -120,8 +146,12 @@ return outputIndex; } -// Gets the preprogrammed EUI node address from the module. -// Returns the number of bytes written or 0 in case of error. +/** +* @brief Gets the preprogrammed EUI node address from the module. +* @param Buffer to read into. +* @param Buffer size. +* @return Returns the number of bytes written or 0 in case of error.. +*/ uint8_t RN2483::getHWEUI(uint8_t* buffer, uint8_t size) { _RN2483.printf(STR_CMD_GET_HWEUI); @@ -133,16 +163,16 @@ Timer t; t.start(); - unsigned long start = t.read_ms (); + int start = t.read_ms (); while (t.read_ms () < start + DEFAULT_TIMEOUT) { if (readLn() > 0) { while (outputIndex < size - && inputIndex + 1 < this->inputBufferSize - && this->inputBuffer[inputIndex] != 0 - && this->inputBuffer[inputIndex + 1] != 0) { + && inputIndex + 1 < this->inputBufferSize + && this->inputBuffer[inputIndex] != 0 + && this->inputBuffer[inputIndex + 1] != 0) { buffer[outputIndex] = HEX_PAIR_TO_BYTE( - this->inputBuffer[inputIndex], - this->inputBuffer[inputIndex + 1]); + this->inputBuffer[inputIndex], + this->inputBuffer[inputIndex + 1]); inputIndex += 2; outputIndex++; } @@ -150,12 +180,14 @@ return outputIndex; } } - t.stop(); + t.stop(); return 0; } #ifdef ENABLE_SLEEP - +/** +* @brief Sends a serial line break to wake up the RN2483 +*/ void RN2483::wakeUp() { // "emulate" break condition @@ -165,17 +197,36 @@ _RN2483.putc((uint8_t)0x55); } +/** +* @brief Sends the RN2483 to sleep for a finite length of time. +* @param Milliseconds to sleep for. +*/ +void RN2483::sleep(uint32_t sleepLength) +{ + if(sleepLength < 4294967296 && sleepLength > 100) { + _RN2483.printf("%s%u",STR_CMD_SLEEP,sleepLength); + _RN2483.printf(CRLF); + } +} + +/** +* @brief Sends the RN2483 to sleep for a finite length of time. +* Roughly three days. +*/ void RN2483::sleep() { - _RN2483.printf(STR_CMD_SLEEP); - _RN2483.printf(CRLF); + sleep(4294967295); } - #endif -// Reads a line from the device stream into the "buffer" starting at the "start" position of the buffer. -// Returns the number of bytes read. +/** +* @brief Reads a line from the device serial stream. +* @param Buffer to read into. +* @param Size of buffer. +* @param Position to start from. +* @return Number of bytes read. +*/ uint16_t RN2483::readLn(char* buffer, uint16_t size, uint16_t start) { int len = readBytesUntil('\n', buffer + start, size); @@ -186,20 +237,26 @@ return len; } -// Waits for the given string. Returns true if the string is received before a timeout. -// Returns false if a timeout occurs or if another string is received. +/** +* @brief Waits for the given string. +* @param String to look for. +* @param Timeout Period +* @param Position to start from. +* @return Returns true if the string is received before a timeout. +* Returns false if a timeout occurs or if another string is received. +*/ bool RN2483::expectString(const char* str, uint16_t timeout) { Timer t; t.start(); - unsigned long start = t.read_ms(); + int start = t.read_ms(); while (t.read_ms() < start + timeout) { if (readLn() > 0) { if (strstr(this->inputBuffer, str) != NULL) { t.stop(); return true; } - t.stop(); + t.stop(); return false; } } @@ -207,14 +264,21 @@ return false; } +/** +* @brief Looks for an 'OK' response from the RN2483 +* @return Returns true if the string is received before a timeout. +* Returns false if a timeout occurs or if another string is received. +*/ bool RN2483::expectOK() { return expectString(STR_RESULT_OK); } -// Sends a reset command to the module and waits for the success response (or timeout). -// Also sets-up some initial parameters like power index, SF and FSB channels. -// Returns true on success. +/** +* @brief Sends a reset command to the module +* Also sets-up some initial parameters like power index, SF and FSB channels. +* @return Waits for sucess reponse or timeout. +*/ bool RN2483::resetDevice() { _RN2483.printf(STR_CMD_RESET); @@ -223,27 +287,27 @@ if (strstr(this->inputBuffer, STR_DEVICE_TYPE_RN2483) != NULL) { isRN2903 = false; return setPowerIndex(DEFAULT_PWR_IDX_868) && - setSpreadingFactor(DEFAULT_SF_868); - } - else if (strstr(this->inputBuffer, STR_DEVICE_TYPE_RN2903) != NULL) { + setSpreadingFactor(DEFAULT_SF_868); + } else if (strstr(this->inputBuffer, STR_DEVICE_TYPE_RN2903) != NULL) { // TODO move into init once it is decided how to handle RN2903-specific operations isRN2903 = true; return setFsbChannels(DEFAULT_FSB) && - setPowerIndex(DEFAULT_PWR_IDX_915) && - setSpreadingFactor(DEFAULT_SF_915); - } - else { + setPowerIndex(DEFAULT_PWR_IDX_915) && + setSpreadingFactor(DEFAULT_SF_915); + } else { return false; } } return false; } -// Enables all the channels that belong to the given Frequency Sub-Band (FSB) -// and disables the rest. -// fsb is [1, 8] or 0 to enable all channels. -// Returns true if all channels were set successfully. +/** +* @brief Enables all the channels that belong to the given Frequency Sub-Band (FSB) +* disables the rest. +* @param FSB is [1, 8] or 0 to enable all channels. +* @return Returns true if all channels were set successfully. +*/ bool RN2483::setFsbChannels(uint8_t fsb) { uint8_t first125kHzChannel = fsb > 0 ? (fsb - 1) * 8 : 0; @@ -264,18 +328,18 @@ return allOk; } -// Sets the spreading factor. -// In reality it sets the datarate of the module according to the -// LoraWAN specs mapping for 868MHz and 915MHz, -// using the given spreading factor parameter. +/** +* @brief Sets the spreading factor. +* @param Spreading factor parameter. +* @return Returns true if was set successfully. +*/ bool RN2483::setSpreadingFactor(uint8_t spreadingFactor) { int8_t datarate; if (!isRN2903) { // RN2483 SF(DR) = 7(5), 8(4), 9(3), 10(2), 11(1), 12(0) datarate = 12 - spreadingFactor; - } - else { + } else { // RN2903 SF(DR) = 7(3), 8(2), 9(1), 10(0) datarate = 10 - spreadingFactor; } @@ -287,17 +351,157 @@ return false; } -// Sets the power index (868MHz: 1 to 5 / 915MHz: 5, 7, 8, 9 or 10) -// Returns true if succesful. +/** +* @brief Sets the power index +* @param 868MHz: 1 to 5 / 915MHz: 5, 7, 8, 9 or 10. +* @return Returns true if succesful. +*/ bool RN2483::setPowerIndex(uint8_t powerIndex) { return setMacParam(STR_PWR_IDX, powerIndex); } -// Sends the command together with the given paramValue (optional) -// to the device and awaits for the response. -// Returns true on success. -// NOTE: command should include a trailing space if paramValue is set +/** +* @brief Sets the time interval for the link check process. When the time expires, the next application +* packet will include a link check command to the server. +* @param Decimal number that sets the time interval in seconds, from 0 to 65535. 0 disables link check process. +* @return Returns true if parameter is valid or false if time interval is not valid. +*/ +bool RN2483::setLinkCheckInterval(uint8_t linkCheckInterval) +{ + if(linkCheckInterval <= 65535) { + return setMacParam(STR_LNK_CHK, linkCheckInterval); + } else { + return 0; + } +} + +/** +* @brief Sets the battery level required for the Device Status Answer frame in LoRaWAN Class A Protocol. +* @param temperature Decimal number between 0-255 representing battery level. 0 means external power, 1 means +* low level, 254 means high level, 255 means the device was unable to measure battery level. +* @return Returns true if battery level is valid or false if value not valid. +*/ +bool RN2483::setBattery(uint8_t batLvl) +{ + if(batLvl <= 255) { + return setMacParam(STR_BAT, batLvl); + } else { + return 0; + } +} + +/** +* @brief Sets the module operation frequency on a given channel ID. +* @param Channel ID from 3 - 15. +* @param Decimal number representing the frequency. +* 863000000 to 870000000 or 433050000 to 434790000 in Hz +* @return Returns true if parameters are valid or false if not. +*/ +bool RN2483::setChannelFreq(uint8_t channelID, uint32_t frequency){ + if((channelID <= 15 && channelID >= 3)){ + if((frequency <=870000000 && frequency >= 863000000)||(frequency <=434790000 && frequency >= 433050000)){ + char buffer [15]; + int bytesWritten = sprintf(buffer, "%d %d", channelID, frequency); + // Check to make sure sprintf did not return an error before sending. + if(bytesWritten > 0) { + setMacParam(STR_CH_FREQ, buffer); + } + } + } + return false; +} + +/** +* @brief Sets the duty cycle allowed on the given channel ID. +* @param Channel ID to set duty cycle (0-15), +* @param Duty cycle is 0 - 100% as a float. +* @return Returns true if parameters are valid or false if not. +*/ +bool RN2483::setDutyCycle(uint8_t channelID, float dutyCycle) +{ + // Convert duty cycle into the required value using equation (100 / X) - 1 + if((dutyCycle <= (float)100 && dutyCycle >=(float)0) && (channelID > 15)) { + uint8_t dutyCycleSetting = ((float)100 / dutyCycle) - 1; + // Create the string for the settings + char buffer [15]; + int bytesWritten = sprintf(buffer, "%d %d", channelID, dutyCycleSetting); + // Check to make sure sprintf did not return an error before sending. + if(bytesWritten > 0) { + setMacParam(STR_CH_DCYCLE, buffer); + } + } + return false; +} + +/** +* @brief Sets the data rate for a given channel ID. +* Please refer to the LoRaWAN spec for the actual values. +* @param Channel ID from 0 - 15. +* @param Number representing the minimum data rate range from 0 to 7. +* @param Number representing the maximum data rate range from 0 to 7 +* @return Returns true if parameters are valid or false if not. +*/ +bool RN2483::setDrRange(uint8_t channelID, uint8_t minRange, uint8_t maxRange){ + if((channelID <= 15)&&(minRange<=7)&&(maxRange<=7)){ + char buffer [15]; + int bytesWritten = sprintf(buffer, "%d %d %d", channelID, minRange, maxRange); + // Check to make sure sprintf did not return an error before sending. + if(bytesWritten > 0) { + return setMacParam(STR_CH_DRRANGE, buffer); + } + } + return false; +} + +/** +* @brief Sets a given channel ID to be enabled or disabled. +* @param Channel ID from 0 - 15. +* @param Flag representing if channel is enabled or disabled. +* Warning: duty cycle, frequency and data range must be set for a channel +* before enabling! +* @return Returns true if parameters are valid or false if not. +*/ +bool RN2483::setStatus(uint8_t channelID, bool status){ + if((channelID <= 15)){ + int bytesWritten = 0; + char buffer [15]; + if(status) + bytesWritten = sprintf(buffer, "%d %s", channelID, "on"); + else { + bytesWritten = sprintf(buffer, "%d %s", channelID, "off"); + } + // Check to make sure sprintf did not return an error before sending. + if(bytesWritten > 0) { + return setMacParam(STR_CH_STATUS, buffer); + } + } + return false; +} + +/** +* @brief The network can issue a command to silence the RN2483. This restores the module. +* @return Returns true if parameters are valid or false if not. +*/ +bool RN2483::forceEnable(){ + return sendCommand(STR_MAC_FORCEENABLE); +} + +/** +* @brief Saves configurable parameters to eeprom. +* @return Returns true if parameters are valid or false if not. +*/ +bool RN2483::saveConfiguration(){ + return sendCommand(STR_CMD_SAVE); +} + +/** +* @brief Sends the command together with the given, paramValue (optional) +* @param Command should include a trailing space if paramValue is set. Refer to RN2483 command ref +* @param Command Parameter to send +* @param Size of param buffer +* @return Returns true on success or false if invalid. +*/ bool RN2483::sendCommand(const char* command, const uint8_t* paramValue, uint16_t size) { _RN2483.printf(command); @@ -312,10 +516,12 @@ return expectOK(); } -// Sends the command together with the given paramValue (optional) -// to the device and awaits for the response. -// Returns true on success. -// NOTE: command should include a trailing space if paramValue is set +/** +* @brief Sends the command together with the given, paramValue (optional) +* @param Command should include a trailing space if paramValue is set. Refer to RN2483 command ref +* @param Command Parameter to send +* @return Returns true on success or false if invalid. +*/ bool RN2483::sendCommand(const char* command, uint8_t paramValue) { _RN2483.printf(command); @@ -325,10 +531,12 @@ return expectOK(); } -// Sends the command together with the given paramValue (optional) -// to the device and awaits for the response. -// Returns true on success. -// NOTE: command should include a trailing space if paramValue is set +/** +* @brief Sends the command together with the given, paramValue (optional) +* @param Command should include a trailing space if paramValue is set. Refer to RN2483 command ref +* @param Command Parameter to send +* @return Returns true on success or false if invalid. +*/ bool RN2483::sendCommand(const char* command, const char* paramValue) { _RN2483.printf(command); @@ -339,8 +547,11 @@ return expectOK(); } -// Sends a join network command to the device and waits for the response (or timeout). -// Returns true on success. +/** +* @brief Sends a join command to the network +* @param Type of join, OTAA or ABP +* @return Returns true on success or false if fail. +*/ bool RN2483::joinNetwork(const char* type) { _RN2483.printf(STR_CMD_JOIN); @@ -350,10 +561,13 @@ return expectOK() && expectString(STR_ACCEPTED, 30000); } -// Sends the given mac command together with the given paramValue -// to the device and awaits for the response. -// Returns true on success. -// NOTE: paramName should include a trailing space +/** +* @brief Sends the command together with the given paramValue (optional) +* @param MAC param should include a trailing space if paramValue is set. Refer to RN2483 command ref. +* @param Param value to send +* @param Size of Param buffer +* @return Returns true on success or false if invalid. +*/ bool RN2483::setMacParam(const char* paramName, const uint8_t* paramValue, uint16_t size) { _RN2483.printf(STR_CMD_SET); @@ -369,10 +583,12 @@ return expectOK(); } -// Sends the given mac command together with the given paramValue -// to the device and awaits for the response. -// Returns true on success. -// NOTE: paramName should include a trailing space +/** +* @brief Sends the command together with the given paramValue (optional) +* @param MAC param should include a trailing space if paramValue is set. Refer to RN2483 command ref. +* @param Param value to send +* @return Returns true on success or false if invalid. +*/ bool RN2483::setMacParam(const char* paramName, uint8_t paramValue) { _RN2483.printf(STR_CMD_SET); @@ -383,10 +599,12 @@ return expectOK(); } -// Sends the given mac command together with the given paramValue -// to the device and awaits for the response. -// Returns true on success. -// NOTE: paramName should include a trailing space +/** +* @brief Sends the command together with the given paramValue (optional) +* @param MAC param should include a trailing space if paramValue is set. Refer to RN2483 command ref. +* @param Param value to send +* @return Returns true on success or false if invalid. +*/ bool RN2483::setMacParam(const char* paramName, const char* paramValue) { _RN2483.printf(STR_CMD_SET); @@ -397,15 +615,18 @@ return expectOK(); } -// Returns the enum that is mapped to the given "error" message. +/** +* @brief Returns the enum that is mapped to the given "error" message +* @param Error to lookup. +* @return Returns the enum. +*/ uint8_t RN2483::lookupMacTransmitError(const char* error) { if (error[0] == 0) { return NoResponse; } - StringEnumPair_t errorTable[] = - { + StringEnumPair_t errorTable[] = { { STR_RESULT_INVALID_PARAM, InternalError }, { STR_RESULT_NOT_JOINED, NotConnected }, { STR_RESULT_NO_FREE_CHANNEL, Busy }, @@ -426,6 +647,15 @@ return NoResponse; } +/** +* @brief Sends a a payload and blocks until there is a response back, +* or the receive windows have closed or the hard timeout has passed. +* @param Transmit type +* @param Port to use for transmit +* @param Payload buffer +* @param Size of payload buffer +* @return Returns if sucessfull or if a MAC transmit error. +*/ uint8_t RN2483::macTransmit(const char* type, uint8_t port, const uint8_t* payload, uint8_t size) { _RN2483.printf(STR_CMD_MAC_TX); @@ -447,34 +677,33 @@ this->packetReceived = false; // prepare for receiving a new packet Timer t; t.start(); - unsigned long timeout = t.read_ms() + RECEIVE_TIMEOUT; // hard timeouts + int timeout = t.read_ms() + RECEIVE_TIMEOUT; // hard timeouts while (t.read_ms() < timeout) { if (readLn() > 0) { - if (strstr(this->inputBuffer, " ") != NULL) // to avoid double delimiter search - { + if (strstr(this->inputBuffer, " ") != NULL) { // to avoid double delimiter search // there is a splittable line -only case known is mac_rx t.stop(); return onMacRX(); - } - else if (strstr(this->inputBuffer, STR_RESULT_MAC_TX_OK)) { + } else if (strstr(this->inputBuffer, STR_RESULT_MAC_TX_OK)) { // done t.stop(); return NoError; - } - else { + } else { // lookup the error message t.stop(); return lookupMacTransmitError(this->inputBuffer); } } } - t.stop(); + t.stop(); return Timedout; } -// Parses the input buffer and copies the received payload into the "received payload" buffer -// when a "mac rx" message has been received. It is called internally by macTransmit(). -// Returns 0 (NoError) or otherwise one of the MacTransmitErrorCodes. +/** +* @brief Parses the input buffer and copies the received payload into +* the "received payload" buffer when a "mac rx" message has been received. +* @return Returns 0 (NoError) or otherwise one of the MacTransmitErrorCodes. +*/ uint8_t RN2483::onMacRX() { // parse inputbuffer, put payload into packet buffer @@ -498,28 +727,43 @@ return NoError; } - // Private method to read serial port with timeout -int RN2483::timedRead(unsigned long _timeout){ +/** +* @brief Private method to read serial port with timeout +* @param The time to wait for in milliseconds. +* @return Returns character or -1 on timeout +*/ +int RN2483::timedRead(int _timeout) +{ int c; Timer t; t.start(); - unsigned long _startMillis = t.read_ms(); // get milliseconds - do { - if(_RN2483.readable()){ - c = _RN2483.getc(); - if (c >= 0){ - t.stop(); - return c; - } - } - } while(t.read_ms() - _startMillis <_timeout); + int _startMillis = t.read_ms(); // get milliseconds + while (! _RN2483.readable() && t.read_ms() - _startMillis <_timeout) { +#ifdef YOTTA_CFG_MBED_OS + Thread::yield(); +#else + wait_ms(10); +#endif + } t.stop(); + if(_RN2483.readable()) { + c = _RN2483.getc(); + if (c >= 0) { + return c; + } + } return -1; // -1 indicates timeout -} +} -// Read characters into buffer terminates if length characters have been read, timeout, -// or if the terminator character detected returns the number of characters placed in the buffer -// (0 means no valid data found) +/** +* @brief Read characters into buffer. +* Terminates if length characters have been read, timeout, or +* if the terminator character has been detected +* @param The terminator character to look for +* @param The buffer to read into. +* @param The size of the buffer. +* @return The number of bytes read. 0 means no valid data found. +*/ size_t RN2483::readBytesUntil(char terminator, char *buffer, size_t length) { if (length < 1) return 0; @@ -530,8 +774,8 @@ *buffer++ = (char)c; index++; } - return index; // return number of characters, not including null terminator -} + return index; // return number of characters, not including null terminator +} #ifdef DEBUG int freeRam()