gpsd-dev
[Top][All Lists]
Advanced

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

[gpsd-dev] [PATCH 1/4] [oscillator] Add concept of a GPS-disciplined osc


From: Michael Brown
Subject: [gpsd-dev] [PATCH 1/4] [oscillator] Add concept of a GPS-disciplined oscillator
Date: Fri, 29 Jan 2016 14:36:46 +0000

Signed-off-by: Michael Brown <address@hidden>
---
 SConstruct    |  1 +
 gps.h         | 14 +++++++++++-
 gps_json.h    |  1 +
 gpsd.h-tail   |  3 ++-
 gpsd_json.c   | 21 ++++++++++++++++++
 gpsd_json.xml | 71 +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
 libgps_json.c | 41 ++++++++++++++++++++++++++++++++++
 test_json.c   | 38 +++++++++++++++++++++++---------
 8 files changed, 177 insertions(+), 13 deletions(-)

diff --git a/SConstruct b/SConstruct
index d638a19..c376f62 100644
--- a/SConstruct
+++ b/SConstruct
@@ -127,6 +127,7 @@ boolopts = (
     ("ntp",           True,  "NTP time hinting support"),
     ("ntpshm",        True,  "NTP time hinting via shared memory"),
     ("pps",           True,  "PPS time syncing support"),
+    ("oscillator",    True,  "Disciplined oscillator support"),
     # Export methods
     ("socket_export", True,  "data export over sockets"),
     ("dbus_export",   True,  "enable DBUS export support"),
diff --git a/gps.h b/gps.h
index 5602b0d..f4535f4 100644
--- a/gps.h
+++ b/gps.h
@@ -1907,6 +1907,13 @@ struct timedelta_t {
 };
 #endif /* TIMEDELTA_DEFINED */
 
+struct oscillator_t {
+    bool running;                      /* oscillator is running */
+    bool reference;                    /* PPS reference is available */
+    bool disciplined;                  /* oscillator is GPS-disciplined */
+    int delta;                         /* last observed PPS delta */
+};
+
 /*
  * Someday we may support Windows, under which socket_t is a separate type.
  * In the meantime, having a typedef for this semantic kind is no bad thing,
@@ -1971,7 +1978,8 @@ struct gps_data_t {
 #define TOFF_SET       (1llu<<32)      /* not yet used */
 #define PPS_SET        (1llu<<33)
 #define NAVDATA_SET     (1llu<<34)
-#define SET_HIGH_BIT   35
+#define OSCILLATOR_SET (1llu<<35)
+#define SET_HIGH_BIT   36
     timestamp_t online;                /* NZ if GPS is on line, 0 if not.
                                 *
                                 * Note: gpsd clears this time when sentences
@@ -2019,6 +2027,8 @@ struct gps_data_t {
        struct devconfig_t list[MAXUSERDEVS];
     } devices;
 
+    struct oscillator_t osc;   /* oscillator data */
+
     /* pack things never reported together to reduce structure size */
 #define UNION_SET      
(RTCM2_SET|RTCM3_SET|SUBFRAME_SET|AIS_SET|ATTITUDE_SET|GST_SET|VERSION_SET|LOGMESSAGE_SET|ERROR_SET|TOFF_SET|PPS_SET)
     union {
@@ -2060,6 +2070,8 @@ int json_toff_read(const char *buf, struct gps_data_t *,
                  const char **);
 int json_pps_read(const char *buf, struct gps_data_t *,
                  const char **);
+int json_oscillator_read(const char *buf, struct gps_data_t *,
+                        const char **);
 
 /* dependencies on struct gpsdata_t end here */
 
diff --git a/gps_json.h b/gps_json.h
index a77b267..1d4cf58 100644
--- a/gps_json.h
+++ b/gps_json.h
@@ -23,6 +23,7 @@ void json_tpv_dump(const struct gps_device_t *,
 void json_noise_dump(const struct gps_data_t *, char *, size_t);
 void json_sky_dump(const struct gps_data_t *, char *, size_t);
 void json_att_dump(const struct gps_data_t *, char *, size_t);
+void json_oscillator_dump(const struct gps_data_t *, char *, size_t);
 void json_subframe_dump(const struct gps_data_t *, char buf[], size_t);
 void json_device_dump(const struct gps_device_t *, char *, size_t);
 void json_watch_dump(const struct policy_t *, char *, size_t);
diff --git a/gpsd.h-tail b/gpsd.h-tail
index 6059223..68ea3ab 100644
--- a/gpsd.h-tail
+++ b/gpsd.h-tail
@@ -32,9 +32,10 @@
  * 3.10 The obsolete tag field has been dropped from JSON.
  * 3.11 A precision field, log2 of the time source jitter, has been added
  *      to the PPS report.  See ntpshm.h for more details.
+ * 3.12 OSC message added to repertoire.
  */
 #define GPSD_PROTO_MAJOR_VERSION       3       /* bump on incompatible changes 
*/
-#define GPSD_PROTO_MINOR_VERSION       11      /* bump on compatible changes */
+#define GPSD_PROTO_MINOR_VERSION       12      /* bump on compatible changes */
 
 #define JSON_DATE_MAX  24      /* ISO8601 timestamp with 2 decimal places */
 
diff --git a/gpsd_json.c b/gpsd_json.c
index 530ee3d..88bab70 100644
--- a/gpsd_json.c
+++ b/gpsd_json.c
@@ -3366,6 +3366,21 @@ void json_att_dump(const struct gps_data_t *gpsdata,
 }
 #endif /* COMPASS_ENABLE */
 
+#ifdef OSCILLATOR_ENABLE
+void json_oscillator_dump(const struct gps_data_t *datap,
+                         char *reply, size_t replylen)
+/* dump the contents of an oscillator_t structure as JSON */
+{
+    (void)snprintf(reply, replylen,
+                  
"{\"class\":\"OSC\",\"device\":\"%s\",\"running\":%s,\"reference\":%s,\"disciplined\":%s,\"delta\":%d}\r\n",
+                  datap->dev.path,
+                  JSON_BOOL(datap->osc.running),
+                  JSON_BOOL(datap->osc.reference),
+                  JSON_BOOL(datap->osc.disciplined),
+                  datap->osc.delta);
+}
+#endif /* OSCILLATOR_ENABLE */
+
 void json_data_report(const gps_mask_t changed,
                 const struct gps_device_t *session,
                 const struct policy_t *policy,
@@ -3418,6 +3433,12 @@ void json_data_report(const gps_mask_t changed,
                        buf+strlen(buf), buflen-strlen(buf));
     }
 #endif /* AIVDM_ENABLE */
+
+#ifdef OSCILLATOR_ENABLE
+    if ((changed & OSCILLATOR_SET) != 0) {
+       json_oscillator_dump(datap, buf+strlen(buf), buflen-strlen(buf));
+    }
+#endif /* OSCILLATOR_ENABLE */
 }
 
 #undef JSON_BOOL
diff --git a/gpsd_json.xml b/gpsd_json.xml
index 03d3cb5..46bcdc0 100644
--- a/gpsd_json.xml
+++ b/gpsd_json.xml
@@ -1341,6 +1341,77 @@ limited to about 1 millisecond. seconds.</para>
 </varlistentry>
 
 <varlistentry>
+<term>OSC</term>
+<listitem>
+
+<para>This message reports the status of a GPS-disciplined oscillator
+(GPSDO).  The GPS PPS output (which has excellent long-term stability)
+is typically used to discipline a local oscillator with much better
+short-term stability (such as a rubidium atomic clock).</para>
+
+<para>An OSC object has the following elements:</para>
+
+<table frame="all" pgwide="0"><title>OSC object</title>
+<tgroup cols="3" align="left" colsep="1" rowsep="1">
+<thead>
+<row>
+       <entry>Name</entry>
+       <entry>Always?</entry>
+       <entry>Type</entry>
+       <entry>Description</entry>
+</row>
+</thead>
+<tbody>
+<row>
+       <entry>class</entry>
+       <entry>Yes</entry>
+       <entry>string</entry>
+        <entry>Fixed: "OSC"</entry>
+</row>
+<row>
+       <entry>device</entry>
+       <entry>Yes</entry>
+       <entry>string</entry>
+        <entry>Name of originating device.</entry>
+</row>
+<row>
+       <entry>running</entry>
+       <entry>Yes</entry>
+       <entry>boolean</entry>
+        <entry>If true, the oscillator is currently running.  Oscillators may 
require warm-up time at start of day.</entry>
+</row>
+<row>
+       <entry>reference</entry>
+       <entry>Yes</entry>
+       <entry>boolean</entry>
+        <entry>If true, the oscillator is receiving a GPS PPS signal.</entry>
+</row>
+<row>
+       <entry>disciplined</entry>
+       <entry>Yes</entry>
+       <entry>boolean</entry>
+        <entry>If true, the GPS PPS signal is sufficiently stable and is being 
used to discipline the local oscillator.</entry>
+</row>
+<row>
+       <entry>delta</entry>
+       <entry>Yes</entry>
+       <entry>numeric</entry>
+        <entry>The time difference (in nanoseconds) between the 
GPS-disciplined oscillator PPS output pulse and the most recent GPS PPS input 
pulse.</entry>
+</row>
+</tbody>
+</tgroup>
+</table>
+
+<para>Here's an example:</para>
+
+<programlisting>
+{"class":"OSC","running":true,"device":"/dev/ttyUSB0",
+    "reference":true,"disciplined":true,"delta":67}
+</programlisting>
+</listitem>
+</varlistentry>
+
+<varlistentry>
 <term>?DEVICE</term>
 <listitem>
 
diff --git a/libgps_json.c b/libgps_json.c
index 7ebb0f7..1d75168 100644
--- a/libgps_json.c
+++ b/libgps_json.c
@@ -395,6 +395,40 @@ int json_pps_read(const char *buf, struct gps_data_t 
*gpsdata,
     return status;
 }
 
+int json_oscillator_read(const char *buf, struct gps_data_t *gpsdata,
+                        const char **endptr)
+{
+    bool running = false, reference = false, disciplined = false;
+    int delta = 0;
+    const struct json_attr_t json_attrs_osc[] = {
+       /* *INDENT-OFF* */
+        {"class",      t_check,   .dflt.check = "OSC"},
+       {"device",      t_string,  .addr.string = gpsdata->dev.path,
+                                  .len = sizeof(gpsdata->dev.path)},
+       {"running",     t_boolean, .addr.boolean = &running,
+                                  .dflt.boolean = false},
+       {"reference",   t_boolean, .addr.boolean = &reference,
+                                  .dflt.boolean = false},
+       {"disciplined", t_boolean, .addr.boolean = &disciplined,
+                                  .dflt.boolean = false},
+       {"delta",       t_integer, .addr.integer = &delta,
+                                  .dflt.integer = 0},
+       {NULL},
+       /* *INDENT-ON* */
+    };
+    int status;
+
+    memset(&gpsdata->osc, '\0', sizeof(gpsdata->osc));
+    status = json_read_object(buf, json_attrs_osc, endptr);
+
+    gpsdata->osc.running = running;
+    gpsdata->osc.reference = reference;
+    gpsdata->osc.disciplined = disciplined;
+    gpsdata->osc.delta = delta;
+
+    return status;
+}
+
 int libgps_json_unpack(const char *buf,
                       struct gps_data_t *gpsdata, const char **end)
 /* the only entry point - unpack a JSON object into gpsdata_t substructures */
@@ -536,6 +570,13 @@ int libgps_json_unpack(const char *buf,
            gpsdata->set |= PPS_SET;
        }
        return status;
+    } else if (str_starts_with(classtag, "\"class\":\"OSC\"")) {
+       status = json_oscillator_read(buf, gpsdata, end);
+       if (status == 0) {
+           gpsdata->set &= ~UNION_SET;
+           gpsdata->set |= OSCILLATOR_SET;
+       }
+       return status;
     } else
        return -1;
 }
diff --git a/test_json.c b/test_json.c
index aff1aa0..84c86fa 100644
--- a/test_json.c
+++ b/test_json.c
@@ -223,8 +223,14 @@ static const char *json_strTOFF = 
"{\"class\":\"TOFF\",\"device\":\"GPS#1\"," \
     "\"real_sec\":1428001514, \"real_nsec\":1000000," \
     "\"clock_sec\":1428001513,\"clock_nsec\":999999999}";
 
+/* Case 12: test parsing of OSC message */
+
+static const char *json_strOSC = "{\"class\":\"OSC\",\"device\":\"GPS#1\"," \
+    "\"running\":true,\"reference\":true,\"disciplined\":false," \
+    "\"delta\":67}";
+
 #ifndef JSON_MINIMAL
-/* Case 12: Read array of integers */
+/* Case 13: Read array of integers */
 
 static const char *json_strInt = "[23,-17,5]";
 static int intstore[4], intcount;
@@ -236,7 +242,7 @@ static const struct json_array_t json_array_Int = {
     .maxlen = sizeof(intstore)/sizeof(intstore[0]),
 };
 
-/* Case 13: Read array of booleans */
+/* Case 14: Read array of booleans */
 
 static const char *json_strBool = "[true,false,true]";
 static bool boolstore[4];
@@ -249,13 +255,13 @@ static const struct json_array_t json_array_Bool = {
     .maxlen = sizeof(boolstore)/sizeof(boolstore[0]),
 };
 
-/* Case 14: Read array of reals */
+/* Case 15: Read array of reals */
 
-static const char *json_str14 = "[23.1,-17.2,5.3]";
+static const char *json_str15 = "[23.1,-17.2,5.3]";
 static double realstore[4];
 static int realcount;
 
-static const struct json_array_t json_array_14 = {
+static const struct json_array_t json_array_15 = {
     .element_type = t_real,
     .arr.reals.store = realstore,
     .count = &realcount,
@@ -386,10 +392,20 @@ static void jsontest(int i)
        assert_integer("clock_nsec", gpsdata.pps.clock.tv_nsec, 999999999);
        break;
 
+    case 12:
+       status = json_oscillator_read(json_strOSC, &gpsdata, NULL);
+       assert_case(12,status);
+       assert_string("device", gpsdata.dev.path, "GPS#1");
+       assert_boolean("running", gpsdata.osc.running, true);
+       assert_boolean("reference", gpsdata.osc.reference, true);
+       assert_boolean("disciplined", gpsdata.osc.disciplined, false);
+       assert_integer("delta", gpsdata.osc.delta, 67);
+       break;
+
 #ifdef JSON_MINIMAL
-#define MAXTEST 11
+#define MAXTEST 12
 #else
-    case 12:
+    case 13:
        status = json_read_array(json_strInt, &json_array_Int, NULL);
        assert_integer("count", intcount, 3);
        assert_integer("intstore[0]", intstore[0], 23);
@@ -398,7 +414,7 @@ static void jsontest(int i)
        assert_integer("intstore[3]", intstore[3], 0);
        break;
 
-    case 13:
+    case 14:
        status = json_read_array(json_strBool, &json_array_Bool, NULL);
        assert_integer("count", boolcount, 3);
        assert_boolean("boolstore[0]", boolstore[0], true);
@@ -407,8 +423,8 @@ static void jsontest(int i)
        assert_boolean("boolstore[3]", boolstore[3], false);
        break;
 
-    case 14:
-       status = json_read_array(json_str14, &json_array_14, NULL);
+    case 15:
+       status = json_read_array(json_str15, &json_array_15, NULL);
        assert_integer("count", realcount, 3);
        assert_real("realstore[0]", realstore[0], 23.1);
        assert_real("realstore[1]", realstore[1], -17.2);
@@ -416,7 +432,7 @@ static void jsontest(int i)
        assert_real("realstore[3]", realstore[3], 0);
        break;
 
-#define MAXTEST 14
+#define MAXTEST 15
 #endif /* JSON_MINIMAL */
 
     default:
-- 
2.3.8




reply via email to

[Prev in Thread] Current Thread [Next in Thread]