LoRaWAN code can join and send positions, proof of concept, far from stable

pull/30/head
Pawel Jalocha 2020-10-09 14:08:50 +01:00
rodzic 38d8ecaf22
commit e9caf1f353
12 zmienionych plików z 224 dodań i 63 usunięć

Wyświetl plik

@ -42,6 +42,10 @@
#include <stdint.h>
#ifdef __cplusplus
extern "C" {
#endif
/*!
* Computes the LoRaMAC frame MIC field
*
@ -124,4 +128,8 @@ void LoRaMacBeaconComputePingOffset( uint64_t beaconTime, uint32_t address, uint
/*! \} defgroup LORAMAC */
#ifdef __cplusplus
} // extern "C"
#endif
#endif // __LORAMAC_CRYPTO_H__

Wyświetl plik

@ -25,7 +25,7 @@
#include "disp_lcd.h"
#ifdef WITH_U8G2_OLED
const uint8_t DISP_Pages = 11;
const uint8_t DISP_Pages = 12;
static uint8_t DISP_Page = 0;
#endif
#if defined(WITH_ST7789) || defined(WITH_ILI9341)
@ -191,7 +191,8 @@ void vTaskDISP(void* pvParameters)
case 7: OLED_DrawRelay (&U8G2_OLED, GPS); break;
case 8: OLED_DrawLookout (&U8G2_OLED, GPS); break;
case 9: OLED_DrawTrafWarn (&U8G2_OLED, GPS); break;
case 10: OLED_DrawLoRaWAN (&U8G2_OLED, GPS); break;
case 10: OLED_DrawFlight (&U8G2_OLED, GPS); break;
case 11: OLED_DrawLoRaWAN (&U8G2_OLED, GPS); break;
}
}
//if ( DISP_Page != 6 )

Wyświetl plik

@ -815,6 +815,12 @@ void OLED_DrawAltitudeAndSpeed(u8g2_t *OLED, GPS_Position *GPS)
u8g2_DrawXBM(OLED, 118, 47, kmh_width, kmh_height, kmh_bits);
}
void OLED_DrawFlight(u8g2_t *OLED, GPS_Position *GPS) // draw flight status page
{ u8g2_SetFont(OLED, u8g2_font_7x13_tf);
u8g2_DrawStr(OLED, 0, 28, "Flight");
}
void OLED_DrawLoRaWAN(u8g2_t *OLED, GPS_Position *GPS) // draw LoRaWAN status page
{
u8g2_SetFont(OLED, u8g2_font_7x13_tf);
@ -822,13 +828,25 @@ void OLED_DrawLoRaWAN(u8g2_t *OLED, GPS_Position *GPS) // draw LoRaWAN status pa
u8g2_DrawStr(OLED, 0, 28, "LoRaWAN: -OFF-");
#endif
#ifdef WITH_LORAWAN
const char *StateName[3] = { "Idle", "Join-Req", "Joined" } ;
const char *StateName[4] = { "Not-Joined", "Join-Req", "+Joined+", "PktSend" } ;
int Len=Format_String(Line, "LoRaWAN: ");
if(WANdev.State<=2) Len+=Format_String(Line+Len, StateName[WANdev.State]);
if(WANdev.State<=3) Len+=Format_String(Line+Len, StateName[WANdev.State]);
else Len+=Format_Hex(Line+Len, WANdev.State);
Line[Len]=0;
u8g2_DrawStr(OLED, 0, 24, Line);
Len =Format_String(Line , "Up: "); Len+=Format_Hex(Line+Len, (uint16_t)WANdev.UpCount);
Len+=Format_String(Line+Len, " Dn: "); Len+=Format_Hex(Line+Len, (uint16_t)WANdev.DnCount);
Line[Len]=0;
u8g2_DrawStr(OLED, 0, 36, Line);
// if(WANdev.State>=2) { }
/*
Len=0;
for(int Idx=0; Idx<16; Idx++)
{ Len+=Format_Hex(Line+Len, WANdev.AppKey[Idx]); }
Line[Len]=0;
u8g2_SetFont(OLED, u8g2_font_5x8_tr);
u8g2_DrawStr(OLED, 0, 48, Line);
*/
#endif // WITH_LORAWAN
}

Wyświetl plik

@ -23,5 +23,6 @@ void OLED_DrawStatusBar(u8g2_t *OLED, GPS_Position *GPS=0);
void OLED_DrawSystem (u8g2_t *OLED, GPS_Position *GPS=0);
void OLED_DrawID (u8g2_t *OLED, GPS_Position *GPS=0);
void OLED_DrawAltitudeAndSpeed(u8g2_t *OLED, GPS_Position *GPS=0);
void OLED_DrawFlight (u8g2_t *OLED, GPS_Position *GPS=0);
void OLED_DrawLoRaWAN (u8g2_t *OLED, GPS_Position *GPS=0);
#endif

Wyświetl plik

@ -33,11 +33,14 @@ uint8_t Format_String(char *Out, const char *String, uint8_t MinLen, uint8_t Max
uint8_t Format_UnsDec (char *Out, uint32_t Value, uint8_t MinDigits=1, uint8_t DecPoint=0);
uint8_t Format_SignDec(char *Out, int32_t Value, uint8_t MinDigits=1, uint8_t DecPoint=0, uint8_t NoPlus=0);
uint8_t Format_Hex( char *Output, uint8_t Byte );
uint8_t Format_Hex( char *Output, uint16_t Word );
uint8_t Format_Hex( char *Output, uint32_t Word );
uint8_t Format_Hex( char *Output, uint32_t Word, uint8_t Digits);
uint8_t Format_Hex( char *Output, uint64_t Word );
uint8_t Format_Hex(char *Output, uint8_t Byte );
uint8_t Format_Hex(char *Output, uint16_t Word );
uint8_t Format_Hex(char *Output, uint32_t Word );
uint8_t Format_Hex(char *Output, uint32_t Word, uint8_t Digits);
uint8_t Format_Hex(char *Output, uint64_t Word );
// uint8_t Format_Hex(char *Output, const uint8_t *Bytes, uint8_t Len );
// uint8_t Format_Hex( char *Output, uint64_t Word, uint8_t Digits);
template <class Type>

Wyświetl plik

@ -919,6 +919,8 @@ void RFM_RESET(uint8_t On) { }
void RFM_IRQ_SetInput(void) { gpio_set_direction(PIN_RFM_IRQ, GPIO_MODE_INPUT); }
bool RFM_IRQ_isOn(void) { return gpio_get_level(PIN_RFM_IRQ); }
void RFM_Delay(int ms) { vTaskDelay(ms); }
static spi_device_handle_t RFM_SPI;
void RFM_TransferBlock(uint8_t *Data, uint8_t Len)

Wyświetl plik

@ -94,6 +94,7 @@ void AERO_UART_SetBaudrate(int BaudRate);
void RFM_TransferBlock(uint8_t *Data, uint8_t Len);
void RFM_RESET(uint8_t On); // RF module reset
bool RFM_IRQ_isOn(void); // query the IRQ state
void RFM_Delay(int ms); // [ms] idle delay
#ifdef WITH_OLED
int OLED_DisplayON(uint8_t ON, uint8_t DispIdx=0); // when OFF then low-power mode

Wyświetl plik

@ -25,7 +25,7 @@ class LoRaWANnode
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 State; // 0:disconencted, 1:join-request sent, 2:join-accept received
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
uint32_t DnCount; // [seq] Downlink frame counter: reset when joining the network
@ -105,9 +105,10 @@ class LoRaWANnode
int getJoinRequest(uint8_t *Req)
{ Req[0] = 0x00; // MHDR, Join-Request: 000 000 00
memcpy(Req+1, &AppEUI, 8); //
memcpy(Req+9, &DevEUI, 8);
Req[17] = DevNonce;
memcpy(Req+1, &AppEUI, 8); // AppEUI
memcpy(Req+9, &DevEUI, 8); // DevEUI
DevNonce++; // increment DevNonce for a new request
Req[17] = DevNonce; // DevNonce
Req[18] = DevNonce>>8;
uint32_t MIC=0;
LoRaMacJoinComputeMic(Req, 19, AppKey, &MIC); // compute MIC
@ -123,7 +124,7 @@ class LoRaWANnode
RxRSSI = RxPacket.RSSI;
return Ret; }
int procJoinAccept(const uint8_t *PktData, int PktLen)
int procJoinAccept(const uint8_t *PktData, int PktLen) // process Join-Accept packet (5sec after Join-Request)
{ if(PktLen<13) return -1;
uint8_t Type = PktData[0]>>5; if(Type!=1) return -1;
Packet[0] = PktData[0];
@ -137,7 +138,7 @@ class LoRaWANnode
DevAddr = readInt<uint32_t>(Packet+7, 4);
DLsetting = Packet[11];
RxDelay = Packet[12];
State = 2; // State = accepted on network
State = 2; // State = accepted on network
UpCount = 0;
DnCount = 0;
#ifdef WITH_PRINTF
@ -151,23 +152,21 @@ class LoRaWANnode
return 0; }
int getDataPacket(uint8_t *Packet, const uint8_t *Data, int DataLen, uint8_t Port=1, bool Confirm=0)
{ uint8_t Type = Confirm?0x04:0x02;
{ if(State<2) return 0; // not joined to the network yet
uint8_t Type = Confirm?0x04:0x02; // request confirmation or not ?
int PktLen=0;
Packet[PktLen++] = Type<<5; // packet-type
PktLen+=writeInt(Packet+PktLen, DevAddr, 4); // Device Address
uint8_t Ctrl=0;
if(TxACK) { Ctrl|=0x20; TxACK=0; }
uint8_t Ctrl=0; // Frame Control
if(TxACK) { Ctrl|=0x20; TxACK=0; } // if there is ACK to be transmitted
Packet[PktLen++] = Ctrl; // Frame Control: ADR | ADR-ACK-Req | ACK | ClassB | FOptsLen[4]
PktLen+=writeInt(Packet+PktLen, UpCount, 2); // uplink frame counter
Packet[PktLen++] = Port; // port
LoRaMacPayloadEncrypt(Data, DataLen, AppSesKey, DevAddr, 0, UpCount, Packet+PktLen); PktLen+=DataLen; // copy+encrypt user data
uint32_t MIC=0;
LoRaMacComputeMic(Packet, PktLen, NetSesKey, DevAddr, 0x00, UpCount, &MIC); // calc. MIC
// uint8_t MIC2[4];
// Tiny.Calculate_MIC(Packet, MIC2, PktLen, UpCount, 0x00);
// printf("Data packet MIC: %08X <=> %02X%02X%02X%02X\n", MIC, MIC2[3], MIC2[2], MIC2[1], MIC2[0]);
memcpy(Packet+PktLen, &MIC, 4); PktLen+=4; // append MIC
UpCount++; return PktLen; }
UpCount++; State=3; return PktLen; } // return the packet size
int getDataPacket(uint8_t **Pkt, const uint8_t *Data, int DataLen, uint8_t Port=1, bool Confirm=0)
{ int Len=getDataPacket(Packet, Data, DataLen, Port, Confirm); *Pkt = Packet; return Len; }
@ -185,17 +184,11 @@ class LoRaWANnode
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);
// Count |= DnCount&0xFFFF0000;
int16_t CountDiff = Count-DnCount; //
if(CountDiff<=0) return -1; // attempt to reuse the counter: drop this packet
// if(Diff<=(-0x4000)) Count+=0x10000;
// else if(Diff>0x4000) Count-=0x10000;
// printf("RxData: %08X\n", Count);
uint32_t MIC=0;
LoRaMacComputeMic(PktData, PktLen-4, NetSesKey, Addr, 0x01, Count, &MIC);
// printf("RxData: %08X\n", MIC);
if(memcmp(PktData+PktLen-4, &MIC, 4)) return -1; // give up if MIC does not match
// if(Count==DnCount) return 0;
uint8_t DataOfs = 8 + (Ctrl&0x0F); // where the port byte should be
uint8_t DataLen = PktLen-DataOfs-4; // number of bytes of the user data field
if(DataLen) // if non-zero
@ -211,6 +204,7 @@ class LoRaWANnode
if(Ctrl&0x40) RxACK=1; // we got ACK to our ACK request
if(Type==5) TxACK=1; // if ACK requested
RxPend = Ctrl&0x10; // is there more data pending to be received on next round ?
State=2;
return DataLen; }
#ifdef WITH_ESP32

Wyświetl plik

@ -46,12 +46,6 @@ void app_main(void)
Parameters.setDefault(getUniqueAddress()); // set default parameter values
if(Parameters.ReadFromNVS()!=ESP_OK) // try to get parameters from NVS
{ Parameters.WriteToNVS(); } // if did not work: try to save (default) parameters to NVS
#ifdef WITH_LORAWAN
WANdev.Reset(getUniqueID(), Parameters.AppKey);
if(WANdev.ReadFromNVS()!=ESP_OK)
{ WANdev.WriteToNVS(); }
if(memcpy(WANdev.AppKey, Parameters.AppKey, 16)) WANdev.Reset(getUniqueID(), Parameters.AppKey);
#endif
#ifdef WITH_SPIFFS
SPIFFS_Register(); // initialize the file system in the Flash
@ -68,6 +62,14 @@ void app_main(void)
// #endif
}
#endif
#ifdef WITH_LORAWAN
WANdev.Reset(getUniqueID(), Parameters.AppKey); // set default LoRaWAN config.
if(WANdev.ReadFromNVS()!=ESP_OK) // if can't read the LoRaWAN setup from NVS
{ WANdev.WriteToNVS(); } // then store the default
// if(memcmp(WANdev.AppKey, Parameters.AppKey, 16)) // if LoRaWAN key different from the one in Parameters
// { WANdev.Reset(getUniqueID(), Parameters.AppKey); // then reset LoRaWAN to this key
// WANdev.WriteToNVS(); } // and save LoRaWAN config. to NVS
#endif
CONS_UART_SetBaudrate(Parameters.CONbaud);
@ -92,7 +94,7 @@ void app_main(void)
xTaskCreate(vTaskLOG , "LOG", 4096, 0, tskIDLE_PRIORITY+1, 0);
#endif
xTaskCreate(vTaskRF, "RF", 2048, 0, tskIDLE_PRIORITY+4, 0);
xTaskCreate(vTaskRF, "RF", 2048, 0, tskIDLE_PRIORITY+5, 0);
xTaskCreate(vTaskPROC, "PROC", 2048, 0, tskIDLE_PRIORITY+3, 0);
xTaskCreate(vTaskGPS, "GPS", 2048, 0, tskIDLE_PRIORITY+4, 0);
@ -107,7 +109,7 @@ void app_main(void)
xTaskCreate(vTaskKNOB, "KNOB", 2048, 0, tskIDLE_PRIORITY+3, 0);
#endif
#ifdef WITH_AERO
xTaskCreate(vTaskAERO, "AERO", 2048, 0, tskIDLE_PRIORITY+4, 0);
xTaskCreate(vTaskAERO, "AERO", 2048, 0, tskIDLE_PRIORITY+3, 0);
#endif
#ifdef WITH_WIFI
xTaskCreate(vTaskWIFI, "WIFI", 4096, 0, tskIDLE_PRIORITY+2, 0);

Wyświetl plik

@ -518,11 +518,12 @@ class FlashParameters
Verbose=Mode; return 1; }
#ifdef WITH_LORAWAN
if(strcmp(Name, "AppKey")==0)
{ for( uint8_t Idx=0; Idx<16; Idx++)
{ for(uint8_t Idx=0; Idx<16; Idx++)
{ uint8_t Byte;
uint8_t Len=Read_Hex(Byte, Value);
if(Len!=2) break;
AppKey[Idx]=Byte; }
AppKey[Idx]=Byte;
Value+=2; }
return 1; }
#endif
#ifdef WITH_ENCRYPT

Wyświetl plik

@ -159,11 +159,15 @@ static void TimeSlot(uint8_t TxChan, uint32_t SlotLen, const uint8_t *PacketByte
ReceiveUntil(End); // listen till the end of the time-slot
}
static void SetFreqPlan(void) // set the RF TRX according to the selected frequency hopping plan
static void SetFreqPlanOGN(void) // set the RF TRX according to the selected frequency hopping plan
{ TRX.setBaseFrequency(RF_FreqPlan.BaseFreq); // set the base frequency (recalculate to RFM69 internal synth. units)
TRX.setChannelSpacing(RF_FreqPlan.ChanSepar); // set the channel separation
TRX.setFrequencyCorrection(Parameters.RFchipFreqCorr); // set the fine correction (to counter the Xtal error)
}
TRX.setFrequencyCorrection(Parameters.RFchipFreqCorr); } // set the fine correction (to counter the Xtal error)
static void SetFreqPlanWAN(void) // set the LoRaWAN EU frequency plan: 8 LoRa channels
{ TRX.setBaseFrequency(867100000);
TRX.setChannelSpacing( 200000);
TRX.setFrequencyCorrection(Parameters.RFchipFreqCorr); }
static uint8_t StartRFchip(void)
{ TRX.WriteMode(RF_OPMODE_STANDBY);
@ -172,7 +176,7 @@ static uint8_t StartRFchip(void)
vTaskDelay(1); // wait 10ms
TRX.RESET(0); // RESET released
vTaskDelay(5); // wait 10ms
SetFreqPlan(); // set TRX base frequency and channel separation after the frequency hopping plan
SetFreqPlanOGN(); // set TRX base frequency and channel separation after the frequency hopping plan
#ifdef DEBUG_PRINT
xSemaphoreTake(CONS_Mutex, portMAX_DELAY);
TRX.PrintReg(CONS_UART_Write);
@ -200,6 +204,11 @@ static uint8_t StartRFchip(void)
#endif
return Version; } // read the RF chip version and return it
static TickType_t WAN_RespTick = xTaskGetTickCount(); // when to expect the WAN response
static RFM_LoRa_RxPacket WAN_RxPacket; // packet received from WAN
// static WAN_Setup()
// static WAN_Back()
extern "C"
void vTaskRF(void* pvParameters)
{
@ -213,12 +222,13 @@ extern "C"
#ifdef USE_BLOCK_SPI
TRX.TransferBlock = RFM_TransferBlock;
#else
TRX.Select = RFM_Select;
TRX.Deselect = RFM_Deselect;
TRX.TransferByte = RFM_TransferByte;
TRX.Select = RFM_Select; // [call]
TRX.Deselect = RFM_Deselect; // [call]
TRX.TransferByte = RFM_TransferByte; // [call]
#endif
TRX.DIO0_isOn = RFM_IRQ_isOn;
TRX.RESET = RFM_RESET;
TRX.DIO0_isOn = RFM_IRQ_isOn; // [call] read IRQrfm_reset
TRX.Delay_ms = RFM_Delay; // [call] delay by N miliseconds
TRX.RESET = RFM_RESET; // [call] chip reset control
RF_FreqPlan.setPlan(Parameters.FreqPlan); // 1 = Europe/Africa, 2 = USA/CA, 3 = Australia and South America
@ -256,18 +266,73 @@ extern "C"
// RF_Print();
// #endif
uint32_t RxRssiSum=0; uint16_t RxRssiCount=0; // measure the average RSSI for lower frequency
do
{ ReceivePacket(); // keep checking for received packets
#ifdef WITH_LORAWAN
bool WANrx=0;
int WAN_RespLeft = WAN_RespTick-xTaskGetTickCount();
if(WANdev.State==1 || WANdev.State==3)
{ if(WAN_RespLeft<=5) WANdev.State--;
else if(WAN_RespLeft<200) { WANrx=1; }
xSemaphoreTake(CONS_Mutex, portMAX_DELAY);
Format_String(CONS_UART_Write, "LoRaWAN Rx: ");
Format_SignDec(CONS_UART_Write, WAN_RespLeft);
Format_String(CONS_UART_Write, "ms ");
Format_UnsDec(CONS_UART_Write, xTaskGetTickCount());
Format_String(CONS_UART_Write, "ms\n");
xSemaphoreGive(CONS_Mutex);
}
if(WANrx)
{ TRX.WriteMode(RF_OPMODE_STANDBY); // TRX to standby
TRX.setLoRa(); // switch to LoRa mode (through sleep)
TRX.WriteMode(RF_OPMODE_LORA_STANDBY); // TRX in standby
SetFreqPlanWAN(); // WAN frequency plan
TRX.WAN_Configure(); // LoRa for WAN config.
TRX.setChannel(WANdev.Chan); // set the channel
TRX.LoRa_InvertIQ(1); TRX.LoRa_setCRC(0); TRX.LoRa_setIRQ(0); // setup for WAN RX
TRX.WriteMode(RF_OPMODE_LORA_RX_SINGLE); // wait for a single packet
int Wait=WAN_RespLeft+100;
for( ; Wait>0; Wait--)
{ vTaskDelay(1);
if(TRX.readIRQ()) break; }
if(Wait)
{ TRX.LoRa_ReceivePacket(WAN_RxPacket);
xSemaphoreTake(CONS_Mutex, portMAX_DELAY);
Format_String(CONS_UART_Write, "LoRaWAN Rx: ");
Format_UnsDec(CONS_UART_Write, (uint16_t)WAN_RxPacket.Len);
Format_String(CONS_UART_Write, "B/");
Format_UnsDec(CONS_UART_Write, (unsigned)Wait);
Format_String(CONS_UART_Write, "ms ");
Format_UnsDec(CONS_UART_Write, xTaskGetTickCount());
Format_String(CONS_UART_Write, "ms\n");
xSemaphoreGive(CONS_Mutex);
if(WANdev.State==1) WANdev.procJoinAccept(WAN_RxPacket);
else if(WANdev.State==3) WANdev.procRxData(WAN_RxPacket);
}
else WANdev.State--;
WANdev.WriteToNVS();
TRX.setFSK(); // back to FSK
SetFreqPlanOGN(); // OGN frequency plan
TRX.OGN_Configure(0, OGN_SYNC); // OGN config
SetRxChannel();
TRX.WriteMode(RF_OPMODE_RECEIVER); // switch to receive mode
}
else
#else
// if(TimeSync_msTime()<260);
{ uint32_t RxRssiSum=0; uint16_t RxRssiCount=0; // measure the average RSSI for lower frequency
do
{ ReceivePacket(); // keep checking for received packets
#ifdef WITH_RFM69
TRX.TriggerRSSI();
TRX.TriggerRSSI();
#endif
vTaskDelay(1);
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
}
#endif
vTaskDelay(1);
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
TRX.WriteMode(RF_OPMODE_STANDBY); // switch to standy
vTaskDelay(1);
@ -279,7 +344,7 @@ extern "C"
TRX.WriteMode(RF_OPMODE_STANDBY);
vTaskDelay(1); }
SetFreqPlan();
SetFreqPlanOGN();
TRX.averRSSI=RX_RSSI.getOutput();
@ -307,7 +372,7 @@ extern "C"
TRX.WriteMode(RF_OPMODE_RECEIVER); // switch to receive mode
vTaskDelay(1);
RxRssiSum=0; RxRssiCount=0; // measure the average RSSI for the upper frequency
uint32_t RxRssiSum=0; uint16_t RxRssiCount=0; // measure the average RSSI for the upper frequency
do
{ ReceivePacket(); // check for packets being received ?
#ifdef WITH_RFM69
@ -349,6 +414,7 @@ extern "C"
{ TRX.setLoRa(); // switch TRX to LoRa
TRX.FNT_Configure();
// TRX.setChannel(0); // configure for FANET
TRX.WriteTxPower(Parameters.getTxPower());
TRX.WriteMode(RF_OPMODE_LORA_RX_CONT);
vTaskDelay(2);
for(uint8_t Wait=50; Wait; Wait--)
@ -389,9 +455,65 @@ extern "C"
TRX.WriteMode(RF_OPMODE_RECEIVER); // switch to receive mode
XorShift32(RX_Random);
TxTime = (RX_Random&0x3F)+1; TxTime*=6;
TxTime = (RX_Random&0x3F)+1; TxTime*=6; // [ms] (1..64)*6 = 6..384ms
#ifdef WITH_LORAWAN
bool WANtx = 0; // decide if send Join-Request
uint16_t SlotEnd = 1240;
if(WANdev.State==0 || WANdev.State==2)
{ XorShift32(RX_Random); if((RX_Random&0x3F)==0x20) WANtx=1; SlotEnd=1200; }
TimeSlot(TxChan, SlotEnd-TimeSync_msTime(), TxPktData1, TRX.averRSSI, 0, TxTime);
#else
TimeSlot(TxChan, 1250-TimeSync_msTime(), TxPktData1, TRX.averRSSI, 0, TxTime);
#endif
#ifdef WITH_LORAWAN
if(WANtx)
{ TRX.WriteMode(RF_OPMODE_STANDBY); // TRX to standby
TRX.setLoRa(); // switch to LoRa mode (through sleep)
TRX.WriteMode(RF_OPMODE_LORA_STANDBY); // TRX in standby
SetFreqPlanWAN(); // WAN frequency plan
TRX.WAN_Configure(); // LoRa for WAN config.
XorShift32(RX_Random); // random
WANdev.Chan = RX_Random&7; // choose random channel
TRX.setChannel(WANdev.Chan); // set the channel
TRX.LoRa_InvertIQ(0); TRX.LoRa_setCRC(1); // setup for WAN TX
TRX.WriteTxPower(Parameters.getTxPower()); // transmit power
int RespDelay=0;
int TxPktLen=0;
if(WANdev.State==0)
{ uint8_t *TxPacket; int TxPktLen=WANdev.getJoinRequest(&TxPacket); // produce Join-Request packet
TRX.LoRa_SendPacket(TxPacket, TxPktLen); RespDelay=5000; // transmit join-request packet
} else if(WANdev.State==2)
{ const uint8_t *PktData=TxPktData0;
if(PktData==0) PktData=TxPktData1;
if(PktData)
{ ((OGN1_Packet *)PktData)->Dewhiten();
uint8_t *TxPacket;
TxPktLen=WANdev.getDataPacket(&TxPacket, PktData, 20, 1, ((RX_Random>>16)&0xF)==0x8 );
TRX.LoRa_SendPacket(TxPacket, TxPktLen); RespDelay=1000; }
}
if(RespDelay)
{ vTaskDelay(8);
for( uint8_t Wait=100; Wait; Wait--) // wait for the end of transmission
{ vTaskDelay(1);
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
xSemaphoreTake(CONS_Mutex, portMAX_DELAY);
Format_String(CONS_UART_Write, "LoRaWAN Tx: ");
Format_UnsDec(CONS_UART_Write, (unsigned)TxPktLen);
Format_String(CONS_UART_Write, "B ");
Format_UnsDec(CONS_UART_Write, xTaskGetTickCount());
Format_String(CONS_UART_Write, "ms\n");
xSemaphoreGive(CONS_Mutex);
}
TRX.setFSK(); // back to FSK
SetFreqPlanOGN(); // OGN frequency plan
TRX.OGN_Configure(0, OGN_SYNC); // OGN config
SetRxChannel();
TRX.WriteMode(RF_OPMODE_RECEIVER); // switch to receive mode
}
#endif
if(TxPkt0) RF_TxFIFO.Read();
if(TxPkt1) RF_TxFIFO.Read();

Wyświetl plik

@ -47,6 +47,7 @@ class RFM_LoRa_Config
} ;
const RFM_LoRa_Config RFM_FNTcfg { 0xF1587190 } ; // LoRa seting for FANET
const RFM_LoRa_Config RFM_WANcfg { 0x34877190 } ; // LoRa WAN setting for TX
class RFM_LoRa_RxPacket
{ public:
@ -246,6 +247,8 @@ class RFM_TRX
// bool (*DIO4_isOn)(void);
void (*RESET)(uint8_t On); // activate or desactivate the RF chip reset
bool readIRQ(void) { return (*DIO0_isOn)(); }
// the following are in units of the synthesizer with 8 extra bits of precision
uint32_t BaseFrequency; // [32MHz/2^19/2^8] base frequency = channel #0
// int32_t FrequencyCorrection; // [32MHz/2^19/2^8] frequency correction (due to Xtal offset)
@ -613,6 +616,11 @@ class RFM_TRX
RFM_LoRa_Config CFG = RFM_FNTcfg; CFG.CR=CR;
return LoRa_Configure(CFG, FANET_Packet::MaxBytes); }
int WAN_Configure(uint8_t CR=1) // configure for FANET/LoRa
{ WriteTxPower(0);
RFM_LoRa_Config CFG = RFM_WANcfg; CFG.CR=CR;
return LoRa_Configure(CFG, 40); }
void LoRa_setIRQ(uint8_t Mode=0) // 0:on RX, 1:on TX, 2: on CAD
{ WriteByte(Mode<<6, REG_DIOMAPPING1); }
@ -662,7 +670,7 @@ class RFM_TRX
Packet.FreqOfs = (FreqOfs*1718+0x8000)>>16; // [10Hz]
Packet.BitErr = 0;
Packet.CodeErr = 0;
int Len=LoRa_ReceivePacket(Packet.Byte, Packet.MaxBytes);
int Len=LoRa_ReceivePacket(Packet.Byte, Packet.MaxBytes); // read packet data
// printf("ReceivePacketFNT() => %d %02X %3.1fdB %+ddBm 0x%08X=%+6.3fkHz, %02X%02X%02X%02X\n",
// Packet.Len, Stat, 0.25*Packet.SNR, Packet.RSSI, FreqOfs, 0.5*0x1000000/32e9*FreqOfs,
// Packet.Byte[0], Packet.Byte[1], Packet.Byte[2], Packet.Byte[3]);