kopia lustrzana https://github.com/pjalocha/esp32-ogn-tracker
LoRaWAN code can join and send positions, proof of concept, far from stable
rodzic
38d8ecaf22
commit
e9caf1f353
|
@ -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__
|
||||
|
|
|
@ -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 )
|
||||
|
|
|
@ -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
|
||||
}
|
||||
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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>
|
||||
|
|
|
@ -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)
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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);
|
||||
|
|
|
@ -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
|
||||
|
|
168
main/rf.cpp
168
main/rf.cpp
|
@ -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();
|
||||
|
|
10
main/rfm.h
10
main/rfm.h
|
@ -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]);
|
||||
|
|
Ładowanie…
Reference in New Issue