GSOF message parsing and decoding
Applicable receivers: All receivers
This topic describes a simple General Serial Output Format (GSOF) message protocol parser. The console utility is written in “C” and compiled in a Linux environment using the GNU Compiler Collection (GCC) version 4.6.3 20120306. The Code has been compiled and validated using Fedora Version 16 (64 Bit) running on VMware Workstation (Virtual Machine) version 9.0.1 build-894247. The source is being provided to Trimble customers who wish to decode and use the GSOF Protocol.
Useful links:
-
Refer to the Output Messages section
Source code description
The data is assumed to be the raw GSOF output from a Trimble receiver. That is, it consists of TRIMCOMM™ packets (02..03) of type 0x40 in which are embedded GSOF subtype records. The program accepts such data on standard input (either live as part of a '|'-pipeline, or from a file via '<'-redirection. It synchronizes with the individual TRIMCOMM packets and extracts the contents. When a complete set of GSOF-0x40 packets is collected, the total contents is parsed and listed. For some GSOF subtypes there is a full decoder below and the contents are listed, item by item. Other packets are listed just as Hex bytes. You can write additional routines to the decoder if required, using the routines as models to implement for additional GSOF subtypes.
The program starts with main which collects TRIMCOMM packets. It then moves to postGsofData() which collects the GSOF data from multiple packets and decides when a complete set has been received. Then it goes to processGsofData() which steps through the collected data parsing the individual GSOF subtype records. If the GSOF subtype is one of the special ones where it has a decoder, that decoder is called, otherwise the program just dumps the Hex bytes of the record. The program runs until the Stdinput indicates end of file (EOF) [see gc()] or the user stops it with a “Ctrl “C” action.
NOTE – This program is not designed to handle corrupted data. It does not contain sophisticated logic to handle corrupted data packets. This source is being provided “As Is”. The program was written to enable viewing the contents of well-formed GSOF data, not to debug the overall formatting. There should be some resistance to additional data such as NMEA being mixed into the GSOF stream, as this has not been validated.
Header, defines, types, and routines
This section contains header, defines, types, and routines parsers for individual GSOF records:
|
Header and defines
#include <stdio.h>
#include <unistd.h>
#include <string.h>
#define PI (3.14159265358979)
Types
typedef unsigned long U32 ;
typedef unsigned short U16 ;
typedef signed short S16 ;
typedef unsigned char U8 ;
Global variables
/* A few global variables needed for collecting full GSOF packets from multiple TRIMCOMM packets. */
unsigned char gsofData[2048] ;
int gsofDataIndex ;
Function: GetU32
/**********************************************************************/
unsigned long getU32( unsigned char * * ppData )
/**********************************************************************/
// Used by the decoding routines to grab 4 bytes and pack them into
// a U32. Fed ppData which is a pointer to a pointer to the start of
// the data bytes. The pointer variable referenced by ppData is moved
// beyond the four bytes.
// This is designed to work on little-endian processors (Like Pentiums).
// Effectively that means we reverse the order of the bytes.
// This would need to be rewritten to work on big-endian PowerPCs.
{
unsigned long retValue ;
unsigned char * pBytes ;
pBytes = (unsigned char *)(&retValue) + 3 ;
*pBytes-- = *(*ppData)++ ;
*pBytes-- = *(*ppData)++ ;
*pBytes-- = *(*ppData)++ ;
*pBytes = *(*ppData)++ ;
return retValue ;
} /* end of getU32() */
Function: GetFloat
/**********************************************************************/
float getFloat( unsigned char * * ppData )
/**********************************************************************/
// Used by the decoding routines to grab 4 bytes and pack them into
// a Float. Fed ppData which is a pointer to a pointer to the start of
// the data bytes. The pointer variable referenced by ppData is moved
// beyond the four bytes.
// This is designed to work on little-endian processors (Like Pentiums).
// Effectively that means we reverse the order of the bytes.
// This would need to be rewritten to work on big-endian PowerPCs.
{
float retValue ;
unsigned char * pBytes ;
pBytes = (unsigned char *)(&retValue) + 3 ;
*pBytes-- = *(*ppData)++ ;
*pBytes-- = *(*ppData)++ ;
*pBytes-- = *(*ppData)++ ;
*pBytes = *(*ppData)++ ;
return retValue ;
} /* end of getFloat() */
Function: GetDouble
/**********************************************************************/
double getDouble( unsigned char * * ppData )
/**********************************************************************/
// Used by the decoding routines to grab 8 bytes and pack them into
// a Double. Fed ppData which is a pointer to a pointer to the start of
// the data bytes. The pointer variable referenced by ppData is moved
// beyond the four bytes.
// This is designed to work on little-endian processors (Like Pentiums).
// Effectively that means we reverse the order of the bytes.
// This would need to be rewritten to work on big-endian PowerPCs.
{
double retValue ;
unsigned char * pBytes ;
pBytes = (unsigned char *)(&retValue) + 7 ;
*pBytes-- = *(*ppData)++ ;
*pBytes-- = *(*ppData)++ ;
*pBytes-- = *(*ppData)++ ;
*pBytes-- = *(*ppData)++ ;
*pBytes-- = *(*ppData)++ ;
*pBytes-- = *(*ppData)++ ;
*pBytes-- = *(*ppData)++ ;
*pBytes = *(*ppData)++ ;
return retValue ;
} /* end of getDouble() */
Function: GetU16
/**********************************************************************/
unsigned short getU16( unsigned char * * ppData )
/**********************************************************************/
// Used by the decoding routines to grab 2 bytes and pack them into
// a U16. Fed ppData which is a pointer to a pointer to the start of
// the data bytes. The pointer variable referenced by ppData is moved
// beyond the four bytes.
// This is designed to work on little-endian processors (Like Pentiums).
// Effectively that means we reverse the order of the bytes.
// This would need to be rewritten to work on big-endian PowerPCs.
{
unsigned short retValue ;
unsigned char * pBytes ;
pBytes = (unsigned char *)(&retValue) + 1 ;
*pBytes-- = *(*ppData)++ ;
*pBytes = *(*ppData)++ ;
return retValue ;
} /* end of getU16() */
/***********************************************************************
* The next section contains routines which are parsers for individual
* GSOF records. They are all passed a length (which is listed but
* usually not used) and a pointer to the data bytes that make up the
* record.
***********************************************************************/
Position Time
/**********************************************************************/
void processPositionTime( int length, unsigned char *pData )
/**********************************************************************/
{
unsigned long msecs ;
unsigned short weekNumber ;
int nSVs ;
int flags1 ;
int flags2 ;
int initNumber ;
printf( " GsofType:1 - PositionTime len:%d\n", length) ;
msecs = getU32( &pData ) ;
weekNumber = getU16( &pData ) ;
nSVs = *pData++ ;
flags1 = *pData++ ;
flags2 = *pData++ ;
initNumber = *pData++ ;
printf( " Milliseconds:%ld Week:%d #Svs:%d "
"flags:%02X:%02X init:%d\n",
msecs,
weekNumber,
nSVs,
flags1,
flags2,
initNumber
) ;
} /* end of processPositionTime() */
Latitude, Longitude and Height
/**********************************************************************/
void processLatLonHeight( int length, unsigned char *pData )
/**********************************************************************/
{
double lat, lon, height ;
printf( " GsofType:2 - LatLongHeight len:%d\n", length ) ;
lat = getDouble( &pData ) * 180.0 / PI ;
lon = getDouble( &pData ) * 180.0 / PI ;
height = getDouble( &pData ) ;
printf( " Lat:%.7f Lon:%.7f Height:%.3f\n",
lat,
lon,
height
) ;
} /* end of processLatLonHeight() */
Earth-Centered, Earth-Fixed Position
/**********************************************************************/
void processECEF( int length, unsigned char *pData )
/**********************************************************************/
{
double X, Y, Z ;
printf( " GsofType:3 - ECEF len:%d\n", length ) ;
X = getDouble( &pData ) ;
Y = getDouble( &pData ) ;
Z = getDouble( &pData ) ;
printf( " X:%.3f Y:%.3f Z:%.3f\n", X, Y, Z ) ;
} /* end of processECEF() */
Earth-Centered, Earth-Fixed Delta Position
/**********************************************************************/
void processEcefDelta( int length, unsigned char *pData )
/**********************************************************************/
{
double X, Y, Z ;
printf( " GsofType:6 - ECEF Delta len:%d\n", length) ;
X = getDouble( &pData ) ;
Y = getDouble( &pData ) ;
Z = getDouble( &pData ) ;
printf( " X:%.3f Y:%.3f Z:%.3f\n", X, Y, Z ) ;
} /* end of processEcefDelta() */
Tangent Plane Delta
/**********************************************************************/
void processTangentPlaneDelta( int length, unsigned char *pData )
/**********************************************************************/
{
double E, N, U ;
printf( " GsofType:7 - Tangent Plane Delta len:%d\n", length) ;
E = getDouble( &pData ) ;
N = getDouble( &pData ) ;
U = getDouble( &pData ) ;
printf( " East:%.3f North:%.3f Up:%.3f\n", E, N, U ) ;
} /* end of processTangentPlaneDelta() */
Velocity Data
/**********************************************************************/
void processVelocityData( int length, unsigned char *pData )
/**********************************************************************/
{
int flags ;
float velocity ;
float heading ;
float vertical ;
printf( " GsofType:8 - Velocity Data len:%d\n", length) ;
flags = *pData++ ;
velocity = getFloat( &pData ) ;
heading = getFloat( &pData ) * 180.0 / PI ;
vertical = getFloat( &pData ) ;
printf( " Flags:%02X velocity:%.3f heading:%.3f vertical:%.3f\n",
flags,
velocity,
heading,
vertical
) ;
} /* end of processVelocityData() */
Current UTC Time
/**********************************************************************/
void processUtcTime( int length, unsigned char *pData )
/**********************************************************************/
{
printf( " GsofType:16 - UTC Time Info len:%d\n", length) ;
U32 msecs = getU32( &pData ) ;
U16 weekNumber = getU16( &pData ) ;
S16 utcOffset = getU16( &pData ) ;
U8 flags = *pData++ ;
printf( " ms:%lu week:%u utcOff:%d flags:%02x\n",
msecs,
weekNumber,
utcOffset,
flags
) ;
} /* end of processUtcTime() */
PDOP Info
/**********************************************************************/
void processPdopInfo( int length, unsigned char *pData )
/**********************************************************************/
{
float pdop ;
float hdop ;
float vdop ;
float tdop ;
printf( " GsofType:9 - PDOP Info len:%d\n", length) ;
pdop = getFloat( &pData ) ;
hdop = getFloat( &pData ) ;
vdop = getFloat( &pData ) ;
tdop = getFloat( &pData ) ;
printf( " PDOP:%.1f HDOP:%.1f VDOP:%.1f TDOP:%.1f\n",
pdop,
hdop,
vdop,
tdop
) ;
} /* end of processPdopInfo() */
SV Brief Info
/**********************************************************************/
void processBriefSVInfo( int length, unsigned char *pData )
/**********************************************************************/
{
int nSVs ;
int i ;
printf( " GsofType:13 - SV Brief Info len:%d\n", length) ;
nSVs = *pData++ ;
printf( " SvCount:%d\n", nSVs ) ;
for ( i = 0 ; i < nSVs ; ++i )
{
int prn ;
int flags1 ;
int flags2 ;
prn = *pData++ ;
flags1 = *pData++ ;
flags2 = *pData++ ;
printf( " Prn:%-2d flags:%02X:%02X\n", prn, flags1, flags2 );
}
} /* end of processBriefSVInfo */
SV Brief Info (All Satellite Systems)
/**********************************************************************/
void processAllBriefSVInfo( int length, unsigned char *pData )
/**********************************************************************/
{
int nSVs ;
int i ;
printf( " GsofType:33 - All SV Brief Info len:%d\n", length) ;
nSVs = *pData++ ;
printf( " SvCount:%d\n", nSVs ) ;
for ( i = 0 ; i < nSVs ; ++i )
{
int prn ;
int system ;
int flags1 ;
int flags2 ;
prn = *pData++ ;
system = *pData++;
flags1 = *pData++ ;
flags2 = *pData++ ;
printf( " %s SV:%-2d flags:%02X:%02X\n",
system == 0 ? "GPS"
: system == 1 ? "SBAS"
: system == 2 ? "GLONASS"
: system == 3 ? "GALILEO"
: system == 4 ? "QZSS"
: system == 5 ? "BEIDOU"
: system == 6 ? "RESERVED" : "RESERVED",
prn, flags1, flags2 );
}
} /* end of processAllBriefSVInfo */
SV Detailed Info (All Satellite Systems)
/**********************************************************************/
void processAllDetailedSVInfo( int length, unsigned char *pData )
/**********************************************************************/
{
int nSVs ;
int i ;
printf( " GsofType:34 - All SV Detailed Info len:%d\n", length) ;
nSVs = *pData++ ;
printf( " SvCount:%d\n", nSVs ) ;
for ( i = 0 ; i < nSVs ; ++i )
{
int prn ;
int system ;
int flags1 ;
int flags2 ;
int elevation ;
int azimuth ;
int snr[ 3 ];
prn = *pData++ ;
system = *pData++;
flags1 = *pData++ ;
flags2 = *pData++ ;
elevation = *pData++ ;
azimuth = getU16( &pData ) ;
snr[ 0 ] = *pData++;
snr[ 1 ] = *pData++;
snr[ 2 ] = *pData++;
printf( " %s SV:%-2d flags:%02X:%02X\n"
" El:%2d Az:%3d\n"
" SNR %3s %5.2f\n"
" SNR %3s %5.2f\n"
" SNR %3s %5.2f\n",
system == 0 ? "GPS"
: system == 1 ? "SBAS"
: system == 2 ? "GLONASS"
: system == 3 ? "GALILEO"
: system == 4 ? "QZSS"
: system == 5 ? "BEIDOU"
: system == 6 ? "RESERVED" : "RESERVED",
prn, flags1, flags2,
elevation, azimuth,
system == 3 ? "E1 " : "L1 ", (float)snr[ 0 ] / 4.0,
system == 3 ? "N/A " : "L2 ", (float)snr[ 1 ] / 4.0,
system == 3 ? "E5 "
: system == 2 ? "G1P" : "L5 ", (float)snr[ 2 ] / 4.0
);
}
} /* end of processAllDetailedSVInfo */
SV Detailed Info
/**********************************************************************/
void processSvDetailedInfo( int length, unsigned char *pData )
/**********************************************************************/
{
int nSVs ;
int i ;
printf( " GsofType:14 - SV Detailed Info len:%d\n", length) ;
nSVs = *pData++ ;
printf( " SvCount:%d\n", nSVs ) ;
for ( i = 0 ; i < nSVs ; ++i )
{
int prn ;
int flags1 ;
int flags2 ;
int elevation ;
int azimuth ;
int l1Snr ;
int l2Snr ;
prn = *pData++ ;
flags1 = *pData++ ;
flags2 = *pData++ ;
elevation = *pData++ ;
azimuth = getU16( &pData ) ;
l1Snr = *pData++ ;
l2Snr = *pData++ ;
printf( " Prn:%-2d flags:%02X:%02X elv:%-2d azm:%-3d "
"L1snr:%-5.2f L2snr:%-5.2f\n",
prn,
flags1,
flags2,
elevation,
azimuth,
((double)l1Snr) / 4.0 ,
((double)l2Snr) / 4.0
) ;
}
} /* end of processSvDetailedInfo() */
Attitude Info
/**********************************************************************/
void processAttitudeInfo( int length , unsigned char *pData )
/**********************************************************************/
{
double gpsTime ;
unsigned char flags ;
unsigned char nSVs ;
unsigned char mode ;
double pitch ;
double yaw ;
double roll ;
double range ;
double pdop ;
printf( " GsofType:27 - AttitudeInfo len:%d\n",
length
) ;
gpsTime = (double)getU32( &pData ) / 1000.0 ;
flags = *pData++ ;
nSVs = *pData++ ;
mode = *pData++ ;
++pData ; // reserved
pitch = getDouble( &pData ) / PI * 180.0 ;
yaw = getDouble( &pData ) / PI * 180.0 ;
roll = getDouble( &pData ) / PI * 180.0 ;
range = getDouble( &pData ) ;
pdop = (double)getU16( &pData ) / 10.0 ;
printf( " Time:%.3f"
" flags:%02X"
" nSVs:%d"
" mode:%d\n"
" pitch:%.3f"
" yaw:%.3f"
" roll:%.3f"
" range:%.3f"
" pdop:%.1f"
"\n",
gpsTime,
flags,
nSVs,
mode,
pitch,
yaw,
roll,
range,
pdop
) ;
// Detect if the extended record information is present
if ( length > 42 )
{
float pitch_var ;
float yaw_var ;
float roll_var ;
float pitch_yaw_covar ;
float pitch_roll_covar ;
float yaw_roll_covar ;
float range_var;
// The variances are in units of radians^2
pitch_var = getFloat( &pData ) ;
yaw_var = getFloat( &pData ) ;
roll_var = getFloat( &pData ) ;
// The covariances are in units of radians^2
pitch_yaw_covar = getFloat( &pData ) ;
pitch_roll_covar = getFloat( &pData ) ;
yaw_roll_covar = getFloat( &pData ) ;
// The range variance is in units of m^2
range_var = getFloat( &pData ) ;printf( " variance (radians^2)"
" pitch:%.4e"
" yaw:%.4e"
" roll:%.4e"
"\n",
pitch_var,
yaw_var,
roll_var ) ;
printf( " covariance (radians^2)"
" pitch-yaw:%.4e"
" pitch-roll:%.4e"
" yaw-roll:%.4e"
"\n",
pitch_yaw_covar,
pitch_roll_covar,
yaw_roll_covar ) ;
printf( " variance (m^2)"
" range: %.4e"
"\n",
range_var ) ;
}
} /* end of processAttitudeInfo() */
L-Band Status Info
/**********************************************************************/
void processLbandStatus( int length , unsigned char *pData )
/**********************************************************************/
{
unsigned char name[5];
float freq;
unsigned short bit_rate;
float snr;
unsigned char hp_xp_subscribed_engine;
unsigned char hp_xp_library_mode;
unsigned char vbs_library_mode;
unsigned char beam_mode;
unsigned char omnistar_motion;
float horiz_prec_thresh;
float vert_prec_thresh;
unsigned char nmea_encryption;
float iq_ratio;
float est_ber;
unsigned long total_uw;
unsigned long total_bad_uw;
unsigned long total_bad_uw_bits;
unsigned long total_viterbi;
unsigned long total_bad_viterbi;
unsigned long total_bad_messages;
unsigned char meas_freq_is_valid = -1;
double meas_freq = 0.0;
printf( " GsofType:40 - LBAND status len:%d\n",
length
) ;
memcpy( name, pData, 5 );
pData += 5;
freq = getFloat( &pData );
bit_rate = getU16( &pData );
snr = getFloat( &pData );
hp_xp_subscribed_engine = *pData++;
hp_xp_library_mode = *pData++;
vbs_library_mode = *pData++;
beam_mode = *pData++;
omnistar_motion = *pData++;
horiz_prec_thresh = getFloat( &pData );
vert_prec_thresh = getFloat( &pData );
nmea_encryption = *pData++;
iq_ratio = getFloat( &pData );
est_ber = getFloat( &pData );
total_uw = getU32( &pData );
total_bad_uw = getU32( &pData );
total_bad_uw_bits = getU32( &pData );
total_viterbi = getU32( &pData );
total_bad_viterbi = getU32( &pData );
total_bad_messages = getU32( &pData );
if( length > 61 )
{
meas_freq_is_valid = *pData++;
meas_freq = getDouble( &pData );
}
printf( " Name:%s"
" Freq:%g"
" bit rate:%d"
" SNR:%g"
"\n"
" HP/XP engine:%d"
" HP/XP mode:%d"
" VBS mode:%d"
"\n"
" Beam mode:%d"
" Omnistar Motion:%d"
"\n"
" Horiz prec. thresh.:%g"
" Vert prec. thresh.:%g"
"\n"
" NMEA encryp.:%d"
" I/Q ratio:%g"
" Estimated BER:%g"
"\n"
" Total unique words(UW):%d"
" Bad UW:%d"
" Bad UW bits:%d"
"\n"
" Total Viterbi:%d"
" Corrected Viterbi:%d"
" Bad messages:%d"
"\n"
" Meas freq valid?:%d"
" Meas freq:%.3f"
"\n"
,
name,
freq,
bit_rate,
snr,
hp_xp_subscribed_engine,
hp_xp_library_mode,
vbs_library_mode,
beam_mode,
omnistar_motion,
horiz_prec_thresh,
vert_prec_thresh,
nmea_encryption,
iq_ratio,
est_ber,
total_uw,
total_bad_uw,
total_bad_uw_bits,
total_viterbi,
total_bad_viterbi,
total_bad_messages,
meas_freq_is_valid,
meas_freq
) ;
} /* end of processLbandStatus() */
Function: Process GSOF Data
/**********************************************************************/
void processGsofData( void )
/**********************************************************************/
/* Called when a complete set of GSOF packets has been received.
* The data bytes collected are available in global gsofData and the
* number of those bytes is in gsofDataIndex.
*
* This routine just goes through the bytes and parses the sub-type
* records. Each of those has a Type and a Length. If the type is
* one of the special types we know about, we call the proper parser.
* Otherwise we just hex-dump the record.
*/
{
int i ;
int gsofType ;
int gsofLength ;
unsigned char * pData ;
printf( "\nGSOF Records\n" ) ;
pData = gsofData ;
while (pData < gsofData + gsofDataIndex )
{
gsofType = *pData++ ;
gsofLength = *pData++ ;
// If the type is one that we know about, then call the specific
// parser for that type.
if ( gsofType == 1 )
{
processPositionTime( gsofLength, pData ) ;
pData += gsofLength ;
}
else
if ( gsofType == 2 )
{
processLatLonHeight( gsofLength, pData ) ;
pData += gsofLength ;
}
else
if ( gsofType == 3 )
{
processECEF( gsofLength, pData ) ;
pData += gsofLength ;
}
else
if ( gsofType == 4 )
{
processLocalDatum( gsofLength, pData ) ;
pData += gsofLength ;
}
else
if ( gsofType == 8 )
{
processVelocityData( gsofLength, pData ) ;
pData += gsofLength ;
}
else
if ( gsofType == 9 )
{
processPdopInfo( gsofLength, pData ) ;
pData += gsofLength ;
}
else
if ( gsofType == 13 )
{
processBriefSVInfo( gsofLength, pData ) ;
pData += gsofLength ;
}
else
if ( gsofType == 16 )
{
processUtcTime( gsofLength, pData ) ;
pData += gsofLength ;
}
else
if ( gsofType == 33 )
{
processAllBriefSVInfo( gsofLength, pData ) ;
pData += gsofLength ;
}
else
if ( gsofType == 34 )
{
processAllDetailedSVInfo( gsofLength, pData ) ;
pData += gsofLength ;
}
else
if ( gsofType == 14 )
{
processSvDetailedInfo( gsofLength, pData ) ;
pData += gsofLength ;
}
else
if ( gsofType == 27 )
{
processAttitudeInfo( gsofLength, pData ) ;
pData += gsofLength ;
}
else
if ( gsofType == 26 )
{
processPositionTimeUtc( gsofLength, pData ) ;
pData += gsofLength ;
}
else
if ( gsofType == 6 )
{
processEcefDelta( gsofLength, pData ) ;
pData += gsofLength ;
}
else
if ( gsofType == 7 )
{
processTangentPlaneDelta( gsofLength, pData ) ;
pData += gsofLength ;
}
else
if ( gsofType == 40 )
{
processLbandStatus( gsofLength, pData ) ;
pData += gsofLength ;
}
else
{
// Not a type we know about. Hex dump the bytes and move on.
printf( " GsofType:%d len:%d\n ",
gsofType,
gsofLength
) ;
for ( i = 0 ; i < gsofLength ; ++i )
{
printf( "%02X%s",
*pData++,
i % 16 == 15 ? "\n " : " "
) ;
}
// Terminate the last line if needed.
if (gsofLength %16 != 0)
printf( "\n" ) ;
}
printf( "\n" ) ;
}
printf( "\n" ) ;
} /* end of processGsofData() */
Function: Post GSOF Data
/**********************************************************************/
void postGsofData( unsigned char * pData, int length )
/**********************************************************************/
// Called whenever we get a new TRIMCOMM GSOF packet (type 0x40).
// These all contain a portion (or all) of a complete GSOF packet.
// Each portion contains a Transmission Number, an incrementing value
// linking related portions.
// Each portion contains a Page Index, 0..N, which increments for each
// portion in the full GSOF packet.
// Each portion contains a Max Page Index, N, which is the same for all
// portions.
//
// Each portion's data is appended to the global buffer, gsofData[].
// The next available index in that buffer is always gsofDataIndex.
// When we receive a portion with Page Index == 0, that signals the
// beginning of a new GSOF packet and we restart the gsofDataIndex at
// zero.
//
// When we receive a portion where Page Index == Max Page Index, then
// we have received the complete GSOF packet and can decode it.
{
int gsofTransmissionNumber ;
int gsofPageIndex ;
int gsofMaxPageIndex ;
int i ;
gsofTransmissionNumber = *pData++ ;
gsofPageIndex = *pData++ ;
gsofMaxPageIndex = *pData++ ;
printf( " GSOF packet: Trans#:%d Page:%d MaxPage:%d\n",
gsofTransmissionNumber,
gsofPageIndex,
gsofMaxPageIndex
) ;
// If this is the first portion, restart the buffering system.
if (gsofPageIndex == 0)
gsofDataIndex = 0 ;
// Transfer the data bytes in this portion to the global buffer.
for (i = 3 ; i < length ; ++i)
gsofData[ gsofDataIndex++ ] = *pData++ ;
// If this is the last portion in a packet, process the whole packet.
if (gsofPageIndex == gsofMaxPageIndex)
processGsofData() ;
} /* end of postGsofData() */
Function: Get Character (gc)
/**********************************************************************/
int gc( void )
/**********************************************************************/
/* This is a getchar() wrapper. It just returns the characters
* from standard input. If it detects end of file, it aborts
* the entire program.
*
* NOTE: This function is not optimal because if the program is in the middle of a packet there is
* no indication. This is a simple parsing application
*/
{
int c ;
c = getchar() ;
if (c != EOF)
return c ;
printf( "END OF FILE \n" ) ;
_exit( 0 ) ;
} /* end of gc() */
Function: Main
/**********************************************************************/
int main( int argn, char **argc )
/**********************************************************************/
/* Main entry point. Looks for TRIMCOMM packets. When we find one with
* type 0x40, its bytes are extracted and passed on to the GSOF
* handler.
*/
{
int tcStx ;
int tcStat ;
int tcType ;
int tcLength ;
int tcCsum ;
int tcEtx ;
unsigned char tcData[256] ;
int i ;
printf( "GSOF Parser\n") ;
while ( 1 )
{
tcStx = gc() ;
if ( tcStx == 0x02 )
{
tcStat = gc() ;
tcType = gc() ;
tcLength = gc() ;
for ( i = 0 ; i < tcLength ; ++i )
tcData[i] = gc() ;
tcCsum = gc() ;
tcEtx = gc() ;
printf( "STX:%02Xh Stat:%02Xh Type:%02Xh "
"Len:%d CS:%02Xh ETX:%02Xh\n",
tcStx,
tcStat,
tcType,
tcLength,
tcCsum,
tcEtx
) ;
if (tcType == 0x40)
postGsofData( tcData, tcLength ) ;
}
else
printf( "Skipping %02X\n", tcStx ) ;
}
return 0 ;
} // main