STM32F103c8t6 LoRaWAN lmic

Dependents:   LoRaWAN-lmic-app_copy

Fork of LMiC by Semtech

Committer:
mistery
Date:
Wed Apr 19 07:57:22 2017 +0000
Revision:
5:30dcb702226b
Parent:
4:85b2b647cb64
LoRaWAN

Who changed what in which revision?

UserRevisionLine numberNew contents of line
mluis 0:62d1edcc13d1 1 /*******************************************************************************
mluis 1:d3b7bde3995c 2 * Copyright (c) 2014-2015 IBM Corporation.
mluis 0:62d1edcc13d1 3 * All rights reserved. This program and the accompanying materials
mluis 0:62d1edcc13d1 4 * are made available under the terms of the Eclipse Public License v1.0
mluis 0:62d1edcc13d1 5 * which accompanies this distribution, and is available at
mluis 0:62d1edcc13d1 6 * http://www.eclipse.org/legal/epl-v10.html
mluis 0:62d1edcc13d1 7 *
mluis 0:62d1edcc13d1 8 * Contributors:
mluis 0:62d1edcc13d1 9 * IBM Zurich Research Lab - initial API, implementation and documentation
mluis 0:62d1edcc13d1 10 *******************************************************************************/
mluis 0:62d1edcc13d1 11
mluis 1:d3b7bde3995c 12 //! @file
mluis 1:d3b7bde3995c 13 //! @brief LMIC API
mluis 0:62d1edcc13d1 14
mluis 0:62d1edcc13d1 15 #ifndef _lmic_h_
mluis 0:62d1edcc13d1 16 #define _lmic_h_
mluis 0:62d1edcc13d1 17
mluis 1:d3b7bde3995c 18 // MBED compiler options
mistery 5:30dcb702226b 19 #define CFG_eu868 1
mistery 5:30dcb702226b 20 //#define CFG_us915 1
mistery 5:30dcb702226b 21 //#define CHNL_HYBRID 0 /* US915: 0-7 to select block of 8 channels used */
mluis 0:62d1edcc13d1 22
mistery 5:30dcb702226b 23 //#define USE_SMTC_RADIO_DRIVER 1
mluis 0:62d1edcc13d1 24
mluis 1:d3b7bde3995c 25 //#define CFG_sx1272_radio 0
mluis 1:d3b7bde3995c 26 #define CFG_sx1276_radio 1
mluis 1:d3b7bde3995c 27 // End MBED compiler options
mluis 0:62d1edcc13d1 28
mluis 0:62d1edcc13d1 29 #include "oslmic.h"
mluis 0:62d1edcc13d1 30 #include "lorabase.h"
mluis 0:62d1edcc13d1 31
mluis 1:d3b7bde3995c 32 // LMIC version
mluis 1:d3b7bde3995c 33 #define LMIC_VERSION_MAJOR 1
dudmuck 2:974cafbfb159 34 #define LMIC_VERSION_MINOR 5
dudmuck 2:974cafbfb159 35 #define LMIC_VERSION_BUILD 1431528305
mluis 1:d3b7bde3995c 36
mluis 1:d3b7bde3995c 37 enum { MAX_FRAME_LEN = 64 }; //!< Library cap on max frame length
mluis 1:d3b7bde3995c 38 enum { TXCONF_ATTEMPTS = 8 }; //!< Transmit attempts for confirmed frames
mluis 0:62d1edcc13d1 39 enum { MAX_MISSED_BCNS = 20 }; // threshold for triggering rejoin requests
mluis 0:62d1edcc13d1 40 enum { MAX_RXSYMS = 100 }; // stop tracking beacon beyond this
mluis 0:62d1edcc13d1 41
dudmuck 2:974cafbfb159 42 enum { LINK_CHECK_CONT = 12 , // continue with this after reported dead link
dudmuck 2:974cafbfb159 43 LINK_CHECK_DEAD = 24 , // after this UP frames and no response from NWK assume link is dead
mluis 1:d3b7bde3995c 44 LINK_CHECK_INIT = -12 , // UP frame count until we inc datarate
mluis 1:d3b7bde3995c 45 LINK_CHECK_OFF =-128 }; // link check disabled
mluis 0:62d1edcc13d1 46
mluis 0:62d1edcc13d1 47 enum { TIME_RESYNC = 6*128 }; // secs
mluis 0:62d1edcc13d1 48 enum { TXRX_GUARD_ms = 6000 }; // msecs - don't start TX-RX transaction before beacon
mluis 0:62d1edcc13d1 49 enum { JOIN_GUARD_ms = 9000 }; // msecs - don't start Join Req/Acc transaction before beacon
mluis 0:62d1edcc13d1 50 enum { TXRX_BCNEXT_secs = 2 }; // secs - earliest start after beacon time
mluis 0:62d1edcc13d1 51 enum { RETRY_PERIOD_secs = 3 }; // secs - random period for retrying a confirmed send
mluis 0:62d1edcc13d1 52
mluis 1:d3b7bde3995c 53 #if defined(CFG_eu868) // EU868 spectrum ====================================================
mluis 0:62d1edcc13d1 54
mluis 1:d3b7bde3995c 55 enum { MAX_CHANNELS = 16 }; //!< Max supported channels
mistery 5:30dcb702226b 56 //enum { MAX_CHANNELS = 1};
mluis 1:d3b7bde3995c 57 enum { MAX_BANDS = 4 };
mistery 5:30dcb702226b 58 //enum { MAX_BANDS = 1 };
mistery 5:30dcb702226b 59 enum { LIMIT_CHANNELS = (1<<4) }; // EU868 will never have more channels
mistery 5:30dcb702226b 60 //enum { LIMIT_CHANNELS = (1) };
mluis 0:62d1edcc13d1 61
mluis 1:d3b7bde3995c 62 //! \internal
mluis 0:62d1edcc13d1 63 struct band_t {
mluis 1:d3b7bde3995c 64 u2_t txcap; // duty cycle limitation: 1/txcap
mluis 1:d3b7bde3995c 65 s1_t txpow; // maximum TX power
mluis 1:d3b7bde3995c 66 u1_t lastchnl; // last used channel
mluis 1:d3b7bde3995c 67 ostime_t avail; // channel is blocked until this time
mluis 0:62d1edcc13d1 68 };
mluis 1:d3b7bde3995c 69 TYPEDEF_xref2band_t; //!< \internal
mluis 0:62d1edcc13d1 70
mluis 1:d3b7bde3995c 71 #elif defined(CFG_us915) // US915 spectrum =================================================
mluis 0:62d1edcc13d1 72
mluis 0:62d1edcc13d1 73 enum { MAX_XCHANNELS = 2 }; // extra channels in RAM, channels 0-71 are immutable
mluis 0:62d1edcc13d1 74 enum { MAX_TXPOW_125kHz = 30 };
mluis 0:62d1edcc13d1 75
mluis 0:62d1edcc13d1 76 #endif // ==========================================================================
mluis 0:62d1edcc13d1 77
mluis 0:62d1edcc13d1 78 // Keep in sync with evdefs.hpp::drChange
mluis 0:62d1edcc13d1 79 enum { DRCHG_SET, DRCHG_NOJACC, DRCHG_NOACK, DRCHG_NOADRACK, DRCHG_NWKCMD };
mluis 0:62d1edcc13d1 80 enum { KEEP_TXPOW = -128 };
mluis 0:62d1edcc13d1 81
mluis 0:62d1edcc13d1 82
mluis 1:d3b7bde3995c 83 //! \internal
mluis 0:62d1edcc13d1 84 struct rxsched_t {
mluis 0:62d1edcc13d1 85 u1_t dr;
mluis 0:62d1edcc13d1 86 u1_t intvExp; // 0..7
mluis 0:62d1edcc13d1 87 u1_t slot; // runs from 0 to 128
mluis 0:62d1edcc13d1 88 u1_t rxsyms;
mluis 0:62d1edcc13d1 89 ostime_t rxbase;
mluis 0:62d1edcc13d1 90 ostime_t rxtime; // start of next spot
mluis 0:62d1edcc13d1 91 u4_t freq;
mluis 0:62d1edcc13d1 92 };
mluis 1:d3b7bde3995c 93 TYPEDEF_xref2rxsched_t; //!< \internal
mluis 0:62d1edcc13d1 94
mluis 0:62d1edcc13d1 95
mluis 1:d3b7bde3995c 96 //! Parsing and tracking states of beacons.
mluis 1:d3b7bde3995c 97 enum { BCN_NONE = 0x00, //!< No beacon received
mluis 1:d3b7bde3995c 98 BCN_PARTIAL = 0x01, //!< Only first (common) part could be decoded (info,lat,lon invalid/previous)
mluis 1:d3b7bde3995c 99 BCN_FULL = 0x02, //!< Full beacon decoded
mluis 1:d3b7bde3995c 100 BCN_NODRIFT = 0x04, //!< No drift value measured yet
mluis 1:d3b7bde3995c 101 BCN_NODDIFF = 0x08 }; //!< No differential drift measured yet
mluis 1:d3b7bde3995c 102 //! Information about the last and previous beacons.
mluis 0:62d1edcc13d1 103 struct bcninfo_t {
mluis 1:d3b7bde3995c 104 ostime_t txtime; //!< Time when the beacon was sent
mluis 1:d3b7bde3995c 105 s1_t rssi; //!< Adjusted RSSI value of last received beacon
mluis 1:d3b7bde3995c 106 s1_t snr; //!< Scaled SNR value of last received beacon
mluis 1:d3b7bde3995c 107 u1_t flags; //!< Last beacon reception and tracking states. See BCN_* values.
mluis 1:d3b7bde3995c 108 u4_t time; //!< GPS time in seconds of last beacon (received or surrogate)
mluis 1:d3b7bde3995c 109 //
mluis 1:d3b7bde3995c 110 u1_t info; //!< Info field of last beacon (valid only if BCN_FULL set)
mluis 1:d3b7bde3995c 111 s4_t lat; //!< Lat field of last beacon (valid only if BCN_FULL set)
mluis 1:d3b7bde3995c 112 s4_t lon; //!< Lon field of last beacon (valid only if BCN_FULL set)
mluis 0:62d1edcc13d1 113 };
mluis 0:62d1edcc13d1 114
mluis 0:62d1edcc13d1 115 // purpose of receive window - lmic_t.rxState
mluis 0:62d1edcc13d1 116 enum { RADIO_RST=0, RADIO_TX=1, RADIO_RX=2, RADIO_RXON=3 };
mluis 0:62d1edcc13d1 117 // Netid values / lmic_t.netid
mluis 1:d3b7bde3995c 118 enum { NETID_NONE=(int)~0U, NETID_MASK=(int)0xFFFFFF };
mluis 0:62d1edcc13d1 119 // MAC operation modes (lmic_t.opmode).
mluis 0:62d1edcc13d1 120 enum { OP_NONE = 0x0000,
mluis 0:62d1edcc13d1 121 OP_SCAN = 0x0001, // radio scan to find a beacon
mluis 0:62d1edcc13d1 122 OP_TRACK = 0x0002, // track my networks beacon (netid)
mluis 0:62d1edcc13d1 123 OP_JOINING = 0x0004, // device joining in progress (blocks other activities)
mluis 0:62d1edcc13d1 124 OP_TXDATA = 0x0008, // TX user data (buffered in pendTxData)
mluis 0:62d1edcc13d1 125 OP_POLL = 0x0010, // send empty UP frame to ACK confirmed DN/fetch more DN data
mluis 0:62d1edcc13d1 126 OP_REJOIN = 0x0020, // occasionally send JOIN REQUEST
mluis 0:62d1edcc13d1 127 OP_SHUTDOWN = 0x0040, // prevent MAC from doing anything
mluis 0:62d1edcc13d1 128 OP_TXRXPEND = 0x0080, // TX/RX transaction pending
mluis 0:62d1edcc13d1 129 OP_RNDTX = 0x0100, // prevent TX lining up after a beacon
mluis 0:62d1edcc13d1 130 OP_PINGINI = 0x0200, // pingable is initialized and scheduling active
mluis 0:62d1edcc13d1 131 OP_PINGABLE = 0x0400, // we're pingable
mluis 0:62d1edcc13d1 132 OP_NEXTCHNL = 0x0800, // find a new channel
mluis 0:62d1edcc13d1 133 OP_LINKDEAD = 0x1000, // link was reported as dead
mluis 1:d3b7bde3995c 134 OP_TESTMODE = 0x2000, // developer test mode
mluis 0:62d1edcc13d1 135 };
mluis 0:62d1edcc13d1 136 // TX-RX transaction flags - report back to user
mluis 0:62d1edcc13d1 137 enum { TXRX_ACK = 0x80, // confirmed UP frame was acked
mluis 0:62d1edcc13d1 138 TXRX_NACK = 0x40, // confirmed UP frame was not acked
mluis 0:62d1edcc13d1 139 TXRX_NOPORT = 0x20, // set if a frame with a port was RXed, clr if no frame/no port
mluis 1:d3b7bde3995c 140 TXRX_PORT = 0x10, // set if a frame with a port was RXed, LMIC.frame[LMIC.dataBeg-1] => port
mluis 0:62d1edcc13d1 141 TXRX_DNW1 = 0x01, // received in 1st DN slot
mluis 0:62d1edcc13d1 142 TXRX_DNW2 = 0x02, // received in 2dn DN slot
mluis 0:62d1edcc13d1 143 TXRX_PING = 0x04 }; // received in a scheduled RX slot
mluis 0:62d1edcc13d1 144 // Event types for event callback
mluis 0:62d1edcc13d1 145 enum _ev_t { EV_SCAN_TIMEOUT=1, EV_BEACON_FOUND,
mluis 1:d3b7bde3995c 146 EV_BEACON_MISSED, EV_BEACON_TRACKED, EV_JOINING,
mluis 1:d3b7bde3995c 147 EV_JOINED, EV_RFU1, EV_JOIN_FAILED, EV_REJOIN_FAILED,
mluis 1:d3b7bde3995c 148 EV_TXCOMPLETE, EV_LOST_TSYNC, EV_RESET,
mluis 1:d3b7bde3995c 149 EV_RXCOMPLETE, EV_LINK_DEAD, EV_LINK_ALIVE };
mluis 0:62d1edcc13d1 150 typedef enum _ev_t ev_t;
mluis 0:62d1edcc13d1 151
mluis 0:62d1edcc13d1 152
mluis 0:62d1edcc13d1 153 struct lmic_t {
mluis 0:62d1edcc13d1 154 // Radio settings TX/RX (also accessed by HAL)
mluis 0:62d1edcc13d1 155 ostime_t txend;
mluis 0:62d1edcc13d1 156 ostime_t rxtime;
mluis 0:62d1edcc13d1 157 u4_t freq;
mluis 1:d3b7bde3995c 158 s1_t rssi;
mluis 1:d3b7bde3995c 159 s1_t snr;
mluis 0:62d1edcc13d1 160 rps_t rps;
mluis 0:62d1edcc13d1 161 u1_t rxsyms;
mluis 1:d3b7bde3995c 162 u1_t dndr;
mluis 0:62d1edcc13d1 163 s1_t txpow; // dBm
dudmuck 2:974cafbfb159 164 s1_t txpow_limit; // dBm maximum permitted
mluis 0:62d1edcc13d1 165
mluis 0:62d1edcc13d1 166 osjob_t osjob;
mluis 0:62d1edcc13d1 167
mluis 0:62d1edcc13d1 168 // Channel scheduling
mluis 1:d3b7bde3995c 169 #if defined(CFG_eu868)
mluis 0:62d1edcc13d1 170 band_t bands[MAX_BANDS];
mluis 0:62d1edcc13d1 171 u4_t channelFreq[MAX_CHANNELS];
mluis 1:d3b7bde3995c 172 u2_t channelDrMap[MAX_CHANNELS];
mluis 0:62d1edcc13d1 173 u2_t channelMap;
mluis 1:d3b7bde3995c 174 #elif defined(CFG_us915)
mluis 1:d3b7bde3995c 175 u4_t xchFreq[MAX_XCHANNELS]; // extra channel frequencies (if device is behind a repeater)
mluis 1:d3b7bde3995c 176 u2_t xchDrMap[MAX_XCHANNELS]; // extra channel datarate ranges ---XXX: ditto
mluis 0:62d1edcc13d1 177 u2_t channelMap[(72+MAX_XCHANNELS+15)/16]; // enabled bits
mluis 1:d3b7bde3995c 178 u2_t chRnd; // channel randomizer
mluis 0:62d1edcc13d1 179 #endif
mluis 0:62d1edcc13d1 180 u1_t txChnl; // channel for next TX
mluis 0:62d1edcc13d1 181 u1_t globalDutyRate; // max rate: 1/2^k
mluis 0:62d1edcc13d1 182 ostime_t globalDutyAvail; // time device can send again
mluis 0:62d1edcc13d1 183
mluis 0:62d1edcc13d1 184 u4_t netid; // current network id (~0 - none)
mluis 0:62d1edcc13d1 185 u2_t opmode;
mluis 0:62d1edcc13d1 186 u1_t upRepeat; // configured up repeat
mluis 0:62d1edcc13d1 187 s1_t adrTxPow; // ADR adjusted TX power
mluis 0:62d1edcc13d1 188 u1_t datarate; // current data rate
mluis 0:62d1edcc13d1 189 u1_t errcr; // error coding rate (used for TX only)
mluis 0:62d1edcc13d1 190 u1_t rejoinCnt; // adjustment for rejoin datarate
dudmuck 2:974cafbfb159 191 u1_t joinBlock; // during join attempt: current channel block
dudmuck 2:974cafbfb159 192 u1_t joinBlockChnl; // during join attempt: current 125KHz channel
mluis 0:62d1edcc13d1 193 s2_t drift; // last measured drift
mluis 0:62d1edcc13d1 194 s2_t lastDriftDiff;
mluis 0:62d1edcc13d1 195 s2_t maxDriftDiff;
mluis 0:62d1edcc13d1 196
mluis 0:62d1edcc13d1 197 u1_t pendTxPort;
mluis 0:62d1edcc13d1 198 u1_t pendTxConf; // confirmed data
mluis 0:62d1edcc13d1 199 u1_t pendTxLen; // +0x80 = confirmed
mluis 0:62d1edcc13d1 200 u1_t pendTxData[MAX_LEN_PAYLOAD];
mluis 0:62d1edcc13d1 201
mluis 0:62d1edcc13d1 202 u2_t devNonce; // last generated nonce
mluis 0:62d1edcc13d1 203 u1_t nwkKey[16]; // network session key
mluis 0:62d1edcc13d1 204 u1_t artKey[16]; // application router session key
mluis 0:62d1edcc13d1 205 devaddr_t devaddr;
mluis 0:62d1edcc13d1 206 u4_t seqnoDn; // device level down stream seqno
mluis 0:62d1edcc13d1 207 u4_t seqnoUp;
mluis 0:62d1edcc13d1 208
mluis 0:62d1edcc13d1 209 u1_t dnConf; // dn frame confirm pending: LORA::FCT_ACK or 0
mluis 0:62d1edcc13d1 210 s1_t adrAckReq; // counter until we reset data rate (0=off)
mluis 0:62d1edcc13d1 211 u1_t adrChanged;
mluis 0:62d1edcc13d1 212
mluis 0:62d1edcc13d1 213 u1_t margin;
mluis 0:62d1edcc13d1 214 bit_t ladrAns; // link adr adapt answer pending
mluis 0:62d1edcc13d1 215 bit_t devsAns; // device status answer pending
mluis 0:62d1edcc13d1 216 u1_t adrEnabled;
mluis 0:62d1edcc13d1 217 u1_t moreData; // NWK has more data pending
mluis 0:62d1edcc13d1 218 bit_t dutyCapAns; // have to ACK duty cycle settings
mluis 0:62d1edcc13d1 219 u1_t snchAns; // answer set new channel
mluis 0:62d1edcc13d1 220 // 2nd RX window (after up stream)
mluis 0:62d1edcc13d1 221 u1_t dn2Dr;
mluis 0:62d1edcc13d1 222 u4_t dn2Freq;
mluis 0:62d1edcc13d1 223 u1_t dn2Ans; // 0=no answer pend, 0x80+ACKs
mluis 0:62d1edcc13d1 224
mluis 0:62d1edcc13d1 225 // Class B state
mluis 0:62d1edcc13d1 226 u1_t missedBcns; // unable to track last N beacons
mluis 0:62d1edcc13d1 227 u1_t bcninfoTries; // how often to try (scan mode only)
mluis 0:62d1edcc13d1 228 u1_t pingSetAns; // answer set cmd and ACK bits
mluis 0:62d1edcc13d1 229 rxsched_t ping; // pingable setup
mluis 0:62d1edcc13d1 230
mluis 0:62d1edcc13d1 231 // Public part of MAC state
mluis 0:62d1edcc13d1 232 u1_t txCnt;
mluis 0:62d1edcc13d1 233 u1_t txrxFlags; // transaction flags (TX-RX combo)
mluis 0:62d1edcc13d1 234 u1_t dataBeg; // 0 or start of data (dataBeg-1 is port)
mluis 0:62d1edcc13d1 235 u1_t dataLen; // 0 no data or zero length data, >0 byte count of data
mluis 0:62d1edcc13d1 236 u1_t frame[MAX_LEN_FRAME];
mluis 0:62d1edcc13d1 237
mluis 0:62d1edcc13d1 238 u1_t bcnChnl;
mluis 0:62d1edcc13d1 239 u1_t bcnRxsyms; //
mluis 0:62d1edcc13d1 240 ostime_t bcnRxtime;
mluis 0:62d1edcc13d1 241 bcninfo_t bcninfo; // Last received beacon info
mluis 0:62d1edcc13d1 242 };
mluis 1:d3b7bde3995c 243 //! \var struct lmic_t LMIC
mluis 1:d3b7bde3995c 244 //! The state of LMIC MAC layer is encapsulated in this variable.
mluis 1:d3b7bde3995c 245 DECLARE_LMIC; //!< \internal
mluis 0:62d1edcc13d1 246
mluis 1:d3b7bde3995c 247 //! Construct a bit map of allowed datarates from drlo to drhi (both included).
mluis 1:d3b7bde3995c 248 #define DR_RANGE_MAP(drlo,drhi) (((u2_t)0xFFFF<<(drlo)) & ((u2_t)0xFFFF>>(15-(drhi))))
mluis 1:d3b7bde3995c 249 #if defined(CFG_eu868)
mluis 1:d3b7bde3995c 250 enum { BAND_MILLI=0, BAND_CENTI=1, BAND_DECI=2, BAND_AUX=3 };
mluis 1:d3b7bde3995c 251 bit_t LMIC_setupBand (u1_t bandidx, s1_t txpow, u2_t txcap);
mluis 1:d3b7bde3995c 252 #endif
mluis 1:d3b7bde3995c 253 bit_t LMIC_setupChannel (u1_t channel, u4_t freq, u2_t drmap, s1_t band);
mluis 1:d3b7bde3995c 254 void LMIC_disableChannel (u1_t channel);
mluis 0:62d1edcc13d1 255
mluis 0:62d1edcc13d1 256 void LMIC_setDrTxpow (dr_t dr, s1_t txpow); // set default/start DR/txpow
mluis 0:62d1edcc13d1 257 void LMIC_setAdrMode (bit_t enabled); // set ADR mode (if mobile turn off)
mluis 0:62d1edcc13d1 258 bit_t LMIC_startJoining (void);
mluis 0:62d1edcc13d1 259
mluis 0:62d1edcc13d1 260 void LMIC_shutdown (void);
mluis 0:62d1edcc13d1 261 void LMIC_init (void);
mluis 0:62d1edcc13d1 262 void LMIC_reset (void);
mluis 0:62d1edcc13d1 263 void LMIC_clrTxData (void);
mluis 0:62d1edcc13d1 264 void LMIC_setTxData (void);
mluis 0:62d1edcc13d1 265 int LMIC_setTxData2 (u1_t port, xref2u1_t data, u1_t dlen, u1_t confirmed);
mluis 0:62d1edcc13d1 266 void LMIC_sendAlive (void);
mluis 0:62d1edcc13d1 267
mluis 0:62d1edcc13d1 268 bit_t LMIC_enableTracking (u1_t tryBcnInfo);
mluis 0:62d1edcc13d1 269 void LMIC_disableTracking (void);
mluis 0:62d1edcc13d1 270
mluis 0:62d1edcc13d1 271 void LMIC_stopPingable (void);
mluis 0:62d1edcc13d1 272 void LMIC_setPingable (u1_t intvExp);
mluis 0:62d1edcc13d1 273 void LMIC_tryRejoin (void);
mluis 1:d3b7bde3995c 274
mluis 1:d3b7bde3995c 275 void LMIC_setSession (u4_t netid, devaddr_t devaddr, xref2u1_t nwkKey, xref2u1_t artKey);
mluis 1:d3b7bde3995c 276 void LMIC_setLinkCheckMode (bit_t enabled);
mluis 1:d3b7bde3995c 277
dudmuck 2:974cafbfb159 278 void LMIC_reverse_memcpy(u1_t *dst, const u1_t *src, size_t len);
mluis 1:d3b7bde3995c 279 // Special APIs - for development or testing
mluis 1:d3b7bde3995c 280 // !!!See implementation for caveats!!!
mluis 0:62d1edcc13d1 281
mluis 0:62d1edcc13d1 282 #endif // _lmic_h_