Generate GAL NMEA sentences at AP side

Generate GAGSV sentence at AP side when
NMEA Provider is set to AP in gps.conf

Change-Id: I2cd436d61bab09386aaa813e85591e02f560b41e
CRs-fixed: 1051996
This commit is contained in:
Baili Feng 2016-08-11 13:11:28 +08:00
parent 2e3d64352b
commit b707704985
2 changed files with 420 additions and 319 deletions

View file

@ -123,6 +123,7 @@ typedef struct loc_eng_data_s
boolean generateNmea; boolean generateNmea;
uint32_t gps_used_mask; uint32_t gps_used_mask;
uint32_t glo_used_mask; uint32_t glo_used_mask;
uint32_t gal_used_mask;
float hdop; float hdop;
float pdop; float pdop;
float vdop; float vdop;

View file

@ -34,6 +34,105 @@
#include <math.h> #include <math.h>
#include <platform_lib_includes.h> #include <platform_lib_includes.h>
#define GLONASS_SV_ID_OFFSET 64
#define MAX_SATELLITES_IN_USE 12
typedef struct loc_nmea_sv_meta_s
{
char talker[3];
GnssConstellationType svType;
uint32_t mask;
uint32_t svIdOffset;
} loc_nmea_sv_meta;
/*===========================================================================
FUNCTION loc_eng_nmea_sv_meta_init
DESCRIPTION
Init loc_nmea_sv_meta passed in
DEPENDENCIES
NONE
RETURN VALUE
Pointer to loc_nmea_sv_meta
SIDE EFFECTS
N/A
===========================================================================*/
static loc_nmea_sv_meta* loc_nmea_sv_meta_init(loc_eng_data_s_type *loc_eng_data_p,
loc_nmea_sv_meta& sv_meta, GnssConstellationType svType, bool needCombine)
{
if (!loc_eng_data_p)
return NULL;
memset(&sv_meta, 0, sizeof(sv_meta));
sv_meta.svType = svType;
sv_meta.talker[0] = 'G';
switch (svType)
{
case GNSS_CONSTELLATION_GPS:
sv_meta.talker[1] = 'P';
sv_meta.mask = loc_eng_data_p->gps_used_mask;
break;
case GNSS_CONSTELLATION_GLONASS:
sv_meta.talker[1] = 'L';
sv_meta.mask = loc_eng_data_p->glo_used_mask;
// GLONASS SV ids are from 65-96
sv_meta.svIdOffset = GLONASS_SV_ID_OFFSET;
break;
case GNSS_CONSTELLATION_GALILEO:
sv_meta.talker[1] = 'A';
sv_meta.mask = loc_eng_data_p->gal_used_mask;
break;
default:
LOC_LOGE("NMEA Error unknow constellation type: %d", svType);
return NULL;
}
if (needCombine &&
(loc_eng_data_p->gps_used_mask ? 1 : 0) +
(loc_eng_data_p->glo_used_mask ? 1 : 0) +
(loc_eng_data_p->gal_used_mask ? 1 : 0) > 1)
{
// If GPS, GLONASS, Galileo etc. are combined
// to obtain the reported position solution,
// talker shall be set to GN, to indicate that
// the satellites are used in a combined solution
sv_meta.talker[1] = 'N';
}
return &sv_meta;
}
/*===========================================================================
FUNCTION loc_eng_nmea_count_bits
DESCRIPTION
Count how many bits are set in mask
DEPENDENCIES
NONE
RETURN VALUE
Bits number set in mask
SIDE EFFECTS
N/A
===========================================================================*/
static uint32_t loc_eng_nmea_count_bits(uint32_t mask)
{
uint32_t count = 0;
while (mask)
{
if (mask & 1)
count++;
mask = mask >> 1;
}
return count;
}
/*=========================================================================== /*===========================================================================
FUNCTION loc_eng_nmea_send FUNCTION loc_eng_nmea_send
@ -96,6 +195,249 @@ int loc_eng_nmea_put_checksum(char *pNmea, int maxSize)
return (length + checksumLength + 1); return (length + checksumLength + 1);
} }
/*===========================================================================
FUNCTION loc_eng_nmea_generate_GSA
DESCRIPTION
Generate NMEA GSA sentences generated based on position report
Currently below sentences are generated:
- $GPGSA : GPS DOP and active SVs
- $GLGSA : GLONASS DOP and active SVs
- $GAGSA : GALILEO DOP and active SVs
- $GNGSA : GNSS DOP and active SVs
DEPENDENCIES
NONE
RETURN VALUE
Number of SVs used
SIDE EFFECTS
N/A
===========================================================================*/
uint32_t loc_eng_nmea_generate_GSA(loc_eng_data_s_type *loc_eng_data_p,
const GpsLocationExtended &locationExtended,
char* sentence,
int bufSize,
loc_nmea_sv_meta* sv_meta_p)
{
if (!loc_eng_data_p || !sentence || bufSize <= 0 || !sv_meta_p)
{
LOC_LOGE("NMEA Error invalid arguments.");
return 0;
}
char* pMarker = sentence;
int lengthRemaining = bufSize;
int length = 0;
uint32_t svUsedCount = 0;
uint32_t svUsedList[32] = {0};
char fixType = '\0';
const char* talker = sv_meta_p->talker;
uint32_t svIdOffset = sv_meta_p->svIdOffset;
uint32_t mask = sv_meta_p->mask;
for (uint8_t i = 1; mask > 0 && svUsedCount < 32; i++)
{
if (mask & 1)
svUsedList[svUsedCount++] = i + svIdOffset;
mask = mask >> 1;
}
if (svUsedCount == 0 && GNSS_CONSTELLATION_GPS != sv_meta_p->svType)
return 0;
if (svUsedCount == 0)
fixType = '1'; // no fix
else if (svUsedCount <= 3)
fixType = '2'; // 2D fix
else
fixType = '3'; // 3D fix
// Start printing the sentence
// Format: $--GSA,a,x,xx,xx,xx,xx,xx,xx,xx,xx,xx,xx,xx,xx,p.p,h.h,v.v*cc
// a : Mode : A : Automatic, allowed to automatically switch 2D/3D
// x : Fixtype : 1 (no fix), 2 (2D fix), 3 (3D fix)
// xx : 12 SV ID
// p.p : Position DOP (Dilution of Precision)
// h.h : Horizontal DOP
// v.v : Vertical DOP
// cc : Checksum value
length = snprintf(pMarker, lengthRemaining, "$%sGSA,A,%c,", talker, fixType);
if (length < 0 || length >= lengthRemaining)
{
LOC_LOGE("NMEA Error in string formatting");
return 0;
}
pMarker += length;
lengthRemaining -= length;
// Add first 12 satellite IDs
for (uint8_t i = 0; i < 12; i++)
{
if (i < svUsedCount)
length = snprintf(pMarker, lengthRemaining, "%02d,", svUsedList[i]);
else
length = snprintf(pMarker, lengthRemaining, ",");
if (length < 0 || length >= lengthRemaining)
{
LOC_LOGE("NMEA Error in string formatting");
return 0;
}
pMarker += length;
lengthRemaining -= length;
}
// Add the position/horizontal/vertical DOP values
if (locationExtended.flags & GPS_LOCATION_EXTENDED_HAS_DOP)
{ // dop is in locationExtended, (QMI)
length = snprintf(pMarker, lengthRemaining, "%.1f,%.1f,%.1f",
locationExtended.pdop,
locationExtended.hdop,
locationExtended.vdop);
}
else if (loc_eng_data_p->pdop > 0 && loc_eng_data_p->hdop > 0 && loc_eng_data_p->vdop > 0)
{ // dop was cached from sv report (RPC)
length = snprintf(pMarker, lengthRemaining, "%.1f,%.1f,%.1f",
loc_eng_data_p->pdop,
loc_eng_data_p->hdop,
loc_eng_data_p->vdop);
}
else
{ // no dop
length = snprintf(pMarker, lengthRemaining, ",,");
}
/* Sentence is ready, add checksum and broadcast */
length = loc_eng_nmea_put_checksum(sentence, bufSize);
loc_eng_nmea_send(sentence, length, loc_eng_data_p);
return svUsedCount;
}
/*===========================================================================
FUNCTION loc_eng_nmea_generate_GSV
DESCRIPTION
Generate NMEA GSV sentences generated based on sv report
Currently below sentences are generated:
- $GPGSV: GPS Satellites in View
- $GNGSV: GLONASS Satellites in View
- $GAGSV: GALILEO Satellites in View
DEPENDENCIES
NONE
RETURN VALUE
NONE
SIDE EFFECTS
N/A
===========================================================================*/
void loc_eng_nmea_generate_GSV(loc_eng_data_s_type *loc_eng_data_p,
const GnssSvStatus &svStatus,
char* sentence,
int bufSize,
loc_nmea_sv_meta* sv_meta_p)
{
if (!loc_eng_data_p || !sentence || bufSize <= 0)
{
LOC_LOGE("NMEA Error invalid argument.");
return;
}
char* pMarker = sentence;
int lengthRemaining = bufSize;
int length = 0;
int sentenceCount = 0;
int sentenceNumber = 1;
int svNumber = 1;
const char* talker = sv_meta_p->talker;
uint32_t svIdOffset = sv_meta_p->svIdOffset;
uint32_t mask = sv_meta_p->mask;
uint32_t svCount = loc_eng_nmea_count_bits(mask);
if (svCount <= 0)
{
// no svs in view, so just send a blank $--GSV sentence
snprintf(sentence, lengthRemaining, "$%sGSV,1,1,0,", talker);
length = loc_eng_nmea_put_checksum(sentence, bufSize);
loc_eng_nmea_send(sentence, length, loc_eng_data_p);
return;
}
svNumber = 1;
sentenceNumber = 1;
sentenceCount = svCount / 4 + (svCount % 4 != 0);
while (sentenceNumber <= sentenceCount)
{
pMarker = sentence;
lengthRemaining = bufSize;
length = snprintf(pMarker, lengthRemaining, "$%sGSV,%d,%d,%02d",
talker, sentenceCount, sentenceNumber, svCount);
if (length < 0 || length >= lengthRemaining)
{
LOC_LOGE("NMEA Error in string formatting");
return;
}
pMarker += length;
lengthRemaining -= length;
for (int i=0; (svNumber <= svStatus.num_svs) && (i < 4); svNumber++)
{
if (sv_meta_p->svType == svStatus.gnss_sv_list[svNumber - 1].constellation)
{
length = snprintf(pMarker, lengthRemaining,",%02d,%02d,%03d,",
svStatus.gnss_sv_list[svNumber - 1].svid,
(int)(0.5 + svStatus.gnss_sv_list[svNumber - 1].elevation), //float to int
(int)(0.5 + svStatus.gnss_sv_list[svNumber - 1].azimuth)); //float to int
if (length < 0 || length >= lengthRemaining)
{
LOC_LOGE("NMEA Error in string formatting");
return;
}
pMarker += length;
lengthRemaining -= length;
if (svStatus.gnss_sv_list[svNumber - 1].c_n0_dbhz > 0)
{
length = snprintf(pMarker, lengthRemaining,"%02d",
(int)(0.5 + svStatus.gnss_sv_list[svNumber - 1].c_n0_dbhz)); //float to int
if (length < 0 || length >= lengthRemaining)
{
LOC_LOGE("NMEA Error in string formatting");
return;
}
pMarker += length;
lengthRemaining -= length;
}
i++;
}
}
length = loc_eng_nmea_put_checksum(sentence, bufSize);
loc_eng_nmea_send(sentence, length, loc_eng_data_p);
sentenceNumber++;
} //while
}
/*=========================================================================== /*===========================================================================
FUNCTION loc_eng_nmea_generate_pos FUNCTION loc_eng_nmea_generate_pos
@ -103,10 +445,12 @@ DESCRIPTION
Generate NMEA sentences generated based on position report Generate NMEA sentences generated based on position report
Currently below sentences are generated within this function: Currently below sentences are generated within this function:
- $GPGSA : GPS DOP and active SVs - $GPGSA : GPS DOP and active SVs
- $GNGSA : GLONASS DOP and active SVs - $GLGSA : GLONASS DOP and active SVs
- $GPVTG : Track made good and ground speed - $GAGSA : GALILEO DOP and active SVs
- $GPRMC : Recommended minimum navigation information - $GNGSA : GNSS DOP and active SVs
- $GPGGA : Time, position and fix related data - $--VTG : Track made good and ground speed
- $--RMC : Recommended minimum navigation information
- $--GGA : Time, position and fix related data
DEPENDENCIES DEPENDENCIES
NONE NONE
@ -144,174 +488,49 @@ void loc_eng_nmea_generate_pos(loc_eng_data_s_type *loc_eng_data_p,
int utcMSeconds = (location.gpsLocation.timestamp)%1000; int utcMSeconds = (location.gpsLocation.timestamp)%1000;
if (generate_nmea) { if (generate_nmea) {
// ------------------ char talker[3] = {'G', 'P', '\0'};
// ------$GPGSA------
// ------------------
uint32_t svUsedCount = 0; uint32_t svUsedCount = 0;
uint32_t svUsedList[32] = {0}; uint32_t count = 0;
uint32_t mask = loc_eng_data_p->gps_used_mask; loc_nmea_sv_meta sv_meta;
for (uint8_t i = 1; mask > 0 && svUsedCount < 32; i++) // -------------------
// ---$GPGSA/$GNGSA---
// -------------------
count = loc_eng_nmea_generate_GSA(loc_eng_data_p, locationExtended, sentence, sizeof(sentence),
loc_nmea_sv_meta_init(loc_eng_data_p, sv_meta, GNSS_CONSTELLATION_GPS, true));
if (count > 0)
{ {
if (mask & 1) svUsedCount += count;
svUsedList[svUsedCount++] = i; talker[1] = sv_meta.talker[1];
mask = mask >> 1;
} }
// clear the cache so they can't be used again
loc_eng_data_p->gps_used_mask = 0;
char fixType; // -------------------
if (svUsedCount == 0) // ---$GLGSA/$GNGSA---
fixType = '1'; // no fix // -------------------
else if (svUsedCount <= 3)
fixType = '2'; // 2D fix
else
fixType = '3'; // 3D fix
length = snprintf(pMarker, lengthRemaining, "$GPGSA,A,%c,", fixType); count = loc_eng_nmea_generate_GSA(loc_eng_data_p, locationExtended, sentence, sizeof(sentence),
loc_nmea_sv_meta_init(loc_eng_data_p, sv_meta, GNSS_CONSTELLATION_GLONASS, true));
if (length < 0 || length >= lengthRemaining) if (count > 0)
{ {
LOC_LOGE("NMEA Error in string formatting"); svUsedCount += count;
return; talker[1] = sv_meta.talker[1];
} }
pMarker += length;
lengthRemaining -= length;
for (uint8_t i = 0; i < 12; i++) // only the first 12 sv go in sentence // -------------------
// ---$GAGSA/$GNGSA---
// -------------------
count = loc_eng_nmea_generate_GSA(loc_eng_data_p, locationExtended, sentence, sizeof(sentence),
loc_nmea_sv_meta_init(loc_eng_data_p, sv_meta, GNSS_CONSTELLATION_GALILEO, true));
if (count > 0)
{ {
if (i < svUsedCount) svUsedCount += count;
length = snprintf(pMarker, lengthRemaining, "%02d,", svUsedList[i]); talker[1] = sv_meta.talker[1];
else
length = snprintf(pMarker, lengthRemaining, ",");
if (length < 0 || length >= lengthRemaining)
{
LOC_LOGE("NMEA Error in string formatting");
return;
}
pMarker += length;
lengthRemaining -= length;
} }
if (locationExtended.flags & GPS_LOCATION_EXTENDED_HAS_DOP) // -------------------
{ // dop is in locationExtended, (QMI) // ------$--VTG-------
length = snprintf(pMarker, lengthRemaining, "%.1f,%.1f,%.1f", // -------------------
locationExtended.pdop,
locationExtended.hdop,
locationExtended.vdop);
}
else if (loc_eng_data_p->pdop > 0 && loc_eng_data_p->hdop > 0 && loc_eng_data_p->vdop > 0)
{ // dop was cached from sv report (RPC)
length = snprintf(pMarker, lengthRemaining, "%.1f,%.1f,%.1f",
loc_eng_data_p->pdop,
loc_eng_data_p->hdop,
loc_eng_data_p->vdop);
}
else
{ // no dop
length = snprintf(pMarker, lengthRemaining, ",,");
}
length = loc_eng_nmea_put_checksum(sentence, sizeof(sentence));
loc_eng_nmea_send(sentence, length, loc_eng_data_p);
// ------------------
// ------$GNGSA------
// ------------------
uint32_t gloUsedCount = 0;
uint32_t gloUsedList[32] = {0};
// Reset locals for GNGSA sentence generation
pMarker = sentence;
lengthRemaining = sizeof(sentence);
mask = loc_eng_data_p->glo_used_mask;
fixType = '\0';
// Parse the glonass sv mask, and fetch glo sv ids
// Mask corresponds to the offset.
// GLONASS SV ids are from 65-96
const int GLONASS_SV_ID_OFFSET = 64;
for (uint8_t i = 1; mask > 0 && gloUsedCount < 32; i++)
{
if (mask & 1)
gloUsedList[gloUsedCount++] = i + GLONASS_SV_ID_OFFSET;
mask = mask >> 1;
}
// clear the cache so they can't be used again
loc_eng_data_p->glo_used_mask = 0;
if (gloUsedCount == 0)
fixType = '1'; // no fix
else if (gloUsedCount <= 3)
fixType = '2'; // 2D fix
else
fixType = '3'; // 3D fix
// Start printing the sentence
// Format: $--GSA,a,x,xx,xx,xx,xx,xx,xx,xx,xx,xx,xx,xx,xx,p.p,h.h,v.v*cc
// GNGSA : for glonass SVs
// a : Mode : A : Automatic, allowed to automatically switch 2D/3D
// x : Fixtype : 1 (no fix), 2 (2D fix), 3 (3D fix)
// xx : 12 SV ID
// p.p : Position DOP (Dilution of Precision)
// h.h : Horizontal DOP
// v.v : Vertical DOP
// cc : Checksum value
length = snprintf(pMarker, lengthRemaining, "$GNGSA,A,%c,", fixType);
if (length < 0 || length >= lengthRemaining)
{
LOC_LOGE("NMEA Error in string formatting");
return;
}
pMarker += length;
lengthRemaining -= length;
// Add first 12 GLONASS satellite IDs
for (uint8_t i = 0; i < 12; i++)
{
if (i < gloUsedCount)
length = snprintf(pMarker, lengthRemaining, "%02d,", gloUsedList[i]);
else
length = snprintf(pMarker, lengthRemaining, ",");
if (length < 0 || length >= lengthRemaining)
{
LOC_LOGE("NMEA Error in string formatting");
return;
}
pMarker += length;
lengthRemaining -= length;
}
// Add the position/horizontal/vertical DOP values
if (locationExtended.flags & GPS_LOCATION_EXTENDED_HAS_DOP)
{ // dop is in locationExtended, (QMI)
length = snprintf(pMarker, lengthRemaining, "%.1f,%.1f,%.1f",
locationExtended.pdop,
locationExtended.hdop,
locationExtended.vdop);
}
else if (loc_eng_data_p->pdop > 0 && loc_eng_data_p->hdop > 0 && loc_eng_data_p->vdop > 0)
{ // dop was cached from sv report (RPC)
length = snprintf(pMarker, lengthRemaining, "%.1f,%.1f,%.1f",
loc_eng_data_p->pdop,
loc_eng_data_p->hdop,
loc_eng_data_p->vdop);
}
else
{ // no dop
length = snprintf(pMarker, lengthRemaining, ",,");
}
/* Sentence is ready, add checksum and broadcast */
length = loc_eng_nmea_put_checksum(sentence, sizeof(sentence));
loc_eng_nmea_send(sentence, length, loc_eng_data_p);
// ------------------
// ------$GPVTG------
// ------------------
pMarker = sentence; pMarker = sentence;
lengthRemaining = sizeof(sentence); lengthRemaining = sizeof(sentence);
@ -328,11 +547,11 @@ void loc_eng_nmea_generate_pos(loc_eng_data_s_type *loc_eng_data_p,
magTrack -= 360.0; magTrack -= 360.0;
} }
length = snprintf(pMarker, lengthRemaining, "$GPVTG,%.1lf,T,%.1lf,M,", location.gpsLocation.bearing, magTrack); length = snprintf(pMarker, lengthRemaining, "$%sVTG,%.1lf,T,%.1lf,M,", talker, location.gpsLocation.bearing, magTrack);
} }
else else
{ {
length = snprintf(pMarker, lengthRemaining, "$GPVTG,,T,,M,"); length = snprintf(pMarker, lengthRemaining, "$%sVTG,,T,,M,", talker);
} }
if (length < 0 || length >= lengthRemaining) if (length < 0 || length >= lengthRemaining)
@ -373,15 +592,15 @@ void loc_eng_nmea_generate_pos(loc_eng_data_s_type *loc_eng_data_p,
length = loc_eng_nmea_put_checksum(sentence, sizeof(sentence)); length = loc_eng_nmea_put_checksum(sentence, sizeof(sentence));
loc_eng_nmea_send(sentence, length, loc_eng_data_p); loc_eng_nmea_send(sentence, length, loc_eng_data_p);
// ------------------ // -------------------
// ------$GPRMC------ // ------$--RMC-------
// ------------------ // -------------------
pMarker = sentence; pMarker = sentence;
lengthRemaining = sizeof(sentence); lengthRemaining = sizeof(sentence);
length = snprintf(pMarker, lengthRemaining, "$GPRMC,%02d%02d%02d.%02d,A," , length = snprintf(pMarker, lengthRemaining, "$%sRMC,%02d%02d%02d.%02d,A," ,
utcHours, utcMinutes, utcSeconds,utcMSeconds/10); talker, utcHours, utcMinutes, utcSeconds,utcMSeconds/10);
if (length < 0 || length >= lengthRemaining) if (length < 0 || length >= lengthRemaining)
{ {
@ -526,15 +745,15 @@ void loc_eng_nmea_generate_pos(loc_eng_data_s_type *loc_eng_data_p,
length = loc_eng_nmea_put_checksum(sentence, sizeof(sentence)); length = loc_eng_nmea_put_checksum(sentence, sizeof(sentence));
loc_eng_nmea_send(sentence, length, loc_eng_data_p); loc_eng_nmea_send(sentence, length, loc_eng_data_p);
// ------------------ // -------------------
// ------$GPGGA------ // ------$--GGA-------
// ------------------ // -------------------
pMarker = sentence; pMarker = sentence;
lengthRemaining = sizeof(sentence); lengthRemaining = sizeof(sentence);
length = snprintf(pMarker, lengthRemaining, "$GPGGA,%02d%02d%02d.%02d," , length = snprintf(pMarker, lengthRemaining, "$%sGGA,%02d%02d%02d.%02d," ,
utcHours, utcMinutes, utcSeconds, utcMSeconds/10); talker, utcHours, utcMinutes, utcSeconds, utcMSeconds/10);
if (length < 0 || length >= lengthRemaining) if (length < 0 || length >= lengthRemaining)
{ {
@ -601,6 +820,9 @@ void loc_eng_nmea_generate_pos(loc_eng_data_s_type *loc_eng_data_p,
else else
gpsQuality = '2'; // 2 means DGPS fix gpsQuality = '2'; // 2 means DGPS fix
// Number of satellites in use, 00-12
if (svUsedCount > MAX_SATELLITES_IN_USE)
svUsedCount = MAX_SATELLITES_IN_USE;
if (locationExtended.flags & GPS_LOCATION_EXTENDED_HAS_DOP) if (locationExtended.flags & GPS_LOCATION_EXTENDED_HAS_DOP)
{ // dop is in locationExtended, (QMI) { // dop is in locationExtended, (QMI)
length = snprintf(pMarker, lengthRemaining, "%c,%02d,%.1f,", length = snprintf(pMarker, lengthRemaining, "%c,%02d,%.1f,",
@ -657,6 +879,10 @@ void loc_eng_nmea_generate_pos(loc_eng_data_s_type *loc_eng_data_p,
length = loc_eng_nmea_put_checksum(sentence, sizeof(sentence)); length = loc_eng_nmea_put_checksum(sentence, sizeof(sentence));
loc_eng_nmea_send(sentence, length, loc_eng_data_p); loc_eng_nmea_send(sentence, length, loc_eng_data_p);
// clear the cache so they can't be used again
loc_eng_data_p->gps_used_mask = 0;
loc_eng_data_p->glo_used_mask = 0;
loc_eng_data_p->gal_used_mask = 0;
} }
//Send blank NMEA reports for non-final fixes //Send blank NMEA reports for non-final fixes
else { else {
@ -719,13 +945,12 @@ void loc_eng_nmea_generate_sv(loc_eng_data_s_type *loc_eng_data_p,
int sentenceCount = 0; int sentenceCount = 0;
int sentenceNumber = 1; int sentenceNumber = 1;
int svNumber = 1; int svNumber = 1;
int gpsCount = 0;
int glnCount = 0;
//Count GPS SVs for saparating GPS from GLONASS and throw others //Count GPS SVs for saparating GPS from GLONASS and throw others
loc_eng_data_p->gps_used_mask = 0; loc_eng_data_p->gps_used_mask = 0;
loc_eng_data_p->glo_used_mask = 0; loc_eng_data_p->glo_used_mask = 0;
loc_eng_data_p->gal_used_mask = 0;
for(svNumber=1; svNumber <= svCount; svNumber++) { for(svNumber=1; svNumber <= svCount; svNumber++) {
if (GNSS_CONSTELLATION_GPS == svStatus.gnss_sv_list[svNumber - 1].constellation) if (GNSS_CONSTELLATION_GPS == svStatus.gnss_sv_list[svNumber - 1].constellation)
{ {
@ -735,7 +960,6 @@ void loc_eng_nmea_generate_sv(loc_eng_data_s_type *loc_eng_data_p,
{ {
loc_eng_data_p->gps_used_mask |= (1 << (svStatus.gnss_sv_list[svNumber - 1].svid - 1)); loc_eng_data_p->gps_used_mask |= (1 << (svStatus.gnss_sv_list[svNumber - 1].svid - 1));
} }
gpsCount++;
} }
else if (GNSS_CONSTELLATION_GLONASS == svStatus.gnss_sv_list[svNumber - 1].constellation) else if (GNSS_CONSTELLATION_GLONASS == svStatus.gnss_sv_list[svNumber - 1].constellation)
{ {
@ -745,164 +969,40 @@ void loc_eng_nmea_generate_sv(loc_eng_data_s_type *loc_eng_data_p,
{ {
loc_eng_data_p->glo_used_mask |= (1 << (svStatus.gnss_sv_list[svNumber - 1].svid - 1)); loc_eng_data_p->glo_used_mask |= (1 << (svStatus.gnss_sv_list[svNumber - 1].svid - 1));
} }
glnCount++; }
else if (GNSS_CONSTELLATION_GALILEO == svStatus.gnss_sv_list[svNumber - 1].constellation)
{
// cache the used in fix mask, as it will be needed to send $GAGSA
// during the position report
if (GNSS_SV_FLAGS_USED_IN_FIX == (svStatus.gnss_sv_list[svNumber - 1].flags & GNSS_SV_FLAGS_USED_IN_FIX))
{
loc_eng_data_p->gal_used_mask |= (1 << (svStatus.gnss_sv_list[svNumber - 1].svid - 1));
}
} }
} }
loc_nmea_sv_meta sv_meta;
// ------------------ // ------------------
// ------$GPGSV------ // ------$GPGSV------
// ------------------ // ------------------
if (gpsCount <= 0) loc_eng_nmea_generate_GSV(loc_eng_data_p, svStatus, sentence, sizeof(sentence),
{ loc_nmea_sv_meta_init(loc_eng_data_p, sv_meta, GNSS_CONSTELLATION_GPS, false));
// no svs in view, so just send a blank $GPGSV sentence
strlcpy(sentence, "$GPGSV,1,1,0,", sizeof(sentence));
length = loc_eng_nmea_put_checksum(sentence, sizeof(sentence));
loc_eng_nmea_send(sentence, length, loc_eng_data_p);
}
else
{
svNumber = 1;
sentenceNumber = 1;
sentenceCount = gpsCount/4 + (gpsCount % 4 != 0);
while (sentenceNumber <= sentenceCount)
{
pMarker = sentence;
lengthRemaining = sizeof(sentence);
length = snprintf(pMarker, lengthRemaining, "$GPGSV,%d,%d,%02d",
sentenceCount, sentenceNumber, gpsCount);
if (length < 0 || length >= lengthRemaining)
{
LOC_LOGE("NMEA Error in string formatting");
return;
}
pMarker += length;
lengthRemaining -= length;
for (int i=0; (svNumber <= svCount) && (i < 4); svNumber++)
{
if (GNSS_CONSTELLATION_GPS == svStatus.gnss_sv_list[svNumber - 1].constellation)
{
length = snprintf(pMarker, lengthRemaining,",%02d,%02d,%03d,",
svStatus.gnss_sv_list[svNumber-1].svid,
(int)(0.5 + svStatus.gnss_sv_list[svNumber-1].elevation), //float to int
(int)(0.5 + svStatus.gnss_sv_list[svNumber-1].azimuth)); //float to int
if (length < 0 || length >= lengthRemaining)
{
LOC_LOGE("NMEA Error in string formatting");
return;
}
pMarker += length;
lengthRemaining -= length;
if (svStatus.gnss_sv_list[svNumber-1].c_n0_dbhz > 0)
{
length = snprintf(pMarker, lengthRemaining,"%02d",
(int)(0.5 + svStatus.gnss_sv_list[svNumber-1].c_n0_dbhz)); //float to int
if (length < 0 || length >= lengthRemaining)
{
LOC_LOGE("NMEA Error in string formatting");
return;
}
pMarker += length;
lengthRemaining -= length;
}
i++;
}
}
length = loc_eng_nmea_put_checksum(sentence, sizeof(sentence));
loc_eng_nmea_send(sentence, length, loc_eng_data_p);
sentenceNumber++;
} //while
} //if
// ------------------ // ------------------
// ------$GLGSV------ // ------$GLGSV------
// ------------------ // ------------------
if (glnCount <= 0) loc_eng_nmea_generate_GSV(loc_eng_data_p, svStatus, sentence, sizeof(sentence),
{ loc_nmea_sv_meta_init(loc_eng_data_p, sv_meta, GNSS_CONSTELLATION_GLONASS, false));
// no svs in view, so just send a blank $GLGSV sentence
strlcpy(sentence, "$GLGSV,1,1,0,", sizeof(sentence));
length = loc_eng_nmea_put_checksum(sentence, sizeof(sentence));
loc_eng_nmea_send(sentence, length, loc_eng_data_p);
}
else
{
svNumber = 1;
sentenceNumber = 1;
sentenceCount = glnCount/4 + (glnCount % 4 != 0);
while (sentenceNumber <= sentenceCount) // ------------------
{ // ------$GAGSV------
pMarker = sentence; // ------------------
lengthRemaining = sizeof(sentence);
length = snprintf(pMarker, lengthRemaining, "$GLGSV,%d,%d,%02d", loc_eng_nmea_generate_GSV(loc_eng_data_p, svStatus, sentence, sizeof(sentence),
sentenceCount, sentenceNumber, glnCount); loc_nmea_sv_meta_init(loc_eng_data_p, sv_meta, GNSS_CONSTELLATION_GALILEO, false));
if (length < 0 || length >= lengthRemaining)
{
LOC_LOGE("NMEA Error in string formatting");
return;
}
pMarker += length;
lengthRemaining -= length;
for (int i=0; (svNumber <= svCount) && (i < 4); svNumber++)
{
if (GNSS_CONSTELLATION_GLONASS == svStatus.gnss_sv_list[svNumber - 1].constellation)
{
length = snprintf(pMarker, lengthRemaining,",%02d,%02d,%03d,",
svStatus.gnss_sv_list[svNumber - 1].svid,
(int)(0.5 + svStatus.gnss_sv_list[svNumber - 1].elevation), //float to int
(int)(0.5 + svStatus.gnss_sv_list[svNumber - 1].azimuth)); //float to int
if (length < 0 || length >= lengthRemaining)
{
LOC_LOGE("NMEA Error in string formatting");
return;
}
pMarker += length;
lengthRemaining -= length;
if (svStatus.gnss_sv_list[svNumber - 1].c_n0_dbhz > 0)
{
length = snprintf(pMarker, lengthRemaining,"%02d",
(int)(0.5 + svStatus.gnss_sv_list[svNumber - 1].c_n0_dbhz)); //float to int
if (length < 0 || length >= lengthRemaining)
{
LOC_LOGE("NMEA Error in string formatting");
return;
}
pMarker += length;
lengthRemaining -= length;
}
i++;
}
}
length = loc_eng_nmea_put_checksum(sentence, sizeof(sentence));
loc_eng_nmea_send(sentence, length, loc_eng_data_p);
sentenceNumber++;
} //while
}//if
// For RPC, the DOP are sent during sv report, so cache them // For RPC, the DOP are sent during sv report, so cache them
// now to be sent during position report. // now to be sent during position report.