Shop OBEX P1 Docs P2 Docs Learn Events
Garmin GPS Communication with Propeller — Parallax Forums

Garmin GPS Communication with Propeller

dman271828dman271828 Posts: 2
edited 2013-09-16 12:09 in General Discussion
What is the serial communication protocol to do serial communication between a Garmin GPS (Nuvi 255W) and the Propeller? I included the C language example. What protocol follows the StartPVTPacket and StopPVTPacket which requests that the GPS send the position velocity and time data? Once I know the proper protocol I can develop the spin code to do the Propeller serial communication directly to the Garmin GPS.


// This file contains sample code to help application developers
// interface with Garmin USB units. This should not be viewed as a
// full implementation of PC to unit communication. It does not include
// error checking and other elements of a full implementation.
// Also, there are notes in the code suggesting other elements that
// might be necessary.


#include <stdio.h>
#include <tchar.h>


#include <windows.h>
#include <initguid.h>
#include <setupapi.h> // You may need to explicitly link with setupapi.lib
#include <winioctl.h>


DEFINE_GUID(GUID_DEVINTERFACE_GRMNUSB, 0x2c9c45c2L, 0x8e7d, 0x4c08, 0xa1, 0x2d, 0x81, 0x6b, 0xba, 0xe7, 0x22, 0xc0);


#define IOCTL_ASYNC_IN CTL_CODE (FILE_DEVICE_UNKNOWN, 0x850, METHOD_BUFFERED, FILE_ANY_ACCESS)
#define IOCTL_USB_PACKET_SIZE CTL_CODE (FILE_DEVICE_UNKNOWN, 0x851, METHOD_BUFFERED, FILE_ANY_ACCESS)


#define MAX_BUFFER_SIZE 4096
#define ASYNC_DATA_SIZE 64


//
HANDLE gHandle;
DWORD gUSBPacketSize;


//
#pragma pack( push, 1)
typedef struct
{
unsigned char mPacketType;
unsigned char mReserved1;
unsigned short mReserved2;
unsigned short mPacketId;
unsigned short mReserved3;
unsigned long mDataSize;
BYTE mData[2];
} Packet_t;
#pragma pack( pop)


//
void
SendPacket
(
Packet_t aPacket
)
{
DWORD theBytesToWrite = sizeof( aPacket ) - 1 + aPacket.mDataSize;
DWORD theBytesReturned = 0;


WriteFile( gHandle,
&aPacket,
theBytesToWrite,
&theBytesReturned,
NULL );


// If the packet size was an exact multiple of the USB packet
// size, we must make a final write call with no data
if( theBytesToWrite % gUSBPacketSize == 0 )
{
WriteFile( gHandle,
0,
0,
&theBytesReturned,
NULL );
}
}


//
// Gets a single packet. Since packets may come simultaneously through
// asynchrous reads and normal (ReadFile) reads, a full implementation
// may require a packet queue and multiple threads.
Packet_t*
GetPacket
(
)
{
Packet_t* thePacket = 0;
DWORD theBufferSize = 0;
BYTE* theBuffer = 0;


for( ; ; )
{
// Read async data until the driver returns less than the
// max async data size, which signifies the end of a packet
BYTE theTempBuffer[ASYNC_DATA_SIZE];
BYTE* theNewBuffer = 0;
DWORD theBytesReturned = 0;


DeviceIoControl( gHandle,
IOCTL_ASYNC_IN,
0,
0,
theTempBuffer,
sizeof( theTempBuffer ),
&theBytesReturned,
NULL );


theBufferSize += ASYNC_DATA_SIZE;
theNewBuffer = (BYTE*) malloc( theBufferSize );
memcpy( theNewBuffer, theBuffer, theBufferSize - ASYNC_DATA_SIZE );
memcpy( theNewBuffer + theBufferSize - ASYNC_DATA_SIZE,
theTempBuffer,
ASYNC_DATA_SIZE );


free( theBuffer );


theBuffer = theNewBuffer;


if( theBytesReturned != ASYNC_DATA_SIZE )
{
thePacket = (Packet_t*) theBuffer;
break;
}
}


// If this was a small "signal" packet, read a real
// packet using ReadFile
if( thePacket->mPacketType == 0 &&
thePacket->mPacketId == 2 )
{
BYTE* theNewBuffer = (BYTE*) malloc( MAX_BUFFER_SIZE );
DWORD theBytesReturned = 0;


free( thePacket );


// A full implementation would keep reading (and queueing)
// packets until the driver returns a 0 size buffer.
ReadFile( gHandle,
theNewBuffer,
MAX_BUFFER_SIZE,
&theBytesReturned,
NULL );


return (Packet_t*) theNewBuffer;
}
else
{
return thePacket;
}
}


//
void
Initialize
(
)
{
// Make all the necessary Windows calls to get a handle
// to our USB device
DWORD theBytesReturned = 0;


PSP_INTERFACE_DEVICE_DETAIL_DATA theDevDetailData = 0;
SP_DEVINFO_DATA theDevInfoData = { sizeof( SP_DEVINFO_DATA ) };


Packet_t theStartSessionPacket = { 0, 0, 0, 5, 0 , 0 };
Packet_t* thePacket = 0;


HDEVINFO theDevInfo = SetupDiGetClassDevs(
(GUID*) &GUID_DEVINTERFACE_GRMNUSB,
NULL,
NULL,
DIGCF_PRESENT | DIGCF_INTERFACEDEVICE );


SP_DEVICE_INTERFACE_DATA theInterfaceData;
theInterfaceData.cbSize = sizeof( theInterfaceData );


if( !SetupDiEnumDeviceInterfaces( theDevInfo,
NULL,
(GUID*) &GUID_DEVINTERFACE_GRMNUSB,
0,
&theInterfaceData ) &&
GetLastError() == ERROR_NO_MORE_ITEMS )
{
gHandle = 0;
return;
}




SetupDiGetDeviceInterfaceDetail(
theDevInfo,
&theInterfaceData,
NULL,
0,
&theBytesReturned,
NULL );


theDevDetailData =
(PSP_INTERFACE_DEVICE_DETAIL_DATA) malloc( theBytesReturned );
theDevDetailData->cbSize = sizeof( SP_INTERFACE_DEVICE_DETAIL_DATA );


SetupDiGetDeviceInterfaceDetail( theDevInfo,
&theInterfaceData,
theDevDetailData,
theBytesReturned,
NULL,
&theDevInfoData );


gHandle = CreateFile(
theDevDetailData->DevicePath,
GENERIC_READ | GENERIC_WRITE,
0,
NULL,
OPEN_EXISTING,
FILE_ATTRIBUTE_NORMAL,
NULL );


free( theDevDetailData );


// Get the USB packet size, which we need for sending packets
DeviceIoControl( gHandle,
IOCTL_USB_PACKET_SIZE,
0,
0,
&gUSBPacketSize,
sizeof( gUSBPacketSize ),
&theBytesReturned,
NULL );


// Tell the device that we are starting a session.
SendPacket( theStartSessionPacket );


// Wait until the device is ready to the start the session
for( ; ; )
{
thePacket = GetPacket();


if( thePacket->mPacketType == 0 &&
thePacket->mPacketId == 6 )
{
break;
}


free( thePacket );
}


free( thePacket );
}


//
int _tmain(int argc, _TCHAR* argv[])
{
int x;


Packet_t theProductDataPacket = { 20, 0, 0, 254, 0, 0, {0,0}};
Packet_t thePosPacket = {20, 0, 0, 10, 0, 2, {2,0}};
Packet_t StartRawPacket = {20, 0, 0, 10, 0, 4, {110,0}};
Packet_t StopRawPacket = {20, 0, 0, 10, 0, 4, {111,0}};
Packet_t StartPVTPacket = {20, 0, 0, 10, 0, 4, {49,0}};
Packet_t StopPVTPacket = {20, 0, 0, 10, 0, 4, {50,0}};
Packet_t SendEphemerisPacket = {20, 0, 0, 10, 0, 4, {93,0}};
Packet_t StopTransPacket = {20, 0, 0, 10, 0, 4, {0,0}};
Packet_t theStartSessionPacket = { 0, 0, 0, 5, 0 , 0 };
Packet_t theTurnOffPacket = { 0, 0, 0, 8, 0 , 0 };




Packet_t* thePacket = 0;


/*
theProductDataPacket.mDataSize = 4;
theProductDataPacket.mPacketId = 10;
theProductDataPacket.mPacketType = 20;
theProductDataPacket.mReserved1 = 0;
theProductDataPacket.mReserved2 = 0;
theProductDataPacket.mReserved3 = 0;
*/


Initialize();


if( gHandle == 0 )
{
printf( "%s", "No device\n" );
return 0;
}


// Tell the device to send product data
SendPacket( theStartSessionPacket );
Sleep(50);
SendPacket( theProductDataPacket );




// Get the product data packet
for( ; ; )
{
thePacket = GetPacket();
printf("ID %d\n", thePacket->mPacketId );


if( thePacket->mPacketType == 20 )// &&
// thePacket->mPacketId == 254 )
{
break;
}


// free( thePacket );
}


//free( thePacket );
// Print out the product description
printf( "%s\n", (char*) &thePacket->mData[0] );




SendPacket( theStartSessionPacket );
Sleep(50);


thePacket = GetPacket();




SendPacket(StartPVTPacket);
Sleep(3000);






thePacket = GetPacket();




/*
Sleep(50);


// Print out the product description
printf( "%s\n", (char*) &thePacket->mData[0] );


Sleep(50);


thePacket = GetPacket();


// Print out the product description
printf( "%s\n", (char*) &thePacket->mData[0] );
*/




// Print out the product description
for(x = 0; x <300 ; x++ )
{
printf( "%c", (char) thePacket->mData[x] );
if( x%60 == 0 )
printf("\n");
}


free( thePacket );


return 0;
}

Comments

  • SRLMSRLM Posts: 5,045
    edited 2013-09-16 12:09
    Well, it looks like you have everything you need in the C code. Are you asking for somebody to go through and extract the protocol from the C code?
Sign In or Register to comment.