/* * 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) // 2..0: Spreading factor // 4..3: bandwidth: 0 == 125kHz, 1 == 250 kHz, 2 == 500 kHz. 3 == reserved. // 6..5: coding rate: 0 == 4/5, 1 == 4/6, 2 == 4/7, 3 == 4/8 // 7: nocrc: 0 == with crc, 1 == without crc // 15..8: Implicit header control: 0 ==> none, 1..0xFF ==> length in bytes. 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 = LMIC_ENABLE_long_messages ? 255 : 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_DlChannelReq = 0x0A, // u1: channel, u3: frequency MCMD_DeviceTimeAns = 0x0D, // u4: seconds since epoch, u1: fractional second // Class B MCMD_PingSlotInfoAns = 0x10, // - MCMD_PingSlotChannelReq = 0x11, // u3: freq, u1:dr [7-4]:RFU [3:0]:datarate MCMD_BeaconTimingAns = 0x12, // u2: delay(in TUNIT millis), u1:channel (DEPRECATED) MCMD_BeaconFreqReq = 0x13, // u3: freq }; enum { MCMD_BeaconTimingAns_TUNIT = 30 // time unit of delay value in millis }; enum { MCMD_LinkADRAns_RFU = 0xF8, // RFU bits MCMD_LinkADRAns_PowerACK = 0x04, // 0=not supported power level MCMD_LinkADRAns_DataRateACK = 0x02, // 0=unknown data rate MCMD_LinkADRAns_ChannelACK = 0x01, // 0=unknown channel enabled }; enum { MCMD_RXParamSetupAns_RFU = 0xF8, // RFU bits MCMD_RXParamSetupAns_RX1DrOffsetAck = 0x04, // 0=dr2 not allowed MCMD_RXParamSetupAns_RX2DataRateACK = 0x02, // 0=unknown data rate MCMD_RXParamSetupAns_ChannelACK = 0x01, // 0=unknown channel enabled }; enum { MCMD_NewChannelAns_RFU = 0xFC, // RFU bits MCMD_NewChannelAns_DataRateACK = 0x02, // 0=unknown data rate MCMD_NewChannelAns_ChannelACK = 0x01, // 0=rejected channel frequency }; enum { MCMD_RXTimingSetupReq_RFU = 0xF0, // RFU bits MCMD_RXTimingSetupReq_Delay = 0x0F, // delay in secs, 1..15; 0 is mapped to 1. }; enum { MCMD_DlChannelAns_RFU = 0xFC, // RFU bits MCMD_DlChannelAns_FreqACK = 0x02, // 0 = uplink frequency not defined for this channel MCMD_DlChannelAns_ChannelACK = 0x01, // 0 = rejected channel freq }; enum { MCMD_PingSlotFreqAns_RFU = 0xFC, MCMD_PingSlotFreqAns_DataRateACK = 0x02, MCMD_PingSlotFreqAns_ChannelACK = 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_LinkADRReq payload enum { MCMD_LinkADRReq_Redundancy_RFU = 0x80, MCMD_LinkADRReq_Redundancy_ChMaskCntl_MASK= 0x70, MCMD_LinkADRReq_Redundancy_NbTrans_MASK = 0x0F, MCMD_LinkADRReq_ChMaskCntl_EULIKE_DIRECT = 0x00, // direct masking for EU MCMD_LinkADRReq_ChMaskCntl_EULIKE_ALL_ON = 0x60, // EU: enable everything. MCMD_LinkADRReq_ChMaskCntl_USLIKE_500K = 0x40, // mask is for the 8 us-like 500 kHz channels MCMD_LinkADRReq_ChMaskCntl_USLIKE_SPECIAL = 0x50, // first special for us-like MCMD_LinkADRReq_ChMaskCntl_USLIKE_BANK = 0x50, // special: bits are banks. MCMD_LinkADRReq_ChMaskCntl_USLIKE_125ON = 0x60, // special channel page enable, bits applied to 64..71 MCMD_LinkADRReq_ChMaskCntl_USLIKE_125OFF = 0x70, // special channel page: disble 125K, bits apply to 64..71 MCMD_LinkADRReq_ChMaskCntl_CN470_ALL_ON = 0x60, // turn all on for China. }; // Bit fields byte#0 of MCMD_LinkADRReq payload enum { MCMD_LinkADRReq_DR_MASK = 0xF0, MCMD_LinkADRReq_POW_MASK = 0x0F, MCMD_LinkADRReq_DR_SHIFT = 4, MCMD_LinkADRReq_POW_SHIFT = 0, }; // 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_