Transition delay calculation. TBC...
authorFlorian Pose <fp@igh-essen.com>
Thu, 30 Apr 2009 14:12:47 +0000
changeset 1425 c1322a8793c0
parent 1424 cb02dbe4076f
child 1426 af45bba80d85
Transition delay calculation. TBC...
TODO
master/cdev.c
master/fsm_master.c
master/fsm_slave_scan.c
master/globals.h
master/ioctl.h
master/master.c
master/master.h
master/slave.c
master/slave.h
tool/CommandGraph.cpp
tool/CommandSlaves.cpp
--- a/TODO	Wed Apr 29 14:03:01 2009 +0000
+++ b/TODO	Thu Apr 30 14:12:47 2009 +0000
@@ -11,7 +11,6 @@
 Version 1.5.0:
 
 * Distributed clocks:
-    - Delay calculation.
     - Use common application time offset when setting start times.
     - Check 32/64 bit operations.
     - Set system time offset only when application time available.
--- a/master/cdev.c	Wed Apr 29 14:03:01 2009 +0000
+++ b/master/cdev.c	Thu Apr 30 14:12:47 2009 +0000
@@ -257,21 +257,23 @@
     data.general_flags = slave->sii.general_flags;
     data.current_on_ebus = slave->sii.current_on_ebus;
     for (i = 0; i < EC_MAX_PORTS; i++) {
-        data.port_descs[i] = slave->base_ports[i];
-        data.ports[i].dl_link = slave->ports[i].dl_link;
-        data.ports[i].dl_loop = slave->ports[i].dl_loop;
-        data.ports[i].dl_signal = slave->ports[i].dl_signal;
-        data.dc_receive_times[i] = slave->dc_receive_times[i];
-        if (slave->next_slave[i]) {
-            data.next_slave[i] = slave->next_slave[i]->ring_position;
+        data.ports[i].desc = slave->ports[i].desc;
+        data.ports[i].link.link_up = slave->ports[i].link.link_up;
+        data.ports[i].link.loop_closed = slave->ports[i].link.loop_closed;
+        data.ports[i].link.signal_detected = slave->ports[i].link.signal_detected;
+        data.ports[i].receive_time = slave->ports[i].receive_time;
+        if (slave->ports[i].next_slave) {
+            data.ports[i].next_slave = slave->ports[i].next_slave->ring_position;
         } else {
-            data.next_slave[i] = 0xffff;
+            data.ports[i].next_slave = 0xffff;
         }
+        data.ports[i].delay_to_next_dc = slave->ports[i].delay_to_next_dc;
     }
     data.fmmu_bit = slave->base_fmmu_bit_operation;
     data.dc_supported = slave->base_dc_supported;
     data.dc_range = slave->base_dc_range;
     data.has_dc_system_time = slave->has_dc_system_time;
+    data.transition_delay = slave->transition_delay;
     data.al_state = slave->current_state;
     data.error_flag = slave->error_flag;
 
--- a/master/fsm_master.c	Wed Apr 29 14:03:01 2009 +0000
+++ b/master/fsm_master.c	Thu Apr 30 14:12:47 2009 +0000
@@ -865,11 +865,7 @@
     master->scan_busy = 0;
     wake_up_interruptible(&master->scan_queue);
 
-	// find DC reference clock
-	ec_master_find_dc_ref_clock(master);
-
-    // calculate bus topology
-    ec_master_calc_topology(master);
+    ec_master_calc_dc(master);
 	
     // Attach slave configurations
     ec_master_attach_slave_configs(master);
--- a/master/fsm_slave_scan.c	Wed Apr 29 14:03:01 2009 +0000
+++ b/master/fsm_slave_scan.c	Thu Apr 30 14:12:47 2009 +0000
@@ -311,7 +311,7 @@
 
     octet = EC_READ_U8(datagram->data + 7);
     for (i = 0; i < EC_MAX_PORTS; i++) {
-        slave->base_ports[i] = (octet >> (2 * i)) & 0x03;
+        slave->ports[i].desc = (octet >> (2 * i)) & 0x03;
     }
     
     octet = EC_READ_U8(datagram->data + 8);
@@ -417,7 +417,7 @@
     }
 
     for (i = 0; i < EC_MAX_PORTS; i++) {
-        slave->dc_receive_times[i] = EC_READ_U32(datagram->data + 4 * i);
+        slave->ports[i].receive_time = EC_READ_U32(datagram->data + 4 * i);
     }
 
     ec_fsm_slave_scan_enter_datalink(fsm);
@@ -478,9 +478,9 @@
 
     dl_status = EC_READ_U16(datagram->data);
     for (i = 0; i < EC_MAX_PORTS; i++) {
-        slave->ports[i].dl_link = dl_status & (1 << (4 + i)) ? 1 : 0;
-        slave->ports[i].dl_loop = dl_status & (1 << (8 + i * 2)) ? 1 : 0;
-        slave->ports[i].dl_signal = dl_status & (1 << (9 + i * 2)) ? 1 : 0;
+        slave->ports[i].link.link_up = dl_status & (1 << (4 + i)) ? 1 : 0;
+        slave->ports[i].link.loop_closed = dl_status & (1 << (8 + i * 2)) ? 1 : 0;
+        slave->ports[i].link.signal_detected = dl_status & (1 << (9 + i * 2)) ? 1 : 0;
     }
 
     // Start fetching SII size
--- a/master/globals.h	Wed Apr 29 14:03:01 2009 +0000
+++ b/master/globals.h	Thu Apr 30 14:12:47 2009 +0000
@@ -169,10 +169,10 @@
 /** EtherCAT slave port information.
  */
 typedef struct {
-    uint8_t dl_link; /**< Link detected. */
-    uint8_t dl_loop; /**< Loop closed. */
-    uint8_t dl_signal; /**< Detected signal on RX port. */
-} ec_slave_port_t;
+    uint8_t link_up; /**< Link detected. */
+    uint8_t loop_closed; /**< Loop closed. */
+    uint8_t signal_detected; /**< Detected signal on RX port. */
+} ec_slave_port_link_t;
 
 /** EtherCAT slave distributed clocks range.
  */
--- a/master/ioctl.h	Wed Apr 29 14:03:01 2009 +0000
+++ b/master/ioctl.h	Thu Apr 30 14:12:47 2009 +0000
@@ -165,14 +165,18 @@
     ec_sii_coe_details_t coe_details;
     ec_sii_general_flags_t general_flags;
     int16_t current_on_ebus;
-    ec_slave_port_desc_t port_descs[EC_MAX_PORTS];
-    ec_slave_port_t ports[EC_MAX_PORTS];
-    uint16_t next_slave[EC_MAX_PORTS];
+    struct {
+        ec_slave_port_desc_t desc;
+        ec_slave_port_link_t link;
+        uint32_t receive_time;
+        uint16_t next_slave;
+        uint32_t delay_to_next_dc;
+    } ports[EC_MAX_PORTS];
     uint8_t fmmu_bit;
     uint8_t dc_supported;
     ec_slave_dc_range_t dc_range;
     uint8_t has_dc_system_time;
-    uint32_t dc_receive_times[EC_MAX_PORTS];
+    uint32_t transition_delay;
     uint8_t al_state;
     uint8_t error_flag;
     uint8_t sync_count;
--- a/master/master.c	Wed Apr 29 14:03:01 2009 +0000
+++ b/master/master.c	Thu Apr 30 14:12:47 2009 +0000
@@ -77,6 +77,7 @@
 #ifdef EC_EOE
 void ec_master_eoe_run(unsigned long);
 #endif
+void ec_master_find_dc_ref_clock(ec_master_t *);
 
 /*****************************************************************************/
 
@@ -342,6 +343,8 @@
 {
     ec_slave_t *slave;
 
+    master->dc_ref_clock = NULL;
+
     for (slave = master->slaves;
             slave < master->slaves + master->slave_count;
             slave++) {
@@ -1357,20 +1360,22 @@
         ec_master_t *master /**< EtherCAT master. */
 		)
 {
-	ec_slave_t *slave;
-	uint16_t ref_clock_addr = 0xffff;
+	ec_slave_t *slave, *ref = NULL;
 
     for (slave = master->slaves;
             slave < master->slaves + master->slave_count;
             slave++) {
-		if (slave->base_dc_supported && slave->has_dc_system_time) {
-			ref_clock_addr = slave->station_address;
-			break;
-		}
-    }
-
-	// This call always succeeds, because the datagram has been pre-allocated.
-	ec_datagram_frmw(&master->sync_datagram, ref_clock_addr, 0x0910, 4);
+        if (slave->base_dc_supported && slave->has_dc_system_time) {
+            ref = slave;
+            break;
+        }
+    }
+
+    master->dc_ref_clock = ref;
+    
+    // This call always succeeds, because the datagram has been pre-allocated.
+    ec_datagram_frmw(&master->sync_datagram,
+            ref ? ref->station_address : 0xffff, 0x0910, 4);
 }
 
 /*****************************************************************************/
@@ -1387,13 +1392,13 @@
     unsigned int i;
     int ret;
 
-    slave->next_slave[0] = port0_slave;
+    slave->ports[0].next_slave = port0_slave;
 
     for (i = 1; i < EC_MAX_PORTS; i++) {
-        if (!slave->ports[i].dl_loop) {
+        if (!slave->ports[i].link.loop_closed) {
             *slave_position = *slave_position + 1;
             if (*slave_position < master->slave_count) {
-                slave->next_slave[i] = master->slaves + *slave_position;
+                slave->ports[i].next_slave = master->slaves + *slave_position;
                 ret = ec_master_calc_topology_rec(master,
                         slave, slave_position);
                 if (ret)
@@ -1424,6 +1429,45 @@
         EC_ERR("Failed to calculate bus topology.\n");
 }
 
+/*****************************************************************************/
+
+/** Calculates the bus transition delays.
+ */
+void ec_master_calc_transition_delays(
+        ec_master_t *master /**< EtherCAT master. */
+		)
+{
+	ec_slave_t *slave;
+
+    for (slave = master->slaves;
+            slave < master->slaves + master->slave_count;
+            slave++) {
+        ec_slave_calc_port_delays(slave);
+    }
+
+    if (master->dc_ref_clock) {
+        uint32_t delay = 0;
+        ec_slave_calc_transition_delays_rec(master->dc_ref_clock, &delay);
+    }
+}
+
+/*****************************************************************************/
+
+/** Distributed-clocks calculations.
+ */
+void ec_master_calc_dc(
+        ec_master_t *master /**< EtherCAT master. */
+		)
+{
+	// find DC reference clock
+	ec_master_find_dc_ref_clock(master);
+
+    // calculate bus topology
+    ec_master_calc_topology(master);
+
+    ec_master_calc_transition_delays(master);
+}
+
 /******************************************************************************
  *  Application interface
  *****************************************************************************/
--- a/master/master.h	Wed Apr 29 14:03:01 2009 +0000
+++ b/master/master.h	Thu Apr 30 14:12:47 2009 +0000
@@ -122,6 +122,7 @@
                                        reference clock to the master clock. */
     ec_datagram_t sync_datagram; /**< Datagram used for DC drift
                                    compensation. */
+    ec_slave_t *dc_ref_clock; /**< DC reference clock slave. */
     
     unsigned int scan_busy; /**< Current scan state. */
     unsigned int allow_scan; /**< \a True, if slave scanning is allowed. */
@@ -233,9 +234,8 @@
 ec_slave_config_t *ecrt_master_slave_config_err(ec_master_t *, uint16_t,
         uint16_t, uint32_t, uint32_t);
 
-void ec_master_find_dc_ref_clock(ec_master_t *);
-void ec_master_calc_topology(ec_master_t *);
-
-/*****************************************************************************/
-
-#endif
+void ec_master_calc_dc(ec_master_t *);
+
+/*****************************************************************************/
+
+#endif
--- a/master/slave.c	Wed Apr 29 14:03:01 2009 +0000
+++ b/master/slave.c	Thu Apr 30 14:12:47 2009 +0000
@@ -89,22 +89,24 @@
     slave->base_sync_count = 0;
 
     for (i = 0; i < EC_MAX_PORTS; i++) {
-        slave->base_ports[i] = EC_PORT_NOT_IMPLEMENTED;
-
-        slave->ports[i].dl_link = 0;
-        slave->ports[i].dl_loop = 0;
-        slave->ports[i].dl_signal = 0;
+        slave->ports[i].desc = EC_PORT_NOT_IMPLEMENTED;
+
+        slave->ports[i].link.link_up = 0;
+        slave->ports[i].link.loop_closed = 0;
+        slave->ports[i].link.signal_detected = 0;
         slave->sii.physical_layer[i] = 0xFF;
 
-        slave->dc_receive_times[i] = 0U;
-
-        slave->next_slave[i] = NULL;
+        slave->ports[i].receive_time = 0U;
+
+        slave->ports[i].next_slave = NULL;
+        slave->ports[i].delay_to_next_dc = 0U;
     }
 
     slave->base_fmmu_bit_operation = 0;
     slave->base_dc_supported = 0;
     slave->base_dc_range = EC_DC_32;
     slave->has_dc_system_time = 0;
+    slave->transition_delay = 0U;
 
     slave->sii_words = NULL;
     slave->sii_nwords = 0;
@@ -740,3 +742,126 @@
 }
 
 /*****************************************************************************/
+
+/** Calculates the sum of round-trip-times of connected ports 1-3.
+ */
+uint32_t ec_slave_calc_rtt_sum(
+        ec_slave_t *slave /**< EtherCAT slave. */
+		)
+{
+    uint32_t rtt_sum = 0, rtt;
+    unsigned int i;
+    
+    for (i = 1; i < EC_MAX_PORTS; i++) {
+        if (slave->ports[i].next_slave) {
+            rtt = slave->ports[i].receive_time - slave->ports[i - 1].receive_time;
+            rtt_sum += rtt;
+        }
+    }
+
+    return rtt_sum;
+}
+
+/*****************************************************************************/
+
+/** Finds the next slave supporting DC delay measurement.
+ */
+ec_slave_t *ec_slave_find_next_dc_slave(
+        ec_slave_t *slave /**< EtherCAT slave. */
+		)
+{
+    ec_slave_t *dc_slave = NULL;
+
+    if (slave->base_dc_supported) {
+        dc_slave = slave;
+    } else {
+        unsigned int i;
+
+        for (i = 1; i < EC_MAX_PORTS; i++) {
+            ec_slave_t *next = slave->ports[i].next_slave;
+            if (next) {
+                dc_slave = ec_slave_find_next_dc_slave(next);
+                if (dc_slave)
+                    break;
+            }
+        }
+    }
+
+    return dc_slave;
+}
+
+/*****************************************************************************/
+
+/** Calculates the port transition delays.
+ */
+void ec_slave_calc_port_delays(
+        ec_slave_t *slave /**< EtherCAT slave. */
+		)
+{
+    unsigned int i;
+    ec_slave_t *next, *next_dc;
+    uint32_t rtt, next_rtt_sum;
+
+    if (!slave->base_dc_supported)
+        return;
+
+    for (i = 1; i < EC_MAX_PORTS; i++) {
+        next = slave->ports[i].next_slave;
+        if (!next)
+            continue;
+        next_dc = ec_slave_find_next_dc_slave(next);
+        if (!next_dc)
+            continue;
+
+        rtt = slave->ports[i].receive_time - slave->ports[i - 1].receive_time;
+        next_rtt_sum = ec_slave_calc_rtt_sum(next_dc);
+
+        slave->ports[i].delay_to_next_dc = (rtt - next_rtt_sum) / 2; // FIXME
+        next_dc->ports[0].delay_to_next_dc = (rtt - next_rtt_sum) / 2;
+
+#if 0
+        EC_DBG("delay %u:%u rtt=%u next_rtt_sum=%u delay=%u\n",
+                slave->ring_position, i, rtt, next_rtt_sum,
+                slave->ports[i].delay_to_next_dc);
+#endif
+    }
+}
+
+/*****************************************************************************/
+
+/** Calculates the bus topology; recursion function.
+ */
+void ec_slave_calc_transition_delays_rec(
+        ec_slave_t *slave, /**< Current slave. */
+        uint32_t *delay /**< Sum of delays. */
+		)
+{
+    unsigned int i;
+    ec_slave_t *next, *next_dc;
+
+#if 0
+    EC_DBG("%u: %u\n", slave->ring_position, *delay);
+#endif
+
+    slave->transition_delay = *delay;
+
+    for (i = 1; i < EC_MAX_PORTS; i++) {
+        ec_slave_port_t *port = &slave->ports[i];
+        next = port->next_slave;
+        if (!next)
+            continue;
+        next_dc = ec_slave_find_next_dc_slave(next);
+        if (!next_dc)
+            continue;
+
+        *delay = *delay + port->delay_to_next_dc;
+#if 0
+        EC_DBG("%u:%u %u\n", slave->ring_position, i, *delay);
+#endif
+        ec_slave_calc_transition_delays_rec(next_dc, delay);
+    }
+
+    *delay = *delay + slave->ports[0].delay_to_next_dc;
+}
+
+/*****************************************************************************/
--- a/master/slave.h	Wed Apr 29 14:03:01 2009 +0000
+++ b/master/slave.h	Thu Apr 30 14:12:47 2009 +0000
@@ -48,6 +48,20 @@
 
 /*****************************************************************************/
 
+/** Slave port.
+ */
+typedef struct {
+    ec_slave_port_desc_t desc; /**< Port descriptors. */
+    ec_slave_port_link_t link; /**< Port link status. */
+    ec_slave_t *next_slave; /**< Connected slaves. */
+    uint32_t receive_time; /**< Port receive times for delay
+                                            measurement. */
+    uint32_t delay_to_next_dc; /**< Delay to next slave with DC support behind
+                                 this port [ns]. */
+} ec_slave_port_t;
+
+/*****************************************************************************/
+
 /** Slave information interface data.
  */
 typedef struct {
@@ -102,6 +116,8 @@
     uint16_t ring_position; /**< Ring position. */
     uint16_t station_address; /**< Configured station address. */
 
+    ec_slave_port_t ports[EC_MAX_PORTS]; /**< Ports. */
+
     // configuration
     ec_slave_config_t *config; /**< Current configuration. */
     ec_slave_state_t requested_state; /**< Requested application state. */
@@ -119,19 +135,14 @@
     uint16_t base_build; /**< Build number. */
     uint8_t base_fmmu_count; /**< Number of supported FMMUs. */
     uint8_t base_sync_count; /**< Number of supported sync managers. */
-    ec_slave_port_desc_t base_ports[EC_MAX_PORTS]; /**< Port descriptors. */
     uint8_t base_fmmu_bit_operation; /**< FMMU bit operation is supported. */
     uint8_t base_dc_supported; /**< Distributed clocks are supported. */
     ec_slave_dc_range_t base_dc_range; /**< DC range. */
     uint8_t has_dc_system_time; /**< The slave supports the DC system time
                                   register. Otherwise it can only be used for
                                   delay measurement. */
-    uint32_t dc_receive_times[EC_MAX_PORTS]; /**< Port receive times for delay
-                                               measurement. */
-
-    // data link status
-    ec_slave_port_t ports[EC_MAX_PORTS]; /**< Port link status. */
-    ec_slave_t *next_slave[EC_MAX_PORTS]; /**< Connected slaves. */
+    uint32_t transition_delay; /**< DC transition delay (from reference
+                                 clock). */
 
     // SII
     uint16_t *sii_words; /**< Complete SII image. */
@@ -175,6 +186,9 @@
 const ec_pdo_t *ec_slave_find_pdo(const ec_slave_t *, uint16_t);
 void ec_slave_attach_pdo_names(ec_slave_t *);
 
+void ec_slave_calc_port_delays(ec_slave_t *);
+void ec_slave_calc_transition_delays_rec(ec_slave_t *, uint32_t *);
+
 /*****************************************************************************/
 
 #endif
--- a/tool/CommandGraph.cpp	Wed Apr 29 14:03:01 2009 +0000
+++ b/tool/CommandGraph.cpp	Thu Apr 30 14:12:47 2009 +0000
@@ -72,7 +72,6 @@
     SlaveVector slaves;
     ec_ioctl_slave_t slave;
     SlaveVector::const_iterator si;
-    string font("fontname=\"Helvetica\"");
     map<int, string> portMedia;
     map<int, string>::const_iterator mi;
     map<int, int> mediaWeights;
@@ -102,51 +101,84 @@
         << endl
         << "strict graph bus {" << endl
         << "    rankdir=\"LR\"" << endl
+        << "    ranksep=0.8" << endl
+        << "    nodesep=0.8" << endl
+        << "    node [fontname=\"Helvetica\"]" << endl
+        << "    edge [fontname=\"Helvetica\",fontsize=\"10\"]" << endl
         << endl
-        << "    master [" << font << ",label=\"EtherCAT\\nMaster\"]" << endl;
+        << "    master [label=\"EtherCAT\\nMaster\"]" << endl;
 
     if (slaves.size()) {
-        cout << "    master -- slave0 [" << font;
+        cout << "    master -- slave0"; 
+        mi = portMedia.find(slaves.front().ports[0].desc);
+        if (mi != portMedia.end())
+            cout << "[label=\"" << mi->second << "\"]";
 
-        mi = portMedia.find(slaves.front().port_descs[0]);
-        if (mi != portMedia.end())
-            cout << ",label=\"" << mi->second << "\"";
-
-        cout << "]" << endl;
+        cout << endl;
     }
     cout << endl;
 
     for (si = slaves.begin(); si != slaves.end(); si++) {
-	    cout << "    slave" << si->position << " [" << font <<
-            ",shape=\"box\",label=\"" << si->position;
+	    cout << "    slave" << si->position << " [shape=\"box\""
+            << ",label=\"" << si->position;
         if (string(si->order).size())
             cout << "\\n" << si->order;
+        if (si->dc_supported) {
+            cout << "\\nDC: ";
+            if (si->has_dc_system_time) {
+                switch (si->dc_range) {
+                    case EC_DC_32:
+                        cout << "32 bit";
+                        break;
+                    case EC_DC_64:
+                        cout << "64 bit";
+                        break;
+                    default:
+                        break;
+                }
+            } else {
+                cout << "Delay meas.";
+            }
+            cout << "\\nDelay: " << si->transition_delay << " ns";
+        }
         cout << "\"]" << endl;
 
         for (i = 1; i < EC_MAX_PORTS; i++) {
-            if (si->next_slave[i] == 0xffff)
+            uint16_t next_pos = si->ports[i].next_slave;
+            ec_ioctl_slave_t *next = NULL;
+
+            if (next_pos == 0xffff)
                 continue;
 
+            if (next_pos < slaves.size()) {
+                next = &slaves[next_pos];
+            } else {
+                cerr << "Invalid next slave pointer." << endl;
+            }
+
             cout << "    slave" << si->position << " -- "
-                << "slave" << si->next_slave[i] << " [" << font << ","
-                << "taillabel=\"" << i << "\"";
+                << "slave" << next_pos << " [taillabel=\"" << i;
 
-            mi = portMedia.find(si->port_descs[i]);
-            if (mi == portMedia.end()) {
+            if (si->dc_supported) {
+                cout << " [" << si->ports[i].delay_to_next_dc << "]";
+            }
+            cout << "\",headlabel=\"0";
+
+            if (next && next->dc_supported) {
+                cout << " [" << next->ports[0].delay_to_next_dc << "]";
+            }
+            cout << "\"";
+
+            mi = portMedia.find(si->ports[i].desc);
+            if (mi == portMedia.end() && next) {
                 /* Try medium of next-hop slave. */
-                unsigned int pos = si->next_slave[i];
-                if (pos < slaves.size()) {
-                    ec_ioctl_slave_t *next = &slaves[pos];
-                    mi = portMedia.find(next->port_descs[0]);
-                } else {
-                    cerr << "Invalid next slave pointer." << endl;
-                }
+                mi = portMedia.find(next->ports[0].desc);
             }
             
             if (mi != portMedia.end())
                 cout << ",label=\"" << mi->second << "\"";
 
-            wi = mediaWeights.find(si->port_descs[i]);
+            wi = mediaWeights.find(si->ports[i].desc);
             if (wi != mediaWeights.end())
                 cout << ",weight=\"" << wi->second << "\"";
             
--- a/tool/CommandSlaves.cpp	Wed Apr 29 14:03:01 2009 +0000
+++ b/tool/CommandSlaves.cpp	Thu Apr 30 14:12:47 2009 +0000
@@ -262,18 +262,20 @@
             } else {
                 cout << "yes, delay measurement only" << endl;
             }
+            cout << "  DC transition delay: "
+                << si->transition_delay << " ns" << endl;
         } else {
             cout << "no" << endl;
         }
 
         cout << "Port  Type  Link  Loop    Signal  NextSlave";
         if (si->dc_supported)
-            cout << "  RxTime      Diff";
+            cout << "  RxTime [ns]  Diff [ns]   NextDc [ns]";
         cout << endl;
             
         for (i = 0; i < EC_MAX_PORTS; i++) {
             cout << "   " << i << "  " << setfill(' ') << left << setw(4);
-            switch (si->port_descs[i]) {
+            switch (si->ports[i].desc) {
                 case EC_PORT_NOT_IMPLEMENTED:
                     cout << "N/A";
                     break;
@@ -291,29 +293,35 @@
             }
 
             cout << "  " << setw(4)
-                << (si->ports[i].dl_link ? "up" : "down")
+                << (si->ports[i].link.link_up ? "up" : "down")
                 << "  " << setw(6)
-                << (si->ports[i].dl_loop ? "closed" : "open")
+                << (si->ports[i].link.loop_closed ? "closed" : "open")
                 << "  " << setw(6)
-                << (si->ports[i].dl_signal ? "yes" : "no")
+                << (si->ports[i].link.signal_detected ? "yes" : "no")
                 << "  " << setw(9) << right;
 
-            if (si->next_slave[i] != 0xffff) {
-                cout << dec << si->next_slave[i];
+            if (si->ports[i].next_slave != 0xffff) {
+                cout << dec << si->ports[i].next_slave;
             } else {
                 cout << "-";
             }
             
             if (si->dc_supported) {
-                cout << "  " << setw(10) << right;
-                if (si->ports[i].dl_signal) {
-                    cout << dec << si->dc_receive_times[i];
+                cout << "  " << setw(11) << right;
+                if (!si->ports[i].link.loop_closed) {
+                    cout << dec << si->ports[i].receive_time;
                 } else {
                     cout << "-";
                 }
                 cout << "  " << setw(10);
-                if (si->ports[i].dl_signal) {
-                    cout << si->dc_receive_times[i] - si->dc_receive_times[0];
+                if (!si->ports[i].link.loop_closed) {
+                    cout << si->ports[i].receive_time - si->ports[0].receive_time;
+                } else {
+                    cout << "-";
+                }
+                cout << "  " << setw(10);
+                if (!si->ports[i].link.loop_closed) {
+                    cout << si->ports[i].delay_to_next_dc;
                 } else {
                     cout << "-";
                 }