From 3d67983d8785d01bc1bc0996ce412db2dce34d9a Mon Sep 17 00:00:00 2001 From: Pawel Jalocha Date: Mon, 23 May 2022 02:47:41 +0100 Subject: [PATCH] Clean up IGC logging to SD card, fixed IGC log name issue, not tested yet for takeoff/landing detection --- main/flight.h | 4 +- main/gps.cpp | 19 +++++---- main/ogn.h | 6 +-- main/proc.cpp | 14 ++++++- main/sdlog.cpp | 112 ++++++++++++++++++++++++++++++++----------------- main/sdlog.h | 2 + 6 files changed, 105 insertions(+), 52 deletions(-) diff --git a/main/flight.h b/main/flight.h index 0bc1a1f..eabf47a 100644 --- a/main/flight.h +++ b/main/flight.h @@ -35,8 +35,8 @@ class FlightMonitor if(Num<36) return 'A'+(Num-10); return '_'; } - int ShortName(char *Name, uint8_t TakeoffNum, const char *Serial) const // produce short IGC file name (a three-character Serial) - { return ShortName(Name, Takeoff, TakeoffNum, Serial); } + // int ShortName(char *Name, uint8_t TakeoffNum, const char *Serial) const // produce short IGC file name (a three-character Serial) + // { return ShortName(Name, Takeoff, TakeoffNum, Serial); } static int ShortName(char *Name, const GPS_Position &Takeoff, uint8_t TakeoffNum, const char *Serial) { int Len=0; diff --git a/main/gps.cpp b/main/gps.cpp index 3231916..7cda164 100644 --- a/main/gps.cpp +++ b/main/gps.cpp @@ -146,7 +146,7 @@ static char GPS_Cmd[64]; // command to be send to the GPS // Satellite count and SNR per system, 0=GPS, 1=GLONASS, 2=GALILEO, 3=BEIDO static uint16_t SatSNRsum[4] = { 0, 0, 0, 0 }; // sum up the satellite SNR's -static uint8_t SatSNRcount[4] = { 0, 0, 0, 0 }; // sum counter +static uint8_t SatSNRcount[4] = { 0, 0, 0, 0 }; // count entries to the sum struct GPS_Sat // store GPS satellite data in single 32-bit word { union @@ -191,6 +191,13 @@ static void ProcessGSV(NMEA_RxMsg &GSV) // process GxGSV to extract SatSNRsum[SatSys]+=SNR; SatSNRcount[SatSys]++; } // add up SNR if(Pkt==Pkts) // if the last packet { + uint8_t Count=0; uint16_t Sum=0; + for(uint8_t Sys=0; Sys<4; Sys++) + { if(SatSNRcount[Sys]==0) continue; + Count+=SatSNRcount[Sys]; Sum+=SatSNRsum[Sys]; } + GPS_SatCnt = Count; + if(Count) GPS_SatSNR = (4*Sum+Count/2)/Count; + else GPS_SatSNR = 0; #ifdef DEBUG_PRINT xSemaphoreTake(CONS_Mutex, portMAX_DELAY); Format_String(CONS_UART_Write, "SatSNR["); @@ -199,15 +206,13 @@ static void ProcessGSV(NMEA_RxMsg &GSV) // process GxGSV to extract Format_UnsDec(CONS_UART_Write, SatSNRsum[SatSys]); CONS_UART_Write('/'); Format_UnsDec(CONS_UART_Write, (uint16_t)SatSNRcount[SatSys]); + CONS_UART_Write(' '); + Format_UnsDec(CONS_UART_Write, (uint16_t)Sum); + CONS_UART_Write('/'); + Format_UnsDec(CONS_UART_Write, (uint16_t)Count); Format_String(CONS_UART_Write, "\n"); xSemaphoreGive(CONS_Mutex); #endif - uint8_t Count=0; uint16_t Sum=0; - for(uint8_t Sys=0; Sys<4; Sys++) - { Count+=SatSNRcount[Sys]; Sum+=SatSNRsum[Sys]; } - GPS_SatCnt = Count; - if(Count) GPS_SatSNR = (4*Sum+Count/2)/Count; - else GPS_SatSNR = 0; } } diff --git a/main/ogn.h b/main/ogn.h index d4e21cc..a41f787 100644 --- a/main/ogn.h +++ b/main/ogn.h @@ -183,8 +183,8 @@ template { uint8_t State; // struct { bool Saved :1; // has been already saved in internal storage - bool Ready :1; // is ready for transmission - bool Sent :1; // has already been transmitted out + bool Warn :1; // there is a warning associated with this packet + bool Spare :1; bool Correct :1; // correctly received or corrected by FEC uint8_t RxErr:4; // number of bit errors corrected upon reception } ; @@ -192,7 +192,7 @@ template uint8_t RxChan; // RF channel where the packet was received uint8_t RxRSSI; // [-0.5dBm] - uint8_t Rank; // rank: low altitude and weak signal => high rank + uint8_t Rank; // relay rank: low altitude and weak signal => high rank public: diff --git a/main/proc.cpp b/main/proc.cpp index b39b9aa..6033b94 100644 --- a/main/proc.cpp +++ b/main/proc.cpp @@ -339,13 +339,21 @@ static uint8_t WritePFLAU(char *NMEA, uint8_t GPS=1) // produce the (mostly d static void ProcessRxPacket(OGN_RxPacket *RxPacket, uint8_t RxPacketIdx, uint32_t RxTime) // process every (correctly) received packet { int32_t LatDist=0, LonDist=0; uint8_t Warn=0; - if( RxPacket->Packet.Header.NonPos /* || RxPacket->Packet.Header.Encrypted */ ) return ; // status packet or encrypted: ignore + if( RxPacket->Packet.Header.NonPos) // status or info packet + { +#ifdef WITH_SDLOG + IGClog_FIFO.Write(*RxPacket); +#endif + return ; } uint8_t MyOwnPacket = ( RxPacket->Packet.Header.Address == Parameters.Address ) && ( RxPacket->Packet.Header.AddrType == Parameters.AddrType ); if(MyOwnPacket) return; // don't process my own (relayed) packets if(RxPacket->Packet.Header.Encrypted && RxPacket->RxErr<10) // here we attempt to relay encrypted packets { RxPacket->calcRelayRank(GPS_Altitude/10); OGN_RxPacket *PrevRxPacket = RelayQueue.addNew(RxPacketIdx); // add to the relay queue and get the previous packet of same ID +#ifdef WITH_SDLOG + IGClog_FIFO.Write(*RxPacket); +#endif return; } bool DistOK = RxPacket->Packet.calcDistanceVector(LatDist, LonDist, GPS_Latitude, GPS_Longitude, GPS_LatCosine)>=0; if(DistOK) @@ -372,6 +380,7 @@ static void ProcessRxPacket(OGN_RxPacket *RxPacket, uint8_t RxPacket #ifdef WITH_LOOKOUT const LookOut_Target *Tgt=Look.ProcessTarget(RxPacket->Packet); // process the received target postion if(Tgt) Warn=Tgt->WarnLevel; // remember warning level of this target + RxPacket->Warn = Warn>0; #ifdef WITH_GDL90 if(Tgt) { Look.Write(GDL_REPORT, Tgt); // produce GDL90 report for this target @@ -395,6 +404,9 @@ static void ProcessRxPacket(OGN_RxPacket *RxPacket, uint8_t RxPacket #ifdef WITH_LOG if(Signif) FlashLog(RxPacket, RxTime); // log only significant packets #endif +#ifdef WITH_SDLOG + if(Signif || Warn) IGClog_FIFO.Write(*RxPacket); +#endif #ifdef WITH_PFLAA if( Parameters.Verbose // print PFLAA on the console for received packets #ifdef WITH_LOOKOUT diff --git a/main/sdlog.cpp b/main/sdlog.cpp index 1c5490f..de55683 100644 --- a/main/sdlog.cpp +++ b/main/sdlog.cpp @@ -107,6 +107,8 @@ static SHA256 IGC_SHA256, IGC_SHA256_bck; // const int IGC_Digest_Size = 32; static uint8_t IGC_Digest[IGC_Digest_Size]; // +FIFO, 32> IGClog_FIFO; + static void IGC_TimeStamp(void) { struct stat FileStat; struct utimbuf FileTime; @@ -137,12 +139,12 @@ static void IGC_Close(void) } */ -static int IGC_Open(void) +static int IGC_Open(const GPS_Position &GPS) { IGC_Close(); // close the previous file, if open if(!SD_isMounted()) return -1; // -1 => SD not mounted memcpy(IGC_FileName, IGC_Path, IGC_PathLen); // copy path IGC_FileName[IGC_PathLen]='/'; // slash after the path - Flight.ShortName(IGC_FileName+IGC_PathLen+1, IGC_FlightNum, IGC_Serial); // full name + Flight.ShortName(IGC_FileName+IGC_PathLen+1, GPS, IGC_FlightNum, IGC_Serial); // full name IGC_File=fopen(IGC_FileName, "rt"); // attempt to open for read, just to try if the file is already there if(IGC_File) { IGC_Close(); return -2; } // -2 => file already exists IGC_File=fopen(IGC_FileName, "wt"); // open for write @@ -176,16 +178,15 @@ static int IGC_LogLine(const char *Line) static char Line[512]; -static int IGC_HeadParm(const char *Name, const char *Parm1, const char *Parm2=0, const char *Parm3=0) +static void IGC_LogHeadParm(const char *Name, const char *Parm1, const char *Parm2=0, const char *Parm3=0) { int Len=Format_String(Line, Name); Len+=Format_String(Line+Len, Parm1); if(Parm2 && Parm2[0]) { Line[Len++]=','; Len+=Format_String(Line+Len, Parm2); } if(Parm3 && Parm3[0]) { Line[Len++]=','; Len+=Format_String(Line+Len, Parm3); } Line[Len++]='\n'; Line[Len]=0; - IGC_LogLine(Line, Len); - return 0; } + IGC_LogLine(Line, Len); } -static int IGC_Header(const GPS_Position &Pos) // write the top of the IGC file +static void IGC_LogHeader(const GPS_Position &Pos) // write the top of the IGC file { IGC_LogLine("AGNE001Tracker\n"); IGC_LogLine("HFFXA020\n"); { int Len=Format_String(Line, "HFDTEDate:"); // date @@ -196,12 +197,12 @@ static int IGC_Header(const GPS_Position &Pos) // write the Len+=Format_UnsDec(Line+Len, (uint16_t)IGC_FlightNum, 2); // flight number of the day Line[Len++]='\n'; Line[Len]=0; IGC_LogLine(Line, Len); } - IGC_HeadParm("HFPLTPilotincharge:", Parameters.Pilot); // Pilot - IGC_HeadParm("HFGTYGliderType:", Parameters.Type, Parameters.Manuf, Parameters.Model); // aircraft type like ASK-21 - IGC_HeadParm("HFGIDGliderID:", Parameters.Reg); // aircraft registration like D-8329 - IGC_HeadParm("HFCM2Crew2:", Parameters.Crew); // Crew member - IGC_HeadParm("HFCCLCompetitionClass:", Parameters.Class); // competition class - IGC_HeadParm("HFCIDCompetitionID:", Parameters.ID); // competition ID + IGC_LogHeadParm("HFPLTPilotincharge:", Parameters.Pilot); // Pilot + IGC_LogHeadParm("HFGTYGliderType:", Parameters.Type, Parameters.Manuf, Parameters.Model); // aircraft type like ASK-21 + IGC_LogHeadParm("HFGIDGliderID:", Parameters.Reg); // aircraft registration like D-8329 + IGC_LogHeadParm("HFCM2Crew2:", Parameters.Crew); // Crew member + IGC_LogHeadParm("HFCCLCompetitionClass:", Parameters.Class); // competition class + IGC_LogHeadParm("HFCIDCompetitionID:", Parameters.ID); // competition ID { #ifdef WITH_FollowMe int Len=Format_String(Line, "HFRHWHardwareVersion:FollowMe"); @@ -230,7 +231,7 @@ static int IGC_Header(const GPS_Position &Pos) // write the #ifdef WITH_BME280 IGC_LogLine("HFPRSPressAltSensor:BME280/BMP280\n"); // pressure sensor #endif - return 0; } +} void IGC_ID(void) { uint32_t Time = TimeSync_Time(); @@ -261,16 +262,22 @@ static int IGC_Log(const GPS_Position &Pos) // log GPS p if(Written!=Len) IGC_Close(); // if not all data written then close the log return Written; } // return number of bytes written or (negative) error -static void IGC_LogSig(const uint8_t *Dig, int DigLen, const uint8_t *Sig, int SigLen, bool Partial=0) // write SHA and Signature to the IGC log +static int IGC_FormatLOGN(char *Out, const char *Type, const GPS_Position &GPS) +{ int Len=Format_String(Out, "LOGN"); + if(GPS.isTimeValid()) Len+=GPS.WriteHHMMSS(Out+Len); + else Len+=Format_String(Out+Len, " "); + Len+=Format_String(Out+Len, Type); return Len; } + +static void IGC_LogSig(const uint8_t *Dig, int DigLen, const uint8_t *Sig, int SigLen, bool Part, const GPS_Position &GPS) // write SHA and Signature to the IGC log { int Len=0; - if(Partial) Line[Len++]='L'; + if(Part) Len+=IGC_FormatLOGN(Line+Len, "DIG ", GPS); Line[Len++]='G'; // produce G-record with SH256 for(int Idx=0; Idx>8, 4, 3); // print the battery voltage readout Len+=Format_String(Line+Len, "V "); Len+=Format_SignDec(Line+Len, (600*BatteryVoltageRate+128)>>8, 3, 1); @@ -289,9 +297,10 @@ static void IGC_LogBATstatus(const GPS_Position &GPS) IGC_LogLine(Line, Len); } static void IGC_LogRFMstatus(const GPS_Position &GPS) -{ int Len=Format_String(Line, "LRFM"); - if(GPS.isTimeValid()) Len+=GPS.WriteHHMMSS(Line+Len); - Len+=Format_String(Line+Len, " Tx:"); // +{ int Len=IGC_FormatLOGN(Line, "RFM Tx:", GPS); + // int Len=Format_String(Line, "LOGNRFM"); + // if(GPS.isTimeValid()) Len+=GPS.WriteHHMMSS(Line+Len); + // Len+=Format_String(Line+Len, "Tx:"); // Len+=Format_SignDec(Line+Len, (int16_t)Parameters.TxPower); // Tx power Len+=Format_String(Line+Len, "dBm "); Len+=Format_SignDec(Line+Len, (int16_t)TRX.chipTemp); // RF chip internal temperature (not calibrated) @@ -309,10 +318,33 @@ static void IGC_LogRFMstatus(const GPS_Position &GPS) Line[Len++]='\n'; Line[Len]=0; // end-of-line, end-of-string IGC_LogLine(Line, Len); } +static void IGC_LogRX(const GPS_Position &GPS) +{ uint32_t Time=0; if(GPS.isTimeValid()) Time=GPS.getUnixTime(); + while(IGClog_FIFO.Full()) + { int Len=IGC_FormatLOGN(Line, "RX ", GPS); + // int Len=Format_String(Line, "LOGNRX"); + // if(GPS.isTimeValid()) Len+=GPS.WriteHHMMSS(Line+Len); + // Line[Len++]=' '; + OGN_RxPacket *RxPacket=IGClog_FIFO.getRead(); + uint8_t RxErr = RxPacket->RxErr; + if(RxErr<=8) + { Len+=RxPacket->Packet.WriteAPRS(Line+Len, Time, "OGNTRK"); + if(RxErr) { Line[Len++]=' '; Line[Len++]='0'+RxErr; Line[Len++]='e'; } + Line[Len++]=' '; + Len+=Format_SignDec(Line+Len, -5*(int16_t)RxPacket->RxRSSI, 1, 1); + Len+=Format_String(Line+Len, "dBm"); + Line[Len++]='\n'; Line[Len]=0; // end-of-line, end-of-string + IGC_LogLine(Line, Len); + } + IGClog_FIFO.Read(); + } +} + static void IGC_LogGPSstatus(const GPS_Position &GPS) -{ int Len=Format_String(Line, "LGPS"); - if(GPS.isTimeValid()) Len+=GPS.WriteHHMMSS(Line+Len); - Line[Len++]=' '; +{ int Len=IGC_FormatLOGN(Line, "GPS ", GPS); + // int Len=Format_String(Line, "LOGNGPS"); + // if(GPS.isTimeValid()) Len+=GPS.WriteHHMMSS(Line+Len); + // Line[Len++]=' '; if(GPS.isValid()) Len+=Format_UnsDec(Line+Len, GPS.Satellites); else @@ -339,11 +371,12 @@ static void IGC_CheckGPS(void) // check if new const uint8_t PosPipeIdxMask = GPS_PosPipeSize-1; // get the GPS position just before in the pipe uint8_t PosIdx = GPS_PosIdx-1; PosIdx&=PosPipeIdxMask; static bool PrevInFlight=0; - bool inFlight = GPS_Pos[PosIdx].InFlight; // Flight.inFlight(); // in-flight or on-the-ground ? + const GPS_Position &GPS = GPS_Pos[PosIdx]; + bool inFlight = GPS.InFlight; // in-flight or on-the-ground ? bool StopFile = PrevInFlight && !inFlight; PrevInFlight = inFlight;; #ifdef DEBUG_PRINT - GPS_Pos[PosIdx].PrintLine(Line); + GPS.PrintLine(Line); xSemaphoreTake(CONS_Mutex, portMAX_DELAY); Format_String(CONS_UART_Write, "IGC_Check() ["); CONS_UART_Write('0'+GPS_PosIdx); @@ -354,36 +387,37 @@ static void IGC_CheckGPS(void) // check if new #endif if(IGC_File) // if IGC file already open { if(Parameters.AcftID!=IGC_AcftID) { IGC_ID(); IGC_AcftID=Parameters.AcftID; } - IGC_Log(GPS_Pos[PosIdx]); // log position + IGC_Log(GPS); // log position + IGC_LogRX(GPS); if(StopFile) // if no longer in flight { IGC_SHA256.Finish(IGC_Digest); // complete SHA256 digest uint8_t *Sig = (uint8_t *)Line+256; // space to write the SHA and signature int SigLen = IGC_SignKey.Sign_MD5_SHA256(Sig, IGC_Digest, IGC_Digest_Size); // produce signature - IGC_LogSig(IGC_Digest, IGC_Digest_Size, Sig, SigLen, 0); + IGC_LogSig(IGC_Digest, IGC_Digest_Size, Sig, SigLen, 0, GPS); IGC_Close(); IGC_TimeStamp(); } // then close the IGC file else // if (still) in flight { uint32_t Time=TimeSync_Time(); // if(Time-IGC_SaveTime>=IGC_SavePeriod) // - { IGC_LogBATstatus(GPS_Pos[PosIdx]); - IGC_LogGPSstatus(GPS_Pos[PosIdx]); - IGC_LogRFMstatus(GPS_Pos[PosIdx]); + { IGC_LogBATstatus(GPS); + IGC_LogGPSstatus(GPS); + IGC_LogRFMstatus(GPS); IGC_SHA256_bck.Clone(IGC_SHA256); IGC_SHA256_bck.Finish(IGC_Digest); // complete SHA256 digest uint8_t *Sig = (uint8_t *)Line+256; // space to write the SHA and signature int SigLen = IGC_SignKey.Sign_MD5_SHA256(Sig, IGC_Digest, IGC_Digest_Size); // produce signature - IGC_LogSig(IGC_Digest, IGC_Digest_Size, Sig, SigLen, 1); + IGC_LogSig(IGC_Digest, IGC_Digest_Size, Sig, SigLen, 1, GPS); IGC_Reopen(); } // re-open IGC thus close it and open it back to save the current data } } - else // if IGC file is not open + else if(GPS.isDateValid()) // if IGC file is not open { for(int Try=0; Try<8; Try++) - { int Err=IGC_Open(); if(Err!=(-2)) break; } // try to open a new IGC file but don't overwrite the old ones - if(IGC_File) // if open succesfully - { IGC_SHA256.Start(); // start the SHA256 calculation - IGC_Header(GPS_Pos[PosIdx]); // then write header + { int Err=IGC_Open(GPS); if(Err!=(-2)) break; } // try to open a new IGC file but don't overwrite the old ones + if(IGC_File) // if open succesfully + { IGC_SHA256.Start(); // start the SHA256 calculation + IGC_LogHeader(GPS); // then write header IGC_ID(); IGC_AcftID=Parameters.AcftID; IGC_MAC(); - IGC_Log(GPS_Pos[PosIdx]); } // log first B-record + IGC_Log(GPS); } // log first B-record } } diff --git a/main/sdlog.h b/main/sdlog.h index 9b907ba..7129769 100644 --- a/main/sdlog.h +++ b/main/sdlog.h @@ -11,6 +11,8 @@ void Log_Write(char Byte); int Log_Free(void); extern SemaphoreHandle_t Log_Mutex; +extern FIFO, 32> IGClog_FIFO; + extern IGC_Key IGC_SignKey; #ifdef __cplusplus