/* * Copyright (c) 2014-2016 IBM Corporation. * Copyritght (c) 2017 MCCI Corporation. * All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions are met: * * Redistributions of source code must retain the above copyright * notice, this list of conditions and the following disclaimer. * * Redistributions in binary form must reproduce the above copyright * notice, this list of conditions and the following disclaimer in the * documentation and/or other materials provided with the distribution. * * Neither the name of the nor the * names of its contributors may be used to endorse or promote products * derived from this software without specific prior written permission. * * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE * DISCLAIMED. IN NO EVENT SHALL BE LIABLE FOR ANY * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. */ #ifndef _lorabase_h_ #define _lorabase_h_ #ifdef __cplusplus extern "C"{ #endif // ================================================================================ // BEG: Keep in sync with lorabase.hpp // enum _cr_t { CR_4_5=0, CR_4_6, CR_4_7, CR_4_8 }; enum _sf_t { FSK=0, SF7, SF8, SF9, SF10, SF11, SF12, SFrfu }; enum _bw_t { BW125=0, BW250, BW500, BWrfu }; typedef u1_t cr_t; typedef u1_t sf_t; typedef u1_t bw_t; typedef u1_t dr_t; // Radio parameter set (encodes SF/BW/CR/IH/NOCRC) typedef u2_t rps_t; TYPEDEF_xref2rps_t; enum { ILLEGAL_RPS = 0xFF }; // Global maximum frame length enum { STD_PREAMBLE_LEN = 8 }; enum { MAX_LEN_FRAME = 64 }; enum { LEN_DEVNONCE = 2 }; enum { LEN_ARTNONCE = 3 }; enum { LEN_NETID = 3 }; enum { DELAY_JACC1 = 5 }; // in secs enum { DELAY_DNW1 = 1 }; // in secs down window #1 enum { DELAY_EXTDNW2 = 1 }; // in secs enum { DELAY_JACC2 = DELAY_JACC1+(int)DELAY_EXTDNW2 }; // in secs enum { DELAY_DNW2 = DELAY_DNW1 +(int)DELAY_EXTDNW2 }; // in secs down window #1 enum { BCN_INTV_exp = 7 }; enum { BCN_INTV_sec = 1< 1) MCMD_TxParamSetupReq = 0x09, // : u1: [7-6]:RFU [5:4]: dl dwell/ul dwell [3:0] max EIRP MCMD_DIChannelReq = 0x0A, // : u1: channel, u3: frequency MCMD_DeviceTimeAns = 0x0D, // Class B MCMD_PING_SET = 0x11, // set ping freq : u3: freq MCMD_BCNI_ANS = 0x12, // next beacon start : u2: delay(in TUNIT millis), u1:channel }; enum { MCMD_BCNI_TUNIT = 30 // time unit of delay value in millis }; enum { MCMD_LADR_ANS_RFU = 0xF8, // RFU bits MCMD_LADR_ANS_POWACK = 0x04, // 0=not supported power level MCMD_LADR_ANS_DRACK = 0x02, // 0=unknown data rate MCMD_LADR_ANS_CHACK = 0x01, // 0=unknown channel enabled }; enum { MCMD_DN2P_ANS_RFU = 0xF8, // RFU bits MCMD_DN2P_ANS_RX1DrOffsetAck = 0x04, // 0=dr2 not allowed MCMD_DN2P_ANS_DRACK = 0x02, // 0=unknown data rate MCMD_DN2P_ANS_CHACK = 0x01, // 0=unknown channel enabled }; enum { MCMD_SNCH_ANS_RFU = 0xFC, // RFU bits MCMD_SNCH_ANS_DRACK = 0x02, // 0=unknown data rate MCMD_SNCH_ANS_FQACK = 0x01, // 0=rejected channel frequency }; enum { MCMD_PING_ANS_RFU = 0xFE, MCMD_PING_ANS_FQACK = 0x01 }; enum { MCMD_DEVS_EXT_POWER = 0x00, // external power supply MCMD_DEVS_BATT_MIN = 0x01, // min battery value MCMD_DEVS_BATT_MAX = 0xFE, // max battery value MCMD_DEVS_BATT_NOINFO = 0xFF, // unknown battery level }; // Bit fields byte#3 of MCMD_LADR_REQ payload enum { MCMD_LADR_CHP_USLIKE_SPECIAL = 0x50, // first special for us-like MCMD_LADR_CHP_BANK = 0x50, // special: bits are banks. MCMD_LADR_CHP_125ON = 0x60, // special channel page enable, bits applied to 64..71 MCMD_LADR_CHP_125OFF = 0x70, // special channel page: disble 125K, bits apply to 64..71 MCMD_LADR_N3RFU_MASK = 0x80, MCMD_LADR_CHPAGE_MASK = 0xF0, MCMD_LADR_REPEAT_MASK = 0x0F, MCMD_LADR_REPEAT_1 = 0x01, MCMD_LADR_CHPAGE_1 = 0x10 }; // Bit fields byte#0 of MCMD_LADR_REQ payload enum { MCMD_LADR_DR_MASK = 0xF0, MCMD_LADR_POW_MASK = 0x0F, MCMD_LADR_DR_SHIFT = 4, MCMD_LADR_POW_SHIFT = 0, #if defined(CFG_eu868) // TODO(tmm@mcci.com): complete refactor. EU868_MCMD_LADR_SF12 = EU868_DR_SF12<<4, EU868_MCMD_LADR_SF11 = EU868_DR_SF11<<4, EU868_MCMD_LADR_SF10 = EU868_DR_SF10<<4, EU868_MCMD_LADR_SF9 = EU868_DR_SF9 <<4, EU868_MCMD_LADR_SF8 = EU868_DR_SF8 <<4, EU868_MCMD_LADR_SF7 = EU868_DR_SF7 <<4, EU868_MCMD_LADR_SF7B = EU868_DR_SF7B<<4, EU868_MCMD_LADR_FSK = EU868_DR_FSK <<4, EU868_MCMD_LADR_20dBm = 0, EU868_MCMD_LADR_14dBm = 1, EU868_MCMD_LADR_11dBm = 2, EU868_MCMD_LADR_8dBm = 3, EU868_MCMD_LADR_5dBm = 4, EU868_MCMD_LADR_2dBm = 5, #elif defined(CFG_us915) US915_MCMD_LADR_SF10 = US915_DR_SF10<<4, US915_MCMD_LADR_SF9 = US915_DR_SF9 <<4, US915_MCMD_LADR_SF8 = US915_DR_SF8 <<4, US915_MCMD_LADR_SF7 = US915_DR_SF7 <<4, US915_MCMD_LADR_SF8C = US915_DR_SF8C<<4, US915_MCMD_LADR_SF12CR = US915_DR_SF12CR<<4, US915_MCMD_LADR_SF11CR = US915_DR_SF11CR<<4, US915_MCMD_LADR_SF10CR = US915_DR_SF10CR<<4, US915_MCMD_LADR_SF9CR = US915_DR_SF9CR<<4, US915_MCMD_LADR_SF8CR = US915_DR_SF8CR<<4, US915_MCMD_LADR_SF7CR = US915_DR_SF7CR<<4, US915_MCMD_LADR_30dBm = 0, US915_MCMD_LADR_28dBm = 1, US915_MCMD_LADR_26dBm = 2, US915_MCMD_LADR_24dBm = 3, US915_MCMD_LADR_22dBm = 4, US915_MCMD_LADR_20dBm = 5, US915_MCMD_LADR_18dBm = 6, US915_MCMD_LADR_16dBm = 7, US915_MCMD_LADR_14dBm = 8, US915_MCMD_LADR_12dBm = 9, US915_MCMD_LADR_10dBm = 10 #endif }; // bit fields of the TxParam request enum { MCMD_TxParam_RxDWELL_SHIFT = 5, MCMD_TxParam_RxDWELL_MASK = 1 << MCMD_TxParam_RxDWELL_SHIFT, MCMD_TxParam_TxDWELL_SHIFT = 4, MCMD_TxParam_TxDWELL_MASK = 1 << MCMD_TxParam_TxDWELL_SHIFT, MCMD_TxParam_MaxEIRP_SHIFT = 0, MCMD_TxParam_MaxEIRP_MASK = 0xF << MCMD_TxParam_MaxEIRP_SHIFT, }; // Device address typedef u4_t devaddr_t; // RX quality (device) enum { RSSI_OFF=64, SNR_SCALEUP=4 }; static inline sf_t getSf (rps_t params) { return (sf_t)(params & 0x7); } static inline rps_t setSf (rps_t params, sf_t sf) { return (rps_t)((params & ~0x7) | sf); } static inline bw_t getBw (rps_t params) { return (bw_t)((params >> 3) & 0x3); } static inline rps_t setBw (rps_t params, bw_t cr) { return (rps_t)((params & ~0x18) | (cr<<3)); } static inline cr_t getCr (rps_t params) { return (cr_t)((params >> 5) & 0x3); } static inline rps_t setCr (rps_t params, cr_t cr) { return (rps_t)((params & ~0x60) | (cr<<5)); } static inline int getNocrc(rps_t params) { return ((params >> 7) & 0x1); } static inline rps_t setNocrc(rps_t params, int nocrc) { return (rps_t)((params & ~0x80) | (nocrc<<7)); } static inline int getIh (rps_t params) { return ((params >> 8) & 0xFF); } static inline rps_t setIh (rps_t params, int ih) { return (rps_t)((params & ~0xFF00) | (ih<<8)); } static inline rps_t makeRps (sf_t sf, bw_t bw, cr_t cr, int ih, int nocrc) { return sf | (bw<<3) | (cr<<5) | (nocrc?(1<<7):0) | ((ih&0xFF)<<8); } #define MAKERPS(sf,bw,cr,ih,nocrc) ((rps_t)((sf) | ((bw)<<3) | ((cr)<<5) | ((nocrc)?(1<<7):0) | ((ih&0xFF)<<8))) // Two frames with params r1/r2 would interfere on air: same SFx + BWx static inline int sameSfBw(rps_t r1, rps_t r2) { return ((r1^r2)&0x1F) == 0; } extern CONST_TABLE(u1_t, _DR2RPS_CRC)[]; static inline rps_t updr2rps (dr_t dr) { return (rps_t)TABLE_GET_U1(_DR2RPS_CRC, dr+1); } static inline rps_t dndr2rps (dr_t dr) { return setNocrc(updr2rps(dr),1); } static inline int isFasterDR (dr_t dr1, dr_t dr2) { return dr1 > dr2; } static inline int isSlowerDR (dr_t dr1, dr_t dr2) { return dr1 < dr2; } static inline dr_t incDR (dr_t dr) { return TABLE_GET_U1(_DR2RPS_CRC, dr+2)==ILLEGAL_RPS ? dr : (dr_t)(dr+1); } // increase data rate static inline dr_t decDR (dr_t dr) { return TABLE_GET_U1(_DR2RPS_CRC, dr )==ILLEGAL_RPS ? dr : (dr_t)(dr-1); } // decrease data rate static inline dr_t assertDR (dr_t dr) { return TABLE_GET_U1(_DR2RPS_CRC, dr+1)==ILLEGAL_RPS ? (dr_t)DR_DFLTMIN : dr; } // force into a valid DR static inline bit_t validDR (dr_t dr) { return TABLE_GET_U1(_DR2RPS_CRC, dr+1)!=ILLEGAL_RPS; } // in range static inline dr_t lowerDR (dr_t dr, u1_t n) { while(n--){dr=decDR(dr);} return dr; } // decrease data rate by n steps // // BEG: Keep in sync with lorabase.hpp // ================================================================================ // Calculate airtime ostime_t calcAirTime (rps_t rps, u1_t plen); // Sensitivity at given SF/BW int getSensitivity (rps_t rps); #ifdef __cplusplus } // extern "C" #endif #endif // _lorabase_h_