From ee76952f5e2bdeae5f3d80dcce6a9e856715c13a Mon Sep 17 00:00:00 2001 From: Saurabh Srivastava Date: Fri, 4 Mar 2016 15:12:35 +0530 Subject: [PATCH] msm8974-common: gps: Adding a new NMEA sentence : $GNGSA. Currently only $GPGSA was being generated for GPS satellites. This change adds $GNGSA for GLONASS satellites as well. Change-Id: I7ab0e92c7ed4ce73be11909eefe0d570a1a0fc1e CRs-Fixed: 978745 --- gps/loc_api/libloc_api_50001/loc_eng.h | 3 +- gps/loc_api/libloc_api_50001/loc_eng_nmea.cpp | 112 +++++++++++++++++- 2 files changed, 110 insertions(+), 5 deletions(-) diff --git a/gps/loc_api/libloc_api_50001/loc_eng.h b/gps/loc_api/libloc_api_50001/loc_eng.h index a203e6b..b4f2564 100644 --- a/gps/loc_api/libloc_api_50001/loc_eng.h +++ b/gps/loc_api/libloc_api_50001/loc_eng.h @@ -119,7 +119,8 @@ typedef struct loc_eng_data_s // For nmea generation boolean generateNmea; - uint32_t sv_used_mask; + uint32_t gps_used_mask; + uint32_t glo_used_mask; float hdop; float pdop; float vdop; diff --git a/gps/loc_api/libloc_api_50001/loc_eng_nmea.cpp b/gps/loc_api/libloc_api_50001/loc_eng_nmea.cpp index e6fbec8..ccfa2bb 100644 --- a/gps/loc_api/libloc_api_50001/loc_eng_nmea.cpp +++ b/gps/loc_api/libloc_api_50001/loc_eng_nmea.cpp @@ -102,6 +102,12 @@ FUNCTION loc_eng_nmea_generate_pos 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 DEPENDENCIES NONE @@ -144,7 +150,7 @@ void loc_eng_nmea_generate_pos(loc_eng_data_s_type *loc_eng_data_p, uint32_t svUsedCount = 0; uint32_t svUsedList[32] = {0}; - uint32_t mask = loc_eng_data_p->sv_used_mask; + uint32_t mask = loc_eng_data_p->gps_used_mask; for (uint8_t i = 1; mask > 0 && svUsedCount < 32; i++) { if (mask & 1) @@ -152,7 +158,7 @@ void loc_eng_nmea_generate_pos(loc_eng_data_s_type *loc_eng_data_p, mask = mask >> 1; } // clear the cache so they can't be used again - loc_eng_data_p->sv_used_mask = 0; + loc_eng_data_p->gps_used_mask = 0; char fixType; if (svUsedCount == 0) @@ -210,6 +216,99 @@ 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); + // ------------------ + // ------$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------ // ------------------ @@ -565,6 +664,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); + strlcpy(sentence, "$GNGSA,A,1,,,,,,,,,,,,,,,", sizeof(sentence)); + length = loc_eng_nmea_put_checksum(sentence, sizeof(sentence)); + loc_eng_nmea_send(sentence, length, loc_eng_data_p); + strlcpy(sentence, "$GPVTG,,T,,M,,N,,K,N", sizeof(sentence)); length = loc_eng_nmea_put_checksum(sentence, sizeof(sentence)); loc_eng_nmea_send(sentence, length, loc_eng_data_p); @@ -790,9 +893,10 @@ void loc_eng_nmea_generate_sv(loc_eng_data_s_type *loc_eng_data_p, }//if - // cache the used in fix mask, as it will be needed to send $GPGSA + // cache the used in fix mask, as it will be needed to send $GPGSA/$GNGSA // during the position report - loc_eng_data_p->sv_used_mask = svStatus.gps_used_in_fix_mask; + loc_eng_data_p->gps_used_mask = svStatus.gps_used_in_fix_mask; + loc_eng_data_p->glo_used_mask = svStatus.glo_used_in_fix_mask; // For RPC, the DOP are sent during sv report, so cache them // now to be sent during position report.