?? nmea.cpp
字號:
#include "stdafx.h"
#include "nmea.h"
#ifdef _DEBUG
#undef THIS_FILE
static char BASED_CODE THIS_FILE[] = __FILE__;
#endif
NMEA_BOOLEAN CNmeaSentence::Boolean(int nField) const
{
CString sField(Field(nField));
if (sField == _T("A"))
return True;
else if (sField == _T("V"))
return False;
else
return Unknown;
}
int CNmeaSentence::HexDigitToInt(char c)
{
int rVal = 0;
if ((c >= 'a') && (c <= 'f'))
rVal = c - 'a' + 10;
else if ((c >= 'A') && (c <= 'F'))
rVal = c - 'A' + 10;
else if ((c >= '0') && (c <= '9'))
rVal = c - '0';
return rVal;
}
DWORD CNmeaSentence::HexValue(const CString& sHexString)
{
int nLen = sHexString.GetLength();
DWORD rVal = 0;
int nMultiplier = 1;
for (int i=nLen-1; i>=0; i--)
{
TCHAR c = sHexString.GetAt(i);
rVal += (HexDigitToInt((char)c) * nMultiplier);
nMultiplier *= 16;
}
return rVal;
}
BYTE CNmeaSentence::ComputeChecksum() const
{
BYTE checksum = 0;
int nLength = m_Sentence.GetLength();
int i = 1; // Skip over the $ at the begining of the CNmeaSentence
while (i < nLength &&
m_Sentence[i] != _T('*') &&
m_Sentence[i] != _T('\r') &&
m_Sentence[i] != _T('\n') )
{
checksum ^= (BYTE) m_Sentence[i];
i++;
}
return checksum;
}
double CNmeaSentence::Double(int nField) const
{
CString sField(Field(nField));
double rVal = 0.0;
#ifdef _UNICODE
int nLength = sField.GetLength();
int nSize = (nLength + 1)/sizeof(TCHAR);
char* pszFieldAscii = new char[nSize];
WideCharToMultiByte(CP_ACP, 0, sField, -1, pszFieldAscii, nSize, NULL, NULL);
rVal = ::atof(pszFieldAscii);
delete [] pszFieldAscii;
#else
rVal = ::atof(sField);
#endif
return rVal;
}
NMEA_EASTWEST CNmeaSentence::EastOrWest(int nField) const
{
CString sField(Field(nField));
if (sField == _T("E"))
return East;
else if (sField == _T("W"))
return West;
else
return EW_Unknown;
}
NMEA_LONGITUDE CNmeaSentence::Longitude(int nPositionFieldNumber, int nEastingFieldNumber) const
{
NMEA_LONGITUDE rVal;
rVal.Value = Angle(nPositionFieldNumber);
rVal.Easting = EastOrWest(nEastingFieldNumber);
return rVal;
}
NMEA_LATITUDE CNmeaSentence::Latitude(int nPositionFieldNumber, int nNorthingFieldNumber) const
{
NMEA_LATITUDE rVal;
rVal.Value = Angle(nPositionFieldNumber);
rVal.Northing = NorthOrSouth(nNorthingFieldNumber);
return rVal;
}
CString CNmeaSentence::Field(int nDesiredField) const
{
CString rVal;
int i = 1;
int nCurrentField = 0;
int nLen = m_Sentence.GetLength();
while (nCurrentField < nDesiredField && i < nLen)
{
if (m_Sentence[i] == _T(',') || m_Sentence[i] == _T('*'))
nCurrentField++;
i++;
}
if (nCurrentField == nDesiredField)
{
while (i < nLen &&
m_Sentence[i] != _T(',') &&
m_Sentence[i] != _T('*') &&
m_Sentence[i] != _T('\n') &&
m_Sentence[i] != _T('\r') &&
m_Sentence[i] != 0x00 )
{
rVal += m_Sentence[i];
i++;
}
}
return rVal;
}
int CNmeaSentence::Integer(int nField) const
{
CString sInteger(Field(nField));
return ::_ttoi(sInteger);
}
NMEA_BOOLEAN CNmeaSentence::IsChecksumBad(int nField) const
{
// Checksums are optional, return TRUE if an existing checksum is known to be bad
CString sChecksum(Field(nField));
if (sChecksum.IsEmpty())
return Unknown;
BYTE CalculatedCheckSum = ComputeChecksum();
DWORD ReceivedCheckSum = HexValue(sChecksum);
if (CalculatedCheckSum != ReceivedCheckSum)
return True;
else
return False;
}
NMEA_NORTHSOUTH CNmeaSentence::NorthOrSouth(int nField) const
{
CString sField(Field(nField));
if (sField == _T("N"))
return North;
else if (sField == _T("S"))
return South;
else
return NS_Unknown;
}
NMEA_TIME CNmeaSentence::Time(int nField) const
{
NMEA_TIME rVal;
ZeroMemory(&rVal, sizeof(NMEA_TIME));
CString sTemp(Field(nField));
if (sTemp.GetLength() >= 6)
{
TCHAR sNumber[3];
sNumber[0] = sTemp[0];
sNumber[1] = sTemp[1];
sNumber[2] = 0x00;
rVal.wHour = (WORD) ::_ttoi(sNumber);
sNumber[0] = sTemp[2];
sNumber[1] = sTemp[3];
rVal.wMinute = (WORD) ::_ttoi(sNumber);
sNumber[0] = sTemp[4];
sNumber[1] = sTemp[5];
rVal.wSecond = (WORD) ::_ttoi(sNumber);
}
return rVal;
}
NMEA_DATE CNmeaSentence::Date(int nField) const
{
NMEA_DATE rVal;
ZeroMemory(&rVal, sizeof(NMEA_DATE));
CString sTemp(Field(nField));
if (sTemp.GetLength() >= 6)
{
TCHAR sNumber[3];
sNumber[0] = sTemp[0];
sNumber[1] = sTemp[1];
sNumber[2] = 0x00;
rVal.wDay = (WORD) ::_ttoi(sNumber);
sNumber[0] = sTemp[2];
sNumber[1] = sTemp[3];
rVal.wMonth = (WORD) ::_ttoi(sNumber);
sNumber[0] = sTemp[4];
sNumber[1] = sTemp[5];
rVal.wYear = (WORD) ::_ttoi(sNumber);
//intelligently adjust the year
if (rVal.wYear < 80)
rVal.wYear += 2000;
else if (rVal.wYear >= 75)
rVal.wYear += 1900;
}
return rVal;
}
NMEA_ANGLE CNmeaSentence::Angle(int nField) const
{
NMEA_ANGLE rVal;
ZeroMemory(&rVal, sizeof(NMEA_ANGLE));
CString sTemp(Field(nField));
int nPointIndex = sTemp.Find(_T('.'));
if (nPointIndex != -1)
{
CString sUnits(sTemp.Left(nPointIndex));
int nValue = ::_ttoi(sUnits);
rVal.Degrees = (WORD) (nValue/100);
rVal.Minutes = (WORD) (nValue - rVal.Degrees*100);
CString sFraction(sTemp.Right(sTemp.GetLength() - nPointIndex));
double fValue = 0.0;
#ifdef _UNICODE
int nLength = sFraction.GetLength();
int nSize = (nLength + 1)/sizeof(TCHAR);
char* pszFieldAscii = new char[nSize];
WideCharToMultiByte(CP_ACP, 0, sFraction, -1, pszFieldAscii, nSize, NULL, NULL);
fValue = ::atof(pszFieldAscii);
delete [] pszFieldAscii;
#else
fValue = ::atof(sFraction);
#endif
rVal.Seconds = (WORD) (fValue*60);
rVal.CentiSeconds = (WORD) ((fValue*60 - rVal.Seconds)*100.0);
}
return rVal;
}
DWORD CNmeaSentence::NmeaAngleToHundrethsOfSeconds(const NMEA_ANGLE& angle)
{
DWORD rVal = angle.Degrees*360000 +
angle.Minutes*6000 +
angle.Seconds*100 +
angle.CentiSeconds;
return rVal;
}
DWORD CNmeaSentence::NmeaBearingToHundrethsOfDegrees(const double& value)
{
int nDigits = (int) value;
int nHundreths = (int) ((value - nDigits)*100);
return nDigits*100 + nHundreths;
}
CRMCResponse::CRMCResponse()
{
Empty();
}
CRMCResponse::~CRMCResponse()
{
Empty();
}
void CRMCResponse::Empty()
{
ZeroMemory(&m_Time, sizeof(NMEA_TIME));
ZeroMemory(&m_Date, sizeof(NMEA_DATE));
m_IsDataValid = Unknown;
ZeroMemory(&m_Latitude, sizeof(NMEA_LATITUDE));
ZeroMemory(&m_Longitude, sizeof(NMEA_LONGITUDE));
m_SpeedOverGroundKnots = 0.0;
}
BOOL CRMCResponse::Parse(const CNmeaSentence& sentence)
{
// First we check the checksum
NMEA_BOOLEAN check = sentence.IsChecksumBad(12);
if (check == True)
{
TRACE(_T("CRMCResponse::Parse detected an Invalid checksum\n"));
return FALSE;
}
else if (check == Unknown)
{
TRACE(_T("CRMCResponse::Parse detected a missing checksum\n"));
return FALSE;
}
//then the data
m_Time = sentence.Time(1);
m_Date = sentence.Date(9);
m_IsDataValid = sentence.Boolean(2);
m_Latitude = sentence.Latitude(3, 4);
m_Longitude = sentence.Longitude(5, 6);
m_SpeedOverGroundKnots = sentence.Double(7);
m_Bearing = sentence.Double(8);
return TRUE;
}
CGGAResponse::CGGAResponse()
{
Empty();
}
CGGAResponse::~CGGAResponse()
{
Empty();
}
void CGGAResponse::Empty()
{
m_GPSQuality = 0;
m_nSatellites = 0;
m_AntennaAltitudeMeters = 0.0;
}
BOOL CGGAResponse::Parse(const CNmeaSentence& sentence)
{
// First we check the checksum...
if (sentence.IsChecksumBad(15) == True)
{
TRACE(_T("CGGAResponse::Parse detected an Invalid Checksum"));
return FALSE;
}
m_GPSQuality = sentence.Integer(6);
m_nSatellites = sentence.Integer(7);
m_AntennaAltitudeMeters = sentence.Double(9);
return TRUE;
}
?? 快捷鍵說明
復制代碼
Ctrl + C
搜索代碼
Ctrl + F
全屏模式
F11
切換主題
Ctrl + Shift + D
顯示快捷鍵
?
增大字號
Ctrl + =
減小字號
Ctrl + -