From 3b8de783469715e90d13fbfb78b2362af59b5717 Mon Sep 17 00:00:00 2001 From: xflynx25 <59663716+xflynx25@users.noreply.github.com> Date: Thu, 10 Apr 2025 11:46:28 +0600 Subject: [PATCH] EU433 Support --- README.md | 5 +- project_config/lmic_project_config.h | 1 + src/lmic/lmic_bandplan.h | 2 + src/lmic/lmic_bandplan_eu433.h | 92 +++++++ src/lmic/lmic_config_preconditions.h | 2 +- src/lmic/lmic_eu433.c | 379 +++++++++++++++++++++++++++ src/lmic/lorabase.h | 46 ++++ src/lmic/lorabase_eu433.h | 103 ++++++++ 8 files changed, 627 insertions(+), 3 deletions(-) create mode 100644 src/lmic/lmic_bandplan_eu433.h create mode 100644 src/lmic/lmic_eu433.c create mode 100644 src/lmic/lorabase_eu433.h diff --git a/README.md b/README.md index ec1f0519..51cb08b8 100644 --- a/README.md +++ b/README.md @@ -36,7 +36,7 @@ - [Selecting V1.0.2](#selecting-v102) - [Selecting V1.0.3](#selecting-v103) - [Selecting the LoRaWAN Region Configuration](#selecting-the-lorawan-region-configuration) - - [eu868, as923, in866, kr920](#eu868-as923-in866-kr920) + - [eu868, as923, in866, kr920, eu433](#eu868-as923-in866-kr920-eu433) - [us915, au915](#us915-au915) - [Selecting the target radio transceiver](#selecting-the-target-radio-transceiver) - [Controlling use of interrupts](#controlling-use-of-interrupts) @@ -257,6 +257,7 @@ The library supports the following regions: ------------|-----------------|:----------------:|:-------------------:|-------- `-D CFG_eu868` | `LMIC_REGION_eu868` | 1 | 2.2 | EU 863-870 MHz ISM `-D CFG_us915` | `LMIC_REGION_us915` | 2 | 2.3 | US 902-928 MHz ISM +`-D CFG_eu433` | `LMIC_REGION_eu433` | 4 | 2.5 | EU 433-434 MHz ISM `-D CFG_au915` | `LMIC_REGION_au915` | 5 | 2.6 | Australia 915-928 MHz ISM `-D CFG_as923` | `LMIC_REGION_as923` | 7 | 2.8 | Asia 923 MHz ISM `-D CFG_as923jp` | `LMIC_REGION_as923` and `LMIC_COUNTRY_CODE_JP` | 7 | 2.8 | Asia 923 MHz ISM with Japan listen-before-talk (LBT) rules @@ -269,7 +270,7 @@ MCCI BSPs add menu entries to the Arduino IDE so you can select the target regio The library changes configuration pretty substantially according to the region selected, and this affects the symbols in-scope in your sketches and `.cpp` files. Some of the differences are listed below. This list is not comprehensive, and is subject to change in future major releases. -#### eu868, as923, in866, kr920 +#### eu868, as923, in866, kr920, eu433 If the library is configured for EU868, AS923, or IN866 operation, we make the following changes: diff --git a/project_config/lmic_project_config.h b/project_config/lmic_project_config.h index 620afbf5..2febc1a4 100644 --- a/project_config/lmic_project_config.h +++ b/project_config/lmic_project_config.h @@ -6,6 +6,7 @@ // #define LMIC_COUNTRY_CODE LMIC_COUNTRY_CODE_JP /* for as923-JP; also define CFG_as923 */ //#define CFG_kr920 1 //#define CFG_in866 1 +//#define CFG_eu433 1 #define CFG_sx1276_radio 1 //#define CFG_sx1261_radio 1 //#define CFG_sx1262_radio 1 diff --git a/src/lmic/lmic_bandplan.h b/src/lmic/lmic_bandplan.h index 3921819f..d69807dd 100644 --- a/src/lmic/lmic_bandplan.h +++ b/src/lmic/lmic_bandplan.h @@ -45,6 +45,8 @@ # include "lmic_bandplan_kr920.h" #elif defined(CFG_in866) # include "lmic_bandplan_in866.h" +#elif defined(CFG_eu433) +# include "lmic_bandplan_eu433.h" #else # error "CFG_... not properly set for bandplan" #endif diff --git a/src/lmic/lmic_bandplan_eu433.h b/src/lmic/lmic_bandplan_eu433.h new file mode 100644 index 00000000..6855fa09 --- /dev/null +++ b/src/lmic/lmic_bandplan_eu433.h @@ -0,0 +1,92 @@ +/* +* Copyright (c) 2014-2016 IBM Corporation. +* Copyright (c) 2017, 2019-2021 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 _lmic_eu433_h_ +# define _lmic_eu433_h_ + +#ifndef _lmic_eu_like_h_ +# include "lmic_eu_like.h" +#endif + +// return maximum frame length (including PHY header) for this data rate (eu433); 0 --> not valid dr. +uint8_t LMICeu433_maxFrameLen(uint8_t dr); +// return maximum frame length (including PHY header) for this data rate; 0 --> not valid dr. +#define LMICbandplan_maxFrameLen(dr) LMICeu433_maxFrameLen(dr) + +int8_t LMICeu433_pow2dBm(uint8_t mcmd_ladr_p1); +#define pow2dBm(mcmd_ladr_p1) LMICeu433_pow2dBm(mcmd_ladr_p1) + +// Times for half symbol per DR +// Per DR table to minimize rounding errors +ostime_t LMICeu433_dr2hsym(uint8_t dr); +#define dr2hsym(dr) LMICeu433_dr2hsym(dr) + +static inline int +LMICeu433_isValidBeacon1(const uint8_t *d) { + return d[OFF_BCN_CRC1] != (u1_t)os_crc16(d, OFF_BCN_CRC1); +} + +#undef LMICbandplan_isValidBeacon1 +#define LMICbandplan_isValidBeacon1(pFrame) LMICeu433_isValidBeacon1(pFrame) + +// override default for LMICbandplan_isFSK() +#undef LMICbandplan_isFSK +#define LMICbandplan_isFSK() (/* RX datarate */LMIC.dndr == EU433_DR_FSK) + +#define LMICbandplan_getInitialDrJoin() (EU433_DR_SF7) + +void LMICeu433_setBcnRxParams(void); +#define LMICbandplan_setBcnRxParams() LMICeu433_setBcnRxParams() + +u4_t LMICeu433_convFreq(xref2cu1_t ptr); +#define LMICbandplan_convFreq(ptr) LMICeu433_convFreq(ptr) + +void LMICeu433_initJoinLoop(void); +#define LMICbandplan_initJoinLoop() LMICeu433_initJoinLoop() + +ostime_t LMICeu433_nextTx(ostime_t now); +#define LMICbandplan_nextTx(now) LMICeu433_nextTx(now) + +ostime_t LMICeu433_nextJoinState(void); +#define LMICbandplan_nextJoinState() LMICeu433_nextJoinState() + +void LMICeu433_initDefaultChannels(bit_t join); +#define LMICbandplan_initDefaultChannels(join) LMICeu433_initDefaultChannels(join) + +#undef LMICbandplan_nextJoinTime +ostime_t LMICeu433_nextJoinTime(ostime_t now); +#define LMICbandplan_nextJoinTime(now) LMICeu433_nextJoinTime(now) + +void LMICeu433_setRx1Params(void); +#define LMICbandplan_setRx1Params() LMICeu433_setRx1Params() + +#undef LMICbandplan_validDR +bit_t LMICeu433_validDR(dr_t dr); +#define LMICbandplan_validDR(dr) LMICeu433_validDR(dr) + +#endif // _lmic_eu433_h_ diff --git a/src/lmic/lmic_config_preconditions.h b/src/lmic/lmic_config_preconditions.h index 3f6ac8b0..b73c3e3f 100644 --- a/src/lmic/lmic_config_preconditions.h +++ b/src/lmic/lmic_config_preconditions.h @@ -109,7 +109,7 @@ Revision history: (1 << LMIC_REGION_eu868) | \ (1 << LMIC_REGION_us915) | \ /* (1 << LMIC_REGION_cn783) | */ \ - /* (1 << LMIC_REGION_eu433) | */ \ + (1 << LMIC_REGION_eu433) | \ (1 << LMIC_REGION_au915) | \ /* (1 << LMIC_REGION_cn490) | */ \ (1 << LMIC_REGION_as923) | \ diff --git a/src/lmic/lmic_eu433.c b/src/lmic/lmic_eu433.c new file mode 100644 index 00000000..e9084337 --- /dev/null +++ b/src/lmic/lmic_eu433.c @@ -0,0 +1,379 @@ +/* +* Copyright (c) 2014-2016 IBM Corporation. +* Copyright (c) 2017, 2019-2023 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. +*/ + +#define LMIC_DR_LEGACY 0 + +#include "lmic_bandplan.h" + +#if defined(CFG_eu433) +// ================================================================================ +// +// BEG: EU433 related stuff +// + +CONST_TABLE(u1_t, _DR2RPS_CRC)[] = { + ILLEGAL_RPS, + (u1_t)MAKERPS(SF12, BW125, CR_4_5, 0, 0), + (u1_t)MAKERPS(SF11, BW125, CR_4_5, 0, 0), + (u1_t)MAKERPS(SF10, BW125, CR_4_5, 0, 0), + (u1_t)MAKERPS(SF9, BW125, CR_4_5, 0, 0), + (u1_t)MAKERPS(SF8, BW125, CR_4_5, 0, 0), + (u1_t)MAKERPS(SF7, BW125, CR_4_5, 0, 0), + (u1_t)MAKERPS(SF7, BW250, CR_4_5, 0, 0), + (u1_t)MAKERPS(FSK, BW125, CR_4_5, 0, 0), + ILLEGAL_RPS +}; + +bit_t +LMICeu433_validDR(dr_t dr) { + // use subtract here to avoid overflow + if (dr >= LENOF_TABLE(_DR2RPS_CRC) - 2) + return 0; + return TABLE_GET_U1(_DR2RPS_CRC, dr+1)!=ILLEGAL_RPS; +} + +static CONST_TABLE(u1_t, maxFrameLens)[] = { + 59+5, 59+5, 59+5, 123+5, 230+5, 230+5, 230+5, 230+5 // Based on EU433 specs +}; + +uint8_t LMICeu433_maxFrameLen(uint8_t dr) { + if (dr < LENOF_TABLE(maxFrameLens)) + return TABLE_GET_U1(maxFrameLens, dr); + else + return 0; +} + +static CONST_TABLE(s1_t, TXPOWLEVELS)[] = { + 12, 10, 8, 6, 4, 2, 0, -2 // Based on EU433 max EIRP of 12.15 dBm +}; + +int8_t LMICeu433_pow2dBm(uint8_t mcmd_ladr_p1) { + uint8_t const pindex = (mcmd_ladr_p1&MCMD_LinkADRReq_POW_MASK)>>MCMD_LinkADRReq_POW_SHIFT; + if (pindex < LENOF_TABLE(TXPOWLEVELS)) { + return TABLE_GET_S1(TXPOWLEVELS, pindex); + } else { + return -128; + } +} + +// only used in this module, but used by variant macro dr2hsym(). +static CONST_TABLE(ostime_t, DR2HSYM_osticks)[] = { + us2osticksRound(128 << 7), // DR_SF12 + us2osticksRound(128 << 6), // DR_SF11 + us2osticksRound(128 << 5), // DR_SF10 + us2osticksRound(128 << 4), // DR_SF9 + us2osticksRound(128 << 3), // DR_SF8 + us2osticksRound(128 << 2), // DR_SF7 + us2osticksRound(128 << 1), // DR_SF7B + us2osticksRound(80) // FSK -- time for 1/2 byte (unused by LMIC) +}; + +ostime_t LMICeu433_dr2hsym(uint8_t dr) { + return TABLE_GET_OSTIME(DR2HSYM_osticks, dr); +} + + +enum { NUM_DEFAULT_CHANNELS = 3 }; +static CONST_TABLE(u4_t, iniChannelFreq)[6] = { + // Join frequencies and duty cycle limit (0.1%) + EU433_F1 | BAND_MILLI, EU433_F2 | BAND_MILLI, EU433_F3 | BAND_MILLI, + // Default operational frequencies and duty cycle limit (1%) + EU433_F1 | BAND_CENTI, EU433_F2 | BAND_CENTI, EU433_F3 | BAND_CENTI, +}; + +void LMICeu433_initDefaultChannels(bit_t join) { + os_clearMem(&LMIC.channelFreq, sizeof(LMIC.channelFreq)); +#if !defined(DISABLE_MCMD_DlChannelReq) + os_clearMem(&LMIC.channelDlFreq, sizeof(LMIC.channelDlFreq)); +#endif // !DISABLE_MCMD_DlChannelReq + os_clearMem(&LMIC.channelDrMap, sizeof(LMIC.channelDrMap)); + os_clearMem(&LMIC.bands, sizeof(LMIC.bands)); + + LMIC.channelMap = (1 << NUM_DEFAULT_CHANNELS) - 1; + u1_t su = join ? 0 : NUM_DEFAULT_CHANNELS; + for (u1_t fu = 0; fu BAND_AUX) return 0; + //band_t* b = &LMIC.bands[bandidx]; + xref2band_t b = &LMIC.bands[bandidx]; + b->txpow = txpow; + b->txcap = txcap; + b->avail = os_getTime(); + b->lastchnl = os_getRndU1() % MAX_CHANNELS; + return 1; +} + +// this table is from highest to lowest +static CONST_TABLE(u4_t, bandAssignments)[] = { + 435375000 /* .. and above */ | BAND_MILLI, + 434790000 /* .. 434790000 */ | BAND_CENTI, + 433050000 /* .. 434790000 */ | BAND_MILLI, +}; + +/// +/// \brief query number of default channels. +/// +u1_t LMIC_queryNumDefaultChannels() { + return NUM_DEFAULT_CHANNELS; +} + +/// +/// \brief LMIC_setupChannel for EU 433 +/// +/// \note according to LoRaWAN 1.0.3 section 5.6, "the acceptable range +/// for **ChIndex** is N to 16", where N is our \c NUM_DEFAULT_CHANNELS. +/// This routine is used internally for MAC commands, so we enforce +/// this for the extenal API as well. +/// +bit_t LMIC_setupChannel(u1_t chidx, u4_t freq, u2_t drmap, s1_t band) { + // zero the band bits in freq, just in case. + freq &= ~3; + + if (chidx < NUM_DEFAULT_CHANNELS) { + // can't do anything to a default channel. + return 0; + } + bit_t fEnable = (freq != 0); + if (chidx >= MAX_CHANNELS) + return 0; + + if (band == -1) { + for (u1_t i = 0; i < LENOF_TABLE(bandAssignments); ++i) { + const u4_t thisFreqBand = TABLE_GET_U4(bandAssignments, i); + const u4_t thisFreq = thisFreqBand & ~3; + if (freq >= thisFreq) { + band = ((u1_t)thisFreqBand & 3); + break; + } + } + + // if we didn't identify a frequency, it's millis. + if (band == -1) { + band = BAND_MILLI; + } + } + + if ((u1_t)band > BAND_AUX) + return 0; + + freq |= band; + + LMIC.channelFreq[chidx] = freq; + LMIC.channelDrMap[chidx] = drmap == 0 ? DR_RANGE_MAP(EU433_DR_SF12, EU433_DR_SF7) : drmap; + if (fEnable) + LMIC.channelMap |= 1 << chidx; // enabled right away + else + LMIC.channelMap &= ~(1 << chidx); + return 1; +} + + + +u4_t LMICeu433_convFreq(xref2cu1_t ptr) { + u4_t freq = (os_rlsbf4(ptr - 1) >> 8) * 100; + if (freq < EU433_FREQ_MIN || freq > EU433_FREQ_MAX) + freq = 0; + return freq; +} + +ostime_t LMICeu433_nextJoinTime(ostime_t time) { + // is the avail time in the future? + if ((s4_t) (time - LMIC.bands[BAND_MILLI].avail) < 0) + // yes: then wait until then. + time = LMIC.bands[BAND_MILLI].avail; + + return time; +} + +/// +/// \brief change the TX channel given the desired tx time. +/// +/// \param [in] now is the time at which we want to transmit. In fact, it's always +/// the current time. +/// +/// \returns the actual time at which we can transmit. \c LMIC.txChnl is set to the +/// selected channel. +/// +/// \details +/// We scan all the channels, creating a mask of all enabled channels that are +/// feasible at the earliest possible time. We then randomly choose one from +/// that, updating the shuffle mask. +/// +/// One sublety is that we have to cope with an artifact of the shuffler. +/// It will zero out bits for candidates that are real candidates, but +/// not in the time window, and not consider them as early as it should. +/// So we keep a mask of all feasible channels, and make sure that they +/// remain set in the shuffle mask if appropriate. +/// +ostime_t LMICeu433_nextTx(ostime_t now) { + ostime_t mintime = now + /*8h*/sec2osticks(28800); + u2_t availMap; + u2_t feasibleMap; + u1_t bandMap; + + // set mintime to the earliest time of all enabled channels + // (can't just look at bands); and for a given channel, we + // can't tell if we're ready till we've checked all possible + // avail times. + bandMap = 0; + for (u1_t chnl = 0; chnl < MAX_CHANNELS; ++chnl) { + u2_t chnlBit = 1 << chnl; + + // none at any higher numbers? + if (LMIC.channelMap < chnlBit) + break; + + // not enabled? + if ((LMIC.channelMap & chnlBit) == 0) + continue; + + // not feasible? + if ((LMIC.channelDrMap[chnl] & (1 << (LMIC.datarate & 0xF))) == 0) + continue; + + u1_t const band = LMIC.channelFreq[chnl] & 0x3; + u1_t const thisBandBit = 1 << band; + // already considered? + if ((bandMap & thisBandBit) != 0) + continue; + + // consider this band. + bandMap |= thisBandBit; + + // enabled, not considered, feasible: adjust the min time. + if ((s4_t)(mintime - LMIC.bands[band].avail) > 0) + mintime = LMIC.bands[band].avail; + } + + // make a mask of candidates available for use + availMap = 0; + feasibleMap = 0; + for (u1_t chnl = 0; chnl < MAX_CHANNELS; ++chnl) { + u2_t chnlBit = 1 << chnl; + + // none at any higher numbers? + if (LMIC.channelMap < chnlBit) + break; + + // not enabled? + if ((LMIC.channelMap & chnlBit) == 0) + continue; + + // not feasible? + if ((LMIC.channelDrMap[chnl] & (1 << (LMIC.datarate & 0xF))) == 0) + continue; + + // This channel is feasible. But might not be available. + feasibleMap |= chnlBit; + + // not available yet? + u1_t const band = LMIC.channelFreq[chnl] & 0x3; + if ((s4_t)(LMIC.bands[band].avail - mintime) > 0) + continue; + + // ok: this is a candidate. + availMap |= chnlBit; + } + + // find the next available chennel. + u2_t saveShuffleMap = LMIC.channelShuffleMap; + int candidateCh = LMIC_findNextChannel(&LMIC.channelShuffleMap, &availMap, 1, LMIC.txChnl == 0xFF ? -1 : LMIC.txChnl); + + // restore bits in the shuffleMap that were on, but might have reset + // if availMap was used to refresh shuffleMap. These are channels that + // are feasble but not yet candidates due to band saturation + LMIC.channelShuffleMap |= saveShuffleMap & feasibleMap & ~availMap; + + if (candidateCh >= 0) { + // update the channel; otherwise we'll just use the + // most recent one. + LMIC.txChnl = candidateCh; + } + return mintime; +} + +#if !defined(DISABLE_BEACONS) +void LMICeu433_setBcnRxParams(void) { + LMIC.dataLen = 0; + LMIC.freq = FREQ_BCN; + // LMIC.freq = LMIC.channelFreq[LMIC.bcnChnl] & ~(u4_t)3; // 868 implementation + LMIC.rps = setIh(setNocrc(dndr2rps((dr_t)DR_BCN), 1), LEN_BCN); +} +#endif // !DISABLE_BEACONS + +#if !defined(DISABLE_JOIN) +ostime_t LMICeu433_nextJoinState(void) { + return LMICeulike_nextJoinState(NUM_DEFAULT_CHANNELS); +} +#endif // !DISABLE_JOIN + +void LMICeu433_setRx1Params(void) { + u1_t const txdr = LMIC.dndr; + s1_t drOffset; + s1_t candidateDr; + + LMICeulike_setRx1Freq(); + + if (LMIC.rx1DrOffset <= 5) + drOffset = (s1_t) LMIC.rx1DrOffset; + else + // make a reasonable assumption for unspecified value. + drOffset = 5; + + candidateDr = (s1_t) txdr - drOffset; + if (candidateDr < LORAWAN_DR0) + candidateDr = LORAWAN_DR0; + else if (candidateDr > LORAWAN_DR7) + candidateDr = LORAWAN_DR7; + + LMIC.dndr = (u1_t) candidateDr; + LMIC.rps = dndr2rps(LMIC.dndr); +} + +void +LMICeu433_initJoinLoop(void) { + LMICeulike_initJoinLoop(NUM_DEFAULT_CHANNELS, /* adr dBm */ EU433_TX_EIRP_MAX_DBM); +} + +// +// +// END: EU433 related stuff +// +// ================================================================================ + +#endif // defined(CFG_eu433) diff --git a/src/lmic/lorabase.h b/src/lmic/lorabase.h index 2e83540e..508d9511 100644 --- a/src/lmic/lorabase.h +++ b/src/lmic/lorabase.h @@ -419,6 +419,52 @@ enum _dr_configured_t { }; # endif // LMIC_DR_LEGACY +#elif defined(CFG_eu433) // ============================================== + +#include "lorabase_eu433.h" + +// per 2.5.3: not implemented +#define LMIC_ENABLE_TxParamSetupReq 0 + +enum { DR_DFLTMIN = EU433_DR_SF7 }; +enum { DR_PAGE = DR_PAGE_EU433 }; // debugging parameter + +enum { FREQ_PING = EU433_F6 }; // default ping freq +enum { DR_PING = EU433_DR_SF9 }; // default ping DR +enum { FREQ_DNW2 = EU433_F6 }; +enum { DR_DNW2 = EU433_DR_SF12 }; +enum { CHNL_BCN = 5 }; +enum { FREQ_BCN = EU433_F6 }; +enum { DR_BCN = EU433_DR_SF9 }; +enum { AIRTIME_BCN = 144384 }; // micros +enum { LMIC_REGION_EIRP = EU433_LMIC_REGION_EIRP }; + +enum { + // Beacon frame format EU SF9 + OFF_BCN_NETID = 0, + OFF_BCN_TIME = 3, + OFF_BCN_CRC1 = 7, + OFF_BCN_INFO = 8, + OFF_BCN_LAT = 9, + OFF_BCN_LON = 12, + OFF_BCN_CRC2 = 15, + LEN_BCN = 17 +}; + +# if LMIC_DR_LEGACY +enum _dr_configured_t { + DR_SF12 = EU433_DR_SF12, + DR_SF11 = EU433_DR_SF11, + DR_SF10 = EU433_DR_SF10, + DR_SF9 = EU433_DR_SF9, + DR_SF8 = EU433_DR_SF8, + DR_SF7 = EU433_DR_SF7, + DR_SF7B = EU433_DR_SF7B, + DR_FSK = EU433_DR_FSK, + DR_NONE = EU433_DR_NONE +}; +# endif // LMIC_DR_LEGACY + #else # error Unsupported configuration setting #endif // =================================================== diff --git a/src/lmic/lorabase_eu433.h b/src/lmic/lorabase_eu433.h new file mode 100644 index 00000000..e4ab7a97 --- /dev/null +++ b/src/lmic/lorabase_eu433.h @@ -0,0 +1,103 @@ +/* +* Copyright (c) 2014-2016 IBM Corporation. +* All rights reserved. +* +* Copyright (c) 2017, 2019 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_eu433_h_ +#define _lorabase_eu433_h_ + +#ifndef _LMIC_CONFIG_PRECONDITIONS_H_ +# include "lmic_config_preconditions.h" +#endif + +/****************************************************************************\ +| +| Basic definitions for EU433 (always in scope) +| +\****************************************************************************/ + + +// Data rates (LoRaWAN Regional Parameters v1.0.3) +enum _dr_eu433_t { + EU433_DR_SF12 = 0, + EU433_DR_SF11, + EU433_DR_SF10, + EU433_DR_SF9, + EU433_DR_SF8, + EU433_DR_SF7, + EU433_DR_SF7B, + EU433_DR_FSK, + EU433_DR_NONE, + + DR_PAGE_EU433 = 0x10 // moved w.r.t. eu868 +}; + + +// EU433 frequency bands (MHz) +// Constructed similarly to 868: +// 1-3 for default joins +// 4-6 for additional channels +// 6 coinciding with the beacon frequency +// J4-6 for supplemental J channels (which also get attached to CF list), assigned to biggest gap +// in reality, network server specifies these freqs +enum { + EU433_F1 = 433175000, // Default channel 1 + EU433_F2 = 433375000, // Default channel 2 + EU433_F3 = 433575000, // Default channel 3 + EU433_F4 = 433775000, + EU433_F5 = 433975000, + EU433_F6 = 434665000, // Beacon/RX2 default + EU433_J4 = 434175000, + EU433_J5 = 434375000, + EU433_J6 = 434575000, +}; +enum { + EU433_FREQ_MIN = 433050000, + EU433_FREQ_MAX = 434790000 +}; +enum { + EU433_TX_EIRP_MAX_DBM = 1215 // 12.15 dBm (Maximum) EIRP. So subtract 3 dBm for a 3 dBi antenna. This is just documentation +}; + + +enum { EU433_LMIC_REGION_EIRP = 1 }; // region uses EIRP + + +// Additional Definitions (unused) Compared to EU868 + +// Noting that we use 1% lorawan congestion-reduction 433 duty cycle, rather than 10% regulatory spec +#define EU433_CONSERVATIVE_DUTY_CYCLE_ENABLED 1 + +// Based on Table 30/31, payload length documentation +enum { + EU433_MAX_PAYLOAD_LEN_REPEATER = 230, + EU433_MAX_PAYLOAD_LEN_NO_REPEATER = 250, + EU433_MAX_PAYLOAD_LEN_JOIN = 59 // For join requests, according to lowest (D0) rate used in join +}; + +#endif /* _lorabase_eu433_h_ */