# index.html.md

# EtherCAT® Master Stack Class A


# dc.html.md

# Synchronization with Distributed Clocks (DC)

DC clock synchronization enables all EtherCAT® devices (MainDevice and SubDevices) to share the same EtherCAT® System Time.

A “DC-SubDevice” is defined as a SubDevice that shall be synchronized by means of distributed clocks.
During network start-up several steps have to be performed by the EC-Master to set-up a consistent time base in all DC-SubDevices:

- Initial propagation delay measurement and compensation (ETG.8000)
- Offset compensation (ETG.8000)
- Set start time (ETG.8000)
- After network start-up: continuous drift compensation (ETG.8000)
- The MainDevice must synchronize itself on the reference clock (ETG.1020) -> DCM

Reference:

- ETG.1000.3 and ETG.1000.4
- ETG.1020 -> Synchronization
- ETG.8000 -> Distributed Clocks


# dc_api.html.md

# Programmer’s Guide

## emDcConfigure

### static EC_T_DWORD ecatDcConfigure(const [EC_T_DC_CONFIGURE](dc_api.html.md#_CPPv417EC_T_DC_CONFIGURE) \*pDcConfigure)

### EC_T_DWORD emDcConfigure(EC_T_DWORD dwInstanceID, const [EC_T_DC_CONFIGURE](dc_api.html.md#_CPPv417EC_T_DC_CONFIGURE) \*pDcConfigure)

Configure the distributed clocks. 

* Set the DC synchronization settling time ([ms]).
* Set the DC slave limit for the wire or’ed clock deviation value. This value determines whether the slave clocks are synchronized or not.
* Configure the ARMW burst frames to compensate the static deviations of the clock speeds.

* **Parameters:**
  * **dwInstanceID** – [in] Instance ID (Multiple EtherCAT Network Support) 
  * **pDcConfigure** – [in] Configuration parameter a pointer to a structure of type [EC_T_DC_CONFIGURE](dc_api.html.md#d4/df5/struct_e_c___t___d_c___c_o_n_f_i_g_u_r_e)
* **Returns:**
  EC_E_NOERROR or error code 

### struct EC_T_DC_CONFIGURE

### Public Members

### EC_T_DWORD dwClntId

[in] Reserved 

### EC_T_DWORD dwTimeout

[in] Timeout [ms] for the DC initialization in which time offsets and propagation delays are evaluated ( default:  12 sec   ) 

### EC_T_DWORD dwDevLimit

[in] Maximum permissible deviation of the individual slave clock and the DC reference clock. The maximum deviation is determined by wire or’ed the deviations of the individual slave clocks with one another. The check against the limit is only active if “Sync Window Monitoring” is set in the configuration tool (EC Engineer), which generates a BRD command to read the slave register 0x092C in every cycle. The limit is calculated as follows:

2^n - 1 ns, e.g. a dwDevLimit of 4 corresponds to 14 ns.


 A value of 0 disables the “Sync Window Monitoring” ( default:  2^10 - 1 = 1023 ns   ) 

### EC_T_DWORD dwSettleTime

[in] Settle time [ms]. At the beginning of the synchronization the slave clocks oscillate strongly. To prevent multiple in-sync and out-of-sync notifications from being generated, a settling time can be set in which no notifications are generated ( default:  1000 msec   ). 

### EC_T_DWORD dwTotalBurstLength

[in] Overall amount of burst frames sent ( default:  10000   ) 

### EC_T_DWORD dwBurstBulk

[in] Amount of burst frames per cycle during initialization burst ( default:  12   ) 

### EC_T_BOOL bBulkInLinkLayer

[in] If EC_TRUE, bulk is realized by link layer, otherwise by master. The MAC needs to support the frame repeating function. In this case the link layer will repeat the DC burst frames itself, reducing the hardware accesses of the master to the MAC. 

### EC_T_BOOL bAcycDistributionDisabled

[in] If EC_TRUE, acyclic distribution is disabled 

### EC_T_DWORD dwDcStartTimeGrid

[in] Time grid [ns] to align DC start time. With the help of the grid, several EtherCAT networks can be synchronized without a random shift value between the SYNC signals. 

### EC_T_BOOL bDcInitBeforeSlaveStateChange

[in] If EC_TRUE, DC is initialized before slaves state change to PREOP 

### EC_T_DWORD dwReserved[4]

[in/out] Reserved 

#### SEE ALSO
Chapter “Drift Compensation” of the ETG Document “ESC Datasheet Section 1 - Technology”

## emDcIsEnabled

### static EC_T_DWORD ecatDcIsEnabled(EC_T_BOOL \*pbDcIsEnabled)

### EC_T_DWORD emDcIsEnabled(EC_T_DWORD dwInstanceID, EC_T_BOOL \*pbDcIsEnabled)

Determines if DC is enabled and used. 

* **Parameters:**
  * **dwInstanceID** – [in] Instance ID (Multiple EtherCAT Network Support) 
  * **pbDcIsEnabled** – [out] EC_TRUE if DC is enabled 
* **Returns:**
  EC_E_NOERROR or error code 

## emGetBusTime

### static EC_T_DWORD ecatGetBusTime(EC_T_UINT64 \*pqwBusTime)

### EC_T_DWORD emGetBusTime(EC_T_DWORD dwInstanceID, EC_T_UINT64 \*pqwBusTime)

This function returns the actual bus time in nanoseconds. 

* **Parameters:**
  * **dwInstanceID** – [in] Instance ID (Multiple EtherCAT Network Support) 
  * **pqwBusTime** – [out] Bus time [ns] 
* **Returns:**
  EC_E_NOERROR or error code 

## emDcContDelayCompEnable

### static EC_T_DWORD ecatDcContDelayCompEnable(EC_T_VOID)

### EC_T_DWORD emDcContDelayCompEnable(EC_T_DWORD dwInstanceID)

Enable the continuous propagation delay compensation. 

Calling this function will generate a propagation delay measurement every 30s. The result of the measurement is used to correct the propagation delay values on the bus.

* **Parameters:**
  **dwInstanceID** – [in] Instance ID (Multiple EtherCAT Network Support) 
* **Returns:**
  EC_E_NOERROR or error code 

## emDcContDelayCompDisable

### static EC_T_DWORD ecatDcContDelayCompDisable(EC_T_VOID)

### EC_T_DWORD emDcContDelayCompDisable(EC_T_DWORD dwInstanceID)

Disable the continuous propagation delay compensation. 

* **Parameters:**
  **dwInstanceID** – [in] Instance ID (Multiple EtherCAT Network Support) 
* **Returns:**
  EC_E_NOERROR or error code 

## emIoCtl - EC_IOCTL_DC_SLV_SYNC_STATUS_GET

### EC_IOCTL_DC_SLV_SYNC_STATUS_GET

Get the last generated emNotify - EC_NOTIFY_DC_SLV_SYNC notification. 

* **Parameters:**
  * **pbyInBuf** – [in] Should be set to EC_NULL 
  * **dwInBufSize** – [in] Should be set to 0 
  * **pbyOutBuf** – [out] Pointer to [EC_T_DC_SYNC_NTFY_DESC](dc_api.html.md#dc/dc4/struct_e_c___t___d_c___s_y_n_c___n_t_f_y___d_e_s_c) data type 
  * **dwOutBufSize** – [in] Size of the output buffer in bytes 
  * **pdwNumOutData** – [out] Pointer to EC_T_DWORD. Amount of bytes written to the output buffer pbyOutBuf 
* **Returns:**
  EC_E_NOERROR or error code 

#### SEE ALSO
- [emNotify - EC_NOTIFY_DC_SLV_SYNC](dc_api.html.md#emnotify-ec-notify-dc-slv-sync) describes [`EC_T_DC_SYNC_NTFY_DESC`](dc_api.html.md#_CPPv422EC_T_DC_SYNC_NTFY_DESC)
- `emIoCtl()` in the [EC-Master Class B](https://developer.acontis.com/ec-master#manuals)  documentation

## emIoCtl - EC_IOCTL_DC_SETSYNCSTARTOFFSET

### EC_IOCTL_DC_SETSYNCSTARTOFFSET

Set the safety offset applied to the “set DC start time” InitCmd during the PS transition. 

* **Parameters:**
  * **pbyInBuf** – [in] Pointer to [EC_T_DC_STARTCYCSAFETY_DESC](dc_api.html.md#d8/d1f/struct_e_c___t___d_c___s_t_a_r_t_c_y_c_s_a_f_e_t_y___d_e_s_c) data type 
  * **dwInBufSize** – [in] Size of the input buffer provided at pbyInBuf in bytes 
  * **pbyOutBuf** – [out] Should be set to EC_NULL 
  * **dwOutBufSize** – [in] Should be set to 0 
  * **pdwNumOutData** – [out] Should be set to EC_NULL 
* **Returns:**
  EC_E_NOERROR or error code 

### struct EC_T_DC_STARTCYCSAFETY_DESC

### Public Members

### EC_T_DWORD dwStartCycSafetyLo

[in] Start SYNC Cyc Safety [ns] Lower 32 Bit 

### EC_T_DWORD dwStartCycSafetyHi

[in] Start SYNC Cyc Safety [ns] Upper 32 Bit 

Default: 50000000ns

#### SEE ALSO
`emIoCtl()` in the [EC-Master Class B](https://developer.acontis.com/ec-master#manuals)  documentation

## emIoCtl - EC_IOCTL_DC_FIRST_DC_SLV_AS_REF_CLOCK

### EC_IOCTL_DC_FIRST_DC_SLV_AS_REF_CLOCK

Enable or disable the usage of the first DC slave on bus overriding the configured reference clock. 

* **Parameters:**
  * **pbyInBuf** – [in] Pointer to EC_T_BOOL. EC_FALSE: disable, EC_TRUE: enable 
  * **dwInBufSize** – [in] Size of the input buffer provided at pbyInBuf in bytes 
  * **pbyOutBuf** – [out] Should be set to EC_NULL 
  * **dwOutBufSize** – [in] Should be set to 0 
  * **pdwNumOutData** – [out] Should be set to EC_NULL 
* **Returns:**
  EC_E_NOERROR or error code 

## emFindInpVarByName - “Inputs.BusTime”

The DC system time (written to ESC register 0x0910) is part of the process data with name “Inputs.BusTime”.

### static EC_T_DWORD ecatFindInpVarByName(const EC_T_CHAR \*szVariableName, EC_T_PROCESS_VAR_INFO \*pProcessVarInfoEntry)

### EC_T_DWORD emFindInpVarByName(EC_T_DWORD dwInstanceID, const EC_T_CHAR \*szVariableName, EC_T_PROCESS_VAR_INFO \*pProcessVarInfoEntry)

#### SEE ALSO
- [`emFindInpVarByName()`](dc_api.html.md#_CPPv418emFindInpVarByName10EC_T_DWORDPK9EC_T_CHARP21EC_T_PROCESS_VAR_INFO) in the [EC-Master Class B](https://developer.acontis.com/ec-master#manuals)  documentation
- `emIoCtl()` in the [EC-Master Class B](https://developer.acontis.com/ec-master#manuals)  documentation

## emIoCtl - EC_IOCTL_DC_ENABLE_ALL_DC_SLV

### EC_IOCTL_DC_ENABLE_ALL_DC_SLV

Enable or disable the usage of DC at all supporting slaves on bus overriding the configured settings. Perhaps [EC_IOCTL_DC_FIRST_DC_SLV_AS_REF_CLOCK](dc_api.html.md#d0/d35/_ec_io_ctl_8h_1a6cc6b13eabe68dd89ac8824bd0812ccd) is necessary to set the reference clock at an allowed position. 

* **Parameters:**
  * **pbyInBuf** – [in] Pointer to EC_T_BOOL. EC_FALSE: disable, EC_TRUE: enable 
  * **dwInBufSize** – [in] Size of the input buffer provided at pbyInBuf in bytes 
  * **pbyOutBuf** – [out] Should be set to EC_NULL 
  * **dwOutBufSize** – [in] Should be set to 0 
  * **pdwNumOutData** – [out] Should be set to EC_NULL 
* **Returns:**
  EC_E_NOERROR or error code 

#### SEE ALSO
`emIoCtl()` in the [EC-Master Class B](https://developer.acontis.com/ec-master#manuals)  documentation

## emNotify - EC_NOTIFY_REFCLOCK_PRESENCE

Distributed clocks reference clock presence notification. It will be received before [emNotify - EC_NOTIFY_DC_SLV_SYNC](dc_api.html.md#emnotify-ec-notify-dc-slv-sync) as soon as reference clock was found on bus or removed from bus.

This notification is disabled by default.

**emNotify - EC_NOTIFY_REFCLOCK_PRESENCE**
: **Parameter**
  : * `pbyInBuf`: [in] Pointer to notification descriptor EC_T_REFCLOCK_PRESENCE_NTFY_DESC
    * `dwInBufSize`: [in] sizeof(EC_T_REFCLOCK_PRESENCE_NTFY_DESC)
    * `pbyOutBuf`: [out] Should be set to EC_NULL
    * `dwOutBufSize`: [in] Should be set to 0
    * `pdwNumOutData`: [out] Should be set to EC_NULL

### struct EC_T_REFCLOCK_PRESENCE_NTFY_DESC

### Public Members

### EC_T_BOOL bPresent

[in] Reference clock present 

### EC_T_SLAVE_PROP SlaveProp

[in] Slave properties 

#### SEE ALSO
- emIoCtl - EC_IOCTL_SET_NOTIFICATION_ENABLED in the [EC-Master Class B](https://developer.acontis.com/ec-master#manuals) documentation for how to control the activation
- `emIoCtl()` in the [EC-Master Class B](https://developer.acontis.com/ec-master#manuals)  documentation

## emNotify - EC_NOTIFY_DC_STATUS

Distributed clocks status notification. It will be received after [emNotify - EC_NOTIFY_DC_SLV_SYNC](dc_api.html.md#emnotify-ec-notify-dc-slv-sync) as soon as DC is initialized or topology change was done. After topology was changed it may be received without [emNotify - EC_NOTIFY_DC_SLV_SYNC](dc_api.html.md#emnotify-ec-notify-dc-slv-sync) if SubDevices did not get out of sync.

If EC_E_NOERROR is returned and window monitoring is enabled, all SubDevices are in SYNC.

**emNotify - EC_NOTIFY_DC_STATUS**
: **Parameter**
  : * `pbyInBuf`: [in] Pointer to EC_T_DWORD (EC_E_NOERROR on success, Error code otherwise)
    * `dwInBufSize`: [in] sizeof(EC_T_DWORD)
    * `pbyOutBuf`: [out] Should be set to EC_NULL
    * `dwOutBufSize`: [in] Should be set to 0
    * `pdwNumOutData`: [out] Should be set to EC_NULL

#### SEE ALSO
- emIoCtl - EC_IOCTL_SET_NOTIFICATION_ENABLED in the [EC-Master Class B](https://developer.acontis.com/ec-master#manuals) documentation for how to control the deactivation
- `emIoCtl()` in the [EC-Master Class B](https://developer.acontis.com/ec-master#manuals)  documentation

## emNotify - EC_NOTIFY_DC_SLV_SYNC

DC SubDevice synchronization notification. Every time the SubDevices are coming in sync or getting out of sync the clients will be notified here.
The notification is raised in any case if any DC SubDevices are configured. SubDevices can only be out of sync if [Sync Window Monitoring](dc_technical.html.md#sync-window-monitoring) is enabled otherwise they are considered in sync.

This notification is enabled by default.

**emNotify - EC_NOTIFY_DC_SLV_SYNC**
: **Parameter**
  : * `pbyInBuf`: [in] Pointer to notification descriptor EC_T_DC_SYNC_NTFY_DESC
    * `dwInBufSize`: [in] sizeof(EC_T_DC_SYNC_NTFY_DESC)
    * `pbyOutBuf`: [out] Should be set to EC_NULL
    * `dwOutBufSize`: [in] Should be set to 0
    * `pdwNumOutData`: [out] Should be set to EC_NULL

### struct EC_T_DC_SYNC_NTFY_DESC

### Public Members

### EC_T_DWORD IsInSync

[in] EC_TRUE : Wire or’ed deviation value meets limit requirements. EC_FALSE: Wire or’ed deviation value does not meet limit requirements. The limit is set by [emDcConfigure()](dc_api.html.md#db/d74/_ec_master_api_8cpp_1aae993e04828f39a77feb3523bb4ef239). 

### EC_T_DWORD IsNegative

[in] EC_TRUE : Deviation value is negative, EC_FALSE: Deviation value is positive 

### EC_T_DWORD dwDeviation

[in] Wire or’ed deviation value [ns] in case of in sync 

### EC_T_SLAVE_PROP SlaveProp

[in] Slave properties in case of out of sync 

#### SEE ALSO
- [`emDcConfigure()`](dc_api.html.md#_CPPv413emDcConfigure10EC_T_DWORDPK17EC_T_DC_CONFIGURE)
- emIoCtl - EC_IOCTL_SET_NOTIFICATION_ENABLED in the [EC-Master Class B](https://developer.acontis.com/ec-master#manuals) documentation for how to control the deactivation
- `emIoCtl()` in the [EC-Master Class B](https://developer.acontis.com/ec-master#manuals)  documentation


# dc_config.html.md

# Configuration with EC-Engineer

The EC-Engineer automatically chooses the DC settings for SubDevices as proposed by the device’s vendor and sets DCM mode to bus shift.

The settings can be changed according to the project’s needs. DC options are part of the EC-Engineer Expert Mode. The Expert Mode can be activated from the menu:

![EC-Engineer menu showing how to activate Expert Mode for accessing Distributed Clocks configuration options](../Media/EC-Engineer.png)

## Distributed Clocks MainDevice settings (Expert)

In this tab, the user can change distributed clocks related settings. The tab is only available if the configuration contains SubDevices.

> ![EC-Engineer Expert Mode Distributed Clocks MainDevice settings tab showing Reference Clock, MainDevice Shift, Bus Shift, and Sync Window Monitoring options](../Media/EC-Engineer2.png)
- Reference Clock Name: Name of the reference clock. By default, this is the first SubDevice with DC support.
- MainDevice Shift: The reference clock controls the MainDevice time
- Bus Shift: The MainDevice time controls the reference clock. A command will be inserted in the Cyclic frame to adjust the reference clock system time (write to register 0x0910).
- Continuous Propagation Compensation: A command will be inserted in the Cyclic frame which allows the EtherCAT® MainDevice to measure and compensate the propagation delay time by time.
- Sync Window Monitoring: A command will be inserted in the cyclic frame to read the ESC registers 0x092C. If this is selected the MainDevice will throw a notification.
- Show 64Bit System Time: MainDevice supports SubDevices with 32bit and 64bit system time register (0x0910). If this is selected he will interpret it as 64bit system time.

#### NOTE
If no reference clock is displayed, please ensure at least one SubDevice in the network is configured for DC operation mode [Distributed Clocks SubDevice settings (Expert)](dc_config.html.md#distributed-clocks-subdevice-settings-expert)

## Distributed Clocks SubDevice settings (Expert)

In this tab, the user can change distributed clocks related settings. The tab is only available if the vendor of the device specified the DC usage. Sync signal generation or DC latching is selected automatically according to Operation Mode.

![EC-Engineer Expert Mode Distributed Clocks SubDevice settings tab showing DC operation modes and Sync Unit Cycle configuration](../Media/Device_Editor.png)
- Operation Mode: Selectable DC operation modes. The modes cannot be edited.
- Sync Unit Cycle: Base interval in microseconds which will be used from MainDevice. The Sync Units can be activated and configured to generate signals.

#### SEE ALSO
SyncSignal Generation in the ET1100 Datasheet for time describing

![Examples of Various SYNC0/SYNC1 Cycle Time Combinations](../Media/Sync_Units.png)


# dc_technical.html.md

# Technical overview

## Support SubDevices and topologies

EC-Master supports all currently existing SubDevice types and possible topologies:

- SubDevices with 32 bit or 64 bit system time register (0x0910)
- Reference Clock with 32 bit or 64 bit system time register (0x0910)
- Reference Clock as first SubDevice (auto increment address 0) or in the middle. Only SubDevices behind the reference clock could be synchronized.
- Drift compensation with 32 bit or 64 bit ARMW command in the cyclic frame
- Topologies: Line, Daisy chain, Daisy chain with drop lines, tree structure, star topology with EK1122 junctions

![EtherCAT network topology diagrams showing line, daisy chain, tree structure, and star topologies supported for Distributed Clocks with a DC Reference Clock and the SubDevices following it.](../Media/DC_Topologie.png)

## Typical Bus Timing

The following diagram gives detailed information about the timing of the system:

![Timing diagram showing the relationship between the MainDevice Job Task cycle, EtherCAT frame send time, SYNC signals, propagation delay for Distributed Clocks and the data flow of Input and Output values.](../Media/Typical_Bus_Timing.png)

The timing of the Job Task must be accurate if the system must operate in real-time.
It can be disturbed by jitter or drift. Small jitter values are irrelevant, but high jitter values can compromise process data exchange by causing delays that violate strict cycle deadlines.
Timing disturbances may have various causes on the MainDevice system like hardware or software delays which are beyond the EC-Master stack’s control.
However, different DCM modes and parameters are available to compensate the natural drift of MainDevice and SubDevices and to fine-tune synchronization.

## Implementation Details

The generation of Sync impulses is started after initialization and sending of 10000 FRMW frames which are required to bring SubDevices initially into sync.
After this FRMW generation a grace period of 50 ms under real-time OSes is used and 500 ms using Windows is configured before the start of cyclic operations of SubDevices,
which causes the Sync impulse generation to be delayed by this grace period.

Initial propagation delay measurement and offset compensation commands are not part of the ENI file. The ARMW command for drift compensation is part of the cyclic frame.

## SubDevices in sync

SubDevices in sync means that the system time difference of all DC SubDevices does not exceed a configured limit. Out of sync is detected individually and immediately for each SubDevice.

The MainDevice awaits that the SubDevices are in sync in MainDevice state transition INIT->PREOP. Therefore the MainDevice state transition may timeout if the SubDevices do not get in sync.

Due to technology the SubDevices are always getting in sync as long as there is no error in setup. In order to detect system time difference exceeding, [Sync Window Monitoring](dc_technical.html.md#sync-window-monitoring) is used.

## Sync Window Monitoring

Sync Window Monitoring must be explicitly enabled in the configuration.

The system time difference exceeding detection in Sync Window Monitoring uses a deviation limit and a settle time and is issued continuously with configured commands (Ado 0x092C) in cyclic frames.

In sync is assumed if there is no violation of the system time difference limit (for all DC SubDevices!) detected within the settle time.
The deviation limit (dwDevLimit) and settle time (dwSettleTime) can be configured using [`emDcConfigure()`](dc_api.html.md#_CPPv413emDcConfigure10EC_T_DWORDPK17EC_T_DC_CONFIGURE).

If the configuration only contains the cyclic commands for SAFE-OP or OP (e.g. ET9000) the MainDevice queues acyclic datagrams (Ado 0x092C) for system time difference measurement.

If there are less than two DC SubDevices on the bus (e.g. if the reference clock is the only DC SubDevices on bus), Sync Window Monitoring is skipped. If it is skipped, because it is not enabled in configuration or there are less than two DC SubDevices on bus, SubDevices are immediately considered in sync.


# dcm.html.md

# MainDevice Synchronization (DCM)

Applications like motion control need process update every cycle in real time and it is unacceptable to miss data of a cycle or that the SubDevices handle the same process data values twice within a cycle.

The Distributed Clocks MasterShift Synchronization (DCM) provides controller mechanisms to synchronize the timing at the MainDevice to the SYNC pulses triggering the SubDevice firmware.
With DCM, the process data update at the MainDevice and the SubDevices is in correlated timely behavior.

Features:

- PI drift controller
- Automatic timer adjustment error determination (I controller)


# dcm_api.html.md

# Programmer’s Guide

## emDcmConfigure

### static EC_T_DWORD ecatDcmConfigure(const [EC_T_DCM_CONFIG](dcm_api.html.md#_CPPv415EC_T_DCM_CONFIG) \*pDcmConfig, EC_T_DWORD dwInSyncTimeout)

### EC_T_DWORD emDcmConfigure(EC_T_DWORD dwInstanceID, const [EC_T_DCM_CONFIG](dcm_api.html.md#_CPPv415EC_T_DCM_CONFIG) \*pDcmConfig, EC_T_DWORD dwInSyncTimeout)

Configure DC master synchronization. 

* **Parameters:**
  * **dwInstanceID** – [in] Instance ID (Multiple EtherCAT Network Support) 
  * **pDcmConfig** – [in] Configuration information, a pointer to a structure of type [EC_T_DCM_CONFIG](dcm_api.html.md#d1/d72/struct_e_c___t___d_c_m___c_o_n_f_i_g)
  * **dwInSyncTimeout** – [in] Currently not implemented 
* **Returns:**
  EC_E_NOERROR or error code 

### struct EC_T_DCM_CONFIG

### Public Members

### [EC_T_DCM_MODE](dcm_api.html.md#_CPPv413EC_T_DCM_MODE) eMode

[in] DCM mode 

### [EC_T_DCM_CONFIG_BUSSHIFT](dcm_api.html.md#_CPPv424EC_T_DCM_CONFIG_BUSSHIFT) BusShift

[in] BusShift configuration. Valid if eMode is set to eDcmMode_BusShift. 

### [EC_T_DCM_CONFIG_MASTERSHIFT](dcm_api.html.md#_CPPv427EC_T_DCM_CONFIG_MASTERSHIFT) MasterShift

[in] MasterShift configuration. Valid if eMode is set to eDcmMode_MasterShift. 

### [EC_T_DCM_CONFIG_LINKLAYERREFCLOCK](dcm_api.html.md#_CPPv433EC_T_DCM_CONFIG_LINKLAYERREFCLOCK) LinkLayerRefClock

[in] LinkLayerRefClock configuration. Valid if eMode is set to eDcmMode_LinkLayerRefClock. 

### [EC_T_DCM_CONFIG_MASTERREFCLOCK](dcm_api.html.md#_CPPv430EC_T_DCM_CONFIG_MASTERREFCLOCK) MasterRefClock

[in] MasterRefClock configuration. Valid if eMode is set to eDcmMode_MasterRefClock. 

### [EC_T_DCM_CONFIG_DCX](dcm_api.html.md#_CPPv419EC_T_DCM_CONFIG_DCX) Dcx

[in] DCX configuration. Valid if eMode is set to eDcmMode_Dcx. 

### enum EC_T_DCM_MODE

*Values:*

### enumerator eDcmMode_Off

DCM disabled 

### enumerator eDcmMode_BusShift

DCM BusShift mode 

### enumerator eDcmMode_MasterShift

DCM MasterShift mode 

### enumerator eDcmMode_LinkLayerRefClock

DCM LinkLayer Ref Clock mode 

### enumerator eDcmMode_MasterRefClock

DCM Master Ref Clock mode 

### enumerator eDcmMode_Dcx

DCM DCX External synchronization mode 

### enumerator eDcmMode_MasterShiftByApp

DCM MasterShift controlled by application mode 

### struct EC_T_DCM_CONFIG_BUSSHIFT

### Public Members

### EC_T_INT nCtlSetVal

[in] Controller set value [ns]. This is the time distance between the cyclic frame send time and the DC base on bus (SYNC0 if shift is zero). 

### EC_T_INT nCtlGain

[in] Proportional gain in ppt (part per thousand). Default is value 2. A value of 0 sets the default value. 

### EC_T_INT nCtlDriftErrorGain

[in] Multiplier for drift error. Default value is 3. A value of 0 sets the default value. 

### EC_T_INT nMaxValidVal

[in] Error inputs above this value are considered invalid. If error input prediction is valid then the difference between the error input and the expected value is taken. Default value is 3000. A value of 0 sets the default value. 

### EC_T_BOOL bLogEnabled

[in] If set to EC_TRUE, logging information are generated and can be got by calling [emDcmGetLog()](dcm_api.html.md#db/d74/_ec_master_api_8cpp_1af51eeb22aae1bd0ceaeb6b764632186d)

### EC_T_DWORD dwInSyncLimit

[in] Limit [ns] for InSync monitoring. Default value is 20% of the cycle time. A value of 0 sets the default value. 

### EC_T_DWORD dwInSyncSettleTime

[in] Settle time [ms] for InSync monitoring. Default value is 1500ms. A value of 0 sets the default value. 

### EC_T_BOOL bCtlOff

[in] If set to EC_TRUE, control loop is disabled. Combined with bLogEnabled, it makes possible to analyze the natural drift between the stack cycle and the reference clock. 

### EC_T_BOOL bUseDcLoopCtlStdValues

[in] If set to EC_TRUE, the values of ESC DC time loop control register 0x930 and 0x934 are not changed by master. This could increase the time it takes to get the InSync. Use only if there are problems with the reference clock to get InSync. 

### EC_T_DWORD dwInSyncStartDelayCycle

[in] Delay time [ms] before InSync monitoring start 

### EC_T_VOID \*pGetTimeElapsedSinceCycleStartContext

[in] Optional context for the pfnGetTimeElapsedSinceCycleStart function, will be passed as first parameter to this function/static method 

### EC_PF_DC_GETTIMEELAPSEDSINCECYCLESTART pfnGetTimeElapsedSinceCycleStart

[in] Setting this function enables synchronising the DC SYNC0 to the CycleStart instead of the time frame send. DC SYNC0 is therefore related to the CycleStart instead of the time frame send. Function must return EC_E_NOERROR to work. If 0 (nullptr, EC_NULL) EC_E_NOTSUPPORTED will be returned on attempt to call. 

### struct EC_T_DCM_CONFIG_MASTERSHIFT

### Public Members

### EC_T_INT nCtlSetVal

[in] Controller set value [ns]. This is the time distance between the cyclic frame send time and the DC base on bus (SYNC0 if shift is zero). 

### EC_T_INT nCtlGain

[in] Proportional gain in ppt (part per thousand). Default is value 2. A value of 0 sets the default value. 

### EC_T_INT nCtlDriftErrorGain

[in] Multiplier for drift error. Default value is 3. A value of 0 sets the default value. 

### EC_T_INT nMaxValidVal

[in] Error inputs above this value are considered invalid. If error input prediction is valid then the difference between the error input and the expected value is taken. Default value is 3000. A value of 0 sets the default value. 

### EC_T_BOOL bLogEnabled

[in] If set to EC_TRUE, logging information are generated and can be got by calling [emDcmGetLog()](dcm_api.html.md#db/d74/_ec_master_api_8cpp_1af51eeb22aae1bd0ceaeb6b764632186d)

### EC_T_DWORD dwInSyncLimit

[in] Limit [ns] for InSync monitoring. Default value is 20% of the cycle time. A value of 0 sets the default value. 

### EC_T_DWORD dwInSyncSettleTime

[in] Settle time [ms] for InSync monitoring. Default value is 1500ms. A value of 0 sets the default value. 

### EC_T_BOOL bCtlOff

[in] If set to EC_TRUE, control loop is disabled. Combined with bLogEnabled, it makes possible to analyze the natural drift between the stack cycle and the reference clock. Also it provides reading of current adjustment value using emDcmGetAdjust function. 

### EC_T_DWORD dwInSyncStartDelayCycle

[in] Delay time [ms] before InSync monitoring start 

### [EC_T_DC_STARTTIME_CB_DESC](dcm_api.html.md#_CPPv425EC_T_DC_STARTTIME_CB_DESC) DcStartTimeCallbackDesc

[in] If not null, DC start time calculated by application, otherwise by master. See also [EC_T_DC_STARTTIME_CB_DESC](dcm_api.html.md#db/d6b/struct_e_c___t___d_c___s_t_a_r_t_t_i_m_e___c_b___d_e_s_c). Shift value configured in ENI will still be applied. 

### EC_T_VOID \*pGetTimeElapsedSinceCycleStartContext

[in] Optional context for the pfnGetTimeElapsedSinceCycleStart function, will be passed as first parameter to this function/static method 

### EC_PF_DC_GETTIMEELAPSEDSINCECYCLESTART pfnGetTimeElapsedSinceCycleStart

[in] Setting this function enables synchronising the DC SYNC0 to the CycleStart instead of the time frame send. DC SYNC0 is therefore related to the CycleStart instead of the time frame send. Function must return EC_E_NOERROR to work. If 0 (nullptr, EC_NULL) EC_E_NOTSUPPORTED will be returned on attempt to call. 

### EC_T_VOID \*pAdjustCycleTimeContext

[in] Optional context for the pfnAdjustCycleTime function, will be passed as first parameter to this function/static method 

### EC_PF_DC_ADJUSTCYCLETIME pfnAdjustCycleTime

[in] Mandatory function to adjust the cycle time of the master. The master must adjust its cycle time by the passed amount to be in sync with the slaves. If 0 (nullptr, EC_NULL) MasterShift will not work. 

### struct EC_T_DCM_CONFIG_LINKLAYERREFCLOCK

### Public Members

### EC_T_INT nCtlSetVal

[in] Controller set value [ns]. This is the time distance between the cyclic frame send time and the DC base on bus (SYNC0 if shift is zero). 

### EC_T_BOOL bLogEnabled

[in] If set to EC_TRUE, logging information are generated and can be got by calling [emDcmGetLog()](dcm_api.html.md#db/d74/_ec_master_api_8cpp_1af51eeb22aae1bd0ceaeb6b764632186d)

### EC_T_DWORD dwInSyncLimit

[in] Limit [ns] for InSync monitoring. Default value is 20% of the cycle time. A value of 0 sets the default value. 

### EC_T_DWORD dwInSyncSettleTime

[in] Settle time [ms] for InSync monitoring. Default value is 1500ms. A value of 0 sets the default value. 

### [EC_T_DC_STARTTIME_CB_DESC](dcm_api.html.md#_CPPv425EC_T_DC_STARTTIME_CB_DESC) DcStartTimeCallbackDesc

[in] If not null, DC start time calculated by application, otherwise by master. See also [EC_T_DC_STARTTIME_CB_DESC](dcm_api.html.md#db/d6b/struct_e_c___t___d_c___s_t_a_r_t_t_i_m_e___c_b___d_e_s_c). Shift value configured in ENI will still be applied. 

### struct EC_T_DCM_CONFIG_MASTERREFCLOCK

### Public Members

### EC_T_INT nCtlSetVal

[in] Controller set value [ns]. This is the time distance between the cyclic frame send time and the DC base on bus (SYNC0 if shift is zero). 

### EC_T_BOOL bLogEnabled

[in] If set to EC_TRUE, logging information are generated and can be got by calling [emDcmGetLog()](dcm_api.html.md#db/d74/_ec_master_api_8cpp_1af51eeb22aae1bd0ceaeb6b764632186d)

### EC_T_DWORD dwInSyncLimit

[in] Limit [ns] for InSync monitoring. Default value is 20% of the cycle time. A value of 0 sets the default value. 

### EC_T_DWORD dwInSyncSettleTime

[in] Settle time [ms] for InSync monitoring. Default value is 1500ms. A value of 0 sets the default value. 

### EC_T_VOID \*pGetHostTimeContext

[in] Optional context for the pfnGetHostTime function, will be passed as first parameter to this function/static method 

### EC_PF_DC_GETHOSTTIME pfnGetHostTime

[in] Mandatory function to offer the host time for the MasterRefClock mode. This time will be distributed to the slaves. If 0 (nullptr, EC_NULL) MasterRefClock mode will not work. 

### [EC_T_DC_STARTTIME_CB_DESC](dcm_api.html.md#_CPPv425EC_T_DC_STARTTIME_CB_DESC) DcStartTimeCallbackDesc

[in] If not null, DC start time calculated by application, otherwise by master. See also [EC_T_DC_STARTTIME_CB_DESC](dcm_api.html.md#db/d6b/struct_e_c___t___d_c___s_t_a_r_t_t_i_m_e___c_b___d_e_s_c). Shift value configured in ENI will still be applied. 

### struct EC_T_DCM_CONFIG_DCX

Contains the configuration information for the DCX external synchronization mode.

#### SEE ALSO
Feature Pack “External Synchronization” for further details.

### struct EC_T_DC_STARTTIME_CB_DESC

### Public Members

### EC_T_VOID \*pvContext

[in] Arbitrarily application-defined parameter passed to pfnCallback 

### [EC_PF_DC_STARTTIME_CB](dcm_api.html.md#_CPPv421EC_PF_DC_STARTTIME_CB) pfnCallback

[in] DC start time callback function pointer. If not EC_NULL, DC start time calculated by application, otherwise by master. 

### typedef EC_T_DWORD (\*EC_PF_DC_STARTTIME_CB)(EC_T_VOID \*pvContext, EC_T_WORD wSlaveFixedAddr, EC_T_UINT64 \*pqwDcStartTime)

EC-Master requests DC start time for every single slave from a given callback DcStartTimeCallbackDesc with slave station address as input parameter. The slave specific DC start time value will be passed directly to the slave without modifications by master. This means no other values like nCtlSetVal will be added. Shift value configured in ENI will still be applied. 

* **Param pvContext:**
  **[in]** Arbitrarily application-defined parameter passed to callback 
* **Param wSlaveFixedAddr:**
  **[in]** Slave fixed address 
* **Param pqwDcStartTime:**
  **[out]** DC start time for specific slave 
* **Return:**
  EC_E_NOERROR or error code 

## emDcmGetStatus

### static EC_T_DWORD ecatDcmGetStatus(EC_T_DWORD \*pdwErrorCode, EC_T_INT \*pnDiffCur, EC_T_INT \*pnDiffAvg, EC_T_INT \*pnDiffMax)

### EC_T_DWORD emDcmGetStatus(EC_T_DWORD dwInstanceID, EC_T_DWORD \*pdwErrorCode, EC_T_INT \*pnDiffCur, EC_T_INT \*pnDiffAvg, EC_T_INT \*pnDiffMax)

Get DC master synchronization controller status. 

* **Parameters:**
  * **dwInstanceID** – [in] Instance ID (Multiple EtherCAT Network Support) 
  * **pdwErrorCode** – [out] Pointer to current error code of the DCM controller. Possible values are:
    * EC_E_NOTREADY DCM control loop is not running
    * EC_E_BUSY DCM control loop is running and try to get InSync
    * [DCM_E_MAX_CTL_ERROR_EXCEED](dcm_api.html.md#d1/d4e/group___e_c___e_r_r_o_r___c_o_d_e_s___d_c_m_1gae592ec678390813a6827181ca605a405) Set if the controller error exceeds the InSyncLimit
    * [DCM_E_DRIFT_TO_HIGH](dcm_api.html.md#d1/d4e/group___e_c___e_r_r_o_r___c_o_d_e_s___d_c_m_1ga75f02c5a05fd656ae76ecd422dd3168f) DCM control loop not able to compensate drift. Drift above 600ppm 
  * **pnDiffCur** – [out] Pointer to current difference between set value and actual value of controller in nanoseconds 
  * **pnDiffAvg** – [out] Pointer to average difference between set value and actual value of controller in nanoseconds 
  * **pnDiffMax** – [out] Pointer to maximum difference between set value and actual value of controller in nanoseconds 
* **Returns:**
  * EC_E_NOERROR if status retrieval was successful
  * EC_E_NOTSUPPORTED if the DC feature is not supported/switched off. EC-Master stack has to be compiled with DC support see “define INCLUDE_DC_SUPPORT”.
  * EC_NULL does not appear in normal flow, if EC_NULL is returned we are in a very exceptional case where m_poDcm == NULL (SW error detection) 

## emDcmResetStatus

### static EC_T_DWORD ecatDcmResetStatus(EC_T_VOID)

### EC_T_DWORD emDcmResetStatus(EC_T_DWORD dwInstanceID)

Reset DC master synchronization controller status, average and maximum difference between set value and actual value. 

* **Parameters:**
  **dwInstanceID** – [in] Instance ID (Multiple EtherCAT Network Support) 
* **Returns:**
  EC_E_NOERROR or error code 

## emDcmGetBusShiftConfigured

### static EC_T_DWORD ecatDcmGetBusShiftConfigured(EC_T_BOOL \*pbBusShiftConfigured)

### EC_T_DWORD emDcmGetBusShiftConfigured(EC_T_DWORD dwInstanceID, EC_T_BOOL \*pbBusShiftConfigured)

Determines if DCM Bus Shift is configured/possible in configuration (ENI file). 

* **Parameters:**
  * **dwInstanceID** – [in] Instance ID (Multiple EtherCAT Network Support) 
  * **pbBusShiftConfigured** – [out] EC_TRUE if DCM bus shift mode is supported by the current configuration 
* **Returns:**
  EC_E_NOERROR or error code 

## emDcmGetLog

### static EC_T_DWORD ecatDcmGetLog(EC_T_CHAR \*\*pszLog)

### EC_T_DWORD emDcmGetLog(EC_T_DWORD dwInstanceID, EC_T_CHAR \*\*pszLog)

Get logging information from the DCM controller. 

This function returns non-zero pointer only if bLogEnabled was set to EC_TRUE in [EC_T_DCM_CONFIG](dcm_api.html.md#d1/d72/struct_e_c___t___d_c_m___c_o_n_f_i_g).

* **Parameters:**
  * **dwInstanceID** – [in] Instance ID (Multiple EtherCAT Network Support) 
  * **pszLog** – [out] Pointer to a string containing the current logging information 
* **Returns:**
  EC_E_NOERROR or error code 

#### SEE ALSO
[Controller adjustment](dcm_technical_controller-adjustment.html.md#controller-adjustment) for content description of pszLog

## emIoCtl - EC_IOCTL_DCM_GET_LOG

### EC_IOCTL_DCM_GET_LOG

Get logging information from the DCM controller. 

* **Parameters:**
  * **pbyInBuf** – [in] Should be set to EC_NULL 
  * **dwInBufSize** – [in] Should be set to 0 
  * **pbyOutBuf** – [out] Pointer to struct [EC_T_DCM_LOG](dcm_api.html.md#dd/d2b/struct_e_c___t___d_c_m___l_o_g)
  * **dwOutBufSize** – [in] Size of the output buffer in bytes 
  * **pdwNumOutData** – [out] Pointer to EC_T_DWORD. Amount of bytes written to the output buffer pbyOutBuf 
* **Returns:**
  EC_E_NOERROR or error code 

### struct EC_T_DCM_LOG

### Public Members

### EC_T_DWORD dwMsecCounter

[out] Current MsecCounter 

### EC_T_INT nCtlSetVal

[out] Configured controller set val [ns] 

### EC_T_UINT64 qwBusTime

[out] Current BusTime 

### EC_T_INT nCtlErrorNsec

[out] Current controller error [ns] 

### EC_T_INT nDrift

[out] Current calculated drift [ppm] 

### EC_T_DWORD dwErrorCode

[out] Last returned error code by controller 

### EC_T_BOOL bDcmInSync

[out] EC_TRUE if DCM is in sync, EC_FALSE if out of sync 

### EC_T_BOOL bDcInSync

[out] EC_TRUE if DC is in sync, EC_FALSE if out of sync 

### EC_T_UINT64 qwDcStartTime

[out] Last used DC StartTime 

### EC_T_INT nSystemTimeDifference

[out] Last read System Time Difference (ESC register 0x092C) 

#### SEE ALSO
`emIoCtl()` in the [EC-Master Class B](https://developer.acontis.com/ec-master#manuals)  documentation

## emDcmShowStatus

### static EC_T_DWORD ecatDcmShowStatus(EC_T_VOID)

### EC_T_DWORD emDcmShowStatus(EC_T_DWORD dwInstanceID)

Show DC master synchronization status as DbgMsg (for development purposes only). 

* **Parameters:**
  **dwInstanceID** – [in] Instance ID (Multiple EtherCAT Network Support) 
* **Returns:**
  EC_E_NOERROR or error code 

## emDcmGetAdjust

### static EC_T_DWORD ecatDcmGetAdjust(EC_T_INT \*pnAdjustPermil)

### EC_T_DWORD emDcmGetAdjust(EC_T_DWORD dwInstanceID, EC_T_INT \*pnAdjustPermil)

Returns the current adjustment value for the timer. 

bCtlOff must be set to EC_TRUE in [EC_T_DCM_CONFIG](dcm_api.html.md#d1/d72/struct_e_c___t___d_c_m___c_o_n_f_i_g) to enable external adjustment.

* **Parameters:**
  * **dwInstanceID** – [in] Instance ID (Multiple EtherCAT Network Support) 
  * **pnAdjustPermil** – [out] Current adjustment value of the timer 
* **Returns:**
  EC_E_NOERROR or error code 

## DCM specific error codes

<!-- -*- mode: rst -*- -->

<a id="d1-d4e-group-e-c-e-r-r-o-r-c-o-d-e-s-d-c-m"></a>

### DCM_E_ERROR

0x981201C0: Unspecific DCM Error 

### DCM_E_NOTINITIALIZED

0x981201C1: Not initialized 

### DCM_E_MAX_CTL_ERROR_EXCEED

0x981201C2: DCM controller - synchronization out of limit 

### DCM_E_NOMEMORY

0x981201C3: Not enough memory 

### DCM_E_INVALID_HWLAYER

0x981201C4: Hardware layer - (BSP) invalid 

### DCM_E_TIMER_MODIFY_ERROR

0x981201C5: Hardware layer - error modifying timer 

### DCM_E_TIMER_NOT_RUNNING

0x981201C6: Hardware layer - timer not running 

### DCM_E_WRONG_CPU

0x981201C7: Hardware layer - function called on wrong CPU 

### DCM_E_INVALID_SYNC_PERIOD

0x981201C8: Invalid DC sync period length (invalid clock master?) 

### DCM_E_INVALID_SETVAL

0x981201C9: DCM controller SetVal too small 

### DCM_E_DRIFT_TO_HIGH

0x981201CA: DCM controller - Drift between local timer and ref clock to high 

### DCM_E_BUS_CYCLE_WRONG

0x981201CB: DCM controller - Bus cycle time (dwBusCycleTimeUsec) doesn’t match real cycle 

### DCX_E_NO_EXT_CLOCK

0x981201CC: DCX controller - No external synchronization clock found 

### DCM_E_INVALID_DATA

0x981201CD: DCM controller - Invalid data 

## Notifications

At startup the MainDevice raises the notifications [emNotify - EC_NOTIFY_DC_SLV_SYNC](dc_api.html.md#emnotify-ec-notify-dc-slv-sync), [emNotify - EC_NOTIFY_DC_STATUS](dc_api.html.md#emnotify-ec-notify-dc-status) and [emNotify - EC_NOTIFY_DCM_SYNC](dcm_api.html.md#emnotify-ec-notify-dcm-sync) at MainDevice state transition from INIT to PREOP.

The order is typically as follows ( [emNotify - EC_NOTIFY_DCM_SYNC](dcm_api.html.md#emnotify-ec-notify-dcm-sync) may be before or after reaching PREOP):

EC_NOTIFY_STATECHANGED(INIT)[…]

EC_NOTIFY_DC_SLV_SYNC […]

EC_NOTIFY_DC_STATUS […]

[EC_NOTIFY_DCM_SYNC] […]

EC_NOTIFY_STATECHANGED(PREOP) […]

[EC_NOTIFY_DCM_SYNC] […]

EC_NOTIFY_STATECHANGED(SAFEOP) […]

EC_NOTIFY_STATECHANGED(OP) […]

## emNotify - EC_NOTIFY_DCM_SYNC

DCM InSync notification.

This notification is enabled by default.

**emNotify - EC_NOTIFY_DCM_SYNC**
: **Parameter**
  : * `pbyInBuf`: [in] Pointer to notification descriptor EC_T_DCM_SYNC_NTFY_DESC
    * `dwInBufSize`: [in] sizeof(EC_T_DCM_SYNC_NTFY_DESC)
    * `pbyOutBuf`: [out] Should be set to EC_NULL
    * `dwOutBufSize`: [in] Should be set to 0
    * `pdwNumOutData`: [out] Should be set to EC_NULL

### struct EC_T_DCM_SYNC_NTFY_DESC

### Public Members

### EC_T_DWORD IsInSync

[in] EC_TRUE as long as time of master and reference clock are in sync. False if the InSyncLimit from the bus shift configuration is exceeded. 

### EC_T_INT nCtlErrorNsecCur

[in] Current difference [ns] between set value and actual value of controller 

### EC_T_INT nCtlErrorNsecAvg

[in] Average difference [ns] between set value and actual value of controller 

### EC_T_INT nCtlErrorNsecMax

[in] Maximum difference [ns] between set value and actual value of controller 

#### SEE ALSO
emIoCtl - EC_IOCTL_SET_NOTIFICATION_ENABLED in the [EC-Master Class B](https://developer.acontis.com/ec-master#manuals) documentation for controlling the deactivation


# dcm_config.html.md

# Configuration with ET9000

Since version 2.11.0 of the EtherCAT® Configurator from Beckhoff explicitly setup whether the DC time shall be controlled by the EC-Master or not.

To create a DCM capable configuration, please accomplish the following steps.

1. Scan the EtherCAT® Bus
2. Select the EtherCAT® network adapter and press the button “Advanced Settings…”
   > ![ET9000 EtherCAT Configurator showing the Advanced Settings button for the selected EtherCAT network adapter](../Media/EC_Configurator1.png)
3. In the open dialog please select “Distributed Clocks” on the left column. Then de-select “Automatic DC Mode Selection” and select the option “DC Time controlled by TwinCAT Time (SubDevice Mode)”.
   > ![ET9000 Distributed Clocks Advanced Settings dialog with Automatic DC Mode Selection disabled and DC Time controlled by TwinCAT Time selected](../Media/EC_Configurator2.png)
4. Now the DC time can be controlled by the EC-Master.
   > #### NOTE
   > Don’t forget to enable DC for the SubDevices.


# dcm_example.html.md

# Code example

The example program EcMasterDemoDc demonstrates, in contrast to EcMasterDemo, how to programmatically configure DCM parameters and how the application can generate the DCM log.

### **DCM Configuration (optional)**

```cpp
/* initialize the master */
dwRes = ecatInitMaster(&oInitParms);

/* configure the master */
dwRes = ecatConfigureNetwork(eCnfType_Filename, (EC_T_BYTE*)"ENI.xml", (EC_T_DWORD)OsStrlen("ENI.xml"));

/* register client */
EC_T_REGISTERRESULTS oRegisterClientResults;
OsMemset(&oRegisterClientResults, 0, sizeof(EC_T_REGISTERRESULTS));
dwRes = ecatRegisterClient(EcMasterNotifyCallback, pAppContext, &oRegisterClientResults);

/* configure DC */
EC_T_DC_CONFIGURE oDcConfigure;
OsMemset(&oDcConfigure, 0, sizeof(EC_T_DC_CONFIGURE));
oDcConfigure.dwTimeout = ETHERCAT_DC_TIMEOUT;
dwRes = ecatDcConfigure(&oDcConfigure);

/* configure DCM Bus Shift */
EC_T_DCM_CONFIG oDcmConfig;
OsMemset(&oDcmConfig, 0, sizeof(EC_T_DCM_CONFIG));
oDcmConfig.eMode = eDcmMode_BusShift;
oDcmConfig.u.BusShift.nCtlSetVal = DCM_CONTROLLER_SETVAL_NANOSEC;
oDcmConfig.u.BusShift.bLogEnabled = EC_TRUE;
dwRes = ecatDcmConfigure(&oDcmConfig, 0 /* dwInSyncTimeout */);

/* set EtherCAT devices to OPERATIONAL state */
dwRes = ecatSetMasterState(ETHERCAT_STATE_CHANGE_TIMEOUT, eEcatState_OP);
```

#### SEE ALSO
[`emDcConfigure()`](dc_api.html.md#_CPPv413emDcConfigure10EC_T_DWORDPK17EC_T_DC_CONFIGURE)

#### SEE ALSO
[`emDcmConfigure()`](dcm_api.html.md#_CPPv414emDcmConfigure10EC_T_DWORDPK15EC_T_DCM_CONFIG10EC_T_DWORD)

### **DCM Log (optional)**

```cpp
do
{
    /* wait for next cycle (event from scheduler task) */
    /* ... */

    /* process all received frames (read new input values) */
    dwRes = ecatExecJob(eUsrJob_ProcessAllRxFrames, &oJobParms);

    /* ... */

    EC_T_CHAR* szDcmLog = EC_NULL;
    ecatDcmGetLog(&szDcmLog);
    if (EC_NULL != szDcmLog)
    {
        ((CAtEmLogging*)pEcLogContext)->LogDcm(szDcmLog);
    }

    /* ... */
} while (!pAppContext->bJobTaskShutdown);
```

#### SEE ALSO
[`emDcmGetLog()`](dcm_api.html.md#_CPPv411emDcmGetLog10EC_T_DWORDPP9EC_T_CHAR)


# dcm_technical.html.md

# Technical overview

The ENI file contains predefined DCM configuration settings.
For example, the EC-Master selects the DCM Mode Bus Shift or DCM Mode MainDevice Shift based on the values specified in the ENI file.
Therefore, the application does not need to activate DCM explicitly via API.
However, some settings can still be modified programmatically after loading the ENI file.
For instance, the parameter “Controller set value” sets the position of the SYNC signals at the SubDevices in relation to the cyclic frame:

![Diagram showing the Controller set value parameter positioning SYNC signals at SubDevices relative to the cyclic frame for DCM Bus Shift mode](../Media/DCM_Topologie.png)

The parameter “Controller set value” (nCtlSetVal) cannot be derived from the ENI file. It is one of the parameters that can be set using emDcmConfigure().

The actual position of the SYNC signals at the SubDevices, relative to the cyclic frame, typically varies from cycle to cycle due to jitter in the application’s JobTask.

The example program EcMasterDemoDc demonstrates, in contrast to EcMasterDemo, how to programmatically configure DCM parameters and how the application can generate the DCM log.

The EtherCAT® technology provides sufficient diagnostic capabilities through WKC monitoring to detect communication issues.
However, for in-depth analysis, more detailed information, such as the DCM log, is required.
The DCM log can be used to evaluate drift control quality and measure jitter values.
To enable this, the application’s JobTask must cyclically retrieve the DCM status from the MainDevice.
This data should be written from a low-priority thread to avoid impacting real-time performance during diagnostics.


# dcm_technical_controller-adjustment.html.md

# Controller adjustment

To adjust the controller parameters the diagnostic values in file dcmlog0.0.csv can be used.
The generation of logging information can be enabled setting bLogEnabled to `EC_TRUE` with the function [`emDcmConfigure()`](dcm_api.html.md#_CPPv414emDcmConfigure10EC_T_DWORDPK15EC_T_DCM_CONFIG10EC_T_DWORD).

Controller log file description:

| Column name               | Description                                                                         |
|---------------------------|-------------------------------------------------------------------------------------|
| Time[ms]                  | Controller execution timestamp                                                      |
| SyncSetVal [ns]           | Controller set value (distance between frame send time and SYNC0)                   |
| BusTime [ns]              | System Time                                                                         |
| BusTimeOff                | System Time modulo Sync Cycle Time                                                  |
| CtlAdj [ns]               | Controller adjust value                                                             |
| CtlErr [ns]               | Controller error (EC_T_DCM_SYNC_NTFY_DESC.nCtlErrorNsecCur)                         |
| CtlErrFilt                | Filtered controller error                                                           |
| Drift [ppm]               | Drift between local clock and DC reference clock                                    |
| CtlErr [1/10 pmil]        | For internal use only                                                               |
| CtlOutSum                 | For internal use only                                                               |
| CtlOutTot                 | For internal use only                                                               |
| DCStartTime               | DC start time send to the SubDevices to activate their SYNC signals                 |
| DCMErrorCode              | Current error code of the DCM controller (same value as returned by emDcmGetStatus) |
| DCMInSync                 | Current InSync state of the DCM controller                                          |
| DCInSync                  | Current InSync state of the DC SubDevices                                           |
| SystemTimeDifference [ns] | Current system time difference of the DC SubDevice if monitoring is enabled         |

Log file analyze:
To understand how the controller values correlates the following table can help:

| Controller error   | Drift         | Reference-Clock   | Output            |
|--------------------|---------------|-------------------|-------------------|
| Positive           | Must decrease | Must run faster   | Double cycle time |
| Negative           | Must increase | Must run slower   | Half cycle time   |

The DCM Controller reacts if the controller error is positive or negative. E.g. on a positive controller error (CtlErr ) the drift is too high and has to be decreased. Therefore the controller will speed up the reference clock.

In some case the drift is too high (EcMasterDemoDc shows error messages) and cannot be balanced by the controller. This holds if the drift is higher than about 400ppm.

Diagram 1: Bus offset in nanoseconds

![DCM Diagram 1 showing bus offset in nanoseconds over time, illustrating the controller's ability to converge the reference clock to the target offset](../Media/DCM_Diagram1.png)

Diagram 2: Drift in ppm (part per million)

![DCM Diagram 2 showing drift in parts per million over time between the MainDevice local clock and the DC reference clock](../Media/DCM_Diagram2.png)

Diagram 3: Controller error in nanoseconds

![DCM Diagram 3 showing controller error in nanoseconds during initial synchronization phase](../Media/DCM_Diagram3.png)

Diagram 4: Controller error in steady state in nanoseconds

![DCM Diagram 4 showing controller error in nanoseconds in steady state after synchronization has stabilized](../Media/DCM_Diagram4.png)

Troubleshooting:

DCM BusShift needs a very deterministic and accurate time base.

The following statements have to be true:

- The timer input frequency must be determined with an accuracy greater than 600 ppm (333333 Hz vs 333000 Hz. E.g. at 1 ms, the cycle time must be between 999.400 µs and 1000.600 µs)
- The timer frequency must never change after the application start

On a PC platform the following settings have to be disabled in the BIOS. Be sure that these settings are really applied.

- System management interrupt
- Legacy USB support
- Intel C-STATE tech
- Intel Speedstep tech
- Spread Spectrum


# dcm_technical_dcm-in-sync.html.md

# DCM in sync

DCM in sync means that the synchronization between the send time of the cyclic frames and the system time of the reference clock was successful.

The MainDevice awaits that DCM is in sync in MainDevice state transition PREOP->SAFEOP. Therefore the MainDevice state transition may timeout if DCM does not get in sync.
Due to the MainDevice’s DC implementation, DCM may get in sync in transition INIT->PREOP.

In sync is assumed if there is no error reported from the DCM controller within the settle time or if there is no DC SubDevice connected.


# dcm_technical_dcm-modes.html.md

# DCM Modes

The following DCM Modes are available:

| Name              | Purpose                                                                                                                                  |
|-------------------|------------------------------------------------------------------------------------------------------------------------------------------|
| BusShift          | Synchronize SubDevices to MainDevice timer (Default)                                                                                     |
| MasterShift       | Synchronize MainDevice timer to SubDevice. Feasibility<br/>depending on target HW and SW.                                                |
| LinkLayerRefClock | Bus Shift using Link Layer clock. Special HW needed.                                                                                     |
| MasterRefClock    | Bus Shift excluding reference clock controlling.<br/>Lowers CPU usages, but very high timer accuracy needed.                             |
| DCX               | Synchronization of two or more EtherCAT® segments by a<br/>bridge device. Only available with Feature Pack<br/>External Synchronization. |

The Distributed Clocks MainDevice Synchronization (DCM) in Bus Shift mode adjusts the bus time register of the DC reference clock. All DC SubDevices converge to this time.
This mode is useful to synchronize multiple EtherCAT® networks or if it is not possible to adjust the timing of the MainDevice.

#### SEE ALSO
[`emDcmConfigure()`](dcm_api.html.md#_CPPv414emDcmConfigure10EC_T_DWORDPK15EC_T_DCM_CONFIG10EC_T_DWORD)


# dcm_technical_linklayerrefclock-mode.html.md

# DCM Linklayer Ref Clock mode

In this mode the Real-time Ethernet Driver should provide the time base for the cyclic frames. `EC_LINKIOCTL_GETTIME` will be called during the DC initialization to initialize the DC related registers of the DC SubDevices and during the SubDevice transition PREOP to SAFEOP to start the DC SYNC signals if needed.

`EC_LINKIOCTL_GETTIME` should return the current 64 bits value in nanoseconds of a time counter running continuously.

During the call to EcLinkSendFrame, the Real-time Ethernet Driver should insert the send time of the frame following the instruction given by `EC_T_LINK_FRAMEDESC::wTimestampOffset` and `EC_T_LINK_FRAMEDESC::wTimestampSize` of the parameter pLinkFrameDesc. A value of 0 means that no time stamp should be inserted.


# dcm_technical_masterrefclock-mode.html.md

# DCM MainDevice Ref Clock mode

The DCM MainDevice Ref Clock mode is similar to the bus shift mode, without its control loop. This reduces the CPU load and makes it a good alternative for low performance CPUs. Because of the missing control loop, the reaction time on disturbance is longer and the cycle must be very accurate.

The bus shift time must be enabled in the ENI file because it uses the same cyclic command to synchronize the EtherCAT® network with the MainDevice system.
This mode can be activated using [`emDcmConfigure()`](dcm_api.html.md#_CPPv414emDcmConfigure10EC_T_DWORDPK15EC_T_DCM_CONFIG10EC_T_DWORD).


# dcm_technical_mastershift-mode.html.md

# DCM MainDevice Shift mode

In this mode, the local time base will be adjusted to synchronize it with the network “bus time”. The following function pointers have to be implemented to enable the adjustment:

`EC_T_OS_PARMS::pfHwTimerGetInputFrequency`

`EC_T_OS_PARMS::pfHwTimerModifyInitialCount`

The MainDevice shift must not be enabled in the ENI file because it doesn’t need any cyclic command. This mode can be activated using [`emDcmConfigure()`](dcm_api.html.md#_CPPv414emDcmConfigure10EC_T_DWORDPK15EC_T_DCM_CONFIG10EC_T_DWORD).


# dcm_technical_sync-activation.html.md

# Sync signal activation

The sync signals are activated during transition PREOP - SAFEOP according to Init Command (Ado 0x0980, 0x0990, 0x09A0, 0x09A8).


# ecmasterdemodc.html.md

# Running EcMasterDemoDc

The EcMasterDemoDc is available “out of the box” for different operating systems. It is an EC-Master example application that handles the following tasks:

- Showing basic EtherCAT® communication
- MainDevice stack initialization into OPERATIONAL state
- DC and DCM configuration
- Process Data operations for e.g. Beckhoff EL2004, EL1004 and EL4132
- Periodic diagnosis task
- Periodic Job Task in polling mode
- Logging

Start the EcMasterDemoDc from the command line to put the EtherCAT® network into operation. At least a Real-time Ethernet Driver must be specified.

```doscon
> EcMasterDemoDc -ndis 192.168.157.2 1 -f eni.xml -t 0 -v 3 -dcmmode busshift
```

## Command line parameters

### EcMasterDemoDc             <LinkLayer> [-f ENI-FileName] [-t time] [-b cycle time] [-a affinity] [-v level] [-perf [level]] [-log prefix [msg cnt]] [-lic key] [-oem key] [-fingerprint method] [-maxbusslaves cnt] [-flash address] [-printvars] [-sp [port]] [-ctloff] [-rec [prefix [frame cnt]]] [-junctionred] [-dcmmode <mode> [<synctocyclestart>]] [-dcmlog]

The parameters are as follows:

### -f <ENI-FileName>

Path to ENI file

### -t <time>

Running duration [ms]. When the time expires the demo application exits completely.

* **<time>:**
  Time [ms], 0 = forever (default = 120000)

### -b <cycle time>

Specifies the bus cycle time. Defaults to 1000 µs (1 ms).

* **<cycle time>:**
  Bus cycle time in µsec

### -a <affinity>

The CPU affinity specifies which CPU the demo application ought to use.

* **<affinity>:**
  0 = first CPU, 1 = second, …

### -v <level>

The verbosity level specifies how much console output messages will be generated by the demo application. A high verbosity level leads to more messages.

* **<level>:**
  Verbosity level: 0=off (default), 1..n=more messages

### -perf [<level>]

Enable max. and average time measurement in µs for all EtherCAT® jobs (e.g. ProcessAllRxFrames).

* **<level>:**
  Depending on level the performance histogram can be activated as well.

### -log <prefix> [<msg cnt>]

Use given file name prefix for log files.

* **<prefix>:**
* **<msg cnt>:**
  Messages count for log buffer allocation

### -lic <key>

Set License key.

* **<key>:**
  License key string

### -oem <key>

Use OEM key

* **<key>:**
  64 bit OEM key.

### -fingerprint <method>

Read license fingerprint

* **<method>:**
  Fingerprint method

### -junctionred

Enable junction redundancy (automatic mode)

### -flash <address>

Flash outputs

* **<address>:**
  0=all, >0 = SubDevice station address

### -sp [<port>]

If platform has support for IP Sockets, this command-line option enables the Remote API Server to be started. The Remote API Server is going to listen on TCP Port 6000 (or port parameter if given) and is available for connecting Remote API Clients.

* **<port>:**
  RAS server port

### -rec [<prefix> [<frame cnt>]]

Packet capture file recording

* **<prefix>:**
  File name prefix
* **<frame cnt>:**
  Frame count for log buffer allocation

### -dcmmode <mode> [<synctocyclestart>]

Set DCM mode

* **<mode>:**
  off | busshift | mastershift | masterrefclock | linklayerrefclock
* **<synctocyclestart>:**
  Sync to cycle start: 0 = disabled (default), 1 = enabled

### -dcmlog

Enable DCM logging (default: disabled)

### -ctloff

Disable DCM control loop for diagnosis


