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_HYBRID | 125KHz | 500KHz |
---|---|---|
defined value | channels | channel |
0 | 0 to 7 | 64 |
1 | 8 to 15 | 65 |
2 | 16 to 23 | 66 |
3 | 24 to 31 | 67 |
4 | 32 to 39 | 68 |
5 | 40 to 47 | 69 |
6 | 48 to 55 | 70 |
7 | 56 to 63 | 71 |
undef | 0 to 63 | 64 to 71 |
lorabase.h@0:62d1edcc13d1, 2015-01-22 (annotated)
- 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?
User | Revision | Line number | New 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_ |