// this is called only when ActiveWayPoint is 0, still waiting for start void CheckStart(NMEA_INFO *Basic, DERIVED_INFO *Calculated, int *LastStartSector) { BOOL StartCrossed= false; if (UseGates()) { #if DEBUGATE StartupStore(_T("... CheckStart Timenow=%d OpenTime=%d CloseTime=%d ActiveGate=%d\n"),LocalTime(),PGOpenTime,PGCloseTime,ActiveGate); #endif int gatetimediff=-1; if ( ActiveGate<0 ) { // init activegate: assign first valid gate, current or future ActiveGate=InitActiveGate(); if (ActiveGate<0||ActiveGate>(PGNumberOfGates-1)) { FailStore(_T("INVALID ActiveGate=%d"),ActiveGate); DoStatusMessage(_T("ERR-430 INVALID ACTIVEGATE: DISABLED")); PGNumberOfGates=0; return; } #if DEBUGATE StartupStore(_T("... CheckStart: INIT ActiveGate=%d\n"),ActiveGate); #endif } else { if (HaveGates()) { gatetimediff=GateTimeDiff(ActiveGate); #if DEBUGATE StartupStore(_T("... CheckStart: ActiveGate=%d RunningGate=%d\n"),ActiveGate,RunningGate()); StartupStore(_T("... CheckStart: gatetimediff=%d\n"),gatetimediff); #endif // a gate can be in the future , or already open! // case: first start, activegate is the first gate if (gatetimediff==0) { #if DEBUGATE StartupStore(_T("... CheckStart: ActiveGate=%d now OPEN\n"),ActiveGate); #endif AlertGateOpen(ActiveGate); // nothing else to do: the current activegate has just open } else { // check that also non-armed start is detected if (ActiveGate<(PGNumberOfGates-1)) { if (GateTimeDiff(ActiveGate+1)==0) { #if DEBUGATE StartupStore(_T("... CheckStart: ActiveGate+1=%d now OPEN\n"),ActiveGate); #endif ActiveGate++; AlertGateOpen(ActiveGate); } } } // now check for special alerts on countdown, only on current armed start if (gatetimediff==3600 && ((PGGateIntervalTime>=70)||ActiveGate==0) ) { // 850 FIRST GATE OPEN IN 1 HOUR DoStatusMessage(gettext(TEXT("_@M850_"))); if (EnableSoundModes) { LKSound(_T("LK_DINGDONG.WAV")); } } if (gatetimediff==1800 && ((PGGateIntervalTime>=45)||ActiveGate==0) ) { // 851 FIRST GATE OPEN IN 30 MINUTES DoStatusMessage(gettext(TEXT("_@M851_"))); if (EnableSoundModes) { LKSound(_T("LK_DINGDONG.WAV")); } } if (gatetimediff==600 && ((PGGateIntervalTime>=15)||ActiveGate==0) ) { // 10 minutes to go // 852 10 MINUTES TO GO DoStatusMessage(gettext(TEXT("_@M852_"))); if (EnableSoundModes) { LKSound(_T("LK_HITONE.WAV")); } } if (gatetimediff==300 && ((PGGateIntervalTime>=10)||ActiveGate==0)) { // 5 minutes to go // 853 5 MINUTES TO GO DoStatusMessage(gettext(TEXT("_@M853_"))); if (EnableSoundModes) { LKSound(_T("LK_HITONE.WAV")); } } if (gatetimediff==60) { // 1 minute to go if (EnableSoundModes) { LKSound(_T("LK_3HITONES.WAV")); } } } // HaveGates } // not init } if (ISPARAGLIDER && PGStartOut) { // start OUT and go in if (!InStartSector(Basic,Calculated,*LastStartSector, &StartCrossed)) { Calculated->IsInSector = false; if (ReadyToStart(Calculated)) { aatdistance.AddPoint(Basic->Longitude, Basic->Latitude, 0); } if (ValidStartSpeed(Basic, Calculated, StartMaxSpeedMargin)) { ReadyToAdvance(Calculated, false, true); } } else Calculated->IsInSector = true; } else { // start IN and go out, OLD CLASSIC MODE if (InStartSector(Basic,Calculated,*LastStartSector, &StartCrossed)) { // InSector check calling this function is resetting IsInSector at each run, so it was false. Calculated->IsInSector = true; if (ReadyToStart(Calculated)) { aatdistance.AddPoint(Basic->Longitude, Basic->Latitude, 0); } // ToLo: we are ready to start even when outside start rules but within margin if (ValidStartSpeed(Basic, Calculated, StartMaxSpeedMargin)) { ReadyToAdvance(Calculated, false, true); } // TODO accuracy: monitor start speed throughout time in start sector } } // end start mode if (StartCrossed && ValidGate() ) { // 100509 #if DEBUGTGATES StartupStore(_T("... CheckStart: start crossed and valid gate!\n")); #endif // ToLo: Check weather speed and height are within the rules or not (zero margin) if(!IsFinalWaypoint() && ValidStartSpeed(Basic, Calculated) && InsideStartHeight(Basic, Calculated)) { // This is set whether ready to advance or not, because it will // appear in the flight log, so if it's valid, it's valid. Calculated->ValidStart = true; if (ReadyToAdvance(Calculated, true, true)) { ActiveWayPoint=0; // enforce this since it may be 1 StartTask(Basic,Calculated, true, true); } if (Calculated->Flying) { Calculated->ValidFinish = false; } // JMW TODO accuracy: This causes Vaverage to go bonkers // if the user has already passed the start // but selects the start // Note: pilot must have armed advance // for the start to be registered // ToLo: If speed and height are outside the rules they must be within the margin... } else { if ((ActiveWayPoint<=1) && !IsFinalWaypoint() && (Calculated->ValidStart==false) && (Calculated->Flying)) { #if 0 // 101014 This is called from wrong thread, and cause bad crashes // moved to new GCE event inside InputEvents - paolo // need to detect bad starts, just to get the statistics // in case the bad start is the best available, or the user // manually started StartTask(Basic, Calculated, false, false); // Calculated->ValidStart = false; bool startTaskAnyway = false; if (ReadyToAdvance(Calculated, true, true)) { dlgStartTaskShowModal(&startTaskAnyway, Calculated->TaskStartTime, Calculated->TaskStartSpeed, Calculated->TaskStartAltitude); if (startTaskAnyway) { ActiveWayPoint=0; // enforce this since it may be 1 StartTask(Basic,Calculated, true, true); } } Calculated->ValidStart = startTaskAnyway; #else // 101014 StartTask(Basic, Calculated, false, false); if (ReadyToAdvance(Calculated, true, true)) { InputEvents::processGlideComputer(GCE_TASK_CONFIRMSTART); } #endif if (Calculated->Flying) { Calculated->ValidFinish = false; } } } } }
void dlgTimeGatesShowModal(void) { WndProperty *wp; TCHAR filename[MAX_PATH]; LocalPathS(filename, TEXT("dlgTimeGates.xml")); wf = dlgLoadFromXML(CallBackTable, filename, hWndMainWindow, TEXT("IDR_XML_TIMEGATES")); if (!wf) return; setVariables(); changed = false; wf->ShowModal(); // TODO enhancement: implement a cancel button that skips all this below after exit. wp = (WndProperty*)wf->FindByName(TEXT("prpPGOptimizeRoute")); if (wp) { if (PGOptimizeRoute != (wp->GetDataField()->GetAsInteger())) { PGOptimizeRoute = (wp->GetDataField()->GetAsInteger()); changed = true; if (ISPARAGLIDER) { if(PGOptimizeRoute) { changed = !AATEnabled; AATEnabled = true; } ClearOptimizedTargetPos(); } } } wp = (WndProperty*)wf->FindByName(TEXT("prpPGNumberOfGates")); if (wp) { if ( PGNumberOfGates != wp->GetDataField()->GetAsInteger()) { PGNumberOfGates = wp->GetDataField()->GetAsInteger(); changed = true; } } wp = (WndProperty*)wf->FindByName(TEXT("prpPGOpenTimeH")); if (wp) { if ( PGOpenTimeH != wp->GetDataField()->GetAsInteger()) { PGOpenTimeH = wp->GetDataField()->GetAsInteger(); changed = true; } } wp = (WndProperty*)wf->FindByName(TEXT("prpPGOpenTimeM")); if (wp) { if ( PGOpenTimeM != wp->GetDataField()->GetAsInteger()) { PGOpenTimeM = wp->GetDataField()->GetAsInteger(); changed = true; } } wp = (WndProperty*)wf->FindByName(TEXT("prpPGCloseTimeH")); if (wp) { if ( PGCloseTimeH != wp->GetDataField()->GetAsInteger()) { PGCloseTimeH = wp->GetDataField()->GetAsInteger(); changed = true; } } wp = (WndProperty*)wf->FindByName(TEXT("prpPGCloseTimeM")); if (wp) { if ( PGCloseTimeM != wp->GetDataField()->GetAsInteger()) { PGCloseTimeM = wp->GetDataField()->GetAsInteger(); changed = true; } } wp = (WndProperty*)wf->FindByName(TEXT("prpPGGateIntervalTime")); if (wp) { if ( PGGateIntervalTime != wp->GetDataField()->GetAsInteger()) { PGGateIntervalTime = wp->GetDataField()->GetAsInteger(); changed = true; } } wp = (WndProperty*)wf->FindByName(TEXT("prpPGStartOut")); if (wp) { if ( PGStartOut != wp->GetDataField()->GetAsInteger()) { PGStartOut = wp->GetDataField()->GetAsInteger(); changed = true; } } if (changed) { InitActiveGate(); } delete wf; wf = NULL; }
// Loads a new task from scratch. // This is called on startup by the even manager because in DEFAULT MENU we have a GCE event // configured to load Default.tsk for STARTUP_SIMULATOR and STARTUP_REAL. // Until we change this, which would be a good thing because these configuration are unnecessary , // we must use the FullResetAsked trick. void LoadNewTask(LPCTSTR szFileName) { TASK_POINT Temp; START_POINT STemp; int i; bool TaskInvalid = false; bool WaypointInvalid = false; bool TaskLoaded = false; char taskinfo[LKPREAMBOLSIZE+1]; // 100207 bool oldversion=false; // 100207 TCHAR taskFileName[MAX_PATH]; LockTaskData(); ClearTask(); if (FullResetAsked) { #if TESTBENCH StartupStore(_T("... LoadNewTask detected FullResetAsked, attempt to load DEMO.TSK\n")); #endif // Clear the flag, forever. FullResetAsked=false; _tcscpy(taskFileName,_T("%LOCAL_PATH%\\\\_Tasks\\DEMO.TSK")); ExpandLocalPath(taskFileName); } else { _tcscpy(taskFileName,szFileName); } StartupStore(_T(". LoadNewTask <%s>%s"),taskFileName,NEWLINE); FILE* stream = _tfopen(taskFileName, _T("rb")); if(stream) { // Defaults int old_StartLine = StartLine; int old_SectorType = SectorType; DWORD old_SectorRadius = SectorRadius; DWORD old_StartRadius = StartRadius; int old_AutoAdvance = AutoAdvance; double old_AATTaskLength = AATTaskLength; BOOL old_AATEnabled = AATEnabled; DWORD old_FinishRadius = FinishRadius; int old_FinishLine = FinishLine; bool old_EnableMultipleStartPoints = EnableMultipleStartPoints; TaskLoaded = true; if(fread(taskinfo, sizeof(char), LKPREAMBOLSIZE, stream) != LKPREAMBOLSIZE) { TaskInvalid = true; goto goEnd; } // task version check if ( (taskinfo[0]!= 'L') || (taskinfo[1]!= 'K') || (taskinfo[2]!=LKTASKVERSION) ) { TaskInvalid = true; oldversion = true; goto goEnd; } for(i=0;i<OLD_MAXTASKPOINTS;i++) { if(fread(&Temp, 1, sizeof(OLD_TASK_POINT), stream) != sizeof(OLD_TASK_POINT)) { TaskInvalid = true; break; } if(i < MAXTASKPOINTS) { memcpy(&Task[i],&Temp, sizeof(OLD_TASK_POINT)); if( !ValidNotResWayPoint(Temp.Index) && (Temp.Index != -1) ) { // 091213 // Task is only invalid here if the index is out of range // of the waypoints and not equal to -1. // (Because -1 indicates a null task item) WaypointInvalid = true; } } } if (!TaskInvalid) { TaskInvalid = fread(&AATEnabled, 1, sizeof(BOOL), stream) != sizeof(BOOL); } if (!TaskInvalid) { TaskInvalid = fread(&AATTaskLength, 1, sizeof(double), stream) != sizeof(double); } // ToDo review by JW // 20060521:sgi added additional task parameters if (!TaskInvalid) { TaskInvalid = fread(&FinishRadius, 1, sizeof(FinishRadius), stream) != sizeof(FinishRadius); } if (!TaskInvalid) { TaskInvalid = fread(&FinishLine, 1, sizeof(FinishLine), stream) != sizeof(FinishLine); } if (!TaskInvalid) { TaskInvalid = fread(&StartRadius, 1, sizeof(StartRadius), stream) != sizeof(StartRadius); } if (!TaskInvalid) { TaskInvalid = fread(&StartLine, 1, sizeof(StartLine), stream) != sizeof(StartLine); } if (!TaskInvalid) { TaskInvalid = fread(&SectorType, 1, sizeof(SectorType), stream) != sizeof(SectorType); } if (!TaskInvalid) { TaskInvalid = fread(&SectorRadius, 1, sizeof(SectorRadius), stream) != sizeof(SectorRadius); } if (!TaskInvalid) { TaskInvalid = fread(&AutoAdvance, 1, sizeof(AutoAdvance), stream) != sizeof(AutoAdvance); } if (!TaskInvalid) { TaskInvalid = fread(&EnableMultipleStartPoints, 1, sizeof(EnableMultipleStartPoints), stream) != sizeof(EnableMultipleStartPoints); } for(i=0;i<MAXSTARTPOINTS;i++) { if(fread(&STemp, 1, sizeof(START_POINT), stream) != sizeof(START_POINT)) { TaskInvalid = true; break; } if( ValidNotResWayPoint(STemp.Index) || (STemp.Index==-1) ) { // 091213 memcpy(&StartPoints[i],&STemp, sizeof(START_POINT)); } else { WaypointInvalid = true; StartupStore(_T("--- LoadNewTask: invalid waypoint=%d found%s"),STemp.Index,NEWLINE); // 091213 } } // search for waypoints... if (!TaskInvalid) { if (!LoadTaskWaypoints(stream) && WaypointInvalid) { // couldn't lookup the waypoints in the file and we know there are invalid waypoints TaskInvalid = true; StartupStore(_T(". LoadTaskNew: cant locate waypoint in file, and invalid wp in task file%s"),NEWLINE); } } // TimeGate config if (!TaskInvalid) { TaskInvalid = fread(&PGOpenTimeH, 1, sizeof(PGOpenTimeH), stream) != sizeof(PGOpenTimeH); } if (!TaskInvalid) { TaskInvalid = fread(&PGOpenTimeM, 1, sizeof(PGOpenTimeM), stream) != sizeof(PGOpenTimeM); } if (!TaskInvalid) { InitActiveGate(); // PGOpenTime is Calculated ! int tmp; TaskInvalid = fread(&tmp, 1, sizeof(tmp), stream) != sizeof(tmp); } if (!TaskInvalid) { PGCloseTime=86399; // PGCloseTime is Calculated ! int tmp; TaskInvalid = fread(&tmp, 1, sizeof(tmp), stream) != sizeof(tmp); } if (!TaskInvalid) { TaskInvalid = fread(&PGGateIntervalTime, 1, sizeof(PGGateIntervalTime), stream) != sizeof(PGGateIntervalTime); } if (!TaskInvalid) { TaskInvalid = fread(&PGNumberOfGates, 1, sizeof(PGNumberOfGates), stream) != sizeof(PGNumberOfGates); } if (!TaskInvalid) { TaskInvalid = fread(&PGStartOut, 1, sizeof(PGStartOut), stream) != sizeof(PGStartOut); } goEnd: fclose(stream); if (TaskInvalid) { if (oldversion) StartupStore(_T("------ Task is invalid: old task format%s"),NEWLINE); else StartupStore(_T("------ Task is invalid%s"),NEWLINE); StartLine = old_StartLine; SectorType = old_SectorType; SectorRadius = old_SectorRadius; StartRadius = old_StartRadius; AutoAdvance = old_AutoAdvance; AATTaskLength = old_AATTaskLength; AATEnabled = old_AATEnabled; FinishRadius = old_FinishRadius; FinishLine = old_FinishLine; EnableMultipleStartPoints = old_EnableMultipleStartPoints; } } else { StartupStore(_T("... LoadNewTask: file <%s> not found%s"),taskFileName,NEWLINE); // 091213 TaskInvalid = true; } if (TaskInvalid) { ClearTask(); } RefreshTask(); if (!ValidTaskPoint(0)) { ActiveWayPoint = 0; } UnlockTaskData(); if (TaskInvalid && TaskLoaded) { if (oldversion) { // LKTOKEN _@M360_ = "Invalid old task format!" MessageBoxX(gettext(TEXT("_@M360_")), // LKTOKEN _@M396_ = "Load task" gettext(TEXT("_@M396_")), mbOk); } else { // LKTOKEN _@M264_ = "Error in task file!" MessageBoxX(gettext(TEXT("_@M264_")), // LKTOKEN _@M396_ = "Load task" gettext(TEXT("_@M396_")), mbOk); } } else { #if TESTBENCH StartupStore(_T("------ Task is Loaded%s"),NEWLINE); #endif TaskModified = false; TargetModified = false; _tcscpy(LastTaskFileName, taskFileName); } }
// // Init runtime variables using _Config variables // This is needed after loading a new profile, and // also on startup after loading a reset configuration. // // LK8000 is (normally!) separating config values from runtime values. // For example, ActiveMap can be configured disabled by default in System Config, // but enabled at runtime with a button or a customkey. However the configuration // will still be "disabled" and saved as disabled in profile. // It is important to keep runtime and config variables separated, if a config // variable can be changed with a button out of System Config! // // Be careful, like AdjustVariables this function is called twice or more times on startup // void LKProfileInitRuntime(void) { #if TESTBENCH StartupStore(_T("... LKProfileInitRuntime\n")); #endif // Todo: use _Config values for files, and then we can compare if they changed WAYPOINTFILECHANGED = TRUE; TERRAINFILECHANGED = TRUE; TOPOLOGYFILECHANGED = TRUE; AIRSPACEFILECHANGED = TRUE; AIRFIELDFILECHANGED = TRUE; POLARFILECHANGED = TRUE; // // Runtime from Config // Appearance.InverseInfoBox = InverseInfoBox_Config; AutoAdvance = AutoAdvance_Config; AutoMcMode = AutoMcMode_Config; BgMapColor = BgMapColor_Config; EnableNavBaroAltitude = EnableNavBaroAltitude_Config; Orbiter = Orbiter_Config; Shading = Shading_Config; TerrainRamp = TerrainRamp_Config; TrailActive = TrailActive_Config; UseTotalEnergy = UseTotalEnergy_Config; AutoWindMode = AutoWindMode_Config; MapWindow::EnableTrailDrift = EnableTrailDrift_Config; AltitudeMode = AltitudeMode_Config; OutlinedTp = OutlinedTp_Config; BUGS = BUGS_Config; MapWindow::zoom.AutoZoom(AutoZoom_Config); CALCULATED_INFO.AutoMacCready = AutoMacCready_Config==true?1:0; DisplayOrientation = DisplayOrientation_Config; MapWindow::SetAutoOrientation(true); // reset old autoorientation MapWindow::GliderScreenPositionY = MapWindow::GliderScreenPosition; GlobalModelType=Appearance.InfoBoxModel; // // Units // switch(SpeedUnit_Config) { case 0 : SPEEDMODIFY = TOMPH; break; case 1 : SPEEDMODIFY = TOKNOTS; break; case 2 : default: SPEEDMODIFY = TOKPH; break; } switch(TaskSpeedUnit_Config) { case 0 : TASKSPEEDMODIFY = TOMPH; break; case 1 : TASKSPEEDMODIFY = TOKNOTS; break; case 2 : default: TASKSPEEDMODIFY = TOKPH; break; } switch(DistanceUnit_Config) { case 0 : DISTANCEMODIFY = TOMILES; break; case 1 : DISTANCEMODIFY = TONAUTICALMILES; break; default: case 2 : DISTANCEMODIFY = TOKILOMETER; break; } switch(AltitudeUnit_Config) { case 0 : ALTITUDEMODIFY = TOFEET; break; default: case 1 : ALTITUDEMODIFY = TOMETER; break; } switch(LiftUnit_Config) { case 0 : LIFTMODIFY = TOKNOTS; break; case 2 : LIFTMODIFY = TOKNOTS; break; default: case 1 : LIFTMODIFY = TOMETER; break; } Units::NotifyUnitChanged(); // set unit strings SetOverColorRef(); InitActiveGate(); if ( ISPARAGLIDER ) { if(PGOptimizeRoute) AATEnabled=true; LoggerTimeStepCruise=1; } else { AATEnabled=FALSE; } if ( ISPARAGLIDER || ISCAR ) { // paragliders can takeoff at 5kmh ground with some head wind! TakeOffSpeedThreshold=1.39; // 5kmh if (ISCAR) TakeOffSpeedThreshold=0.83; // 3 kmh } else { TakeOffSpeedThreshold=11.12; // 40kmh } // // ModelType specials for PNAs // #if (WINDOWSPC<1) if (GlobalModelType == MODELTYPE_PNA_HP31X ) { DeviceNeedClipping=true; // key transcoding for this one #if TESTBENCH StartupStore(TEXT(". Loading HP31X settings%s"),NEWLINE); #endif } else if (GlobalModelType == MODELTYPE_PNA_PN6000 ) { // key transcoding for this one } else if (GlobalModelType == MODELTYPE_PNA_MIO ) { #if TESTBENCH StartupStore(TEXT(". Loading MIO settings%s"),NEWLINE); #endif // currently no special settings from MIO but need to handle hw keys } else if (GlobalModelType == MODELTYPE_PNA_NOKIA_500 ) { #if TESTBENCH StartupStore(TEXT(". Loading Nokia500 settings%s"),NEWLINE); #endif // key transcoding is made } else if (GlobalModelType == MODELTYPE_PNA_MEDION_P5 ) { #if TESTBENCH StartupStore(TEXT(".Loading Medion settings%s"),NEWLINE); #endif DeviceNeedClipping=true; } if (GlobalModelType == MODELTYPE_PNA_NAVIGON ) { #if TESTBENCH StartupStore(TEXT(".Loading Navigon settings%s"),NEWLINE); #endif DeviceNeedClipping=true; } else if (GlobalModelType == MODELTYPE_PNA_PNA ) { #if TESTBENCH StartupStore(TEXT(". Loading default PNA settings%s"),NEWLINE); #endif } #if TESTBENCH else StartupStore(TEXT(". No special regsets for this device%s"),NEWLINE); #endif #endif // ModelType specials LKalarms[0].triggervalue=(int)AlarmMaxAltitude1/1000; LKalarms[1].triggervalue=(int)AlarmMaxAltitude2/1000; LKalarms[2].triggervalue=(int)AlarmMaxAltitude3/1000; UpdateConfBB(); UpdateConfIP(); UpdateMultimapOrient(); }