Skip to content

Commit 502cdfb

Browse files
committed
Fix inconsistent LoRaConfig 42 results (#23387)
1 parent 75b109c commit 502cdfb

File tree

3 files changed

+247
-218
lines changed

3 files changed

+247
-218
lines changed

tasmota/tasmota_xdrv_driver/xdrv_73_0_lora_struct.ino

Lines changed: 13 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -24,7 +24,7 @@
2424

2525
// AU915 value
2626
#ifndef TAS_LORA_AU915_FREQUENCY
27-
#define TAS_LORA_AU915_FREQUENCY 915.0 // Allowed values range from 150.0 to 960.0 MHz
27+
#define TAS_LORA_AU915_FREQUENCY 915.2 // Allowed values range from 150.0 to 960.0 MHz
2828
#endif
2929

3030
// EU868 value
@@ -206,6 +206,12 @@ enum TasLoraWanCIDNode {
206206
TAS_LORAWAN_CID_DEVICE_TIME_REQ
207207
};
208208

209+
enum LoRaWanRadioMode_t {
210+
TAS_LORAWAN_RADIO_UPLINK,
211+
TAS_LORAWAN_RADIO_RX1,
212+
TAS_LORAWAN_RADIO_RX2
213+
};
214+
209215
enum TasLoraRegion {
210216
TAS_LORA_REGION_EU868, // 0
211217
TAS_LORA_REGION_US915, // 1
@@ -224,6 +230,12 @@ const char kLoraRegions[] PROGMEM = "EU868|US915|CN779|EU433|AU915|CN470|AS923|K
224230

225231
/*********************************************************************************************/
226232

233+
typedef struct LoRaWanRadioInfo_t {
234+
float frequency;
235+
float bandwidth;
236+
uint8_t spreading_factor;
237+
} LoRaWanRadioInfo_t;
238+
227239
typedef struct LoraNodeData_t {
228240
float rssi;
229241
float snr;

tasmota/tasmota_xdrv_driver/xdrv_73_8_lorawan_bridge.ino

Lines changed: 223 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -63,6 +63,191 @@
6363
* LoRaWanBridge 1
6464
\*********************************************************************************************/
6565

66+
/*
67+
For LoraWan EU bands, the Uplink/Downlink (TX/RX) frequencies can be the same.
68+
For Others, same Uplink/Downlink (TX/RX) frequencies may not be allowed.
69+
See: https://lora-alliance.org/wp-content/uploads/2020/11/RP_2-1.0.2.pdf
70+
*/
71+
72+
// Determines the channel from the current Uplink LoraSettings
73+
// return 0..71
74+
uint32_t LoraWanChannel(void) {
75+
float fFrequencyDiff;
76+
uint8_t uChannel = 0;
77+
78+
switch (Lora->settings.region) {
79+
case TAS_LORA_REGION_AU915:
80+
if (125.0 == Lora->settings.bandwidth) {
81+
fFrequencyDiff = Lora->settings.frequency - TAS_LORAWAN_AU915_FREQUENCY_UP1;
82+
uChannel = (0.01 + (fFrequencyDiff / 0.2)); // 0.01 to fix rounding errors
83+
} else {
84+
fFrequencyDiff = Lora->settings.frequency - TAS_LORAWAN_AU915_FREQUENCY_UP2;
85+
uChannel = 64 + ((0.01 + (fFrequencyDiff / 1.6)));
86+
}
87+
break;
88+
89+
//default:
90+
//not implemented
91+
}
92+
return uChannel;
93+
}
94+
95+
/*****************************************************************************
96+
LoraWanRadioInfo()
97+
Some regional profiles use different radio profiles for the Uplink, RX1, and RX2 transmissions
98+
99+
Get radio profiles for the Uplink, and RX1 & RX2 downlink transmissions
100+
RX1 & RX2 profiles are derived from Lora->settings
101+
102+
****************************************************************************/
103+
const uint8_t RX1DRs[] PROGMEM = {8,9,10,11,12,13,13}; // DR0..6
104+
const uint8_t SF[] PROGMEM = {12,11,10,9,8,7,8,0,12,11,10,9,8,7}; // DR0..13
105+
106+
void LoraWanRadioInfo(uint8_t mode, void* pInfo) {
107+
LoRaWanRadioInfo_t* pResult = (LoRaWanRadioInfo_t*) pInfo;
108+
109+
switch (Lora->settings.region) {
110+
case TAS_LORA_REGION_AU915: {
111+
//////////////// AU915 ////////////////////
112+
/* ref: https://lora-alliance.org/wp-content/uploads/2020/11/RP_2-1.0.2.pdf page 47
113+
DR0 LoRa: SF12 / 125 kHz
114+
DR1 LoRa: SF11 / 125 kHz
115+
DR2 LoRa: SF10 / 125 kHz <-- JOIN REQUEST
116+
DR3 LoRa: SF9 / 125 kHz
117+
DR4 LoRa: SF8 / 125 kHz
118+
DR5 LoRa: SF7 / 125 kHz
119+
DR6 LoRa: SF8 / 500 kHz Same as DR12
120+
DR7 LR-FHSS CR1/3: 1.523 MHz OCW 162
121+
DR8 LoRa: SF12 / 500 kHz
122+
DR9 LoRa: SF11 / 500 kHz
123+
DR10 LoRa: SF10 / 500 kHz
124+
DR11 LoRa: SF9 / 500 kHz
125+
DR12 LoRa: SF8 / 500 kHz Same as DR6
126+
DR13 LoRa: SF7 / 500 kHz
127+
128+
UPLINK (RX) CHANNELS
129+
There are 72 channels
130+
0-63: DR0 to 5. Starting 915.2, incrementing by 0.2 Mhz to 927.8 <-- JOIN REQUEST
131+
64-71: DR6 . Starting 915.9, incrementing by 1.6 MHz to 927.1
132+
NOTE: Testing with two Dragino end devices shows they do not play nice with channels 64-71
133+
1) LHT52 will JOIN OK on Ch64, but never sends any sensor messages on same channel
134+
2) LHT65 will not even broadcast JOIN requests on any of the channels (as required by RP002)
135+
For this reason, channels above 63 are not permitted.
136+
137+
DOWNLINK (TX) CHANNELS
138+
There are 8 channels
139+
0-7: DR8 to 13. Starting 923.3, incrementing by 0.6 MHz to 927.5
140+
141+
After an uplink: Downlink (TX) link subchannel = Uplink (RX) Channel Number modulo 8
142+
e.g. --Uplink (RX)-- --Downlink (TX)--
143+
Freq Channel Channel Frequency
144+
915.2 0 0 923.3
145+
927.8 63 7 927.1
146+
147+
After an uplink:
148+
Downlink DR for RX1 must follow this table
149+
Uplink Downlink
150+
DR0 DR8
151+
DR1 DR8
152+
DR2 DR10 <----- channels 1-62
153+
DR3 DR11
154+
DR4 DR12
155+
DR5 DR13
156+
DR6 DR13 <------ channels 63-71
157+
158+
Downlink DR for RX2 must be DR8
159+
160+
Downlink
161+
Reference: https://lora-alliance.org/wp-content/uploads/2020/11/lorawan_regional_parameters_v1.0.3reva_0.pdf)
162+
Assume this is in response to an uplink RX, so we already know RX freq & bw & sf
163+
TX channel depends on RX freq
164+
DR for RX1 depends on incoming DR (and RX1DROffset)
165+
DR for RX2 is fixed ar DR8
166+
167+
Tasmota does not support different RX1 & RX2 DRs (yet), so just use DR8 and rely on RX2 arriving at end device OK.
168+
*/
169+
uint32_t uChannel = LoraWanChannel();
170+
uint8_t UplinkChannelBand = uChannel %8; //0..7
171+
switch (mode) {
172+
case TAS_LORAWAN_RADIO_UPLINK: {
173+
// if (uChannel > 71) uChannel = 71; See note above
174+
if (uChannel > 63) uChannel = 63;
175+
if (uChannel < 64) {
176+
(*pResult).frequency = TAS_LORAWAN_AU915_FREQUENCY_UP1 + (uChannel * 0.2);
177+
(*pResult).bandwidth = TAS_LORAWAN_AU915_BANDWIDTH_UP1; // DR2
178+
(*pResult).spreading_factor = TAS_LORAWAN_AU915_SPREADING_FACTOR_UP1; // DR2
179+
} else {
180+
(*pResult).frequency = TAS_LORAWAN_AU915_FREQUENCY_UP2 + ((uChannel-64) * 1.6);
181+
(*pResult).bandwidth = TAS_LORAWAN_AU915_BANDWIDTH_UP2; // DR6
182+
(*pResult).spreading_factor = TAS_LORAWAN_AU915_SPREADING_FACTOR_UP2; // DR6
183+
}
184+
break;
185+
}
186+
case TAS_LORAWAN_RADIO_RX1: {
187+
// RX1 DR depends on the Uplink settings
188+
// https://lora-alliance.org/wp-content/uploads/2020/11/lorawan_regional_parameters_v1.0.3reva_0.pdf
189+
// Page 41
190+
uint32_t UplinkDR = (125.0 == Lora->settings.bandwidth) ? (12 - Lora->settings.spreading_factor) : 6; // 0 .. 6
191+
uint32_t RX1DR = pgm_read_byte(&RX1DRs[UplinkDR]);
192+
uint32_t RX1SF = pgm_read_byte(&SF[RX1DR]);
193+
float RX1BW = (RX1DR > 5) ? 500.0 : 125.0;
194+
(*pResult).frequency = TAS_LORAWAN_AU915_FREQUENCY_DN + (UplinkChannelBand * 0.6);
195+
(*pResult).bandwidth = RX1BW;
196+
(*pResult).spreading_factor = RX1SF;
197+
break;
198+
}
199+
case TAS_LORAWAN_RADIO_RX2: {
200+
(*pResult).frequency = TAS_LORAWAN_AU915_FREQUENCY_DN;
201+
(*pResult).bandwidth = TAS_LORAWAN_AU915_BANDWIDTH_RX2;
202+
(*pResult).spreading_factor = TAS_LORAWAN_AU915_SPREADING_FACTOR_RX2;
203+
break;
204+
}
205+
// default:
206+
// not implemented
207+
}
208+
break;
209+
}
210+
default: { // TAS_LORA_REGION_EU868
211+
//Default TX/RX1/TX1 same
212+
(*pResult).frequency = TAS_LORAWAN_FREQUENCY;
213+
(*pResult).bandwidth = TAS_LORAWAN_BANDWIDTH;
214+
(*pResult).spreading_factor = TAS_LORAWAN_SPREADING_FACTOR;
215+
}
216+
}
217+
}
218+
219+
bool LoraWanDefaults(uint32_t region = TAS_LORA_REGION_EU868, LoRaWanRadioMode_t mode = TAS_LORAWAN_RADIO_UPLINK) {
220+
bool multi_profile = false;
221+
Lora->settings.region = region;
222+
switch (region) {
223+
case TAS_LORA_REGION_AU915:
224+
// TO DO: Need 3 profiles: Uplink, RX1, RX2
225+
// Works OK for now as RX2 always received by end device.
226+
multi_profile = true;
227+
if ((Lora->settings.frequency < 915.2) || (Lora->settings.frequency > 927.8)) {
228+
Lora->settings.frequency = TAS_LORAWAN_AU915_FREQUENCY_UP1;
229+
}
230+
LoRaWanRadioInfo_t RadioInfo;
231+
LoraWanRadioInfo(mode, &RadioInfo); // Region specific
232+
Lora->settings.frequency = RadioInfo.frequency;
233+
Lora->settings.bandwidth = RadioInfo.bandwidth;
234+
Lora->settings.spreading_factor = RadioInfo.spreading_factor;
235+
break;
236+
default: // TAS_LORA_REGION_EU868
237+
Lora->settings.frequency = TAS_LORAWAN_FREQUENCY;
238+
Lora->settings.bandwidth = TAS_LORAWAN_BANDWIDTH;
239+
Lora->settings.spreading_factor = TAS_LORAWAN_SPREADING_FACTOR;
240+
}
241+
Lora->settings.coding_rate = TAS_LORAWAN_CODING_RATE;
242+
Lora->settings.sync_word = TAS_LORAWAN_SYNC_WORD;
243+
Lora->settings.output_power = TAS_LORAWAN_OUTPUT_POWER;
244+
Lora->settings.preamble_length = TAS_LORAWAN_PREAMBLE_LENGTH;
245+
Lora->settings.current_limit = TAS_LORAWAN_CURRENT_LIMIT;
246+
Lora->settings.implicit_header = TAS_LORAWAN_HEADER;
247+
Lora->settings.crc_bytes = TAS_LORAWAN_CRC_BYTES;
248+
return multi_profile;
249+
}
250+
66251
/*********************************************************************************************\
67252
* Driver Settings load and save
68253
\*********************************************************************************************/
@@ -146,6 +331,41 @@ void LoraWanDeleteData(void) {
146331
#include <Ticker.h>
147332
Ticker LoraWan_Send;
148333

334+
void LoraWanSend(uint8_t* data, uint32_t len, bool uplink_profile) {
335+
LoraSettings_t RXsettings;
336+
if (uplink_profile) {
337+
// Different TX/RX profiles allowed. (e.g. LoRaWAN)
338+
// For CmndLoraSend() ... do not allow changes.
339+
RXsettings = Lora->settings; // Make a copy;
340+
LoraWanDefaults(Lora->settings.region, TAS_LORAWAN_RADIO_RX2); // Set Downlink profile TO DO: Support different RX1 & RX2 profiles
341+
Lora->Config();
342+
}
343+
LoraSend(data, len, true);
344+
if (uplink_profile) {
345+
Lora->settings = RXsettings; // Restore copy
346+
Lora->Config();
347+
}
348+
}
349+
350+
void LoraWanTickerSend(void) {
351+
Lora->send_buffer_step--;
352+
if (1 == Lora->send_buffer_step) {
353+
Lora->rx = true; // Always send during RX1
354+
Lora->receive_time = 0; // Reset receive timer
355+
LoraWan_Send.once_ms(TAS_LORAWAN_RECEIVE_DELAY2, LoraWanTickerSend); // Retry after 1000 ms
356+
}
357+
358+
bool uplink_profile = (Lora->settings.region == TAS_LORA_REGION_AU915);
359+
if (Lora->rx) { // If received in RX1 do not resend in RX2
360+
LoraWanSend(Lora->send_buffer, Lora->send_buffer_len, uplink_profile);
361+
}
362+
363+
if (uplink_profile && (0 == Lora->send_buffer_step)) {
364+
Lora->Init(); // Necessary to re-init the SXxxxx chip in cases where TX/RX frequencies differ
365+
}
366+
}
367+
368+
/*
149369
void LoraWanTickerSend(void) {
150370
Lora->send_buffer_step--;
151371
if (1 == Lora->send_buffer_step) {
@@ -162,6 +382,7 @@ void LoraWanTickerSend(void) {
162382
Lora->Init(); // Necessary to re-init the SXxxxx chip in cases where TX/RX frequencies differ
163383
}
164384
}
385+
*/
165386

166387
void LoraWanSendResponse(uint8_t* buffer, size_t len, uint32_t lorawan_delay) {
167388
free(Lora->send_buffer); // Free previous buffer (if any)
@@ -184,7 +405,7 @@ size_t LoraWanCFList(uint8_t * CFList, size_t uLen) {
184405
case TAS_LORA_REGION_AU915: {
185406
if (uLen < 16) return 0;
186407

187-
uint8_t uChannel = LoraChannel(); // 0..71
408+
uint8_t uChannel = LoraWanChannel(); // 0..71
188409
uint8_t uMaskByte = uChannel /8; // 0..8
189410

190411
// Add first 10 bytes
@@ -279,7 +500,7 @@ void LoraWanSendLinkADRReq(uint32_t node) {
279500
case TAS_LORA_REGION_AU915: {
280501
//Ref: https://lora-alliance.org/wp-content/uploads/2020/11/lorawan_regional_parameters_v1.0.3reva_0.pdf
281502
// page 39
282-
uint8_t uChannel = LoraChannel(); // 0..71
503+
uint8_t uChannel = LoraWanChannel(); // 0..71
283504
uint8_t ChMaskCntl = uChannel/16.0; // 0..4
284505
uChannel = uChannel%16; // 0..15
285506
uint16_t uMask = 0x01 << uChannel;

0 commit comments

Comments
 (0)