From 4938273b69a7baf0144f1a8179f151f70054fdb9 Mon Sep 17 00:00:00 2001 From: Shoichi Sakane Date: Tue, 15 May 2018 14:12:13 +0900 Subject: [PATCH 01/19] merged TMM-feature-as923jp into master. but, it hangups sometimes. --- src/hal/hal.cpp | 4 ++ src/hal/hal.h | 3 + src/lmic/config.h | 9 +++ src/lmic/hal.h | 5 ++ src/lmic/lmic.c | 8 ++- src/lmic/lmic.h | 5 ++ src/lmic/lmic_as923.c | 21 +++++- src/lmic/lmic_bandplan.h | 3 + src/lmic/lmic_bandplan_as923.h | 16 +++++ src/lmic/lmic_config_preconditions.h | 10 +++ src/lmic/lmic_eu_like.h | 3 + src/lmic/lorabase.h | 3 +- src/lmic/lorabase_as923.h | 5 +- src/lmic/oslmic.h | 14 +++- src/lmic/radio.c | 98 +++++++++++++++++++++++++++- 15 files changed, 199 insertions(+), 8 deletions(-) diff --git a/src/hal/hal.cpp b/src/hal/hal.cpp index d9aede92..74a23c7a 100644 --- a/src/hal/hal.cpp +++ b/src/hal/hal.cpp @@ -61,6 +61,10 @@ void hal_pin_rst (u1_t val) { } } +s1_t hal_getRssiCal (void) { + return plmic_pins->rssi_cal; +} + #if !defined(LMIC_USE_INTERRUPTS) static void hal_interrupt_init() { pinMode(plmic_pins->dio[0], INPUT); diff --git a/src/hal/hal.h b/src/hal/hal.h index f40e19f2..796d0dd2 100644 --- a/src/hal/hal.h +++ b/src/hal/hal.h @@ -18,6 +18,9 @@ struct lmic_pinmap { u1_t rst; u1_t dio[NUM_DIO]; u1_t rxtx_rx_active; + s1_t rssi_cal; // byte 7: cal in dB -- added to RSSI + // measured prior to decision. + // Must include noise guardband! u4_t spi_freq; }; diff --git a/src/lmic/config.h b/src/lmic/config.h index 3a86f036..c71905fa 100644 --- a/src/lmic/config.h +++ b/src/lmic/config.h @@ -35,6 +35,15 @@ # error The selected CFG_... region is not supported yet. #endif +#ifndef LMIC_COUNTRY_CODE +# define LMIC_COUNTRY_CODE LMIC_COUNTRY_CODE_NONE +#endif + +// if the country code is japan, then the region must be AS923 +#if LMIC_COUNTRY_CODE == LMIC_COUNTRY_CODE_JP && CFG_region != LMIC_REGION_as923 +# error "If country code is JP, then region must be AS923" +#endif + #if !(CFG_LMIC_EU_like || CFG_LMIC_US_like) # error "Internal error: Neither EU-like nor US-like!" #endif diff --git a/src/lmic/hal.h b/src/lmic/hal.h index b69e4fb4..562b4283 100644 --- a/src/lmic/hal.h +++ b/src/lmic/hal.h @@ -105,6 +105,11 @@ u1_t hal_checkTimer (u4_t targettime); */ void hal_failed (const char *file, u2_t line); +/* + * get the calibration value for radio_rssi + */ +s1_t hal_getRssiCal (void); + #ifdef __cplusplus } // extern "C" #endif diff --git a/src/lmic/lmic.c b/src/lmic/lmic.c index 10039b97..a713dcd7 100644 --- a/src/lmic/lmic.c +++ b/src/lmic/lmic.c @@ -615,15 +615,20 @@ scan_mac_cmds( case MCMD_DN2P_SET: { #if !defined(DISABLE_MCMD_DN2P_SET) dr_t dr = (dr_t)(opts[oidx+1] & 0x0F); + u1_t rx1DrOffset = (u1_t)((opts[oidx+1] & 0x70) >> 4); u4_t freq = LMICbandplan_convFreq(&opts[oidx+2]); LMIC.dn2Ans = 0x80; // answer pending if( validDR(dr) ) LMIC.dn2Ans |= MCMD_DN2P_ANS_DRACK; if( freq != 0 ) LMIC.dn2Ans |= MCMD_DN2P_ANS_CHACK; - if( LMIC.dn2Ans == (0x80|MCMD_DN2P_ANS_DRACK|MCMD_DN2P_ANS_CHACK) ) { + if (rx1DrOffset <= 3) + LMIC.dn2Ans |= MCMD_DN2P_ANS_RX1DrOffsetAck; + + if( LMIC.dn2Ans == (0x80|MCMD_DN2P_ANS_DRACK|MCMD_DN2P_ANS_CHACK| MCMD_DN2P_ANS_RX1DrOffsetAck) ) { LMIC.dn2Dr = dr; LMIC.dn2Freq = freq; + LMIC.rx1DrOffset = rx1DrOffset; DO_DEVDB(LMIC.dn2Dr,dn2Dr); DO_DEVDB(LMIC.dn2Freq,dn2Freq); } @@ -1866,6 +1871,7 @@ void LMIC_reset (void) { void LMIC_init (void) { LMIC.opmode = OP_SHUTDOWN; + LMICbandplan_init(); } diff --git a/src/lmic/lmic.h b/src/lmic/lmic.h index 2145e1f3..0b902809 100644 --- a/src/lmic/lmic.h +++ b/src/lmic/lmic.h @@ -207,6 +207,11 @@ struct lmic_t { // Radio settings TX/RX (also accessed by HAL) ostime_t txend; ostime_t rxtime; + + // LBT info + ostime_t lbt_ticks; // ticks to listen + s1_t lbt_dbmax; // max permissible dB on our channle (eg -80) + u4_t freq; s1_t rssi; s1_t snr; diff --git a/src/lmic/lmic_as923.c b/src/lmic/lmic_as923.c index 13b9d31a..85959286 100644 --- a/src/lmic/lmic_as923.c +++ b/src/lmic/lmic_as923.c @@ -181,6 +181,25 @@ void LMICas923_initDefaultChannels(bit_t join) { LMIC.bands[BAND_CENTI].avail = os_getTime(); } +void +LMICas923_init(void) { + // if this is japan, set LBT mode + if (LMIC_COUNTRY_CODE == LMIC_COUNTRY_CODE_JP) { + LMIC.lbt_ticks = us2osticks(AS923JP_LBT_US); + LMIC.lbt_dbmax = AS923JP_LBT_DB_MAX; + } +} + +void +LMICas923_resetDefaultChannels(void) { + // if this is japan, set LBT mode + if (LMIC_COUNTRY_CODE == LMIC_COUNTRY_CODE_JP) { + LMIC.lbt_ticks = us2osticks(AS923JP_LBT_US); + LMIC.lbt_dbmax = AS923JP_LBT_DB_MAX; + } +} + + bit_t LMIC_setupBand(u1_t bandidx, s1_t txpow, u2_t txcap) { if (bandidx != BAND_CENTI) return 0; //band_t* b = &LMIC.bands[bandidx]; @@ -343,4 +362,4 @@ LMICas923_updateTx(ostime_t txbeg) { // END: AS923 related stuff // // ================================================================================ -#endif \ No newline at end of file +#endif diff --git a/src/lmic/lmic_bandplan.h b/src/lmic/lmic_bandplan.h index 6aa2c743..0c3c5036 100644 --- a/src/lmic/lmic_bandplan.h +++ b/src/lmic/lmic_bandplan.h @@ -140,6 +140,9 @@ # error "LMICbandplan_nextJoinTime() not defined by bandplan" #endif +#if !defined(LMICbandplan_init) +# error "LMICbandplan_init() not defined by bandplan" +#endif // // Things common to lmic.c code // diff --git a/src/lmic/lmic_bandplan_as923.h b/src/lmic/lmic_bandplan_as923.h index 10dd2224..50017f29 100644 --- a/src/lmic/lmic_bandplan_as923.h +++ b/src/lmic/lmic_bandplan_as923.h @@ -52,6 +52,22 @@ LMICas923_isValidBeacon1(const uint8_t *d) { #undef LMICbandplan_isValidBeacon1 #define LMICbandplan_isValidBeacon1(pFrame) LMICas923_isValidBeacon1(pFrame) +// override default for LMICbandplan_resetDefaultChannels +void +LMICas923_resetDefaultChannels(void); + +#undef LMICbandplan_resetDefaultChannels +#define LMICbandplan_resetDefaultChannels() \ + LMICas923_resetDefaultChannels() + +// override default for LMICbandplan_init +void LMICas923_init(void); + +#undef LMICbandplan_init +#define LMICbandplan_init() \ + LMICas923_init() + + // override default for LMICbandplan_isFSK() #undef LMICbandplan_isFSK #define LMICbandplan_isFSK() (/* TX datarate */LMIC.rxsyms == AS923_DR_FSK) diff --git a/src/lmic/lmic_config_preconditions.h b/src/lmic/lmic_config_preconditions.h index cd925003..52ec4771 100644 --- a/src/lmic/lmic_config_preconditions.h +++ b/src/lmic/lmic_config_preconditions.h @@ -72,6 +72,16 @@ Revision history: #define LMIC_REGION_kr921 8 #define LMIC_REGION_in866 9 +// country codes for comparison. These values are chosen from the 2-letter domain suffixes (which +// I think are ISO standardized) +#define LMIC_COUNTRY_CODE_C(c1, c2) ((c1) * 256 + (c2)) + +// this special code means "no country code defined" +#define LMIC_COUNTRY_CODE_NONE 0 + +// specific countries. Only the ones that are known in the code are defined. +#define LMIC_COUNTRY_CODE_JP LMIC_COUNTRY_CODE_C('j', 'p') + // include the file that the user is really supposed to edit. But for really strange // ports, this can be suppressed #ifndef ARDUINO_LMIC_PROJECT_CONFIG_H_SUPPRESS diff --git a/src/lmic/lmic_eu_like.h b/src/lmic/lmic_eu_like.h index e6ea820e..f147790d 100644 --- a/src/lmic/lmic_eu_like.h +++ b/src/lmic/lmic_eu_like.h @@ -92,4 +92,7 @@ static inline ostime_t LMICeulike_nextJoinTime(ostime_t now) { } #define LMICbandplan_nextJoinTime(now) LMICeulike_nextJoinTime(now) +#define LMICbandplan_init() \ + do { /* nothing */ } while (0) + #endif // _lmic_eu_like_h_ diff --git a/src/lmic/lorabase.h b/src/lmic/lorabase.h index 7368329f..3e57a9cd 100644 --- a/src/lmic/lorabase.h +++ b/src/lmic/lorabase.h @@ -483,7 +483,8 @@ enum { MCMD_LADR_ANS_CHACK = 0x01, // 0=unknown channel enabled }; enum { - MCMD_DN2P_ANS_RFU = 0xFC, // RFU bits + 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 }; diff --git a/src/lmic/lorabase_as923.h b/src/lmic/lorabase_as923.h index aa5e62e3..2b95249c 100644 --- a/src/lmic/lorabase_as923.h +++ b/src/lmic/lorabase_as923.h @@ -74,4 +74,7 @@ enum { DR_PAGE_AS923 = 0x10 * (LMIC_REGION_as923 - 1) }; enum { AS923_LMIC_REGION_EIRP = 1 }; // region uses EIRP -#endif /* _lorabase_as923_h_ */ \ No newline at end of file +enum { AS923JP_LBT_US = 125 }; // microseconds of LBT time +enum { AS923JP_LBT_DB_MAX = -80 }; // maximum channel strength + +#endif /* _lorabase_as923_h_ */ diff --git a/src/lmic/oslmic.h b/src/lmic/oslmic.h index 9e190333..1cef61bf 100644 --- a/src/lmic/oslmic.h +++ b/src/lmic/oslmic.h @@ -73,6 +73,8 @@ typedef struct rxsched_t rxsched_t; typedef struct bcninfo_t bcninfo_t; typedef const u1_t* xref2cu1_t; typedef u1_t* xref2u1_t; +typedef s4_t ostime_t; + #define TYPEDEF_xref2rps_t typedef rps_t* xref2rps_t #define TYPEDEF_xref2rxsched_t typedef rxsched_t* xref2rxsched_t #define TYPEDEF_xref2chnldef_t typedef chnldef_t* xref2chnldef_t @@ -96,6 +98,15 @@ u1_t radio_rand1 (void); #define DEFINE_LMIC struct lmic_t LMIC #define DECLARE_LMIC extern struct lmic_t LMIC +typedef struct oslmic_radio_rssi_s oslmic_radio_rssi_t; + +struct oslmic_radio_rssi_s { + s2_t min_rssi; + s2_t max_rssi; + s2_t mean_rssi; + u2_t n_rssi; +}; + int radio_init (void); void radio_irq_handler (u1_t dio); void os_init (void); @@ -103,6 +114,7 @@ int os_init_ex (const void *pPinMap); void os_runloop (void); void os_runloop_once (void); u1_t radio_rssi (void); +void radio_monitor_rssi(ostime_t n, oslmic_radio_rssi_t *pRssi); //================================================================================ @@ -120,8 +132,6 @@ u1_t radio_rssi (void); #error Illegal OSTICKS_PER_SEC - must be in range [10000:64516]. One tick must be 15.5us .. 100us long. #endif -typedef s4_t ostime_t; - #if !HAS_ostick_conv #define us2osticks(us) ((ostime_t)( ((int64_t)(us) * OSTICKS_PER_SEC) / 1000000)) #define ms2osticks(ms) ((ostime_t)( ((int64_t)(ms) * OSTICKS_PER_SEC) / 1000)) diff --git a/src/lmic/radio.c b/src/lmic/radio.c index c3114e1b..60c4ff27 100644 --- a/src/lmic/radio.c +++ b/src/lmic/radio.c @@ -195,7 +195,17 @@ #define RXLORA_RXMODE_RSSI_REG_MODEM_CONFIG2 0x74 #endif - +//----------------------------------------- +// Parameters for RSSI monitoring +#define SX127X_FREQ_LF_MAX 525000000 // per datasheet 6.3 + +// per datasheet 5.5.3: +#define SX127X_RSSI_ADJUST_LF -164 // add to rssi value to get dB (LF) +#define SX127X_RSSI_ADJUST_HF -157 // add to rssi value to get dB (HF) + +// per datasheet 2.5.2 (but note that we ought to ask Semtech to confirm, because +// datasheet is unclear). +#define SX127X_RX_POWER_UP us2osticks(500) // delay this long to let the receiver power up. // ---------------------------------------- // Constants for radio registers @@ -549,7 +559,27 @@ static void txlora () { // start transmitter (buf=LMIC.frame, len=LMIC.dataLen) static void starttx () { - ASSERT( (readReg(RegOpMode) & OPMODE_MASK) == OPMODE_SLEEP ); + u1_t const rOpMode = readReg(RegOpMode); + + // originally, this code ASSERT()ed, but asserts are both bad and + // blunt instruments. If we see that we're not in sleep mode, + // force sleep (because we might have to switch modes) + if ((rOpMode & OPMODE_MASK) != OPMODE_SLEEP) { + opmode(OPMODE_SLEEP); + hal_waitUntil(os_getTime() + ms2osticks(1)); + } + + if (LMIC.lbt_ticks > 0) { + oslmic_radio_rssi_t rssi; + radio_monitor_rssi(LMIC.lbt_ticks, &rssi); + + if (rssi.max_rssi >= LMIC.lbt_dbmax) { + // complete the request by scheduling the job + os_setCallback(&LMIC.osjob, LMIC.osjob.func); + return; + } + } + if(getSf(LMIC.rps) == FSK) { // FSK modem txfsk(); } else { // LoRa modem @@ -791,6 +821,70 @@ u1_t radio_rssi () { return r; } +// monitor rssi for specified number of ostime_t ticks, and return statistics +// This puts the radio into RX continuous mode, waits long enough for the +// oscillators to start and the PLL to lock, and then measures for the specified +// period of time. The radio is then returned to idle. +// +// RSSI returned is expressed in units of dB, and is offset according to the +// current radio setting per section 5.5.5 of Semtech 1276 datasheet. +void radio_monitor_rssi(ostime_t nTicks, oslmic_radio_rssi_t *pRssi) { + uint8_t rssiMax, rssiMin; + uint16_t rssiSum; + uint16_t rssiN; + + int rssiAdjust; + ostime_t tBegin; + int notDone; + + rxlora(RXMODE_SCAN); + + // while we're waiting for the PLLs to spin up, determine which + // band we're in and choose the base RSSI. + if (LMIC.freq > SX127X_FREQ_LF_MAX) { + rssiAdjust = SX127X_RSSI_ADJUST_HF; + } else { + rssiAdjust = SX127X_RSSI_ADJUST_LF; + } + rssiAdjust += hal_getRssiCal(); + + // zero the results + rssiMax = 255; + rssiMin = 0; + rssiSum = 0; + rssiN = 0; + + // wait for PLLs + hal_waitUntil(os_getTime() + SX127X_RX_POWER_UP); + + // scan for the desired time. + tBegin = os_getTime(); + rssiMax = 0; + do { + ostime_t now; + + u1_t rssiNow = readReg(LORARegRssiValue); + + if (rssiMax < rssiNow) + rssiMax = rssiNow; + if (rssiNow < rssiMin) + rssiMin = rssiNow; + rssiSum += rssiNow; + ++rssiN; + now = os_getTime(); + notDone = now - (tBegin + nTicks) < 0; + } while (notDone); + + // put radio back to sleep + opmode(OPMODE_SLEEP); + + // compute the results + pRssi->max_rssi = (s2_t) (rssiMax + rssiAdjust); + pRssi->min_rssi = (s2_t) (rssiMin + rssiAdjust); + pRssi->mean_rssi = (s2_t) (rssiAdjust + ((rssiSum + (rssiN >> 1)) / rssiN)); + pRssi->n_rssi = rssiN; +} + static CONST_TABLE(u2_t, LORA_RXDONE_FIXUP)[] = { [FSK] = us2osticks(0), // ( 0 ticks) [SF7] = us2osticks(0), // ( 0 ticks) From 6c39b60558d4defbb6be82f8c515e52da0ab6568 Mon Sep 17 00:00:00 2001 From: Shoichi Sakane Date: Tue, 15 May 2018 14:22:34 +0900 Subject: [PATCH 02/19] oslmic_radio_rssi_s for radio_monitor_rssi() should be a static. it makes stable. --- src/lmic/radio.c | 13 +++++++------ 1 file changed, 7 insertions(+), 6 deletions(-) diff --git a/src/lmic/radio.c b/src/lmic/radio.c index 60c4ff27..714a051d 100644 --- a/src/lmic/radio.c +++ b/src/lmic/radio.c @@ -557,6 +557,8 @@ static void txlora () { #endif } +static oslmic_radio_rssi_t xRssi; + // start transmitter (buf=LMIC.frame, len=LMIC.dataLen) static void starttx () { u1_t const rOpMode = readReg(RegOpMode); @@ -570,13 +572,12 @@ static void starttx () { } if (LMIC.lbt_ticks > 0) { - oslmic_radio_rssi_t rssi; - radio_monitor_rssi(LMIC.lbt_ticks, &rssi); + radio_monitor_rssi(LMIC.lbt_ticks, &xRssi); - if (rssi.max_rssi >= LMIC.lbt_dbmax) { - // complete the request by scheduling the job - os_setCallback(&LMIC.osjob, LMIC.osjob.func); - return; + if (xRssi.max_rssi >= LMIC.lbt_dbmax) { + // complete the request by scheduling the job + os_setCallback(&LMIC.osjob, LMIC.osjob.func); + return; } } From 459967ba7efed344575fc5ca0b9ac0585220618a Mon Sep 17 00:00:00 2001 From: Shoichi Sakane Date: Tue, 15 May 2018 14:36:40 +0900 Subject: [PATCH 03/19] defined LMIC_X_DEBUG_LEVEL. when you use LMIC_DEBUG_LEVEL, it makes the stack bigger so as not to be suitable into 2KB. --- src/lmic/lmic.h | 11 +++++++++++ 1 file changed, 11 insertions(+) diff --git a/src/lmic/lmic.h b/src/lmic/lmic.h index 0b902809..06a89ed4 100644 --- a/src/lmic/lmic.h +++ b/src/lmic/lmic.h @@ -70,6 +70,17 @@ # define LMIC_DEBUG_FLUSH() do { ; } while (0) #endif // LMIC_DEBUG_LEVEL == 0 +#if LMIC_X_DEBUG_LEVEL > 0 +# ifdef LMIC_DEBUG_PRINTF_FN + extern void LMIC_DEBUG_PRINTF_FN(const char *f, ...); +# define LMIC_X_DEBUG_PRINTF(f, ...) LMIC_DEBUG_PRINTF_FN(f, ## __VA_ARGS__) +# else +# error "LMIC_DEBUG_PRINTF_FN must be defined." +# endif +#else +# define LMIC_X_DEBUG_PRINTF(f, ...) do {;} while(0) +#endif + #ifdef __cplusplus extern "C"{ #endif From 78392d3c3de71e1d35224dc0c11d26e3876047fe Mon Sep 17 00:00:00 2001 From: Shoichi Sakane Date: Wed, 16 May 2018 01:14:08 +0900 Subject: [PATCH 04/19] reverted. --- src/lmic/radio.c | 7 +++---- 1 file changed, 3 insertions(+), 4 deletions(-) diff --git a/src/lmic/radio.c b/src/lmic/radio.c index 714a051d..3397a6e7 100644 --- a/src/lmic/radio.c +++ b/src/lmic/radio.c @@ -557,8 +557,6 @@ static void txlora () { #endif } -static oslmic_radio_rssi_t xRssi; - // start transmitter (buf=LMIC.frame, len=LMIC.dataLen) static void starttx () { u1_t const rOpMode = readReg(RegOpMode); @@ -572,9 +570,10 @@ static void starttx () { } if (LMIC.lbt_ticks > 0) { - radio_monitor_rssi(LMIC.lbt_ticks, &xRssi); + oslmic_radio_rssi_t rssi; + radio_monitor_rssi(LMIC.lbt_ticks, &rssi); - if (xRssi.max_rssi >= LMIC.lbt_dbmax) { + if (rssi.max_rssi >= LMIC.lbt_dbmax) { // complete the request by scheduling the job os_setCallback(&LMIC.osjob, LMIC.osjob.func); return; From 378506d159bfcd4f5cf047b0f79bd1df2f42ccf7 Mon Sep 17 00:00:00 2001 From: Shoichi Sakane Date: Wed, 16 May 2018 01:19:34 +0900 Subject: [PATCH 05/19] defined AS923JP_LBT_5MS for Japan regulation. It assumes to use from 920.6 to 923.4 and the longer sensing time. 128us of the sensing time for 922.4 or upper freqs. is not supported yet. --- src/lmic/lmic_as923.c | 4 ++-- src/lmic/lorabase_as923.h | 2 +- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/src/lmic/lmic_as923.c b/src/lmic/lmic_as923.c index 85959286..5b8da1f8 100644 --- a/src/lmic/lmic_as923.c +++ b/src/lmic/lmic_as923.c @@ -185,7 +185,7 @@ void LMICas923_init(void) { // if this is japan, set LBT mode if (LMIC_COUNTRY_CODE == LMIC_COUNTRY_CODE_JP) { - LMIC.lbt_ticks = us2osticks(AS923JP_LBT_US); + LMIC.lbt_ticks = ms2osticks(AS923JP_LBT_5MS); LMIC.lbt_dbmax = AS923JP_LBT_DB_MAX; } } @@ -194,7 +194,7 @@ void LMICas923_resetDefaultChannels(void) { // if this is japan, set LBT mode if (LMIC_COUNTRY_CODE == LMIC_COUNTRY_CODE_JP) { - LMIC.lbt_ticks = us2osticks(AS923JP_LBT_US); + LMIC.lbt_ticks = ms2osticks(AS923JP_LBT_5MS); LMIC.lbt_dbmax = AS923JP_LBT_DB_MAX; } } diff --git a/src/lmic/lorabase_as923.h b/src/lmic/lorabase_as923.h index 2b95249c..9637e5cc 100644 --- a/src/lmic/lorabase_as923.h +++ b/src/lmic/lorabase_as923.h @@ -74,7 +74,7 @@ enum { DR_PAGE_AS923 = 0x10 * (LMIC_REGION_as923 - 1) }; enum { AS923_LMIC_REGION_EIRP = 1 }; // region uses EIRP -enum { AS923JP_LBT_US = 125 }; // microseconds of LBT time +enum { AS923JP_LBT_5MS = 5 }; // microseconds of LBT time enum { AS923JP_LBT_DB_MAX = -80 }; // maximum channel strength #endif /* _lorabase_as923_h_ */ From ea5ebae2fc872148bc16258c59900df37e5cfbdc Mon Sep 17 00:00:00 2001 From: Shoichi Sakane Date: Wed, 16 May 2018 01:28:29 +0900 Subject: [PATCH 06/19] added a work-around to avoid the infinite loop while radio_monitor_rssi(). micros() is not stable in the loop. --- src/lmic/radio.c | 24 ++++++++++++++++++++---- 1 file changed, 20 insertions(+), 4 deletions(-) diff --git a/src/lmic/radio.c b/src/lmic/radio.c index 714a051d..9dcb0058 100644 --- a/src/lmic/radio.c +++ b/src/lmic/radio.c @@ -25,6 +25,10 @@ * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. */ +#if LMIC_X_DEBUG_LEVEL > 0 +#include +#endif + #define LMIC_DR_LEGACY 0 #include "lmic.h" @@ -557,8 +561,6 @@ static void txlora () { #endif } -static oslmic_radio_rssi_t xRssi; - // start transmitter (buf=LMIC.frame, len=LMIC.dataLen) static void starttx () { u1_t const rOpMode = readReg(RegOpMode); @@ -572,9 +574,13 @@ static void starttx () { } if (LMIC.lbt_ticks > 0) { - radio_monitor_rssi(LMIC.lbt_ticks, &xRssi); + oslmic_radio_rssi_t rssi; + radio_monitor_rssi(LMIC.lbt_ticks, &rssi); +#if LMIC_X_DEBUG_LEVEL > 0 + LMIC_X_DEBUG_PRINTF("rssi max:min=%d:%d %d times in %d\n", rssi.max_rssi, rssi.min_rssi, rssi.n_rssi, LMIC.lbt_ticks); +#endif - if (xRssi.max_rssi >= LMIC.lbt_dbmax) { + if (rssi.max_rssi >= LMIC.lbt_dbmax) { // complete the request by scheduling the job os_setCallback(&LMIC.osjob, LMIC.osjob.func); return; @@ -861,6 +867,9 @@ void radio_monitor_rssi(ostime_t nTicks, oslmic_radio_rssi_t *pRssi) { // scan for the desired time. tBegin = os_getTime(); rssiMax = 0; + + // XXX duty hack. any other solutions ? + int sentry = 0; //xxx do { ostime_t now; @@ -872,8 +881,15 @@ void radio_monitor_rssi(ostime_t nTicks, oslmic_radio_rssi_t *pRssi) { rssiMin = rssiNow; rssiSum += rssiNow; ++rssiN; + hal_enableIRQs(); //xxx now = os_getTime(); + hal_disableIRQs(); //xxx notDone = now - (tBegin + nTicks) < 0; +#if LMIC_X_DEBUG_LEVEL > 0 + LMIC_X_DEBUG_PRINTF("notDone:%d\n", notDone); //xxx +#endif + if (sentry++ > 20) //xxx + break; //xxx } while (notDone); // put radio back to sleep From c345af7fe8ab6fa35437f578ad9c90b3740cc42b Mon Sep 17 00:00:00 2001 From: Shoichi Sakane Date: Wed, 16 May 2018 21:43:35 +0900 Subject: [PATCH 07/19] removed the debug code. seems be stable. --- src/lmic/radio.c | 3 --- 1 file changed, 3 deletions(-) diff --git a/src/lmic/radio.c b/src/lmic/radio.c index 9dcb0058..03316a96 100644 --- a/src/lmic/radio.c +++ b/src/lmic/radio.c @@ -885,9 +885,6 @@ void radio_monitor_rssi(ostime_t nTicks, oslmic_radio_rssi_t *pRssi) { now = os_getTime(); hal_disableIRQs(); //xxx notDone = now - (tBegin + nTicks) < 0; -#if LMIC_X_DEBUG_LEVEL > 0 - LMIC_X_DEBUG_PRINTF("notDone:%d\n", notDone); //xxx -#endif if (sentry++ > 20) //xxx break; //xxx } while (notDone); From 77ea3de7c9f65df1befdb300196aed420bd0be7f Mon Sep 17 00:00:00 2001 From: Shoichi Sakane Date: Wed, 16 May 2018 21:44:06 +0900 Subject: [PATCH 08/19] added simple message print for debug. --- src/lmic/lmic.h | 2 ++ 1 file changed, 2 insertions(+) diff --git a/src/lmic/lmic.h b/src/lmic/lmic.h index 06a89ed4..57cdffac 100644 --- a/src/lmic/lmic.h +++ b/src/lmic/lmic.h @@ -74,11 +74,13 @@ # ifdef LMIC_DEBUG_PRINTF_FN extern void LMIC_DEBUG_PRINTF_FN(const char *f, ...); # define LMIC_X_DEBUG_PRINTF(f, ...) LMIC_DEBUG_PRINTF_FN(f, ## __VA_ARGS__) +# define LMIC_X_DEBUG_PRINTS(s) Serial.println(F(s)) # else # error "LMIC_DEBUG_PRINTF_FN must be defined." # endif #else # define LMIC_X_DEBUG_PRINTF(f, ...) do {;} while(0) +# define LMIC_X_DEBUG_PRINTS(s) do {;} while(0) #endif #ifdef __cplusplus From 61911c5e8ef3b815459b0531ef761b84f4c0d1ae Mon Sep 17 00:00:00 2001 From: Shoichi Sakane Date: Thu, 17 May 2018 00:12:54 +0900 Subject: [PATCH 09/19] fixed indent. --- src/lmic/lmic.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/lmic/lmic.c b/src/lmic/lmic.c index a713dcd7..36c9cf22 100644 --- a/src/lmic/lmic.c +++ b/src/lmic/lmic.c @@ -1711,7 +1711,7 @@ static void engineUpdate (void) { // Earliest possible time vs overhead to setup radio if( txbeg - (now + TX_RAMPUP) < 0 ) { // We could send right now! - txbeg = now; + txbeg = now; dr_t txdr = (dr_t)LMIC.datarate; #if !defined(DISABLE_JOIN) if( jacc ) { From 00c565a673596d07f66345b94ac5a85fe7488199 Mon Sep 17 00:00:00 2001 From: Shoichi Sakane Date: Thu, 17 May 2018 17:21:09 +0900 Subject: [PATCH 10/19] commented about the issue that the infinite loop happens in radio_monitor_rssi(). --- src/lmic/radio.c | 20 ++++++++++++++------ 1 file changed, 14 insertions(+), 6 deletions(-) diff --git a/src/lmic/radio.c b/src/lmic/radio.c index 03316a96..fa40027d 100644 --- a/src/lmic/radio.c +++ b/src/lmic/radio.c @@ -868,9 +868,17 @@ void radio_monitor_rssi(ostime_t nTicks, oslmic_radio_rssi_t *pRssi) { tBegin = os_getTime(); rssiMax = 0; - // XXX duty hack. any other solutions ? - int sentry = 0; //xxx + /* XXX + * In this loop, micros() in os_getTime() returns a past time sometimes. + * At least, it happens on Dragino LoRa Mini. + * the return value of micros() looks not to be stable in IRQ disabled. + * Once it happens, this loop never exit infinitely. + * In order to prevent it, it enables IRQ before calling os_getTime(), + * disable IRQ again after that. in addition to, a sentry checks the + * number of loop for sure. + */ do { + int sentry = 0; ostime_t now; u1_t rssiNow = readReg(LORARegRssiValue); @@ -881,12 +889,12 @@ void radio_monitor_rssi(ostime_t nTicks, oslmic_radio_rssi_t *pRssi) { rssiMin = rssiNow; rssiSum += rssiNow; ++rssiN; - hal_enableIRQs(); //xxx + hal_enableIRQs(); now = os_getTime(); - hal_disableIRQs(); //xxx + hal_disableIRQs(); notDone = now - (tBegin + nTicks) < 0; - if (sentry++ > 20) //xxx - break; //xxx + if (sentry++ > 20) + break; } while (notDone); // put radio back to sleep From 55989ac9e7a256d137daa4b653d28b7ecedf5db3 Mon Sep 17 00:00:00 2001 From: Shoichi Sakane Date: Thu, 17 May 2018 18:09:01 +0900 Subject: [PATCH 11/19] removed a debug print. --- src/lmic/lmic.h | 2 -- 1 file changed, 2 deletions(-) diff --git a/src/lmic/lmic.h b/src/lmic/lmic.h index 57cdffac..06a89ed4 100644 --- a/src/lmic/lmic.h +++ b/src/lmic/lmic.h @@ -74,13 +74,11 @@ # ifdef LMIC_DEBUG_PRINTF_FN extern void LMIC_DEBUG_PRINTF_FN(const char *f, ...); # define LMIC_X_DEBUG_PRINTF(f, ...) LMIC_DEBUG_PRINTF_FN(f, ## __VA_ARGS__) -# define LMIC_X_DEBUG_PRINTS(s) Serial.println(F(s)) # else # error "LMIC_DEBUG_PRINTF_FN must be defined." # endif #else # define LMIC_X_DEBUG_PRINTF(f, ...) do {;} while(0) -# define LMIC_X_DEBUG_PRINTS(s) do {;} while(0) #endif #ifdef __cplusplus From 95788f8e48c4b263b5f5750b9d63d800701c5e7c Mon Sep 17 00:00:00 2001 From: Shoichi Sakane Date: Thu, 17 May 2018 18:09:49 +0900 Subject: [PATCH 12/19] addded debug code for joining. --- src/lmic/lmic.c | 3 +++ 1 file changed, 3 insertions(+) diff --git a/src/lmic/lmic.c b/src/lmic/lmic.c index 36c9cf22..e8659a5c 100644 --- a/src/lmic/lmic.c +++ b/src/lmic/lmic.c @@ -971,6 +971,7 @@ static void schedRx12 (ostime_t delay, osjobcb_t func, u1_t dr) { // (again note that hsym is half a sumbol time, so no /2 needed) LMIC.rxtime = LMIC.txend + delay + PAMBL_SYMS * hsym - LMIC.rxsyms * hsym; + LMIC_X_DEBUG_PRINTF("%lu: sched Rx12 %lu\n", os_getTime(), LMIC.rxtime - RX_RAMPUP); os_setTimedCallback(&LMIC.osjob, LMIC.rxtime - RX_RAMPUP, func); } @@ -1129,6 +1130,7 @@ static bit_t processJoinAccept (void) { static void processRx2Jacc (xref2osjob_t osjob) { + LMIC_X_DEBUG_PRINTF("%lu: Jacc Rx2\n", os_getTime()); if( LMIC.dataLen == 0 ) { initTxrxFlags(__func__, 0); // nothing in 1st/2nd DN slot } @@ -1143,6 +1145,7 @@ static void setupRx2Jacc (xref2osjob_t osjob) { static void processRx1Jacc (xref2osjob_t osjob) { + LMIC_X_DEBUG_PRINTF("%lu: Jacc Rx1\n", os_getTime()); if( LMIC.dataLen == 0 || !processJoinAccept() ) schedRx12(DELAY_JACC2_osticks, FUNC_ADDR(setupRx2Jacc), LMIC.dn2Dr); } From 6ddd2e1fae0716fc889543f4c7eee7e105029d5b Mon Sep 17 00:00:00 2001 From: Shoichi Sakane Date: Thu, 17 May 2018 23:34:43 +0900 Subject: [PATCH 13/19] - enable to print the tick for the next calling engineupdate(). - removed unused debug messages. --- src/lmic/lmic.c | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/src/lmic/lmic.c b/src/lmic/lmic.c index e8659a5c..32359443 100644 --- a/src/lmic/lmic.c +++ b/src/lmic/lmic.c @@ -1130,7 +1130,6 @@ static bit_t processJoinAccept (void) { static void processRx2Jacc (xref2osjob_t osjob) { - LMIC_X_DEBUG_PRINTF("%lu: Jacc Rx2\n", os_getTime()); if( LMIC.dataLen == 0 ) { initTxrxFlags(__func__, 0); // nothing in 1st/2nd DN slot } @@ -1145,7 +1144,6 @@ static void setupRx2Jacc (xref2osjob_t osjob) { static void processRx1Jacc (xref2osjob_t osjob) { - LMIC_X_DEBUG_PRINTF("%lu: Jacc Rx1\n", os_getTime()); if( LMIC.dataLen == 0 || !processJoinAccept() ) schedRx12(DELAY_JACC2_osticks, FUNC_ADDR(setupRx2Jacc), LMIC.dn2Dr); } @@ -1816,6 +1814,7 @@ static void engineUpdate (void) { e_.eui = MAIN::CDEV->getEui(), e_.info = osticks2ms(txbeg-now), e_.info2 = LMIC.seqnoUp-1)); + LMIC_X_DEBUG_PRINTF("%lu: next engine update in %lu\n", now, txbeg-TX_RAMPUP); os_setTimedCallback(&LMIC.osjob, txbeg-TX_RAMPUP, FUNC_ADDR(runEngineUpdate)); } From d2b676599ba655a06437d295205e705d2a700694 Mon Sep 17 00:00:00 2001 From: Shoichi Sakane Date: Thu, 24 May 2018 22:13:14 +0900 Subject: [PATCH 14/19] in the join of AS923 v1.1 or older, only DR2 is used. no need to change the DR. --- src/lmic/lmic_eu_like.c | 8 ++++++++ 1 file changed, 8 insertions(+) diff --git a/src/lmic/lmic_eu_like.c b/src/lmic/lmic_eu_like.c index 39841431..f5fdee0a 100644 --- a/src/lmic/lmic_eu_like.c +++ b/src/lmic/lmic_eu_like.c @@ -103,7 +103,15 @@ ostime_t LMICeulike_nextJoinState(uint8_t nDefaultChannels) { if (LMIC.datarate == LORAWAN_DR0) failed = 1; // we have tried all DR - signal EV_JOIN_FAILED else + { +#if CFG_region != LMIC_REGION_as923 LMICcore_setDrJoin(DRCHG_NOJACC, decDR((dr_t)LMIC.datarate)); +#else + // in the join of AS923 v1.1 or older, only DR2 is used. + // no need to change the DR. + LMIC.datarate = AS923_DR_SF10; +#endif + } } // Clear NEXTCHNL because join state engine controls channel hopping LMIC.opmode &= ~OP_NEXTCHNL; From 46b24b3341d5a3dae4b03cfb576afc722d5cd7ad Mon Sep 17 00:00:00 2001 From: Shoichi Sakane Date: Thu, 24 May 2018 22:16:57 +0900 Subject: [PATCH 15/19] added debug messages. --- src/lmic/radio.c | 7 +++++-- 1 file changed, 5 insertions(+), 2 deletions(-) diff --git a/src/lmic/radio.c b/src/lmic/radio.c index fa40027d..116662fc 100644 --- a/src/lmic/radio.c +++ b/src/lmic/radio.c @@ -577,7 +577,7 @@ static void starttx () { oslmic_radio_rssi_t rssi; radio_monitor_rssi(LMIC.lbt_ticks, &rssi); #if LMIC_X_DEBUG_LEVEL > 0 - LMIC_X_DEBUG_PRINTF("rssi max:min=%d:%d %d times in %d\n", rssi.max_rssi, rssi.min_rssi, rssi.n_rssi, LMIC.lbt_ticks); + LMIC_X_DEBUG_PRINTF("LBT rssi max:min=%d:%d %d times in %d\n", rssi.max_rssi, rssi.min_rssi, rssi.n_rssi, LMIC.lbt_ticks); #endif if (rssi.max_rssi >= LMIC.lbt_dbmax) { @@ -936,6 +936,7 @@ void radio_irq_handler (u1_t dio) { #endif if( (readReg(RegOpMode) & OPMODE_LORA) != 0) { // LORA modem u1_t flags = readReg(LORARegIrqFlags); + LMIC_X_DEBUG_PRINTF("IRQ=%02x\n", flags); if( flags & IRQ_LORA_TXDONE_MASK ) { // save exact tx time LMIC.txend = now - us2osticks(43); // TXDONE FIXUP @@ -954,7 +955,9 @@ void radio_irq_handler (u1_t dio) { readBuf(RegFifo, LMIC.frame, LMIC.dataLen); // read rx quality parameters LMIC.snr = readReg(LORARegPktSnrValue); // SNR [dB] * 4 - LMIC.rssi = readReg(LORARegPktRssiValue) - 125 + 64; // RSSI [dBm] (-196...+63) + LMIC.rssi = readReg(LORARegPktRssiValue); + LMIC_X_DEBUG_PRINTF("RX snr=%u rssi=%d\n", LMIC.snr/4, SX127X_RSSI_ADJUST_HF + LMIC.rssi); + LMIC.rssi = LMIC.rssi - 125 + 64; // RSSI [dBm] (-196...+63) } else if( flags & IRQ_LORA_RXTOUT_MASK ) { // indicate timeout LMIC.dataLen = 0; From 59fc43cafa5e85d85a7086572aabd831c288c073 Mon Sep 17 00:00:00 2001 From: Shoichi Sakane Date: Thu, 24 May 2018 23:18:19 +0900 Subject: [PATCH 16/19] defined AS923_TX_CAP to avoid from using a number directly. --- src/lmic/lmic_as923.c | 3 +-- src/lmic/lorabase_as923.h | 5 +++++ 2 files changed, 6 insertions(+), 2 deletions(-) diff --git a/src/lmic/lmic_as923.c b/src/lmic/lmic_as923.c index 5b8da1f8..cf382a9a 100644 --- a/src/lmic/lmic_as923.c +++ b/src/lmic/lmic_as923.c @@ -174,8 +174,7 @@ void LMICas923_initDefaultChannels(bit_t join) { LMIC.channelDrMap[fu] = DR_RANGE_MAP(AS923_DR_SF12, AS923_DR_SF7B); } - // all channels face a 1% duty cycle. - LMIC.bands[BAND_CENTI].txcap = 100; // 1% + LMIC.bands[BAND_CENTI].txcap = AS923_TX_CAP; LMIC.bands[BAND_CENTI].txpow = AS923_TX_EIRP_MAX_DBM; LMIC.bands[BAND_CENTI].lastchnl = os_getRndU1() % MAX_CHANNELS; LMIC.bands[BAND_CENTI].avail = os_getTime(); diff --git a/src/lmic/lorabase_as923.h b/src/lmic/lorabase_as923.h index 9637e5cc..dae623a4 100644 --- a/src/lmic/lorabase_as923.h +++ b/src/lmic/lorabase_as923.h @@ -77,4 +77,9 @@ enum { AS923_LMIC_REGION_EIRP = 1 }; // region uses EIRP enum { AS923JP_LBT_5MS = 5 }; // microseconds of LBT time enum { AS923JP_LBT_DB_MAX = -80 }; // maximum channel strength +#if !defined(AS923_TX_CAP) +// AS923 v1.1, all channels face a 1% duty cycle. +# define AS923_TX_CAP 100 +#endif + #endif /* _lorabase_as923_h_ */ From a76993daa815017da81415e8ee588f44bdf58385 Mon Sep 17 00:00:00 2001 From: Shoichi Sakane Date: Thu, 24 May 2018 23:32:33 +0900 Subject: [PATCH 17/19] in the join of AS923, only DR2 is used and not changed. --- src/lmic/lmic.c | 16 ++++++++++++++++ 1 file changed, 16 insertions(+) diff --git a/src/lmic/lmic.c b/src/lmic/lmic.c index 32359443..ceaa284e 100644 --- a/src/lmic/lmic.c +++ b/src/lmic/lmic.c @@ -1044,10 +1044,18 @@ static bit_t processJoinAccept (void) { // Build next JOIN REQUEST with next engineUpdate call // Optionally, report join failed. // Both after a random/chosen amount of ticks. +#if CFG_region != LMIC_REGION_as923 os_setTimedCallback(&LMIC.osjob, os_getTime()+delay, (delay&1) != 0 ? FUNC_ADDR(onJoinFailed) // one JOIN iteration done and failed : FUNC_ADDR(runEngineUpdate)); // next step to be delayed +#else + // in the join of AS923 v1.1 older, only DR2 is used. Therefore, + // not much improvement when it handles two different behavior; + // onJoinFailed or runEngineUpdate. + os_setTimedCallback(&LMIC.osjob, os_getTime()+delay, + FUNC_ADDR(onJoinFailed)); +#endif return 1; } u1_t hdr = LMIC.frame[0]; @@ -1114,8 +1122,13 @@ static bit_t processJoinAccept (void) { ASSERT((LMIC.opmode & (OP_JOINING|OP_REJOIN))!=0); if( (LMIC.opmode & OP_REJOIN) != 0 ) { +#if CFG_region != LMIC_REGION_as923 // Lower DR every try below current UP DR LMIC.datarate = lowerDR(LMIC.datarate, LMIC.rejoinCnt); +#else + // in the join of AS923 v1.1 or older, only DR2 (SF10) is used. + LMIC.datarate = AS923_DR_SF10; +#endif } LMIC.opmode &= ~(OP_JOINING|OP_TRACK|OP_REJOIN|OP_TXRXPEND|OP_PINGINI) | OP_NEXTCHNL; LMIC.txCnt = 0; @@ -1718,7 +1731,10 @@ static void engineUpdate (void) { if( jacc ) { u1_t ftype; if( (LMIC.opmode & OP_REJOIN) != 0 ) { +#if CFG_region != LMIC_REGION_as923 + // in AS923 v1.1 or older, no need to change the datarate. txdr = lowerDR(txdr, LMIC.rejoinCnt); +#endif ftype = HDR_FTYPE_REJOIN; } else { ftype = HDR_FTYPE_JREQ; From 865dcf042208a4a71bfe3c8c97a74b8141761b4c Mon Sep 17 00:00:00 2001 From: Shoichi Sakane Date: Thu, 7 Jun 2018 07:52:05 +0900 Subject: [PATCH 18/19] LMICas923_getMaxEIRP() returns a Tx power itself, not a diff. --- src/lmic/lmic_as923.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/lmic/lmic_as923.c b/src/lmic/lmic_as923.c index cf382a9a..6b224bed 100644 --- a/src/lmic/lmic_as923.c +++ b/src/lmic/lmic_as923.c @@ -350,7 +350,7 @@ LMICas923_updateTx(ostime_t txbeg) { // Update channel/global duty cycle stats xref2band_t band = &LMIC.bands[freq & 0x3]; LMIC.freq = freq & ~(u4_t)3; - LMIC.txpow = band->txpow + LMICas923_getMaxEIRP(LMIC.txParam); + LMIC.txpow = LMICas923_getMaxEIRP(LMIC.txParam); band->avail = txbeg + airtime * band->txcap; if (LMIC.globalDutyRate != 0) LMIC.globalDutyAvail = txbeg + (airtime << LMIC.globalDutyRate); From b3d59ec797cba161f37df3b4e23beec2d58f47b1 Mon Sep 17 00:00:00 2001 From: Terry Moore Date: Wed, 6 Jun 2018 23:03:27 -0400 Subject: [PATCH 19/19] Polish up changes for pull reguest #70 --- README.md | 13 +++++++++++++ src/lmic/lmic.c | 24 ++++++++++++++++++------ src/lmic/lmic.h | 14 +++++++++++--- src/lmic/lmic_as923.c | 4 ++-- src/lmic/lmic_eu_like.c | 26 ++++++++++++++++++++++++++ src/lmic/lmic_us_like.c | 12 ++++++++++++ src/lmic/lorabase_as923.h | 21 ++++++++++++++++----- src/lmic/radio.c | 4 ---- 8 files changed, 98 insertions(+), 20 deletions(-) diff --git a/README.md b/README.md index b9c24286..8b16f739 100644 --- a/README.md +++ b/README.md @@ -65,6 +65,7 @@ requires C99 mode to be enabled by default. - [Timing](#timing) - [Downlink datarate](#downlink-datarate) - [Release History](#release-history) +- [Contributions](#contributions) - [Trademark Acknowledgements](#trademark-acknowledgements) - [License](#license) @@ -685,6 +686,18 @@ When using OTAA, the network communicates the RX2 settings in the join accept me - V2.0.2 adds support for the extended bandplans. +## Contributions + +This library started from the IBM V1.5 open-source code. + +- Thomas Telkamp and Matthijs Kooijman ported V1.5 to Arduino and did a lot of bug fixing. + +- Terry Moore, LeRoy Leslie, Frank Rose, and ChaeHee Won did a lot of work on US support. + +- Terry Moore added the AU921, AS923 and IN866 bandplans, and created the regionalization framework. + +- [@tanupoo](https://github.com/tanupoo) of the WIDE Project debugged AS923JP and LBT support. + ## Trademark Acknowledgements LoRa is a registered trademark of the LoRa Alliance. LoRaWAN is a trademark of the LoRa Alliance. diff --git a/src/lmic/lmic.c b/src/lmic/lmic.c index c2e424a1..f5ff4220 100644 --- a/src/lmic/lmic.c +++ b/src/lmic/lmic.c @@ -1036,24 +1036,30 @@ static bit_t processJoinAccept (void) { return 1; } LMIC.opmode &= ~OP_TXRXPEND; - ostime_t delay = LMICbandplan_nextJoinState(); + int failed = LMICbandplan_nextJoinState(); EV(devCond, DEBUG, (e_.reason = EV::devCond_t::NO_JACC, e_.eui = MAIN::CDEV->getEui(), e_.info = LMIC.datarate|DR_PAGE, - e_.info2 = osticks2ms(delay))); + e_.info2 = failed)); // Build next JOIN REQUEST with next engineUpdate call // Optionally, report join failed. - // Both after a random/chosen amount of ticks. + // Both after a random/chosen amount of ticks. That time + // is in LMIC.txend. The delay here is either zero or 1 + // tick; onJoinFailed()/runEngineUpdate() are responsible + // for honoring that. XXX(tmm@mcci.com) The IBM 1.6 code + // claimed to return a delay but really returns 0 or 1. + // Once we update as923 to return failed after dr2, we + // can take out this #if. #if CFG_region != LMIC_REGION_as923 - os_setTimedCallback(&LMIC.osjob, os_getTime()+delay, - (delay&1) != 0 + os_setTimedCallback(&LMIC.osjob, os_getTime()+failed, + failed ? FUNC_ADDR(onJoinFailed) // one JOIN iteration done and failed : FUNC_ADDR(runEngineUpdate)); // next step to be delayed #else // in the join of AS923 v1.1 older, only DR2 is used. Therefore, // not much improvement when it handles two different behavior; // onJoinFailed or runEngineUpdate. - os_setTimedCallback(&LMIC.osjob, os_getTime()+delay, + os_setTimedCallback(&LMIC.osjob, os_getTime()+failed, FUNC_ADDR(onJoinFailed)); #endif return 1; @@ -1121,8 +1127,14 @@ static bit_t processJoinAccept (void) { : EV::joininfo_t::ACCEPT))); ASSERT((LMIC.opmode & (OP_JOINING|OP_REJOIN))!=0); + // + // XXX(tmm@mcci.com) OP_REJOIN confuses me, and I'm not sure why we're + // adjusting DRs here. We've just recevied a join accept, and the + // datarate therefore shouldn't be in play. + // if( (LMIC.opmode & OP_REJOIN) != 0 ) { #if CFG_region != LMIC_REGION_as923 + // TODO(tmm@mcci.com) regionalize // Lower DR every try below current UP DR LMIC.datarate = lowerDR(LMIC.datarate, LMIC.rejoinCnt); #else diff --git a/src/lmic/lmic.h b/src/lmic/lmic.h index c4a6feeb..210fbd61 100644 --- a/src/lmic/lmic.h +++ b/src/lmic/lmic.h @@ -34,14 +34,20 @@ #include "oslmic.h" #include "lorabase.h" -#if LMIC_DEBUG_LEVEL > 0 +#if LMIC_DEBUG_LEVEL > 0 || LMIC_X_DEBUG_LEVEL > 0 # if defined(LMIC_DEBUG_INCLUDE) # define LMIC_STRINGIFY_(x) #x # define LMIC_STRINGIFY(x) LMIC_STRINGIFY_(x) # include LMIC_STRINGIFY(LMIC_DEBUG_INCLUDE) # endif +# ifdef LMIC_DEBUG_PRINTF_FN + extern void LMIC_DEBUG_PRINTF_FN(const char *f, ...); +# endif // ndef LMIC_DEBUG_PRINTF_FN +#endif + // if LMIC_DEBUG_PRINTF is now defined, just use it. This lets you do anything // you like with a sufficiently crazy header file. +#if LMIC_LEVEL_DEBUG > 0 # ifndef LMIC_DEBUG_PRINTF // otherwise, check whether someone configured a print-function to be used, // and use it if so. @@ -70,12 +76,14 @@ # define LMIC_DEBUG_FLUSH() do { ; } while (0) #endif // LMIC_DEBUG_LEVEL == 0 +// +// LMIC_X_DEBUG_LEVEL enables additional, special print functions for debugging +// RSSI features. This is used sparingly. #if LMIC_X_DEBUG_LEVEL > 0 # ifdef LMIC_DEBUG_PRINTF_FN - extern void LMIC_DEBUG_PRINTF_FN(const char *f, ...); # define LMIC_X_DEBUG_PRINTF(f, ...) LMIC_DEBUG_PRINTF_FN(f, ## __VA_ARGS__) # else -# error "LMIC_DEBUG_PRINTF_FN must be defined." +# error "LMIC_DEBUG_PRINTF_FN must be defined for LMIC_X_DEBUG_LEVEL > 0." # endif #else # define LMIC_X_DEBUG_PRINTF(f, ...) do {;} while(0) diff --git a/src/lmic/lmic_as923.c b/src/lmic/lmic_as923.c index 6b224bed..f0e0250b 100644 --- a/src/lmic/lmic_as923.c +++ b/src/lmic/lmic_as923.c @@ -184,7 +184,7 @@ void LMICas923_init(void) { // if this is japan, set LBT mode if (LMIC_COUNTRY_CODE == LMIC_COUNTRY_CODE_JP) { - LMIC.lbt_ticks = ms2osticks(AS923JP_LBT_5MS); + LMIC.lbt_ticks = us2osticks(AS923JP_LBT_US); LMIC.lbt_dbmax = AS923JP_LBT_DB_MAX; } } @@ -193,7 +193,7 @@ void LMICas923_resetDefaultChannels(void) { // if this is japan, set LBT mode if (LMIC_COUNTRY_CODE == LMIC_COUNTRY_CODE_JP) { - LMIC.lbt_ticks = ms2osticks(AS923JP_LBT_5MS); + LMIC.lbt_ticks = us2osticks(AS923JP_LBT_US); LMIC.lbt_dbmax = AS923JP_LBT_DB_MAX; } } diff --git a/src/lmic/lmic_eu_like.c b/src/lmic/lmic_eu_like.c index f5fdee0a..75349616 100644 --- a/src/lmic/lmic_eu_like.c +++ b/src/lmic/lmic_eu_like.c @@ -91,6 +91,16 @@ void LMICeulike_updateTx(ostime_t txbeg) { } #if !defined(DISABLE_JOIN) +// +// TODO(tmm@mcci.com): +// +// The definition of this is a little strange. this seems to return a time, but +// in reality it returns 0 if the caller should continue scanning through +// channels, and 1 if the caller has scanned all channels on this session, +// and therefore should reset to the beginning. The IBM 1.6 code is the +// same way, so apparently I just carried this across. We should declare +// as bool_t and change callers to use the result clearly as a flag. +// ostime_t LMICeulike_nextJoinState(uint8_t nDefaultChannels) { u1_t failed = 0; @@ -100,10 +110,17 @@ ostime_t LMICeulike_nextJoinState(uint8_t nDefaultChannels) { LMIC.txChnl = 0; if ((++LMIC.txCnt % nDefaultChannels) == 0) { // Lower DR every nth try (having all default channels with same DR) + // + // TODO(tmm@mcci.com) add new DR_REGIN_JOIN_MIN instead of LORAWAN_DR0; + // then we can eliminate the LMIC_REGION_as923 below because we'll set + // the failed flag here. This will cause the outer caller to take the + // appropriate join path. Or add new LMICeulike_GetLowestJoinDR() + // if (LMIC.datarate == LORAWAN_DR0) failed = 1; // we have tried all DR - signal EV_JOIN_FAILED else { +// TODO(tmm@mcci.com) - see above; please remove regional dependency from this file. #if CFG_region != LMIC_REGION_as923 LMICcore_setDrJoin(DRCHG_NOJACC, decDR((dr_t)LMIC.datarate)); #else @@ -118,12 +135,21 @@ ostime_t LMICeulike_nextJoinState(uint8_t nDefaultChannels) { // Move txend to randomize synchronized concurrent joins. // Duty cycle is based on txend. ostime_t const time = LMICbandplan_nextJoinTime(os_getTime()); + + // TODO(tmm@mcci.com): change delay to (0:1) secs + a known t0, but randomized; + // starting adding a bias after 1 hour, 25 hours, etc.; and limit the duty + // cycle on power up. For testability, add a way to set the join start time + // externally (a test API) so we can check this feature. + // See https://github.com/mcci-catena/arduino-lmic/issues/2 + // Current code doesn't match LoRaWAN 1.0.2 requirements. + LMIC.txend = time + (isTESTMODE() // Avoid collision with JOIN ACCEPT @ SF12 being sent by GW (but we missed it) ? DNW2_SAFETY_ZONE // Otherwise: randomize join (street lamp case): // SF12:255, SF11:127, .., SF7:8secs + // : DNW2_SAFETY_ZONE + LMICcore_rndDelay(255 >> LMIC.datarate)); // 1 - triggers EV_JOIN_FAILED event return failed; diff --git a/src/lmic/lmic_us_like.c b/src/lmic/lmic_us_like.c index abe77c5d..b31dcdb9 100644 --- a/src/lmic/lmic_us_like.c +++ b/src/lmic/lmic_us_like.c @@ -193,6 +193,16 @@ void LMICuslike_initJoinLoop(void) { #endif // !DISABLE_JOIN #if !defined(DISABLE_JOIN) +// +// TODO(tmm@mcci.com): +// +// The definition of this is a little strange. this seems to return a time, but +// in reality it returns 0 if the caller should continue scanning through +// channels, and 1 if the caller has scanned all channels on this session, +// and therefore should reset to the beginning. The IBM 1.6 code is the +// same way, so apparently I just carried this across. We should declare +// as bool_t and change callers to use the result clearly as a flag. +// ostime_t LMICuslike_nextJoinState(void) { // Try the following: // DR0 (SF10) on a random channel 0..63 @@ -227,6 +237,8 @@ ostime_t LMICuslike_nextJoinState(void) { // cycle on power up. For testability, add a way to set the join start time // externally (a test API) so we can check this feature. // See https://github.com/mcci-catena/arduino-lmic/issues/2 + // Current code doesn't match LoRaWAN 1.0.2 requirements. + LMIC.txend = os_getTime() + (isTESTMODE() // Avoid collision with JOIN ACCEPT being sent by GW (but we missed it - GW is still busy) diff --git a/src/lmic/lorabase_as923.h b/src/lmic/lorabase_as923.h index dae623a4..9cba8c45 100644 --- a/src/lmic/lorabase_as923.h +++ b/src/lmic/lorabase_as923.h @@ -74,12 +74,23 @@ enum { DR_PAGE_AS923 = 0x10 * (LMIC_REGION_as923 - 1) }; enum { AS923_LMIC_REGION_EIRP = 1 }; // region uses EIRP -enum { AS923JP_LBT_5MS = 5 }; // microseconds of LBT time -enum { AS923JP_LBT_DB_MAX = -80 }; // maximum channel strength +enum { AS923JP_LBT_US = 5000 }; // microseconds of LBT time -- 5000 ==> + // 5 ms. We use us rather than ms for + // future 128us support, and just for + // backward compatibility -- there + // is code that uses the _US constant, + // and it's awkward to break it. -#if !defined(AS923_TX_CAP) -// AS923 v1.1, all channels face a 1% duty cycle. -# define AS923_TX_CAP 100 +enum { AS923JP_LBT_DB_MAX = -80 }; // maximum channel strength in dB; if TX + // we measure more than this, we don't tx. + +// AS923 v1.1, all channels face a 1% duty cycle. So this will have to change +// in the future via a config. But this code base needs major changes for +// v1.1 in any case. +enum { AS923_V102_TX_CAP = 100 }; // v1.0.2 allows 100% + +#ifndef AS923_TX_CAP +# define AS923_TX_CAP AS923_V102_TX_CAP #endif #endif /* _lorabase_as923_h_ */ diff --git a/src/lmic/radio.c b/src/lmic/radio.c index 41ccb971..c43da5e6 100644 --- a/src/lmic/radio.c +++ b/src/lmic/radio.c @@ -25,10 +25,6 @@ * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. */ -#if LMIC_X_DEBUG_LEVEL > 0 -#include -#endif - #define LMIC_DR_LEGACY 0 #include "lmic.h"