diff --git a/Solutions/Inc/Nmea_Gga.h b/Solutions/Inc/Nmea_Gga.h new file mode 100644 index 0000000..2cde215 --- /dev/null +++ b/Solutions/Inc/Nmea_Gga.h @@ -0,0 +1,72 @@ +// +// Created by villuton on 25.03.25. +// + +#ifndef NMEA_GGA_H +#define NMEA_GGA_H + +#include "Nmea0183Parser_Time.h" +#include "Nmea0183_Sentence.h" +#define GGA_MSG_ID "GGA" +#define GGA_MSG_ID_LEN (3) + +#define DGPS_SID_MIN (0000) +#define DGPS_SID_MAX (1023) + +/** + * GPS Quality indicator: + */ +typedef enum { + SIG_Invalid = 0, /**< Fix not valid*/ + SIG_Fix = 1, /**< GPS fix */ + SIG_Differential = 2, /**< Differential GPS fix (DGNSS), SBAS, OmniSTAR VBS, Beacon, RTX in GVBS mode */ + SIG_Sensitive = 3, /**< Not applicable */ + SIG_RtkFixed = 4, /**< RTK Fixed, xFill */ + SIG_RtkFloat = 5, /**< RTK Float, OmniSTAR XP/HP, Location RTK, RTX */ + SIG_InsDead = 6 /**< INS Dead reckoning */ +}eGGA_sig; + +/** + * Reference station ID's descriptors + * When using one of the MSS (Mobile Satellite Services), + * the Reference Station ID field indicates the following services: + */ +typedef enum { + SID_CenterPoint = 0002, /**< CenterPoint or ViewPoint RTX */ + SID_RangePoint = 0005, /**< RangePoint RTX */ + SID_FieldPoint = 0006, /**< FieldPoint RTX */ + SID_VBS = 0100, /**< VBS */ + SID_HP = 1000, /**< HP */ + SID_HP_XP_Orbits = 1001, /**< HP/XP (Orbits) */ + SID_HP_G2_Orbits = 1002, /**< HP/G2 (Orbits) */ + SID_XP_GPS = 1008, /**< XP (GPS) */ + SID_G2_GPS = 1012, /**< G2 (GPS) */ + SID_G2_GPS_GLONASS = 1013, /**< G2 (GPS/GLONASS) */ + SID_G2_GLONASS = 1014, /**< G2 (GLONASS) */ + SID_HP_XP_GPS = 1016, /**< HP/XP (GPS) */ + SID_HP_G2_GPS = 1020, /**< HP/G2 (GPS) */ + SID_HP_G2_GPS_GLONASS = 1021, /**< HP/G2 (GPS/GLONASS) */ + +}eGGA_dgps_sid; + + +/** + * GGA packet information structure (Global Positioning System Fix Data) + */ +typedef struct +{ + tNmeaUtc utc; /**< UTC of position (just time) */ + tNmeaLocation location; /**< Sentence location data in fractional NDEG and Cardinal directions */ + eGGA_sig sig; /**< GPS quality indicator (0 = Invalid; 1 = Fix; 2 = Differential, 3 = Sensitive) */ + int satinuse; /**< Number of satellites in use (not those in view) */ + double HDOP; /**< Horizontal dilution of precision */ + double elv; /**< Antenna altitude above/below mean sea level (geoid) */ + char elv_units; /**< [M]eters (Antenna height unit) */ + double diff; /**< Geoidal separation (Diff. between WGS-84 earth ellipsoid and mean sea level. '-' = geoid is below WGS-84 ellipsoid) */ + char diff_units; /**< [M]eters (Units of geoidal separation) */ + double dgps_age; /**< Time in seconds since last DGPS update */ + int dgps_sid; /**< DGPS station ID number */ +} tNmeaGGA; + + +#endif //NMEA_GGA_H diff --git a/Solutions/Inc/Nmea_Gsa.h b/Solutions/Inc/Nmea_Gsa.h new file mode 100644 index 0000000..43991db --- /dev/null +++ b/Solutions/Inc/Nmea_Gsa.h @@ -0,0 +1,41 @@ +// +// Created by villuton on 25.03.25. +// + +#ifndef NMEA_GSA_H +#define NMEA_GSA_H + +#include "Nmea_Config.h" + +#define GSA_MSG_ID "GSA" +#define GSA_MSG_ID_LEN (3) + +#define GSA_FIX_MODE_EMPTY (0) +#define GSA_FIX_MODE_Manual 'M' +#define GSA_FIX_MODE_Automatic 'A' + +typedef enum { + GSA_NaN = 0, /**< (Empty field) */ + GSA_FixNotAvailable = 1, /**< Fix not available */ + GSA_2D = 2, /**< 2D */ + GSA_3D = 3 /**< 3D */ +}eGSA_fix_type; + + +/** + * GSA packet information structure (Satellite status) + */ +typedef struct +{ + char fix_mode; /**< Mode (M = Manual, forced to operate in 2D or 3D; A = Automatic, 3D/2D) */ + int fix_type; /**< Type, used for navigation (1 = Fix not available; 2 = 2D; 3 = 3D) */ + int sat_prn[NMEA_MAXSAT]; /**< PRNs of satellites used in position fix (null for unused fields) */ + double PDOP; /**< Dilution of precision */ + double HDOP; /**< Horizontal dilution of precision */ + double VDOP; /**< Vertical dilution of precision */ + +} tNmeaGSA; + +bool NmeaGsa_Parse(char *str, size_t len, tNmeaGSA *result); + +#endif //NMEA_GSA_H diff --git a/Solutions/Inc/Nmea_Gsv.h b/Solutions/Inc/Nmea_Gsv.h new file mode 100644 index 0000000..34a84af --- /dev/null +++ b/Solutions/Inc/Nmea_Gsv.h @@ -0,0 +1,43 @@ +// +// Created by villuton on 25.03.25. +// + +#ifndef NMEA_GSV_H +#define NMEA_GSV_H + +#include "Nmea_Config.h" + +#define GSV_MSG_ID "GSV" +#define GSV_MSG_ID_LEN (3) + +/** + * Information about satellite + * @see nmeaSATINFO + * @see nmeaGPGSV + */ +typedef struct +{ + int id; /**< Satellite PRN number */ + int in_use; /**< Used in position fix */ + int elv; /**< Elevation in degrees, 90 maximum */ + int azimuth; /**< Azimuth, degrees from true north, 000 to 359 */ + int sig; /**< Signal, 00-99 dB */ + +} tNmeaSATELLITE; + + +/** + * GSV packet information structure (Satellites in view) + */ +typedef struct +{ + int pack_count; /**< Total number of messages of this type in this cycle */ + int pack_index; /**< Message number */ + int sat_count; /**< Total number of satellites in view */ + tNmeaSATELLITE sat_data[NMEA_SATINPACK]; + +} tNmeaGSV; + +bool NmeaGsv_Parse(char *str, size_t len, tNmeaGSV *result); + +#endif //NMEA_GSV_H diff --git a/Solutions/Inc/Nmea_Rmc.h b/Solutions/Inc/Nmea_Rmc.h new file mode 100644 index 0000000..31fd77a --- /dev/null +++ b/Solutions/Inc/Nmea_Rmc.h @@ -0,0 +1,41 @@ +// +// Created by villuton on 25.03.25. +// + +#ifndef NMEA_RMC_H +#define NMEA_RMC_H + +#include "Nmea0183Parser_Time.h" +#include "Nmea0183_Sentence.h" + +#define RMC_MSG_ID "RMC" +#define RMC_MSG_ID_LEN (3) + +#define RMC_STATUS_NotValid 'V' +#define RMC_STATUS_Valid 'A' + +#define RMC_MODE_Autonomous 'A' +#define RMC_MODE_Differential 'D' +#define RMC_MODE_Estimated 'E' +#define RMC_MODE_NotValid 'N' +#define RMC_MODE_Simulator 'S' + +/** + * RMC packet information structure (Recommended Minimum sentence C) + */ +typedef struct { + tNmeaTime time; /**< time of position */ + char status; /**< Status (A = active or V = void) */ + tNmeaLocation location; /**< Sentence location data in fractional NDEG and Cardinal directions */ + double speed; /**< Speed over the ground in knots */ + double direction; /**< Track angle in degrees True */ + double declination; /**< Magnetic variation degrees (Easterly var. subtracts from true course) */ + char declin_ew; /**< [E]ast or [W]est */ + char mode; /**< Mode indicator of fix type (A = autonomous, D = differential, E = estimated, N = not valid, S = simulator) */ +}tNmeaRMC; + + +bool NmeaRmc_Parse(char *str, size_t len, tNmeaRMC *result); + + +#endif //NMEA_RMC_H diff --git a/Solutions/Src/Nmea_Gga.c b/Solutions/Src/Nmea_Gga.c new file mode 100644 index 0000000..c7d7378 --- /dev/null +++ b/Solutions/Src/Nmea_Gga.c @@ -0,0 +1,77 @@ +// +// Created by villuton on 25.03.25. +// +#include +#include "Nmea_Gga.h" +#include "Nmea0183Parser_Private.h" +#include "Nmea_Config.h" + +bool NmeaGga_Parse(char *str, size_t len, tNmeaGGA *result) +{ + char *end = str + len; + char *front = str; + char *nextDivider = front-1; + if (Nmea0183ParseNextPortion(&front, &nextDivider, end) > 0) { + if (!Nmea0183ParseUtc(front, nextDivider, &result->utc)) { + return false; + } + } else { + result->utc = (tNmeaUtc){0}; + } + result->location.lat = + (Nmea0183ParseNextPortion(&front, &nextDivider, end) > 0) ? + Nmea0183ParseDouble(front, nextDivider - front) : NMEA_DEF_LAT; + + result->location.ns = + (Nmea0183ParseNextPortion(&front, &nextDivider, end) > 0)? + *front : 0; + + result->location.lon = + (Nmea0183ParseNextPortion(&front, &nextDivider, end) > 0)? + Nmea0183ParseDouble(front, nextDivider - front) : NMEA_DEF_LON; + + result->location.ew = + (Nmea0183ParseNextPortion(&front, &nextDivider, end) > 0) ? + *front : 0; + + result->sig = + (Nmea0183ParseNextPortion(&front, &nextDivider, end) > 0) ? + Nmea0183ParseShortCharsDecimalNumber(front,nextDivider - front) : SIG_Invalid; + + result->satinuse = + (Nmea0183ParseNextPortion(&front, &nextDivider, end) > 0) ? + Nmea0183ParseShortCharsDecimalNumber(front,nextDivider - front) : 0; + + result->HDOP = + (Nmea0183ParseNextPortion(&front, &nextDivider, end) > 0) ? + Nmea0183ParseDouble(front,nextDivider - front) : 0; + result->elv = + (Nmea0183ParseNextPortion(&front, &nextDivider, end) > 0) ? + Nmea0183ParseDouble(front,nextDivider - front) : 0; + result->elv_units = + (Nmea0183ParseNextPortion(&front, &nextDivider, end) > 0) ? + *front : 0; + result->diff = + (Nmea0183ParseNextPortion(&front, &nextDivider, end) > 0) ? + Nmea0183ParseDouble(front,nextDivider - front) : 0; + result->diff_units = + (Nmea0183ParseNextPortion(&front, &nextDivider, end) > 0) ? + *front : 0; + + if(result->sig == SIG_Differential){ + result->dgps_age = + (Nmea0183ParseNextPortion(&front, &nextDivider, end) > 0) ? + Nmea0183ParseShortCharsDecimalNumber(front,nextDivider - front) : 0; + result->dgps_sid = + (Nmea0183ParseNextPortion(&front, &nextDivider, end) > 0) ? + Nmea0183ParseShortCharsDecimalNumber(front,nextDivider - front) : 0; + result->dgps_sid = + ((DGPS_SID_MIN <= result->dgps_sid) && (result->dgps_sid<= DGPS_SID_MAX)) ? + result->dgps_sid : 0; + } else{ + result->dgps_age = 0; + result->dgps_sid = 0; + } + + return true; +} \ No newline at end of file diff --git a/Solutions/Src/Nmea_Gsa.c b/Solutions/Src/Nmea_Gsa.c new file mode 100644 index 0000000..5fd5205 --- /dev/null +++ b/Solutions/Src/Nmea_Gsa.c @@ -0,0 +1,51 @@ +// +// Created by villuton on 26.03.25. +// +#include +#include +#include "Nmea_Gsa.h" +#include "Nmea0183Parser_Private.h" +#include "Nmea_Config.h" + +/** + * + * @param str NMEA string with GSA solutions + * @param len len GSA string + * @param result < (0) tNmeaGSA struct + * @return TRUE if parsing complete + */ +bool NmeaGsa_Parse(char *str, size_t len, tNmeaGSA *result) +{ + char *end = str + len; + char *front = str; + char *nextDivider = front - 1; + + result->fix_mode = + (Nmea0183ParseNextPortion(&front, &nextDivider, end) > 0) ? + *front : GSA_FIX_MODE_EMPTY; + + result->fix_type = + (Nmea0183ParseNextPortion(&front, &nextDivider, end) > 0) ? + Nmea0183ParseShortCharsDecimalNumber(front,nextDivider - front) : GSA_NaN; + + for(int i = 0; i < NMEA_MAXSAT; i++) + { + result->sat_prn[i] = + (Nmea0183ParseNextPortion(&front, &nextDivider, end) > 0) ? + Nmea0183ParseShortCharsDecimalNumber(front,nextDivider - front) : GSA_FIX_MODE_EMPTY; + } + + result->PDOP = + (Nmea0183ParseNextPortion(&front, &nextDivider, end) > 0) ? + Nmea0183ParseDouble(front, nextDivider - front) : 0; + + result->HDOP = + (Nmea0183ParseNextPortion(&front, &nextDivider, end) > 0) ? + Nmea0183ParseDouble(front, nextDivider - front) : 0; + + result->VDOP = + (Nmea0183ParseNextPortion(&front, &nextDivider, end) > 0) ? + Nmea0183ParseDouble(front, nextDivider - front) : 0; + + return true; +} \ No newline at end of file diff --git a/Solutions/Src/Nmea_Gsv.c b/Solutions/Src/Nmea_Gsv.c new file mode 100644 index 0000000..2d9ea1f --- /dev/null +++ b/Solutions/Src/Nmea_Gsv.c @@ -0,0 +1,48 @@ +// +// Created by villuton on 26.03.25. +// +#include +#include +#include "Nmea_Gsv.h" +#include "Nmea0183Parser_Private.h" +#include "Nmea_Config.h" + +/** + * + * @param str NMEA string with GSV solutions + * @param len len GSV string + * @param result < (0) tNmeaGSV struct + * @return TRUE if parsing complete + */ +bool NmeaGsv_Parse(char *str, size_t len, tNmeaGSV *result) +{ + char *end = str + len; + char *front = str; + char *nextDivider = front - 1; + + result->pack_count = + (Nmea0183ParseNextPortion(&front, &nextDivider, end) > 0) ? + Nmea0183ParseShortCharsDecimalNumber(front,nextDivider - front) : 0; + result->pack_index = + (Nmea0183ParseNextPortion(&front, &nextDivider, end) > 0) ? + Nmea0183ParseShortCharsDecimalNumber(front,nextDivider - front) : 0; + result->sat_count = + (Nmea0183ParseNextPortion(&front, &nextDivider, end) > 0) ? + Nmea0183ParseShortCharsDecimalNumber(front,nextDivider - front) : 0; + for(int i = 0; i < NMEA_SATINPACK; i++) + { + result->sat_data[i].id = + (Nmea0183ParseNextPortion(&front, &nextDivider, end) > 0) ? + Nmea0183ParseShortCharsDecimalNumber(front,nextDivider - front) : 0; + result->sat_data[i].elv = + (Nmea0183ParseNextPortion(&front, &nextDivider, end) > 0) ? + Nmea0183ParseShortCharsDecimalNumber(front,nextDivider - front) : 0; + result->sat_data[i].azimuth = + (Nmea0183ParseNextPortion(&front, &nextDivider, end) > 0) ? + Nmea0183ParseShortCharsDecimalNumber(front,nextDivider - front) : 0; + result->sat_data[i].sig = + (Nmea0183ParseNextPortion(&front, &nextDivider, end) > 0) ? + Nmea0183ParseShortCharsDecimalNumber(front,nextDivider - front) : 0; + } + return true; +} \ No newline at end of file diff --git a/Solutions/Src/Nmea_Rmc.c b/Solutions/Src/Nmea_Rmc.c new file mode 100644 index 0000000..b502e30 --- /dev/null +++ b/Solutions/Src/Nmea_Rmc.c @@ -0,0 +1,79 @@ +// +// Created by villuton on 25.03.25. +// +#include +#include "Nmea_Rmc.h" +#include "Nmea0183Parser_Private.h" +#include "Nmea_Config.h" + + +/** + * + * @param str NMEA string with RMC solutions + * @param len len NMEA string + * @param result < (0) tNmeaRMC struct + * @return TRUE if parsing complete + */ +bool NmeaRmc_Parse(char *str, size_t len, tNmeaRMC *result) +{ + char *end = str + len; + char *front = str; + char *nextDivider = front - 1; + result->status = RMC_STATUS_NotValid; + if (Nmea0183ParseNextPortion(&front, &nextDivider, end) > 0) { + if (!Nmea0183ParseUtc(front, nextDivider, &result->time.utc)) { + return false; + } + } else { + result->time.utc = (tNmeaUtc){0}; + } + + result->status = + (Nmea0183ParseNextPortion(&front, &nextDivider, end) > 0) ? + *front : RMC_STATUS_NotValid; + + result->location.lat = + (Nmea0183ParseNextPortion(&front, &nextDivider, end) > 0) ? + Nmea0183ParseDouble(front, nextDivider - front) : NMEA_DEF_LAT; + + result->location.ns = + (Nmea0183ParseNextPortion(&front, &nextDivider, end) > 0)? + *front : 0; + + result->location.lon = + (Nmea0183ParseNextPortion(&front, &nextDivider, end) > 0)? + Nmea0183ParseDouble(front, nextDivider - front) : NMEA_DEF_LON; + + result->location.ew = + (Nmea0183ParseNextPortion(&front, &nextDivider, end) > 0) ? + *front : 0; + + result->speed = + (Nmea0183ParseNextPortion(&front, &nextDivider, end) > 0) ? + Nmea0183ParseDouble(front, nextDivider - front) : 0; + + result->direction = + (Nmea0183ParseNextPortion(&front, &nextDivider, end) > 0) ? + Nmea0183ParseDouble(front, nextDivider - front) : 0; + + if (Nmea0183ParseNextPortion(&front, &nextDivider, end) > 0) { + if (!Nmea0183ParseDate(front, nextDivider, &result->time.date)) { + return false; + } + } else { + result->time.date = (tNmeaDate){0}; + } + + result->declination = + (Nmea0183ParseNextPortion(&front, &nextDivider, end) > 0) ? + Nmea0183ParseDouble(front, nextDivider - front) : 0; + + result->declin_ew = + (Nmea0183ParseNextPortion(&front, &nextDivider, end) > 0) ? + *front : 0; + + result->mode = + (Nmea0183ParseNextPortion(&front, &nextDivider, end) > 0) ? + *front : RMC_MODE_NotValid; + return true; +} \ No newline at end of file