IBM LoRa MAC in C (LMiC) mbed library port

Dependents:   lora-temperature LoRaWAN-lmic-app_HS LoRaWAN-lmic-app_huynh

LoRa WAN in C for sx1276 shield

Currently version 1.5


LoRaWAN network configuration for end-device

The following three pieces of information uniquely identifies end-device to network to allow over-the-air activation. These are stored in the end-device prior to join procedure.

AppEUI

Uniquely identifies application provider of end-device.

Least-significant byte first, 8 bytes, use reverse memcpy() to keep same order as shown on lora server.

example C code

static const u1_t APPEUI[8]  = { 0x01, 0x00, 0x01, 0x00, 0x00, 0x0C, 0x25, 0x00 };

This is copied into LMIC by os_getArtEui() callback function in application.

DevEUI

End-device ID, unique to each end-node.

Least-significant byte first, 8 bytes, use reverse memcpy() to keep same order as shown on lora server.

example C code

static const u1_t DEVEUI[8]  = { 0x00, 0x00, 0x00, 0x00, 0x01, 0x0C, 0x25, 0x00 }; 

This is copied into LMIC by os_getDevEui() callback function in application.

AppKey (aka DevKey)

128-bit (16byte) AES key.

example C code

static const u1_t DEVKEY[16] = { 0xe4, 0x72, 0x71, 0xc5, 0xf5, 0x30, 0xa9, 0x9f, 0xcf, 0xc4, 0x0e, 0xab, 0xea, 0xd7, 0x19, 0x42 };

This is copied into LMIC by os_getDevKey() callback function in application.

Using over-the air activation, the end-device (LMIC) performs a join procedure every time it starts for first time, or has lost session context information. When join procedure has successfully completed, the end-device will have a network session key (NwkSKey) and an application session key (AppSKey), which are used for encryption and message integrity check.


US915 configuration with http://us01-iot.semtech.com/

  • log in to server
  • click on Applications
  • find your application and click it
  • go to configure motes
  • to create a mote, you may enter a new DevEUI
    • you may copy-paste the 16byte application key from an already existing mote, if you desire.
CHNL_HYBRID125KHz500KHz
defined valuechannelschannel
00 to 764
18 to 1565
216 to 2366
324 to 3167
432 to 3968
540 to 4769
648 to 5570
756 to 6371
undef0 to 6364 to 71
Committer:
mluis
Date:
Thu Jan 22 12:50:49 2015 +0000
Revision:
0:62d1edcc13d1
Child:
1:d3b7bde3995c
Porting of IBM LoRa MAC in C (LMiC) to the mbed platform.

Who changed what in which revision?

UserRevisionLine numberNew contents of line
mluis 0:62d1edcc13d1 1 /*******************************************************************************
mluis 0:62d1edcc13d1 2 * Copyright (c) 2014 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 0:62d1edcc13d1 12 #ifndef _lorabase_h_
mluis 0:62d1edcc13d1 13 #define _lorabase_h_
mluis 0:62d1edcc13d1 14
mluis 0:62d1edcc13d1 15 // ================================================================================
mluis 0:62d1edcc13d1 16 // BEG: Keep in sync with lorabase.hpp
mluis 0:62d1edcc13d1 17 //
mluis 0:62d1edcc13d1 18
mluis 0:62d1edcc13d1 19 enum _cr_t { CR_4_5=0, CR_4_6, CR_4_7, CR_4_8 };
mluis 0:62d1edcc13d1 20 enum _sf_t { FSK=0, SF7, SF8, SF9, SF10, SF11, SF12, SFrfu };
mluis 0:62d1edcc13d1 21 enum _bw_t { BW125=0, BW250, BW500, BWrfu };
mluis 0:62d1edcc13d1 22 typedef u1_t cr_t;
mluis 0:62d1edcc13d1 23 typedef u1_t sf_t;
mluis 0:62d1edcc13d1 24 typedef u1_t bw_t;
mluis 0:62d1edcc13d1 25 typedef u1_t dr_t;
mluis 0:62d1edcc13d1 26 // Radio parameter set (encodes SF/BW/CR/IH/NOCRC)
mluis 0:62d1edcc13d1 27 typedef u2_t rps_t;
mluis 0:62d1edcc13d1 28 TYPEDEF_xref2rps_t;
mluis 0:62d1edcc13d1 29
mluis 0:62d1edcc13d1 30 enum { ILLEGAL_RPS = 0xFF };
mluis 0:62d1edcc13d1 31 enum { DR_PAGE_EU868 = 0x00 };
mluis 0:62d1edcc13d1 32 enum { DR_PAGE_US915 = 0x10 };
mluis 0:62d1edcc13d1 33
mluis 0:62d1edcc13d1 34 // Global maximum frame length
mluis 0:62d1edcc13d1 35 enum { STD_PREAMBLE_LEN = 8 };
mluis 0:62d1edcc13d1 36 enum { MAX_LEN_FRAME = 64 };
mluis 0:62d1edcc13d1 37 enum { LEN_DEVNONCE = 2 };
mluis 0:62d1edcc13d1 38 enum { LEN_ARTNONCE = 3 };
mluis 0:62d1edcc13d1 39 enum { LEN_NETID = 3 };
mluis 0:62d1edcc13d1 40 enum { DELAY_JACC1 = 5 }; // in secs
mluis 0:62d1edcc13d1 41 enum { DELAY_DNW1 = 1 }; // in secs down window #1
mluis 0:62d1edcc13d1 42 enum { DELAY_EXTDNW2 = 1 }; // in secs
mluis 0:62d1edcc13d1 43 enum { DELAY_JACC2 = DELAY_JACC1+(int)DELAY_EXTDNW2 }; // in secs
mluis 0:62d1edcc13d1 44 enum { DELAY_DNW2 = DELAY_DNW1 +(int)DELAY_EXTDNW2 }; // in secs down window #1
mluis 0:62d1edcc13d1 45 enum { BCN_INTV_exp = 7 };
mluis 0:62d1edcc13d1 46 enum { BCN_INTV_sec = 1<<BCN_INTV_exp };
mluis 0:62d1edcc13d1 47 enum { BCN_INTV_ms = BCN_INTV_sec*1000L };
mluis 0:62d1edcc13d1 48 enum { BCN_INTV_us = BCN_INTV_ms*1000L };
mluis 0:62d1edcc13d1 49 enum { BCN_RESERVE_ms = 2120 }; // space reserved for beacon and NWK management
mluis 0:62d1edcc13d1 50 enum { BCN_GUARD_ms = 3000 }; // end of beacon period to prevent interference with beacon
mluis 0:62d1edcc13d1 51 enum { BCN_SLOT_SPAN_ms = 30 }; // 2^12 reception slots a this span
mluis 0:62d1edcc13d1 52 enum { BCN_WINDOW_ms = BCN_INTV_ms-(int)BCN_GUARD_ms-(int)BCN_RESERVE_ms };
mluis 0:62d1edcc13d1 53 enum { BCN_RESERVE_us = 2120000 };
mluis 0:62d1edcc13d1 54 enum { BCN_GUARD_us = 3000000 };
mluis 0:62d1edcc13d1 55 enum { BCN_SLOT_SPAN_us = 30000 };
mluis 0:62d1edcc13d1 56
mluis 0:62d1edcc13d1 57 #if CFG_eu868 // ==============================================
mluis 0:62d1edcc13d1 58
mluis 0:62d1edcc13d1 59 enum _dr_eu868_t { DR_SF12=0, DR_SF11, DR_SF10, DR_SF9, DR_SF8, DR_SF7, DR_SF7B, DR_FSK, DR_NONE };
mluis 0:62d1edcc13d1 60 enum { DR_DFLTMIN = DR_SF7 };
mluis 0:62d1edcc13d1 61 enum { DR_PAGE = DR_PAGE_EU868 };
mluis 0:62d1edcc13d1 62
mluis 0:62d1edcc13d1 63 // Default frequency plan for EU 868MHz ISM band
mluis 0:62d1edcc13d1 64 // Bands:
mluis 0:62d1edcc13d1 65 // g1 : 1% 14dBm
mluis 0:62d1edcc13d1 66 // g2 : 0.1% 14dBm
mluis 0:62d1edcc13d1 67 // g3 : 10% 27dBm
mluis 0:62d1edcc13d1 68 // freq band datarates
mluis 0:62d1edcc13d1 69 enum { EU868_F1 = 868100000, // g1 SF7-12
mluis 0:62d1edcc13d1 70 EU868_F2 = 868300000, // g1 SF7-12 FSK SF7/250
mluis 0:62d1edcc13d1 71 EU868_F3 = 868500000, // g1 SF7-12
mluis 0:62d1edcc13d1 72 EU868_F4 = 868850000, // g2 SF7-12
mluis 0:62d1edcc13d1 73 EU868_F5 = 869050000, // g2 SF7-12
mluis 0:62d1edcc13d1 74 EU868_F6 = 869525000, // g3 SF7-12
mluis 0:62d1edcc13d1 75 EU868_J4 = 864100000, // g2 SF7-12 used during join
mluis 0:62d1edcc13d1 76 EU868_J5 = 864300000, // g2 SF7-12 ditto
mluis 0:62d1edcc13d1 77 EU868_J6 = 864500000, // g2 SF7-12 ditto
mluis 0:62d1edcc13d1 78 };
mluis 0:62d1edcc13d1 79 enum { EU868_FREQ_MIN = 863000000,
mluis 0:62d1edcc13d1 80 EU868_FREQ_MAX = 870000000 };
mluis 0:62d1edcc13d1 81
mluis 0:62d1edcc13d1 82 enum { CHNL_PING = 5 };
mluis 0:62d1edcc13d1 83 enum { FREQ_PING = EU868_F6 }; // default ping freq
mluis 0:62d1edcc13d1 84 enum { DR_PING = SF9 }; // default ping DR
mluis 0:62d1edcc13d1 85 enum { CHNL_DNW2 = 5 };
mluis 0:62d1edcc13d1 86 enum { FREQ_DNW2 = EU868_F6 };
mluis 0:62d1edcc13d1 87 enum { DR_DNW2 = DR_SF9 };
mluis 0:62d1edcc13d1 88 enum { CHNL_BCN = 5 };
mluis 0:62d1edcc13d1 89 enum { FREQ_BCN = EU868_F6 };
mluis 0:62d1edcc13d1 90 enum { DR_BCN = DR_SF9 };
mluis 0:62d1edcc13d1 91 enum { AIRTIME_BCN = 185344 }; // micros
mluis 0:62d1edcc13d1 92
mluis 0:62d1edcc13d1 93 #elif CFG_us915 // =========================================
mluis 0:62d1edcc13d1 94
mluis 0:62d1edcc13d1 95 enum _dr_us915_t { DR_SF10=0, DR_SF9, DR_SF8, DR_SF7, DR_SF8C, DR_NONE,
mluis 0:62d1edcc13d1 96 // Devices behind a router:
mluis 0:62d1edcc13d1 97 DR_SF12CR=8, DR_SF11CR, DR_SF10CR, DR_SF9CR, DR_SF8CR, DR_SF7CR };
mluis 0:62d1edcc13d1 98 enum { DR_DFLTMIN = DR_SF8C };
mluis 0:62d1edcc13d1 99 enum { DR_PAGE = DR_PAGE_US915 };
mluis 0:62d1edcc13d1 100
mluis 0:62d1edcc13d1 101 // Default frequency plan for US 915MHz
mluis 0:62d1edcc13d1 102 enum { US915_125kHz_UPFBASE = 902300000,
mluis 0:62d1edcc13d1 103 US915_125kHz_UPFSTEP = 200000,
mluis 0:62d1edcc13d1 104 US915_500kHz_UPFBASE = 903000000,
mluis 0:62d1edcc13d1 105 US915_500kHz_UPFSTEP = 1600000,
mluis 0:62d1edcc13d1 106 US915_500kHz_DNFBASE = 923300000,
mluis 0:62d1edcc13d1 107 US915_500kHz_DNFSTEP = 600000
mluis 0:62d1edcc13d1 108 };
mluis 0:62d1edcc13d1 109 enum { US915_FREQ_MIN = 902000000,
mluis 0:62d1edcc13d1 110 US915_FREQ_MAX = 928000000 };
mluis 0:62d1edcc13d1 111
mluis 0:62d1edcc13d1 112 enum { CHNL_PING = 2 };
mluis 0:62d1edcc13d1 113 enum { FREQ_PING = US915_500kHz_DNFBASE + CHNL_PING*US915_500kHz_DNFSTEP }; // default ping freq
mluis 0:62d1edcc13d1 114 enum { DR_PING = DR_SF10CR }; // default ping DR
mluis 0:62d1edcc13d1 115 enum { CHNL_DNW2 = 1 };
mluis 0:62d1edcc13d1 116 enum { FREQ_DNW2 = US915_500kHz_DNFBASE + CHNL_DNW2*US915_500kHz_DNFSTEP };
mluis 0:62d1edcc13d1 117 enum { DR_DNW2 = DR_SF10CR };
mluis 0:62d1edcc13d1 118 enum { CHNL_BCN = 0 };
mluis 0:62d1edcc13d1 119 enum { FREQ_BCN = US915_500kHz_DNFBASE + CHNL_BCN*US915_500kHz_DNFSTEP };
mluis 0:62d1edcc13d1 120 enum { DR_BCN = DR_SF10CR };
mluis 0:62d1edcc13d1 121 enum { AIRTIME_BCN = 82432 }; // micros
mluis 0:62d1edcc13d1 122
mluis 0:62d1edcc13d1 123 #endif // ===================================================
mluis 0:62d1edcc13d1 124
mluis 0:62d1edcc13d1 125
mluis 0:62d1edcc13d1 126 enum {
mluis 0:62d1edcc13d1 127 // Beacon frame format
mluis 0:62d1edcc13d1 128 OFF_BCN_RFU = 0,
mluis 0:62d1edcc13d1 129 OFF_BCN_NETID = 4,
mluis 0:62d1edcc13d1 130 OFF_BCN_CMAP = 7,
mluis 0:62d1edcc13d1 131 OFF_BCN_TIME = 9,
mluis 0:62d1edcc13d1 132 OFF_BCN_CRC1 = 13,
mluis 0:62d1edcc13d1 133 OFF_BCN_INFO = 15,
mluis 0:62d1edcc13d1 134 OFF_BCN_LAT = 16,
mluis 0:62d1edcc13d1 135 OFF_BCN_LON = 19,
mluis 0:62d1edcc13d1 136 OFF_BCN_CRC2 = 22,
mluis 0:62d1edcc13d1 137 LEN_BCN = 24
mluis 0:62d1edcc13d1 138 };
mluis 0:62d1edcc13d1 139 enum {
mluis 0:62d1edcc13d1 140 // Join Request frame format
mluis 0:62d1edcc13d1 141 OFF_JR_HDR = 0,
mluis 0:62d1edcc13d1 142 OFF_JR_ARTEUI = 1,
mluis 0:62d1edcc13d1 143 OFF_JR_DEVEUI = 9,
mluis 0:62d1edcc13d1 144 OFF_JR_DEVNONCE = 17,
mluis 0:62d1edcc13d1 145 OFF_JR_MIC = 19,
mluis 0:62d1edcc13d1 146 LEN_JR = 23
mluis 0:62d1edcc13d1 147 };
mluis 0:62d1edcc13d1 148 enum {
mluis 0:62d1edcc13d1 149 // Join Accept frame format
mluis 0:62d1edcc13d1 150 OFF_JA_HDR = 0,
mluis 0:62d1edcc13d1 151 OFF_JA_ARTNONCE = 1,
mluis 0:62d1edcc13d1 152 OFF_JA_NETID = 4,
mluis 0:62d1edcc13d1 153 OFF_JA_DEVADDR = 7,
mluis 0:62d1edcc13d1 154 OFF_JA_RFU = 11,
mluis 0:62d1edcc13d1 155 OFF_CFLIST = 14,
mluis 0:62d1edcc13d1 156 LEN_JA = 17,
mluis 0:62d1edcc13d1 157 LEN_JAEXT = 17+16
mluis 0:62d1edcc13d1 158 };
mluis 0:62d1edcc13d1 159 enum {
mluis 0:62d1edcc13d1 160 // Data frame format
mluis 0:62d1edcc13d1 161 OFF_DAT_HDR = 0,
mluis 0:62d1edcc13d1 162 OFF_DAT_ADDR = 1,
mluis 0:62d1edcc13d1 163 OFF_DAT_FCT = 5,
mluis 0:62d1edcc13d1 164 OFF_DAT_SEQNO = 6,
mluis 0:62d1edcc13d1 165 OFF_DAT_OPTS = 8,
mluis 0:62d1edcc13d1 166 };
mluis 0:62d1edcc13d1 167 enum { MAX_LEN_PAYLOAD = MAX_LEN_FRAME-(int)OFF_DAT_OPTS-4 };
mluis 0:62d1edcc13d1 168 enum {
mluis 0:62d1edcc13d1 169 // Bitfields in frame format octet
mluis 0:62d1edcc13d1 170 HDR_FTYPE = 0xE0,
mluis 0:62d1edcc13d1 171 HDR_RFU = 0x1C,
mluis 0:62d1edcc13d1 172 HDR_MAJOR = 0x03
mluis 0:62d1edcc13d1 173 };
mluis 0:62d1edcc13d1 174 enum { HDR_FTYPE_DNFLAG = 0x20 }; // flags DN frame except for HDR_FTYPE_PROP
mluis 0:62d1edcc13d1 175 enum {
mluis 0:62d1edcc13d1 176 // Values of frame type bit field
mluis 0:62d1edcc13d1 177 HDR_FTYPE_JREQ = 0x00,
mluis 0:62d1edcc13d1 178 HDR_FTYPE_JACC = 0x20,
mluis 0:62d1edcc13d1 179 HDR_FTYPE_DAUP = 0x40, // data (unconfirmed) up
mluis 0:62d1edcc13d1 180 HDR_FTYPE_DADN = 0x60, // data (unconfirmed) dn
mluis 0:62d1edcc13d1 181 HDR_FTYPE_DCUP = 0x80, // data confirmed up
mluis 0:62d1edcc13d1 182 HDR_FTYPE_DCDN = 0xA0, // data confirmed dn
mluis 0:62d1edcc13d1 183 HDR_FTYPE_REJOIN = 0xC0, // rejoin for roaming
mluis 0:62d1edcc13d1 184 HDR_FTYPE_PROP = 0xE0
mluis 0:62d1edcc13d1 185 };
mluis 0:62d1edcc13d1 186 enum {
mluis 0:62d1edcc13d1 187 HDR_MAJOR_V1 = 0x00,
mluis 0:62d1edcc13d1 188 };
mluis 0:62d1edcc13d1 189 enum {
mluis 0:62d1edcc13d1 190 // Bitfields in frame control octet
mluis 0:62d1edcc13d1 191 FCT_ADREN = 0x80,
mluis 0:62d1edcc13d1 192 FCT_ADRARQ = 0x40,
mluis 0:62d1edcc13d1 193 FCT_ACK = 0x20,
mluis 0:62d1edcc13d1 194 FCT_MORE = 0x10,
mluis 0:62d1edcc13d1 195 FCT_OPTLEN = 0x0F,
mluis 0:62d1edcc13d1 196 };
mluis 0:62d1edcc13d1 197 enum {
mluis 0:62d1edcc13d1 198 NWKID_MASK = (int)0xFE000000,
mluis 0:62d1edcc13d1 199 NWKID_BITS = 7
mluis 0:62d1edcc13d1 200 };
mluis 0:62d1edcc13d1 201
mluis 0:62d1edcc13d1 202 // MAC uplink commands downwlink too
mluis 0:62d1edcc13d1 203 enum {
mluis 0:62d1edcc13d1 204 // Class A
mluis 0:62d1edcc13d1 205 MCMD_LCHK_REQ = 0x02, // - link check request : -
mluis 0:62d1edcc13d1 206 MCMD_LADR_ANS = 0x03, // - link ADR answer : u1:7-3:RFU, 3/2/1: pow/DR/Ch ACK
mluis 0:62d1edcc13d1 207 MCMD_DCAP_ANS = 0x04, // - duty cycle answer : -
mluis 0:62d1edcc13d1 208 MCMD_DN2P_ANS = 0x05, // - 2nd DN slot status : u1:7-2:RFU 1/0:datarate/channel ack
mluis 0:62d1edcc13d1 209 MCMD_DEVS_ANS = 0x06, // - device status ans : u1:battery 0,1-254,255=?, u1:7-6:RFU,5-0:margin(-32..31)
mluis 0:62d1edcc13d1 210 MCMD_SNCH_ANS = 0x07, // - set new channel : u1: 7-2=RFU, 1/0:DR/freq ACK
mluis 0:62d1edcc13d1 211 // Class B
mluis 0:62d1edcc13d1 212 MCMD_PING_IND = 0x10, // - pingability indic : u1: 7=RFU, 6-4:interval, 3-0:datarate
mluis 0:62d1edcc13d1 213 MCMD_PING_ANS = 0x11, // - ack ping freq : u1: 7-1:RFU, 0:freq ok
mluis 0:62d1edcc13d1 214 MCMD_BCNI_REQ = 0x12, // - next beacon start : -
mluis 0:62d1edcc13d1 215 };
mluis 0:62d1edcc13d1 216
mluis 0:62d1edcc13d1 217 // MAC downlink commands
mluis 0:62d1edcc13d1 218 enum {
mluis 0:62d1edcc13d1 219 // Class A
mluis 0:62d1edcc13d1 220 MCMD_LCHK_ANS = 0x02, // link check answer : u1:margin 0-254,255=unknown margin / u1:gwcnt
mluis 0:62d1edcc13d1 221 MCMD_LADR_REQ = 0x03, // link ADR request : u1:DR/TXPow, u2:chmask, u1:chpage/repeat
mluis 0:62d1edcc13d1 222 MCMD_DCAP_REQ = 0x04, // duty cycle cap : u1:255 dead [7-4]:RFU, [3-0]:cap 2^-k
mluis 0:62d1edcc13d1 223 MCMD_DN2P_SET = 0x05, // 2nd DN window param: u1:7-4:RFU/3-0:datarate, u3:freq
mluis 0:62d1edcc13d1 224 MCMD_DEVS_REQ = 0x06, // device status req : -
mluis 0:62d1edcc13d1 225 MCMD_SNCH_REQ = 0x07, // set new channel : u1:chidx, u3:freq, u1:DRrange
mluis 0:62d1edcc13d1 226 // Class B
mluis 0:62d1edcc13d1 227 MCMD_PING_SET = 0x11, // set ping freq : u3: freq
mluis 0:62d1edcc13d1 228 MCMD_BCNI_ANS = 0x12, // next beacon start : u2: delay(10ms), u1:channel
mluis 0:62d1edcc13d1 229 };
mluis 0:62d1edcc13d1 230
mluis 0:62d1edcc13d1 231 enum {
mluis 0:62d1edcc13d1 232 MCMD_LADR_ANS_RFU = 0xF8, // RFU bits
mluis 0:62d1edcc13d1 233 MCMD_LADR_ANS_POWACK = 0x04, // 0=not supported power level
mluis 0:62d1edcc13d1 234 MCMD_LADR_ANS_DRACK = 0x02, // 0=unknown data rate
mluis 0:62d1edcc13d1 235 MCMD_LADR_ANS_CHACK = 0x01, // 0=unknown channel enabled
mluis 0:62d1edcc13d1 236 };
mluis 0:62d1edcc13d1 237 enum {
mluis 0:62d1edcc13d1 238 MCMD_DN2P_ANS_RFU = 0xFC, // RFU bits
mluis 0:62d1edcc13d1 239 MCMD_DN2P_ANS_DRACK = 0x02, // 0=unknown data rate
mluis 0:62d1edcc13d1 240 MCMD_DN2P_ANS_CHACK = 0x01, // 0=unknown channel enabled
mluis 0:62d1edcc13d1 241 };
mluis 0:62d1edcc13d1 242 enum {
mluis 0:62d1edcc13d1 243 MCMD_SNCH_ANS_RFU = 0xFC, // RFU bits
mluis 0:62d1edcc13d1 244 MCMD_SNCH_ANS_DRACK = 0x02, // 0=unknown data rate
mluis 0:62d1edcc13d1 245 MCMD_SNCH_ANS_FQACK = 0x01, // 0=rejected channel frequency
mluis 0:62d1edcc13d1 246 };
mluis 0:62d1edcc13d1 247 enum {
mluis 0:62d1edcc13d1 248 MCMD_PING_ANS_RFU = 0xFE,
mluis 0:62d1edcc13d1 249 MCMD_PING_ANS_FQACK = 0x01
mluis 0:62d1edcc13d1 250 };
mluis 0:62d1edcc13d1 251
mluis 0:62d1edcc13d1 252 enum {
mluis 0:62d1edcc13d1 253 MCMD_DEVS_EXT_POWER = 0x00, // external power supply
mluis 0:62d1edcc13d1 254 MCMD_DEVS_BATT_MIN = 0x01, // min battery value
mluis 0:62d1edcc13d1 255 MCMD_DEVS_BATT_MAX = 0xFE, // max battery value
mluis 0:62d1edcc13d1 256 MCMD_DEVS_BATT_NOINFO = 0xFF, // unknown battery level
mluis 0:62d1edcc13d1 257 };
mluis 0:62d1edcc13d1 258
mluis 0:62d1edcc13d1 259 // Bit fields byte#3 of MCMD_LADR_REQ payload
mluis 0:62d1edcc13d1 260 enum {
mluis 0:62d1edcc13d1 261 MCMD_LADR_CHP_125ON = 0x60, // special channel page enable, bits applied to 64..71
mluis 0:62d1edcc13d1 262 MCMD_LADR_CHP_125OFF = 0x70, // ditto
mluis 0:62d1edcc13d1 263 MCMD_LADR_N3RFU_MASK = 0x80,
mluis 0:62d1edcc13d1 264 MCMD_LADR_CHPAGE_MASK = 0xF0,
mluis 0:62d1edcc13d1 265 MCMD_LADR_REPEAT_MASK = 0x0F,
mluis 0:62d1edcc13d1 266 MCMD_LADR_REPEAT_1 = 0x01,
mluis 0:62d1edcc13d1 267 MCMD_LADR_CHPAGE_1 = 0x10
mluis 0:62d1edcc13d1 268 };
mluis 0:62d1edcc13d1 269 // Bit fields byte#0 of MCMD_LADR_REQ payload
mluis 0:62d1edcc13d1 270 enum {
mluis 0:62d1edcc13d1 271 MCMD_LADR_DR_MASK = 0xF0,
mluis 0:62d1edcc13d1 272 MCMD_LADR_POW_MASK = 0x0F,
mluis 0:62d1edcc13d1 273 MCMD_LADR_DR_SHIFT = 4,
mluis 0:62d1edcc13d1 274 MCMD_LADR_POW_SHIFT = 0,
mluis 0:62d1edcc13d1 275 #if CFG_eu868
mluis 0:62d1edcc13d1 276 MCMD_LADR_SF12 = DR_SF12<<4,
mluis 0:62d1edcc13d1 277 MCMD_LADR_SF11 = DR_SF11<<4,
mluis 0:62d1edcc13d1 278 MCMD_LADR_SF10 = DR_SF10<<4,
mluis 0:62d1edcc13d1 279 MCMD_LADR_SF9 = DR_SF9 <<4,
mluis 0:62d1edcc13d1 280 MCMD_LADR_SF8 = DR_SF8 <<4,
mluis 0:62d1edcc13d1 281 MCMD_LADR_SF7 = DR_SF7 <<4,
mluis 0:62d1edcc13d1 282 MCMD_LADR_SF7B = DR_SF7B<<4,
mluis 0:62d1edcc13d1 283 MCMD_LADR_FSK = DR_FSK <<4,
mluis 0:62d1edcc13d1 284
mluis 0:62d1edcc13d1 285 MCMD_LADR_20dBm = 0,
mluis 0:62d1edcc13d1 286 MCMD_LADR_14dBm = 1,
mluis 0:62d1edcc13d1 287 MCMD_LADR_11dBm = 2,
mluis 0:62d1edcc13d1 288 MCMD_LADR_8dBm = 3,
mluis 0:62d1edcc13d1 289 MCMD_LADR_5dBm = 4,
mluis 0:62d1edcc13d1 290 MCMD_LADR_2dBm = 5,
mluis 0:62d1edcc13d1 291 #elif CFG_us915
mluis 0:62d1edcc13d1 292 MCMD_LADR_SF10 = DR_SF10<<4,
mluis 0:62d1edcc13d1 293 MCMD_LADR_SF9 = DR_SF9 <<4,
mluis 0:62d1edcc13d1 294 MCMD_LADR_SF8 = DR_SF8 <<4,
mluis 0:62d1edcc13d1 295 MCMD_LADR_SF7 = DR_SF7 <<4,
mluis 0:62d1edcc13d1 296 MCMD_LADR_SF8C = DR_SF8C<<4,
mluis 0:62d1edcc13d1 297 MCMD_LADR_SF12CR = DR_SF12CR<<4,
mluis 0:62d1edcc13d1 298 MCMD_LADR_SF11CR = DR_SF11CR<<4,
mluis 0:62d1edcc13d1 299 MCMD_LADR_SF10CR = DR_SF10CR<<4,
mluis 0:62d1edcc13d1 300 MCMD_LADR_SF9CR = DR_SF9CR<<4,
mluis 0:62d1edcc13d1 301 MCMD_LADR_SF8CR = DR_SF8CR<<4,
mluis 0:62d1edcc13d1 302 MCMD_LADR_SF7CR = DR_SF7CR<<4,
mluis 0:62d1edcc13d1 303
mluis 0:62d1edcc13d1 304 MCMD_LADR_30dBm = 0,
mluis 0:62d1edcc13d1 305 MCMD_LADR_28dBm = 1,
mluis 0:62d1edcc13d1 306 MCMD_LADR_26dBm = 2,
mluis 0:62d1edcc13d1 307 MCMD_LADR_24dBm = 3,
mluis 0:62d1edcc13d1 308 MCMD_LADR_22dBm = 4,
mluis 0:62d1edcc13d1 309 MCMD_LADR_20dBm = 5,
mluis 0:62d1edcc13d1 310 MCMD_LADR_18dBm = 6,
mluis 0:62d1edcc13d1 311 MCMD_LADR_16dBm = 7,
mluis 0:62d1edcc13d1 312 MCMD_LADR_14dBm = 8,
mluis 0:62d1edcc13d1 313 MCMD_LADR_12dBm = 9,
mluis 0:62d1edcc13d1 314 MCMD_LADR_10dBm = 10
mluis 0:62d1edcc13d1 315 #endif
mluis 0:62d1edcc13d1 316 };
mluis 0:62d1edcc13d1 317
mluis 0:62d1edcc13d1 318 // Device address
mluis 0:62d1edcc13d1 319 typedef u4_t devaddr_t;
mluis 0:62d1edcc13d1 320
mluis 0:62d1edcc13d1 321
mluis 0:62d1edcc13d1 322 // RX quality (device)
mluis 0:62d1edcc13d1 323 enum { RSSI_OFF=64, SNR_SCALEUP=4 };
mluis 0:62d1edcc13d1 324 struct rxqu_t {
mluis 0:62d1edcc13d1 325 s1_t rssi; // offset by RSSI_OFF, max physical RSSI range -198..+63
mluis 0:62d1edcc13d1 326 s1_t snr; // scaled by SNR_SCALEUP, max physical SNR range -32..+31.75
mluis 0:62d1edcc13d1 327 };
mluis 0:62d1edcc13d1 328 TYPEDEF_xref2rxqu_t;
mluis 0:62d1edcc13d1 329
mluis 0:62d1edcc13d1 330
mluis 0:62d1edcc13d1 331 inline sf_t getSf (rps_t params) { return (sf_t)(params & 0x7); }
mluis 0:62d1edcc13d1 332 inline rps_t setSf (rps_t params, sf_t sf) { return (rps_t)((params & ~0x7) | sf); }
mluis 0:62d1edcc13d1 333 inline bw_t getBw (rps_t params) { return (bw_t)((params >> 3) & 0x3); }
mluis 0:62d1edcc13d1 334 inline rps_t setBw (rps_t params, bw_t cr) { return (rps_t)((params & ~0x18) | (cr<<3)); }
mluis 0:62d1edcc13d1 335 inline cr_t getCr (rps_t params) { return (cr_t)((params >> 5) & 0x3); }
mluis 0:62d1edcc13d1 336 inline rps_t setCr (rps_t params, cr_t cr) { return (rps_t)((params & ~0x60) | (cr<<5)); }
mluis 0:62d1edcc13d1 337 inline int getNocrc(rps_t params) { return ((params >> 7) & 0x1); }
mluis 0:62d1edcc13d1 338 inline rps_t setNocrc(rps_t params, int nocrc) { return (rps_t)((params & ~0x80) | (nocrc<<7)); }
mluis 0:62d1edcc13d1 339 inline int getIh (rps_t params) { return ((params >> 8) & 0xFF); }
mluis 0:62d1edcc13d1 340 inline rps_t setIh (rps_t params, int ih) { return (rps_t)((params & ~0xFF00) | (ih<<8)); }
mluis 0:62d1edcc13d1 341 inline rps_t makeRps (sf_t sf, bw_t bw, cr_t cr, int ih, int nocrc) {
mluis 0:62d1edcc13d1 342 return sf | (bw<<3) | (cr<<5) | (nocrc?(1<<7):0) | ((ih&0xFF)<<8);
mluis 0:62d1edcc13d1 343 }
mluis 0:62d1edcc13d1 344 #define MAKERPS(sf,bw,cr,ih,nocrc) ((rps_t)((sf) | ((bw)<<3) | ((cr)<<5) | ((nocrc)?(1<<7):0) | ((ih&0xFF)<<8)))
mluis 0:62d1edcc13d1 345 // Two frames with params r1/r2 would interfere on air: same SFx + BWx
mluis 0:62d1edcc13d1 346 inline int sameSfBw(rps_t r1, rps_t r2) { return ((r1^r2)&0x1F) == 0; }
mluis 0:62d1edcc13d1 347
mluis 0:62d1edcc13d1 348 extern const u1_t _DR2RPS_CRC[];
mluis 0:62d1edcc13d1 349 inline rps_t updr2rps (dr_t dr) { return (rps_t)_DR2RPS_CRC[dr+1]; }
mluis 0:62d1edcc13d1 350 inline rps_t dndr2rps (dr_t dr) { return setNocrc(updr2rps(dr),1); }
mluis 0:62d1edcc13d1 351 inline int isFasterDR (dr_t dr1, dr_t dr2) { return dr1 > dr2; }
mluis 0:62d1edcc13d1 352 inline int isSlowerDR (dr_t dr1, dr_t dr2) { return dr1 < dr2; }
mluis 0:62d1edcc13d1 353 inline dr_t incDR (dr_t dr) { return _DR2RPS_CRC[dr+2]==ILLEGAL_RPS ? dr : (dr_t)(dr+1); } // increase data rate
mluis 0:62d1edcc13d1 354 inline dr_t decDR (dr_t dr) { return _DR2RPS_CRC[dr ]==ILLEGAL_RPS ? dr : (dr_t)(dr-1); } // decrease data rate
mluis 0:62d1edcc13d1 355 inline dr_t assertDR (dr_t dr) { return _DR2RPS_CRC[dr+1]==ILLEGAL_RPS ? DR_DFLTMIN : dr; } // force into a valid DR
mluis 0:62d1edcc13d1 356 inline bit_t validDR (dr_t dr) { return _DR2RPS_CRC[dr+1]!=ILLEGAL_RPS; } // in range
mluis 0:62d1edcc13d1 357 inline dr_t lowerDR (dr_t dr, u1_t n) { while(n--){dr=decDR(dr);} return dr; } // decrease data rate by n steps
mluis 0:62d1edcc13d1 358
mluis 0:62d1edcc13d1 359 //
mluis 0:62d1edcc13d1 360 // BEG: Keep in sync with lorabase.hpp
mluis 0:62d1edcc13d1 361 // ================================================================================
mluis 0:62d1edcc13d1 362
mluis 0:62d1edcc13d1 363
mluis 0:62d1edcc13d1 364 // Convert between dBm values and power codes (MCMD_LADR_XdBm)
mluis 0:62d1edcc13d1 365 s1_t pow2dBm (u1_t mcmd_ladr_p1);
mluis 0:62d1edcc13d1 366 // Calculate airtime
mluis 0:62d1edcc13d1 367 ostime_t calcAirTime (rps_t rps, u1_t plen);
mluis 0:62d1edcc13d1 368 // Sensitivity at given SF/BW
mluis 0:62d1edcc13d1 369 int getSensitivity (rps_t rps);
mluis 0:62d1edcc13d1 370
mluis 0:62d1edcc13d1 371
mluis 0:62d1edcc13d1 372 #endif // _lorabase_h_