# 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:

## 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.
> 
- 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.

- 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

# 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

## Typical Bus Timing
The following diagram gives detailed information about the timing of the system:

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
### 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…”
> 
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)”.
> 
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:

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

Diagram 2: Drift in ppm (part per million)

Diagram 3: Controller error in nanoseconds

Diagram 4: Controller error in steady state in nanoseconds

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 depending on target HW and SW. |
| LinkLayerRefClock | Bus Shift using Link Layer clock. Special HW needed. |
| MasterRefClock | Bus Shift excluding reference clock controlling. Lowers CPU usages, but very high timer accuracy needed. |
| DCX | Synchronization of two or more EtherCAT® segments by a bridge device. Only available with Feature Pack 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 [-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 []] [-dcmlog]
The parameters are as follows:
### -f
Path to ENI file
### -t