Пример #1
0
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;
}
Пример #2
0
DWORD MapWindow::DrawThread (LPVOID lpvoid)
{

  FILETIME CreationTime, ExitTime, StartKernelTime, EndKernelTime, StartUserTime, EndUserTime ;


  while ((!ProgramStarted) || (!Initialised)) {
	Sleep(100);
  }

  #if TRACETHREAD
  StartupStore(_T("##############  DRAW threadid=%d\n"),GetCurrentThreadId());
  #endif


  // THREADRUNNING = FALSE;
  THREADEXIT = FALSE;

  // Reset common topology and waypoint label declutter, first init. Done also in other places.
  ResetLabelDeclutter();

  GetClientRect(hWndMapWindow, &MapRect);
  // Default draw area is full screen, no opacity
  DrawRect=MapRect;

  UpdateTimeStats(true);

  
  SetBkMode(hdcDrawWindow,TRANSPARENT);
  SetBkMode(hDCTemp,OPAQUE);
  SetBkMode(hDCMask,OPAQUE);

  // paint draw window black to start
  SelectObject(hdcDrawWindow, GetStockObject(BLACK_PEN));
  Rectangle(hdcDrawWindow,MapRect.left,MapRect.top,
            MapRect.right,MapRect.bottom);

  BitBlt(hdcScreen, 0, 0, MapRect.right-MapRect.left,
         MapRect.bottom-MapRect.top, 
         hdcDrawWindow, 0, 0, SRCCOPY);

  // This is just here to give fully rendered start screen
  UpdateInfo(&GPS_INFO, &CALCULATED_INFO);
  MapDirty = true;
  UpdateTimeStats(true);

  zoom.RequestedScale(zoom.Scale());
  zoom.ModifyMapScale();
  FillScaleListForEngineeringUnits();
  
  bool lastdrawwasbitblitted=false;
  bool first_run=true;

  // 
  // Big LOOP
  //

  while (!CLOSETHREAD) 
  {
	WaitForSingleObject(drawTriggerEvent, 5000);
	ResetEvent(drawTriggerEvent);
	if (CLOSETHREAD) break; // drop out without drawing

	if ((!THREADRUNNING) || (!GlobalRunning)) {
		Sleep(100);
		continue;
	}

	// This is also occuring on resolution change
	if (LKSW_ReloadProfileBitmaps) {
		#if TESTBENCH
		StartupStore(_T(".... SWITCH: ReloadProfileBitmaps detected\n"));
		#endif
		// This is needed to update resolution change
		GetClientRect(hWndMapWindow, &MapRect);
		DrawRect=MapRect;
		FillScaleListForEngineeringUnits();
		LKUnloadProfileBitmaps();
		LKLoadProfileBitmaps();
		LKUnloadFixedBitmaps();
		LKLoadFixedBitmaps();
		MapWindow::zoom.Reset();

		// This will reset the function for the new ScreenScale
		PolygonRotateShift((POINT*)NULL,0,0,0,DisplayAngle+1);

		// Restart from moving map
		if (MapSpaceMode!=MSM_WELCOME) SetModeType(LKMODE_MAP, MP_MOVING);

		LKSW_ReloadProfileBitmaps=false;
		// These should be better checked. first_run is forcing also cache update for topo.
		ForceRenderMap=true;
		first_run=true;
	}



	GetThreadTimes( hDrawThread, &CreationTime, &ExitTime,&StartKernelTime,&StartUserTime);

	// Until MapDirty is set true again, we shall only repaint the screen. No Render, no calculations, no updates.
	// This is intended for very fast immediate screen refresh.
	//
	// MapDirty is set true by:
	//   - TriggerRedraws()  in calculations thread
	//   - RefreshMap()      in drawthread generally
	//


	extern int XstartScreen, YstartScreen, XtargetScreen, YtargetScreen;
	extern bool OnFastPanning;
	// While we are moving in bitblt mode, ignore RefreshMap requests from LK
	// unless a timeout was triggered by MapWndProc itself.
	if (OnFastPanning) {
		MapDirty=false;
	} 

	// We must check if we are on FastPanning, because we may be in pan mode even while
	// the menu buttons are active and we are using them, accessing other functions.
	// In that case, without checking OnFastPanning, we would fall back here and repaint
	// with bitblt everytime, while instead we were asked a simple fastrefresh!
	//
	// Notice: we could be !MapDirty without OnFastPanning, of course!
	//
	if (!MapDirty && !ForceRenderMap && OnFastPanning && !first_run) {
		
		if (!mode.Is(Mode::MODE_TARGET_PAN) && mode.Is(Mode::MODE_PAN)) {

			int fromX=0, fromY=0;

			fromX=XstartScreen-XtargetScreen;
			fromY=YstartScreen-YtargetScreen;

			BitBlt(hdcScreen, 0, 0, 
				MapRect.right-MapRect.left, 
				MapRect.bottom-MapRect.top, 
				hdcDrawWindow, 0, 0, WHITENESS);


			BitBlt(hdcScreen, 0, 0,
				MapRect.right-MapRect.left,
				MapRect.bottom-MapRect.top, 
				hdcDrawWindow, 
				fromX,fromY, 				// source
				SRCCOPY);

			POINT centerscreen;
			centerscreen.x=ScreenSizeX/2; centerscreen.y=ScreenSizeY/2;
			DrawMapScale(hdcScreen,MapRect,false);
			DrawCrossHairs(hdcScreen, centerscreen, MapRect);
			lastdrawwasbitblitted=true;
		} else {
			// THIS IS NOT GOING TO HAPPEN!
			//
			// The map was not dirty, and we are not in fastpanning mode.
			// FastRefresh!  We simply redraw old bitmap. 
			//
			BitBlt(hdcScreen, 0, 0, MapRect.right-MapRect.left,
				MapRect.bottom-MapRect.top, 
				hdcDrawWindow, 0, 0, SRCCOPY);

			lastdrawwasbitblitted=true;
		}

		// Now we can clear the flag. If it was off already, no problems.
		OnFastPanning=false;
		continue;

	} else {
		//
		// Else the map wasy dirty, and we must render it..
		// Notice: if we were fastpanning, than the map could not be dirty.
		//

		#if 1 // --------------------- EXPERIMENTAL, CHECK ZOOM IS WORKING IN PNA
		static double lasthere=0;
		// Only for special case: PAN mode, map not dirty (including requests for zooms!)
		// not in the ForceRenderMap run and last time was a real rendering. THEN, at these conditions,
		// we simply redraw old bitmap, for the scope of accelerating touch response.
		// In fact, if we are panning the map while rendering, there would be an annoying delay.
		// This is using lastdrawwasbitblitted
		if (INPAN && !MapDirty && !lastdrawwasbitblitted && !ForceRenderMap && !first_run) {
			// In any case, after 5 seconds redraw all
			if ( (LKHearthBeats-8) >lasthere ) {
				lasthere=LKHearthBeats;
				goto _dontbitblt;
			}
			BitBlt(hdcScreen, 0, 0, MapRect.right-MapRect.left,
				MapRect.bottom-MapRect.top, 
				hdcDrawWindow, 0, 0, SRCCOPY);

			POINT centerscreen;
			centerscreen.x=ScreenSizeX/2; centerscreen.y=ScreenSizeY/2;
			DrawMapScale(hdcScreen,MapRect,false);
			DrawCrossHairs(hdcScreen, centerscreen, MapRect);
			continue;
		} 
		#endif // --------------------------
_dontbitblt:
		MapDirty = false;
		PanRefreshed=true;
	} // MapDirty

	lastdrawwasbitblitted=false;
	MapWindow::UpdateInfo(&GPS_INFO, &CALCULATED_INFO);

	RenderMapWindow(MapRect);
    
	if (!ForceRenderMap && !first_run) {
		BitBlt(hdcScreen, 0, 0, 
			MapRect.right-MapRect.left,
			MapRect.bottom-MapRect.top, 
			hdcDrawWindow, 0, 0, SRCCOPY);
		InvalidateRect(hWndMapWindow, &MapRect, false);
	}

	// Draw cross sight for pan mode, in the screen center, 
	// after a full repaint while not fastpanning
	if (mode.AnyPan() && !mode.Is(Mode::MODE_TARGET_PAN) && !OnFastPanning) {
		POINT centerscreen;
		centerscreen.x=ScreenSizeX/2; centerscreen.y=ScreenSizeY/2;
		DrawMapScale(hdcScreen,MapRect,false);
		DrawCompass(hdcScreen, MapRect, DisplayAngle);
		DrawCrossHairs(hdcScreen, centerscreen, MapRect);
	}

	UpdateTimeStats(false);

	// we do caching after screen update, to minimise perceived delay
	// UpdateCaches is updating topology bounds when either forced (only here)
	// or because MapWindow::ForceVisibilityScan  is set true.
	UpdateCaches(first_run);
	first_run=false;

	ForceRenderMap = false;

	if (ProgramStarted==psInitDone) {
		ProgramStarted = psFirstDrawDone;
	}

	if ( (GetThreadTimes( hDrawThread, &CreationTime, &ExitTime,&EndKernelTime,&EndUserTime)) == 0) {
		Cpu_Draw=9999;
	} else {
		Cpustats(&Cpu_Draw,&StartKernelTime, &EndKernelTime, &StartUserTime, &EndUserTime);
	}
    
  } // Big LOOP

  #if TESTBENCH
  StartupStore(_T("... Thread_Draw terminated\n"));
  #endif
  THREADEXIT = TRUE;
  return 0;
}
Пример #3
0
DWORD SerialPort::RxThread() {
#if ( (WINDOWSPC == 0)) && !NEWCOMM	// 100222
    DWORD dwCommModemStatus = 0;
    // Specify a set of events to be monitored for the port.
#endif
    DWORD dwBytesTransferred = 0; // 091117 initialized variables
    _Buff_t szString;
    FILETIME CreationTime, ExitTime, StartKernelTime, EndKernelTime, StartUserTime, EndUserTime;

    Purge();
#if TRACETHREAD
    StartupStore(_T("##############  PORT=%d threadid=%d\n"), GetPortIndex(), GetCurrentThreadId());
    if (GetPortIndex() = 0) _THREADID_PORT1 = GetCurrentThreadId();
    if (GetPortIndex() = 1) _THREADID_PORT2 = GetCurrentThreadId();
    if (GetPortIndex() != 1 && GetPortIndex() != 2) _THREADID_UNKNOWNPORT = GetCurrentThreadId();
#endif
    // Specify a set of events to be monitored for the port.
    _dwMask = EV_RXFLAG | EV_CTS | EV_DSR | EV_RING | EV_RXCHAR;

#if ( (WINDOWSPC == 0)) && !NEWCOMM
    SetCommMask(hPort, _dwMask);
#endif
#if (WINDOWSPC<1)
    if (!_PollingMode) SetCommMask(hPort, _dwMask);
#endif

    while ((hPort != INVALID_HANDLE_VALUE) && (::WaitForSingleObject(hStop, 0) == WAIT_TIMEOUT)) {
        GetThreadTimes(hReadThread, &CreationTime, &ExitTime, &StartKernelTime, &StartUserTime);

        UpdateStatus();

#if (WINDOWSPC>0) || NEWCOMM // 091206
        // PC version does BUSY WAIT
        Sleep(50); // ToDo rewrite the whole driver to use overlaped IO on W2K or higher
#else
        if (_PollingMode)
            Sleep(100);
        else
            // Wait for an event to occur for the port.
            if (!WaitCommEvent(hPort, &dwCommModemStatus, 0)) {
            // error reading from port
            Sleep(100);
        }
#endif

        // Re-specify the set of events to be monitored for the port.
        //    SetCommMask(hPort, dwMask1);

        // #if (WINDOWSPC == 0) 091206
#if ( (WINDOWSPC == 0)) && !NEWCOMM
        if (_PollingMode || (dwCommModemStatus & EV_RXFLAG) || (dwCommModemStatus & EV_RXCHAR)) // Do this only for non-PC
#endif
        {
            // Loop for waiting for the data.
            do {
                // Read the data from the serial port.
                dwBytesTransferred = ReadData(szString);
                if (dwBytesTransferred > 0) {
                    if (ProgramStarted >= psNormalOp) { // ignore everything until started
                        std::for_each(begin(szString), begin(szString) + dwBytesTransferred, std::bind1st(std::mem_fun(&SerialPort::ProcessChar), this));
                    }
                } else {
                    dwBytesTransferred = 0;
                }

                Sleep(50); // JMW20070515: give port some time to
                // fill... prevents ReadFile from causing the
                // thread to take up too much CPU
                if ((GetThreadTimes(hReadThread, &CreationTime, &ExitTime, &EndKernelTime, &EndUserTime)) == 0) {
                    if (GetPortIndex() == 0)
                        Cpu_PortA = 9999;
                    else
                        Cpu_PortB = 9999;
                } else {
                    Cpustats((GetPortIndex() == 0) ? &Cpu_PortA : &Cpu_PortB, &StartKernelTime, &EndKernelTime, &StartUserTime, &EndUserTime);
                }

                if (::WaitForSingleObject(hStop, 0) != WAIT_TIMEOUT) {
                    dwBytesTransferred = 0;
                }
            } while (dwBytesTransferred != 0);
        }

        // give port some time to fill
        Sleep(5);

        // Retrieve modem control-register values.
#if ((WINDOWSPC == 0)) 
        if (!_PollingMode) {
            // this is causing problems on PC BT, apparently. Setting Polling will not call this, but it is a bug
            GetCommModemStatus(hPort, &dwCommModemStatus);
        }
#endif
    }

    DirtyPurge();

    return 0;
}
Пример #4
0
/***********************************************************************

  PortReadThread (LPVOID lpvoid)

***********************************************************************/
DWORD ComPort::ReadThread()
{
  #if (!defined(WINDOWSPC) || (WINDOWSPC == 0)) && !NEWCOMM	// 100222
  DWORD dwCommModemStatus=0;
  #endif
  DWORD dwBytesTransferred=0; // 091117 initialized variables
  BYTE inbuf[1024];
  #ifdef CPUSTATS
  FILETIME CreationTime, ExitTime, StartKernelTime, EndKernelTime, StartUserTime, EndUserTime ;
  #endif

  // JMW added purging of port on open to prevent overflow
  Flush();
  StartupStore(_T(". ReadThread running on port %d%s"),sportnumber+1,NEWLINE);
  
  // Specify a set of events to be monitored for the port.

  dwMask = EV_RXFLAG | EV_CTS | EV_DSR | EV_RING | EV_RXCHAR;

  // #if !defined(WINDOWSPC) || (WINDOWSPC == 0) 091206
  #if (!defined(WINDOWSPC) || (WINDOWSPC == 0)) && !NEWCOMM
  SetCommMask(hPort, dwMask);
  #endif
#if (WINDOWSPC<1)
  if (!PollingMode) SetCommMask(hPort, dwMask);
#endif

  fRxThreadTerminated = FALSE;
  DWORD dwErrors=0;
  COMSTAT comStat;
  short valid_frames=0;

  while ((hPort != INVALID_HANDLE_VALUE) && (!MapWindow::CLOSETHREAD) && (!CloseThread)) 
  {
	#ifdef CPUSTATS
	GetThreadTimes( hReadThread, &CreationTime, &ExitTime,&StartKernelTime,&StartUserTime);
	#endif

	ClearCommError(hPort,&dwErrors,&comStat);
	if ( dwErrors & CE_FRAME ) {
		//StartupStore(_T("... Com port %d, dwErrors=%ld FRAME (old status=%d)\n"),
		//	sportnumber,dwErrors,ComPortStatus[sportnumber]);
		ComPortStatus[sportnumber]=CPS_EFRAME;
		ComPortErrRx[sportnumber]++;
		valid_frames=0;
	} else {
		if (++valid_frames>10) { 
			valid_frames=20; 
			ComPortStatus[sportnumber]=CPS_OPENOK;
		}
	}

	#if (WINDOWSPC>0) || NEWCOMM // 091206
	// PC version does BUSY WAIT
	Sleep(50);  // ToDo rewrite the whole driver to use overlaped IO on W2K or higher
	#else
	if (PollingMode)  
		Sleep(100);
	else
	// Wait for an event to occur for the port.
	if (!WaitCommEvent(hPort, &dwCommModemStatus, 0)) {
		// error reading from port
		Sleep(100);
	}
	#endif

	// Re-specify the set of events to be monitored for the port.
	//    SetCommMask(hPort, dwMask1);

	// #if !defined(WINDOWSPC) || (WINDOWSPC == 0) 091206
	#if (!defined(WINDOWSPC) || (WINDOWSPC == 0)) && !NEWCOMM
	if (PollingMode || (dwCommModemStatus & EV_RXFLAG) || (dwCommModemStatus & EV_RXCHAR)) // Do this only for non-PC
	#endif
	{

		// Loop for waiting for the data.
		do {
			dwBytesTransferred = 0;
			// Read the data from the serial port.
			if (ReadFile(hPort, inbuf, 1024, &dwBytesTransferred, (OVERLAPPED *)NULL)) {
				if (ProgramStarted >= psNormalOp) {  // ignore everything until started
					for (unsigned int j = 0; j < dwBytesTransferred; j++) {
						ProcessChar(inbuf[j]);
					}
				}
				ComPortRx[sportnumber]+=dwBytesTransferred; // 100210
			} else {
				dwBytesTransferred = 0;
			}

			Sleep(50); // JMW20070515: give port some time to
			// fill... prevents ReadFile from causing the
			// thread to take up too much CPU
			#ifdef CPUSTATS
			if ( (GetThreadTimes( hReadThread, &CreationTime, &ExitTime,&EndKernelTime,&EndUserTime)) == 0) {
				Cpu_Port=9999;
			} else {
				Cpustats(&Cpu_Port,&StartKernelTime, &EndKernelTime, &StartUserTime, &EndUserTime);
			}
			#endif
		  
			if (CloseThread) {
				dwBytesTransferred = 0;
				StartupStore(_T(". ComPort %d ReadThread: CloseThread ordered%s"),sportnumber+1,NEWLINE);
			}
		} while (dwBytesTransferred != 0);
	}

	// give port some time to fill
	Sleep(5);

	// Retrieve modem control-register values.
	#if (!defined(WINDOWSPC) || (WINDOWSPC == 0)) 

	if (!PollingMode)
	// this is causing problems on PC BT, apparently. Setting Polling will not call this, but it is a bug
	GetCommModemStatus(hPort, &dwCommModemStatus);

	#endif

  }

  Flush();      

  fRxThreadTerminated = TRUE;
  StartupStore(_T(". ComPort %d ReadThread: terminated%s"),sportnumber+1,NEWLINE);

  return 0;
}