diff --git a/main/flight.h b/main/flight.h index 51dbcf9..0bc1a1f 100644 --- a/main/flight.h +++ b/main/flight.h @@ -12,8 +12,8 @@ class FlightMonitor GPS_Position MaxAltitude; // est. positon at peak altitude // GPS_Position Recent; // const char *IGCpath; - static const uint8_t MinHold = 5; // [sec] minimum hold time before takeoff declared - static const uint16_t MinSpeed = 60; // [0.1m/s] minimum speed to trigger the takeoff + static const uint8_t MinHold = 5; // [sec] minimum hold time before takeoff declared + static const uint16_t MinSpeed = 50; // [0.1m/s] minimum speed to trigger the takeoff uint8_t HoldTime; // uint8_t TakeoffCount; // count take-off/landing cycles for the IGC file name @@ -57,6 +57,7 @@ class FlightMonitor static int FlightThresh(const GPS_Position &Position, uint16_t MinSpeed) // does the GPS position meed the in-flight criteria ? { if(!Position.isValid()) return -1; + if(Position.Altitude>20000) return 1; // [0.1] Altitude above 2000m implies a flight uint16_t Speed=Position.Speed; // [0.1m/s] Horizontal speed int16_t Climb=Position.ClimbRate; // [0.1m/s] Vertical speed uint8_t DOP=Position.PDOP; if(DOP==0) DOP=Position.HDOP; // [0.1] Dilution of Precision diff --git a/main/proc.cpp b/main/proc.cpp index 96e6d17..edeefc4 100644 --- a/main/proc.cpp +++ b/main/proc.cpp @@ -408,7 +408,7 @@ static void ProcessRxPacket(OGN_RxPacket *RxPacket, uint8_t RxPacket } } -static void DecodeRxPacket(RFM_RxPktData *RxPkt) +static void DecodeRxPacket(RFM_FSK_RxPktData *RxPkt) { uint8_t RxPacketIdx = RelayQueue.getNew(); // get place for this new packet OGN_RxPacket *RxPacket = RelayQueue[RxPacketIdx]; @@ -466,7 +466,7 @@ void vTaskPROC(void* pvParameters) for( ; ; ) { vTaskDelay(1); - RFM_RxPktData *RxPkt = RF_RxFIFO.getRead(); // check for new received packets + RFM_FSK_RxPktData *RxPkt = RF_RxFIFO.getRead(); // check for new received packets if(RxPkt) // if there is a new received packet { #ifdef DEBUG_PRINT diff --git a/main/rf.cpp b/main/rf.cpp index 5fd5c90..302e004 100644 --- a/main/rf.cpp +++ b/main/rf.cpp @@ -27,7 +27,7 @@ static const uint8_t *OGN_SYNC = OGN2_SYNC; static uint32_t RF_SlotTime; // [sec] UTC time which belongs to the current time slot (0.3sec late by GPS UTC) FreqPlan RF_FreqPlan; // frequency hopping pattern calculator - FIFO RF_RxFIFO; // buffer for received packets + FIFO RF_RxFIFO; // buffer for received packets FIFO, 4> RF_TxFIFO; // buffer for transmitted packets #ifdef WITH_FANET @@ -58,15 +58,15 @@ static void SetTxChannel(uint8_t TxChan=RX_Channel) // default channel t TRX.WriteTxPower(Parameters.getTxPower(), Parameters.isTxTypeHW()); // set TX for transmission #endif #if defined(WITH_RFM95) || defined(WITH_SX1272) - TRX.WriteTxPower(Parameters.getTxPower()); // set TX for transmission + TRX.WriteTxPower(Parameters.getTxPower()); // set TX for transmission #endif TRX.setChannel(TxChan&0x7F); - TRX.WriteSYNC(8, 7, OGN_SYNC); } // Full SYNC for TX + TRX.FSK_WriteSYNC(8, 7, OGN_SYNC); } // Full SYNC for TX static void SetRxChannel(uint8_t RxChan=RX_Channel) { TRX.WriteTxPowerMin(); // setup for RX TRX.setChannel(RxChan&0x7F); - TRX.WriteSYNC(7, 7, OGN_SYNC); } // Shorter SYNC for RX + TRX.FSK_WriteSYNC(7, 7, OGN_SYNC); } // Shorter SYNC for RX static uint8_t ReceivePacket(void) // see if a packet has arrived { if(!TRX.DIO0_isOn()) return 0; // DIO0 line HIGH signals a new packet has arrived @@ -76,7 +76,7 @@ static uint8_t ReceivePacket(void) // see if a pack uint8_t RxRSSI = TRX.ReadRSSI(); // signal strength for the received packet RX_Random = (RX_Random<<1) | (RxRSSI&1); // use the lowest bit to add entropy - RFM_RxPktData *RxPkt = RF_RxFIFO.getWrite(); + RFM_FSK_RxPktData *RxPkt = RF_RxFIFO.getWrite(); RxPkt->Time = RF_SlotTime; // store reception time RxPkt->msTime = TimeSync_msTime(); if(RxPkt->msTime<200) RxPkt->msTime+=1000; RxPkt->Channel = RX_Channel; // store reception channel @@ -177,7 +177,7 @@ static uint8_t StartRFchip(void) // #ifdef WITH_RFM95 // TRX.WriteDefaultReg(); // #endif - TRX.ConfigureOGN(0, OGN_SYNC); // setup RF chip parameters and set to channel #0 + TRX.OGN_Configure(0, OGN_SYNC); // setup RF chip parameters and set to channel #0 TRX.WriteMode(RF_OPMODE_STANDBY); // set RF chip mode to STANDBY uint8_t Version = TRX.ReadVersion(); #ifdef DEBUG_PRINT @@ -342,8 +342,9 @@ extern "C" #if defined(WITH_FANET) && defined(WITH_RFM95) const FANET_Packet *FNTpkt = FNT_TxFIFO.getRead(0); // read the packet from the FANET transmitt queue if(FNTpkt) // was there any ? - { TRX.SetLoRa(); // switch TRX to LoRa - TRX.ConfigureFNT(); // configure for FANET + { TRX.setLoRa(); // switch TRX to LoRa + TRX.FNT_Configure(); + // TRX.setChannel(0); // configure for FANET TRX.WriteMode(RF_OPMODE_LORA_RX_CONT); vTaskDelay(2); for(uint8_t Wait=50; Wait; Wait--) @@ -351,7 +352,7 @@ extern "C" uint8_t Stat = TRX.ReadByte(REG_LORA_MODEM_STATUS); if((Stat&0x0B)==0) break; } TRX.WriteMode(RF_OPMODE_LORA_STANDBY); - TRX.SendPacketFNT(FNTpkt->Byte, FNTpkt->Len); + TRX.FNT_SendPacket(FNTpkt->Byte, FNTpkt->Len); FNT_TxFIFO.Read(); // remove the last packet from the queue /* xSemaphoreTake(CONS_Mutex, portMAX_DELAY); @@ -375,8 +376,8 @@ extern "C" { vTaskDelay(1); uint8_t Mode=TRX.ReadMode(); if(Mode!=RF_OPMODE_LORA_TX) break; } - TRX.SetFSK(); - TRX.ConfigureOGN(0, OGN_SYNC); + TRX.setFSK(); + TRX.OGN_Configure(0, OGN_SYNC); } #endif diff --git a/main/rf.h b/main/rf.h index 855fa05..8a6cd9a 100644 --- a/main/rf.h +++ b/main/rf.h @@ -16,7 +16,7 @@ #include "fanet.h" #endif - extern FIFO RF_RxFIFO; // buffer for received packets + extern FIFO RF_RxFIFO; // buffer for received packets extern FIFO, 4> RF_TxFIFO; // buffer for transmitted packets #ifdef WITH_FANET diff --git a/main/rfm.h b/main/rfm.h index 18225c0..33ebf69 100644 --- a/main/rfm.h +++ b/main/rfm.h @@ -9,7 +9,81 @@ #include "ogn.h" #include "fanet.h" -class RFM_RxPktData // OGN packet received by the RF chip +class RFM_LoRa_Config +{ public: + + union + { uint32_t Word; + struct + { uint8_t Spare :3; + uint8_t LowRate :1; // 0..1 + uint8_t TxInv :1; // 0..1, invert on TX + uint8_t RxInv :1; // 0..1, invert on RX + uint8_t IHDR :1; // 0..1, implicit header (no header on TX) + uint8_t CRC :1; // 0..1, produce CRC on TX and check CRC on RX + uint8_t CR :4; // 1..4, Coding Rate + uint8_t SF :4; // 6..12, Spreading Factor + uint8_t BW :4; // 0..9, 7=125kHz, 8=250kHz, 9=500kHz + uint8_t Preamble:4; // 0..15, preamble symbols + uint8_t SYNC :8; // 0..0xFF, SYNC + } ; + } ; + + public: + void Print(void) + { printf("RFM_LoRa_Config: SYNC:0x%02X/%d, BW%d, SF%d, CR%d, IHDR:%d, Inv:%d/%d, LR:%d\n", SYNC, Preamble, BW, SF, CR, IHDR, RxInv, TxInv, LowRate); } + + uint16_t getAirTime(uint8_t PktLen) // [ms] estimated time on the air for given packet length + { uint16_t Symbols = Preamble+2+3+8; // [symbols] preamble, SYNC and header + uint8_t NibPerBlock = SF; if(LowRate) NibPerBlock-=2; // [nibbles/block] byte-halfs + uint8_t SymbPerBlock = 4+CR; // [symbols] + uint16_t Nibbles = 2*(PktLen+2); // [nibbles] + uint8_t Blocks = (Nibbles+NibPerBlock-1)/NibPerBlock; // [FEC blocks] for the data part + Symbols += (uint16_t)Blocks*SymbPerBlock; // [symbols] + uint32_t SymbTime = 1<<(10-BW+SF); // [usec/symbol] + uint32_t Time = SymbTime*Symbols; // [usec] + return (Time+500)/1000; } + +} ; + +const RFM_LoRa_Config RFM_FNTcfg { 0xF1587190 } ; // LoRa seting for FANET + +class RFM_LoRa_RxPacket +{ public: + + union + { uint8_t Flags; + struct + { uint8_t CR:3; // Coding rate used (RX) or to be used (TX) + bool hasCRC:1; // CRC was there (RX) + bool badCRC:1; // CRC was bad (RX) + bool Done:1; + } ; + } ; + uint8_t Len; // [bytes] packet length + static const int MaxBytes = 40; + uint8_t Byte[MaxBytes+2]; + + uint32_t sTime; // [ s] reception time + uint16_t msTime; // [ms] + int16_t FreqOfs; // [ 10Hz] + int8_t SNR; // [0.25dB] + int8_t RSSI; // [dBm] + uint8_t BitErr; // number of bit errors + uint8_t CodeErr; // number of block errors + + public: + void Print(void) const + { char HHMMSS[8]; + Format_HHMMSS(HHMMSS, sTime); HHMMSS[6]='h'; HHMMSS[7]=0; + printf("%s CR%c%c%c %3.1fdB/%de %+3.1fkHz ", HHMMSS, '0'+CR, hasCRC?'c':'_', badCRC?'-':'+', 0.25*SNR, BitErr, 1e-2*FreqOfs); + for(uint8_t Idx=0; Idx7) SyncTol=7; // no more than 7 bit errors can be tolerated on SYNC if(WriteSize>8) WriteSize=8; // up to 8 bytes of SYNC can be programmed WriteBytes(SyncData+(8-WriteSize), WriteSize, REG_SYNCVALUE1); // write the SYNC, skip some initial bytes @@ -391,7 +466,7 @@ class RFM_TRX // #ifdef WITH_RFM95 #if defined(WITH_RFM95) || defined(WITH_SX1272) - void WriteSYNC(uint8_t WriteSize, uint8_t SyncTol, const uint8_t *SyncData) + void FSK_WriteSYNC(uint8_t WriteSize, uint8_t SyncTol, const uint8_t *SyncData) { if(SyncTol>7) SyncTol=7; if(WriteSize>8) WriteSize=8; WriteBytes(SyncData+(8-WriteSize), WriteSize, REG_SYNCVALUE1); // write the SYNC, skip some initial bytes @@ -441,14 +516,14 @@ class RFM_TRX void WriteTxPowerMin(void) { WriteTxPower_W(-18); } // set minimal Tx power and setup for reception - int ConfigureOGN(int16_t Channel, const uint8_t *Sync, bool PW=0) + int FSK_Configure(int16_t Channel, const uint8_t *Sync, bool PW=0) { WriteMode(RF_OPMODE_STANDBY); // mode = STDBY ClearIrqFlags(); WriteByte( 0x02, REG_DATAMODUL); // [0x00] Packet mode, FSK, 0x02: BT=0.5, 0x01: BT=1.0, 0x03: BT=0.3 WriteWord(PW?0x0341:0x0140, REG_BITRATEMSB); // bit rate = 100kbps WriteWord(PW?0x013B:0x0333, REG_FDEVMSB); // FSK deviation = +/-50kHz setChannel(Channel); // operating channel - WriteSYNC(8, 7, Sync); // SYNC pattern (setup for reception) + FSK_WriteSYNC(8, 7, Sync); // SYNC pattern (setup for reception) WriteByte( 0x00, REG_PACKETCONFIG1); // [0x10] Fixed size packet, no DC-free encoding, no CRC, no address filtering WriteByte(0x80+51, REG_FIFOTHRESH); // [ ] TxStartCondition=FifoNotEmpty, FIFO threshold = 51 bytes WriteByte( 2*26, REG_PAYLOADLENGTH); // [0x40] Packet size = 26 bytes Manchester encoded into 52 bytes @@ -498,35 +573,57 @@ class RFM_TRX void WriteTxPowerMin(void) { WriteTxPower(0); } - int SetLoRa(void) // switch to LoRa: has to go througth the SLEEP mode + int setLoRa(void) // switch to LoRa: has to go througth the SLEEP mode { WriteMode(RF_OPMODE_LORA_SLEEP); WriteMode(RF_OPMODE_LORA_SLEEP); return 0; } - int SetFSK(void) // switch to FSK: has to go through the SLEEP mode + int setFSK(void) // switch to FSK: has to go through the SLEEP mode { WriteMode(RF_OPMODE_SLEEP); WriteMode(RF_OPMODE_SLEEP); return 0; } - int ConfigureFNT(uint8_t CR=1) // configure for FANET/LoRa - { WriteTxPower(0); - WriteByte(0x00, REG_LORA_HOPPING_PERIOD); // disable fast-hopping - WriteByte(0xF1, REG_LORA_SYNC); // SYNC for FANET - WriteWord(0x0005, REG_LORA_PREAMBLE_MSB); // [symbols] minimal preamble - WriteByte(0x80 | (CR<<1), REG_LORA_MODEM_CONFIG1); // 0x88 = 250kHz, 4+4, explicit header - WriteByte(0x74, REG_LORA_MODEM_CONFIG2); // 0x74 = SF7, CRC on + int LoRa_Configure(RFM_LoRa_Config CFG, uint8_t MaxSize=64) + { WriteByte(0x00, REG_LORA_HOPPING_PERIOD); // disable fast-hopping + WriteByte(CFG.SYNC, REG_LORA_SYNC); // SYNC + WriteWord(CFG.Preamble, REG_LORA_PREAMBLE_MSB); // [symbols] minimal preamble + WriteByte((CFG.BW<<4) | (CFG.CR<<1) | CFG.IHDR, REG_LORA_MODEM_CONFIG1); // 0x88 = 250kHz, 4+4, explicit header + WriteByte((CFG.SF<<4) | (CFG.CRC<<2), REG_LORA_MODEM_CONFIG2); // 0x74 = SF7, CRC on + // WriteByte(CFG.InvIQ?0x67:0x26, REG_LORA_INVERT_IQ); + // WriteByte(CFG.InvIQ?0x19:0x1D, REG_LORA_INVERT_IQ2); + WriteByte((CFG.RxInv<<6) | 0x26 | CFG.TxInv, REG_LORA_INVERT_IQ); + // Format_String(CONS_UART_Write, "REG_LORA_INVERT_IQ:"); + // Format_Hex(CONS_UART_Write, CFG.Word); + // Format_String(CONS_UART_Write, ":"); + // Format_Hex(CONS_UART_Write, ReadByte(REG_LORA_INVERT_IQ)); + // Format_String(CONS_UART_Write, "\n"); WriteByte(0xC3, REG_LORA_DETECT_OPTIMIZE); WriteByte(0x0A, REG_LORA_DETECT_THRESHOLD); - WriteByte(0x04, REG_LORA_MODEM_CONFIG3); // LNA auto-gain ? - WriteByte(0xFF, REG_LORA_SYMBOL_TIMEOUT); // 0x64 = default or more ? - WriteByte(FANET_Packet::MaxBytes, REG_LORA_PACKET_MAXLEN); // [bytes] enough ? + WriteByte(0x04, REG_LORA_MODEM_CONFIG3); // LNA auto-gain ? + WriteByte(0xFF, REG_LORA_SYMBOL_TIMEOUT); // + WriteByte(MaxSize, REG_LORA_PACKET_MAXLEN); // [bytes] WriteByte(0x00, REG_LORA_RX_ADDR); - setChannel(0); // operating channel - WriteWord(0x0000, REG_DIOMAPPING1); // 001122334455___D signals: 00=DIO0 11=DIO1 22=DIO2 33=DIO3 44=DIO4 55=DIO5 D=MapPreambleDetect - // DIO0: 00=RxDone, 01=TxDone, 10=CadDone + setChannel(0); // operating channel + WriteWord(0x0000, REG_DIOMAPPING1); // 001122334455___D signals: 00=DIO0 11=DIO1 22=DIO2 33=DIO3 44=DIO4 55=DIO5 D=MapPreambleDetect + // DIO0: 00=RxDone, 01=TxDone, 10=CadDone return 0; } - int SendPacketFNT(const uint8_t *Data, uint8_t Len) + int FNT_Configure(uint8_t CR=1) // configure for FANET/LoRa + { WriteTxPower(0); + RFM_LoRa_Config CFG = RFM_FNTcfg; CFG.CR=CR; + return LoRa_Configure(CFG, FANET_Packet::MaxBytes); } + + void LoRa_setCRC(bool ON=1) // LoRaWAN: uplink with CRC, downlink without CRC + { uint8_t Reg=ReadByte(REG_LORA_MODEM_CONFIG2); + if(ON) Reg|=0x04; + else Reg&=0xFB; + WriteByte(Reg, REG_LORA_MODEM_CONFIG2); } + + void LoRa_InvertIQ(bool ON=0) // LoRaWAN + { WriteByte(ON?0x66:0x27, REG_LORA_INVERT_IQ); + WriteByte(ON?0x19:0x1D, REG_LORA_INVERT_IQ2); } + + int LoRa_SendPacket(const uint8_t *Data, uint8_t Len) { // WriteMode(RF_OPMODE_LORA_STANDBY); // check if FIFO empty, packets could be received ? WriteByte(0x00, REG_LORA_FIFO_ADDR); // tell write to FIFO at address 0x00 @@ -536,7 +633,11 @@ class RFM_TRX WriteMode(RF_OPMODE_LORA_TX); // enter transmission mode return 0; } // afterwards just wait for TX mode to stop - int ReceivePacketFNT(FANET_RxPacket &Packet) + int FNT_SendPacket(const uint8_t *Data, uint8_t Len) + { return LoRa_SendPacket(Data, Len); } + + template + int LoRa_ReceivePacket(RxPacket &Packet) { uint8_t Flags = ReadByte(REG_LORA_IRQ_FLAGS); if((Flags&LORA_FLAG_RX_DONE)==0) return 0; uint8_t Stat = ReadByte(REG_LORA_MODEM_STATUS); // coding rate in three top bits @@ -552,7 +653,7 @@ class RFM_TRX Packet.FreqOfs = (FreqOfs*1718+0x8000)>>16; // [10Hz] Packet.BitErr = 0; Packet.CodeErr = 0; - int Len=ReceivePacketFNT(Packet.Byte, Packet.MaxBytes); + int Len=LoRa_ReceivePacket(Packet.Byte, Packet.MaxBytes); // 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]); @@ -560,7 +661,7 @@ class RFM_TRX WriteByte(LORA_FLAG_RX_DONE | LORA_FLAG_BAD_CRC, REG_LORA_IRQ_FLAGS); return Len; } - int ReceivePacketFNT(uint8_t *Data, uint8_t MaxLen) + int LoRa_ReceivePacket(uint8_t *Data, uint8_t MaxLen) { uint8_t Len=ReadByte(REG_LORA_PACKET_BYTES); // packet length uint8_t Ptr=ReadByte(REG_LORA_PACKET_ADDR); // packet address in FIFO WriteByte(Ptr, REG_LORA_FIFO_ADDR); // ask to read FIFO from this address @@ -577,7 +678,7 @@ class RFM_TRX // ReadData[0], ReadData[1], ReadData[2], ReadData[3]); return Len; } - int ConfigureOGN(int16_t Channel, const uint8_t *Sync, bool PW=0) + int OGN_Configure(int16_t Channel, const uint8_t *Sync, bool PW=0) { // WriteMode(RF_OPMODE_STANDBY); // mode: STDBY, modulation: FSK, no LoRa // usleep(1000); WriteTxPower(0); @@ -588,7 +689,7 @@ class RFM_TRX WriteWord(PW?0x013B:0x0333, REG_FDEVMSB); // FSK deviation = +/-50kHz [32MHz/(1<<19)] (0x013B = 19.226kHz) // ReadWord(REG_FDEVMSB); setChannel(Channel); // operating channel - WriteSYNC(8, 7, Sync); // SYNC pattern (setup for reception) + FSK_WriteSYNC(8, 7, Sync); // SYNC pattern (setup for reception) WriteByte( 0x85, REG_PREAMBLEDETECT); // preamble detect: 1 byte, page 92 (or 0x85 ?) WriteByte( 0x00, REG_PACKETCONFIG1); // Fixed size packet, no DC-free encoding, no CRC, no address filtering WriteByte( 0x40, REG_PACKETCONFIG2); // Packet mode diff --git a/main/sdlog.cpp b/main/sdlog.cpp index 72f6cea..5a4564d 100644 --- a/main/sdlog.cpp +++ b/main/sdlog.cpp @@ -81,6 +81,8 @@ static int WriteLog(size_t MaxBlock=FIFOsize/2) // process th // ============================================================================================ +#ifdef WITH_SDLOG + const char *IGC_Path = "/sdcard/IGC"; const int IGC_PathLen = 11; const uint32_t IGC_SavePeriod = 20; @@ -276,6 +278,8 @@ static void IGC_Check(void) // check if } } +#endif // WITH_SDLOG + // ============================================================================================ #ifdef WITH_SDLOG diff --git a/main/sx1276.h b/main/sx1276.h index c16fb25..bdd827c 100644 --- a/main/sx1276.h +++ b/main/sx1276.h @@ -136,9 +136,10 @@ Maintainer: Miguel Luis and Gregory Cristian #define REG_LORA_FREQ_ERR_MID 0x29 #define REG_LORA_FREQ_ERR_LSB 0x2A #define REG_LORA_DETECT_OPTIMIZE 0x31 // -#define REG_LORA_INVERT_IQ 0x33 +#define REG_LORA_INVERT_IQ 0x33 // #define REG_LORA_DETECT_THRESHOLD 0x37 // for SF6 #define REG_LORA_SYNC 0x39 // 0xF1 for FANET, default = 0x12 (for old FANET) +#define REG_LORA_INVERT_IQ2 0x3B // // LoRa flags #define LORA_FLAG_TIMEOUT 0x80 // timeout in single packet reception ?