changeset 194:0faaa371df10 main

Use a simpler format for GPS decoding and messages over the canbus.
author Bob Cook <bob@bobcookdev.com>
date Wed, 21 Aug 2013 06:19:06 -0700
parents 95a4cd2a4d26
children d6621e43b91b
files main/packages/common/can/can_messages.h main/packages/common/gps/nmea.cpp main/packages/common/gps/nmea.h
diffstat 3 files changed, 94 insertions(+), 53 deletions(-) [+]
line wrap: on
line diff
--- a/main/packages/common/can/can_messages.h	Tue Aug 20 19:53:42 2013 -0700
+++ b/main/packages/common/can/can_messages.h	Wed Aug 21 06:19:06 2013 -0700
@@ -110,25 +110,17 @@
 
 // ----------------------------------------------------------------------------------------
 
-const uint16_t can_dataid_latitude = 0x0101;
+const uint16_t can_dataid_latitude  = 0x0101;
+const uint16_t can_dataid_longitude = 0x0102;
+
+const int32_t  can_data_gps_min_multiplier = 1000;
 
 typedef struct
 {
-    int16_t      degrees;
-    fixed16dot16 minutes;
-
-} can_data_latitude;
-
-// ----------------------------------------------------------------------------------------
+    int16_t degrees;
+    int32_t min_thousandths;  // fractional minutes * 1,000 (can_data_gps_min_multiplier)
 
-const uint16_t can_dataid_longitude = 0x0102;
-
-typedef struct
-{
-    int16_t      degrees;
-    fixed16dot16 minutes;
-
-} can_data_longitude;
+} can_data_gps_data;
 
 // ----------------------------------------------------------------------------------------
 
--- a/main/packages/common/gps/nmea.cpp	Tue Aug 20 19:53:42 2013 -0700
+++ b/main/packages/common/gps/nmea.cpp	Wed Aug 21 06:19:06 2013 -0700
@@ -7,7 +7,7 @@
 //    
 //  This file implements a state machine to parse selected NMEA sentences.
 //
-//  Copyright (c) 2010 Bob Cook
+//  Copyright (c) 2010-2013 Bob Cook
 //  
 //  Permission is hereby granted, free of charge, to any person obtaining a copy
 //  of this software and associated documentation files (the "Software"), to deal
@@ -44,19 +44,15 @@
 
 // ----------------------------------------------------------------------------------------
 
-#if !defined( PRJ_FIXED16DOT16_ENABLE_CONVERT_FROM_STRING )
-#error Support for converting strings to 16.16 fixed point numbers is required!
-#endif
-
-// ----------------------------------------------------------------------------------------
-
 static uint8_t g_error_count;
 
-static int16_t      g_latitude_deg;
-static fixed16dot16 g_latitude_min;
+static int16_t  g_latitude_deg;
+static uint16_t g_latitude_min;
+static uint16_t g_latitude_min_fract;
 
-static int16_t      g_longitude_deg;
-static fixed16dot16 g_longitude_min;
+static int16_t  g_longitude_deg;
+static uint16_t g_longitude_min;
+static uint16_t g_longitude_min_fract;
 
 static uint8_t g_enc_timestamp[ 6 ];
 static uint8_t g_position_fix;
@@ -129,6 +125,13 @@
 
 // ----------------------------------------------------------------------------------------
 
+static bool is_digit_char( uint8_t character )
+{
+    return ( ( character >= '0' ) && ( character <= '9' ) );
+}
+
+// ----------------------------------------------------------------------------------------
+
 static uint8_t convert_digit_char( uint8_t digitchar )
 {
     if ( ( digitchar >= '0' ) && ( digitchar <= '9' ) )
@@ -143,19 +146,20 @@
 
 static void convert_buffer_to_latitude( const uint8_t* buffer )
 {
-    g_latitude_deg = 0;
-    g_latitude_min = 0;
+    g_latitude_deg       = 0;
+    g_latitude_min       = 0;
+    g_latitude_min_fract = 0;
     
     //--    Layout: DDMM.MMM
 
-    if ( *buffer == '\0' )
+    if ( ! is_digit_char( *buffer ) )
     {
         return;
     }
 
     g_latitude_deg = convert_digit_char( *buffer++ );
      
-    if ( *buffer == '\0' )
+    if ( ! is_digit_char( *buffer ) )
     {
         return;
     }
@@ -163,32 +167,56 @@
     g_latitude_deg *= 10;
     g_latitude_deg += convert_digit_char( *buffer++ );
 
-    if ( *buffer == '\0' )
+    if ( ! is_digit_char( *buffer ) )
+    {
+        return;
+    }
+
+    g_latitude_min = convert_digit_char( *buffer++ );
+     
+    if ( ! is_digit_char( *buffer ) )
     {
         return;
     }
 
-    g_latitude_min
-        = fixed16dot16_from_string( reinterpret_cast< const char* >( buffer ) );
+    g_latitude_min *= 10;
+    g_latitude_min += convert_digit_char( *buffer++ );
+
+    if ( *buffer != '.' )
+    {
+        return;
+    }
+    buffer++; // skip decimal pt
+
+    for ( uint8_t i = 0; i < 4; ++i ) // scaled to 10,000
+    {
+        g_latitude_min_fract *= 10;
+
+        if ( is_digit_char( *buffer ) )
+        {
+            g_latitude_min_fract += convert_digit_char( *buffer++ );
+        }
+    }
 }
 
 // ----------------------------------------------------------------------------------------
 
 static void convert_buffer_to_longitude( const uint8_t* buffer )
 {
-    g_longitude_deg = 0;
-    g_longitude_min = 0;
+    g_longitude_deg       = 0;
+    g_longitude_min       = 0;
+    g_longitude_min_fract = 0;
     
     //--    Layout: DDDMM.MMM
 
-    if ( *buffer == '\0' )
+    if ( ! is_digit_char( *buffer ) )
     {
         return;
     }
 
     g_longitude_deg = convert_digit_char( *buffer++ );
      
-    if ( *buffer == '\0' )
+    if ( ! is_digit_char( *buffer ) )
     {
         return;
     }
@@ -196,7 +224,7 @@
     g_longitude_deg *= 10;
     g_longitude_deg += convert_digit_char( *buffer++ );
 
-    if ( *buffer == '\0' )
+    if ( ! is_digit_char( *buffer ) )
     {
         return;
     }
@@ -204,13 +232,26 @@
     g_longitude_deg *= 10;
     g_longitude_deg += convert_digit_char( *buffer++ );
 
-    if ( *buffer == '\0' )
+    if ( ! is_digit_char( *buffer ) )
     {
         return;
     }
 
-    g_longitude_min 
-        = fixed16dot16_from_string( reinterpret_cast< const char* >( buffer ) );
+    if ( *buffer != '.' )
+    {
+        return;
+    }
+    buffer++; // skip decimal pt
+
+    for ( uint8_t i = 0; i < 4; ++i ) // scaled to 10,000
+    {
+        g_longitude_min_fract *= 10;
+
+        if ( is_digit_char( *buffer ) )
+        {
+            g_longitude_min_fract += convert_digit_char( *buffer++ );
+        }
+    }
 }
 
 // ----------------------------------------------------------------------------------------
@@ -451,18 +492,20 @@
 
 // ----------------------------------------------------------------------------------------
 
-void nmea_latitude( int16_t* degrees, fixed16dot16* minutes )
+void nmea_latitude( int16_t* degrees, uint16_t* minutes, uint16_t* fractional_minutes )
 {
-    *degrees = g_latitude_deg;
-    *minutes = g_latitude_min;
+    *degrees            = g_latitude_deg;
+    *minutes            = g_latitude_min;
+    *fractional_minutes = g_latitude_min_fract;
 }
 
 // ----------------------------------------------------------------------------------------
 
-void nmea_longitude( int16_t* degrees, fixed16dot16* minutes )
+void nmea_longitude( int16_t* degrees, uint16_t* minutes, uint16_t* fractional_minutes )
 {
-    *degrees = g_longitude_deg;
-    *minutes = g_longitude_min;
+    *degrees            = g_longitude_deg;
+    *minutes            = g_longitude_min;
+    *fractional_minutes = g_longitude_min_fract;
 }
 
 // ----------------------------------------------------------------------------------------
--- a/main/packages/common/gps/nmea.h	Tue Aug 20 19:53:42 2013 -0700
+++ b/main/packages/common/gps/nmea.h	Wed Aug 21 06:19:06 2013 -0700
@@ -7,7 +7,7 @@
 //    
 //  This file implements a state machine to parse selected NMEA sentences.
 //
-//  Copyright (c) 2010 Bob Cook
+//  Copyright (c) 2010-2013 Bob Cook
 //  
 //  Permission is hereby granted, free of charge, to any person obtaining a copy
 //  of this software and associated documentation files (the "Software"), to deal
@@ -36,7 +36,9 @@
 
 #include <stdint.h>
 
-#include "packages/common/util/fixedpoint.h"
+// ----------------------------------------------------------------------------------------
+
+const int32_t nmea_fractional_minutes_multiplier = 10000;
 
 // ----------------------------------------------------------------------------------------
 //  nmea_parse
@@ -71,23 +73,27 @@
 //  nmea_latitude
 //
 //      Retrieve the degrees and minutes of the latitude field from a GPGGA sentence.
-//      The degrees will be positive for northern locations, negative for southern.
+//      The degrees will be positive for northern locations, negative for southern. The
+//      minutes are whole numbers, and the fractional portion of the minutes are scaled
+//      by 10,000 e.g. 0.123 will be stored as 1,230. Only four significant digits are
+//      returned e.g. 0.9999 is the maximum fractional value.
 //
 //      This value will only be meaningful if nmea_parse() returns true.
 //
 
-void nmea_latitude( int16_t* degrees, fixed16dot16* minutes );
+void nmea_latitude( int16_t* degrees, uint16_t* minutes, uint16_t* fractional_minutes );
 
 // ----------------------------------------------------------------------------------------
 //  nmea_longitude
 //
 //      Retrieve the degrees and minutes of the longitude field from a GPGGA sentence.
-//      The degrees will be positive for eastern locations, negative for western.
+//      The degrees will be positive for eastern locations, negative for western. The
+//      minutes and fractional minutes follow the same format as nmea_latitude().
 //
 //      This value will only be meaningful if nmea_parse() returns true.
 //
 
-void nmea_longitude( int16_t* degrees, fixed16dot16* minutes );
+void nmea_longitude( int16_t* degrees, uint16_t* minutes, uint16_t* fractional_minutes );
 
 // ----------------------------------------------------------------------------------------
 //  nmea_position_fix