//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ /// Parses LXWP0 sentence. /// /// @param d device descriptor /// @param sentence received NMEA sentence /// @param info GPS info to be updated /// /// @retval true if the sentence has been parsed /// //static bool DevLXV7::LXWP0(PDeviceDescriptor_t d, const TCHAR* sentence, NMEA_INFO* info) { // $LXWP0,logger_stored, airspeed, airaltitude, // v1[0],v1[1],v1[2],v1[3],v1[4],v1[5], hdg, windspeed*CS<CR><LF> // // 0 loger_stored : [Y|N] (not used in LX1600) // 1 IAS [km/h] ----> Condor uses TAS! // 2 baroaltitude [m] // 3-8 vario values [m/s] (last 6 measurements in last second) // 9 heading of plane (not used in LX1600) // 10 windcourse [deg] (not used in LX1600) // 11 windspeed [km/h] (not used in LX1600) // // e.g.: // $LXWP0,Y,222.3,1665.5,1.71,,,,,,239,174,10.1 /* if (ParToDouble(sentence, 10, &info->ExternalWindDirection) && ParToDouble(sentence, 11, &info->ExternalWindSpeed)) info->ExternalWindAvailalbe = TRUE; */ TriggerVarioUpdate(); return(true); } // LXWP0()
void MergeThread::Tick() { ScopeLock protect(device_blackboard.mutex); Process(); const MoreData &basic = device_blackboard.Basic(); if (last_any.location_available != basic.location_available) // trigger update if gps has become available or dropped out TriggerGPSUpdate(); if ((bool)last_any.alive != (bool)basic.alive || (bool)last_any.location_available != (bool)basic.location_available) /* trigger a redraw when the connection was just lost, to show the new state; when no GPS is connected, no other entity triggers the redraw, so we have to do it */ TriggerCalculatedUpdate(); TriggerVarioUpdate(); /* update last_any in every iteration */ last_any = basic; /* update last_fix only when a new GPS fix was received */ if ((basic.time_available && (!last_fix.time_available || basic.time != last_fix.time)) || basic.location_available != last_fix.location_available) last_fix = basic; }
void MergeThread::Tick() { bool gps_updated, calculated_updated; #ifdef HAVE_PCM_PLAYER bool vario_available; double vario; #endif { ScopeLock protect(device_blackboard.mutex); Process(); const MoreData &basic = device_blackboard.Basic(); /* call Driver::OnSensorUpdate() on all devices */ if (devices != nullptr) devices->NotifySensorUpdate(basic); /* trigger update if gps has become available or dropped out */ gps_updated = last_any.location_available != basic.location_available; /* trigger a redraw when the connection was just lost, to show the new state; when no GPS is connected, no other entity triggers the redraw, so we have to do it */ calculated_updated = (bool)last_any.alive != (bool)basic.alive || (bool)last_any.location_available != (bool)basic.location_available; #ifdef HAVE_PCM_PLAYER vario_available = basic.brutto_vario_available; vario = vario_available ? basic.brutto_vario : 0; #endif /* update last_any in every iteration */ last_any = basic; /* update last_fix only when a new GPS fix was received */ if ((basic.time_available && (!last_fix.time_available || basic.time != last_fix.time)) || basic.location_available != last_fix.location_available) last_fix = basic; } #ifdef HAVE_PCM_PLAYER if (vario_available) AudioVarioGlue::SetValue(vario); else AudioVarioGlue::NoValue(); #endif if (gps_updated) TriggerGPSUpdate(); if (calculated_updated) TriggerCalculatedUpdate(); TriggerVarioUpdate(); }
static BOOL PZAN2(PDeviceDescriptor_t d, TCHAR *String, NMEA_INFO *apGPS) { TCHAR ctemp[80]; double vtas, wnet, vias; NMEAParser::ExtractParameter(String,ctemp,0); vtas = StrToDouble(ctemp,NULL)/3.6; NMEAParser::ExtractParameter(String,ctemp,1); wnet = (StrToDouble(ctemp,NULL)-10000)/100; // cm/s apGPS->Vario = wnet; if (apGPS->BaroAltitudeAvailable) { vias = vtas/AirDensityRatio(AltitudeToQNEAltitude(apGPS->BaroAltitude)); } else { vias = 0.0; } apGPS->AirspeedAvailable = TRUE; apGPS->TrueAirspeed = vtas; apGPS->IndicatedAirspeed = vias; apGPS->VarioAvailable = TRUE; TriggerVarioUpdate(); return TRUE; }
static BOOL _PRS(PDeviceDescriptor_t d, TCHAR *String, NMEA_INFO *_INFO){ (void)d; if(UpdateBaroSource(_INFO, 0, d, StaticPressureToAltitude((HexStrToInt(String)*1.0)))){ TriggerVarioUpdate(); } return TRUE; }
static BOOL VARIO(PDeviceDescriptor_t d, TCHAR *String, NMEA_INFO *pGPS) { // $VARIO,fPressure,fVario,Bat1Volts,Bat2Volts,BatBank,TempSensor1,TempSensor2*CS TCHAR ctemp[80]; NMEAParser::ExtractParameter(String,ctemp,0); double ps = StrToDouble(ctemp,NULL); UpdateBaroSource( pGPS, 0,d, (1 - pow(fabs(ps / QNH), 0.190284)) * 44307.69); NMEAParser::ExtractParameter(String,ctemp,1); pGPS->Vario = StrToDouble(ctemp,NULL)/10.0; // JMW vario is in dm/s NMEAParser::ExtractParameter(String,ctemp,2); pGPS->ExtBatt1_Voltage = StrToDouble(ctemp,NULL); NMEAParser::ExtractParameter(String,ctemp,3); pGPS->ExtBatt2_Voltage = StrToDouble(ctemp,NULL); NMEAParser::ExtractParameter(String,ctemp,4); pGPS->ExtBatt_Bank = (int)StrToDouble(ctemp,NULL); /* StartupStore(_T("++++++ BATTBANK: ")); StartupStore(ctemp); StartupStore(_T("\n")); */ pGPS->VarioAvailable = TRUE; TriggerVarioUpdate(); return TRUE; }
static BOOL LK8EX1(PDeviceDescriptor_t d, TCHAR *String, NMEA_INFO *GPS_INFO) { TCHAR ctemp[80]; bool havebaro=false; // HPA from the pressure sensor NMEAParser::ExtractParameter(String,ctemp,0); double ps = StrToDouble(ctemp,NULL); if (ps!=999999) { ps/=100; if (d == pDevPrimaryBaroSource) { UpdateBaroSource( GPS_INFO, LK_EXT1, (1 - pow(fabs(ps / QNH), 0.190284)) * 44307.69); } } // QNE if (!havebaro) { NMEAParser::ExtractParameter(String,ctemp,1); double ba = StrToDouble(ctemp,NULL); if (ba!=99999) { if (d == pDevPrimaryBaroSource) { UpdateBaroSource( GPS_INFO, LK_EXT1, AltitudeToQNHAltitude(ba)); } } } // VARIO NMEAParser::ExtractParameter(String,ctemp,2); double va = StrToDouble(ctemp,NULL); if (va != 9999) { GPS_INFO->Vario = va/100; GPS_INFO->VarioAvailable = TRUE; } else GPS_INFO->VarioAvailable = FALSE; // OAT NMEAParser::ExtractParameter(String,ctemp,3); double ta = StrToDouble(ctemp,NULL); if (ta != 99) { GPS_INFO->OutsideAirTemperature = ta; GPS_INFO->TemperatureAvailable=TRUE; } // BATTERY PERCENTAGES NMEAParser::ExtractParameter(String,ctemp,4); double voa = StrToDouble(ctemp,NULL); if (voa!=999) { GPS_INFO->ExtBatt1_Voltage = voa; } // currently unused in LK, but ready for next future TriggerVarioUpdate(); return TRUE; }
BOOL PBB50(TCHAR *String, NMEA_INFO *pGPS) { // $PBB50,100,0,10,1,10000,0,1,0,20*4A.. // $PBB50,0,.0,.0,0,0,1.07,0,-228*58 // $PBB50,14,-.2,.0,196,0,.92,0,-228*71 double vtas, vias, wnet; TCHAR ctemp[80]; NMEAParser::ExtractParameter(String,ctemp,0); vtas = StrToDouble(ctemp,NULL)/TOKNOTS; NMEAParser::ExtractParameter(String,ctemp,1); wnet = StrToDouble(ctemp,NULL)/TOKNOTS; NMEAParser::ExtractParameter(String,ctemp,2); pGPS->MacReady = StrToDouble(ctemp,NULL)/TOKNOTS; CheckSetMACCREADY(pGPS->MacReady); NMEAParser::ExtractParameter(String,ctemp,3); vias = sqrt(StrToDouble(ctemp,NULL))/TOKNOTS; // inclimb/incruise 1=cruise,0=climb, OAT NMEAParser::ExtractParameter(String,ctemp,6); #if USESWITCHES int climb = iround(StrToDouble(ctemp,NULL)); pGPS->SwitchState.VarioCircling = (climb==1); #endif #if 0 // UNUSED EnableExternalTriggerCruise if (EnableExternalTriggerCruise) { if (climb) { ExternalTriggerCruise = false; ExternalTriggerCircling = true; } else { ExternalTriggerCruise = true; ExternalTriggerCircling = false; } } else { ExternalTriggerCruise = false; } #endif NMEAParser::ExtractParameter(String,ctemp,7); pGPS->OutsideAirTemperature = StrToDouble(ctemp,NULL); pGPS->TemperatureAvailable = true; pGPS->AirspeedAvailable = TRUE; pGPS->IndicatedAirspeed = vias; pGPS->TrueAirspeed = vtas; pGPS->VarioAvailable = TRUE; pGPS->Vario = wnet; TriggerVarioUpdate(); return FALSE; }
static BOOL VMVABD(PDeviceDescriptor_t d, TCHAR *String, NMEA_INFO *GPS_INFO) { /* $VMVABD, 0000.0 gps altitude, 0 M, 1 0000.0 bari altitude, 2 M, 3 -0.0 vario ms,,, 4 MS, 7 0.0 ias or tas, 8 KH, 9 22.4 temp, 10 C*nn 091129 The Brauniger Compeo can send TAS if a pitot is connected (delta hang gliders) or IAS is rotary device for para. Since rotary is seldom used, we assume TAS is received. No indication from NMEA about IAS or TAS selected. 100114 IAS or TAS??? */ TCHAR ctemp[80]; double vtas, vias; NMEAParser::ExtractParameter(String,ctemp,0); GPS_INFO->Altitude = StrToDouble(ctemp,NULL); NMEAParser::ExtractParameter(String,ctemp,2); if (d == pDevPrimaryBaroSource) { GPS_INFO->BaroAltitude = AltitudeToQNHAltitude(StrToDouble(ctemp,NULL)); GPS_INFO->BaroAltitudeAvailable = TRUE; } NMEAParser::ExtractParameter(String,ctemp,4); GPS_INFO->Vario = StrToDouble(ctemp,NULL); GPS_INFO->VarioAvailable = TRUE; NMEAParser::ExtractParameter(String,ctemp,8); if (ctemp[0] != '\0') { // 100209 // we store m/s , so we convert it from kmh vias = StrToDouble(ctemp,NULL)/3.6; GPS_INFO->IndicatedAirspeed = vias; // Check if zero? vtas = vias*AirDensityRatio(GPS_INFO->BaroAltitude); GPS_INFO->TrueAirspeed = vtas; if (GPS_INFO->IndicatedAirspeed >0) GPS_INFO->AirspeedAvailable = TRUE; else GPS_INFO->AirspeedAvailable = FALSE; } else GPS_INFO->AirspeedAvailable = FALSE; TriggerVarioUpdate(); return TRUE; }
static BOOL PILC(PDeviceDescriptor_t d, TCHAR *String, NMEA_INFO *GPS_INFO) { TCHAR ctemp[80]; NMEAParser::ExtractParameter(String,ctemp,0); if (_tcscmp(ctemp,_T("PDA1"))==0) { NMEAParser::ExtractParameter(String,ctemp,1); if (d == pDevPrimaryBaroSource) { UpdateBaroSource( GPS_INFO, ILEC, AltitudeToQNHAltitude(StrToDouble(ctemp, NULL))); } NMEAParser::ExtractParameter(String,ctemp,2); GPS_INFO->Vario = StrToDouble(ctemp,NULL); NMEAParser::ExtractParameter(String,ctemp,3); // wind direction, integer double wfrom; wfrom = StrToDouble(ctemp,NULL); //@ could also be the NMEA checksum! NMEAParser::ExtractParameter(String,ctemp,4); // wind speed kph integer if (_tcslen(ctemp)!=0) { double wspeed, wconfidence; wspeed = StrToDouble(ctemp,NULL); NMEAParser::ExtractParameter(String,ctemp,5); // confidence 0-100 percentage wconfidence = StrToDouble(ctemp,NULL); // StartupStore(_T(".... WIND from %.0f speed=%.0f kph confidence=%.0f\n"),wfrom,wspeed,wconfidence); SetWindEstimate(wspeed/TOKPH, wfrom,(int)(wconfidence/100)*10); CALCULATED_INFO.WindSpeed=wspeed/TOKPH; CALCULATED_INFO.WindBearing=wfrom; } // else StartupStore(_T(".. NO WIND\n")); GPS_INFO->VarioAvailable = TRUE; TriggerVarioUpdate(); return TRUE; } if (_tcscmp(ctemp,_T("SET"))==0) { NMEAParser::ExtractParameter(String,ctemp,1); QNH = StrToDouble(ctemp,NULL); // StartupStore(_T("... SET QNH= %.1f\n"),QNH); CAirspaceManager::Instance().QnhChangeNotify(QNH); return TRUE; } // Using the polar requires recalculating polar coefficients internally each time.. no thanks. // if (_tcscmp(ctemp,_T("POLAR"))==0) { } return TRUE; }
//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ /// Parses LXWP0 sentence. /// /// @param d device descriptor /// @param sentence received NMEA sentence /// @param info GPS info to be updated /// /// @retval true if the sentence has been parsed /// //static bool DevLXMiniMap::LXWP0(PDeviceDescriptor_t d, const TCHAR* sentence, NMEA_INFO* info) { // $LXWP0,logger_stored, airspeed, airaltitude, // v1[0],v1[1],v1[2],v1[3],v1[4],v1[5], hdg, windspeed*CS<CR><LF> // // 0 loger_stored : [Y|N] (not used in LX1600) // 1 IAS [km/h] ----> Condor uses TAS! // 2 baroaltitude [m] // 3-8 vario values [m/s] (last 6 measurements in last second) // 9 heading of plane (not used in LX1600) // 10 windcourse [deg] (not used in LX1600) // 11 windspeed [km/h] (not used in LX1600) // // e.g.: // $LXWP0,Y,222.3,1665.5,1.71,,,,,,239,174,10.1 TICKER = GetTickCount(); double alt, airspeed; if (ParToDouble(sentence, 1, &airspeed)) { airspeed /= TOKPH; info->TrueAirspeed = airspeed; info->AirspeedAvailable = TRUE; } if (ParToDouble(sentence, 2, &alt)) { info->IndicatedAirspeed = airspeed / AirDensityRatio(alt); if (d == pDevPrimaryBaroSource) { UpdateQNH(CalculateQNH(alt, alt + AltOffset)); UpdateBaroSource(info, 0, d, alt + AltOffset); /* if(FirstCheckBaroAlt) { FirstCheckBaroAlt = false; InputEvents::eventSetup(_T("Basic")); }*/ } } if (ParToDouble(sentence, 3, &info->Vario)) info->VarioAvailable = TRUE; if (ParToDouble(sentence, 10, &info->ExternalWindDirection) && ParToDouble(sentence, 11, &info->ExternalWindSpeed)) info->ExternalWindAvailable = TRUE; TriggerVarioUpdate(); return(true); } // LXWP0()
bool DevLXV7_EXP::PLXVF(PDeviceDescriptor_t d, const TCHAR* sentence, NMEA_INFO* info) { double alt, airspeed; if (ParToDouble(sentence, 1, &info->AccelX)) if (ParToDouble(sentence, 2, &info->AccelY)) if (ParToDouble(sentence, 3, &info->AccelZ)) info->AccelerationAvailable = true; if (ParToDouble(sentence, 5, &airspeed)) { // airspeed = 135.0/TOKPH; info->IndicatedAirspeed = airspeed; info->AirspeedAvailable = TRUE; } if (ParToDouble(sentence, 6, &alt)) { UpdateBaroSource( info, 0, d, AltitudeToQNHAltitude(alt)); info->TrueAirspeed = airspeed * AirDensityRatio(alt); } if (ParToDouble(sentence, 4, &info->Vario)) { info->VarioAvailable = TRUE; TriggerVarioUpdate(); } // Get STF switch double fTmp; if (ParToDouble(sentence, 7, &fTmp)) { int iTmp = (int)(fTmp+0.1); EnableExternalTriggerCruise = true; static int iOldVarioSwitch=0; if(iTmp != iOldVarioSwitch) { iOldVarioSwitch = iTmp; if(iTmp==1) { ExternalTriggerCruise = true; ExternalTriggerCircling = false; } else { ExternalTriggerCruise = false; ExternalTriggerCircling = true; } } } return(true); } // PLXVF()
void NMEAParser::Reset(void) { // clear status nmeaParser1._Reset(); nmeaParser2._Reset(); // trigger updates TriggerGPSUpdate(); TriggerVarioUpdate(); }
static BOOL LK8EX1(PDeviceDescriptor_t d, TCHAR *String, NMEA_INFO *pGPS) { TCHAR ctemp[80]; bool havebaro=false; // HPA from the pressure sensor NMEAParser::ExtractParameter(String,ctemp,0); double ps = StrToDouble(ctemp,NULL); if (ps!=999999) { UpdateBaroSource( pGPS, 0,d, StaticPressureToAltitude(ps)); havebaro = true; } // QNE if (!havebaro) { NMEAParser::ExtractParameter(String,ctemp,1); double ba = StrToDouble(ctemp,NULL); if (ba!=99999) { UpdateBaroSource( pGPS, 0,d, AltitudeToQNHAltitude(ba)); } } // VARIO NMEAParser::ExtractParameter(String,ctemp,2); double va = StrToDouble(ctemp,NULL); if (va != 9999) { pGPS->Vario = va/100; pGPS->VarioAvailable = TRUE; } else pGPS->VarioAvailable = FALSE; // OAT NMEAParser::ExtractParameter(String,ctemp,3); double ta = StrToDouble(ctemp,NULL); if (ta != 99) { pGPS->OutsideAirTemperature = ta; pGPS->TemperatureAvailable=TRUE; } // BATTERY PERCENTAGES NMEAParser::ExtractParameter(String,ctemp,4); double voa = StrToDouble(ctemp,NULL); if (voa!=999) { pGPS->ExtBatt1_Voltage = voa; } // currently unused in LK, but ready for next future TriggerVarioUpdate(); return TRUE; }
/** * Main loop of the CalculationThread */ void CalculationThread::tick() { const bool gps_updated = gps_trigger.test(); // update and transfer master info to glide computer { ScopeLock protect(mutexBlackboard); const GlidePolar &glide_polar = glide_computer.get_glide_polar(); // if (new GPS data available) if (gps_updated) device_blackboard.tick(glide_polar); else device_blackboard.tick_fast(glide_polar); // Copy data from DeviceBlackboard to GlideComputerBlackboard glide_computer.ReadBlackboard(device_blackboard.Basic()); // Copy settings form SettingsComputerBlackboard to GlideComputerBlackboard glide_computer.ReadSettingsComputer(device_blackboard.SettingsComputer()); // Copy mapprojection from MapProjectionBlackboard to GlideComputerBlackboard glide_computer.ReadMapProjection(device_blackboard.MapProjection()); } // if (time advanced and slow calculations need to be updated) if (gps_updated && glide_computer.ProcessGPS()) // do slow calculations glide_computer.ProcessIdle(); // values changed, so copy them back now: ONLY CALCULATED INFO // should be changed in DoCalculations, so we only need to write // that one back (otherwise we may write over new data) { ScopeLock protect(mutexBlackboard); device_blackboard.ReadBlackboard(glide_computer.Calculated()); if (device_blackboard.Basic().MacCready != glide_computer.Basic().MacCready) device_blackboard.SetMC(glide_computer.Basic().MacCready); } // if (new GPS data) if (gps_updated) { // inform map new data is ready #ifdef ENABLE_OPENGL CommonInterface::main_window.map.invalidate(); #else draw_thread->trigger_redraw(); #endif if (!glide_computer.Basic().TotalEnergyVarioAvailable) // emulate vario update TriggerVarioUpdate(); } }
//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ /// Parses LXWP0 sentence. /// /// @param d device descriptor /// @param sentence received NMEA sentence /// @param info GPS info to be updated /// /// @retval true if the sentence has been parsed /// //static bool DevLX::LXWP0(PDeviceDescriptor_t d, const TCHAR* sentence, NMEA_INFO* info) { // $LXWP0,logger_stored, airspeed, airaltitude, // v1[0],v1[1],v1[2],v1[3],v1[4],v1[5], hdg, windspeed*CS<CR><LF> // // 0 loger_stored : [Y|N] (not used in LX1600) // 1 IAS [km/h] ----> Condor uses TAS! // 2 baroaltitude [m] // 3-8 vario values [m/s] (last 6 measurements in last second) // 9 heading of plane (not used in LX1600) // 10 windcourse [deg] (not used in LX1600) // 11 windspeed [km/h] (not used in LX1600) // // e.g.: // $LXWP0,Y,222.3,1665.5,1.71,,,,,,239,174,10.1 double alt=0, airspeed=0; if (ParToDouble(sentence, 1, &airspeed)) { airspeed /= TOKPH; info->TrueAirspeed = airspeed; info->AirspeedAvailable = TRUE; } if (ParToDouble(sentence, 2, &alt)) { if (airspeed>0) { LKASSERT(AirDensityRatio(alt)!=0); info->IndicatedAirspeed = airspeed / AirDensityRatio(alt); } UpdateBaroSource( info, 0,d, AltitudeToQNHAltitude(alt)); } if (ParToDouble(sentence, 8, &info->Vario)) /* take the last value to be more recent */ info->VarioAvailable = TRUE; if (ParToDouble(sentence, 9, &info->MagneticHeading)) info->MagneticHeadingAvailable=TRUE; if (ParToDouble(sentence, 10, &info->ExternalWindDirection) && ParToDouble(sentence, 11, &info->ExternalWindSpeed)) { info->ExternalWindSpeed /= TOKPH; /* convert to m/s */ info->ExternalWindAvailable = TRUE; } TriggerVarioUpdate(); return(true); } // LXWP0()
//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ /// Parses LXWP0 sentence. /// /// @param d device descriptor /// @param sentence received NMEA sentence /// @param info GPS info to be updated /// /// @retval true if the sentence has been parsed /// //static bool DevLX16xx::LXWP0(PDeviceDescriptor_t d, const TCHAR* sentence, NMEA_INFO* info) { // $LXWP0,logger_stored, airspeed, airaltitude, // v1[0],v1[1],v1[2],v1[3],v1[4],v1[5], hdg, windspeed*CS<CR><LF> // // 0 loger_stored : [Y|N] (not used in LX1600) // 1 IAS [km/h] ----> Condor uses TAS! // 2 baroaltitude [m] // 3-8 vario values [m/s] (last 6 measurements in last second) // 9 heading of plane (not used in LX1600) // 10 windcourse [deg] (not used in LX1600) // 11 windspeed [km/h] (not used in LX1600) // // e.g.: // $LXWP0,Y,222.3,1665.5,1.71,,,,,,239,174,10.1 double alt, airspeed; if (ParToDouble(sentence, 1, &airspeed)) { airspeed /= TOKPH; info->TrueAirspeed = airspeed; info->AirspeedAvailable = TRUE; } if(LX166AltitudeUpdateTimeout >0) LX166AltitudeUpdateTimeout--; else if (ParToDouble(sentence, 2, &alt)) { LX16xxAlt = (int) alt; info->IndicatedAirspeed = airspeed / AirDensityRatio(alt); UpdateBaroSource( info, 0,d, AltitudeToQNHAltitude(alt)); } if (ParToDouble(sentence, 3, &info->Vario)) info->VarioAvailable = TRUE; /* if (ParToDouble(sentence, 10, &info->ExternalWindDirection) && ParToDouble(sentence, 11, &info->ExternalWindSpeed)) info->ExternalWindAvailable = TRUE; */ TriggerVarioUpdate(); return(true); } // LXWP0()
static bool LXWP0(NMEAInputLine &line, NMEA_INFO *GPS_INFO, bool enable_baro) { /* $LXWP0,Y,222.3,1665.5,1.71,,,,,,239,174,10.1 0 loger_stored (Y/N) 1 IAS (kph) ----> Condor uses TAS! 2 baroaltitude (m) 3-8 vario (m/s) (last 6 measurements in last second) 9 heading of plane 10 windcourse (deg) 11 windspeed (kph) */ line.skip(); fixed airspeed; GPS_INFO->AirspeedAvailable = line.read_checked(airspeed); fixed alt = line.read(fixed_zero); if (GPS_INFO->AirspeedAvailable) { GPS_INFO->TrueAirspeed = Units::ToSysUnit(airspeed, unKiloMeterPerHour); GPS_INFO->IndicatedAirspeed = GPS_INFO->TrueAirspeed / AtmosphericPressure::AirDensityRatio(alt); } if (enable_baro) { GPS_INFO->BaroAltitudeAvailable = true; GPS_INFO->BaroAltitude = alt; // ToDo check if QNH correction is needed! } GPS_INFO->TotalEnergyVarioAvailable = line.read_checked(GPS_INFO->TotalEnergyVario); line.skip(6); GPS_INFO->ExternalWindAvailable = ReadSpeedVector(line, GPS_INFO->wind); TriggerVarioUpdate(); return true; }
static BOOL cLXWP0(PDeviceDescriptor_t d, const TCHAR *String, NMEA_INFO *GPS_INFO) { TCHAR ctemp[80]; /* $LXWP0,Y,222.3,1665.5,1.71,,,,,,239,174,10.1 0 loger_stored (Y/N) 1 IAS (kph) ----> Condor uses TAS! 2 baroaltitude (m) 3 vario (m/s) 4-8 unknown 9 heading of plane 10 windcourse (deg) 11 windspeed (kph) */ double alt, airspeed; NMEAParser::ExtractParameter(String,ctemp,1); airspeed = StrToDouble(ctemp,NULL)/TOKPH; NMEAParser::ExtractParameter(String,ctemp,2); alt = StrToDouble(ctemp,NULL); GPS_INFO->IndicatedAirspeed = airspeed/AirDensityRatio(alt); GPS_INFO->TrueAirspeed = airspeed; if (d == pDevPrimaryBaroSource){ GPS_INFO->BaroAltitudeAvailable = TRUE; GPS_INFO->BaroAltitude = alt; // ToDo check if QNH correction is needed! } NMEAParser::ExtractParameter(String,ctemp,3); GPS_INFO->Vario = StrToDouble(ctemp,NULL); GPS_INFO->AirspeedAvailable = TRUE; GPS_INFO->VarioAvailable = TRUE; TriggerVarioUpdate(); return TRUE; }
// TASMAN instruments support for Tasman Flight Pack model Fp10 BOOL NMEAParser::PTAS1(TCHAR *String, TCHAR **params, size_t nparams, NMEA_INFO *pGPS) { double wnet,baralt,vtas; wnet = (StrToDouble(params[0],NULL)-200)/(10*TOKNOTS); baralt = max(0.0, (StrToDouble(params[2],NULL)-2000)/TOFEET); vtas = StrToDouble(params[3],NULL)/TOKNOTS; pGPS->AirspeedAvailable = TRUE; pGPS->TrueAirspeed = vtas; pGPS->VarioAvailable = TRUE; pGPS->Vario = wnet; UpdateBaroSource(pGPS, BARO__TASMAN, NULL, AltitudeToQNHAltitude(baralt)); pGPS->IndicatedAirspeed = vtas/AirDensityRatio(baralt); TASAvailable = true; // 100411 TriggerVarioUpdate(); return FALSE; }
bool PLXVF(PDeviceDescriptor_t d, const TCHAR* sentence, NMEA_INFO* info) { double alt, airspeed; if (ParToDouble(sentence, 5, &airspeed)) { info->IndicatedAirspeed = airspeed; info->AirspeedAvailable = TRUE; } if (ParToDouble(sentence, 6, &alt)) { UpdateBaroSource( info, 0, d, AltitudeToQNHAltitude(alt)); info->TrueAirspeed = airspeed * AirDensityRatio(alt); } if (ParToDouble(sentence, 4, &info->Vario)) { info->VarioAvailable = TRUE; TriggerVarioUpdate(); } return(true); }
static bool VARIO(NMEAInputLine &line, NMEA_INFO *GPS_INFO) { // $VARIO,fPressure,fVario,Bat1Volts,Bat2Volts,BatBank,TempSensor1,TempSensor2*CS fixed value; if (line.read_checked(value)) { GPS_INFO->BaroAltitude = GPS_INFO->pressure.StaticPressureToQNHAltitude(value * 100); GPS_INFO->BaroAltitudeAvailable = true; } if (line.read_checked(value)) { // vario is in dm/s GPS_INFO->TotalEnergyVario = value / 10; GPS_INFO->TotalEnergyVarioAvailable = true; } TriggerVarioUpdate(); return true; }
void DeviceBlackboard::Merge() { real_data.reset(); for (unsigned i = 0; i < NUMDEV; ++i) { per_device_data[i].expire(); real_data.complement(per_device_data[i]); } if (replay_data.Connected) { replay_data.expire(); SetBasic() = replay_data; } else if (simulator_data.Connected) { simulator_data.expire(); SetBasic() = simulator_data; } else { SetBasic() = real_data; } computer.Fill(SetBasic(), SettingsComputer()); ProcessFLARM(); if (last_location_available != Basic().LocationAvailable) { last_location_available = Basic().LocationAvailable; TriggerGPSUpdate(); } else if (last_vario_counter != Basic().VarioCounter) { last_vario_counter = Basic().VarioCounter; TriggerGPSUpdate(); } if (last_te_vario_available != Basic().TotalEnergyVarioAvailable || last_netto_vario_available != Basic().NettoVarioAvailable) { last_te_vario_available = Basic().TotalEnergyVarioAvailable; last_netto_vario_available = Basic().NettoVarioAvailable; TriggerVarioUpdate(); } }
static bool PZAN2(NMEAInputLine &line, NMEA_INFO *GPS_INFO) { fixed vtas, wnet; if (line.read_checked(vtas)) { vtas /= fixed(3.6); // km/h -> m/s GPS_INFO->TrueAirspeed = vtas; GPS_INFO->IndicatedAirspeed = GPS_INFO->BaroAltitudeAvailable ? vtas / AtmosphericPressure::AirDensityRatio(GPS_INFO->BaroAltitude) : fixed_zero; GPS_INFO->AirspeedAvailable = true; } if (line.read_checked(wnet)) { GPS_INFO->TotalEnergyVario = (wnet - fixed(10000)) / 100; GPS_INFO->TotalEnergyVarioAvailable = true; } TriggerVarioUpdate(); return true; }
//////////////////////////////////////////////////////////////////////////////////////////////////////// // $PCPROBE,T,Q0,Q1,Q2,Q3,ax,ay,az,temp,rh,batt,delta_press,abs_press,C, // - "T" after "$PCPROBE" indicates that the string contains data. Data are represented as signed, // 16-bit hexadecimal integers. The only exception is abs_press which is in signed 24-bits hex // format. // - Q0, Q1, Q2, Q3: 3D orientation of the C-Probe in quaternion format. Heading, pitch, and roll can // be calculated as follows: // q0 = Q0 * 0.001; // q1 = Q1 * 0.001; // q2 = Q2 * 0.001; // q3 = Q3 * 0.001; // sin_pitch = -2 * (q0 * q2 - q3 * q1); // if sin_pitch > 1 or sin_pitch < -1, discard the data // pitch = asin(sin_pitch); // heading = M_PI + atan2(2*(q1 * q2 + q3 * q0), q3 * q3 - q0 * q0 - q1 * q1 + q2 * q2); // roll = atan2( 2 * (q0 * q1 + q3 * q2), q3 * q3 + q0 * q0 - q1 * q1 - q2 * q2); // - ax, ay, az: x, y, z components of the acceleration in units of 0.001 g. // - temp: temperature in units of 0.1°C. // - rh: relative humidity in units of 0.1%. // - batt: battery level from 0 to 100%. // - delta_press: differential pressure (dynamic - static) in units of 0.1 Pa. // - abs_press: absolute pressure in units of 1/400 Pa // - C: is transmitted only if the C-Probe is being charged. In this case, heat produced by the charging // process is likely to affect the readings of the temperature and humidity sensors. //////////////////////////////////////////////////////////////////////////////////////////////////////// BOOL CDevCProbe::ParseData( wnmeastring& wiss, NMEA_INFO *pINFO ) { double q0 = int16toDouble(HexStrToInt(wiss.GetNextString())) * 0.001; double q1 = int16toDouble(HexStrToInt(wiss.GetNextString())) * 0.001; double q2 = int16toDouble(HexStrToInt(wiss.GetNextString())) * 0.001; double q3 = int16toDouble(HexStrToInt(wiss.GetNextString())) * 0.001; double sin_pitch = -2 * (q0 * q2 - q3 * q1); // if sin_pitch > 1 or sin_pitch < -1, discard the data if(sin_pitch < 1.0 && sin_pitch > -1.0){ pINFO->MagneticCompassAvailable=TRUE; pINFO->Heading = (PI + atan2(2*(q1 * q2 + q3 * q0), q3 * q3 - q0 * q0 - q1 * q1 + q2 * q2))*RAD_TO_DEG; pINFO->GyroscopeAvailable=TRUE; pINFO->Pitch = asin(sin_pitch)*RAD_TO_DEG; pINFO->Roll = atan2( 2 * (q0 * q1 + q3 * q2), q3 * q3 + q0 * q0 - q1 * q1 - q2 * q2)*RAD_TO_DEG; }else{ pINFO->MagneticCompassAvailable=FALSE; pINFO->GyroscopeAvailable=FALSE; } pINFO->AccelerationAvailable=TRUE; pINFO->AccelX = int16toDouble(HexStrToInt(wiss.GetNextString())) * 0.001; pINFO->AccelY = int16toDouble(HexStrToInt(wiss.GetNextString())) * 0.001; pINFO->AccelZ = int16toDouble(HexStrToInt(wiss.GetNextString())) * 0.001; pINFO->Gload = sqrt(pow(pINFO->AccelX,2.0)+pow(pINFO->AccelY,2.0)+pow(pINFO->AccelZ,2.0)); pINFO->TemperatureAvailable=TRUE; pINFO->OutsideAirTemperature = int16toDouble(HexStrToInt(wiss.GetNextString())) * 0.1; pINFO->HumidityAvailable=TRUE; pINFO->RelativeHumidity = int16toDouble(HexStrToInt(wiss.GetNextString())) * 0.1; pINFO->ExtBatt1_Voltage = int16toDouble(HexStrToInt(wiss.GetNextString()))+1000; double delta_press = int16toDouble(HexStrToInt(wiss.GetNextString())) / 10.0 ; double abs_press = int24toDouble(HexStrToInt(wiss.GetNextString())) / 400.0; if(abs_press > 0.0) { UpdateBaroSource(pINFO, BARO__CPROBE, NULL, StaticPressureToAltitude(abs_press*100)); } else { if(pINFO->BaroAltitudeAvailable) { abs_press = QNHAltitudeToStaticPressure(pINFO->BaroAltitude); } else { abs_press = QNHAltitudeToStaticPressure(pINFO->Altitude); } } if(delta_press>=0){ pINFO->AirspeedAvailable = TRUE; pINFO->IndicatedAirspeed = sqrt(2*delta_press); pINFO->TrueAirspeed = TrueAirSpeed(delta_press, pINFO->RelativeHumidity, pINFO->OutsideAirTemperature, abs_press>0.0?abs_press*100:101325.0); } if(*(wiss.GetNextString()) == L'C'){ pINFO->ExtBatt1_Voltage *= -1; } LockDeviceData(); m_delta_press = delta_press; m_abs_press = abs_press; UnlockDeviceData(); TriggerVarioUpdate(); return TRUE; }
//////////////////////////////////////////////////////////////////////////////////////////////////////// // $PCPROBE,T,Q0,Q1,Q2,Q3,ax,ay,az,temp,rh,batt,delta_press,abs_press,C, // - "T" after "$PCPROBE" indicates that the string contains data. Data are represented as signed, // 16-bit hexadecimal integers. The only exception is abs_press which is in signed 24-bits hex // format. // - Q0, Q1, Q2, Q3: 3D orientation of the C-Probe in quaternion format. Heading, pitch, and roll can // be calculated as follows: // q0 = Q0 * 0.001; // q1 = Q1 * 0.001; // q2 = Q2 * 0.001; // q3 = Q3 * 0.001; // sin_pitch = -2 * (q0 * q2 - q3 * q1); // if sin_pitch > 1 or sin_pitch < -1, discard the data // pitch = asin(sin_pitch); // heading = M_PI + atan2(2*(q1 * q2 + q3 * q0), q3 * q3 - q0 * q0 - q1 * q1 + q2 * q2); // roll = atan2( 2 * (q0 * q1 + q3 * q2), q3 * q3 + q0 * q0 - q1 * q1 - q2 * q2); // - ax, ay, az: x, y, z components of the acceleration in units of 0.001 g. // - temp: temperature in units of 0.1°C. // - rh: relative humidity in units of 0.1%. // - batt: battery level from 0 to 100%. // - delta_press: differential pressure (dynamic - static) in units of 0.1 Pa. // - abs_press: absolute pressure in units of 1/400 Pa // - C: is transmitted only if the C-Probe is being charged. In this case, heat produced by the charging // process is likely to affect the readings of the temperature and humidity sensors. //////////////////////////////////////////////////////////////////////////////////////////////////////// BOOL CDevCProbe::ParseData( tnmeastring& wiss, NMEA_INFO *pINFO ) { double q0 = int16toDouble(HexStrToInt(wiss.GetNextString())) * 0.001; double q1 = int16toDouble(HexStrToInt(wiss.GetNextString())) * 0.001; double q2 = int16toDouble(HexStrToInt(wiss.GetNextString())) * 0.001; double q3 = int16toDouble(HexStrToInt(wiss.GetNextString())) * 0.001; double sin_pitch = -2 * (q0 * q2 - q3 * q1); // if sin_pitch > 1 or sin_pitch < -1, discard the data if(sin_pitch < 1.0 && sin_pitch > -1.0){ pINFO->MagneticHeadingAvailable=TRUE; pINFO->MagneticHeading = (PI + atan2(2*(q1 * q2 + q3 * q0), q3 * q3 - q0 * q0 - q1 * q1 + q2 * q2))*RAD_TO_DEG; pINFO->GyroscopeAvailable=TRUE; pINFO->Pitch = asin(sin_pitch)*RAD_TO_DEG; pINFO->Roll = atan2( 2 * (q0 * q1 + q3 * q2), q3 * q3 + q0 * q0 - q1 * q1 - q2 * q2)*RAD_TO_DEG; }else{ pINFO->MagneticHeadingAvailable=FALSE; pINFO->GyroscopeAvailable=FALSE; } pINFO->AccelerationAvailable=TRUE; pINFO->AccelX = int16toDouble(HexStrToInt(wiss.GetNextString())) * 0.001; pINFO->AccelY = int16toDouble(HexStrToInt(wiss.GetNextString())) * 0.001; pINFO->AccelZ = int16toDouble(HexStrToInt(wiss.GetNextString())) * 0.001; pINFO->TemperatureAvailable=TRUE; pINFO->OutsideAirTemperature = int16toDouble(HexStrToInt(wiss.GetNextString())) * 0.1; pINFO->HumidityAvailable=TRUE; pINFO->RelativeHumidity = int16toDouble(HexStrToInt(wiss.GetNextString())) * 0.1; pINFO->ExtBatt1_Voltage = int16toDouble(HexStrToInt(wiss.GetNextString()))+1000; double delta_press = int16toDouble(HexStrToInt(wiss.GetNextString())) * 1.0/10.0 ; double abs_press = int24toDouble(HexStrToInt(wiss.GetNextString())) * (1.0/4.0); LockDeviceData(); m_delta_press = delta_press; m_abs_press = abs_press; UnlockDeviceData(); // the highest sea level air pressure ever recorded was 1084 mb (32.01 in.) // at Siberia associated with an extremely cold air mass. if(abs_press > 0.0 && abs_press < 115000.0) { UpdateBaroSource(pINFO, BARO__CPROBE, NULL, StaticPressureToAltitude(abs_press)); } else { if(pINFO->BaroAltitudeAvailable) { abs_press = QNHAltitudeToStaticPressure(pINFO->BaroAltitude); } else { abs_press = QNHAltitudeToStaticPressure(pINFO->Altitude); } } if(delta_press>0.0){ pINFO->AirspeedAvailable = TRUE; pINFO->IndicatedAirspeed = sqrt(2 * delta_press / 1.225); pINFO->TrueAirspeed = TrueAirSpeed(delta_press, pINFO->RelativeHumidity, pINFO->OutsideAirTemperature, abs_press>0.0?abs_press:101325.0); } if(*(wiss.GetNextString()) == L'C'){ pINFO->ExtBatt1_Voltage *= -1; } TriggerVarioUpdate(); return TRUE; }
static BOOL FLYSEN(PDeviceDescriptor_t d, TCHAR *String, NMEA_INFO *pGPS) { TCHAR ctemp[80]; double vtas; static int offset=-1; d->nmeaParser.connected = true; // firmware 3.31h no offset // firmware 3.32 1 offset // Determine firmware version, assuming it will not change in the session! if (offset<0) { NMEAParser::ExtractParameter(String,ctemp,8); if ( (_tcscmp(ctemp,_T("A"))==0) || (_tcscmp(ctemp,_T("V"))==0)) offset=0; else { NMEAParser::ExtractParameter(String,ctemp,9); if ( (_tcscmp(ctemp,_T("A"))==0) || (_tcscmp(ctemp,_T("V"))==0)) offset=1; else return TRUE; } } // VOID GPS SIGNAL NMEAParser::ExtractParameter(String,ctemp,8+offset); if (_tcscmp(ctemp,_T("V"))==0) { pGPS->NAVWarning=true; // GPSCONNECT=false; // 121127 NO!! goto label_nogps; } // ------------------------ double tmplat; double tmplon; NMEAParser::ExtractParameter(String,ctemp,1+offset); tmplat = MixedFormatToDegrees(StrToDouble(ctemp, NULL)); NMEAParser::ExtractParameter(String,ctemp,2+offset); tmplat = NorthOrSouth(tmplat, ctemp[0]); NMEAParser::ExtractParameter(String,ctemp,3+offset); tmplon = MixedFormatToDegrees(StrToDouble(ctemp, NULL)); NMEAParser::ExtractParameter(String,ctemp,4+offset); tmplon = EastOrWest(tmplon,ctemp[0]); if (!((tmplat == 0.0) && (tmplon == 0.0))) { pGPS->Latitude = tmplat; pGPS->Longitude = tmplon; pGPS->NAVWarning=false; } // GPS SPEED NMEAParser::ExtractParameter(String,ctemp,6+offset); pGPS->Speed = StrToDouble(ctemp,NULL)/10; // TRACK BEARING if (pGPS->Speed>1.0) { NMEAParser::ExtractParameter(String,ctemp,5+offset); pGPS->TrackBearing = AngleLimit360(StrToDouble(ctemp, NULL)); } // HGPS NMEAParser::ExtractParameter(String,ctemp,7+offset); pGPS->Altitude = StrToDouble(ctemp,NULL); // ------------------------ label_nogps: // SATS NMEAParser::ExtractParameter(String,ctemp,9+offset); pGPS->SatellitesUsed = (int) StrToDouble(ctemp,NULL); // DATE // Firmware 3.32 has got the date if (offset>0) { NMEAParser::ExtractParameter(String,ctemp,0); long gy, gm, gd; TCHAR *Stop; gy = _tcstol(&ctemp[4], &Stop, 10) + 2000; ctemp[4] = '\0'; gm = _tcstol(&ctemp[2], &Stop, 10); ctemp[2] = '\0'; gd = _tcstol(&ctemp[0], &Stop, 10); if ( ((gy > 1980) && (gy <2100) ) && (gm != 0) && (gd != 0) ) { pGPS->Year = gy; pGPS->Month = gm; pGPS->Day = gd; } } // TIME // ignoring 00:00.00 // We need to manage UTC time #ifndef OLD_TIME_MODIFY static int StartDay=-1; if (pGPS->SatellitesUsed>0) { NMEAParser::ExtractParameter(String,ctemp,0+offset); pGPS->Time = TimeModify(ctemp, pGPS, StartDay); } // TODO : check if TimeHasAdvanced check is needed (cf. Parser.cpp) #else NMEAParser::ExtractParameter(String,ctemp,0+offset); double fixTime = StrToDouble(ctemp,NULL); static int day_difference=0, previous_months_day_difference=0; static int startday=-1; if (fixTime>0 && pGPS->SatellitesUsed>0) { double hours, mins,secs; hours = fixTime / 10000; pGPS->Hour = (int)hours; mins = fixTime / 100; mins = mins - (pGPS->Hour*100); pGPS->Minute = (int)mins; secs = fixTime - (pGPS->Hour*10000) - (pGPS->Minute*100); pGPS->Second = (int)secs; fixTime = secs + (pGPS->Minute*60) + (pGPS->Hour*3600); if ((startday== -1) && (pGPS->Day != 0)) { if (offset) StartupStore(_T(". FLYSEN First GPS DATE: %d-%d-%d%s"), pGPS->Year, pGPS->Month, pGPS->Day,NEWLINE); else StartupStore(_T(". FLYSEN No Date, using PNA GPS DATE: %d-%d-%d%s"), pGPS->Year, pGPS->Month, pGPS->Day,NEWLINE); startday = pGPS->Day; day_difference=0; previous_months_day_difference=0; } if (startday != -1) { if (pGPS->Day < startday) { // detect change of month (e.g. day=1, startday=26) previous_months_day_difference=day_difference+1; day_difference=0; startday = pGPS->Day; StartupStore(_T(". FLYSEN Change GPS DATE to NEW MONTH: %d-%d-%d (%d days running)%s"), pGPS->Year, pGPS->Month, pGPS->Day,previous_months_day_difference,NEWLINE); } if ( (pGPS->Day-startday)!=day_difference) { StartupStore(_T(". FLYSEN Change GPS DATE: %d-%d-%d%s"), pGPS->Year, pGPS->Month, pGPS->Day,NEWLINE); } day_difference = pGPS->Day-startday; if ((day_difference+previous_months_day_difference)>0) { fixTime += (day_difference+previous_months_day_difference) * 86400; } } pGPS->Time = fixTime; } #endif // HPA from the pressure sensor // NMEAParser::ExtractParameter(String,ctemp,10+offset); // double ps = StrToDouble(ctemp,NULL)/100; // pGPS->BaroAltitude = (1 - pow(fabs(ps / QNH), 0.190284)) * 44307.69; // HBAR 1013.25 NMEAParser::ExtractParameter(String,ctemp,11+offset); double palt=StrToDouble(ctemp,NULL); UpdateBaroSource( pGPS, 0,d, QNEAltitudeToQNHAltitude(palt)); // VARIO NMEAParser::ExtractParameter(String,ctemp,12+offset); pGPS->Vario = StrToDouble(ctemp,NULL)/100; // TAS NMEAParser::ExtractParameter(String,ctemp,13+offset); vtas=StrToDouble(ctemp,NULL)/10; pGPS->IndicatedAirspeed = vtas/AirDensityRatio(palt); pGPS->TrueAirspeed = vtas; if (pGPS->IndicatedAirspeed >0) pGPS->AirspeedAvailable = TRUE; else pGPS->AirspeedAvailable = FALSE; // ignore n.14 airspeed source // OAT NMEAParser::ExtractParameter(String,ctemp,15+offset); pGPS->OutsideAirTemperature = StrToDouble(ctemp,NULL); pGPS->TemperatureAvailable=TRUE; // ignore n.16 baloon temperature // BATTERY PERCENTAGES NMEAParser::ExtractParameter(String,ctemp,17+offset); pGPS->ExtBatt1_Voltage = StrToDouble(ctemp,NULL)+1000; NMEAParser::ExtractParameter(String,ctemp,18+offset); pGPS->ExtBatt2_Voltage = StrToDouble(ctemp,NULL)+1000; pGPS->VarioAvailable = TRUE; // currently unused in LK, but ready for next future TriggerVarioUpdate(); TriggerGPSUpdate(); return TRUE; }
DWORD CalculationThread (LPVOID lpvoid) { (void)lpvoid; bool needcalculationsslow; NMEA_INFO tmpGPS; DERIVED_INFO tmpCALCULATED; FILETIME CreationTime, ExitTime, StartKernelTime, EndKernelTime, StartUserTime, EndUserTime ; needcalculationsslow = false; // let's not create a deadlock here, setting the go after another race condition goCalculationThread=true; // 091119 CHECK // wait for proper startup signal while (!MapWindow::IsDisplayRunning()) { Sleep(100); } // while (!goCalculating) Sleep(100); Sleep(1000); // 091213 BUGFIX need to syncronize !!! TOFIX02 TODO while (!MapWindow::CLOSETHREAD) { WaitForSingleObject(dataTriggerEvent, 5000); ResetEvent(dataTriggerEvent); if (MapWindow::CLOSETHREAD) break; // drop out on exit GetThreadTimes( hCalculationThread, &CreationTime, &ExitTime,&StartKernelTime,&StartUserTime); // make local copy before editing... LockFlightData(); FLARM_RefreshSlots(&GPS_INFO); memcpy(&tmpGPS,&GPS_INFO,sizeof(NMEA_INFO)); memcpy(&tmpCALCULATED,&CALCULATED_INFO,sizeof(DERIVED_INFO)); UnlockFlightData(); DoCalculationsVario(&tmpGPS,&tmpCALCULATED); if (!tmpGPS.VarioAvailable) { TriggerVarioUpdate(); // emulate vario update } if(DoCalculations(&tmpGPS,&tmpCALCULATED)){ #if (WINDOWSPC>0) && !TESTBENCH #else if (!INPAN) #endif { MapWindow::MapDirty = true; } needcalculationsslow = true; if (tmpCALCULATED.Circling) MapWindow::mode.Fly(MapWindow::Mode::MODE_FLY_CIRCLING); else if (tmpCALCULATED.FinalGlide) MapWindow::mode.Fly(MapWindow::Mode::MODE_FLY_FINAL_GLIDE); else MapWindow::mode.Fly(MapWindow::Mode::MODE_FLY_CRUISE); } if (MapWindow::CLOSETHREAD) break; // drop out on exit // This is activating another run for Thread Draw TriggerRedraws(&tmpGPS, &tmpCALCULATED); if (MapWindow::CLOSETHREAD) break; // drop out on exit if (SIMMODE) { if (needcalculationsslow || ( ReplayLogger::IsEnabled() ) ) { DoCalculationsSlow(&tmpGPS,&tmpCALCULATED); needcalculationsslow = false; } } else { if (needcalculationsslow) { DoCalculationsSlow(&tmpGPS,&tmpCALCULATED); needcalculationsslow = false; } } if (MapWindow::CLOSETHREAD) break; // drop out on exit // values changed, so copy them back now: ONLY CALCULATED INFO // should be changed in DoCalculations, so we only need to write // that one back (otherwise we may write over new data) LockFlightData(); memcpy(&CALCULATED_INFO,&tmpCALCULATED,sizeof(DERIVED_INFO)); UnlockFlightData(); // update live tracker with new values // this is a nonblocking call, live tracker runs on different thread LiveTrackerUpdate(&tmpGPS, &tmpCALCULATED); if (FlightDataRecorderActive) UpdateFlightDataRecorder(&tmpGPS,&tmpCALCULATED); if ( (GetThreadTimes( hCalculationThread, &CreationTime, &ExitTime,&EndKernelTime,&EndUserTime)) == 0) { Cpu_Calc=9999; } else { Cpustats(&Cpu_Calc,&StartKernelTime, &EndKernelTime, &StartUserTime, &EndUserTime); } } return 0; }
// // Support for new 2011 Digifly TOURTELL protocol // (Subset of TL1, pending upgrade in june 2011 for all devices) // static BOOL PDGFTTL(PDeviceDescriptor_t d, TCHAR *String, NMEA_INFO *pGPS) { /* $PDGFTTL field example QNE 1013.25 altitude 0 2025 meters QNH altitude 1 2000 meters vario cm/s 2 250 2.5m/s IAS 4 45 kmh netto vario 3 -14 dm/s */ TCHAR ctemp[80]; double vtas, vias; double altqne, altqnh; static bool initqnh=true; NMEAParser::ExtractParameter(String,ctemp,0); altqne = StrToDouble(ctemp,NULL); NMEAParser::ExtractParameter(String,ctemp,1); altqnh = StrToDouble(ctemp,NULL); // AutoQNH will take care of setting an average QNH if nobody does it for a while if (initqnh) { // if digifly has qnh set by user qne and qnh are of course different if (altqne != altqnh) { QNH=FindQNH(altqne,altqnh); CAirspaceManager::Instance().QnhChangeNotify(QNH); StartupStore(_T(". Using Digifly QNH %f%s"),QNH,NEWLINE); initqnh=false; } else { // if locally QNH was set, either by user of by AutoQNH, stop processing QNH from digifly if ( (QNH <= 1012) || (QNH>=1014)) initqnh=false; // else continue entering initqnh until somebody changes qnh in either digifly or lk8000 } } UpdateBaroSource( pGPS, 0,d, AltitudeToQNHAltitude(altqne)); NMEAParser::ExtractParameter(String,ctemp,2); #if 1 pGPS->Vario = StrToDouble(ctemp,NULL)/100; #else double newVario = StrToDouble(ctemp,NULL)/100; pGPS->Vario = LowPassFilter(pGPS->Vario,newVario,0.1); #endif pGPS->VarioAvailable = TRUE; NMEAParser::ExtractParameter(String,ctemp,4); if (ctemp[0] != '\0') { pGPS->NettoVario = StrToDouble(ctemp,NULL)/10; // dm/s pGPS->NettoVarioAvailable = TRUE; } else pGPS->NettoVarioAvailable = FALSE; NMEAParser::ExtractParameter(String,ctemp,4); if (ctemp[0] != '\0') { // we store m/s , so we convert it from kmh vias = StrToDouble(ctemp,NULL)/3.6; if (vias >1) { vtas = vias*AirDensityRatio(pGPS->BaroAltitude); pGPS->TrueAirspeed = vtas; pGPS->IndicatedAirspeed = vias; pGPS->AirspeedAvailable = TRUE; } } else { pGPS->AirspeedAvailable = FALSE; } TriggerVarioUpdate(); return TRUE; }
static BOOL PDGFTL1(PDeviceDescriptor_t d, TCHAR *String, NMEA_INFO *pGPS) { /* $PDGFTL1 field example QNE 1013.25 altitude 0 2025 meters QNH altitude 1 2000 meters vario cm/s 2 250 2.5m/s netto vario 3 -14 dm/s IAS 4 45 kmh ground efficiency 5 134 13:4 GR Wind speed 6 28 kmh Wind direction 7 65 degrees Main lithium battery 3,82 v 8 382 0.01v Backup AA battery 1,53 v 9 153 0.01v 100209 Paolo Ventafridda netto and ias optionals */ TCHAR ctemp[80]; double vtas, vias; double altqne, altqnh; static bool initqnh=true; NMEAParser::ExtractParameter(String,ctemp,0); altqne = StrToDouble(ctemp,NULL); NMEAParser::ExtractParameter(String,ctemp,1); altqnh = StrToDouble(ctemp,NULL); // AutoQNH will take care of setting an average QNH if nobody does it for a while if (initqnh) { // if digifly has qnh set by user qne and qnh are of course different if (altqne != altqnh) { UpdateQNH(FindQNH(altqne,altqnh)); StartupStore(_T(". Using Digifly QNH %f%s"),QNH,NEWLINE); initqnh=false; } else { // if locally QNH was set, either by user of by AutoQNH, stop processing QNH from digifly if ( (QNH <= 1012) || (QNH>=1014)) initqnh=false; // else continue entering initqnh until somebody changes qnh in either digifly or lk8000 } } UpdateBaroSource( pGPS,0, d, AltitudeToQNHAltitude(altqne)); NMEAParser::ExtractParameter(String,ctemp,2); #if 1 pGPS->Vario = StrToDouble(ctemp,NULL)/100; #else double newVario = StrToDouble(ctemp,NULL)/100; pGPS->Vario = LowPassFilter(pGPS->Vario,newVario,0.1); #endif pGPS->VarioAvailable = TRUE; NMEAParser::ExtractParameter(String,ctemp,3); if (ctemp[0] != '\0') { pGPS->NettoVario = StrToDouble(ctemp,NULL)/10; // dm/s pGPS->NettoVarioAvailable = TRUE; } else pGPS->NettoVarioAvailable = FALSE; NMEAParser::ExtractParameter(String,ctemp,4); if (ctemp[0] != '\0') { // we store m/s , so we convert it from kmh vias = StrToDouble(ctemp,NULL)/3.6; if (vias >1) { vtas = vias*AirDensityRatio(altqne); pGPS->TrueAirspeed = vtas; pGPS->IndicatedAirspeed = vias; pGPS->AirspeedAvailable = TRUE; } } else { pGPS->AirspeedAvailable = FALSE; } NMEAParser::ExtractParameter(String,ctemp,8); pGPS->ExtBatt1_Voltage = StrToDouble(ctemp,NULL)/100; NMEAParser::ExtractParameter(String,ctemp,9); pGPS->ExtBatt2_Voltage = StrToDouble(ctemp,NULL)/100; TriggerVarioUpdate(); return TRUE; }