LMiC LoRa Semtech + Nucleo

Dependents:   LoRaWAN-lmic-app

Fork of LMiC by Pascal Nysten

Embed: (wiki syntax)

« Back to documentation index

Show/hide line numbers lorabase.h Source File

lorabase.h

00001 /*******************************************************************************
00002  * Copyright (c) 2014-2015 IBM Corporation.
00003  * All rights reserved. This program and the accompanying materials
00004  * are made available under the terms of the Eclipse Public License v1.0
00005  * which accompanies this distribution, and is available at
00006  * http://www.eclipse.org/legal/epl-v10.html
00007  *
00008  * Contributors:
00009  *    IBM Zurich Research Lab - initial API, implementation and documentation
00010  *******************************************************************************/
00011 
00012 #ifndef _lorabase_h_
00013 #define _lorabase_h_
00014 
00015 // ================================================================================
00016 // BEG: Keep in sync with lorabase.hpp
00017 //
00018 
00019 enum _cr_t { CR_4_5=0, CR_4_6, CR_4_7, CR_4_8 };
00020 enum _sf_t { FSK=0, SF7, SF8, SF9, SF10, SF11, SF12, SFrfu };
00021 enum _bw_t { BW125=0, BW250, BW500, BWrfu };
00022 typedef u1_t cr_t;
00023 typedef u1_t sf_t;
00024 typedef u1_t bw_t;
00025 typedef u1_t dr_t;
00026 // Radio parameter set (encodes SF/BW/CR/IH/NOCRC)
00027 typedef u2_t rps_t;
00028 TYPEDEF_xref2rps_t;
00029 
00030 enum { ILLEGAL_RPS = 0xFF };
00031 enum { DR_PAGE_EU868 = 0x00 };
00032 enum { DR_PAGE_US915 = 0x10 };
00033 
00034 // Global maximum frame length
00035 enum { STD_PREAMBLE_LEN  =  8 };
00036 //enum { MAX_LEN_FRAME     =  96 };
00037 enum { MAX_LEN_FRAME     =  64 };
00038 enum { LEN_DEVNONCE      =  2 };
00039 enum { LEN_ARTNONCE      =  3 };
00040 enum { LEN_NETID         =  3 };
00041 enum { DELAY_JACC1       =  5 }; // in secs
00042 enum { DELAY_DNW1        =  1 }; // in secs down window #1
00043 enum { DELAY_EXTDNW2     =  1 }; // in secs
00044 enum { DELAY_JACC2       =  DELAY_JACC1+(int)DELAY_EXTDNW2 }; // in secs
00045 enum { DELAY_DNW2        =  DELAY_DNW1 +(int)DELAY_EXTDNW2 }; // in secs down window #1
00046 enum { BCN_INTV_exp      = 7 };
00047 enum { BCN_INTV_sec      = 1<<BCN_INTV_exp };
00048 enum { BCN_INTV_ms       = BCN_INTV_sec*1000L };
00049 enum { BCN_INTV_us       = BCN_INTV_ms*1000L };
00050 enum { BCN_RESERVE_ms    = 2120 };   // space reserved for beacon and NWK management
00051 enum { BCN_GUARD_ms      = 3000 };   // end of beacon period to prevent interference with beacon
00052 enum { BCN_SLOT_SPAN_ms  =   30 };   // 2^12 reception slots a this span
00053 enum { BCN_WINDOW_ms     = BCN_INTV_ms-(int)BCN_GUARD_ms-(int)BCN_RESERVE_ms };
00054 enum { BCN_RESERVE_us    = 2120000 };
00055 enum { BCN_GUARD_us      = 3000000 };
00056 enum { BCN_SLOT_SPAN_us  =   30000 };
00057 
00058 #if defined(CFG_eu868) // ==============================================
00059 
00060 enum _dr_eu868_t { DR_SF12=0, DR_SF11, DR_SF10, DR_SF9, DR_SF8, DR_SF7, DR_SF7B, DR_FSK, DR_NONE };
00061 enum { DR_DFLTMIN = DR_SF7 };
00062 enum { DR_PAGE = DR_PAGE_EU868 };
00063 
00064 // Default frequency plan for EU 868MHz ISM band
00065 // Bands:
00066 //  g1 :   1%  14dBm  
00067 //  g2 : 0.1%  14dBm  
00068 //  g3 :  10%  27dBm  
00069 //                 freq             band     datarates
00070 enum { EU868_F1 = 868100000,      // g1   SF7-12 
00071        EU868_F2 = 868300000,      // g1   SF7-12 FSK SF7/250         
00072        EU868_F3 = 868500000,      // g1   SF7-12         
00073        EU868_F4 = 868850000,      // g2   SF7-12         
00074        EU868_F5 = 869050000,      // g2   SF7-12         
00075        EU868_F6 = 869525000,      // g3   SF7-12         
00076        EU868_J4 = 864100000,      // g2   SF7-12  used during join
00077        EU868_J5 = 864300000,      // g2   SF7-12   ditto
00078        EU868_J6 = 864500000,      // g2   SF7-12   ditto
00079 };
00080 enum { EU868_FREQ_MIN = 863000000,
00081        EU868_FREQ_MAX = 870000000 };
00082 
00083 enum { CHNL_PING         = 5 };
00084 enum { FREQ_PING         = EU868_F6 };  // default ping freq
00085 enum { DR_PING           = SF9 };       // default ping DR
00086 enum { CHNL_DNW2         = 5 };
00087 enum { FREQ_DNW2         = EU868_F6 };
00088 enum { DR_DNW2           = DR_SF9 };    // changed from LoRaWAN specification.
00089                                         // Default value is DR_SF12
00090 enum { CHNL_BCN          = 5 };
00091 enum { FREQ_BCN          = EU868_F6 };
00092 enum { DR_BCN            = DR_SF9 };
00093 enum { AIRTIME_BCN       = 144384 };  // micros
00094 
00095 enum {
00096     // Beacon frame format EU SF9
00097     OFF_BCN_NETID    = 0,         
00098     OFF_BCN_TIME     = 3,
00099     OFF_BCN_CRC1     = 7,
00100     OFF_BCN_INFO     = 8,
00101     OFF_BCN_LAT      = 9,
00102     OFF_BCN_LON      = 12,
00103     OFF_BCN_CRC2     = 15,
00104     LEN_BCN          = 17
00105 };
00106 
00107 #elif defined(CFG_us915)  // =========================================
00108 
00109 enum _dr_us915_t { DR_SF10=0, DR_SF9, DR_SF8, DR_SF7, DR_SF8C, DR_NONE,
00110                    // Devices behind a router:
00111                    DR_SF12CR=8, DR_SF11CR, DR_SF10CR, DR_SF9CR, DR_SF8CR, DR_SF7CR };
00112 enum { DR_DFLTMIN = DR_SF8C };
00113 enum { DR_PAGE = DR_PAGE_US915 };
00114 
00115 // Default frequency plan for US 915MHz
00116 enum { US915_125kHz_UPFBASE = 902300000,
00117        US915_125kHz_UPFSTEP =    200000,
00118        US915_500kHz_UPFBASE = 903000000,
00119        US915_500kHz_UPFSTEP =   1600000,
00120        US915_500kHz_DNFBASE = 923300000,
00121        US915_500kHz_DNFSTEP =    600000
00122 };
00123 enum { US915_FREQ_MIN = 902000000,
00124        US915_FREQ_MAX = 928000000 };
00125 
00126 enum { CHNL_PING         = 0 }; // used only for default init of state (follows beacon - rotating)
00127 enum { FREQ_PING         = US915_500kHz_DNFBASE + CHNL_PING*US915_500kHz_DNFSTEP };  // default ping freq
00128 enum { DR_PING           = DR_SF10CR };       // default ping DR
00129 enum { CHNL_DNW2         = 0 };
00130 enum { FREQ_DNW2         = US915_500kHz_DNFBASE + CHNL_DNW2*US915_500kHz_DNFSTEP };
00131 enum { DR_DNW2           = DR_SF12CR };
00132 enum { CHNL_BCN          = 0 }; // used only for default init of state (rotating beacon scheme)
00133 enum { DR_BCN            = DR_SF10CR };
00134 enum { AIRTIME_BCN       = 72192 };  // micros
00135 
00136 enum {
00137     // Beacon frame format US SF10
00138     OFF_BCN_NETID    = 0,         
00139     OFF_BCN_TIME     = 3,
00140     OFF_BCN_CRC1     = 7,
00141     OFF_BCN_INFO     = 9,
00142     OFF_BCN_LAT      = 10,
00143     OFF_BCN_LON      = 13,
00144     OFF_BCN_RFU1     = 16,
00145     OFF_BCN_CRC2     = 17,
00146     LEN_BCN          = 19
00147 };
00148 
00149 #endif // ===================================================
00150 
00151 enum {
00152     // Join Request frame format
00153     OFF_JR_HDR      = 0,
00154     OFF_JR_ARTEUI   = 1,
00155     OFF_JR_DEVEUI   = 9,
00156     OFF_JR_DEVNONCE = 17,
00157     OFF_JR_MIC      = 19,
00158     LEN_JR          = 23
00159 };
00160 enum {
00161     // Join Accept frame format
00162     OFF_JA_HDR      = 0,
00163     OFF_JA_ARTNONCE = 1,
00164     OFF_JA_NETID    = 4,
00165     OFF_JA_DEVADDR  = 7,
00166     OFF_JA_RFU      = 11,
00167     OFF_JA_DLSET    = 11,
00168     OFF_JA_RXDLY    = 12,
00169     OFF_CFLIST      = 13,
00170     LEN_JA          = 17,
00171     LEN_JAEXT       = 17+16
00172 };
00173 enum {
00174     // Data frame format
00175     OFF_DAT_HDR      = 0,
00176     OFF_DAT_ADDR     = 1,
00177     OFF_DAT_FCT      = 5,
00178     OFF_DAT_SEQNO    = 6,
00179     OFF_DAT_OPTS     = 8,
00180 };
00181 enum { MAX_LEN_PAYLOAD = MAX_LEN_FRAME-(int)OFF_DAT_OPTS-4 };
00182 enum {
00183     // Bitfields in frame format octet
00184     HDR_FTYPE   = 0xE0,
00185     HDR_RFU     = 0x1C,
00186     HDR_MAJOR   = 0x03
00187 };
00188 enum { HDR_FTYPE_DNFLAG = 0x20 };  // flags DN frame except for HDR_FTYPE_PROP
00189 enum {
00190     // Values of frame type bit field
00191     HDR_FTYPE_JREQ   = 0x00,
00192     HDR_FTYPE_JACC   = 0x20,
00193     HDR_FTYPE_DAUP   = 0x40,  // data (unconfirmed) up
00194     HDR_FTYPE_DADN   = 0x60,  // data (unconfirmed) dn
00195     HDR_FTYPE_DCUP   = 0x80,  // data confirmed up
00196     HDR_FTYPE_DCDN   = 0xA0,  // data confirmed dn
00197     HDR_FTYPE_REJOIN = 0xC0,  // rejoin for roaming
00198     HDR_FTYPE_PROP   = 0xE0
00199 };
00200 enum {
00201     HDR_MAJOR_V1 = 0x00,
00202 };
00203 enum {
00204     // Bitfields in frame control octet
00205     FCT_ADREN  = 0x80,
00206     FCT_ADRARQ = 0x40,
00207     FCT_ACK    = 0x20,
00208     FCT_MORE   = 0x10,   // also in DN direction: Class B indicator
00209     FCT_OPTLEN = 0x0F,
00210 };
00211 enum {
00212     // In UP direction: signals class B enabled
00213     FCT_CLASSB = FCT_MORE
00214 };
00215 enum {
00216     NWKID_MASK = (int)0xFE000000,
00217     NWKID_BITS = 7
00218 };
00219 
00220 // MAC uplink commands   downwlink too
00221 enum {
00222     // Class A
00223     MCMD_LCHK_REQ = 0x02, // -  link check request : -
00224     MCMD_LADR_ANS = 0x03, // -  link ADR answer    : u1:7-3:RFU, 3/2/1: pow/DR/Ch ACK
00225     MCMD_DCAP_ANS = 0x04, // -  duty cycle answer  : -
00226     MCMD_DN2P_ANS = 0x05, // -  2nd DN slot status : u1:7-2:RFU  1/0:datarate/channel ack
00227     MCMD_DEVS_ANS = 0x06, // -  device status ans  : u1:battery 0,1-254,255=?, u1:7-6:RFU,5-0:margin(-32..31)
00228     MCMD_SNCH_ANS = 0x07, // -  set new channel    : u1: 7-2=RFU, 1/0:DR/freq ACK
00229     // Class B
00230     MCMD_PING_IND = 0x10, // -  pingability indic  : u1: 7=RFU, 6-4:interval, 3-0:datarate
00231     MCMD_PING_ANS = 0x11, // -  ack ping freq      : u1: 7-1:RFU, 0:freq ok
00232     MCMD_BCNI_REQ = 0x12, // -  next beacon start  : -
00233 };
00234 
00235 // MAC downlink commands
00236 enum {
00237     // Class A
00238     MCMD_LCHK_ANS = 0x02, // link check answer  : u1:margin 0-254,255=unknown margin / u1:gwcnt
00239     MCMD_LADR_REQ = 0x03, // link ADR request   : u1:DR/TXPow, u2:chmask, u1:chpage/repeat
00240     MCMD_DCAP_REQ = 0x04, // duty cycle cap     : u1:255 dead [7-4]:RFU, [3-0]:cap 2^-k
00241     MCMD_DN2P_SET = 0x05, // 2nd DN window param: u1:7-4:RFU/3-0:datarate, u3:freq
00242     MCMD_DEVS_REQ = 0x06, // device status req  : -
00243     MCMD_SNCH_REQ = 0x07, // set new channel    : u1:chidx, u3:freq, u1:DRrange
00244     // Class B
00245     MCMD_PING_SET = 0x11, // set ping freq      : u3: freq
00246     MCMD_BCNI_ANS = 0x12, // next beacon start  : u2: delay(in TUNIT millis), u1:channel
00247 };
00248 
00249 enum {
00250     MCMD_BCNI_TUNIT = 30  // time unit of delay value in millis
00251 };
00252 enum {
00253     MCMD_LADR_ANS_RFU    = 0xF8, // RFU bits
00254     MCMD_LADR_ANS_POWACK = 0x04, // 0=not supported power level
00255     MCMD_LADR_ANS_DRACK  = 0x02, // 0=unknown data rate
00256     MCMD_LADR_ANS_CHACK  = 0x01, // 0=unknown channel enabled
00257 };
00258 enum {
00259     MCMD_DN2P_ANS_RFU    = 0xFC, // RFU bits
00260     MCMD_DN2P_ANS_DRACK  = 0x02, // 0=unknown data rate
00261     MCMD_DN2P_ANS_CHACK  = 0x01, // 0=unknown channel enabled
00262 };
00263 enum {
00264     MCMD_SNCH_ANS_RFU    = 0xFC, // RFU bits
00265     MCMD_SNCH_ANS_DRACK  = 0x02, // 0=unknown data rate
00266     MCMD_SNCH_ANS_FQACK  = 0x01, // 0=rejected channel frequency
00267 };
00268 enum {
00269     MCMD_PING_ANS_RFU   = 0xFE,
00270     MCMD_PING_ANS_FQACK = 0x01
00271 };
00272 
00273 enum {
00274     MCMD_DEVS_EXT_POWER   = 0x00, // external power supply
00275     MCMD_DEVS_BATT_MIN    = 0x01, // min battery value
00276     MCMD_DEVS_BATT_MAX    = 0xFE, // max battery value
00277     MCMD_DEVS_BATT_NOINFO = 0xFF, // unknown battery level
00278 };
00279 
00280 // Bit fields byte#3 of MCMD_LADR_REQ payload
00281 enum {
00282     MCMD_LADR_CHP_125ON   = 0x60,  // special channel page enable, bits applied to 64..71
00283     MCMD_LADR_CHP_125OFF  = 0x70,  //  ditto
00284     MCMD_LADR_N3RFU_MASK  = 0x80,
00285     MCMD_LADR_CHPAGE_MASK = 0xF0,
00286     MCMD_LADR_REPEAT_MASK = 0x0F,
00287     MCMD_LADR_REPEAT_1    = 0x01,
00288     MCMD_LADR_CHPAGE_1    = 0x10
00289 };
00290 // Bit fields byte#0 of MCMD_LADR_REQ payload
00291 enum {
00292     MCMD_LADR_DR_MASK    = 0xF0,
00293     MCMD_LADR_POW_MASK   = 0x0F,
00294     MCMD_LADR_DR_SHIFT   = 4,
00295     MCMD_LADR_POW_SHIFT  = 0,
00296 #if defined(CFG_eu868)
00297     MCMD_LADR_SF12      = DR_SF12<<4,
00298     MCMD_LADR_SF11      = DR_SF11<<4,
00299     MCMD_LADR_SF10      = DR_SF10<<4,
00300     MCMD_LADR_SF9       = DR_SF9 <<4,
00301     MCMD_LADR_SF8       = DR_SF8 <<4,
00302     MCMD_LADR_SF7       = DR_SF7 <<4,
00303     MCMD_LADR_SF7B      = DR_SF7B<<4,
00304     MCMD_LADR_FSK       = DR_FSK <<4,
00305 
00306     MCMD_LADR_20dBm     = 0,
00307     MCMD_LADR_14dBm     = 1,
00308     MCMD_LADR_11dBm     = 2,
00309     MCMD_LADR_8dBm      = 3,
00310     MCMD_LADR_5dBm      = 4,
00311     MCMD_LADR_2dBm      = 5,
00312 #elif defined(CFG_us915)
00313     MCMD_LADR_SF10      = DR_SF10<<4,
00314     MCMD_LADR_SF9       = DR_SF9 <<4,
00315     MCMD_LADR_SF8       = DR_SF8 <<4,
00316     MCMD_LADR_SF7       = DR_SF7 <<4,
00317     MCMD_LADR_SF8C      = DR_SF8C<<4,
00318     MCMD_LADR_SF12CR    = DR_SF12CR<<4,
00319     MCMD_LADR_SF11CR    = DR_SF11CR<<4,
00320     MCMD_LADR_SF10CR    = DR_SF10CR<<4,
00321     MCMD_LADR_SF9CR     = DR_SF9CR<<4,
00322     MCMD_LADR_SF8CR     = DR_SF8CR<<4,
00323     MCMD_LADR_SF7CR     = DR_SF7CR<<4,
00324 
00325     MCMD_LADR_30dBm     = 0,
00326     MCMD_LADR_28dBm     = 1,
00327     MCMD_LADR_26dBm     = 2,
00328     MCMD_LADR_24dBm     = 3,
00329     MCMD_LADR_22dBm     = 4,
00330     MCMD_LADR_20dBm     = 5,
00331     MCMD_LADR_18dBm     = 6,
00332     MCMD_LADR_16dBm     = 7,
00333     MCMD_LADR_14dBm     = 8,
00334     MCMD_LADR_12dBm     = 9,
00335     MCMD_LADR_10dBm     = 10
00336 #endif
00337 };
00338 
00339 // Device address
00340 typedef u4_t devaddr_t;
00341 
00342 // RX quality (device)
00343 enum { RSSI_OFF=64, SNR_SCALEUP=4 };
00344 
00345 inline sf_t  getSf   (rps_t params)            { return   (sf_t)(params &  0x7); }
00346 inline rps_t setSf   (rps_t params, sf_t sf)   { return (rps_t)((params & ~0x7) | sf); }
00347 inline bw_t  getBw   (rps_t params)            { return  (bw_t)((params >> 3) & 0x3); }
00348 inline rps_t setBw   (rps_t params, bw_t cr)   { return (rps_t)((params & ~0x18) | (cr<<3)); }
00349 inline cr_t  getCr   (rps_t params)            { return  (cr_t)((params >> 5) & 0x3); }
00350 inline rps_t setCr   (rps_t params, cr_t cr)   { return (rps_t)((params & ~0x60) | (cr<<5)); }
00351 inline int   getNocrc(rps_t params)            { return        ((params >> 7) & 0x1); }
00352 inline rps_t setNocrc(rps_t params, int nocrc) { return (rps_t)((params & ~0x80) | (nocrc<<7)); }
00353 inline int   getIh   (rps_t params)            { return        ((params >> 8) & 0xFF); }
00354 inline rps_t setIh   (rps_t params, int ih)    { return (rps_t)((params & ~0xFF00) | (ih<<8)); }
00355 inline rps_t makeRps (sf_t sf, bw_t bw, cr_t cr, int ih, int nocrc) {
00356     return sf | (bw<<3) | (cr<<5) | (nocrc?(1<<7):0) | ((ih&0xFF)<<8);
00357 }
00358 #define MAKERPS(sf,bw,cr,ih,nocrc) ((rps_t)((sf) | ((bw)<<3) | ((cr)<<5) | ((nocrc)?(1<<7):0) | ((ih&0xFF)<<8)))
00359 // Two frames with params r1/r2 would interfere on air: same SFx + BWx 
00360 inline int sameSfBw(rps_t r1, rps_t r2) { return ((r1^r2)&0x1F) == 0; }
00361 
00362 extern const u1_t _DR2RPS_CRC[];
00363 inline rps_t updr2rps (dr_t dr) { return (rps_t)_DR2RPS_CRC[dr+1]; }
00364 inline rps_t dndr2rps (dr_t dr) { return setNocrc(updr2rps(dr),1); }
00365 inline int isFasterDR (dr_t dr1, dr_t dr2) { return dr1 > dr2; }
00366 inline int isSlowerDR (dr_t dr1, dr_t dr2) { return dr1 < dr2; }
00367 inline dr_t  incDR    (dr_t dr) { return _DR2RPS_CRC[dr+2]==ILLEGAL_RPS ? dr : (dr_t)(dr+1); } // increase data rate
00368 inline dr_t  decDR    (dr_t dr) { return _DR2RPS_CRC[dr  ]==ILLEGAL_RPS ? dr : (dr_t)(dr-1); } // decrease data rate
00369 inline dr_t  assertDR (dr_t dr) { return _DR2RPS_CRC[dr+1]==ILLEGAL_RPS ? DR_DFLTMIN : dr; }   // force into a valid DR
00370 inline bit_t validDR  (dr_t dr) { return _DR2RPS_CRC[dr+1]!=ILLEGAL_RPS; } // in range
00371 inline dr_t  lowerDR  (dr_t dr, u1_t n) { while(n--){dr=decDR(dr);} return dr; } // decrease data rate by n steps
00372 
00373 //
00374 // BEG: Keep in sync with lorabase.hpp
00375 // ================================================================================
00376 
00377 
00378 // Convert between dBm values and power codes (MCMD_LADR_XdBm)
00379 s1_t pow2dBm (u1_t mcmd_ladr_p1);
00380 // Calculate airtime
00381 ostime_t calcAirTime (rps_t rps, u1_t plen);
00382 // Sensitivity at given SF/BW
00383 int getSensitivity (rps_t rps);
00384 
00385 
00386 #endif // _lorabase_h_