Please ignore/delete my previous email with identical subject,
 line wrapping ruined the formatting.

Purpose of this patch: 
* For 1pps pulse widths != 500ms, the pulse width allows unambiguous 
  determination of the correct edge on popular devices like i211 and i210 which
  can only time stamp external pulses with  extts_polarity=both. For 500ms 
pulses
  the edge closest to the whole second is chosen.

* Fix error handling: timeout=1500ms
  The old value of 2000 ms would allow a missing pulse undetected if the PHC is 
running a 
  little bit slow.
  A sign orror of EINTR is fixed
  The behavior for missing pulses (cnt==0) is changed to an error such that a 
silent 
  1pps source can be acted upon.

Signed-off-by: Jürgen Appel <j...@dfm.dk>
---
 ts2phc_pps_sink.c | 66 +++++++++++++++++++++++++++++++++++------------
 1 file changed, 49 insertions(+), 17 deletions(-)

diff --git a/ts2phc_pps_sink.c b/ts2phc_pps_sink.c
index d25bc89..1e86849 100644
--- a/ts2phc_pps_sink.c
+++ b/ts2phc_pps_sink.c
@@ -30,8 +30,8 @@ struct ts2phc_pps_sink {
        struct ptp_pin_desc pin_desc;
        unsigned int polarity;
        tmv_t correction;
-       uint32_t ignore_lower;
-       uint32_t ignore_upper;
+       int pulsewidth;
+       tmv_t last;
        struct ts2phc_clock *clock;
 };
 
@@ -175,9 +175,8 @@ static struct ts2phc_pps_sink 
*ts2phc_pps_sink_create(struct ts2phc_private *pri
        sink->correction = nanoseconds_to_tmv(correction);
 
        pulsewidth = config_get_int(cfg, device, "ts2phc.pulsewidth");
-       pulsewidth /= 2;
-       sink->ignore_upper = 1000000000 - pulsewidth;
-       sink->ignore_lower = pulsewidth;
+       sink->pulsewidth = pulsewidth;
+       sink->last.ns = 0;
 
        sink->clock = ts2phc_clock_add(priv, device);
        if (!sink->clock) {
@@ -238,15 +237,40 @@ static void ts2phc_pps_sink_destroy(struct 
ts2phc_pps_sink *sink)
 
 static bool ts2phc_pps_sink_ignore(struct ts2phc_private *priv,
                                   struct ts2phc_pps_sink *sink,
+                                  struct ptp_extts_event event,
                                   struct timespec source_ts)
 {
-       tmv_t source_tmv = timespec_to_tmv(source_ts);
-
-       source_tmv = tmv_sub(source_tmv, priv->perout_phase);
-       source_ts = tmv_to_timespec(source_tmv);
-
-       return source_ts.tv_nsec > sink->ignore_lower &&
-              source_ts.tv_nsec < sink->ignore_upper;
+       tmv_t event_tmv, source_tmv, dt;
+
+       if (sink->pulsewidth == NS_PER_SEC/2) {
+               /*
+                * 1pps has exactly 50% duty cycle: discriminate edges
+                * by CLOCK_REALTIME timestamp, requires CLOCK_REALTIME/
+                * to be approximately correct and stable
+                */
+               source_tmv = timespec_to_tmv(source_ts);
+               source_tmv = tmv_sub(source_tmv, priv->perout_phase);
+               source_ts = tmv_to_timespec(source_tmv);
+
+               return (source_ts.tv_nsec > NS_PER_SEC/4) &&
+                 (source_ts.tv_nsec < NS_PER_SEC/4*3);
+       } else {
+               /*
+                * use pulse-width to discriminate rising/falling edges,
+                * does not require CLOCK_REALTIME to run correctly,
+                * tolerates jumps there
+                */
+               event_tmv = pct_to_tmv(event.t);
+               if (sink->last.ns) {
+                       dt = tmv_sub(event_tmv, sink->last);
+                       sink->last = event_tmv;
+                       return ((dt.ns < (NS_PER_SEC / 2)) ^
+                               (sink->pulsewidth > (NS_PER_SEC / 2)));
+               } else { /* ignore first event */
+                       sink->last = event_tmv;
+                       return true;
+               }
+       }
 }
 
 static enum extts_result ts2phc_pps_sink_event(struct ts2phc_private *priv,
@@ -277,7 +301,7 @@ static enum extts_result ts2phc_pps_sink_event(struct 
ts2phc_private *priv,
        }
 
        if (sink->polarity == (PTP_RISING_EDGE | PTP_FALLING_EDGE) &&
-           ts2phc_pps_sink_ignore(priv, sink, source_ts)) {
+           ts2phc_pps_sink_ignore(priv, sink, event, source_ts)) {
 
                pr_debug("%s SKIP extts index %u at %lld.%09u src %" PRIi64 
".%ld",
                 sink->name, event.index, event.t.sec, event.t.nsec,
@@ -379,17 +403,25 @@ int ts2phc_pps_sink_poll(struct ts2phc_private *priv)
        while (!all_sinks_have_events) {
                struct ts2phc_pps_sink *sink;
 
-               cnt = poll(polling_array->pfd, priv->n_sinks, 2000);
+               cnt = poll(polling_array->pfd, priv->n_sinks, 1500);
+               /*
+                * timeout =1.5 s ensures that every missing pulse is
+                * detected, even if the PHC is running a little
+                * bit slow, and that a slightly fast PHC causes
+                * no false alarms.
+                */
                if (cnt < 0) {
-                       if (errno == -EINTR) {
+                       if (errno == EINTR) {
+                               /* signal occurred */
+                               pr_err("poll interrupted");
                                return 0;
                        } else {
-                               pr_emerg("poll failed");
+                               pr_err("poll failed");
                                return -1;
                        }
                } else if (!cnt) {
                        pr_debug("poll returns zero, no events");
-                       return 0;
+                       return -1;
                }
 
                for (i = 0; i < priv->n_sinks; i++) {
-- 
2.34.1




_______________________________________________
Linuxptp-devel mailing list
Linuxptp-devel@lists.sourceforge.net
https://lists.sourceforge.net/lists/listinfo/linuxptp-devel

Reply via email to