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
RN2483.h@0:a8609e6f88f3, 2016-11-08 (annotated)
- 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?
User | Revision | Line number | New 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 |