diff --git a/core/ContextBase.cpp b/core/ContextBase.cpp index d2f90704..1ae84823 100644 --- a/core/ContextBase.cpp +++ b/core/ContextBase.cpp @@ -88,31 +88,35 @@ LocApiBase* ContextBase::createLocApi(LOC_API_ADAPTER_EVENT_MASK_T exMask) { LocApiBase* locApi = NULL; - if (NULL == (locApi = mLBSProxy->getLocApi(mMsgTask, exMask, this))) { - void *handle = NULL; - //try to see if LocApiV02 is present - if ((handle = dlopen("libloc_api_v02.so", RTLD_NOW)) != NULL) { - LOC_LOGD("%s:%d]: libloc_api_v02.so is present", __func__, __LINE__); - getLocApi_t* getter = (getLocApi_t*) dlsym(handle, "getLocApi"); - if (getter != NULL) { - LOC_LOGD("%s:%d]: getter is not NULL for LocApiV02", __func__, - __LINE__); - locApi = (*getter)(mMsgTask, exMask, this); - } - } - // only RPC is the option now - else { - LOC_LOGD("%s:%d]: libloc_api_v02.so is NOT present. Trying RPC", - __func__, __LINE__); - handle = dlopen("libloc_api-rpc-qc.so", RTLD_NOW); - if (NULL != handle) { + // Check the target + if (TARGET_NO_GNSS != loc_get_target()){ + + if (NULL == (locApi = mLBSProxy->getLocApi(mMsgTask, exMask, this))) { + void *handle = NULL; + //try to see if LocApiV02 is present + if ((handle = dlopen("libloc_api_v02.so", RTLD_NOW)) != NULL) { + LOC_LOGD("%s:%d]: libloc_api_v02.so is present", __func__, __LINE__); getLocApi_t* getter = (getLocApi_t*) dlsym(handle, "getLocApi"); - if (NULL != getter) { - LOC_LOGD("%s:%d]: getter is not NULL in RPC", __func__, + if (getter != NULL) { + LOC_LOGD("%s:%d]: getter is not NULL for LocApiV02", __func__, __LINE__); locApi = (*getter)(mMsgTask, exMask, this); } } + // only RPC is the option now + else { + LOC_LOGD("%s:%d]: libloc_api_v02.so is NOT present. Trying RPC", + __func__, __LINE__); + handle = dlopen("libloc_api-rpc-qc.so", RTLD_NOW); + if (NULL != handle) { + getLocApi_t* getter = (getLocApi_t*) dlsym(handle, "getLocApi"); + if (NULL != getter) { + LOC_LOGD("%s:%d]: getter is not NULL in RPC", __func__, + __LINE__); + locApi = (*getter)(mMsgTask, exMask, this); + } + } + } } } diff --git a/core/gps_extended_c.h b/core/gps_extended_c.h index e16d7584..46be08b5 100644 --- a/core/gps_extended_c.h +++ b/core/gps_extended_c.h @@ -1016,8 +1016,9 @@ typedef enum typedef struct { size_t size; - uint8_t gnssSvId; - /* GPS: 1-32, GLO: 65-96, 0: Invalid + uint16_t gnssSvId; + /* GPS: 1-32, GLO: 65-96, 0: Invalid, + SBAS: 120-151, BDS:201-237,GAL:301 to 336 All others are reserved */ int8_t freqNum; diff --git a/loc_api/libloc_api_50001/loc_eng.h b/loc_api/libloc_api_50001/loc_eng.h index 1ff391ad..dc39f60b 100644 --- a/loc_api/libloc_api_50001/loc_eng.h +++ b/loc_api/libloc_api_50001/loc_eng.h @@ -123,6 +123,7 @@ typedef struct loc_eng_data_s boolean generateNmea; uint32_t gps_used_mask; uint32_t glo_used_mask; + uint32_t gal_used_mask; float hdop; float pdop; float vdop; diff --git a/loc_api/libloc_api_50001/loc_eng_nmea.cpp b/loc_api/libloc_api_50001/loc_eng_nmea.cpp index 3d2336f7..ac057c11 100644 --- a/loc_api/libloc_api_50001/loc_eng_nmea.cpp +++ b/loc_api/libloc_api_50001/loc_eng_nmea.cpp @@ -34,6 +34,105 @@ #include #include +#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 @@ -96,6 +195,249 @@ int loc_eng_nmea_put_checksum(char *pNmea, int maxSize) 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 @@ -103,10 +445,12 @@ DESCRIPTION Generate NMEA sentences generated based on position report Currently below sentences are generated within this function: - $GPGSA : GPS DOP and active SVs - - $GNGSA : GLONASS DOP and active SVs - - $GPVTG : Track made good and ground speed - - $GPRMC : Recommended minimum navigation information - - $GPGGA : Time, position and fix related data + - $GLGSA : GLONASS DOP and active SVs + - $GAGSA : GALILEO DOP and active SVs + - $GNGSA : GNSS DOP and active SVs + - $--VTG : Track made good and ground speed + - $--RMC : Recommended minimum navigation information + - $--GGA : Time, position and fix related data DEPENDENCIES 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; if (generate_nmea) { - // ------------------ - // ------$GPGSA------ - // ------------------ - + char talker[3] = {'G', 'P', '\0'}; uint32_t svUsedCount = 0; - uint32_t svUsedList[32] = {0}; - uint32_t mask = loc_eng_data_p->gps_used_mask; - for (uint8_t i = 1; mask > 0 && svUsedCount < 32; i++) + uint32_t count = 0; + loc_nmea_sv_meta sv_meta; + // ------------------- + // ---$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) - svUsedList[svUsedCount++] = i; - mask = mask >> 1; + svUsedCount += count; + talker[1] = sv_meta.talker[1]; } - // clear the cache so they can't be used again - loc_eng_data_p->gps_used_mask = 0; - char fixType; - if (svUsedCount == 0) - fixType = '1'; // no fix - else if (svUsedCount <= 3) - fixType = '2'; // 2D fix - else - fixType = '3'; // 3D fix + // ------------------- + // ---$GLGSA/$GNGSA--- + // ------------------- - length = snprintf(pMarker, lengthRemaining, "$GPGSA,A,%c,", fixType); - - if (length < 0 || length >= lengthRemaining) + 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 (count > 0) { - LOC_LOGE("NMEA Error in string formatting"); - return; + svUsedCount += count; + 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) - 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; - } - pMarker += length; - lengthRemaining -= length; + svUsedCount += count; + talker[1] = sv_meta.talker[1]; } - 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, ",,"); - } - - 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------ - // ------------------ + // ------------------- + // ------$--VTG------- + // ------------------- pMarker = 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; } - 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 { - length = snprintf(pMarker, lengthRemaining, "$GPVTG,,T,,M,"); + length = snprintf(pMarker, lengthRemaining, "$%sVTG,,T,,M,", talker); } 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)); loc_eng_nmea_send(sentence, length, loc_eng_data_p); - // ------------------ - // ------$GPRMC------ - // ------------------ + // ------------------- + // ------$--RMC------- + // ------------------- pMarker = sentence; lengthRemaining = sizeof(sentence); - length = snprintf(pMarker, lengthRemaining, "$GPRMC,%02d%02d%02d.%02d,A," , - utcHours, utcMinutes, utcSeconds,utcMSeconds/10); + length = snprintf(pMarker, lengthRemaining, "$%sRMC,%02d%02d%02d.%02d,A," , + talker, utcHours, utcMinutes, utcSeconds,utcMSeconds/10); 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)); loc_eng_nmea_send(sentence, length, loc_eng_data_p); - // ------------------ - // ------$GPGGA------ - // ------------------ + // ------------------- + // ------$--GGA------- + // ------------------- pMarker = sentence; lengthRemaining = sizeof(sentence); - length = snprintf(pMarker, lengthRemaining, "$GPGGA,%02d%02d%02d.%02d," , - utcHours, utcMinutes, utcSeconds, utcMSeconds/10); + length = snprintf(pMarker, lengthRemaining, "$%sGGA,%02d%02d%02d.%02d," , + talker, utcHours, utcMinutes, utcSeconds, utcMSeconds/10); 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 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) { // dop is in locationExtended, (QMI) 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)); 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 else { @@ -719,13 +945,12 @@ void loc_eng_nmea_generate_sv(loc_eng_data_s_type *loc_eng_data_p, int sentenceCount = 0; int sentenceNumber = 1; int svNumber = 1; - int gpsCount = 0; - int glnCount = 0; //Count GPS SVs for saparating GPS from GLONASS and throw others loc_eng_data_p->gps_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++) { 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)); } - gpsCount++; } 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)); } - 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------ // ------------------ - if (gpsCount <= 0) - { - // 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 + 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)); // ------------------ // ------$GLGSV------ // ------------------ - if (glnCount <= 0) - { - // 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); + 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)); - while (sentenceNumber <= sentenceCount) - { - pMarker = sentence; - lengthRemaining = sizeof(sentence); + // ------------------ + // ------$GAGSV------ + // ------------------ - length = snprintf(pMarker, lengthRemaining, "$GLGSV,%d,%d,%02d", - sentenceCount, sentenceNumber, glnCount); + 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_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 // now to be sent during position report.