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

Committer:
azazeal88
Date:
Tue Nov 08 17:11:08 2016 +0000
Revision:
0:a8609e6f88f3
Child:
1:cf9b0c21907a
First Commit

Who changed what in which revision?

UserRevisionLine numberNew contents of line
azazeal88 0:a8609e6f88f3 1 /*
azazeal88 0:a8609e6f88f3 2 * Copyright (c) 2016 Dan Knox. All rights reserved.
azazeal88 0:a8609e6f88f3 3 *
azazeal88 0:a8609e6f88f3 4 * This file is part of RN2483.
azazeal88 0:a8609e6f88f3 5 *
azazeal88 0:a8609e6f88f3 6 * RN2483 is free software: you can redistribute it and/or modify
azazeal88 0:a8609e6f88f3 7 * it under the terms of the GNU Lesser General Public License as
azazeal88 0:a8609e6f88f3 8 * published by the Free Software Foundation, either version 3 of
azazeal88 0:a8609e6f88f3 9 * the License, or(at your option) any later version.
azazeal88 0:a8609e6f88f3 10 *
azazeal88 0:a8609e6f88f3 11 * RN2483 is distributed in the hope that it will be useful,
azazeal88 0:a8609e6f88f3 12 * but WITHOUT ANY WARRANTY; without even the implied warranty of
azazeal88 0:a8609e6f88f3 13 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
azazeal88 0:a8609e6f88f3 14 * GNU Lesser General Public License for more details.
azazeal88 0:a8609e6f88f3 15 *
azazeal88 0:a8609e6f88f3 16 * You should have received a copy of the GNU Lesser General Public
azazeal88 0:a8609e6f88f3 17 * License along with RN2483. If not, see
azazeal88 0:a8609e6f88f3 18 * <http://www.gnu.org/licenses/>.
azazeal88 0:a8609e6f88f3 19 */
azazeal88 0:a8609e6f88f3 20
azazeal88 0:a8609e6f88f3 21 #ifndef _RN2483_h
azazeal88 0:a8609e6f88f3 22 #define _RN2483_h
azazeal88 0:a8609e6f88f3 23
azazeal88 0:a8609e6f88f3 24 #include "mbed.h"
azazeal88 0:a8609e6f88f3 25 #include <stdint.h>
azazeal88 0:a8609e6f88f3 26
azazeal88 0:a8609e6f88f3 27 //#define USE_DYNAMIC_BUFFER
azazeal88 0:a8609e6f88f3 28
azazeal88 0:a8609e6f88f3 29 #define DEFAULT_INPUT_BUFFER_SIZE 64
azazeal88 0:a8609e6f88f3 30 #define DEFAULT_RECEIVED_PAYLOAD_BUFFER_SIZE 32
azazeal88 0:a8609e6f88f3 31 #define DEFAULT_TIMEOUT 120
azazeal88 0:a8609e6f88f3 32 #define RECEIVE_TIMEOUT 60000
azazeal88 0:a8609e6f88f3 33 #define DEFAULT_FSB 2
azazeal88 0:a8609e6f88f3 34 #define DEFAULT_PWR_IDX_868 1
azazeal88 0:a8609e6f88f3 35 #define DEFAULT_PWR_IDX_915 5
azazeal88 0:a8609e6f88f3 36 #define DEFAULT_SF_868 7
azazeal88 0:a8609e6f88f3 37 #define DEFAULT_SF_915 7
azazeal88 0:a8609e6f88f3 38
azazeal88 0:a8609e6f88f3 39 #define ENABLE_SLEEP
azazeal88 0:a8609e6f88f3 40
azazeal88 0:a8609e6f88f3 41 // Available error codes.
azazeal88 0:a8609e6f88f3 42 enum MacTransmitErrorCodes
azazeal88 0:a8609e6f88f3 43 {
azazeal88 0:a8609e6f88f3 44 NoError = 0,
azazeal88 0:a8609e6f88f3 45 NoResponse = 1,
azazeal88 0:a8609e6f88f3 46 Timedout = 2,
azazeal88 0:a8609e6f88f3 47 PayloadSizeError = 3,
azazeal88 0:a8609e6f88f3 48 InternalError = 4,
azazeal88 0:a8609e6f88f3 49 Busy = 5,
azazeal88 0:a8609e6f88f3 50 NetworkFatalError = 6,
azazeal88 0:a8609e6f88f3 51 NotConnected = 7,
azazeal88 0:a8609e6f88f3 52 NoAcknowledgment = 8,
azazeal88 0:a8609e6f88f3 53 };
azazeal88 0:a8609e6f88f3 54
azazeal88 0:a8609e6f88f3 55 // Provides a simple, abstracted interface to Microchip's RN2483 LoRaWAN module.
azazeal88 0:a8609e6f88f3 56
azazeal88 0:a8609e6f88f3 57 class RN2483
azazeal88 0:a8609e6f88f3 58 {
azazeal88 0:a8609e6f88f3 59 public:
azazeal88 0:a8609e6f88f3 60 // Creates a new RN2483 instance.
azazeal88 0:a8609e6f88f3 61 RN2483(PinName tx, PinName rx);
azazeal88 0:a8609e6f88f3 62
azazeal88 0:a8609e6f88f3 63 // Returns the correct baudrate for the serial port that connects to the device.
azazeal88 0:a8609e6f88f3 64 uint32_t getDefaultBaudRate() { return 57600; };
azazeal88 0:a8609e6f88f3 65
azazeal88 0:a8609e6f88f3 66 void writeSomething();
azazeal88 0:a8609e6f88f3 67 // Initializes the device and connects to the network using Over-The-Air Activation.
azazeal88 0:a8609e6f88f3 68 // Returns true on successful connection.
azazeal88 0:a8609e6f88f3 69 bool initOTA(const uint8_t devEUI[8], const uint8_t appEUI[8], const uint8_t appKey[16], bool adr = true);
azazeal88 0:a8609e6f88f3 70
azazeal88 0:a8609e6f88f3 71 // Initializes the device and connects to the network using Activation By Personalization.
azazeal88 0:a8609e6f88f3 72 // Returns true on successful connection.
azazeal88 0:a8609e6f88f3 73 bool initABP(const uint8_t devAddr[4], const uint8_t appSKey[16], const uint8_t nwkSKey[16], bool adr = true);
azazeal88 0:a8609e6f88f3 74
azazeal88 0:a8609e6f88f3 75 // Sends the given payload without acknowledgement.
azazeal88 0:a8609e6f88f3 76 // Returns 0 (NoError) when transmission is successful or one of the MacTransmitErrorCodes otherwise.
azazeal88 0:a8609e6f88f3 77 uint8_t send(uint8_t port, const uint8_t* payload, uint8_t size);
azazeal88 0:a8609e6f88f3 78
azazeal88 0:a8609e6f88f3 79 // Sends the given payload with acknowledgement.
azazeal88 0:a8609e6f88f3 80 // Returns 0 (NoError) when transmission is successful or one of the MacTransmitErrorCodes otherwise.
azazeal88 0:a8609e6f88f3 81 uint8_t sendReqAck(uint8_t port, const uint8_t* payload, uint8_t size, uint8_t maxRetries);
azazeal88 0:a8609e6f88f3 82
azazeal88 0:a8609e6f88f3 83 // Copies the latest received packet (optionally starting from the "payloadStartPosition"
azazeal88 0:a8609e6f88f3 84 // position of the payload) into the given "buffer", up to "size" number of bytes.
azazeal88 0:a8609e6f88f3 85 // Returns the number of bytes written or 0 if no packet is received since last transmission.
azazeal88 0:a8609e6f88f3 86 uint16_t receive(uint8_t* buffer, uint16_t size, uint16_t payloadStartPosition = 0);
azazeal88 0:a8609e6f88f3 87
azazeal88 0:a8609e6f88f3 88 // Gets the preprogrammed EUI node address from the module.
azazeal88 0:a8609e6f88f3 89 // Returns the number of bytes written or 0 in case of error.
azazeal88 0:a8609e6f88f3 90 uint8_t getHWEUI(uint8_t* buffer, uint8_t size);
azazeal88 0:a8609e6f88f3 91
azazeal88 0:a8609e6f88f3 92 // Enables all the channels that belong to the given Frequency Sub-Band (FSB)
azazeal88 0:a8609e6f88f3 93 // and disables the rest.
azazeal88 0:a8609e6f88f3 94 // fsb is [1, 8] or 0 to enable all channels.
azazeal88 0:a8609e6f88f3 95 // Returns true if all channels were set successfully.
azazeal88 0:a8609e6f88f3 96 bool setFsbChannels(uint8_t fsb);
azazeal88 0:a8609e6f88f3 97
azazeal88 0:a8609e6f88f3 98 // Sets the spreading factor.
azazeal88 0:a8609e6f88f3 99 // In reality it sets the datarate of the module according to the
azazeal88 0:a8609e6f88f3 100 // LoraWAN specs mapping for 868MHz and 915MHz,
azazeal88 0:a8609e6f88f3 101 // using the given spreading factor parameter.
azazeal88 0:a8609e6f88f3 102 bool setSpreadingFactor(uint8_t spreadingFactor);
azazeal88 0:a8609e6f88f3 103
azazeal88 0:a8609e6f88f3 104 // Sets the power index (868MHz: 1 to 5 / 915MHz: 5, 7, 8, 9 or 10)
azazeal88 0:a8609e6f88f3 105 // Returns true if succesful.
azazeal88 0:a8609e6f88f3 106 bool setPowerIndex(uint8_t powerIndex);
azazeal88 0:a8609e6f88f3 107
azazeal88 0:a8609e6f88f3 108 // Sends the command together with the given paramValue (optional)
azazeal88 0:a8609e6f88f3 109 // to the device and awaits for the response.
azazeal88 0:a8609e6f88f3 110 // Returns true on success.
azazeal88 0:a8609e6f88f3 111 // NOTE: command should include a trailing space if paramValue is set
azazeal88 0:a8609e6f88f3 112 bool sendCommand(const char* command, const uint8_t* paramValue, uint16_t size);
azazeal88 0:a8609e6f88f3 113 bool sendCommand(const char* command, uint8_t paramValue);
azazeal88 0:a8609e6f88f3 114 bool sendCommand(const char* command, const char* paramValue = NULL);
azazeal88 0:a8609e6f88f3 115
azazeal88 0:a8609e6f88f3 116 // Sends the given mac command together with the given paramValue
azazeal88 0:a8609e6f88f3 117 // to the device and awaits for the response.
azazeal88 0:a8609e6f88f3 118 // Returns true on success.
azazeal88 0:a8609e6f88f3 119 // NOTE: paramName should include a trailing space
azazeal88 0:a8609e6f88f3 120 bool setMacParam(const char* paramName, const uint8_t* paramValue, uint16_t size);
azazeal88 0:a8609e6f88f3 121 bool setMacParam(const char* paramName, uint8_t paramValue);
azazeal88 0:a8609e6f88f3 122 bool setMacParam(const char* paramName, const char* paramValue);
azazeal88 0:a8609e6f88f3 123
azazeal88 0:a8609e6f88f3 124 #ifdef ENABLE_SLEEP
azazeal88 0:a8609e6f88f3 125 void wakeUp();
azazeal88 0:a8609e6f88f3 126
azazeal88 0:a8609e6f88f3 127 void sleep();
azazeal88 0:a8609e6f88f3 128 #endif
azazeal88 0:a8609e6f88f3 129
azazeal88 0:a8609e6f88f3 130 #ifdef USE_DYNAMIC_BUFFER
azazeal88 0:a8609e6f88f3 131 // Sets the size of the input buffer.
azazeal88 0:a8609e6f88f3 132 // Needs to be called before initOTA()/initABP().
azazeal88 0:a8609e6f88f3 133 void setInputBufferSize(uint16_t value) { this->inputBufferSize = value; };
azazeal88 0:a8609e6f88f3 134
azazeal88 0:a8609e6f88f3 135 // Sets the size of the "Received Payload" buffer.
azazeal88 0:a8609e6f88f3 136 // Needs to be called before initOTA()/initABP().
azazeal88 0:a8609e6f88f3 137 void setReceivedPayloadBufferSize(uint16_t value) { this->receivedPayloadBufferSize = value; };
azazeal88 0:a8609e6f88f3 138 #endif
azazeal88 0:a8609e6f88f3 139
azazeal88 0:a8609e6f88f3 140
azazeal88 0:a8609e6f88f3 141 private:
azazeal88 0:a8609e6f88f3 142
azazeal88 0:a8609e6f88f3 143 Serial _RN2483;
azazeal88 0:a8609e6f88f3 144
azazeal88 0:a8609e6f88f3 145 // The size of the input buffer. Equals DEFAULT_INPUT_BUFFER_SIZE
azazeal88 0:a8609e6f88f3 146 // by default or (optionally) a user-defined value when using USE_DYNAMIC_BUFFER.
azazeal88 0:a8609e6f88f3 147 uint16_t inputBufferSize;
azazeal88 0:a8609e6f88f3 148
azazeal88 0:a8609e6f88f3 149 // The size of the received payload buffer. Equals DEFAULT_RECEIVED_PAYLOAD_BUFFER_SIZE
azazeal88 0:a8609e6f88f3 150 // by default or (optionally) a user-defined value when using USE_DYNAMIC_BUFFER.
azazeal88 0:a8609e6f88f3 151 uint16_t receivedPayloadBufferSize;
azazeal88 0:a8609e6f88f3 152
azazeal88 0:a8609e6f88f3 153 // Flag used to make sure the received payload buffer is
azazeal88 0:a8609e6f88f3 154 // current with the latest transmission.
azazeal88 0:a8609e6f88f3 155 bool packetReceived;
azazeal88 0:a8609e6f88f3 156
azazeal88 0:a8609e6f88f3 157 // Used to distinguise between RN2483 and RN2903.
azazeal88 0:a8609e6f88f3 158 // Currently only being set during reset().
azazeal88 0:a8609e6f88f3 159 bool isRN2903;
azazeal88 0:a8609e6f88f3 160
azazeal88 0:a8609e6f88f3 161 #ifdef USE_DYNAMIC_BUFFER
azazeal88 0:a8609e6f88f3 162 // Flag to make sure the buffers are not allocated more than once.
azazeal88 0:a8609e6f88f3 163 bool isBufferInitialized;
azazeal88 0:a8609e6f88f3 164
azazeal88 0:a8609e6f88f3 165 char* inputBuffer;
azazeal88 0:a8609e6f88f3 166 char* receivedPayloadBuffer;
azazeal88 0:a8609e6f88f3 167 #else
azazeal88 0:a8609e6f88f3 168 char inputBuffer[DEFAULT_INPUT_BUFFER_SIZE];
azazeal88 0:a8609e6f88f3 169 char receivedPayloadBuffer[DEFAULT_RECEIVED_PAYLOAD_BUFFER_SIZE];
azazeal88 0:a8609e6f88f3 170 #endif
azazeal88 0:a8609e6f88f3 171
azazeal88 0:a8609e6f88f3 172 // Takes care of the init tasks common to both initOTA() and initABP.
azazeal88 0:a8609e6f88f3 173 inline void init();
azazeal88 0:a8609e6f88f3 174
azazeal88 0:a8609e6f88f3 175 // Reads a line from the device stream into the "buffer" starting at the "start" position of the buffer.
azazeal88 0:a8609e6f88f3 176 // Returns the number of bytes read.
azazeal88 0:a8609e6f88f3 177 uint16_t readLn(char* buffer, uint16_t size, uint16_t start = 0);
azazeal88 0:a8609e6f88f3 178
azazeal88 0:a8609e6f88f3 179 // Reads a line from the device stream into the input buffer.
azazeal88 0:a8609e6f88f3 180 // Returns the number of bytes read.
azazeal88 0:a8609e6f88f3 181 uint16_t readLn() { return readLn(this->inputBuffer, this->inputBufferSize); };
azazeal88 0:a8609e6f88f3 182
azazeal88 0:a8609e6f88f3 183 // Waits for the given string. Returns true if the string is received before a timeout.
azazeal88 0:a8609e6f88f3 184 // Returns false if a timeout occurs or if another string is received.
azazeal88 0:a8609e6f88f3 185 bool expectString(const char* str, uint16_t timeout = DEFAULT_TIMEOUT);
azazeal88 0:a8609e6f88f3 186 bool expectOK();
azazeal88 0:a8609e6f88f3 187
azazeal88 0:a8609e6f88f3 188 // Sends a reset command to the module and waits for the success response (or timeout).
azazeal88 0:a8609e6f88f3 189 // Returns true on success.
azazeal88 0:a8609e6f88f3 190 bool resetDevice();
azazeal88 0:a8609e6f88f3 191
azazeal88 0:a8609e6f88f3 192 // Sends a join network command to the device and waits for the response (or timeout).
azazeal88 0:a8609e6f88f3 193 // Returns true on success.
azazeal88 0:a8609e6f88f3 194 bool joinNetwork(const char* type);
azazeal88 0:a8609e6f88f3 195
azazeal88 0:a8609e6f88f3 196 // Returns the enum that is mapped to the given "error" message.
azazeal88 0:a8609e6f88f3 197 uint8_t lookupMacTransmitError(const char* error);
azazeal88 0:a8609e6f88f3 198
azazeal88 0:a8609e6f88f3 199 // Sends a a payload and blocks until there is a response back, or the receive windows have closed,
azazeal88 0:a8609e6f88f3 200 // or the hard timeout has passed.
azazeal88 0:a8609e6f88f3 201 uint8_t macTransmit(const char* type, uint8_t port, const uint8_t* payload, uint8_t size);
azazeal88 0:a8609e6f88f3 202
azazeal88 0:a8609e6f88f3 203 // Parses the input buffer and copies the received payload into the "received payload" buffer
azazeal88 0:a8609e6f88f3 204 // when a "mac rx" message has been received. It is called internally by macTransmit().
azazeal88 0:a8609e6f88f3 205 // Returns 0 (NoError) or otherwise one of the MacTransmitErrorCodes.
azazeal88 0:a8609e6f88f3 206 uint8_t onMacRX();
azazeal88 0:a8609e6f88f3 207
azazeal88 0:a8609e6f88f3 208 // Private method to read serial port with timeout
azazeal88 0:a8609e6f88f3 209 int timedRead(unsigned long _timeout);
azazeal88 0:a8609e6f88f3 210
azazeal88 0:a8609e6f88f3 211 // Read characters into buffer erminates if length characters have been read, timeout,
azazeal88 0:a8609e6f88f3 212 // or if the terminator character detected returns the number of characters placed in the buffer
azazeal88 0:a8609e6f88f3 213 // (0 means no valid data found)
azazeal88 0:a8609e6f88f3 214 size_t readBytesUntil(char terminator, char *buffer, size_t length);
azazeal88 0:a8609e6f88f3 215 };
azazeal88 0:a8609e6f88f3 216
azazeal88 0:a8609e6f88f3 217 #endif // RN2483