logo

English

이곳의 프로그래밍관련 정보와 소스는 마음대로 활용하셔도 좋습니다. 다만 쓰시기 전에 통보 정도는 해주시는 것이 예의 일것 같습니다. 질문이나 오류 수정은 siseong@gmail.com 으로 주세요. 감사합니다.

WIN CE, GPS - NMEA protocol - GPS Virtual Driver

by digipine posted Oct 28, 2017
?

Shortcut

PrevPrev Article

NextNext Article

Larger Font Smaller Font Up Down Go comment Print
?

Shortcut

PrevPrev Article

NextNext Article

Larger Font Smaller Font Up Down Go comment Print


Introduction

This article shows how to use virtual serial (COM) port to read and convert GPS data stream from one format to another allowing older legacy GPS applications to work with the newer GPS receivers.


Background


I have HPC CASIO Cassiopeia A-10 with Windows CE 2.00 that I'm using exclusively for GPS navigation. I'm using TeleType application for WinCE 2.00 with Delorme Tripmate GPS. Recently I upgraded my GPS with Pharos GPS-500 SiRF III and the TeleType application didn't work with it. It turns out that the application is working with an older version of the NMEA protocol than the GPS-500. The application is using NMEA 0183 v2.0 and the GPS-500 NMEA 0183 v2.3.

The application is actually using only two sentences from the NMEA protocol - GGA and RMC:

GGA —Global Positioning System Fixed Data

$GPGGA,161229.487,3723.2475,N,12158.3416,W,1,07,1.0,9.0,M,,,,0000*18
Name Example Units Description
Message ID $GPGGA   GGA protocol header
UTC Time 161229.487   hhmmss.sss
Latitude 3723.2475   ddmm.mmmm
N/S Indicator N   N=north or S=south
Longitude 12158.3416   dddmm.mmmm
E/W Indicator W   E=east or W=west
Position Fix Indicator 1   See Table 1-4
Satellites Used 7   Range 0 to 12
HDOP 1   Horizontal Dilution of Precision
MSL Altitude 9 meters
Units M meters
Geoid Separation   meters
Units M meters
Age of Diff. Corr.   second Null fields when DGPS is not used
Diff. Ref. Station ID 0000
Checksum *18
<CR> <LF>     End of message termination

Note that there are no differences in GGA between NMEA v2.0 and v2.3.

RMC—Recommended Minimum Specific GNSS Data

$GPRMC,161229.487,A,3723.2475,N,12158.3416,W,0.13,309.62,120598,,A*10
Name Example Units Description
Message ID $GPRMC   RMC protocol header
UTC Time 161229.487   hhmmss.sss
Status A   A=data valid or V=data not valid
Latitude 3723.2475   ddmm.mmmm
N/S Indicator N   N=north or S=south
Longitude 12158.3416   dddmm.mmmm
E/W Indicator W   E=east or W=west
Speed Over Ground 0.13 knots
Course Over Ground 309.62 degrees True
Date 120598   ddmmyy
Magnetic Variation   degrees E=east or W=west
Mode A   A=Autonomous, D=DGPS, E= DR (missing in v2.0)
Checksum *10
<CR> <LF>     End of message termination

The last field "Mode" does not exists in NMEA v2.0. In order for my application to work, it needs to translate the RMC from v2.3 (the GPS-500) to v2.0 (the application). In the translation, it needs to remove the last field from the RMC data and made it look like this:

$GPRMC,161229.487,A,3723.2475,N,12158.3416,W,0.13,309.62,120598,*20


Using the code


To build virtual serial (COM) port I used the excellent example provided in the following article DemoDriver.asp. (Big thanks to the author.)

The virtual port serves as a connection between the actual port and the application. In the process of reading the data from the GPS and passing it to the application, the virtual port translates the GPS data format from NMEA 2.3 to NMEA 2.0 for the RMC sentences.

The following code shows the virtual port "read" function:

DWORD COM_Read( DWORD hOpenContext, LPVOID pBuffer, DWORD Count )
{
    if (hOpenContext != OPEN_CONTEXT)
        return 0;

    // read from the actual port 
    DWORD dwBytes = 0;
    ReadFile(hComm, pBuffer, Count, &dwBytes, NULL);

    // convert the data before it's returned
    Convert( pBuffer, dwBytes );

    return dwBytes;
}

The function "Convert" is doing the work of locating and translating the RMC sentences:

 Collapse
char * atoh = "0123456789ABCDEF";

//             "   0    1    2    3    4    5    6    7    8    9 : ; < = > ? @    A    B    C    D    E    F"
BYTE htoa1[] = {0x00,0x10,0x20,0x30,0x40,0x50,0x60,0x70,0x80,0x90,0,0,0,0,0,0,0,0xA0,0xB0,0xC0,0xD0,0xE0,0xF0};
BYTE htoa2[] = {0x00,0x01,0x02,0x03,0x04,0x05,0x06,0x07,0x08,0x09,0,0,0,0,0,0,0,0x0A,0x0B,0x0C,0x0D,0x0E,0x0F};

void Convert( LPVOID pBuffer, DWORD Count )
{
    char* pCh = (char*)pBuffer;
    char ch, crc1, crc2; DWORD nCRC; BYTE state = 10;
    for (DWORD i=0;i<Count; i++)
    {
        ch = pCh[i];

        if (ch == '$') 
            state = 11; 
        else
        {
            switch ( state )
            {
            case 11: state = ch == 'G'? 12:10; break;
            case 12: state = ch == 'P'? 13:10; break;
            case 13: state = ch == 'R'? 14:10; break;
            case 14: state = ch == 'M'? 15:10; break;
            case 15: state = ch == 'C'? 16:10; break;
            case 16: state = ch == ','? 20:10; break;

            case 20:     if (ch == 'A') state = 21; break;
            case 21: state = ch == '*'? 22:20; break;
            case 22: 
                    crc1 = ch; state = 23; break;
            case 23: 
                { 
                    crc2 = ch; 

                    // get the crc
                    nCRC = htoa1[crc1 - '0'] + htoa2[crc2 - '0'];

                    // remove the chars we are deleting
                    nCRC -= 'A';
                    nCRC -= ',';

                    // ... ,,A*72\n
                    //          ^ current pos
                    //      ^ write over pos

                    pCh[i-4]='*';
                    pCh[i-3]=atoh[(nCRC & 0xF0) >> 4];
                    pCh[i-2]=atoh[ nCRC & 0x0F ];
                    pCh[i-1]=13;
                    pCh[i-0]=10;

                    state = 10;
                }
                break;
            }
        }
    }
}

The function goes through the input buffer pBuffer and locates any RMC sentences. For each RMC it checks for the string "A*" at the end and removes it. It also calculates and updates the CRC check sum at the end.

To install the virtual port driver we need to copy the driver dll file to \windows folder at the device and add these entries in the registry:

[HKEY_LOCAL_MACHINE\Drivers\BuiltIn\Serial6]
"ManagePort"=dword:00000002
"DeviceType"=dword:00000001
"Index"=dword:00000006
"DevConfig"=hex: 10,00,00,00,05,00,00,00,10,01,00,00,00,4b,00,00,00,00,08,00,00,00,00,00,00
"Tsp"="Unimodem.dll"
"Order"=dword:00000006
"Prefix"="COM"
"FriendlyName"="GPS Virtual Driver"
"Dll"="GpsVirtualDriver.dll"

"ManagePort" is the port number where the GPS device is connected to. In my case the GPS is connected with PCMCIA card and shows up as COM2 in the device.
"Index" is the virtual serial port COM number. In this example it is COM6.

To deploy the application to the device we need to build a cab file. This is simple INF file that is used to build the cab file:

 Collapse
; sample.inf
;
;==================================================

[Version]
Signature    = "$Windows NT$"
Provider    = "Gps"
CESignature    = "$Windows CE$"

;
; Supports only WinCE 2.00
;
[CEDevice]
VersionMin=2.00
VersionMax=2.00

[CEStrings]
AppName = "Virtual Driver"
InstallDir = %CE2%

[Strings]
reg_path = Drivers\Builtin\Serial6

;==================================================

[DefaultInstall]
CopyFiles    = Dllfiles
Addreg        = Regkeys

;==================================================

[SourceDisksNames]
1 =, "Common Files",, .

[SourceDisksFiles]
GpsVirtualDriver.dll    = 1

;==================================================
; Ouput directories for files & shortcuts

[DestinationDirs]
Dllfiles = 0, %CE2%

[Dllfiles]
GpsVirtualDriver.dll

[Regkeys]
HKLM,%reg_path%,Dll,0x00000000,GpsVirtualDriver.dll
HKLM,%reg_path%,Prefix,0x00000000,COM
HKLM,%reg_path%,FriendlyName,0x00000000,GPS Virtual Driver
HKLM,%reg_path%,Index,0x00010001,6
HKLM,%reg_path%,Order,0x00010001,2
HKLM,%reg_path%,ManagePort,0x00010001,2
HKLM,%reg_path%,DeviceType,0x00010001,1
HKLM,%reg_path%,Tsp,0x00000000,Unimodem.dll
HKLM,%reg_path%,DevConfig,0x00000001,10,00,00,00,05,00,00,00,10,01,00,00,00,4b,00,00,00,00,08,00,00,00,00,00,00

After the cab file is installed a soft reset is required for the driver to start working.


Points of Interest


Doing this small project was full of fun and I learned how to build simple device drivers for Windows CE 2.00. Now I have my Cassiopeia running the TeleType GPS application with the new GPS-500 receiver. The GPS-500 is very compact and it works out of my PCMCIA extension slot from where it gets its power and doesn't require batteries and/or bulky cables. It also gives me the opportunity to continue using my old and brave Cassiopeia A-10 for GPS navigation.


References


TeleType GPS FAQ: http://www.teletype.com/pages/support/faq.html
NMEA Reference Manual: http://www.sparkfun.com/datasheets/GPS/NMEA Reference Manual1.pdf

 
TAG •

List of Articles
No. Subject Author Date Views
25 [Linux] ubuntu 16.04에 QT Creator 설치하기 digipine 2017.11.02 24376
24 [Qt] QSettings 클래스의 설명과 사용법, 설정 저장위치 digipine 2017.11.02 1488
23 [Swift, MacOS] 맥 한글 파일명이 윈도우에서 자소 분리되는 현상 해결, NFD, NFC 엉뚱도마뱀 2018.12.11 20085
22 [ubuntu, 우분투] sendmail 설치 digipine 2017.11.02 2318
21 공짜 무료 C/C++ 컴파일러들 file digipine 2017.10.28 4383
20 난수발생기 개론 엉뚱도마뱀 2017.11.22 4332
19 대칭키 암호화관련 개념 정리 digipine 2017.11.09 1645
18 리눅스 /dev/random을 이용한 랜덤값 생성 엉뚱도마뱀 2017.11.22 1573
17 리눅스 커널의 Swap Memory에 대해서 digipine 2017.11.02 679
16 비밀번호 해쉬에 Salt(소금) 첨가하기 file 엉뚱도마뱀 2017.11.23 4284
15 소프트웨어 테스팅 전문가들을 위한 사이트 digipine 2017.11.02 610
14 수학적 구조물 모델링 만들기 소개 비디오 엉뚱도마뱀 2018.09.24 1052
13 악성코드 종류 구분 digipine 2017.11.13 962
12 언어 IDE 별로 git ignore 파일을 자동으로 만들어 주는 사이트 엉뚱도마뱀 2018.12.17 122936
11 우분투 18.04 MongoDB 설치 및 구성 lizard2019 2021.02.26 505
10 우분투 Nabi 한글 입력기 Tray(트레이) 상단 메뉴바로 옮기기 digipine 2017.11.03 1630
9 윈도우 한영 전환 쉬프트 스페이스로 변경 digipine 2017.11.03 413
8 윈도우즈 도스 커멘드(Command) 네트워크 관련 명령어 lizard2019 2019.02.07 1351
7 유닉스/리눅스 명령어 레퍼런스 digipine 2017.11.03 745
6 이벤트 텍소노미(Event Taxonomy)란 무엇인가요? digipine 2023.08.11 268
Board Pagination Prev 1 2 3 4 5 6 Next
/ 6