kopia lustrzana https://github.com/pjalocha/esp32-ogn-tracker
Correct LoRaWAN timing
rodzic
9837f79c88
commit
c2380d81be
|
@ -23,8 +23,8 @@ class LoRaWANnode
|
|||
uint32_t JoinNonce; // from Join-Accept: unique must not be reused
|
||||
uint32_t HomeNetID; // from Join-Accept: Home Network ID
|
||||
uint32_t DevAddr; // from Join-Accept: Device Address
|
||||
uint8_t DLsetting; // from Join-Accept: DownLink configuration: OptNeg | RX1DRoffset | RX2 data rate
|
||||
uint8_t RxDelay; // from Join-Accept:
|
||||
uint8_t DLsetting; // from Join-Accept: DownLink configuration: OptNeg:1 | RX1 data rate offset:3 | RX2 data rate:4
|
||||
uint8_t RxDelay; // from Join-Accept: RFU:4 | Del:4 Del=1..15s for the RX1, RX2 delay is Del+1
|
||||
uint8_t State; // 0:disconencted, 1:join-request sent, 2:join-accept received, 3:uplink-packet sent
|
||||
uint8_t Chan; // [0..7] Current channel being used
|
||||
uint32_t UpCount; // [seq] Uplink frame counter: reset when joining the network
|
||||
|
@ -175,24 +175,26 @@ class LoRaWANnode
|
|||
{ int Len=getDataPacket(Packet, Data, DataLen, Port, Confirm); *Pkt = Packet; return Len; }
|
||||
|
||||
int procRxData(const RFM_LoRa_RxPacket &RxPacket)
|
||||
{ int Ret=procRxData(RxPacket.Byte, RxPacket.Len); if(Ret<0) return Ret;
|
||||
RxSNR += (RxPacket.SNR-RxSNR+1)/2;
|
||||
{ int Ret = procRxData(RxPacket.Byte, RxPacket.Len); if(Ret<0) return Ret;
|
||||
RxSNR += (RxPacket.SNR-RxSNR+1)/2; // if good packet then update the signal statistics
|
||||
RxRSSI += (RxPacket.RSSI-RxRSSI+1)/2;
|
||||
return Ret; }
|
||||
|
||||
int procRxData(const uint8_t *PktData, int PktLen)
|
||||
{ if(PktLen<12) return -1;
|
||||
uint8_t Type = PktData[0]>>5; if(Type!=3 && Type!=5) return -1;
|
||||
uint32_t Addr=readInt<uint32_t>(PktData+1, 4);
|
||||
if(Addr!=DevAddr) return 0;
|
||||
uint8_t Ctrl = PktData[5]; // Frame control: ADR | RFU | ACK | FPending | FOptLen[4]
|
||||
uint32_t Count=readInt<uint32_t>(PktData+6, 2);
|
||||
int16_t CountDiff = Count-DnCount; //
|
||||
if(CountDiff<=0) return -1; // attempt to reuse the counter: drop this packet
|
||||
uint8_t Type = PktData[0]>>5; if(Type!=3 && Type!=5) return -1; // Frame Type: 3=unconfirmed data downlink, 5=confirmed data downlink
|
||||
uint32_t Addr=readInt<uint32_t>(PktData+1, 4); // device address
|
||||
if(Addr!=DevAddr) return 0; // check if packet is for us (it could be for somebody else)
|
||||
uint8_t Ctrl = PktData[5]; // Frame Control: ADR | RFU | ACK | FPending | FOptLen[4]
|
||||
uint32_t Count = readInt<uint32_t>(PktData+6, 2); // download counter
|
||||
int16_t CountDiff = Count-DnCount; // how many we have missed ?
|
||||
if(CountDiff<=0) return -1; // attempt to reuse the counter: drop this packet
|
||||
uint32_t MIC=0;
|
||||
LoRaMacComputeMic(PktData, PktLen-4, NetSesKey, Addr, 0x01, Count, &MIC);
|
||||
if(memcmp(PktData+PktLen-4, &MIC, 4)) return -1; // give up if MIC does not match
|
||||
uint8_t DataOfs = 8 + (Ctrl&0x0F); // where the port byte should be
|
||||
uint8_t OptLen = Ctrl&0x0F; // Options: how many bytes
|
||||
uint8_t DataOfs = 8 + OptLen; // where the port byte should be
|
||||
if(OptLen) procRxOpt(PktData+8, OptLen); // process the options (these are not encrypted)
|
||||
uint8_t DataLen = PktLen-DataOfs-4; // number of bytes of the user data field
|
||||
if(DataLen) // if non-zero
|
||||
{ Packet[0] = PktData[DataOfs]; // copy port number
|
||||
|
@ -208,8 +210,20 @@ class LoRaWANnode
|
|||
if(Type==5) TxACK=1; // if ACK requested
|
||||
RxPend = Ctrl&0x10; // is there more data pending to be received on next round ?
|
||||
State=2;
|
||||
// if(DataLen==0)
|
||||
// { Packet[0]=0x00; DataLen++; // copy MAC commands to user buffer for debug
|
||||
// for(uint8_t Idx=0; Idx<OptLen; Idx++)
|
||||
// { Packet[DataLen++] = PktData[8+Idx]; }
|
||||
// }
|
||||
return DataLen; }
|
||||
|
||||
void procRxOpt(const uint8_t *Opt, uint8_t Len) // process the options
|
||||
{ }
|
||||
// { Format_String(CONS_UART_Write, "LoRaWAN Opt: ");
|
||||
// for(uint8_t Idx=0; Idx<Len; Idx++)
|
||||
// Format_Hex(CONS_UART_Write, Opt[Idx]);
|
||||
// Format_String(CONS_UART_Write, "\n"); }
|
||||
|
||||
#ifdef WITH_ESP32
|
||||
esp_err_t WriteToNVS(const char *Name="LoRaWAN", const char *NameSpace="TRACKER")
|
||||
{ nvs_handle Handle;
|
||||
|
|
55
main/rf.cpp
55
main/rf.cpp
|
@ -410,19 +410,20 @@ extern "C"
|
|||
if(WANdev.State==1 || WANdev.State==3) // if State indicates we are waiting for the response
|
||||
{ if(WAN_RespLeft<=5) WANdev.State--; // if time below 5 ticks we have not enough time
|
||||
else if(WAN_RespLeft<200) { WANrx=1; } // if more than 200ms then we can't wait this long now
|
||||
// xSemaphoreTake(CONS_Mutex, portMAX_DELAY);
|
||||
// Format_UnsDec(CONS_UART_Write, xTaskGetTickCount(), 4, 3);
|
||||
// Format_String(CONS_UART_Write, "s LoRaWAN Rx: ");
|
||||
// Format_SignDec(CONS_UART_Write, WAN_RespLeft);
|
||||
// Format_String(CONS_UART_Write, "ms\n");
|
||||
// xSemaphoreGive(CONS_Mutex);
|
||||
if(WANrx==0 && WAN_RespLeft<=5)
|
||||
{ xSemaphoreTake(CONS_Mutex, portMAX_DELAY);
|
||||
Format_UnsDec(CONS_UART_Write, xTaskGetTickCount(), 4, 3);
|
||||
Format_String(CONS_UART_Write, "s LoRaWAN missed Rx: ");
|
||||
Format_SignDec(CONS_UART_Write, WAN_RespLeft);
|
||||
Format_String(CONS_UART_Write, "ms\n");
|
||||
xSemaphoreGive(CONS_Mutex); }
|
||||
}
|
||||
|
||||
if(WANrx) // if reception expected from WAN
|
||||
{ int RxLen=0;
|
||||
TRX.setModeStandby(); // TRX to standby
|
||||
TRX.setModeStandby(); // TRX to standby
|
||||
TRX.setLoRa(); // switch to LoRa mode (through sleep)
|
||||
TRX.setModeLoRaStandby(); // TRX in standby
|
||||
TRX.setModeLoRaStandby(); // TRX in LoRa (not FSK) standby
|
||||
SetFreqPlanWAN(); // WAN frequency plan
|
||||
TRX.WAN_Configure(); // LoRa for WAN config.
|
||||
TRX.setChannel(WANdev.Chan); // set the channel
|
||||
|
@ -432,7 +433,7 @@ extern "C"
|
|||
for( ; Wait>0; Wait--)
|
||||
{ vTaskDelay(1);
|
||||
if(TRX.readIRQ()) break; } // IRQ signals packet reception
|
||||
if(Wait)
|
||||
if(Wait) // if no timeout thus a packet has been received.
|
||||
{ TRX.LoRa_ReceivePacket(WAN_RxPacket);
|
||||
xSemaphoreTake(CONS_Mutex, portMAX_DELAY);
|
||||
Format_UnsDec(CONS_UART_Write, xTaskGetTickCount(), 4, 3);
|
||||
|
@ -442,42 +443,42 @@ extern "C"
|
|||
Format_UnsDec(CONS_UART_Write, (unsigned)Wait);
|
||||
Format_String(CONS_UART_Write, "ms\n");
|
||||
xSemaphoreGive(CONS_Mutex);
|
||||
if(WANdev.State==1) WANdev.procJoinAccept(WAN_RxPacket); // if join-request state then expect a join-accept packet
|
||||
if(WANdev.State==1) WANdev.procJoinAccept(WAN_RxPacket); // if join-request state then expect a join-accept packet
|
||||
else if(WANdev.State==3) RxLen=WANdev.procRxData(WAN_RxPacket); // if data send then respect ACK and/or downlink data packet
|
||||
}
|
||||
else WANdev.State--;
|
||||
TRX.setFSK(); // back to FSK
|
||||
SetFreqPlanOGN(); // OGN frequency plan
|
||||
TRX.OGN_Configure(0, OGN_SYNC); // OGN config
|
||||
else WANdev.State--; // if no packet received then retreat the State
|
||||
TRX.setFSK(); // back to FSK
|
||||
SetFreqPlanOGN(); // OGN frequency plan
|
||||
TRX.OGN_Configure(0, OGN_SYNC); // OGN config
|
||||
SetRxChannel();
|
||||
TRX.setModeRX(); // switch to receive mode
|
||||
TRX.setModeRX(); // switch to receive mode
|
||||
TRX.ClearIrqFlags();
|
||||
WANdev.WriteToNVS(); // store new WAN state in flash
|
||||
if(RxLen>0) // if Downlink data received
|
||||
WANdev.WriteToNVS(); // store new WAN state in flash
|
||||
if(RxLen>0) // if Downlink data received
|
||||
{ xSemaphoreTake(CONS_Mutex, portMAX_DELAY);
|
||||
Format_String(CONS_UART_Write, "LoRaWAN Msg: ");
|
||||
// Format_UnsDec(CONS_UART_Write, (uint16_t)RxLen);
|
||||
// Format_String(CONS_UART_Write, "B");
|
||||
for(int Idx=0; Idx<RxLen; Idx++)
|
||||
{ Format_Hex(CONS_UART_Write, WANdev.Packet[Idx]); }
|
||||
{ Format_Hex(CONS_UART_Write, WANdev.Packet[Idx]); } //
|
||||
Format_String(CONS_UART_Write, "\n");
|
||||
xSemaphoreGive(CONS_Mutex); }
|
||||
}
|
||||
else
|
||||
else // if no WAN reception expected or possible
|
||||
#else // WITH_LORAWAN
|
||||
// if(TimeSync_msTime()<260);
|
||||
{ uint32_t RxRssiSum=0; uint16_t RxRssiCount=0; // measure the average RSSI for lower frequency
|
||||
{ uint32_t RxRssiSum=0; uint16_t RxRssiCount=0; // measure the average RSSI for lower frequency
|
||||
do
|
||||
{ ReceivePacket(); // keep checking for received packets
|
||||
{ ReceivePacket(); // keep checking for received packets
|
||||
#ifdef WITH_RFM69
|
||||
TRX.TriggerRSSI();
|
||||
#endif
|
||||
vTaskDelay(1);
|
||||
uint8_t RxRSSI=TRX.ReadRSSI(); // measure the channel noise level
|
||||
uint8_t RxRSSI=TRX.ReadRSSI(); // measure the channel noise level
|
||||
RX_Random = (RX_Random<<1) | (RxRSSI&1);
|
||||
RxRssiSum+=RxRSSI; RxRssiCount++;
|
||||
} while(TimeSync_msTime()<270); // until 300ms from the PPS
|
||||
RX_RSSI.Process(RxRssiSum/RxRssiCount); // [-0.5dBm] average noise on channel
|
||||
} while(TimeSync_msTime()<270); // until 300ms from the PPS
|
||||
RX_RSSI.Process(RxRssiSum/RxRssiCount); // [-0.5dBm] average noise on channel
|
||||
#ifdef DEBUG_PRINT
|
||||
xSemaphoreTake(CONS_Mutex, portMAX_DELAY);
|
||||
Format_String(CONS_UART_Write, "RSSI: ");
|
||||
|
@ -619,7 +620,7 @@ extern "C"
|
|||
if(WAN_BackOff) WAN_BackOff--;
|
||||
else if(Parameters.TxPower!=(-32)) // decide to transmit in this slot
|
||||
{ if(WANdev.State==0 || WANdev.State==2) //
|
||||
{ WANtx=1; SlotEnd=1200; }
|
||||
{ WANtx=1; SlotEnd=1220; }
|
||||
}
|
||||
TimeSlot(TxChan, SlotEnd-TimeSync_msTime(), TxPktData1, TRX.averRSSI, 0, TxTime);
|
||||
#else
|
||||
|
@ -697,7 +698,7 @@ extern "C"
|
|||
{ TxPktLen=WANdev.getDataPacket(&TxPacket, PktData+4, 16, 1, ((RX_Random>>16)&0xF)==0x8 ); }
|
||||
else
|
||||
{ TxPktLen=WANdev.getDataPacket(&TxPacket, PktData, 20, 1, ((RX_Random>>16)&0xF)==0x8 ); }
|
||||
TRX.LoRa_SendPacket(TxPacket, TxPktLen); RespDelay=1000;
|
||||
TRX.LoRa_SendPacket(TxPacket, TxPktLen); RespDelay = WANdev.RxDelay&0x0F; if(RespDelay<1) RespDelay=1; RespDelay*=1000;
|
||||
WAN_BackOff=50+(RX_Random%21); XorShift32(RX_Random); }
|
||||
}
|
||||
if(RespDelay)
|
||||
|
@ -706,7 +707,7 @@ extern "C"
|
|||
{ vTaskDelay(1); if(!TRX.isModeLoRaTX()) break; }
|
||||
// uint8_t Mode=TRX.ReadMode();
|
||||
// if(Mode!=RF_OPMODE_LORA_TX) break; }
|
||||
WAN_RespTick=xTaskGetTickCount()+RespDelay; // when to expect the response: 5sec after the end of Join-Request packet
|
||||
WAN_RespTick=xTaskGetTickCount()+RespDelay; // when to expect the response after the end of transmitted packet
|
||||
xSemaphoreTake(CONS_Mutex, portMAX_DELAY);
|
||||
Format_UnsDec(CONS_UART_Write, xTaskGetTickCount(), 4, 3);
|
||||
Format_String(CONS_UART_Write, "s LoRaWAN Tx: ");
|
||||
|
|
18
main/rfm.h
18
main/rfm.h
|
@ -243,12 +243,12 @@ SX1262 setup calls
|
|||
#ifdef WITH_SX1262
|
||||
#include "sx1262.h"
|
||||
|
||||
#define RF_IRQ_PacketSent 0x0001 // packet transmission was completed
|
||||
#define RF_IRQ_PayloadReady 0x0002 //
|
||||
#define RF_IRQ_PreambleDetect 0x0004 //
|
||||
#define RF_IRQ_SyncAddrMatch 0x0008 //
|
||||
#define RF_IRQ_CrcErr 0x0040 //
|
||||
#define RF_IRQ_Timeout 0x0200 //
|
||||
// #define RF_IRQ_PacketSent 0x0001 // packet transmission was completed
|
||||
// #define RF_IRQ_PayloadReady 0x0002 //
|
||||
// #define RF_IRQ_PreambleDetect 0x0004 //
|
||||
// #define RF_IRQ_SyncAddrMatch 0x0008 //
|
||||
// #define RF_IRQ_CrcErr 0x0040 //
|
||||
// #define RF_IRQ_Timeout 0x0200 //
|
||||
|
||||
#endif
|
||||
|
||||
|
@ -738,7 +738,6 @@ class RFM_TRX
|
|||
|
||||
void LoRa_Configure(RFM_LoRa_Config CFG, uint8_t MaxSize=64)
|
||||
{ setChannel(0);
|
||||
setDioMode(IRQ_TXDONE | IRQ_RXDONE);
|
||||
uint8_t Param[8];
|
||||
Param[0] = CFG.SF; // Spreading Factor
|
||||
Param[1] = CFG.BW-3; // work only for 62.5/125/256/512kHz
|
||||
|
@ -752,13 +751,13 @@ class RFM_TRX
|
|||
Param[4] = CFG.CRC; // check or not CRC
|
||||
Param[5] = CFG.InvIQ; // common flag for Tx/Rx
|
||||
Cmd_Write(CMD_SETPACKETPARAMS, Param, 6); // 0x8C, PacketParam
|
||||
setDioMode( /* IRQ_TXDONE | */ IRQ_RXDONE);
|
||||
Param[0] = (CFG.SYNC&0xF0) | 0x04;
|
||||
Param[1] = (CFG.SYNC<<4) | 0x04;
|
||||
Regs_Write(REG_LORASYNCWORD, Param, 2); }
|
||||
|
||||
void OGN_Configure(int16_t Channel, const uint8_t *SyncData)
|
||||
{ setChannel(Channel);
|
||||
setDioMode(IRQ_TXDONE | IRQ_RXDONE);
|
||||
uint8_t Param[12];
|
||||
Pack3bytes(Param, 10240); // data bitrate = 32*Xtal/100e3 for OGN 100kbps
|
||||
Param[3] = 0x09; // 0x00:no filter, 0x08:BT=0.3, 0x09:BT=0.5, 0x0A:BT=0.7, 0x0B:BT=1.0
|
||||
|
@ -775,11 +774,11 @@ class RFM_TRX
|
|||
Param[7] = 0x01; // no CRC
|
||||
Param[8] = 0x00; // no whitening
|
||||
Cmd_Write(CMD_SETPACKETPARAMS, Param, 9); // 0x8C, PacketParam
|
||||
setDioMode(/* IRQ_TXDONE | */ IRQ_RXDONE);
|
||||
Regs_Write(REG_SYNCWORD0, SyncData, 8); } // Write the SYNC word
|
||||
|
||||
void PAW_Configure(const uint8_t *Sync)
|
||||
{ setFrequency(869525000);
|
||||
setDioMode(IRQ_TXDONE | IRQ_RXDONE);
|
||||
uint8_t Param[12];
|
||||
Pack3bytes(Param, 26667); // data bitrate = 32*Xtal/38.4e3 for PAW 38.4kbps
|
||||
Param[3] = 0x09; // 0x00:no filter, 0x08:BT=0.3, 0x09:BT=0.5, 0x0A:BT=0.7, 0x0B:BT=1.0
|
||||
|
@ -796,6 +795,7 @@ class RFM_TRX
|
|||
Param[7] = 0x01; // no CRC
|
||||
Param[8] = 0x00; // no whitening
|
||||
Cmd_Write(CMD_SETPACKETPARAMS, Param, 9); // 0x8C, PacketParam
|
||||
setDioMode( /* IRQ_TXDONE | */ IRQ_RXDONE);
|
||||
Regs_Write(REG_SYNCWORD0, Sync, 8); } // Write the SYNC word
|
||||
|
||||
void ClearIrqFlags(uint16_t Mask=IRQ_ALL) { uint8_t Data[2]; Data[0]=Mask>>8; Data[1]=Mask; Cmd_Write(CMD_CLEARIRQSTATUS, Data, 2); }
|
||||
|
|
Ładowanie…
Reference in New Issue