From b91f6eb6d06028f840b7ffbcc01a320f8ecb283c Mon Sep 17 00:00:00 2001
From: Florian Pose <fp@igh-essen.com>
Date: Fri, 24 Apr 2009 10:24:53 +0000
Subject: [PATCH] Replaced timeval by 64-bit EtherCAT time.

---
 TODO                              |  4 ++--
 examples/dc_rtai/dc_rtai_sample.c |  7 +++++--
 examples/dc_user/main.c           |  2 +-
 include/ecrt.h                    | 20 +++++++++++++++++---
 lib/master.c                      |  6 ++----
 master/cdev.c                     |  2 +-
 master/globals.h                  |  7 -------
 master/ioctl.h                    |  2 +-
 master/master.c                   |  4 ++--
 9 files changed, 31 insertions(+), 23 deletions(-)

diff --git a/TODO b/TODO
index 41ee54ac..42ba4707 100644
--- a/TODO
+++ b/TODO
@@ -12,8 +12,8 @@ Version 1.5.0:
 
 * Distributed clocks:
     - Delay calculation.
-    - User same application time offset when setting start times.
-    - Replace timeval by uint64 EtherCAT time.
+    - Use common application time offset when setting start times.
+    - Check 32/64 bit operations.
 * Fix arguments of reg_read.
 * Sign/Abs type for reg_ commands?
 * Number layout for reg_read.
diff --git a/examples/dc_rtai/dc_rtai_sample.c b/examples/dc_rtai/dc_rtai_sample.c
index c587302a..503cbdeb 100644
--- a/examples/dc_rtai/dc_rtai_sample.c
+++ b/examples/dc_rtai/dc_rtai_sample.c
@@ -220,13 +220,16 @@ void run(long data)
             tv.tv_usec -= 1000000;
             tv.tv_sec++;
         }
-        //printk(KERN_INFO PFX "tv=%u.%06u\n", (u32) tv.tv_sec, (u32) tv.tv_usec);
             
         if (sync_ref_counter) {
             sync_ref_counter--;
         } else {
             sync_ref_counter = 9;
-            ecrt_master_sync_reference_clock(master, &tv);
+#if 0
+            printk(KERN_INFO PFX "ref: %u %u %llu\n",
+                    (u32) tv.tv_sec, (u32) tv.tv_usec, EC_TIMEVAL2NANO(&tv));
+#endif
+            ecrt_master_sync_reference_clock(master, EC_TIMEVAL2NANO(&tv));
         }
 		ecrt_master_sync_slave_clocks(master);
         ecrt_domain_queue(domain1);
diff --git a/examples/dc_user/main.c b/examples/dc_user/main.c
index 1bffa4e3..444a0abf 100644
--- a/examples/dc_user/main.c
+++ b/examples/dc_user/main.c
@@ -169,7 +169,7 @@ void cyclic_task()
         sync_ref_counter--;
     } else {
         sync_ref_counter = 9;
-        ecrt_master_sync_reference_clock(master, &app_time);
+        ecrt_master_sync_reference_clock(master, EC_TIMEVAL2NANO(&app_time));
     }
     ecrt_master_sync_slave_clocks(master);
 
diff --git a/include/ecrt.h b/include/ecrt.h
index ac53f9e7..ed8317a9 100644
--- a/include/ecrt.h
+++ b/include/ecrt.h
@@ -46,7 +46,8 @@
  *   ecrt_slave_config_dc_sync_cycle_times() and
  *   ecrt_slave_config_dc_sync_shift_times() to configure a slave for cyclic
  *   operation, and ecrt_master_sync_reference_clock() and
- *   ecrt_master_sync_slave_clocks() for drift compensation.
+ *   ecrt_master_sync_slave_clocks() for drift compensation. The
+ *   EC_TIMEVAL2NANO() macro can be used for epoch time conversion.
  * - Changed the meaning of the negative return values of
  *   ecrt_slave_config_reg_pdo_entry() and ecrt_slave_config_sdo*().
  * - Imlemented the Vendor-specific over EtherCAT mailbox protocol. See
@@ -114,6 +115,17 @@
  */
 #define EC_MAX_STRING_LENGTH 64
 
+/** Timeval to nanoseconds conversion.
+ *
+ * This macro converts a unix epoch time to EtherCAT DC time.
+ *
+ * \see ecrt_master_sync_reference_clock()
+ *
+ * \param TV Pointer to struct timeval.
+ */
+#define EC_TIMEVAL2NANO(TV) \
+    (((TV)->tv_sec - 946684800ULL) * 1000000000ULL + (TV)->tv_usec * 1000ULL)
+
 /******************************************************************************
  * Data types 
  *****************************************************************************/
@@ -510,11 +522,13 @@ void ecrt_master_state(
 
 /** Queues the DC reference clock drift compensation datagram for sending.
  *
- * The reference clock will by synchronized to the \a app_time.
+ * The reference clock will by synchronized to the \a app_time. The time is
+ * defined as nanoseconds from 2000-01-01 00:00. Converting an epoch time can
+ * be done with the EC_TIMEVAL2NANO() macro.
  */
 void ecrt_master_sync_reference_clock(
         ec_master_t *master, /**< EtherCAT master. */
-        const struct timeval *app_time /**< Application time. */
+        uint64_t app_time /**< Application time. */
         );
 
 /** Queues the DC clock drift compensation datagram for sending.
diff --git a/lib/master.c b/lib/master.c
index 298cd60f..f266f752 100644
--- a/lib/master.c
+++ b/lib/master.c
@@ -190,13 +190,11 @@ void ecrt_master_state(const ec_master_t *master, ec_master_state_t *state)
 
 /*****************************************************************************/
 
-void ecrt_master_sync_reference_clock(ec_master_t *master,
-        const struct timeval *app_time)
+void ecrt_master_sync_reference_clock(ec_master_t *master, uint64_t app_time)
 {
     ec_ioctl_dc_t data;
 
-    data.app_time.tv_sec = app_time->tv_sec;
-    data.app_time.tv_usec = app_time->tv_usec;
+    data.app_time = app_time;
 
     if (ioctl(master->fd, EC_IOCTL_SYNC_REF, &data) == -1) {
         fprintf(stderr, "Failed to sync reference clock: %s\n",
diff --git a/master/cdev.c b/master/cdev.c
index 8fbd265c..395ccdb2 100644
--- a/master/cdev.c
+++ b/master/cdev.c
@@ -1647,7 +1647,7 @@ int ec_cdev_ioctl_sync_ref(
         return -EFAULT;
 
     spin_lock_bh(&master->internal_lock);
-    ecrt_master_sync_reference_clock(master, &data.app_time);
+    ecrt_master_sync_reference_clock(master, data.app_time);
     spin_unlock_bh(&master->internal_lock);
     return 0;
 }
diff --git a/master/globals.h b/master/globals.h
index 2daf06c6..3444f150 100644
--- a/master/globals.h
+++ b/master/globals.h
@@ -251,13 +251,6 @@ enum {
         .name = EC_STR(NAME), .owner = THIS_MODULE, .mode = S_IRUGO | S_IWUSR \
     }
 
-/** Timeval to nanoseconds conversion.
- *
- * \param TV Pointer to struct timeval.
- */
-#define EC_TIMEVAL2NANO(TV) \
-    (((TV)->tv_sec - 946684800ULL) * 1000000000ULL + (TV)->tv_usec * 1000ULL)
-
 /*****************************************************************************/
 
 extern char *ec_master_version_str;
diff --git a/master/ioctl.h b/master/ioctl.h
index fb3d3171..431fe246 100644
--- a/master/ioctl.h
+++ b/master/ioctl.h
@@ -389,7 +389,7 @@ typedef struct {
 
 typedef struct {
     // inputs
-    struct timeval app_time;
+    uint64_t app_time;
 } ec_ioctl_dc_t;
 
 /*****************************************************************************/
diff --git a/master/master.c b/master/master.c
index e0a8384f..231b7a80 100644
--- a/master/master.c
+++ b/master/master.c
@@ -1651,9 +1651,9 @@ void ecrt_master_state(const ec_master_t *master, ec_master_state_t *state)
 /*****************************************************************************/
 
 void ecrt_master_sync_reference_clock(ec_master_t *master,
-        const struct timeval *app_time)
+        uint64_t app_time)
 {
-    master->app_time = EC_TIMEVAL2NANO(app_time);
+    master->app_time = app_time;
     EC_WRITE_U32(master->ref_sync_datagram.data, master->app_time);
     ec_master_queue_datagram(master, &master->ref_sync_datagram);
 }
-- 
GitLab