diff --git a/src/LMIC-node.cpp b/src/LMIC-node.cpp index 4753748..a146151 100644 --- a/src/LMIC-node.cpp +++ b/src/LMIC-node.cpp @@ -98,36 +98,57 @@ int16_t getSnrTenfold() { // Returns ten times the SNR (dB) value of the last received packet. // Ten times to prevent the use of float but keep 1 decimal digit accuracy. - // Calculation per SX1276 datasheet (Rev.6) 6.4. + // Calculation per SX1276 datasheet rev.7 §6.4, SX1276 datasheet rev.4 §6.4. // LMIC.snr contains value of PacketSnr, which is 4 times the actual SNR value. return (LMIC.snr * 10) / 4; } -int16_t getRssi(int16_t snr) +int16_t getRssi(int8_t snr) { // Returns correct RSSI (dBm) value of the last received packet. - // Calculation per SX1276 datasheet (Rev.6) 5.5.5. - // Correct calculation of RSSI depends on whether the HF or LF port is used. - // Note: Below code assumes that only HF port is used and only SX1276 is used (not SX1272) - // if not then the values will be less reliable. + // Calculation per SX1276 datasheet rev.7 §5.5.5, SX1272 datasheet rev.4 §5.5.5. - const int16_t rssiOffset = -157; // For HF port use -157, for LF port use -164. - - // LMIC.rssi contains modified value of PacketRssi. - // Revert modification (applied in lmic/radio.c) to get PacketRssi. - // (Purpose of modification is unclear and the magic numbers seem undocumented.) - int16_t packetRssi = LMIC.rssi + 125 - 64; + #define RSSI_OFFSET 64 + #define SX1276_FREQ_LF_MAX 525000000 // per datasheet 6.3 + #define SX1272_RSSI_ADJUST -139 + #define SX1276_RSSI_ADJUST_LF -164 + #define SX1276_RSSI_ADJUST_HF -157 int16_t rssi; - if (snr < 0) - { - rssi = rssiOffset + packetRssi + snr; - } - else - { - rssi = rssiOffset + (16 / 15.0 * packetRssi); - } + + #ifdef MCCI_LMIC + + rssi = LMIC.rssi - RSSI_OFFSET; + + #else + int16_t rssiAdjust; + #ifdef CFG_sx1276_radio + if (LMIC.freq > SX1276_FREQ_LF_MAX) + { + rssiAdjust = SX1276_RSSI_ADJUST_HF; + } + else + { + rssiAdjust = SX1276_RSSI_ADJUST_LF; + } + #else + // CFG_sx1272_radio + rssiAdjust = SX1272_RSSI_ADJUST; + #endif + + // Revert modification (applied in lmic/radio.c) to get PacketRssi. + int16_t packetRssi = LMIC.rssi + 125 - RSSI_OFFSET; + if (snr < 0) + { + rssi = rssiAdjust + packetRssi + snr; + } + else + { + rssi = rssiAdjust + (16 * packetRssi) / 15; + } + #endif + return rssi; } @@ -142,7 +163,7 @@ void printEvent(ostime_t timestamp, if (target == PrintTarget::All || target == PrintTarget::Display) { display.clearLine(TIME_ROW); - display.setCursor(0, TIME_ROW); + display.setCursor(COL_0, TIME_ROW); display.print(F("Time:")); display.print(timestamp); display.clearLine(EVENT_ROW); @@ -150,7 +171,7 @@ void printEvent(ostime_t timestamp, { display.clearLine(STATUS_ROW); } - display.setCursor(0, EVENT_ROW); + display.setCursor(COL_0, EVENT_ROW); display.print(message); } #endif @@ -179,7 +200,9 @@ void printEvent(ostime_t timestamp, void printEvent(ostime_t timestamp, ev_t ev, PrintTarget target = PrintTarget::All, bool clearDisplayStatusRow = true) { - printEvent(timestamp, lmicEventNames[ev], target, clearDisplayStatusRow, true); + #if defined(USE_DISPLAY) || defined(USE_SERIAL) + printEvent(timestamp, lmicEventNames[ev], target, clearDisplayStatusRow, true); + #endif } @@ -189,7 +212,7 @@ void printFrameCounters(PrintTarget target = PrintTarget::All) if (target == PrintTarget::Display || target == PrintTarget::All) { display.clearLine(FRMCNTRS_ROW); - display.setCursor(0, FRMCNTRS_ROW); + display.setCursor(COL_0, FRMCNTRS_ROW); display.print(F("Up:")); display.print(LMIC.seqnoUp); display.print(F(" Dn:")); @@ -201,9 +224,9 @@ void printFrameCounters(PrintTarget target = PrintTarget::All) if (target == PrintTarget::Serial || target == PrintTarget::All) { printSpaces(serial, MESSAGE_INDENT); - serial.print(F("Up#: ")); + serial.print(F("Up: ")); serial.print(LMIC.seqnoUp); - serial.print(F(", Dn#: ")); + serial.print(F(", Down: ")); serial.println(LMIC.seqnoDn); } #endif @@ -247,8 +270,8 @@ void printDownlinkInfo() // bool ackReceived = LMIC.txrxFlags & TXRX_ACK; int16_t snrTenfold = getSnrTenfold(); - int16_t snr = snrTenfold / 10; - int16_t snrDecimalFraction = snrTenfold % 10; + int8_t snr = snrTenfold / 10; + int8_t snrDecimalFraction = snrTenfold % 10; int16_t rssi = getRssi(snr); uint8_t fPort = 0; @@ -259,7 +282,7 @@ void printDownlinkInfo() #ifdef USE_DISPLAY display.clearLine(EVENT_ROW); - display.setCursor(0, EVENT_ROW); + display.setCursor(COL_0, EVENT_ROW); display.print(F("RX P:")); display.print(fPort); if (dataLength != 0) @@ -268,7 +291,7 @@ void printDownlinkInfo() display.print(LMIC.dataLen); } display.clearLine(STATUS_ROW); - display.setCursor(0, STATUS_ROW); + display.setCursor(COL_0, STATUS_ROW); display.print(F("RSSI")); display.print(rssi); display.print(F(" SNR")); @@ -312,14 +335,16 @@ void printHeader(void) { #ifdef USE_DISPLAY display.clear(); - display.setCursor(0, HEADER_ROW); + display.setCursor(COL_0, HEADER_ROW); display.print(F("LMIC-node")); - // OTAA is default so is not shown here #ifdef ABP_ACTIVATION - display.print(F(" ABP")); - #endif - display.drawString(0, DEVICEID_ROW, deviceId); - display.setCursor(0, INTERVAL_ROW); + display.drawString(ABPMODE_COL, HEADER_ROW, "ABP"); + #endif + #ifdef CLASSIC_LMIC + display.drawString(CLMICSYMBOL_COL, HEADER_ROW, "*"); + #endif + display.drawString(COL_0, DEVICEID_ROW, deviceId); + display.setCursor(COL_0, INTERVAL_ROW); display.print(F("Interval:")); display.print(doWorkIntervalSeconds); display.print("s"); @@ -327,17 +352,27 @@ void printHeader(void) #ifdef USE_SERIAL serial.println(F("\n\nLMIC-node\n")); - serial.print(F("Device-id: ")); + serial.print(F("Device-id: ")); serial.println(deviceId); - serial.print(F("Activation: ")); + serial.print(F("LMIC library: ")); + #ifdef MCCI_LMIC + serial.println(F("MCCI")); + #else + serial.println(F("Classic [Deprecated]")); + #endif + serial.print(F("Activation: ")); #ifdef OTAA_ACTIVATION serial.println(F("OTAA")); #else serial.println(F("ABP")); #endif - serial.print(F("Interval: ")); - serial.print(doWorkIntervalSeconds); - serial.println(F(" seconds")); + #if defined(LMIC_DEBUG_LEVEL) && LMIC_DEBUG_LEVEL > 0 + serial.print(F("LMIC debug: ")); + serial.println(LMIC_DEBUG_LEVEL); + #endif + serial.print(F("Interval: ")); + serial.print(doWorkIntervalSeconds); + serial.println(F(" seconds")); #endif } @@ -463,7 +498,7 @@ void initLmic() { LMIC_setClockError(clockError); #ifdef USE_SERIAL - serial.print(F("\nClock Error: ")); + serial.print(F("Clock Error: ")); serial.print(LMIC_CLOCK_ERROR_PPM); serial.print(" ppm ("); serial.print(clockError); @@ -661,6 +696,7 @@ void processWork(ostime_t doWorkJobTimeStamp) // The counter is increased automatically by getCounterValue() // and can be reset with a 'reset counter' command downlink message. + // Collect input data uint16_t counterValue = getCounterValue(); ostime_t timestamp = os_getTime(); @@ -669,7 +705,7 @@ void processWork(ostime_t doWorkJobTimeStamp) // This allows to keep the 3rd row empty which makes the // information better readable on the small display. display.clearLine(INTERVAL_ROW); - display.setCursor(0, INTERVAL_ROW); + display.setCursor(COL_0, INTERVAL_ROW); display.print("I:"); display.print(doWorkIntervalSeconds); display.print("s"); @@ -677,7 +713,7 @@ void processWork(ostime_t doWorkJobTimeStamp) display.print(counterValue); #endif #ifdef USE_SERIAL - printEvent(timestamp, "Data read", PrintTarget::Serial); + printEvent(timestamp, "Input data collected", PrintTarget::Serial); printSpaces(serial, MESSAGE_INDENT); serial.print(F("COUNTER value: ")); serial.println(counterValue); @@ -767,7 +803,7 @@ void setup() #endif #ifdef USE_DISPLAY // Following mesage shown only if failure was unrelated to I2C. - display.setCursor(0, FRMCNTRS_ROW); + display.setCursor(COL_0, FRMCNTRS_ROW); display.print(F("HW init failed")); #endif abort(); diff --git a/src/LMIC-node.h b/src/LMIC-node.h index 8cd93be..4d21aaa 100644 --- a/src/LMIC-node.h +++ b/src/LMIC-node.h @@ -61,59 +61,28 @@ void processDownlink(ostime_t eventTimestamp, uint8_t fPort, uint8_t* data, uint #define CLASSIC_LMIC #endif -// Determine if a valid region is defined. -// This actually has little effect because -// CLASSIC LMIC: defines CFG_eu868 by default, -// MCCI LMIC: if no region is defined it -// sets CFG_eu868 as default. -#if ( \ - ( defined(CLASSIC_LMIC) \ - && !( defined(CFG_eu868) \ - || defined(CFG_us915) ) ) \ - || \ - ( defined(MCCI_LMIC) \ - && !( defined(CFG_as923) \ - || defined(CFG_as923jp) \ - || defined(CFG_au915) \ - || defined(CFG_eu868) \ - || defined(CFG_in866) \ - || defined(CFG_kr920) \ - || defined(CFG_us915) ) ) \ -) - #Error No valid region defined -#endif - -#include BSFILE // Include Board Support File -#include "../keyfiles/lorawan-keys.h" - -#ifdef OTAA_ACTIVATION - #if !defined(OTAA_DEVEUI) || !defined(OTAA_APPEUI) || !defined(OTAA_APPKEY) - #error One or more LoRaWAN keys (OTAA_DEVEUI, OTAA_APPEUI, OTAA_APPKEY) are not defined. - #endif -#else - // ABP activation - #if !defined(ABP_DEVADDR) || !defined(ABP_NWKSKEY) || !defined(ABP_APPSKEY) - #error One or more LoRaWAN keys (ABP_DEVADDR, ABP_NWKSKEY, ABP_APPSKEY) are not defined. - #endif +#if !defined(ABP_ACTIVATION) && !defined(OTAA_ACTIVATION) + #define OTAA_ACTIVATION #endif + +#include BSFILE // Include Board Support File +#include "../keyfiles/lorawan-keys.h" + + #if defined(LMIC_DEBUG_LEVEL) && LMIC_DEBUG_LEVEL > 0 - #ifdef LMIC_PRINTF_TO - #undef LMIC_PRINTF_TO + // Do not overrule if already defined + #ifndef LMIC_PRINTF_TO + #define LMIC_PRINTF_TO serial #endif - #define LMIC_PRINTF_TO serial #endif #if defined(ABP_ACTIVATION) && defined(OTAA_ACTIVATION) #error Only one of ABP_ACTIVATION and OTAA_ACTIVATION can be defined. #endif -#if !defined(ABP_ACTIVATION) && !defined(OTAA_ACTIVATION) - #define OTAA_ACTIVATION -#endif - -#if defined(ABP_ACTIVATION) && defined(DEVICEID_ABP) - const char deviceId[] = DEVICEID_ABP; +#if defined(ABP_ACTIVATION) && defined(ABP_DEVICEID) + const char deviceId[] = ABP_DEVICEID; #elif defined(DEVICEID) const char deviceId[] = DEVICEID; #else @@ -134,6 +103,44 @@ void processDownlink(ostime_t eventTimestamp, uint8_t fPort, uint8_t* data, uint #define WAITFOR_SERIAL_S 0 #endif +#if defined(ABP_ACTIVATION) && defined(CLASSIC_LMIC) + #error Do NOT use ABP activation when using the deprecated IBM LMIC framework library. \ + On The Things Network V3 this will cause a downlink message for EACH uplink message \ + because it does properly handle MAC commands. +#endif + +#ifdef OTAA_ACTIVATION + #if !defined(OTAA_DEVEUI) || !defined(OTAA_APPEUI) || !defined(OTAA_APPKEY) + #error One or more LoRaWAN keys (OTAA_DEVEUI, OTAA_APPEUI, OTAA_APPKEY) are not defined. + #endif +#else + // ABP activation + #if !defined(ABP_DEVADDR) || !defined(ABP_NWKSKEY) || !defined(ABP_APPSKEY) + #error One or more LoRaWAN keys (ABP_DEVADDR, ABP_NWKSKEY, ABP_APPSKEY) are not defined. + #endif +#endif + +// Determine if a valid region is defined. +// This actually has little effect because +// CLASSIC LMIC: defines CFG_eu868 by default, +// MCCI LMIC: if no region is defined it +// sets CFG_eu868 as default. +#if ( \ + ( defined(CLASSIC_LMIC) \ + && !( defined(CFG_eu868) \ + || defined(CFG_us915) ) ) \ + || \ + ( defined(MCCI_LMIC) \ + && !( defined(CFG_as923) \ + || defined(CFG_as923jp) \ + || defined(CFG_au915) \ + || defined(CFG_eu868) \ + || defined(CFG_in866) \ + || defined(CFG_kr920) \ + || defined(CFG_us915) ) ) \ +) + #Error No valid LoRaWAN region defined +#endif #ifndef LMIC_MCCI #define LMIC_ERROR_SUCCESS 0 @@ -217,19 +224,25 @@ void processDownlink(ostime_t eventTimestamp, uint8_t fPort, uint8_t* data, uint #ifdef USE_DISPLAY uint8_t transmitSymbol[8] = {0x18, 0x18, 0x00, 0x24, 0x99, 0x42, 0x3c, 0x00}; - #define LAST_COL 15 - #define HEADER_ROW 0 - #define DEVICEID_ROW 1 - #define INTERVAL_ROW 2 - #define TIME_ROW 4 - #define EVENT_ROW 5 - #define STATUS_ROW 6 - #define FRMCNTRS_ROW 7 - #define ROW_0 0 - #define ROW_1 1 - #define ROW_2 2 - #define ROW_3 3 - #define ROW_4 4 + #define ROW_0 0 + #define ROW_1 1 + #define ROW_2 2 + #define ROW_3 3 + #define ROW_4 4 + #define ROW_5 5 + #define ROW_6 6 + #define ROW_7 7 + #define HEADER_ROW ROW_0 + #define DEVICEID_ROW ROW_1 + #define INTERVAL_ROW ROW_2 + #define TIME_ROW ROW_4 + #define EVENT_ROW ROW_5 + #define STATUS_ROW ROW_6 + #define FRMCNTRS_ROW ROW_7 + #define COL_0 0 + #define ABPMODE_COL 10 + #define CLMICSYMBOL_COL 14 + #define TXSYMBOL_COL 15 void initDisplay() { @@ -241,11 +254,11 @@ void processDownlink(ostime_t eventTimestamp, uint8_t fPort, uint8_t* data, uint { if (visible) { - display.drawTile(LAST_COL, ROW_0, 1, transmitSymbol); + display.drawTile(TXSYMBOL_COL, ROW_0, 1, transmitSymbol); } else { - display.drawGlyph(LAST_COL, ROW_0, char(0x20)); + display.drawGlyph(TXSYMBOL_COL, ROW_0, char(0x20)); } } #endif // USE_DISPLAY