LMIC for MOTE_L152RC

Dependents:   lmic_transmit

LoRa WAN in C for NA-mote 72

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 LMIC_reverse_memcpy() for AppEUI to keep same byte order as that 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 LMIC_reverse_memcpy() for DevEUI to keep same byte order as that 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.


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.

Information

DevEUI is entered in reverse order into C-code from that shown on server (unique device ID).

AppEUI is entered in reverse order into C-code from that shown on server.

AppEUI is equivalent to "Application"

transmit power limits

FCC Part 15 rules permit one watt of transmit power when more than 50 channels are used. When received by a 64-channel gateway, the maximum power may be used.

However, if end-device is sending to a 8-channel gateway (single SX1301), the maximum transmit power permitted is +20dBm.

To configure LMIC for use with 8-channel gateway, CHNL_HYBRID should be defined in in config.h, and should be undefined for use with 64-channel gateway.

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:
dudmuck
Date:
Fri Dec 04 01:05:11 2015 +0000
Revision:
10:6c0830baf10f
Parent:
0:f2716e543d97
correct DR4 channel used in 8ch mode.  added JOIN_SINGLE_CHANNEL_BLOCK option for faster joining in 8ch mode.

Who changed what in which revision?

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