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

Committer:
azazeal88
Date:
2016-11-08
Revision:
0:a8609e6f88f3
Child:
1:cf9b0c21907a

File content as of revision 0:a8609e6f88f3:

/*
* Copyright (c) 2016 Dan Knox. All rights reserved.
*
* This file is part of RN2483.
*
* RN2483 is free software: you can redistribute it and/or modify
* it under the terms of the GNU Lesser General Public License as
* published by the Free Software Foundation, either version 3 of
* the License, or(at your option) any later version.
*
* RN2483 is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU Lesser General Public License for more details.
*
* You should have received a copy of the GNU Lesser General Public
* License along with RN2483.  If not, see
* <http://www.gnu.org/licenses/>.
*/

#ifndef _RN2483_h
#define _RN2483_h

#include "mbed.h"
#include <stdint.h>

 //#define USE_DYNAMIC_BUFFER

#define DEFAULT_INPUT_BUFFER_SIZE 64
#define DEFAULT_RECEIVED_PAYLOAD_BUFFER_SIZE 32
#define DEFAULT_TIMEOUT 120
#define RECEIVE_TIMEOUT 60000
#define DEFAULT_FSB 2
#define DEFAULT_PWR_IDX_868 1
#define DEFAULT_PWR_IDX_915 5
#define DEFAULT_SF_868 7
#define DEFAULT_SF_915 7

#define ENABLE_SLEEP

// Available error codes.
enum MacTransmitErrorCodes
{
    NoError = 0,
    NoResponse = 1,
    Timedout = 2,
    PayloadSizeError = 3,
    InternalError = 4,
    Busy = 5,
    NetworkFatalError = 6,
    NotConnected = 7,
    NoAcknowledgment = 8,
};

// Provides a simple, abstracted interface to Microchip's RN2483 LoRaWAN module.

class RN2483
{
public:
    // Creates a new RN2483 instance.
    RN2483(PinName tx, PinName rx);
    
    // Returns the correct baudrate for the serial port that connects to the device.
    uint32_t getDefaultBaudRate() { return 57600; };
    
    void writeSomething();
    // Initializes the device and connects to the network using Over-The-Air Activation.
    // Returns true on successful connection.
    bool initOTA(const uint8_t devEUI[8], const uint8_t appEUI[8], const uint8_t appKey[16], bool adr = true);

    // Initializes the device and connects to the network using Activation By Personalization.
    // Returns true on successful connection.
    bool initABP(const uint8_t devAddr[4], const uint8_t appSKey[16], const uint8_t nwkSKey[16], bool adr = true);

    // Sends the given payload without acknowledgement.
    // Returns 0 (NoError) when transmission is successful or one of the MacTransmitErrorCodes otherwise.
    uint8_t send(uint8_t port, const uint8_t* payload, uint8_t size);

    // Sends the given payload with acknowledgement.
    // Returns 0 (NoError) when transmission is successful or one of the MacTransmitErrorCodes otherwise.
    uint8_t sendReqAck(uint8_t port, const uint8_t* payload, uint8_t size, uint8_t maxRetries);

    // 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.
    uint16_t receive(uint8_t* buffer, uint16_t size, uint16_t payloadStartPosition = 0);

    // Gets the preprogrammed EUI node address from the module.
    // Returns the number of bytes written or 0 in case of error.
    uint8_t getHWEUI(uint8_t* buffer, uint8_t size);

    // 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.
    bool setFsbChannels(uint8_t fsb);

    // 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.
    bool setSpreadingFactor(uint8_t spreadingFactor);

    // Sets the power index (868MHz: 1 to 5 / 915MHz: 5, 7, 8, 9 or 10)
    // Returns true if succesful.
    bool setPowerIndex(uint8_t 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
    bool sendCommand(const char* command, const uint8_t* paramValue, uint16_t size);
    bool sendCommand(const char* command, uint8_t paramValue);
    bool sendCommand(const char* command, const char* paramValue = NULL);

    // 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
    bool setMacParam(const char* paramName, const uint8_t* paramValue, uint16_t size);
    bool setMacParam(const char* paramName, uint8_t paramValue);
    bool setMacParam(const char* paramName, const char* paramValue);

#ifdef ENABLE_SLEEP
    void wakeUp();

    void sleep();
#endif

#ifdef USE_DYNAMIC_BUFFER
    // Sets the size of the input buffer.
    // Needs to be called before initOTA()/initABP().
    void setInputBufferSize(uint16_t value) { this->inputBufferSize = value; };

    // Sets the size of the "Received Payload" buffer.
    // Needs to be called before initOTA()/initABP().
    void setReceivedPayloadBufferSize(uint16_t value) { this->receivedPayloadBufferSize = value; };
#endif


private:

    Serial _RN2483;
    
    // The size of the input buffer. Equals DEFAULT_INPUT_BUFFER_SIZE
    // by default or (optionally) a user-defined value when using USE_DYNAMIC_BUFFER.
    uint16_t inputBufferSize;

    // The size of the received payload buffer. Equals DEFAULT_RECEIVED_PAYLOAD_BUFFER_SIZE
    // by default or (optionally) a user-defined value when using USE_DYNAMIC_BUFFER.
    uint16_t receivedPayloadBufferSize;

    // Flag used to make sure the received payload buffer is
    // current with the latest transmission.
    bool packetReceived;

    // Used to distinguise between RN2483 and RN2903. 
    // Currently only being set during reset().
    bool isRN2903;

#ifdef USE_DYNAMIC_BUFFER
    // Flag to make sure the buffers are not allocated more than once.
    bool isBufferInitialized;

    char* inputBuffer;
    char* receivedPayloadBuffer;
#else
    char inputBuffer[DEFAULT_INPUT_BUFFER_SIZE];
    char receivedPayloadBuffer[DEFAULT_RECEIVED_PAYLOAD_BUFFER_SIZE];
#endif

    // Takes care of the init tasks common to both initOTA() and initABP.
    inline void init();

    // Reads a line from the device stream into the "buffer" starting at the "start" position of the buffer.
    // Returns the number of bytes read.
    uint16_t readLn(char* buffer, uint16_t size, uint16_t start = 0);

    // Reads a line from the device stream into the input buffer.
    // Returns the number of bytes read.
    uint16_t readLn() { return readLn(this->inputBuffer, this->inputBufferSize); };

    // 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.
    bool expectString(const char* str, uint16_t timeout = DEFAULT_TIMEOUT);
    bool expectOK();

    // Sends a reset command to the module and waits for the success response (or timeout).
    // Returns true on success.
    bool resetDevice();

    // Sends a join network command to the device and waits for the response (or timeout).
    // Returns true on success.
    bool joinNetwork(const char* type);

    // Returns the enum that is mapped to the given "error" message.
    uint8_t lookupMacTransmitError(const char* error);

    // Sends a a payload and blocks until there is a response back, or the receive windows have closed,
    // or the hard timeout has passed.
    uint8_t macTransmit(const char* type, uint8_t port, const uint8_t* payload, uint8_t size);

    // 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.
    uint8_t onMacRX();
    
    // Private method to read serial port with timeout
    int timedRead(unsigned long _timeout);
    
    // Read characters into buffer erminates 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)
    size_t readBytesUntil(char terminator, char *buffer, size_t length);
};

#endif // RN2483