📄 gps.cpp
字号:
// Gps.cpp: implementation of the CGps class.
//
//////////////////////////////////////////////////////////////////////
#include "stdafx.h"
#include "gmark.h"
#include "define.h"
#include "Gps.h"
#include "GmarkDoc.h"
#include "GmarkView.h"
#ifdef _DEBUG
#undef THIS_FILE
static char THIS_FILE[]=__FILE__;
#define new DEBUG_NEW
#endif
FILE *fpRinex;
//////////////////////////////////////////////////////////////////////
// Construction/Destruction
//////////////////////////////////////////////////////////////////////
CGps::CGps()
{
m_portA.SetGps( this );
m_portA.m_bNoRead = FALSE;
m_portB.m_bNoRead = TRUE;
// Initialize the local variable
for(int i=0; i<GPS_MAX_RECNUM; i++)
{
m_tCommData[i] = NULL;
}
m_CurrIndex = 0;
m_bGpsMsgBusy = FALSE;
}
CGps::~CGps()
{
// Release the memory
for(int i=0; i<GPS_MAX_RECNUM; i++)
{
if(m_tCommData[i] != NULL) delete m_tCommData[i];
}
}
void CGps::OnReceived(unsigned char *buf, int nBytes)
{
m_pLog->Write((const char *)buf);
/* char sTemp[256];
memset(sTemp,0,sizeof(sTemp));
sprintf(sTemp,"nBytes=%d, len=%d, buf[0]=%2X", nBytes, strlen((const char*)buf), buf[0]);
m_pLog->Write((const char *)sTemp);*/
::SendMessage( m_hGmarkView, WM_GPSRECEIVED, (WORD)nBytes, (LONG)buf );
}
void CGps::AddChecksum(LPSTR cmd, LPSTR chksum)
{
int nIndex;
int nLength;
unsigned char cChkSum;
unsigned char str[4];
if(cmd == NULL || chksum == NULL) return;
nLength = strlen(cmd);
if( nLength < 1 ) return; //empty command not need to add chksum
memset( str, 0, sizeof(str) );
cChkSum = 0;
nIndex = 1;
while( nIndex < nLength )
{
cChkSum = cChkSum^cmd[nIndex];
nIndex++;
}
sprintf((char *)str, "*%02X", cChkSum);
strcpy( chksum, cmd );
chksum[nLength] = str[0];
chksum[nLength+1] = str[1];
chksum[nLength+2] = str[2];
}
void CGps::GetToken(LPSTR str, int n, LPSTR token)
{
int nLength = strlen(str);
int nCount = 0;
int nTokenCount = 0;
LPSTR szResult = new char[nLength+1];
memset( szResult, 0, nLength+1);
while( nCount < nLength)
{
if( str[nCount] == ',' || str[nCount] == '*' )
{
if( nTokenCount == n )
{
break;
}
else
{
nTokenCount++;
memset( szResult, 0, nLength+1);
}
}
else
{
szResult[strlen(szResult)] = str[nCount];
}
nCount++;
}
strcpy( token, szResult );
delete szResult;
}
void CGps::CompleteMsg(unsigned char *buf, int nBytes)
{
int nLen = nBytes;
char *p = (char *)buf;
char *CompMsg = new char[nLen + 1];
int index = m_CurrIndex;
int nIsCompleted;
int nIsFoundPlace = 0;
int nOrgLen = 0;
int nCompLen= 0;
nOrgLen = nBytes;
do
{
memset( CompMsg, 0, nLen + 1 );
nIsCompleted = GetCompleteMsg( p, nOrgLen, CompMsg, nCompLen );
//reset the offset in case anything left
if( nIsCompleted == RET_OK)
{
p = p + nCompLen + 2;
nOrgLen = nOrgLen - nCompLen - 2;
}
// Find an index not completed to place the message
index = m_CurrIndex;
nIsFoundPlace = 0;
do
{
if( m_tCommData[index] == NULL )
{
m_tCommData[index] = new COMM_DATA;
m_tCommData[index]->CompleteFlg = 0;
memset( m_tCommData[index]->Message,
0,
sizeof(m_tCommData[index]->Message) );
nIsFoundPlace = 1;
break;
}
else
{
if( m_tCommData[index]->CompleteFlg == 1 )
{
index = IndexIncrease( index );
continue;
}
nIsFoundPlace = 1;
break;
}
} while(index != m_CurrIndex); //search only one round
// append the message
if(nIsFoundPlace == 1)
{
memcpy( m_tCommData[index]->Message + strlen(m_tCommData[index]->Message),
(const char *)CompMsg, nCompLen );
}
else
{
memset( m_tCommData[index]->Message,
0,
sizeof(m_tCommData[index]->Message) );
memcpy( m_tCommData[index]->Message,
(const char *)CompMsg, nCompLen );
}
// set the flag
if(nIsCompleted == RET_OK)
{
m_tCommData[index]->CompleteFlg = 1;
// refresh the current index
m_CurrIndex = IndexIncrease( index );
}
}while( (nIsCompleted == RET_OK) && (strlen(p) > 0) );
delete CompMsg;
}
void CGps::CreateGPSData()
{
int index;
char szCmdType[GPS_MAX_NEMASIZE+1];
int nIsUpdate;
index = m_CurrIndex;
nIsUpdate = 0;
do {
if( m_tCommData[index] != NULL &&
m_tCommData[index]->CompleteFlg == 1 )
{
// process message only when the checksum is right
if( IsChecksumCorrect( m_tCommData[index]->Message) )
{
memset( szCmdType, 0, sizeof(szCmdType) );
//according the command type do corresponding deal
GetToken( m_tCommData[index]->Message, 0, szCmdType );
if(strcmp(szCmdType, "$GPGGA") == 0)
{
ParseGGA( m_tCommData[index]->Message );
// need to update gps data in the view
nIsUpdate = 1;
}
else if(strcmp(szCmdType, "$GPGLL") == 0)
{
ParseGLL( m_tCommData[index]->Message );
nIsUpdate = 1;
}
else if(strcmp(szCmdType, "$GPGSA") == 0)
{
ParseGSA( m_tCommData[index]->Message );
nIsUpdate = 1;
}
else if(strcmp(szCmdType, "$PASHR") == 0)
{
GetToken( m_tCommData[index]->Message, 1, szCmdType );
if(strcmp(szCmdType, "PBN") == 0) // PBN data
{
ParsePBN( m_tCommData[index]->Message );
}
if(strcmp(szCmdType, "MCA") == 0) // MCA data
{
ParseMCA( m_tCommData[index]->Message );
}
if(strcmp(szCmdType, "SNV") == 0) // SNV data
{
ParseSNV( m_tCommData[index]->Message );
}
else if(strcmp(szCmdType, "CRT") == 0)
{
ParseCRT( m_tCommData[index]->Message );
}
}
}
// release the record memory
delete m_tCommData[index];
m_tCommData[index] = NULL;
}
index = IndexIncrease( index );
}
while( index != m_CurrIndex );
if( nIsUpdate == 1 )
{
// Notify the view to refresh the gps data
::PostMessage( m_hGmarkView, WM_GPSUPDATE, 0, 0 );
}
}
int CGps::IndexIncrease(int index)
{
if( index >= GPS_MAX_RECNUM - 1 ) index = 0;
else index++;
return index;
}
int CGps::IndexDecrease(int index)
{
if( index <= 0 ) index = GPS_MAX_RECNUM - 1;
else index--;
return index;
}
void CGps::ParseGGA(char *Message)
{
char szToken[GPS_MAX_NEMASIZE+1];
double c = 111352.0044; // = r*pai/180 = 6380000(m)*3.1415926/180
GetToken( Message, 6, szToken );
m_tGpsData.Status = atoi(szToken);
GetToken( Message, 7, szToken );
m_tGpsData.SatCount = atoi(szToken);
GetToken( Message, 4, szToken );
m_tGpsData.Longitude = DegToVal(szToken); //Jing du
m_tGpsData.LonDeg = (int)m_tGpsData.Longitude;
m_tGpsData.LonMin = (int)((m_tGpsData.Longitude - m_tGpsData.LonDeg)*60);
m_tGpsData.LonSec = ((m_tGpsData.Longitude - m_tGpsData.LonDeg)*60 - m_tGpsData.LonMin)*60;
GetToken( Message, 2, szToken );
m_tGpsData.Latitude = DegToVal(szToken); //Wei du
m_tGpsData.LatDeg = (int)m_tGpsData.Latitude;
m_tGpsData.LatMin = (int)((m_tGpsData.Latitude - m_tGpsData.LatDeg)*60);
m_tGpsData.LatSec = ((m_tGpsData.Latitude - m_tGpsData.LatDeg)*60 - m_tGpsData.LatMin)*60;
// chang (longitude,latitude) to (x,y)
// m_tGpsData.X =(m_tGpsData.Longitude - m_orig_lon)*c;
// m_tGpsData.Y =(m_tGpsData.Latitude - m_orig_lat)*c;
}
void CGps::ParseGLL(char *Message)
{
char szToken[GPS_MAX_NEMASIZE+1];
GetToken( Message, 1, szToken );
m_tGpsData.Latitude = DegToVal(szToken);
GetToken( Message, 3, szToken );
m_tGpsData.Longitude = DegToVal(szToken);
GetToken( Message, 6, szToken );
// m_tGpsData.Status = atoi(szToken);
}
void CGps::ParseGSA(char *Message)
{
char szToken[GPS_MAX_NEMASIZE+1];
GetToken( Message, 15, szToken );
m_tGpsData.PDOP = atof(szToken);
GetToken( Message, 16, szToken );
m_tGpsData.HDOP = atof(szToken);
GetToken( Message, 17, szToken );
m_tGpsData.VDOP = atof(szToken);
}
void CGps::ParseCRT(char *Message)
{
char szToken[GPS_MAX_NEMASIZE+1];
GetToken( Message, 2, szToken );
m_tGpsData.Status = atoi(szToken);
GetToken( Message, 3, szToken );
m_tGpsData.SatCount = atoi(szToken);
GetToken( Message, 5, szToken );
m_tGpsData.X = atof(szToken);
GetToken( Message, 6, szToken );
m_tGpsData.Y = atof(szToken);
GetToken( Message, 13, szToken );
m_tGpsData.PDOP = atof(szToken);
GetToken( Message, 14, szToken );
m_tGpsData.HDOP = atof(szToken);
GetToken( Message, 15, szToken );
m_tGpsData.VDOP = atof(szToken);
}
void CGps::ParsePBN(char *Message)
{
#define PBN_DATA_SIZE 56
char PbnData[PBN_DATA_SIZE];
memcpy( PbnData, Message + 11, PBN_DATA_SIZE );
if( !BinCheckSum(PbnData, PBN_DATA_SIZE) ) return;
PBN_DATA *pbnData;
// get PBN_DATA structure
pbnData = (PBN_DATA *)PbnData;
// write PBN_DATA to RINEX file
fwrite(pbnData, 1, sizeof(PBN_DATA), fpRinex);
}
void CGps::ParseMCA(char *Message)
{
#define MCA_DATA_SIZE 37
char McaData[MCA_DATA_SIZE];
memcpy( McaData, Message + 11, MCA_DATA_SIZE );
if( !BinCheckSum(McaData, MCA_DATA_SIZE, 1) ) return;
MCA_DATA *mcaData;
// get MCA_DATA structure
mcaData = (MCA_DATA *)McaData;
// write MCA_DATA to RINEX file
fwrite(mcaData, 1, sizeof(MCA_DATA), fpRinex);
}
void CGps::ParseSNV(char *Message)
{
#define SNV_DATA_SIZE 132
char SnvData[SNV_DATA_SIZE];
memcpy( SnvData, Message + 11, SNV_DATA_SIZE );
if( !BinCheckSum(SnvData, SNV_DATA_SIZE) ) return;
SNV_DATA *snvData;
// get SNV_DATA structure
snvData = (SNV_DATA *)SnvData;
// write SNV_DATA to RINEX file
fwrite(snvData, 1, sizeof(SNV_DATA), fpRinex);
}
double CGps::DegToVal(char *deg)
{
double result;
char *p=NULL;
char d[4];
char m[9];
memset( d, 0, sizeof(d) );
memset( m, 0, sizeof(m) );
p = strstr( deg, "." );
if(p)
{
int n = p-deg;
strncpy( d, deg, n-2 );
strncpy( m, deg+n-2, 8 );
}
else
{
strncpy( d, deg, sizeof(d)-1 );
strcpy( m, "" );
}
result = atoi(d) + atof(m)/60;
return result;
}
int CGps::SendCmd(LPSTR cmd)
{
LPSTR pSendCmd;
char szCrLf[3] = {0x0d, 0x0a, 0};
int nLength;
int nRet;
nLength = strlen(cmd);
pSendCmd = new char[nLength + 6];
memset( pSendCmd, 0, nLength + 6 );
// add checksum to command
AddChecksum(cmd, pSendCmd);
// add <cr>+<lf>
strcpy( pSendCmd + strlen(pSendCmd), szCrLf );
nRet = m_portA.SendData(pSendCmd, strlen(pSendCmd));
if( (unsigned int)nRet != strlen(pSendCmd) ) nRet = RET_NG;
else nRet = RET_OK;
delete pSendCmd;
return nRet;
}
int CGps::Initialize(int baudrate)
{
int nRet = RET_OK;
//set the GGA message to be output automatically every 1 second.
SendCmd("$PASHS,NME,GGA,A,ON,1");
//Initialize the COM6 for port B of GPS module
return nRet;
}
int CGps::Close()
{
int nRet = RET_OK;
if(!m_portA.Close()) nRet = RET_NG;
if(!m_portB.Close()) nRet = RET_NG;
//close the raw data file
fclose(fpRinex);
return nRet;
}
void CGps::SetViewHandle(HWND hView)
{
m_hGmarkView = hView;
}
int CGps::Connect()
{
int nRet = RET_OK;
//Initialize the COM2 for port A of GPS module
while(1)
{
//the default bps of port A is 4800
#ifndef _WIN32_WCE_CEPC
if( m_portA.Open(2, 115200) == FALSE )
#else
if( m_portA.Open(1, 115200) == FALSE )
#endif
{
nRet = RET_NG;
break;
}
//the default bps of port B is 4800
#ifndef _WIN32_WCE_CEPC
if( m_portB.Open(6, 57600) == FALSE )
#else
if( m_portB.Open(0, 57600) == FALSE )
#endif
{
nRet = RET_NG;
break;
}
break;
}
//open file to write raw data
char filename[MAX_PATH];
memset( filename, 0, sizeof(filename) );
this->m_GmarkView->CreateFilename(filename, FN_RAW);
fpRinex = fopen( filename, "wb" );
return nRet;
}
HWND CGps::GetViewHandle()
{
return m_hGmarkView;
}
int CGps::GetCompleteMsg(LPSTR OrgMsg, int nOrgLen, LPSTR CompMsg, int & nCompLen)
{
int nRet = RET_NG;
char * p = NULL;
for(int i = 0; i < nOrgLen-1; i++)
{
if( OrgMsg[i] == 0x0d &&
OrgMsg[i+1] == 0x0a )
{
p = OrgMsg + i;
break;
}
}
if( p == NULL )
{
memcpy( CompMsg, OrgMsg, nOrgLen );
nCompLen = nOrgLen;
nRet = RET_NG;
}
else
{
nCompLen = p - OrgMsg;
memcpy( CompMsg, OrgMsg, nCompLen );
nRet = RET_OK;
}
return nRet;
}
void CGps::ClearGpsData()
{
m_tGpsData.Latitude = -1;
m_tGpsData.Longitude = -1;
m_tGpsData.SatCount = -1;
m_tGpsData.Status = -1;
// Notify the view to refresh the gps data
::PostMessage( m_hGmarkView, WM_GPSUPDATE, 0, 0 );
}
void CGps::WriteRTCM(char *rtcm)
{
m_portB.SendData( rtcm, strlen(rtcm) );
}
void CGps::SetOrigPosition(double orig_lon, double orig_lat)
{
m_orig_lon = orig_lon;
m_orig_lat = orig_lat;
}
BOOL CGps::IsChecksumCorrect(char *message)
{
char szCmd[GPS_MAX_NEMASIZE+1];
char szChecksum[GPS_MAX_NEMASIZE+1];
char *p;
memset(szCmd, 0, sizeof(szCmd));
memset(szChecksum, 0, sizeof(szChecksum));
if(strncmp(message, "$PASHR,PBN,", 11)==0)
{
return TRUE;
}
p = strstr( message, "*" );
if(!p)
{
return FALSE;
}
strncpy( szCmd, message, p-message );
AddChecksum( szCmd, szChecksum );
if( strcmp( message, szChecksum ) != 0 )
{
return FALSE;
}
return TRUE;
}
void CGps::SetViewWnd(CWnd *pWnd)
{
m_GmarkView = (CGmarkView *)pWnd;
}
BOOL CGps::BinCheckSum(char *buf, int len, int BinType)
{
if(BinType == 0)
{
unsigned short chsum, checksum;
unsigned short * p;
p = (unsigned short *)buf;
chsum = 0;
for(int i=0; i<len-2; i+=2)
{
chsum += *p;
p++;
}
checksum = *p;
if(chsum == checksum) return TRUE;
else return FALSE;
}
else
{
unsigned char chsum, checksum;
unsigned char * p;
p = (unsigned char *)buf;
chsum = 0;
for(int i=0; i<len-1; i++)
{
chsum = (*p)^chsum;
p++;
}
checksum = *p;
if(chsum == checksum) return TRUE;
else return FALSE;
}
}
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -