예제 #1
0
파일: Parser.cpp 프로젝트: rkalman/LK8000
BOOL NMEAParser::RMC(TCHAR *String, TCHAR **params, size_t nparams, NMEA_INFO *pGPS)
{
  TCHAR *Stop;
  static bool logbaddate=true;
  double speed=0;

  gpsValid = !NAVWarn(params[1][0]);

  GPSCONNECT = TRUE;    
  RMCAvailable=true; // 100409

  #ifdef PNA
  if (DeviceIsGM130) {

	double ps = GM130BarPressure();
	RMZAltitude = (1 - pow(fabs(ps / QNH),  0.190284)) * 44307.69;
	// StartupStore(_T("....... Pressure=%.0f QNH=%.2f Altitude=%.1f\n"),ps,QNH,RMZAltitude);

	RMZAvailable = TRUE;

	UpdateBaroSource(pGPS, BARO__GM130, NULL,   RMZAltitude);
  }
  if (DeviceIsRoyaltek3200) {
	if (Royaltek3200_ReadBarData()) {
		double ps = Royaltek3200_GetPressure();
		RMZAltitude = (1 - pow(fabs(ps / QNH),  0.190284)) * 44307.69;

		#if 0
		pGPS->TemperatureAvailable=true;
		pGPS->OutsideAirTemperature = Royaltek3200_GetTemperature();
		#endif
	}

	RMZAvailable = TRUE;

	UpdateBaroSource(pGPS, BARO__ROYALTEK3200,  NULL,  RMZAltitude);

  }
  #endif // PNA

  if (!activeGPS) return TRUE;

  // if no valid fix, we dont get speed either!
  if (gpsValid)
  {
	// speed is in knots, 2 = 3.7kmh
	speed = StrToDouble(params[6], NULL);
  }
  
  pGPS->NAVWarning = !gpsValid;

  // say we are updated every time we get this,
  // so infoboxes get refreshed if GPS connected
  // the RMC sentence marks the start of a new fix, so we force the old data to be saved for calculations

	// Even with no valid position, we let RMC set the time and date if valid
	long gy, gm, gd;
	gy = _tcstol(&params[8][4], &Stop, 10) + 2000;   
	params[8][4] = '\0';
	gm = _tcstol(&params[8][2], &Stop, 10); 
	params[8][2] = '\0';
	gd = _tcstol(&params[8][0], &Stop, 10); 

	// SeeYou PC is sending NMEA sentences with RMC date 2072-02-27
	if ( ((gy > 1980) && (gy <2100) ) && (gm != 0) && (gd != 0) ) { 
		pGPS->Year = gy;
		pGPS->Month = gm;
		pGPS->Day = gd;

force_advance:
		RMCtime = StrToDouble(params[0],NULL);
		double ThisTime = TimeModify(RMCtime, pGPS);

		// RMC time has priority on GGA and GLL etc. so if we have it we use it at once
		if (!TimeHasAdvanced(ThisTime, pGPS)) {
			#if DEBUGSEQ
			StartupStore(_T("..... RMC time not advanced, skipping \n")); // 31C
			#endif
			return FALSE;
		}
			
	}  else {
		if (devIsCondor(devA())) {
			#if DEBUGSEQ
			StartupStore(_T(".. Condor not sending valid date, using 1.1.2012%s"),NEWLINE);
			#endif
			gy=2012; gm=1; gd=1;
			goto force_advance;
		}

		if (gpsValid && logbaddate) { // 091115
			StartupStore(_T("------ NMEAParser:RMC Receiving an invalid or null DATE from GPS%s"),NEWLINE);
			StartupStore(_T("------ NMEAParser: Date received is y=%d m=%d d=%d%s"),gy,gm,gd,NEWLINE); // 100422
			StartupStore(_T("------ This message will NOT be repeated.%s"),NEWLINE);
			DoStatusMessage(MsgToken(875));
			logbaddate=false;
		}
		gy=2012; gm=2; gd=30;	// an impossible date!
		goto force_advance;
		 
	}

  if (gpsValid) { 
	double tmplat;
	double tmplon;

	tmplat = MixedFormatToDegrees(StrToDouble(params[2], NULL));
	tmplat = NorthOrSouth(tmplat, params[3][0]);
	  
	tmplon = MixedFormatToDegrees(StrToDouble(params[4], NULL));
	tmplon = EastOrWest(tmplon,params[5][0]);
  
	if (!((tmplat == 0.0) && (tmplon == 0.0))) {
		pGPS->Latitude = tmplat;
		pGPS->Longitude = tmplon;
	}
  
	pGPS->Speed = KNOTSTOMETRESSECONDS * speed;
  
	if (pGPS->Speed>trackbearingminspeed) {
		pGPS->TrackBearing = AngleLimit360(StrToDouble(params[7], NULL));
	}
  } // gpsvalid 091108
    
  // As soon as we get a fix for the first time, set the
  // system clock to the GPS time.
  static bool sysTimeInitialised = false;
  
  if (!pGPS->NAVWarning && (gpsValid)) {
	if (SetSystemTimeFromGPS) {
		if (!sysTimeInitialised) {
			if ( ( pGPS->Year > 1980 && pGPS->Year<2100) && ( pGPS->Month > 0) && ( pGPS->Hour > 0)) {
        
				sysTimeInitialised =true; // Attempting only once
				SYSTEMTIME sysTime;
				// ::GetSystemTime(&sysTime);
				int hours = (int)pGPS->Hour;
				int mins = (int)pGPS->Minute;
				int secs = (int)pGPS->Second;
				sysTime.wYear = (unsigned short)pGPS->Year;
				sysTime.wMonth = (unsigned short)pGPS->Month;
				sysTime.wDay = (unsigned short)pGPS->Day;
				sysTime.wHour = (unsigned short)hours;
				sysTime.wMinute = (unsigned short)mins;
				sysTime.wSecond = (unsigned short)secs;
				sysTime.wMilliseconds = 0;
				::SetSystemTime(&sysTime);
			}
		}
	}
  }

  if(RMZAvailable) {
	UpdateBaroSource(pGPS, BARO__RMZ, NULL,  RMZAltitude);
  }
  else if(RMAAvailable) {
     UpdateBaroSource(pGPS, BARO__RMA, NULL,  RMAAltitude);
  }
  if (!GGAAvailable) {
	// update SatInUse, some GPS receiver dont emmit GGA sentance
	if (!gpsValid) { 
		pGPS->SatellitesUsed = 0;
	} else {
		pGPS->SatellitesUsed = -1;
	}
  }
  
  if ( !GGAAvailable || (GGAtime == RMCtime)  )  {
	#if DEBUGSEQ
	StartupStore(_T("... RMC trigger gps, GGAtime==RMCtime\n")); // 31C
	#endif
	TriggerGPSUpdate(); 
  }

  return TRUE;

} // END RMC
예제 #2
0
bool
NMEAParser::RMC(NMEAInputLine &line, NMEAInfo &info)
{
    /*
     * $--RMC,hhmmss.ss,A,llll.ll,a,yyyyy.yy,a,x.x,x.x,xxxx,x.x,a,m,*hh
     *
     * Field Number:
     *  1) UTC Time
     *  2) Status, V=Navigation receiver warning A=Valid
     *  3) Latitude
     *  4) N or S
     *  5) Longitude
     *  6) E or W
     *  7) Speed over ground, knots
     *  8) Track made good, degrees true
     *  9) Date, ddmmyy
     * 10) Magnetic Variation, degrees
     * 11) E or W
     * 12) FAA mode indicator (NMEA 2.3 and later)
     * 13) Checksum
     */

    fixed this_time;
    if (!ReadTime(line, info.date_time_utc, this_time))
        return true;

    bool gps_valid = !NAVWarn(line.ReadFirstChar());

    GeoPoint location;
    bool valid_location = ReadGeoPoint(line, location);

    fixed speed;
    bool ground_speed_available = line.ReadChecked(speed);

    Angle track;
    bool track_available = ReadBearing(line, track);

    // JMW get date info first so TimeModify is accurate
    ReadDate(line, info.date_time_utc);

    Angle variation;
    bool variation_available = ReadVariation(line, variation);

    if (!TimeHasAdvanced(this_time, info))
        return true;

    if (!gps_valid)
        info.location_available.Clear();
    else if (valid_location)
        info.location_available.Update(info.clock);

    if (valid_location)
        info.location = location;

    if (ground_speed_available) {
        info.ground_speed = Units::ToSysUnit(speed, Unit::KNOTS);
        info.ground_speed_available.Update(info.clock);
    }

    if (track_available && info.MovementDetected()) {
        // JMW don't update bearing unless we're moving
        info.track = track;
        info.track_available.Update(info.clock);
    }

    if (!variation_available)
        info.variation_available.Clear();
    else if (variation_available) {
        info.variation = variation;
        info.variation_available.Update(info.clock);
    }

    info.gps.real = real;
#if defined(ANDROID) || defined(__APPLE__)
    info.gps.nonexpiring_internal_gps = false;
#endif

    return true;
}
예제 #3
0
파일: Parser.cpp 프로젝트: miza/LK8000
BOOL NMEAParser::RMC(TCHAR *String, TCHAR **params, size_t nparams, NMEA_INFO *GPS_INFO)
{
  TCHAR *Stop;
  static bool logbaddate=true;
  double speed=0;

  gpsValid = !NAVWarn(params[1][0]);

  GPSCONNECT = TRUE;    
  RMCAvailable=true; // 100409

  if (!activeGPS) return TRUE; // 091205 BUGFIX true

  // if no valid fix, we dont get speed either!
  if (gpsValid)
  {
	speed = StrToDouble(params[6], NULL);
	// speed is in knots, 2 = 3.7kmh
	if (speed>2.0) {
		GPS_INFO->MovementDetected = TRUE;
		if (ReplayLogger::IsEnabled()) {
			// stop logger replay if aircraft is actually moving.
			ReplayLogger::Stop();
		}
	} else {
		GPS_INFO->MovementDetected = FALSE;
		if (ReplayLogger::IsEnabled()) {
			// block actual GPS signal if not moving and a log is being replayed
			return TRUE;
		}
	}
  }
  
  GPS_INFO->NAVWarning = !gpsValid;

  // say we are updated every time we get this,
  // so infoboxes get refreshed if GPS connected
  // the RMC sentence marks the start of a new fix, so we force the old data to be saved for calculations
#ifndef NEWTRIGGERGPS
  if (!GGAAvailable) { 
	TriggerGPSUpdate();
  }
#endif

	// Even with no valid position, we let RMC set the time and date if valid
	long gy, gm, gd;
	gy = _tcstol(&params[8][4], &Stop, 10) + 2000;   
	params[8][4] = '\0';
	gm = _tcstol(&params[8][2], &Stop, 10); 
	params[8][2] = '\0';
	gd = _tcstol(&params[8][0], &Stop, 10); 

	// SeeYou PC is sending NMEA sentences with RMC date 2072-02-27
	if ( ((gy > 1980) && (gy <2100) ) && (gm != 0) && (gd != 0) ) { 
		GPS_INFO->Year = gy;
		GPS_INFO->Month = gm;
		GPS_INFO->Day = gd;
#ifdef NEWTRIGGERGPS
		double ThisTime = TimeConvert(StrToDouble(params[0],NULL), GPS_INFO); // 091208
#else
		double ThisTime = TimeModify(StrToDouble(params[0],NULL), GPS_INFO);
#endif

#ifndef NEWTRIGGERGPS
		if (!TimeHasAdvanced(ThisTime, GPS_INFO))
			return FALSE;
#endif
#ifdef NEWTRIGGERGPS
		// is time advanced to a new quantum?
		if (ThisTime >NmeaTime) {
			// yes so lets trigger the gps event
			TriggerGPSUpdate();
			// and only then advance the time in the GPSINFO
			Sleep(50); // 091208
			NmeaTime=ThisTime;
			TimeSet(GPS_INFO); // 091208
			TimeHasAdvanced(ThisTime, GPS_INFO); // 091208
			StartupStore(_T(".............. trigger from RMC\n"));
		}
#endif
			
	}  else {
		if (gpsValid && logbaddate) { // 091115
			StartupStore(_T("------ NMEAParser:RMC Receiving an invalid or null DATE from GPS%s"),NEWLINE);
			StartupStore(_T("------ NMEAParser: Date received is y=%d m=%d d=%d%s"),gy,gm,gd,NEWLINE); // 100422
			StartupStore(_T("------ This message will NOT be repeated.%s"),NEWLINE);
			// DoStatusMessage(_T("WARNING: GPS IS SENDING INVALID DATE, AND PROBABLY WRONG TIME")); // REMOVE FIXV2
			// LKTOKEN 875  WARNING: GPS IS SENDING INVALID DATE, AND PROBABLY WRONG TIME")); 
			DoStatusMessage(gettext(TEXT("_@M875_")));
			logbaddate=false;
		}
	}
//  } // 091108

  if (gpsValid) {   // 091108 BUGFIX set latlon and speed ONLY if valid gpsdata, missing check!
	double tmplat;
	double tmplon;

	tmplat = MixedFormatToDegrees(StrToDouble(params[2], NULL));
	tmplat = NorthOrSouth(tmplat, params[3][0]);
	  
	tmplon = MixedFormatToDegrees(StrToDouble(params[4], NULL));
	tmplon = EastOrWest(tmplon,params[5][0]);
  
	if (!((tmplat == 0.0) && (tmplon == 0.0))) {
		GPS_INFO->Latitude = tmplat;
		GPS_INFO->Longitude = tmplon;
	}
  
	GPS_INFO->Speed = KNOTSTOMETRESSECONDS * speed;
  
	if (GPS_INFO->Speed>1.0) {
		// JMW don't update bearing unless we're moving
		GPS_INFO->TrackBearing = AngleLimit360(StrToDouble(params[7], NULL));
	}
  } // gpsvalid 091108
    
  // Altair doesn't have a battery-backed up realtime clock,
  // so as soon as we get a fix for the first time, set the
  // system clock to the GPS time.
  static bool sysTimeInitialised = false;
  
  if (!GPS_INFO->NAVWarning && (gpsValid)) {
	if (SetSystemTimeFromGPS) {
		if (!sysTimeInitialised) {
			if ( ( GPS_INFO->Year > 1980 && GPS_INFO->Year<2100) && ( GPS_INFO->Month > 0) && ( GPS_INFO->Hour > 0)) {
        
				sysTimeInitialised =true; // Attempting only once
				SYSTEMTIME sysTime;
				// ::GetSystemTime(&sysTime);
				int hours = (int)GPS_INFO->Hour;
				int mins = (int)GPS_INFO->Minute;
				int secs = (int)GPS_INFO->Second;
				sysTime.wYear = (unsigned short)GPS_INFO->Year;
				sysTime.wMonth = (unsigned short)GPS_INFO->Month;
				sysTime.wDay = (unsigned short)GPS_INFO->Day;
				sysTime.wHour = (unsigned short)hours;
				sysTime.wMinute = (unsigned short)mins;
				sysTime.wSecond = (unsigned short)secs;
				sysTime.wMilliseconds = 0;
				::SetSystemTime(&sysTime);
			}
		}
	}
  }

  if (!ReplayLogger::IsEnabled()) {      
	if(RMZAvailable) {
		// JMW changed from Altitude to BaroAltitude
		GPS_INFO->BaroAltitudeAvailable = true;
		GPS_INFO->BaroAltitude = RMZAltitude;
	}
	else if(RMAAvailable) {
	// JMW changed from Altitude to BaroAltitude
		GPS_INFO->BaroAltitudeAvailable = true;
		GPS_INFO->BaroAltitude = RMAAltitude;
	}
  }
  if (!GGAAvailable) {
	// update SatInUse, some GPS receiver dont emmit GGA sentance
	if (!gpsValid) { 
		GPS_INFO->SatellitesUsed = 0;
	} else {
		GPS_INFO->SatellitesUsed = -1;
	}
  }
  
  return TRUE;
}