diff --git a/Projects/EFC_EcatDriver/.ccsproject b/Projects/EFC_EcatDriver/.ccsproject
new file mode 100644
index 0000000..0d4c64e
--- /dev/null
+++ b/Projects/EFC_EcatDriver/.ccsproject
@@ -0,0 +1,16 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/Projects/EFC_EcatDriver/.cproject b/Projects/EFC_EcatDriver/.cproject
new file mode 100644
index 0000000..0df1797
--- /dev/null
+++ b/Projects/EFC_EcatDriver/.cproject
@@ -0,0 +1,160 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/Projects/EFC_EcatDriver/.gitignore b/Projects/EFC_EcatDriver/.gitignore
new file mode 100644
index 0000000..c0f2758
--- /dev/null
+++ b/Projects/EFC_EcatDriver/.gitignore
@@ -0,0 +1,8 @@
+/Debug/
+/Release/
+
+/doc/*
+!/doc/.placeholder
+
+/.settings/
+
diff --git a/Projects/EFC_EcatDriver/.project b/Projects/EFC_EcatDriver/.project
new file mode 100644
index 0000000..e1f2106
--- /dev/null
+++ b/Projects/EFC_EcatDriver/.project
@@ -0,0 +1,27 @@
+
+
+ EFC_EcatDriver
+
+
+
+
+
+ org.eclipse.cdt.managedbuilder.core.genmakebuilder
+
+
+
+
+ org.eclipse.cdt.managedbuilder.core.ScannerConfigBuilder
+ full,incremental,
+
+
+
+
+
+ com.ti.ccstudio.core.ccsNature
+ org.eclipse.cdt.core.cnature
+ org.eclipse.cdt.managedbuilder.core.managedBuildNature
+ org.eclipse.cdt.core.ccnature
+ org.eclipse.cdt.managedbuilder.core.ScannerConfigNature
+
+
diff --git a/Projects/EFC_EcatDriver/Doxyfile b/Projects/EFC_EcatDriver/Doxyfile
new file mode 100644
index 0000000..d1e079b
--- /dev/null
+++ b/Projects/EFC_EcatDriver/Doxyfile
@@ -0,0 +1,2815 @@
+# Doxyfile 1.9.7
+
+# This file describes the settings to be used by the documentation system
+# doxygen (www.doxygen.org) for a project.
+#
+# All text after a double hash (##) is considered a comment and is placed in
+# front of the TAG it is preceding.
+#
+# All text after a single hash (#) is considered a comment and will be ignored.
+# The format is:
+# TAG = value [value, ...]
+# For lists, items can also be appended using:
+# TAG += value [value, ...]
+# Values that contain spaces should be placed between quotes (\" \").
+#
+# Note:
+#
+# Use doxygen to compare the used configuration file with the template
+# configuration file:
+# doxygen -x [configFile]
+# Use doxygen to compare the used configuration file with the template
+# configuration file without replacing the environment variables or CMake type
+# replacement variables:
+# doxygen -x_noenv [configFile]
+
+#---------------------------------------------------------------------------
+# Project related configuration options
+#---------------------------------------------------------------------------
+
+# This tag specifies the encoding used for all characters in the configuration
+# file that follow. The default is UTF-8 which is also the encoding used for all
+# text before the first occurrence of this tag. Doxygen uses libiconv (or the
+# iconv built into libc) for the transcoding. See
+# https://www.gnu.org/software/libiconv/ for the list of possible encodings.
+# The default value is: UTF-8.
+
+DOXYFILE_ENCODING = UTF-8
+
+# The PROJECT_NAME tag is a single word (or a sequence of words surrounded by
+# double-quotes, unless you are using Doxywizard) that should identify the
+# project for which the documentation is generated. This name is used in the
+# title of most generated pages and in a few other places.
+# The default value is: My Project.
+
+PROJECT_NAME = EFC_UsbDriver
+
+# The PROJECT_NUMBER tag can be used to enter a project or revision number. This
+# could be handy for archiving the generated documentation or if some version
+# control system is used.
+
+PROJECT_NUMBER = 0.1
+
+# Using the PROJECT_BRIEF tag one can provide an optional one line description
+# for a project that appears at the top of each page and should give viewer a
+# quick idea about the purpose of the project. Keep the description short.
+
+PROJECT_BRIEF = "Библиотека USB драйвера для ядра Cortex-M4 платформы TMS320F2838x"
+
+# With the PROJECT_LOGO tag one can specify a logo or an icon that is included
+# in the documentation. The maximum height of the logo should not exceed 55
+# pixels and the maximum width should not exceed 200 pixels. Doxygen will copy
+# the logo to the output directory.
+
+PROJECT_LOGO =
+
+# The OUTPUT_DIRECTORY tag is used to specify the (relative or absolute) path
+# into which the generated documentation will be written. If a relative path is
+# entered, it will be relative to the location where doxygen was started. If
+# left blank the current directory will be used.
+
+OUTPUT_DIRECTORY = ./doc
+
+# If the CREATE_SUBDIRS tag is set to YES then doxygen will create up to 4096
+# sub-directories (in 2 levels) under the output directory of each output format
+# and will distribute the generated files over these directories. Enabling this
+# option can be useful when feeding doxygen a huge amount of source files, where
+# putting all generated files in the same directory would otherwise causes
+# performance problems for the file system. Adapt CREATE_SUBDIRS_LEVEL to
+# control the number of sub-directories.
+# The default value is: NO.
+
+CREATE_SUBDIRS = NO
+
+# Controls the number of sub-directories that will be created when
+# CREATE_SUBDIRS tag is set to YES. Level 0 represents 16 directories, and every
+# level increment doubles the number of directories, resulting in 4096
+# directories at level 8 which is the default and also the maximum value. The
+# sub-directories are organized in 2 levels, the first level always has a fixed
+# number of 16 directories.
+# Minimum value: 0, maximum value: 8, default value: 8.
+# This tag requires that the tag CREATE_SUBDIRS is set to YES.
+
+CREATE_SUBDIRS_LEVEL = 8
+
+# If the ALLOW_UNICODE_NAMES tag is set to YES, doxygen will allow non-ASCII
+# characters to appear in the names of generated files. If set to NO, non-ASCII
+# characters will be escaped, for example _xE3_x81_x84 will be used for Unicode
+# U+3044.
+# The default value is: NO.
+
+ALLOW_UNICODE_NAMES = NO
+
+# The OUTPUT_LANGUAGE tag is used to specify the language in which all
+# documentation generated by doxygen is written. Doxygen will use this
+# information to generate all constant output in the proper language.
+# Possible values are: Afrikaans, Arabic, Armenian, Brazilian, Bulgarian,
+# Catalan, Chinese, Chinese-Traditional, Croatian, Czech, Danish, Dutch, English
+# (United States), Esperanto, Farsi (Persian), Finnish, French, German, Greek,
+# Hindi, Hungarian, Indonesian, Italian, Japanese, Japanese-en (Japanese with
+# English messages), Korean, Korean-en (Korean with English messages), Latvian,
+# Lithuanian, Macedonian, Norwegian, Persian (Farsi), Polish, Portuguese,
+# Romanian, Russian, Serbian, Serbian-Cyrillic, Slovak, Slovene, Spanish,
+# Swedish, Turkish, Ukrainian and Vietnamese.
+# The default value is: English.
+
+OUTPUT_LANGUAGE = Russian
+
+# If the BRIEF_MEMBER_DESC tag is set to YES, doxygen will include brief member
+# descriptions after the members that are listed in the file and class
+# documentation (similar to Javadoc). Set to NO to disable this.
+# The default value is: YES.
+
+BRIEF_MEMBER_DESC = YES
+
+# If the REPEAT_BRIEF tag is set to YES, doxygen will prepend the brief
+# description of a member or function before the detailed description
+#
+# Note: If both HIDE_UNDOC_MEMBERS and BRIEF_MEMBER_DESC are set to NO, the
+# brief descriptions will be completely suppressed.
+# The default value is: YES.
+
+REPEAT_BRIEF = YES
+
+# This tag implements a quasi-intelligent brief description abbreviator that is
+# used to form the text in various listings. Each string in this list, if found
+# as the leading text of the brief description, will be stripped from the text
+# and the result, after processing the whole list, is used as the annotated
+# text. Otherwise, the brief description is used as-is. If left blank, the
+# following values are used ($name is automatically replaced with the name of
+# the entity):The $name class, The $name widget, The $name file, is, provides,
+# specifies, contains, represents, a, an and the.
+
+ABBREVIATE_BRIEF = "The $name class" \
+ "The $name widget" \
+ "The $name file" \
+ is \
+ provides \
+ specifies \
+ contains \
+ represents \
+ a \
+ an \
+ the
+
+# If the ALWAYS_DETAILED_SEC and REPEAT_BRIEF tags are both set to YES then
+# doxygen will generate a detailed section even if there is only a brief
+# description.
+# The default value is: NO.
+
+ALWAYS_DETAILED_SEC = NO
+
+# If the INLINE_INHERITED_MEMB tag is set to YES, doxygen will show all
+# inherited members of a class in the documentation of that class as if those
+# members were ordinary class members. Constructors, destructors and assignment
+# operators of the base classes will not be shown.
+# The default value is: NO.
+
+INLINE_INHERITED_MEMB = NO
+
+# If the FULL_PATH_NAMES tag is set to YES, doxygen will prepend the full path
+# before files name in the file list and in the header files. If set to NO the
+# shortest path that makes the file name unique will be used
+# The default value is: YES.
+
+FULL_PATH_NAMES = YES
+
+# The STRIP_FROM_PATH tag can be used to strip a user-defined part of the path.
+# Stripping is only done if one of the specified strings matches the left-hand
+# part of the path. The tag can be used to show relative paths in the file list.
+# If left blank the directory from which doxygen is run is used as the path to
+# strip.
+#
+# Note that you can specify absolute paths here, but also relative paths, which
+# will be relative from the directory where doxygen is started.
+# This tag requires that the tag FULL_PATH_NAMES is set to YES.
+
+STRIP_FROM_PATH =
+
+# The STRIP_FROM_INC_PATH tag can be used to strip a user-defined part of the
+# path mentioned in the documentation of a class, which tells the reader which
+# header file to include in order to use a class. If left blank only the name of
+# the header file containing the class definition is used. Otherwise one should
+# specify the list of include paths that are normally passed to the compiler
+# using the -I flag.
+
+STRIP_FROM_INC_PATH =
+
+# If the SHORT_NAMES tag is set to YES, doxygen will generate much shorter (but
+# less readable) file names. This can be useful is your file systems doesn't
+# support long names like on DOS, Mac, or CD-ROM.
+# The default value is: NO.
+
+SHORT_NAMES = NO
+
+# If the JAVADOC_AUTOBRIEF tag is set to YES then doxygen will interpret the
+# first line (until the first dot) of a Javadoc-style comment as the brief
+# description. If set to NO, the Javadoc-style will behave just like regular Qt-
+# style comments (thus requiring an explicit @brief command for a brief
+# description.)
+# The default value is: NO.
+
+JAVADOC_AUTOBRIEF = NO
+
+# If the JAVADOC_BANNER tag is set to YES then doxygen will interpret a line
+# such as
+# /***************
+# as being the beginning of a Javadoc-style comment "banner". If set to NO, the
+# Javadoc-style will behave just like regular comments and it will not be
+# interpreted by doxygen.
+# The default value is: NO.
+
+JAVADOC_BANNER = NO
+
+# If the QT_AUTOBRIEF tag is set to YES then doxygen will interpret the first
+# line (until the first dot) of a Qt-style comment as the brief description. If
+# set to NO, the Qt-style will behave just like regular Qt-style comments (thus
+# requiring an explicit \brief command for a brief description.)
+# The default value is: NO.
+
+QT_AUTOBRIEF = NO
+
+# The MULTILINE_CPP_IS_BRIEF tag can be set to YES to make doxygen treat a
+# multi-line C++ special comment block (i.e. a block of //! or /// comments) as
+# a brief description. This used to be the default behavior. The new default is
+# to treat a multi-line C++ comment block as a detailed description. Set this
+# tag to YES if you prefer the old behavior instead.
+#
+# Note that setting this tag to YES also means that rational rose comments are
+# not recognized any more.
+# The default value is: NO.
+
+MULTILINE_CPP_IS_BRIEF = NO
+
+# By default Python docstrings are displayed as preformatted text and doxygen's
+# special commands cannot be used. By setting PYTHON_DOCSTRING to NO the
+# doxygen's special commands can be used and the contents of the docstring
+# documentation blocks is shown as doxygen documentation.
+# The default value is: YES.
+
+PYTHON_DOCSTRING = YES
+
+# If the INHERIT_DOCS tag is set to YES then an undocumented member inherits the
+# documentation from any documented member that it re-implements.
+# The default value is: YES.
+
+INHERIT_DOCS = YES
+
+# If the SEPARATE_MEMBER_PAGES tag is set to YES then doxygen will produce a new
+# page for each member. If set to NO, the documentation of a member will be part
+# of the file/class/namespace that contains it.
+# The default value is: NO.
+
+SEPARATE_MEMBER_PAGES = NO
+
+# The TAB_SIZE tag can be used to set the number of spaces in a tab. Doxygen
+# uses this value to replace tabs by spaces in code fragments.
+# Minimum value: 1, maximum value: 16, default value: 4.
+
+TAB_SIZE = 4
+
+# This tag can be used to specify a number of aliases that act as commands in
+# the documentation. An alias has the form:
+# name=value
+# For example adding
+# "sideeffect=@par Side Effects:^^"
+# will allow you to put the command \sideeffect (or @sideeffect) in the
+# documentation, which will result in a user-defined paragraph with heading
+# "Side Effects:". Note that you cannot put \n's in the value part of an alias
+# to insert newlines (in the resulting output). You can put ^^ in the value part
+# of an alias to insert a newline as if a physical newline was in the original
+# file. When you need a literal { or } or , in the value part of an alias you
+# have to escape them by means of a backslash (\), this can lead to conflicts
+# with the commands \{ and \} for these it is advised to use the version @{ and
+# @} or use a double escape (\\{ and \\})
+
+ALIASES =
+
+# Set the OPTIMIZE_OUTPUT_FOR_C tag to YES if your project consists of C sources
+# only. Doxygen will then generate output that is more tailored for C. For
+# instance, some of the names that are used will be different. The list of all
+# members will be omitted, etc.
+# The default value is: NO.
+
+OPTIMIZE_OUTPUT_FOR_C = YES
+
+# Set the OPTIMIZE_OUTPUT_JAVA tag to YES if your project consists of Java or
+# Python sources only. Doxygen will then generate output that is more tailored
+# for that language. For instance, namespaces will be presented as packages,
+# qualified scopes will look different, etc.
+# The default value is: NO.
+
+OPTIMIZE_OUTPUT_JAVA = NO
+
+# Set the OPTIMIZE_FOR_FORTRAN tag to YES if your project consists of Fortran
+# sources. Doxygen will then generate output that is tailored for Fortran.
+# The default value is: NO.
+
+OPTIMIZE_FOR_FORTRAN = NO
+
+# Set the OPTIMIZE_OUTPUT_VHDL tag to YES if your project consists of VHDL
+# sources. Doxygen will then generate output that is tailored for VHDL.
+# The default value is: NO.
+
+OPTIMIZE_OUTPUT_VHDL = NO
+
+# Set the OPTIMIZE_OUTPUT_SLICE tag to YES if your project consists of Slice
+# sources only. Doxygen will then generate output that is more tailored for that
+# language. For instance, namespaces will be presented as modules, types will be
+# separated into more groups, etc.
+# The default value is: NO.
+
+OPTIMIZE_OUTPUT_SLICE = NO
+
+# Doxygen selects the parser to use depending on the extension of the files it
+# parses. With this tag you can assign which parser to use for a given
+# extension. Doxygen has a built-in mapping, but you can override or extend it
+# using this tag. The format is ext=language, where ext is a file extension, and
+# language is one of the parsers supported by doxygen: IDL, Java, JavaScript,
+# Csharp (C#), C, C++, Lex, D, PHP, md (Markdown), Objective-C, Python, Slice,
+# VHDL, Fortran (fixed format Fortran: FortranFixed, free formatted Fortran:
+# FortranFree, unknown formatted Fortran: Fortran. In the later case the parser
+# tries to guess whether the code is fixed or free formatted code, this is the
+# default for Fortran type files). For instance to make doxygen treat .inc files
+# as Fortran files (default is PHP), and .f files as C (default is Fortran),
+# use: inc=Fortran f=C.
+#
+# Note: For files without extension you can use no_extension as a placeholder.
+#
+# Note that for custom extensions you also need to set FILE_PATTERNS otherwise
+# the files are not read by doxygen. When specifying no_extension you should add
+# * to the FILE_PATTERNS.
+#
+# Note see also the list of default file extension mappings.
+
+EXTENSION_MAPPING =
+
+# If the MARKDOWN_SUPPORT tag is enabled then doxygen pre-processes all comments
+# according to the Markdown format, which allows for more readable
+# documentation. See https://daringfireball.net/projects/markdown/ for details.
+# The output of markdown processing is further processed by doxygen, so you can
+# mix doxygen, HTML, and XML commands with Markdown formatting. Disable only in
+# case of backward compatibilities issues.
+# The default value is: YES.
+
+MARKDOWN_SUPPORT = YES
+
+# When the TOC_INCLUDE_HEADINGS tag is set to a non-zero value, all headings up
+# to that level are automatically included in the table of contents, even if
+# they do not have an id attribute.
+# Note: This feature currently applies only to Markdown headings.
+# Minimum value: 0, maximum value: 99, default value: 5.
+# This tag requires that the tag MARKDOWN_SUPPORT is set to YES.
+
+TOC_INCLUDE_HEADINGS = 5
+
+# The MARKDOWN_ID_STYLE tag can be used to specify the algorithm used to
+# generate identifiers for the Markdown headings. Note: Every identifier is
+# unique.
+# Possible values are: DOXYGEN Use a fixed 'autotoc_md' string followed by a
+# sequence number starting at 0. and GITHUB Use the lower case version of title
+# with any whitespace replaced by '-' and punctations characters removed..
+# The default value is: DOXYGEN.
+# This tag requires that the tag MARKDOWN_SUPPORT is set to YES.
+
+MARKDOWN_ID_STYLE = DOXYGEN
+
+# When enabled doxygen tries to link words that correspond to documented
+# classes, or namespaces to their corresponding documentation. Such a link can
+# be prevented in individual cases by putting a % sign in front of the word or
+# globally by setting AUTOLINK_SUPPORT to NO.
+# The default value is: YES.
+
+AUTOLINK_SUPPORT = YES
+
+# If you use STL classes (i.e. std::string, std::vector, etc.) but do not want
+# to include (a tag file for) the STL sources as input, then you should set this
+# tag to YES in order to let doxygen match functions declarations and
+# definitions whose arguments contain STL classes (e.g. func(std::string);
+# versus func(std::string) {}). This also make the inheritance and collaboration
+# diagrams that involve STL classes more complete and accurate.
+# The default value is: NO.
+
+BUILTIN_STL_SUPPORT = NO
+
+# If you use Microsoft's C++/CLI language, you should set this option to YES to
+# enable parsing support.
+# The default value is: NO.
+
+CPP_CLI_SUPPORT = NO
+
+# Set the SIP_SUPPORT tag to YES if your project consists of sip (see:
+# https://www.riverbankcomputing.com/software/sip/intro) sources only. Doxygen
+# will parse them like normal C++ but will assume all classes use public instead
+# of private inheritance when no explicit protection keyword is present.
+# The default value is: NO.
+
+SIP_SUPPORT = NO
+
+# For Microsoft's IDL there are propget and propput attributes to indicate
+# getter and setter methods for a property. Setting this option to YES will make
+# doxygen to replace the get and set methods by a property in the documentation.
+# This will only work if the methods are indeed getting or setting a simple
+# type. If this is not the case, or you want to show the methods anyway, you
+# should set this option to NO.
+# The default value is: YES.
+
+IDL_PROPERTY_SUPPORT = YES
+
+# If member grouping is used in the documentation and the DISTRIBUTE_GROUP_DOC
+# tag is set to YES then doxygen will reuse the documentation of the first
+# member in the group (if any) for the other members of the group. By default
+# all members of a group must be documented explicitly.
+# The default value is: NO.
+
+DISTRIBUTE_GROUP_DOC = NO
+
+# If one adds a struct or class to a group and this option is enabled, then also
+# any nested class or struct is added to the same group. By default this option
+# is disabled and one has to add nested compounds explicitly via \ingroup.
+# The default value is: NO.
+
+GROUP_NESTED_COMPOUNDS = NO
+
+# Set the SUBGROUPING tag to YES to allow class member groups of the same type
+# (for instance a group of public functions) to be put as a subgroup of that
+# type (e.g. under the Public Functions section). Set it to NO to prevent
+# subgrouping. Alternatively, this can be done per class using the
+# \nosubgrouping command.
+# The default value is: YES.
+
+SUBGROUPING = YES
+
+# When the INLINE_GROUPED_CLASSES tag is set to YES, classes, structs and unions
+# are shown inside the group in which they are included (e.g. using \ingroup)
+# instead of on a separate page (for HTML and Man pages) or section (for LaTeX
+# and RTF).
+#
+# Note that this feature does not work in combination with
+# SEPARATE_MEMBER_PAGES.
+# The default value is: NO.
+
+INLINE_GROUPED_CLASSES = NO
+
+# When the INLINE_SIMPLE_STRUCTS tag is set to YES, structs, classes, and unions
+# with only public data fields or simple typedef fields will be shown inline in
+# the documentation of the scope in which they are defined (i.e. file,
+# namespace, or group documentation), provided this scope is documented. If set
+# to NO, structs, classes, and unions are shown on a separate page (for HTML and
+# Man pages) or section (for LaTeX and RTF).
+# The default value is: NO.
+
+INLINE_SIMPLE_STRUCTS = NO
+
+# When TYPEDEF_HIDES_STRUCT tag is enabled, a typedef of a struct, union, or
+# enum is documented as struct, union, or enum with the name of the typedef. So
+# typedef struct TypeS {} TypeT, will appear in the documentation as a struct
+# with name TypeT. When disabled the typedef will appear as a member of a file,
+# namespace, or class. And the struct will be named TypeS. This can typically be
+# useful for C code in case the coding convention dictates that all compound
+# types are typedef'ed and only the typedef is referenced, never the tag name.
+# The default value is: NO.
+
+TYPEDEF_HIDES_STRUCT = NO
+
+# The size of the symbol lookup cache can be set using LOOKUP_CACHE_SIZE. This
+# cache is used to resolve symbols given their name and scope. Since this can be
+# an expensive process and often the same symbol appears multiple times in the
+# code, doxygen keeps a cache of pre-resolved symbols. If the cache is too small
+# doxygen will become slower. If the cache is too large, memory is wasted. The
+# cache size is given by this formula: 2^(16+LOOKUP_CACHE_SIZE). The valid range
+# is 0..9, the default is 0, corresponding to a cache size of 2^16=65536
+# symbols. At the end of a run doxygen will report the cache usage and suggest
+# the optimal cache size from a speed point of view.
+# Minimum value: 0, maximum value: 9, default value: 0.
+
+LOOKUP_CACHE_SIZE = 0
+
+# The NUM_PROC_THREADS specifies the number of threads doxygen is allowed to use
+# during processing. When set to 0 doxygen will based this on the number of
+# cores available in the system. You can set it explicitly to a value larger
+# than 0 to get more control over the balance between CPU load and processing
+# speed. At this moment only the input processing can be done using multiple
+# threads. Since this is still an experimental feature the default is set to 1,
+# which effectively disables parallel processing. Please report any issues you
+# encounter. Generating dot graphs in parallel is controlled by the
+# DOT_NUM_THREADS setting.
+# Minimum value: 0, maximum value: 32, default value: 1.
+
+NUM_PROC_THREADS = 1
+
+# If the TIMESTAMP tag is set different from NO then each generated page will
+# contain the date or date and time when the page was generated. Setting this to
+# NO can help when comparing the output of multiple runs.
+# Possible values are: YES, NO, DATETIME and DATE.
+# The default value is: NO.
+
+TIMESTAMP = NO
+
+#---------------------------------------------------------------------------
+# Build related configuration options
+#---------------------------------------------------------------------------
+
+# If the EXTRACT_ALL tag is set to YES, doxygen will assume all entities in
+# documentation are documented, even if no documentation was available. Private
+# class members and static file members will be hidden unless the
+# EXTRACT_PRIVATE respectively EXTRACT_STATIC tags are set to YES.
+# Note: This will also disable the warnings about undocumented members that are
+# normally produced when WARNINGS is set to YES.
+# The default value is: NO.
+
+EXTRACT_ALL = NO
+
+# If the EXTRACT_PRIVATE tag is set to YES, all private members of a class will
+# be included in the documentation.
+# The default value is: NO.
+
+EXTRACT_PRIVATE = YES
+
+# If the EXTRACT_PRIV_VIRTUAL tag is set to YES, documented private virtual
+# methods of a class will be included in the documentation.
+# The default value is: NO.
+
+EXTRACT_PRIV_VIRTUAL = NO
+
+# If the EXTRACT_PACKAGE tag is set to YES, all members with package or internal
+# scope will be included in the documentation.
+# The default value is: NO.
+
+EXTRACT_PACKAGE = NO
+
+# If the EXTRACT_STATIC tag is set to YES, all static members of a file will be
+# included in the documentation.
+# The default value is: NO.
+
+EXTRACT_STATIC = YES
+
+# If the EXTRACT_LOCAL_CLASSES tag is set to YES, classes (and structs) defined
+# locally in source files will be included in the documentation. If set to NO,
+# only classes defined in header files are included. Does not have any effect
+# for Java sources.
+# The default value is: YES.
+
+EXTRACT_LOCAL_CLASSES = YES
+
+# This flag is only useful for Objective-C code. If set to YES, local methods,
+# which are defined in the implementation section but not in the interface are
+# included in the documentation. If set to NO, only methods in the interface are
+# included.
+# The default value is: NO.
+
+EXTRACT_LOCAL_METHODS = YES
+
+# If this flag is set to YES, the members of anonymous namespaces will be
+# extracted and appear in the documentation as a namespace called
+# 'anonymous_namespace{file}', where file will be replaced with the base name of
+# the file that contains the anonymous namespace. By default anonymous namespace
+# are hidden.
+# The default value is: NO.
+
+EXTRACT_ANON_NSPACES = NO
+
+# If this flag is set to YES, the name of an unnamed parameter in a declaration
+# will be determined by the corresponding definition. By default unnamed
+# parameters remain unnamed in the output.
+# The default value is: YES.
+
+RESOLVE_UNNAMED_PARAMS = YES
+
+# If the HIDE_UNDOC_MEMBERS tag is set to YES, doxygen will hide all
+# undocumented members inside documented classes or files. If set to NO these
+# members will be included in the various overviews, but no documentation
+# section is generated. This option has no effect if EXTRACT_ALL is enabled.
+# The default value is: NO.
+
+HIDE_UNDOC_MEMBERS = NO
+
+# If the HIDE_UNDOC_CLASSES tag is set to YES, doxygen will hide all
+# undocumented classes that are normally visible in the class hierarchy. If set
+# to NO, these classes will be included in the various overviews. This option
+# will also hide undocumented C++ concepts if enabled. This option has no effect
+# if EXTRACT_ALL is enabled.
+# The default value is: NO.
+
+HIDE_UNDOC_CLASSES = NO
+
+# If the HIDE_FRIEND_COMPOUNDS tag is set to YES, doxygen will hide all friend
+# declarations. If set to NO, these declarations will be included in the
+# documentation.
+# The default value is: NO.
+
+HIDE_FRIEND_COMPOUNDS = NO
+
+# If the HIDE_IN_BODY_DOCS tag is set to YES, doxygen will hide any
+# documentation blocks found inside the body of a function. If set to NO, these
+# blocks will be appended to the function's detailed documentation block.
+# The default value is: NO.
+
+HIDE_IN_BODY_DOCS = NO
+
+# The INTERNAL_DOCS tag determines if documentation that is typed after a
+# \internal command is included. If the tag is set to NO then the documentation
+# will be excluded. Set it to YES to include the internal documentation.
+# The default value is: NO.
+
+INTERNAL_DOCS = NO
+
+# With the correct setting of option CASE_SENSE_NAMES doxygen will better be
+# able to match the capabilities of the underlying filesystem. In case the
+# filesystem is case sensitive (i.e. it supports files in the same directory
+# whose names only differ in casing), the option must be set to YES to properly
+# deal with such files in case they appear in the input. For filesystems that
+# are not case sensitive the option should be set to NO to properly deal with
+# output files written for symbols that only differ in casing, such as for two
+# classes, one named CLASS and the other named Class, and to also support
+# references to files without having to specify the exact matching casing. On
+# Windows (including Cygwin) and MacOS, users should typically set this option
+# to NO, whereas on Linux or other Unix flavors it should typically be set to
+# YES.
+# Possible values are: SYSTEM, NO and YES.
+# The default value is: SYSTEM.
+
+CASE_SENSE_NAMES = SYSTEM
+
+# If the HIDE_SCOPE_NAMES tag is set to NO then doxygen will show members with
+# their full class and namespace scopes in the documentation. If set to YES, the
+# scope will be hidden.
+# The default value is: NO.
+
+HIDE_SCOPE_NAMES = YES
+
+# If the HIDE_COMPOUND_REFERENCE tag is set to NO (default) then doxygen will
+# append additional text to a page's title, such as Class Reference. If set to
+# YES the compound reference will be hidden.
+# The default value is: NO.
+
+HIDE_COMPOUND_REFERENCE= NO
+
+# If the SHOW_HEADERFILE tag is set to YES then the documentation for a class
+# will show which file needs to be included to use the class.
+# The default value is: YES.
+
+SHOW_HEADERFILE = YES
+
+# If the SHOW_INCLUDE_FILES tag is set to YES then doxygen will put a list of
+# the files that are included by a file in the documentation of that file.
+# The default value is: YES.
+
+SHOW_INCLUDE_FILES = YES
+
+# If the SHOW_GROUPED_MEMB_INC tag is set to YES then Doxygen will add for each
+# grouped member an include statement to the documentation, telling the reader
+# which file to include in order to use the member.
+# The default value is: NO.
+
+SHOW_GROUPED_MEMB_INC = NO
+
+# If the FORCE_LOCAL_INCLUDES tag is set to YES then doxygen will list include
+# files with double quotes in the documentation rather than with sharp brackets.
+# The default value is: NO.
+
+FORCE_LOCAL_INCLUDES = NO
+
+# If the INLINE_INFO tag is set to YES then a tag [inline] is inserted in the
+# documentation for inline members.
+# The default value is: YES.
+
+INLINE_INFO = YES
+
+# If the SORT_MEMBER_DOCS tag is set to YES then doxygen will sort the
+# (detailed) documentation of file and class members alphabetically by member
+# name. If set to NO, the members will appear in declaration order.
+# The default value is: YES.
+
+SORT_MEMBER_DOCS = YES
+
+# If the SORT_BRIEF_DOCS tag is set to YES then doxygen will sort the brief
+# descriptions of file, namespace and class members alphabetically by member
+# name. If set to NO, the members will appear in declaration order. Note that
+# this will also influence the order of the classes in the class list.
+# The default value is: NO.
+
+SORT_BRIEF_DOCS = NO
+
+# If the SORT_MEMBERS_CTORS_1ST tag is set to YES then doxygen will sort the
+# (brief and detailed) documentation of class members so that constructors and
+# destructors are listed first. If set to NO the constructors will appear in the
+# respective orders defined by SORT_BRIEF_DOCS and SORT_MEMBER_DOCS.
+# Note: If SORT_BRIEF_DOCS is set to NO this option is ignored for sorting brief
+# member documentation.
+# Note: If SORT_MEMBER_DOCS is set to NO this option is ignored for sorting
+# detailed member documentation.
+# The default value is: NO.
+
+SORT_MEMBERS_CTORS_1ST = NO
+
+# If the SORT_GROUP_NAMES tag is set to YES then doxygen will sort the hierarchy
+# of group names into alphabetical order. If set to NO the group names will
+# appear in their defined order.
+# The default value is: NO.
+
+SORT_GROUP_NAMES = NO
+
+# If the SORT_BY_SCOPE_NAME tag is set to YES, the class list will be sorted by
+# fully-qualified names, including namespaces. If set to NO, the class list will
+# be sorted only by class name, not including the namespace part.
+# Note: This option is not very useful if HIDE_SCOPE_NAMES is set to YES.
+# Note: This option applies only to the class list, not to the alphabetical
+# list.
+# The default value is: NO.
+
+SORT_BY_SCOPE_NAME = NO
+
+# If the STRICT_PROTO_MATCHING option is enabled and doxygen fails to do proper
+# type resolution of all parameters of a function it will reject a match between
+# the prototype and the implementation of a member function even if there is
+# only one candidate or it is obvious which candidate to choose by doing a
+# simple string match. By disabling STRICT_PROTO_MATCHING doxygen will still
+# accept a match between prototype and implementation in such cases.
+# The default value is: NO.
+
+STRICT_PROTO_MATCHING = NO
+
+# The GENERATE_TODOLIST tag can be used to enable (YES) or disable (NO) the todo
+# list. This list is created by putting \todo commands in the documentation.
+# The default value is: YES.
+
+GENERATE_TODOLIST = YES
+
+# The GENERATE_TESTLIST tag can be used to enable (YES) or disable (NO) the test
+# list. This list is created by putting \test commands in the documentation.
+# The default value is: YES.
+
+GENERATE_TESTLIST = YES
+
+# The GENERATE_BUGLIST tag can be used to enable (YES) or disable (NO) the bug
+# list. This list is created by putting \bug commands in the documentation.
+# The default value is: YES.
+
+GENERATE_BUGLIST = YES
+
+# The GENERATE_DEPRECATEDLIST tag can be used to enable (YES) or disable (NO)
+# the deprecated list. This list is created by putting \deprecated commands in
+# the documentation.
+# The default value is: YES.
+
+GENERATE_DEPRECATEDLIST= YES
+
+# The ENABLED_SECTIONS tag can be used to enable conditional documentation
+# sections, marked by \if ... \endif and \cond
+# ... \endcond blocks.
+
+ENABLED_SECTIONS =
+
+# The MAX_INITIALIZER_LINES tag determines the maximum number of lines that the
+# initial value of a variable or macro / define can have for it to appear in the
+# documentation. If the initializer consists of more lines than specified here
+# it will be hidden. Use a value of 0 to hide initializers completely. The
+# appearance of the value of individual variables and macros / defines can be
+# controlled using \showinitializer or \hideinitializer command in the
+# documentation regardless of this setting.
+# Minimum value: 0, maximum value: 10000, default value: 30.
+
+MAX_INITIALIZER_LINES = 30
+
+# Set the SHOW_USED_FILES tag to NO to disable the list of files generated at
+# the bottom of the documentation of classes and structs. If set to YES, the
+# list will mention the files that were used to generate the documentation.
+# The default value is: YES.
+
+SHOW_USED_FILES = YES
+
+# Set the SHOW_FILES tag to NO to disable the generation of the Files page. This
+# will remove the Files entry from the Quick Index and from the Folder Tree View
+# (if specified).
+# The default value is: YES.
+
+SHOW_FILES = YES
+
+# Set the SHOW_NAMESPACES tag to NO to disable the generation of the Namespaces
+# page. This will remove the Namespaces entry from the Quick Index and from the
+# Folder Tree View (if specified).
+# The default value is: YES.
+
+SHOW_NAMESPACES = YES
+
+# The FILE_VERSION_FILTER tag can be used to specify a program or script that
+# doxygen should invoke to get the current version for each file (typically from
+# the version control system). Doxygen will invoke the program by executing (via
+# popen()) the command command input-file, where command is the value of the
+# FILE_VERSION_FILTER tag, and input-file is the name of an input file provided
+# by doxygen. Whatever the program writes to standard output is used as the file
+# version. For an example see the documentation.
+
+FILE_VERSION_FILTER =
+
+# The LAYOUT_FILE tag can be used to specify a layout file which will be parsed
+# by doxygen. The layout file controls the global structure of the generated
+# output files in an output format independent way. To create the layout file
+# that represents doxygen's defaults, run doxygen with the -l option. You can
+# optionally specify a file name after the option, if omitted DoxygenLayout.xml
+# will be used as the name of the layout file. See also section "Changing the
+# layout of pages" for information.
+#
+# Note that if you run doxygen from a directory containing a file called
+# DoxygenLayout.xml, doxygen will parse it automatically even if the LAYOUT_FILE
+# tag is left empty.
+
+LAYOUT_FILE =
+
+# The CITE_BIB_FILES tag can be used to specify one or more bib files containing
+# the reference definitions. This must be a list of .bib files. The .bib
+# extension is automatically appended if omitted. This requires the bibtex tool
+# to be installed. See also https://en.wikipedia.org/wiki/BibTeX for more info.
+# For LaTeX the style of the bibliography can be controlled using
+# LATEX_BIB_STYLE. To use this feature you need bibtex and perl available in the
+# search path. See also \cite for info how to create references.
+
+CITE_BIB_FILES =
+
+#---------------------------------------------------------------------------
+# Configuration options related to warning and progress messages
+#---------------------------------------------------------------------------
+
+# The QUIET tag can be used to turn on/off the messages that are generated to
+# standard output by doxygen. If QUIET is set to YES this implies that the
+# messages are off.
+# The default value is: NO.
+
+QUIET = NO
+
+# The WARNINGS tag can be used to turn on/off the warning messages that are
+# generated to standard error (stderr) by doxygen. If WARNINGS is set to YES
+# this implies that the warnings are on.
+#
+# Tip: Turn warnings on while writing the documentation.
+# The default value is: YES.
+
+WARNINGS = YES
+
+# If the WARN_IF_UNDOCUMENTED tag is set to YES then doxygen will generate
+# warnings for undocumented members. If EXTRACT_ALL is set to YES then this flag
+# will automatically be disabled.
+# The default value is: YES.
+
+WARN_IF_UNDOCUMENTED = YES
+
+# If the WARN_IF_DOC_ERROR tag is set to YES, doxygen will generate warnings for
+# potential errors in the documentation, such as documenting some parameters in
+# a documented function twice, or documenting parameters that don't exist or
+# using markup commands wrongly.
+# The default value is: YES.
+
+WARN_IF_DOC_ERROR = YES
+
+# If WARN_IF_INCOMPLETE_DOC is set to YES, doxygen will warn about incomplete
+# function parameter documentation. If set to NO, doxygen will accept that some
+# parameters have no documentation without warning.
+# The default value is: YES.
+
+WARN_IF_INCOMPLETE_DOC = YES
+
+# This WARN_NO_PARAMDOC option can be enabled to get warnings for functions that
+# are documented, but have no documentation for their parameters or return
+# value. If set to NO, doxygen will only warn about wrong parameter
+# documentation, but not about the absence of documentation. If EXTRACT_ALL is
+# set to YES then this flag will automatically be disabled. See also
+# WARN_IF_INCOMPLETE_DOC
+# The default value is: NO.
+
+WARN_NO_PARAMDOC = NO
+
+# If WARN_IF_UNDOC_ENUM_VAL option is set to YES, doxygen will warn about
+# undocumented enumeration values. If set to NO, doxygen will accept
+# undocumented enumeration values. If EXTRACT_ALL is set to YES then this flag
+# will automatically be disabled.
+# The default value is: NO.
+
+WARN_IF_UNDOC_ENUM_VAL = NO
+
+# If the WARN_AS_ERROR tag is set to YES then doxygen will immediately stop when
+# a warning is encountered. If the WARN_AS_ERROR tag is set to FAIL_ON_WARNINGS
+# then doxygen will continue running as if WARN_AS_ERROR tag is set to NO, but
+# at the end of the doxygen process doxygen will return with a non-zero status.
+# If the WARN_AS_ERROR tag is set to FAIL_ON_WARNINGS_PRINT then doxygen behaves
+# like FAIL_ON_WARNINGS but in case no WARN_LOGFILE is defined doxygen will not
+# write the warning messages in between other messages but write them at the end
+# of a run, in case a WARN_LOGFILE is defined the warning messages will be
+# besides being in the defined file also be shown at the end of a run, unless
+# the WARN_LOGFILE is defined as - i.e. standard output (stdout) in that case
+# the behavior will remain as with the setting FAIL_ON_WARNINGS.
+# Possible values are: NO, YES, FAIL_ON_WARNINGS and FAIL_ON_WARNINGS_PRINT.
+# The default value is: NO.
+
+WARN_AS_ERROR = NO
+
+# The WARN_FORMAT tag determines the format of the warning messages that doxygen
+# can produce. The string should contain the $file, $line, and $text tags, which
+# will be replaced by the file and line number from which the warning originated
+# and the warning text. Optionally the format may contain $version, which will
+# be replaced by the version of the file (if it could be obtained via
+# FILE_VERSION_FILTER)
+# See also: WARN_LINE_FORMAT
+# The default value is: $file:$line: $text.
+
+WARN_FORMAT = "$file:$line: $text"
+
+# In the $text part of the WARN_FORMAT command it is possible that a reference
+# to a more specific place is given. To make it easier to jump to this place
+# (outside of doxygen) the user can define a custom "cut" / "paste" string.
+# Example:
+# WARN_LINE_FORMAT = "'vi $file +$line'"
+# See also: WARN_FORMAT
+# The default value is: at line $line of file $file.
+
+WARN_LINE_FORMAT = "at line $line of file $file"
+
+# The WARN_LOGFILE tag can be used to specify a file to which warning and error
+# messages should be written. If left blank the output is written to standard
+# error (stderr). In case the file specified cannot be opened for writing the
+# warning and error messages are written to standard error. When as file - is
+# specified the warning and error messages are written to standard output
+# (stdout).
+
+WARN_LOGFILE =
+
+#---------------------------------------------------------------------------
+# Configuration options related to the input files
+#---------------------------------------------------------------------------
+
+# The INPUT tag is used to specify the files and/or directories that contain
+# documented source files. You may enter file names like myfile.cpp or
+# directories like /usr/src/myproject. Separate the files or directories with
+# spaces. See also FILE_PATTERNS and EXTENSION_MAPPING
+# Note: If this tag is empty the current directory is searched.
+
+INPUT = ./
+
+# This tag can be used to specify the character encoding of the source files
+# that doxygen parses. Internally doxygen uses the UTF-8 encoding. Doxygen uses
+# libiconv (or the iconv built into libc) for the transcoding. See the libiconv
+# documentation (see:
+# https://www.gnu.org/software/libiconv/) for the list of possible encodings.
+# See also: INPUT_FILE_ENCODING
+# The default value is: UTF-8.
+
+INPUT_ENCODING = UTF-8
+
+# This tag can be used to specify the character encoding of the source files
+# that doxygen parses The INPUT_FILE_ENCODING tag can be used to specify
+# character encoding on a per file pattern basis. Doxygen will compare the file
+# name with each pattern and apply the encoding instead of the default
+# INPUT_ENCODING) if there is a match. The character encodings are a list of the
+# form: pattern=encoding (like *.php=ISO-8859-1). See cfg_input_encoding
+# "INPUT_ENCODING" for further information on supported encodings.
+
+INPUT_FILE_ENCODING =
+
+# If the value of the INPUT tag contains directories, you can use the
+# FILE_PATTERNS tag to specify one or more wildcard patterns (like *.cpp and
+# *.h) to filter out the source-files in the directories.
+#
+# Note that for custom extensions or not directly supported extensions you also
+# need to set EXTENSION_MAPPING for the extension otherwise the files are not
+# read by doxygen.
+#
+# Note the list of default checked file patterns might differ from the list of
+# default file extension mappings.
+#
+# If left blank the following patterns are tested:*.c, *.cc, *.cxx, *.cpp,
+# *.c++, *.java, *.ii, *.ixx, *.ipp, *.i++, *.inl, *.idl, *.ddl, *.odl, *.h,
+# *.hh, *.hxx, *.hpp, *.h++, *.l, *.cs, *.d, *.php, *.php4, *.php5, *.phtml,
+# *.inc, *.m, *.markdown, *.md, *.mm, *.dox (to be provided as doxygen C
+# comment), *.py, *.pyw, *.f90, *.f95, *.f03, *.f08, *.f18, *.f, *.for, *.vhd,
+# *.vhdl, *.ucf, *.qsf and *.ice.
+
+FILE_PATTERNS = *.c \
+ *.cc \
+ *.cxx \
+ *.cpp \
+ *.c++ \
+ *.java \
+ *.ii \
+ *.ixx \
+ *.ipp \
+ *.i++ \
+ *.inl \
+ *.idl \
+ *.ddl \
+ *.odl \
+ *.h \
+ *.hh \
+ *.hxx \
+ *.hpp \
+ *.h++ \
+ *.l \
+ *.cs \
+ *.d \
+ *.php \
+ *.php4 \
+ *.php5 \
+ *.phtml \
+ *.inc \
+ *.m \
+ *.markdown \
+ *.md \
+ *.mm \
+ *.dox \
+ *.py \
+ *.pyw \
+ *.f90 \
+ *.f95 \
+ *.f03 \
+ *.f08 \
+ *.f18 \
+ *.f \
+ *.for \
+ *.vhd \
+ *.vhdl \
+ *.ucf \
+ *.qsf \
+ *.ice
+
+# The RECURSIVE tag can be used to specify whether or not subdirectories should
+# be searched for input files as well.
+# The default value is: NO.
+
+RECURSIVE = YES
+
+# The EXCLUDE tag can be used to specify files and/or directories that should be
+# excluded from the INPUT source files. This way you can easily exclude a
+# subdirectory from a directory tree whose root is specified with the INPUT tag.
+#
+# Note that relative paths are relative to the directory from which doxygen is
+# run.
+
+EXCLUDE =
+
+# The EXCLUDE_SYMLINKS tag can be used to select whether or not files or
+# directories that are symbolic links (a Unix file system feature) are excluded
+# from the input.
+# The default value is: NO.
+
+EXCLUDE_SYMLINKS = NO
+
+# If the value of the INPUT tag contains directories, you can use the
+# EXCLUDE_PATTERNS tag to specify one or more wildcard patterns to exclude
+# certain files from those directories.
+#
+# Note that the wildcards are matched against the file with absolute path, so to
+# exclude all test directories for example use the pattern */test/*
+
+EXCLUDE_PATTERNS =
+
+# The EXCLUDE_SYMBOLS tag can be used to specify one or more symbol names
+# (namespaces, classes, functions, etc.) that should be excluded from the
+# output. The symbol name can be a fully qualified name, a word, or if the
+# wildcard * is used, a substring. Examples: ANamespace, AClass,
+# ANamespace::AClass, ANamespace::*Test
+
+EXCLUDE_SYMBOLS =
+
+# The EXAMPLE_PATH tag can be used to specify one or more files or directories
+# that contain example code fragments that are included (see the \include
+# command).
+
+EXAMPLE_PATH =
+
+# If the value of the EXAMPLE_PATH tag contains directories, you can use the
+# EXAMPLE_PATTERNS tag to specify one or more wildcard pattern (like *.cpp and
+# *.h) to filter out the source-files in the directories. If left blank all
+# files are included.
+
+EXAMPLE_PATTERNS = *
+
+# If the EXAMPLE_RECURSIVE tag is set to YES then subdirectories will be
+# searched for input files to be used with the \include or \dontinclude commands
+# irrespective of the value of the RECURSIVE tag.
+# The default value is: NO.
+
+EXAMPLE_RECURSIVE = NO
+
+# The IMAGE_PATH tag can be used to specify one or more files or directories
+# that contain images that are to be included in the documentation (see the
+# \image command).
+
+IMAGE_PATH =
+
+# The INPUT_FILTER tag can be used to specify a program that doxygen should
+# invoke to filter for each input file. Doxygen will invoke the filter program
+# by executing (via popen()) the command:
+#
+#
+#
+# where is the value of the INPUT_FILTER tag, and is the
+# name of an input file. Doxygen will then use the output that the filter
+# program writes to standard output. If FILTER_PATTERNS is specified, this tag
+# will be ignored.
+#
+# Note that the filter must not add or remove lines; it is applied before the
+# code is scanned, but not when the output code is generated. If lines are added
+# or removed, the anchors will not be placed correctly.
+#
+# Note that doxygen will use the data processed and written to standard output
+# for further processing, therefore nothing else, like debug statements or used
+# commands (so in case of a Windows batch file always use @echo OFF), should be
+# written to standard output.
+#
+# Note that for custom extensions or not directly supported extensions you also
+# need to set EXTENSION_MAPPING for the extension otherwise the files are not
+# properly processed by doxygen.
+
+INPUT_FILTER =
+
+# The FILTER_PATTERNS tag can be used to specify filters on a per file pattern
+# basis. Doxygen will compare the file name with each pattern and apply the
+# filter if there is a match. The filters are a list of the form: pattern=filter
+# (like *.cpp=my_cpp_filter). See INPUT_FILTER for further information on how
+# filters are used. If the FILTER_PATTERNS tag is empty or if none of the
+# patterns match the file name, INPUT_FILTER is applied.
+#
+# Note that for custom extensions or not directly supported extensions you also
+# need to set EXTENSION_MAPPING for the extension otherwise the files are not
+# properly processed by doxygen.
+
+FILTER_PATTERNS =
+
+# If the FILTER_SOURCE_FILES tag is set to YES, the input filter (if set using
+# INPUT_FILTER) will also be used to filter the input files that are used for
+# producing the source files to browse (i.e. when SOURCE_BROWSER is set to YES).
+# The default value is: NO.
+
+FILTER_SOURCE_FILES = NO
+
+# The FILTER_SOURCE_PATTERNS tag can be used to specify source filters per file
+# pattern. A pattern will override the setting for FILTER_PATTERN (if any) and
+# it is also possible to disable source filtering for a specific pattern using
+# *.ext= (so without naming a filter).
+# This tag requires that the tag FILTER_SOURCE_FILES is set to YES.
+
+FILTER_SOURCE_PATTERNS =
+
+# If the USE_MDFILE_AS_MAINPAGE tag refers to the name of a markdown file that
+# is part of the input, its contents will be placed on the main page
+# (index.html). This can be useful if you have a project on for instance GitHub
+# and want to reuse the introduction page also for the doxygen output.
+
+USE_MDFILE_AS_MAINPAGE =
+
+# The Fortran standard specifies that for fixed formatted Fortran code all
+# characters from position 72 are to be considered as comment. A common
+# extension is to allow longer lines before the automatic comment starts. The
+# setting FORTRAN_COMMENT_AFTER will also make it possible that longer lines can
+# be processed before the automatic comment starts.
+# Minimum value: 7, maximum value: 10000, default value: 72.
+
+FORTRAN_COMMENT_AFTER = 72
+
+#---------------------------------------------------------------------------
+# Configuration options related to source browsing
+#---------------------------------------------------------------------------
+
+# If the SOURCE_BROWSER tag is set to YES then a list of source files will be
+# generated. Documented entities will be cross-referenced with these sources.
+#
+# Note: To get rid of all source code in the generated output, make sure that
+# also VERBATIM_HEADERS is set to NO.
+# The default value is: NO.
+
+SOURCE_BROWSER = NO
+
+# Setting the INLINE_SOURCES tag to YES will include the body of functions,
+# classes and enums directly into the documentation.
+# The default value is: NO.
+
+INLINE_SOURCES = NO
+
+# Setting the STRIP_CODE_COMMENTS tag to YES will instruct doxygen to hide any
+# special comment blocks from generated source code fragments. Normal C, C++ and
+# Fortran comments will always remain visible.
+# The default value is: YES.
+
+STRIP_CODE_COMMENTS = YES
+
+# If the REFERENCED_BY_RELATION tag is set to YES then for each documented
+# entity all documented functions referencing it will be listed.
+# The default value is: NO.
+
+REFERENCED_BY_RELATION = NO
+
+# If the REFERENCES_RELATION tag is set to YES then for each documented function
+# all documented entities called/used by that function will be listed.
+# The default value is: NO.
+
+REFERENCES_RELATION = NO
+
+# If the REFERENCES_LINK_SOURCE tag is set to YES and SOURCE_BROWSER tag is set
+# to YES then the hyperlinks from functions in REFERENCES_RELATION and
+# REFERENCED_BY_RELATION lists will link to the source code. Otherwise they will
+# link to the documentation.
+# The default value is: YES.
+
+REFERENCES_LINK_SOURCE = YES
+
+# If SOURCE_TOOLTIPS is enabled (the default) then hovering a hyperlink in the
+# source code will show a tooltip with additional information such as prototype,
+# brief description and links to the definition and documentation. Since this
+# will make the HTML file larger and loading of large files a bit slower, you
+# can opt to disable this feature.
+# The default value is: YES.
+# This tag requires that the tag SOURCE_BROWSER is set to YES.
+
+SOURCE_TOOLTIPS = YES
+
+# If the USE_HTAGS tag is set to YES then the references to source code will
+# point to the HTML generated by the htags(1) tool instead of doxygen built-in
+# source browser. The htags tool is part of GNU's global source tagging system
+# (see https://www.gnu.org/software/global/global.html). You will need version
+# 4.8.6 or higher.
+#
+# To use it do the following:
+# - Install the latest version of global
+# - Enable SOURCE_BROWSER and USE_HTAGS in the configuration file
+# - Make sure the INPUT points to the root of the source tree
+# - Run doxygen as normal
+#
+# Doxygen will invoke htags (and that will in turn invoke gtags), so these
+# tools must be available from the command line (i.e. in the search path).
+#
+# The result: instead of the source browser generated by doxygen, the links to
+# source code will now point to the output of htags.
+# The default value is: NO.
+# This tag requires that the tag SOURCE_BROWSER is set to YES.
+
+USE_HTAGS = NO
+
+# If the VERBATIM_HEADERS tag is set the YES then doxygen will generate a
+# verbatim copy of the header file for each class for which an include is
+# specified. Set to NO to disable this.
+# See also: Section \class.
+# The default value is: YES.
+
+VERBATIM_HEADERS = YES
+
+# If the CLANG_ASSISTED_PARSING tag is set to YES then doxygen will use the
+# clang parser (see:
+# http://clang.llvm.org/) for more accurate parsing at the cost of reduced
+# performance. This can be particularly helpful with template rich C++ code for
+# which doxygen's built-in parser lacks the necessary type information.
+# Note: The availability of this option depends on whether or not doxygen was
+# generated with the -Duse_libclang=ON option for CMake.
+# The default value is: NO.
+
+CLANG_ASSISTED_PARSING = NO
+
+# If the CLANG_ASSISTED_PARSING tag is set to YES and the CLANG_ADD_INC_PATHS
+# tag is set to YES then doxygen will add the directory of each input to the
+# include path.
+# The default value is: YES.
+# This tag requires that the tag CLANG_ASSISTED_PARSING is set to YES.
+
+CLANG_ADD_INC_PATHS = YES
+
+# If clang assisted parsing is enabled you can provide the compiler with command
+# line options that you would normally use when invoking the compiler. Note that
+# the include paths will already be set by doxygen for the files and directories
+# specified with INPUT and INCLUDE_PATH.
+# This tag requires that the tag CLANG_ASSISTED_PARSING is set to YES.
+
+CLANG_OPTIONS =
+
+# If clang assisted parsing is enabled you can provide the clang parser with the
+# path to the directory containing a file called compile_commands.json. This
+# file is the compilation database (see:
+# http://clang.llvm.org/docs/HowToSetupToolingForLLVM.html) containing the
+# options used when the source files were built. This is equivalent to
+# specifying the -p option to a clang tool, such as clang-check. These options
+# will then be passed to the parser. Any options specified with CLANG_OPTIONS
+# will be added as well.
+# Note: The availability of this option depends on whether or not doxygen was
+# generated with the -Duse_libclang=ON option for CMake.
+
+CLANG_DATABASE_PATH =
+
+#---------------------------------------------------------------------------
+# Configuration options related to the alphabetical class index
+#---------------------------------------------------------------------------
+
+# If the ALPHABETICAL_INDEX tag is set to YES, an alphabetical index of all
+# compounds will be generated. Enable this if the project contains a lot of
+# classes, structs, unions or interfaces.
+# The default value is: YES.
+
+ALPHABETICAL_INDEX = YES
+
+# The IGNORE_PREFIX tag can be used to specify a prefix (or a list of prefixes)
+# that should be ignored while generating the index headers. The IGNORE_PREFIX
+# tag works for classes, function and member names. The entity will be placed in
+# the alphabetical list under the first letter of the entity name that remains
+# after removing the prefix.
+# This tag requires that the tag ALPHABETICAL_INDEX is set to YES.
+
+IGNORE_PREFIX =
+
+#---------------------------------------------------------------------------
+# Configuration options related to the HTML output
+#---------------------------------------------------------------------------
+
+# If the GENERATE_HTML tag is set to YES, doxygen will generate HTML output
+# The default value is: YES.
+
+GENERATE_HTML = YES
+
+# The HTML_OUTPUT tag is used to specify where the HTML docs will be put. If a
+# relative path is entered the value of OUTPUT_DIRECTORY will be put in front of
+# it.
+# The default directory is: html.
+# This tag requires that the tag GENERATE_HTML is set to YES.
+
+HTML_OUTPUT = html
+
+# The HTML_FILE_EXTENSION tag can be used to specify the file extension for each
+# generated HTML page (for example: .htm, .php, .asp).
+# The default value is: .html.
+# This tag requires that the tag GENERATE_HTML is set to YES.
+
+HTML_FILE_EXTENSION = .html
+
+# The HTML_HEADER tag can be used to specify a user-defined HTML header file for
+# each generated HTML page. If the tag is left blank doxygen will generate a
+# standard header.
+#
+# To get valid HTML the header file that includes any scripts and style sheets
+# that doxygen needs, which is dependent on the configuration options used (e.g.
+# the setting GENERATE_TREEVIEW). It is highly recommended to start with a
+# default header using
+# doxygen -w html new_header.html new_footer.html new_stylesheet.css
+# YourConfigFile
+# and then modify the file new_header.html. See also section "Doxygen usage"
+# for information on how to generate the default header that doxygen normally
+# uses.
+# Note: The header is subject to change so you typically have to regenerate the
+# default header when upgrading to a newer version of doxygen. For a description
+# of the possible markers and block names see the documentation.
+# This tag requires that the tag GENERATE_HTML is set to YES.
+
+HTML_HEADER =
+
+# The HTML_FOOTER tag can be used to specify a user-defined HTML footer for each
+# generated HTML page. If the tag is left blank doxygen will generate a standard
+# footer. See HTML_HEADER for more information on how to generate a default
+# footer and what special commands can be used inside the footer. See also
+# section "Doxygen usage" for information on how to generate the default footer
+# that doxygen normally uses.
+# This tag requires that the tag GENERATE_HTML is set to YES.
+
+HTML_FOOTER =
+
+# The HTML_STYLESHEET tag can be used to specify a user-defined cascading style
+# sheet that is used by each HTML page. It can be used to fine-tune the look of
+# the HTML output. If left blank doxygen will generate a default style sheet.
+# See also section "Doxygen usage" for information on how to generate the style
+# sheet that doxygen normally uses.
+# Note: It is recommended to use HTML_EXTRA_STYLESHEET instead of this tag, as
+# it is more robust and this tag (HTML_STYLESHEET) will in the future become
+# obsolete.
+# This tag requires that the tag GENERATE_HTML is set to YES.
+
+HTML_STYLESHEET =
+
+# The HTML_EXTRA_STYLESHEET tag can be used to specify additional user-defined
+# cascading style sheets that are included after the standard style sheets
+# created by doxygen. Using this option one can overrule certain style aspects.
+# This is preferred over using HTML_STYLESHEET since it does not replace the
+# standard style sheet and is therefore more robust against future updates.
+# Doxygen will copy the style sheet files to the output directory.
+# Note: The order of the extra style sheet files is of importance (e.g. the last
+# style sheet in the list overrules the setting of the previous ones in the
+# list).
+# Note: Since the styling of scrollbars can currently not be overruled in
+# Webkit/Chromium, the styling will be left out of the default doxygen.css if
+# one or more extra stylesheets have been specified. So if scrollbar
+# customization is desired it has to be added explicitly. For an example see the
+# documentation.
+# This tag requires that the tag GENERATE_HTML is set to YES.
+
+HTML_EXTRA_STYLESHEET =
+
+# The HTML_EXTRA_FILES tag can be used to specify one or more extra images or
+# other source files which should be copied to the HTML output directory. Note
+# that these files will be copied to the base HTML output directory. Use the
+# $relpath^ marker in the HTML_HEADER and/or HTML_FOOTER files to load these
+# files. In the HTML_STYLESHEET file, use the file name only. Also note that the
+# files will be copied as-is; there are no commands or markers available.
+# This tag requires that the tag GENERATE_HTML is set to YES.
+
+HTML_EXTRA_FILES =
+
+# The HTML_COLORSTYLE tag can be used to specify if the generated HTML output
+# should be rendered with a dark or light theme.
+# Possible values are: LIGHT always generate light mode output, DARK always
+# generate dark mode output, AUTO_LIGHT automatically set the mode according to
+# the user preference, use light mode if no preference is set (the default),
+# AUTO_DARK automatically set the mode according to the user preference, use
+# dark mode if no preference is set and TOGGLE allow to user to switch between
+# light and dark mode via a button.
+# The default value is: AUTO_LIGHT.
+# This tag requires that the tag GENERATE_HTML is set to YES.
+
+HTML_COLORSTYLE = AUTO_LIGHT
+
+# The HTML_COLORSTYLE_HUE tag controls the color of the HTML output. Doxygen
+# will adjust the colors in the style sheet and background images according to
+# this color. Hue is specified as an angle on a color-wheel, see
+# https://en.wikipedia.org/wiki/Hue for more information. For instance the value
+# 0 represents red, 60 is yellow, 120 is green, 180 is cyan, 240 is blue, 300
+# purple, and 360 is red again.
+# Minimum value: 0, maximum value: 359, default value: 220.
+# This tag requires that the tag GENERATE_HTML is set to YES.
+
+HTML_COLORSTYLE_HUE = 220
+
+# The HTML_COLORSTYLE_SAT tag controls the purity (or saturation) of the colors
+# in the HTML output. For a value of 0 the output will use gray-scales only. A
+# value of 255 will produce the most vivid colors.
+# Minimum value: 0, maximum value: 255, default value: 100.
+# This tag requires that the tag GENERATE_HTML is set to YES.
+
+HTML_COLORSTYLE_SAT = 100
+
+# The HTML_COLORSTYLE_GAMMA tag controls the gamma correction applied to the
+# luminance component of the colors in the HTML output. Values below 100
+# gradually make the output lighter, whereas values above 100 make the output
+# darker. The value divided by 100 is the actual gamma applied, so 80 represents
+# a gamma of 0.8, The value 220 represents a gamma of 2.2, and 100 does not
+# change the gamma.
+# Minimum value: 40, maximum value: 240, default value: 80.
+# This tag requires that the tag GENERATE_HTML is set to YES.
+
+HTML_COLORSTYLE_GAMMA = 80
+
+# If the HTML_DYNAMIC_MENUS tag is set to YES then the generated HTML
+# documentation will contain a main index with vertical navigation menus that
+# are dynamically created via JavaScript. If disabled, the navigation index will
+# consists of multiple levels of tabs that are statically embedded in every HTML
+# page. Disable this option to support browsers that do not have JavaScript,
+# like the Qt help browser.
+# The default value is: YES.
+# This tag requires that the tag GENERATE_HTML is set to YES.
+
+HTML_DYNAMIC_MENUS = YES
+
+# If the HTML_DYNAMIC_SECTIONS tag is set to YES then the generated HTML
+# documentation will contain sections that can be hidden and shown after the
+# page has loaded.
+# The default value is: NO.
+# This tag requires that the tag GENERATE_HTML is set to YES.
+
+HTML_DYNAMIC_SECTIONS = NO
+
+# With HTML_INDEX_NUM_ENTRIES one can control the preferred number of entries
+# shown in the various tree structured indices initially; the user can expand
+# and collapse entries dynamically later on. Doxygen will expand the tree to
+# such a level that at most the specified number of entries are visible (unless
+# a fully collapsed tree already exceeds this amount). So setting the number of
+# entries 1 will produce a full collapsed tree by default. 0 is a special value
+# representing an infinite number of entries and will result in a full expanded
+# tree by default.
+# Minimum value: 0, maximum value: 9999, default value: 100.
+# This tag requires that the tag GENERATE_HTML is set to YES.
+
+HTML_INDEX_NUM_ENTRIES = 100
+
+# If the GENERATE_DOCSET tag is set to YES, additional index files will be
+# generated that can be used as input for Apple's Xcode 3 integrated development
+# environment (see:
+# https://developer.apple.com/xcode/), introduced with OSX 10.5 (Leopard). To
+# create a documentation set, doxygen will generate a Makefile in the HTML
+# output directory. Running make will produce the docset in that directory and
+# running make install will install the docset in
+# ~/Library/Developer/Shared/Documentation/DocSets so that Xcode will find it at
+# startup. See https://developer.apple.com/library/archive/featuredarticles/Doxy
+# genXcode/_index.html for more information.
+# The default value is: NO.
+# This tag requires that the tag GENERATE_HTML is set to YES.
+
+GENERATE_DOCSET = NO
+
+# This tag determines the name of the docset feed. A documentation feed provides
+# an umbrella under which multiple documentation sets from a single provider
+# (such as a company or product suite) can be grouped.
+# The default value is: Doxygen generated docs.
+# This tag requires that the tag GENERATE_DOCSET is set to YES.
+
+DOCSET_FEEDNAME = "Doxygen generated docs"
+
+# This tag determines the URL of the docset feed. A documentation feed provides
+# an umbrella under which multiple documentation sets from a single provider
+# (such as a company or product suite) can be grouped.
+# This tag requires that the tag GENERATE_DOCSET is set to YES.
+
+DOCSET_FEEDURL =
+
+# This tag specifies a string that should uniquely identify the documentation
+# set bundle. This should be a reverse domain-name style string, e.g.
+# com.mycompany.MyDocSet. Doxygen will append .docset to the name.
+# The default value is: org.doxygen.Project.
+# This tag requires that the tag GENERATE_DOCSET is set to YES.
+
+DOCSET_BUNDLE_ID = org.doxygen.Project
+
+# The DOCSET_PUBLISHER_ID tag specifies a string that should uniquely identify
+# the documentation publisher. This should be a reverse domain-name style
+# string, e.g. com.mycompany.MyDocSet.documentation.
+# The default value is: org.doxygen.Publisher.
+# This tag requires that the tag GENERATE_DOCSET is set to YES.
+
+DOCSET_PUBLISHER_ID = org.doxygen.Publisher
+
+# The DOCSET_PUBLISHER_NAME tag identifies the documentation publisher.
+# The default value is: Publisher.
+# This tag requires that the tag GENERATE_DOCSET is set to YES.
+
+DOCSET_PUBLISHER_NAME = Publisher
+
+# If the GENERATE_HTMLHELP tag is set to YES then doxygen generates three
+# additional HTML index files: index.hhp, index.hhc, and index.hhk. The
+# index.hhp is a project file that can be read by Microsoft's HTML Help Workshop
+# on Windows. In the beginning of 2021 Microsoft took the original page, with
+# a.o. the download links, offline the HTML help workshop was already many years
+# in maintenance mode). You can download the HTML help workshop from the web
+# archives at Installation executable (see:
+# http://web.archive.org/web/20160201063255/http://download.microsoft.com/downlo
+# ad/0/A/9/0A939EF6-E31C-430F-A3DF-DFAE7960D564/htmlhelp.exe).
+#
+# The HTML Help Workshop contains a compiler that can convert all HTML output
+# generated by doxygen into a single compiled HTML file (.chm). Compiled HTML
+# files are now used as the Windows 98 help format, and will replace the old
+# Windows help format (.hlp) on all Windows platforms in the future. Compressed
+# HTML files also contain an index, a table of contents, and you can search for
+# words in the documentation. The HTML workshop also contains a viewer for
+# compressed HTML files.
+# The default value is: NO.
+# This tag requires that the tag GENERATE_HTML is set to YES.
+
+GENERATE_HTMLHELP = NO
+
+# The CHM_FILE tag can be used to specify the file name of the resulting .chm
+# file. You can add a path in front of the file if the result should not be
+# written to the html output directory.
+# This tag requires that the tag GENERATE_HTMLHELP is set to YES.
+
+CHM_FILE =
+
+# The HHC_LOCATION tag can be used to specify the location (absolute path
+# including file name) of the HTML help compiler (hhc.exe). If non-empty,
+# doxygen will try to run the HTML help compiler on the generated index.hhp.
+# The file has to be specified with full path.
+# This tag requires that the tag GENERATE_HTMLHELP is set to YES.
+
+HHC_LOCATION =
+
+# The GENERATE_CHI flag controls if a separate .chi index file is generated
+# (YES) or that it should be included in the main .chm file (NO).
+# The default value is: NO.
+# This tag requires that the tag GENERATE_HTMLHELP is set to YES.
+
+GENERATE_CHI = NO
+
+# The CHM_INDEX_ENCODING is used to encode HtmlHelp index (hhk), content (hhc)
+# and project file content.
+# This tag requires that the tag GENERATE_HTMLHELP is set to YES.
+
+CHM_INDEX_ENCODING =
+
+# The BINARY_TOC flag controls whether a binary table of contents is generated
+# (YES) or a normal table of contents (NO) in the .chm file. Furthermore it
+# enables the Previous and Next buttons.
+# The default value is: NO.
+# This tag requires that the tag GENERATE_HTMLHELP is set to YES.
+
+BINARY_TOC = NO
+
+# The TOC_EXPAND flag can be set to YES to add extra items for group members to
+# the table of contents of the HTML help documentation and to the tree view.
+# The default value is: NO.
+# This tag requires that the tag GENERATE_HTMLHELP is set to YES.
+
+TOC_EXPAND = NO
+
+# The SITEMAP_URL tag is used to specify the full URL of the place where the
+# generated documentation will be placed on the server by the user during the
+# deployment of the documentation. The generated sitemap is called sitemap.xml
+# and placed on the directory specified by HTML_OUTPUT. In case no SITEMAP_URL
+# is specified no sitemap is generated. For information about the sitemap
+# protocol see https://www.sitemaps.org
+# This tag requires that the tag GENERATE_HTML is set to YES.
+
+SITEMAP_URL =
+
+# If the GENERATE_QHP tag is set to YES and both QHP_NAMESPACE and
+# QHP_VIRTUAL_FOLDER are set, an additional index file will be generated that
+# can be used as input for Qt's qhelpgenerator to generate a Qt Compressed Help
+# (.qch) of the generated HTML documentation.
+# The default value is: NO.
+# This tag requires that the tag GENERATE_HTML is set to YES.
+
+GENERATE_QHP = NO
+
+# If the QHG_LOCATION tag is specified, the QCH_FILE tag can be used to specify
+# the file name of the resulting .qch file. The path specified is relative to
+# the HTML output folder.
+# This tag requires that the tag GENERATE_QHP is set to YES.
+
+QCH_FILE =
+
+# The QHP_NAMESPACE tag specifies the namespace to use when generating Qt Help
+# Project output. For more information please see Qt Help Project / Namespace
+# (see:
+# https://doc.qt.io/archives/qt-4.8/qthelpproject.html#namespace).
+# The default value is: org.doxygen.Project.
+# This tag requires that the tag GENERATE_QHP is set to YES.
+
+QHP_NAMESPACE = org.doxygen.Project
+
+# The QHP_VIRTUAL_FOLDER tag specifies the namespace to use when generating Qt
+# Help Project output. For more information please see Qt Help Project / Virtual
+# Folders (see:
+# https://doc.qt.io/archives/qt-4.8/qthelpproject.html#virtual-folders).
+# The default value is: doc.
+# This tag requires that the tag GENERATE_QHP is set to YES.
+
+QHP_VIRTUAL_FOLDER = doc
+
+# If the QHP_CUST_FILTER_NAME tag is set, it specifies the name of a custom
+# filter to add. For more information please see Qt Help Project / Custom
+# Filters (see:
+# https://doc.qt.io/archives/qt-4.8/qthelpproject.html#custom-filters).
+# This tag requires that the tag GENERATE_QHP is set to YES.
+
+QHP_CUST_FILTER_NAME =
+
+# The QHP_CUST_FILTER_ATTRS tag specifies the list of the attributes of the
+# custom filter to add. For more information please see Qt Help Project / Custom
+# Filters (see:
+# https://doc.qt.io/archives/qt-4.8/qthelpproject.html#custom-filters).
+# This tag requires that the tag GENERATE_QHP is set to YES.
+
+QHP_CUST_FILTER_ATTRS =
+
+# The QHP_SECT_FILTER_ATTRS tag specifies the list of the attributes this
+# project's filter section matches. Qt Help Project / Filter Attributes (see:
+# https://doc.qt.io/archives/qt-4.8/qthelpproject.html#filter-attributes).
+# This tag requires that the tag GENERATE_QHP is set to YES.
+
+QHP_SECT_FILTER_ATTRS =
+
+# The QHG_LOCATION tag can be used to specify the location (absolute path
+# including file name) of Qt's qhelpgenerator. If non-empty doxygen will try to
+# run qhelpgenerator on the generated .qhp file.
+# This tag requires that the tag GENERATE_QHP is set to YES.
+
+QHG_LOCATION =
+
+# If the GENERATE_ECLIPSEHELP tag is set to YES, additional index files will be
+# generated, together with the HTML files, they form an Eclipse help plugin. To
+# install this plugin and make it available under the help contents menu in
+# Eclipse, the contents of the directory containing the HTML and XML files needs
+# to be copied into the plugins directory of eclipse. The name of the directory
+# within the plugins directory should be the same as the ECLIPSE_DOC_ID value.
+# After copying Eclipse needs to be restarted before the help appears.
+# The default value is: NO.
+# This tag requires that the tag GENERATE_HTML is set to YES.
+
+GENERATE_ECLIPSEHELP = NO
+
+# A unique identifier for the Eclipse help plugin. When installing the plugin
+# the directory name containing the HTML and XML files should also have this
+# name. Each documentation set should have its own identifier.
+# The default value is: org.doxygen.Project.
+# This tag requires that the tag GENERATE_ECLIPSEHELP is set to YES.
+
+ECLIPSE_DOC_ID = org.doxygen.Project
+
+# If you want full control over the layout of the generated HTML pages it might
+# be necessary to disable the index and replace it with your own. The
+# DISABLE_INDEX tag can be used to turn on/off the condensed index (tabs) at top
+# of each HTML page. A value of NO enables the index and the value YES disables
+# it. Since the tabs in the index contain the same information as the navigation
+# tree, you can set this option to YES if you also set GENERATE_TREEVIEW to YES.
+# The default value is: NO.
+# This tag requires that the tag GENERATE_HTML is set to YES.
+
+DISABLE_INDEX = NO
+
+# The GENERATE_TREEVIEW tag is used to specify whether a tree-like index
+# structure should be generated to display hierarchical information. If the tag
+# value is set to YES, a side panel will be generated containing a tree-like
+# index structure (just like the one that is generated for HTML Help). For this
+# to work a browser that supports JavaScript, DHTML, CSS and frames is required
+# (i.e. any modern browser). Windows users are probably better off using the
+# HTML help feature. Via custom style sheets (see HTML_EXTRA_STYLESHEET) one can
+# further fine tune the look of the index (see "Fine-tuning the output"). As an
+# example, the default style sheet generated by doxygen has an example that
+# shows how to put an image at the root of the tree instead of the PROJECT_NAME.
+# Since the tree basically has the same information as the tab index, you could
+# consider setting DISABLE_INDEX to YES when enabling this option.
+# The default value is: NO.
+# This tag requires that the tag GENERATE_HTML is set to YES.
+
+GENERATE_TREEVIEW = NO
+
+# When both GENERATE_TREEVIEW and DISABLE_INDEX are set to YES, then the
+# FULL_SIDEBAR option determines if the side bar is limited to only the treeview
+# area (value NO) or if it should extend to the full height of the window (value
+# YES). Setting this to YES gives a layout similar to
+# https://docs.readthedocs.io with more room for contents, but less room for the
+# project logo, title, and description. If either GENERATE_TREEVIEW or
+# DISABLE_INDEX is set to NO, this option has no effect.
+# The default value is: NO.
+# This tag requires that the tag GENERATE_HTML is set to YES.
+
+FULL_SIDEBAR = NO
+
+# The ENUM_VALUES_PER_LINE tag can be used to set the number of enum values that
+# doxygen will group on one line in the generated HTML documentation.
+#
+# Note that a value of 0 will completely suppress the enum values from appearing
+# in the overview section.
+# Minimum value: 0, maximum value: 20, default value: 4.
+# This tag requires that the tag GENERATE_HTML is set to YES.
+
+ENUM_VALUES_PER_LINE = 4
+
+# If the treeview is enabled (see GENERATE_TREEVIEW) then this tag can be used
+# to set the initial width (in pixels) of the frame in which the tree is shown.
+# Minimum value: 0, maximum value: 1500, default value: 250.
+# This tag requires that the tag GENERATE_HTML is set to YES.
+
+TREEVIEW_WIDTH = 250
+
+# If the EXT_LINKS_IN_WINDOW option is set to YES, doxygen will open links to
+# external symbols imported via tag files in a separate window.
+# The default value is: NO.
+# This tag requires that the tag GENERATE_HTML is set to YES.
+
+EXT_LINKS_IN_WINDOW = NO
+
+# If the OBFUSCATE_EMAILS tag is set to YES, doxygen will obfuscate email
+# addresses.
+# The default value is: YES.
+# This tag requires that the tag GENERATE_HTML is set to YES.
+
+OBFUSCATE_EMAILS = YES
+
+# If the HTML_FORMULA_FORMAT option is set to svg, doxygen will use the pdf2svg
+# tool (see https://github.com/dawbarton/pdf2svg) or inkscape (see
+# https://inkscape.org) to generate formulas as SVG images instead of PNGs for
+# the HTML output. These images will generally look nicer at scaled resolutions.
+# Possible values are: png (the default) and svg (looks nicer but requires the
+# pdf2svg or inkscape tool).
+# The default value is: png.
+# This tag requires that the tag GENERATE_HTML is set to YES.
+
+HTML_FORMULA_FORMAT = png
+
+# Use this tag to change the font size of LaTeX formulas included as images in
+# the HTML documentation. When you change the font size after a successful
+# doxygen run you need to manually remove any form_*.png images from the HTML
+# output directory to force them to be regenerated.
+# Minimum value: 8, maximum value: 50, default value: 10.
+# This tag requires that the tag GENERATE_HTML is set to YES.
+
+FORMULA_FONTSIZE = 10
+
+# The FORMULA_MACROFILE can contain LaTeX \newcommand and \renewcommand commands
+# to create new LaTeX commands to be used in formulas as building blocks. See
+# the section "Including formulas" for details.
+
+FORMULA_MACROFILE =
+
+# Enable the USE_MATHJAX option to render LaTeX formulas using MathJax (see
+# https://www.mathjax.org) which uses client side JavaScript for the rendering
+# instead of using pre-rendered bitmaps. Use this if you do not have LaTeX
+# installed or if you want to formulas look prettier in the HTML output. When
+# enabled you may also need to install MathJax separately and configure the path
+# to it using the MATHJAX_RELPATH option.
+# The default value is: NO.
+# This tag requires that the tag GENERATE_HTML is set to YES.
+
+USE_MATHJAX = NO
+
+# With MATHJAX_VERSION it is possible to specify the MathJax version to be used.
+# Note that the different versions of MathJax have different requirements with
+# regards to the different settings, so it is possible that also other MathJax
+# settings have to be changed when switching between the different MathJax
+# versions.
+# Possible values are: MathJax_2 and MathJax_3.
+# The default value is: MathJax_2.
+# This tag requires that the tag USE_MATHJAX is set to YES.
+
+MATHJAX_VERSION = MathJax_2
+
+# When MathJax is enabled you can set the default output format to be used for
+# the MathJax output. For more details about the output format see MathJax
+# version 2 (see:
+# http://docs.mathjax.org/en/v2.7-latest/output.html) and MathJax version 3
+# (see:
+# http://docs.mathjax.org/en/latest/web/components/output.html).
+# Possible values are: HTML-CSS (which is slower, but has the best
+# compatibility. This is the name for Mathjax version 2, for MathJax version 3
+# this will be translated into chtml), NativeMML (i.e. MathML. Only supported
+# for NathJax 2. For MathJax version 3 chtml will be used instead.), chtml (This
+# is the name for Mathjax version 3, for MathJax version 2 this will be
+# translated into HTML-CSS) and SVG.
+# The default value is: HTML-CSS.
+# This tag requires that the tag USE_MATHJAX is set to YES.
+
+MATHJAX_FORMAT = HTML-CSS
+
+# When MathJax is enabled you need to specify the location relative to the HTML
+# output directory using the MATHJAX_RELPATH option. The destination directory
+# should contain the MathJax.js script. For instance, if the mathjax directory
+# is located at the same level as the HTML output directory, then
+# MATHJAX_RELPATH should be ../mathjax. The default value points to the MathJax
+# Content Delivery Network so you can quickly see the result without installing
+# MathJax. However, it is strongly recommended to install a local copy of
+# MathJax from https://www.mathjax.org before deployment. The default value is:
+# - in case of MathJax version 2: https://cdn.jsdelivr.net/npm/mathjax@2
+# - in case of MathJax version 3: https://cdn.jsdelivr.net/npm/mathjax@3
+# This tag requires that the tag USE_MATHJAX is set to YES.
+
+MATHJAX_RELPATH =
+
+# The MATHJAX_EXTENSIONS tag can be used to specify one or more MathJax
+# extension names that should be enabled during MathJax rendering. For example
+# for MathJax version 2 (see
+# https://docs.mathjax.org/en/v2.7-latest/tex.html#tex-and-latex-extensions):
+# MATHJAX_EXTENSIONS = TeX/AMSmath TeX/AMSsymbols
+# For example for MathJax version 3 (see
+# http://docs.mathjax.org/en/latest/input/tex/extensions/index.html):
+# MATHJAX_EXTENSIONS = ams
+# This tag requires that the tag USE_MATHJAX is set to YES.
+
+MATHJAX_EXTENSIONS =
+
+# The MATHJAX_CODEFILE tag can be used to specify a file with javascript pieces
+# of code that will be used on startup of the MathJax code. See the MathJax site
+# (see:
+# http://docs.mathjax.org/en/v2.7-latest/output.html) for more details. For an
+# example see the documentation.
+# This tag requires that the tag USE_MATHJAX is set to YES.
+
+MATHJAX_CODEFILE =
+
+# When the SEARCHENGINE tag is enabled doxygen will generate a search box for
+# the HTML output. The underlying search engine uses javascript and DHTML and
+# should work on any modern browser. Note that when using HTML help
+# (GENERATE_HTMLHELP), Qt help (GENERATE_QHP), or docsets (GENERATE_DOCSET)
+# there is already a search function so this one should typically be disabled.
+# For large projects the javascript based search engine can be slow, then
+# enabling SERVER_BASED_SEARCH may provide a better solution. It is possible to
+# search using the keyboard; to jump to the search box use + S
+# (what the is depends on the OS and browser, but it is typically
+# , /, or both). Inside the search box use the to jump into the search results window, the results can be navigated
+# using the . Press to select an item or to cancel
+# the search. The filter options can be selected when the cursor is inside the
+# search box by pressing +. Also here use the
+# to select a filter and or to activate or cancel the filter
+# option.
+# The default value is: YES.
+# This tag requires that the tag GENERATE_HTML is set to YES.
+
+SEARCHENGINE = YES
+
+# When the SERVER_BASED_SEARCH tag is enabled the search engine will be
+# implemented using a web server instead of a web client using JavaScript. There
+# are two flavors of web server based searching depending on the EXTERNAL_SEARCH
+# setting. When disabled, doxygen will generate a PHP script for searching and
+# an index file used by the script. When EXTERNAL_SEARCH is enabled the indexing
+# and searching needs to be provided by external tools. See the section
+# "External Indexing and Searching" for details.
+# The default value is: NO.
+# This tag requires that the tag SEARCHENGINE is set to YES.
+
+SERVER_BASED_SEARCH = NO
+
+# When EXTERNAL_SEARCH tag is enabled doxygen will no longer generate the PHP
+# script for searching. Instead the search results are written to an XML file
+# which needs to be processed by an external indexer. Doxygen will invoke an
+# external search engine pointed to by the SEARCHENGINE_URL option to obtain the
+# search results.
+#
+# Doxygen ships with an example indexer (doxyindexer) and search engine
+# (doxysearch.cgi) which are based on the open source search engine library
+# Xapian (see:
+# https://xapian.org/).
+#
+# See the section "External Indexing and Searching" for details.
+# The default value is: NO.
+# This tag requires that the tag SEARCHENGINE is set to YES.
+
+EXTERNAL_SEARCH = NO
+
+# The SEARCHENGINE_URL should point to a search engine hosted by a web server
+# which will return the search results when EXTERNAL_SEARCH is enabled.
+#
+# Doxygen ships with an example indexer (doxyindexer) and search engine
+# (doxysearch.cgi) which are based on the open source search engine library
+# Xapian (see:
+# https://xapian.org/). See the section "External Indexing and Searching" for
+# details.
+# This tag requires that the tag SEARCHENGINE is set to YES.
+
+SEARCHENGINE_URL =
+
+# When SERVER_BASED_SEARCH and EXTERNAL_SEARCH are both enabled the unindexed
+# search data is written to a file for indexing by an external tool. With the
+# SEARCHDATA_FILE tag the name of this file can be specified.
+# The default file is: searchdata.xml.
+# This tag requires that the tag SEARCHENGINE is set to YES.
+
+SEARCHDATA_FILE = searchdata.xml
+
+# When SERVER_BASED_SEARCH and EXTERNAL_SEARCH are both enabled the
+# EXTERNAL_SEARCH_ID tag can be used as an identifier for the project. This is
+# useful in combination with EXTRA_SEARCH_MAPPINGS to search through multiple
+# projects and redirect the results back to the right project.
+# This tag requires that the tag SEARCHENGINE is set to YES.
+
+EXTERNAL_SEARCH_ID =
+
+# The EXTRA_SEARCH_MAPPINGS tag can be used to enable searching through doxygen
+# projects other than the one defined by this configuration file, but that are
+# all added to the same external search index. Each project needs to have a
+# unique id set via EXTERNAL_SEARCH_ID. The search mapping then maps the id of
+# to a relative location where the documentation can be found. The format is:
+# EXTRA_SEARCH_MAPPINGS = tagname1=loc1 tagname2=loc2 ...
+# This tag requires that the tag SEARCHENGINE is set to YES.
+
+EXTRA_SEARCH_MAPPINGS =
+
+#---------------------------------------------------------------------------
+# Configuration options related to the LaTeX output
+#---------------------------------------------------------------------------
+
+# If the GENERATE_LATEX tag is set to YES, doxygen will generate LaTeX output.
+# The default value is: YES.
+
+GENERATE_LATEX = NO
+
+# The LATEX_OUTPUT tag is used to specify where the LaTeX docs will be put. If a
+# relative path is entered the value of OUTPUT_DIRECTORY will be put in front of
+# it.
+# The default directory is: latex.
+# This tag requires that the tag GENERATE_LATEX is set to YES.
+
+LATEX_OUTPUT = latex
+
+# The LATEX_CMD_NAME tag can be used to specify the LaTeX command name to be
+# invoked.
+#
+# Note that when not enabling USE_PDFLATEX the default is latex when enabling
+# USE_PDFLATEX the default is pdflatex and when in the later case latex is
+# chosen this is overwritten by pdflatex. For specific output languages the
+# default can have been set differently, this depends on the implementation of
+# the output language.
+# This tag requires that the tag GENERATE_LATEX is set to YES.
+
+LATEX_CMD_NAME =
+
+# The MAKEINDEX_CMD_NAME tag can be used to specify the command name to generate
+# index for LaTeX.
+# Note: This tag is used in the Makefile / make.bat.
+# See also: LATEX_MAKEINDEX_CMD for the part in the generated output file
+# (.tex).
+# The default file is: makeindex.
+# This tag requires that the tag GENERATE_LATEX is set to YES.
+
+MAKEINDEX_CMD_NAME = makeindex
+
+# The LATEX_MAKEINDEX_CMD tag can be used to specify the command name to
+# generate index for LaTeX. In case there is no backslash (\) as first character
+# it will be automatically added in the LaTeX code.
+# Note: This tag is used in the generated output file (.tex).
+# See also: MAKEINDEX_CMD_NAME for the part in the Makefile / make.bat.
+# The default value is: makeindex.
+# This tag requires that the tag GENERATE_LATEX is set to YES.
+
+LATEX_MAKEINDEX_CMD = makeindex
+
+# If the COMPACT_LATEX tag is set to YES, doxygen generates more compact LaTeX
+# documents. This may be useful for small projects and may help to save some
+# trees in general.
+# The default value is: NO.
+# This tag requires that the tag GENERATE_LATEX is set to YES.
+
+COMPACT_LATEX = NO
+
+# The PAPER_TYPE tag can be used to set the paper type that is used by the
+# printer.
+# Possible values are: a4 (210 x 297 mm), letter (8.5 x 11 inches), legal (8.5 x
+# 14 inches) and executive (7.25 x 10.5 inches).
+# The default value is: a4.
+# This tag requires that the tag GENERATE_LATEX is set to YES.
+
+PAPER_TYPE = a4
+
+# The EXTRA_PACKAGES tag can be used to specify one or more LaTeX package names
+# that should be included in the LaTeX output. The package can be specified just
+# by its name or with the correct syntax as to be used with the LaTeX
+# \usepackage command. To get the times font for instance you can specify :
+# EXTRA_PACKAGES=times or EXTRA_PACKAGES={times}
+# To use the option intlimits with the amsmath package you can specify:
+# EXTRA_PACKAGES=[intlimits]{amsmath}
+# If left blank no extra packages will be included.
+# This tag requires that the tag GENERATE_LATEX is set to YES.
+
+EXTRA_PACKAGES =
+
+# The LATEX_HEADER tag can be used to specify a user-defined LaTeX header for
+# the generated LaTeX document. The header should contain everything until the
+# first chapter. If it is left blank doxygen will generate a standard header. It
+# is highly recommended to start with a default header using
+# doxygen -w latex new_header.tex new_footer.tex new_stylesheet.sty
+# and then modify the file new_header.tex. See also section "Doxygen usage" for
+# information on how to generate the default header that doxygen normally uses.
+#
+# Note: Only use a user-defined header if you know what you are doing!
+# Note: The header is subject to change so you typically have to regenerate the
+# default header when upgrading to a newer version of doxygen. The following
+# commands have a special meaning inside the header (and footer): For a
+# description of the possible markers and block names see the documentation.
+# This tag requires that the tag GENERATE_LATEX is set to YES.
+
+LATEX_HEADER =
+
+# The LATEX_FOOTER tag can be used to specify a user-defined LaTeX footer for
+# the generated LaTeX document. The footer should contain everything after the
+# last chapter. If it is left blank doxygen will generate a standard footer. See
+# LATEX_HEADER for more information on how to generate a default footer and what
+# special commands can be used inside the footer. See also section "Doxygen
+# usage" for information on how to generate the default footer that doxygen
+# normally uses. Note: Only use a user-defined footer if you know what you are
+# doing!
+# This tag requires that the tag GENERATE_LATEX is set to YES.
+
+LATEX_FOOTER =
+
+# The LATEX_EXTRA_STYLESHEET tag can be used to specify additional user-defined
+# LaTeX style sheets that are included after the standard style sheets created
+# by doxygen. Using this option one can overrule certain style aspects. Doxygen
+# will copy the style sheet files to the output directory.
+# Note: The order of the extra style sheet files is of importance (e.g. the last
+# style sheet in the list overrules the setting of the previous ones in the
+# list).
+# This tag requires that the tag GENERATE_LATEX is set to YES.
+
+LATEX_EXTRA_STYLESHEET =
+
+# The LATEX_EXTRA_FILES tag can be used to specify one or more extra images or
+# other source files which should be copied to the LATEX_OUTPUT output
+# directory. Note that the files will be copied as-is; there are no commands or
+# markers available.
+# This tag requires that the tag GENERATE_LATEX is set to YES.
+
+LATEX_EXTRA_FILES =
+
+# If the PDF_HYPERLINKS tag is set to YES, the LaTeX that is generated is
+# prepared for conversion to PDF (using ps2pdf or pdflatex). The PDF file will
+# contain links (just like the HTML output) instead of page references. This
+# makes the output suitable for online browsing using a PDF viewer.
+# The default value is: YES.
+# This tag requires that the tag GENERATE_LATEX is set to YES.
+
+PDF_HYPERLINKS = YES
+
+# If the USE_PDFLATEX tag is set to YES, doxygen will use the engine as
+# specified with LATEX_CMD_NAME to generate the PDF file directly from the LaTeX
+# files. Set this option to YES, to get a higher quality PDF documentation.
+#
+# See also section LATEX_CMD_NAME for selecting the engine.
+# The default value is: YES.
+# This tag requires that the tag GENERATE_LATEX is set to YES.
+
+USE_PDFLATEX = YES
+
+# The LATEX_BATCHMODE tag ignals the behavior of LaTeX in case of an error.
+# Possible values are: NO same as ERROR_STOP, YES same as BATCH, BATCH In batch
+# mode nothing is printed on the terminal, errors are scrolled as if is
+# hit at every error; missing files that TeX tries to input or request from
+# keyboard input (\read on a not open input stream) cause the job to abort,
+# NON_STOP In nonstop mode the diagnostic message will appear on the terminal,
+# but there is no possibility of user interaction just like in batch mode,
+# SCROLL In scroll mode, TeX will stop only for missing files to input or if
+# keyboard input is necessary and ERROR_STOP In errorstop mode, TeX will stop at
+# each error, asking for user intervention.
+# The default value is: NO.
+# This tag requires that the tag GENERATE_LATEX is set to YES.
+
+LATEX_BATCHMODE = NO
+
+# If the LATEX_HIDE_INDICES tag is set to YES then doxygen will not include the
+# index chapters (such as File Index, Compound Index, etc.) in the output.
+# The default value is: NO.
+# This tag requires that the tag GENERATE_LATEX is set to YES.
+
+LATEX_HIDE_INDICES = NO
+
+# The LATEX_BIB_STYLE tag can be used to specify the style to use for the
+# bibliography, e.g. plainnat, or ieeetr. See
+# https://en.wikipedia.org/wiki/BibTeX and \cite for more info.
+# The default value is: plain.
+# This tag requires that the tag GENERATE_LATEX is set to YES.
+
+LATEX_BIB_STYLE = plain
+
+# The LATEX_EMOJI_DIRECTORY tag is used to specify the (relative or absolute)
+# path from which the emoji images will be read. If a relative path is entered,
+# it will be relative to the LATEX_OUTPUT directory. If left blank the
+# LATEX_OUTPUT directory will be used.
+# This tag requires that the tag GENERATE_LATEX is set to YES.
+
+LATEX_EMOJI_DIRECTORY =
+
+#---------------------------------------------------------------------------
+# Configuration options related to the RTF output
+#---------------------------------------------------------------------------
+
+# If the GENERATE_RTF tag is set to YES, doxygen will generate RTF output. The
+# RTF output is optimized for Word 97 and may not look too pretty with other RTF
+# readers/editors.
+# The default value is: NO.
+
+GENERATE_RTF = YES
+
+# The RTF_OUTPUT tag is used to specify where the RTF docs will be put. If a
+# relative path is entered the value of OUTPUT_DIRECTORY will be put in front of
+# it.
+# The default directory is: rtf.
+# This tag requires that the tag GENERATE_RTF is set to YES.
+
+RTF_OUTPUT = rtf
+
+# If the COMPACT_RTF tag is set to YES, doxygen generates more compact RTF
+# documents. This may be useful for small projects and may help to save some
+# trees in general.
+# The default value is: NO.
+# This tag requires that the tag GENERATE_RTF is set to YES.
+
+COMPACT_RTF = NO
+
+# If the RTF_HYPERLINKS tag is set to YES, the RTF that is generated will
+# contain hyperlink fields. The RTF file will contain links (just like the HTML
+# output) instead of page references. This makes the output suitable for online
+# browsing using Word or some other Word compatible readers that support those
+# fields.
+#
+# Note: WordPad (write) and others do not support links.
+# The default value is: NO.
+# This tag requires that the tag GENERATE_RTF is set to YES.
+
+RTF_HYPERLINKS = NO
+
+# Load stylesheet definitions from file. Syntax is similar to doxygen's
+# configuration file, i.e. a series of assignments. You only have to provide
+# replacements, missing definitions are set to their default value.
+#
+# See also section "Doxygen usage" for information on how to generate the
+# default style sheet that doxygen normally uses.
+# This tag requires that the tag GENERATE_RTF is set to YES.
+
+RTF_STYLESHEET_FILE =
+
+# Set optional variables used in the generation of an RTF document. Syntax is
+# similar to doxygen's configuration file. A template extensions file can be
+# generated using doxygen -e rtf extensionFile.
+# This tag requires that the tag GENERATE_RTF is set to YES.
+
+RTF_EXTENSIONS_FILE =
+
+#---------------------------------------------------------------------------
+# Configuration options related to the man page output
+#---------------------------------------------------------------------------
+
+# If the GENERATE_MAN tag is set to YES, doxygen will generate man pages for
+# classes and files.
+# The default value is: NO.
+
+GENERATE_MAN = NO
+
+# The MAN_OUTPUT tag is used to specify where the man pages will be put. If a
+# relative path is entered the value of OUTPUT_DIRECTORY will be put in front of
+# it. A directory man3 will be created inside the directory specified by
+# MAN_OUTPUT.
+# The default directory is: man.
+# This tag requires that the tag GENERATE_MAN is set to YES.
+
+MAN_OUTPUT = man
+
+# The MAN_EXTENSION tag determines the extension that is added to the generated
+# man pages. In case the manual section does not start with a number, the number
+# 3 is prepended. The dot (.) at the beginning of the MAN_EXTENSION tag is
+# optional.
+# The default value is: .3.
+# This tag requires that the tag GENERATE_MAN is set to YES.
+
+MAN_EXTENSION = .3
+
+# The MAN_SUBDIR tag determines the name of the directory created within
+# MAN_OUTPUT in which the man pages are placed. If defaults to man followed by
+# MAN_EXTENSION with the initial . removed.
+# This tag requires that the tag GENERATE_MAN is set to YES.
+
+MAN_SUBDIR =
+
+# If the MAN_LINKS tag is set to YES and doxygen generates man output, then it
+# will generate one additional man file for each entity documented in the real
+# man page(s). These additional files only source the real man page, but without
+# them the man command would be unable to find the correct page.
+# The default value is: NO.
+# This tag requires that the tag GENERATE_MAN is set to YES.
+
+MAN_LINKS = NO
+
+#---------------------------------------------------------------------------
+# Configuration options related to the XML output
+#---------------------------------------------------------------------------
+
+# If the GENERATE_XML tag is set to YES, doxygen will generate an XML file that
+# captures the structure of the code including all documentation.
+# The default value is: NO.
+
+GENERATE_XML = NO
+
+# The XML_OUTPUT tag is used to specify where the XML pages will be put. If a
+# relative path is entered the value of OUTPUT_DIRECTORY will be put in front of
+# it.
+# The default directory is: xml.
+# This tag requires that the tag GENERATE_XML is set to YES.
+
+XML_OUTPUT = xml
+
+# If the XML_PROGRAMLISTING tag is set to YES, doxygen will dump the program
+# listings (including syntax highlighting and cross-referencing information) to
+# the XML output. Note that enabling this will significantly increase the size
+# of the XML output.
+# The default value is: YES.
+# This tag requires that the tag GENERATE_XML is set to YES.
+
+XML_PROGRAMLISTING = YES
+
+# If the XML_NS_MEMB_FILE_SCOPE tag is set to YES, doxygen will include
+# namespace members in file scope as well, matching the HTML output.
+# The default value is: NO.
+# This tag requires that the tag GENERATE_XML is set to YES.
+
+XML_NS_MEMB_FILE_SCOPE = NO
+
+#---------------------------------------------------------------------------
+# Configuration options related to the DOCBOOK output
+#---------------------------------------------------------------------------
+
+# If the GENERATE_DOCBOOK tag is set to YES, doxygen will generate Docbook files
+# that can be used to generate PDF.
+# The default value is: NO.
+
+GENERATE_DOCBOOK = NO
+
+# The DOCBOOK_OUTPUT tag is used to specify where the Docbook pages will be put.
+# If a relative path is entered the value of OUTPUT_DIRECTORY will be put in
+# front of it.
+# The default directory is: docbook.
+# This tag requires that the tag GENERATE_DOCBOOK is set to YES.
+
+DOCBOOK_OUTPUT = docbook
+
+#---------------------------------------------------------------------------
+# Configuration options for the AutoGen Definitions output
+#---------------------------------------------------------------------------
+
+# If the GENERATE_AUTOGEN_DEF tag is set to YES, doxygen will generate an
+# AutoGen Definitions (see https://autogen.sourceforge.net/) file that captures
+# the structure of the code including all documentation. Note that this feature
+# is still experimental and incomplete at the moment.
+# The default value is: NO.
+
+GENERATE_AUTOGEN_DEF = NO
+
+#---------------------------------------------------------------------------
+# Configuration options related to Sqlite3 output
+#---------------------------------------------------------------------------
+
+#---------------------------------------------------------------------------
+# Configuration options related to the Perl module output
+#---------------------------------------------------------------------------
+
+# If the GENERATE_PERLMOD tag is set to YES, doxygen will generate a Perl module
+# file that captures the structure of the code including all documentation.
+#
+# Note that this feature is still experimental and incomplete at the moment.
+# The default value is: NO.
+
+GENERATE_PERLMOD = NO
+
+# If the PERLMOD_LATEX tag is set to YES, doxygen will generate the necessary
+# Makefile rules, Perl scripts and LaTeX code to be able to generate PDF and DVI
+# output from the Perl module output.
+# The default value is: NO.
+# This tag requires that the tag GENERATE_PERLMOD is set to YES.
+
+PERLMOD_LATEX = NO
+
+# If the PERLMOD_PRETTY tag is set to YES, the Perl module output will be nicely
+# formatted so it can be parsed by a human reader. This is useful if you want to
+# understand what is going on. On the other hand, if this tag is set to NO, the
+# size of the Perl module output will be much smaller and Perl will parse it
+# just the same.
+# The default value is: YES.
+# This tag requires that the tag GENERATE_PERLMOD is set to YES.
+
+PERLMOD_PRETTY = YES
+
+# The names of the make variables in the generated doxyrules.make file are
+# prefixed with the string contained in PERLMOD_MAKEVAR_PREFIX. This is useful
+# so different doxyrules.make files included by the same Makefile don't
+# overwrite each other's variables.
+# This tag requires that the tag GENERATE_PERLMOD is set to YES.
+
+PERLMOD_MAKEVAR_PREFIX =
+
+#---------------------------------------------------------------------------
+# Configuration options related to the preprocessor
+#---------------------------------------------------------------------------
+
+# If the ENABLE_PREPROCESSING tag is set to YES, doxygen will evaluate all
+# C-preprocessor directives found in the sources and include files.
+# The default value is: YES.
+
+ENABLE_PREPROCESSING = YES
+
+# If the MACRO_EXPANSION tag is set to YES, doxygen will expand all macro names
+# in the source code. If set to NO, only conditional compilation will be
+# performed. Macro expansion can be done in a controlled way by setting
+# EXPAND_ONLY_PREDEF to YES.
+# The default value is: NO.
+# This tag requires that the tag ENABLE_PREPROCESSING is set to YES.
+
+MACRO_EXPANSION = NO
+
+# If the EXPAND_ONLY_PREDEF and MACRO_EXPANSION tags are both set to YES then
+# the macro expansion is limited to the macros specified with the PREDEFINED and
+# EXPAND_AS_DEFINED tags.
+# The default value is: NO.
+# This tag requires that the tag ENABLE_PREPROCESSING is set to YES.
+
+EXPAND_ONLY_PREDEF = NO
+
+# If the SEARCH_INCLUDES tag is set to YES, the include files in the
+# INCLUDE_PATH will be searched if a #include is found.
+# The default value is: YES.
+# This tag requires that the tag ENABLE_PREPROCESSING is set to YES.
+
+SEARCH_INCLUDES = YES
+
+# The INCLUDE_PATH tag can be used to specify one or more directories that
+# contain include files that are not input files but should be processed by the
+# preprocessor. Note that the INCLUDE_PATH is not recursive, so the setting of
+# RECURSIVE has no effect here.
+# This tag requires that the tag SEARCH_INCLUDES is set to YES.
+
+INCLUDE_PATH =
+
+# You can use the INCLUDE_FILE_PATTERNS tag to specify one or more wildcard
+# patterns (like *.h and *.hpp) to filter out the header-files in the
+# directories. If left blank, the patterns specified with FILE_PATTERNS will be
+# used.
+# This tag requires that the tag ENABLE_PREPROCESSING is set to YES.
+
+INCLUDE_FILE_PATTERNS =
+
+# The PREDEFINED tag can be used to specify one or more macro names that are
+# defined before the preprocessor is started (similar to the -D option of e.g.
+# gcc). The argument of the tag is a list of macros of the form: name or
+# name=definition (no spaces). If the definition and the "=" are omitted, "=1"
+# is assumed. To prevent a macro definition from being undefined via #undef or
+# recursively expanded use the := operator instead of the = operator.
+# This tag requires that the tag ENABLE_PREPROCESSING is set to YES.
+
+PREDEFINED =
+
+# If the MACRO_EXPANSION and EXPAND_ONLY_PREDEF tags are set to YES then this
+# tag can be used to specify a list of macro names that should be expanded. The
+# macro definition that is found in the sources will be used. Use the PREDEFINED
+# tag if you want to use a different macro definition that overrules the
+# definition found in the source code.
+# This tag requires that the tag ENABLE_PREPROCESSING is set to YES.
+
+EXPAND_AS_DEFINED =
+
+# If the SKIP_FUNCTION_MACROS tag is set to YES then doxygen's preprocessor will
+# remove all references to function-like macros that are alone on a line, have
+# an all uppercase name, and do not end with a semicolon. Such function macros
+# are typically used for boiler-plate code, and will confuse the parser if not
+# removed.
+# The default value is: YES.
+# This tag requires that the tag ENABLE_PREPROCESSING is set to YES.
+
+SKIP_FUNCTION_MACROS = YES
+
+#---------------------------------------------------------------------------
+# Configuration options related to external references
+#---------------------------------------------------------------------------
+
+# The TAGFILES tag can be used to specify one or more tag files. For each tag
+# file the location of the external documentation should be added. The format of
+# a tag file without this location is as follows:
+# TAGFILES = file1 file2 ...
+# Adding location for the tag files is done as follows:
+# TAGFILES = file1=loc1 "file2 = loc2" ...
+# where loc1 and loc2 can be relative or absolute paths or URLs. See the
+# section "Linking to external documentation" for more information about the use
+# of tag files.
+# Note: Each tag file must have a unique name (where the name does NOT include
+# the path). If a tag file is not located in the directory in which doxygen is
+# run, you must also specify the path to the tagfile here.
+
+TAGFILES =
+
+# When a file name is specified after GENERATE_TAGFILE, doxygen will create a
+# tag file that is based on the input files it reads. See section "Linking to
+# external documentation" for more information about the usage of tag files.
+
+GENERATE_TAGFILE =
+
+# If the ALLEXTERNALS tag is set to YES, all external class will be listed in
+# the class index. If set to NO, only the inherited external classes will be
+# listed.
+# The default value is: NO.
+
+ALLEXTERNALS = NO
+
+# If the EXTERNAL_GROUPS tag is set to YES, all external groups will be listed
+# in the modules index. If set to NO, only the current project's groups will be
+# listed.
+# The default value is: YES.
+
+EXTERNAL_GROUPS = YES
+
+# If the EXTERNAL_PAGES tag is set to YES, all external pages will be listed in
+# the related pages index. If set to NO, only the current project's pages will
+# be listed.
+# The default value is: YES.
+
+EXTERNAL_PAGES = YES
+
+#---------------------------------------------------------------------------
+# Configuration options related to diagram generator tools
+#---------------------------------------------------------------------------
+
+# If set to YES the inheritance and collaboration graphs will hide inheritance
+# and usage relations if the target is undocumented or is not a class.
+# The default value is: YES.
+
+HIDE_UNDOC_RELATIONS = YES
+
+# If you set the HAVE_DOT tag to YES then doxygen will assume the dot tool is
+# available from the path. This tool is part of Graphviz (see:
+# https://www.graphviz.org/), a graph visualization toolkit from AT&T and Lucent
+# Bell Labs. The other options in this section have no effect if this option is
+# set to NO
+# The default value is: NO.
+
+HAVE_DOT = NO
+
+# The DOT_NUM_THREADS specifies the number of dot invocations doxygen is allowed
+# to run in parallel. When set to 0 doxygen will base this on the number of
+# processors available in the system. You can set it explicitly to a value
+# larger than 0 to get control over the balance between CPU load and processing
+# speed.
+# Minimum value: 0, maximum value: 32, default value: 0.
+# This tag requires that the tag HAVE_DOT is set to YES.
+
+DOT_NUM_THREADS = 0
+
+# DOT_COMMON_ATTR is common attributes for nodes, edges and labels of
+# subgraphs. When you want a differently looking font in the dot files that
+# doxygen generates you can specify fontname, fontcolor and fontsize attributes.
+# For details please see Node,
+# Edge and Graph Attributes specification You need to make sure dot is able
+# to find the font, which can be done by putting it in a standard location or by
+# setting the DOTFONTPATH environment variable or by setting DOT_FONTPATH to the
+# directory containing the font. Default graphviz fontsize is 14.
+# The default value is: fontname=Helvetica,fontsize=10.
+# This tag requires that the tag HAVE_DOT is set to YES.
+
+DOT_COMMON_ATTR = "fontname=Helvetica,fontsize=10"
+
+# DOT_EDGE_ATTR is concatenated with DOT_COMMON_ATTR. For elegant style you can
+# add 'arrowhead=open, arrowtail=open, arrowsize=0.5'. Complete documentation about
+# arrows shapes.
+# The default value is: labelfontname=Helvetica,labelfontsize=10.
+# This tag requires that the tag HAVE_DOT is set to YES.
+
+DOT_EDGE_ATTR = "labelfontname=Helvetica,labelfontsize=10"
+
+# DOT_NODE_ATTR is concatenated with DOT_COMMON_ATTR. For view without boxes
+# around nodes set 'shape=plain' or 'shape=plaintext' Shapes specification
+# The default value is: shape=box,height=0.2,width=0.4.
+# This tag requires that the tag HAVE_DOT is set to YES.
+
+DOT_NODE_ATTR = "shape=box,height=0.2,width=0.4"
+
+# You can set the path where dot can find font specified with fontname in
+# DOT_COMMON_ATTR and others dot attributes.
+# This tag requires that the tag HAVE_DOT is set to YES.
+
+DOT_FONTPATH =
+
+# If the CLASS_GRAPH tag is set to YES or GRAPH or BUILTIN then doxygen will
+# generate a graph for each documented class showing the direct and indirect
+# inheritance relations. In case the CLASS_GRAPH tag is set to YES or GRAPH and
+# HAVE_DOT is enabled as well, then dot will be used to draw the graph. In case
+# the CLASS_GRAPH tag is set to YES and HAVE_DOT is disabled or if the
+# CLASS_GRAPH tag is set to BUILTIN, then the built-in generator will be used.
+# If the CLASS_GRAPH tag is set to TEXT the direct and indirect inheritance
+# relations will be shown as texts / links.
+# Possible values are: NO, YES, TEXT, GRAPH and BUILTIN.
+# The default value is: YES.
+
+CLASS_GRAPH = YES
+
+# If the COLLABORATION_GRAPH tag is set to YES then doxygen will generate a
+# graph for each documented class showing the direct and indirect implementation
+# dependencies (inheritance, containment, and class references variables) of the
+# class with other documented classes.
+# The default value is: YES.
+# This tag requires that the tag HAVE_DOT is set to YES.
+
+COLLABORATION_GRAPH = YES
+
+# If the GROUP_GRAPHS tag is set to YES then doxygen will generate a graph for
+# groups, showing the direct groups dependencies. See also the chapter Grouping
+# in the manual.
+# The default value is: YES.
+# This tag requires that the tag HAVE_DOT is set to YES.
+
+GROUP_GRAPHS = YES
+
+# If the UML_LOOK tag is set to YES, doxygen will generate inheritance and
+# collaboration diagrams in a style similar to the OMG's Unified Modeling
+# Language.
+# The default value is: NO.
+# This tag requires that the tag HAVE_DOT is set to YES.
+
+UML_LOOK = NO
+
+# If the UML_LOOK tag is enabled, the fields and methods are shown inside the
+# class node. If there are many fields or methods and many nodes the graph may
+# become too big to be useful. The UML_LIMIT_NUM_FIELDS threshold limits the
+# number of items for each type to make the size more manageable. Set this to 0
+# for no limit. Note that the threshold may be exceeded by 50% before the limit
+# is enforced. So when you set the threshold to 10, up to 15 fields may appear,
+# but if the number exceeds 15, the total amount of fields shown is limited to
+# 10.
+# Minimum value: 0, maximum value: 100, default value: 10.
+# This tag requires that the tag UML_LOOK is set to YES.
+
+UML_LIMIT_NUM_FIELDS = 10
+
+# If the DOT_UML_DETAILS tag is set to NO, doxygen will show attributes and
+# methods without types and arguments in the UML graphs. If the DOT_UML_DETAILS
+# tag is set to YES, doxygen will add type and arguments for attributes and
+# methods in the UML graphs. If the DOT_UML_DETAILS tag is set to NONE, doxygen
+# will not generate fields with class member information in the UML graphs. The
+# class diagrams will look similar to the default class diagrams but using UML
+# notation for the relationships.
+# Possible values are: NO, YES and NONE.
+# The default value is: NO.
+# This tag requires that the tag UML_LOOK is set to YES.
+
+DOT_UML_DETAILS = NO
+
+# The DOT_WRAP_THRESHOLD tag can be used to set the maximum number of characters
+# to display on a single line. If the actual line length exceeds this threshold
+# significantly it will wrapped across multiple lines. Some heuristics are apply
+# to avoid ugly line breaks.
+# Minimum value: 0, maximum value: 1000, default value: 17.
+# This tag requires that the tag HAVE_DOT is set to YES.
+
+DOT_WRAP_THRESHOLD = 17
+
+# If the TEMPLATE_RELATIONS tag is set to YES then the inheritance and
+# collaboration graphs will show the relations between templates and their
+# instances.
+# The default value is: NO.
+# This tag requires that the tag HAVE_DOT is set to YES.
+
+TEMPLATE_RELATIONS = NO
+
+# If the INCLUDE_GRAPH, ENABLE_PREPROCESSING and SEARCH_INCLUDES tags are set to
+# YES then doxygen will generate a graph for each documented file showing the
+# direct and indirect include dependencies of the file with other documented
+# files.
+# The default value is: YES.
+# This tag requires that the tag HAVE_DOT is set to YES.
+
+INCLUDE_GRAPH = YES
+
+# If the INCLUDED_BY_GRAPH, ENABLE_PREPROCESSING and SEARCH_INCLUDES tags are
+# set to YES then doxygen will generate a graph for each documented file showing
+# the direct and indirect include dependencies of the file with other documented
+# files.
+# The default value is: YES.
+# This tag requires that the tag HAVE_DOT is set to YES.
+
+INCLUDED_BY_GRAPH = YES
+
+# If the CALL_GRAPH tag is set to YES then doxygen will generate a call
+# dependency graph for every global function or class method.
+#
+# Note that enabling this option will significantly increase the time of a run.
+# So in most cases it will be better to enable call graphs for selected
+# functions only using the \callgraph command. Disabling a call graph can be
+# accomplished by means of the command \hidecallgraph.
+# The default value is: NO.
+# This tag requires that the tag HAVE_DOT is set to YES.
+
+CALL_GRAPH = NO
+
+# If the CALLER_GRAPH tag is set to YES then doxygen will generate a caller
+# dependency graph for every global function or class method.
+#
+# Note that enabling this option will significantly increase the time of a run.
+# So in most cases it will be better to enable caller graphs for selected
+# functions only using the \callergraph command. Disabling a caller graph can be
+# accomplished by means of the command \hidecallergraph.
+# The default value is: NO.
+# This tag requires that the tag HAVE_DOT is set to YES.
+
+CALLER_GRAPH = NO
+
+# If the GRAPHICAL_HIERARCHY tag is set to YES then doxygen will graphical
+# hierarchy of all classes instead of a textual one.
+# The default value is: YES.
+# This tag requires that the tag HAVE_DOT is set to YES.
+
+GRAPHICAL_HIERARCHY = YES
+
+# If the DIRECTORY_GRAPH tag is set to YES then doxygen will show the
+# dependencies a directory has on other directories in a graphical way. The
+# dependency relations are determined by the #include relations between the
+# files in the directories.
+# The default value is: YES.
+# This tag requires that the tag HAVE_DOT is set to YES.
+
+DIRECTORY_GRAPH = YES
+
+# The DIR_GRAPH_MAX_DEPTH tag can be used to limit the maximum number of levels
+# of child directories generated in directory dependency graphs by dot.
+# Minimum value: 1, maximum value: 25, default value: 1.
+# This tag requires that the tag DIRECTORY_GRAPH is set to YES.
+
+DIR_GRAPH_MAX_DEPTH = 1
+
+# The DOT_IMAGE_FORMAT tag can be used to set the image format of the images
+# generated by dot. For an explanation of the image formats see the section
+# output formats in the documentation of the dot tool (Graphviz (see:
+# https://www.graphviz.org/)).
+# Note: If you choose svg you need to set HTML_FILE_EXTENSION to xhtml in order
+# to make the SVG files visible in IE 9+ (other browsers do not have this
+# requirement).
+# Possible values are: png, jpg, gif, svg, png:gd, png:gd:gd, png:cairo,
+# png:cairo:gd, png:cairo:cairo, png:cairo:gdiplus, png:gdiplus and
+# png:gdiplus:gdiplus.
+# The default value is: png.
+# This tag requires that the tag HAVE_DOT is set to YES.
+
+DOT_IMAGE_FORMAT = png
+
+# If DOT_IMAGE_FORMAT is set to svg, then this option can be set to YES to
+# enable generation of interactive SVG images that allow zooming and panning.
+#
+# Note that this requires a modern browser other than Internet Explorer. Tested
+# and working are Firefox, Chrome, Safari, and Opera.
+# Note: For IE 9+ you need to set HTML_FILE_EXTENSION to xhtml in order to make
+# the SVG files visible. Older versions of IE do not have SVG support.
+# The default value is: NO.
+# This tag requires that the tag HAVE_DOT is set to YES.
+
+INTERACTIVE_SVG = NO
+
+# The DOT_PATH tag can be used to specify the path where the dot tool can be
+# found. If left blank, it is assumed the dot tool can be found in the path.
+# This tag requires that the tag HAVE_DOT is set to YES.
+
+DOT_PATH =
+
+# The DOTFILE_DIRS tag can be used to specify one or more directories that
+# contain dot files that are included in the documentation (see the \dotfile
+# command).
+# This tag requires that the tag HAVE_DOT is set to YES.
+
+DOTFILE_DIRS =
+
+# You can include diagrams made with dia in doxygen documentation. Doxygen will
+# then run dia to produce the diagram and insert it in the documentation. The
+# DIA_PATH tag allows you to specify the directory where the dia binary resides.
+# If left empty dia is assumed to be found in the default search path.
+
+DIA_PATH =
+
+# The DIAFILE_DIRS tag can be used to specify one or more directories that
+# contain dia files that are included in the documentation (see the \diafile
+# command).
+
+DIAFILE_DIRS =
+
+# When using plantuml, the PLANTUML_JAR_PATH tag should be used to specify the
+# path where java can find the plantuml.jar file or to the filename of jar file
+# to be used. If left blank, it is assumed PlantUML is not used or called during
+# a preprocessing step. Doxygen will generate a warning when it encounters a
+# \startuml command in this case and will not generate output for the diagram.
+
+PLANTUML_JAR_PATH =
+
+# When using plantuml, the PLANTUML_CFG_FILE tag can be used to specify a
+# configuration file for plantuml.
+
+PLANTUML_CFG_FILE =
+
+# When using plantuml, the specified paths are searched for files specified by
+# the !include statement in a plantuml block.
+
+PLANTUML_INCLUDE_PATH =
+
+# The DOT_GRAPH_MAX_NODES tag can be used to set the maximum number of nodes
+# that will be shown in the graph. If the number of nodes in a graph becomes
+# larger than this value, doxygen will truncate the graph, which is visualized
+# by representing a node as a red box. Note that doxygen if the number of direct
+# children of the root node in a graph is already larger than
+# DOT_GRAPH_MAX_NODES then the graph will not be shown at all. Also note that
+# the size of a graph can be further restricted by MAX_DOT_GRAPH_DEPTH.
+# Minimum value: 0, maximum value: 10000, default value: 50.
+# This tag requires that the tag HAVE_DOT is set to YES.
+
+DOT_GRAPH_MAX_NODES = 50
+
+# The MAX_DOT_GRAPH_DEPTH tag can be used to set the maximum depth of the graphs
+# generated by dot. A depth value of 3 means that only nodes reachable from the
+# root by following a path via at most 3 edges will be shown. Nodes that lay
+# further from the root node will be omitted. Note that setting this option to 1
+# or 2 may greatly reduce the computation time needed for large code bases. Also
+# note that the size of a graph can be further restricted by
+# DOT_GRAPH_MAX_NODES. Using a depth of 0 means no depth restriction.
+# Minimum value: 0, maximum value: 1000, default value: 0.
+# This tag requires that the tag HAVE_DOT is set to YES.
+
+MAX_DOT_GRAPH_DEPTH = 0
+
+# Set the DOT_MULTI_TARGETS tag to YES to allow dot to generate multiple output
+# files in one run (i.e. multiple -o and -T options on the command line). This
+# makes dot run faster, but since only newer versions of dot (>1.8.10) support
+# this, this feature is disabled by default.
+# The default value is: NO.
+# This tag requires that the tag HAVE_DOT is set to YES.
+
+DOT_MULTI_TARGETS = NO
+
+# If the GENERATE_LEGEND tag is set to YES doxygen will generate a legend page
+# explaining the meaning of the various boxes and arrows in the dot generated
+# graphs.
+# Note: This tag requires that UML_LOOK isn't set, i.e. the doxygen internal
+# graphical representation for inheritance and collaboration diagrams is used.
+# The default value is: YES.
+# This tag requires that the tag HAVE_DOT is set to YES.
+
+GENERATE_LEGEND = YES
+
+# If the DOT_CLEANUP tag is set to YES, doxygen will remove the intermediate
+# files that are used to generate the various graphs.
+#
+# Note: This setting is not only used for dot files but also for msc temporary
+# files.
+# The default value is: YES.
+
+DOT_CLEANUP = YES
+
+# You can define message sequence charts within doxygen comments using the \msc
+# command. If the MSCGEN_TOOL tag is left empty (the default), then doxygen will
+# use a built-in version of mscgen tool to produce the charts. Alternatively,
+# the MSCGEN_TOOL tag can also specify the name an external tool. For instance,
+# specifying prog as the value, doxygen will call the tool as prog -T
+# -o . The external tool should support
+# output file formats "png", "eps", "svg", and "ismap".
+
+MSCGEN_TOOL =
+
+# The MSCFILE_DIRS tag can be used to specify one or more directories that
+# contain msc files that are included in the documentation (see the \mscfile
+# command).
+
+MSCFILE_DIRS =
diff --git a/Projects/EFC_EcatDriver/device/cm.c b/Projects/EFC_EcatDriver/device/cm.c
new file mode 100644
index 0000000..d51b972
--- /dev/null
+++ b/Projects/EFC_EcatDriver/device/cm.c
@@ -0,0 +1,137 @@
+//#############################################################################
+//
+// FILE: cm.c
+//
+// TITLE: Communication manager setup for examples.
+//
+//#############################################################################
+//
+//
+// $Copyright:
+// Copyright (C) 2022 Texas Instruments Incorporated - http://www.ti.com
+//
+// Redistribution and use in source and binary forms, with or without
+// modification, are permitted provided that the following conditions
+// are met:
+//
+// Redistributions of source code must retain the above copyright
+// notice, this list of conditions and the following disclaimer.
+//
+// Redistributions in binary form must reproduce the above copyright
+// notice, this list of conditions and the following disclaimer in the
+// documentation and/or other materials provided with the
+// distribution.
+//
+// Neither the name of Texas Instruments Incorporated nor the names of
+// its contributors may be used to endorse or promote products derived
+// from this software without specific prior written permission.
+//
+// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+// $
+//#############################################################################
+
+//
+// Included Files
+//
+#include "cm.h"
+
+//*****************************************************************************
+//
+// Function to initialize the device. Primarily initializes system control to a
+// known state by disabling the watchdog and enabling the clocks to the peripherals.
+//
+//*****************************************************************************
+void CM_init(void)
+{
+ //
+ // Disable the watchdog
+ //
+ SysCtl_disableWatchdog();
+
+#ifdef _FLASH
+ //
+ // Copy time critical code and flash setup code to RAM. This includes the
+ // following functions: InitFlash();
+ //
+ // The RamfuncsLoadStart, RamfuncsLoadSize, and RamfuncsRunStart symbols
+ // are created by the linker. Refer to the device .cmd file.
+ //
+ memcpy(&RamfuncsRunStart, &RamfuncsLoadStart, (size_t)&RamfuncsLoadSize);
+
+ //
+ // Call Flash Initialization to setup flash waitstates. This function must
+ // reside in RAM.
+ //
+ Flash_initModule(FLASH0CTRL_BASE, FLASH0ECC_BASE, DEVICE_FLASH_WAITSTATES);
+#endif
+
+ //
+ // Turn on all peripherals
+ //
+ CM_enableAllPeripherals();
+
+ //
+ // Sets the NVIC vector table offset address.
+ //
+#ifdef _FLASH
+ Interrupt_setVectorTableOffset((uint32_t)vectorTableFlash);
+#else
+ Interrupt_setVectorTableOffset((uint32_t)vectorTableRAM);
+#endif
+
+}
+
+//*****************************************************************************
+//
+// Function to turn on all peripherals, enabling reads and writes to the
+// peripherals' registers.
+//
+// Note that to reduce power, unused peripherals should be disabled.
+//
+//*****************************************************************************
+void CM_enableAllPeripherals(void)
+{
+
+ SysCtl_enablePeripheral(SYSCTL_PERIPH_CLK_UART0);
+ SysCtl_enablePeripheral(SYSCTL_PERIPH_CLK_SSI0);
+ SysCtl_enablePeripheral(SYSCTL_PERIPH_CLK_I2C0);
+ SysCtl_enablePeripheral(SYSCTL_PERIPH_CLK_USB);
+
+ SysCtl_enablePeripheral(SYSCTL_PERIPH_CLK_ENET);
+ SysCtl_enablePeripheral(SYSCTL_PERIPH_CLK_ECAT);
+ SysCtl_enablePeripheral(SYSCTL_PERIPH_CLK_CAN_A);
+ SysCtl_enablePeripheral(SYSCTL_PERIPH_CLK_CAN_B);
+ SysCtl_enablePeripheral(SYSCTL_PERIPH_CLK_MCAN_A);
+
+ SysCtl_enablePeripheral(SYSCTL_PERIPH_CLK_TIMER0);
+ SysCtl_enablePeripheral(SYSCTL_PERIPH_CLK_TIMER1);
+ SysCtl_enablePeripheral(SYSCTL_PERIPH_CLK_TIMER2);
+ SysCtl_enablePeripheral(SYSCTL_PERIPH_CLK_UDMA);
+ SysCtl_enablePeripheral(SYSCTL_PERIPH_CLK_AESIP);
+ SysCtl_enablePeripheral(SYSCTL_PERIPH_CLK_GCRC);
+
+}
+
+////*****************************************************************************
+////
+//// Error handling function to be called when an ASSERT is violated
+////
+////*****************************************************************************
+//void __error__(const char *filename, uint32_t line)
+//{
+// //
+// // An ASSERT condition was evaluated as false. You can use the filename and
+// // line parameters to determine what went wrong.
+// //
+// __asm(" bkpt #0");
+//}
diff --git a/Projects/EFC_EcatDriver/device/cm.h b/Projects/EFC_EcatDriver/device/cm.h
new file mode 100644
index 0000000..1b80f67
--- /dev/null
+++ b/Projects/EFC_EcatDriver/device/cm.h
@@ -0,0 +1,112 @@
+//#############################################################################
+//
+// FILE: cm.h
+//
+// TITLE: Communication manager setup for examples.
+//
+//#############################################################################
+//
+//
+// $Copyright:
+// Copyright (C) 2022 Texas Instruments Incorporated - http://www.ti.com
+//
+// Redistribution and use in source and binary forms, with or without
+// modification, are permitted provided that the following conditions
+// are met:
+//
+// Redistributions of source code must retain the above copyright
+// notice, this list of conditions and the following disclaimer.
+//
+// Redistributions in binary form must reproduce the above copyright
+// notice, this list of conditions and the following disclaimer in the
+// documentation and/or other materials provided with the
+// distribution.
+//
+// Neither the name of Texas Instruments Incorporated nor the names of
+// its contributors may be used to endorse or promote products derived
+// from this software without specific prior written permission.
+//
+// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+// $
+//#############################################################################
+
+//
+// Included Files
+//
+#include "driverlib_cm.h"
+
+//*****************************************************************************
+//
+// Defines related to clock configuration. This frequency will be the CM clock
+// frequency driven by c28x.
+//
+//*****************************************************************************
+
+#define CM_CLK_FREQ 125000000U
+
+//*****************************************************************************
+//
+// Macro to call SysCtl_delay() to achieve a delay in microseconds. The macro
+// will convert the desired delay in microseconds to the count value expected
+// by the function. \b x is the number of microseconds to delay.
+// The SysCtl_delay() function takes around 3 cycles per iteration plus 9
+// cycles of overhead which needs to be accounted for when converting the
+// microseconds delay into the number of delay loop iterations passed to the
+// SysCtl_delay() function.
+//
+// Note that 3 cycles per iteration is valid if SysCtl_delay function resides
+// in CxRAM. SxRAM is 2x slower than CxRAM and hence will consume 6 cycles per
+// iteration.
+//
+//*****************************************************************************
+#define DEVICE_DELAY_US(x) SysCtl_delay(((((long double)(x)) / (1000000.0L / \
+ (long double)CM_CLK_FREQ)) - 9.0L) / 3.0L)
+
+//*****************************************************************************
+//
+// Defines, Globals, and Header Includes related to Flash Support
+//
+//*****************************************************************************
+#ifdef _FLASH
+#include
+
+extern uint16_t RamfuncsLoadStart;
+extern uint16_t RamfuncsLoadEnd;
+extern uint16_t RamfuncsLoadSize;
+extern uint16_t RamfuncsRunStart;
+extern uint16_t RamfuncsRunEnd;
+extern uint16_t RamfuncsRunSize;
+
+#define DEVICE_FLASH_WAITSTATES 2
+
+#endif
+
+//*****************************************************************************
+//
+// Defines for pin numbers and other GPIO configuration
+//
+//*****************************************************************************
+//
+// LEDs
+//
+#define DEVICE_GPIO_PIN_LED1 31U // GPIO number for LD2
+#define DEVICE_GPIO_PIN_LED2 34U // GPIO number for LD3
+
+//*****************************************************************************
+//
+// Function Prototypes
+//
+//*****************************************************************************
+extern void CM_init(void);
+extern void CM_enableAllPeripherals(void);
+extern void __error__(const char *filename, uint32_t line);
diff --git a/Projects/EFC_EcatDriver/device/driverlib.h b/Projects/EFC_EcatDriver/device/driverlib.h
new file mode 100644
index 0000000..6fbc580
--- /dev/null
+++ b/Projects/EFC_EcatDriver/device/driverlib.h
@@ -0,0 +1,95 @@
+//#############################################################################
+//
+// FILE: driverlib.h
+//
+// TITLE: C28x Driverlib Header File
+//
+//#############################################################################
+//
+//
+// $Copyright:
+// Copyright (C) 2022 Texas Instruments Incorporated - http://www.ti.com
+//
+// Redistribution and use in source and binary forms, with or without
+// modification, are permitted provided that the following conditions
+// are met:
+//
+// Redistributions of source code must retain the above copyright
+// notice, this list of conditions and the following disclaimer.
+//
+// Redistributions in binary form must reproduce the above copyright
+// notice, this list of conditions and the following disclaimer in the
+// documentation and/or other materials provided with the
+// distribution.
+//
+// Neither the name of Texas Instruments Incorporated nor the names of
+// its contributors may be used to endorse or promote products derived
+// from this software without specific prior written permission.
+//
+// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+// $
+//#############################################################################
+#ifndef DRIVERLIB_H
+#define DRIVERLIB_H
+
+#include "inc/hw_memmap.h"
+
+#include "adc.h"
+#include "asysctl.h"
+#include "bgcrc.h"
+#include "can.h"
+#include "cla.h"
+#include "clb.h"
+#include "cmpss.h"
+#include "cpu.h"
+#include "cputimer.h"
+#include "dac.h"
+#include "dcc.h"
+#include "dcsm.h"
+#include "debug.h"
+#include "dma.h"
+#include "ecap.h"
+#include "emif.h"
+#include "epwm.h"
+#include "eqep.h"
+#include "erad.h"
+#include "escss.h"
+#include "flash.h"
+#include "fsi.h"
+#include "gpio.h"
+#include "hrcap.h"
+#include "hrpwm.h"
+#include "i2c.h"
+#include "interrupt.h"
+#include "ipc.h"
+#include "mcbsp.h"
+#include "memcfg.h"
+#include "pin_map.h"
+#include "pmbus.h"
+#include "sci.h"
+#include "sdfm.h"
+#include "spi.h"
+#include "sysctl.h"
+#include "usb.h"
+#include "xbar.h"
+
+//
+// Include MCAN driverlib header only if bitfield header is not already included
+//
+#ifndef F2838x_MCAN_H
+#include "mcan.h"
+#endif
+
+#include "driver_inclusive_terminology_mapping.h"
+
+#endif // end of DRIVERLIB_H definition
diff --git a/Projects/EFC_EcatDriver/doc/.placeholder b/Projects/EFC_EcatDriver/doc/.placeholder
new file mode 100644
index 0000000..e69de29
diff --git a/Projects/EFC_EcatDriver/include/efc_ecat.h b/Projects/EFC_EcatDriver/include/efc_ecat.h
new file mode 100644
index 0000000..5e2cd13
--- /dev/null
+++ b/Projects/EFC_EcatDriver/include/efc_ecat.h
@@ -0,0 +1,159 @@
+/*
+ * efc_ecat.h
+ *
+ * Created on: 20 Nov 2023
+ * Author: titov
+ */
+
+#ifndef INCLUDE_EFC_ECAT_H_
+#define INCLUDE_EFC_ECAT_H_
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+#include
+#include
+
+#include "../src/ssc/applInterface.h"
+
+/**
+ * @defgroup Api API
+ *
+ * @{
+ */
+
+/**
+ * @defgroup Common Общий API
+ *
+ * @{
+ */
+
+/**
+ * @brief Инициализация EtherCat драйвера
+ *
+ * Вызов функции инициализации должен предшествовать всем оставльным функциям драйвера
+ *
+ * @return @c true при успешной инициализации; иначе @c false
+ */
+bool efc_ecat_init(void);
+
+/**
+ * @brief Денициализация EtherCat драйвера
+ *
+ * После вызова драйвера обращения к его функциям запрещено
+ *
+ * @return @c void
+ */
+void efc_ecat_fini(void);
+
+/**
+ * @brief Обработчик циклических задач EtherCat драйвера
+ *
+ * Обработчик должен исполняться в низкоприоритетном потоке
+ *
+ * @return void
+ */
+void efc_ecat_loop(void);
+
+/** @} */ /* Common */
+
+/**
+ * @defgroup EthercatStateMachine Обработка событий машины состояния API
+ *
+ * @{
+ */
+
+typedef enum ESMS1 {
+ PreOp = 1,
+ SafeOp = 2,
+ Op = 3
+} EcatStateMachineStates;
+
+bool efc_ecat_state_pending( EcatStateMachineStates state );
+void efc_ecat_state_approve( EcatStateMachineStates state );
+
+typedef void (*efc_ecat_state_pend_handler)( EcatStateMachineStates state );
+void efc_ecat_set_state_pend_handler( efc_ecat_state_pend_handler pf );
+
+/** @} */ /* EthercatStateMachine */
+
+typedef void (*efc_ecat_update_sync0_time)( uint32_t time_in_us );
+void efc_ecat_set_sync0_time_update_handler( efc_ecat_update_sync0_time pf );
+
+void efc_ecat_set_device_id( uint16_t device_id );
+
+typedef void (*efc_ecat_application_handler)( void );
+void efc_ecat_set_application_handler( efc_ecat_application_handler pf );
+
+/**
+ * @defgroup ProcessDataInterface Обработка данных реального времени
+ *
+ * @{
+ */
+
+
+
+
+/** @} */ /* ProcessDataInterface */
+
+/**
+ * @defgroup ServiceDataInterface Обработка сервисных данных
+ *
+ * @{
+ */
+
+typedef UINT16 Index;
+typedef UINT8 SubIndex;
+typedef UINT32 Size;
+typedef UINT8 CompliteAccess;
+
+typedef UINT16 Data;
+
+typedef UINT8 ResultType;
+
+enum ResultCode {
+ Done = 0x00, //!<Успешное завершение.
+ ToggleBitNotChanged = 0x01, /**< Index of "Toggle bit not changed" */
+ SdoProtocolTimeout = 0x02, /**< Index of "SDO timeout" */
+ CommandSpecifierUnknown = 0x03, /**< Index of "Command specifier unknown" */
+ OutOfMemory = 0x04, /**< Index of "Out of memory" */
+ UnsupportedAccess = 0x05, /**< Index of "Unsupported Access" */
+ WriteOnlyEntry = 0x06, /**< Index of "Write only entry" */
+ ReadOnlyEntry = 0x07, /**< Index of "Read only entry" */
+ ObjectNotExisting = 0x08, /**< Index of "Object not existing" */
+ ObjectCantBePdoMapped = 0x09, /**< Index of "Object can not be mapped to PDO" */
+ MappedObjectsExceedPdo = 0x0A, /**< Index of "Mapped Object exceeds PDO" */
+ ParamIsIncompatible = 0x0B, /**< Index of "Parameter is incompatible" */
+ InternalDeviceIncompatibility = 0x0C, /**< Index of "Device incompatibility" */
+ HardwareError = 0x0D, /**< Index of "Hardware error" */
+ ParamLengthError = 0x0E, /**< Index of "Parameter length error" */
+ ParamLengthTooLong = 0x0F, /**< Index of "Parameter is too long" */
+ ParamLengthTooShort = 0x10, /**< Index of "Parameter is too short" */
+ SubindexNotExisting = 0x11, /**< Index of "Subindex (Entry) not exists" */
+ ValueExceeded = 0x12, /**< Index of "Value exceeds" */
+ ValueTooGreat = 0x13, /**< Index of "Value is too great" */
+ ValueTooSmall = 0x14, /**< Index of "Value is too small" */
+ ModuleIdListNotMatch = 0x15, /**< Index of "Unequal Module Id list" */
+ MaxValueIsLessThanMinValue = 0x16, /**< Index of "Value is less than minimum value" */
+ GeneralError = 0x17, /**< Index of "General error" */
+ DataCannotBeReadWrite = 0x18, /**< Index of "Data can not be read or written" */
+ DataCannotBeAccessedWithLocalControl = 0x19, /**< Index of "Data can not be accessed because of local control" */
+ DataCannotBeReadWriteInCurrentState = 0x1A, /**< Index of "Data can not be read or written in the current state" */
+ NoObjectDictionaryIsPresent = 0x1B, /**< Index of "Object is not in the object dictionary" */
+ EntryCantBeWrittenSi0Not0 = 0x1C, /**< Index of "Entry can not be written because Subindex0 is not 0" */
+ CompleteAccessNotSupported = 0x1D, /**< The object can not be accessed via complete access */
+ Working = 0xFF /**< Index of application is handling the SDO request */
+};
+
+typedef ResultType (* InterfaceRead)( Index index, SubIndex subindex, Size size, Data * data, CompliteAccess complete_access );
+typedef ResultType (* InterfaceWrite)( Index index, SubIndex subindex, Size size, Data * data, CompliteAccess complete_access );
+
+
+/** @} */ /* Api */
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif /* INCLUDE_EFC_ECAT_H_ */
diff --git a/Projects/EFC_EcatDriver/src/ethercat_slave_api.c b/Projects/EFC_EcatDriver/src/ethercat_slave_api.c
new file mode 100644
index 0000000..2721970
--- /dev/null
+++ b/Projects/EFC_EcatDriver/src/ethercat_slave_api.c
@@ -0,0 +1,705 @@
+/*
+ * ethercat_slave_api.c
+ *
+ * Created on: 20 нояб. 2023 г.
+ * Author: titov
+ */
+
+#include
+
+#include "ssc/ecat_def.h"
+#include "ssc/ecatappl.h"
+#include "ssc/sdoserv.h"
+#include "ssc/objdef.h"
+
+/******************************************************************************
+* Object 0x1600 : OutputMapping
+******************************************************************************/
+/**
+* \addtogroup 0x1600 0x1600 | OutputMapping
+* @{
+* \brief Object 0x1600 (OutputMapping) definition
+*/
+
+/**
+* \brief Object entry descriptions
+*
+* SubIndex 0
+* SubIndex 1 - map 0x7000 SIO 32bit
+* SubIndex 2 - map 0x7001 SIO 8bit
+* SubIndex 3 - 8bit padding
+*/
+OBJCONST TSDOINFOENTRYDESC OBJMEM asEntryDesc0x1600[] = {
+{ DEFTYPE_UNSIGNED8 , 0x8 , ACCESS_READ },
+
+{ DEFTYPE_UNSIGNED32 , 0x20 , ACCESS_READ },
+{ DEFTYPE_UNSIGNED32 , 0x20 , ACCESS_READ },
+{ DEFTYPE_UNSIGNED32 , 0x20 , ACCESS_READ },
+{ DEFTYPE_UNSIGNED32 , 0x20 , ACCESS_READ },
+
+{ DEFTYPE_UNSIGNED32 , 0x20 , ACCESS_READ },
+{ DEFTYPE_UNSIGNED32 , 0x20 , ACCESS_READ },
+{ DEFTYPE_UNSIGNED32 , 0x20 , ACCESS_READ },
+{ DEFTYPE_UNSIGNED32 , 0x20 , ACCESS_READ },
+
+{ DEFTYPE_UNSIGNED32 , 0x20 , ACCESS_READ },
+{ DEFTYPE_UNSIGNED32 , 0x20 , ACCESS_READ },
+{ DEFTYPE_UNSIGNED32 , 0x20 , ACCESS_READ },
+{ DEFTYPE_UNSIGNED32 , 0x20 , ACCESS_READ },
+
+{ DEFTYPE_UNSIGNED32 , 0x20 , ACCESS_READ },
+{ DEFTYPE_UNSIGNED32 , 0x20 , ACCESS_READ },
+{ DEFTYPE_UNSIGNED32 , 0x20 , ACCESS_READ },
+{ DEFTYPE_UNSIGNED32 , 0x20 , ACCESS_READ }
+
+
+};
+
+/**
+* \brief Object/Entry names
+*/
+OBJCONST UCHAR OBJMEM aName0x1600[] = "OutputMapping\000"
+"SubIndex 001\000"
+"SubIndex 002\000"
+"SubIndex 003\000"
+"SubIndex 004\000"
+"SubIndex 005\000"
+"SubIndex 006\000"
+"SubIndex 007\000"
+"SubIndex 008\000"
+"SubIndex 009\000"
+"SubIndex 010\000"
+"SubIndex 011\000"
+"SubIndex 012\000"
+"SubIndex 013\000"
+"SubIndex 014\000"
+"SubIndex 015\000"
+"SubIndex 016\000\377";
+
+/**
+* \brief Object structure
+*/
+typedef struct OBJ_STRUCT_PACKED_START {
+UINT16 u16SubIndex0;
+UINT32 aEntries[16];
+} OBJ_STRUCT_PACKED_END
+TOBJ1600;
+
+/**
+* \brief Object variable
+*/
+TOBJ1600 OutputMapping0x1600;
+/** @}*/
+
+
+
+/******************************************************************************
+* Object 0x1A00 : InputMapping
+******************************************************************************/
+/**
+* \addtogroup 0x1A00 0x1A00 | InputMapping
+* @{
+* \brief Object 0x1A00 (InputMapping) definition
+*/
+
+/**
+* \brief Object entry descriptions
+*
+* SubIndex 0
+* SubIndex 1 - map SI 0bit
+* SubIndex 2 - 8bit padding
+* SubIndex 3 - map 0x6001 SIO 16bit
+*/
+OBJCONST TSDOINFOENTRYDESC OBJMEM asEntryDesc0x1A00[] = {
+{ DEFTYPE_UNSIGNED8 , 0x8 , ACCESS_READ },
+
+{ DEFTYPE_UNSIGNED32 , 0x20 , ACCESS_READ },
+{ DEFTYPE_UNSIGNED32 , 0x20 , ACCESS_READ },
+{ DEFTYPE_UNSIGNED32 , 0x20 , ACCESS_READ },
+{ DEFTYPE_UNSIGNED32 , 0x20 , ACCESS_READ },
+
+{ DEFTYPE_UNSIGNED32 , 0x20 , ACCESS_READ },
+{ DEFTYPE_UNSIGNED32 , 0x20 , ACCESS_READ },
+{ DEFTYPE_UNSIGNED32 , 0x20 , ACCESS_READ },
+{ DEFTYPE_UNSIGNED32 , 0x20 , ACCESS_READ },
+
+{ DEFTYPE_UNSIGNED32 , 0x20 , ACCESS_READ },
+{ DEFTYPE_UNSIGNED32 , 0x20 , ACCESS_READ },
+{ DEFTYPE_UNSIGNED32 , 0x20 , ACCESS_READ },
+{ DEFTYPE_UNSIGNED32 , 0x20 , ACCESS_READ },
+
+{ DEFTYPE_UNSIGNED32 , 0x20 , ACCESS_READ },
+{ DEFTYPE_UNSIGNED32 , 0x20 , ACCESS_READ },
+{ DEFTYPE_UNSIGNED32 , 0x20 , ACCESS_READ },
+{ DEFTYPE_UNSIGNED32 , 0x20 , ACCESS_READ }
+
+};
+
+/**
+* \brief Object/Entry names
+*/
+OBJCONST UCHAR OBJMEM aName0x1A00[] = "InputMapping\000"
+"SubIndex 001\000"
+"SubIndex 002\000"
+"SubIndex 003\000"
+"SubIndex 004\000"
+"SubIndex 005\000"
+"SubIndex 006\000"
+"SubIndex 007\000"
+"SubIndex 008\000"
+"SubIndex 009\000"
+"SubIndex 010\000"
+"SubIndex 011\000"
+"SubIndex 012\000"
+"SubIndex 013\000"
+"SubIndex 014\000"
+"SubIndex 015\000"
+"SubIndex 016\000\377";
+
+/**
+* \brief Object structure
+*/
+typedef struct OBJ_STRUCT_PACKED_START {
+UINT16 u16SubIndex0;
+UINT32 aEntries[16];
+} OBJ_STRUCT_PACKED_END
+TOBJ1A00;
+
+/**
+* \brief Object variable
+*/
+TOBJ1A00 InputMapping0x1A00;
+/** @}*/
+
+
+
+/******************************************************************************
+* Object 0x1C12 : Obj0x1C12
+******************************************************************************/
+/**
+* \addtogroup 0x1C12 0x1C12 | Obj0x1C12
+* @{
+* \brief Object 0x1C12 (Obj0x1C12) definition
+*/
+
+/**
+* \brief Entry descriptions
+*
+* Subindex 0
+* Subindex 1 - n (the same entry description is used)
+*/
+OBJCONST TSDOINFOENTRYDESC OBJMEM asEntryDesc0x1C12[] = {
+{ DEFTYPE_UNSIGNED8 , 0x8 , ACCESS_READ },
+{ DEFTYPE_UNSIGNED16 , 0x10 , ACCESS_READ }};
+
+/**
+* \brief Object name definition
+* For Subindex 1 to n the syntax 'Subindex XXX' is used
+*/
+OBJCONST UCHAR OBJMEM aName0x1C12[] = "Obj0x1C12\000\377";
+
+/**
+* \brief Object structure
+*/
+typedef struct OBJ_STRUCT_PACKED_START {
+UINT16 u16SubIndex0; /**< \brief Subindex 0 */
+UINT16 aEntries[1]; /**< \brief Subindex 1 - 1 */
+} OBJ_STRUCT_PACKED_END
+TOBJ1C12;
+
+/**
+* \brief Object variable
+*/
+TOBJ1C12 sRxPDOassign;
+/** @}*/
+
+
+
+/******************************************************************************
+* Object 0x1C13 : Obj0x1C13
+******************************************************************************/
+/**
+* \addtogroup 0x1C13 0x1C13 | Obj0x1C13
+* @{
+* \brief Object 0x1C13 (Obj0x1C13) definition
+*/
+
+/**
+* \brief Entry descriptions
+*
+* Subindex 0
+* Subindex 1 - n (the same entry description is used)
+*/
+OBJCONST TSDOINFOENTRYDESC OBJMEM asEntryDesc0x1C13[] = {
+{ DEFTYPE_UNSIGNED8 , 0x8 , ACCESS_READ },
+{ DEFTYPE_UNSIGNED16 , 0x10 , ACCESS_READ }};
+
+/**
+* \brief Object name definition
+* For Subindex 1 to n the syntax 'Subindex XXX' is used
+*/
+OBJCONST UCHAR OBJMEM aName0x1C13[] = "Obj0x1C13\000\377";
+
+/**
+* \brief Object structure
+*/
+typedef struct OBJ_STRUCT_PACKED_START {
+UINT16 u16SubIndex0; /**< \brief Subindex 0 */
+UINT16 aEntries[1]; /**< \brief Subindex 1 - 1 */
+} OBJ_STRUCT_PACKED_END
+TOBJ1C13;
+
+/**
+* \brief Object variable
+*/
+TOBJ1C13 sTxPDOassign;
+/** @}*/
+
+
+TOBJECT OBJMEM ApplicationObjDic[] = {
+
+ /* Object 0x1600 */
+ {NULL , NULL , 0x1600 , {DEFTYPE_PDOMAPPING , 3 | (OBJCODE_REC << 8)} , asEntryDesc0x1600 , aName0x1600 , &OutputMapping0x1600 , NULL , NULL , 0x0000 },
+ /* Object 0x1A00 */
+ {NULL , NULL , 0x1A00 , {DEFTYPE_PDOMAPPING , 3 | (OBJCODE_REC << 8)} , asEntryDesc0x1A00 , aName0x1A00 , &InputMapping0x1A00 , NULL , NULL , 0x0000 },
+ /* Object 0x1C12 */
+ {NULL , NULL , 0x1C12 , {DEFTYPE_UNSIGNED16 , 1 | (OBJCODE_ARR << 8)} , asEntryDesc0x1C12 , aName0x1C12 , &sRxPDOassign , NULL , NULL , 0x0000 },
+ /* Object 0x1C13 */
+ {NULL , NULL , 0x1C13 , {DEFTYPE_UNSIGNED16 , 1 | (OBJCODE_ARR << 8)} , asEntryDesc0x1C13 , aName0x1C13 , &sTxPDOassign , NULL , NULL , 0x0000 },
+
+ {NULL,NULL, 0xFFFF, {0, 0}, NULL, NULL, NULL, NULL}
+
+};
+
+void PDO_Mapping_init(void) {
+
+ OutputMapping0x1600.u16SubIndex0 = 16;
+
+ for( int i = 0; i < 16; i++)
+ OutputMapping0x1600.aEntries[i] = 0;
+
+ InputMapping0x1A00.u16SubIndex0 = 16;
+
+ for( int i = 0; i < 16; i++)
+ InputMapping0x1A00.aEntries[i] = 0;
+
+ sRxPDOassign.u16SubIndex0 = 1;
+ sRxPDOassign.aEntries[0] = 0x1600;
+
+ sTxPDOassign.u16SubIndex0 = 1;
+ sTxPDOassign.aEntries[0] = 0x1A00;
+
+}
+
+/** @}*/
+
+
+
+bool efc_ecat_init( void ) {
+
+ PDO_Mapping_init();
+
+ HW_Init();
+
+ MainInit();
+
+ return true;
+}
+
+/**
+ * @brief Денициализация EtherCat драйвера
+ *
+ * После вызова драйвера обращения к его функциям запрещено
+ *
+ * @return @c void
+ */
+void efc_ecat_fini( void ) {
+
+ HW_Release();
+
+}
+
+/**
+ * @brief Обработчик циклических задач EtherCat драйвера
+ *
+ * Обработчик должен быть зарегистрирован на прерывание от используемого модуля EtherCat
+ *
+ * @return void
+ */
+void efc_ecat_loop( void ) {
+
+ MainLoop();
+
+}
+
+//!Подтверждение сброса ошибки от мастера
+void APPL_AckErrorInd(UINT16 stateTrans) {}
+
+EcatStateMachineStates efc_ecat_pend_state;
+efc_ecat_state_pend_handler efc_ecat_pend_handler;
+efc_ecat_update_sync0_time efc_ecat_sync0_time;
+uint16_t efc_ecat_device_id;
+efc_ecat_application_handler efc_ecat_app_handler;
+
+/*!
+ * Функция вызывается при переходе состояния из INIT в PREOP,
+ * когда все общие настройки были проверены для запуска обработчика почтового ящика.
+ * Эта функция информирует приложение о переходе состояния, приложение может отказаться от перехода состояния,
+ * возвращая код ошибки AL Status.
+ *
+ * Код возврата NOERROR_INWORK можно использовать, если приложение не может немедленно подтвердить переход состояния,
+ * в этом случае приложению необходимо завершить переход,
+ * вызвав ECAT_StateChange.
+ *
+ *
+ */
+UINT16 APPL_StartMailboxHandler(void) {
+
+ efc_ecat_pend_state = PreOp;
+
+ efc_ecat_pend_handler( efc_ecat_pend_state );
+
+ //Нужно будет вызвать ECAT_StateChange.
+ return NOERROR_INWORK;
+
+}
+
+/*!
+ * Функция вызывается при переходе состояния от PREEOP к INIT, чтобы остановить обработчик почтового ящика.
+ * Эта функция информирует приложение о переходе состояния, приложение не может отказаться от перехода состояния.
+ */
+UINT16 APPL_StopMailboxHandler(void) {
+
+ return ALSTATUSCODE_NOERROR;
+
+}
+
+/*!
+ * Функция вызывается при переходе состояния от PREOP к SAFEOP, когда все общие настройки были проверены для запуска обработчика ввода.
+ * Эта функция информирует приложение о переходе состояния, приложение может отказаться от перехода состояния,
+ * возвращая код ошибки AL Status.
+ *
+ * Код возврата NOERROR_INWORK можно использовать, если приложение не может немедленно подтвердить переход состояния,
+ * в этом случае приложению необходимо завершить переход, вызвав ECAT_StateChange.
+ *
+ * \param pIntMask указатель на маску событий AL,
+ * которая будет записана в регистр маски событий AL (0x204) при успешном выполнении этой функции.
+ * В этой функции можно настроить маску события.
+ *
+ */
+UINT16 APPL_StartInputHandler( UINT16 * pIntMask ) {
+
+ efc_ecat_pend_state = SafeOp;
+
+ //Уведомление словаря объектов
+ //
+ // Object 0xF030 was not written before
+ // => update object 0xF010 (Module profile list) and 0xF050 (Detected Module List)
+ //
+ // Update 0xF010.0
+ // Update 0xF050.0
+
+ /*Init CiA402 structure if the device is in SM Sync mode
+ the CiA402 structure will be Initialized after calculation of the Cycle time*/
+ if(bDcSyncActive == TRUE) {
+
+ UINT32 Sync0CycleTime = 0;
+ HW_EscReadDWord(Sync0CycleTime, ESC_DC_SYNC0_CYCLETIME_OFFSET);
+ Sync0CycleTime = SWAPDWORD(Sync0CycleTime);
+ efc_ecat_sync0_time( Sync0CycleTime / 1000 ); //get cycle time in us
+
+ }
+
+ efc_ecat_pend_handler( efc_ecat_pend_state );
+
+ return NOERROR_INWORK;
+
+}
+
+/*!
+ * Функция вызывается при переходе состояния от SAFEOP к PREEOP, чтобы остановить обработчик ввода.
+ * Эта функция информирует приложение о переходе состояния, приложение не может отказаться от перехода состояния.
+ */
+UINT16 APPL_StopInputHandler(void) {
+
+ return ALSTATUSCODE_NOERROR;
+
+}
+
+
+UINT16 APPL_StartOutputHandler(void) {
+
+ efc_ecat_pend_state = Op;
+
+ efc_ecat_pend_handler( efc_ecat_pend_state );
+
+ return NOERROR_INWORK;
+
+}
+
+UINT16 APPL_StopOutputHandler(void) {
+
+ return ALSTATUSCODE_NOERROR;
+
+}
+
+typedef struct Part_t {
+
+ void * original;
+ uint16_t offset;
+ uint16_t size;
+
+} MatchingElement;
+
+//MappingMap
+uint16_t recieve_elements_map_num = 0;
+const uint16_t recieve_elements_map_size = 16;
+MatchingElement recieve_elements_map[16];
+
+uint16_t transmit_elements_map_num = 0;
+const uint16_t transmit_elements_map_size = 16;
+MatchingElement transmit_elements_map[16];
+
+
+/*!
+ * Вычислить размеры данных процесса на основе фактического SM-PDO-Assign и сопоставления PDO.
+ */
+UINT16 APPL_GenerateMapping( UINT16 * pInputSize, UINT16 * pOutputSize ) {
+
+ UINT16 result = ALSTATUSCODE_NOERROR;
+
+ UINT16 InputSize = 0;
+ UINT16 OutputSize = 0;
+
+ UINT16 PDOAssignEntryCnt = 0;
+ OBJCONST TOBJECT OBJMEM * pPDO = NULL;
+ UINT16 PDOSubindex0 = 0;
+ UINT32 *pPDOEntry = NULL;
+ UINT16 PDOEntryCnt = 0;
+
+ //Расчет размера TPDO, RPDO.
+
+ /*Scan object 0x1C12 RXPDO assign*/
+ for( PDOAssignEntryCnt = 0; PDOAssignEntryCnt < sRxPDOassign.u16SubIndex0; PDOAssignEntryCnt++ ) {
+
+ //PDO Mapping Object
+ pPDO = OBJ_GetObjectHandle(sRxPDOassign.aEntries[PDOAssignEntryCnt]);
+
+ if(pPDO != NULL) {
+
+
+ PDOSubindex0 = *((UINT16 *)pPDO->pVarPtr);
+
+ for(PDOEntryCnt = 0; PDOEntryCnt < PDOSubindex0; PDOEntryCnt++) {
+
+
+ pPDOEntry = (UINT32 *)(((UINT16 *)pPDO->pVarPtr) + (OBJ_GetEntryOffset((PDOEntryCnt+1),pPDO)>>4)); //goto PDO entry
+ // we increment the expected output size depending on the mapped Entry
+
+ uint16_t PdoObjectId = (UINT16) ((*pPDOEntry) >> 16);
+ uint16_t PdoObjectSubId = (UINT16) (((*pPDOEntry) >> 8) & 0xFF);
+ uint16_t PdoObjectSize = (UINT16) ((*pPDOEntry) & 0xFF);
+
+ if( PdoObjectId ) {
+
+ OBJCONST TOBJECT OBJMEM * object = OBJ_GetObjectHandle( PdoObjectId );
+
+ uint8_t * PdoObjectData = (UINT16 *)object->pVarPtr + (OBJ_GetEntryOffset((PdoObjectSubId),pPDO)>>4);
+
+ recieve_elements_map[recieve_elements_map_num].original = PdoObjectData;
+ recieve_elements_map[recieve_elements_map_num].size = (PdoObjectSize + 7) >> 3; //TODO: Вопрос, что будет если объект будет некоторого малого количества бит??
+ recieve_elements_map[recieve_elements_map_num].offset = (OutputSize + 7) >> 3;
+
+ recieve_elements_map_num++;
+
+ }
+
+ OutputSize += PdoObjectSize;
+ }
+ }
+ else
+ {
+ /*assigned PDO was not found in object dictionary. return invalid mapping*/
+ OutputSize = 0;
+ result = ALSTATUSCODE_INVALIDOUTPUTMAPPING;
+ break;
+ }
+ }
+
+ //Из битов в октеты
+ OutputSize = (OutputSize + 7) >> 3;
+
+ if(result == 0)
+ {
+ /*Scan Object 0x1C13 TXPDO assign*/
+ for(PDOAssignEntryCnt = 0; PDOAssignEntryCnt < sTxPDOassign.u16SubIndex0; PDOAssignEntryCnt++)
+ {
+ pPDO = OBJ_GetObjectHandle(sTxPDOassign.aEntries[PDOAssignEntryCnt]);
+ if(pPDO != NULL)
+ {
+ PDOSubindex0 = *((UINT16 *)pPDO->pVarPtr);
+ for(PDOEntryCnt = 0; PDOEntryCnt < PDOSubindex0; PDOEntryCnt++)
+ {
+ pPDOEntry = (UINT32 *)(((UINT16 *)pPDO->pVarPtr) + (OBJ_GetEntryOffset((PDOEntryCnt+1),pPDO)>>4)); //goto PDO entry
+ // we increment the expected output size depending on the mapped Entry
+
+ uint16_t PdoObjectId = (UINT16) ((*pPDOEntry) >> 16);
+ uint16_t PdoObjectSubId = (UINT16) (((*pPDOEntry) >> 8) & 0xFF);
+ uint16_t PdoObjectSize = (UINT16) ((*pPDOEntry) & 0xFF);
+
+ OBJCONST TOBJECT OBJMEM * object = OBJ_GetObjectHandle( PdoObjectId );
+
+ if( PdoObjectId ) {
+
+ uint8_t * PdoObjectData = (UINT16 *)object->pVarPtr + (OBJ_GetEntryOffset((PdoObjectSubId),pPDO)>>4);
+
+ transmit_elements_map[recieve_elements_map_num].original = PdoObjectData;
+ transmit_elements_map[recieve_elements_map_num].size = (PdoObjectSize + 7) >> 3; //TODO: Вопрос, что будет если объект будет некоторого малого количества бит??
+ transmit_elements_map[recieve_elements_map_num].offset = (InputSize + 7) >> 3;
+
+ transmit_elements_map_num++;
+
+ }
+
+ InputSize += PdoObjectSize;
+ }
+ }
+ else
+ {
+ /*assigned PDO was not found in object dictionary. return invalid mapping*/
+ InputSize = 0;
+ result = ALSTATUSCODE_INVALIDINPUTMAPPING;
+ break;
+ }
+ }
+ }
+
+ InputSize = (InputSize + 7) >> 3;
+
+
+ *pInputSize = InputSize;
+ *pOutputSize = OutputSize;
+
+ return result;
+
+}
+
+
+
+
+
+/*!
+ * Обновить значение TXPDO буффера (исходящего из устройства).
+ */
+void APPL_InputMapping( UINT16 * pData ) {
+
+ uint8_t * write_data = (UINT8 *)pData;
+
+ //Обновление TXPDO.
+
+ for( uint16_t el = 0; el < transmit_elements_map_num; el++ ) {
+
+ memcpy( transmit_elements_map[el].original, write_data + transmit_elements_map[el].offset, transmit_elements_map[el].size );
+
+ }
+
+
+
+}
+
+/*!
+ * Обновить значение RXPDO буффера (входящее в устройства).
+ */
+void APPL_OutputMapping( UINT16 * pData ) {
+
+ const uint8_t * read_data = (UINT8 *)pData;
+
+ //Обновление RXPDO.
+ for( uint16_t el = 0; el < recieve_elements_map_num; el++ ) {
+
+ memcpy( read_data + recieve_elements_map[el].offset, recieve_elements_map[el].original, recieve_elements_map[el].size );
+
+ }
+
+}
+
+/*!
+ * Синхронизация приложения с циклом EtherCat.
+ * Функция вызывается из прерывания синхронизации, или главного цикла.
+ */
+void APPL_Application(void) {
+
+ efc_ecat_app_handler();
+
+}
+
+
+UINT16 APPL_GetDeviceID(void) {
+
+ return efc_ecat_device_id;
+
+}
+
+bool efc_ecat_state_pending( EcatStateMachineStates state ) {
+
+ return efc_ecat_pend_state = state;
+
+}
+
+void efc_ecat_state_approve( EcatStateMachineStates state ) {
+
+ if( !efc_ecat_state_pending(state) )
+ return;
+
+ switch(state) {
+ case PreOp: {
+
+ ECAT_StateChange(INIT_2_PREOP, ALSTATUSCODE_NOERROR);
+
+ } break;
+ case SafeOp: {
+
+ ECAT_StateChange(PREOP_2_SAFEOP, ALSTATUSCODE_NOERROR);
+
+ } break;
+ case Op: {
+
+ ECAT_StateChange(SAFEOP_2_OP, ALSTATUSCODE_NOERROR);
+
+ } break;
+ }
+}
+
+typedef void (*efc_ecat_state_pend_handler)( EcatStateMachineStates state );
+void efc_ecat_set_state_pend_handler( efc_ecat_state_pend_handler pf ) {
+
+ efc_ecat_pend_handler = pf;
+
+}
+
+/** @} */ /* EthercatStateMachineAPI */
+
+typedef void (*efc_ecat_update_sync0_time)( uint32_t time_in_us );
+void efc_ecat_set_sync0_time_update_handler( efc_ecat_update_sync0_time pf ) {
+
+ efc_ecat_sync0_time = pf;
+
+}
+
+typedef uint16_t (*efc_ecat_get_device_id_handler)( void );
+void efc_ecat_set_device_id( uint16_t device_id ) {
+
+ efc_ecat_device_id = device_id;
+
+}
+
+typedef void (*efc_ecat_application_handler)( void );
+void efc_ecat_set_application_handler( efc_ecat_application_handler pf ) {
+
+ efc_ecat_app_handler = pf;
+
+}
+
+
+
+
diff --git a/Projects/EFC_EcatDriver/src/ethercat_slave_cm_hal.c b/Projects/EFC_EcatDriver/src/ethercat_slave_cm_hal.c
new file mode 100644
index 0000000..b05bb89
--- /dev/null
+++ b/Projects/EFC_EcatDriver/src/ethercat_slave_cm_hal.c
@@ -0,0 +1,1242 @@
+//###########################################################################
+//
+// FILE: ethercat_slave_cm_hal.c
+//
+// TITLE: CM EtherCAT HAL Driver.
+//
+// This contains the source of the CM HAL APIs required by EtherCAT stack
+// as well as HAL PDI test application.
+//
+//###########################################################################
+// $TI Release: F2838x EtherCAT Software v2.02.00.00 $
+// $Release Date: Wed Jul 12 21:23:06 IST 2023 $
+// $Copyright:
+// Copyright (C) 2023 Texas Instruments Incorporated - http://www.ti.com/
+//
+// Redistribution and use in source and binary forms, with or without
+// modification, are permitted provided that the following conditions
+// are met:
+//
+// Redistributions of source code must retain the above copyright
+// notice, this list of conditions and the following disclaimer.
+//
+// Redistributions in binary form must reproduce the above copyright
+// notice, this list of conditions and the following disclaimer in the
+// documentation and/or other materials provided with the
+// distribution.
+//
+// Neither the name of Texas Instruments Incorporated nor the names of
+// its contributors may be used to endorse or promote products derived
+// from this software without specific prior written permission.
+//
+// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+// $
+//###########################################################################
+
+//
+// Included Files
+//
+#include "ethercat_slave_cm_hal.h"
+
+#ifdef PDI_HAL_TEST
+
+//
+// HAL Test Application - Register Debug Structure
+//
+ESC_DebugRegisters ESC_escRegs[ESC_HAL_TEST_DEBUG_REGS_LENGTH];
+
+//
+// HAL Block Data Arrays
+//
+static uint32_t ESC_writeBlockData[ESC_HAL_TEST_BLOCK_LENGTH / 4U];
+static uint32_t ESC_readBlockData[ESC_HAL_TEST_BLOCK_LENGTH / 4U];
+
+#endif // PDI_HAL_TEST
+
+//*****************************************************************************
+//
+// ESC_getTimer
+//
+//*****************************************************************************
+uint32_t
+ESC_getTimer(void)
+{
+ //
+ // Return 1's compliment of the CPU timer
+ //
+ return(~((uint32_t)CPUTimer_getTimerCount(CPUTIMER0_BASE)));
+}
+
+//*****************************************************************************
+//
+// ESC_clearTimer
+//
+//*****************************************************************************
+void
+ESC_clearTimer(void)
+{
+ //
+ // Set the timer period count
+ //
+ CPUTimer_setPeriod(CPUTIMER0_BASE, 0xFFFFFFFFUL);
+
+ //
+ // Reload timer with the period count value
+ //
+ CPUTimer_reloadTimerCounter(CPUTIMER0_BASE);
+}
+
+//*****************************************************************************
+//
+// ESC_timerIncPerMilliSec
+//
+//*****************************************************************************
+uint32_t
+ESC_timerIncPerMilliSec(void)
+{
+ //
+ // Returns value based on core frequency of 125MHz.
+ //
+ return((uint32_t)125000UL);
+}
+
+//*****************************************************************************
+//
+// ESC_readBlockISR
+//
+//*****************************************************************************
+void
+ESC_readBlockISR(ESCMEM_ADDR *pData, uint16_t address, uint16_t len)
+{
+ //
+ // Create pointer to ESC Address
+ //
+ const void * escSource = (void *)(ESC_BASE + (uint32_t)address);
+
+ //
+ // Copy ESC data to buffer
+ //
+ memcpy(pData, escSource, (size_t)len);
+}
+
+//*****************************************************************************
+//
+// ESC_readBlock
+//
+//*****************************************************************************
+void
+ESC_readBlock(ESCMEM_ADDR *pData, uint16_t address, uint16_t len)
+{
+ //
+ // Disables interrupts
+ //
+ _disable_IRQ();
+
+ //
+ // Perform copy of ESC data to buffer
+ //
+ ESC_readBlockISR(pData, address, len);
+
+ //
+ // Enable interrupts
+ //
+ _enable_IRQ();
+}
+
+//*****************************************************************************
+//
+// ESC_readDWordISR
+//
+//*****************************************************************************
+uint32_t
+ESC_readDWordISR(uint16_t address)
+{
+ //
+ // Read 32-bit address from ESC memory
+ //
+ return(HWREG(ESC_BASE + address));
+}
+
+//*****************************************************************************
+//
+// ESC_readDWord
+//
+//*****************************************************************************
+uint32_t
+ESC_readDWord(uint16_t address)
+{
+ uint32_t dWordValue;
+
+ //
+ // Disables interrupts
+ //
+ _disable_IRQ();
+
+ //
+ // Read 32-bit address from ESC memory
+ //
+ dWordValue = ESC_readDWordISR(address);
+
+ //
+ // Enable interrupts
+ //
+ _enable_IRQ();
+
+ //
+ // Return value
+ //
+ return(dWordValue);
+}
+
+//*****************************************************************************
+//
+// ESC_readWordISR
+//
+//*****************************************************************************
+uint16_t
+ESC_readWordISR(uint16_t address)
+{
+ //
+ // Read 16-bit address from ESC memory
+ //
+ return(HWREGH(ESC_BASE + address));
+}
+
+//*****************************************************************************
+//
+// ESC_readWord
+//
+//*****************************************************************************
+uint16_t
+ESC_readWord(uint16_t address)
+{
+ uint16_t wordValue;
+
+ //
+ // Disables interrupts
+ //
+ _disable_IRQ();
+
+ //
+ // Read 16-bit address from ESC memory
+ //
+ wordValue = ESC_readWordISR(address);
+
+ //
+ // Enable interrupts
+ //
+ _enable_IRQ();
+
+ //
+ // Return value
+ //
+ return(wordValue);
+}
+
+//*****************************************************************************
+//
+// ESC_readByteISR
+//
+//*****************************************************************************
+uint8_t
+ESC_readByteISR(uint16_t address)
+{
+ //
+ // Read 8-bit address from ESC memory
+ //
+ return(HWREGB(ESC_BASE + address));
+}
+
+//*****************************************************************************
+//
+// ESC_readByte
+//
+//*****************************************************************************
+uint8_t
+ESC_readByte(uint16_t address)
+{
+ uint8_t byteValue;
+
+ //
+ // Disables interrupts
+ //
+ _disable_IRQ();
+
+ //
+ // Read 8-bit address from ESC memory
+ //
+ byteValue = ESC_readByteISR(address);
+
+ //
+ // Enable interrupts
+ //
+ _enable_IRQ();
+
+ //
+ // Return Value
+ //
+ return(byteValue);
+}
+
+//*****************************************************************************
+//
+// ESC_writeBlockISR
+//
+//*****************************************************************************
+void
+ESC_writeBlockISR(ESCMEM_ADDR *pData, uint16_t address, uint16_t len)
+{
+ //
+ // Create pointer to ESC Address
+ //
+ void * escDest = (void *)(ESC_BASE + (uint32_t)address);
+
+ //
+ // Copy buffer data to ESC memory
+ //
+ memcpy(escDest, pData, (size_t)len);
+}
+
+//*****************************************************************************
+//
+// ESC_writeBlock
+//
+//*****************************************************************************
+void
+ESC_writeBlock(ESCMEM_ADDR *pData, uint16_t address, uint16_t len)
+{
+ //
+ // Disables interrupts
+ //
+ _disable_IRQ();
+
+ //
+ // Write data buffer into ESC memory
+ //
+ ESC_writeBlockISR(pData, address, len);
+
+ //
+ // Enable interrupts
+ //
+ _enable_IRQ();
+}
+
+//*****************************************************************************
+//
+// ESC_writeDWordISR
+//
+//*****************************************************************************
+void
+ESC_writeDWordISR(uint32_t dWordValue, uint16_t address)
+{
+ //
+ // Write two 16-bit words to ESC memory
+ //
+ HWREG(ESC_BASE + address) = dWordValue;
+}
+
+//*****************************************************************************
+//
+// ESC_writeDWord
+//
+//*****************************************************************************
+void
+ESC_writeDWord(uint32_t dWordValue, uint16_t address)
+{
+ //
+ // Disables interrupts
+ //
+ _disable_IRQ();
+
+ //
+ // Write two 16-words into ESC memory
+ //
+ ESC_writeDWordISR(dWordValue, address);
+
+ //
+ // Enable interrupts
+ //
+ _enable_IRQ();
+}
+
+//*****************************************************************************
+//
+// ESC_writeWordISR
+//
+//*****************************************************************************
+void
+ESC_writeWordISR(uint16_t wordValue, uint16_t address)
+{
+ //
+ // Write 16-bit word into ESC memory
+ //
+ HWREGH(ESC_BASE + address) = wordValue;
+}
+
+//*****************************************************************************
+//
+// ESC_writeWord
+//
+//*****************************************************************************
+void
+ESC_writeWord(uint16_t wordValue, uint16_t address)
+{
+ //
+ // Disables interrupts
+ //
+ _disable_IRQ();
+
+ //
+ // Write one 16-word into ESC memory
+ //
+ ESC_writeWordISR(wordValue, address);
+
+ //
+ // Enable interrupts
+ //
+ _enable_IRQ();
+}
+
+//*****************************************************************************
+//
+// ESC_writeByteISR
+//
+//*****************************************************************************
+void
+ESC_writeByteISR(uint8_t byteValue, uint16_t address)
+{
+ //
+ // Write 8-bit data into ESC memory
+ //
+ HWREGB(ESC_BASE + address) = byteValue;
+}
+
+//*****************************************************************************
+//
+// ESC_writeByte
+//
+//*****************************************************************************
+void
+ESC_writeByte(uint8_t byteValue, uint16_t address)
+{
+ //
+ // Disables interrupts
+ //
+ _disable_IRQ();
+
+ //
+ // Write one byte into ESC memory
+ //
+ ESC_writeByteISR(byteValue, address);
+
+ //
+ // Enable interrupts
+ //
+ _enable_IRQ();
+}
+
+//*****************************************************************************
+//
+// ESC_setLed
+//
+//*****************************************************************************
+void
+ESC_setLed(uint8_t runLed, uint8_t errLed)
+{
+ //
+ // Set/Clear Run LED
+ //
+ GPIO_writePin(ESC_RUN_LED_GPIO, (uint32_t)(runLed));
+
+ //
+ // Set/Clear Error LED
+ //
+ GPIO_writePin(ESC_ERR_LED_GPIO, (uint32_t)(errLed));
+}
+
+#ifdef PDI_HAL_TEST
+//*****************************************************************************
+//
+// HAL_performDelay
+//
+//*****************************************************************************
+void HAL_performDelay(void)
+{
+ uint32_t i;
+
+ //
+ // Perform software delay
+ //
+ for(i = 0U; i < 0xFFFFF; i++)
+ {
+ NOP;
+ }
+}
+
+//*****************************************************************************
+//
+// HAL_initWriteBlockData
+//
+//*****************************************************************************
+void HAL_initWriteBlockData(void)
+{
+ uint16_t i;
+
+ //
+ // Initialize write block data array
+ //
+ for(i = 0U; i < (ESC_HAL_TEST_BLOCK_LENGTH / 4U); i++)
+ {
+ ESC_writeBlockData[i] = 0x1234ABCDUL;
+ }
+}
+
+//*****************************************************************************
+//
+// HAL_clearReadBlockData
+//
+//*****************************************************************************
+void HAL_clearReadBlockData(void)
+{
+ uint16_t i;
+
+ //
+ // Clear read block data array
+ //
+ for(i = 0U; i < (ESC_HAL_TEST_BLOCK_LENGTH / 4U); i++)
+ {
+ ESC_readBlockData[i] = 0x0UL;
+ }
+}
+
+//*****************************************************************************
+//
+// HAL_testBlockData
+//
+//*****************************************************************************
+uint16_t HAL_testBlockData(uint16_t length)
+{
+ uint16_t i;
+ uint8_t * writeData = (uint8_t *)(&ESC_writeBlockData[0]);
+ uint8_t * readData = (uint8_t *)(&ESC_readBlockData[0]);
+
+ //
+ // Check that data written and data read match
+ //
+ for(i = 0U; i < length; i++)
+ {
+ if(*writeData != *readData)
+ {
+ return(ESC_HAL_BLOCK_TEST_FAIL);
+ }
+
+ writeData++;
+ readData++;
+ }
+
+ return(ESC_HAL_BLOCK_TEST_PASS);
+}
+
+//*****************************************************************************
+//
+// ESC_setupPDITestInterface
+//
+//*****************************************************************************
+void
+ESC_setupPDITestInterface(void)
+{
+ uint16_t currentAddress = 0x0U;
+ uint32_t doubleWordData = 0x0UL;
+ uint16_t wordData = 0x0U;
+ uint8_t byteData = 0x0U;
+
+ //
+ // Setup and add various ESC registers to monitor
+ //
+ ESC_debugInitESCRegLogs();
+ ESC_debugAddESCRegsAddress(0x0U); // Type, Revision
+ ESC_debugAddESCRegsAddress(0x2U); // Build
+ ESC_debugAddESCRegsAddress(0x4U); // FMMUs, SyncManagers Supported
+ ESC_debugAddESCRegsAddress(0x8U); // ESC Supported Features
+ ESC_debugAddESCRegsAddress(0x100U); // DL Control
+ ESC_debugAddESCRegsAddress(0x102U); // DL Control (Extended)
+ ESC_debugAddESCRegsAddress(0x110U); // DL Status
+ ESC_debugAddESCRegsAddress(0x310U); // Lost Link Counter 1
+ ESC_debugAddESCRegsAddress(0x312U); // Lost Link Counter 2
+ ESC_debugAddESCRegsAddress(0x510U); // MII Control/Status
+ ESC_debugAddESCRegsAddress(0x512U); // PHY Address
+ ESC_debugAddESCRegsAddress(0x514U); // PHY Data
+ ESC_debugAddESCRegsAddress(0x516U); // MII ECAT Access State
+ ESC_debugAddESCRegsAddress(0x518U); // PHY Port Status (1)
+ ESC_debugAddESCRegsAddress(0x51AU); // PHY Port Status (2)
+ ESC_debugAddESCRegsAddress(0x1000U); // First data word of ESC RAM
+
+ //
+ // Check that correct PDI type (ASYNC16) is configured
+ //
+ if(ESC_readByte(ESC_O_PDI_CONTROL) != ESC_PDI_CONTROL_ASYNC16)
+ {
+ //
+ // PDI not operational or incorrect
+ //
+ while(1)
+ {
+ //
+ // Toggle Error
+ //
+ ESC_signalFail();
+ }
+ }
+
+ //
+ // Perform PDI read and write tests for entire ESC PDI RAM range
+ //
+ for(currentAddress = ESC_PDI_RAM_START_ADDRESS_OFFSET;
+ currentAddress <= ESC_PDI_RAM_END_ADDRESS_OFFSET;
+ currentAddress += 4U)
+ {
+ //
+ // Read DWord and Write DWord API Tests
+ //
+ doubleWordData = ESC_readDWord(currentAddress);
+ ESC_writeDWord(0xABCD1234UL, currentAddress);
+ doubleWordData = ESC_readDWord(currentAddress);
+
+ if(doubleWordData != 0xABCD1234UL)
+ {
+ while(1)
+ {
+ //
+ // Toggle Error
+ //
+ ESC_signalFail();
+ }
+ }
+
+ doubleWordData = ESC_readDWordISR(currentAddress);
+ ESC_writeDWordISR(0x1A2B3C4DUL, currentAddress);
+ doubleWordData = ESC_readDWordISR(currentAddress);
+
+ if(doubleWordData != 0x1A2B3C4DUL)
+ {
+ while(1)
+ {
+ //
+ // Toggle Error
+ //
+ ESC_signalFail();
+ }
+ }
+
+ //
+ // Read Word and Write Word API Tests
+ //
+ wordData = ESC_readWord(currentAddress);
+ ESC_writeWord(0x6789U, currentAddress);
+ wordData = ESC_readWord(currentAddress);
+
+ if(wordData != 0x6789U)
+ {
+ while(1)
+ {
+ //
+ // Toggle Error
+ //
+ ESC_signalFail();
+ }
+ }
+
+ wordData = ESC_readWordISR(currentAddress);
+ ESC_writeWordISR(0x5A5AU, currentAddress);
+ wordData = ESC_readWordISR(currentAddress);
+
+ if(wordData != 0x5A5AU)
+ {
+ while(1)
+ {
+ //
+ // Toggle Error
+ //
+ ESC_signalFail();
+ }
+ }
+
+ //
+ // Read Byte and Write Byte API Tests
+ //
+ byteData = ESC_readByte(currentAddress);
+ ESC_writeByte(0xEFU, currentAddress);
+ byteData = ESC_readByte(currentAddress);
+
+ if(byteData != 0xEFU)
+ {
+ while(1)
+ {
+ //
+ // Toggle Error
+ //
+ ESC_signalFail();
+ }
+ }
+
+ byteData = ESC_readByteISR(currentAddress);
+ ESC_writeByteISR(0xBCU, currentAddress);
+ byteData = ESC_readByteISR(currentAddress);
+
+ if(byteData != 0xBCU)
+ {
+ while(1)
+ {
+ //
+ // Toggle Error
+ //
+ ESC_signalFail();
+ }
+ }
+ }
+
+ //
+ // Setup for read/write block API Tests
+ //
+ HAL_initWriteBlockData();
+
+ //
+ // Perform even length write and read block (non-ISR) API Test
+ //
+ ESC_writeBlock((uint8_t *)(&ESC_writeBlockData[0]),
+ ESC_PDI_RAM_START_ADDRESS_OFFSET,
+ ESC_HAL_TEST_BLOCK_LENGTH);
+ ESC_readBlock((uint8_t *)(&ESC_readBlockData[0]),
+ ESC_PDI_RAM_START_ADDRESS_OFFSET,
+ ESC_HAL_TEST_BLOCK_LENGTH);
+
+ if(HAL_testBlockData(ESC_HAL_TEST_BLOCK_LENGTH) != ESC_HAL_BLOCK_TEST_PASS)
+ {
+ while(1)
+ {
+ //
+ // Toggle Error
+ //
+ ESC_signalFail();
+ }
+ }
+
+ HAL_clearReadBlockData();
+
+ //
+ // Perform even length write and read block API Test
+ //
+ ESC_writeBlockISR((uint8_t *)(&ESC_writeBlockData[0]),
+ (ESC_PDI_RAM_START_ADDRESS_OFFSET + 0x1000U),
+ ESC_HAL_TEST_BLOCK_LENGTH);
+ ESC_readBlockISR((uint8_t *)(&ESC_readBlockData[0]),
+ (ESC_PDI_RAM_START_ADDRESS_OFFSET + 0x1000U),
+ ESC_HAL_TEST_BLOCK_LENGTH);
+
+ if(HAL_testBlockData(ESC_HAL_TEST_BLOCK_LENGTH) != ESC_HAL_BLOCK_TEST_PASS)
+ {
+ while(1)
+ {
+ //
+ // Toggle Error
+ //
+ ESC_signalFail();
+ }
+ }
+
+ HAL_clearReadBlockData();
+
+ //
+ // Perform odd length write and read block (non-ISR) API Test
+ //
+ ESC_writeBlock((uint8_t *)(&ESC_writeBlockData[0]),
+ (ESC_PDI_RAM_START_ADDRESS_OFFSET + 0x2000U),
+ (ESC_HAL_TEST_BLOCK_LENGTH - 1U));
+ ESC_readBlock((uint8_t *)(&ESC_readBlockData[0]),
+ (ESC_PDI_RAM_START_ADDRESS_OFFSET + 0x2000U),
+ (ESC_HAL_TEST_BLOCK_LENGTH - 1U));
+
+ if(HAL_testBlockData((ESC_HAL_TEST_BLOCK_LENGTH - 1U)) !=
+ ESC_HAL_BLOCK_TEST_PASS)
+ {
+ while(1)
+ {
+ //
+ // Toggle Error
+ //
+ ESC_signalFail();
+ }
+ }
+
+ HAL_clearReadBlockData();
+
+ //
+ // Perform odd length write and read block API Test
+ //
+ ESC_writeBlockISR((uint8_t *)(&ESC_writeBlockData[0]),
+ (ESC_PDI_RAM_START_ADDRESS_OFFSET + 0x3000U),
+ (ESC_HAL_TEST_BLOCK_LENGTH - 1U));
+ ESC_readBlockISR((uint8_t *)(&ESC_readBlockData[0]),
+ (ESC_PDI_RAM_START_ADDRESS_OFFSET + 0x3000U),
+ (ESC_HAL_TEST_BLOCK_LENGTH - 1U));
+
+ if(HAL_testBlockData((ESC_HAL_TEST_BLOCK_LENGTH - 1U)) !=
+ ESC_HAL_BLOCK_TEST_PASS)
+ {
+ while(1)
+ {
+ //
+ // Toggle Error
+ //
+ ESC_signalFail();
+ }
+ }
+
+ //
+ // Pass
+ //
+ ESC_signalPass();
+}
+
+//*****************************************************************************
+//
+// ESC_debugUpdateESCRegLogs
+//
+//*****************************************************************************
+void
+ESC_debugUpdateESCRegLogs(void)
+{
+ uint16_t i = 0U;
+
+ //
+ // Update ESC register data into debug array
+ //
+ while(ESC_escRegs[i].address != 0xFFFFU)
+ {
+ ESC_escRegs[i].data = ESC_readWord(ESC_escRegs[i].address);
+ i++;
+ }
+}
+
+//*****************************************************************************
+//
+// ESC_debugAddESCRegsAddress
+//
+//*****************************************************************************
+void
+ESC_debugAddESCRegsAddress(uint16_t address)
+{
+ uint16_t i = 0U;
+
+ //
+ // Add ESC Register Address to debug array
+ //
+ for(i = 0U; i < ESC_HAL_TEST_DEBUG_REGS_LENGTH; i++)
+ {
+ if(ESC_escRegs[i].address == 0xFFFFU)
+ {
+ ESC_escRegs[i].address = address;
+ return;
+ }
+ }
+}
+
+//*****************************************************************************
+//
+// ESC_debugInitESCRegLogs
+//
+//*****************************************************************************
+void
+ESC_debugInitESCRegLogs(void)
+{
+ uint16_t i = 0U;
+
+ //
+ // Initialize ESC register debug array
+ //
+ for(i = 0U; i < ESC_HAL_TEST_DEBUG_REGS_LENGTH ; i++)
+ {
+ ESC_escRegs[i].address = 0xFFFFU;
+ ESC_escRegs[i].data = 0xFFFFU;
+ }
+}
+
+//*****************************************************************************
+//
+// ESC_signalPass
+//
+//*****************************************************************************
+void
+ESC_signalPass(void)
+{
+ //
+ // Turn on controlCARD LEDs
+ //
+ GPIO_writePin(CCARD_LED_1_GPIO, 0UL);
+ GPIO_writePin(CCARD_LED_2_GPIO, 0UL);
+}
+
+//*****************************************************************************
+//
+// ESC_signalFail
+//
+//*****************************************************************************
+void
+ESC_signalFail(void)
+{
+ //
+ // Toggle controlCARD LEDs and delay
+ //
+ GPIO_togglePin(CCARD_LED_1_GPIO);
+ GPIO_togglePin(CCARD_LED_2_GPIO);
+
+ HAL_performDelay();
+}
+
+//*****************************************************************************
+//
+// ESC_passFailSignalSetup
+//
+//*****************************************************************************
+void
+ESC_passFailSignalSetup(void)
+{
+ //
+ // LED GPIO configuration completed by CPU1
+ //
+
+ //
+ // Turn off controlCARD LEDs
+ //
+ GPIO_writePin(CCARD_LED_1_GPIO, 1UL);
+ GPIO_writePin(CCARD_LED_2_GPIO, 1UL);
+}
+#endif // PDI_HAL_TEST
+
+//*****************************************************************************
+//
+// ESC_loadedCheckEEPROM
+//
+//*****************************************************************************
+uint16_t
+ESC_loadedCheckEEPROM(void)
+{
+ uint16_t status;
+
+ //
+ // Get ESC DL Status register
+ //
+ status = ESC_readWord(ESC_O_DL_STATUS);
+
+ //
+ // Check if EEPROM is loaded
+ //
+ if((status & ESC_DL_STATUS_EEPROMLOAD_M) == ESC_DL_STATUS_EEPROMLOAD_M)
+ {
+ //
+ // Get ESC EEPROM Status register
+ //
+ status = ESC_readWord(ESC_O_EEPROM_STATUS);
+
+ //
+ // Check if EEPROM is loaded and device information is okay
+ //
+ if((status & ESC_EEPROM_STATUS_EEPROMLOAD_M) == ESC_EEPROM_SUCCESS)
+ {
+ return(ESC_EEPROM_SUCCESS);
+ }
+ else
+ {
+ return(ESC_EEPROM_LOAD_ERROR);
+ }
+ }
+ else
+ {
+ //
+ // DL Status indicated EEPROM is not loaded
+ //
+ return(ESC_EEPROM_NOT_LOADED);
+ }
+}
+
+//*****************************************************************************
+//
+// ESC_resetESC
+//
+//*****************************************************************************
+void
+ESC_resetESC(void)
+{
+ SysCtl_resetPeripheral(SYSCTL_PERIPH_RES_ECAT);
+}
+
+//*****************************************************************************
+//
+// ESC_holdESCInReset
+//
+//*****************************************************************************
+void
+ESC_holdESCInReset(void)
+{
+ //
+ // Put ESC in reset
+ //
+ HWREG(CMSYSCTL_BASE + SYSCTL_O_CMSOFTPRESET1) |=
+ (SYSCTL_CMSOFTPRESET1_ETHERCAT |
+ (((uint32_t)SYSCTL_CMSYSCTL_KEY << 16U ) &
+ SYSCTL_CMSOFTPRESET1_KEY_M));
+}
+
+//*****************************************************************************
+//
+// ESC_releaseESCReset
+//
+//*****************************************************************************
+void
+ESC_releaseESCReset(void)
+{
+ //
+ // Release from reset
+ //
+ HWREG(CMSYSCTL_BASE + SYSCTL_O_CMSOFTPRESET1) =
+ ((HWREG(CMSYSCTL_BASE + SYSCTL_O_CMSOFTPRESET1) &
+ (~SYSCTL_CMSOFTPRESET1_ETHERCAT)) |
+ (((uint32_t)SYSCTL_CMSYSCTL_KEY << 16U ) &
+ SYSCTL_CMSOFTPRESET1_KEY_M));
+}
+
+//*****************************************************************************
+//
+// ESC_initHW
+//
+//*****************************************************************************
+uint16_t
+ESC_initHW(void)
+{
+ //
+ // Set application-specific timeout for waiting for EEPROM to load
+ // and one for waiting for memory initialization
+ // (End user can adjust as needed)
+ //
+ uint16_t eepromTimeOut = 0x1000U;
+ uint16_t memoryTimeOut = 0x300U;
+
+ //
+ // Initialize CM - Disable watchdog, enable peripherals
+ // (Device clocking setup by CPU1)
+ //
+// CM_init();
+ SysCtl_enablePeripheral(SYSCTL_PERIPH_CLK_ECAT);
+ SysCtl_enablePeripheral(SYSCTL_PERIPH_CLK_TIMER0);
+
+ //
+ // Initialize ESC GPIOs
+ //
+ // Already setup and initialized by CPU1
+ //
+
+ //
+ // Register EtherCAT Interrupt Handlers
+ //
+ Interrupt_registerHandler(INT_ECAT, &ESC_applicationLayerHandler);
+ Interrupt_registerHandler(INT_ECAT_SYNC0, &ESC_applicationSync0Handler);
+ Interrupt_registerHandler(INT_ECAT_SYNC1, &ESC_applicationSync1Handler);
+
+ //
+ // Enable ECAT/PDI, Sync0, and Sync1 interrupts in NVIC
+ //
+ Interrupt_enable(INT_ECAT);
+ Interrupt_enable(INT_ECAT_SYNC0);
+ Interrupt_enable(INT_ECAT_SYNC1);
+
+ //
+ // Configure and Start timer
+ //
+ CPUTimer_setPeriod(CPUTIMER0_BASE, 0xFFFFFFFFUL);
+ CPUTimer_setPreScaler(CPUTIMER0_BASE, 0U);
+ CPUTimer_startTimer(CPUTIMER0_BASE);
+
+#ifdef PDI_HAL_TEST
+ //
+ // Enable Pass, fail signals for HAL PDI Test
+ //
+ ESC_passFailSignalSetup();
+#endif // PDI_HAL_TEST
+
+ //
+ // Configure EEPROM Size for 16K bits or less
+ //
+ ESCSS_configureEEPROMSize(ESC_SS_CONFIG_BASE, ESCSS_LESS_THAN_16K);
+
+ //
+ // Reset ESC
+ //
+ ESC_resetESC();
+
+#ifdef PDI_HAL_TEST
+ //
+ // Enable the debug access
+ //
+ while((HWREGH(ESC_SS_BASE + ESCSS_O_ACCESS_CTRL) &
+ ESCSS_ACCESS_CTRL_ENABLE_DEBUG_ACCESS) !=
+ ESCSS_ACCESS_CTRL_ENABLE_DEBUG_ACCESS)
+ {
+ ESCSS_enableDebugAccess(ESC_SS_BASE);
+ }
+#endif // PDI_HAL_TEST
+
+ //
+ // Initialize ESCSS Memory
+ //
+ ESCSS_initMemory(ESC_SS_BASE);
+
+ //
+ // Wait for ESCSS memory initialization to complete
+ //
+ if(ESCSS_getMemoryInitDoneStatusBlocking(ESC_SS_BASE, memoryTimeOut) !=
+ ESCSS_API_SUCCESS)
+ {
+ return(ESC_HW_INIT_FAIL);
+ }
+
+ //
+ // Wait (with time out) for EEPROM to be loaded
+ //
+ while(ESC_loadedCheckEEPROM() != ESC_EEPROM_SUCCESS)
+ {
+ eepromTimeOut--;
+
+ //
+ // On time out, return fail
+ //
+ if(eepromTimeOut == 0U)
+ {
+ return(ESC_HW_INIT_FAIL);
+ }
+ }
+
+ //
+ // Initialize AL Event Mask to zero to prevent ESC interrupts until
+ // set during stack state transition to SAFEOP
+ //
+ ESC_writeDWord(0UL, ESC_O_AL_EVENTMASK);
+
+ //
+ // Enable ECAT/PDI, Sync0, and Sync1 interrupts in ESCSS
+ //
+ ESCSS_setMaskedInterruptStatus(ESC_SS_BASE,
+ (ESCSS_INTR_MASK_IRQ_MASK |
+ ESCSS_INTR_MASK_SYNC0_MASK |
+ ESCSS_INTR_MASK_SYNC1_MASK));
+
+ //
+ // Connect ESCSS Sync0/1 signals to respective interrupts in NVIC
+ //
+ ESCSS_configureSync0Connections(ESC_SS_BASE, ESCSS_SYNC0_CONFIG_CM4_NVIC_EN,
+ ESCSS_VALID_KEY_VALUE);
+ ESCSS_configureSync1Connections(ESC_SS_BASE, ESCSS_SYNC1_CONFIG_CM4_NVIC_EN,
+ ESCSS_VALID_KEY_VALUE);
+
+ //
+ // Enable interrupts to CM
+ //
+ _enable_IRQ();
+
+ return(ESC_HW_INIT_SUCCESS);
+}
+
+//*****************************************************************************
+//
+// ESC_releaseHW
+//
+//*****************************************************************************
+void
+ESC_releaseHW(void)
+{
+ //
+ // Intentionally empty - Implementation is left to the end user
+ //
+}
+
+//*****************************************************************************
+//
+// ESC_applicationLayerHandler
+//
+//*****************************************************************************
+__interrupt void
+ESC_applicationLayerHandler(void)
+{
+#ifdef ETHERCAT_STACK
+#if AL_EVENT_ENABLED
+ //
+ // When stack is included and application event enabled, call stack PDI ISR
+ //
+ PDI_Isr();
+#endif // AL_EVENT_ENABLED
+#endif // ETHERCAT_STACK
+
+ //
+ // Acknowledge and clear interrupt
+ //
+ ESCSS_clearRawInterruptStatus(ESC_SS_BASE, ESCSS_INTR_CLR_IRQ_CLR);
+}
+
+//*****************************************************************************
+//
+// ESC_applicationSync0Handler
+//
+//*****************************************************************************
+__interrupt void
+ESC_applicationSync0Handler(void)
+{
+#ifdef ETHERCAT_STACK
+#if DC_SUPPORTED
+ //
+ // When stack is included and DC is enabled, call stack Sync0 ISR
+ //
+ Sync0_Isr();
+#endif // DC_SUPPORTED
+#endif // ETHERCAT_STACK
+
+ //
+ // Acknowledge and clear interrupt
+ //
+ ESCSS_clearRawInterruptStatus(ESC_SS_BASE, ESCSS_INTR_CLR_SYNC0_CLR);
+}
+
+//*****************************************************************************
+//
+// ESC_applicationSync1Handler
+//
+//*****************************************************************************
+__interrupt void
+ESC_applicationSync1Handler(void)
+{
+#ifdef ETHERCAT_STACK
+#if DC_SUPPORTED
+ //
+ // When stack is included and DC is enabled, call stack Sync1 ISR
+ //
+ Sync1_Isr();
+#endif // DC_SUPPORTED
+#endif // ETHERCAT_STACK
+
+ //
+ // Acknowledge and clear interrupt
+ //
+ ESCSS_clearRawInterruptStatus(ESC_SS_BASE, ESCSS_INTR_CLR_SYNC1_CLR);
+}
+
+//
+// End of File
+//
diff --git a/Projects/EFC_EcatDriver/src/ssc/applInterface.h b/Projects/EFC_EcatDriver/src/ssc/applInterface.h
new file mode 100644
index 0000000..8aede0f
--- /dev/null
+++ b/Projects/EFC_EcatDriver/src/ssc/applInterface.h
@@ -0,0 +1,149 @@
+/*
+* This source file is part of the EtherCAT Slave Stack Code licensed by Beckhoff Automation GmbH & Co KG, 33415 Verl, Germany.
+* The corresponding license agreement applies. This hint shall not be removed.
+* https://www.beckhoff.com/media/downloads/slave-stack-code/ethercat_ssc_license.pdf
+*/
+
+/**
+\addtogroup EcatAppl EtherCAT application
+@{
+*/
+
+/**
+\file applInterface.h
+\author EthercatSSC@beckhoff.com
+\brief Definition of the application interface functions
+
+\version 5.13
+
+ Changes to version V5.12:
+V5.13 COE4: update default entry name handling in case of 16Bit characters, add CoE Read/write indication functions
+ Changes to version V5.11:
+V5.12 APPL1: add optional application function called from the main loop (after mbx and esm are executed)
+V5.12 EEPROM3: implement a store EEPROM timeout handler
+V5.12 EOE1: move icmp sample to the sampleappl,add EoE application interface functions
+V5.12 FOE1: update new interface,move the FoE sample to sampleappl,add FoE application callback functions
+ Changes to version - :
+V5.10.1 : Start file change log
+*/
+
+/*-----------------------------------------------------------------------------------------
+------
+------ Includes
+------
+-----------------------------------------------------------------------------------------*/
+
+
+#ifndef _APPL_INTERFACE_H_
+#define _APPL_INTERFACE_H_
+
+#include "ecat_def.h"
+#include
+#include
+#include "esc.h"
+#include "ecatslv.h"
+#include "objdef.h"
+#include "ecatappl.h"
+
+/*ET9300 Project Handler :(#if DIAGNOSIS_SUPPORTED) lines 49 to 51 deleted*/
+
+
+/*ET9300 Project Handler :(#if EOE_SUPPORTED) lines 54 to 56 deleted*/
+
+/*ET9300 Project Handler :(#if FOE_SUPPORTED) lines 58 to 60 deleted*/
+
+#endif /*#ifndef _APPL_INTERFACE_H_*/
+
+#if defined(_APPL_INTERFACE_) && (_APPL_INTERFACE_ == 1)
+ #define PROTO
+#else
+ #define PROTO extern
+#endif
+
+/*-----------------------------------------------------------------------------------------
+------
+------ Function pointer which are used to call optional functions from the application
+------
+-----------------------------------------------------------------------------------------*/
+
+/*ET9300 Project Handler :(#if ESC_EEPROM_EMULATION) lines 76 to 122 deleted*/
+
+
+/*ET9300 Project Handler :(#if EOE_SUPPORTED) lines 125 to 152 deleted*/
+
+
+/*ET9300 Project Handler :(#if FOE_SUPPORTED) lines 155 to 274 deleted*/
+
+/* ECATCHANGE_START(V5.13) COE4*/
+/////////////////////////////////////////////////////////////////////////////////////////
+/**
+\param Index Index of the object to be read
+\param Subindex Subindex of the object entry to be read
+\param CompleteAccess Indicates if the object is read with complete access
+
+\brief The function is called before an object/entry is read
+*////////////////////////////////////////////////////////////////////////////////////////
+PROTO void(*pAPPL_CoeReadInd)(UINT16 Index, UINT8 Subindex, BOOL CompleteAccess);
+
+/////////////////////////////////////////////////////////////////////////////////////////
+/**
+\param Index Index of the object which was written
+\param Subindex Subindex of the object entry which was written
+\param CompleteAccess Indicates if the object was written with complete access
+
+\brief The function is called after an object/entry was successfully written
+*////////////////////////////////////////////////////////////////////////////////////////
+PROTO void(*pAPPL_CoeWriteInd)(UINT16 Index, UINT8 Subindex, BOOL CompleteAccess);
+
+/* ECATCHANGE_END(V5.13) COE4*/
+/////////////////////////////////////////////////////////////////////////////////////////
+/**
+\brief This function is called by the SSC from the main loop
+\brief The function pointer is reset in MainInit() so it shall be set afterwards
+*////////////////////////////////////////////////////////////////////////////////////////
+PROTO void(*pAPPL_MainLoop)();
+
+/*-----------------------------------------------------------------------------------------
+------
+------ Functions provided by the SSC to be called from the application
+------
+-----------------------------------------------------------------------------------------*/
+
+
+/////////////////////////////////////////////////////////////////////////////////////////
+/**
+\return 0 if successful or greater 0 in case of an error
+
+\brief Initialize the generic slave stack.
+\brief This function should be called after the platform including operating system and
+\brief ESC is ready to use.
+*////////////////////////////////////////////////////////////////////////////////////////
+PROTO UINT16 MainInit(void);
+
+
+/////////////////////////////////////////////////////////////////////////////////////////
+/**
+\brief This function handles the low priority function like EtherCAT state machine
+\brief handling, mailbox protocols and if no synchronization is enabled also the
+\brief application.
+\brief This function shall be called cyclically from the application.
+*////////////////////////////////////////////////////////////////////////////////////////
+PROTO void MainLoop(void);
+
+
+/////////////////////////////////////////////////////////////////////////////////////////
+/**
+\param alStatus requested AL Status
+\param alStatusCode requested AL Status Code
+
+\brief This function shall be called by the application to trigger state transition in case
+\brief of an application error or to complete a pending transition.
+\brief If the function was called due to an error it shall be again if the error is gone.
+\brief NOTE: state requests to a higher state than the current state are not allowed.
+*////////////////////////////////////////////////////////////////////////////////////////
+PROTO void ECAT_StateChange(UINT8 alStatus, UINT16 alStatusCode);
+
+
+/*ET9300 Project Handler :(#if EOE_SUPPORTED) lines 348 to 361 deleted*/
+
+#undef PROTO
diff --git a/Projects/EFC_EcatDriver/src/ssc/coeappl.c b/Projects/EFC_EcatDriver/src/ssc/coeappl.c
new file mode 100644
index 0000000..83deae5
--- /dev/null
+++ b/Projects/EFC_EcatDriver/src/ssc/coeappl.c
@@ -0,0 +1,907 @@
+/*
+* This source file is part of the EtherCAT Slave Stack Code licensed by Beckhoff Automation GmbH & Co KG, 33415 Verl, Germany.
+* The corresponding license agreement applies. This hint shall not be removed.
+* https://www.beckhoff.com/media/downloads/slave-stack-code/ethercat_ssc_license.pdf
+*/
+
+/**
+\addtogroup CoE CAN Application Profile over EtherCAT
+@{
+*/
+
+/**
+\file coeappl.c
+\author EthercatSSC@beckhoff.com
+\brief Implementation
+This file contains an example for CoE services and the CoE object dictionary
+
+\version 5.13
+
+ Changes to version V5.12:
+V5.13 CIA402 3: change define "CIA402_DEVICE" to "CiA402_SAMPLE_APPLICATION"
+V5.13 COE1: handling objects with 255 entries
+V5.13 COE10: change 0x10F1.1 access from "rw" to "ro"
+V5.13 COE2: handle Backup entries with the code VAR
+V5.13 COE6: add 0x10F0.2 (Backup parameter changed)
+V5.13 COE7: define 0x1C3x.13 Shift Time too short, just define variable because expected in DC mode but shift mode is not supported by the SSC
+ Changes to version V5.11:
+V5.12 COE1: load backup value after the complete OD was initialized
+V5.12 COE4: add time stamp object (0x10F8) and update diagnosis handling
+V5.12 COE8: fix invalid size calculation to init backup entries
+V5.12 ECAT1: update SM Parameter measurement (based on the system time), enhancement for input only devices and no mailbox support, use only 16Bit pointer in process data length caluclation
+V5.12 ECAT5: update Sync error counter/flag handling,check enum memory alignment depending on the processor,in case of a polled timer disable ESC interrupts during DC_CheckWatchdog
+ Changes to version V5.10:
+V5.11 COE1: update invalid end entry in the object dictionaries (error with some compilers)
+V5.11 COE3: change 0x10F3.2 (Sync Error limit) from UINT32 to UINT16 (according to the ETG.1020)
+V5.11 ECAT10: change PROTO handling to prevent compiler errors
+V5.11 ECAT4: enhance SM/Sync monitoring for input/output only slaves
+ Changes to version V5.01:
+V5.10 COE1: Define one entry description for all 0x1C3x objects and change data type of SI11,12,13 to UINT16 (according ETG.1020)
+V5.10 COE2: Change return value of Get ObjectSize to UINT32
+ Change object size to UINT32
+V5.10 ECAT13: Update Synchronization handling (FreeRun,SM Sync, Sync0, Sync1)
+ Compare DC UINT configuration (by ESC Config data) vs. DC activation register settings
+ Update 0x1C3x entries
+ Changes to version V5.0:
+V5.01 APPL3: Include library demo application
+V5.01 COE1: Remove alignment entry (SI33) from objects 0x1C32/0x1C33
+V5.01 EL9800 1: Read/Write functions for setting object 0x8020 moved to el9800appl.c
+V5.01 EL9800 2: Add TxPdo Parameter object 0x1802
+V5.01 SDO6: Update SDO response interface handling. (used if the object access function returns "ABORTIDX_WORKING" and SDO_RES_INTERFACE is active)
+ Changes to version V4.40:
+V5.0 TEST1: Add test application. See Application Note ET9300 for more details.
+V5.0 COE1: Add reserved Subindex7 to object 0x1C32 and 0x1C33.
+V5.0 COE4: Create object dictionary on device startup.
+V5.0 COE6: Update entry descriptions for object with the code ARRAY.
+V5.0 ECAT2: Reference to application specific object dictionary is set to "ApplicationObjDic".
+ Changes to version V4.30:
+V4.40 COE 6: change dynamic object dictionary handling
+V4.40 CiA402 2: enable freerun Sync Mode for CiA402 Device (The motion controller application will only be triggered if DC Synchronisation is disabled)
+V4.40 COE5: move identification and synchronisation object values to ecat_def.h
+V4.40 DIAG1: Add diagnosis object 0x10F3
+V4.40 OBJ3: Update the global object dictionary pointer if a new list head is added
+V4.40 COE4: Prevent access NULL pointer
+V4.40 SYNC1: Initialize 0x1C3x objects
+V4.40 HW1: Add (adapt) objects for FC1100 support
+ Changes to version V4.20:
+V4.30 OBJ 3: Handle object dictionary in double link list
+V4.30 OBJ 2: General EtherCAT device objects are moved from chnappl.h to coeappl.c
+V4.30 SYNC: set 0x1C32:05; 0x1C33:05 (minCyleTime) to MIN_PD_CYCLE_TIME
+ (should be set dynamic if required)
+V4.30 PDO: rename PDO specific function calls
+ (PDO specific functions are moved to ecatappl.c)
+V4.20 PIC24: Add EL9800_4 (PIC24) required source code
+V4.11 ECAT 1: C166: MinDelayTime renamed in CalcAndCopyTime
+ Changes to version V4.07:
+V4.10 ECAT 1: To save and restore arrays in the object directory.
+ The code to get the size of an array entry was changed.
+V4.10 COE 1: The SM-Parameter were extended
+ Changes to version V4.06:
+V4.07 COEAPPL 1: The PDO numbers were adapted according top the modular device profile,
+ the PDO numbers increment now with every module (in chnappl.h)
+V4.07 COEAPPL 2: The example is working for the NIOS with the evaluation board DBC2C20 V1.2
+ which is available by Altera
+V4.07 ECAT 1: The sources for SPI and MCI were merged (in ecat_def.h
+ set the switch MCI_HW to 1 when using the MCI,
+ set the switch SPI_HW to 1 when using the SPI
+ Changes to version V4.03:
+V4.04 SDO 1: The SDO interface was changed in that way that a SDO response
+ could be sent by the application to a later time. In that case
+ the functions OBJ_Read and OBJ_Write shall return the value
+ ABORTIDX_WORKING. To send the SDO response the new function SDOS_SdoRes
+ has to be called by the application. While waiting for the call
+ of SDOS_SdoRes the SDO interface will answer to another SDO request
+ with the error MBXERR_SERVICEINWORK in the mailbox protocol.
+ In this example the reading and writing of object 0x8020 is delayed,
+ the function SDOS_SdoRes will be called from COE_Main.
+ Changes to version V4.00:
+V4.01 COEAPPL 1: The object dictionary and the mapping functions are now defined
+ in chnappl.h (chnappl.inc made problems with some developing tools)
+ Changes to version V3.20:
+V4.00 COEAPPL 1: The object dictionary and the mapping functions are now defined
+ in chnappl.c and were adapted to the modular device profile
+V4.00 COEAPPL 2: The handling of backup parameters was included according to
+ the EtherCAT Guidelines and Protocol Enhancements Specification
+V4.00 COEAPPL 3: The handling of the TxPDO Toggle was included according to
+ the EtherCAT Guidelines and Protocol Enhancements Specification
+V4.00 COEAPPL 4: The handling of the TxPDO State was included according to
+ the EtherCAT Guidelines and Protocol Enhancements Specification
+V4.00 ECAT 1: The handling of the Sync Manager Parameter was included according to
+ the EtherCAT Guidelines and Protocol Enhancements Specification
+*/
+
+/*-----------------------------------------------------------------------------------------
+------
+------ Includes
+------
+-----------------------------------------------------------------------------------------*/
+
+#include "ecat_def.h"
+
+
+#include "ecatslv.h"
+
+#define _COEAPPL_ 1
+#include "coeappl.h"
+#undef _COEAPPL_
+/*remove definition of _COEAPPL_ (#ifdef is used in coeappl.h)*/
+
+#define _OBJD_
+/*ET9300 Project Handler :(#if DIAGNOSIS_SUPPORTED && !TEST_APPLICATION) lines 130 to 133 deleted*/
+
+
+/*Add Application specific Objects*/
+/*ECATCHANGE_START(V5.13) CIA402 3*/
+/*ET9300 Project Handler :(#if CiA402_SAMPLE_APPLICATION #elif EL9800_APPLICATION #elif SAMPLE_APPLICATION #elif TEST_APPLICATION #elif SAMPLE_APPLICATION_INTERFACE) lines 138 to 149 deleted*/
+extern TOBJECT OBJMEM ApplicationObjDic[];
+
+
+#undef _OBJD_
+/*-----------------------------------------------------------------------------------------
+------
+------ Backup Parameter
+------
+-----------------------------------------------------------------------------------------*/
+/*ET9300 Project Handler :(#if BACKUP_PARAMETER_SUPPORTED) lines 161 to 168 deleted*/
+
+/*-----------------------------------------------------------------------------------------
+------
+------ Generic EtherCAT device object
+------
+-----------------------------------------------------------------------------------------*/
+
+/*---------------------------------------------
+- 0x1000
+-----------------------------------------------*/
+/**
+ * \brief 0x1000 (Device type) variable to handle the object data
+ */
+UINT32 u32Devicetype = (DEVICE_PROFILE_TYPE);
+
+/**
+ * \brief 0x1000 (Device type) entry description
+ */
+OBJCONST TSDOINFOENTRYDESC OBJMEM sEntryDesc0x1000 = {DEFTYPE_UNSIGNED32, 0x20, ACCESS_READ};
+
+/**
+ * \brief 0x1000 (Device type) object name
+ */
+OBJCONST UCHAR OBJMEM aName0x1000[] = "Device type";
+
+
+/*---------------------------------------------
+- 0x1001
+-----------------------------------------------*/
+/**
+ * \brief 0x1001 (Error Register) variable to handle the object data
+ */
+UINT16 u16ErrorRegister = 0x0;
+
+/**
+ * \brief 0x1001 (Error Register) entry description
+ */
+OBJCONST TSDOINFOENTRYDESC OBJMEM sEntryDesc0x1001 = {DEFTYPE_UNSIGNED8, 0x08, ACCESS_READ};
+
+/**
+ * \brief 0x1001 (Error Register) object name
+ */
+OBJCONST UCHAR OBJMEM aName0x1001[] = "Error register";
+
+
+/*---------------------------------------------
+- 0x1008
+-----------------------------------------------*/
+/**
+ * \brief 0x1008 (Device name) variable to handle the object data
+ */
+CHAR acDevicename[] = DEVICE_NAME;
+
+/**
+ * \brief 0x1008 (Device name) entry description
+ */
+OBJCONST TSDOINFOENTRYDESC OBJMEM sEntryDesc0x1008 = {DEFTYPE_VISIBLESTRING, BYTE2BIT(DEVICE_NAME_LEN), ACCESS_READ};
+
+/**
+ * \brief 0x1008 (Device name) object name
+ */
+OBJCONST UCHAR OBJMEM aName0x1008[] = "Device name";
+
+
+/*---------------------------------------------
+- 0x1009
+-----------------------------------------------*/
+/**
+ * \brief 0x1009 (Hardware version) variable to handle the object data
+ */
+CHAR acHardwareversion[] = DEVICE_HW_VERSION;
+
+/**
+ * \brief 0x1009 (Hardware version) entry description
+ */
+OBJCONST TSDOINFOENTRYDESC OBJMEM sEntryDesc0x1009 = {DEFTYPE_VISIBLESTRING,BYTE2BIT(DEVICE_HW_VERSION_LEN), ACCESS_READ};
+
+/**
+ * \brief 0x1009 (Hardware version) object name
+ */
+OBJCONST UCHAR OBJMEM aName0x1009[] = "Manufacturer Hardware version";
+
+
+/*---------------------------------------------
+- 0x100A
+-----------------------------------------------*/
+/**
+ * \brief 0x100A (Software version) variable to handle the object data
+ */
+CHAR acSoftwareversion[] = DEVICE_SW_VERSION;
+
+/**
+ * \brief 0x100A (Software version) entry description
+ */
+OBJCONST TSDOINFOENTRYDESC OBJMEM sEntryDesc0x100A = {DEFTYPE_VISIBLESTRING,BYTE2BIT(DEVICE_SW_VERSION_LEN), ACCESS_READ};
+
+/**
+ * \brief 0x100A (Software version) object name
+ */
+OBJCONST UCHAR OBJMEM aName0x100A[] = "Manufacturer Software version";
+
+
+/*ET9300 Project Handler :(#if BACKUP_PARAMETER_SUPPORTED) lines 271 to 397 deleted*/
+
+
+/*---------------------------------------------
+- 0x1018
+-----------------------------------------------*/
+
+/**
+ * \brief 0x1018 (Identity) variable to handle the object data
+ */
+TOBJ1018 sIdentity = {4, (VENDOR_ID), (PRODUCT_CODE), (REVISION_NUMBER), (SERIAL_NUMBER)};
+
+/**
+ * \brief 0x1018 (Identity) entry descriptions
+ *
+ * Subindex 000
+ * SubIndex 001: Vendor ID
+ * SubIndex 002: Product code
+ * SubIndex 003: Revision
+ * SubIndex 004: Serial number
+ */
+OBJCONST TSDOINFOENTRYDESC OBJMEM asEntryDesc0x1018[] = {
+ {DEFTYPE_UNSIGNED8, 0x8, ACCESS_READ },
+ {DEFTYPE_UNSIGNED32, 0x20, ACCESS_READ},
+ {DEFTYPE_UNSIGNED32, 0x20, ACCESS_READ},
+ {DEFTYPE_UNSIGNED32, 0x20, ACCESS_READ},
+ {DEFTYPE_UNSIGNED32, 0x20, ACCESS_READ}};
+
+/**
+ * \brief 0x1018 (Identity) object and entry names
+ */
+OBJCONST UCHAR OBJMEM aName0x1018[] = "Identity Object\000Vendor ID\000Product Code\000Revision Number\000Serial Number\000\377";
+
+
+/*ET9300 Project Handler :(#if BACKUP_PARAMETER_SUPPORTED) lines 431 to 456 deleted*/
+
+/*---------------------------------------------
+- 0x10F1
+-----------------------------------------------*/
+/**
+ * \brief 0x10F1 (Error settings) entry description
+ * Subindex 000
+ * SubIndex 001: Local Error Reaction
+ * SubIndex 002: Sync Error Counter Limit
+ */
+OBJCONST TSDOINFOENTRYDESC OBJMEM asEntryDesc0x10F1[] = {
+ {DEFTYPE_UNSIGNED8, 0x8, ACCESS_READ },
+/*ECATCHANGE_START(V5.13) COE10*/
+ {DEFTYPE_UNSIGNED32, 0x20, ACCESS_READ},
+/*ECATCHANGE_END(V5.13) COE10*/
+ {DEFTYPE_UNSIGNED16, 0x10, ACCESS_READWRITE}};
+
+/**
+ * \brief 0x10F1 (Error settings) object and entry names
+ */
+OBJCONST UCHAR OBJMEM aName0x10F1[] = "Error Settings\000Local Error Reaction\000Sync Error Counter Limit\000\377";
+
+
+//object declaration and initialization in objdef.h
+
+
+/*---------------------------------------------
+- 0x10F8 (Timestamp object)
+-----------------------------------------------*/
+/**
+* \brief 0x10F8 (Timestamp object) entry description
+*/
+OBJCONST TSDOINFOENTRYDESC OBJMEM sEntryDesc0x10F8 = { DEFTYPE_UNSIGNED64, 0x40, ACCESS_READWRITE | OBJACCESS_TXPDOMAPPING } ;
+/**
+* \brief 0x10F8 (Timestamp object) object name
+*/
+OBJCONST UCHAR OBJMEM aName0x10F8[] = "Timestamp Object\000\377";
+
+
+//object declaration and initialization in coeappl.h
+
+/**
+\param index index of the requested object.
+\param subindex subindex of the requested object.
+\param dataSize received data size of the SDO Download
+\param pData Pointer to the buffer where the written data can be copied from
+\param bCompleteAccess Indicates if a complete write of all subindices of the
+object shall be done or not
+
+\return result of the write operation (0 (success) or an abort code (ABORTIDX_.... defined in
+sdosrv.h))
+
+\brief This function reads the object 0x10F8
+*/
+UINT8 Read0x10F8(UINT16 index, UINT8 subindex, UINT32 dataSize, UINT16 MBXMEM * pData, UINT8 bCompleteAccess)
+{
+
+ if (index != 0x10F8)
+ {
+ return ABORTIDX_PARAM_IS_INCOMPATIBLE;
+ }
+
+
+ if (bCompleteAccess)
+ {
+ /* Complete Access is not supported for object 0x10F8 */
+ return ABORTIDX_UNSUPPORTED_ACCESS;
+ }
+
+ if (subindex > 0)
+ {
+ return ABORTIDX_SUBINDEX_NOT_EXISTING;
+ }
+
+ if (dataSize > 8)
+ {
+ return ABORTIDX_PARAM_LENGTH_TOO_LONG;
+ }
+
+
+/*ET9300 Project Handler :(#if DC_SUPPORTED) lines 540 to 542 deleted*/
+
+ MEMCPY(pData, &u64Timestamp, dataSize);
+ return 0;
+}
+
+
+/*ET9300 Project Handler :(#if DC_SUPPORTED) lines 550 to 587 deleted*/
+
+
+
+/*---------------------------------------------
+- 0x1C00
+-----------------------------------------------*/
+
+/**
+ * \brief 0x1C00 (Sync manager type) variable to handle the object data
+ *
+ * SI 0 : 4 (4 SyncManagers available)
+ * SI1 (SM0): Mailbox Out (0x1)
+ * SI2 (SM1): Mailbox In (0x2)
+ * SI3 (SM2): Process data Out (0x3)
+ * SI4 (SM3): Process data In (0x4)
+ *
+ */
+ /*ECATCHANGE_START(V5.13)*/
+TOBJ1C00 sSyncmanagertype = {0x04, {0x0201, 0x0403}};
+/*ECATCHANGE_END(V5.13)*/
+
+
+/**
+ * \brief 0x1C00 (Sync manager type) entry descriptions
+ *
+ * The object is an array so only the first entry is described (which is used for all entries).
+ */
+OBJCONST TSDOINFOENTRYDESC OBJMEM asEntryDesc0x1C00[] = {
+ {DEFTYPE_UNSIGNED8, 0x08, ACCESS_READ},
+ {DEFTYPE_UNSIGNED8, 0x08, ACCESS_READ}};
+
+/**
+ * \brief 0x1C00 (Sync manager type) object name
+ */
+OBJCONST UCHAR OBJMEM aName0x1C00[] = "Sync manager type";
+
+
+/*---------------------------------------------
+- 0x1C3x
+-----------------------------------------------*/
+/**
+ * \brief 0x1C3x (SyncManager parameter) entry description
+ *
+ * The entry descriptions are used for 0x1C32 and 0x1C33
+ */
+OBJCONST TSDOINFOENTRYDESC OBJMEM asEntryDesc0x1C3x[] = {
+ {DEFTYPE_UNSIGNED8, 0x8, ACCESS_READ }, /* Subindex 000 */
+/*ET9300 Project Handler :(#if !AL_EVENT_ENABLED && !DC_SUPPORTED) lines 635 to 637 deleted*/
+ {DEFTYPE_UNSIGNED16, 0x10, (ACCESS_READ | ACCESS_WRITE_PREOP)}, /* SubIndex 001: Synchronization Type */
+ {DEFTYPE_UNSIGNED32, 0x20, ACCESS_READ}, /* SubIndex 002: Cycle Time */
+ {0x0000, 0x20, 0}, /* SubIndex 003: Shift Time (not supported)*/
+ {DEFTYPE_UNSIGNED16, 0x10, ACCESS_READ}, /* SubIndex 004: Synchronization Types supported */
+ {DEFTYPE_UNSIGNED32, 0x20, ACCESS_READ}, /* SubIndex 005: Minimum Cycle Time */
+ {DEFTYPE_UNSIGNED32, 0x20, ACCESS_READ}, /* SubIndex 006: Calc and Copy Time */
+ {0x0000, 0x20, 0}, /* Subindex 007 Minimum Delay Time (not supported)*/
+ {DEFTYPE_UNSIGNED16, 0x10, ACCESS_READWRITE}, /* SubIndex 008: Get Cycle Time */
+ {DEFTYPE_UNSIGNED32, 0x20, ACCESS_READ}, /* SubIndex 009: Delay Time */
+ {DEFTYPE_UNSIGNED32, 0x20, ACCESS_READWRITE}, /* SubIndex 010: Sync0 Cycle Time */
+ {DEFTYPE_UNSIGNED16, 0x10, ACCESS_READ}, /* SubIndex 011: SM-Event Missed */
+ {DEFTYPE_UNSIGNED16, 0x10, ACCESS_READ}, /* SubIndex 012: Cycle Time Too Small */
+ /*ECATCHANGE_START(V5.13) COE7*/
+ {DEFTYPE_UNSIGNED16, 0x10, ACCESS_READ}, /* SubIndex 013: Shift Too Short Counter*/
+ /*ECATCHANGE_END(V5.13) COE7*/
+ {0x0000, 0x10, 0}, /* Subindex 014: RxPDO Toggle Failed (not supported)*/
+ {0x0000, 0x20, 0}, /* Subindex 015: Minimum Cycle Distance (not supported)*/
+ {0x0000, 0x20, 0}, /* Subindex 016: Maximum Cycle Distance (not supported)*/
+ {0x0000, 0x20, 0}, /* Subindex 017: Minimum SM Sync Distance (not supported)*/
+ {0x0000, 0x20, 0}, /* Subindex 018: Maximum SM Sync Distance (not supported)*/
+ {0x0000, 0, 0}, /* Subindex 019 doesn't exist */
+ {0x0000, 0, 0}, /* Subindex 020 doesn't exist */
+ {0x0000, 0, 0}, /* Subindex 021 doesn't exist */
+ {0x0000, 0, 0}, /* Subindex 022 doesn't exist */
+ {0x0000, 0, 0}, /* Subindex 023 doesn't exist */
+ {0x0000, 0, 0}, /* Subindex 024 doesn't exist */
+ {0x0000, 0, 0}, /* Subindex 025 doesn't exist */
+ {0x0000, 0, 0}, /* Subindex 026 doesn't exist */
+ {0x0000, 0, 0}, /* Subindex 027 doesn't exist */
+ {0x0000, 0, 0}, /* Subindex 028 doesn't exist */
+ {0x0000, 0, 0}, /* Subindex 029 doesn't exist */
+ {0x0000, 0, 0}, /* Subindex 030 doesn't exist */
+ {0x0000, 0, 0}, /* Subindex 031 doesn't exist */
+ {DEFTYPE_BOOLEAN, 0x01, ACCESS_READ}}; /* SubIndex 032: Sync error */
+
+/**
+ * \brief 0x1C32 (SyncManager 2 parameter) object and entry names
+ */
+OBJCONST UCHAR OBJMEM aName0x1C32[] = "SM output parameter\000Synchronization Type\000Cycle Time\000\000Synchronization Types supported\000Minimum Cycle Time\000Calc and Copy Time\000\000Get Cycle Time\000Delay Time\000Sync0 Cycle Time\000SM-Event Missed\000Cycle Time Too Small\000Shift Time Too Short Counter\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000Sync Error\000\377";
+
+/**
+ * \brief 0x1C33 (SyncManager 3 parameter) object and entry names
+ */
+OBJCONST UCHAR OBJMEM aName0x1C33[] = "SM input parameter\000Synchronization Type\000Cycle Time\000\000Synchronization Types supported\000Minimum Cycle Time\000Calc and Copy Time\000\000Get Cycle Time\000Delay Time\000Sync0 Cycle Time\000SM-Event Missed\000Cycle Time Too Small\000Shift Time Too Short Counter\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000Sync Error\000\377";
+
+/******************************************************************************
+** Object Dictionary
+******************************************************************************/
+/**
+ * \brief Object dictionary pointer
+ */
+TOBJECT OBJMEM * ObjDicList = NULL;
+
+/**
+ * \brief List of generic application independent objects
+ */
+TOBJECT OBJMEM GenObjDic[] = {
+ /* Object 0x1000 */
+ {NULL,NULL, 0x1000, {DEFTYPE_UNSIGNED32, 0 | (OBJCODE_VAR << 8)}, &sEntryDesc0x1000, aName0x1000, &u32Devicetype, NULL, NULL, 0x0000 },
+ /* Object 0x1001 */
+ {NULL,NULL, 0x1001, {DEFTYPE_UNSIGNED8, 0 | (OBJCODE_VAR << 8)}, &sEntryDesc0x1001, aName0x1001, &u16ErrorRegister, NULL, NULL, 0x0000 },
+/* Object 0x1008 */
+ {NULL,NULL, 0x1008, {DEFTYPE_VISIBLESTRING, 0 | (OBJCODE_VAR << 8)}, &sEntryDesc0x1008, aName0x1008, acDevicename, NULL, NULL, 0x0000 },
+ /* Object 0x1009 */
+ {NULL,NULL, 0x1009, {DEFTYPE_VISIBLESTRING, 0 | (OBJCODE_VAR << 8)}, &sEntryDesc0x1009, aName0x1009, acHardwareversion, NULL, NULL, 0x0000 },
+ /* Object 0x100A */
+ {NULL,NULL, 0x100A, {DEFTYPE_VISIBLESTRING, 0 | (OBJCODE_VAR << 8)}, &sEntryDesc0x100A, aName0x100A, acSoftwareversion, NULL, NULL, 0x0000 },
+/*ET9300 Project Handler :(#if BACKUP_PARAMETER_SUPPORTED) lines 711 to 716 deleted*/
+ /* Object 0x1018 */
+ {NULL,NULL, 0x1018, {DEFTYPE_IDENTITY, 4 | (OBJCODE_REC << 8)}, asEntryDesc0x1018, aName0x1018, &sIdentity, NULL, NULL, 0x0000 },
+/*ET9300 Project Handler :(#if BACKUP_PARAMETER_SUPPORTED) lines 719 to 724 deleted*/
+ /* Object 0x10F1 */
+ {NULL,NULL, 0x10F1, {DEFTYPE_RECORD, 2 | (OBJCODE_REC << 8)}, asEntryDesc0x10F1, aName0x10F1, &sErrorSettings, NULL, NULL, 0x0000 },
+ /* Object 0x10F8 */
+ { NULL,NULL, 0x10F8,{ DEFTYPE_UNSIGNED64, 0 | (OBJCODE_VAR << 8) }, &sEntryDesc0x10F8, aName0x10F8, &u64Timestamp, Read0x10F8, NULL , 0x0000 },
+/*ET9300 Project Handler :(#if DIAGNOSIS_SUPPORTED) lines 730 to 733 deleted*/
+ /* Object 0x1C00 */
+ {NULL,NULL, 0x1C00, {DEFTYPE_UNSIGNED8, 4 | (OBJCODE_ARR << 8)}, asEntryDesc0x1C00, aName0x1C00, &sSyncmanagertype, NULL, NULL, 0x0000 },
+ /* Object 0x1C32 */
+ {NULL,NULL, 0x1C32, {DEFTYPE_SMPAR, 32 | (OBJCODE_REC << 8)}, asEntryDesc0x1C3x, aName0x1C32, &sSyncManOutPar, NULL, NULL, 0x0000 },
+ /* Object 0x1C33 */
+ {NULL,NULL, 0x1C33, {DEFTYPE_SMPAR, 32 | (OBJCODE_REC << 8)}, asEntryDesc0x1C3x, aName0x1C33, &sSyncManInPar, NULL, NULL, 0x0000 },
+
+ /*end of entries*/
+ {NULL,NULL, 0xFFFF, {0, 0}, NULL, NULL, NULL, NULL, NULL, 0x000}};
+
+/*ET9300 Project Handler :(#if !STATIC_OBJECT_DIC #else) lines 749 to 820 deleted*/
+
+/*-----------------------------------------------------------------------------------------
+------
+------ Functions
+------
+-----------------------------------------------------------------------------------------*/
+
+/////////////////////////////////////////////////////////////////////////////////////////
+/**
+
+ \brief returns the pointer to the object dictionary
+*////////////////////////////////////////////////////////////////////////////////////////
+OBJCONST TOBJECT OBJMEM * COE_GetObjectDictionary(void)
+{
+ return (OBJCONST TOBJECT OBJMEM *) ObjDicList;
+}
+
+/*ET9300 Project Handler :(#if BACKUP_PARAMETER_SUPPORTED) lines 838 to 1048 deleted*/
+
+/////////////////////////////////////////////////////////////////////////////////////////
+/**
+\brief Update the Sync Error Indication
+*////////////////////////////////////////////////////////////////////////////////////////
+void COE_UpdateSyncErrorStatus(void)
+{
+ if (sSyncManOutPar.u16CycleExceededCounter > 0 || sSyncManOutPar.u16SmEventMissedCounter > sErrorSettings.u16SyncErrorCounterLimit)
+/*ET9300 Project Handler :(#if !_PIC18 #else) lines 1059 to 1061 deleted*/
+ {
+ sSyncManOutPar.u8SyncError = 1;
+ }
+ else
+ {
+ sSyncManOutPar.u8SyncError = 0;
+ }
+
+
+ if (sSyncManInPar.u16CycleExceededCounter > 0 || sSyncManInPar.u16SmEventMissedCounter > sErrorSettings.u16SyncErrorCounterLimit)
+/*ET9300 Project Handler :(#if !_PIC18 #else) lines 1075 to 1077 deleted*/
+ {
+ sSyncManInPar.u8SyncError = 1;
+ }
+ else
+ {
+ sSyncManInPar.u8SyncError = 0;
+ }
+
+}
+
+/////////////////////////////////////////////////////////////////////////////////////////
+/**
+ \brief This function initialize the several objects
+*////////////////////////////////////////////////////////////////////////////////////////
+
+void COE_ObjInit(void)
+{
+
+ /* initialize the Sync Manager Output parameter object 0x1C32 */
+
+ sSyncManOutPar.subindex0 = 32;
+ /*
+ subindex 1 contains the actual synchronization mode, it could be written
+ from the master to switch between ECAT FreeRun and ECAT Synchron Mode
+ if the slave supports both modes,
+ in DC mode (selected by the DC registers) this value will be overwritten
+ with SYNCTYPE_DCSYNC0 or SYNCTYPE_DCSYNC1 */
+ /*default mode is ECAT Synchron Mode */
+ sSyncManOutPar.u16SyncType = SYNCTYPE_FREERUN;
+
+ /* subindex 2 contains the cycle time of the application,
+ in ECAT FreeRun mode it could be used for a timer interrupt to run the application,
+ in ECAT Synchron mode it could be written from the master with its local cycle time
+ that the slave can check if this cycle time is supported,
+ in DC Mode this value will be overwritten with the DC cycle time register */
+ sSyncManOutPar.u32CycleTime = 0;
+
+ /* the subindex 4 contains the supported synchronization types */
+
+ sSyncManOutPar.u16SyncTypesSupported = SYNCTYPE_FREERUNSUPP /* ECAT FreeRun Mode is supported */
+
+#if (PD_OUTPUT_CALC_AND_COPY_TIME == 0) || (PD_INPUT_CALC_AND_COPY_TIME == 0) || (MIN_PD_CYCLE_TIME == 0)
+ | SYNCTYPE_TIMESVARIABLE /* the execution times depend on the connected modules */
+#endif
+ | SYNCTYPE_SYNCHRONSUPP /* ECAT Synchron Mode is supported */
+/*ET9300 Project Handler :(#if DC_SUPPORTED) lines 1127 to 1133 deleted*/
+ ;
+
+ /* subindex 5 contains the minimum cycle time the slave is able to support,
+ will be calculated dynamically because it depends on the connected modules
+ (in this example we will make an online measurement in the ESC Interrupt Routine).
+ For the sample application this value is set to MIN_PD_CYCLE_TIME */
+ sSyncManOutPar.u32MinCycleTime = MIN_PD_CYCLE_TIME;
+ /* only for DC Mode important: subindex 6 contains the minimum delay time the slave
+ needs after receiving the SM2-event before the SYNC0(SYNC1) can be received without delays
+ will be calculated dynamically because it depends on the connected modules
+ (in this example we will make an online measurement in the ESC Interrupt Routine) */
+ sSyncManOutPar.u32CalcAndCopyTime = (PD_OUTPUT_CALC_AND_COPY_TIME);
+
+ /*subindex 8: trigger cycle time measurement*/
+ sSyncManOutPar.u16GetCycleTime = 0;
+
+ /*subindex 9: time from start driving outputs until outputs are valid*/
+ sSyncManOutPar.u32DelayTime = (PD_OUTPUT_DELAY_TIME);
+
+ /*subindex 11: reset the sm missed error counter*/
+ sSyncManOutPar.u16SmEventMissedCounter = 0;
+
+ /*subindex 12: reset the cycle exceed error counter*/
+ sSyncManOutPar.u16CycleExceededCounter = 0;
+
+ /*subindex 32: indicates if a synchronisation error has occurred*/
+ sSyncManOutPar.u8SyncError = 0;
+
+ /* initialize the Sync Manager Input parameter object 0x1C33 */
+ sSyncManInPar.subindex0 = 32;
+ /* default mode is ECAT Synchron Mode, if output size > 0 the inputs are updated with the SM2-event */
+ sSyncManInPar.u16SyncType = SYNCTYPE_FREERUN;
+
+
+ /* subindex 2: same as 0x1C32:02 */
+ sSyncManInPar.u32CycleTime = sSyncManOutPar.u32CycleTime;
+/*ET9300 Project Handler :(#if MAX_PD_OUTPUT_SIZE > 0 #else) lines 1173 to 1175 deleted*/
+
+ /* subindex 4: same as 0x1C32:04 */
+ sSyncManInPar.u16SyncTypesSupported = sSyncManOutPar.u16SyncTypesSupported;
+/*ET9300 Project Handler :(#elif MAX_PD_INPUT_SIZE > 0) lines 1180 to 1198 deleted*/
+
+ /* subindex 5: same as 0x1C32:05 */
+ sSyncManInPar.u32MinCycleTime = MIN_PD_CYCLE_TIME;
+ /* subindex 6: delay read inputs, calculation and copy to SM buffer*/
+ sSyncManInPar.u32CalcAndCopyTime = (PD_INPUT_CALC_AND_COPY_TIME);
+ /*subindex 8: trigger cycle time measurement*/
+ sSyncManInPar.u16GetCycleTime = 0;
+ /*subindex 9: delay to prepare input latch*/
+ sSyncManInPar.u32DelayTime = (PD_INPUT_DELAY_TIME);
+
+ /*subindex 11: reset the sm missed error counter*/
+ sSyncManInPar.u16SmEventMissedCounter = 0;
+
+ /*subindex 12: reset the cycle exceed error counter*/
+ sSyncManInPar.u16CycleExceededCounter = 0;
+
+ /*subindex 32: incremented if a synchronisation error has occurred*/
+ sSyncManInPar.u8SyncError = 0;
+
+ /*Indicate no user specified Sync mode*/
+ bSyncSetByUser = FALSE;
+
+ {
+ UINT16 result = COE_ObjDictionaryInit();
+ if(result != 0)
+ {
+ /*clear already linked objects*/
+ COE_ClearObjDictionary();
+ }
+ }
+
+ u8PendingSdo = 0;
+ bStoreCompleteAccess = FALSE;
+ u16StoreIndex = 0;
+ u8StoreSubindex = 0;
+ u32StoreDataSize = 0;
+ pStoreData = NULL;
+ pSdoPendFunc = NULL;
+
+ pSdoSegData = NULL;
+
+/*ET9300 Project Handler :(#if BACKUP_PARAMETER_SUPPORTED) lines 1247 to 1259 deleted*/
+
+/*ET9300 Project Handler :(#if DC_SUPPORTED) lines 1261 to 1280 deleted*/
+}
+
+/////////////////////////////////////////////////////////////////////////////////////////
+/**
+ \return 0 object successful added to object dictionary
+ ALSTATUSCODE_XX add object failed
+
+ \brief This function adds an object to the object dictionary
+ *////////////////////////////////////////////////////////////////////////////////////////
+UINT16 COE_AddObjectToDic(TOBJECT OBJMEM * pNewObjEntry)
+{
+ if(pNewObjEntry != NULL)
+ {
+ if(ObjDicList == NULL)
+ {
+ /* Object dictionary is empty */
+ ObjDicList = pNewObjEntry;
+ ObjDicList->pNext = NULL;
+ ObjDicList->pPrev = NULL;
+ return 0;
+ }
+ else if(ObjDicList->Index > pNewObjEntry->Index)
+ {
+ /*insert new object dictionary head*/
+ pNewObjEntry->pPrev = NULL;
+ pNewObjEntry->pNext = ObjDicList;
+ ObjDicList->pPrev = pNewObjEntry;
+ ObjDicList = pNewObjEntry;
+ return 0;
+ }
+ else
+ {
+ TOBJECT OBJMEM * pDicEntry = ObjDicList;
+ while(pDicEntry != NULL)
+ {
+ if(pDicEntry->Index == pNewObjEntry->Index)
+ {
+ /*object already exists in object dictionary*/
+ return ALSTATUSCODE_UNSPECIFIEDERROR;
+ }
+ else if(pDicEntry->Index > pNewObjEntry->Index)
+ {
+ pNewObjEntry->pPrev = pDicEntry->pPrev;
+ pNewObjEntry->pNext = pDicEntry;
+
+ if(pDicEntry->pPrev != NULL)
+ pDicEntry->pPrev->pNext = pNewObjEntry;
+
+ pDicEntry->pPrev = pNewObjEntry;
+
+ return 0;
+ }
+ else if(pDicEntry->pNext == NULL)
+ {
+ /*Last entry reached => add object to list tail*/
+ pDicEntry->pNext = pNewObjEntry;
+ pNewObjEntry->pPrev = pDicEntry;
+ pNewObjEntry->pNext = NULL;
+ return 0;
+ }
+ else
+ {
+ /*The new object index is smaller than the current index. Get next object handle.*/
+ pDicEntry = pDicEntry->pNext;
+ }
+ }
+ }
+ }
+ return ALSTATUSCODE_UNSPECIFIEDERROR;
+}
+/////////////////////////////////////////////////////////////////////////////////////////
+/**
+
+ \brief This function removes an object to the object dictionary
+*////////////////////////////////////////////////////////////////////////////////////////
+void COE_RemoveDicEntry(UINT16 index)
+{
+ TOBJECT OBJMEM * pDicEntry = ObjDicList;
+
+ while(pDicEntry != NULL)
+ {
+ if(pDicEntry->Index == index)
+ {
+ TOBJECT OBJMEM *pPrevEntry = pDicEntry->pPrev;
+ TOBJECT OBJMEM *pNextEntry = pDicEntry->pNext;
+
+ if(pPrevEntry != NULL)
+ {
+ pPrevEntry->pNext = pNextEntry;
+ }
+
+ if(pNextEntry != NULL)
+ {
+ pNextEntry->pPrev = pPrevEntry;
+ }
+
+ pDicEntry->pPrev = NULL;
+ pDicEntry->pNext = NULL;
+ /*Update Object dictionary pointer if list head was removed*/
+ if(pDicEntry->Index == ObjDicList->Index)
+ {
+ ObjDicList = pNextEntry;
+ }
+ return;
+ }
+
+ pDicEntry = pDicEntry->pNext;
+ }
+}
+/////////////////////////////////////////////////////////////////////////////////////////
+/**
+
+ \brief This function clear the object dictionary
+*////////////////////////////////////////////////////////////////////////////////////////
+void COE_ClearObjDictionary(void)
+{
+ TOBJECT OBJMEM * pObjEntry = (TOBJECT OBJMEM *) ObjDicList;
+ UINT16 Index = 0;
+
+ while(pObjEntry != NULL)
+ {
+ Index = pObjEntry->Index;
+ pObjEntry = pObjEntry->pNext;
+
+ COE_RemoveDicEntry(Index);
+ }
+ ObjDicList = NULL;
+}
+
+
+UINT16 AddObjectsToObjDictionary(TOBJECT OBJMEM * pObjEntry)
+{
+ UINT16 result = 0;
+ TOBJECT OBJMEM * pEntry = (TOBJECT OBJMEM *)pObjEntry;
+
+ while(pEntry->Index != 0xFFFF)
+ {
+ result = COE_AddObjectToDic(pEntry);
+
+ if(result != 0)
+ {
+ return result;
+ }
+
+ pEntry++;
+ }
+
+ return result;
+
+}
+/////////////////////////////////////////////////////////////////////////////////////////
+/**
+ \return 0 object dictionary created successful
+ ALSTATUSCODE_XX create object dictionary failed
+
+ \brief This function initialize the object dictionary
+*////////////////////////////////////////////////////////////////////////////////////////
+UINT16 COE_ObjDictionaryInit(void)
+{
+ UINT16 result = 0;
+
+ /*Reset object dictionary pointer*/
+ ObjDicList = NULL;
+
+ result = AddObjectsToObjDictionary((TOBJECT OBJMEM *) GenObjDic);
+
+ if(result != 0)
+ {
+ return result;
+ }
+
+ if(ApplicationObjDic != NULL)
+ {
+ result = AddObjectsToObjDictionary((TOBJECT OBJMEM *) ApplicationObjDic);
+ }
+
+
+
+ return result;
+}
+
+
+/////////////////////////////////////////////////////////////////////////////////////////
+/**
+
+ \brief is called for background calculations which should not influence the
+ ECAT_Application in synchronous modes
+*////////////////////////////////////////////////////////////////////////////////////////
+
+void COE_Main(void)
+{
+ UINT8 abort = 0;
+
+ if(pSdoPendFunc != NULL)
+ {
+ abort = pSdoPendFunc(u16StoreIndex,u8StoreSubindex,u32StoreDataSize,pStoreData,bStoreCompleteAccess);
+
+ if(abort != ABORTIDX_WORKING)
+ {
+ switch(u8PendingSdo)
+ {
+ case SDO_PENDING_SEG_WRITE:
+ if(pSdoSegData)
+ {
+ /* the allocated buffer can be released */
+ FREEMEM( (UINT16 VARMEM *) pSdoSegData );
+ pSdoSegData = NULL;
+ }
+ case SDO_PENDING_WRITE:
+ /*send SDO Download Response*/
+ SDOS_SdoRes(abort, 0, NULL);
+ break;
+
+ case SDO_PENDING_SEG_READ:
+ case SDO_PENDING_READ:
+ /* send SDO upload response */
+ SDOS_SdoRes(abort, u32StoreDataSize, pStoreData);
+ break;
+
+ }
+
+ u8PendingSdo = 0;
+ u16StoreIndex = 0;
+ u8StoreSubindex = 0;
+ u32StoreDataSize = 0;
+ pStoreData = NULL;
+ bStoreCompleteAccess = 0;
+ pSdoPendFunc = NULL;
+ }
+ }
+}
+
+/** @} */
diff --git a/Projects/EFC_EcatDriver/src/ssc/coeappl.h b/Projects/EFC_EcatDriver/src/ssc/coeappl.h
new file mode 100644
index 0000000..26cc08f
--- /dev/null
+++ b/Projects/EFC_EcatDriver/src/ssc/coeappl.h
@@ -0,0 +1,120 @@
+/*
+* This source file is part of the EtherCAT Slave Stack Code licensed by Beckhoff Automation GmbH & Co KG, 33415 Verl, Germany.
+* The corresponding license agreement applies. This hint shall not be removed.
+* https://www.beckhoff.com/media/downloads/slave-stack-code/ethercat_ssc_license.pdf
+*/
+
+/**
+ * \addtogroup CoE CAN Application Profile over EtherCAT
+ * @{
+ */
+
+/**
+\file coeappl.h
+\author EthercatSSC@beckhoff.com
+
+\version 5.13
+
+ Changes to version V5.12:
+V5.13 COE6: add 0x10F0.2 (Backup parameter changed)
+ Changes to version V5.11:
+V5.12 COE4: add timestamp object (0x10F8) and update diagnosis handling
+V5.12 ECAT5: update Sync error counter/flag handling,check enum memory alignment depending on the processor,in case of a polled timer disable ESC interrupts during DC_CheckWatchdog
+ Changes to version V5.01:
+V5.11 ECAT10: change PROTO handling to prevent compiler errors
+ Changes to version - :
+V5.01 : Start file change log
+ */
+
+/*-----------------------------------------------------------------------------------------
+------
+------ Includes
+------
+-----------------------------------------------------------------------------------------*/
+#include "objdef.h"
+#include "ecatappl.h"
+
+#ifndef _COEAPPL_H_
+#define _COEAPPL_H_
+
+/*-----------------------------------------------------------------------------------------
+------
+------ Defines and Types
+------
+-----------------------------------------------------------------------------------------*/
+/*ET9300 Project Handler :(#if BACKUP_PARAMETER_SUPPORTED) lines 44 to 69 deleted*/
+
+
+/*---------------------------------------------
+- 0x1018
+-----------------------------------------------*/
+/**
+* \brief 0x1018 (Identity) object structure
+*/
+typedef struct OBJ_STRUCT_PACKED_START {
+ UINT16 u16SubIndex0; /**< \brief SubIndex 0*/
+ UINT32 u32VendorID; /**< \brief EtherCAT vendor ID */
+ UINT32 u32Productcode; /**< \brief Product code*/
+ UINT32 u32Revision; /**< \brief Revision number*/
+ UINT32 u32Serialnumber; /**< \brief Serial number*/
+} OBJ_STRUCT_PACKED_END
+TOBJ1018;
+
+
+
+/*ET9300 Project Handler :(#if BACKUP_PARAMETER_SUPPORTED) lines 89 to 105 deleted*/
+
+
+/*---------------------------------------------
+- 0x1C00
+-----------------------------------------------*/
+/**
+* \brief 0x1C00 (Sync manager type) object structure
+*/
+typedef struct OBJ_STRUCT_PACKED_START {
+ UINT16 u16SubIndex0; /**< \brief SubIndex 0*/
+ UINT16 aEntries[2]; /**< \brief Entry buffer (one for two SyncManagers)*/
+} OBJ_STRUCT_PACKED_END
+TOBJ1C00;
+
+/*ET9300 Project Handler :(#if DC_SUPPORTED) lines 120 to 122 deleted*/
+
+#endif //_COEAPPL_H_
+
+#if defined(_COEAPPL_) && (_COEAPPL_ == 1)
+ #define PROTO
+#else
+ #define PROTO extern
+#endif
+
+/*-----------------------------------------------------------------------------------------
+------
+------ Global variables
+------
+-----------------------------------------------------------------------------------------*/
+
+PROTO UINT64 u64Timestamp
+#ifdef _COEAPPL_
+= { 0 }
+#endif
+;
+
+/*ET9300 Project Handler :(#if DC_SUPPORTED) lines 146 to 149 deleted*/
+/*-----------------------------------------------------------------------------------------
+------
+------ Global functions
+------
+-----------------------------------------------------------------------------------------*/
+PROTO void COE_UpdateSyncErrorStatus(void);
+
+PROTO void COE_ObjInit(void);
+PROTO void COE_Main(void);
+PROTO UINT16 COE_ObjDictionaryInit(void);
+PROTO UINT16 COE_AddObjectToDic(TOBJECT OBJMEM * pNewObjEntry);
+PROTO void COE_RemoveDicEntry(UINT16 index);
+PROTO void COE_ClearObjDictionary(void);
+PROTO OBJCONST TOBJECT OBJMEM * COE_GetObjectDictionary(void);
+/*ET9300 Project Handler :(#if DC_SUPPORTED) lines 166 to 168 deleted*/
+
+#undef PROTO
+/** @}*/
diff --git a/Projects/EFC_EcatDriver/src/ssc/ecat_def.h b/Projects/EFC_EcatDriver/src/ssc/ecat_def.h
new file mode 100644
index 0000000..d5008bb
--- /dev/null
+++ b/Projects/EFC_EcatDriver/src/ssc/ecat_def.h
@@ -0,0 +1,1083 @@
+/*
+* This source file is part of the EtherCAT Slave Stack Code licensed by Beckhoff Automation GmbH & Co KG, 33415 Verl, Germany.
+* The corresponding license agreement applies. This hint shall not be removed.
+* https://www.beckhoff.com/media/downloads/slave-stack-code/ethercat_ssc_license.pdf
+*/
+
+
+/*-----------------------------------------------------------------------------------------
+------
+------ ecat_def.h
+------ SSC version : 5.13
+-----------------------------------------------------------------------------------------*/
+
+#ifndef _ECATDEF_H_
+#define _ECATDEF_H_
+
+/*-----------------------------------------------------------------------------------------
+------
+------ Includes
+------
+-----------------------------------------------------------------------------------------*/
+#include
+#include
+
+#include "f2838x_cm_system.h"
+/*-----------------------------------------------------------------------------------------
+------
+------ Slave Sample Code Configuration Defines
+------
+-----------------------------------------------------------------------------------------*/
+#define SSC_VERSION_MAJOR 5
+#define SSC_VERSION_MINOR 13
+
+
+/**
+EL9800_HW: Shall be set if the Slave code is executed on the PIC mounted on the EL9800 EtherCAT Evaluation Board.
+(if the MCI interface provided by EL9800 board should be used MCI_HW shall be set and this define shall be reset).
+This settings should also be enabled if the ESC is connected via a serial interface and no specific hardware access files are avilable yet.
+NOTE: The PDI type needs also to be configured in the "ESC_CONFIG_DATA". */
+#ifndef EL9800_HW
+#define EL9800_HW 0 //This define was already evaluated by ET9300 Project Handler(V. 1.5.3.0)!
+#endif
+
+/**
+MCI_HW: Shall be set if the MCI of the ESC is connected.
+This settings should also be enabled if the ESC is connected via a parallel interface and no specific hardware access files are avilable yet.
+NOTE: The PDI type needs also to be configured in the "ESC_CONFIG_DATA". */
+#ifndef MCI_HW
+#define MCI_HW 0 //This define was already evaluated by ET9300 Project Handler(V. 1.5.3.0)!
+#endif
+
+/**
+FC1100_HW: Shall be set if the EtherCAT slave controller is located on an FC1100 PCI card.
+NOTE: The PDI type needs also to be configured in the "ESC_CONFIG_DATA". */
+#ifndef FC1100_HW
+#define FC1100_HW 0 //This define was already evaluated by ET9300 Project Handler(V. 1.5.3.0)!
+#endif
+
+/**
+TIESC_HW: Temporary define to support TI ICE/IDK development board (Shall be set if the Slave code shall executed on an AM335X ICE/IDK Evaluation Board
+from Texas Instruments) */
+#ifndef TIESC_HW
+#define TIESC_HW 0 //This define was already evaluated by ET9300 Project Handler(V. 1.5.3.0)!
+#endif
+
+/**
+CONTROLLER_16BIT: Shall be set if the host controller is a 16Bit architecture */
+#ifndef CONTROLLER_16BIT
+#define CONTROLLER_16BIT 0 //This define was already evaluated by ET9300 Project Handler(V. 1.5.3.0)!
+#endif
+
+/**
+CONTROLLER_32BIT: Shall be set if the host controller is a 32Bit architecture */
+#ifndef CONTROLLER_32BIT
+#define CONTROLLER_32BIT 0 //This define was already evaluated by ET9300 Project Handler(V. 1.5.3.0)!
+#endif
+
+/**
+MEMORY_UNIT_16BIT: Shall be set if the smallest controller memory unit is 16bit */
+#ifndef MEMORY_UNIT_16BIT
+#define MEMORY_UNIT_16BIT 0 //This define was already evaluated by ET9300 Project Handler(V. 1.5.3.0)!
+#endif
+
+/**
+_PIC18: Microchip PIC18F452 Specific Code
+This processor is mounted on the Beckhoff Slave Evaluation Board (Hardware version up to EL9800_2). */
+#ifndef _PIC18
+#define _PIC18 0 //This define was already evaluated by ET9300 Project Handler(V. 1.5.3.0)!
+#endif
+
+/**
+_PIC24: Microchip PIC24HJ128GP306 Specific Code
+This processor is mounted on the Beckhoff Slave Evaluation Board (Hardware version up to EL9800_4A). */
+#ifndef _PIC24
+#define _PIC24 0 //This define was already evaluated by ET9300 Project Handler(V. 1.5.3.0)!
+#endif
+
+/**
+ESC_16BIT_ACCESS: If the microcontroller only supports 16Bit access to the ESC. */
+#ifndef ESC_16BIT_ACCESS
+#define ESC_16BIT_ACCESS 0 //This define was already evaluated by ET9300 Project Handler(V. 1.5.3.0)!
+#endif
+
+/**
+ESC_32BIT_ACCESS: If the microcontroller only supports 32Bit access to the ESC. */
+#ifndef ESC_32BIT_ACCESS
+#define ESC_32BIT_ACCESS 0 //This define was already evaluated by ET9300 Project Handler(V. 1.5.3.0)!
+#endif
+
+/**
+MBX_16BIT_ACCESS: If the microcontroller only supports 16Bit access to local mailbox memory(access to ESC DPRAM is controlled by "ESC_16BIT_ACCESS"). If reset 8Bit access is used. */
+#ifndef MBX_16BIT_ACCESS
+#define MBX_16BIT_ACCESS 0 //This define was already evaluated by ET9300 Project Handler(V. 1.5.3.0)!
+#endif
+
+/**
+BIG_ENDIAN_16BIT: If the microcontroller always make 16 bit access to external memory, operates in BigEndian format
+and the switching of the high and low byte is done in hardware. */
+#ifndef BIG_ENDIAN_16BIT
+#define BIG_ENDIAN_16BIT 0 //This define was already evaluated by ET9300 Project Handler(V. 1.5.3.0)!
+#endif
+
+/**
+BIG_ENDIAN_FORMAT: If the microcontroller works with BigEndian format, then this switch shall be set. In that case all WORD-
+and DWORD-accesses will make a BYTE- or WORD-swapping, the macros SWAPWORD and SWAPDWORD in ecatslv.h might be adapted.
+If this switch is set, then BIG_ENDIAN_16BIT shall be reset. */
+#ifndef BIG_ENDIAN_FORMAT
+#define BIG_ENDIAN_FORMAT 0 //This define was already evaluated by ET9300 Project Handler(V. 1.5.3.0)!
+#endif
+
+/**
+EXT_DEBUGER_INTERFACE: If this switch is set, the external debugger interface on the EL9800_4A (_PIC24) will be activated.
+This define will be ignored if _PIC24 is not set. */
+#ifndef EXT_DEBUGER_INTERFACE
+#define EXT_DEBUGER_INTERFACE 0
+#endif
+
+/**
+UC_SET_ECAT_LED: If set the EtherCAT Run and Error LEDs are set by the uController. If set ESC_SUPPORT_ECAT_LED shall be reset. */
+#ifndef UC_SET_ECAT_LED
+#define UC_SET_ECAT_LED 1 //This define was already evaluated by ET9300 Project Handler(V. 1.5.3.0)!
+#endif
+
+/**
+ESC_SUPPORT_ECAT_LED: This switch can be enabled if the connected ESC support Error and Run LED indication. See the ESC datasheet if the LED indication is supported. If set UC_SET_ECAT_LED shall be reset. */
+#ifndef ESC_SUPPORT_ECAT_LED
+#define ESC_SUPPORT_ECAT_LED 0 //This define was already evaluated by ET9300 Project Handler(V. 1.5.3.0)!
+#endif
+
+/**
+ESC_EEPROM_EMULATION: If this switch is set EEPROM emulation is supported. Not all ESC types support EEPROM emulation. See ESC datasheet for more information. */
+#ifndef ESC_EEPROM_EMULATION
+#define ESC_EEPROM_EMULATION 0 //This define was already evaluated by ET9300 Project Handler(V. 1.5.3.0)!
+#endif
+
+/**
+ESC_EEPROM_SIZE: Specify the EEPROM size in Bytes of the connected EEPROM or the emulated EEPROM. */
+#ifndef ESC_EEPROM_SIZE
+#define ESC_EEPROM_SIZE 0x800
+#endif
+
+/**
+EEPROM_WRITE_SIZE: Only required if EEPROM emulation is active. This value defines the number of bytes which will be written per opertion. */
+#ifndef EEPROM_WRITE_SIZE
+#define EEPROM_WRITE_SIZE 0x2
+#endif
+
+/**
+AL_EVENT_ENABLED: If an interrupt routine shall be called when one of the Events in the AL Event Register (0x220) changes,
+this switch has to be defined to 1 (synchronous modes are supported).
+If the AL Event register shall only be polled, this switch has to be defined to 0 (only free run mode is supported). */
+#ifndef AL_EVENT_ENABLED
+#define AL_EVENT_ENABLED 1 //This define was already evaluated by ET9300 Project Handler(V. 1.5.3.0)!
+#endif
+
+/**
+DC_SUPPORTED: If distributed clocks should be supported by the slave, this switch shall be set.
+NOTE: The DC support needs also be set in the "ESC_CONFIG_DATA" settings. */
+#ifndef DC_SUPPORTED
+#define DC_SUPPORTED 0 //This define was already evaluated by ET9300 Project Handler(V. 1.5.3.0)!
+#endif
+
+/**
+ECAT_TIMER_INT: If this switch is set, then the watchdog time for the EtherCAT watchdog will be checked in a timer interrupt routine. */
+#ifndef ECAT_TIMER_INT
+#define ECAT_TIMER_INT 0 //This define was already evaluated by ET9300 Project Handler(V. 1.5.3.0)!
+#endif
+
+/**
+INTERRUPTS_SUPPORTED: If this switch is set the slave stack provides interrupt handling.
+NOTE: value will be evaluated automatically!! */
+#ifndef INTERRUPTS_SUPPORTED
+#define INTERRUPTS_SUPPORTED 1 //This define was already evaluated by ET9300 Project Handler(V. 1.5.3.0)!
+#endif
+
+/**
+TEST_APPLICATION: NOTE: THIS SETTING SHALL NOT BE USED TO CREATE A USER SPECIFIC APPLICATION!
+Select this setting to test the slave stack or a master implementation. For further information about this application see the SSC Application Node. */
+#ifndef TEST_APPLICATION
+#define TEST_APPLICATION 0 //This define was already evaluated by ET9300 Project Handler(V. 1.5.3.0)!
+#endif
+
+/**
+TEST_APPLICATION_REDUCED_MEMORY: This define reduces the memory footprint of the test application (should only be used if the default test application generates no memory errors when accessing the OD or FoE files) */
+#ifndef TEST_APPLICATION_REDUCED_MEMORY
+#define TEST_APPLICATION_REDUCED_MEMORY 0 //This define was already evaluated by ET9300 Project Handler(V. 1.5.3.0)!
+#endif
+
+/**
+EL9800_APPLICATION: Should be set if the Slave Sample Code runs on an EL9800_x Evaluation Board. */
+#ifndef EL9800_APPLICATION
+#define EL9800_APPLICATION 0 //This define was already evaluated by ET9300 Project Handler(V. 1.5.3.0)!
+#endif
+
+/**
+CiA402_SAMPLE_APPLICATION: If this switch is set, then the sample implementation of CiA402 device profile will be activated. */
+#ifndef CiA402_SAMPLE_APPLICATION
+#define CiA402_SAMPLE_APPLICATION 0 //This define was already evaluated by ET9300 Project Handler(V. 1.5.3.0)!
+#endif
+
+/**
+SAMPLE_APPLICATION: Select this define if the hardware independent sample application shall be activated. */
+#ifndef SAMPLE_APPLICATION
+#define SAMPLE_APPLICATION 0 //This define was already evaluated by ET9300 Project Handler(V. 1.5.3.0)!
+#endif
+
+/**
+SAMPLE_APPLICATION_INTERFACE: Select this define to activate the Sample Application Interface. This provides an simple interface to create a static library and used in an external application.
+NOTE: The file "EtherCATSampleLibrary.h" includes the library interface (maybe need to be adapted). */
+#ifndef SAMPLE_APPLICATION_INTERFACE
+#define SAMPLE_APPLICATION_INTERFACE 0 //This define was already evaluated by ET9300 Project Handler(V. 1.5.3.0)!
+#endif
+
+/**
+BOOTLOADER_SAMPLE: Select this define to enable a small footprint application which only supports the BOOT state and FoE mailbox protocol. */
+#ifndef BOOTLOADER_SAMPLE
+#define BOOTLOADER_SAMPLE 0 //This define was already evaluated by ET9300 Project Handler(V. 1.5.3.0)!
+#endif
+
+/**
+USE_DEFAULT_MAIN: Set to 1 if the main function of a default application shall be used.
+Otherwise the Init functions and the mainloop handler shall be called for a user specific function (see ET9300 Application Note for further details https://www.beckhoff.com/de-de/support/downloadfinder/technische-dokumentationen/?q=ET1100). */
+#ifndef USE_DEFAULT_MAIN
+#define USE_DEFAULT_MAIN 0 //This define was already evaluated by ET9300 Project Handler(V. 1.5.3.0)!
+#endif
+
+/**
+MAILBOX_QUEUE: If this switch is set, the mailbox services will be stored in a queue.
+With this switch reset only one mailbox service can be processed in parallel. */
+#ifndef MAILBOX_QUEUE
+#define MAILBOX_QUEUE 1 //This define was already evaluated by ET9300 Project Handler(V. 1.5.3.0)!
+#endif
+
+/**
+AOE_SUPPORTED: If the AoE services are supported, then this switch shall be set. */
+#ifndef AOE_SUPPORTED
+#define AOE_SUPPORTED 0 //This define was already evaluated by ET9300 Project Handler(V. 1.5.3.0)!
+#endif
+
+/**
+COE_SUPPORTED: If the CoE services are supported, then his switch shall be set. */
+#ifndef COE_SUPPORTED
+#define COE_SUPPORTED 1 //This define was already evaluated by ET9300 Project Handler(V. 1.5.3.0)!
+#endif
+
+/**
+COMPLETE_ACCESS_SUPPORTED: If the complete SDO access (accessing all entries of an object with one SDO service, then this
+switch shall be set. Furthermore,COE_SUPPORTED shall be set. */
+#ifndef COMPLETE_ACCESS_SUPPORTED
+#define COMPLETE_ACCESS_SUPPORTED 1 //This define was already evaluated by ET9300 Project Handler(V. 1.5.3.0)!
+#endif
+
+/**
+SEGMENTED_SDO_SUPPORTED: If the segmented SDO services should be supported, then this switch shall be set.
+Furthermore, COE_SUPPORTED shall be set. */
+#ifndef SEGMENTED_SDO_SUPPORTED
+#define SEGMENTED_SDO_SUPPORTED 1 //This define was already evaluated by ET9300 Project Handler(V. 1.5.3.0)!
+#endif
+
+/**
+SDO_RES_INTERFACE: If a SDO response cannot be generated immediately (e.g. when access over
+a serial interface is needed), this switch should be set. In that case ABORTIDX_WORKING shall be
+returned from OBJ_Read or OBJ_Write and the response shall be sent by calling SDOS_SdoRes, when
+the response is available. */
+#ifndef SDO_RES_INTERFACE
+#define SDO_RES_INTERFACE 1 //This define was already evaluated by ET9300 Project Handler(V. 1.5.3.0)!
+#endif
+
+/**
+USE_SINGLE_PDO_MAPPING_ENTRY_DESCR: If this setting is set a PDO mapping entry description just need to be defined for the first entry. For all furher entries the same description is used. */
+#ifndef USE_SINGLE_PDO_MAPPING_ENTRY_DESCR
+#define USE_SINGLE_PDO_MAPPING_ENTRY_DESCR 1 //This define was already evaluated by ET9300 Project Handler(V. 1.5.3.0)!
+#endif
+
+/**
+BACKUP_PARAMETER_SUPPORTED: If this switch is set, then the functions in the application example to load and
+store backup parameter will be compiled. Furthermore, COE_SUPPORTED shall be set. */
+#ifndef BACKUP_PARAMETER_SUPPORTED
+#define BACKUP_PARAMETER_SUPPORTED 0 //This define was already evaluated by ET9300 Project Handler(V. 1.5.3.0)!
+#endif
+
+/**
+STORE_BACKUP_PARAMETER_IMMEDIATELY: Objet values will be stored when they are written.This switch is only evaluated if "BACKUP_PARAMETER_SUPPORTED" is set. */
+#ifndef STORE_BACKUP_PARAMETER_IMMEDIATELY
+#define STORE_BACKUP_PARAMETER_IMMEDIATELY 0 //This define was already evaluated by ET9300 Project Handler(V. 1.5.3.0)!
+#endif
+
+/**
+DIAGNOSIS_SUPPORTED: If this define is set the slave stack supports diagnosis messages (Object 0x10F3).
+To support diagnosis messages COE_SUPPORTED shall be enabled and the platform shall support dynamic memory allocation.
+NOTE: this feature is implemented according to ETG.1020 */
+#ifndef DIAGNOSIS_SUPPORTED
+#define DIAGNOSIS_SUPPORTED 0 //This define was already evaluated by ET9300 Project Handler(V. 1.5.3.0)!
+#endif
+
+/**
+EMERGENCY_SUPPORTED: If this define is set the slave stack supports emergency messages. COE_SUPPORTED or SOE_SUPPORTED shall be enabled */
+#ifndef EMERGENCY_SUPPORTED
+#define EMERGENCY_SUPPORTED 0 //This define was already evaluated by ET9300 Project Handler(V. 1.5.3.0)!
+#endif
+
+/**
+VOE_SUPPORTED: If the VoE services should be supported, then this switch shall be set. This means only the calling of the
+VoE functions in mailbox.c are implemented, but the VoE service functions have to be added. Furthermore, the example code cannot be linked
+correctly, because these functions are missing. */
+#ifndef VOE_SUPPORTED
+#define VOE_SUPPORTED 0 //This define was already evaluated by ET9300 Project Handler(V. 1.5.3.0)!
+#endif
+
+/**
+SOE_SUPPORTED: If the SoE services should be supported, then this switch shall be set. This means only the calling of the
+SoE functions in mailbox.c are implemented, but the SoE service functions have to be added. Furthermore, the example code cannot be linked
+correctly, because these functions are missing. */
+#ifndef SOE_SUPPORTED
+#define SOE_SUPPORTED 0 //This define was already evaluated by ET9300 Project Handler(V. 1.5.3.0)!
+#endif
+
+/**
+EOE_SUPPORTED: If the EoE services should be supported, then this switch shall be set. */
+#ifndef EOE_SUPPORTED
+#define EOE_SUPPORTED 0 //This define was already evaluated by ET9300 Project Handler(V. 1.5.3.0)!
+#endif
+
+/**
+STATIC_ETHERNET_BUFFER: If this switch is set a static buffer is used to store ethernet frames, otherwise the buffer is allocated on demand */
+#ifndef STATIC_ETHERNET_BUFFER
+#define STATIC_ETHERNET_BUFFER 1 //This define was already evaluated by ET9300 Project Handler(V. 1.5.3.0)!
+#endif
+
+/**
+FOE_SUPPORTED: If the FoE services should be supported, then this switch shall be set. */
+#ifndef FOE_SUPPORTED
+#define FOE_SUPPORTED 0 //This define was already evaluated by ET9300 Project Handler(V. 1.5.3.0)!
+#endif
+
+/**
+MAILBOX_SUPPORTED: This switch is set automatically if at least one mailbox protocol is enabled. */
+#ifndef MAILBOX_SUPPORTED
+#define MAILBOX_SUPPORTED 1 //This define was already evaluated by ET9300 Project Handler(V. 1.5.3.0)!
+#endif
+
+/**
+BOOTSTRAPMODE_SUPPORTED: If the firmware update over FoE services should be supported, then this switch shall be set.
+If this switch is set, then also "FOE_SUPPORTED" shall be set. */
+#ifndef BOOTSTRAPMODE_SUPPORTED
+#define BOOTSTRAPMODE_SUPPORTED 0 //This define was already evaluated by ET9300 Project Handler(V. 1.5.3.0)!
+#endif
+
+/**
+OP_PD_REQUIRED: If this switch is reset the state transition SAFEOP_2_OP will also successful if no process data was received. The watchdog will only be active when first process data was received (bEcatFirstOutputsReceived) */
+#ifndef OP_PD_REQUIRED
+#define OP_PD_REQUIRED 1 //This define was already evaluated by ET9300 Project Handler(V. 1.5.3.0)!
+#endif
+
+/**
+PREOPTIMEOUT: Specify timeout value in ms for the state transition from Init to PreOP/Boot.(ESI Value : "PreopTimeout").
+NOTE: Within the stack this value - 50ms will be used to react before the master run into the timeout. */
+#ifndef PREOPTIMEOUT
+#define PREOPTIMEOUT 0x7D0
+#endif
+
+/**
+SAFEOP2OPTIMEOUT: Specifiy the timeout in ms from SafeOP to OP. (ESI Value : "SafeopOpTimeout")
+NOTE: Within the stack this value - 50ms will be used to react before the master run into the timeout. */
+#ifndef SAFEOP2OPTIMEOUT
+#define SAFEOP2OPTIMEOUT 0x2328
+#endif
+
+/**
+CHECK_SM_PARAM_ALIGNMENT: If true the SyncManager length and start address will be checked according the ESC Access.
+e.g. ESC_32BIT_ACCESS is set the length and address shall be to an even 4Byte address. */
+#ifndef CHECK_SM_PARAM_ALIGNMENT
+#define CHECK_SM_PARAM_ALIGNMENT 0 //This define was already evaluated by ET9300 Project Handler(V. 1.5.3.0)!
+#endif
+
+/**
+EXPLICIT_DEVICE_ID: If this switch is set Explicit device ID requests are handled. For further information about Explicit Device ID see ETG.1020 specification: www.ethercat.org/MemberArea/download_protocolenhancements.asp */
+#ifndef EXPLICIT_DEVICE_ID
+#define EXPLICIT_DEVICE_ID 0 //This define was already evaluated by ET9300 Project Handler(V. 1.5.3.0)!
+#endif
+
+/**
+ESC_SM_WD_SUPPORTED: This switch should be set if the SyncManger watchdog provided by the ESC should be used. If reset the process data watchdog is triggered by a local timer */
+#ifndef ESC_SM_WD_SUPPORTED
+#define ESC_SM_WD_SUPPORTED 1 //This define was already evaluated by ET9300 Project Handler(V. 1.5.3.0)!
+#endif
+
+/**
+STATIC_OBJECT_DIC: If this switch is set, the object dictionary is "build" static (by default only PIC18 objects are added static) */
+#ifndef STATIC_OBJECT_DIC
+#define STATIC_OBJECT_DIC 0 //This define was already evaluated by ET9300 Project Handler(V. 1.5.3.0)!
+#endif
+
+/**
+ESC_EEPROM_ACCESS_SUPPORT: If this switch is set the slave stack provides functions to access the EEPROM. */
+#ifndef ESC_EEPROM_ACCESS_SUPPORT
+#define ESC_EEPROM_ACCESS_SUPPORT 0 //This define was already evaluated by ET9300 Project Handler(V. 1.5.3.0)!
+#endif
+
+
+/*-----------------------------------------------------------------------------------------
+------
+------ Compiler Defines
+------
+-----------------------------------------------------------------------------------------*/
+
+/**
+FALSE: Will be used for variables from type BOOL */
+#ifndef FALSE
+#define FALSE 0
+#endif
+
+/**
+TRUE: Will be used for variables from type BOOL */
+#ifndef TRUE
+#define TRUE 1
+#endif
+
+/**
+BOOL: Should be adapted to the boolean type of the microcontroller */
+#ifndef BOOL
+#define BOOL unsigned char
+#endif
+
+/**
+UINT8: Should be adapted to the unsigned8 type of the microcontroller */
+#ifndef UINT8
+#define UINT8 unsigned char
+#endif
+
+/**
+UINT16: Should be adapted to the unsigned16 type of the microcontroller */
+#ifndef UINT16
+#define UINT16 unsigned short
+#endif
+
+/**
+UINT32: Should be adapted to the unsigned32 type of the microcontroller */
+#ifndef UINT32
+#define UINT32 unsigned int
+#endif
+
+/**
+UINT64: Should be adapted to the unsigned64 type of the microcontroller */
+#ifndef UINT64
+#define UINT64 unsigned long long
+#endif
+
+/**
+USHORT: Should be adapted to the unsigned16 type of the microcontroller */
+#ifndef USHORT
+#define USHORT unsigned short
+#endif
+
+/**
+INT8: Should be adapted to the integer8 type of the microcontroller */
+#ifndef INT8
+#define INT8 char
+#endif
+
+/**
+INT16: Should be adapted to the integer16 type of the microcontroller */
+#ifndef INT16
+#define INT16 short
+#endif
+
+/**
+INT32: Should be adapted to the integer32 type of the microcontroller */
+#ifndef INT32
+#define INT32 int
+#endif
+
+/**
+INT64: Should be adapted to the integer64 type of the microcontroller */
+#ifndef INT64
+#define INT64 long long
+#endif
+
+/**
+CHAR: Should be adapted to the character type of the microcontroller */
+#ifndef CHAR
+#define CHAR char
+#endif
+
+/**
+UCHAR: Should be adapted to the unsigned character type of the microcontroller */
+#ifndef UCHAR
+#define UCHAR unsigned char
+#endif
+
+/**
+REAL32: Should be adapted to the 32bit real type of the microcontroller */
+#ifndef REAL32
+#define REAL32 float
+#endif
+
+/**
+REAL64: Should be adapted to the 64bit real type of the microcontroller */
+#ifndef REAL64
+#define REAL64 long double
+#endif
+
+/**
+SIZEOF(x): Used to calculate the size in Bytes */
+#ifndef SIZEOF
+#define SIZEOF(x) (sizeof(x))
+#endif
+
+/**
+HUGE: Should be adapted to the huge type of the microcontroller, if the microcontroller
+does not support a huge type, HUGE shall be defined to nothing */
+#ifndef HUGE
+#define HUGE
+#endif
+
+/**
+HMEMSET: Should be defined to the memset function for huge memory, if the microcontroller
+does not support a huge type, HMEMSET shall be defined to a 'normal' memset function */
+#ifndef HMEMSET
+#define HMEMSET memset
+#endif
+
+/**
+HMEMCPY: Should be defined to the memcpy function for huge memory, if the microcontroller
+does not support a huge type, HMEMCPY shall be defined to a 'normal' memcpy function */
+#ifndef HMEMCPY
+#define HMEMCPY memcpy
+#endif
+
+/**
+HMEMCMP: Should be defined to the memcmp function for huge memory, if the microcontroller
+does not support a huge type, HMEMCMP shall be defined to a 'normal' memcmp function */
+#ifndef HMEMCMP
+#define HMEMCMP memcmp
+#endif
+
+/**
+ESCMEM: Should be defined to select the memory type of the ESC memory (e.g. near, far or huge), if the microcontroller
+does not support different memory types, ESCMEM shall be defined to nothing */
+#ifndef ESCMEM
+#define ESCMEM
+#endif
+
+/**
+ESCMEMCPY: Should be defined to the memcpy function for ESCMEM memory, if the microcontroller
+does not support different memory types, ESCMEMCPY shall be defined to a 'normal' memcpy function */
+#ifndef ESCMEMCPY
+#define ESCMEMCPY memcpy
+#endif
+
+/**
+ESCMEMSET: Should be defined to the memset function for ESCMEM memory, if the microcontroller
+does not support different memory types, ESCMEMSET shall be defined to a 'normal' memset function */
+#ifndef ESCMEMSET
+#define ESCMEMSET memset
+#endif
+
+/**
+ESCMBXMEMCPY: Should be defined to the memcpy function for copying ESCMEM memory to or from MBXMEM memory, if the microcontroller
+does not support different memory types, ESCMBXMEMCPY shall be defined to a 'normal' memcpy function */
+#ifndef ESCMBXMEMCPY
+#define ESCMBXMEMCPY memcpy
+#endif
+
+/**
+MBXMEM: Should be defined to select the memory type of the memory used for mailbox communication (e.g. near, far or huge),
+if the microcontroller does not support different memory types, MBXMEM shall be defined to nothing */
+#ifndef MBXMEM
+#define MBXMEM
+#endif
+
+/**
+MBXMEMCPY: Should be defined to the memcpy function for MBXMEM memory, if the microcontroller
+does not support different memory types, MBXMEMCPY shall be defined to a 'normal' memcpy function */
+#ifndef MBXMEMCPY
+#define MBXMEMCPY memcpy
+#endif
+
+/**
+MBXMEMCMP: Should be defined to the memcmp function for MBXMEM memory, if the microcontroller
+does not support different memory types, MBXMEMCMP shall be defined to a 'normal' memcmp function */
+#ifndef MBXMEMCMP
+#define MBXMEMCMP memcmp
+#endif
+
+/**
+MBXMEMSET: Should be defined to the memcpy function for MBXMEM memory, if the microcontroller
+does not support different memory types, MBXMEMSET shall be defined to a 'normal' memset function */
+#ifndef MBXMEMSET
+#define MBXMEMSET memset
+#endif
+
+/**
+MBXSTRLEN: Should be defined to the strlen function for MBXMEM memory, if the microcontroller
+does not support different memory types, MBXSTRLEN shall be defined to a 'normal' strlen function */
+#ifndef MBXSTRLEN
+#define MBXSTRLEN strlen
+#endif
+
+/**
+MBXSTRCPY: Should be defined to the strcpy function for MBXMEM memory, if the microcontroller
+does not support different memory types, MBXSTRCPY shall be defined to a 'normal' strcpy function */
+#ifndef MBXSTRCPY
+#define MBXSTRCPY F2838XCM_strcpy
+#endif
+
+/**
+OBJCONST: Should be used to define the object dictionary in ROM (f.e. define OBJCONST const) or
+in RAM (e.g. define OBJCONST) */
+#ifndef OBJCONST
+#define OBJCONST const
+#endif
+
+/**
+VARCONST: Should be used to define the constant variables in ROM (f.e. define VARCONST const) or
+in RAM (e.g. define VARCONST) */
+#ifndef VARCONST
+#define VARCONST
+#endif
+
+/**
+VARVOLATILE: Should be used to prevent dummy variables to be deleted due to compiler optimization. */
+#ifndef VARVOLATILE
+#define VARVOLATILE volatile
+#endif
+
+/**
+OBJMEM: Should be defined to select the memory type of the memory used for the object dictionary (e.g. near, far or huge),
+if the microcontroller does not support different memory types, OBJMEM shall be defined to nothing */
+#ifndef OBJMEM
+#define OBJMEM
+#endif
+
+/**
+OBJTOMBXMEMCPY: Should be defined to the memcpy function for copying OBJMEM memory to MBXMEM memory, if the microcontroller
+does not support different memory types, OBJTOMBXMEMCPY shall be defined to a 'normal' memcpy function */
+#ifndef OBJTOMBXMEMCPY
+#define OBJTOMBXMEMCPY memcpy
+#endif
+
+/**
+OBJTOMBXSTRCPY: Should be defined to the strcpy function for copying OBJMEM memory to MBXMEM memory, if the microcontroller
+does not support different memory types, OBJTOMBXSTRCPY shall be defined to a 'normal' memcpy function */
+#ifndef OBJTOMBXSTRCPY
+#define OBJTOMBXSTRCPY F2838XCM_strcpy
+#endif
+
+/**
+MBXTOOBJSTRCPY: Should be defined to the strcpy function for copying MBXMEM memory to OBJMEM memory, if the microcontroller
+does not support different memory types, MBXTOOBJSTRCPY shall be defined to a 'normal' memcpy function */
+#ifndef MBXTOOBJSTRCPY
+#define MBXTOOBJSTRCPY memcpy
+#endif
+
+/**
+OBJMEMCPY: Should be defined to the memcpy function for OBJMEM memory, if the microcontroller
+does not support different memory types, OBJMEMCPY shall be defined to a 'normal' memcpy function */
+#ifndef OBJMEMCPY
+#define OBJMEMCPY memcpy
+#endif
+
+/**
+OBJSTRLEN: Should be defined to the strlen function for OBJMEM memory, if the microcontroller
+does not support different memory types, OBJSTRLEN shall be defined to a 'normal' strlen function */
+#ifndef OBJSTRLEN
+#define OBJSTRLEN strlen
+#endif
+
+/**
+OBJSTRCPY: Should be defined to the strcpy function for OBJMEM memory, if the microcontroller
+does not support different memory types, OBJSTRCPY shall be defined to a 'normal' strcpy function */
+#ifndef OBJSTRCPY
+#define OBJSTRCPY F2838XCM_strcpy
+#endif
+
+/**
+MAKE_HUGE_PTR: Should be defined to the initialize a pointer variable with an absolute address */
+#ifndef MAKE_HUGE_PTR
+#define MAKE_HUGE_PTR
+#endif
+
+/**
+MAKE_PTR_TO_ESC: Should be defined to the initialize the pointer to the ESC */
+#ifndef MAKE_PTR_TO_ESC
+#define MAKE_PTR_TO_ESC
+#endif
+
+/**
+EMCYMEMCPY: Should be defined to the memcpy function for EMCYMEM memory, if the microcontroller
+does not support different memory types, EMCYMEMCPY shall be defined to a 'normal' memcpy function */
+#ifndef EMCYMEMCPY
+#define EMCYMEMCPY memcpy
+#endif
+
+/**
+EMCYMEMSET: Should be defined to the memset function for EMCYMEM memory, if the microcontroller
+does not support different memory types, EMCYMEMSET shall be defined to a 'normal' memcset function */
+#ifndef EMCYMEMSET
+#define EMCYMEMSET memset
+#endif
+
+/**
+EMCYMEM: Should be defined to select the memory type of the memory used for the emergencies (e.g. near, far or huge),
+if the microcontroller does not support different memory types, EMCYMEM shall be defined to nothing */
+#ifndef EMCYMEM
+#define EMCYMEM
+#endif
+
+/**
+MEMCPY: Should be defined to copy data within local memory. */
+#ifndef MEMCPY
+#define MEMCPY memcpy
+#endif
+
+/**
+ALLOCMEM(size): Should be defined to the alloc function to get dynamic memory */
+#ifndef ALLOCMEM
+#define ALLOCMEM(size) malloc((size))
+#endif
+
+/**
+FREEMEM(pointer): Should be defined to the free function to put back dynamic memory */
+#ifndef FREEMEM
+#define FREEMEM(pointer) free((pointer))
+#endif
+
+/**
+VARMEMSET: Should be defined to the memset function for VARMEM memory, if the microcontroller
+does not support different memory types, EMCYMEMSET shall be defined to a 'normal' memcset function */
+#ifndef VARMEMSET
+#define VARMEMSET memset
+#endif
+
+/**
+VARMEM: Should be defined to select the memory type of the memory used for dynamic memory (e.g. near, far or huge),
+if the microcontroller does not support different memory types, VARMEM shall be defined to nothing */
+#ifndef VARMEM
+#define VARMEM
+#endif
+
+/**
+MEM_ADDR: Type to access local memory addresses */
+#ifndef MEM_ADDR
+#define MEM_ADDR UINT8
+#endif
+
+/**
+GET_MEM_SIZE(ByteSize): Round up the byte size to next matching memory boundary depending on "MEM_ADDR" */
+#ifndef GET_MEM_SIZE
+#define GET_MEM_SIZE(ByteSize) (ByteSize)
+#endif
+
+/**
+APPL_AllocMailboxBuffer(size): Should be defined to a function to get a buffer for a mailbox service,
+this is only used if the switch MAILBOX_QUEUE is set */
+#ifndef APPL_AllocMailboxBuffer
+#define APPL_AllocMailboxBuffer(size) malloc((size))
+#endif
+
+/**
+APPL_FreeMailboxBuffer(pointer): Should be defined to a function to put back a buffer for a mailbox service,
+this is only used if the switch MAILBOX_QUEUE is set */
+#ifndef APPL_FreeMailboxBuffer
+#define APPL_FreeMailboxBuffer(pointer) free((pointer))
+#endif
+
+/**
+STRUCT_PACKED_START: Is defined before the typedef struct construct to pack the generic structures if necessary */
+#ifndef STRUCT_PACKED_START
+#define STRUCT_PACKED_START
+#endif
+
+/**
+STRUCT_PACKED_END: Is defined after the typedef struct {} construct to pack the generic structures if necessary */
+#ifndef STRUCT_PACKED_END
+#define STRUCT_PACKED_END
+#endif
+
+/**
+MBX_STRUCT_PACKED_START: Is defined before the typedef struct construct to pack the MAILBOX structures if necessary */
+#ifndef MBX_STRUCT_PACKED_START
+#define MBX_STRUCT_PACKED_START
+#endif
+
+/**
+MBX_STRUCT_PACKED_END: Is defined after the typedef struct {} construct to pack the MAILBOX structures if necessary */
+#ifndef MBX_STRUCT_PACKED_END
+#define MBX_STRUCT_PACKED_END
+#endif
+
+/**
+OBJ_STRUCT_PACKED_START: Is defined before the typedef struct construct to pack the OBJECT structures if necessary */
+#ifndef OBJ_STRUCT_PACKED_START
+#define OBJ_STRUCT_PACKED_START
+#endif
+
+/**
+OBJ_STRUCT_PACKED_END: Is defined after the typedef struct {} construct to pack the OBJECT structures if necessary */
+#ifndef OBJ_STRUCT_PACKED_END
+#define OBJ_STRUCT_PACKED_END
+#endif
+
+/**
+OBJ_DWORD_ALIGN: Shall be set if the object structures are not Byte aligned and 32bit entries are implicitly padded to even 32bit memory addresses. */
+#ifndef OBJ_DWORD_ALIGN
+#define OBJ_DWORD_ALIGN 1
+#endif
+
+/**
+OBJ_WORD_ALIGN: Shall be set if the object structures are not Byte aligned and 16bit entries are implicitly padded to even 16bit memory addresses. */
+#ifndef OBJ_WORD_ALIGN
+#define OBJ_WORD_ALIGN 1
+#endif
+
+/**
+ENTER_MBX_CRITICAL: Macro which is called when a critical mailbox section is entered */
+#ifndef ENTER_MBX_CRITICAL
+#define ENTER_MBX_CRITICAL
+#endif
+
+/**
+LEAVE_MBX_CRITICAL: Macro which is called when a critical mailbox section is left */
+#ifndef LEAVE_MBX_CRITICAL
+#define LEAVE_MBX_CRITICAL
+#endif
+
+/**
+ENTER_AOE_CRITICAL: Macro which is called when a critical AoE section is entered */
+#ifndef ENTER_AOE_CRITICAL
+#define ENTER_AOE_CRITICAL
+#endif
+
+/**
+LEAVE_AOE_CRITICAL: Macro which is called when a critical AoE section is left */
+#ifndef LEAVE_AOE_CRITICAL
+#define LEAVE_AOE_CRITICAL
+#endif
+
+/**
+ENTER_EMCY_CRITICAL: Macro which is called when a critical emergency section is entered */
+#ifndef ENTER_EMCY_CRITICAL
+#define ENTER_EMCY_CRITICAL
+#endif
+
+/**
+LEAVE_EMCY_CRITICAL: Macro which is called when a critical emergency section is left */
+#ifndef LEAVE_EMCY_CRITICAL
+#define LEAVE_EMCY_CRITICAL
+#endif
+
+
+/*-----------------------------------------------------------------------------------------
+------
+------ Application Specific Defines
+------
+-----------------------------------------------------------------------------------------*/
+
+/**
+MAX_DIAG_MSG: Number of diagnosis message ringbuffer */
+#ifndef MAX_DIAG_MSG
+#define MAX_DIAG_MSG 0x14
+#endif
+
+/**
+MAX_EMERGENCIES: Number of emergencies supported in parallel */
+#ifndef MAX_EMERGENCIES
+#define MAX_EMERGENCIES 0x1
+#endif
+
+/**
+VENDOR_ID: Object 0x1018 SI1 (Vendor ID)
+An unique EtherCAT Vendor ID is required. Please find all valid Vendor IDs listed at www.ethercat.org/en/vendor_id_list.html.
+If your company is not listed, please assign an ID for free at www.ethercat.org/memberarea/vendor_id.asp */
+#ifndef VENDOR_ID
+#define VENDOR_ID 0xD5D
+#endif
+
+/**
+PRODUCT_CODE: Object 0x1018 SI2 (EtherCAT product code) */
+#ifndef PRODUCT_CODE
+#define PRODUCT_CODE 0x10003101
+#endif
+
+/**
+REVISION_NUMBER: Object 0x1018 SI3 (EtherCAT product revision number) */
+#ifndef REVISION_NUMBER
+#define REVISION_NUMBER 0x00000001
+#endif
+
+/**
+SERIAL_NUMBER: Object 0x1018 SI4 (EtherCAT product serial number) */
+#ifndef SERIAL_NUMBER
+#define SERIAL_NUMBER 0x00001419
+#endif
+
+/**
+DEVICE_PROFILE_TYPE: Slave device type (Object 0x1000) */
+#ifndef DEVICE_PROFILE_TYPE
+#define DEVICE_PROFILE_TYPE 0x00001389
+#endif
+
+/**
+DEVICE_NAME: Name of the slave device (Object 0x1008) */
+#ifndef DEVICE_NAME
+#define DEVICE_NAME "F2838x CM EtherCAT Slave SM1"
+#endif
+
+/**
+DEVICE_NAME_LEN: Length of 'DEVICE_NAME' without '\0' */
+#ifndef DEVICE_NAME_LEN
+#define DEVICE_NAME_LEN 0x1C
+#endif
+
+/**
+DEVICE_HW_VERSION: Hardware version of the slave device (Object 0x1009) */
+#ifndef DEVICE_HW_VERSION
+#define DEVICE_HW_VERSION "F2838X_CCMCU0063_E1"
+#endif
+
+/**
+DEVICE_HW_VERSION_LEN: Length of 'DEVICE_HW_VERSION' without '\0' */
+#ifndef DEVICE_HW_VERSION_LEN
+#define DEVICE_HW_VERSION_LEN 0x13
+#endif
+
+/**
+DEVICE_SW_VERSION: Software version of the slave device (Object 0x100A) */
+#ifndef DEVICE_SW_VERSION
+#define DEVICE_SW_VERSION "SSC_5_12_C28_1_0_02"
+#endif
+
+/**
+DEVICE_SW_VERSION_LEN: Length of 'DEVICE_SW_VERSION' without '\0' */
+#ifndef DEVICE_SW_VERSION_LEN
+#define DEVICE_SW_VERSION_LEN 0x13
+#endif
+
+/**
+MIN_PD_WRITE_ADDRESS: Minimum address for the process output data (Sync Manager 2)
+inside the application memory of the EtherCAT Slave Controller which could be set by the master. The setting have to be within the ranges of the user memory of the ESC (this is not checked by the tool). */
+#ifndef MIN_PD_WRITE_ADDRESS
+#define MIN_PD_WRITE_ADDRESS 0x1000
+#endif
+
+/**
+MAX_PD_WRITE_ADDRESS: Maximum address for the process output data (Sync Manager 2)
+inside the application memory of the EtherCAT Slave Controller which could be set by the master. The setting have to be within the ranges of the user memory of the ESC (this is not checked by the tool). */
+#ifndef MAX_PD_WRITE_ADDRESS
+#define MAX_PD_WRITE_ADDRESS 0x4FFF
+#endif
+
+/**
+MIN_PD_READ_ADDRESS: Minimum address for the process input data (Sync Manager 3)
+inside the application memory of the EtherCAT Slave Controller which could be set by the master. The setting have to be within the ranges of the user memory of the ESC (this is not checked by the tool). */
+#ifndef MIN_PD_READ_ADDRESS
+#define MIN_PD_READ_ADDRESS 0x1000
+#endif
+
+/**
+MAX_PD_READ_ADDRESS: Maximum address for the process input data (Sync Manager 3)
+inside the application memory of the EtherCAT Slave Controller which could be set by the master. The setting have to be within the ranges of the user memory of the ESC (this is not checked by the tool). */
+#ifndef MAX_PD_READ_ADDRESS
+#define MAX_PD_READ_ADDRESS 0x4FFF
+#endif
+
+/**
+MIN_MBX_SIZE: Minimum mailbox size (Sync Manager 0 and 1) which could be set by the master. The SSC don't support fragmented SDO info object/entry service => at least entry info including 12byte name shall fit in the mailbox buffer */
+#ifndef MIN_MBX_SIZE
+#define MIN_MBX_SIZE 0x0022
+#endif
+
+/**
+MAX_MBX_SIZE: Maximum mailbox size (Sync Manager 0 and 1) which could be set by the master. */
+#ifndef MAX_MBX_SIZE
+#define MAX_MBX_SIZE 0x0100
+#endif
+
+/**
+MIN_MBX_WRITE_ADDRESS: Minimum address for the write (receive) mailbox (Sync Manager 0). The setting have to be within the ranges of the user memory of the ESC (this is not checked by the tool). */
+#ifndef MIN_MBX_WRITE_ADDRESS
+#define MIN_MBX_WRITE_ADDRESS 0x1000
+#endif
+
+/**
+MAX_MBX_WRITE_ADDRESS: Maximum address for the write (receive) mailbox (Sync Manager 0). The setting have to be within the ranges of the user memory of the ESC (this is not checked by the tool). */
+#ifndef MAX_MBX_WRITE_ADDRESS
+#define MAX_MBX_WRITE_ADDRESS 0x4FFF
+#endif
+
+/**
+MAX_PD_INPUT_SIZE: Maximum size of the process input data (Sync Manager 3) for cyclic exchange. */
+#ifndef MAX_PD_INPUT_SIZE
+#define MAX_PD_INPUT_SIZE 0x0044 //This define was already evaluated by ET9300 Project Handler(V. 1.5.3.0)!
+#endif
+
+/**
+MIN_MBX_READ_ADDRESS: Minimum address for the read (send) mailbox (Sync Manager 1). */
+#ifndef MIN_MBX_READ_ADDRESS
+#define MIN_MBX_READ_ADDRESS 0x1000
+#endif
+
+/**
+MAX_MBX_READ_ADDRESS: Maximum address for the read (send) mailbox (Sync Manager 1). */
+#ifndef MAX_MBX_READ_ADDRESS
+#define MAX_MBX_READ_ADDRESS 0x4FFF
+#endif
+
+/**
+MAX_PD_OUTPUT_SIZE: Maximum size of the process output data (Sync Manager 2) for cyclic exchange. */
+#ifndef MAX_PD_OUTPUT_SIZE
+#define MAX_PD_OUTPUT_SIZE 0x044 //This define was already evaluated by ET9300 Project Handler(V. 1.5.3.0)!
+#endif
+
+/**
+MIN_PD_CYCLE_TIME: Minimum cycle time in ns the slave is supporting (entry 0x1C3x:05).
+In case that the value is set to 0 the value of 0x1C3x:5 is calculated if 0x1C3x.8 is 1 */
+#ifndef MIN_PD_CYCLE_TIME
+#define MIN_PD_CYCLE_TIME 0x7A120
+#endif
+
+/**
+MAX_PD_CYCLE_TIME: Maximum cycle time in ns the slave is supporting */
+#ifndef MAX_PD_CYCLE_TIME
+#define MAX_PD_CYCLE_TIME 0xC3500000
+#endif
+
+/**
+PD_OUTPUT_DELAY_TIME: Minimum output delay time in ns the slave is supporting (entry 0x1C32:09) */
+#ifndef PD_OUTPUT_DELAY_TIME
+#define PD_OUTPUT_DELAY_TIME 0x0
+#endif
+
+/**
+PD_OUTPUT_CALC_AND_COPY_TIME: Output calc+copy time in ns the slave is supporting (entry 0x1C32:06)
+In case that the value is set to 0 the value of 0x1C32:6 is calculated if 0x1C3x.8 is 1 */
+#ifndef PD_OUTPUT_CALC_AND_COPY_TIME
+#define PD_OUTPUT_CALC_AND_COPY_TIME 0x0
+#endif
+
+/**
+PD_INPUT_CALC_AND_COPY_TIME: Input calc+copy time in ns the slave is supporting (entry 0x1C33:06)
+In case that the value is set to 0 the value of 0x1C33:6 is calculated if 0x1C3x.8 is 1 */
+#ifndef PD_INPUT_CALC_AND_COPY_TIME
+#define PD_INPUT_CALC_AND_COPY_TIME 0x0
+#endif
+
+/**
+PD_INPUT_DELAY_TIME: Input delay time in ns the slave is supporting (entry 0x1C33:09) */
+#ifndef PD_INPUT_DELAY_TIME
+#define PD_INPUT_DELAY_TIME 0x0
+#endif
+
+
+
+/*-----------------------------------------------------------------------------------------
+------
+------ Test Configuration Defines
+------
+-----------------------------------------------------------------------------------------*/
+
+
+#endif // _ECATDEF_H_
+
diff --git a/Projects/EFC_EcatDriver/src/ssc/ecatappl.c b/Projects/EFC_EcatDriver/src/ssc/ecatappl.c
new file mode 100644
index 0000000..43ec1e5
--- /dev/null
+++ b/Projects/EFC_EcatDriver/src/ssc/ecatappl.c
@@ -0,0 +1,1019 @@
+/*
+* This source file is part of the EtherCAT Slave Stack Code licensed by Beckhoff Automation GmbH & Co KG, 33415 Verl, Germany.
+* The corresponding license agreement applies. This hint shall not be removed.
+* https://www.beckhoff.com/media/downloads/slave-stack-code/ethercat_ssc_license.pdf
+*/
+
+/**
+\addtogroup EcatAppl EtherCAT application
+@{
+*/
+
+
+/**
+\file ecatappl.c
+\author EthercatSSC@beckhoff.com
+\brief Implementation
+This file contains the Process Data interface
+
+\version 5.13
+
+ Changes to version V5.12:
+V5.13 CIA402 3: change define "CIA402_DEVICE" to "CiA402_SAMPLE_APPLICATION"
+V5.13 CIA402 4: decouple CIA402 state machine and application from ESM (according ETG.6010, clause 4)
+V5.13 COE4: update default entry name handling in case of 16Bit characters, add CoE Read/write indication functions
+V5.13 ECAT 5: check inputsize before calling PDO_InputMappingdo not call PDO_InputMapping in case of no available process data
+V5.13 ECAT 6: change input mapping trigger in case of DC Sync
+V5.13 ECAT1: handle Sync mapped to AL Event
+V5.13 ECAT4: set delay between EEPROM access retries to 10ms
+V5.13 EEPROM1: update eeprom reload in case of ESC 32Bit access (and the small eeprom emulation)
+V5.13 TEST6: add 0xA002 monitoring ob function calls
+ Changes to version V5.11:
+V5.12 APPL1: add optional application function called from the main loop (after mbx and esm are executed)
+V5.12 BOOT1: add a bootloader sample application (only the ESM and FoE is supported)
+V5.12 COE4: add timestamp object (0x10F8) and update diagnosis handling
+V5.12 ECAT1: update SM Parameter measurement (based on the system time), enhancement for input only devices and no mailbox support, use only 16Bit pointer in process data length caluclation
+V5.12 ECAT3: update PD monitoring variables even if the slave is not in OP, disable all interrupts in case that the pd handling is called from the mainloop
+V5.12 ECAT5: update Sync error counter/flag handling,check enum memory alignment depending on the processor,in case of a polled timer disable ESC interrupts during DC_CheckWatchdog
+V5.12 ECAT8: reset appl function pointer on startup, update timeout calculation during eeprom access
+V5.12 EEPROM1: get read size from register 0x502.6
+V5.12 EEPROM2: clear CRC Error bit only in case of a valid reload, write station alias only in case of an successful reload,handle full eeprom emlation relaod commands
+V5.12 EEPROM3: implement a store EEPROM timeout handler
+ Changes to version V5.10.1:
+V5.11 COE3: change 0x10F3.2 (Sync Error limit) from UINT32 to UINT16 (according to the ETG.1020)
+V5.11 ECAT1: update EEPROM access reset operation
+V5.11 ECAT10: change PROTO handling to prevent compiler errors
+V5.11 ECAT11: create application interface function pointer, add eeprom emulation interface functions
+V5.11 ECAT2: update EEPROM access retry cycle (add 10ms delay between two retry cycles)
+V5.11 ECAT3: handle bus cycle calculation for input/output only devices and create warning diag message only if calculation failed
+V5.11 ECAT4: enhance SM/Sync monitoring for input/output only slaves
+V5.11 ECAT6: add function to calculate bus cycle time
+V5.11 ECAT8: call PDO_InputMapping only once if DC is enabled and COE is not supported
+V5.11 EEPROM1: fix compiler error during pEEPROM pointer initialization
+V5.11 EEPROM2: write Station alias value to EEPROM data register on EEPROM reload command
+V5.11 EEPROM3: clear EEPROM error bits
+V5.11 EEPROM4: prevent the variable in the EEPROM busy loop to be removed by the compiler
+V5.11 ESM7: "add Sync define for 0x22 (""SYNCTYPE_SM2_SYNCHRON""), support value 0x22 for 0x1C33.1 (SM2 sync)"
+ Changes to version V5.01:
+V5.10 COE1: Define one entry description for all 0x1C3x objects and change data type of SI11,12,13 to UINT16 (according ETG.1020)
+V5.10 ECAT1: Correct calculation of blinking and flashing sequence
+V5.10 ECAT13: Update Synchronisation handling (FreeRun,SM Sync, Sync0, Sync1)
+ Compare DC UINT configuration (by ESC Config data) vs. DC activation register settings
+ Update 0x1C3x entries
+V5.10 ECAT2: Prevent EEPROM data null pointer access (if the pointer is null an command error is set)
+ EEPROM emulation return command error if unknown command was received
+V5.10 ECAT4: Update alignment macro for 8 to 15 bit alignments (16 and 32 Bit controllers)
+ Bugfix calculate LED blink frequency
+V5.10 ECAT7: Add "bInitFinished" to indicate if the initialization is complete
+V5.10 HW2: Change HW_GetTimer return value to UINT32
+ Changes to version V5.0:
+V5.01 APPL3: Include library demo application
+V5.01 ESC1: Change ESC access function (if EEPROM Emulation is active)
+V5.01 ESC2: Add missed value swapping
+ Changes to version V4.40:
+V5.0 TEST1: Add test application. See Application Note ET9300 for more details.
+V5.0 ECAT2: Application specific functions are moved to application files.
+V5.0 ECAT3: Global dummy variables used for dummy ESC operations.
+V5.0 ESC1: ESC 32Bit Access added.
+V5.0 ESC3: Add EEPROM emulation support.
+V5.0 ESM3: Handling pending ESM transitions.
+V5.0 ESC5: Enhance EEPROM access handling.
+V5.0 PDO1: AL Event flags are not rechecked in PDO_OutputMappping(). (Already checked before call function)
+V5.0 SYNC1: Add missed SM event indication (0x1C32/0x1C33 SI11).
+ Changes to version V4.30:
+V4.40 DIAG1: add diagnosis message support
+V4.40 PDO1: merge content of HW_InputMapping (spihw.c/mcihw.c) to PDO_InputMapping. merge content of HW_OutputMapping (spihw.c/mcihw.c) to PDO_OutputMapping.
+V4.40 PDO2: Generic process data length calculation
+V4.40 ECAT2: call cyclic CheckIfLocalError() to check the local flags
+V4.40 HW0: Generic hardware access functions. Add Function (PDI_Isr()), content merged from spihw.c and mcihw.c.
+V4.40 WD1: define (ESC_SM_WD_SUPPORTED) to choose ESC SyncManager watchdog or local watchdog
+V4.40 ESM2: Change state transition behaviour from SafeOP to OP
+V4.40 TIMER1: Change bus cycle time calculation and trigger of ECAT_CheckTimer() if ECAT_TIMER_INT is reset
+V4.40 HW1: Add support for fc1100 hardware
+ Changes to version V4.20:
+V4.30 EL9800: EL9800_x cyclic application is moved to el9800.c
+V4.30 OBJ 3: add object dictionary initialization
+V4.30 SYNC: add CalcSMCycleTime() (calculation of bus cycle time); change synchronisation control functions
+V4.30 PDO: include PDO specific functions (moved from coeappl.c).
+ xxx_InputMapping(); xxx_OutputMapping(); xxx_ReadInputs(); xxx_ResetOutputs(); xxx_Application()
+V4.30 CiA402: Add CiA402_StateMachine() and CiA402_Application() call
+V4.20 DC 1: Add DC pending Statemachine handling
+V4.20 PIC24: Add EL9800_4 (PIC24) required source code
+V4.20 LED 1: Modified LED Handling
+V4.11 APPL 1: The checkWatchdog() function should not called in checkTimer() if this function is triggered by an Interrupt
+ Changes to version V4.08:
+V4.10 LED 1: The handling of the EtherCAT-Error-LED was added
+V4.10 AOE 3: The AoE fragment size has to be initialized during the state transition
+ from INIT to PREOP
+ Changes to version V4.07:
+V4.08 LED 1: The handling of the EtherCAT-LED can be (de-)selected by the switch LEDS_SUPPORTED
+ because the ET1100 and ET1200 have an output port which could be connected directly.
+ Changes to version V4.01:
+V4.02 ECAT 1: The watchdog timer variables shall be initialized.
+ Changes to version V4.00:
+V4.01 APPL 1: If the application is running in synchron mode and no SM event
+ is received, the application should be called from the main loop
+V4.01 APPL 2: In FreeRun mode the output should only be copied if the slave is in OP
+ Changes to version V3.20:
+V4.00 APPL 1: The watchdog checking should be done by a microcontroller
+ timer because the watchdog trigger of the ESC will be reset too
+ if only a part of the sync manager data is written
+V4.00 APPL 2: The setting of EtherCAT state LEDs were included
+V4.00 APPL 3: The outputs should be reset to a safe state,
+ when the state OP is left
+V4.00 APPL 4: An example for the EEPROM access through the ESC is shown in
+ the function APPL_StartMailboxHandler
+V4.00 APPL 5: The inputs should be read once when the state transition
+ from PREOP to SAFEOP is made
+V4.00 APPL 6: The main function was split in MainInit and MainLoop
+*/
+
+
+/*-----------------------------------------------------------------------------------------
+------
+------ Includes
+------
+-----------------------------------------------------------------------------------------*/
+#include "ecatslv.h"
+
+#define _ECATAPPL_ 1
+#include "ecatappl.h"
+#undef _ECATAPPL_
+/*remove definition of _ECATAPPL_ (#ifdef is used in ecatappl.h)*/
+
+#include "coeappl.h"
+
+
+/*ET9300 Project Handler :(#if DIAGNOSIS_SUPPORTED) lines 148 to 150 deleted*/
+
+#define _APPL_INTERFACE_ 1
+#include "applInterface.h"
+#undef _APPL_INTERFACE_
+
+/*ECATCHANGE_START(V5.13) CIA402 3*/
+/*ET9300 Project Handler :(#if CiA402_SAMPLE_APPLICATION #elif EL9800_APPLICATION #elif SAMPLE_APPLICATION #elif TEST_APPLICATION #elif SAMPLE_APPLICATION_INTERFACE #elif BOOTLOADER_SAMPLE) lines 157 to 170 deleted*/
+
+/*--------------------------------------------------------------------------------------
+------
+------ local Types and Defines
+------
+--------------------------------------------------------------------------------------*/
+
+/*ET9300 Project Handler :(#if ESC_EEPROM_ACCESS_SUPPORT) lines 185 to 187 deleted*/
+
+#ifndef ECAT_TIMER_INC_P_MS
+/**
+ * \todo Define the timer ticks per ms
+ */
+#warning "Define the timer ticks per ms"
+#endif /* #ifndef ECAT_TIMER_INC_P_MS */
+
+
+
+#define MEASUREMENT_ACTIVE (((sSyncManOutPar.u16GetCycleTime & 0x1) == 0x1) || ((sSyncManInPar.u16GetCycleTime & 0x1) == 0x1))
+/*ET9300 Project Handler :(#elif MAX_PD_OUTPUT_SIZE > 0) lines 204 to 210 deleted*/
+
+/*-----------------------------------------------------------------------------------------
+------
+------ local variables and constants
+------
+-----------------------------------------------------------------------------------------*/
+/*variables required to calculate values for SM Synchronisation objects (0x1C3x)*/
+
+UINT32 u32CycleTimeStartValue; /** <\brief contains the timer start value to measure the application cycle (used in freerun and SM2 sync)*/
+
+UINT32 u32MinCycleTimeStartValue; /** <\brief timeout counter in ms to measure the process timings (stored in 0x1C3x)*/
+
+UINT32 u32SystemTimeReadFailure; /** <\brief System time measurement failure (the value is calculated on main init)*/
+
+BOOL bMinCycleTimeMeasurementStarted; /** <\brief Indicates if the min cycle measurement is started*/
+
+UINT32 u32MinCycleTimeValue; /** <\brief tmp value of the min cycle time during measurement*/
+
+
+
+/*ET9300 Project Handler :(#if ESC_EEPROM_EMULATION) lines 237 to 241 deleted*/
+
+
+UINT16 aPdOutputData[(MAX_PD_OUTPUT_SIZE>>1)];
+UINT16 aPdInputData[(MAX_PD_INPUT_SIZE>>1)];
+
+/*variables are declared in ecatslv.c*/
+/*ET9300 Project Handler :(#if ESC_32BIT_ACCESS #elif ESC_16BIT_ACCESS) lines 252 to 256 deleted*/
+ extern VARVOLATILE UINT8 u8dummy;
+
+BOOL bInitFinished = FALSE; /** < \brief indicates if the initialization is finished*/
+
+/*-----------------------------------------------------------------------------------------
+------
+------ local functions
+------
+-----------------------------------------------------------------------------------------*/
+UINT32 GetSystemTimeDelay(UINT32 u32StartTime);
+void HandleCycleTimeMeasurement(void);
+
+/*-----------------------------------------------------------------------------------------
+------
+------ Functions
+------
+-----------------------------------------------------------------------------------------*/
+/////////////////////////////////////////////////////////////////////////////////////////
+/**
+\brief This function will copies the inputs from the local memory to the ESC memory
+*////////////////////////////////////////////////////////////////////////////////////////
+/*ET9300 Project Handler :(#if _PIC18 && AL_EVENT_ENABLED) lines 284 to 288 deleted*/
+void PDO_InputMapping(void)
+{
+
+#if ((MIN_PD_CYCLE_TIME == 0) || (PD_INPUT_CALC_AND_COPY_TIME == 0))
+ UINT32 u32TimeValue = 0;
+ UINT16 ALEvent = HW_GetALEventRegister_Isr();
+ ALEvent = SWAPWORD(ALEvent);
+
+ if (MEASUREMENT_ACTIVE)
+ {
+ u32TimeValue = GetSystemTimeDelay(0);
+ }
+#endif /* ((MIN_PD_CYCLE_TIME == 0) || (PD_INPUT_CALC_AND_COPY_TIME == 0)) */
+
+
+
+
+
+
+
+ APPL_InputMapping((UINT16*)aPdInputData);
+ HW_EscWriteIsr(((MEM_ADDR *) aPdInputData), nEscAddrInputData, nPdInputSize );
+
+
+
+#if ((MIN_PD_CYCLE_TIME == 0) || (PD_INPUT_CALC_AND_COPY_TIME == 0))
+
+ if (MEASUREMENT_ACTIVE)
+ {
+ u32TimeValue = GetSystemTimeDelay(u32TimeValue);
+
+#if (PD_INPUT_CALC_AND_COPY_TIME == 0)
+ if (sSyncManInPar.u32CalcAndCopyTime < u32TimeValue)
+ {
+ sSyncManInPar.u32CalcAndCopyTime = u32TimeValue;
+ }
+#endif
+
+#if (MIN_PD_CYCLE_TIME == 0)
+ /* handle the min cycle time measurement only if a new cycle was started (prevent measurement failures if the get cycle time bit is set within a process data cycle)*/
+ if (bMinCycleTimeMeasurementStarted == TRUE)
+ {
+
+ /* add input mapping time to the min cycle time*/
+ u32MinCycleTimeValue = u32MinCycleTimeValue + u32TimeValue;
+
+
+ if (sSyncManOutPar.u32MinCycleTime < u32MinCycleTimeValue)
+ {
+ sSyncManOutPar.u32MinCycleTime = u32MinCycleTimeValue;
+ }
+
+ if (sSyncManInPar.u32MinCycleTime < u32MinCycleTimeValue)
+ {
+ sSyncManInPar.u32MinCycleTime = u32MinCycleTimeValue;
+ }
+
+ bMinCycleTimeMeasurementStarted = FALSE;
+ }
+#endif /* (MIN_PD_CYCLE_TIME == 0) */
+ }
+
+#endif /* ((MIN_PD_CYCLE_TIME == 0) || (PD_INPUT_CALC_AND_COPY_TIME == 0)) */
+
+}
+/////////////////////////////////////////////////////////////////////////////////////////
+/**
+\brief This function will copies the outputs from the ESC memory to the local memory.
+ This function is only called in case of an SM2 (output process data) event.
+*////////////////////////////////////////////////////////////////////////////////////////
+/*ET9300 Project Handler :(#if _PIC18 && AL_EVENT_ENABLED) lines 371 to 375 deleted*/
+void PDO_OutputMapping(void)
+{
+ UINT32 u32TimeValue = 0;
+ if (MEASUREMENT_ACTIVE)
+ {
+#if ((MIN_PD_CYCLE_TIME == 0) || (PD_OUTPUT_CALC_AND_COPY_TIME == 0))
+ u32TimeValue = GetSystemTimeDelay(0);
+ u32MinCycleTimeStartValue = u32TimeValue;
+
+ bMinCycleTimeMeasurementStarted = TRUE;
+ u32MinCycleTimeValue = 0;
+
+#endif /* ((MIN_PD_CYCLE_TIME == 0) || (PD_OUTPUT_CALC_AND_COPY_TIME == 0)) */
+
+ HandleCycleTimeMeasurement();
+
+ }
+
+ HW_EscReadIsr(((MEM_ADDR *)aPdOutputData), nEscAddrOutputData, nPdOutputSize );
+ APPL_OutputMapping((UINT16*) aPdOutputData);
+
+
+#if ((MIN_PD_CYCLE_TIME == 0) || (PD_OUTPUT_CALC_AND_COPY_TIME == 0))
+ if (MEASUREMENT_ACTIVE)
+ {
+ u32TimeValue = GetSystemTimeDelay(u32TimeValue);
+
+#if (PD_OUTPUT_CALC_AND_COPY_TIME == 0)
+ if (sSyncManOutPar.u32CalcAndCopyTime < u32TimeValue)
+ {
+ sSyncManOutPar.u32CalcAndCopyTime = u32TimeValue;
+ }
+#endif
+
+#if (MIN_PD_CYCLE_TIME == 0)
+ /* add the first part of the min cycle time */
+ u32MinCycleTimeValue = u32TimeValue;
+#endif
+ }
+#endif /* #if ((MIN_PD_CYCLE_TIME == 0) || (PD_OUTPUT_CALC_AND_COPY_TIME == 0)) */
+}
+
+/////////////////////////////////////////////////////////////////////////////////////////
+/**
+ \brief This function shall be called every 1ms.
+ \brief If the switch ECAT_TIMER_INT is 0, the watchdog control is implemented without using
+ \brief interrupts. In this case a local timer register is checked every ECAT_Main cycle
+ \brief and the function is triggered if 1 ms is elapsed
+ *////////////////////////////////////////////////////////////////////////////////////////
+
+void ECAT_CheckTimer(void)
+{
+
+ /*decrement the state transition timeout counter*/
+ if(bEcatWaitForAlControlRes && (EsmTimeoutCounter > 0))
+ {
+ EsmTimeoutCounter--;
+ }
+
+/*ET9300 Project Handler :(#if !ESC_SM_WD_SUPPORTED) lines 444 to 449 deleted*/
+
+ ECAT_SetLedIndication();
+
+/*ET9300 Project Handler :(#if DC_SUPPORTED) lines 455 to 457 deleted*/
+
+/*ET9300 Project Handler :(#if ESC_EEPROM_EMULATION) lines 459 to 478 deleted*/
+
+
+/*ET9300 Project Handler :(#if DC_SUPPORTED) lines 483 to 489 deleted*/
+
+ /* the timestamp is stored in ns */
+ u64Timestamp = u64Timestamp + 1000000;
+
+/*ET9300 Project Handler :(#if DC_SUPPORTED) lines 494 to 503 deleted*/
+
+
+/*ET9300 Project Handler :(#if TEST_APPLICATION && COE_SUPPORTED) lines 508 to 512 deleted*/
+}
+
+/////////////////////////////////////////////////////////////////////////////////////////
+/**
+\brief In case of non DC synchronization the cycle time measurement is started and 0x1C3.2 (Cycle time) is updated
+*////////////////////////////////////////////////////////////////////////////////////////
+void HandleCycleTimeMeasurement(void)
+{
+ if (!bDcSyncActive) //no DC sync configured (cycle time measurement 0x1C3x.2 is only available in no DC sync modes)
+ {
+ if (u32CycleTimeStartValue > 0)
+ {
+ /* bus cycle completed*/
+ u32CycleTimeStartValue = GetSystemTimeDelay(u32CycleTimeStartValue);
+
+ if ((sSyncManOutPar.u32CycleTime == 0) || (sSyncManOutPar.u32CycleTime > u32CycleTimeStartValue))
+ {
+ sSyncManOutPar.u32CycleTime = u32CycleTimeStartValue;
+ }
+
+ if ((sSyncManInPar.u32CycleTime == 0) || (sSyncManInPar.u32CycleTime > u32CycleTimeStartValue))
+ {
+ sSyncManInPar.u32CycleTime = u32CycleTimeStartValue;
+ }
+ }
+ /* get next start value */
+ u32CycleTimeStartValue = GetSystemTimeDelay(0);
+
+ }/* No DC sync configured */
+}
+
+/////////////////////////////////////////////////////////////////////////////////////////
+/**
+\param u32StartTime Old system time (0x910:0x913) value
+
+\return System time delta in ns
+
+\brief Calculates the difference between the old and current system time value in ns.
+ NOTE: This function only handles a 32Bit system time values (therefore the maximum delay about 4sec).
+*////////////////////////////////////////////////////////////////////////////////////////
+
+UINT32 GetSystemTimeDelay(UINT32 u32StartTime)
+{
+ UINT32 u32CurValue = 0;
+ UINT32 u32Delta = 0;
+
+
+ HW_EscReadDWordIsr(u32CurValue, ESC_SYSTEMTIME_OFFSET);
+
+ if (u32CurValue > 0)
+ {
+ if (u32StartTime <= u32CurValue)
+ {
+ u32Delta = u32CurValue - u32StartTime;
+ }
+ else
+ {
+ //The 32Bit timer is wrapped around
+ u32Delta = u32CurValue + (0xFFFFFFFF - u32StartTime);
+ }
+ }// current value successfully read out
+
+ if (u32StartTime > 0)
+ {
+
+ /*the difference between two timestamps are calculated => subtract measurement failure*/
+ if (u32SystemTimeReadFailure < u32Delta)
+ {
+ u32Delta = u32Delta - u32SystemTimeReadFailure;
+ }
+ else
+ {
+ /*set the delta to 0 if the measurement failure is greater than the calculated difference*/
+ u32Delta = 0;
+ }
+ }
+ return u32Delta;
+}
+
+/*ECATCHANGE_START(V5.13) ECAT1*/
+/*ECATCHANGE_END(V5.13) ECAT1*/
+/*ET9300 Project Handler :(#if _PIC18) lines 603 to 607 deleted*/
+void PDI_Isr(void)
+{
+/*ET9300 Project Handler :(#if DC_SUPPORTED) lines 610 to 613 deleted*/
+
+ /* get the AL event register */
+ UINT16 ALEvent = HW_GetALEventRegister_Isr();
+ ALEvent = SWAPWORD(ALEvent);
+
+
+/*ET9300 Project Handler :(#if DC_SUPPORTED) lines 620 to 630 deleted*/
+
+
+ if(bEscIntEnabled)
+ {
+ if ( ALEvent & PROCESS_OUTPUT_EVENT )
+ {
+/*ET9300 Project Handler :(#if DC_SUPPORTED) lines 638 to 661 deleted*/
+
+ /* Outputs were updated, set flag for watchdog monitoring */
+ bEcatFirstOutputsReceived = TRUE;
+
+/*ET9300 Project Handler :(#if !ESC_SM_WD_SUPPORTED) lines 666 to 669 deleted*/
+
+ /*
+ handle output process data event
+ */
+ if ( bEcatOutputUpdateRunning )
+ {
+ /* slave is in OP, update the outputs */
+ PDO_OutputMapping();
+ }
+ else
+ {
+ /* Just acknowledge the process data event in the INIT,PreOP and SafeOP state */
+/*ET9300 Project Handler :(#if ESC_32BIT_ACCESS #elif ESC_16BIT_ACCESS) lines 682 to 688 deleted*/
+ HW_EscReadByteIsr(u8dummy,nEscAddrOutputData);
+ HW_EscReadByteIsr(u8dummy,(nEscAddrOutputData+nPdOutputSize-1));
+ }
+ }
+/*ET9300 Project Handler :(#elif MAX_PD_INPUT_SIZE > 0) lines 694 to 718 deleted*/
+
+ /*
+ Call ECAT_Application() in SM Sync mode
+ */
+ if (sSyncManOutPar.u16SyncType == SYNCTYPE_SM_SYNCHRON)
+ {
+ /* The Application is synchronized to process data Sync Manager event*/
+ ECAT_Application();
+ }
+/*ET9300 Project Handler :(#elif MAX_PD_INPUT_SIZE > 0) lines 730 to 736 deleted*/
+/*ET9300 Project Handler :(#if COE_SUPPORTED #else) lines 737 to 744 deleted*/
+
+/*ECATCHANGE_START(V5.13) ECAT 5*/
+ if ( (bEcatInputUpdateRunning == TRUE) && (nPdInputSize > 0)
+/*ECATCHANGE_END(V5.13) ECAT 5*/
+ && ((sSyncManInPar.u16SyncType == SYNCTYPE_SM_SYNCHRON) || (sSyncManInPar.u16SyncType == SYNCTYPE_SM2_SYNCHRON))
+/*ET9300 Project Handler :(#if COE_SUPPORTED #else) lines 752 to 754 deleted*/
+ )
+ {
+ /* EtherCAT slave is at least in SAFE-OPERATIONAL, update inputs */
+ PDO_InputMapping();
+ }
+
+ /*
+ Check if cycle exceed
+ */
+ /*if next SM event was triggered during runtime increment cycle exceed counter*/
+ ALEvent = HW_GetALEventRegister_Isr();
+ ALEvent = SWAPWORD(ALEvent);
+
+ if ( ALEvent & PROCESS_OUTPUT_EVENT )
+ {
+ sSyncManOutPar.u16CycleExceededCounter++;
+ sSyncManInPar.u16CycleExceededCounter = sSyncManOutPar.u16CycleExceededCounter;
+
+ /* Acknowledge the process data event*/
+/*ET9300 Project Handler :(#if ESC_32BIT_ACCESS #elif ESC_16BIT_ACCESS) lines 780 to 786 deleted*/
+ HW_EscReadByteIsr(u8dummy,nEscAddrOutputData);
+ HW_EscReadByteIsr(u8dummy,(nEscAddrOutputData+nPdOutputSize-1));
+ }
+/*ET9300 Project Handler :(#elif MAX_PD_INPUT_SIZE > 0) lines 791 to 811 deleted*/
+ } //if(bEscIntEnabled)
+
+/*ET9300 Project Handler :(#if DC_SUPPORTED) lines 814 to 831 deleted*/
+
+ COE_UpdateSyncErrorStatus();
+
+}
+
+/*ET9300 Project Handler :(#if DC_SUPPORTED) lines 840 to 1033 deleted*/
+/////////////////////////////////////////////////////////////////////////////////////////
+/**
+
+ \brief This function shall called within a 1ms cycle.
+ Set Run and Error Led depending on the Led state
+
+*////////////////////////////////////////////////////////////////////////////////////////
+void ECAT_SetLedIndication(void)
+{
+ static UINT16 ms = 0;
+ static UINT16 RunCounter = 0;
+ static UINT16 ErrorCounter = 0;
+
+ static UINT8 u8PrevErrorLed = LED_OFF ;
+ static UINT8 u8PrevRunLed = LED_OFF ;
+
+ // this code should be called every ms in average
+ if ( bEcatOutputUpdateRunning )
+ {
+ // in OP the EtherCAT state LED is always 1 and ErrorLED is 0
+ bEtherCATRunLed = TRUE;
+ bEtherCATErrorLed = FALSE;
+ }
+ else
+ {
+ ms++;
+ if(ms == 50 || ms == 100 ||ms == 150 ||ms == 200) //set flickering LED if required
+ {
+ /*Set run Led State*/
+ switch ( nAlStatus & STATE_MASK)
+ {
+ case STATE_INIT:
+ // in INIT the EtherCAT state LED is off
+ u8EcatRunLed = LED_OFF;
+ break;
+ case STATE_PREOP:
+ // in PREOP the EtherCAT state LED toggles every 200 ms
+ u8EcatRunLed = LED_BLINKING;
+ break;
+ case STATE_SAFEOP:
+ // in SAFEOP the EtherCAT state LED is 200 ms on and 1s off
+ u8EcatRunLed = LED_SINGLEFLASH;
+ break;
+ case STATE_OP:
+ u8EcatRunLed = LED_ON;
+ break;
+ case STATE_BOOT:
+ u8EcatRunLed = LED_FLICKERING;
+ break;
+ default:
+ u8EcatRunLed = LED_OFF;
+ break;
+ }//switch nAlStatus
+
+ /*Calculate current Run LED state*/
+ if((u8EcatRunLed & 0x20) || ms == 200) //if fast flag or slow cycle event
+ {
+ UINT8 NumFlashes = 0;
+ if ((u8EcatRunLed & 0x1F) > 0)
+ {
+ NumFlashes = (u8EcatRunLed & 0x1F)+((u8EcatRunLed & 0x1F)-1); //total number
+ }
+
+ /*generate LED code*/
+ if(u8EcatRunLed != u8PrevRunLed) //state changed start with active LED
+ {
+ if(u8EcatRunLed & 0x80) //invert flag enable?
+ {
+ bEtherCATRunLed = FALSE;
+ }
+ else
+ {
+ bEtherCATRunLed = TRUE;
+ }
+
+ RunCounter = 1;
+ }
+ else //second and following LED cycle
+ {
+ if(u8EcatRunLed & 0x40) //toggle LED bit on
+ {
+ bEtherCATRunLed = !bEtherCATRunLed;
+
+ if(NumFlashes) //NumFlashes defined => limited LED toggle
+ {
+ RunCounter++;
+
+ if(RunCounter > NumFlashes) //toggle led finished
+ {
+ if(u8EcatRunLed & 0x80) //invert flag enable?
+ {
+ bEtherCATRunLed = TRUE;
+ }
+ else
+ {
+ bEtherCATRunLed = FALSE;
+ }
+
+ if(RunCounter >= (NumFlashes+5)) //toggle time + 5 cycles low
+ {
+ RunCounter = 0;
+ }
+ }
+ }
+ }
+ else
+ {
+ bEtherCATRunLed = (u8EcatRunLed & 0x01);
+ }
+ }
+ u8PrevRunLed = u8EcatRunLed;
+ }
+
+ /*Calculate current Error LED state*/
+ if((u8EcatErrorLed & 0x20) || ms == 200) //if fast flag or slow cycle event
+ {
+ UINT8 NumFlashes = 0;
+ if ((u8EcatErrorLed & 0x1F) > 0)
+ {
+ NumFlashes = (u8EcatErrorLed & 0x1F)+((u8EcatErrorLed & 0x1F)-1); //total number
+ }
+
+ /*generate LED code*/
+ if(u8EcatErrorLed != u8PrevErrorLed) //state changed start with active LED
+ {
+ if(u8EcatErrorLed & 0x80) //invert flag enable?
+ {
+ bEtherCATErrorLed = FALSE;
+ }
+ else
+ {
+ bEtherCATErrorLed = TRUE;
+ }
+
+ ErrorCounter = 1;
+ }
+ else //second and following LED cycle
+ {
+ if(u8EcatErrorLed & 0x40) //toggle LED bit on
+ {
+ bEtherCATErrorLed = !bEtherCATErrorLed;
+
+ if(NumFlashes) //NumFlashes defined => limited LED toggle
+ {
+ ErrorCounter++;
+
+ if(ErrorCounter > NumFlashes) //toggle led finished
+ {
+ if(u8EcatErrorLed & 0x80) //invert flag enable?
+ {
+ bEtherCATErrorLed = TRUE;
+ }
+ else
+ {
+ bEtherCATErrorLed = FALSE;
+ }
+
+ if(ErrorCounter >= (NumFlashes+5)) //toggle time + 5 cycles low
+ {
+ ErrorCounter = 0;
+ }
+ }
+ }
+ }
+ else
+ {
+ bEtherCATErrorLed = (u8EcatErrorLed & 0x01);
+ }
+ }
+
+ u8PrevErrorLed = u8EcatErrorLed;
+ }
+
+ if(ms == 200)
+ {
+ ms = 0;
+ }
+ }
+ }
+
+ /* set the EtherCAT-LED */
+ HW_SetLed(((UINT8)bEtherCATRunLed),((UINT8)bEtherCATErrorLed));
+}
+/////////////////////////////////////////////////////////////////////////////////////////
+/**
+ \param pObjectDictionary Pointer to application specific object dictionary.
+ NULL if no specific object are available.
+\return 0 if initialization was successful
+
+ \brief This function initialize the EtherCAT Sample Code
+
+*////////////////////////////////////////////////////////////////////////////////////////
+
+UINT16 MainInit(void)
+{
+ UINT16 Error = 0;
+/*Hardware init function need to be called from the application layer*/
+
+#ifdef SET_EEPROM_PTR
+ SET_EEPROM_PTR
+#endif
+
+
+/* Reset application function pointer*/
+/*ET9300 Project Handler :(#if ESC_EEPROM_EMULATION) lines 1240 to 1245 deleted*/
+
+
+/*ET9300 Project Handler :(#if EOE_SUPPORTED) lines 1248 to 1251 deleted*/
+
+/*ET9300 Project Handler :(#if FOE_SUPPORTED) lines 1253 to 1259 deleted*/
+
+ /* ECATCHANGE_START(V5.13) COE4*/
+ pAPPL_CoeReadInd = NULL;
+ pAPPL_CoeWriteInd = NULL;
+ /* ECATCHANGE_END(V5.13) COE4*/
+
+ pAPPL_MainLoop = NULL;
+
+ /* initialize the EtherCAT Slave Interface */
+ ECAT_Init();
+ /* initialize the objects */
+ COE_ObjInit();
+
+/*ET9300 Project Handler :(#if DIAGNOSIS_SUPPORTED) lines 1277 to 1280 deleted*/
+
+/*ET9300 Project Handler :(#if ESC_EEPROM_ACCESS_SUPPORT) lines 1282 to 1315 deleted*/
+ /*indicate that the slave stack initialization finished*/
+ bInitFinished = TRUE;
+
+
+ bMinCycleTimeMeasurementStarted = FALSE;
+ u32CycleTimeStartValue = 0;
+ u32MinCycleTimeStartValue = 0;
+
+ u32SystemTimeReadFailure = 0;
+
+ /* Get the System Time read failure */
+ {
+ UINT32 u32TimeValue = 0;
+ UINT32 u32Cnt = 0;
+ UINT32 u32Delta = 0;
+
+ while (u32Cnt < 1000)
+ {
+ HW_EscReadDWordIsr(u32TimeValue, ESC_SYSTEMTIME_OFFSET);
+ HW_EscReadDWordIsr(u32Delta, ESC_SYSTEMTIME_OFFSET);
+
+ if (u32TimeValue <= u32Delta)
+ {
+ u32Delta = u32Delta - u32TimeValue;
+ }
+ else
+ {
+ //The 32Bit timer is wrapped around
+ u32Delta = u32Delta + (0xFFFFFFFF - u32TimeValue);
+ }
+
+
+ if (u32SystemTimeReadFailure == 0)
+ {
+ u32SystemTimeReadFailure = u32Delta;
+ }
+ else if (u32SystemTimeReadFailure > u32Delta)
+ {
+ u32SystemTimeReadFailure = u32Delta;
+ }
+
+ u32Cnt++;
+ }
+
+ }
+
+
+
+/*ET9300 Project Handler :(#if ESC_EEPROM_EMULATION) lines 1368 to 1391 deleted*/
+
+/*Application Init need to be called from the application layer*/
+ return Error;
+}
+
+
+/////////////////////////////////////////////////////////////////////////////////////////
+/**
+
+ \brief This function shall be called cyclically from main
+
+*////////////////////////////////////////////////////////////////////////////////////////
+
+void MainLoop(void)
+{
+
+ /*return if initialization not finished */
+ if(bInitFinished == FALSE)
+ {
+ return;
+ }
+
+
+
+ /* FreeRun-Mode: bEscIntEnabled = FALSE, bDcSyncActive = FALSE
+ Synchron-Mode: bEscIntEnabled = TRUE, bDcSyncActive = FALSE
+ DC-Mode: bEscIntEnabled = TRUE, bDcSyncActive = TRUE */
+ if (
+ (!bEscIntEnabled || !bEcatFirstOutputsReceived) /* SM-Synchronous, but not SM-event received */
+/*ET9300 Project Handler :(#if MAX_PD_OUTPUT_SIZE > 0 #else) lines 1422 to 1424 deleted*/
+/*ET9300 Project Handler :(#if DC_SUPPORTED) lines 1425 to 1427 deleted*/
+ )
+ {
+ /* if the application is running in ECAT Synchron Mode the function ECAT_Application is called
+ from the ESC interrupt routine,
+ in ECAT Synchron Mode it should be additionally checked, if the SM-event is received
+ at least once (bEcatFirstOutputsReceived = 1), otherwise no interrupt is generated
+ and the function ECAT_Application has to be called here (with interrupts disabled,
+ because the SM-event could be generated while executing ECAT_Application) */
+ if ( !bEscIntEnabled )
+ {
+ /* application is running in ECAT FreeRun Mode,
+ first we have to check, if outputs were received */
+ UINT16 ALEvent = HW_GetALEventRegister();
+ ALEvent = SWAPWORD(ALEvent);
+
+ if ( ALEvent & PROCESS_OUTPUT_EVENT )
+ {
+ /* set the flag for the state machine behavior */
+ bEcatFirstOutputsReceived = TRUE;
+/*ET9300 Project Handler :(#if !ESC_SM_WD_SUPPORTED) lines 1448 to 1451 deleted*/
+ if ( bEcatOutputUpdateRunning )
+ {
+ /* update the outputs */
+ PDO_OutputMapping();
+ }
+ }
+ else if ( nPdOutputSize == 0 )
+ {
+ /* if no outputs are transmitted, the watchdog must be reset, when the inputs were read */
+ if ( ALEvent & PROCESS_INPUT_EVENT )
+ {
+ /* Outputs were updated, set flag for watchdog monitoring */
+ bEcatFirstOutputsReceived = TRUE;
+/*ET9300 Project Handler :(#if !ESC_SM_WD_SUPPORTED) lines 1466 to 1469 deleted*/
+ }
+ }
+ }
+
+ DISABLE_ESC_INT();
+ ECAT_Application();
+
+/*ECATCHANGE_START(V5.13) ECAT 5*/
+ if ( (bEcatInputUpdateRunning == TRUE) && (nPdInputSize > 0))
+/*ECATCHANGE_END(V5.13) ECAT 5*/
+ {
+ /* EtherCAT slave is at least in SAFE-OPERATIONAL, update inputs */
+ PDO_InputMapping();
+ }
+ ENABLE_ESC_INT();
+ }
+
+ /* there is no interrupt routine for the hardware timer so check the timer register if the desired cycle elapsed*/
+ {
+ UINT32 CurTimer = (UINT32)HW_GetTimer();
+
+ if(CurTimer>= ECAT_TIMER_INC_P_MS)
+ {
+ ECAT_CheckTimer();
+
+ HW_ClearTimer();
+ }
+ }
+
+/*ET9300 Project Handler :(#if DC_SUPPORTED && COE_SUPPORTED) lines 1509 to 1516 deleted*/
+
+ /* call EtherCAT functions */
+ ECAT_Main();
+
+ /* call lower prior application part */
+ COE_Main();
+ CheckIfEcatError();
+
+/*ET9300 Project Handler :(#if CiA402_SAMPLE_APPLICATION) lines 1527 to 1532 deleted*/
+
+ if (pAPPL_MainLoop != NULL)
+ {
+ pAPPL_MainLoop();
+ }
+}
+
+/*The main function was moved to the application files.*/
+/////////////////////////////////////////////////////////////////////////////////////////
+/**
+ \brief ECAT_Application (prev. SSC versions "COE_Application")
+ this function calculates and the physical process signals and triggers the input mapping
+*////////////////////////////////////////////////////////////////////////////////////////
+/*ET9300 Project Handler :(#if _PIC18 && AL_EVENT_ENABLED) lines 1546 to 1550 deleted*/
+void ECAT_Application(void)
+{
+#if (MIN_PD_CYCLE_TIME == 0)
+ UINT32 u32TimeValue = 0;
+
+
+ if (MEASUREMENT_ACTIVE)
+ {
+ u32TimeValue = GetSystemTimeDelay(0);
+
+ if (nPdOutputSize == 0)
+ {
+ /* in case of an input only device the cycle starts with an ECAT_Application call*/
+
+ u32MinCycleTimeStartValue = u32TimeValue;
+ bMinCycleTimeMeasurementStarted = TRUE;
+ u32MinCycleTimeValue = 0;
+ }
+ } /* measurement started*/
+#endif /* (MIN_PD_CYCLE_TIME == 0)*/
+
+ if (MEASUREMENT_ACTIVE)
+ {
+ if (nPdOutputSize == 0)
+ {
+ /* in case of an input only device the cycle starts with an ECAT_Application call*/
+ HandleCycleTimeMeasurement();
+ }
+ }
+
+
+ /*ECATCHANGE_START(V5.13) CIA402 4*/
+ /*decouple CIA402 application from ESM*/
+ /*ECATCHANGE_END(V5.13) CIA402 4*/
+ APPL_Application();
+
+/* PDO Input mapping is called from the specific trigger ISR */
+
+#if (MIN_PD_CYCLE_TIME == 0)
+
+ if (MEASUREMENT_ACTIVE)
+ {
+ u32TimeValue = GetSystemTimeDelay(u32TimeValue);
+
+
+ /* handle the min cycle time measurement only if a new cycle was started (prevent measurement failures if the get cycle time bit is set within a process data cycle)*/
+ if (bMinCycleTimeMeasurementStarted == TRUE)
+ {
+
+ /* add application execution time to the min cycle time*/
+ u32MinCycleTimeValue = u32MinCycleTimeValue + u32TimeValue;
+
+ if (nPdInputSize == 0)
+ {
+ /* In case of an output only device the cycle ends with an ECAT_Application call*/
+
+
+ if (sSyncManOutPar.u32MinCycleTime < u32MinCycleTimeValue)
+ {
+ sSyncManOutPar.u32MinCycleTime = u32MinCycleTimeValue;
+ }
+
+ if (sSyncManInPar.u32MinCycleTime < u32MinCycleTimeValue)
+ {
+ sSyncManInPar.u32MinCycleTime = u32MinCycleTimeValue;
+ }
+
+ bMinCycleTimeMeasurementStarted = FALSE;
+ }
+ }
+
+ }/* measurement started*/
+#endif /* #if MIN_PD_CYCLE_TIME == 0 */
+}
+
+/*ET9300 Project Handler :(#if ESC_EEPROM_ACCESS_SUPPORT) lines 1644 to 2002 deleted*/
+
+/*ET9300 Project Handler :(#if ESC_EEPROM_EMULATION) lines 2004 to 2224 deleted*/
+
+
+/** @} */
+
diff --git a/Projects/EFC_EcatDriver/src/ssc/ecatappl.h b/Projects/EFC_EcatDriver/src/ssc/ecatappl.h
new file mode 100644
index 0000000..1a5bd37
--- /dev/null
+++ b/Projects/EFC_EcatDriver/src/ssc/ecatappl.h
@@ -0,0 +1,139 @@
+/*
+* This source file is part of the EtherCAT Slave Stack Code licensed by Beckhoff Automation GmbH & Co KG, 33415 Verl, Germany.
+* The corresponding license agreement applies. This hint shall not be removed.
+* https://www.beckhoff.com/media/downloads/slave-stack-code/ethercat_ssc_license.pdf
+*/
+
+/**
+ \addtogroup EcatAppl EtherCAT application
+ * @{
+ */
+
+/**
+\file ecatappl.h
+\author EthercatSSC@beckhoff.com
+
+\version 5.12
+
+ Changes to version V5.11:
+V5.12 EEPROM1: get read size from register 0x502.6
+ Changes to version V5.10:
+V5.11 ECAT10: change PROTO handling to prevent compiler errors
+ Changes to version V5.01:
+V5.10 ECAT13: Update Synchronisation handling (FreeRun,SM Sync, Sync0, Sync1)
+ Compare DC UINT configuration (by ESC Config data) vs. DC activation register settings
+ Update 0x1C3x entries
+V5.10 ECAT4: Update alignment macro for 8 to 15 bit alignments (16 and 32 Bit controllers)
+ Bugfix calculate LED blink frequency
+ Changes to version - :
+V5.01 : Start file change log
+ */
+/*-----------------------------------------------------------------------------------------
+------
+------ Description
+------
+------ ecatappl.h
+------
+------ EtherCAT Slave Application
+------ ------
+-----------------------------------------------------------------------------------------*/
+
+/*-----------------------------------------------------------------------------------------
+------
+------ Includes
+------
+-----------------------------------------------------------------------------------------*/
+
+#include "ecat_def.h"
+
+
+#ifndef _ECATAPPL_H_
+#define _ECATAPPL_H_
+
+/*-----------------------------------------------------------------------------------------
+------
+------ Defines and Types
+------
+-----------------------------------------------------------------------------------------*/
+
+/*ET9300 Project Handler :(#if CONTROLLER_16BIT || CONTROLLER_32BIT) lines 58 to 85 deleted*/
+#define BOOLEAN(x) UINT8 x:1 /**< \brief Macro to define BOOLEAN object entry*/
+#define BIT1(x) UINT8 x:1 /**< \brief Macro to define BIT1 object entry*/
+#define BIT2(x) UINT8 x:2 /**< \brief Macro to define BIT2 object entry*/
+#define BIT3(x) UINT8 x:3 /**< \brief Macro to define BIT3 object entry*/
+#define BIT4(x) UINT8 x:4 /**< \brief Macro to define BIT4 object entry*/
+#define BIT5(x) UINT8 x:5 /**< \brief Macro to define BIT5 object entry*/
+#define BIT6(x) UINT8 x:6 /**< \brief Macro to define BIT5 object entry*/
+#define BIT7(x) UINT8 x:7 /**< \brief Macro to define BIT6 object entry*/
+#define BIT8(x) UINT8 x:8 /**< \brief Macro to define BIT7 object entry*/
+#define ALIGN0(x)
+#define ALIGN1(x) UINT8 x:1; /**< \brief Macro to define ALIGN1 object entry*/
+#define ALIGN2(x) UINT8 x:2; /**< \brief Macro to define ALIGN2 object entry*/
+#define ALIGN3(x) UINT8 x:3; /**< \brief Macro to define ALIGN3 object entry*/
+#define ALIGN4(x) UINT8 x:4; /**< \brief Macro to define ALIGN4 object entry*/
+#define ALIGN5(x) UINT8 x:5; /**< \brief Macro to define ALIGN5 object entry*/
+#define ALIGN6(x) UINT8 x:6; /**< \brief Macro to define ALIGN6 object entry*/
+#define ALIGN7(x) UINT8 x:7; /**< \brief Macro to define ALIGN7 object entry*/
+#define ALIGN8(x) UINT8 x:8; /**< \brief Macro to define ALIGN8 object entry*/
+/*ET9300 Project Handler :(#if _PIC18) lines 104 to 112 deleted*/
+#define ALIGN9(x) UINT16 x:9; /**< \brief Macro to define ALIGN9 object entry*/
+#define ALIGN10(x) UINT16 x:10; /**< \brief Macro to define ALIGN10 object entry*/
+#define ALIGN11(x) UINT16 x:11; /**< \brief Macro to define ALIGN11 object entry*/
+#define ALIGN12(x) UINT16 x:12; /**< \brief Macro to define ALIGN12 object entry*/
+#define ALIGN13(x) UINT16 x:13; /**< \brief Macro to define ALIGN13 object entry*/
+#define ALIGN14(x) UINT16 x:14; /**< \brief Macro to define ALIGN14 object entry*/
+#define ALIGN15(x) UINT16 x:15; /**< \brief Macro to define ALIGN15 object entry*/
+#endif //_ECATAPPL_H_
+
+#if defined(_ECATAPPL_) && (_ECATAPPL_ == 1)
+ #define PROTO
+#else
+ #define PROTO extern
+#endif
+
+
+/*-----------------------------------------------------------------------------------------
+------
+------ Global Variables
+------
+-----------------------------------------------------------------------------------------*/
+
+
+/*ET9300 Project Handler :(#if ESC_EEPROM_EMULATION) lines 138 to 140 deleted*/
+
+PROTO BOOL bEcatWaitForInputUpdate; /**< \brief Wait for input update*/
+PROTO BOOL bEtherCATRunLed; /**< \brief Current run LED value*/
+PROTO BOOL bEtherCATErrorLed; /**< \brief Current error LED value*/
+PROTO BOOL bRunApplication; /**< \brief Indicates if the stack shall be running (if false the Hardware will be released)*/
+
+
+
+/*ET9300 Project Handler :(#if ESC_EEPROM_EMULATION) lines 149 to 151 deleted*/
+/*-----------------------------------------------------------------------------------------
+------
+------ Global Functions
+------
+-----------------------------------------------------------------------------------------*/
+
+
+
+
+PROTO void ECAT_CheckTimer(void);
+PROTO void PDI_Isr(void);
+PROTO void Sync0_Isr(void);
+PROTO void Sync1_Isr(void);
+PROTO void ECAT_Application(void);
+PROTO void PDO_ResetOutputs(void);
+PROTO void PDO_ReadInputs(void);
+PROTO void PDO_InputMapping(void);
+
+PROTO void ECAT_SetLedIndication(void);
+/*ET9300 Project Handler :(#if DC_SUPPORTED) lines 175 to 177 deleted*/
+/*ET9300 Project Handler :(#if ESC_EEPROM_ACCESS_SUPPORT) lines 178 to 181 deleted*/
+
+/*ET9300 Project Handler :(#if ESC_EEPROM_EMULATION) lines 183 to 185 deleted*/
+
+
+
+#undef PROTO
+/** @}*/
diff --git a/Projects/EFC_EcatDriver/src/ssc/ecatcoe.c b/Projects/EFC_EcatDriver/src/ssc/ecatcoe.c
new file mode 100644
index 0000000..11a5f6b
--- /dev/null
+++ b/Projects/EFC_EcatDriver/src/ssc/ecatcoe.c
@@ -0,0 +1,191 @@
+/*
+* This source file is part of the EtherCAT Slave Stack Code licensed by Beckhoff Automation GmbH & Co KG, 33415 Verl, Germany.
+* The corresponding license agreement applies. This hint shall not be removed.
+* https://www.beckhoff.com/media/downloads/slave-stack-code/ethercat_ssc_license.pdf
+*/
+
+/**
+\addtogroup CoE CAN Application Profile over EtherCAT
+@{
+*/
+
+/**
+\file ecatcoe.c
+\author EthercatSSC@beckhoff.com
+\brief Implementation
+This file contains the CoE mailbox interface
+
+\version 5.13
+
+ Changes to version V5.11:
+V5.13 COE8: handle failure on continue indication
+V5.13 TEST4: memory leak on SDO response receive
+ Changes to version V5.0:
+V5.11 COE4: "change prototype of ""COE_ContinueInd()"" return <> 0 if a failure occurred"
+V5.11 ECAT10: change PROTO handling to prevent compiler errors
+V5.11 TEST6: add test object to trigger Slave-to-Slave communication
+V5.11 TEST7: add test behaviour to send an emergency on every SDO request (in SafeOP)
+ Changes to version V4.40:
+V5.0 SDO7: "SDOS_SdoInfoInd()" never return pending SDO Info service. Delete "NOERROR_INWORK" handling.
+ Changes to version V4.08:
+V4.40 SDO1: add initial value for "nSdoInfoFragmentsLeft"
+V4.40 MBX6: change return value if no mailbox buffer is available
+V4.08 MBX 1: If the switch MAILBOX_QUEUE was set, we have to put all SDO Info Responses in the Send Queue
+*/
+
+/*---------------------------------------------------------------------------------------
+------
+------ Includes
+------
+---------------------------------------------------------------------------------------*/
+
+#include "ecat_def.h"
+
+
+#include "sdoserv.h"
+#define _ECATCOE_ 1
+#include "ecatcoe.h"
+#undef _ECATCOE_
+/*remove definition of _ECATCOE_ (#ifdef is used in ecatcoe.h)*/
+
+
+/*ET9300 Project Handler :(#if TEST_APPLICATION) lines 52 to 60 deleted*/
+
+
+/*---------------------------------------------------------------------------------------
+------
+------ internal Types and Defines
+------
+---------------------------------------------------------------------------------------*/
+
+#define ECATCOE 0x4300
+#define ECATCOEMAX 0x02
+
+/*---------------------------------------------------------------------------------------
+------
+------ static variables
+------
+---------------------------------------------------------------------------------------*/
+
+/*---------------------------------------------------------------------------------------
+------
+------ static functions
+------
+---------------------------------------------------------------------------------------*/
+
+/*---------------------------------------------------------------------------------------
+------
+------ functions
+------
+---------------------------------------------------------------------------------------*/
+
+/////////////////////////////////////////////////////////////////////////////////////////
+/**
+
+ \brief This function intialize the CoE Interface.
+*////////////////////////////////////////////////////////////////////////////////////////
+
+void COE_Init(void)
+{
+ pCoeSendStored = 0;
+ nSdoInfoFragmentsLeft = 0;
+}
+
+/////////////////////////////////////////////////////////////////////////////////////////
+/**
+ \param pCoeMbx Pointer to the received mailbox data from the master.
+
+ \return result of the operation (0 (success) or mailbox error code (MBXERR_.... defined in
+ mailbox.h))
+
+ \brief This function is called when a CoE (CAN application layer over EtherCAT) service is received from
+ the master.
+*////////////////////////////////////////////////////////////////////////////////////////
+
+UINT8 COE_ServiceInd(TCOEMBX MBXMEM *pCoeMbx)
+{
+ UINT8 result = 0;
+
+ switch ((pCoeMbx->CoeHeader & COEHEADER_COESERVICEMASK) >> COEHEADER_COESERVICESHIFT)
+ {
+ case COESERVICE_SDOREQUEST:
+ /* SDO-Request received, call SDOS_SdoInd to process the SDO-Request
+ if an existing SDO-Stack shall be used, the corresponding function
+ should be called */
+/*ET9300 Project Handler :(#if TEST_APPLICATION && EMERGENCY_SUPPORTED) lines 125 to 152 deleted*/
+ result = SDOS_SdoInd( (TINITSDOMBX MBXMEM *) pCoeMbx );
+ break;
+
+ case COESERVICE_SDOINFO:
+ /* SDO-Information Request received, call SDOS_SdoInfoInd to process the SDO-Request */
+ result = SDOS_SdoInfoInd( (TSDOINFORMATION MBXMEM *) pCoeMbx );
+ /*NOERROR_INWORK is never returned by SDOS_SdoInfoInd() => delete return code handling*/
+ break;
+
+
+ case COESERVICE_SDORESPONSE:
+/*ET9300 Project Handler :(#if TEST_APPLICATION) lines 164 to 178 deleted*/
+ case COESERVICE_EMERGENCY:
+ case COESERVICE_TXPDO:
+ case COESERVICE_RXPDO:
+ case COESERVICE_TXPDOREMREQ:
+ case COESERVICE_RXPDOREMREQ:
+ /* these CoE services are not supported yet */
+ result = MBXERR_SERVICENOTSUPPORTED;
+ break;
+
+ default:
+ result = MBXERR_INVALIDHEADER;
+ break;
+ }
+ return result;
+}
+
+/////////////////////////////////////////////////////////////////////////////////////////
+/**
+ \param pMbx Pointer to the free mailbox to sent.
+
+ \return result of the operation (0 (success)
+
+ \brief This function is called when a CoE service to be sent is stored and can
+ \brief be put in the send mailbox.
+*////////////////////////////////////////////////////////////////////////////////////////
+
+UINT8 COE_ContinueInd(TMBX MBXMEM * pMbx)
+{
+ if (pCoeSendStored)
+ {
+ /* send the stored CoE service which could not be sent before */
+/*ECATCHANGE_START(V5.13) COE8*/
+ if (MBX_MailboxSendReq(pCoeSendStored, COE_SERVICE) == 0)
+ {
+ pCoeSendStored = 0;
+ }
+/*ECATCHANGE_END(V5.13) COE8*/
+ }
+ else
+ {
+ /* send the next fragment of the last CoE service (only for SDO-Information possible) */
+ /* in mailbox queue mode pMbx is always 0, so a mailbox buffer shall be get */
+ pMbx = (TMBX MBXMEM *) APPL_AllocMailboxBuffer(SIZEOF(TMBX));
+ /* it shall be checked if a valid pointer was returned */
+ if (pMbx == NULL)
+ {
+ return MBXERR_NOMOREMEMORY;
+ }
+ else
+ {
+ /* copy the stored SDO-Info-Header in the request */
+ MBXMEMCPY(pMbx, aSdoInfoHeader, SDO_INFO_HEADER_BYTE_SIZE);
+ /* call SDOS_SdoInfoInd to generate and send the next fragment */
+ SDOS_SdoInfoInd( (TSDOINFORMATION MBXMEM *) pMbx );
+ }
+ }
+
+ return 0;
+}
+
+/** @} */
+
+
+
diff --git a/Projects/EFC_EcatDriver/src/ssc/ecatcoe.h b/Projects/EFC_EcatDriver/src/ssc/ecatcoe.h
new file mode 100644
index 0000000..3cf31a7
--- /dev/null
+++ b/Projects/EFC_EcatDriver/src/ssc/ecatcoe.h
@@ -0,0 +1,116 @@
+/*
+* This source file is part of the EtherCAT Slave Stack Code licensed by Beckhoff Automation GmbH & Co KG, 33415 Verl, Germany.
+* The corresponding license agreement applies. This hint shall not be removed.
+* https://www.beckhoff.com/media/downloads/slave-stack-code/ethercat_ssc_license.pdf
+*/
+
+/**
+ * \addtogroup CoE CAN Application Profile over EtherCAT
+ * @{
+ */
+
+/**
+\file ecatcoe.h
+\author EthercatSSC@beckhoff.com
+
+\version 5.11
+
+ Changes to version V5.01:
+V5.11 COE4: "change prototype of ""COE_ContinueInd()"" return <> 0 if a failure occurred"
+V5.11 ECAT10: change PROTO handling to prevent compiler errors
+ Changes to version - :
+V5.01 : Start file change log
+ */
+
+/*-----------------------------------------------------------------------------------------
+------
+------ Includes
+------
+-----------------------------------------------------------------------------------------*/
+#include "mailbox.h"
+
+#ifndef _ECATCOE_H_
+#define _ECATCOE_H_
+
+/*-----------------------------------------------------------------------------------------
+------
+------ Defines and Types
+------
+-----------------------------------------------------------------------------------------*/
+
+/*---------------------------------------------
+- Error codes
+-----------------------------------------------*/
+#define ERROR_COEINVALIDSERVICE 0x01 /**< \brief Invalid SDO service*/
+#define ERROR_COENOTSUPPORTED 0x02 /**< \brief Not supported service*/
+
+
+/*---------------------------------------------
+- COE services
+-----------------------------------------------*/
+#define COESERVICE_EMERGENCY 0x01 /**< \brief CoE Emergency*/
+#define COESERVICE_SDOREQUEST 0x02 /**< \brief CoE SDO request*/
+#define COESERVICE_SDORESPONSE 0x03 /**< \brief CoE SDO response*/
+#define COESERVICE_TXPDO 0x04 /**< \brief CoE TxPDO*/
+#define COESERVICE_RXPDO 0x05 /**< \brief CoE RxPDO*/
+#define COESERVICE_TXPDOREMREQ 0x06 /**< \brief CoE TxPDO map request*/
+#define COESERVICE_RXPDOREMREQ 0x07 /**< \brief CoE RxPDO map request*/
+#define COESERVICE_SDOINFO 0x08 /**< \brief CoE SDO Info*/
+
+
+
+/*---------------------------------------------
+- COE Structures
+-----------------------------------------------*/
+/*ET9300 Project Handler :(#if BIG_ENDIAN_FORMAT) lines 64 to 67 deleted*/
+#define COEHEADER_COESERVICESHIFT 12 /**< \brief CoE service shift (within CoE header)*/
+#define COEHEADER_COESERVICEMASK 0xF000 /**< \brief CoE service mask (within CoE header)*/
+
+#define COE_HEADER_SIZE 2 /**< \brief CoE header size*/
+
+typedef UINT16 TCOEHEADER; /**< \brief CoE header*/
+
+
+/**
+ * \brief CoE Mailbox header
+ */
+typedef struct MBX_STRUCT_PACKED_START
+{
+ TMBXHEADER MbxHeader; /**< \brief mailbox header*/
+ TCOEHEADER CoeHeader; /**< \brief CoE header*/
+ UINT16 Data[((MAX_MBX_DATA_SIZE)-(COE_HEADER_SIZE)) >> 1]; /**< \brief CoE data*/
+}MBX_STRUCT_PACKED_END
+TCOEMBX;
+
+
+#endif //_ECATCOE_H_
+
+#if defined(_ECATCOE_) && (_ECATCOE_ == 1)
+ #define PROTO
+#else
+ #define PROTO extern
+#endif
+
+/*-----------------------------------------------------------------------------------------
+------
+------ Global Variables
+------
+-----------------------------------------------------------------------------------------*/
+PROTO TMBX MBXMEM * VARMEM pCoeSendStored; /** if the mailbox service could not be sent (or stored),
+ the CoE service will be stored in this variable
+ and will be sent automatically from the mailbox handler
+ (COE_ContinueInd) when the send mailbox will be read
+ the next time from the master */
+
+/*-----------------------------------------------------------------------------------------
+------
+------ Global Functions
+------
+-----------------------------------------------------------------------------------------*/
+
+PROTO void COE_Init(void);
+PROTO UINT8 COE_ServiceInd(TCOEMBX MBXMEM *pCoeMbx);
+PROTO UINT8 COE_ContinueInd(TMBX MBXMEM * pMbx);
+
+#undef PROTO
+/** @}*/
diff --git a/Projects/EFC_EcatDriver/src/ssc/ecatslv.c b/Projects/EFC_EcatDriver/src/ssc/ecatslv.c
new file mode 100644
index 0000000..5062ae4
--- /dev/null
+++ b/Projects/EFC_EcatDriver/src/ssc/ecatslv.c
@@ -0,0 +1,2342 @@
+/*
+* This source file is part of the EtherCAT Slave Stack Code licensed by Beckhoff Automation GmbH & Co KG, 33415 Verl, Germany.
+* The corresponding license agreement applies. This hint shall not be removed.
+* https://www.beckhoff.com/media/downloads/slave-stack-code/ethercat_ssc_license.pdf
+*/
+
+/**
+\addtogroup ESM EtherCAT State Machine
+@{
+*/
+
+/**
+\file ecatslv.c
+\author EthercatSSC@beckhoff.com
+\brief Implementation
+This file contains the EtherCAT State Machine.
+
+\version 5.13
+
+ Changes to version V5.12:
+V5.13 BOOT1: support Init-to-Init transition in bootloader application
+V5.13 CIA402 3: change define "CIA402_DEVICE" to "CiA402_SAMPLE_APPLICATION"
+V5.13 CIA402 4: decouple CIA402 state machine and application from ESM (according ETG.6010, clause 4)
+V5.13 ECAT1: handle Sync mapped to AL Event
+V5.13 ECAT2: explicit device ID handling, the ID value shall only be latched on the rising edge of 0x120.5
+V5.13 ECAT3: reset local Error flag in case of two consecutive pending state response and the the first failes
+V5.13 ESM1: local error handling update, ECAT_StateChange triggers only transitions from Op->Any or reject/accept a pending transition
+V5.13 ESM2: support ErrorSafeOP to OP transition
+V5.13 ESM3: Safe-to-OP transition in DC mode, ack OP state if no error was detected
+V5.13 ESM4: implement disable sync error reaction 0x10F1.2 is set to 0
+V5.13 MBX1: change mbx_read flag handling to SM1 buffer state handling (required in case of a mbx read frame with an invalid CRC, the read flag would be set but the SM bufer is still locked)
+ Changes to version V5.11:
+V5.12 BOOT1: add a bootloader sample application (only the ESM and FoE is supported)
+V5.12 ECAT1: update SM Parameter measurement (based on the system time), enhancement for input only devices and no mailbox support, use only 16Bit pointer in process data length caluclation
+V5.12 ECAT4: update Sync1 watchdog calculation (in case of subordinated cycles take one addiitonal Sync0 cycle into account )
+V5.12 ECAT5: update Sync error counter/flag handling,check enum memory alignment depending on the processor,in case of a polled timer disable ESC interrupts during DC_CheckWatchdog
+V5.12 ECAT7: set error single flash also in case of an application error
+V5.12 ESM1: overwrite the current error in case of a local error with a lower target state,Do not overwrite the current AL Status in case of an local error
+V5.12 ESM2: enable the PD SM in case of a clear error transition
+V5.12 ESM3: set internal ESM timeout to -10% of the configured value (to return an errorcode before the master will run into an timeout)
+V5.12 ESM4: enable the AL Event mask in case of pending ESM transition
+V5.12 TEST2: add pending ESM test,trigger complete ESM transition from ecat main
+ Changes to version V5.10:
+V5.11 COE3: change 0x10F3.2 (Sync Error limit) from UINT32 to UINT16 (according to the ETG.1020)
+V5.11 DIAG4: change parameter handling in DIAG_CreateNewMessage()
+V5.11 ECAT10: change PROTO handling to prevent compiler errors
+V5.11 ECAT4: enhance SM/Sync monitoring for input/output only slaves
+V5.11 ECAT5: "Add missing ""bEscIntEnabled"" initialization if ""AL_EVENT_ENBALED"" is 0"""
+V5.11 ECAT7: add missing big endian swapping
+V5.11 ESC1: update max address calculation
+V5.11 ESM1: update calculation of subordinated cycles
+V5.11 ESM2: DC_SUPPORTED, Sync0 is not supported and Sync0 is generated according register values the state transition to SafeOP shall be rejected
+V5.11 ESM3: update checking of the user configured sync type
+V5.11 ESM4: prevent to go from ErrSafeOP to OP without re enabling Sync0/1
+V5.11 ESM5: DPRAM range was double checked
+V5.11 ESM6: in the SO transition wait by default until the master has send process data
+V5.11 HW1: "move hardware independent functions ""HW_DisableSyncManChannel()"", ""HW_EnableSyncManChannel()"", ""HW_GetSyncMan()"", ""HW_ResetALEventMask()"", ""HW_SetALEventMask()"" to ecatalv.c"
+V5.11 HW2: check during ESM handling if the SM address and length is aligned according the ESC access
+V5.11 TEST9: "add behaviour 0x2020.7 (SDO requests on 0x3006.0 are set to pending until an FoE read request on ""UnlockSdoResp"" is received or in case that no mbx queue is supported when a new mbx request was received)"
+ Changes to version V5.01:
+V5.10 COE1: Define one entry description for all 0x1C3x objects and change data type of SI11,12,13 to UINT16 (according ETG.1020)
+V5.10 DIAG1: Define diagmessage textIDs
+V5.10 ECAT13: Update Synchronisation handling (FreeRun,SM Sync, Sync0, Sync1)
+ Compare DC UINT configuration (by ESC Config data) vs. DC activation register settings
+ Update 0x1C3x entries
+V5.10 ESC2: Check if defined SM settings do not exceed the available DPRAM range (in error case AL Status 0x14 is returned)
+V5.10 ESC3: Handle DC cControl register values in case of 32Bit ESC access (a Sync activation mask need to defined/used)
+V5.10 ESC4: Mask lower 4 Bit of AL status to get Run led value
+ Invalid RunLed code was calculated if ESC set ECAT Run Led
+V5.10 ESC5: Add missing swapping
+V5.10 ESM2: Update "bApplEsmPending" flag during a transition to a lower state
+V5.10 ESM3: Add "volatile" directive for ESM dummy variables
+V5.10 HW5: Block ESC interrupts during Timer ISR
+V5.10 TEST9: Add option to prevent SM3 unlock during PS
+ Changes to version V5.0:
+V5.01 APPL3: Include library demo application
+V5.01 ESC2: Add missed value swapping
+V5.01 ESM1: Don't overwrite the error reason in case of an failed PS transition
+V5.01 ESM2: Don't check the "appl trigger" flag in case on an regular transition to a lower state (OS, SP, PI).
+V5.01 ESM3: Call Error acknowledge indication only if error was acknowledged by the master
+V5.01 HW3: Update blink code of an SM watchdog error
+ Changes to version V4.42:
+V5.0 ECAT1: Support Explicit Device ID.
+V5.0 ECAT2: Application specific functions are moved to application files.
+V5.0 ECAT3: Global dummy variables used for dummy ESC operations.
+V5.0 ESC1: ESC 32Bit Access added.
+V5.0 ESC2: Support ESC EtherCAT LED Indication.
+V5.0 ESC3: Support EEPROM Emulation.
+V5.0 ESM1: Update "LocalErrorFlag" handling.
+V5.0 ESM2: Update Error Acknowledge by ALControl INIT (without error acknowledge)
+V5.0 ESM3: Handle pending ESM transition
+V5.0 ESM4: ECAT_StateChange() will only be called form application. In case of an communication error AL_ControlInd is called.
+V5.0 MBX1: Support configuration without mailbox protocol support.
+V5.0 TEST1: Add test application. See Application Note ET9300 for more details.
+ Changes to version V4.40:
+V4.42 ESM1: Reset local error flag if master set the acknowledge bit (0x120.4)
+ Changes to version V4.30:
+V4.40 ESM5: Enable output SyncManager if local error acknowledged
+V4.40 HW0: Use common hardware access functions
+V4.40 PDO3: Add support if only input process data is used
+V4.40 ECAT4: Add read SM activation register to acknowledge SM Change event
+V4.40 PDO2: Check if max process data size was exceed
+V4.40 DIAG1: add diagnosis message support
+V4.40 ESM4: Change Check WD setup; add define OP_PD_REQUIRED (defines if process data required in state change to OP)
+V4.40 WD1: change WD behaviour depending if process data required in OP state
+V4.40 MBX4: Change processing order of mailbox SyncManager flags
+V4.40 ECAT1: Merge content of HW_Main (spihw.c /mcihw.c) to ECAT_Main
+V4.40 ECAT2: Added CheckIfLocalError() to check local flags and set ALStatus /Al Status code if required. This function is called cyclic from MainLoop.
+V4.40 ESM2: Add AL_ControlRes() to complete pending state requests. Change SafeOP to OP state response
+V4.40 ESM1: Prevent double call of StopOutputHandler()
+V4.40 BOOT1: Enable Mailbox SyncManger on state change to BOOT state (to enable FoE)
+V4.40 ESM3: Change State machine behaviour according to ETG.1000 V1.0.2 (state change #26)
+V4.40 LED1: Set error blink code
+V4.40 TIMER1: Added DC_CheckWatchdog() triggered from ECAT_CheckTimer(). Change local Sync0 watchdog variables. Change bus cycle calculation
+V4.40 WD1: Change check process data watchdog settings
+ Changes to version V4.20:
+V4.30 OBJ 3: initialize the object dictionary in state change INIT->PREOP; clear object dictionary in state change PREOP->INIT
+V4.30 SYNC: add 0x1C32:10; 0x1C33:10 (Sync0 cycle), change synchronisation control functionality
+V4.30 CiA402: add CiA402_Init() call in state change from PREOP to SAFEOP if DC synchronisation is enabled,
+ else the Init function is called when bus cycle time is calculated [CalcSMCycleTime() ].
+ trigger error handling if the EtherCAT state machine gets a transition from OP to an "lower" state
+V4.20 ECAT 1: add LEGACY_MODE behaviour in ECAT_CheckWatchdog()
+V4.20 DC 1: Add DC pending state machine handling and Dc watchdog functionality
+V4.20 ESM 2: Add State transition from BOOT to INIT
+V4.20 ESM 1: Non LEGACY_MODE State change handling
+V4.11 Renamed the function parameter "code" of Function "SendSmFailedEmergency() to avoid
+problems with some compilers"
+V4.11 ECAT 1: Fixed a possible problem with state change Init -> SafeOP. The output syncmanager
+was enabled by the state change-flag and not by the actual state
+V4.11 LED 1: Clear the error LED during error acknowledgement
+V4.11 ESC 1: fixed size of MBXHEADER in the TFOEMBX struct
+ Changes to version V4.08:
+V4.10 ECAT 1: clear bEcatOutputsReceived in startMailboxhandler()
+V4.10 ECAT 2: clear bEcatOutputsReceived in stopMailboxhandler()
+V4.10 ECAT 3: when switching from INIT to BOOT the SM settings shall be checked
+V4.10 ECAT 4: APPL_StartInputHandler shall always be called and bEcatInputUpdateRunning shall always be set
+ in StartInputHandler independent of the input size
+V4.10 ECAT 5: AL_ControlInd: the error acknowledge behaviour was changed
+ according to the protocol enhancements and the conformance test
+V4.10 ECAT 6: AL_ControlInd: if a state transitions failed the corresponding stop function is
+ called to get a consistent set of variables
+V4.10 ECAT 7: the local application requested to leave the state OP so we have to disable the SM2
+ and make the state change from OP to SAFEOP by calling StopOutputHandler
+V4.10 ECAT 8: the AL Status Code has to be reset if the error was acknowledged by the master
+V4.10 ECAT 9: ECAT_StateChange: when waiting for a State Change response from the application the
+ AL Status shall only be written if the final state was reached
+ Changes to version V4.07:
+V4.08 ECAT 1: The watchdog value was not rounded up
+V4.08 ECAT 2: The value of u16WdValue was not set 0 if the register 0x420 is 0
+V4.08 ECAT 3: The AlStatusCode is changed as parameter of the function AL_ControlInd
+V4.08 ECAT 4: In a state transition OP2PREOP, SAFEOP2INIT or OP2INIT is requested,
+ this was not working correctly if one of the application functions
+ APPL_StopInputHandler or APPL_StopOutputHandler were returning NOERROR_INWORK
+ (because only the first state transition was made in that case)
+V4.08 AOE 1: AoE was added
+ Changes to version V4.06:
+V4.07 ECAT 1: The sources for SPI and MCI were merged (in ecat_def.h
+ set the switch MCI_HW to 1 when using the MCI,
+ set the switch SPI_HW to 1 when using the SPI
+ Changes to version V4.00:
+V4.01 ECAT 1: The Output sync Manager was not disabled when the state OP was left
+ by a local request (watchdog or io error)
+V4.01 ECAT 2: APPL_StopOutputHandler returns an UINT16
+V4.01 ECAT 3: TwinCAT compatibility mode: The state transition to OP is allowed when the
+ WD-Trigger-Bit of the SM2-Control-Byte (0x814.6) is FALSE, in that case the
+ watchdog will not be started before the outputs were received the first time
+V4.01 ECAT 4: "else" was too much
+ Changes to version V3.20:
+V4.00 ECAT 1: The handling of the Sync Manager Parameter was included according to
+ the EtherCAT Guidelines and Protocol Enhancements Specification
+V4.00 ECAT 2: The output sync manager is initialized during the state transition
+ from PREOP to SAFEOP that the master can check if the slave could update
+ inputs and outputs before switching the slave to OP
+ behaviour according to the EtherCAT Guidelines and Protocol Enhancements Specification
+V4.00 ECAT 3: The watchdog will be enabled in SAFE-OP that it can be checked if the last SM event
+ was received during the watchdog time before switching to OP
+V4.00 ECAT 4: The function CheckSmChannelParameters is included in the function
+ CheckSmSettings to get a better overview
+V4.00 ECAT 5: In synchronous mode the slave should support 1- and 3-buffer mode, 3-buffer mode
+ should be the standard setting, because the controlling if the process data was updated
+ should be done with the TxPDO Toggle, but the 1-buffer mode should be setable too,
+ that the master could easily check if all slaves are synchronous by checking the
+ the working counter (if the outputs were not read or the inputs were not written
+ the ESC of the slave would not increment the working counter with expected value
+ if the 1-buffer mode is running)
+V4.00 ECAT 6: The function ECAT_StateChange was added, which the application should call if a local error
+ is detected (with the parameters alStatus = STATE_SAFEOP, alStatusCode = error code (> 0x1000))
+ or gone (with the parameters alStatus = STATE_OP, alStatusCode = 0)
+ or if one of the functions APPL_StartMailboxHandler, APPL_StopMailboxHandler, APPL_StartInputHandler,
+ APPL_StopInputHandler, APPL_StartOutputHandler, APPL_StopOutputHandler has returned NOERROR_INWORK
+ to acknowledge the last state transition (with the parameters alStatus = new AL-Status, alStatusCode =
+ new AL-Status-Code)
+V4.00 ECAT 7: The return values for the AL-StatusCode were changed to UINT16
+*/
+
+/*-----------------------------------------------------------------------------------------
+------
+------ Includes
+------
+-----------------------------------------------------------------------------------------*/
+
+#define _ECATSLV_ 1
+#include "ecatslv.h"
+#undef _ECATSLV_
+/*remove definition of _ECATSLV_ (#ifdef is used in ecatslv.h)*/
+
+#include "ecatappl.h"
+
+
+/*ET9300 Project Handler :(#if BOOTSTRAPMODE_SUPPORTED) lines 209 to 211 deleted*/
+
+
+/*ET9300 Project Handler :(#if DIAGNOSIS_SUPPORTED) lines 214 to 216 deleted*/
+
+#include "mailbox.h"
+
+#include "ecatcoe.h"
+#include "objdef.h"
+
+/*ET9300 Project Handler :(#if EMERGENCY_SUPPORTED) lines 227 to 229 deleted*/
+
+/*ET9300 Project Handler :(#if AOE_SUPPORTED) lines 231 to 233 deleted*/
+
+/*ECATCHANGE_START(V5.13) CIA402 3*/
+/*ET9300 Project Handler :(#if CiA402_SAMPLE_APPLICATION #elif TEST_APPLICATION #elif EL9800_APPLICATION #elif SAMPLE_APPLICATION_INTERFACE #elif SAMPLE_APPLICATION #elif BOOTLOADER_SAMPLE) lines 236 to 249 deleted*/
+
+
+/*--------------------------------------------------------------------------------------
+------
+------ local Types and Defines
+------
+--------------------------------------------------------------------------------------*/
+
+
+/*-----------------------------------------------------------------------------------------
+------
+------ local variables and constants
+------
+-----------------------------------------------------------------------------------------*/
+UINT16 u16ALEventMask; // Value which will be written to the 0x204 register (AL event mask) during the state transition PreOP to SafeOP
+/*ET9300 Project Handler :(#if EXPLICIT_DEVICE_ID) lines 267 to 271 deleted*/
+
+/*Dummy variable to trigger read or writes events in the ESC*/
+/*ET9300 Project Handler :(#if ESC_32BIT_ACCESS #elif ESC_16BIT_ACCESS) lines 274 to 278 deleted*/
+ VARVOLATILE UINT8 u8dummy;
+
+/*ET9300 Project Handler :(#if !COE_SUPPORTED) lines 282 to 288 deleted*/
+
+/*ET9300 Project Handler :(#if ESC_32BIT_ACCESS #elif ESC_16BIT_ACCESS) lines 290 to 294 deleted*/
+ VARVOLATILE UINT8 SMActivate = 0;
+
+TSYNCMAN SyncManInfo;
+
+//indicates if the EEPORM was loaded correct
+BOOL EepromLoaded = FALSE;
+
+
+/*-----------------------------------------------------------------------------------------
+------
+------ local functions
+------
+-----------------------------------------------------------------------------------------*/
+/*ECATCHANGE_START(V5.13) ECAT1*/
+/*ECATCHANGE_END(V5.13) ECAT1*/
+void ResetALEventMask(UINT16 intMask);
+
+/////////////////////////////////////////////////////////////////////////////////////////
+/**
+ \param intMask interrupt mask (disabled interrupt shall be zero)
+
+ \brief This function makes an logical and with the AL Event Mask register (0x204)
+*////////////////////////////////////////////////////////////////////////////////////////
+void ResetALEventMask(UINT16 intMask)
+{
+/*ET9300 Project Handler :(#if ESC_32BIT_ACCESS) lines 322 to 330 deleted*/
+ UINT16 mask;
+ HW_EscReadWord(mask, ESC_AL_EVENTMASK_OFFSET);
+
+/*ET9300 Project Handler :(#if BIG_ENDIAN_FORMAT) lines 334 to 336 deleted*/
+ mask &= intMask;
+
+
+ DISABLE_ESC_INT();
+
+/*ET9300 Project Handler :(#if ESC_32BIT_ACCESS) lines 345 to 350 deleted*/
+
+/*ET9300 Project Handler :(#if BIG_ENDIAN_FORMAT) lines 352 to 354 deleted*/
+ HW_EscWriteWord(mask, ESC_AL_EVENTMASK_OFFSET);
+ ENABLE_ESC_INT();
+}
+
+/////////////////////////////////////////////////////////////////////////////////////////
+/**
+ \param intMask interrupt mask (enabled interrupt shall be one)
+
+ \brief This function makes an logical or with the AL Event Mask register (0x204)
+*////////////////////////////////////////////////////////////////////////////////////////
+void SetALEventMask(UINT16 intMask)
+{
+/*ET9300 Project Handler :(#if ESC_32BIT_ACCESS) lines 368 to 376 deleted*/
+ UINT16 mask;
+ HW_EscReadWord(mask, ESC_AL_EVENTMASK_OFFSET);
+
+
+/*ET9300 Project Handler :(#if BIG_ENDIAN_FORMAT) lines 381 to 383 deleted*/
+ mask |= intMask;
+
+ DISABLE_ESC_INT();
+
+/*ET9300 Project Handler :(#if ESC_32BIT_ACCESS) lines 391 to 396 deleted*/
+
+/*ET9300 Project Handler :(#if BIG_ENDIAN_FORMAT) lines 398 to 400 deleted*/
+ HW_EscWriteWord(mask, ESC_AL_EVENTMASK_OFFSET);
+ ENABLE_ESC_INT();
+}
+
+
+/////////////////////////////////////////////////////////////////////////////////////////
+/**
+
+\brief This function reads the EEPROM loaded state
+*////////////////////////////////////////////////////////////////////////////////////////
+void UpdateEEPROMLoadedState(void)
+{
+/*ET9300 Project Handler :(#if ESC_32BIT_ACCESS) lines 415 to 420 deleted*/
+ UINT16 TmpVar = 0;
+ //read EEPROM loaded information
+ HW_EscReadWord(TmpVar, ESC_EEPROM_CONTROL_OFFSET);
+ TmpVar = SWAPWORD(TmpVar);
+
+
+ if (((TmpVar & ESC_EEPROM_ERROR_CRC) > 0)
+ || ((TmpVar & ESC_EEPROM_ERROR_LOAD) > 0))
+ {
+ EepromLoaded = FALSE;
+ }
+ else
+ {
+ EepromLoaded = TRUE;
+ }
+}
+
+
+/*-----------------------------------------------------------------------------------------
+------
+------ functions
+------
+-----------------------------------------------------------------------------------------*/
+
+
+/////////////////////////////////////////////////////////////////////////////////////////
+/**
+ \param channel Sync Manager channel
+
+ \return pPdSyncMan Pointer to the settings of requested SYNC Manager channel
+
+ \brief This function is called to read the SYNC Manager channel descriptions of the
+ process data SYNC Managers.
+*////////////////////////////////////////////////////////////////////////////////////////
+
+TSYNCMAN ESCMEM * GetSyncMan( UINT8 channel )
+{
+ HW_EscRead((MEM_ADDR *)&SyncManInfo, ESC_SYNCMAN_REG_OFFSET + (channel * SIZEOF_SM_REGISTER), SIZEOF_SM_REGISTER );
+
+
+/*ET9300 Project Handler :(#if BIG_ENDIAN_FORMAT) lines 462 to 474 deleted*/
+
+ return &SyncManInfo;
+}
+
+/////////////////////////////////////////////////////////////////////////////////////////
+/**
+ \param channel Sync Manager channel
+
+ \brief This function disables a Sync Manager channel
+*////////////////////////////////////////////////////////////////////////////////////////
+void DisableSyncManChannel(UINT8 channel)
+{
+ UINT16 Offset;
+/*ET9300 Project Handler :(#if ESC_32BIT_ACCESS #elif ESC_16BIT_ACCESS) lines 488 to 526 deleted*/
+ VARVOLATILE UINT8 smStatus = SM_SETTING_PDI_DISABLE;
+ Offset = (ESC_SM_PDICONTROL_OFFSET + (SIZEOF_SM_REGISTER*channel));
+
+ HW_EscWriteByte(smStatus,Offset);
+
+ /*wait until SyncManager is disabled*/
+ do
+ {
+ HW_EscReadByte(smStatus, Offset);
+ }while(!(smStatus & SM_SETTING_PDI_DISABLE));
+}
+
+/////////////////////////////////////////////////////////////////////////////////////////
+/**
+ \param channel Sync Manager channel
+
+ \brief This function enables a Sync Manager channel
+*////////////////////////////////////////////////////////////////////////////////////////
+void EnableSyncManChannel(UINT8 channel)
+{
+ UINT16 Offset;
+/*ET9300 Project Handler :(#if ESC_32BIT_ACCESS #elif ESC_16BIT_ACCESS) lines 549 to 589 deleted*/
+ VARVOLATILE UINT8 smStatus = 0x00;
+ Offset = (ESC_SM_PDICONTROL_OFFSET + (SIZEOF_SM_REGISTER*channel));
+
+ HW_EscWriteByte(smStatus,Offset);
+
+ /*wait until SyncManager is enabled*/
+ do
+ {
+ HW_EscReadByte(smStatus,Offset);
+ }while((smStatus & SM_SETTING_PDI_DISABLE));
+}
+
+/*ET9300 Project Handler :(#if DIAGNOSIS_SUPPORTED) lines 603 to 661 deleted*/
+
+/*ET9300 Project Handler :(#if EMERGENCY_SUPPORTED && (COE_SUPPORTED || SOE_SUPPORTED)) lines 663 to 820 deleted*/
+
+/////////////////////////////////////////////////////////////////////////////////////////
+/**
+ \param maxChannel last SM channel which should be checked
+
+ \return 0: okay else AL Status Code
+
+ \brief This function checks all SM channels
+
+*////////////////////////////////////////////////////////////////////////////////////////
+
+UINT8 CheckSmSettings(UINT8 maxChannel)
+{
+ UINT8 i;
+ UINT8 result = 0;
+ TSYNCMAN ESCMEM *pSyncMan;
+ UINT16 SMLength = 0;
+ UINT16 SMAddress = 0;
+
+
+ //Check if max address defines are within the available ESC address range
+ if ((nMaxEscAddress < MAX_PD_WRITE_ADDRESS)
+ || (nMaxEscAddress < MAX_PD_READ_ADDRESS)
+ || (nMaxEscAddress < MAX_MBX_WRITE_ADDRESS)
+ || (nMaxEscAddress < MAX_MBX_READ_ADDRESS))
+ {
+ /*The defines for maximum SM addresses are invalid for the used ESC (change the defines in the file ecat_def.h or the SSC Tool)
+ It may be also required to adapt the SM settings in the ESI file*/
+
+
+ return ALSTATUSCODE_NOVALIDFIRMWARE;
+ }
+
+ /* check the Sync Manager Parameter for the Receive Mailbox (Sync Manager Channel 0) */
+ pSyncMan = GetSyncMan(MAILBOX_WRITE);
+
+/*ET9300 Project Handler :(#if ESC_32BIT_ACCESS) lines 858 to 874 deleted*/
+ SMLength = pSyncMan->Length;
+ SMAddress = pSyncMan->PhysicalStartAddress;
+
+/*ET9300 Project Handler :(#if CHECK_SM_PARAM_ALIGNMENT) lines 878 to 891 deleted*/
+
+
+ if (!(pSyncMan->Settings[SM_SETTING_ACTIVATE_OFFSET] & SM_SETTING_ENABLE_VALUE))
+ {
+ /* receive mailbox is not enabled */
+ result = ALSTATUSCODE_INVALIDMBXCFGINPREOP;
+ }
+ else if ((pSyncMan->Settings[SM_SETTING_CONTROL_OFFSET] & SM_SETTING_DIRECTION_MASK) != SM_SETTING_DIRECTION_WRITE_VALUE)
+ {
+ /* receive mailbox is not writable by the master*/
+ result = ALSTATUSCODE_INVALIDMBXCFGINPREOP;
+ }
+ else if ((pSyncMan->Settings[SM_SETTING_CONTROL_OFFSET] & SM_SETTING_MODE_MASK) != SM_SETTING_MODE_ONE_BUFFER_VALUE)
+ {
+ /* receive mailbox is not in one buffer mode */
+ result = ALSTATUSCODE_INVALIDMBXCFGINPREOP;
+ }
+ else if (SMLength < MIN_MBX_SIZE)
+ {
+ /* receive mailbox size is too small */
+ result = ALSTATUSCODE_INVALIDMBXCFGINPREOP;
+ }
+ else if (SMLength > MAX_MBX_SIZE)
+ {
+ /* receive mailbox size is too great */
+ result = ALSTATUSCODE_INVALIDMBXCFGINPREOP;
+ }
+ else if (SMAddress < MIN_MBX_WRITE_ADDRESS)
+ {
+ /* receive mailbox address is too small */
+ result = ALSTATUSCODE_INVALIDMBXCFGINPREOP;
+ }
+ else if (SMAddress > MAX_MBX_WRITE_ADDRESS)
+ {
+ /* receive mailbox address is too great */
+ result = ALSTATUSCODE_INVALIDMBXCFGINPREOP;
+ }
+
+/*ET9300 Project Handler :(#if TEST_APPLICATION && COE_SUPPORTED) lines 931 to 937 deleted*/
+
+ if ( result == 0 )
+ {
+ /* check the Sync Manager Parameter for the Send Mailbox (Sync Manager Channel 1) */
+ pSyncMan = GetSyncMan(MAILBOX_READ);
+
+/*ET9300 Project Handler :(#if ESC_32BIT_ACCESS) lines 944 to 960 deleted*/
+ SMLength = pSyncMan->Length;
+ SMAddress = pSyncMan->PhysicalStartAddress;
+
+/*ET9300 Project Handler :(#if CHECK_SM_PARAM_ALIGNMENT) lines 964 to 977 deleted*/
+
+ if (!(pSyncMan->Settings[SM_SETTING_ACTIVATE_OFFSET] & SM_SETTING_ENABLE_VALUE))
+ {
+ /* send mailbox is not enabled */
+ result = ALSTATUSCODE_INVALIDMBXCFGINPREOP;
+ }
+ else if ((pSyncMan->Settings[SM_SETTING_CONTROL_OFFSET] & SM_SETTING_DIRECTION_MASK) != SM_SETTING_DIRECTION_READ_VALUE)
+ {
+ /* receive mailbox is not readable by the master*/
+ result = ALSTATUSCODE_INVALIDMBXCFGINPREOP;
+ }
+ else if ((pSyncMan->Settings[SM_SETTING_CONTROL_OFFSET] & SM_SETTING_MODE_MASK) != SM_SETTING_MODE_ONE_BUFFER_VALUE)
+ {
+ /* receive mailbox is not in one buffer mode */
+ result = ALSTATUSCODE_INVALIDMBXCFGINPREOP;
+ }
+ else if (SMLength < MIN_MBX_SIZE)
+ {
+ /* send mailbox size is too small */
+ result = ALSTATUSCODE_INVALIDMBXCFGINPREOP;
+ }
+ else if (SMLength > MAX_MBX_SIZE)
+ {
+ /* send mailbox size is too great */
+ result = ALSTATUSCODE_INVALIDMBXCFGINPREOP;
+ }
+ else if (SMAddress < MIN_MBX_READ_ADDRESS)
+ {
+ /* send mailbox address is too small */
+ result = ALSTATUSCODE_INVALIDMBXCFGINPREOP;
+ }
+ else if (SMAddress > MAX_MBX_READ_ADDRESS)
+ {
+ /* send mailbox address is too great */
+ result = ALSTATUSCODE_INVALIDMBXCFGINPREOP;
+ }
+ }
+
+ if ( result == 0 && maxChannel > PROCESS_DATA_IN )
+ {
+ /* b3BufferMode is only set, if inputs and outputs are running in 3-Buffer-Mode when leaving this function */
+ b3BufferMode = TRUE;
+ /* check the Sync Manager Parameter for the Inputs (Sync Manager Channel 2 (0 in case if no mailbox is supported)) */
+ pSyncMan = GetSyncMan(PROCESS_DATA_IN);
+
+/*ET9300 Project Handler :(#if ESC_32BIT_ACCESS) lines 1025 to 1041 deleted*/
+ SMLength = pSyncMan->Length;
+ SMAddress = pSyncMan->PhysicalStartAddress;
+
+/*ET9300 Project Handler :(#if CHECK_SM_PARAM_ALIGNMENT) lines 1045 to 1058 deleted*/
+
+
+ if ((pSyncMan->Settings[SM_SETTING_ACTIVATE_OFFSET] & SM_SETTING_ENABLE_VALUE) != 0 && SMLength == 0)
+ {
+ /* the SM3 size is 0 and the SM3 is active */
+ result = SYNCMANCHSETTINGS + 1;
+ }
+ else if (pSyncMan->Settings[SM_SETTING_ACTIVATE_OFFSET] & SM_SETTING_ENABLE_VALUE)
+ {
+ /* Sync Manager Channel 3 is active, input size has to greater 0 */
+ if (SMLength != nPdInputSize || nPdInputSize == 0 || SMLength > MAX_PD_INPUT_SIZE)
+ {
+ /* sizes don't match */
+ result = SYNCMANCHSIZE + 1;
+ }
+ else
+ {
+ /* sizes matches */
+ if ((pSyncMan->Settings[SM_SETTING_CONTROL_OFFSET] & SM_SETTING_DIRECTION_MASK) == SM_SETTING_DIRECTION_READ_VALUE)
+ {
+ /* settings match */
+ if (((nAlStatus == STATE_PREOP) && (SMAddress >= MIN_PD_READ_ADDRESS) && (SMAddress <= MAX_PD_READ_ADDRESS))
+ || ((nAlStatus != STATE_PREOP) && (SMAddress == nEscAddrInputData))
+ )
+ {
+ /* addresses match */
+
+ if ((pSyncMan->Settings[SM_SETTING_CONTROL_OFFSET] & SM_SETTING_MODE_MASK) == SM_SETTING_MODE_ONE_BUFFER_VALUE)
+ {
+ /* inputs are running in 1-Buffer-Mode, reset flag b3BufferMode */
+ b3BufferMode = FALSE;
+ }
+ }
+ else
+ {
+ /* input address is out of the allowed area or has changed in SAFEOP or OP */
+ result = SYNCMANCHADDRESS + 1;
+ }
+ }
+ else
+ {
+ /* input settings do not match */
+ result = SYNCMANCHSETTINGS + 1;
+ }
+ }
+ }
+ else if (SMLength != 0 || nPdInputSize != 0)
+ {
+ /* input size is not zero although the SM3 channel is not enabled */
+ result = SYNCMANCHSIZE + 1;
+ }
+
+/*ET9300 Project Handler :(#if TEST_APPLICATION && COE_SUPPORTED) lines 1113 to 1119 deleted*/
+
+/*ET9300 Project Handler :(#if MAX_PD_INPUT_SIZE > 0 #else) lines 1121 to 1127 deleted*/
+
+ if ( result != 0 )
+ {
+/*ET9300 Project Handler :(#if DIAGNOSIS_SUPPORTED #elif EMERGENCY_SUPPORTED && (COE_SUPPORTED || SOE_SUPPORTED)) lines 1131 to 1136 deleted*/
+ result = ALSTATUSCODE_INVALIDSMINCFG;
+ }
+ }
+
+
+// else
+ if (result == 0 && maxChannel > PROCESS_DATA_OUT)
+ {
+/*ET9300 Project Handler :(#if MAX_PD_INPUT_SIZE == 0) lines 1145 to 1148 deleted*/
+ /* check the Sync Manager Parameter for the Outputs (Sync Manager Channel 2) */
+ pSyncMan = GetSyncMan(PROCESS_DATA_OUT);
+
+/*ET9300 Project Handler :(#if ESC_32BIT_ACCESS) lines 1152 to 1168 deleted*/
+ SMLength = pSyncMan->Length;
+ SMAddress = pSyncMan->PhysicalStartAddress;
+
+/*ET9300 Project Handler :(#if CHECK_SM_PARAM_ALIGNMENT) lines 1172 to 1185 deleted*/
+
+
+ if ((pSyncMan->Settings[SM_SETTING_ACTIVATE_OFFSET] & SM_SETTING_ENABLE_VALUE) != 0 && SMLength == 0)
+ {
+ /* the SM2 size is 0 and the SM2 is active */
+ result = SYNCMANCHSETTINGS + 1;
+ }
+ else if (pSyncMan->Settings[SM_SETTING_ACTIVATE_OFFSET] & SM_SETTING_ENABLE_VALUE)
+ {
+ /* Sync Manager Channel 2 is active, output size has to greater 0 */
+ if ( SMLength == nPdOutputSize && nPdOutputSize != 0 && SMLength <= ((UINT16)MAX_PD_OUTPUT_SIZE))
+ {
+ /* sizes match */
+ if ( (pSyncMan->Settings[SM_SETTING_CONTROL_OFFSET] & SM_SETTING_DIRECTION_MASK) == SM_SETTING_DIRECTION_WRITE_VALUE )
+ {
+ /* settings match */
+ if ( ( ( nAlStatus == STATE_PREOP )&&( SMAddress >= MIN_PD_WRITE_ADDRESS )&&( SMAddress <= MAX_PD_WRITE_ADDRESS ) )
+ ||( ( nAlStatus != STATE_PREOP )&&( SMAddress == nEscAddrOutputData ) )
+ )
+ {
+ /* addresses match */
+ {
+ /* check, if watchdog trigger is enabled */
+ if (pSyncMan->Settings[SM_SETTING_CONTROL_OFFSET] & SM_SETTING_WATCHDOG_VALUE)
+ {
+ bWdTrigger = TRUE;
+ }
+ else
+ {
+ bWdTrigger = FALSE;
+ }
+
+ if ((pSyncMan->Settings[SM_SETTING_CONTROL_OFFSET] & SM_SETTING_MODE_MASK) == SM_SETTING_MODE_ONE_BUFFER_VALUE)
+ {
+ /* outputs are running in 1-Buffer-Mode, reset flag b3BufferMode */
+ b3BufferMode = FALSE;
+ }
+ }
+ }
+ else
+ {
+ /* output address is out of the allowed area or has changed in SAFEOP or OP */
+ result = SYNCMANCHADDRESS + 1;
+ }
+ }
+ else
+ {
+ /* output settings do not match */
+ result = SYNCMANCHSETTINGS + 1;
+ }
+ }
+ else
+ {
+ /* output sizes don't match */
+ result = SYNCMANCHSIZE + 1;
+ }
+ }
+ else if (SMLength != 0 || nPdOutputSize != 0)
+ {
+ /* output size is not zero although the SM2 channel is not enabled */
+ result = SYNCMANCHSIZE + 1;
+ }
+/*ET9300 Project Handler :(#if MAX_PD_OUTPUT_SIZE > 0 #else) lines 1250 to 1256 deleted*/
+
+/*ET9300 Project Handler :(#if TEST_APPLICATION && COE_SUPPORTED) lines 1258 to 1265 deleted*/
+ if ( result != 0 )
+ {
+/*ET9300 Project Handler :(#if DIAGNOSIS_SUPPORTED #elif EMERGENCY_SUPPORTED && (COE_SUPPORTED || SOE_SUPPORTED)) lines 1268 to 1273 deleted*/
+ result = ALSTATUSCODE_INVALIDSMOUTCFG;
+ }
+ }
+
+
+ if ( result == 0 )
+ {
+ /* the Enable-Byte of the rest of the SM channels has to be read to acknowledge the SM-Change-Interrupt */
+ for (i = maxChannel; i < nMaxSyncMan; i++)
+ {
+ pSyncMan = GetSyncMan(i);
+/*ET9300 Project Handler :(#if ESC_32BIT_ACCESS) lines 1285 to 1287 deleted*/
+ SMActivate = pSyncMan->Settings[SM_SETTING_ACTIVATE_OFFSET];
+ }
+ }
+ return result;
+}
+
+/////////////////////////////////////////////////////////////////////////////////////////
+/**
+ \return AL Status Code (see ecatslv.h ALSTATUSCODE_....)
+
+ \brief This function is called in case of the state transition from PREOP to SAFEOP.
+ |brief the areas of the Sync Managers will be checked for overlapping,
+ \brief the synchronization mode (Free Run, Synchron, Distributed Clocks) is selected,
+ \brief the requested cycle time will be checked, the watchdog is started
+ \brief and the AL Event Mask register will be set
+
+*////////////////////////////////////////////////////////////////////////////////////////
+
+UINT16 StartInputHandler(void)
+{
+ TSYNCMAN ESCMEM * pSyncMan;
+
+/*ET9300 Project Handler :(#if ESC_32BIT_ACCESS #elif ESC_16BIT_ACCESS) lines 1312 to 1316 deleted*/
+ UINT8 dcControl;
+
+ UINT16 wdiv = 0;
+ UINT16 wd = 0;
+/*ET9300 Project Handler :(#if DC_SUPPORTED) lines 1324 to 1328 deleted*/
+
+ UINT16 nPdInputBuffer = 3;
+
+ UINT16 nPdOutputBuffer = 3;
+
+ UINT16 SyncType0x1C32 = 0; /* Helper variable for sync type for SM2 (required if no CoE is supported or no output process data available)*/
+ UINT16 SyncType0x1C33 = 0; /* Helper variable for sync type for SM3 (required if no CoE is supported or no input process data available)*/
+
+ UINT16 u16MinSuppSyncType = 0xFFFF; /* Minimum supported Sync Types */
+
+/*ET9300 Project Handler :(#if MAX_PD_OUTPUT_SIZE == 0 && MAX_PD_INPUT_SIZE == 0) lines 1346 to 1348 deleted*/
+ u16MinSuppSyncType &= sSyncManOutPar.u16SyncTypesSupported;
+ u16MinSuppSyncType &= sSyncManInPar.u16SyncTypesSupported;
+
+ u16ALEventMask = 0;
+
+
+ /*
+ --- Check if SyncManager areas overlapping ---
+ */
+ bEcatFirstOutputsReceived = FALSE;
+
+ /* get a pointer to the Sync Manager Channel 2 (Outputs) */
+ pSyncMan = GetSyncMan(PROCESS_DATA_OUT);
+ /* store the address of the Sync Manager Channel 2 (Outputs) */
+/*ET9300 Project Handler :(#if ESC_32BIT_ACCESS) lines 1370 to 1372 deleted*/
+ nEscAddrOutputData = pSyncMan->PhysicalStartAddress;
+ /* get the number of output buffer used for calculating the address areas */
+ if (pSyncMan->Settings[SM_SETTING_CONTROL_OFFSET] & SM_SETTING_MODE_ONE_BUFFER_VALUE)
+ {
+ nPdOutputBuffer = 1;
+ }
+
+
+ /* get a pointer to the Sync Manager Channel 3 (Inputs) */
+ pSyncMan = GetSyncMan(PROCESS_DATA_IN);
+ /* store the address of the Sync Manager Channel 3 (Inputs)*/
+/*ET9300 Project Handler :(#if ESC_32BIT_ACCESS) lines 1387 to 1389 deleted*/
+ nEscAddrInputData = pSyncMan->PhysicalStartAddress;
+
+
+ /* get the number of input buffer used for calculating the address areas */
+ if (pSyncMan->Settings[SM_SETTING_CONTROL_OFFSET] & SM_SETTING_MODE_ONE_BUFFER_VALUE)
+ {
+ nPdInputBuffer = 1;
+ }
+ /* it has be checked if the Sync Manager memory areas for Inputs and Outputs will not overlap
+ the Sync Manager memory areas for the Mailbox */
+
+ if (((nEscAddrInputData + nPdInputSize * nPdInputBuffer) > u16EscAddrSendMbx && (nEscAddrInputData < (u16EscAddrSendMbx + u16SendMbxSize)))
+ || ((nEscAddrInputData + nPdInputSize * nPdInputBuffer) > u16EscAddrReceiveMbx && (nEscAddrInputData < (u16EscAddrReceiveMbx + u16ReceiveMbxSize)))
+ )
+ {
+/*ET9300 Project Handler :(#if DIAGNOSIS_SUPPORTED #elif EMERGENCY_SUPPORTED && (COE_SUPPORTED || SOE_SUPPORTED)) lines 1407 to 1412 deleted*/
+ return ALSTATUSCODE_INVALIDSMINCFG;
+ }
+
+ if (
+ ((nEscAddrOutputData + nPdOutputSize * nPdOutputBuffer) > u16EscAddrSendMbx && (nEscAddrOutputData < (u16EscAddrSendMbx + u16SendMbxSize)))
+ ||((nEscAddrOutputData + nPdOutputSize * nPdOutputBuffer) > u16EscAddrReceiveMbx && (nEscAddrOutputData < (u16EscAddrReceiveMbx + u16ReceiveMbxSize)))
+ ||
+ ((nEscAddrOutputData + nPdOutputSize * nPdOutputBuffer) > nEscAddrInputData && (nEscAddrOutputData < (nEscAddrInputData + nPdInputSize)))
+ )
+ {
+
+ /* Sync Manager Channel 2 memory area (Outputs) overlaps the Sync Manager memory areas for the Mailbox
+ or the Sync Manager Channel 3 memory area (Inputs) */
+/*ET9300 Project Handler :(#if DIAGNOSIS_SUPPORTED #elif EMERGENCY_SUPPORTED && (COE_SUPPORTED || SOE_SUPPORTED)) lines 1435 to 1440 deleted*/
+ return ALSTATUSCODE_INVALIDSMOUTCFG;
+ }
+
+ /*
+ --- Check configured synchronization ---
+ */
+
+ /* Get the DC Control/Activation register value*/
+/*ET9300 Project Handler :(#if ESC_32BIT_ACCESS #elif ESC_16BIT_ACCESS) lines 1450 to 1459 deleted*/
+ /*Read register 0x981 (corresponding masks are adapted)*/
+ HW_EscReadByte(dcControl, ESC_DC_SYNC_ACTIVATION_OFFSET);
+
+/*ET9300 Project Handler :(#if DC_SUPPORTED) lines 1464 to 1472 deleted*/
+
+
+ SyncType0x1C32 = sSyncManOutPar.u16SyncType;
+ SyncType0x1C33 = sSyncManInPar.u16SyncType;
+
+
+
+ /* check general DC register plausibility and if configuration is supported
+ - 0x981 DC Active
+ - 0x9A0:0x9A3 Sync0 Cycle
+ - 0x9A4:0x9A7 Sync1 Cycle
+ */
+ /*DC out unit shall not be active because no DC supported*/
+ if((dcControl & (ESC_DC_SYNC_UNIT_ACTIVE_MASK | ESC_DC_SYNC_UNIT_AUTO_ACTIVE_MASK)) != 0)
+ {
+/*ET9300 Project Handler :(#if DIAGNOSIS_SUPPORTED) lines 1496 to 1498 deleted*/
+
+ return ALSTATUSCODE_DCINVALIDSYNCCFG;
+ }
+/*ET9300 Project Handler :(#if !DC_SUPPORTED #else) lines 1502 to 1579 deleted*/
+
+ /*
+ Check if the user configured Sync Type matches the DC register values (if the Sync Type is supported was already checked in the object write function)
+ */
+ if(bSyncSetByUser)
+ {
+/*ET9300 Project Handler :(#if DC_SUPPORTED) lines 1586 to 1588 deleted*/
+ {
+ /* DC out unit not enabled => no DC mode shall be set */
+ if((SyncType0x1C32 == SYNCTYPE_DCSYNC0) || (SyncType0x1C32 == SYNCTYPE_DCSYNC1)
+ ||(SyncType0x1C33 == SYNCTYPE_DCSYNC0) || (SyncType0x1C33 == SYNCTYPE_DCSYNC1))
+ {
+/*ET9300 Project Handler :(#if DIAGNOSIS_SUPPORTED) lines 1594 to 1596 deleted*/
+ return ALSTATUSCODE_DCINVALIDSYNCCFG;
+ }
+ } //if((dcControl & (ESC_DC_SYNC_UNIT_ACTIVE_MASK | ESC_DC_SYNC_UNIT_AUTO_ACTIVE_MASK)) == 0)
+/*ET9300 Project Handler :(#if DC_SUPPORTED) lines 1600 to 1602 deleted*/
+ {
+/*ET9300 Project Handler :(#if DC_SUPPORTED) lines 1604 to 1630 deleted*/
+
+/*ET9300 Project Handler :(#if !AL_EVENT_ENABLED) lines 1632 to 1654 deleted*/
+ }
+ } //if(bSyncSetByUser)
+ else
+ {
+ /* No Sync Type selected by user => Configure Sync Type based on DC register values*/
+/*ET9300 Project Handler :(#if DC_SUPPORTED) lines 1660 to 1662 deleted*/
+ {
+ /* Activation or auto activation of the Sync Out Unit is disabled => Free Run or SM Sync is configured*/
+
+ /* AL Event enabled => Configure SM Sync*/
+ if (nPdOutputSize > 0)
+ {
+ SyncType0x1C32 = SYNCTYPE_SM_SYNCHRON;
+
+ if (nPdInputSize > 0)
+ {
+ SyncType0x1C33 = SYNCTYPE_SM2_SYNCHRON;
+ }
+ else
+ {
+ SyncType0x1C33 = SYNCTYPE_FREERUN;
+ }
+ }
+ else if (nPdInputSize > 0)
+ {
+ SyncType0x1C32 = SYNCTYPE_FREERUN;
+ SyncType0x1C33 = SYNCTYPE_SM_SYNCHRON;
+ }
+ else
+ {
+ SyncType0x1C32 = SYNCTYPE_FREERUN;
+ SyncType0x1C33 = SYNCTYPE_FREERUN;
+ }
+/*ET9300 Project Handler :(#if AL_EVENT_ENABLED #else) lines 1691 to 1696 deleted*/
+
+ }
+/*ET9300 Project Handler :(#if DC_SUPPORTED) lines 1699 to 1738 deleted*/
+ }
+
+/*ET9300 Project Handler :(#if COE_SUPPORTED && DC_SUPPORTED) lines 1741 to 1767 deleted*/
+
+ /* Set global flags based on Sync Type */
+ if ( !b3BufferMode )
+ {
+ /* 1-Buffer-Mode configured => For free run it shall be 3Buffer mode*/
+ if (( SyncType0x1C32 == SYNCTYPE_FREERUN ) || ( SyncType0x1C33 == SYNCTYPE_FREERUN ))
+ {
+ return ALSTATUSCODE_FREERUNNEEDS3BUFFERMODE;
+ }
+ }
+
+ /* If no free run is supported the EscInt is always enabled*/
+ if (( SyncType0x1C32 != SYNCTYPE_FREERUN ) || ( SyncType0x1C33 != SYNCTYPE_FREERUN ))
+ {
+ /* ECAT Synchron Mode, the ESC interrupt is enabled */
+ bEscIntEnabled = TRUE;
+ }
+
+ /* Update value for AL Event Mask register (0x204) */
+ if(bEscIntEnabled)
+ {
+ if(nPdOutputSize > 0)
+ {
+ u16ALEventMask = PROCESS_OUTPUT_EVENT;
+ }
+ else if(nPdInputSize > 0)
+ {
+ u16ALEventMask = PROCESS_INPUT_EVENT;
+ }
+
+/*ET9300 Project Handler :(#elif MAX_PD_INPUT_SIZE > 0) lines 1803 to 1808 deleted*/
+ }
+
+ if ((SyncType0x1C32 == SYNCTYPE_DCSYNC0) || (SyncType0x1C32 == SYNCTYPE_DCSYNC1)
+ || (SyncType0x1C33 == SYNCTYPE_DCSYNC0) || (SyncType0x1C33 == SYNCTYPE_DCSYNC1))/* Sync to Sync0 or Sync1 is enabled*/
+ {
+ /* slave is running in DC-mode */
+ bDcSyncActive = TRUE;
+
+ /*In case of an Input only application with DC no PDI Isr handling is required*/
+ if (nPdOutputSize == 0)
+ {
+ u16ALEventMask = 0;
+ }
+ }
+
+
+
+ sSyncManOutPar.u16SyncType = SyncType0x1C32;
+ sSyncManInPar.u16SyncType = SyncType0x1C33;
+
+ /* Calculate number of Sync0 events within one SM cycle and the Sync0 events on which the inputs has to be latched*/
+/*ET9300 Project Handler :(#if DC_SUPPORTED) lines 1836 to 1893 deleted*/
+
+
+ /* reset the error counter indicating synchronization problems */
+ sCycleDiag.syncFailedCounter = 0;
+
+
+ /*
+ --- Check watchdog settings ---
+ */
+
+ /*get the watchdog time (register 0x420). if value is > 0 watchdog is active*/
+/*ET9300 Project Handler :(#if ESC_32BIT_ACCESS) lines 1909 to 1916 deleted*/
+ HW_EscReadWord(wd, ESC_PD_WD_TIME);
+ wd = SWAPWORD(wd);
+
+ if (nPdOutputSize > 0 && wd != 0 )
+ {
+ /*get watchdog divider (register 0x400)*/
+/*ET9300 Project Handler :(#if ESC_32BIT_ACCESS) lines 1924 to 1932 deleted*/
+ HW_EscReadWord(wdiv, ESC_WD_DIVIDER_OFFSET);
+ wdiv = SWAPWORD(wdiv);
+ if ( wdiv != 0 )
+ {
+ /* the ESC subtracts 2 in register 0x400 so it has to be added here */
+ UINT32 d = wdiv+2;
+
+
+ d *= wd;
+ /* store watchdog in ms in variable EcatWdValue */
+ /* watchdog value has to be rounded up */
+ d = (INT32)(d + 24999);
+ d /= 25000;
+ EcatWdValue = (UINT16) d;
+ }
+ else
+ {
+ wd = 0;
+ /* wd value has to be set to zero, if the wd is 0 */
+ EcatWdValue = 0;
+ }
+/*ET9300 Project Handler :(#if !ESC_SM_WD_SUPPORTED) lines 1955 to 1958 deleted*/
+ }
+ else
+ {
+ /* the watchdog is deactivated or slave has no output process data*/
+ wdiv = 0;
+ EcatWdValue = 0;
+ }
+
+ if((EcatWdValue == 0 && bWdTrigger) || (EcatWdValue != 0 && !bWdTrigger))
+ {
+ /* if the WD-Trigger in the Sync Manager Channel 2 Control-Byte is set (Bit 6 of Register 0x814)
+ an error has to be returned */
+ return ALSTATUSCODE_INVALIDWDCFG;
+ }
+
+ if ( bEscIntEnabled && nPdOutputSize != 0 )
+ {
+ /* ECAT synchron Mode is active, the Sync Manager Channel 2 event
+ has to activated in the AL-Event mask register */
+ u16ALEventMask |= PROCESS_OUTPUT_EVENT;
+ }
+/*The application ESM function is separated from this function to handle pending transitions*/
+
+/*ET9300 Project Handler :(#if DC_SUPPORTED) lines 1985 to 2092 deleted*/
+
+ if(nPdOutputSize > 0)
+ {
+ EnableSyncManChannel(PROCESS_DATA_OUT);
+ }
+
+ if(nPdInputSize > 0)
+ {
+ EnableSyncManChannel(PROCESS_DATA_IN);
+ }
+
+/*ET9300 Project Handler :(#if TEST_APPLICATION && COE_SUPPORTED) lines 2109 to 2119 deleted*/
+ /*write initial input data*/
+ PDO_InputMapping();
+
+ return ALSTATUSCODE_NOERROR;
+}
+
+/////////////////////////////////////////////////////////////////////////////////////////
+/**
+ \return AL Status Code (see ecatslv.h ALSTATUSCODE_....)
+
+ \brief This function is called in case of the state transition from SAFEOP to OP.
+ \brief It will be checked if outputs had to be received before switching to OP
+ \brief and the state transition would be refused if outputs are missing
+
+*////////////////////////////////////////////////////////////////////////////////////////
+
+UINT16 StartOutputHandler(void)
+{
+ /* by default the SO transition should be completed in AlControlRes().
+ required to support also masters which starts to send process data after the SO transition was triggered
+ (if the master don't send process data within "SAFEOP2OPTIMEOUT" the transition is rejected)*/
+ UINT16 result = NOERROR_INWORK;
+ /*ECATCHANGE_START(V5.13) ESM1*/
+ if(STATE_VALID(u8LocalErrorState))
+/*ECATCHANGE_END(V5.13) ESM1*/
+ {
+ /*Local error still exists => skip state request to OP and response with "u16LocalErrorCode"*/
+ return u16LocalErrorCode;
+ }
+/*The application ESM function is separated from this function to handle pending transitions*/
+
+
+/*ET9300 Project Handler :(#if DC_SUPPORTED) lines 2154 to 2163 deleted*/
+
+
+ sSyncManOutPar.u16SmEventMissedCounter = 0;
+ sSyncManOutPar.u8SyncError = 0;
+
+
+ sSyncManInPar.u16SmEventMissedCounter = 0;
+ sSyncManInPar.u8SyncError = 0;
+
+/*ET9300 Project Handler :(#if COE_SUPPORTED #else) lines 2178 to 2180 deleted*/
+
+ return result;
+}
+
+/////////////////////////////////////////////////////////////////////////////////////////
+/**
+ \brief This function is called in case of the state transition from OP to SAFEOP
+ \brief the outputs can be set to an application specific safe state,
+ \brief the state transition can be delayed by returning NOERROR_INWORK
+
+*////////////////////////////////////////////////////////////////////////////////////////
+
+void StopOutputHandler(void)
+{
+ /* reset the flags that outputs were received and that the slave is in OP */
+ bEcatFirstOutputsReceived = FALSE;
+ bEcatOutputUpdateRunning = FALSE;
+}
+
+/////////////////////////////////////////////////////////////////////////////////////////
+/**
+ \brief This function is called in case of the state transition from SAFEOP to PREOP
+
+*////////////////////////////////////////////////////////////////////////////////////////
+
+void StopInputHandler(void)
+{
+ if(nPdOutputSize > 0)
+ {
+ /* disable the Sync Manager Channel 2 (outputs) */
+ DisableSyncManChannel(PROCESS_DATA_OUT);
+ }
+
+ if(nPdInputSize > 0)
+ {
+ /*disable Sync Manager 3 (inputs) if no outputs available*/
+ DisableSyncManChannel(PROCESS_DATA_IN);
+ }
+
+ /* reset the events in the AL Event mask register (0x204) */
+/*ECATCHANGE_START(V5.13) ECAT1*/
+/*ECATCHANGE_END(V5.13) ECAT1*/
+ {
+ UINT16 ResetMask = SYNC0_EVENT | SYNC1_EVENT;
+ ResetMask |= PROCESS_OUTPUT_EVENT;
+ ResetMask |= PROCESS_INPUT_EVENT;
+
+ ResetALEventMask( ~(ResetMask) );
+ }
+ /* reset the flags */
+ bEcatFirstOutputsReceived = FALSE;
+ bEscIntEnabled = FALSE;
+/*The application ESM function is separated from this function to handle pending transitions*/
+
+/*ET9300 Project Handler :(#if DC_SUPPORTED) lines 2251 to 2284 deleted*/
+
+ bWdTrigger = FALSE;
+ bEcatInputUpdateRunning = FALSE;
+
+ /*Indicate no user specified Sync mode*/
+ bSyncSetByUser = FALSE;
+}
+
+/////////////////////////////////////////////////////////////////////////////////////////
+/**
+\brief This function is called when a X to Init transition is completed
+
+*////////////////////////////////////////////////////////////////////////////////////////
+
+void BackToInitTransition(void)
+{
+ /* Reset indication that the user has written a sync mode*/
+ bSyncSetByUser = FALSE;
+}
+
+/////////////////////////////////////////////////////////////////////////////////////////
+/**
+ \param alStatus New AL Status (written to register 0x130)
+ \param alStatusCode New AL Status Code (written to register 0x134)
+
+ \brief The function changes the state of the EtherCAT ASIC to the requested.
+*////////////////////////////////////////////////////////////////////////////////////////
+void SetALStatus(UINT8 alStatus, UINT16 alStatusCode)
+{
+ UINT16 Value = alStatusCode;
+/*ET9300 Project Handler :(#if ESC_32BIT_ACCESS) lines 2318 to 2320 deleted*/
+
+ /*update global status variable if required*/
+ if(nAlStatus != alStatus)
+ {
+ nAlStatus = alStatus;
+ }
+
+/*ET9300 Project Handler :(#if EXPLICIT_DEVICE_ID) lines 2328 to 2341 deleted*/
+
+ if (alStatusCode != 0xFFFF)
+ {
+/*ET9300 Project Handler :(#if ESC_32BIT_ACCESS) lines 2345 to 2349 deleted*/
+ Value = SWAPWORD(Value);
+
+ HW_EscWriteWord(Value,ESC_AL_STATUS_CODE_OFFSET);
+ }
+
+/*ET9300 Project Handler :(#if ESC_32BIT_ACCESS) lines 2356 to 2361 deleted*/
+ Value = nAlStatus;
+ Value = SWAPWORD(Value);
+ HW_EscWriteWord(Value,ESC_AL_STATUS_OFFSET);
+
+ /*The Run LED state is set in Set LED Indication, only the Error LED blink code is set here*/
+
+ /*set Error blink code*/
+ if(alStatusCode == 0x00 || !(alStatus & STATE_CHANGE))
+ {
+ u8EcatErrorLed = LED_OFF;
+ }
+ else if((alStatusCode == ALSTATUSCODE_NOSYNCERROR) ||
+ (alStatusCode == ALSTATUSCODE_SYNCERROR) ||
+ (alStatusCode == ALSTATUSCODE_DCPLLSYNCERROR)
+/*ECATCHANGE_START(V5.13) ESM1*/
+ || (u8LocalErrorState > 0))
+/*ECATCHANGE_END(V5.13) ESM1*/
+ {
+ u8EcatErrorLed = LED_SINGLEFLASH;
+ }
+ else if((alStatusCode == ALSTATUSCODE_SMWATCHDOG))
+ {
+ u8EcatErrorLed = LED_DOUBLEFLASH;
+ }
+ else
+ {
+ u8EcatErrorLed = LED_BLINKING;
+ }
+/*ET9300 Project Handler :(#if ESC_SUPPORT_ECAT_LED) lines 2392 to 2435 deleted*/
+}
+
+/////////////////////////////////////////////////////////////////////////////////////////
+/**
+ \param alControl requested new state
+ \param alStatusCode requested status code
+
+ \brief This function handles the EtherCAT State Machine. It is called
+ * in case of an AL Control event (Bit 0 of AL-Event (Reg 0x220),
+ when the Master has written the AL Control Register (from ECAT_Main),
+ alControl contains the content of the AL Control (Reg 0x120)
+ * in case of a SM-Change event (Bit 4 of AL-Event (Reg 0x220)),
+ when an Activate SYNCM y register is written by the master (from ECAT_Main),
+ alControl contains the actual state (Bit 0-3 of AL Status (Reg 0x130))
+ * in case of a locally expired watchdog (from ECAT_Main),
+ alControl contains the requested new state (SAFE_OP)
+ * in case of an application specific event to change the EtherCAT state (from application),
+ alControl contains the requested new state (INIT, PRE_OP or SAFE_OP)
+
+*////////////////////////////////////////////////////////////////////////////////////////
+
+void AL_ControlInd(UINT8 alControl, UINT16 alStatusCode)
+{
+ UINT16 result = 0;
+ UINT8 bErrAck = 0;
+ UINT8 stateTrans;
+ /*deactivate ESM timeout counter*/
+ EsmTimeoutCounter = -1;
+ bApplEsmPending = TRUE;
+
+ /* reset the Error Flag in case of acknowledge by the Master */
+ if ( alControl & STATE_CHANGE )
+ {
+ bErrAck = 1;
+ nAlStatus &= ~STATE_CHANGE;
+ /*enable SM2 is moved to state transition block. First check SM Settings.*/
+ }
+ else if ((nAlStatus & STATE_CHANGE)
+ // HBu 17.04.08: the error has to be acknowledged before when sending the same (or a higher) state
+ // (the error was acknowledged with the same state before independent of the acknowledge flag)
+ /*Error Acknowledge with 0xX1 is allowed*/
+ && (alControl & STATE_MASK) != STATE_INIT)
+ {
+ /* the error flag (Bit 4) is set in the AL-Status and the ErrAck bit (Bit 4)
+ is not set in the AL-Control, so the state cannot be set to a higher state
+ and the new state request will be ignored */
+ return;
+ }
+ else
+ {
+ nAlStatus &= STATE_MASK;
+ }
+
+
+
+ /* generate a variable for the state transition
+ (Bit 0-3: new state (AL Control), Bit 4-7: old state (AL Status) */
+ alControl &= STATE_MASK;
+ stateTrans = nAlStatus;
+ stateTrans <<= 4;
+ stateTrans += alControl;
+
+ /* check the SYNCM settings depending on the state transition */
+ switch ( stateTrans )
+ {
+ case INIT_2_PREOP:
+ case OP_2_PREOP:
+ case SAFEOP_2_PREOP:
+ case PREOP_2_PREOP:
+ /* in PREOP only the SYNCM settings for SYNCM0 and SYNCM1 (mailbox)
+ are checked, if result is unequal 0, the slave will stay in or
+ switch to INIT and set the ErrorInd Bit (bit 4) of the AL-Status */
+ result = CheckSmSettings(MAILBOX_READ+1);
+ break;
+ case PREOP_2_SAFEOP:
+ {
+ /* before checking the SYNCM settings for SYNCM2 and SYNCM3 (process data)
+ the expected length of input data (nPdInputSize) and output data (nPdOutputSize)
+ could be adapted (changed by PDO-Assign and/or PDO-Mapping)
+ if result is unequal 0, the slave will stay in PREOP and set
+ the ErrorInd Bit (bit 4) of the AL-Status */
+ result = APPL_GenerateMapping(&nPdInputSize,&nPdOutputSize);
+
+ if (result != 0)
+ {
+ break;
+ }
+/*ET9300 Project Handler :(#if (MAX_PD_OUTPUT_SIZE == 0) || (MAX_PD_INPUT_SIZE == 0)) lines 2527 to 2543 deleted*/
+ }
+ case SAFEOP_2_OP:
+ case OP_2_SAFEOP:
+ case SAFEOP_2_SAFEOP:
+ case OP_2_OP:
+ /* in SAFEOP or OP the SYNCM settings for all SYNCM are checked
+ if result is unequal 0, the slave will stay in or
+ switch to PREOP and set the ErrorInd Bit (bit 4) of the AL-Status */
+ result = CheckSmSettings(nMaxSyncMan);
+ break;
+
+ }
+
+ if ( result == 0 )
+ {
+ /* execute the corresponding local management service(s) depending on the state transition */
+ nEcatStateTrans = 0;
+ switch ( stateTrans )
+ {
+ case INIT_2_BOOT :
+/*ET9300 Project Handler :(#if BOOTSTRAPMODE_SUPPORTED) lines 2565 to 2624 deleted*/
+ result = ALSTATUSCODE_BOOTNOTSUPP;
+
+
+
+ break;
+
+ case BOOT_2_INIT :
+/*ET9300 Project Handler :(#if BOOTSTRAPMODE_SUPPORTED) lines 2633 to 2650 deleted*/
+ result = ALSTATUSCODE_BOOTNOTSUPP;
+
+ BackToInitTransition();
+
+
+
+ break;
+ case INIT_2_PREOP :
+
+ UpdateEEPROMLoadedState();
+
+ if (EepromLoaded == FALSE)
+ {
+ //return an error if the EEPROM was not loaded correct (device restart is required after the new EEPORM update)
+ result = ALSTATUSCODE_EE_ERROR;
+ }
+ if (result == 0)
+ {
+ /* MBX_StartMailboxHandler (in mailbox.c) checks if the areas of the mailbox
+ sync managers SYNCM0 and SYNCM1 overlap each other
+ if result is unequal 0, the slave will stay in INIT
+ and sets the ErrorInd Bit (bit 4) of the AL-Status */
+ result = MBX_StartMailboxHandler();
+ if (result == 0)
+ {
+ bApplEsmPending = FALSE;
+ /* additionally there could be an application specific check (in ecatappl.c)
+ if the state transition from INIT to PREOP should be done
+ if result is unequal 0, the slave will stay in INIT
+ and sets the ErrorInd Bit (bit 4) of the AL-Status */
+ result = APPL_StartMailboxHandler();
+ if ( result == 0 )
+ {
+ bMbxRunning = TRUE;
+ }
+ }
+
+ if(result != 0 && result != NOERROR_INWORK)
+ {
+ /*Stop APPL Mbx handler if APPL Start Mbx handler was called before*/
+ if (!bApplEsmPending)
+ {
+ APPL_StopMailboxHandler();
+ }
+
+ MBX_StopMailboxHandler();
+ }
+
+ }
+/*ET9300 Project Handler :(#if MAILBOX_SUPPORTED #else) lines 2702 to 2704 deleted*/
+ break;
+
+ case PREOP_2_SAFEOP:
+ /* start the input handler (function is defined above) */
+ result = StartInputHandler();
+ if ( result == 0 )
+ {
+ bApplEsmPending = FALSE;
+ result = APPL_StartInputHandler(&u16ALEventMask);
+
+ if(result == 0)
+ {
+/*ECATCHANGE_START(V5.13) ECAT1*/
+/*ECATCHANGE_END(V5.13) ECAT1*/
+ /* initialize the AL Event Mask register (0x204) */
+ SetALEventMask( u16ALEventMask );
+
+ bEcatInputUpdateRunning = TRUE;
+ }
+ }
+
+ /*if one start input handler returned an error stop the input handler*/
+ if(result != 0 && result != NOERROR_INWORK)
+ {
+ if(!bApplEsmPending)
+ {
+ /*Call only the APPL stop handler if the APPL start handler was called before*/
+ /*The application can react to the state transition in the function APPL_StopInputHandler */
+ APPL_StopInputHandler();
+ }
+
+ StopInputHandler();
+ }
+ break;
+
+ case SAFEOP_2_OP:
+/*ECATCHANGE_START(V5.13) ESM2*/
+ /*enable SM if error was acknowledged*/
+ if (bErrAck)
+ {
+ if (nPdOutputSize > 0)
+ {
+ EnableSyncManChannel(PROCESS_DATA_OUT);
+ }
+ else
+ if (nPdInputSize > 0)
+ {
+ EnableSyncManChannel(PROCESS_DATA_IN);
+ }
+ }
+ /*ECATCHANGE_END(V5.13) ESM2*/
+
+ /* start the output handler (function is defined above) */
+ result = StartOutputHandler();
+ if(result == 0)
+ {
+ bApplEsmPending = FALSE;
+ result = APPL_StartOutputHandler();
+
+ if(result == 0)
+ {
+ /*Device is in OPERATINAL*/
+ bEcatOutputUpdateRunning = TRUE;
+ }
+
+ }
+
+ if ( result != 0 && result != NOERROR_INWORK)
+ {
+ if (!bApplEsmPending)
+ {
+ APPL_StopOutputHandler();
+ }
+
+ StopOutputHandler();
+ }
+
+ break;
+
+ case OP_2_SAFEOP:
+ /* stop the output handler (function is defined above) */
+ APPL_StopOutputHandler();
+
+ StopOutputHandler();
+
+ bApplEsmPending = FALSE;
+
+ break;
+
+ case OP_2_PREOP:
+ /* stop the output handler (function is defined above) */
+ result = APPL_StopOutputHandler();
+
+ StopOutputHandler();
+
+ bApplEsmPending = FALSE;
+
+ if (result != 0)
+ {
+ break;
+ }
+
+ stateTrans = SAFEOP_2_PREOP;
+
+ case SAFEOP_2_PREOP:
+ /* stop the input handler (function is defined above) */
+ APPL_StopInputHandler();
+
+ StopInputHandler();
+
+ bApplEsmPending = FALSE;
+
+ break;
+
+ case OP_2_INIT:
+ /* stop the output handler (function is defined above) */
+ result = APPL_StopOutputHandler();
+
+ StopOutputHandler();
+
+ bApplEsmPending = FALSE;
+
+ if (result != 0)
+ {
+ break;
+ }
+
+ stateTrans = SAFEOP_2_INIT;
+
+ case SAFEOP_2_INIT:
+ /* stop the input handler (function is defined above) */
+ result = APPL_StopInputHandler();
+
+ StopInputHandler();
+
+ bApplEsmPending = FALSE;
+
+ if (result != 0)
+ {
+ break;
+ }
+ stateTrans = PREOP_2_INIT;
+
+ case PREOP_2_INIT:
+ MBX_StopMailboxHandler();
+ result = APPL_StopMailboxHandler();
+
+ BackToInitTransition();
+ break;
+/*ET9300 Project Handler :(#if !BOOTLOADER_SAMPLE #else) lines 2865 to 2872 deleted*/
+ case INIT_2_INIT:
+ BackToInitTransition();
+ case PREOP_2_PREOP:
+ case SAFEOP_2_SAFEOP:
+ case OP_2_OP:
+ if(bErrAck)
+ {
+ APPL_AckErrorInd(stateTrans);
+ }
+
+
+ /*no local error flag is currently active, enable SM*/
+ if ( nAlStatus & (STATE_SAFEOP | STATE_OP))
+ {
+ if(nPdOutputSize > 0)
+ {
+ EnableSyncManChannel(PROCESS_DATA_OUT);
+ }
+ else
+ if(nPdInputSize > 0)
+ {
+ EnableSyncManChannel(PROCESS_DATA_IN);
+ }
+ }
+
+ result = NOERROR_NOSTATECHANGE;
+ break;
+
+ case INIT_2_SAFEOP:
+ case INIT_2_OP:
+ case PREOP_2_OP:
+ case PREOP_2_BOOT:
+ case SAFEOP_2_BOOT:
+ case OP_2_BOOT:
+ case BOOT_2_PREOP:
+ case BOOT_2_SAFEOP:
+ case BOOT_2_OP:
+ result = ALSTATUSCODE_INVALIDALCONTROL;
+ break;
+
+ default:
+ result = ALSTATUSCODE_UNKNOWNALCONTROL;
+ break;
+ }
+ }
+ else
+ {
+ /* the checking of the sync manager settings was not successful
+ switch back the state to PREOP or INIT */
+ switch (nAlStatus)
+ {
+ case STATE_OP:
+ /* stop the output handler (function is defined above) */
+ APPL_StopOutputHandler();
+ StopOutputHandler();
+ case STATE_SAFEOP:
+ /* stop the input handler (function is defined above) */
+ APPL_StopInputHandler();
+
+ StopInputHandler();
+ case STATE_PREOP:
+ if ( result == ALSTATUSCODE_INVALIDMBXCFGINPREOP )
+ {
+ /* the mailbox sync manager settings were wrong, switch back to INIT */
+ MBX_StopMailboxHandler();
+ APPL_StopMailboxHandler();
+
+ /*Disable SM0 (MBX Out)*/
+ DisableSyncManChannel(MAILBOX_WRITE);
+
+ /*Disable SM1 (MBX In)*/
+ DisableSyncManChannel(MAILBOX_READ);
+/*ET9300 Project Handler :(#if MAILBOX_SUPPORTED #else) lines 2956 to 2958 deleted*/
+
+ nAlStatus = STATE_INIT;
+ }
+ else
+ {
+ nAlStatus = STATE_PREOP;
+ }
+ }
+ }
+
+ if ( result == NOERROR_INWORK )
+ {
+ /* state transition is still in work
+ ECAT_StateChange must be called from the application */
+ bEcatWaitForAlControlRes = TRUE;
+ /* state transition has to be stored */
+ nEcatStateTrans = stateTrans;
+
+ /*Init ESM timeout counter (will be decremented with the local 1ms timer)*/
+ switch(nEcatStateTrans)
+ {
+ case INIT_2_PREOP:
+ case INIT_2_BOOT:
+ EsmTimeoutCounter = PREOPTIMEOUT;
+ break;
+ case PREOP_2_SAFEOP:
+ case SAFEOP_2_OP:
+ EsmTimeoutCounter = SAFEOP2OPTIMEOUT;
+ break;
+ default:
+ EsmTimeoutCounter = 200; //Set default timeout value to 200ms
+ break;
+ }
+ EsmTimeoutCounter -= (INT16) (EsmTimeoutCounter / 10); //subtract 10% from the timeout to react before the master runs into a timeout.
+
+ }
+ else if ( alControl != (nAlStatus & STATE_MASK) )
+ {
+ /* The slave state has changed */
+
+ if ( (result != 0 || alStatusCode != 0) && ((alControl | nAlStatus) & STATE_OP) )
+ {
+ /* the local application requested to leave the state OP so we have to disable the SM2
+ and make the state change from OP to SAFEOP by calling StopOutputHandler */
+
+ //only execute StopOutputHandler() if Output update is still running
+ if(bEcatOutputUpdateRunning)
+ {
+ APPL_StopOutputHandler();
+
+ StopOutputHandler();
+ }
+
+ if(nPdOutputSize > 0)
+ {
+ /* disable the Sync Manager Channel 2 (outputs) */
+ DisableSyncManChannel(PROCESS_DATA_OUT);
+ }
+ else
+ if(nPdInputSize > 0)
+ {
+ /*disable Sync Manager 3 (inputs) if no outputs available*/
+ DisableSyncManChannel(PROCESS_DATA_IN);
+ }
+
+ }
+ if ( result != 0 )
+ {
+ if (nAlStatus == STATE_OP)
+ {
+ nAlStatus = STATE_SAFEOP;
+ }
+ /* save the failed status to be able to decide, if the AL Status Code shall be
+ reset in case of a coming successful state transition */
+ nAlStatus |= STATE_CHANGE;
+ }
+ else
+ {
+ /* state transition was successful */
+ if ( alStatusCode != 0 )
+ {
+ /* state change request from the user */
+ result = alStatusCode;
+ alControl |= STATE_CHANGE;
+ }
+ /* acknowledge the new state */
+ nAlStatus = alControl;
+ }
+
+ bEcatWaitForAlControlRes = FALSE;
+
+ /* write the AL Status register */
+ SetALStatus(nAlStatus, result);
+ }
+ else
+ {
+ /* Error acknowledgement without a state transition */
+
+ bEcatWaitForAlControlRes = FALSE;
+
+ /* AL-Status has to be updated and AL-Status-Code has to be reset
+ if the the error bit was acknowledged */
+ SetALStatus(nAlStatus, 0);
+ }
+ /*ECATCHANGE_START(V5.13) CIA402 4*/
+ /*decouple CIA402 state machine from ESM*/
+ /*ECATCHANGE_END(V5.13) CIA402 4*/
+
+}
+
+/////////////////////////////////////////////////////////////////////////////////////////
+/**
+
+ \brief This function is called cyclic if a state transition is pending (bEcatWaitForAlControlRes == TRUE)
+ \brief If the ESM timeout is expired the state transition will be rejected. Otherwise the application specific state transition function is called.
+ \brief If the pending state transition is triggered by the application the transition need to be completed by the application (ECAT_StateChange())
+ *////////////////////////////////////////////////////////////////////////////////////////
+void AL_ControlRes(void)
+{
+ if(bEcatWaitForAlControlRes)
+ {
+ UINT16 result = 0;
+ UINT8 Status = 0;
+ UINT16 StatusCode = 0;
+
+ if(EsmTimeoutCounter == 0)
+ {
+ Status = (UINT8)(nEcatStateTrans >> 4);
+
+ /* ESM timeout expired*/
+ switch(nEcatStateTrans)
+ {
+ case INIT_2_PREOP:
+ case INIT_2_BOOT:
+
+ if (!bApplEsmPending)
+ {
+ APPL_StopMailboxHandler();
+ }
+
+ MBX_StopMailboxHandler();
+ /*ECATCHANGE_START(V5.13) ESM1*/
+ if((u8LocalErrorState & STATE_MASK) == STATE_INIT)
+ /*ECATCHANGE_END(V5.13) ESM1*/
+ {
+ /*Set application specified error*/
+ StatusCode = u16LocalErrorCode;
+ }
+ else
+ {
+ /*Set unspecified error*/
+ StatusCode = ALSTATUSCODE_UNSPECIFIEDERROR;
+ }
+ break;
+ case PREOP_2_SAFEOP:
+
+ if (!bApplEsmPending)
+ {
+ APPL_StopInputHandler();
+ }
+
+ StopInputHandler();
+
+ /*ECATCHANGE_START(V5.13) ESM1*/
+ if ((u8LocalErrorState & STATE_MASK) == STATE_PREOP)
+ /*ECATCHANGE_END(V5.13) ESM1*/
+ {
+ /*Set application specified error*/
+ StatusCode = u16LocalErrorCode;
+ }
+ else
+ {
+ /*Set unspecified error*/
+ StatusCode = ALSTATUSCODE_UNSPECIFIEDERROR;
+ }
+ break;
+ case SAFEOP_2_OP:
+/*ET9300 Project Handler :(#if DC_SUPPORTED) lines 3147 to 3180 deleted*/
+ {
+ if (nPdOutputSize > 0)
+ {
+ StatusCode = ALSTATUSCODE_SMWATCHDOG;
+ }
+ else
+ {
+ /*ECATCHANGE_START(V5.13) ESM1*/
+ if ((u8LocalErrorState & STATE_MASK) == STATE_SAFEOP)
+ {
+ /*Set application specified error*/
+ StatusCode = u16LocalErrorCode;
+ }
+ else
+ /*ECATCHANGE_END(V5.13) ESM1*/
+ {
+ /*Set valid state transition even if timeout expired*/
+ Status = STATE_OP;
+ StatusCode = 0;
+ /* Slave is OPERATIONAL */
+ bEcatOutputUpdateRunning = TRUE;
+ }
+ }
+ }
+
+ /*Stop handler on failed transition*/
+ if(StatusCode != 0)
+ {
+ if (!bApplEsmPending)
+ {
+ APPL_StopOutputHandler();
+ }
+
+ StopOutputHandler();
+ }
+ break;
+ }
+ } //ESM timeout
+ else
+ {
+ /*Call application specific transition function and complete transition it the function returns 0*/
+ switch(nEcatStateTrans)
+ {
+ case INIT_2_PREOP:
+ case INIT_2_BOOT:
+ if(bApplEsmPending)
+ {
+ bApplEsmPending = FALSE;
+ /*APPL_StartMailboxHandler() need to be called*/
+ result = APPL_StartMailboxHandler();
+
+ if(result == 0)
+ {
+ /*The application specific transition was successful => set active mailbox handler indication*/
+ bMbxRunning = TRUE;
+ Status = (UINT8)(nEcatStateTrans & STATE_MASK);
+ }
+ else
+ {
+ /*The application specific transition failed.
+ (In pending case the application need to complete the transition)*/
+
+ if(result != NOERROR_INWORK)
+ {
+ APPL_StopMailboxHandler();
+ MBX_StopMailboxHandler();
+ }
+ }
+ }
+ break;
+ case PREOP_2_SAFEOP:
+ if(bApplEsmPending)
+ {
+ bApplEsmPending = FALSE;
+ result = APPL_StartInputHandler(&u16ALEventMask);
+
+ if(result == 0)
+ {
+ bEcatInputUpdateRunning = TRUE;
+ Status = STATE_SAFEOP;
+ }
+ else
+ {
+ /*The application specific transition failed.
+ (In pending case the application need to complete the transition)*/
+
+ if(result != NOERROR_INWORK)
+ {
+ APPL_StopInputHandler();
+ StopInputHandler();
+ }
+ }
+ }
+ break;
+ case SAFEOP_2_OP:
+ if(bApplEsmPending)
+ {
+/*ET9300 Project Handler :(#if DC_SUPPORTED) lines 3284 to 3315 deleted*/
+ {
+ if(nPdOutputSize == 0 || bEcatFirstOutputsReceived)
+ {
+ bApplEsmPending = FALSE;
+ result = APPL_StartOutputHandler();
+
+ if(result == 0)
+ {
+ /* Slave is OPERATIONAL */
+ bEcatOutputUpdateRunning = TRUE;
+ Status = STATE_OP;
+ }
+ else
+ {
+ if(result != NOERROR_INWORK)
+ {
+ APPL_StopOutputHandler();
+ StopOutputHandler();
+ }
+ }
+ }
+ }
+ }
+ break;
+ }//Switch - transition
+ }
+
+ if(Status != 0)
+ {
+ /*Pending state transition finished => write AL Status and AL Status Code*/
+ bEcatWaitForAlControlRes = FALSE;
+
+ if (StatusCode != 0)
+ {
+ Status |= STATE_CHANGE;
+ }
+
+ SetALStatus(Status,StatusCode);
+ }
+ }// Pending state transition (bEcatWaitForAlControlRes == true)
+}
+
+/*ET9300 Project Handler :(#if !ESC_SM_WD_SUPPORTED) lines 3363 to 3410 deleted*/
+
+/*ET9300 Project Handler :(#if DC_SUPPORTED) lines 3412 to 3504 deleted*/
+
+/////////////////////////////////////////////////////////////////////////////////////////
+/**
+
+ \brief Checks communication and synchronisation variables and update AL status / AL status code if an error has occurred
+
+*////////////////////////////////////////////////////////////////////////////////////////
+void CheckIfEcatError(void)
+{
+ /*if the watchdog is enabled check the process data watchdog in the ESC
+ and set the AL status code 0x1B if the watchdog expired*/
+ if (EcatWdValue != 0)
+ {
+ /*watchdog time is set => watchdog is active*/
+/*ET9300 Project Handler :(#if ESC_32BIT_ACCESS) lines 3520 to 3526 deleted*/
+ UINT16 WdStatusOK = 0;
+
+ HW_EscReadWord(WdStatusOK, ESC_PD_WD_STATE);
+ WdStatusOK = SWAPWORD(WdStatusOK);
+
+ if (!(WdStatusOK & ESC_PD_WD_TRIGGER_MASK) && (nPdOutputSize > 0))
+ {
+ /*The device is in OP state*/
+
+ if (bEcatOutputUpdateRunning
+/*ET9300 Project Handler :(#if !OP_PD_REQUIRED) lines 3539 to 3541 deleted*/
+ )
+ {
+ AL_ControlInd(STATE_SAFEOP, ALSTATUSCODE_SMWATCHDOG);
+ return;
+ }
+
+ else
+ {
+ bEcatFirstOutputsReceived = FALSE;
+ }
+ }
+ }
+
+/*ET9300 Project Handler :(#if DC_SUPPORTED) lines 3557 to 3576 deleted*/
+}
+/////////////////////////////////////////////////////////////////////////////////////////
+/**
+ \param alStatus: requested state (ignored if the "alStatusCode" is 0)
+ \param alStatusCode: value for the AL-Status register
+
+ \brief This function changes the state of the EtherCAT slave if the requested state
+ is lower than the actual state, otherwise the error condition will be reset.
+*////////////////////////////////////////////////////////////////////////////////////////
+
+void ECAT_StateChange(UINT8 alStatus, UINT16 alStatusCode)
+{
+ UINT8 Status = alStatus;
+
+ /*ECATCHANGE_START(V5.13) ESM1*/
+ /*return in case of invalid parameters*/
+ if (alStatusCode != 0 && !STATE_VALID(alStatus))
+ {
+ return;
+ }
+
+ /* call the application requested state transition only once*/
+ if (bEcatWaitForAlControlRes == FALSE && u8LocalErrorState == alStatus && u16LocalErrorCode == alStatusCode)
+ {
+ return;
+ }
+ /*ECATCHANGE_END(V5.13) ESM1*/
+
+
+ if(bEcatWaitForAlControlRes)
+ {
+ /*State transition is pending*/
+
+ if(bApplEsmPending)
+ {
+ /*The generic stack has currently control of the state transition.
+ In case on an local error force ESM timeout*/
+ if(alStatusCode != 0)
+ {
+ /*ECATCHANGE_START(V5.13) ESM1*/
+ u8LocalErrorState = (alStatus & STATE_MASK);
+ /*ECATCHANGE_END(V5.13) ESM1*/
+ u16LocalErrorCode = alStatusCode;
+ EsmTimeoutCounter = 0;
+ }
+ else
+ {
+ u8LocalErrorState = 0;
+ u16LocalErrorCode = alStatusCode;
+ }
+ }
+ else
+ {
+ /*complete the state transition*/
+
+ if(alStatusCode != 0)
+ {
+ /*ECATCHANGE_START(V5.13) ESM1*/
+ u8LocalErrorState = (alStatus & STATE_MASK);
+ /*ECATCHANGE_END(V5.13) ESM1*/
+ u16LocalErrorCode = alStatusCode;
+
+ /*State transition failed due to local application reasons*/
+ switch(nEcatStateTrans)
+ {
+ case INIT_2_PREOP:
+ case INIT_2_BOOT:
+
+ APPL_StopMailboxHandler();
+ MBX_StopMailboxHandler();
+ break;
+ case PREOP_2_SAFEOP:
+ APPL_StopInputHandler();
+ StopInputHandler();
+ break;
+ case SAFEOP_2_OP:
+ APPL_StopOutputHandler();
+ StopOutputHandler();
+ break;
+ }
+
+ /*In case of a failed state transition the */
+ Status = (UINT8)(nEcatStateTrans >> 4);
+ }
+ else
+ {
+ /*State transition succeed*/
+
+ switch(nEcatStateTrans)
+ {
+ case INIT_2_PREOP:
+ case INIT_2_BOOT:
+ bMbxRunning = TRUE;
+ break;
+ case PREOP_2_SAFEOP:
+/*ECATCHANGE_START(V5.13) ECAT1*/
+/*ECATCHANGE_END(V5.13) ECAT1*/
+ /* initialize the AL Event Mask register (0x204) */
+ SetALEventMask(u16ALEventMask);
+ bEcatInputUpdateRunning = TRUE;
+ break;
+ case SAFEOP_2_OP:
+ bEcatOutputUpdateRunning = TRUE;
+ break;
+ }
+
+
+
+ Status = (UINT8)(nEcatStateTrans & STATE_MASK);
+ }
+ /*Pending state transition finished => write AL Status and AL Status Code*/
+ bEcatWaitForAlControlRes = FALSE;
+
+ if (alStatusCode != 0)
+ {
+ Status |= STATE_CHANGE;
+ }
+/*ECATCHANGE_START(V5.13) ECAT3*/
+ else if (u8LocalErrorState != 0)
+ {
+ /*a local error is cleared*/
+ /*ECATCHANGE_START(V5.13) ESM1*/
+ u8LocalErrorState = 0;
+ /*ECATCHANGE_END(V5.13) ESM1*/
+ u16LocalErrorCode = 0x00;
+ }
+/*ECATCHANGE_END(V5.13) ECAT3*/
+
+ SetALStatus(Status,alStatusCode);
+
+ }/*state transition need to be completed by the local application*/
+ }/*State transition pending*/
+ else
+ {
+ /*ECATCHANGE_START(V5.13) ESM1*/
+ if ( alStatusCode != 0 && ((alStatus & STATE_MASK) != STATE_OP) && STATE_VALID(alStatus))
+ {
+ u8LocalErrorState = (alStatus & STATE_MASK);
+ /*ECATCHANGE_END(V5.13) ESM1*/
+ u16LocalErrorCode = alStatusCode;
+
+ /*trigger state transition only state transition from OP to lower state (for all other transitions the corresponding state transition functions shall be used)*/
+ if ((nAlStatus & STATE_MASK) == STATE_OP)
+ {
+ /* no error pending and the target state is lower than the current one*/
+ AL_ControlInd(alStatus, alStatusCode);
+ }
+ }
+ /*ECATCHANGE_START(V5.13) ESM1*/
+ else if (u8LocalErrorState != 0)
+ {
+ /*a local error is gone*/
+ u8LocalErrorState = 0;
+ u16LocalErrorCode = 0x00;
+ }
+ /*ECATCHANGE_END(V5.13) ESM1*/
+ }
+}
+
+/////////////////////////////////////////////////////////////////////////////////////////
+/**
+
+ \brief This function initialize the EtherCAT Slave Interface.
+*////////////////////////////////////////////////////////////////////////////////////////
+
+void ECAT_Init(void)
+{
+ UINT8 i;
+ /*Get Maximum Number of SyncManagers and supported DPRAM size*/
+/*ET9300 Project Handler :(#if ESC_32BIT_ACCESS #elif ESC_16BIT_ACCESS) lines 3756 to 3783 deleted*/
+ HW_EscReadByte(nMaxSyncMan, ESC_SM_CHANNELS_OFFSET);
+
+ HW_EscReadWord(nMaxEscAddress, ESC_DPRAM_SIZE_OFFSET);
+ //get max address (register + DPRAM size in Byte (in the register it is stored in KB))
+ nMaxEscAddress = (nMaxEscAddress << 10) + 0xFFF;
+
+/*ET9300 Project Handler :(#if EXPLICIT_DEVICE_ID) lines 3791 to 3795 deleted*/
+
+ /* Get EEPROM loaded information */
+ UpdateEEPROMLoadedState();
+
+ /* disable all Sync Manager channels */
+ for (i = 0; i < nMaxSyncMan; i++)
+ {
+ DisableSyncManChannel(i);
+ }
+
+ /* initialize the mailbox handler */
+ MBX_Init();
+
+ /* initialize variables */
+/*ET9300 Project Handler :(#if BOOTSTRAPMODE_SUPPORTED) lines 3812 to 3814 deleted*/
+ bApplEsmPending = FALSE;
+ bEcatWaitForAlControlRes = FALSE;
+ bEcatFirstOutputsReceived = FALSE;
+ bEcatOutputUpdateRunning = FALSE;
+ bEcatInputUpdateRunning = FALSE;
+/*ET9300 Project Handler :(#if EXPLICIT_DEVICE_ID) lines 3822 to 3824 deleted*/
+ bWdTrigger = FALSE;
+ EcatWdValue = 0;
+/*ET9300 Project Handler :(#if !ESC_SM_WD_SUPPORTED) lines 3829 to 3831 deleted*/
+/*ET9300 Project Handler :(#if DC_SUPPORTED) lines 3832 to 3839 deleted*/
+ /*ECATCHANGE_START(V5.13) ESM1*/
+ u8LocalErrorState = 0;
+ /*ECATCHANGE_END(V5.13) ESM1*/
+ u16LocalErrorCode = 0x00;
+
+ u16ALEventMask = 0;
+ nPdOutputSize = 0;
+ nPdInputSize = 0;
+
+ /* initialize the AL Status register */
+ nAlStatus = STATE_INIT;
+ SetALStatus(nAlStatus, 0);
+ nEcatStateTrans = 0;
+ u8EcatErrorLed = LED_OFF;
+
+ bEscIntEnabled = FALSE;
+
+/*ET9300 Project Handler :(#if EMERGENCY_SUPPORTED && (COE_SUPPORTED || SOE_SUPPORTED)) lines 3859 to 3862 deleted*/
+ /* initialize the COE part */
+ COE_Init();
+/*ET9300 Project Handler :(#if AOE_SUPPORTED) lines 3867 to 3870 deleted*/
+
+/*ECATCHANGE_START(V5.13) ECAT1*/
+/*ECATCHANGE_END(V5.13) ECAT1*/
+ /*reset AL event mask*/
+ ResetALEventMask(0);
+}
+
+/////////////////////////////////////////////////////////////////////////////////////////
+/**
+ \brief This function has to be called cyclically.
+*////////////////////////////////////////////////////////////////////////////////////////
+
+void ECAT_Main(void)
+{
+ UINT16 ALEventReg;
+ UINT16 EscAlControl = 0x0000;
+/*ECATCHANGE_START(V5.13) MBX1*/
+/*ET9300 Project Handler :(#if ESC_32BIT_ACCESS #elif ESC_16BIT_ACCESS) lines 3891 to 3897 deleted*/
+ UINT8 sm1Activate = SM_SETTING_ENABLE_VALUE;
+ UINT8 sm1Status = 0; /*SM1 status need to be read (not MBX_READ_EVENT) to handle readframes with invalid CRCs*/
+/*ECATCHANGE_END(V5.13) MBX1*/
+
+
+ /* check if services are stored in the mailbox */
+ MBX_Main();
+
+/*ET9300 Project Handler :(#if COE_SUPPORTED && TEST_APPLICATION) lines 3909 to 3949 deleted*/
+
+ if ( bMbxRunning )
+ {
+ /* Slave is at least in PREOP, Mailbox is running */
+
+/*ECATCHANGE_START(V5.13) MBX1*/
+/*ET9300 Project Handler :(#if ESC_32BIT_ACCESS #elif ESC_16BIT_ACCESS) lines 3956 to 3968 deleted*/
+ /* get the Activate-Byte of SM 1 (Register 0x80E) to check if a mailbox repeat request was received */
+ HW_EscReadByte(sm1Activate,(ESC_SYNCMAN_ACTIVE_OFFSET + SIZEOF_SM_REGISTER));
+
+ HW_EscReadByte(sm1Status, (ESC_SYNCMAN_STATUS_OFFSET + SIZEOF_SM_REGISTER));
+/*ECATCHANGE_END(V5.13) MBX1*/
+ }
+
+ /* Read AL Event-Register from ESC */
+ ALEventReg = HW_GetALEventRegister();
+ ALEventReg = SWAPWORD(ALEventReg);
+
+/*ET9300 Project Handler :(#if ESC_EEPROM_EMULATION) lines 3982 to 3987 deleted*/
+
+ if ((ALEventReg & AL_CONTROL_EVENT) && !bEcatWaitForAlControlRes)
+ {
+ /* AL Control event is set, get the AL Control register sent by the Master to acknowledge the event
+ (that the corresponding bit in the AL Event register will be reset) */
+/*ET9300 Project Handler :(#if ESC_32BIT_ACCESS #elif ESC_16BIT_ACCESS) lines 3993 to 4002 deleted*/
+
+ HW_EscReadByte( EscAlControl, ESC_AL_CONTROL_OFFSET);
+ EscAlControl = SWAPWORD(EscAlControl);
+
+/*ET9300 Project Handler :(#if TEST_APPLICATION) lines 4008 to 4023 deleted*/
+
+/*ET9300 Project Handler :(#if EXPLICIT_DEVICE_ID) lines 4025 to 4042 deleted*/
+
+ /* reset AL Control event and the SM Change event (because the Sync Manager settings will be checked
+ in AL_ControlInd, too)*/
+ ALEventReg &= ~((AL_CONTROL_EVENT) | (SM_CHANGE_EVENT));
+
+ AL_ControlInd((UINT8)EscAlControl, 0); /* in AL_ControlInd the state transition will be checked and done */
+
+ /* SM-Change-Event was handled too */
+
+/*ET9300 Project Handler :(#if TEST_APPLICATION) lines 4052 to 4054 deleted*/
+ }
+
+ if ( (ALEventReg & SM_CHANGE_EVENT) && !bEcatWaitForAlControlRes && (nAlStatus & STATE_CHANGE) == 0 && (nAlStatus & ~STATE_CHANGE) != STATE_INIT )
+ {
+ /* the SM Change event is set (Bit 4 of Register 0x220), when the Byte 6 (Enable, Lo-Byte of Register 0x806, 0x80E, 0x816,...)
+ of a Sync Manager channel was written */
+ ALEventReg &= ~(SM_CHANGE_EVENT);
+
+ /* AL_ControlInd is called with the actual state, so that the correct SM settings will be checked */
+ AL_ControlInd(nAlStatus & STATE_MASK, 0);
+ }
+
+ if(bEcatWaitForAlControlRes)
+ {
+ AL_ControlRes();
+ }
+ /*The order of mailbox event processing was changed to prevent race condition errors.
+ The SM1 activate Byte (Register 0x80E) was read before reading AL Event register.
+ 1. Handle Mailbox Read event
+ 2. Handle repeat toggle request
+ 3. Handle Mailbox write event
+ */
+ if ( bMbxRunning )
+ {
+ /*SnycManger change event (0x220:4) could be acknowledged by reading the SM1 control register without notification to the local application
+ => check if the SyncManger 1 is still enabled*/
+ if (!(sm1Activate & SM_SETTING_ENABLE_VALUE))
+ {
+ AL_ControlInd(nAlStatus & STATE_MASK, 0);
+ }
+
+/*ECATCHANGE_START(V5.13) MBX1*/
+ if (((sm1Status & SM_STATUS_MBX_BUFFER_FULL) == 0)
+ && bSendMbxIsFull)
+/*ECATCHANGE_END(V5.13) MBX1*/
+ {
+ /* SM 1 (Mailbox Read) event is set, when the mailbox was read from the master,
+ to acknowledge the event the first byte of the mailbox has to be written,
+ by writing the first byte the mailbox is locked, too */
+/*ET9300 Project Handler :(#if ESC_32BIT_ACCESS #elif ESC_16BIT_ACCESS) lines 4095 to 4101 deleted*/
+ u8dummy = 0;
+ HW_EscWriteByte(u8dummy,u16EscAddrSendMbx);
+
+ /* the Mailbox Read event in the variable ALEventReg shall be reset before calling
+ MBX_MailboxReadInd, where a new mailbox datagram (if available) could be stored in the send mailbox */
+ ALEventReg &= ~(MAILBOX_READ_EVENT);
+ MBX_MailboxReadInd();
+ }
+
+/*ET9300 Project Handler :(#if TEST_APPLICATION) lines 4112 to 4115 deleted*/
+ /* bMbxRepeatToggle holds the last state of the Repeat Bit (Bit 1) */
+
+ if (((sm1Activate & SM_SETTING_REPAET_REQ_MASK) && !bMbxRepeatToggle)
+ || (!(sm1Activate & SM_SETTING_REPAET_REQ_MASK) && bMbxRepeatToggle))
+ {
+ /* Repeat Bit (Bit 1) has toggled, there is a repeat request, in MBX_MailboxRepeatReq the correct
+ response will put in the send mailbox again */
+ MBX_MailboxRepeatReq();
+ /* acknowledge the repeat request after the send mailbox was updated by writing the Repeat Bit
+ in the Repeat Ack Bit (Bit 1) of the PDI Ctrl-Byte of SM 1 (Register 0x80F) */
+/*ET9300 Project Handler :(#if ESC_32BIT_ACCESS #elif ESC_16BIT_ACCESS) lines 4126 to 4150 deleted*/
+ sm1Activate &= SM_SETTING_REPEAT_ACK;
+ HW_EscWriteByte(sm1Activate, (ESC_SM_PDICONTROL_OFFSET + SIZEOF_SM_REGISTER));
+ }
+
+/*ET9300 Project Handler :(#if TEST_APPLICATION) lines 4156 to 4162 deleted*/
+
+ /* Reload the AlEvent because it may be changed due to a SM disable, enable in case of an repeat request */
+ ALEventReg = HW_GetALEventRegister();
+ ALEventReg = SWAPWORD(ALEventReg);
+
+ if ( ALEventReg & (MAILBOX_WRITE_EVENT) )
+ {
+ /* SM 0 (Mailbox Write) event is set, when the mailbox was written from the master,
+ to acknowledge the event the first byte of the mailbox has to be read,
+ which will be done in MBX_CheckAndCopyMailbox */
+ /* the Mailbox Write event in the variable ALEventReg shall be reset before calling
+ MBX_CheckAndCopyMailbox, where the received mailbox datagram will be processed */
+ ALEventReg &= ~(MAILBOX_WRITE_EVENT);
+ MBX_CheckAndCopyMailbox();
+
+/*ET9300 Project Handler :(#if TEST_APPLICATION && !MAILBOX_QUEUE) lines 4178 to 4183 deleted*/
+ }
+ }
+}
+
+
+/** @} */
+
diff --git a/Projects/EFC_EcatDriver/src/ssc/ecatslv.h b/Projects/EFC_EcatDriver/src/ssc/ecatslv.h
new file mode 100644
index 0000000..3008f95
--- /dev/null
+++ b/Projects/EFC_EcatDriver/src/ssc/ecatslv.h
@@ -0,0 +1,465 @@
+/*
+* This source file is part of the EtherCAT Slave Stack Code licensed by Beckhoff Automation GmbH & Co KG, 33415 Verl, Germany.
+* The corresponding license agreement applies. This hint shall not be removed.
+* https://www.beckhoff.com/media/downloads/slave-stack-code/ethercat_ssc_license.pdf
+*/
+
+/**
+ * \addtogroup ESM EtherCAT State Machine
+ * @{
+ */
+
+/**
+\file ecatslv.h
+\author EthercatSSC@beckhoff.com
+
+\version 5.13
+
+ Changes to version V5.12:
+V5.13 EMCY1: update emergency diagcodes for invalid sm configuration
+V5.13 ESM1: local error handling update, ECAT_StateChange triggers only transitions from Op->Any or reject/accept a pending transition
+ Changes to version V5.11:
+V5.12 COE4: add timestamp object (0x10F8) and update diagnosis handling
+V5.12 ECAT6: remove mailbox SyncManager if no mailbox is supported (SM0 Output, SM1 Input)
+ Changes to version V5.10:
+V5.11 ECAT10: change PROTO handling to prevent compiler errors
+V5.11 ECAT4: enhance SM/Sync monitoring for input/output only slaves
+V5.11 ECAT9: add new AL Status Codes (ALSTATUSCODE_FW_SII_NOT_MATCH/0x0006, ALSTATUSCODE_FW_UPDATE_FAILED / 0x0007)
+V5.11 ESM7: "add Sync define for 0x22 (""SYNCTYPE_SM2_SYNCHRON""), support value 0x22 for 0x1C33.1 (SM2 sync)"
+V5.11 HW1: "move hardware independent functions ""HW_DisableSyncManChannel()"", ""HW_EnableSyncManChannel()"", ""HW_GetSyncMan()"", ""HW_ResetALEventMask()"", ""HW_SetALEventMask()"" to ecatalv.c"
+ Changes to version V5.01:
+V5.10 COE1: Define one entry description for all 0x1C3x objects and change data type of SI11,12,13 to UINT16 (according ETG.1020)
+V5.10 ECAT12: Add new AL Status Codes (0x2E,0x52,0x70)
+V5.10 ECAT13: Update Synchronisation handling (FreeRun,SM Sync, Sync0, Sync1)
+ Compare DC UINT configuration (by ESC Config data) vs. DC activation register settings
+ Update 0x1C3x entries
+ Changes to version - :
+V5.01 : Start file change log
+ */
+
+/*-----------------------------------------------------------------------------------------
+------
+------ Includes
+------
+-----------------------------------------------------------------------------------------*/
+
+#include "ecat_def.h"
+
+/*ET9300 Project Handler :(#if EL9800_HW #elif FC1100_HW #elif MCI_HW) lines 47 to 53 deleted*/
+#include "esc.h"
+#include "f2838x_cm_hw.h"
+
+#ifndef _ECATSLV_H_
+#define _ECATSLV_H_
+
+
+/*-----------------------------------------------------------------------------------------
+------
+------ Defines and Types
+------
+-----------------------------------------------------------------------------------------*/
+
+#ifndef OBJGETNEXTSTR
+ /* the old definition was not working with all compilers */
+ /* old: #define OBJGETNEXTSTR(p) ( (OBJCONST CHAR OBJMEM * )( ((UINT32) p) + OBJSTRLEN( (OBJCONST CHAR OBJMEM *) p ) + 1 ) ) */
+ #define OBJGETNEXTSTR(p) ( (OBJCONST CHAR OBJMEM * )( &((p)[OBJSTRLEN( (OBJCONST CHAR OBJMEM *) (p) ) + 1]) ) ) /**< \brief Macro to get next name within the objetc name string*/
+#endif
+
+/*ET9300 Project Handler :(#if BIG_ENDIAN_FORMAT) lines 75 to 115 deleted*/
+#ifndef LO_BYTE
+ #define LO_BYTE 0 /**< \brief LowByte within an WORD*/
+#endif
+
+#ifndef HI_BYTE
+ #define HI_BYTE 1 /**< \brief HighByte within an WORD*/
+#endif
+
+#ifndef LOLO_BYTE
+ #define LOLO_BYTE 0 /**< \brief LowLowByte within an DWORD*/
+#endif
+
+#ifndef LOHI_BYTE
+ #define LOHI_BYTE 1 /**< \brief LowHighByte within an DWORD*/
+#endif
+
+#ifndef HILO_BYTE
+ #define HILO_BYTE 2 /**< \brief HighLowByte within an DWORD*/
+#endif
+
+#ifndef HIHI_BYTE
+ #define HIHI_BYTE 3 /**< \brief HighHighByte within an DWORD*/
+#endif
+
+#ifndef LO_WORD
+ #define LO_WORD 0 /**< \brief LowWord within an DWORD*/
+#endif
+
+#ifndef HI_WORD
+ #define HI_WORD 1 /**< \brief HighWord within an DWORD*/
+#endif
+
+#ifndef SWAPWORD
+ #define SWAPWORD(x) (x) /**< \brief Macro to swap a WORD*/
+#endif
+
+#ifndef SWAPDWORD
+ #define SWAPDWORD(x) (x) /**< \brief Macro to swap a DWORD*/
+#endif
+
+#ifndef LOBYTE
+ #define LOBYTE(x) ((x)&0xFF) /**< \brief LowByte mask*/
+#endif
+
+#ifndef HIBYTE
+ #define HIBYTE(x) (((x)&0xFF00)>>8)/**< \brief HighwByte mask*/
+#endif
+
+#ifndef LOLOBYTE
+ #define LOLOBYTE(x) ((x)&0xFF)/**< \brief LowLowByte mask*/
+#endif
+
+#ifndef LOHIBYTE
+ #define LOHIBYTE(x) (((x)&0xFF00)>>8)/**< \brief LowHighByte mask*/
+#endif
+
+#ifndef HILOBYTE
+ #define HILOBYTE(x) (((x)&0xFF0000)>>16)/**< \brief HighLowByte mask*/
+#endif
+
+#ifndef HIHIBYTE
+ #define HIHIBYTE(x) (((x)&0xFF000000)>>24)/**< \brief HighHighByte mask*/
+#endif
+
+#ifndef LOWORD
+ #define LOWORD(x) ((x)&0xFFFF)/**< \brief LowWord mask*/
+#endif
+
+#ifndef HIWORD
+ #define HIWORD(x) (((x)&0xFFFF0000)>>16)/**< \brief HighByte mask*/
+#endif
+
+#ifndef BIT2BYTE
+ #define BIT2BYTE(x) (((x)+7)>>3) /**< \brief Macro to convert Bit size to Byte size (round up)*/
+#endif
+
+#ifndef BYTE2BIT
+ #define BYTE2BIT(x) ((x)<<3) /**< \brief Macro to convert Byte size to Bit size*/
+#endif
+
+#ifndef BIT2WORD
+ #define BIT2WORD(x) (((x)+15)>>4) /**< \brief Macro to convert Bit size to Word size (round up)*/
+#endif
+
+#ifndef BYTE2WORD
+ #define BYTE2WORD(x) (((x)+1)>>1) /**< \brief Macro to convert Bytes size to Word size (round up)*/
+#endif
+
+#ifndef ROUNDUPBYTE2WORD
+ #define ROUNDUPBYTE2WORD(x) ((((x)+1)>>1)<<1) /**< \brief Round up Byte size to even number of Words*/
+#endif
+
+
+/*---------------------------------------------
+- State defines
+-----------------------------------------------*/
+#define STATE_INIT ((UINT8) 0x01) /**< \brief State INIT*/
+#define STATE_PREOP ((UINT8) 0x02) /**< \brief State PreOP*/
+#define STATE_BOOT ((UINT8) 0x03) /**< \brief State BOOT*/
+#define STATE_SAFEOP ((UINT8) 0x04) /**< \brief State SafeOP*/
+#define STATE_OP ((UINT8) 0x08) /**< \brief State OP*/
+
+#define STATE_MASK ((UINT8) 0x0F) /**< \brief State mask*/
+#define STATE_CHANGE ((UINT8) 0x10) /**< \brief State change (Error indication/acknowledge) mask and value*/
+#define STATE_DEVID ((UINT8) 0x20) /**< \brief Request/response Explicit device ID*/
+#define STATE_VALID(x) ((((x) & STATE_MASK) == STATE_INIT) || (((x) & STATE_MASK) == STATE_PREOP) || (((x) & STATE_MASK) == STATE_SAFEOP) || (((x) & STATE_MASK) == STATE_OP)) /**< \brief Check if one of the mandatory supported state values are set*/
+
+#define BOOT_2_INIT ((UINT8)((STATE_BOOT) << 4) | (STATE_INIT)) /**< \brief State transition BOOT to INIT*/
+#define BOOT_2_PREOP ((UINT8)((STATE_BOOT) << 4) | (STATE_PREOP)) /**< \brief State transition BOOT to INIT*/
+#define BOOT_2_SAFEOP ((UINT8)((STATE_BOOT) << 4) | (STATE_SAFEOP)) /**< \brief State transition BOOT to INIT*/
+#define BOOT_2_OP ((UINT8)((STATE_BOOT) << 4) | (STATE_OP)) /**< \brief State transition BOOT to INIT*/
+
+#define INIT_2_BOOT ((UINT8)((STATE_INIT) << 4) | (STATE_BOOT)) /**< \brief State transition INIT to BOOT*/
+#define PREOP_2_BOOT ((UINT8)((STATE_PREOP) << 4) | (STATE_BOOT)) /**< \brief State transition PREOP to BOOT*/
+#define SAFEOP_2_BOOT ((UINT8)((STATE_SAFEOP) << 4) | (STATE_BOOT)) /**< \brief State transition SAFEOP to BOOT*/
+#define OP_2_BOOT ((UINT8)((STATE_OP) << 4) | (STATE_BOOT)) /**< \brief State transition OP to BOOT*/
+
+#define INIT_2_INIT ((UINT8)((STATE_INIT) << 4) | (STATE_INIT)) /**< \brief State transition INIT to INIT*/
+#define INIT_2_PREOP ((UINT8)((STATE_INIT) << 4) | (STATE_PREOP)) /**< \brief State transition INIT to PREOP*/
+#define INIT_2_SAFEOP ((UINT8)((STATE_INIT) << 4) | (STATE_SAFEOP)) /**< \brief State transition INIT to SAFEOP*/
+#define INIT_2_OP ((UINT8)((STATE_INIT) << 4) | (STATE_OP)) /**< \brief State transition INIT to OP*/
+
+#define PREOP_2_INIT ((UINT8)((STATE_PREOP) << 4) | (STATE_INIT)) /**< \brief State transition PREOP to INIT*/
+#define PREOP_2_PREOP ((UINT8)((STATE_PREOP) << 4) | (STATE_PREOP)) /**< \brief State transition PREOP to PREOP*/
+#define PREOP_2_SAFEOP ((UINT8)((STATE_PREOP) << 4) | (STATE_SAFEOP)) /**< \brief State transition PREOP to SAFEOP*/
+#define PREOP_2_OP ((UINT8)((STATE_PREOP) << 4) | (STATE_OP)) /**< \brief State transition PREOP to OP*/
+
+#define SAFEOP_2_INIT ((UINT8)((STATE_SAFEOP) << 4) | (STATE_INIT)) /**< \brief State transition SAFEOP to INIT*/
+#define SAFEOP_2_PREOP ((UINT8)((STATE_SAFEOP) << 4) | (STATE_PREOP)) /**< \brief State transition SAFEOP to PREOP*/
+#define SAFEOP_2_SAFEOP ((UINT8)((STATE_SAFEOP) << 4) | (STATE_SAFEOP)) /**< \brief State transition SAFEOP to SAFEOP*/
+#define SAFEOP_2_OP ((UINT8)((STATE_SAFEOP) << 4) |( STATE_OP)) /**< \brief State transition SAFEOP to OP*/
+
+#define OP_2_INIT ((UINT8)((STATE_OP) << 4) | (STATE_INIT)) /**< \brief State transition OP to INIT*/
+#define OP_2_PREOP ((UINT8)((STATE_OP) << 4) | (STATE_PREOP)) /**< \brief State transition OP to PREOP*/
+#define OP_2_SAFEOP ((UINT8)((STATE_OP) << 4) | (STATE_SAFEOP)) /**< \brief State transition OP to SAFEOP*/
+#define OP_2_OP ((UINT8)((STATE_OP) << 4) | (STATE_OP)) /**< \brief State transition OP to OP*/
+
+
+/*-------------------------------------------------------------------------------------------------------------------------
+
+ ESM transition error codes
+
+*/
+/*ECATCHANGE_START(V5.13) EMCY1*/
+#define SYNCMANCHSIZE 0x00 /**< \brief Emergency and Diagnosis code for an invalid SyncManager size*/
+#define SYNCMANCHADDRESS 0x01 /**< \brief Emergency and Diagnosis code for an invalid SyncManager address*/
+#define SYNCMANCHSETTINGS 0x02 /**< \brief Emergency and Diagnosis code for an invalid SyncManager settings*/
+#define ERROR_SYNCMANCH(code, channel) ((code)+((channel)<<2)) /**< \brief Macro to add SyncManager channel*/
+
+/*ECATCHANGE_END(V5.13) EMCY1*/
+#define ERROR_SYNCMANCHADDRESS(channel) ((SYNCMANCHADDRESS)+((channel)<<2)) /**< \brief Macro to add SyncManager channel*/
+#define ERROR_SYNCMANCHSIZE(channel) ((SYNCMANCHSIZE)+((channel)<<2)) /**< \brief Macro to add SyncManager channel*/
+#define ERROR_SYNCMANCHSETTINGS(channel) ((SYNCMANCHSETTINGS)+((channel)<<2)) /**< \brief Macro to add SyncManager channel*/
+#define ERROR_SYNCTYPES 0x80 /**< \brief Emergency and Diagnosis code for an invalid Sync types*/
+#define ERROR_DCSYNCCONTROL 0x81 /**< \brief Emergency and Diagnosis code for an invalid DC Sync control*/
+#define ERROR_DCSYNC0CYCLETIME 0x82 /**< \brief Emergency and Diagnosis code for an invalid Sync0 cycle time*/
+#define ERROR_DCSYNC1CYCLETIME 0x83 /**< \brief Emergency and Diagnosis code for an invalid Sync1 cycle time*/
+#define ERROR_DCCYCLEPARAMETER 0x84 /**< \brief Emergency and Diagnosis code for an invalid Cycle parameter*/
+#define ERROR_DCLATCHCONTROL 0x85 /**< \brief Emergency and Diagnosis code for an invalid Latch control*/
+
+#define ERROR_INVALIDSTATE 0xF0 /**< \brief Emergency and Diagnosis code for an invalid State*/
+#define ERROR_NOMEMORY 0xF1 /**< \brief Emergency and Diagnosis code for no memory*/
+#define ERROR_OBJECTDICTIONARY 0xF2 /**< \brief Emergency and Diagnosis code for generic object dictionary error*/
+#define ERROR_NOSYNCMANACCESS 0xF3 /**< \brief Emergency and Diagnosis code for no SyncManager access*/
+#define ERROR_NOOFRXPDOS 0xF4 /**< \brief Emergency and Diagnosis code for no RxPDOs*/
+#define ERROR_NOOFTXPDOS 0xF5 /**< \brief Emergency and Diagnosis code for no TxPDOs*/
+#define ERROR_STATECHANGE 0xF6 /**< \brief Emergency and Diagnosis code state change error*/
+
+#define NOERROR_NOSTATECHANGE 0xFE /**< \brief Indicates no state change*/
+#define NOERROR_INWORK 0xFF /**< \brief Indication for no error but operation is pending*/
+
+#define EMCY_SM_ERRORCODE 0xA000 /**< \brief Emergency and Diagnosis code for an SyncManager error*/
+#define EMCY_SM_DEVICESPECIFIC 0xFF00 /**< \brief Emergency and Diagnosis code for a device specific error*/
+
+
+/*---------------------------------------------
+- AL Status Codes
+-----------------------------------------------*/
+#define ALSTATUSCODE_NOERROR 0x0000 /**< \brief No error*/
+#define ALSTATUSCODE_UNSPECIFIEDERROR 0x0001 /**< \brief Unspecified error*/
+#define ALSTATUSCODE_NOMEMORY 0x0002 /**< \brief No Memory*/
+#define ALSTATUSCODE_INVALID_REVISION 0x0004 /**< \brief Output/Input mapping is not valid for this hardware or software revision (0x1018:03)*/
+#define ALSTATUSCODE_FW_SII_NOT_MATCH 0x0006 /**< \brief Firmware and EEPROM do not match. Slave needs BOOT-INIT transition*/
+#define ALSTATUSCODE_FW_UPDATE_FAILED 0x0007 /**< \brief Firmware update not successful. Old firmware still running*/
+#define ALSTATUSCODE_INVALIDALCONTROL 0x0011 /**< \brief Invalid requested state change*/
+#define ALSTATUSCODE_UNKNOWNALCONTROL 0x0012 /**< \brief Unknown requested state*/
+#define ALSTATUSCODE_BOOTNOTSUPP 0x0013 /**< \brief Bootstrap not supported*/
+#define ALSTATUSCODE_NOVALIDFIRMWARE 0x0014 /**< \brief No valid firmware*/
+#define ALSTATUSCODE_INVALIDMBXCFGINBOOT 0x0015 /**< \brief Invalid mailbox configuration (BOOT state)*/
+#define ALSTATUSCODE_INVALIDMBXCFGINPREOP 0x0016 /**< \brief Invalid mailbox configuration (PreOP state)*/
+#define ALSTATUSCODE_INVALIDSMCFG 0x0017 /**< \brief Invalid sync manager configuration*/
+#define ALSTATUSCODE_NOVALIDINPUTS 0x0018 /**< \brief No valid inputs available*/
+#define ALSTATUSCODE_NOVALIDOUTPUTS 0x0019 /**< \brief No valid outputs*/
+#define ALSTATUSCODE_SYNCERROR 0x001A /**< \brief Synchronization error*/
+#define ALSTATUSCODE_SMWATCHDOG 0x001B /**< \brief Sync manager watchdog*/
+#define ALSTATUSCODE_SYNCTYPESNOTCOMPATIBLE 0x001C /**< \brief Invalid Sync Manager Types*/
+#define ALSTATUSCODE_INVALIDSMOUTCFG 0x001D /**< \brief Invalid Output Configuration*/
+#define ALSTATUSCODE_INVALIDSMINCFG 0x001E /**< \brief Invalid Input Configuration*/
+#define ALSTATUSCODE_INVALIDWDCFG 0x001F /**< \brief Invalid Watchdog Configuration*/
+#define ALSTATUSCODE_WAITFORCOLDSTART 0x0020 /**< \brief Slave needs cold start*/
+#define ALSTATUSCODE_WAITFORINIT 0x0021 /**< \brief Slave needs INIT*/
+#define ALSTATUSCODE_WAITFORPREOP 0x0022 /**< \brief Slave needs PREOP*/
+#define ALSTATUSCODE_WAITFORSAFEOP 0x0023 /**< \brief Slave needs SAFEOP*/
+#define ALSTATUSCODE_INVALIDINPUTMAPPING 0x0024 /**< \brief Invalid Input Mapping*/
+#define ALSTATUSCODE_INVALIDOUTPUTMAPPING 0x0025 /**< \brief Invalid Output Mapping*/
+#define ALSTATUSCODE_INCONSISTENTSETTINGS 0x0026 /**< \brief Inconsistent Settings*/
+#define ALSTATUSCODE_FREERUNNOTSUPPORTED 0x0027 /**< \brief FreeRun not supported*/
+#define ALSTATUSCODE_SYNCHRONNOTSUPPORTED 0x0028 /**< \brief SyncMode not supported*/
+#define ALSTATUSCODE_FREERUNNEEDS3BUFFERMODE 0x0029 /**< \brief FreeRun needs 3Buffer Mode*/
+#define ALSTATUSCODE_BACKGROUNDWATCHDOG 0x002A /**< \brief Background Watchdog*/
+#define ALSTATUSCODE_NOVALIDINPUTSANDOUTPUTS 0x002B /**< \brief No Valid Inputs and Outputs*/
+#define ALSTATUSCODE_FATALSYNCERROR 0x002C /**< \brief Fatal Sync Error*/
+#define ALSTATUSCODE_NOSYNCERROR 0x002D /**< \brief No Sync Error*/
+#define ALSTATUSCODE_CYCLETIMETOOSMALL 0x002E /**< \brief EtherCAT cycle time smaller Minimum Cycle Time supported by slave*/
+#define ALSTATUSCODE_DCINVALIDSYNCCFG 0x0030 /**< \brief Invalid DC SYNCH Configuration*/
+#define ALSTATUSCODE_DCINVALIDLATCHCFG 0x0031 /**< \brief Invalid DC Latch Configuration*/
+#define ALSTATUSCODE_DCPLLSYNCERROR 0x0032 /**< \brief PLL Error*/
+#define ALSTATUSCODE_DCSYNCIOERROR 0x0033 /**< \brief DC Sync IO Error*/
+#define ALSTATUSCODE_DCSYNCMISSEDERROR 0x0034 /**< \brief DC Sync Timeout Error*/
+#define ALSTATUSCODE_DCINVALIDSYNCCYCLETIME 0x0035 /**< \brief DC Invalid Sync Cycle Time*/
+#define ALSTATUSCODE_DCSYNC0CYCLETIME 0x0036 /**< \brief DC Sync0 Cycle Time*/
+#define ALSTATUSCODE_DCSYNC1CYCLETIME 0x0037 /**< \brief DC Sync1 Cycle Time*/
+#define ALSTATUSCODE_MBX_AOE 0x0041 /**< \brief MBX_AOE*/
+#define ALSTATUSCODE_MBX_EOE 0x0042 /**< \brief MBX_EOE*/
+#define ALSTATUSCODE_MBX_COE 0x0043 /**< \brief MBX_COE*/
+#define ALSTATUSCODE_MBX_FOE 0x0044 /**< \brief MBX_FOE*/
+#define ALSTATUSCODE_MBX_SOE 0x0045 /**< \brief MBX_SOE*/
+#define ALSTATUSCODE_MBX_VOE 0x004F /**< \brief MBX_VOE*/
+#define ALSTATUSCODE_EE_NOACCESS 0x0050 /**< \brief EEPROM no access*/
+#define ALSTATUSCODE_EE_ERROR 0x0051 /**< \brief EEPROM Error*/
+#define ALSTATUSCODE_EXT_HARDWARE_NOT_READY 0x0052 /**< \brief External hardware not ready. This AL Status Code should be used if the EtherCAT-Slave refused the state transition due to an external connection to another device or signal is missing*/
+#define ALSTATUSCODE_DEVICE_IDENT_VALUE_UPDATED 0x0061 /**< \brief In legacy identification mode (dip switch mapped to register 0x12) this error is returned if the EEPROM ID value does not match to dipswitch value*/
+#define ALSTATUSCODE_MODULE_ID_LIST_NOT_MATCH 0x0070 /**< \brief Detected Module Ident List (0xF030) and Configured Module Ident List (0xF050) does not match*/
+#define ALSTATUSCODE_SUPPLY_VOLTAGE_TOO_LOW 0x0080 /**< \brief The slave supply voltage is too low*/
+#define ALSTATUSCODE_SUPPLY_VOLTAGE_TOO_HIGH 0x0081 /**< \brief The slave supply voltage is too high*/
+#define ALSTATUSCODE_TEMPERATURE_TOO_LOW 0x0082 /**< \brief The slave temperature is too low*/
+#define ALSTATUSCODE_TEMPERATURE_TOO_HIGH 0x0083 /**< \brief The slave temperature is too high*/
+
+
+
+/*---------------------------------------------
+- Configured Sync Type (0x1C32.1 / 0x1C33.1)
+-----------------------------------------------*/
+#define SYNCTYPE_FREERUN 0x0000 /**< \brief Sync type FreeRun*/
+#define SYNCTYPE_SM_SYNCHRON 0x0001 /**< \brief SyncManager synchron (synchron to the corresponding SM, 0x1C32.1 -> SM2 ; 0x1C33.1 -> SM3) */
+#define SYNCTYPE_SM2_SYNCHRON 0x0022 /**< \brief SyncManager2 synchron (only used for 0x1C33.1)*/
+#define SYNCTYPE_DCSYNC0 0x0002 /**< \brief Sync type Sync0 synchron*/
+#define SYNCTYPE_DCSYNC1 0x0003 /**< \brief Sync type Sync1 synchron*/
+
+
+/*---------------------------------------------
+- AL Event masks
+-----------------------------------------------*/
+#define AL_CONTROL_EVENT ((UINT16) 0x01) /**< \brief AL Control event*/
+#define SYNC0_EVENT ((UINT16) 0x04) /**< \brief Sync0 event*/
+#define SYNC1_EVENT ((UINT16) 0x08) /**< \brief Sync1 event*/
+#define SM_CHANGE_EVENT ((UINT16) 0x10) /**< \brief SyncManager changed event*/
+#define EEPROM_CMD_PENDING ((UINT16) 0x20) /**< \brief EEPROM command pending*/
+#define MAILBOX_WRITE_EVENT ((UINT16) 0x0100) /**< \brief MBoxOut write event*/
+#define MAILBOX_READ_EVENT ((UINT16) 0x0200) /**< \brief MBoxIn read event*/
+#define PROCESS_OUTPUT_EVENT ((UINT16) 0x0400) /**< \brief Output process data write event*/
+#define PROCESS_INPUT_EVENT ((UINT16) 0x0800) /**< \brief Input process data read event*/
+/*ET9300 Project Handler :(#if MAILBOX_SUPPORTED #else) lines 380 to 383 deleted*/
+
+#define MAILBOX_WRITE 0 /**< \brief SyncManager ID for MBoxOut (master to slave)*/
+#define MAILBOX_READ 1 /**< \brief SyncManager ID for MBoxIn (slave to master)*/
+#define PROCESS_DATA_OUT 2 /**< \brief SyncManager ID for output process data (master to slave)*/
+#define PROCESS_DATA_IN 3 /**< \brief SyncManager ID for input process data (slave to master)*/
+/*ET9300 Project Handler :(#if MAILBOX_SUPPORTED #else) lines 390 to 393 deleted*/
+
+
+
+
+/*---------------------------------------------
+- Codes for LED
+ bit 7: invert flag
+ bit 6: toggle (if toggle == 1 and number of flashes == 0 => infinite toggle)
+ bit 5: fast toggle flag (50ms cycle)
+ bit 4-0: number of flashes
+-----------------------------------------------*/
+#define LED_OFF 0x00 /**< \brief LED off*/
+#define LED_FLICKERING 0x60 /**< \brief LED flickering*/
+#define LED_BLINKING 0x40 /**< \brief LED blinking*/
+#define LED_SINGLEFLASH 0x41 /**< \brief LED single flash*/
+#define LED_DOUBLEFLASH 0x42 /**< \brief LED double flash*/
+#define LED_INVERT_DOUBLEFLASH 0xC2 /**< \brief LED invert double flash*/
+#define LED_ON 0x01 /**< \brief LED on*/
+
+/*ET9300 Project Handler :(#elif ESC_SUPPORT_ECAT_LED) lines 414 to 422 deleted*/
+
+
+#define MEMORY_START_ADDRESS 0x1000 /**< \brief ESC DPRAM start address*/
+
+
+#ifndef DC_SYNC_ACTIVE
+ #define DC_SYNC_ACTIVE ESC_DC_SYNC0_ACTIVE_MASK /**< \brief Expected activated Sync signals by the master*/
+#endif
+#ifndef DC_EVENT_MASK
+ #define DC_EVENT_MASK PROCESS_OUTPUT_EVENT /**< \brief AL Event mask (value of register 0x204) in case of DC synchronisation*/
+/*ET9300 Project Handler :(#if MAX_PD_OUTPUT_SIZE > 0 #else) lines 434 to 436 deleted*/
+#endif
+
+
+#endif //_ECATSLV_H_
+
+#if defined(_ECATSLV_) && (_ECATSLV_ == 1)
+ #define PROTO
+#else
+ #define PROTO extern
+#endif
+/*-----------------------------------------------------------------------------------------
+------
+------ Global Variables
+------
+-----------------------------------------------------------------------------------------*/
+/*ET9300 Project Handler :(#if BOOTSTRAPMODE_SUPPORTED) lines 452 to 454 deleted*/
+PROTO BOOL bEcatOutputUpdateRunning; /**< \brief Indicates the OP state, will be set in StartOutputHandler
+ and reset in StopOutputHandler*/
+
+PROTO BOOL bEcatInputUpdateRunning; /**< \brief Indicates the SAFEOP or OP state, will be set in StartInputHandler
+ and reset in Stop InputHandler*/
+
+PROTO BOOL bEcatFirstOutputsReceived; /**< \brief Indicates if outputs were received (SM2-event)
+ or inputs were read (SM3-event, if the output size is 0),
+ has to be set by the application and reset in StopOutputHandler*/
+
+PROTO BOOL bWdTrigger; /**< \brief Indicates that the SM2 WD trigger bit (0x814 bit6) is set.*/
+
+PROTO BOOL bDcSyncActive; /**< \brief Indicates that the Distributed Clocks synchronization is active,*/
+
+PROTO INT16 EsmTimeoutCounter; /**< \brief Counter used to detect an ESM timeout.
+ -1 indicates a deactivated counter and 0 is expired*/
+
+#define MAX_SM_EVENT_MISSED 4 /**< \brief threshold of max missed counter value (0x1C32.11 / 0x1C33.11)*/
+
+/*ET9300 Project Handler :(#if DC_SUPPORTED) lines 476 to 498 deleted*/
+
+/*ET9300 Project Handler :(#if !COE_SUPPORTED) lines 500 to 502 deleted*/
+
+
+PROTO BOOL bEscIntEnabled; /**< \brief Indicates that the ESC interrupt is enabled (SM2/3 or SYNC0/1-event),
+ will be set in StartInputHandler and reset in StopInputHandler*/
+
+PROTO BOOL b3BufferMode; /**< \brief Indicates that inputs and outputs are running in 3-Buffer-Mode*/
+
+/*ECATCHANGE_START(V5.13) ESM1*/
+PROTO UINT16 u16LocalErrorCode; /**< \brief Reason for local error*/
+PROTO UINT8 u8LocalErrorState; /**< \brief State of the current local error (lower state could be set by the master)*/
+/*ECATCHANGE_END(V5.13) ESM1*/
+PROTO BOOL bApplEsmPending; /**< \brief Indicates if the local application ESM function need to be called from Al_ConntrolRes (is true if NOERR_INWORK is returned by generic ESM function)*/
+PROTO BOOL bEcatWaitForAlControlRes; /**< \brief Contains the information that the state machine waits for an acknowledge
+ for the last AL_ControlInd from the application/generic stack*/
+
+PROTO UINT16 nEcatStateTrans; /**< \brief Current state transition*/
+
+PROTO UINT8 u8EcatErrorLed; /**< \brief Current value of the error LED*/
+
+PROTO UINT8 u8EcatRunLed; /**< \brief Current value of the run LED*/
+
+PROTO UINT16 nPdInputSize; /**< \brief Contains the input size (SM3 size)/SM2 if no outputs are supported, has to be written by the application*/
+
+PROTO UINT16 nPdOutputSize; /**< \brief Contains the output size (SM2 size), has to be written by the application*/
+
+PROTO UINT8 nMaxSyncMan; /**< \brief Contains the maximum number of Sync Manager channels, will be initialized in ECAT_Main*/
+
+PROTO UINT16 nMaxEscAddress; /**< \brief Max supported address by the ESC (register(0x1000) + size of the supported DPRAM in Byte)*/
+
+PROTO UINT8 nAlStatus; /**< \brief Contains the actual AL Status, will be written in AL_ControlInd*/
+
+/*ET9300 Project Handler :(#if EXPLICIT_DEVICE_ID) lines 536 to 538 deleted*/
+
+PROTO UINT16 EcatWdValue; /**< \brief Contains the value of the watchdog in ms, will be written in StartInputHandler.
+ In case that the ESC watchdog feature is used this variable just indicates if the watchdog is enabled or disabled*/
+/*ET9300 Project Handler :(#if !ESC_SM_WD_SUPPORTED) lines 542 to 546 deleted*/
+PROTO UINT16 nEscAddrOutputData; /**< \brief Contains the SM address for the output process data*/
+PROTO UINT16 nEscAddrInputData; /**< \brief Contains the SM address for the input process data*/
+
+
+/*-----------------------------------------------------------------------------------------
+------
+------ Global Functions
+------
+-----------------------------------------------------------------------------------------*/
+PROTO void EnableSyncManChannel(UINT8 channel);
+PROTO void DisableSyncManChannel(UINT8 channel);
+PROTO TSYNCMAN ESCMEM *GetSyncMan(UINT8 channel);
+PROTO void SetALStatus(UINT8 alStatus, UINT16 alStatusCode);
+PROTO void AL_ControlInd(UINT8 alControl, UINT16 alStatusCode);
+/*ET9300 Project Handler :(#if !ESC_SM_WD_SUPPORTED) lines 565 to 569 deleted*/
+/*ET9300 Project Handler :(#if DC_SUPPORTED) lines 570 to 572 deleted*/
+PROTO void CheckIfEcatError(void);
+PROTO void ECAT_Init(void);
+
+PROTO void ECAT_Main(void);
+
+#undef PROTO
+/** @}*/
diff --git a/Projects/EFC_EcatDriver/src/ssc/esc.h b/Projects/EFC_EcatDriver/src/ssc/esc.h
new file mode 100644
index 0000000..6fd056f
--- /dev/null
+++ b/Projects/EFC_EcatDriver/src/ssc/esc.h
@@ -0,0 +1,204 @@
+/*
+* This source file is part of the EtherCAT Slave Stack Code licensed by Beckhoff Automation GmbH & Co KG, 33415 Verl, Germany.
+* The corresponding license agreement applies. This hint shall not be removed.
+* https://www.beckhoff.com/media/downloads/slave-stack-code/ethercat_ssc_license.pdf
+*/
+
+/**
+ * \addtogroup ESCRegister ESC Register
+ * @{
+ */
+
+/**
+\file esc.h
+\author EthercatSSC@beckhoff.com
+\brief EtherCAT Slave Controller related defines and Types
+
+\version 5.10
+
+ Changes to version V5.01:
+V5.10 ESC1: Update address register offset for 32Bit ESC access
+V5.10 ESC2: Check if defined SM settings do not exceed the available DPRAM range (in error case AL Status 0x14 is returned)
+V5.10 ESC3: Handle DC cControl register values in case of 32Bit ESC access (a Sync activation mask need to defined/used)
+ Changes to version - :
+V5.01 : Start file change log
+ */
+
+/*-----------------------------------------------------------------------------------------
+------
+------ Includes
+------
+-----------------------------------------------------------------------------------------*/
+#include "ecat_def.h"
+
+#ifndef _ESC_H_
+#define _ESC_H_
+
+/*-----------------------------------------------------------------------------------------
+------
+------ Defines and Types
+------
+-----------------------------------------------------------------------------------------*/
+
+#define SIZEOF_SM_REGISTER 8 /**< \brief Each SyncManger has 8Byte Configuration/Status Registers*/
+#define MAX_NO_OF_SYNC_MAN 16/**< \brief Maximum Number of SyncManager channels supported by an ESC*/
+
+#define BL_PAGE_SIZE 512
+
+/*---------------------------------------------
+- ESC Offsets (Detailed Information about the registers are located in the ESC Datasheets e.g. ET1100 Datasheet http://www.beckhoff.com/english.asp?download/ethercat_development_products.htm?id=71003127100387)
+-----------------------------------------------*/
+#define ESC_INFO_OFFSET 0x0000 /**< \brief ESC information registers startoffset*/
+
+#define ESC_COMM_INFO_OFFSET 0x0004 /**< \brief Communication information registers startoffset*/
+
+/*ET9300 Project Handler :(#if ESC_32BIT_ACCESS) lines 54 to 59 deleted*/
+#define ESC_DPRAM_SIZE_OFFSET 0x0006 /**< \brief Register Description: Size of the supported DPRAM in KB*/
+/*ET9300 Project Handler :(#if ESC_16BIT_ACCESS) lines 61 to 65 deleted*/
+#define ESC_SM_CHANNELS_OFFSET 0x0005 /**< \brief Register Description: Number of supported SyncManager channels (or entities) of the EtherCAT Slave Controller*/
+
+#define ESC_FEATURES_OFFSET 0x0008 /**< \brief Register indicating ESC features*/
+#define ESC_DC_32BIT_MASK 0x00000008 /**< \brief register 0x0008.3 indicates if the DC Unit supports 32Bit/64Bit DC*/
+
+/*ET9300 Project Handler :(#if ESC_32BIT_ACCESS) lines 73 to 75 deleted*/
+
+#define ESC_SLAVE_ADDRESS_OFFSET 0x0010 /**< \brief Register Description: Address used for node addressing (FPxx commands)*/
+
+
+
+#define ESC_AL_CONTROL_OFFSET 0x0120 /**< \brief Register Description: Initiate State Transition of the Device State Machine*/
+#define ESC_AL_STATUS_OFFSET 0x0130 /**< \brief Register Description: Actual State of the Device State Machine*/
+#define ESC_AL_STATUS_CODE_OFFSET 0x0134 /**< \brief Register Description: AL Status Code*/
+
+#define ESC_RUN_LED_OVERRIDE 0x0138 /**< \brief Register Description: Set Ecat Run indication via ESC. (not all ESC types support this feature)*/
+#define ESC_ERROR_LED_OVERRIDE 0x0139 /**< \brief Register Description: Set Ecat Error indication via ESC. (not all ESC types support this feature)*/
+
+#define ESC_PDI_CONTROL_OFFSET 0x0140 /**< \brief Register Description: Specifies the process data interface*/
+/*ET9300 Project Handler :(#if ESC_32BIT_ACCESS) lines 89 to 91 deleted*/
+#define ESC_DEVICE_EMULATION 0x0100 /**< \brief Device emulation bit*/
+
+/*ET9300 Project Handler :(#if ESC_32BIT_ACCESS || ESC_16BIT_ACCESS) lines 95 to 99 deleted*/
+#define ESC_PDI_CONFIGURATION 0x0151 /**< \brief Register Description: PDI configuration register (values defined by the ESC configuration data)*/
+#define ESC_SYNC0_MAPPED_TO_ALEVENT 0x08 /**< \brief bit indicating if the Sync0 event is mapped to the AL Event register*/
+#define ESC_SYNC1_MAPPED_TO_ALEVENT 0x80 /**< \brief bit indicating if the Sync1 event is mapped to the AL Event register*/
+
+
+#define ESC_AL_EVENTMASK_OFFSET 0x0204 /**< \brief Register Description: AL Event masking of the AL Event Request register Events for mapping to PDI IRQ signal*/
+#define ESC_AL_EVENT_OFFSET 0x0220 /**< \brief Register Description: "Mirror" register for ESC events*/
+
+#define ESC_WD_DIVIDER_OFFSET 0x0400 /**< \brief Register Description: Number of 25 MHz tics (minus 2) that represents the basic watchdog increment. (Default value is 100us = 2498)*/
+
+#define ESC_PD_WD_TIME 0x0420 /**< \brief Register Description: Number of basic watchdog increments (Default value with Watchdog divider 100us means 100ms Watchdog)*/
+#define ESC_PD_WD_STATE 0x0440 /**< \brief Register Description: Watchdog Status of Process Data (triggered by SyncManagers)*/
+/*ET9300 Project Handler :(#if ESC_32BIT_ACCESS) lines 113 to 115 deleted*/
+#define ESC_PD_WD_TRIGGER_MASK 0x0001 /**< \brief Trigger state of the process data watchdog*/
+
+#define ESC_EEPROM_CONFIG_OFFSET 0x0500 /**< \brief Register Description: EEPROM Access Configuration*/
+/*ET9300 Project Handler :(#if ESC_32BIT_ACCESS) lines 120 to 138 deleted*/
+/*EEPROM config and access state bit mask (based on "ESC_EEPROM_CONFIG_OFFSET") - START*/
+#define ESC_EEPROM_ASSIGN_TO_PDI_MASK 0x0001 /**< \brief Description (0x500.0): PDI has EEPROM control*/
+#define ESC_EEPROM_LOCKED_BY_PDI_MASK 0x0100 /**< \brief Description (0x500.8): PDI locked EEPROM access*/
+/*EEPROM config and access state bit mask (based on "ESC_EEPROM_CONFIG_OFFSET") - END*/
+
+#define ESC_EEPROM_CONTROL_OFFSET 0x0502
+/* EEPROM command and status bit masks (based on "ESC_EEPROM_CONTROL_OFFSET") - START*/
+#define ESC_EEPROM_SUPPORTED_READBYTES_MASK 0x0040 /**< \brief Description (0x502.6): Supported number of EEPROM read bytes: 0-> 4 Bytes; 1 -> 8 Bytes*/
+#define ESC_EEPROM_CMD_MASK 0x0700 /**< \brief Description (0x502.8:10): Command bit mask*/
+#define ESC_EEPROM_CMD_READ_MASK 0x0100 /**< \brief Description (0x502.8): Currently executed read command*/
+#define ESC_EEPROM_CMD_WRITE_MASK 0x0200 /**< \brief Description (0x502.9): Initialize Write Command*/
+#define ESC_EEPROM_CMD_RELOAD_MASK 0x0400 /**< \brief Description (0x502.10): Trigger EEPROM reload*/
+#define ESC_EEPROM_ERROR_MASK 0x7800 /**< \brief Description : Mask all EEPROM error bits; Checksum error (0x0502.11); EEPROM not loaded (0x0502.12); Missing EEPROM Acknowledge (0x0502.13); Write Error (0x0502.14)*/
+#define ESC_EEPROM_ERROR_CRC 0x0800 /**< \brief Description (0x502.11): EEPROM CRC Error*/
+#define ESC_EEPROM_ERROR_LOAD 0x1000 /**< \brief Description (0x502.11): EEPROM loading status (0 = OK)*/
+#define ESC_EEPROM_ERROR_CMD_ACK 0x2000 /**< \brief Description (0x502.13): EEPROM Acknowledge/Command*/
+#define ESC_EEPROM_BUSY_MASK 0x8000 /**< \brief Description (0x502.15): EEPROM Busy*/
+/* EEPROM command and status bit masks (based on "ESC_EEPROM_CONTROL_OFFSET") - END*/
+#define ESC_EEPROM_ADDRESS_OFFSET 0x0504
+#define ESC_EEPROM_DATA_OFFSET 0x0508
+
+#define ESC_SYNCMAN_REG_OFFSET 0x0800 /**< \brief Register Description: Start address of the SyncManager Configuration/Staus registers*/
+#define ESC_SYNCMAN_CONTROL_OFFSET 0x0804 /**< \brief Register Description: SyncManager Setting Register*/
+
+#define ESC_SYNCMAN_STATUS_OFFSET 0x0805 /**< \brief Register Description: SyncManager Status Register*/
+
+#define ESC_SYNCMAN_ACTIVE_OFFSET 0x0806 /**< \brief Register Description: SyncManager Activation Register*/
+
+#define ESC_SM_PDICONTROL_OFFSET 0x0807
+
+#define ESC_SYSTEMTIME_OFFSET 0x0910 /**< \brief Register Description: Local copy of the System Time*/
+
+#define ESC_DC_UNIT_CONTROL_OFFSET 0x0980 /**< \brief Register Description: Control registers for Cycle and Sync Unit (can be predefined with the "AssignActivate" Element in the device description, for further information see ETG.2000)*/
+/*ET9300 Project Handler :(#if ESC_32BIT_ACCESS #elif ESC_16BIT_ACCESS) lines 179 to 190 deleted*/
+#define ESC_DC_SYNC_ACTIVATION_OFFSET 0x0981 /**< \brief Register Description: Sync Configuration*/
+#define ESC_DC_SYNC_UNIT_ACTIVE_MASK 0x01 /**< \brief Description (0x981.0): Sync Out Unit is activated*/
+#define ESC_DC_SYNC0_ACTIVE_MASK 0x02 /**< \brief Description (0x981.1): Sync0 generation is activated*/
+#define ESC_DC_SYNC1_ACTIVE_MASK 0x04 /**< \brief Description (0x981.2): Sync1 generation is activated*/
+#define ESC_DC_SYNC_UNIT_AUTO_ACTIVE_MASK 0x08 /**< \brief Description (0x980.11): Sync Out Unit is activated automatic when System time was written*/
+
+#define ESC_DC_SYNC_STATUS 0x098C /**< \brief Register Description: register 0x98E and 0x98F reflecting the status of Sync0 and Sync1*/
+
+#define ESC_DC_SYNC0_CYCLETIME_OFFSET 0x09A0 /**< \brief Register Description: 32Bit Time between two consecutive SYNC0 pulses in ns*/
+#define ESC_DC_SYNC1_CYCLETIME_OFFSET 0x09A4 /**< \brief Register Description: 32Bit Time between two consecutive SYNC1 pulses in ns*/
+
+
+/*ET9300 Project Handler :(#if FC1100_HW) lines 205 to 207 deleted*/
+
+
+/*---------------------------------------------
+- Sync Manager
+-----------------------------------------------*/
+/** \brief SyncManager register structure*/
+typedef struct STRUCT_PACKED_START
+{
+/*ET9300 Project Handler :(#if ESC_32BIT_ACCESS) lines 217 to 259 deleted*/
+
+ UINT16 PhysicalStartAddress; /**< \brief SyncManager address*/
+ UINT16 Length; /**< \brief SyncManager length*/
+
+/*ET9300 Project Handler :(#if ESC_16BIT_ACCESS) lines 264 to 303 deleted*/
+//ESC_8BIT ACCESS
+ UINT8 Settings[4]; /**< \brief Register values 0x0804 : 0x0807*/
+
+/*Defines to access :
+* - SM Control register 0x0804
+*/
+/*ET9300 Project Handler :(#if BIG_ENDIAN_16BIT) lines 310 to 312 deleted*/
+#define SM_SETTING_CONTROL_OFFSET 0 /**< \brief Offset to value of register 0x0804*/
+#define SM_SETTING_MODE_MASK 0x02 /**< \brief SyncManager mode mask*/
+#define SM_SETTING_MODE_THREE_BUFFER_VALUE 0x00 /**< \brief SyncManager 3Buffer mode value*/
+#define SM_SETTING_MODE_ONE_BUFFER_VALUE 0x02 /**< \brief SyncManager 1Buffer mode value*/
+#define SM_SETTING_DIRECTION_MASK 0x0C /**< \brief SyncManager direction mask*/
+#define SM_SETTING_DIRECTION_READ_VALUE 0x00 /**< \brief SyncManager read direction*/
+#define SM_SETTING_DIRECTION_WRITE_VALUE 0x04 /**< \brief SyncManager write direction*/
+#define SM_SETTING_WATCHDOG_VALUE 0x40 /**< \brief SyncManager watchdog value*/
+
+/*Defines to access :
+* - SM Status register 0x0805
+*/
+/*ET9300 Project Handler :(#if BIG_ENDIAN_16BIT) lines 326 to 328 deleted*/
+#define SM_SETTING_STATUS_OFFSET 1 /**< \brief Offset to value of register 0x0805*/
+#define SM_STATUS_MBX_BUFFER_FULL 0x08 /**< \brief Indicates in one buffer mode if buffer was completely written (based on "ESC_SYNCMAN_STATUS_OFFSET")*/
+/*Defines to access :
+* - SM Active register 0x0806
+*/
+/*ET9300 Project Handler :(#if BIG_ENDIAN_16BIT) lines 335 to 337 deleted*/
+#define SM_SETTING_ACTIVATE_OFFSET 2 /**< \brief Offset to value of register 0x0806*/
+#define SM_SETTING_ENABLE_VALUE 0x01 /**< \brief SyncManager enable*/
+#define SM_SETTING_REPAET_REQ_MASK 0x02 /**< \brief SyncManager Repeat request*/
+#define SM_SETTING_REPEAT_REQ_SHIFT 0 /**< \brief SyncManager Repeat request shift*/
+
+/*Defines to access :
+* - SM PDI COntrol register 0x0807
+*/
+/*ET9300 Project Handler :(#if BIG_ENDIAN_16BIT) lines 347 to 349 deleted*/
+#define SM_SETTING_PDICONTROL_OFFSET 3 /**< \brief Offset to value of register 0x0807*/
+#define SM_SETTING_PDI_DISABLE 0x01 /**< \brief Bit0 of register 0x0807 (if 1 SM is disabled from PDI)*/
+#define SM_SETTING_REPEAT_ACK 0x02 /**< \brief Bit1 of register 0x0807*/
+}STRUCT_PACKED_END
+TSYNCMAN;
+
+
+/*ET9300 Project Handler :(#if FC1100_HW) lines 361 to 363 deleted*/
+
+#endif //_ESC_H_
+/** @}*/
diff --git a/Projects/EFC_EcatDriver/src/ssc/f2838x_cm_hw.c b/Projects/EFC_EcatDriver/src/ssc/f2838x_cm_hw.c
new file mode 100644
index 0000000..f6908e8
--- /dev/null
+++ b/Projects/EFC_EcatDriver/src/ssc/f2838x_cm_hw.c
@@ -0,0 +1,24 @@
+//###########################################################################
+//
+// FILE: f2838x_cm_hw.c
+//
+// TITLE: F2838x CM EtherCAT Hardware API Mapping
+//
+// This file contains the source for any EtherCAT stack APIs that require
+// extended or modified functionality.
+//
+//###########################################################################
+// $TI Release: F2838x EtherCAT Software v2.01.00.00 $
+// $Release Date: August 31 2020 $
+// $Copyright: Copyright (C) 2020 Texas Instruments Incorporated -
+// http://www.ti.com/ ALL RIGHTS RESERVED $
+//###########################################################################
+
+//
+// Included Files
+//
+#include "f2838x_cm_hw.h"
+
+//
+// End of File
+//
diff --git a/Projects/EFC_EcatDriver/src/ssc/f2838x_cm_hw.h b/Projects/EFC_EcatDriver/src/ssc/f2838x_cm_hw.h
new file mode 100644
index 0000000..fba97e3
--- /dev/null
+++ b/Projects/EFC_EcatDriver/src/ssc/f2838x_cm_hw.h
@@ -0,0 +1,114 @@
+//###########################################################################
+//
+// FILE: f2838x_cm_hw.h
+//
+// TITLE: F2838x CM EtherCAT Hardware API Mapping
+//
+// This file maps the F2838x CM HAL APIs to the EtherCAT stack API naming.
+//
+//###########################################################################
+// $TI Release: F2838x EtherCAT Software v2.01.00.00 $
+// $Release Date: August 31 2020 $
+// $Copyright: Copyright (C) 2020 Texas Instruments Incorporated -
+// http://www.ti.com/ ALL RIGHTS RESERVED $
+//###########################################################################
+
+#ifndef F2838X_CM_HW_H
+#define F2838X_CM_HW_H
+
+//
+// Included Files
+//
+#include
+#include
+#include "esc.h"
+
+
+//
+// Defines - Mapping HAL APIs to Stack APIS
+//
+
+//
+// Interrupt APIs
+//
+#define DISABLE_ESC_INT() _disable_IRQ()
+#define ENABLE_ESC_INT() _enable_IRQ()
+
+//
+// Timer APIs
+//
+#define ECAT_TIMER_INC_P_MS ESC_timerIncPerMilliSec()
+#define HW_GetTimer() ESC_getTimer()
+#define HW_ClearTimer() ESC_clearTimer()
+
+//
+// System APIs
+//
+#define HW_Init() ESC_initHW()
+#define HW_Release() ESC_releaseHW()
+#define HW_SetLed(RunLed, ErrLed) ESC_setLed(RunLed, ErrLed)
+
+//
+// Read and Write APIs
+//
+#define HW_EscRead(pData, Address, Len) ESC_readBlock(pData, Address, Len)
+#define HW_EscReadIsr(pData, Address, Len) ESC_readBlockISR(pData, Address, Len)
+#define HW_EscReadDWord(DWordValue, Address) ((DWordValue) = ESC_readDWord(Address))
+#define HW_EscReadDWordIsr(DWordValue, Address) ((DWordValue) = ESC_readDWordISR(Address))
+#define HW_EscReadWord(WordValue, Address) ((WordValue) = ESC_readWord(Address))
+#define HW_EscReadWordIsr(WordValue, Address) ((WordValue) = ESC_readWordISR(Address))
+#define HW_EscReadByte(ByteValue, Address) ((ByteValue) = ESC_readByte(Address))
+#define HW_EscReadByteIsr(ByteValue, Address) ((ByteValue) = ESC_readByteISR(Address))
+#define HW_EscReadMbxMem(pData, Address, Len) ESC_readBlock(pData, Address, Len)
+
+#define HW_EscWrite(pData, Address, Len) ESC_writeBlock(pData, Address, Len)
+#define HW_EscWriteIsr(pData, Address, Len) ESC_writeBlockISR(pData, Address, Len)
+#define HW_EscWriteDWord(DWordValue, Address) ESC_writeDWord(DWordValue, Address)
+#define HW_EscWriteDWordIsr(DWordValue, Address) ESC_writeDWordISR(DWordValue, Address)
+#define HW_EscWriteWord(WordValue, Address) ESC_writeWord(WordValue, Address)
+#define HW_EscWriteWordIsr(WordValue, Address) ESC_writeWordISR(WordValue, Address)
+#define HW_EscWriteByte(ByteValue, Address) ESC_writeByte(ByteValue, Address)
+#define HW_EscWriteByteIsr(ByteValue, Address) ESC_writeByteISR(ByteValue, Address)
+#define HW_EscWriteMbxMem(pData, Address, Len) ESC_writeBlock(pData, Address, Len)
+
+//
+// Application Layer Event APIs
+//
+#define HW_GetALEventRegister() ESC_readWord(ESC_AL_EVENT_OFFSET)
+#define HW_GetALEventRegister_Isr() ESC_readWordISR(ESC_AL_EVENT_OFFSET)
+
+
+//
+// Function Prototypes
+//
+extern uint16_t ESC_initHW(void);
+extern void ESC_releaseHW(void);
+extern void ESC_setLed(uint8_t RunLed, uint8_t ErrLed);
+
+extern uint32_t ESC_getTimer(void);
+extern void ESC_clearTimer(void);
+extern uint32_t ESC_timerIncPerMilliSec(void);
+
+extern void ESC_readBlock(uint8_t *pData, uint16_t Address, uint16_t Len);
+extern void ESC_readBlockISR(uint8_t *pData, uint16_t Address, uint16_t Len);
+extern uint32_t ESC_readDWord(uint16_t Address);
+extern uint32_t ESC_readDWordISR(uint16_t Address);
+extern uint16_t ESC_readWord(uint16_t Address);
+extern uint16_t ESC_readWordISR(uint16_t Address);
+extern uint8_t ESC_readByte(uint16_t Address);
+extern uint8_t ESC_readByteISR(uint16_t Address);
+
+extern void ESC_writeBlock(uint8_t *pData, uint16_t Address, uint16_t Len);
+extern void ESC_writeBlockISR(uint8_t *pData, uint16_t Address, uint16_t Len);
+extern void ESC_writeDWord(uint32_t DWordValue, uint16_t Address);
+extern void ESC_writeDWordISR(uint32_t DWordValue, uint16_t Address);
+extern void ESC_writeWord(uint16_t WordValue, uint16_t Address);
+extern void ESC_writeWordISR(uint16_t WordValue, uint16_t Address);
+extern void ESC_writeByte(uint8_t WordValue, uint16_t Address);
+extern void ESC_writeByteISR(uint8_t WordValue, uint16_t Address);
+
+#endif // F2838X_CM_HW_H
+
+//
+// End of File
+//
diff --git a/Projects/EFC_EcatDriver/src/ssc/f2838x_cm_system.c b/Projects/EFC_EcatDriver/src/ssc/f2838x_cm_system.c
new file mode 100644
index 0000000..0da1f1a
--- /dev/null
+++ b/Projects/EFC_EcatDriver/src/ssc/f2838x_cm_system.c
@@ -0,0 +1,37 @@
+//###########################################################################
+//
+// FILE: f2838x_cm_system.c
+//
+// TITLE: F2838x CM EtherCAT System APIs
+//
+// This file contains the source for any device system APIs that require
+// modification for compatibility with EtherCAT stack usage.
+//
+//###########################################################################
+// $TI Release: F2838x EtherCAT Software v2.01.00.00 $
+// $Release Date: August 31 2020 $
+// $Copyright: Copyright (C) 2020 Texas Instruments Incorporated -
+// http://www.ti.com/ ALL RIGHTS RESERVED $
+//###########################################################################
+
+//
+// Included Files
+//
+#include "f2838x_cm_system.h"
+
+//
+// F2838XCM_strcpy - String copy wrapper for compatibility with EtherCAT stack
+// calls to "strncpy"
+//
+void F2838XCM_strcpy(void * __restrict dest, const void * __restrict src,
+ size_t n)
+{
+ //
+ // Call standard strncpy from string.h
+ //
+ strncpy((char *)dest, (const char *)src, (size_t)n);
+}
+
+//
+// End of File
+//
diff --git a/Projects/EFC_EcatDriver/src/ssc/f2838x_cm_system.h b/Projects/EFC_EcatDriver/src/ssc/f2838x_cm_system.h
new file mode 100644
index 0000000..0cdca15
--- /dev/null
+++ b/Projects/EFC_EcatDriver/src/ssc/f2838x_cm_system.h
@@ -0,0 +1,35 @@
+//###########################################################################
+//
+// FILE: f2838x_cm_system.h
+//
+// TITLE: F2838x CM EtherCAT System APIs
+//
+// This file contains the function prototypes for any device system APIs that
+// require modification for compatibility with EtherCAT stack usage.
+//
+//###########################################################################
+// $TI Release: F2838x EtherCAT Software v2.01.00.00 $
+// $Release Date: August 31 2020 $
+// $Copyright: Copyright (C) 2020 Texas Instruments Incorporated -
+// http://www.ti.com/ ALL RIGHTS RESERVED $
+//###########################################################################
+
+#ifndef F2838X_CM_SYSTEM_H
+#define F2838X_CM_SYSTEM_H
+
+//
+// Included Files
+//
+#include
+
+//
+// Function Prototypes
+//
+void F2838XCM_strcpy(void * __restrict dest, const void * __restrict src,
+ size_t n);
+
+#endif // F2838X_CM_SYSTEM_H
+
+//
+// End of File
+//
diff --git a/Projects/EFC_EcatDriver/src/ssc/mailbox.c b/Projects/EFC_EcatDriver/src/ssc/mailbox.c
new file mode 100644
index 0000000..1af6040
--- /dev/null
+++ b/Projects/EFC_EcatDriver/src/ssc/mailbox.c
@@ -0,0 +1,1036 @@
+/*
+* This source file is part of the EtherCAT Slave Stack Code licensed by Beckhoff Automation GmbH & Co KG, 33415 Verl, Germany.
+* The corresponding license agreement applies. This hint shall not be removed.
+* https://www.beckhoff.com/media/downloads/slave-stack-code/ethercat_ssc_license.pdf
+*/
+
+/**
+\addtogroup Mailbox Mailbox Functions
+@{
+*/
+
+/**
+\file mailbox.c
+\author EthercatSSC@beckhoff.com
+\brief Implementation
+
+ Description of the mailbox buffer handling (MAILBOX_QUEUE = 0):
+There are two mailbox buffer for sending and receiving mailbox services.
+Normal operation:
+When starting the mailbox handler psWriteMbx contains mailbox buffer 1,
+psReadMbx, psRepeatMbx and psStoreMbx are 0.
+In this state a repeat request would be ignored because there was no service sent yet.
+When the first mailbox service is sent (in MBX_CopyToSendMailbox), psWriteMbx gets mailbox buffer 2
+and psReadMbx gets the sent mailbox buffer 1, psRepeatMbx and psStoreMbx are still 0.
+When the first mailbox service was read from the master, the sent mailbox buffer 1 is stored
+in psRepeatMbx (in MBX_MailboxReadInd).
+After that psReadMbx gets always the actual sent mailbox buffer, psWriteMbx is set to 0 (another
+received mailbox service from the master will not be handled until the sent mailbox service was read
+and MBX_MailboxReadInd was called).
+When the mailbox service is read, psWriteMbx gets the Buffer of psRepeatMbx and psRepeatMbx gets the
+buffer of psReadMbx.
+Repeat Request from the master:
+When a Repeat from the master is requested (MBX_MailboxRepeatReq), there are three different possibilities:
+1. no mailbox service was sent since the mailbox handler was started (psRepeatMbx = 0): nothing to do
+2. the acknowledge of the last sent mailbox service was received (in MBX_MailboxReadInd) (bSendMbxIsFull = 0):
+the last sent mailbox service (psRepeatMbx) will be sent again (in MBX_CopyToSendMailbox) and stored in psReadMbx,
+psRepeatMbx will be set to 0
+3. the acknowledge of the last sent mailbox service was not received (psReadMbx and psRepeatMbx contain different buffers,
+psReadMbx is still in the mailbox (because MBX_MailboxReadInd is not called yet, bSendMbxIsFull = 1):
+psReadMbx will be deleted in the mailbox (call of DisableSyncManChannel and EnableSyncManChannel) and
+stored in psStoreMbx, psRepeatMbx will be sent again (in MBX_CopyToSendMailbox) and stored in psReadMbx,
+psRepeatMbx will be set to 0.
+When the repeated mailbox service was sent (call of MBX_MailboxReadInd), psReadMbx will be stored in psRepeatMbx
+and psStoreMbx will be sent (in MBX_CopyToSendMailbox) and stored in psReadMbx, psStoreMbx will be set to 0.
+
+ Description of the mailbox buffer handling (MAILBOX_QUEUE = 1):
+There are two mailbox buffer for sending and receiving mailbox services.
+Normal operation (psWriteMbx is only used for local storage):
+When starting the mailbox handler psReadMbx, psRepeatMbx and psStoreMbx are 0.
+In this state a repeat request would be ignored because there was no service sent yet.
+When a mailbox service is received from the master (in MBX_CheckAndCopyMailbox) a mailbox buffer
+will be get with APPL_AllocMailboxBuffer and the corresponding protocol service function will
+be called (in MBX_WriteMailboxInd). This buffer shall be used for the protocol service response.
+When the first mailbox service is sent (in MBX_CopyToSendMailbox), psReadMbx gets the sent mailbox buffer,
+psRepeatMbx and psStoreMbx are still 0.
+When the first mailbox service was read from the master, the sent mailbox buffer (psReadMbx) is stored
+in psRepeatMbx (in MBX_MailboxReadInd).
+After that psReadMbx gets always the actual sent mailbox buffer (in MBX_CopyToSendMailbox)
+When the mailbox service is read, psRepeatMbx is returned (with APPL_FreeMailboxBuffer) and psRepeatMbx gets the
+buffer of psReadMbx.
+Repeat Request from the master:
+When a Repeat from the master is requested (MBX_MailboxRepeatReq), there are three different possibilities:
+1. no mailbox service was sent since the mailbox handler was started (psRepeatMbx = 0): nothing to do
+2. the acknowledge of the last sent mailbox service was received (in MBX_MailboxReadInd) (bSendMbxIsFull = 0):
+the last sent mailbox service (psRepeatMbx) will be sent again (in MBX_CopyToSendMailbox) and stored in psReadMbx,
+psRepeatMbx will be set to 0
+3. the acknowledge of the last sent mailbox service was not received (psReadMbx and psRepeatMbx contain different buffers,
+psReadMbx is still in the mailbox (because MBX_MailboxReadInd is not called yet, bSendMbxIsFull = 1):
+psReadMbx will be deleted in the mailbox (call of DisableSyncManChannel and EnableSyncManChannel) and
+stored in psStoreMbx, psRepeatMbx will be sent again (in MBX_CopyToSendMailbox) and stored in psReadMbx,
+psRepeatMbx will be set to 0.
+When the repeated mailbox service was sent (call of MBX_MailboxReadInd), psReadMbx will be stored in psRepeatMbx
+and psStoreMbx will be sent (in MBX_CopyToSendMailbox) and stored in psReadMbx, psStoreMbx will be set to 0.
+
+\version 5.13
+
+ Changes to version V5.12:
+V5.13 EOE1:
+V5.13 MBX2: clear unused bytes before write mailbox response
+V5.13 MBX3: fix potential double free memory and lost of last read mailbox data
+V5.13 TEST3: 0x2040.4 send ARP on unsupported mailbox request
+ Changes to version V5.11:
+V5.12 EOE5: free pending buffer in EoE_Init, EoE_Init is called on startup and PI transition
+V5.12 MBX1: use only 16Bit variables to write the last byte of the mailbox buffer in case of ESC_16BIT_Access,update clear message queue in case of stop mailbox handler
+V5.12 MBX2: do not set the pending indication in case of a EoE request, application triggered eoe datagram update
+V5.12 MBX3: handle incomplete mailbox communication
+V5.12 MBX4: in case of a disable mailbox queue and two consecutive foe uploads the mailbox receive handler is blocked
+ Changes to version V5.10:
+V5.11 ECAT10: change PROTO handling to prevent compiler errors
+V5.11 ECAT7: add missing big endian swapping
+V5.11 HW1: "move hardware independent functions ""HW_DisableSyncManChannel()"", ""HW_EnableSyncManChannel()"", ""HW_GetSyncMan()"", ""HW_ResetALEventMask()"", ""HW_SetALEventMask()"" to ecatalv.c"
+V5.11 MBX2: "check in IP if enough dynamic memory is available to handle mailbox communication, if it is not the case the mbx error ""no memory"" is returned on any mbx request"
+V5.11 MBX3: set application triggered emergency and EoE data to pending if no mailbox queue is supported and another mailbox request is currently handled, Handle only one mailbox request at a time (in case that MAILBPX_QUEUE is disabled)
+V5.11 TEST4: add new mailbox test behavior (the master mailbox cnt shall be incremented by 1 and the slave mailbox cnt is alternating)
+ Changes to version V5.01:
+V5.10 EOE3: Change local send frame pending indication variable to a global variable (it need to be resetted if the mailbox is stopped and a frame is pending)
+V5.10 ESC6: Update SyncManager register size (only for 8Bit ESC access)
+V5.10 MBX2: Allocate only memory for current configured mailbox size (max supported size was allocated before)
+ Changes to version V5.0:
+V5.01 ESC2: Add missed value swapping
+V5.01 MBX2: Return an error if length specified in mailbnox header is too large.
+ Changes to version V4.40:
+V5.0 ECAT3: Global dummy variables used for dummy ESC operations.
+V5.0 ESC1: ESC 32Bit Access added.
+V5.0 MBX2: Prevent double swapping (MBX repeat service) of MBX length field.
+V5.0 MBX4: Unlock SM buffer based on SM state.
+ Changes to version V4.11:
+V4.40 MBX8: Handle pending mailbox data even if mailbox queue is enabled
+V4.40 MBX7: Reset SyncManger 1 Repeat Acknowledge bit if local variable is reset
+V4.40 EMCY2: Send queued emergency messages
+V4.40 BOOT2: Support only FoE in Bootstrap state
+V4.40 MBX5: Prevent multiple free buffer
+V4.40 MBX6: change return value if no mailbox buffer is available
+ Changes to version V4.08:
+V4.11 MBX 1: free some dynamic memory to avoid memory leaks in the mailbox queue
+ Changes to version V4.07:
+V4.10 MBX 1: check Mailbox message buffer and print emergency messages
+ during state change Init -> PreOP
+ Changes to version V4.07:
+V4.08 MBX 1: The mailbox queue was added (switch MAILBOX_QUEUE), if the
+ mailbox should be handled in the ESC-Interrupt Service Routine
+ the defines ENTER_MBX_CRITICAL and LEAVE_MBX_CRITICAL could be used
+ to disable the interrupts or change the priority
+V4.08 AOE 1: AoE was added
+ Changes to version V4.06:
+V4.07 ECAT 1: The sources for SPI and MCI were merged (in ecat_def.h
+ set the switch MCI_HW to 1 when using the MCI,
+ set the switch SPI_HW to 1 when using the SPI
+*/
+
+
+/*---------------------------------------------------------------------------------------
+------
+------ Includes
+------
+---------------------------------------------------------------------------------------*/
+
+#include "ecat_def.h"
+
+
+#include "ecatslv.h"
+
+/*ET9300 Project Handler :(#if TEST_APPLICATION) lines 143 to 145 deleted*/
+
+
+#define _MAILBOX_ 1
+#include "mailbox.h"
+#undef _MAILBOX_
+/*remove definition of _MAILBOX_ (#ifdef is used in mailbox.h)*/
+
+/*ET9300 Project Handler :(#if SOE_SUPPORTED) lines 153 to 155 deleted*/
+/*ET9300 Project Handler :(#if AOE_SUPPORTED) lines 156 to 158 deleted*/
+#include "ecatcoe.h"
+#include "sdoserv.h"
+/*ET9300 Project Handler :(#if EOE_SUPPORTED) lines 165 to 167 deleted*/
+/*ET9300 Project Handler :(#if FOE_SUPPORTED) lines 168 to 170 deleted*/
+/*ET9300 Project Handler :(#if EMERGENCY_SUPPORTED) lines 171 to 173 deleted*/
+
+
+/*--------------------------------------------------------------------------------------
+------
+------ internal Types and Defines
+------
+--------------------------------------------------------------------------------------*/
+
+/*--------------------------------------------------------------------------------------
+------
+------ internal Variables
+------
+--------------------------------------------------------------------------------------*/
+/*variables are declared in ecatslv.c*/
+/*ET9300 Project Handler :(#if ESC_32BIT_ACCESS #elif ESC_16BIT_ACCESS) lines 188 to 192 deleted*/
+ extern VARVOLATILE UINT8 u8dummy;
+
+ BOOL bNoMbxMemoryAvailable; /**< \brief Indicates if enough dynamic memory is available to handle at least one mailbox datagram */
+
+/*--------------------------------------------------------------------------------------
+------
+------ internal functions
+------
+--------------------------------------------------------------------------------------*/
+
+/*---------------------------------------------------------------------------------------
+------
+------ functions
+------
+---------------------------------------------------------------------------------------*/
+
+
+///////////////////////////////////////////////////////////////////////////////////////////
+//
+// PutInMbxQueue
+//
+
+UINT8 PutInMbxQueue(TMBX MBXMEM * pMbx, TMBXQUEUE MBXMEM * pQueue)
+{
+ UINT16 lastInQueue;
+ ENTER_MBX_CRITICAL;
+
+
+ lastInQueue = pQueue->lastInQueue+1;
+ if (lastInQueue == pQueue->maxQueueSize)
+ {
+ // Umbruch der Queue
+ lastInQueue = 0;
+ }
+
+ if (pQueue->firstInQueue == lastInQueue)
+ {
+ // Ueberlauf der Queue -> letztes Element wieder herausnehmen
+ LEAVE_MBX_CRITICAL;
+ return MBXERR_NOMOREMEMORY;
+ }
+
+ pQueue->queue[pQueue->lastInQueue] = pMbx;
+ pQueue->lastInQueue = lastInQueue;
+
+ LEAVE_MBX_CRITICAL;
+
+ return 0;
+}
+
+///////////////////////////////////////////////////////////////////////////////////////////
+//
+// GetOutOfMbxQueue
+//
+
+TMBX MBXMEM * GetOutOfMbxQueue(TMBXQUEUE MBXMEM * pQueue)
+{
+ TMBX MBXMEM * pMbx;
+ ENTER_MBX_CRITICAL;
+
+ if (pQueue->firstInQueue != pQueue->lastInQueue)
+ {
+ // Queue ist nicht leer
+ UINT16 firstInQueue = pQueue->firstInQueue;
+ pMbx = pQueue->queue[firstInQueue];
+ firstInQueue++;
+ pQueue->firstInQueue = firstInQueue;
+
+ if (pQueue->firstInQueue == pQueue->maxQueueSize)
+ {
+ // Umbruch der Queue
+ pQueue->firstInQueue = 0;
+ }
+ }
+ else
+ {
+ pMbx = 0;
+ }
+
+
+ LEAVE_MBX_CRITICAL;
+
+ return pMbx;
+}
+
+/////////////////////////////////////////////////////////////////////////////////////////
+/**
+ \brief This function intialize the Mailbox Interface.
+*////////////////////////////////////////////////////////////////////////////////////////
+
+void MBX_Init(void)
+{
+
+ u16ReceiveMbxSize = MIN_MBX_SIZE;
+ u16SendMbxSize = MAX_MBX_SIZE;
+ u16EscAddrReceiveMbx = MIN_MBX_WRITE_ADDRESS;
+ u16EscAddrSendMbx = MIN_MBX_READ_ADDRESS;
+
+ sMbxReceiveQueue.firstInQueue = 0;
+ sMbxReceiveQueue.lastInQueue = 0;
+ sMbxReceiveQueue.maxQueueSize = MAX_MBX_QUEUE_SIZE;
+ sMbxSendQueue.firstInQueue = 0;
+ sMbxSendQueue.lastInQueue = 0;
+ sMbxSendQueue.maxQueueSize = MAX_MBX_QUEUE_SIZE;
+ psWriteMbx = NULL;
+/*ET9300 Project Handler :(#if MAILBOX_QUEUE #else) lines 304 to 306 deleted*/
+
+/*ET9300 Project Handler :(#if EOE_SUPPORTED) lines 308 to 310 deleted*/
+
+ psRepeatMbx = NULL;
+ psReadMbx = NULL;
+ psStoreMbx = NULL;
+
+ bMbxRepeatToggle = FALSE;
+ /*Reset Repeat acknowledge bit of SyncManager1 (0x80F bit 2)*/
+/*ET9300 Project Handler :(#if ESC_32BIT_ACCESS #elif ESC_16BIT_ACCESS) lines 318 to 332 deleted*/
+ {
+ UINT8 sm1Activate = 0;
+ HW_EscReadByte(sm1Activate,(ESC_SM_PDICONTROL_OFFSET + SIZEOF_SM_REGISTER));
+ sm1Activate &= ~0x02;
+ HW_EscWriteByte(sm1Activate,(ESC_SM_PDICONTROL_OFFSET + SIZEOF_SM_REGISTER));
+ }
+ bMbxRunning = FALSE;
+ bSendMbxIsFull = FALSE;
+ bReceiveMbxIsLocked = FALSE;
+ u8MailboxSendReqStored = 0;
+ u8MbxWriteCounter = 0;
+ u8MbxReadCounter = 0;
+/*ET9300 Project Handler :(#if !MAILBOX_QUEUE) lines 346 to 348 deleted*/
+}
+
+/////////////////////////////////////////////////////////////////////////////////////////
+/**
+
+ \brief This function includes the state transition from INIT to
+ \brief PRE-OPERATIONAL in the EtherCAT Slave corresponding to
+ \brief local management service Start Mailbox Handler
+ \brief it is checked if the mailbox areas overlaps each other
+ \brief and the Sync Manager channels 0 and 1 are enabled.
+ \brief This function shall only be called if mailbox is supported.
+*////////////////////////////////////////////////////////////////////////////////////////
+UINT16 MBX_StartMailboxHandler(void)
+{
+ UINT16 result = 0;
+
+ /* get address of the receive mailbox sync manager (SM0) */
+ TSYNCMAN ESCMEM * pSyncMan = (TSYNCMAN ESCMEM *)GetSyncMan(MAILBOX_WRITE);
+
+/*ET9300 Project Handler :(#if ESC_32BIT_ACCESS) lines 368 to 373 deleted*/
+ /* store size of the receive mailbox */
+ u16ReceiveMbxSize = pSyncMan->Length;
+ /* store the address of the receive mailbox */
+ u16EscAddrReceiveMbx = pSyncMan->PhysicalStartAddress;
+
+ /* get address of the send mailbox sync manager (SM1) */
+ pSyncMan =(TSYNCMAN ESCMEM *) GetSyncMan(MAILBOX_READ);
+
+/*ET9300 Project Handler :(#if ESC_32BIT_ACCESS) lines 383 to 388 deleted*/
+ /* store the size of the send mailbox */
+ u16SendMbxSize = pSyncMan->Length;
+ /* store the address of the send mailbox */
+ u16EscAddrSendMbx = pSyncMan->PhysicalStartAddress;
+
+ // HBu 02.05.06: it should be checked if there are overlaps in the sync manager areas
+ if ((u16EscAddrReceiveMbx + u16ReceiveMbxSize) > u16EscAddrSendMbx && (u16EscAddrReceiveMbx < (u16EscAddrSendMbx + u16SendMbxSize)))
+ {
+ return ALSTATUSCODE_INVALIDMBXCFGINPREOP;
+ }
+/*ET9300 Project Handler :(#if AOE_SUPPORTED) lines 400 to 408 deleted*/
+
+/*ET9300 Project Handler :(#if FOE_SUPPORTED) lines 410 to 412 deleted*/
+
+ /* enable the receive mailbox sync manager channel */
+ EnableSyncManChannel(MAILBOX_WRITE);
+ /* enable the send mailbox sync manager channel */
+ EnableSyncManChannel(MAILBOX_READ);
+
+ psWriteMbx = (TMBX MBXMEM *) APPL_AllocMailboxBuffer(u16ReceiveMbxSize);
+ if(psWriteMbx == NULL)
+ {
+ bNoMbxMemoryAvailable = TRUE;
+
+ //check if at least enough memory for an mailbox error is available (other wise stop the state transition)
+ psWriteMbx = (TMBX MBXMEM *) APPL_AllocMailboxBuffer(10); /* a mailbox error datagram length*/
+ if(psWriteMbx == NULL)
+ {
+ result = ALSTATUSCODE_NOMEMORY;
+ }
+
+ APPL_FreeMailboxBuffer(psWriteMbx);
+ psWriteMbx = NULL;
+ }
+ else
+ {
+ bNoMbxMemoryAvailable = FALSE;
+ APPL_FreeMailboxBuffer(psWriteMbx);
+ psWriteMbx = NULL;
+ }
+
+ return result;
+}
+
+/////////////////////////////////////////////////////////////////////////////////////////
+/**
+
+ \brief This function includes the state transition from
+ \brief PRE-OPERATIONAL to INIT in the EtherCAT Slave corresponding to
+ \brief local management service Stop Mailbox Handler
+ \brief the Sync Manager channels 0 and 1 are disabled
+*////////////////////////////////////////////////////////////////////////////////////////
+
+void MBX_StopMailboxHandler(void)
+{
+ TMBX MBXMEM * pMbx;
+
+ /* mailbox handler is stopped */
+ bMbxRunning = FALSE;
+ /* disable the receive mailbox sync manager channel */
+ DisableSyncManChannel(MAILBOX_WRITE);
+ /* disable the send mailbox sync manager channel */
+ DisableSyncManChannel(MAILBOX_READ);
+ /* initialize variables again */
+
+
+ if (psRepeatMbx != NULL)
+ {
+ APPL_FreeMailboxBuffer(psRepeatMbx);
+ }
+
+ if (psStoreMbx != NULL && psStoreMbx != psRepeatMbx)
+ {
+ APPL_FreeMailboxBuffer(psStoreMbx);
+ }
+
+ if (psReadMbx != NULL && psReadMbx != psRepeatMbx && psReadMbx != psStoreMbx)
+ {
+ APPL_FreeMailboxBuffer(psReadMbx);
+ }
+
+/*ET9300 Project Handler :(#if MAILBOX_QUEUE #else) lines 486 to 488 deleted*/
+
+ SDOS_ClearPendingResponse();
+
+/*ET9300 Project Handler :(#if EOE_SUPPORTED) lines 494 to 496 deleted*/
+
+/*ET9300 Project Handler :(#if FOE_SUPPORTED) lines 498 to 500 deleted*/
+
+ psWriteMbx = NULL;
+ psRepeatMbx = NULL;
+ psReadMbx = NULL;
+ psStoreMbx = NULL;
+
+ bMbxRepeatToggle = FALSE;
+ /*Reset Repeat acknowledge bit of SyncManager1 (0x080F bit 2)*/
+/*ET9300 Project Handler :(#if ESC_32BIT_ACCESS #elif ESC_16BIT_ACCESS) lines 511 to 525 deleted*/
+ {
+ UINT8 sm1Activate = 0;
+ HW_EscReadByte(sm1Activate,(ESC_SM_PDICONTROL_OFFSET + SIZEOF_SM_REGISTER));
+ sm1Activate &= ~0x02;
+ HW_EscWriteByte(sm1Activate,(ESC_SM_PDICONTROL_OFFSET + SIZEOF_SM_REGISTER));
+ }
+ bSendMbxIsFull = FALSE;
+ bReceiveMbxIsLocked = FALSE;
+ u8MailboxSendReqStored = 0;
+ u8MbxWriteCounter = 0;
+ u8MbxReadCounter = 0;
+
+ do
+ {
+ pMbx = GetOutOfMbxQueue(&sMbxReceiveQueue);
+ if (pMbx)
+ {
+ APPL_FreeMailboxBuffer(pMbx);
+ }
+ } while (pMbx != NULL);
+
+ do
+ {
+ pMbx = GetOutOfMbxQueue(&sMbxSendQueue);
+ if (pMbx)
+ {
+ APPL_FreeMailboxBuffer(pMbx);
+ }
+ } while (pMbx != NULL);
+/*ET9300 Project Handler :(#if MAILBOX_QUEUE #else) lines 557 to 559 deleted*/
+
+/*ET9300 Project Handler :(#if EMERGENCY_SUPPORTED) lines 561 to 563 deleted*/
+}
+
+/////////////////////////////////////////////////////////////////////////////////////////
+/**
+ \param pMbx Pointer to the received Mailbox command from Master.
+
+ \brief The function checks the mailbox header for the requested service and calls the
+ \brief corresponding XXXX_ServiceInd-function
+*////////////////////////////////////////////////////////////////////////////////////////
+
+UINT8 MailboxServiceInd(TMBX MBXMEM *pMbx)
+{
+ UINT8 result;
+
+/*ET9300 Project Handler :(#if BOOTSTRAPMODE_SUPPORTED) lines 578 to 584 deleted*/
+
+ switch ( (pMbx->MbxHeader.Flags[MBX_OFFS_TYPE] & MBX_MASK_TYPE) >> MBX_SHIFT_TYPE )
+ {
+/*ET9300 Project Handler :(#if AOE_SUPPORTED) lines 588 to 594 deleted*/
+ case MBX_TYPE_COE:
+ /* CoE datagram received */
+ result = COE_ServiceInd((TCOEMBX MBXMEM *) pMbx);
+ break;
+
+/*ET9300 Project Handler :(#if SOE_SUPPORTED) lines 602 to 608 deleted*/
+/*ET9300 Project Handler :(#if EOE_SUPPORTED) lines 609 to 619 deleted*/
+/*ET9300 Project Handler :(#if FOE_SUPPORTED) lines 620 to 626 deleted*/
+/*ET9300 Project Handler :(#if VOE_SUPPORTED) lines 627 to 633 deleted*/
+ default:
+
+/*ET9300 Project Handler :(#if TEST_APPLICATION && EOE_SUPPORTED) lines 636 to 704 deleted*/
+ result = MBXERR_UNSUPPORTEDPROTOCOL;
+ break;
+ }
+
+ return result;
+}
+
+/////////////////////////////////////////////////////////////////////////////////////////
+/**
+ \param pMbx Pointer to the received Mailbox command from Master.
+
+ \brief This function is called when the Master has written the Receive-Mailbox.
+ \brief It will only be called if the send mailbox is empty, that a response for the
+ \brief mailbox service could be stored.
+ \brief The function checks the mailbox header for the requested service and calls the
+ \brief corresponding XXXX_ServiceInd-function
+*////////////////////////////////////////////////////////////////////////////////////////
+
+void MBX_MailboxWriteInd(TMBX MBXMEM *pMbx)
+{
+ UINT8 result = 0;
+ UINT8 mbxCounter = pMbx->MbxHeader.Flags[MBX_OFFS_COUNTER] >> MBX_SHIFT_COUNTER;
+ UINT16 MbxLen = SWAPWORD(pMbx->MbxHeader.Length);
+
+ if(MbxLen > MAX_MBX_SIZE)
+ {
+ /* Mailbox error response: size specified in mailbox header too large*/
+ pMbx->MbxHeader.Length = 4;
+ pMbx->MbxHeader.Flags[MBX_OFFS_TYPE] &= ~MBX_MASK_TYPE;
+ pMbx->Data[0] = SWAPWORD(MBXSERVICE_MBXERRORCMD);
+ pMbx->Data[1] = SWAPWORD(MBXERR_INVALIDSIZE);
+ MBX_MailboxSendReq(pMbx, 0);
+ }
+ else
+ /* if the mailbox datagram counter (Bit 4-6 of Byte 5 of the mailbox header) is unequal zero,
+ the master supports the mailbox data link layer,
+ in that case a repeated mailbox write request will be detected, if the counter is unequal zero
+ and unchanged */
+ if ( mbxCounter == 0 || mbxCounter != u8MbxWriteCounter )
+ {
+/*ET9300 Project Handler :(#if TEST_APPLICATION) lines 745 to 769 deleted*/
+ /* new mailbox service received */
+ /* mbxCounter = 0: old EtherCAT master */
+ /* new MBX service received, store the new mailbox counter */
+ u8MbxWriteCounter = mbxCounter;
+
+ {
+ /* check the protocol type and call the XXXX_ServiceInd-function */
+
+ result = PutInMbxQueue(pMbx, &sMbxReceiveQueue);
+/*ET9300 Project Handler :(#if MAILBOX_QUEUE #else) lines 780 to 782 deleted*/
+ }
+
+ if ( result != 0 )
+ {
+ /* Mailbox error response: type 0 (mailbox service protocol) */
+ pMbx->MbxHeader.Length = 4;
+ pMbx->MbxHeader.Flags[MBX_OFFS_TYPE] &= ~MBX_MASK_TYPE;
+ pMbx->Data[0] = SWAPWORD(MBXSERVICE_MBXERRORCMD);
+ pMbx->Data[1] = SWAPWORD(result);
+ MBX_MailboxSendReq(pMbx, 0);
+ }
+ }
+ else
+ {
+ // the mailbox buffer has to be freed here
+ APPL_FreeMailboxBuffer(pMbx);
+ pMbx = NULL;
+
+/*ET9300 Project Handler :(#if MAILBOX_QUEUE #else) lines 802 to 805 deleted*/
+ }
+}
+
+/////////////////////////////////////////////////////////////////////////////////////////
+/**
+ \brief This function is called when the Master has read the Send-Mailbox.
+*////////////////////////////////////////////////////////////////////////////////////////
+
+void MBX_MailboxReadInd(void)
+{
+ bSendMbxIsFull = FALSE;
+
+/*ET9300 Project Handler :(#if TEST_APPLICATION && EOE_SUPPORTED) lines 818 to 823 deleted*/
+ // HBu 02.05.06: the pointer psRepeatMbx is only free if there is no stored
+ // mailbox service from the last repeat
+ if (psRepeatMbx && psStoreMbx == NULL)
+ {
+ /* the last sent service is not stored for repeat any longer */
+/*ECATCHANGE_START(V5.13) MBX3*/
+ if (psReadMbx != psRepeatMbx)
+ {
+ APPL_FreeMailboxBuffer(psRepeatMbx);
+ psRepeatMbx = NULL;
+ }
+/*ECATCHANGE_END(V5.13) MBX3*/
+
+/*ET9300 Project Handler :(#if MAILBOX_QUEUE #else) lines 838 to 840 deleted*/
+ }
+
+ /* the actual sent service has to be stored for repeat */
+ psRepeatMbx = psReadMbx;
+
+ if ( psStoreMbx )
+ {
+ /* there was a buffer stored */
+ MBX_CopyToSendMailbox(psStoreMbx);
+ /* no more buffer to be stored any more */
+ psStoreMbx = NULL;
+ }
+ else
+ {
+ TMBX MBXMEM* pMbx = GetOutOfMbxQueue(&sMbxSendQueue);
+
+
+ if (pMbx)
+ {
+ MBX_CopyToSendMailbox(pMbx);
+ }
+ }
+
+ if ( u8MailboxSendReqStored )
+ {
+ /* there are mailbox services stored to be sent */
+/*ET9300 Project Handler :(#if EMERGENCY_SUPPORTED) lines 869 to 880 deleted*/
+ if ( u8MailboxSendReqStored & COE_SERVICE )
+ {
+ UINT8 result = 0;
+ /* reset the flag indicating that CoE service to be sent was stored */
+ u8MailboxSendReqStored &= ~COE_SERVICE;
+
+ /* call CoE function that will send the stored CoE service */
+ result = COE_ContinueInd(psWriteMbx);
+
+ if (result != 0)
+ {
+ /*Set the pending CoE indication is an error occurred during the continue indication*/
+ u8MailboxSendReqStored |= COE_SERVICE;
+ }
+ }
+ else
+/*ET9300 Project Handler :(#if SOE_SUPPORTED) lines 899 to 908 deleted*/
+/*ET9300 Project Handler :(#if FOE_SUPPORTED) lines 909 to 918 deleted*/
+/*ET9300 Project Handler :(#if VOE_SUPPORTED) lines 919 to 928 deleted*/
+/*ECATCHANGE_START(V5.13) EOE1*/
+/*pending EoE commands are handled from the MBX_Main function*/
+/*ECATCHANGE_END(V5.13) EOE1*/
+
+/*ET9300 Project Handler :(#if MAILBOX_QUEUE #else) lines 934 to 944 deleted*/
+ {
+ }
+ }
+}
+
+/////////////////////////////////////////////////////////////////////////////////////////
+/**
+ \brief This function is called if the Master has requested a resending of the last
+ \brief sent mailbox
+*////////////////////////////////////////////////////////////////////////////////////////
+
+void MBX_MailboxRepeatReq(void)
+{
+ if (psRepeatMbx)
+ {
+ TMBX MBXMEM *pMbx = psRepeatMbx;
+
+ /* send mailbox service stored for repeat */
+ /* HBu 13.10.06: if a repeat request is received (again) before the previously repeated mailbox telegram
+ was read from the master (psStoreMbx != NULL) the next mailbox telegram to be sent is still in the
+ read mailbox so it has not to updated exchanged */
+ ENTER_MBX_CRITICAL;
+
+ if (bSendMbxIsFull && psStoreMbx == NULL)
+ {
+ /* mailbox is full, take the buffer off */
+ DisableSyncManChannel(MAILBOX_READ);
+
+ /* store the buffer to be sent next */
+ psStoreMbx = psReadMbx;
+ /* enable the mailbox again */
+ EnableSyncManChannel(MAILBOX_READ);
+
+ /* HBu 15.02.06: flag has to be reset otherwise the mailbox service
+ will not be copied by MBX_CopyToSendMailbox */
+ bSendMbxIsFull = FALSE;
+ }
+
+/*ET9300 Project Handler :(#if BIG_ENDIAN_FORMAT) lines 983 to 987 deleted*/
+
+ MBX_CopyToSendMailbox(pMbx);
+ // HBu 17.06.06: psRepeatMbx has to be set to 0, when it was repeated, otherwise it would be returned twice
+ // to the empty queue (MAILBOX_QUEUE=1) or a buffer get lost, if the the next repeat request will happen before
+ // the repeated buffer was read
+ psRepeatMbx = NULL;
+ LEAVE_MBX_CRITICAL;
+ }
+
+ // Repeat was finished, toggle the acknowledge bit
+ bMbxRepeatToggle = !bMbxRepeatToggle;
+}
+
+/////////////////////////////////////////////////////////////////////////////////////////
+/**
+ \param pMbx Pointer to a Mailbox command to be sent (read by the Master)
+ \param flags Bit 0-6: mailbox protocol type:
+ 0x01 - emergency service
+ 0x02 - CoE service
+ 0x04 - SoE service
+ 0x80 - EoE service
+ 0x10 - AoE service
+ 0x20 - VoE service
+ Bit 7: 0 - no more fragments to be sent for the requested mailbox service
+ 1 - additional fragments to be sent for the mailbox service, the
+ corresponding XXXX_ContinueInd-function will be called to get
+ the next fragment
+
+ \return 0: Success - mailbox command could be stored in the send mailbox
+ 1: Failed - mailbox command could not be stored in the send mailbox, the
+ XXXX_ContinueInd service will be called when the mailbox was
+ read from the master to
+
+ \brief This function puts a new Mailbox service in the Send Mailbox
+*////////////////////////////////////////////////////////////////////////////////////////
+
+UINT8 MBX_MailboxSendReq( TMBX MBXMEM * pMbx, UINT8 flags )
+{
+ UINT8 result = 0;
+
+ /* HBu 06.02.06: in INIT-state a mailbox send request shall be refused */
+ if ( (nAlStatus & STATE_MASK) == STATE_INIT )
+ {
+ return ERROR_INVALIDSTATE;
+ }
+
+
+
+ ENTER_MBX_CRITICAL;
+
+ /* the counter in the mailbox header has to be incremented with every new mailbox service to be sent
+ if the mailbox data link layer is supported (software switch MAILBOX_REPEAT_SUPPORTED set)*/
+ pMbx->MbxHeader.Flags[MBX_OFFS_COUNTER] &= ~MBX_MASK_COUNTER;
+ /* HBu 13.02.06: Repeat-Counter was incremented too much if the mailbox service could not be sent */
+ /* u8MbxCounter holds the actual counter for the mailbox header, only the values
+ 1-7 are allowed if the mailbox data link layer is supported */
+ if ( (u8MbxReadCounter & 0x07) == 0 )
+ {
+ u8MbxReadCounter = 1;
+ }
+
+ pMbx->MbxHeader.Flags[MBX_OFFS_COUNTER] |= u8MbxReadCounter << MBX_SHIFT_COUNTER;
+
+ /* try to copy the mailbox command in the ESC */
+ if ( MBX_CopyToSendMailbox(pMbx) != 0 )
+ {
+ /* no success, send mailbox was full, set flag */
+ result = PutInMbxQueue(pMbx, &sMbxSendQueue);
+ if (result != 0)
+ {
+ flags |= FRAGMENTS_FOLLOW;
+ }
+ else
+ {
+ u8MbxReadCounter++;
+ }
+/*ET9300 Project Handler :(#if MAILBOX_QUEUE #else) lines 1067 to 1070 deleted*/
+ }
+ /* HBu 13.02.06: Repeat-Counter was incremented too much if the mailbox service could not be sent */
+ else
+ {
+ u8MbxReadCounter++;
+ }
+
+/*ET9300 Project Handler :(#if TEST_APPLICATION) lines 1078 to 1104 deleted*/
+ if ( flags & FRAGMENTS_FOLLOW )
+ {
+ /* store the mailbox service that the corresponding XXX_ContinueInd function will
+ be called when the send mailbox will have been read by the master because there
+ are mailbox commands to be sent for this service */
+ u8MailboxSendReqStored |= (flags & ((UINT8) ~FRAGMENTS_FOLLOW));
+ }
+
+ LEAVE_MBX_CRITICAL;
+
+ return result;
+}
+
+/////////////////////////////////////////////////////////////////////////////////////////
+/**
+ \brief This function is used to check if the received mailbox command can be processed.
+
+ Also the contents of the Receive Mailbox will be copied in the variable sMbx.
+*////////////////////////////////////////////////////////////////////////////////////////
+
+void MBX_CheckAndCopyMailbox( void )
+{
+ UINT16 mbxLen;
+
+/*ET9300 Project Handler :(#if ESC_32BIT_ACCESS) lines 1129 to 1137 deleted*/
+ /* get the size of the received mailbox command and acknowledge the event*/
+ HW_EscReadWord(mbxLen,u16EscAddrReceiveMbx);
+
+ /* the size has to be swapped here, all other bytes of the mailbox service will be swapped later */
+ mbxLen = SWAPWORD(mbxLen);
+
+ if(bNoMbxMemoryAvailable == TRUE)
+ {
+ /* Return a no memory error in case of any mailbox request*/
+ TMBX MBXMEM *pMbx = (TMBX MBXMEM *) APPL_AllocMailboxBuffer(10); /* a mailbox error datagram length*/
+
+ if(pMbx != NULL)
+ {
+ HMEMSET(pMbx,0x00,10);
+
+ /* Mailbox error response: type 0 (mailbox service protocol) */
+ pMbx->MbxHeader.Length = 4;
+ pMbx->MbxHeader.Flags[MBX_OFFS_TYPE] &= ~(MBX_MASK_TYPE);
+ pMbx->Data[0] = SWAPWORD(MBXSERVICE_MBXERRORCMD);
+ pMbx->Data[1] = SWAPWORD(MBXERR_NOMOREMEMORY);
+ MBX_MailboxSendReq(pMbx, 0);
+
+ APPL_FreeMailboxBuffer(pMbx);
+ }
+ }
+ /* the length of the mailbox data is in the first two bytes of the mailbox,
+ so the length of the mailbox header has to be added */
+ mbxLen += MBX_HEADER_SIZE;
+
+ /* in this example there are only two mailbox buffers available in the firmware (one for processing and
+ one to stored the last sent response for a possible repeat request), so a
+ received mailbox service can only be processed if a free buffer is available */
+ if ( ( bSendMbxIsFull ) /* a received mailbox service will not be processed
+ as long as the send mailbox is still full
+ (waits to be read from the master) */
+ ||( u8MailboxSendReqStored ) /* a mailbox service to be sent is still stored
+ so the received mailbox service will not be processed
+ until all stored mailbox services are sent */
+/*ET9300 Project Handler :(#if !MAILBOX_QUEUE) lines 1179 to 1181 deleted*/
+ )
+ {
+ /* set flag that the processing of the mailbox service will be checked in the
+ function MBX_Main (called from ECAT_Main) */
+ bReceiveMbxIsLocked = TRUE;
+ }
+ else
+ {
+ /* received mailbox command can be processed, reset flag */
+ bReceiveMbxIsLocked = FALSE;
+
+ /* if the read mailbox size is too big for the buffer, set the copy size to the maximum buffer size, otherwise
+ memory could be overwritten,
+ the evaluation of the mailbox size will be done in the mailbox protocols called from MBX_WriteMailboxInd */
+
+ if (mbxLen > u16ReceiveMbxSize)
+ {
+ mbxLen = u16ReceiveMbxSize;
+ }
+
+ psWriteMbx = (TMBX MBXMEM *) APPL_AllocMailboxBuffer(u16ReceiveMbxSize);
+
+ /* if there is no more memory for mailbox buffer, the mailbox should not be read */
+ if (psWriteMbx == NULL)
+ {
+ /* set flag that the processing of the mailbox service will be checked in the
+ function MBX_Main (called from ECAT_Main) */
+ bReceiveMbxIsLocked = TRUE;
+ return;
+ }
+ /* copy the mailbox header and data*/
+ HW_EscReadMbxMem((MEM_ADDR MBXMEM *) psWriteMbx,u16EscAddrReceiveMbx,mbxLen);
+
+/*ET9300 Project Handler :(#if !MAILBOX_QUEUE) lines 1217 to 1219 deleted*/
+
+ {
+ /*Read Control and Status of SyncManager 0 to check if the buffer is unlocked*/
+/*ET9300 Project Handler :(#if ESC_32BIT_ACCESS #elif ESC_16BIT_ACCESS) lines 1223 to 1231 deleted*/
+ VARVOLATILE UINT8 smstate = 0x00;
+ HW_EscReadByte(smstate,ESC_SYNCMAN_STATUS_OFFSET);
+
+ if(smstate & SM_STATUS_MBX_BUFFER_FULL)
+ {
+ /*Unlock the mailbox SyncManger buffer*/
+/*ET9300 Project Handler :(#if ESC_32BIT_ACCESS #elif ESC_16BIT_ACCESS) lines 1239 to 1245 deleted*/
+ u8dummy = 0;
+ HW_EscReadByte(u8dummy,(u16EscAddrReceiveMbx + u16ReceiveMbxSize - 1));
+
+ }
+
+ }
+
+ /* in MBX_MailboxWriteInd the mailbox protocol will be processed */
+ MBX_MailboxWriteInd( psWriteMbx );
+
+ }
+}
+
+
+/////////////////////////////////////////////////////////////////////////////////////////
+/**
+ \param pMbx Pointer to the Mailbox command to be send to the master.
+
+ \brief This function copies data to the Send Mailbox.
+*////////////////////////////////////////////////////////////////////////////////////////
+
+UINT8 MBX_CopyToSendMailbox( TMBX MBXMEM *pMbx )
+{
+ if ( (nAlStatus & STATE_MASK) == STATE_INIT)
+ {
+ /* the mailbox is disabled if the slave is in the INIT state */
+ return( ERROR_INVALIDSTATE );
+ }
+
+
+ if ( !bMbxRunning )
+ {
+ /* the mailbox is disabled if the slave is in the INIT state */
+ return( ERROR_INVALIDSTATE );
+ }
+
+ if ( bSendMbxIsFull )
+ {
+ /* mailbox service cannot be sent because the send mailbox is still full */
+ return MBXERR_NOMOREMEMORY;
+ }
+ else
+ {
+ /* the variable mbxSize contains the size of the mailbox data to be sent */
+ UINT16 mbxSize = pMbx->MbxHeader.Length;
+/*ET9300 Project Handler :(#if BIG_ENDIAN_FORMAT) lines 1292 to 1295 deleted*/
+/*ECATCHANGE_START(V5.13) MBX2*/
+ /*Reset the not used mailbox memory*/
+ {
+ UINT16 LastUsedAddr = u16EscAddrSendMbx + mbxSize + MBX_HEADER_SIZE;
+ UINT16 LastAddrToReset = (u16EscAddrSendMbx + u16SendMbxSize);
+/*ET9300 Project Handler :(#if ESC_32BIT_ACCESS #elif ESC_16BIT_ACCESS) lines 1301 to 1326 deleted*/
+ LastAddrToReset = LastAddrToReset - 1;
+ u8dummy = 0;
+
+ /*clear all unused bytes*/
+ while (LastUsedAddr < LastAddrToReset) /*reset all bytes until the second last valid address*/
+ {
+ HW_EscWriteByte(u8dummy, LastUsedAddr);
+ LastUsedAddr = LastUsedAddr + 1;
+ }
+ }
+/*ECATCHANGE_END(V5.13) MBX2*/
+
+ HW_EscWriteMbxMem((MEM_ADDR *)pMbx, u16EscAddrSendMbx, (mbxSize + MBX_HEADER_SIZE));
+
+
+ {
+ /*Read Control and Status of SyncManager 1 to check if the buffer is still marked as empty*/
+/*ET9300 Project Handler :(#if ESC_32BIT_ACCESS #elif ESC_16BIT_ACCESS) lines 1345 to 1353 deleted*/
+ VARVOLATILE UINT8 smstate = 0x00;
+ HW_EscReadByte(smstate,(ESC_SYNCMAN_STATUS_OFFSET + SIZEOF_SM_REGISTER));
+
+ if(!(smstate & SM_STATUS_MBX_BUFFER_FULL))
+ {
+
+/*ET9300 Project Handler :(#if ESC_32BIT_ACCESS || ESC_16BIT_ACCESS) lines 1361 to 1363 deleted*/
+
+ /*Write last Byte to trigger mailbox full flag*/
+/*ET9300 Project Handler :(#if ESC_32BIT_ACCESS #elif ESC_16BIT_ACCESS) lines 1366 to 1397 deleted*/
+ u8dummy = 0;
+ HW_EscWriteByte(u8dummy, (u16EscAddrSendMbx + u16SendMbxSize - 1));
+ }
+ }
+
+/*ET9300 Project Handler :(#if !MAILBOX_QUEUE) lines 1404 to 1413 deleted*/
+ /* store last send mailbox service for a possible repeat
+ one buffer includes the last send service (psRepeatMbx),
+ the other one the actual service to be sent (psReadMbx),
+ there is no buffer available for a mailbox receive service
+ until the last sent buffer was read from the master
+ the exception is after the INIT2PREOP transition, in that
+ case there is no last sent service (psReadMbx = 0) */
+ if ( psReadMbx )
+ {
+ psWriteMbx = NULL;
+ }
+/*ET9300 Project Handler :(#if !MAILBOX_QUEUE) lines 1425 to 1431 deleted*/
+ psReadMbx = pMbx;
+
+ /* set flag that send mailbox is full now */
+ bSendMbxIsFull = TRUE;
+
+/*ET9300 Project Handler :(#if !MAILBOX_QUEUE) lines 1437 to 1440 deleted*/
+
+ return 0;
+ }
+}
+
+/////////////////////////////////////////////////////////////////////////////////////////
+/**
+ \brief This function is called cyclically to check if a received Mailbox service was
+ stored.
+*////////////////////////////////////////////////////////////////////////////////////////
+
+void MBX_Main(void)
+{
+ TMBX MBXMEM *pMbx = NULL;
+
+ do
+ {
+ UINT8 result = 0;
+
+ pMbx = GetOutOfMbxQueue(&sMbxReceiveQueue);
+ if ( pMbx )
+ {
+ result = MailboxServiceInd(pMbx);
+ }
+
+ if ( result != 0 )
+ {
+ /* Mailbox error response: type 0 (mailbox service protocol) */
+ pMbx->MbxHeader.Length = 4;
+ pMbx->MbxHeader.Flags[MBX_OFFS_TYPE] &= ~(MBX_MASK_TYPE);
+ pMbx->Data[0] = SWAPWORD(MBXSERVICE_MBXERRORCMD);
+ pMbx->Data[1] = SWAPWORD(result);
+ MBX_MailboxSendReq(pMbx, 0);
+ }
+ }
+ while ( pMbx != NULL );
+/*ET9300 Project Handler :(#if MAILBOX_QUEUE #else) lines 1478 to 1480 deleted*/
+
+/*ET9300 Project Handler :(#if EMERGENCY_SUPPORTED) lines 1482 to 1489 deleted*/
+
+ if (bReceiveMbxIsLocked)
+ {
+ /* the work on the receive mailbox is locked, check if it can be unlocked (if all
+ mailbox commands has been sent */
+ MBX_CheckAndCopyMailbox();
+ }
+
+ /*ECATCHANGE_START(V5.13) EOE1*/
+ /*Try to send pending Mailbox data,
+ could be to pending previously due to local (memory) limitations which are no available*/
+ if (u8MailboxSendReqStored)
+ {
+ /* there are mailbox services stored to be sent */
+/*ET9300 Project Handler :(#if EOE_SUPPORTED) lines 1505 to 1513 deleted*/
+ }
+/*ECATCHANGE_END(V5.13) EOE1*/
+}
+
+/** @} */
+
+
diff --git a/Projects/EFC_EcatDriver/src/ssc/mailbox.h b/Projects/EFC_EcatDriver/src/ssc/mailbox.h
new file mode 100644
index 0000000..7446ce3
--- /dev/null
+++ b/Projects/EFC_EcatDriver/src/ssc/mailbox.h
@@ -0,0 +1,197 @@
+/*
+* This source file is part of the EtherCAT Slave Stack Code licensed by Beckhoff Automation GmbH & Co KG, 33415 Verl, Germany.
+* The corresponding license agreement applies. This hint shall not be removed.
+* https://www.beckhoff.com/media/downloads/slave-stack-code/ethercat_ssc_license.pdf
+*/
+
+/**
+ * \addtogroup Mailbox Mailbox Functions
+ * @{
+ */
+
+/**
+\file mailbox.h
+\author EthercatSSC@beckhoff.com
+
+\version 5.12
+
+ Changes to version V5.11:
+V5.12 ECAT2: big endian changes
+V5.12 MBX3: handle incomplete mailbox communication
+ Changes to version V5.01:
+V5.11 ECAT10: change PROTO handling to prevent compiler errors
+V5.11 MBX1: "return value of ""MBX_StartMailboxHandler()"" changed to UINT16"
+V5.11 MBX3: set application triggered emergency and EoE data to pending if no mailbox queue is supported and another mailbox request is currently handled, Handle only one mailbox request at a time (in case that MAILBPX_QUEUE is disabled)
+ Changes to version - :
+V5.01 : Start file change log
+ */
+
+/*-----------------------------------------------------------------------------------------
+------
+------ Includes
+------
+-----------------------------------------------------------------------------------------*/
+#include "ecat_def.h"
+
+
+#ifndef _MAILBOX_H_
+#define _MAILBOX_H_
+
+/*-----------------------------------------------------------------------------------------
+------
+------ Defines and Types
+------
+-----------------------------------------------------------------------------------------*/
+#define MBX_TYPE_AOE 1 /**< \brief Mailbox type AoE*/
+#define MBX_TYPE_EOE 2 /**< \brief Mailbox type EoE*/
+#define MBX_TYPE_COE 3 /**< \brief Mailbox type CoE*/
+#define MBX_TYPE_FOE 4 /**< \brief Mailbox type FoE*/
+#define MBX_TYPE_SOE 5 /**< \brief Mailbox type SoE*/
+#define MBX_TYPE_VOE 15 /**< \brief Mailbox type VoE*/
+
+#define EMCY_SERVICE ((UINT8) 0x0001) /**< \brief Emergency service*/
+#define COE_SERVICE ((UINT8) 0x0002) /**< \brief CoE service*/
+#define SOE_SERVICE ((UINT8) 0x0004) /**< \brief SoE service*/
+#define EOE_SERVICE ((UINT8) 0x0008) /**< \brief EoE service*/
+#define AOE_SERVICE ((UINT8) 0x0010) /**< \brief AoE service*/
+#define VOE_SERVICE ((UINT8) 0x0020) /**< \brief VoE service*/
+#define FOE_SERVICE ((UINT8) 0x0040) /**< \brief FoE service*/
+#define FRAGMENTS_FOLLOW ((UINT8) 0x0080) /**< \brief Fragments follow service*/
+
+#ifndef ENTER_MBX_CRITICAL
+ #define ENTER_MBX_CRITICAL /**< \brief Enter mailbox critical section*/
+#endif
+
+#ifndef LEAVE_MBX_CRITICAL
+ #define LEAVE_MBX_CRITICAL /**< \brief Leave mailbox critical section*/
+#endif
+
+#ifndef MAX_MBX_QUEUE_SIZE
+ #define MAX_MBX_QUEUE_SIZE 10 /**< \brief Mailbox queue size*/
+#endif
+
+
+/*---------------------------------------------
+- Command Codes for the mailbox type 0
+-----------------------------------------------*/
+#define MBXSERVICE_MBXERRORCMD 0x01 /**< \brief Mailbox error command*/
+
+
+/*---------------------------------------------
+- Error Codes for a mailbox error response
+-----------------------------------------------*/
+#define MBXERR_SYNTAX 0x01 /**< \brief Mailbox error "syntax"*/
+#define MBXERR_UNSUPPORTEDPROTOCOL 0x02 /**< \brief Mailbox error "unsupported protocol"*/
+#define MBXERR_INVALIDCHANNEL 0x03 /**< \brief Mailbox error "invalid channel"*/
+#define MBXERR_SERVICENOTSUPPORTED 0x04 /**< \brief Mailbox error "service not supported"*/
+#define MBXERR_INVALIDHEADER 0x05 /**< \brief Mailbox error "invalid header"*/
+#define MBXERR_SIZETOOSHORT 0x06 /**< \brief Mailbox error "Size too short"*/
+#define MBXERR_NOMOREMEMORY 0x07 /**< \brief Mailbox error "No memory"*/
+#define MBXERR_INVALIDSIZE 0x08 /**< \brief Mailbox error "Invalid size"*/
+#define MBXERR_SERVICEINWORK 0x09 /**< \brief Mailbox error "Service in work"*/
+
+
+/**
+ * \brief Mailbox header
+ */
+typedef struct MBX_STRUCT_PACKED_START
+{
+ UINT16 Length; /**< \brief Length*/
+ UINT16 Address; /**< \brief Address*/
+
+/*ET9300 Project Handler :(#if MBX_16BIT_ACCESS) lines 103 to 120 deleted*/
+ UINT8 Flags[2]; /**< \brief Flags*/
+/*ET9300 Project Handler :(#if BIG_ENDIAN_16BIT) lines 122 to 125 deleted*/
+ #define MBX_OFFS_TYPE 1 /**< \brief Protocol type offset*/
+ #define MBX_OFFS_COUNTER 1 /**< \brief Protocol counter offset*/
+ #define MBX_MASK_TYPE 0x0F /**< \brief Protocol type mask*/
+ #define MBX_MASK_COUNTER 0xF0 /**< \brief Protocol counter mask*/
+ #define MBX_SHIFT_TYPE 0 /**< \brief Protocol type shift*/
+ #define MBX_SHIFT_COUNTER 4 /**< \brief Protocol counter shift*/
+}MBX_STRUCT_PACKED_END
+TMBXHEADER;
+
+
+#define MBX_HEADER_SIZE 6 /**< \brief Mailbox header size*/
+
+
+#define MAX_MBX_DATA_SIZE (MAX_MBX_SIZE - MBX_HEADER_SIZE) /**< \brief Mailbox data size*/
+
+/**
+ * \brief Mailbox datagram
+ */
+typedef struct MBX_STRUCT_PACKED_START
+{
+ TMBXHEADER MbxHeader; /**< \brief Mailbox header*/
+ UINT16 Data[(MAX_MBX_DATA_SIZE >> 1)]; /**< \brief Mailbox data*/
+}MBX_STRUCT_PACKED_END
+TMBX;
+
+
+/**
+ * \brief Mailbox queue
+ */
+typedef struct
+{
+ UINT16 firstInQueue; /**< \brief First in Queue*/
+ UINT16 lastInQueue; /**< \brief Last in Queue*/
+ UINT16 maxQueueSize; /**< \brief Max queue size*/
+ TMBX MBXMEM * queue[(MAX_MBX_QUEUE_SIZE)+1]; /**< \brief Queue buffer*/
+} TMBXQUEUE;
+
+
+
+#endif //_MAILBOX_H_
+
+
+/*-----------------------------------------------------------------------------------------
+------
+------ Global Variables
+------
+-----------------------------------------------------------------------------------------*/
+#if defined(_MAILBOX_) && (_MAILBOX_ == 1)
+ #define PROTO
+#else
+ #define PROTO extern
+#endif
+
+PROTO BOOL bReceiveMbxIsLocked; /**< \brief Receive mailbox is locked (MBoxOut, default SM0)*/
+PROTO BOOL bSendMbxIsFull; /**< \brief Send mailbox is full (MBoxIn, default SM1)*/
+PROTO BOOL bMbxRunning; /**< \brief Mailbox running (At least PreOP state)*/
+PROTO BOOL bMbxRepeatToggle; /**< \brief Mailbox repeat toggle*/
+PROTO UINT16 u16SendMbxSize; /**< \brief Send mailbox size (default SM1)*/
+PROTO UINT16 u16ReceiveMbxSize; /**< \brief Receive mailbox size (default SM0)*/
+PROTO UINT16 u16EscAddrReceiveMbx; /**< \brief Receive mailbox address (default SM0)*/
+PROTO UINT16 u16EscAddrSendMbx; /**< \brief Send mailbox address (default SM1)*/
+PROTO UINT8 u8MbxWriteCounter; /**< \brief Write mailbox counter*/
+PROTO UINT8 u8MbxReadCounter; /**< \brief Read mailbox counter*/
+/*ET9300 Project Handler :(#if !MAILBOX_QUEUE) lines 193 to 195 deleted*/
+PROTO UINT8 u8MailboxSendReqStored; /**< \brief Mailbox send request stored*/
+PROTO TMBX MBXMEM * psWriteMbx; /**< \brief Pointer to write mailbox buffer*/
+PROTO TMBX MBXMEM * psReadMbx; /**< \brief Pointer to read mailbox buffer*/
+PROTO TMBX MBXMEM * psRepeatMbx; /**< \brief Pointer to repeat mailbox buffer*/
+PROTO TMBX MBXMEM * psStoreMbx; /**< \brief Pointer to store mailbox buffer*/
+/*ET9300 Project Handler :(#if !MAILBOX_QUEUE) lines 201 to 203 deleted*/
+PROTO TMBXQUEUE MBXMEM sMbxSendQueue; /**< \brief Send mailbox queue*/
+PROTO TMBXQUEUE MBXMEM sMbxReceiveQueue; /**< \brief Receive mailbox queue*/
+
+
+/*-----------------------------------------------------------------------------------------
+------
+------ Global Functions
+------
+-----------------------------------------------------------------------------------------*/
+
+PROTO void MBX_Init(void);
+PROTO UINT16 MBX_StartMailboxHandler(void);
+PROTO void MBX_StopMailboxHandler(void);
+PROTO void MBX_MailboxWriteInd(TMBX MBXMEM *pMbx);
+PROTO void MBX_MailboxReadInd(void);
+PROTO void MBX_MailboxRepeatReq(void);
+PROTO UINT8 MBX_MailboxSendReq(TMBX MBXMEM * pMbx, UINT8 flags);
+PROTO void MBX_CheckAndCopyMailbox(void);
+PROTO UINT8 MBX_CopyToSendMailbox(TMBX MBXMEM *pMbx);
+PROTO void MBX_Main(void);
+
+#undef PROTO
+/** @}*/
diff --git a/Projects/EFC_EcatDriver/src/ssc/objdef.c b/Projects/EFC_EcatDriver/src/ssc/objdef.c
new file mode 100644
index 0000000..f169aca
--- /dev/null
+++ b/Projects/EFC_EcatDriver/src/ssc/objdef.c
@@ -0,0 +1,1813 @@
+/*
+* This source file is part of the EtherCAT Slave Stack Code licensed by Beckhoff Automation GmbH & Co KG, 33415 Verl, Germany.
+* The corresponding license agreement applies. This hint shall not be removed.
+* https://www.beckhoff.com/media/downloads/slave-stack-code/ethercat_ssc_license.pdf
+*/
+
+/**
+\addtogroup CoE CAN Application Profile over EtherCAT
+@{
+*/
+
+/**
+\file objdef.c
+\author EthercatSSC@beckhoff.com
+\brief Implementation
+This file contains the object dictionary access functions
+
+\version 5.13
+
+ Changes to version V5.12:
+V5.13 COE1: handling objects with 255 entries
+V5.13 COE4: update default entry name handling in case of 16Bit characters, add CoE Read/write indication functions
+V5.13 COE9: prevent compiler warning in get entry description if char is 8bit
+V5.13 TEST7: add entries with bit9-16 types
+ Changes to version V5.11:
+V5.12 COE10: update object entry string handling
+V5.12 COE3: update entry access right handling
+V5.12 COE6: handle get object length in case of an out of range subindex
+V5.12 COE7: in case of a padding entry SDO upload/download return Unsupported access
+V5.12 COE9: SDO download 0xF030.0 shall be 0 before writing entries 1..n
+V5.12 ECAT1: update SM Parameter measurement (based on the system time), enhancement for input only devices and no mailbox support, use only 16Bit pointer in process data length caluclation
+V5.12 ECAT5: update Sync error counter/flag handling,check enum memory alignment depending on the processor,in case of a polled timer disable ESC interrupts during DC_CheckWatchdog
+ Changes to version V5.10.1:
+V5.11 DIAG4: change parameter handling in DIAG_CreateNewMessage()
+V5.11 ECAT:
+V5.11 ECAT10: change PROTO handling to prevent compiler errors
+V5.11 ESM7: "add Sync define for 0x22 (""SYNCTYPE_SM2_SYNCHRON""), support value 0x22 for 0x1C33.1 (SM2 sync)"
+V5.11 OBJ1: OBJ_GetEntryOffset: return offset 0 for si0 (always offset 16 was returned before)
+V5.11 SDO1: "Obj_Read/Obj_Write: Check if entries > 8bit has even word offset (otherwise ""unsupported access"" is returned). To support these object a read/write callback function need to be used (see Application Note ET9300)"
+V5.11 SDO2: Obj_Read/Obj_Write: Handle arrays (string, array of byte, ...) with an odd word length (buffer shift was wrong). Only an entry <=8Bit is allowed after such an entry.
+V5.11 SDO3: handle not word aligned enums
+V5.11 SDO5: add missing swapping on SI0 write access
+V5.11 SDO6: OBJ_GetDesc ensure that the default string is used if no string was found
+V5.11 SDO7: add missing value swapping if memory values are bitwise modified on object read/write access
+V5.11 SDO9: "handle SDO access for entries which are not accessible (in case of SDO complete access), SDO access handle ""DEFTYPE_ARRAY_OF_INT"" , ""DEFTYPE_ARRAY_OF_SINT"" , ""DEFTYPE_ARRAY_OF_DINT"" , ""DEFTYPE_ARRAY_OF_UDINT"", SDO access handle : ""BYTE"" , ""WORD"" and ""DWORD"""
+V5.11 TEST2: add test 0x300C object (entry bitlength > 65535)
+V5.11 TEST8: create diag message on SDO write access to 0x3002
+ Changes to version V5.01:
+V5.10 COE2: Change return value of Get ObjectSize to UINT32
+ Change object size to UINT32
+V5.10 ECAT11: Add define "USE_SINGLE_PDO_MAPPING_ENTRY_DESCR" (Only one entry description is required for all PDO mapping entries)
+V5.10 ECAT13: Update Synchronisation handling (FreeRun,SM Sync, Sync0, Sync1)
+ Compare DC UINT configuration (by ESC Config data) vs. DC activation register settings
+ Update 0x1C3x entries
+V5.10 ECAT3: Add new datatype handling (BITARRxx)
+ Use read/write macro to access STRING entries
+V5.10 SDO1: Handle access to enums on odd memory addresses (only for MBX_16BIT_ACCESS)
+V5.10 SDO2: Check for termination char in every substring
+V5.10 SDO5: Check also for PDO mapping object if the subindex 0 was set to 0 before the entries will be changed.
+V5.10 SDO9: SDO complete write access update buffer offset calculation in case of SI0 is readonly
+V5.10 TEST2: Add 0x3004.14 (Access to this entry will always rejected with the code "cannot be acceesd because of local control")
+V5.10 TEST4: Add CoE test (0x2020.5) to return always max object data on complete access (not limited to value of SI0)
+ Changes to version V5.0:
+V5.01 COE2: Calculate the bit offset also for SI0 in case if an SDO download access.
+V5.01 SDO1: Update alignment entry handling.
+V5.01 SDO5: Update offset calculation in case of an not accessible entry
+V5.01 SDO7: Update object length calculation in case of an BitArray
+V5.01 TEST5: Add slave configuration object handling (0x8000, if test application is active)
+V5.01 TEST6: Add test to create dummy object dictionary.
+ Changes to version V4.40:
+V5.0 TEST1: Add test application.
+V5.0 COE3: Update OCTED_STRING and VISIBLE_STRING read/write.
+V5.0 COE5: Add BigEndian support for enum SDO read, handle complete access also for objects with align or not existing entries.
+V5.0 COE7: Support SDO Info entry name handling for 16Bit access
+V5.0 DIAG2: SDO Info request for diagnosis messages 0x10F3 SI5 or greater return always description of SI6.
+V5.0 COE2: Add plausibility check for PDO assign objects.
+V5.0 OBJ2: Support DWORD/WORD aligned object structures.
+V5.0 SDO7: Update SDO read/write for object(entries) less or equal 8Bit.
+ Changes to version V4.30:
+V4.40 DIAG1: Add diagnosis access functions
+V4.40 OBJ2: change counter variable to prevent deadlock caused by overrun (required if subindex0 is 255)
+V4.40 COE2: Prevent accessing empty object dictionary entry
+V4.40 COE3: Read whole object dictionary
+V4.40 COE1: Prototype of OBJ_GetObjectList() changed, set abort code if object dictionary is empty
+V4.30 OBJ 3: Object dictionary list handling
+V4.30 OBJ 2: fix SDO complete access bug
+V4.11 OBJ 1-3: OBJ_GetDesc() Now, subindex 0 instead of 0xFF is used to return the description of the whole object
+Subindex 0xFF could be used like a normal subindex.
+ Changes to version V4.08:
+V4.10 OBJ 1: calculate size of PdoObjectEntry Index 1 and not Index 0
+V4.10 OBJ 2: the pointer of the object dictionary will be get by a function (COE_GetObjectDictionary)
+ Changes to version V4.07:
+V4.08 OBJ 1: if subindex 0 is writable, the maximum subindex should be checked in an object specific function,
+ because for the PDO mapping and PDO assign the object shall only be written if subindex 0 is 0.
+ Changes to version V4.04:
+V4.04 OBJ 1: The loop in OBJ_GetObjectList was one subindex too low
+ Changes to version V4.03:
+V4.04 SDO 1: The SDO interface was changed in that way that a SDO response
+ could be sent by the application to a later time. In that case
+ the functions OBJ_Read and OBJ_Write shall return the value
+ ABORTIDX_WORKING. To send the SDO response the new function SDOS_SdoRes
+ has to be called by the application. While waiting for the call
+ of SDOS_SdoRes the SDO interface will answer to another SDO request
+ with the error MBXERR_SERVICEINWORK in the mailbox protocol
+V4.04 OBJ 1: The loop in OBJ_GetNoOfObjects was one subindex too low
+ Changes to version V4.02:
+V4.03 OBJ 1: The object list was not returned correctly for the list types 2-5
+ Changes to version V3.20:
+V4.00 OBJ 1: The OBJ functions are modified for a more flexible definition of
+ the object dictionary and to support bit types too
+V4.00 SDO 2: The object lists will be generated in the functions OBJ_GetNoOfObjects
+ and OBJ_GetObjectList in objdef.c to decouple the SDO services from
+ the implementation of the object dictionary
+V4.00 COEAPPL 2: The handling of backup parameters was included according to
+ the EtherCAT Guidelines and Protocol Enhancements Specification
+
+*/
+
+
+#define OBJDEF 0x4000
+#define OBJDEFMAX 0x0A
+
+/*---------------------------------------------------------------------------------------
+------
+------ Includes
+------
+---------------------------------------------------------------------------------------*/
+
+#include "ecat_def.h"
+
+
+#include "ecatslv.h"
+#include "coeappl.h"
+
+
+#define _OBJDEF_ 1
+#include "objdef.h"
+#undef _OBJDEF_
+/*remove definition of _OBJDEF_ (#ifdef is used in objdef.h)*/
+
+#include "applInterface.h"
+
+/*ET9300 Project Handler :(#if TEST_APPLICATION) lines 143 to 145 deleted*/
+
+/*ET9300 Project Handler :(#if DIAGNOSIS_SUPPORTED) lines 147 to 149 deleted*/
+
+
+
+
+extern OBJCONST TOBJECT OBJMEM *pSdoInfoObjEntry;
+extern OBJCONST TSDOINFOENTRYDESC OBJMEM * OBJ_GetEntryDesc(OBJCONST TOBJECT OBJMEM * pObjEntry, UINT8 Subindex);
+
+//---------------------------------------------------------------------------------------
+
+/*---------------------------------------------------------------------------------------
+------
+------ Internal types and defines
+------
+---------------------------------------------------------------------------------------*/
+
+/*---------------------------------------------------------------------------------------
+------
+------ module internal function declarations
+------
+---------------------------------------------------------------------------------------*/
+
+/*---------------------------------------------------------------------------------------
+------
+------ Module internal variable definitions
+------
+---------------------------------------------------------------------------------------*/
+const UINT16 cBitMask[16] = {0x0000,0x0001,0x0003,0x0007,0x000F,0x001F,0x003F,0x007F,0x00FF,0x01FF,0x03FF,0x07FF,0x0FFF,0x1FFF,0x3FFF,0x7FFF};
+/*---------------------------------------------------------------------------------------
+------
+------ Functions
+------
+---------------------------------------------------------------------------------------*/
+
+
+/////////////////////////////////////////////////////////////////////////////////////////
+/**
+ \param index Indicates the index of the dictionary object.
+
+ \return A handle to an object of the requested index or NULL if not found.
+
+ \brief The function looks in all objects of the dictionary after the indicated index
+ and returns a handle if found.
+
+*////////////////////////////////////////////////////////////////////////////////////////
+
+OBJCONST TOBJECT OBJMEM * OBJ_GetObjectHandle( UINT16 index )
+{
+ OBJCONST TOBJECT OBJMEM * pObjEntry = (OBJCONST TOBJECT OBJMEM *) COE_GetObjectDictionary();
+
+ while (pObjEntry!= NULL)
+/*ET9300 Project Handler :(#if !STATIC_OBJECT_DIC #else) lines 201 to 203 deleted*/
+ {
+
+ if (pObjEntry->Index == index)
+ {
+ return pObjEntry;
+ }
+ pObjEntry = (TOBJECT OBJMEM *) pObjEntry->pNext;
+/*ET9300 Project Handler :(#if !STATIC_OBJECT_DIC #else) lines 212 to 214 deleted*/
+ }
+ return 0;
+}
+
+/////////////////////////////////////////////////////////////////////////////////////////
+/**
+ \param index Index of the requested object.
+ \param subindex Subindex of the requested object.
+ \param pObjEntry Handle to the dictionary object returned by
+ OBJ_GetObjectHandle which was called before
+ \param bCompleteAccess Indicates if a complete read of all subindices of the
+ object shall be done or not
+
+ \return The size of the object entry in bytes (!).
+
+ \brief This function returns the size of the requested entry. If bCompleteaccess is set the size of the complete object is returned (the returned size is byte packed, gaps based on the used platform/compiler are not taken into account)
+
+*////////////////////////////////////////////////////////////////////////////////////////
+UINT32 OBJ_GetObjectLength( UINT16 index, UINT8 subindex, OBJCONST TOBJECT OBJMEM * pObjEntry, UINT8 bCompleteAccess)
+{
+ /* get the information of ObjCode and MaxSubindex in local variables to support different types of microcontroller */
+ UINT8 objCode = (pObjEntry->ObjDesc.ObjFlags & OBJFLAGS_OBJCODEMASK) >> OBJFLAGS_OBJCODESHIFT;
+
+ UINT8 maxSubindex = (pObjEntry->ObjDesc.ObjFlags & OBJFLAGS_MAXSUBINDEXMASK) >> OBJFLAGS_MAXSUBINDEXSHIFT;
+ UINT32 size = 0;
+
+ if ( bCompleteAccess )
+ {
+ if ( objCode == OBJCODE_VAR )
+ {
+ return 0;
+ }
+ else if ((objCode == OBJCODE_ARR)
+ || (IS_RX_PDO(pObjEntry->Index) || IS_TX_PDO(pObjEntry->Index))
+/*ET9300 Project Handler :(#if TEST_APPLICATION) lines 252 to 255 deleted*/
+ )
+ {
+/*ET9300 Project Handler :(#if TEST_APPLICATION) lines 258 to 270 deleted*/
+
+ /* we have to get the maxSubindex from the actual value of subindex 0,
+ which is stored as UINT16 at the beginning of the object's variable */
+ maxSubindex = (UINT8) ((UINT16 MBXMEM *) (pObjEntry->pVarPtr))[0];
+
+
+ size = pObjEntry->pEntryDesc[1].BitLength *maxSubindex;
+
+/* no padding required: Bit entries within an array object may overlap byte borders*/
+
+ /* we have to convert the size in bytes */
+ size = BIT2BYTE(size);
+
+ if ( subindex == 0 )
+ {
+ /* add size for subindex 0 (is transmitted as UINT16) */
+ size += 2;
+ }
+ return size;
+ }
+ else
+ {
+/*ECATCHANGE_START(V5.13) COE1*/
+ UINT16 i;
+/*ECATCHANGE_END(V5.13) COE1*/
+
+ /* add the sizes of all entries */
+ for (i = 1; i <= maxSubindex; i++)
+ {
+ size += pObjEntry->pEntryDesc[i].BitLength;
+ }
+ /* we have to convert the size in bytes */
+ size = BIT2BYTE(size);
+
+ if ( subindex == 0 )
+ {
+ /* add size for subindex 0 (is transmitted as UINT16) */
+ size += 2;
+ }
+ return size;
+ }
+ }
+ else
+ {
+ if ( objCode == OBJCODE_VAR )
+ {
+/*ET9300 Project Handler :(#if TEST_APPLICATION) lines 318 to 326 deleted*/
+
+ return (BIT2BYTE(pObjEntry->pEntryDesc->BitLength));
+
+ }
+ else if ( subindex == 0 )
+ {
+ /* for single access subindex 0 is transmitted as UINT8 */
+ return 1;
+ }
+ else if((objCode == OBJCODE_ARR)
+ || (IS_RX_PDO(pObjEntry->Index) || IS_TX_PDO(pObjEntry->Index))
+/*ET9300 Project Handler :(#if TEST_APPLICATION) lines 340 to 343 deleted*/
+ )
+ {
+ return (BIT2BYTE(pObjEntry->pEntryDesc[1].BitLength));
+ }
+ else
+ {
+/*ET9300 Project Handler :(#if DIAGNOSIS_SUPPORTED) lines 350 to 356 deleted*/
+ {
+ if (maxSubindex < subindex)
+ {
+ return 0;
+
+ }
+ else
+ {
+ return (BIT2BYTE(pObjEntry->pEntryDesc[subindex].BitLength));
+ }
+ }
+ }
+ }
+}
+
+/////////////////////////////////////////////////////////////////////////////////////////
+/**
+ \param pStr Pointer to a string
+ \param Number Number to be included in the string
+
+ \brief The function copies the Number in the string pStr,
+ which shall be initialized with 000
+
+*////////////////////////////////////////////////////////////////////////////////////////
+
+void OBJ_CopyNumberToString(UCHAR MBXMEM *pStr, UINT8 Number)
+{
+ UINT8 Modulo;
+
+ pStr[2] = '0';
+ pStr[0] += (Number / 100);
+ Modulo = Number % 100;
+ pStr[1] += (Modulo / 10);
+ pStr[2] += (Modulo % 10);
+}
+
+/////////////////////////////////////////////////////////////////////////////////////////
+/**
+ \param listType requested listType (0=all objects, 1=RxPDO mappable objects,
+ 2=TxPDO mappable objects, 3=backup objects, 4=setting objects)
+
+ \return Number of objects of the requested list type
+
+ \brief The function counts the number of objects of the requested list type
+
+*////////////////////////////////////////////////////////////////////////////////////////
+
+UINT16 OBJ_GetNoOfObjects(UINT8 listType)
+{
+ /* the variable listFlags contains the mask used for the ObjAccess in the Entry-Desc
+ see the structure TSDOINFOENTRYDESC in sdoserv.h, listType = 0 indicates that
+ all objects has to be counted */
+
+ UINT16 listFlags = 0x0020 << listType;
+
+ /* set pObjEntry to the beginning of the object dictionary */
+ OBJCONST TOBJECT OBJMEM * pObjEntry = (OBJCONST TOBJECT OBJMEM *) COE_GetObjectDictionary();
+ UINT16 n = 0;
+
+/*ET9300 Project Handler :(#if TEST_APPLICATION) lines 416 to 422 deleted*/
+
+ while (pObjEntry != NULL)
+/*ET9300 Project Handler :(#if !STATIC_OBJECT_DIC #else) lines 426 to 428 deleted*/
+ {
+ /* count the objects of the requested list type */
+ if ( pObjEntry->Index >= 0x1000 )
+ {
+ UINT8 t = listType;
+ if ( t )
+ {
+ UINT8 maxSubindex = (pObjEntry->ObjDesc.ObjFlags & OBJFLAGS_MAXSUBINDEXMASK) >> OBJFLAGS_MAXSUBINDEXSHIFT;
+ UINT16 i = 0;
+
+ while ( t && i <= maxSubindex )
+ {
+ if ( OBJ_GetEntryDesc(pObjEntry,(UINT8) i)->ObjAccess & listFlags )
+ {
+ t = 0;
+ }
+ i++;
+ }
+ }
+ if ( !t )
+ {
+ /* object from listType found */
+ n++;
+ }
+ }
+ /* next object in object dictionary */
+ pObjEntry = (TOBJECT OBJMEM *) pObjEntry->pNext;
+/*ET9300 Project Handler :(#if !STATIC_OBJECT_DIC #else) lines 457 to 459 deleted*/
+ }
+
+ return n;
+}
+
+/////////////////////////////////////////////////////////////////////////////////////////
+/**
+ \param listType Requested listType (0=all objects, 1=RxPDO mappable objects,
+ 2=TxPDO mappable objects, 3=backup objects, 4=setting objects)
+ \param pIndex Pointer to the next Index of the object list to copied in the mailbox buffer,
+ has to adapted at the end of the function
+ \param size Size of the available mailbox buffer
+ \param pData Pointer to the mailbox buffer where (the part of) the object list requested listType (0=all objects, 1=RxPDO mappable objects,
+ \param pAbort Pointer to abortCode
+
+ \return Size of the available mailbox buffer which was not copied to
+
+ \brief The function copies (the part of) the object list in the mailbox buffer
+
+*////////////////////////////////////////////////////////////////////////////////////////
+UINT16 OBJ_GetObjectList(UINT16 listType, UINT16 *pIndex, UINT16 size, UINT16 MBXMEM *pData,UINT8 *pAbort)
+{
+ /* the variable listFlags contains the mask used for the ObjAccess in the Entry-Desc
+ see the structure TSDOINFOENTRYDESC in sdoserv.h, listType = 0 indicates that
+ all objects has to be counted */
+ UINT16 listFlags = 0x0020 << listType;
+ OBJCONST TOBJECT OBJMEM * pObjEntry;
+
+/*ET9300 Project Handler :(#if TEST_APPLICATION) lines 488 to 500 deleted*/
+
+ if ( pIndex[0] == 0x1000 )
+ {
+ /* beginning of object list, set pObjEntry to the beginning of the object dictionary */
+ pObjEntry = (OBJCONST TOBJECT OBJMEM *) COE_GetObjectDictionary();
+ // set abort code if no object dictionary is available
+ if((pObjEntry == NULL) && (pAbort != NULL))
+ {
+ *pAbort = ABORTIDX_NO_OBJECT_DICTIONARY_IS_PRESENT;
+ }
+ }
+ else
+ {
+ /* next fragment, the next object to be handled was stored in pSdoInfoObjEntry */
+ pObjEntry = pSdoInfoObjEntry;
+ }
+
+ if ( pObjEntry != NULL )
+ {
+ while (pObjEntry != NULL && size > 1 )
+/*ET9300 Project Handler :(#if !STATIC_OBJECT_DIC #else) lines 522 to 524 deleted*/
+ {
+ /* get the next index of the requested object list if there is enough space in the mailbox buffer */
+ if ( pObjEntry->Index >= 0x1000 )
+ {
+ /* UINT8 was changed to UINT16 */
+ UINT16 t = listType;
+ if ( t )
+ {
+ UINT8 maxSubindex = (pObjEntry->ObjDesc.ObjFlags & OBJFLAGS_MAXSUBINDEXMASK) >> OBJFLAGS_MAXSUBINDEXSHIFT;
+/*ECATCHANGE_START(V5.13) COE1*/
+ UINT16 i = 0;
+/*ECATCHANGE_END(V5.13) COE1*/
+
+ while ( t && i <= maxSubindex )
+ {
+ if ( OBJ_GetEntryDesc(pObjEntry, (UINT8)i)->ObjAccess & listFlags )
+ {
+ t = 0;
+ }
+ i++;
+ }
+ }
+ if ( !t )
+ {
+ /* store the index in the mailbox buffer */
+ *pData = SWAPWORD(pObjEntry->Index);
+ pData++;
+ size -= 2;
+ }
+ }
+ pObjEntry = (TOBJECT OBJMEM *) pObjEntry->pNext;
+/*ET9300 Project Handler :(#if !STATIC_OBJECT_DIC #else) lines 557 to 559 deleted*/
+ }
+ }
+
+ /* return the next Index to be handled */
+ if(pObjEntry != NULL)
+ {
+ pIndex[0] = pObjEntry->Index;
+ }
+ else
+ {
+ /*last entry reached*/
+ pIndex[0] = 0xFFFF;
+ }
+
+ /* store object description pointer and index for next fragment */
+ pSdoInfoObjEntry = pObjEntry;
+
+ /* return the size of the available mailbox buffer which was not copied to */
+ return size;
+}
+
+/////////////////////////////////////////////////////////////////////////////////////////
+/**
+ \param index Indicates the index of the dictionary object.
+ \param subindex Indicates the subindex of the dictionary object.
+ Subindex 0xff returns the description of the whole object ( the name of
+ the object ).
+ Subindex 0x00 returns the description of the subindex 0 and so on.
+ \param pObjEntry Is a handle to the dictionary object ( for faster access ) or NULL.
+ \param pData Is the memory field for the description string or NULL ( if the size of
+ string is unknown ):
+
+ \return The size in bytes of the description string (without null termination byte ).
+ 0 will be returned if a description for the indicated entry was not found.
+
+ \brief The function returns size and description string of the requested entry.
+
+ Its possible to define all description strings of one entry ( including the name
+ of the object ) in one structure:
+ {
+ name_of_object with index,
+ description_of_subindex0,
+ .
+ description_of_subindexN,
+ 0xFF
+ }
+*////////////////////////////////////////////////////////////////////////////////////////
+
+UINT16 OBJ_GetDesc( UINT16 index, UINT8 subindex, OBJCONST TOBJECT OBJMEM * pObjEntry, UINT16 MBXMEM * pData )
+{
+ UINT16 strSize = 0;
+ OBJCONST UCHAR OBJMEM * pDesc = (OBJCONST UCHAR OBJMEM *) pObjEntry->pName;
+/* get the information of ObjCode and MaxSubindex in local variables to support different types of microcontroller */
+ UINT8 objCode = (pObjEntry->ObjDesc.ObjFlags & OBJFLAGS_OBJCODEMASK) >> OBJFLAGS_OBJCODESHIFT;
+
+
+
+ if ( (subindex == 0) || (objCode == OBJCODE_VAR) )
+ {
+ // Get object description length
+ strSize = (UINT16) OBJSTRLEN((OBJCONST CHAR OBJMEM *) pDesc);
+
+ // If there is a pointer given, copy data:
+ if ( pData )
+ {
+ OBJTOMBXSTRCPY( pData, pDesc, strSize );
+ }
+ }
+ else
+ {
+ if ( objCode == OBJCODE_REC )
+ {
+/*ET9300 Project Handler :(#if TEST_APPLICATION) lines 632 to 653 deleted*/
+ {
+ // get pointer to description of subindex 1 :
+ // 16bit variable to avoid overflow if subindex 0xFF is read
+ UINT16 i = 1;
+ UINT16 tmpSubindex = subindex;
+
+/*ET9300 Project Handler :(#if DIAGNOSIS_SUPPORTED) lines 660 to 666 deleted*/
+ {
+
+ OBJCONST UCHAR OBJMEM * pSubDesc = (OBJCONST UCHAR OBJMEM *) OBJGETNEXTSTR( pDesc );
+ while (( i <= tmpSubindex )
+ &&( pSubDesc[0] != 0xFF && pSubDesc[0] != 0xFE
+/* ECATCHANGE_START(V5.13) COE9*/
+/*ET9300 Project Handler :(#if MEMORY_UNIT_16BIT) lines 673 to 676 deleted*/
+/* ECATCHANGE_END(V5.13) COE9*/
+ ))
+ {
+ if ( i == tmpSubindex )
+ {
+ strSize = (UINT16) OBJSTRLEN((OBJCONST CHAR OBJMEM *) pSubDesc);
+ if ( pData && strSize )
+ {
+ OBJTOMBXSTRCPY( pData, pSubDesc, strSize );
+ }
+ break;
+ }
+ else
+ {
+ i++;
+ pSubDesc = (OBJCONST UCHAR OBJMEM *) OBJGETNEXTSTR( pSubDesc );
+ }
+ }
+ }
+ }
+ }
+
+ if ( strSize == 0 )
+ {
+ // no string found for subindex x -> name is Subindex x
+ strSize = 12;
+
+ if ( pData )
+ {
+ UCHAR OBJMEM TmpDescr[13];
+ /* ECATCHANGE_START(V5.13) COE4*/
+ MEMCPY(TmpDescr, aSubindexDesc, SIZEOF(TmpDescr));
+ /* ECATCHANGE_END(V5.13) COE4*/
+
+ OBJ_CopyNumberToString( &TmpDescr[9], subindex );
+ MBXSTRCPY( pData, TmpDescr, SIZEOF(TmpDescr) );
+ }
+ }
+ }
+
+ return strSize;
+}
+
+/////////////////////////////////////////////////////////////////////////////////////////
+/**
+ \param pObjEntry handle to the dictionary object returned by
+ OBJ_GetObjectHandle which was called before
+ \param Subindex subindex of the requested object.
+
+ \return Pointer to the EntryDesc of the Subindex
+
+ \brief The function returns the Entry-Desc of a subindex to allow the application
+ to define the object dictionary independent of the sdoserv-files
+
+*////////////////////////////////////////////////////////////////////////////////////////
+
+OBJCONST TSDOINFOENTRYDESC OBJMEM * OBJ_GetEntryDesc(OBJCONST TOBJECT OBJMEM * pObjEntry, UINT8 Subindex)
+{
+ OBJCONST TSDOINFOENTRYDESC OBJMEM *pEntry;
+ UINT8 objCode = (pObjEntry->ObjDesc.ObjFlags & OBJFLAGS_OBJCODEMASK) >> OBJFLAGS_OBJCODESHIFT;
+
+ if ((objCode == OBJCODE_ARR)
+ || (IS_RX_PDO(pObjEntry->Index) || IS_TX_PDO(pObjEntry->Index))
+/*ET9300 Project Handler :(#if TEST_APPLICATION) lines 742 to 746 deleted*/
+ )
+ {
+ /* object is an array */
+ if ( Subindex == 0 )
+ {
+ /* subindex 0 has a description */
+ pEntry = &pObjEntry->pEntryDesc[0];
+ }
+ else
+ {
+ /* and all other elements have the same description */
+ pEntry = &pObjEntry->pEntryDesc[1];
+ }
+ }
+ else
+ {
+/*ET9300 Project Handler :(#if DIAGNOSIS_SUPPORTED) lines 763 to 771 deleted*/
+ {
+ /* object is a variable or a record return the corresponding entry */
+ pEntry = &pObjEntry->pEntryDesc[Subindex];
+ }
+ }
+
+ return pEntry;
+}
+
+/////////////////////////////////////////////////////////////////////////////////////////
+/**
+ \param pObjEntry handle to the dictionary object returned by
+ OBJ_GetObjectHandle which was called before
+
+ \return Pointer to the ObjDesc of the Object
+
+ \brief The function returns the Obj-Desc of an object to allow the application
+ to define the object dictionary independent of the sdoserv-files
+
+*////////////////////////////////////////////////////////////////////////////////////////
+
+OBJCONST TSDOINFOOBJDESC OBJMEM * OBJ_GetObjDesc(OBJCONST TOBJECT OBJMEM * pObjEntry)
+{
+ return &pObjEntry->ObjDesc;
+}
+
+/////////////////////////////////////////////////////////////////////////////////////////
+/**
+ \param subindex subindex of the entry
+ \param pObjEntry handle to the dictionary object returned by
+ OBJ_GetObjectHandle which was called before
+
+ \return bit offset of the entry in the variable
+
+ \brief This function calculates the bit offset of the entry in the object's variable
+*////////////////////////////////////////////////////////////////////////////////////////
+
+UINT16 OBJ_GetEntryOffset(UINT8 subindex, OBJCONST TOBJECT OBJMEM * pObjEntry)
+{
+ UINT16 i;
+ /* bitOffset will be initialized with the bit offset of subindex 1 */
+ UINT16 bitOffset = 0;
+ UINT8 objCode = (pObjEntry->ObjDesc.ObjFlags & OBJFLAGS_OBJCODEMASK) >> OBJFLAGS_OBJCODESHIFT;
+ OBJCONST TSDOINFOENTRYDESC OBJMEM *pEntry;
+
+
+ if(subindex > 0)
+ {
+ /*subindex 1 has an offset of 16Bit (even if Si0 is only an UINT8) */
+ bitOffset +=16;
+ }
+
+ if (objCode == OBJCODE_VAR)
+ {
+ return 0;
+ }
+
+ for (i = 1; i <= subindex; i++)
+ {
+ /* get the entry description */
+ if ((objCode == OBJCODE_ARR)
+ || (IS_RX_PDO(pObjEntry->Index) || IS_TX_PDO(pObjEntry->Index))
+ )
+ {
+ pEntry = &pObjEntry->pEntryDesc[1];
+ }
+ else
+ {
+ pEntry = &pObjEntry->pEntryDesc[i];
+ }
+
+ switch (pEntry->DataType)
+ {
+ case DEFTYPE_INTEGER16:
+ case DEFTYPE_UNSIGNED16:
+ case DEFTYPE_BITARR16:
+ case DEFTYPE_WORD:
+ case DEFTYPE_UNICODE_STRING:
+ case DEFTYPE_ARRAY_OF_INT :
+
+#if OBJ_WORD_ALIGN || OBJ_DWORD_ALIGN
+ /* the 16-bit variables in the structure are word-aligned,
+ align the actual bitOffset to a word */
+ bitOffset = (bitOffset+15) & 0xFFF0;
+#endif
+
+
+ if (i < subindex)
+ {
+ if((pEntry->DataType == DEFTYPE_UNICODE_STRING)
+ ||(pEntry->DataType == DEFTYPE_ARRAY_OF_INT))
+ {
+ bitOffset += pEntry->BitLength;
+ }
+ else
+ {
+ bitOffset += 16;
+ }
+ }
+ break;
+ case DEFTYPE_UNSIGNED32:
+ case DEFTYPE_INTEGER32:
+ case DEFTYPE_REAL32:
+ case DEFTYPE_BITARR32:
+ case DEFTYPE_DWORD:
+ case DEFTYPE_ARRAY_OF_DINT :
+ case DEFTYPE_ARRAY_OF_UDINT:
+#if OBJ_DWORD_ALIGN
+ /* the 32-bit variables in the structure are dword-aligned,
+ align the actual bitOffset to a dword */
+ bitOffset = (bitOffset+31) & 0xFFE0;
+#elif OBJ_WORD_ALIGN
+ /* the 32-bit variables in the structure are word-aligned,
+ align the actual bitOffset to a word */
+ bitOffset = (bitOffset+15) & 0xFFF0;
+#endif
+
+ if (i < subindex)
+ {
+ if((pEntry->DataType == DEFTYPE_ARRAY_OF_DINT)
+ ||(pEntry->DataType == DEFTYPE_ARRAY_OF_UDINT))
+ {
+ bitOffset += pEntry->BitLength;
+ }
+ else
+ {
+ bitOffset += 32;
+ }
+ }
+ break;
+
+ case DEFTYPE_REAL64:
+ case DEFTYPE_INTEGER64:
+ case DEFTYPE_UNSIGNED64:
+#if OBJ_DWORD_ALIGN
+ /* the 64-bit variables in the structure are dword-aligned,
+ align the actual bitOffset to a dword */
+ bitOffset = (bitOffset + 31) & 0xFFE0;
+#elif OBJ_WORD_ALIGN
+ /* the 64-bit variables in the structure are word-aligned,
+ align the actual bitOffset to a word */
+ bitOffset = (bitOffset + 15) & 0xFFF0;
+#endif
+
+ if (i < subindex)
+ {
+
+ bitOffset += 64;
+ }
+ break;
+ default:
+ /* align the actual bitOffset to a byte */
+ if (i < subindex)
+ {
+ bitOffset += pEntry->BitLength;
+ }
+ break;
+ }
+ }
+
+ return bitOffset;
+}
+
+/////////////////////////////////////////////////////////////////////////////////////////
+/**
+ \param index index of the SyncManager Parameter object
+ \param NewSyncType New value for the Sync Type (SubIndex 1)
+
+ \return result Result of the value validation
+
+ \brief Checks if the new Sync type value is valid
+*////////////////////////////////////////////////////////////////////////////////////////
+UINT8 CheckSyncTypeValue(UINT16 index, UINT16 NewSyncType)
+{
+ switch (NewSyncType)
+ {
+ case SYNCTYPE_FREERUN:
+ return 0; //free run sync mode is always accepted
+
+ case SYNCTYPE_SM_SYNCHRON:
+ if ((index == 0x1C32)
+ && (nPdOutputSize > 0)
+ && ((sSyncManOutPar.u16SyncTypesSupported & SYNCTYPE_SYNCHRONSUPP) > 0))
+ {
+ /*SyncManager sync mode is supported and output process data is configured*/
+ return 0;
+ }
+ else
+ if ((index == 0x1C33)
+ && ((sSyncManInPar.u16SyncTypesSupported & SYNCTYPE_SYNCHRONSUPP) > 0)
+ && (nPdOutputSize == 0)
+ && (nPdInputSize > 0))
+ {
+ /*SyncManager sync mode is supported and input only shall be configured*/
+ return 0;
+ }
+ break;
+
+ case SYNCTYPE_SM2_SYNCHRON:
+ if ((index == 0x1C33)
+ && ((sSyncManInPar.u16SyncTypesSupported & SYNCTYPE_SYNCHRONSUPP) > 0)
+ && (nPdOutputSize > 0))
+ {
+ /*SyncManager sync mode is supported and outputs are defined*/
+ return 0;
+ }
+ break;
+
+/*ET9300 Project Handler :(#if DC_SUPPORTED) lines 990 to 1022 deleted*/
+ } //switch
+ return ABORTIDX_VALUE_EXCEEDED;
+
+}
+
+/////////////////////////////////////////////////////////////////////////////////////////
+/**
+ \param index index of the requested object.
+ \param subindex subindex of the requested object.
+ \param objSize Size of the object, returned by the function OBJ_GetObjectLength
+ which was called before
+ \param pObjEntry handle to the dictionary object returned by
+ OBJ_GetObjectHandle which was called before
+ \param pData Pointer to the buffer where the read data shall be copied to
+ \param bCompleteAccess Indicates if a complete read of all subindices of the
+ object shall be done or not
+
+ \return result of the read operation (0 (success) or an abort code (ABORTIDX_.... defined in
+ sdosrv.h))
+
+ \brief This function reads the requested object
+*////////////////////////////////////////////////////////////////////////////////////////
+
+UINT8 OBJ_Read( UINT16 index, UINT8 subindex, UINT32 objSize, OBJCONST TOBJECT OBJMEM * pObjEntry, UINT16 MBXMEM * pData, UINT8 bCompleteAccess )
+{
+ UINT16 i = subindex;
+ /* get the information of ObjCode and MaxSubindex in local variables to support different types of microcontroller */
+ UINT8 objCode = (pObjEntry->ObjDesc.ObjFlags & OBJFLAGS_OBJCODEMASK) >> OBJFLAGS_OBJCODESHIFT;
+ UINT16 maxSubindex = (pObjEntry->ObjDesc.ObjFlags & OBJFLAGS_MAXSUBINDEXMASK) >> OBJFLAGS_MAXSUBINDEXSHIFT;
+ OBJCONST TSDOINFOENTRYDESC OBJMEM *pEntry;
+ /* lastSubindex is used for complete access to make loop over the requested entries
+ to be read, we initialize this variable with the requested subindex that only
+ one loop will be done for a single access */
+ UINT16 lastSubindex = subindex;
+
+ if ( objCode != OBJCODE_VAR && index >= 0x1000 )
+ {
+ /* if the object is an array or record we have to get the maxSubindex from the
+ actual value of subindex 0, which is stored as UINT16 at the beginning of the
+ object's variable */
+ maxSubindex = (*((UINT16 *) (pObjEntry->pVarPtr))) & 0x00FF;
+
+/*ET9300 Project Handler :(#if TEST_APPLICATION) lines 1067 to 1080 deleted*/
+ }
+
+ if ( bCompleteAccess )
+ {
+ if ( objCode == OBJCODE_VAR || index < 0x1000 )
+ {
+ /* complete access is not supported with simple objects or ENUM descriptions */
+ return ABORTIDX_UNSUPPORTED_ACCESS;
+ }
+
+
+ /* we read until the maximum subindex */
+ lastSubindex = maxSubindex;
+ }
+ else
+ if ( subindex > maxSubindex )
+ {
+ /* the maximum subindex is reached */
+ return ABORTIDX_SUBINDEX_NOT_EXISTING;
+ }
+ else
+ {
+ /* get the corresponding entry description */
+ pEntry = OBJ_GetEntryDesc(pObjEntry, (UINT8)i);
+
+ /*Check access only for non-align entries*/
+ if(pEntry->ObjAccess != 0x0)
+ {
+ /* check if we have read access (bits 0-2 (PREOP, SAFEOP, OP) of ObjAccess)
+ by comparing with the actual state (bits 1-3 (PREOP, SAFEOP, OP) of AL Status) */
+ if (0 == (((UINT8) ((pEntry->ObjAccess & ACCESS_READ)<<1)) & (nAlStatus & STATE_MASK)))
+ {
+ /* we don't have read access */
+ if ( (pEntry->ObjAccess & ACCESS_READ) == 0 )
+ {
+ /* it is a write only entry */
+ return ABORTIDX_WRITE_ONLY_ENTRY;
+ }
+ else
+ {
+ /* we don't have read access in this state */
+ return ABORTIDX_IN_THIS_STATE_DATA_CANNOT_BE_READ_OR_STORED;
+ }
+ }
+ }
+ else
+ {
+ return ABORTIDX_UNSUPPORTED_ACCESS;
+ }
+
+/*ET9300 Project Handler :(#if TEST_APPLICATION) lines 1133 to 1140 deleted*/
+ }
+
+ /* ECATCHANGE_START(V5.13) COE4*/
+ if (pAPPL_CoeReadInd != NULL)
+ {
+ pAPPL_CoeReadInd(index, subindex, bCompleteAccess);
+ }
+ /* ECATCHANGE_END(V5.13) COE4*/
+
+ if ( pObjEntry->Read != NULL )
+ {
+ /* Read function is defined, we call the object specific read function */
+ return pObjEntry->Read(index, subindex, objSize, pData, bCompleteAccess);
+ }
+ else if ( index < 0x1000 && subindex != 0 )
+ {
+ /* an ENUM description is read */
+ UINT16 size;
+ UINT16 MBXMEM *pVarPtr = (UINT16 MBXMEM *) pObjEntry->pVarPtr;
+ CHAR **p;
+
+ /* we get the corresponding entry description */
+ pEntry = OBJ_GetEntryDesc(pObjEntry, subindex);
+ size = BIT2BYTE(pEntry->BitLength);
+
+ p = (CHAR **) pVarPtr;
+ pVarPtr = (UINT16 MBXMEM *)p[subindex-1];
+
+ /*ECATCHANGE_START(V5.13) */
+/*ET9300 Project Handler :(#if MBX_16BIT_ACCESS && !MEMORY_UNIT_16BIT) lines 1170 to 1200 deleted*/
+ {
+ // Get enum value (first 32Bit)
+/*ECATCHANGE_START(V5.13) */
+/*ET9300 Project Handler :(#if MEMORY_UNIT_16BIT) lines 1204 to 1210 deleted*/
+
+/*ET9300 Project Handler :(#if (BIG_ENDIAN_16BIT || BIG_ENDIAN_FORMAT)) lines 1212 to 1215 deleted*/
+ pData[0] = pVarPtr[0];
+ pData[1] = pVarPtr[1];
+ pData += 2;
+ pVarPtr += 2;
+/*ECATCHANGE_END(V5.13) */
+
+ // Get enum description
+ OBJTOMBXSTRCPY(pData,pVarPtr,size-4);
+ }
+ }
+ else
+ {
+ UINT8 bRead = 0x0;
+ UINT8 result = 0;
+
+
+ /* a variable object is read */
+ for (i = subindex; i <= lastSubindex; i++)
+ {
+ /* if only a single entry is requested, this loop will only be done once */
+ UINT16 MBXMEM *pVarPtr = (UINT16 MBXMEM *) pObjEntry->pVarPtr;
+ UINT16 bitOffset = 0;
+
+
+ if (i == 0)
+ {
+ /* subindex 0 is requested, the entry's data is at the beginning of the object's variable */
+ }
+ else if ( index >= 0x1000 )
+ {
+ /* subindex 1-n of an variable object is requested, we get the offset of the variable here */
+ bitOffset = OBJ_GetEntryOffset((UINT8)i, pObjEntry);
+ }
+
+ /* we increment the variable pointer to the corresponding word address */
+ pVarPtr += (bitOffset >> 4);
+
+ /* get the corresponding entry description */
+ pEntry = OBJ_GetEntryDesc(pObjEntry, (UINT8)i);
+ if (0 != (((UINT8) ((pEntry->ObjAccess & ACCESS_READ)<<1)) & (nAlStatus & STATE_MASK)) )
+ {
+ if ( i == subindex /* requested entry */
+ || (bCompleteAccess && i >= subindex) ) /* complete access and entry should be read */
+ {
+ UINT16 bitMask;
+
+ /* we have to copy the entry */
+ if ( i == 0 && objCode != OBJCODE_VAR )
+ {
+ /* we read subindex 0 of an array or record */
+/*ET9300 Project Handler :(#if TEST_APPLICATION) lines 1270 to 1276 deleted*/
+ {
+ pData[0] = SWAPWORD((UINT16)maxSubindex);
+ }
+
+ /* we increment the destination pointer by 2 because the subindex 0 will be
+ transmitted as UINT16 for a complete access */
+ pData++;
+ }
+ else
+ {
+ UINT16 dataType = pEntry->DataType;
+
+ if (pEntry->DataType >= 0x700)
+ {
+ /* the ENUM data types are defined from index 0x700 in this example
+ convert in standard data type for the read access */
+ if ( pEntry->BitLength <= 8 )
+ {
+ dataType = DEFTYPE_BIT1-1+pEntry->BitLength;
+ }
+ else if ( pEntry->BitLength == 16 )
+ {
+ dataType = DEFTYPE_UNSIGNED16;
+ }
+ else if ( pEntry->BitLength == 32 )
+ {
+ dataType = DEFTYPE_UNSIGNED32;
+ }
+ }
+
+ switch (dataType)
+ {
+ case DEFTYPE_NULL:
+ if(bCompleteAccess)
+ {
+ /*Handle alignment entry*/
+ if (((pEntry->BitLength & 0xF) > 0)
+ && (((bitOffset + pEntry->BitLength) & 0x0F) == 0 ))
+ {
+ /* we have reached the UINT16 border */
+ pData++;
+ }
+
+ /*increment WORD offset*/
+ pData += ((pEntry->BitLength & 0xF0) >> 4);
+ }
+ else
+ {
+ return ABORTIDX_DATA_CANNOT_BE_READ_OR_STORED;
+ }
+ break;
+ case DEFTYPE_BOOLEAN:
+ case DEFTYPE_BIT1:
+ case DEFTYPE_BIT2:
+ case DEFTYPE_BIT3:
+ case DEFTYPE_BIT4:
+ case DEFTYPE_BIT5:
+ case DEFTYPE_BIT6:
+ case DEFTYPE_BIT7:
+ case DEFTYPE_BIT8:
+/*ET9300 Project Handler :(#if TEST_APPLICATION) lines 1337 to 1348 deleted*/
+ case DEFTYPE_BITARR8:
+ /* in this example the objects are defined in that way,
+ that the bit types are always inside a 16-bit field,
+ and they shall not overlap a byte border*/
+ case DEFTYPE_INTEGER8:
+ case DEFTYPE_UNSIGNED8:
+ case DEFTYPE_BYTE :
+ {
+ /* depending on the bitOffset we have to copy the Hi or the Lo-Byte */
+ UINT16 TmpValue = 0x0000;
+
+
+ bitMask = cBitMask[pEntry->BitLength] << (bitOffset & 0x0F);
+
+ /*Swap object data (if required); all masks and offsets are defined for little endian format*/
+ TmpValue = SWAPWORD(pVarPtr[0]);
+
+ /*Clear pData if the first bits within the WORD memory will be copied*/
+ if ((bitOffset & 0x0F) == 0)
+ {
+ pData[0] = 0;
+ }
+
+ pData[0] = SWAPWORD(pData[0]);
+
+ if (bCompleteAccess)
+ {
+ /*shifting is not required for Complete access because the bits are set to the correct offset by the master*/
+ pData[0] |= TmpValue & bitMask;
+ }
+ else
+ {
+ /*Shift Bits to the beginning of the mailbox memory*/
+ pData[0] |= ((TmpValue & bitMask) >> (bitOffset & 0x0F));
+ }
+
+ pData[0] = SWAPWORD(pData[0]);
+ if ( ((bitOffset + pEntry->BitLength) & 0x0F) == 0 )
+ {
+ /* we have reached the UINT16 border */
+ pData++;
+ }
+
+ }
+ break;
+ case DEFTYPE_INTEGER16:
+ case DEFTYPE_UNSIGNED16:
+ case DEFTYPE_BITARR16:
+ case DEFTYPE_WORD:
+
+ if(bitOffset & 0xF)
+ {
+ /* return an error in case of an odd word offset (to support 16bit data type on odd word addresses an object specific access function need to be implemented and register in the object dictionary, see SSC Application Note)*/
+ return ABORTIDX_UNSUPPORTED_ACCESS;
+ }
+ /* in this example the objects are defined in that way,
+ that the 16 bit type are always starting at an exact WORD offset */
+ pData[0] = SWAPWORD(pVarPtr[0]);
+ pData++;
+ break;
+ case DEFTYPE_UNSIGNED32:
+ case DEFTYPE_INTEGER32:
+ case DEFTYPE_REAL32:
+ case DEFTYPE_BITARR32:
+ case DEFTYPE_DWORD:
+ if(bitOffset & 0xF)
+ {
+ /* return an error in case of an odd word offset (to support 16bit data type on odd word addresses an object specific access function need to be implemented and register in the object dictionary, see SSC Application Note)*/
+ return ABORTIDX_UNSUPPORTED_ACCESS;
+ }
+
+ /* in this example the objects are defined in that way,
+ that the 32 bit type are always starting at an exact WORD offset */
+/*ET9300 Project Handler :(#if BIG_ENDIAN_16BIT || BIG_ENDIAN_FORMAT) lines 1422 to 1425 deleted*/
+ pData[0] = pVarPtr[0];
+ pData[1] = pVarPtr[1];
+ pData += 2;
+ break;
+ case DEFTYPE_REAL64:
+ case DEFTYPE_INTEGER64:
+ case DEFTYPE_UNSIGNED64:
+ if(bitOffset & 0xF)
+ {
+ /* return an error in case of an odd word offset (to support 16bit data type on odd word addresses an object specific access function need to be implemented and register in the object dictionary, see SSC Application Note)*/
+ return ABORTIDX_UNSUPPORTED_ACCESS;
+ }
+
+ /* in this example the objects are defined in that way,
+ that the 64 bit type are always starting at an exact WORD offset */
+/*ET9300 Project Handler :(#if BIG_ENDIAN_16BIT || BIG_ENDIAN_FORMAT) lines 1442 to 1447 deleted*/
+ pData[0] = pVarPtr[0];
+ pData[1] = pVarPtr[1];
+ pData[2] = pVarPtr[2];
+ pData[3] = pVarPtr[3];
+ pData += 4;
+ break;
+ case DEFTYPE_OCTETSTRING:
+ case DEFTYPE_UNICODE_STRING:
+ case DEFTYPE_ARRAY_OF_INT :
+ case DEFTYPE_ARRAY_OF_SINT :
+ case DEFTYPE_ARRAY_OF_DINT :
+ case DEFTYPE_ARRAY_OF_UDINT:
+
+ if(bitOffset & 0xF)
+ {
+ /* return an error in case of an odd word offset (to support 16bit data type on odd word addresses an object specific access function need to be implemented and register in the object dictionary, see SSC Application Note)*/
+ return ABORTIDX_UNSUPPORTED_ACCESS;
+ }
+
+ OBJTOMBXMEMCPY(pData, pVarPtr, BIT2BYTE(pEntry->BitLength));
+
+ pData += BIT2WORD((pEntry->BitLength & ~0xF));
+
+ if((pEntry->BitLength & 0xF) != 0)
+ {
+ /*current entry has an odd word length => clear last byte of next word*/
+ *pData &= 0xFF;
+ }
+
+ break;
+ case DEFTYPE_VISIBLESTRING:
+ if(bitOffset & 0xF)
+ {
+ /* return an error in case of an odd word offset (to support 16bit data type on odd word addresses an object specific access function need to be implemented and register in the object dictionary, see SSC Application Note)*/
+ return ABORTIDX_UNSUPPORTED_ACCESS;
+ }
+
+ /* in this example the objects are defined in that way,
+ that these types are always starting at an even WORD offset */
+ OBJTOMBXSTRCPY(pData, pVarPtr, BIT2BYTE(pEntry->BitLength));
+ pData += BIT2WORD((pEntry->BitLength & ~0xF));
+
+ if((pEntry->BitLength & 0xF) != 0)
+ {
+ /*current entry has an odd word length => clear last byte of next word*/
+ *pData &= 0xFF;
+ }
+
+ break;
+ default:
+ /* other data types are not supported from this example */
+ return ABORTIDX_DATA_CANNOT_BE_READ_OR_STORED;
+ } //switch (deftype)
+
+ bRead = 1;
+ }
+ }
+ }
+ else
+ {
+ /*No access to current object entry => shift pData if required*/
+ UINT8 cnt = 0;
+
+ /*If this entry is the first in the 16Bit block clear the memory*/
+ if ((bitOffset & 0x0F) == 0)
+ {
+ *pData = 0;
+ }
+
+ /*Handle Bit/Byte Offset*/
+ if (((pEntry->BitLength & 0xF) > 0)
+ && (((bitOffset + pEntry->BitLength) & 0x0F) == 0 ))
+ {
+ /* we have reached the UINT16 border */
+ pData++;
+
+ /*Clear new buffer*/
+ *pData = 0;
+ }
+
+ /*increment WORD offset*/
+ for(cnt = 0; cnt <((pEntry->BitLength & 0xF0) >> 4); cnt++)
+ {
+
+ /*current 16Bit are skipped => clear current buffer */
+ pData++;
+
+ /*Clear new buffer*/
+ *pData = 0;
+ }
+
+
+
+
+ /* we don't have read access */
+ if ( (pEntry->ObjAccess & ACCESS_READ) == 0 )
+ {
+ /* it is a write only entry */
+ result = ABORTIDX_WRITE_ONLY_ENTRY;
+ }
+ else
+ {
+ /* we don't have read access in this state */
+ result = ABORTIDX_IN_THIS_STATE_DATA_CANNOT_BE_READ_OR_STORED;
+ }
+ }
+ }
+
+ if(bRead == 0)
+ {
+ return result;
+ }
+ }
+
+ return 0;
+}
+
+/////////////////////////////////////////////////////////////////////////////////////////
+/**
+ \param index index of the requested object.
+ \param subindex subindex of the requested object.
+ \param dataSize received data size of the SDO Download
+ \param pObjEntry handle to the dictionary object returned by
+ OBJ_GetObjectHandle which was called before
+ \param pData Pointer to the buffer where the written data can be copied from
+ \param bCompleteAccess Indicates if a complete write of all subindices of the
+ object shall be done or not
+
+ \return result of the write operation (0 (success) or an abort code (ABORTIDX_.... defined in
+ sdoserv.h))
+
+ \brief This function writes the requested object
+*////////////////////////////////////////////////////////////////////////////////////////
+
+UINT8 OBJ_Write( UINT16 index, UINT8 subindex, UINT32 dataSize, OBJCONST TOBJECT OBJMEM * pObjEntry, UINT16 MBXMEM * pData, UINT8 bCompleteAccess )
+{
+ UINT16 i = subindex;
+ /* get the information of ObjCode and MaxSubindex in local variables to support different types of microcontroller */
+ UINT8 objCode = (pObjEntry->ObjDesc.ObjFlags & OBJFLAGS_OBJCODEMASK) >> OBJFLAGS_OBJCODESHIFT;
+ UINT16 maxSubindex = 0;
+ UINT16 maxConfiguredSubindex = (pObjEntry->ObjDesc.ObjFlags & OBJFLAGS_MAXSUBINDEXMASK) >> OBJFLAGS_MAXSUBINDEXSHIFT; //required to check if value for Subindex0 is valid
+ OBJCONST TSDOINFOENTRYDESC OBJMEM *pEntry;
+ BOOL bClearSubindex0Required = FALSE;
+ /* lastSubindex is used for complete access to make loop over the requested entries
+ to be read, we initialize this variable with the requested subindex that only
+ one loop will be done for a single access */
+ UINT16 lastSubindex = subindex;
+
+ /* if subindex 0 is writable, the maximum subindex should be checked in an object specific function,
+ because for the PDO mapping and PDO assign the object shall only be written if subindex 0 is 0. */
+ if ( objCode != OBJCODE_VAR )
+ {
+ /* if the object is an array or record we have to get the maxSubindex from the
+ actual value of subindex 0, which is stored as UINT16 at the beginning of the
+ object's variable */
+ maxSubindex = (UINT8) ((UINT16 MBXMEM *) (pObjEntry->pVarPtr))[0];
+
+ /*If the subindex0 of a PDO assign or PDO mapping object is 0 the maximum subindex is specified by the object description*/
+ if(maxSubindex == 0 && (IS_PDO_ASSIGN(index) || IS_RX_PDO(index) || IS_TX_PDO(index) || (index == 0xF030)))
+ {
+ maxSubindex = maxConfiguredSubindex;
+ }
+ }
+
+
+ if ( bCompleteAccess )
+ {
+ if ( objCode == OBJCODE_VAR )
+ {
+ /* complete access is not supported with simple objects */
+ return ABORTIDX_UNSUPPORTED_ACCESS;
+ }
+
+ if ((subindex == 0) && (dataSize > 0))
+ {
+ /* we change the subindex 0 */
+ maxSubindex = (UINT8) SWAPWORD(pData[0]);
+ }
+
+
+ /* we write until the maximum subindex */
+ lastSubindex = maxSubindex;
+ }
+ else
+ if (subindex > maxSubindex)
+ {
+ /* the maximum subindex is reached */
+ return ABORTIDX_SUBINDEX_NOT_EXISTING;
+ }
+ else
+ {
+ /* we check the write access for single accesses here, a complete write access
+ is allowed if at least one entry is writable (in this case the values for the
+ read only entries shall be ignored) */
+ /* we get the corresponding entry description */
+ pEntry = OBJ_GetEntryDesc(pObjEntry, subindex);
+
+ /* check if we have write access (bits 3-5 (PREOP, SAFEOP, OP) of ObjAccess)
+ by comparing with the actual state (bits 1-3 (PREOP, SAFEOP, OP) of AL Status) */
+ if (0 == (((UINT8)((pEntry->ObjAccess & ACCESS_WRITE) >> 2)) & (nAlStatus & STATE_MASK) ))
+ {
+ /* we don't have write access */
+ if ( (pEntry->ObjAccess & ACCESS_WRITE) == 0 )
+ {
+ if (pEntry->ObjAccess == 0)
+ {
+ return ABORTIDX_UNSUPPORTED_ACCESS;
+ }
+ else
+ {
+ /* it is a read only entry */
+ return ABORTIDX_READ_ONLY_ENTRY;
+ }
+ }
+ else
+ {
+ /* we don't have write access in this state */
+ return ABORTIDX_IN_THIS_STATE_DATA_CANNOT_BE_READ_OR_STORED;
+ }
+ }
+
+/*ET9300 Project Handler :(#if TEST_APPLICATION) lines 1674 to 1681 deleted*/
+
+ }
+
+ /* Subindex 0 shall be set to zero if a single PDO / PDO assign entry is written
+ or a complete access without subindex0 is requested */
+ if((subindex > 0) &&
+ (IS_PDO_ASSIGN(index) || IS_RX_PDO(index)|| IS_TX_PDO(index) || (index == 0xF030))
+ )
+ {
+ /*Check if Subindex0 was cleared before*/
+ UINT16 Subindex0 = (*(UINT16 *)pObjEntry->pVarPtr) & 0x00FF;
+ if(Subindex0 != 0x00)
+ {
+ bClearSubindex0Required = TRUE;
+ }
+ }
+
+ if ( pObjEntry->Write != NULL )
+ {
+ /* Write function is defined, we call the object specific write function */
+ /* ECATCHANGE_START(V5.13) COE4*/
+ UINT8 result = 0;
+
+ result = pObjEntry->Write(index, subindex, dataSize, pData, bCompleteAccess);
+
+ if ((result == 0) && (pAPPL_CoeWriteInd != NULL))
+ {
+ pAPPL_CoeWriteInd(index, subindex, bCompleteAccess);
+ }
+
+ return result;
+ /* ECATCHANGE_END(V5.13) COE4*/
+ }
+ else
+ {
+ UINT8 bWritten = 0;
+ UINT8 result = ABORTIDX_READ_ONLY_ENTRY;
+
+ if (dataSize == 0)
+ {
+ return 0; //no error
+ }
+
+/*ET9300 Project Handler :(#if TEST_APPLICATION) lines 1725 to 1731 deleted*/
+ /* we use the standard write function */
+ for (i = subindex; i <= lastSubindex; i++)
+ {
+ /* if only a single entry is requested, this loop will only be done once */
+ UINT16 MBXMEM *pVarPtr = (UINT16 MBXMEM *) pObjEntry->pVarPtr;
+ UINT16 bitOffset = 0;
+
+ /* we get the corresponding entry description */
+ pEntry = OBJ_GetEntryDesc(pObjEntry,(UINT8) i);
+
+ /*Get the bitOffset before check the access rights to calculate pData offset*/
+ bitOffset = OBJ_GetEntryOffset((UINT8)i, pObjEntry);
+
+ /* we check if we have write access (bits 3-5 (PREOP, SAFEOP, OP) of ObjAccess)
+ by comparing with the actual state (bits 1-3 (PREOP, SAFEOP, OP) of AL Status) */
+ if (0 != (((UINT8)((pEntry->ObjAccess & ACCESS_WRITE) >> 2)) & (nAlStatus & STATE_MASK) ))
+ {
+ /* we have write access for this entry */
+ if (i != 0)
+ {
+ /* we increment the variable pointer to the corresponding word address */
+ pVarPtr += (bitOffset >> 4);
+ }
+
+
+ if ( i == subindex /* requested entry */
+ || (bCompleteAccess && i >= subindex) ) /* complete access and entry should be read */
+ {
+ UINT16 bitMask;
+
+ /* we have to copy the entry */
+ if (i == 0 && objCode != OBJCODE_VAR)
+ {
+ /*check if the value for subindex0 is valid */
+ UINT8 NewSubindex0 = (UINT8) SWAPWORD(pData[0]);
+
+ if(maxConfiguredSubindex < NewSubindex0)
+ {
+ return ABORTIDX_VALUE_TOO_GREAT;
+ }
+
+ /* subindex 0 of an array or record shall be written */
+ pVarPtr[0] = SWAPWORD(pData[0]);
+ /* we increment the destination pointer by 2 because the subindex 0 will be
+ transmitted as UINT16 for a complete access */
+ pData++;
+ }
+ else
+ {
+ UINT16 dataType = pEntry->DataType;
+ if (pEntry->DataType >= 0x700)
+ {
+ /* the ENUM data types are defined from index 0x700 in this example
+ convert in standard data type for the write access */
+ if ( pEntry->BitLength <= 8 )
+ {
+ dataType = DEFTYPE_BIT1-1+pEntry->BitLength;
+ }
+ else if ( pEntry->BitLength == 16 )
+ {
+ dataType = DEFTYPE_UNSIGNED16;
+ }
+ else if ( pEntry->BitLength == 32 )
+ {
+ dataType = DEFTYPE_UNSIGNED32;
+ }
+ }
+
+ switch (dataType)
+ {
+ case DEFTYPE_NULL:
+ if(bCompleteAccess)
+ {
+ /*Handle alignment entry*/
+ if (((pEntry->BitLength & 0xF) > 0)
+ && (((bitOffset + pEntry->BitLength) & 0x0F) == 0 ))
+ {
+ /* we have reached the UINT16 border */
+ pData++;
+ }
+
+ /*increment WORD offset*/
+ pData += ((pEntry->BitLength & 0xF0) >> 4);
+ }
+ else
+ {
+ return ABORTIDX_DATA_CANNOT_BE_READ_OR_STORED;
+ }
+ break;
+ case DEFTYPE_BOOLEAN:
+ case DEFTYPE_BIT1:
+ case DEFTYPE_BIT2:
+ case DEFTYPE_BIT3:
+ case DEFTYPE_BIT4:
+ case DEFTYPE_BIT5:
+ case DEFTYPE_BIT6:
+ case DEFTYPE_BIT7:
+ case DEFTYPE_BIT8:
+/*ET9300 Project Handler :(#if TEST_APPLICATION) lines 1832 to 1843 deleted*/
+ case DEFTYPE_BITARR8:
+ /* in this example the objects are defined in that way,
+ that the bit types are always inside a 16-bit field,
+ and shall not overlap a byte border*/
+ case DEFTYPE_INTEGER8:
+ case DEFTYPE_UNSIGNED8:
+ case DEFTYPE_BYTE :
+ {
+ /* depending on the bitOffset we have to copy the Hi or the Lo-Byte */
+ UINT16 TmpValue = 0x0000;
+
+ bitMask = cBitMask[pEntry->BitLength] << (bitOffset & 0x0F);
+
+ /*Swap object data (if required); all masks and offsets are defined for little endian format*/
+ TmpValue = SWAPWORD(pVarPtr[0]);
+
+ /*Clear corresponding bits*/
+ TmpValue &= ~bitMask;
+
+ if (bCompleteAccess)
+ {
+ /*shifting is not required for Complete access because the bits are set to the correct offset by the master*/
+ TmpValue |= (SWAPWORD(pData[0]) & bitMask);
+ }
+ else
+ {
+ if((SWAPWORD(pData[0]) & ~cBitMask[pEntry->BitLength]))
+ {
+ /*written value exceed entry range*/
+ return ABORTIDX_VALUE_EXCEEDED;
+ }
+ else
+ {
+ /*Shift Bits to corresponding offset within the object memory*/
+ TmpValue |= ((SWAPWORD(pData[0]) & cBitMask[pEntry->BitLength]) << (bitOffset & 0x0F));
+ }
+ }
+
+ /*Swap written data to big endian format (if required)*/
+ pVarPtr[0] = SWAPWORD(TmpValue);
+
+ if ( ((bitOffset+pEntry->BitLength) & 0x0F) == 0 )
+ {
+ /* we have reached the UINT16 border */
+ pData++;
+ }
+ }
+ break;
+ case DEFTYPE_INTEGER16:
+ case DEFTYPE_UNSIGNED16:
+ case DEFTYPE_BITARR16:
+ case DEFTYPE_WORD:
+ if(bitOffset & 0xF)
+ {
+ /* return an error in case of an odd word offset (to support 16bit data type on odd word addresses an object specific access function need to be implemented and register in the object dictionary, see SSC Application Note)*/
+ return ABORTIDX_UNSUPPORTED_ACCESS;
+ }
+
+ {
+ /* in this example the objects are defined in that way,
+ that the 16 bit type are always starting at an exact WORD offset */
+ UINT16 u16NewData = SWAPWORD(pData[0]);
+ if(bClearSubindex0Required && (pVarPtr[0] != u16NewData))
+ {
+ /* try to write new data when subindex0 shall be reset*/
+ return ABORTIDX_ENTRY_CANT_BE_WRITTEN_SI0_NOT_0;
+ }
+
+ /*check value if a new PDO assign entry should be written*/
+ if(IS_PDO_ASSIGN(index)) //PDO assign
+ {
+ if (!IS_RX_PDO(u16NewData) && !IS_TX_PDO(u16NewData) && (u16NewData != 0)) //check if the new assign entry value is valid
+ {
+ return ABORTIDX_VALUE_EXCEEDED;
+ }
+ }
+
+ if(index == 0x1C32 || index == 0x1C33)
+ {
+ if (i == 1) /* "Synchronisation type" written */
+ {
+ /* The Synchronisation type (0x1C3x.1) was written by the user => the Sync type will not be calculated based on the register settings (if they don't match an error will be returned P_2_S)*/
+ if (pVarPtr[0] != u16NewData)
+ {
+ result = CheckSyncTypeValue(index, u16NewData);
+
+ if (result != 0)
+ {
+ return result;
+ }
+ }
+
+ /* The user may force to current Sync Mode for that reason the flag has also to be set if the same value was written */
+ bSyncSetByUser = TRUE;
+ }
+
+ if (i == 8) /* "Get Cycle Time" written*/
+ {
+
+ sSyncManOutPar.u32CalcAndCopyTime = (PD_OUTPUT_CALC_AND_COPY_TIME);
+ sSyncManOutPar.u32MinCycleTime = (MIN_PD_CYCLE_TIME);
+ sSyncManOutPar.u32CycleTime = 0;
+
+ sSyncManInPar.u32CalcAndCopyTime = (PD_INPUT_CALC_AND_COPY_TIME);
+ sSyncManInPar.u32MinCycleTime = (MIN_PD_CYCLE_TIME);
+ sSyncManInPar.u32CycleTime = 0;
+
+
+ if ((u16NewData & 0x2) == 0x2)
+ {
+ /* reset the error counters*/
+ sSyncManOutPar.u16CycleExceededCounter = 0;
+ sSyncManOutPar.u16SmEventMissedCounter = 0;
+ sSyncManOutPar.u8SyncError = 0;
+
+ sSyncManInPar.u16CycleExceededCounter = 0;
+ sSyncManInPar.u16SmEventMissedCounter = 0;
+ sSyncManInPar.u8SyncError = 0;
+ }
+ } /* Subindex 8 written*/
+ }
+
+ pVarPtr[0] = u16NewData;
+ pData++;
+ }
+ break;
+ case DEFTYPE_UNSIGNED32:
+ case DEFTYPE_INTEGER32:
+ case DEFTYPE_REAL32:
+ case DEFTYPE_BITARR32:
+ case DEFTYPE_DWORD:
+ if(bitOffset & 0xF)
+ {
+ /* return an error in case of an odd word offset (to support 16bit data type on odd word addresses an object specific access function need to be implemented and register in the object dictionary, see SSC Application Note)*/
+ return ABORTIDX_UNSUPPORTED_ACCESS;
+ }
+ {
+
+ /* in this example the objects are defined in that way,
+ that the 32 bit type are always starting at an exact WORD offset */
+/*ET9300 Project Handler :(#if BIG_ENDIAN_16BIT || BIG_ENDIAN_FORMAT) lines 1992 to 2003 deleted*/
+ if(bClearSubindex0Required &&
+ ((pVarPtr[0] != pData[0])
+ || (pVarPtr[1] != pData[1])))
+ {
+ /* try to write new data when subindex0 shall be reset*/
+ return ABORTIDX_ENTRY_CANT_BE_WRITTEN_SI0_NOT_0;
+ }
+
+ pVarPtr[0] = pData[0];
+ pVarPtr[1] = pData[1];
+ pData += 2;
+ }
+/*ET9300 Project Handler :(#if TEST_APPLICATION && DIAGNOSIS_SUPPORTED) lines 2017 to 2028 deleted*/
+ break;
+ case DEFTYPE_REAL64:
+ case DEFTYPE_INTEGER64:
+ case DEFTYPE_UNSIGNED64:
+ if(bitOffset & 0xF)
+ {
+ /* return an error in case of an odd word offset (to support 16bit data type on odd word addresses an object specific access function need to be implemented and register in the object dictionary, see SSC Application Note)*/
+ return ABORTIDX_UNSUPPORTED_ACCESS;
+ }
+ /* in this example the objects are defined in that way,
+ that the 64 bit type are always starting at an exact WORD offset */
+/*ET9300 Project Handler :(#if BIG_ENDIAN_16BIT || BIG_ENDIAN_FORMAT) lines 2040 to 2045 deleted*/
+ pVarPtr[0] = pData[0];
+ pVarPtr[1] = pData[1];
+ pVarPtr[2] = pData[2];
+ pVarPtr[3] = pData[3];
+ pData += 4;
+ break;
+ case DEFTYPE_VISIBLESTRING:
+ if(bitOffset & 0xF)
+ {
+ /* return an error in case of an odd word offset (to support 16bit data type on odd word addresses an object specific access function need to be implemented and register in the object dictionary, see SSC Application Note)*/
+ return ABORTIDX_UNSUPPORTED_ACCESS;
+ }
+
+ OBJTOMBXSTRCPY(pVarPtr, pData, BIT2BYTE(pEntry->BitLength));
+
+ pData += BIT2WORD((pEntry->BitLength)& ~0xF);
+ break;
+ case DEFTYPE_OCTETSTRING:
+ case DEFTYPE_UNICODE_STRING:
+ case DEFTYPE_ARRAY_OF_INT :
+ case DEFTYPE_ARRAY_OF_SINT :
+ case DEFTYPE_ARRAY_OF_DINT :
+ case DEFTYPE_ARRAY_OF_UDINT:
+ if(bitOffset & 0xF)
+ {
+ /* return an error in case of an odd word offset (to support 16bit data type on odd word addresses an object specific access function need to be implemented and register in the object dictionary, see SSC Application Note)*/
+ return ABORTIDX_UNSUPPORTED_ACCESS;
+ }
+
+ /* in this example the objects are defined in that way,
+ that the other types are always starting at an even byte offset */
+ OBJTOMBXMEMCPY(pVarPtr, pData, BIT2BYTE(pEntry->BitLength));
+ pData += BIT2WORD((pEntry->BitLength) & ~0xF);
+
+ break;
+ default:
+ /* other data types are not supported from this example */
+ return ABORTIDX_DATA_CANNOT_BE_READ_OR_STORED;
+ }
+ }
+
+ /* set flag */
+ bWritten = 1;
+
+/*ET9300 Project Handler :(#if STORE_BACKUP_PARAMETER_IMMEDIATELY && BACKUP_PARAMETER_SUPPORTED) lines 2091 to 2098 deleted*/
+ }
+ }
+ else
+ {
+ if(i == 0)
+ {
+ /* For SubIndex0 16Bit are reserved even if the BitLength is 8 */
+ pData++;
+ }
+ else
+ {
+ /*Handle Bit/Byte Offset*/
+ if (((pEntry->BitLength & 0xF) > 0)
+ && (((bitOffset + pEntry->BitLength) & 0x0F) == 0 ))
+ {
+ /* we have reached the UINT16 border */
+ pData++;
+ }
+
+ /*increment WORD offset*/
+ pData += ((pEntry->BitLength & 0xFFF0) >> 4);
+ }
+ /*If no other entry was written this result will be returned*/
+ result = ABORTIDX_DATA_CANNOT_BE_READ_OR_STORED;
+ }
+ }
+
+ if (bWritten == 0)
+ {
+ /* we didn't write anything, so we have to return the stored error code */
+ return result;
+ }
+ }
+
+ /* ECATCHANGE_START(V5.13) COE4*/
+ if (pAPPL_CoeWriteInd != NULL)
+ {
+ pAPPL_CoeWriteInd(index, subindex, bCompleteAccess);
+ }
+ /* ECATCHANGE_END(V5.13) COE4*/
+
+ return 0;
+}
+/** @} */
+
+
+
diff --git a/Projects/EFC_EcatDriver/src/ssc/objdef.h b/Projects/EFC_EcatDriver/src/ssc/objdef.h
new file mode 100644
index 0000000..be74ddc
--- /dev/null
+++ b/Projects/EFC_EcatDriver/src/ssc/objdef.h
@@ -0,0 +1,293 @@
+/*
+* This source file is part of the EtherCAT Slave Stack Code licensed by Beckhoff Automation GmbH & Co KG, 33415 Verl, Germany.
+* The corresponding license agreement applies. This hint shall not be removed.
+* https://www.beckhoff.com/media/downloads/slave-stack-code/ethercat_ssc_license.pdf
+*/
+
+/**
+ * \addtogroup CoE CAN Application Profile over EtherCAT
+ * @{
+ */
+
+/**
+\file objdef.h
+\author EthercatSSC@beckhoff.com
+\brief CAN application profile over EtherCAT object dictionary
+
+\version 5.11
+
+ Changes to version V5.10:
+V5.11 COE2: update synctype supported flag for freerun
+V5.11 COE3: change 0x10F3.2 (Sync Error limit) from UINT32 to UINT16 (according to the ETG.1020)
+V5.11 ECAT10: change PROTO handling to prevent compiler errors
+ Changes to version V5.01:
+V5.10 COE1: Define one entry description for all 0x1C3x objects and change data type of SI11,12,13 to UINT16 (according ETG.1020)
+V5.10 COE2: Change return value of Get ObjectSize to UINT32
+ Change object size to UINT32
+V5.10 ECAT13: Update Synchronisation handling (FreeRun,SM Sync, Sync0, Sync1)
+ Compare DC UINT configuration (by ESC Config data) vs. DC activation register settings
+ Update 0x1C3x entries
+V5.10 ECAT8: Update Datatype defines according ETG.1020
+ Changes to version - :
+V5.01 : Start file change log
+ */
+
+/*-----------------------------------------------------------------------------------------
+------
+------ Includes
+------
+-----------------------------------------------------------------------------------------*/
+#include "sdoserv.h"
+
+
+#ifndef _OBJDEF_H_
+#define _OBJDEF_H_
+
+
+/*-----------------------------------------------------------------------------------------
+------
+------ Defines and Types
+------
+-----------------------------------------------------------------------------------------*/
+
+/*---------------------------------------------
+- DataTypes
+-----------------------------------------------*/
+#define DEFTYPE_NULL 0x0000 /**< \brief Null*/
+#define DEFTYPE_BOOLEAN 0x0001 /**< \brief BOOLEAN*/
+#define DEFTYPE_INTEGER8 0x0002 /**< \brief INTEGER8*/
+#define DEFTYPE_INTEGER16 0x0003 /**< \brief INTEGER16*/
+#define DEFTYPE_INTEGER24 0x0010 /**< \brief INTEGER24*/
+#define DEFTYPE_INTEGER32 0x0004 /**< \brief INTEGER32*/
+#define DEFTYPE_INTEGER40 0x0012 /**< \brief INTEGER40*/
+#define DEFTYPE_INTEGER48 0x0013 /**< \brief INTEGER48*/
+#define DEFTYPE_INTEGER56 0x0014 /**< \brief INTEGER56*/
+#define DEFTYPE_UNSIGNED8 0x0005 /**< \brief UNSIGNED8*/
+#define DEFTYPE_UNSIGNED16 0x0006 /**< \brief UNSIGNED16*/
+#define DEFTYPE_UNSIGNED24 0x0016 /**< \brief UNSIGNED24*/
+#define DEFTYPE_UNSIGNED32 0x0007 /**< \brief UNSIGNED32*/
+#define DEFTYPE_REAL32 0x0008 /**< \brief REAL32*/
+#define DEFTYPE_VISIBLESTRING 0x0009 /**< \brief VISIBLE_STRING*/
+#define DEFTYPE_OCTETSTRING 0x000A /**< \brief OCTET_STRING*/
+#define DEFTYPE_UNICODE_STRING 0x000B /**< \brief UNICODE_STRING*/
+#define DEFTYPE_TIME_OF_DAY 0x000C /**< \brief TIME_OF_DAY*/
+#define DEFTYPE_TIME_DIFFERENCE 0x000D /**< \brief TIME_DIFFERENCE*/
+#define DEFTYPE_INTEGER24 0x0010 /**< \brief INTEGER24*/
+#define DEFTYPE_REAL64 0x0011 /**< \brief REAL64*/
+#define DEFTYPE_INTEGER40 0x0012 /**< \brief INTEGER40*/
+#define DEFTYPE_INTEGER48 0x0013 /**< \brief INTEGER48*/
+#define DEFTYPE_INTEGER56 0x0014 /**< \brief INTEGER56*/
+#define DEFTYPE_INTEGER64 0x0015 /**< \brief INTEGER64*/
+#define DEFTYPE_UNSIGNED24 0x0016 /**< \brief UNSIGNED24*/
+#define DEFTYPE_UNSIGNED40 0x0018 /**< \brief UNSIGNED40*/
+#define DEFTYPE_UNSIGNED48 0x0019 /**< \brief UNSIGNED48*/
+#define DEFTYPE_UNSIGNED56 0x001A /**< \brief UNSIGNED56*/
+#define DEFTYPE_UNSIGNED64 0x001B /**< \brief UNSIGNED64*/
+#define DEFTYPE_GUID 0x001D /**< \brief DEFTYPE_GUID*/
+#define DEFTYPE_BYTE 0x001E /**< \brief DEFTYPE_BYTE*/
+#define DEFTYPE_WORD 0x001F /**< \brief DEFTYPE_WORD*/
+#define DEFTYPE_DWORD 0x0020 /**< \brief DEFTYPE_DWORD*/
+#define DEFTYPE_PDOMAPPING 0x0021 /**< \brief PDO_MAPPING*/
+#define DEFTYPE_IDENTITY 0x0023 /**< \brief IDENTITY*/
+#define DEFTYPE_COMMAND 0x0025 /**< \brief COMMAND_PAR*/
+#define DEFTYPE_PDOCOMPAR 0x0027 /**< \brief PDO_PARAMETER*/
+#define DEFTYPE_ENUM 0x0028 /**< \brief DEFTYPE_ENUM */
+#define DEFTYPE_SMPAR 0x0029 /**< \brief SM_SYNCHRONISATION*/
+#define DEFTYPE_RECORD 0x002A /**< \brief DEFTYPE_RECORD */
+#define DEFTYPE_BACKUP 0x002B /**< \brief BACKUP_PARAMETER*/
+#define DEFTYPE_MDP 0x002C /**< \brief MODULAR_DEVICE_PROFILE*/
+#define DEFTYPE_BITARR8 0x002D /**< \brief BITARR8*/
+#define DEFTYPE_BITARR16 0x002E /**< \brief BITARR16*/
+#define DEFTYPE_BITARR32 0x002F /**< \brief BITARR32*/
+#define DEFTYPE_BIT1 0x0030 /**< \brief BIT1*/
+#define DEFTYPE_BIT2 0x0031 /**< \brief BIT2*/
+#define DEFTYPE_BIT3 0x0032 /**< \brief BIT3*/
+#define DEFTYPE_BIT4 0x0033 /**< \brief BIT4*/
+#define DEFTYPE_BIT5 0x0034 /**< \brief BIT5*/
+#define DEFTYPE_BIT6 0x0035 /**< \brief BIT6*/
+#define DEFTYPE_BIT7 0x0036 /**< \brief BIT7*/
+#define DEFTYPE_BIT8 0x0037 /**< \brief BIT8*/
+#define DEFTYPE_ARRAY_OF_INT 0x0260 /**< \brief DEFTYPE_ARRAY_OF_INT*/
+#define DEFTYPE_ARRAY_OF_SINT 0x0261 /**< \brief DEFTYPE_ARRAY_OF_SINT*/
+#define DEFTYPE_ARRAY_OF_DINT 0x0262 /**< \brief DEFTYPE_ARRAY_OF_DINT*/
+#define DEFTYPE_ARRAY_OF_UDINT 0x0263 /**< \brief DEFTYPE_ARRAY_OF_UDINT*/
+#define DEFTYPE_ERRORHANDLING 0x0281 /**< \brief DEFTYPE_ERRORHANDLING*/
+#define DEFTYPE_DIAGHISTORY 0x0282 /**< \brief DEFTYPE_DIAGHISTORY*/
+#define DEFTYPE_SYNCSTATUS 0x0283 /**< \brief DEFTYPE_SYNCSTATUS*/
+#define DEFTYPE_SYNCSETTINGS 0x0284 /**< \brief DEFTYPE_SYNCSETTINGS*/
+#define DEFTYPE_FSOEFRAME 0x0285 /**< \brief DEFTYPE_FSOEFRAME*/
+#define DEFTYPE_FSOECOMMPAR 0x0286 /**< \brief DEFTYPE_FSOECOMMPAR*/
+
+
+/*---------------------------------------------
+- Flags for supported Synctypes (0x1C32.4 / 0x1C33.4)
+-----------------------------------------------*/
+
+#define SYNCTYPE_FREERUNSUPP 0x0001 /**< \brief FreeRun supported*/
+#define SYNCTYPE_SYNCHRONSUPP 0x0002 /**< \brief SyncManager synchron supported*/
+#define SYNCTYPE_DCSYNC0SUPP 0x0004 /**< \brief Sync0 synchron supported*/
+#define SYNCTYPE_DCSYNC1SUPP 0x0008 /**< \brief Sync1 synchron supported*/
+#define SYNCTYPE_SUBCYCLESUPP 0x0010 /**< \brief Subordinated Application with fixed Sync0 supported*/
+#define SYNCTYPE_LOCALSHIFTSUPP 0x0020 /**< \brief Event shift with local timer supported. Output shift : 0x1C32.4 ; Input shift : 0x1C33.4 (not supported by the default SSC)*/
+#define SYNCTYPE_SHIFTBYSYNC1SUPP 0x0040 /**< \brief Event shift with Sync1 event supported. Output shift : 0x1C32.4 ; Input shift : 0x1C33.4*/
+#define SYNCTYPE_MEASURE_DELAYSUPP 0x0200 /**< \brief Delay times should be measured (not supported by the default SSC, only the cycle time can be measured (1ms resolution)*/
+#define SYNCTYPE_FIXED_DELAYSUPP 0x0400 /**< \brief Delay times are fixed*/
+#define SYNCTYPE_TIMESVARIABLE 0x4000 /**< \brief Dynamic Cycle Times supported*/
+
+
+#define IS_PDO_ASSIGN(x) ((x >= 0x1C10) && (x <= 0x1C2F)) /**< \brief Macro to check if object index is SyncManager assign object*/
+#define IS_RX_PDO(x) (((x) >= 0x1600) && ((x) <= 0x17FF)) /**< \brief Macro to check if object index RxPDO mapping object*/
+#define IS_TX_PDO(x) (((x) >= 0x1A00) && ((x) <= 0x1BFF)) /**< \brief Macro to check if object index TxPDO mapping object*/
+
+
+/**
+ * \brief Object dictionary entry structure
+ */
+typedef struct OBJ_ENTRY
+{
+ struct OBJ_ENTRY *pPrev; /**< \brief Previous entry(object) in the object dictionary list*/
+ struct OBJ_ENTRY *pNext; /**< \brief Next entry(object) in the object dictionary list*/
+
+ UINT16 Index; /**< \brief Object index*/
+ TSDOINFOOBJDESC ObjDesc; /**< \brief Object access, type and code*/
+ OBJCONST TSDOINFOENTRYDESC OBJMEM *pEntryDesc; /**< \brief pointer to object entry descriptions*/
+ OBJCONST UCHAR OBJMEM *pName; /**< \brief Pointer to object and entry names*/
+ void MBXMEM *pVarPtr; /**< \brief Pointer to object buffer*/
+ UINT8 (* Read)( UINT16 Index, UINT8 Subindex, UINT32 Size, UINT16 MBXMEM * pData, UINT8 bCompleteAccess ); /**< \brief Function pointer to read function (if NULL default read function will be used)*/
+ UINT8 (* Write)( UINT16 Index, UINT8 Subindex, UINT32 Size, UINT16 MBXMEM * pData, UINT8 bCompleteAccess ); /**< \brief Function pointer to write function (if NULL default write function will be used)*/
+ UINT16 NonVolatileOffset; /**< \brief Offset within the non volatile memory (need to be defined for backup objects)*/
+}
+TOBJECT;
+
+
+/**
+ * Object 0x1C3x (SyncManager Parameter) data structure
+ */
+typedef struct OBJ_STRUCT_PACKED_START
+{
+ UINT16 subindex0;/**< \brief SubIndex0*/
+ UINT16 u16SyncType; /**< \brief SunbIndex 001: Sync type*/
+ UINT32 u32CycleTime;/**< \brief SunbIndex 002: Cycle time */
+ UINT32 u32Subindex003;/**< \brief SunbIndex 003: Shift time (not supported, variable is only used as a place holder)*/
+ UINT16 u16SyncTypesSupported;/**< \brief SunbIndex 004: Supported Sync types*/
+ UINT32 u32MinCycleTime;/**< \brief SunbIndex 005: Min cycle time*/
+ UINT32 u32CalcAndCopyTime;/**< \brief SunbIndex 006: Calc and Copy time*/
+ UINT32 u32Si7Reserved;/**< \brief SunbIndex 007: 32Bit Reserved*/
+ UINT16 u16GetCycleTime;/**< \brief SunbIndex 008: Get cycle time*/
+ UINT32 u32DelayTime; /**< \brief SunbIndex 009: Delay time*/
+ UINT32 u32Sync0CycleTime; /**< \brief SunbIndex 010: Sync0 cycle time*/
+ UINT16 u16SmEventMissedCounter; /**< \brief SunbIndex 011: SyncManager event missed counter*/
+ UINT16 u16CycleExceededCounter; /**< \brief SunbIndex 012: Cycle exceed counter*/
+ UINT16 u16ShiftTooShort; /**< \brief SunbIndex 013: Shift too short*/
+ UINT16 u16Si14Reserved; /**< \brief SubIndex14 not supported*/
+ UINT32 u32Si15Reserved; /**< \brief SubIndex15 not supported*/
+ UINT32 u32Si16Reserved; /**< \brief SubIndex16 not supported*/
+ UINT32 u32Si17Reserved; /**< \brief SubIndex17 not supported*/
+ UINT32 u32Si18Reserved; /**< \brief SubIndex18 not supported*/
+ UINT8 u8SyncError; /**< \brief Sync Error*/
+}OBJ_STRUCT_PACKED_END
+TSYNCMANPAR;
+
+/**
+ * Cycle diagnosis
+ */
+typedef struct OBJ_STRUCT_PACKED_START
+{
+ UINT16 syncFailedCounter; /**< \brief Sync Failed Counter*/
+}OBJ_STRUCT_PACKED_END
+TCYCLEDIAG;
+
+
+/**
+ * Object 0x10F1 (Error Settings Object) data structure
+ */
+typedef struct OBJ_STRUCT_PACKED_START {
+ UINT16 u16SubIndex0; /**< \brief SubIndex0*/
+ UINT32 u32LocalErrorReaction; /**< \brief Local error reaction*/
+ UINT16 u16SyncErrorCounterLimit; /**< \brief Sync error counter limit*/
+} OBJ_STRUCT_PACKED_END
+TOBJ10F1;
+
+#endif //_OBJDEF_H_
+
+
+/*-----------------------------------------------------------------------------------------
+------
+------ Global variables
+------
+-----------------------------------------------------------------------------------------*/
+#if defined(_OBJDEF_) && (_OBJDEF_ == 1)
+ #define PROTO
+#else
+ #define PROTO extern
+#endif
+
+/**
+ * Indicates if the synchronisation was written by the user on startup (by writing 0x1C3x.1).
+ * If it was not written the sync mode will be set based on the DC registers 0x980:0x981
+ */
+PROTO BOOL bSyncSetByUser;
+
+/**
+ * \brief Cycle diagnosis variable
+ */
+PROTO TCYCLEDIAG sCycleDiag;
+
+
+/**
+ * \brief Object 0x1C32 (SyncManager 2 Parameter) object variable
+ */
+PROTO TSYNCMANPAR MBXMEM sSyncManOutPar;
+
+
+/**
+ * \brief Object 0x1C33 (SyncManager 3 Parameter) object variable
+ */
+PROTO TSYNCMANPAR MBXMEM sSyncManInPar;
+
+
+/**
+ * \brief Object 0x10F1 (Error Settings) object variable
+ *
+ * SubIndex0 : 2
+ * Local error reaction : 1
+ * Sync error counter limit : MAX_SM_EVENT_MISSED
+ */
+PROTO TOBJ10F1 sErrorSettings
+#if defined(_OBJDEF_) && (_OBJDEF_ == 1)
+= {2, 0x01, MAX_SM_EVENT_MISSED}
+#endif
+;
+
+
+/**
+ * \brief Default entry name "SubIndex 000"
+ */
+PROTO CHAR OBJMEM aSubindexDesc[13]
+#if defined(_OBJDEF_) && (_OBJDEF_ == 1)
+ = { "SubIndex 000" }
+#endif
+;
+
+
+/*-----------------------------------------------------------------------------------------
+------
+------ Global functions
+------
+-----------------------------------------------------------------------------------------*/
+
+PROTO OBJCONST TOBJECT OBJMEM * OBJ_GetObjectHandle( UINT16 index );
+PROTO UINT32 OBJ_GetObjectLength( UINT16 index, UINT8 subindex, OBJCONST TOBJECT OBJMEM * pObjEntry, UINT8 bCompleteAccess);
+PROTO UINT16 OBJ_GetNoOfObjects(UINT8 listType);
+PROTO UINT16 OBJ_GetObjectList(UINT16 listType, UINT16 *pIndex, UINT16 size, UINT16 MBXMEM *pData,UINT8 *pAbort);
+PROTO UINT16 OBJ_GetDesc( UINT16 index, UINT8 subindex, OBJCONST TOBJECT OBJMEM * pObjEntry, UINT16 MBXMEM * pData );
+PROTO OBJCONST TSDOINFOENTRYDESC OBJMEM * OBJ_GetEntryDesc(OBJCONST TOBJECT OBJMEM * pObjEntry, UINT8 Subindex);
+PROTO OBJCONST TSDOINFOOBJDESC OBJMEM * OBJ_GetObjDesc(OBJCONST TOBJECT OBJMEM * pObjEntry);
+PROTO UINT16 OBJ_GetEntryOffset(UINT8 subindex, OBJCONST TOBJECT OBJMEM * pObjEntry);
+PROTO UINT8 CheckSyncTypeValue(UINT16 index, UINT16 NewSyncType);
+PROTO UINT8 OBJ_Read(UINT16 index, UINT8 subindex, UINT32 objSize, OBJCONST TOBJECT OBJMEM * pObjEntry, UINT16 MBXMEM * pData, UINT8 bCompleteAccess);
+PROTO UINT8 OBJ_Write(UINT16 index, UINT8 subindex, UINT32 dataSize, OBJCONST TOBJECT OBJMEM * pObjEntry, UINT16 MBXMEM * pData, UINT8 bCompleteAccess);
+PROTO void COE_WriteBackupEntry(UINT8 subindex, OBJCONST TOBJECT OBJMEM * pObjEntry);
+
+#undef PROTO
+/** @}*/
diff --git a/Projects/EFC_EcatDriver/src/ssc/sdoserv.c b/Projects/EFC_EcatDriver/src/ssc/sdoserv.c
new file mode 100644
index 0000000..3b05fe7
--- /dev/null
+++ b/Projects/EFC_EcatDriver/src/ssc/sdoserv.c
@@ -0,0 +1,1382 @@
+/*
+* This source file is part of the EtherCAT Slave Stack Code licensed by Beckhoff Automation GmbH & Co KG, 33415 Verl, Germany.
+* The corresponding license agreement applies. This hint shall not be removed.
+* https://www.beckhoff.com/media/downloads/slave-stack-code/ethercat_ssc_license.pdf
+*/
+
+/**
+\addtogroup CoE CAN Application Profile over EtherCAT
+@{
+*/
+
+/**
+\file sdoserv.c
+\author EthercatSSC@beckhoff.com
+\brief Implementation
+The SDO server handles all sdo and sdo information services
+
+\version 5.13
+
+ Changes to version V5.12:
+V5.13 COE5: handle complete access if segmented transfer is required, handle unsupported segmented uploads
+ Changes to version V5.11:
+V5.12 COE2: do not clear the object index low byte in case of creating a SDO Abort
+V5.12 COE5: updates in case of MBX_16BIT_ACCESS == 0
+V5.12 COE6: handle get object length in case of an out of range subindex
+V5.12 ECAT2: big endian changes
+V5.12 EOE4: handle 16bit only acceess, move ethernet protocol defines and structures to application header files
+V5.12 MBX3: handle incomplete mailbox communication
+V5.12 TEST3: Send ping request or invalid mbx data in case of access to idx 0x1009
+ Changes to version V5.10:
+V5.11 ECAT10: change PROTO handling to prevent compiler errors
+V5.11 ECAT7: add missing big endian swapping
+V5.11 SDO10: add new SDO abort code 0x6010004 (complete access not supported)
+V5.11 SDO4: "if insufficient memory is available on complete download access return ""unsupported access"""
+ Changes to version V5.01:
+V5.10 ESC5: Add missing swapping
+V5.10 MBX1: Remove multiple swapping of length filed in mailbox header
+V5.10 SDO3: Add new SDO Abort Code (0x06090033)
+V5.10 SDO4: Block SDO Info services for indices less 0x1000
+V5.10 SDO7: Correct mailbox length calculation on segmented or normal SDO upload response
+V5.10 SDO8: Fix invalid fragment calculation on SdoInfo list response
+V5.10 TEST5: test 0x2020.1 change limit from 10 to 16 Byte
+ Add test object 0x3009/0x300A (huge array and record objects)
+ Changes to version V5.0:
+V5.01 MBX1: Allocate always complete 16Bit memory areas
+V5.01 SDO2: Prevent invalid memory access in case of 8Bit mailbox memory handling
+V5.01 SDO3: Update mailbox data length calculation
+V5.01 SDO4: Update length calculation in case of an segmented SDO list response
+V5.01 SDO6: Update SDO response interface handling. (used if the object access function returns "ABORTIDX_WORKING" and SDO_RES_INTERFACE is active)
+V5.01 TEST2: Change Test 0x2020.1 (force Segmented transfer) to 16Byte
+ Changes to version V4.40:
+V5.0 TEST1: Add test application. see Application Note ET9300 for more details.
+V5.0 MBX3: Calculate MBX datagram length independent of SM size.
+V5.0 SDO2: SDO toggle bit don not do be cleared for segmented communication.
+V5.0 SDO3: Set SDO OpCode in list response.
+V5.0 SDO4: Update abort code for "BIG_ENDIAN_16BIT" configuration.
+V5.0 SDO5: Object code was calculated wrong for SDO Info service.
+V5.0 SDO6: Handle SDO segmented transfer if only 16Bit MBX memory access is allowed.
+ Changes to version V4.20:
+V4.40 SDO1: change size calculation for SDO services
+V4.40 MBX1: Prevent accessing odd address
+V4.40 COE1: Abort code is set in OBJ_GetObjectList()
+ Changes to version V4.11:
+V4.20 PIC24: Add EL9800_4 (PIC24) required source code
+V4.20 SDO 2: SDO mask value bug
+V4.20 SDO 1: check zero size object length
+ Changes to version V4.10:
+V4.11 SDO 1: fixed calculation of frame fragments during a object dictionary array list request
+V4.11 SDO 2-3: fixed size of entry description
+V4.11 SDO 4-7: add STRUCT_PACKED defines
+ Changes to version V4.08:\a
+V4.10 SDO 1: fixed zero size SDO comparison
+V4.10 SDO 2: set SdoService_CommandOffset to 0
+V4.10 SDO 3: fixed zero size SDO comparison
+V4.10 SDO 4: fixed struct_packed definition
+ Changes to version V4.07:
+V4.08 SDO 1: For an upload segment response the toggle bit was overwritten
+V4.08 SDO 2: For a segmented response the command was wrong in the response
+ Changes to version V4.06:
+V4.07 SDO 1: In SdoRes the command specifier was not set correctly in case of an abort
+V4.07 ECAT 1: The sources for SPI and MCI were merged (in ecat_def.h
+ set the switch MCI_HW to 1 when using the MCI,
+ set the switch SPI_HW to 1 when using the SPI
+ Changes to version V4.05:
+V4.06 SDO 1: The variable dataSize was used wrong in function SdoRes
+ Changes to version V4.03:
+V4.04 SDO 1: The SDO interface was changed in that way that a SDO response
+ could be sent by the application to a later time. In that case
+ the functions OBJ_Read and OBJ_Write shall return the value
+ ABORTIDX_WORKING. To send the SDO response the new function SDOS_SdoRes
+ has to be called by the application. While waiting for the call
+ of SDOS_SdoRes the SDO interface will answer to another SDO request
+ with the error MBXERR_SERVICEINWORK in the mailbox protocol
+ Changes to version V3.20:
+V4.00 SDO 1: The size of the written data in case of a SDO Download will be
+ in the function OBJ_Write to be more flexible
+V4.00 SDO 2: The object lists will be generated in the functions OBJ_GetNoOfObjects
+ and OBJ_GetObjectList in objdef.c to decouple the SDO services from
+ the implementation of the object dictionary
+V4.00 SDO 3: The name of an object or entry description will only be transmitted
+ if it fits in the mailbox because the fragmentation is not supported in the sample code.
+V4.00 SDO 4: SDOs with size greater than 65535 were not handled correctly, that is fixed now
+*/
+
+/*---------------------------------------------------------------------------------------
+------
+------ Includes
+------
+---------------------------------------------------------------------------------------*/
+
+#include "ecat_def.h"
+
+#include "ecatslv.h"
+
+
+#define _SDOSERV_ 1
+#include "objdef.h"
+#undef _SDOSERV_
+/*remove definition of _SDOSERV_ (#ifdef is used in objdef.h)*/
+
+
+/*ET9300 Project Handler :(#if TEST_APPLICATION) lines 122 to 124 deleted*/
+
+/*ET9300 Project Handler :(#if TEST_APPLICATION && EOE_SUPPORTED) lines 126 to 128 deleted*/
+
+
+extern OBJCONST TOBJECT OBJMEM asObjDef[];
+extern UINT16 OBJ_GetDesc(UINT16 index, UINT8 subindex, OBJCONST TOBJECT OBJMEM * pObjEntry, UINT16 MBXMEM * pData);
+extern OBJCONST TSDOINFOENTRYDESC OBJMEM * OBJ_GetEntryDesc(OBJCONST TOBJECT OBJMEM * pObjEntry, UINT8 Subindex);
+extern OBJCONST TSDOINFOOBJDESC OBJMEM * OBJ_GetObjDesc(OBJCONST TOBJECT OBJMEM * pObjEntry);
+
+/*---------------------------------------------------------------------------------------
+------
+------ Modulintern variable definitions
+------
+---------------------------------------------------------------------------------------*/
+
+const UINT32 MBXMEM cAbortCode[] =
+{
+ ABORT_NOERROR,
+ ABORT_TOGGLE_BIT_NOT_CHANGED,
+ ABORT_SDO_PROTOCOL_TIMEOUT,
+ ABORT_COMMAND_SPECIFIER_UNKNOWN,
+ ABORT_OUT_OF_MEMORY,
+ ABORT_UNSUPPORTED_ACCESS,
+ ABORT_WRITE_ONLY_ENTRY,
+ ABORT_READ_ONLY_ENTRY,
+ ABORT_OBJECT_NOT_EXISTING,
+ ABORT_OBJECT_CANT_BE_PDOMAPPED,
+ ABORT_MAPPED_OBJECTS_EXCEED_PDO,
+ ABORT_PARAM_IS_INCOMPATIBLE,
+ ABORT_INTERNAL_DEVICE_INCOMPATIBILITY,
+ ABORT_HARDWARE_ERROR,
+ ABORT_PARAM_LENGTH_ERROR,
+ ABORT_PARAM_LENGTH_TOO_LONG,
+ ABORT_PARAM_LENGTH_TOO_SHORT,
+ ABORT_SUBINDEX_NOT_EXISTING,
+ ABORT_VALUE_EXCEEDED,
+ ABORT_VALUE_TOO_GREAT,
+ ABORT_VALUE_TOO_SMALL,
+ ABORT_MODULE_ID_LIST_NOT_MATCH,
+ ABORT_MAX_VALUE_IS_LESS_THAN_MIN_VALUE,
+ ABORT_GENERAL_ERROR,
+ ABORT_DATA_CANNOT_BE_READ_OR_STORED,
+ ABORT_DATA_CANNOT_BE_READ_OR_STORED_BECAUSE_OF_LOCAL_CONTROL,
+ ABORT_DATA_CANNOT_BE_READ_OR_STORED_IN_THIS_STATE,
+ ABORT_NO_OBJECT_DICTIONARY_IS_PRESENT,
+ ABORT_ENTRY_CANT_BE_WRITTEN_SI0_NOT_0,
+ ABORT_COMPLETE_ACCESS_NOT_SUPPORTED
+};
+
+UINT16 VARMEM nSdoInfoIndex;
+OBJCONST TOBJECT OBJMEM * VARMEM pSdoInfoObjEntry;
+
+TINITSDOMBX MBXMEM * VARMEM pSdoResStored;
+BOOL VARMEM bSdoInWork = FALSE;
+
+UINT8 VARMEM nSdoSegService;
+UINT8 VARMEM bSdoSegFollows;
+UINT8 VARMEM bSdoSegAccess;
+UINT16 VARMEM nSdoSegIndex;
+UINT8 VARMEM nSdoSegSubindex;
+UINT32 VARMEM nSdoSegBytesToHandle;
+UINT8 VARMEM bSdoSegLastToggle;
+UINT32 VARMEM nSdoSegCompleteSize;
+OBJCONST TOBJECT OBJMEM * VARMEM pSdoSegObjEntry;
+
+/*ET9300 Project Handler :(#if _PIC18) lines 195 to 202 deleted*/
+/*---------------------------------------------------------------------------------------
+------
+------ module internal function declarations
+------
+---------------------------------------------------------------------------------------*/
+static UINT8 SdoDownloadSegmentInd(TDOWNLOADSDOSEGREQMBX MBXMEM * pSdoInd);
+static UINT8 SdoUploadSegmentInd(TUPLOADSDOSEGREQMBX MBXMEM * pSdoInd);
+/*---------------------------------------------------------------------------------------
+------
+------ Functions
+------
+---------------------------------------------------------------------------------------*/
+
+/////////////////////////////////////////////////////////////////////////////////////////
+/**
+ \param pSdoInd Pointer to the received mailbox data from the master.
+
+ \return Indicates if an error occurred while the operation ( good = 0 ).
+
+ \brief This function is called when a Download SDO Segment request
+ service is received from the master. If its the last segment
+ the data will be written to the object dictionary. The
+ function sends a response by itself.
+*////////////////////////////////////////////////////////////////////////////////////////
+
+static UINT8 SdoDownloadSegmentInd(TDOWNLOADSDOSEGREQMBX MBXMEM * pSdoInd)
+{
+ UINT8 abort = 0;
+ UINT32 bytesToSave = 0;
+
+ if (SWAPWORD(pSdoInd->SdoHeader.SegHeader & SEGHEADER_TOGGLE) == bSdoSegLastToggle)
+ {
+ /* toggle bit has not toggled... */
+ abort = ABORTIDX_TOGGLE_BIT_NOT_CHANGED;
+ }
+ else
+ {
+ /* maxData contains the maximum data to be received with a SDO-DownloadSegment */
+ UINT16 maxData = u16ReceiveMbxSize - MBX_HEADER_SIZE - SEGMENT_NORM_HEADER_SIZE;
+ /* the new toggle bit is stored in bSdoSegLastToggle */
+ bSdoSegLastToggle = SWAPWORD(pSdoInd->SdoHeader.SegHeader & SEGHEADER_TOGGLE);
+
+ /* a SDO-Download Segment is only allowed if a SDO-Download Request was received before,
+ in that case a buffer for the received data was allocated in SDOS_SdoInd before */
+ if (pSdoSegData)
+ {
+ /* bytesToSave contains the remaining data with this and maybe the following
+ SDO-Download Segment services */
+ bytesToSave = nSdoSegCompleteSize - nSdoSegBytesToHandle;
+
+ if (pSdoInd->SdoHeader.SegHeader & SEGHEADER_NOMOREFOLLOWS)
+ {
+ /* the last segment is received, check if the length of the remaining data is the
+ same as the length of the received data */
+ if (bytesToSave <= maxData)
+ {
+ UINT16 mbxSize = SWAPWORD(pSdoInd->MbxHeader.Length);
+
+ /* for the check it is distinguished if the remaining bytes are less than 8 (in that
+ case 7 data bytes were sent and the SDO-Download Segment header contains the information
+ how much bytes are valid (CAN-compatibility)), otherwise the length has to match exactly
+ and the SDO-Download Segment-Headerbyte is ignored */
+ if (((bytesToSave <= (UINT32)(mbxSize - SEGMENT_NORM_HEADER_SIZE))
+ && (bytesToSave == ((UINT16)(MIN_SEGMENTED_DATA - ((pSdoInd->SdoHeader.SegHeader & SEGHEADER_SEGDATASIZE) >> SEGHEADERSHIFT_SEGDATASIZE))))
+ )
+ || ((bytesToSave > MIN_SEGMENTED_DATA)
+ && (bytesToSave == (UINT32)(mbxSize - SEGMENT_NORM_HEADER_SIZE))
+ ))
+ {
+ /* length is correct */
+ bSdoSegFollows = FALSE;
+ }
+ else
+ {
+ abort = ABORTIDX_PARAM_LENGTH_ERROR;
+ }
+ }
+ else
+ {
+ abort = ABORTIDX_PARAM_LENGTH_ERROR;
+ }
+ }
+ else
+ {
+ /* its not the last segment */
+ bSdoSegFollows = TRUE;
+ /* we have to check if we expect less bytes than the maximum size which can be send with a single
+ SDO Download Segment */
+ if (bytesToSave <= maxData)
+ {
+ abort = ABORTIDX_PARAM_LENGTH_ERROR;
+ }
+ else
+ {
+ /* length is okay, bytesToSave contains the data size to be copied */
+ bytesToSave = maxData;
+ }
+ }
+
+ if (abort == 0)
+ {
+ /* the received data is copied in the buffer */
+/*ET9300 Project Handler :(#if MBX_16BIT_ACCESS) lines 309 to 334 deleted*/
+ MBXMEMCPY(((UINT8*)pSdoSegData) + (nSdoSegBytesToHandle), pSdoInd->SdoHeader.Data, bytesToSave);
+
+ if (bSdoSegFollows == FALSE)
+ {
+ /* it was the last segment, OBJ_Write will called to make the Write-operation */
+ abort = OBJ_Write(nSdoSegIndex, nSdoSegSubindex, nSdoSegCompleteSize, pSdoSegObjEntry, (UINT16 MBXMEM *) pSdoSegData, bSdoSegAccess);
+ if (abort == ABORTIDX_WORKING)
+ {
+ /* the application generates the SDO-Response later on by calling SDOS_SdoRes (only possible if object access function pointer is defined) */
+ u8PendingSdo = SDO_PENDING_SEG_WRITE;
+ bStoreCompleteAccess = bSdoSegAccess;
+ u8StoreSubindex = nSdoSegSubindex;
+ u16StoreIndex = nSdoSegIndex;
+ u32StoreDataSize = nSdoSegCompleteSize;
+ pStoreData = pSdoSegData;
+
+ pSdoPendFunc = pSdoSegObjEntry->Write;
+
+ bSdoInWork = TRUE;
+ pSdoResStored = (TINITSDOMBX MBXMEM *) pSdoInd;
+
+ bSdoSegFollows = FALSE;
+ nSdoSegService = 0;
+ nSdoSegBytesToHandle = 0;
+
+ return ABORTIDX_WORKING;
+ }
+ else
+ {
+ /* the allocated buffer can be released */
+ FREEMEM((UINT16 VARMEM *) pSdoSegData);
+ pSdoSegData = NULL;
+ }
+ }
+ }
+ }
+ else
+ {
+ abort = ABORTIDX_COMMAND_SPECIFIER_UNKNOWN;
+ }
+ }
+
+ if (abort == 0)
+ {
+ /* send the SDO Download Segment response */
+ pSdoInd->MbxHeader.Length = SEGMENT_NORM_RES_SIZE;
+ pSdoInd->CoeHeader &= ~COEHEADER_COESERVICEMASK;
+ pSdoInd->CoeHeader |= ((UINT16)COESERVICE_SDORESPONSE) << COEHEADER_COESERVICESHIFT;
+ /* the SDO Download Segment header depends if it was the last segment or not */
+ if (bSdoSegLastToggle)
+ {
+ pSdoInd->SdoHeader.SegHeader = SWAPWORD(SDOSERVICE_DOWNLOADSEGMENTRES | SEGHEADER_TOGGLE);
+ }
+ else
+ {
+ pSdoInd->SdoHeader.SegHeader = SWAPWORD(SDOSERVICE_DOWNLOADSEGMENTRES);
+ }
+
+ if (bSdoSegFollows == TRUE)
+ {
+ /* segments are still expected, nSdoSegBytesToHandle contains the number of received data bytes */
+ nSdoSegBytesToHandle += bytesToSave;
+ }
+ else
+ {
+ /* the last segment was received, the variables are reset */
+ nSdoSegBytesToHandle = 0;
+ nSdoSegService = 0;
+ }
+ }
+ else
+ {
+ /* the Abort-Response will be sent in SDOS_SdoInd*/
+ bSdoSegFollows = FALSE;
+ nSdoSegService = 0;
+ if (pSdoSegData)
+ {
+ /* the memory has to be released if it is not released before.
+ In case of AbortIdx_Working the buffer will be freed in SDOS_SdoRes*/
+ FREEMEM((UINT16 VARMEM *) pSdoSegData);
+ pSdoSegData = NULL;
+ }
+
+ nSdoSegBytesToHandle = 0;
+ }
+
+ return abort;
+}
+
+/////////////////////////////////////////////////////////////////////////////////////////
+/**
+ \param pSdoInd Pointer to the received mailbox data from the master.
+
+ \return Indicates if an error occurred while the operation ( good = 0 ).
+
+ \brief This function is called when a Upload SDO Segment request service
+ is received from the master. It prepares and operates the
+ response and sends it by itself.
+*////////////////////////////////////////////////////////////////////////////////////////
+
+static UINT8 SdoUploadSegmentInd(TUPLOADSDOSEGREQMBX MBXMEM * pSdoInd)
+{
+ UINT8 abort = 0;
+ TUPLOADSDOSEGRESMBX MBXMEM * pSdoSegRes = (TUPLOADSDOSEGRESMBX MBXMEM *)pSdoInd;
+
+ if (SWAPWORD(pSdoInd->SegHeader & SEGHEADER_TOGGLE) == bSdoSegLastToggle)
+ {
+ /* toggle bit has not toggled... */
+ abort = ABORTIDX_TOGGLE_BIT_NOT_CHANGED;
+ }
+ else
+ {
+ /* maxData contains the maximum data to be sent with a SDO-Upload Segment response */
+
+ UINT32 size = 0;
+ UINT16 maxData;
+
+/*ET9300 Project Handler :(#if TEST_APPLICATION) lines 455 to 462 deleted*/
+ {
+ maxData = u16SendMbxSize - MBX_HEADER_SIZE - SEGMENT_NORM_HEADER_SIZE;
+ }
+
+ /* the new toggle bit is stored in bSdoSegLastToggle */
+ bSdoSegLastToggle = pSdoInd->SegHeader & SEGHEADER_TOGGLE;
+
+ if (nSdoSegCompleteSize < (nSdoSegBytesToHandle + maxData))
+ {
+ /* the remaining data can be send with one SDO Upload Segment response,
+ size contains the data to be copied */
+ size = nSdoSegCompleteSize - nSdoSegBytesToHandle;
+ bSdoSegFollows = FALSE;
+ }
+ else
+ {
+ /* more data will follow, size contains the data to be copied */
+ size = maxData;
+ bSdoSegFollows = TRUE;
+ }
+
+ /* copy the object data in the SDO Upload segment response */
+/*ET9300 Project Handler :(#if MBX_16BIT_ACCESS) lines 485 to 512 deleted*/
+ MBXMEMCPY(pSdoSegRes->SdoHeader.Data, &(((UINT8*)pSdoSegData)[nSdoSegBytesToHandle]), size);
+
+ /* the SDO Upload Segment header depends if there is still data to be sent */
+ pSdoSegRes->CoeHeader &= ~COEHEADER_COESERVICEMASK;
+ pSdoSegRes->CoeHeader |= ((UINT16)COESERVICE_SDORESPONSE) << COEHEADER_COESERVICESHIFT;
+
+ /*Clear SDO header*/
+ pSdoSegRes->SdoHeader.SegHeader &= ~SEGHEADER_MASK;
+ if (bSdoSegFollows)
+ {
+ pSdoSegRes->SdoHeader.SegHeader |= SWAPWORD(SDOSERVICE_UPLOADSEGMENTRES | bSdoSegLastToggle);
+ }
+ else
+ {
+ pSdoSegRes->SdoHeader.SegHeader |= SWAPWORD(SDOSERVICE_UPLOADSEGMENTRES | bSdoSegLastToggle | SEGHEADER_NOMOREFOLLOWS);
+ }
+
+ // operate CAN specific flag segDataSize:
+ /* HBu 06.02.06: the sizes were wrong */
+ if (size < MIN_SEGMENTED_DATA)
+ {
+ // at least MIN_SEGMENTED_DATA bytes have to be send:
+ pSdoSegRes->MbxHeader.Length = SEGMENT_NORM_RES_SIZE;
+ pSdoSegRes->SdoHeader.SegHeader |= (MIN_SEGMENTED_DATA - size) << SEGHEADERSHIFT_SEGDATASIZE;
+ }
+ else
+ {
+ pSdoSegRes->MbxHeader.Length = ((UINT16)size) + SEGMENT_NORM_HEADER_SIZE;
+ }
+
+ if (bSdoSegFollows == TRUE)
+ {
+ // updating the value of send bytes:
+ nSdoSegBytesToHandle += size;
+ }
+ else
+ {
+ FREEMEM((UINT16 VARMEM *) pSdoSegData);
+ pSdoSegData = NULL;
+ nSdoSegBytesToHandle = 0;
+ nSdoSegService = 0;
+ }
+ }
+
+ return abort;
+}
+
+
+/////////////////////////////////////////////////////////////////////////////////////////
+/**
+ \param abort Result of the SDO access
+ \param command SDO command index
+ \param completeAccess Indicates if complete access was requested
+ \param dataSize Available data buffer in the response
+ \param objLength Complete size of the object
+ \param pSdoRes Pointer to the mailbox buffer
+
+ \brief This function is called when a SDO response shall be sent
+*////////////////////////////////////////////////////////////////////////////////////////
+
+void SdoRes(UINT8 abort, UINT8 command, UINT8 completeAccess, UINT16 dataSize, UINT32 objLength, TINITSDOMBX MBXMEM *pSdoRes)
+{
+ /* for an upload segment response the toggle bit was overwritten */
+ if ((command != SDOSERVICE_UPLOADSEGMENTREQ) && (command != SDOSERVICE_DOWNLOADSEGMENTREQ))
+ {
+/*ET9300 Project Handler :(#if MBX_16BIT_ACCESS) lines 580 to 586 deleted*/
+ pSdoRes->SdoHeader.Sdo[SDOHEADER_COMMANDOFFSET] = 0;
+ }
+ if (abort == 0)
+ {
+ /* SDO-Download or SDO-Upload was successful, generate the SDO- and CoE-Header */
+ pSdoRes->CoeHeader &= ~COEHEADER_COESERVICEMASK;
+ pSdoRes->CoeHeader |= ((UINT16)COESERVICE_SDORESPONSE) << COEHEADER_COESERVICESHIFT;
+ if (command == SDOSERVICE_INITIATEUPLOADREQ)
+ {
+ // HBu 06.02.06: Complete Access Bit in the SDO-Upload-Response too */
+ if ((objLength <= 4) && (objLength > 0))
+ {
+ /* Expedited Upload Response */
+ pSdoRes->MbxHeader.Length = EXPEDITED_FRAME_SIZE;
+/*ET9300 Project Handler :(#if MBX_16BIT_ACCESS) lines 602 to 608 deleted*/
+ pSdoRes->SdoHeader.Sdo[SDOHEADER_COMMANDOFFSET] |= SDOHEADER_SIZEINDICATOR |
+ SDOHEADER_TRANSFERTYPE |
+ completeAccess |
+ ((MAX_EXPEDITED_DATA - ((UINT8)objLength)) << SDOHEADERSHIFT_DATASETSIZE) |
+ SDOSERVICE_INITIATEUPLOADRES;
+ }
+ else
+ {
+ /* Normal or Segmented Upload Response */
+ if (dataSize < objLength)
+ {
+ pSdoRes->MbxHeader.Length = UPLOAD_NORM_RES_SIZE + dataSize;
+ }
+ else
+ {
+ pSdoRes->MbxHeader.Length = UPLOAD_NORM_RES_SIZE + ((UINT16)objLength);
+ }
+ ((TINITSDOUPLOADNORMRESMBX MBXMEM *) pSdoRes)->CompleteSize[0] = SWAPWORD((UINT16)objLength);
+ ((TINITSDOUPLOADNORMRESMBX MBXMEM *) pSdoRes)->CompleteSize[1] = SWAPWORD((UINT16)(objLength >> 16));
+/*ET9300 Project Handler :(#if MBX_16BIT_ACCESS) lines 631 to 635 deleted*/
+ pSdoRes->SdoHeader.Sdo[SDOHEADER_COMMANDOFFSET] |= SDOHEADER_SIZEINDICATOR |
+ completeAccess |
+ SDOSERVICE_INITIATEUPLOADRES;
+
+ }
+ }
+ /* for a segmented response the command was wrong in the response */
+ else if (command == SDOSERVICE_DOWNLOADSEGMENTREQ)
+ {
+ /* Download segmented response */
+ pSdoRes->MbxHeader.Length = DOWNLOAD_NORM_RES_SIZE;
+/*ET9300 Project Handler :(#if MBX_16BIT_ACCESS) lines 648 to 650 deleted*/
+ pSdoRes->SdoHeader.Sdo[SDOHEADER_COMMANDOFFSET] |= SDOSERVICE_DOWNLOADSEGMENTRES;
+ }
+ else if (command != SDOSERVICE_UPLOADSEGMENTREQ)
+ {
+ /* Download response */
+ pSdoRes->MbxHeader.Length = DOWNLOAD_NORM_RES_SIZE;
+/*ET9300 Project Handler :(#if MBX_16BIT_ACCESS) lines 658 to 660 deleted*/
+ pSdoRes->SdoHeader.Sdo[SDOHEADER_COMMANDOFFSET] |= SDOSERVICE_INITIATEDOWNLOADRES;
+ }
+ }
+ else
+ {
+ /* generate a SDO-Abort-Request */
+ pSdoRes->MbxHeader.Length = ABORT_NORM_RES_SIZE;
+ pSdoRes->CoeHeader &= ~COEHEADER_COESERVICEMASK;
+ pSdoRes->CoeHeader |= ((UINT16)COESERVICE_SDOREQUEST) << COEHEADER_COESERVICESHIFT;
+/*ET9300 Project Handler :(#if MBX_16BIT_ACCESS) lines 671 to 673 deleted*/
+ pSdoRes->SdoHeader.Sdo[SDOHEADER_COMMANDOFFSET] |= SDOSERVICE_ABORTTRANSFER;
+
+/*ET9300 Project Handler :(#if BIG_ENDIAN_16BIT) lines 677 to 680 deleted*/
+ ((TABORTSDOTRANSFERREQMBX MBXMEM *) pSdoRes)->AbortCode = SWAPDWORD(cAbortCode[abort]);
+ }
+
+ // HBu 02.05.06: if the CoE-response could not be sent because the
+ // send mailbox is full it should be stored
+ if (MBX_MailboxSendReq((TMBX MBXMEM *) pSdoRes, COE_SERVICE) != 0)
+ {
+ /* we store the CoE mailbox service to send it later (in COE_ContinueInd) when the mailbox is read */
+ pCoeSendStored = (TMBX MBXMEM *) pSdoRes;
+ }
+}
+
+/////////////////////////////////////////////////////////////////////////////////////////
+/**
+ \param pSdoInd Pointer to the received mailbox data from the master.
+
+ \return Indicates if an error occurred while the operation ( good = 0 ).
+
+ \brief This function is called when a SDO request service
+ is received from the master and calls depending from
+ the command the concerning function.
+*////////////////////////////////////////////////////////////////////////////////////////
+
+UINT8 SDOS_SdoInd(TINITSDOMBX MBXMEM *pSdoInd)
+{
+ UINT8 abort = 0;
+/*ET9300 Project Handler :(#if MBX_16BIT_ACCESS) lines 708 to 710 deleted*/
+ UINT8 sdoHeader = (pSdoInd->SdoHeader.Sdo[SDOHEADER_COMMANDOFFSET] & SDOHEADER_COMMANDMASK);
+ /* the SDO-command is in bit 5-7 of the first SDO-Byte */
+ UINT8 command = (sdoHeader & SDOHEADER_COMMAND);
+ /* mbxSize contains the size of the mailbox (CoE-Header (2 Bytes) + SDO-Header (8 Bytes) + SDO-Data (if the data length is greater than 4)) */
+ UINT16 mbxSize = SWAPWORD(pSdoInd->MbxHeader.Length);
+ UINT16 index;
+ UINT8 subindex;
+ OBJCONST TOBJECT OBJMEM * pObjEntry;
+ /* this variable contains the information, if all entries of an object will be read (bCompleteAccess > 0) or a single entry */
+ UINT8 bCompleteAccess = 0;
+ UINT32 objLength = 0;
+ UINT32 dataSize = 0;
+
+ if (bSdoInWork)
+ {
+ /* the last SDO is still in work */
+ return MBXERR_SERVICEINWORK;
+ }
+
+/* ECATCHANGE_START(V5.13) COE5*/
+ if (sdoHeader & SDOHEADER_COMPLETEACCESS)
+ {
+ bCompleteAccess = 1;
+ }
+/* ECATCHANGE_END(V5.13) COE5*/
+
+ switch (command)
+ {
+ case SDOSERVICE_INITIATEDOWNLOADREQ:
+ case SDOSERVICE_INITIATEUPLOADREQ:
+ /* the variable index contains the requested index of the SDO service */
+/*ET9300 Project Handler :(#if MBX_16BIT_ACCESS) lines 745 to 747 deleted*/
+ index = ((UINT16)(pSdoInd->SdoHeader.Sdo[SDOHEADER_INDEXHIOFFSET] & SDOHEADER_INDEXHIMASK));
+ index <<= 8;
+/*ET9300 Project Handler :(#if MBX_16BIT_ACCESS) lines 753 to 757 deleted*/
+ index += (pSdoInd->SdoHeader.Sdo[SDOHEADER_INDEXLOOFFSET]);
+ /* the variable subindex contains the requested subindex of the SDO service */
+ subindex = pSdoInd->SdoHeader.Sdo[SDOHEADER_SUBINDEXOFFSET];
+
+
+/*ET9300 Project Handler :(#if TEST_APPLICATION && EOE_SUPPORTED) lines 764 to 834 deleted*/
+
+
+/*ET9300 Project Handler :(#if TEST_APPLICATION) lines 837 to 855 deleted*/
+
+ /* OBJ_GetObjectHandle checks if the requested index is defined in the object dictionary */
+ pObjEntry = OBJ_GetObjectHandle(index);
+
+ if (pObjEntry)
+ {
+ /* transferType contains the information if the SDO Download Request or the SDO Upload Response
+ can be an expedited service (SDO data length <= 4, that means the data is stored in the
+ SDO-Header completely */
+ UINT8 bTransferType = 0;
+ /* pData is the pointer to the received (SDO-Download) or sent (SDO-Upload) SDO data in the mailbox */
+ UINT16 MBXMEM * pData = NULL;
+ UINT8 segTransfer = 0;
+
+ {
+ UINT8 maxSubindex = (pObjEntry->ObjDesc.ObjFlags & OBJFLAGS_MAXSUBINDEXMASK) >> OBJFLAGS_MAXSUBINDEXSHIFT;
+
+ if (subindex > maxSubindex)
+ {
+ abort = ABORTIDX_SUBINDEX_NOT_EXISTING;
+ }
+ else
+ {
+ dataSize = objLength = OBJ_GetObjectLength(index, subindex, pObjEntry, (UINT8)(sdoHeader & SDOHEADER_COMPLETEACCESS));
+ }
+
+ if (abort == 0)
+ {
+ if (command == SDOSERVICE_INITIATEUPLOADREQ)
+ {
+ /* SDO Upload */
+ if (mbxSize != EXPEDITED_FRAME_SIZE)
+ {
+ /* a SDO Upload request has always a fixed size (2 Byte CoE-Header plus 8 Byte SDO-Header) */
+ return MBXERR_INVALIDSIZE;
+ }
+ /* distinguish between expedited and normal upload response within the length of the response data */
+ if ((objLength <= MAX_EXPEDITED_DATA) && objLength != 0)
+ {
+ /* Expedited Upload */
+ bTransferType = 1;
+ /* pData is the pointer where the object data has to be copied for the response */
+ pData = (UINT16 MBXMEM *) ((TINITSDOUPLOADEXPRESMBX MBXMEM *) pSdoInd)->Data;
+ /* initialize the 4 data bytes of the SDO upload response because the requested object data
+ could be less than 4 */
+ pData[0] = 0;
+ pData[1] = 0;
+ }
+ else
+ {
+ /* HBu 06.02.06: the variable dataSize has to be set to the available size in one mailbox */
+/*ET9300 Project Handler :(#if TEST_APPLICATION) lines 910 to 920 deleted*/
+ dataSize = u16SendMbxSize - MBX_HEADER_SIZE - UPLOAD_NORM_RES_SIZE;
+ if (dataSize < objLength)
+ {
+ /* Segmented Upload */
+ segTransfer = 1;
+ }
+
+
+/*ET9300 Project Handler :(#if SEGMENTED_SDO_SUPPORTED #else) lines 930 to 946 deleted*/
+ else
+ {
+ /* Normal Upload */
+
+ /* pData is the pointer where the object data has to be copied for the response */
+ pData = (UINT16 MBXMEM *) ((TINITSDOUPLOADNORMRESMBX MBXMEM *) pSdoInd)->Data;
+ }
+ }
+ }
+ else
+ {
+ /* SDO-Download: store if the request is a expedited or normal request */
+ bTransferType = sdoHeader & SDOHEADER_TRANSFERTYPE;
+ }
+ }
+ }
+
+ if ((abort == 0) && (command == SDOSERVICE_INITIATEDOWNLOADREQ))
+ {
+ /* SDO Download */
+ if (bTransferType)
+ {
+ /* Expedited Download */
+ if (mbxSize != EXPEDITED_FRAME_SIZE)
+ {
+ /* an Expedited SDO Download request has always a fixed size (2 Byte CoE-Header plus 8 Byte SDO-Header) */
+ return MBXERR_INVALIDSIZE;
+ }
+ /* dataSize gets the real size of the downloaded object data (1,2,3 or 4) */
+ dataSize = MAX_EXPEDITED_DATA - ((sdoHeader & SDOHEADER_DATASETSIZE) >> SDOHEADERSHIFT_DATASETSIZE);
+ /* pData is the pointer to the downloaded object data */
+ pData = (UINT16 MBXMEM *) &pSdoInd[1];
+ }
+ else
+ {
+ /* Normal Download */
+ /* downloadSize gets the real size of the downloaded data */
+ /* '&' operator was too much */
+
+ UINT32 downloadSize = ((UINT32)(SWAPWORD(((TINITSDODOWNLOADNORMREQMBX MBXMEM *) pSdoInd)->CompleteSize[1])) << 16) + (SWAPWORD(((TINITSDODOWNLOADNORMREQMBX MBXMEM *) pSdoInd)->CompleteSize[0]));
+
+ /* HBu 29.03.06: if it is a segmented download the mbxSize has to be the complete mailbox size */
+ if ((MBX_HEADER_SIZE + EXPEDITED_FRAME_SIZE + downloadSize) > u16ReceiveMbxSize)
+ {
+ if (mbxSize != (u16ReceiveMbxSize - MBX_HEADER_SIZE))
+ {
+ return MBXERR_INVALIDSIZE;
+ }
+ }
+ else
+ {
+ if (mbxSize != (EXPEDITED_FRAME_SIZE + downloadSize))
+ {
+ /* the mbxSize and the downloadSize are not consistent (mbxSize = downloadSize + 2 byte CoE-Header + 8 byte SDO Header */
+ return MBXERR_INVALIDSIZE;
+ }
+ }
+
+ /* pData is the pointer to the downloaded object data */
+ pData = (UINT16 MBXMEM *) ((TINITSDODOWNLOADNORMREQMBX MBXMEM *) pSdoInd)->Data;
+ /* the received dataSize will be checked in the object specific functions called from
+ OBJ_Write (in objdef.c) */
+ dataSize = downloadSize;
+ if (dataSize > (UINT32)(mbxSize - DOWNLOAD_NORM_REQ_SIZE))
+ {
+ /* Segmented Download */
+ segTransfer = 1;
+/*ET9300 Project Handler :(#if SEGMENTED_SDO_SUPPORTED #else) lines 1015 to 1017 deleted*/
+ }
+ }
+ }
+
+/* ECATCHANGE_START(V5.13) COE5*/
+ if ((abort == 0) && (bCompleteAccess == 1))
+/* ECATCHANGE_END(V5.13) COE5*/
+ {
+ // HBu 02.05.06: Complete Access is only supported with subindex 0 and 1
+ if (subindex > 1)
+ {
+ abort = ABORTIDX_UNSUPPORTED_ACCESS;
+ }
+ }
+/*ET9300 Project Handler :(#if COMPLETE_ACCESS_SUPPORTED #else) lines 1033 to 1037 deleted*/
+
+ if (abort == 0)
+ {
+ if (segTransfer)
+ {
+ bSdoSegFollows = TRUE;
+ bSdoSegLastToggle = 1;
+ bSdoSegAccess = bCompleteAccess;
+ nSdoSegIndex = index;
+ nSdoSegSubindex = subindex;
+ pSdoSegObjEntry = pObjEntry;
+ if (command == SDOSERVICE_INITIATEUPLOADREQ)
+ {
+ nSdoSegCompleteSize = objLength;
+ }
+ else
+ {
+ nSdoSegCompleteSize = dataSize;
+ }
+
+ if (pSdoSegData != NULL)
+ {
+ FREEMEM((UINT16 VARMEM *) pSdoSegData);
+ pSdoSegData = NULL;
+ }
+ pSdoSegData = (UINT16 VARMEM *) ALLOCMEM(ROUNDUPBYTE2WORD(nSdoSegCompleteSize));
+
+ if (pSdoSegData == NULL)
+ {
+ if (bCompleteAccess)
+ {
+ abort = ABORTIDX_UNSUPPORTED_ACCESS;
+ }
+ else
+ {
+ abort = ABORTIDX_OUT_OF_MEMORY;
+ }
+ }
+ else
+ {
+ if (command == SDOSERVICE_INITIATEUPLOADREQ)
+ {
+ /* Segmented Upload */
+ abort = OBJ_Read(index, subindex, objLength, pObjEntry, (UINT16 MBXMEM *) pSdoSegData, bCompleteAccess);
+ if (abort == 0)
+ {
+ MBXMEMCPY((UINT16 *)((TINITSDOUPLOADNORMRESMBX MBXMEM *) pSdoInd)->Data, pSdoSegData, dataSize);
+ nSdoSegService = SDOSERVICE_UPLOADSEGMENTREQ;
+ }
+ else if (abort == ABORTIDX_WORKING)
+ {
+ /* the application generates the SDO-Response later on by calling SDOS_SdoRes (only possible if object access function pointer is defined) */
+ u8PendingSdo = SDO_PENDING_SEG_READ;
+ bStoreCompleteAccess = bCompleteAccess;
+ u8StoreSubindex = subindex;
+ u16StoreIndex = index;
+ u32StoreDataSize = objLength;
+ pStoreData = pSdoSegData;
+ pSdoPendFunc = pObjEntry->Read;
+
+ bSdoInWork = TRUE;
+ /* we have to store the buffer and the response header */
+ pSdoResStored = pSdoInd;
+
+ /*update command field*/
+ pSdoResStored->SdoHeader.Sdo[SDOHEADER_COMMANDOFFSET] &= ~SDOHEADER_COMMANDMASK;
+ pSdoResStored->SdoHeader.Sdo[SDOHEADER_COMMANDOFFSET] |= (sdoHeader & (SDOHEADER_COMPLETEACCESS | SDOHEADER_COMMAND));
+ nSdoSegService = SDOSERVICE_UPLOADSEGMENTREQ;
+ return 0;
+ }
+ }
+ else
+ {
+ /* Segmented Download */
+ MBXMEMCPY(pSdoSegData, (UINT16 *)((TINITSDODOWNLOADNORMREQMBX MBXMEM *) pSdoInd)->Data, mbxSize - DOWNLOAD_NORM_REQ_SIZE);
+ nSdoSegService = SDOSERVICE_DOWNLOADSEGMENTREQ;
+ dataSize = (mbxSize - DOWNLOAD_NORM_REQ_SIZE);
+ }
+
+ nSdoSegBytesToHandle = dataSize;
+ }
+ }
+ else
+ {
+ if (objLength == 0)
+ {
+ /* the objLength is not known, therefore the variables for a possible segmented transfer
+ should be initialized */
+ nSdoSegIndex = index;
+ nSdoSegSubindex = subindex;
+ pSdoSegObjEntry = pObjEntry;
+ }
+ if (command == SDOSERVICE_INITIATEUPLOADREQ)
+ {
+ /* Expedited or Normal Upload */
+ abort = OBJ_Read(index, subindex, objLength, pObjEntry, pData, bCompleteAccess);
+ if (abort == ABORTIDX_WORKING)
+ {
+ /* the application generates the SDO-Response later on by calling SDOS_SdoRes (only possible if object access function pointer is defined) */
+ u8PendingSdo = SDO_PENDING_READ;
+ bStoreCompleteAccess = bCompleteAccess;
+ u8StoreSubindex = subindex;
+ u16StoreIndex = index;
+ u32StoreDataSize = objLength;
+ pStoreData = pData;
+ pSdoPendFunc = pObjEntry->Read;
+
+ bSdoInWork = TRUE;
+ /* we have to store the buffer and the response header */
+ pSdoResStored = pSdoInd;
+
+ /*update command field*/
+ pSdoResStored->SdoHeader.Sdo[SDOHEADER_COMMANDOFFSET] &= ~SDOHEADER_COMMANDMASK;
+ pSdoResStored->SdoHeader.Sdo[SDOHEADER_COMMANDOFFSET] |= (sdoHeader & (SDOHEADER_COMPLETEACCESS | SDOHEADER_COMMAND));
+ return 0;
+ }
+ }
+ else
+ {
+ /* Expedited or Normal Download */
+ abort = OBJ_Write(index, subindex, dataSize, pObjEntry, pData, bCompleteAccess);
+ if (abort == ABORTIDX_WORKING)
+ {
+ /* the application generates the SDO-Response later on by calling SDOS_SdoRes (only possible if object access function pointer is defined) */
+ u8PendingSdo = SDO_PENDING_WRITE;
+ bStoreCompleteAccess = bCompleteAccess;
+ u8StoreSubindex = subindex;
+ u16StoreIndex = index;
+ u32StoreDataSize = dataSize;
+ pStoreData = pData;
+ pSdoPendFunc = pObjEntry->Write;
+
+ bSdoInWork = TRUE;
+ /* we have to store the buffer and the response header */
+ pSdoResStored = pSdoInd;
+
+ /*update command field*/
+ pSdoResStored->SdoHeader.Sdo[SDOHEADER_COMMANDOFFSET] &= ~SDOHEADER_COMMANDMASK;
+ pSdoResStored->SdoHeader.Sdo[SDOHEADER_COMMANDOFFSET] |= (sdoHeader & (SDOHEADER_COMPLETEACCESS | SDOHEADER_COMMAND));
+ return 0;
+ }
+ }
+ } /* else if ( objLength == 0 ) */
+ } /* if ( abort == 0 ) */
+
+ } //if(pObjEntry) (Object handle found)
+ else
+ {
+ abort = ABORTIDX_OBJECT_NOT_EXISTING;
+ }
+ break;
+
+ case SDOSERVICE_DOWNLOADSEGMENTREQ:
+ case SDOSERVICE_UPLOADSEGMENTREQ:
+ if (command == nSdoSegService)
+ {
+ if (command == SDOSERVICE_DOWNLOADSEGMENTREQ)
+ {
+ abort = SdoDownloadSegmentInd((TDOWNLOADSDOSEGREQMBX MBXMEM *) pSdoInd);
+ }
+ else
+ {
+ abort = SdoUploadSegmentInd((TUPLOADSDOSEGREQMBX MBXMEM *) pSdoInd);
+ }
+ }
+ else
+ {
+ abort = ABORTIDX_COMMAND_SPECIFIER_UNKNOWN;
+ }
+ break;
+
+ default:
+ abort = ABORTIDX_COMMAND_SPECIFIER_UNKNOWN;
+ break;
+ }
+
+ if (abort != ABORTIDX_WORKING)
+ {
+ /* type cast was added because of warning */
+ SdoRes(abort, command, (UINT8)(sdoHeader & SDOHEADER_COMPLETEACCESS), (UINT16)dataSize, objLength, pSdoInd);
+ }
+
+ return 0;
+}
+
+/////////////////////////////////////////////////////////////////////////////////////////
+/**
+ \param abort Result of the SDO access
+ \param objLength Complete size of the object
+ \param pData Pointer to the mailbox buffer
+
+ \brief This function is called when a SDO response shall be sent
+*////////////////////////////////////////////////////////////////////////////////////////
+
+void SDOS_SdoRes(UINT8 abort, UINT32 objLength, UINT16 MBXMEM *pData)
+{
+ UINT16 dataSize = 0;
+
+ if (bSdoInWork)
+ {
+ /* SDO-Response is expected */
+ UINT8 command = pSdoResStored->SdoHeader.Sdo[SDOHEADER_COMMANDOFFSET] & SDOHEADER_COMMAND;
+ UINT8 completeAccess = pSdoResStored->SdoHeader.Sdo[SDOHEADER_COMMANDOFFSET] & SDOHEADER_COMPLETEACCESS;
+
+ if (command == SDOSERVICE_INITIATEUPLOADREQ)
+ {
+ /* dataSize contains the available size in one mailbox */
+ dataSize = u16SendMbxSize - MBX_HEADER_SIZE - UPLOAD_NORM_RES_SIZE;
+ if (dataSize < objLength)
+ {
+ /* Segmented Upload, the variables for the segmented transfer should be initialized */
+ bSdoSegFollows = TRUE;
+ bSdoSegLastToggle = 1;
+ bSdoSegAccess = completeAccess;
+ nSdoSegCompleteSize = objLength;
+ nSdoSegService = SDOSERVICE_UPLOADSEGMENTREQ;
+ pSdoSegData = (UINT16 VARMEM *) pData;
+ /* the first segment shall be copied */
+ MBXMEMCPY((UINT16 *)((TINITSDOUPLOADNORMRESMBX MBXMEM *) pSdoResStored)->Data, pData, dataSize);
+ nSdoSegBytesToHandle = dataSize;
+ }
+ else
+ if ((objLength <= 4) && (objLength > 0))
+ {
+ /* Expedited response */
+ if (pData != ((TINITSDOUPLOADEXPRESMBX MBXMEM *) pSdoResStored)->Data)
+ {
+ /* the data is not in the response buffer yet, it shall be copied */
+ MBXMEMCPY((UINT16 *)((TINITSDOUPLOADEXPRESMBX MBXMEM *) pSdoResStored)->Data, pData, objLength);
+ }
+ }
+ else
+ {
+ /* Normal response */
+ if (pData != ((TINITSDOUPLOADNORMRESMBX MBXMEM *) pSdoResStored)->Data)
+ {
+ /* the data is not in the response buffer yet, it shall be copied */
+ MBXMEMCPY((UINT16 *)((TINITSDOUPLOADNORMRESMBX MBXMEM *) pSdoResStored)->Data, pData, objLength);
+ }
+ }
+ }
+
+ /* SDO access is finished, send the response */
+ bSdoInWork = FALSE;
+ SdoRes(abort, command, completeAccess, dataSize, objLength, pSdoResStored);
+ }
+}
+
+/////////////////////////////////////////////////////////////////////////////////////////
+/**
+\brief Clear the variables handling a pending SDO Response
+ This function shall be called before the other mailbox data pointer are set to NULL
+*////////////////////////////////////////////////////////////////////////////////////////
+
+void SDOS_ClearPendingResponse(void)
+{
+ if ((bSdoInWork == TRUE) && (pSdoResStored != NULL) && (((TMBX MBXMEM *)pSdoResStored) != psRepeatMbx) && (((TMBX MBXMEM *)pSdoResStored) != psStoreMbx))
+ {
+ APPL_FreeMailboxBuffer(pSdoResStored);
+ pSdoResStored = NULL;
+ }
+
+ u8PendingSdo = 0;
+ bStoreCompleteAccess = FALSE;
+ u16StoreIndex = 0;
+ u8StoreSubindex = 0;
+ u32StoreDataSize = 0;
+ pStoreData = NULL;
+ pSdoPendFunc = NULL;
+ bSdoInWork = FALSE;
+
+ if (pSdoSegData != NULL)
+ {
+ FREEMEM((UINT16 VARMEM *) pSdoSegData);
+ pSdoSegData = NULL;
+ }
+
+ nSdoSegBytesToHandle = 0;
+ nSdoSegService = 0;
+
+}
+
+/////////////////////////////////////////////////////////////////////////////////////////
+/**
+ \param pSdoInfoInd Pointer to the received mailbox data from the master.
+
+ \return Indicates if an error occurred while the operation ( good = 0 ).
+
+ \brief This function is called when a SDO-Info request service
+ is received from the master and calls depending from
+ the opcode the concerning function.
+*////////////////////////////////////////////////////////////////////////////////////////
+
+UINT8 SDOS_SdoInfoInd(TSDOINFORMATION MBXMEM *pSdoInfoInd)
+{
+ UINT8 abort = 0;
+ /* the variable opCode contains the requested SDO Information type */
+ UINT8 opCode = (UINT8)((pSdoInfoInd->SdoHeader.InfoHead & INFOHEAD_OPCODE_MASK) >> INFOHEAD_OPCODE_SHIFT);
+ OBJCONST TOBJECT OBJMEM * pObjEntry;
+ UINT16 index;
+ UINT8 flags = COE_SERVICE;
+
+ /* it has to be checked if the mailbox protocol is correct, the sent mailbox data length has to
+ great enough for the service header of the requested SDO Information type */
+ if (opCode == SDOINFOSERVICE_ENTRYDESCRIPTION_Q)
+ {
+ if (pSdoInfoInd->MbxHeader.Length < SIZEOF_SDOINFOENTRYREQSTRUCT)
+ {
+ return MBXERR_SIZETOOSHORT;
+ }
+ }
+ else
+ {
+ if (pSdoInfoInd->MbxHeader.Length < SIZEOF_SDOINFOLISTSTRUCT)
+ {
+ return MBXERR_SIZETOOSHORT;
+ }
+ }
+
+ switch (opCode)
+ {
+ case SDOINFOSERVICE_OBJDICTIONARYLIST_Q:
+ /* an object list is requested, check if the list type is supported */
+ if (SWAPWORD(pSdoInfoInd->SdoHeader.Data.List.ListType) <= INFO_LIST_TYPE_MAX)
+ {
+ UINT16 size = 0;
+ /* the variable listType contains the requested listType */
+ UINT8 listType = (UINT8)SWAPWORD(pSdoInfoInd->SdoHeader.Data.List.ListType);
+
+ /* the SDO Information Header has to be stored because this function will be
+ called again if the response could not be sent with one mailbox service, the
+ variable nSdoInfoFragmentsLeft is 0 zero for the first call and unequal 0
+ for the following calls */
+ MBXMEMCPY(aSdoInfoHeader, pSdoInfoInd, SDO_INFO_HEADER_BYTE_SIZE);
+ if (listType-- == 0)
+ {
+ /* List-Type 0: length of the lists */
+ UINT8 i;
+
+ /* the needed mailbox size for List-Type 0 response is just 24 bytes, the mailbox has always
+ to be at least 24 bytes to support the SDO Information service */
+ nSdoInfoFragmentsLeft = 0;
+ for (i = 0; i < INFO_LIST_TYPE_MAX; i++)
+ {
+ UINT16 n = OBJ_GetNoOfObjects(i);
+
+ /* copy the number of objects of the list type in the SDO Information response */
+ ((UINT16 MBXMEM *) &pSdoInfoInd->CoeHeader)[(SIZEOF_SDOINFOLISTSTRUCT >> 1) + i] = SWAPWORD(n);
+ }
+
+ /* size of the mailbox service response */
+ size = (INFO_LIST_TYPE_MAX << 1) + SIZEOF_SDOINFOLISTSTRUCT;
+ }
+ else
+ {
+ /* object list with indexes is requested */
+ UINT16 MBXMEM * pData;
+ UINT16 n = 0;
+
+ if (nSdoInfoFragmentsLeft)
+ {
+ /* the next fragment of the SDO Information response shall be sent */
+ /* initialize size with the maximum size fits into one mailbox service */
+/*ET9300 Project Handler :(#if TEST_APPLICATION) lines 1436 to 1443 deleted*/
+ {
+ size = u16SendMbxSize - SIZEOF_SDOINFO - MBX_HEADER_SIZE;
+ }
+ /* initialize pData with the pointer where the fragment has to be copied */
+ pData = &((UINT16 MBXMEM *) &pSdoInfoInd->CoeHeader)[SIZEOF_SDOINFO >> 1];
+ /* initialize index with the next index to be sent */
+ index = nSdoInfoIndex;
+ /* decrement the number of fragments to be sent */
+ nSdoInfoFragmentsLeft--;
+ }
+ else
+ {
+ /* the first fragment of the SDO Information response has to be sent */
+ /* get the number of objects of the requested object list */
+ n = OBJ_GetNoOfObjects(listType);
+ /* we start with index 0x1000 */
+ index = 0x1000;
+ /* initialize size with the maximum size fits into one mailbox service */
+/*ET9300 Project Handler :(#if TEST_APPLICATION) lines 1463 to 1470 deleted*/
+ {
+ size = u16SendMbxSize - SIZEOF_SDOINFOLISTSTRUCT - MBX_HEADER_SIZE;
+ }
+ /* initialize pData with the pointer where the fragment has to be copied */
+ pData = &((UINT16 MBXMEM *) &pSdoInfoInd->CoeHeader)[SIZEOF_SDOINFOLISTSTRUCT >> 1];
+ /*Check if List need to be send in fragments*/
+ if ((n << 1) > size)
+ {
+ /*number of Bytes to transmit don't fit into one mailbox datagram*/
+
+ /*calculate number of fragments which need to be send
+ total number of bytes - bytes which will be transmitted with the current response plus the fragment size - 1 (to round up) divided by the size of the following fragments
+ */
+ UINT16 Fragsize = size + 2;
+
+ nSdoInfoFragmentsLeft = (((n << 1) - size + (Fragsize - 1)) / Fragsize);
+ }
+ else
+ {
+ nSdoInfoFragmentsLeft = 0;
+ }
+/*ET9300 Project Handler :(#if SEGMENTED_SDO_SUPPORTED #else) lines 1493 to 1497 deleted*/
+ }
+
+ /* get the next part of the requested object list */
+ size = OBJ_GetObjectList(listType, &index, size, pData, &abort);
+
+ /* store index for next fragment */
+ nSdoInfoIndex = index;
+ /* size contains before the instruction the size still available in the mailbox buffer
+ and shall contain the size of the mailbox response data after the next instruction */
+/*ET9300 Project Handler :(#if TEST_APPLICATION) lines 1507 to 1514 deleted*/
+ {
+ size = u16SendMbxSize - size - MBX_HEADER_SIZE;
+ }
+ }
+
+ /* size of the mailbox response data */
+ pSdoInfoInd->MbxHeader.Length = size;
+
+ if (abort == 0)
+ {
+ pSdoInfoInd->SdoHeader.InfoHead &= ~INFOHEAD_OPCODE_MASK;
+ pSdoInfoInd->SdoHeader.InfoHead |= (UINT16)(SDOINFOSERVICE_OBJDICTIONARYLIST_S << INFOHEAD_OPCODE_SHIFT);
+/*ET9300 Project Handler :(#if !SEGMENTED_SDO_SUPPORTED) lines 1527 to 1529 deleted*/
+ /* number of fragments still has to be sent */
+ pSdoInfoInd->SdoHeader.FragmentsLeft = SWAPWORD(nSdoInfoFragmentsLeft);
+
+ if (nSdoInfoFragmentsLeft)
+ {
+ /* there still are fragments to be sent,
+ the InComplete flag in the SDO Information response has to be sent */
+ pSdoInfoInd->SdoHeader.InfoHead &= ~INFOHEADER_INCOMPLETE_MASK;
+ pSdoInfoInd->SdoHeader.InfoHead |= (UINT16)(SDOINFOSERVICE_INCOMPLETE << INFOHEAD_OPCODE_SHIFT);
+ /* the FRAGMENTS_FOLLOW flag has to be set for the function MBX_MailboxSendReq to
+ indicate the mailbox handler that still fragments has to be sent so that this
+ function shall be called again from COE_ContinueInd when the actual mailbox buffer
+ was sent */
+ flags = FRAGMENTS_FOLLOW | COE_SERVICE;
+ }
+ }
+ }
+ break;
+
+ case SDOINFOSERVICE_OBJDESCRIPTION_Q:
+ case SDOINFOSERVICE_ENTRYDESCRIPTION_Q:
+ /* get the requested index */
+ index = SWAPWORD(pSdoInfoInd->SdoHeader.Data.Obj.Index);
+
+/*ET9300 Project Handler :(#if TEST_APPLICATION && EOE_SUPPORTED) lines 1555 to 1623 deleted*/
+
+/*ET9300 Project Handler :(#if TEST_APPLICATION) lines 1625 to 1642 deleted*/
+
+ if (index < 0x1000)
+ {
+ /*SDO Info access is only allowed for objects >= 0x1000*/
+ abort = ABORTIDX_UNSUPPORTED_ACCESS;
+ }
+ else
+ {
+ /* get the object handle of the requested index */
+ pObjEntry = OBJ_GetObjectHandle(index);
+
+ if (pObjEntry)
+ {
+ /* object exists */
+ UINT16 size = 0;
+
+ if (opCode == SDOINFOSERVICE_OBJDESCRIPTION_Q)
+ {
+ /* object description is requested */
+/*ET9300 Project Handler :(#if BIG_ENDIAN_FORMAT) lines 1662 to 1666 deleted*/
+ OBJTOMBXMEMCPY(&pSdoInfoInd->SdoHeader.Data.Obj.Res, OBJ_GetObjDesc(pObjEntry), SDO_INFO_OBJ_DESC_SIZE);
+
+
+/*ET9300 Project Handler :(#if TEST_APPLICATION) lines 1671 to 1683 deleted*/
+ /* the mailbox should be big enough that the maximum object description
+ fits in the mailbox (the fragmentation is not done in the sample code),
+ so it will be checked only if the object description fits */
+ size = OBJ_GetDesc(index, 0, pObjEntry, NULL) + SIZEOF_SDOINFOOBJSTRUCT;
+
+ if (size > (u16SendMbxSize - MBX_HEADER_SIZE))
+ {
+ /* size of the object description does not fit in the mailbox,
+ the object description will be sent without the name */
+ size = SIZEOF_SDOINFOOBJSTRUCT;
+ }
+ else
+ {
+ /* object description fits in the mailbox, get the name of the object */
+ size = OBJ_GetDesc(index, 0, pObjEntry, ((UINT16 MBXMEM *) &(&pSdoInfoInd->SdoHeader.Data.Obj.Res)[1])) + SIZEOF_SDOINFOOBJSTRUCT;
+ }
+ }
+ else
+ {
+ /* entry description is requested,
+ get the requested subindex */
+ UINT8 subindex = (UINT8)((pSdoInfoInd->SdoHeader.Data.Entry.Info & ENTRY_MASK_SUBINDEX) >> ENTRY_SUBINDEX_SHIFT);
+
+ /* get the maximum subindex */
+ UINT8 maxSubindex = (OBJ_GetObjDesc(pObjEntry)->ObjFlags & OBJFLAGS_MAXSUBINDEXMASK) >> OBJFLAGS_MAXSUBINDEXSHIFT;
+
+ if (subindex <= maxSubindex)
+ {
+ UINT16 ObjectFlags;
+ /* requested subindex is not too great */
+ /* get the entry description of the requested entry */
+/*ET9300 Project Handler :(#if BIG_ENDIAN_FORMAT) lines 1715 to 1720 deleted*/
+ OBJTOMBXMEMCPY(&pSdoInfoInd->SdoHeader.Data.Entry.Res, OBJ_GetEntryDesc(pObjEntry, subindex), SIZEOF(TSDOINFOENTRYDESC));
+
+ /* the transmission of the value info is not supported yet of the sample code */
+ pSdoInfoInd->SdoHeader.Data.Entry.Info &= ~ENTRY_MASK_VALUEINFO;
+ ObjectFlags = OBJ_GetObjDesc(pObjEntry)->ObjFlags;
+ ObjectFlags = (ObjectFlags & OBJFLAGS_OBJCODEMASK) >> OBJFLAGS_OBJCODESHIFT;
+
+ if (((ObjectFlags == OBJCODE_ARR) || (ObjectFlags == OBJCODE_REC)) && (subindex == 0))
+ {
+ OBJTOMBXSTRCPY(((UINT16 MBXMEM *) &(&pSdoInfoInd->SdoHeader.Data.Entry.Res)[1]), aSubindexDesc, SIZEOF(aSubindexDesc));
+ size = 12 + SIZEOF_SDOINFO + SIZEOF(TSDOINFOENTRY); // 12: Length of "SubIndex 000"
+ }
+ else
+ {
+ /* the mailbox should be big enough that the maximum entry description
+ fits in the mailbox (the fragmentation is not done in the sample code),
+ so it will be checked only if the entry description fits */
+ size = OBJ_GetDesc(index, subindex, pObjEntry, NULL) + SIZEOF_SDOINFO + SIZEOF(TSDOINFOENTRY);
+ if (size > (u16SendMbxSize - MBX_HEADER_SIZE))
+ {
+ /* size of the object description does not fit in the mailbox,
+ the object description will be sent without the name */
+ size = SIZEOF_SDOINFO + SIZEOF(TSDOINFOENTRY);
+ }
+ else
+ {
+ /* object description fits in the mailbox, get the name of the entry */
+ size = OBJ_GetDesc(index, subindex, pObjEntry, ((UINT16 MBXMEM *) &(&pSdoInfoInd->SdoHeader.Data.Entry.Res)[1])) + SIZEOF_SDOINFO + SIZEOF(TSDOINFOENTRY);
+ }
+ }
+ }
+ else
+ {
+ abort = ABORTIDX_SUBINDEX_NOT_EXISTING;
+ }
+ }
+
+ if (abort == 0)
+ {
+ {
+ /* for the object and entry description the sample code does not support the fragmentation,
+ the mailbox has to be big enough */
+ pSdoInfoInd->SdoHeader.FragmentsLeft = 0;
+ /* store the size of the mailbox data in the mailbox buffer */
+ pSdoInfoInd->MbxHeader.Length = size;
+ /* set the opCode of the SDO Information response */
+ pSdoInfoInd->SdoHeader.InfoHead &= ~INFOHEAD_OPCODE_MASK;
+ pSdoInfoInd->SdoHeader.InfoHead |= (UINT16)((opCode + 1) << INFOHEAD_OPCODE_SHIFT);
+ }
+ }
+ }
+ else
+ {
+ abort = ABORTIDX_OBJECT_NOT_EXISTING;
+ }
+ }
+ break;
+ default:
+ abort = ABORTIDX_COMMAND_SPECIFIER_UNKNOWN;
+ }
+
+ if (abort)
+ {
+ /* send a SDO Information Error response */
+ pSdoInfoInd->MbxHeader.Length = SIZEOF_SDOINFOERRORSTRUCT;
+
+ pSdoInfoInd->SdoHeader.InfoHead &= ~INFOHEAD_OPCODE_MASK;
+ pSdoInfoInd->SdoHeader.InfoHead |= (UINT16)((SDOINFOSERVICE_ERROR_Q) << INFOHEAD_OPCODE_SHIFT);
+
+ pSdoInfoInd->SdoHeader.FragmentsLeft = 0;
+/*ET9300 Project Handler :(#if BIG_ENDIAN_16BIT) lines 1792 to 1795 deleted*/
+ pSdoInfoInd->SdoHeader.Data.Error.ErrorCode = SWAPDWORD(cAbortCode[abort]);
+
+ nSdoInfoFragmentsLeft = 0;
+ }
+
+ if (MBX_MailboxSendReq((TMBX MBXMEM *) pSdoInfoInd, flags) != 0)
+ {
+ /* if the mailbox response could not be sent (or stored), the response will be
+ stored in the variable pCoeSendStored and will be sent automatically
+ from the mailbox handler (COE_ContinueInd) when the send mailbox will be read
+ the next time from the master */
+ pCoeSendStored = (TMBX MBXMEM *) pSdoInfoInd;
+ }
+
+ return 0;
+}
+
+/** @} */
+
+
diff --git a/Projects/EFC_EcatDriver/src/ssc/sdoserv.h b/Projects/EFC_EcatDriver/src/ssc/sdoserv.h
new file mode 100644
index 0000000..c4ad14f
--- /dev/null
+++ b/Projects/EFC_EcatDriver/src/ssc/sdoserv.h
@@ -0,0 +1,649 @@
+/*
+* This source file is part of the EtherCAT Slave Stack Code licensed by Beckhoff Automation GmbH & Co KG, 33415 Verl, Germany.
+* The corresponding license agreement applies. This hint shall not be removed.
+* https://www.beckhoff.com/media/downloads/slave-stack-code/ethercat_ssc_license.pdf
+*/
+
+/**
+ * \addtogroup CoE CAN Application Profile over EtherCAT
+ * @{
+ */
+
+
+/**
+\file sdoserv.h
+\author EthercatSSC@beckhoff.com
+\brief SDO Service definitions
+
+\version 5.12
+
+ Changes to version V5.11:
+V5.12 ECAT2: big endian changes
+V5.12 MBX3: handle incomplete mailbox communication
+ Changes to version V5.10:
+V5.11 ECAT10: change PROTO handling to prevent compiler errors
+V5.11 SDO10: add new SDO abort code 0x6010004 (complete access not supported)
+ Changes to version V5.01:
+V5.10 SDO3: Add new SDO Abort Code (0x06090033)
+ Changes to version - :
+V5.01 : Start file change log
+ */
+
+
+/*-----------------------------------------------------------------------------------------
+------
+------ Includes
+------
+-----------------------------------------------------------------------------------------*/
+#include "ecatcoe.h"
+
+
+#ifndef _SDOSERV_H_
+#define _SDOSERV_H_
+
+/*-----------------------------------------------------------------------------------------
+------
+------ Defines and Types
+------
+-----------------------------------------------------------------------------------------*/
+
+/**
+ * \addtogroup SdoErrorCodes SDO Error Codes
+ * @{
+ */
+#define ERROR_SDOINVALIDCOMMAND 0x1101 /**< \brief Invalid SDO command*/
+#define ERROR_SDOINVALIDHEADER 0x1102 /**< \brief Invalid SDO header*/
+#define ERROR_SDONOTSUPPORTED 0x1103 /**< \brief SDO service not supported*/
+/** @}*/
+
+
+/**
+ * \addtogroup SdoHeaderData SDO Header and Data
+ * @{
+ */
+#define SDOHEADER_SIZEINDICATOR ((UINT8) 0x01) /**< \brief Size Indicator size of data in Data Set Size specified*/
+#define SDOHEADER_TRANSFERTYPE ((UINT8) 0x02) /**< \brief Transfer Type 1: Expedited 0: Normal*/
+#define SDOHEADER_DATASETSIZE ((UINT8) 0x0C) /**< \brief Data Set Size (used for Expedited transfer)*/
+#define SDOHEADER_COMPLETEACCESS ((UINT8) 0x10) /**< \brief Complete Access indication 0: Only specified entry will be transferred 1: Whole object (with or without Subindex0) will be transferred)*/
+#define SDOHEADER_COMMAND ((UINT8) 0xE0) /**< \brief SDO Command*/
+#define SDOHEADERSHIFT_SIZEINDICATOR ((UINT8) 0) /**< \brief Shift for Size Indicator*/
+#define SDOHEADERSHIFT_TRANSFERTYPE ((UINT8) 1) /**< \brief Shift for Transfer Type*/
+#define SDOHEADERSHIFT_DATASETSIZE ((UINT8) 2) /**< \brief Shift for Data Set Size*/
+#define SDOHEADERSHIFT_INDEXACCESS ((UINT8) 4) /**< \brief Shift for Complete Access*/
+#define SDOHEADERSHIFT_COMMAND ((UINT8) 5) /**< \brief Shift for SDO Command*/
+/** @}*/
+
+
+/**
+ * \addtogroup SdoServices SDO Services
+ * @{
+ */
+#define SDOSERVICE_INITIATEDOWNLOADREQ ((UINT8) (0x01 << (SDOHEADERSHIFT_COMMAND))) /**< \brief SDO download request*/
+#define SDOSERVICE_INITIATEDOWNLOADRES ((UINT8) (0x03 << (SDOHEADERSHIFT_COMMAND))) /**< \brief SDO download response*/
+#define SDOSERVICE_DOWNLOADSEGMENTREQ ((UINT8) (0x00 << (SDOHEADERSHIFT_COMMAND))) /**< \brief SDO segmented download request*/
+#define SDOSERVICE_DOWNLOADSEGMENTRES ((UINT8) (0x01 << (SDOHEADERSHIFT_COMMAND))) /**< \brief SDO segmented download response*/
+#define SDOSERVICE_INITIATEUPLOADREQ ((UINT8) (0x02 << (SDOHEADERSHIFT_COMMAND))) /**< \brief SDO upload request*/
+#define SDOSERVICE_INITIATEUPLOADRES ((UINT8) (0x02 << (SDOHEADERSHIFT_COMMAND))) /**< \brief SDO upload response*/
+#define SDOSERVICE_UPLOADSEGMENTREQ ((UINT8) (0x03 << (SDOHEADERSHIFT_COMMAND))) /**< \brief SDO segmented upload request*/
+#define SDOSERVICE_UPLOADSEGMENTRES ((UINT8) (0x00 << (SDOHEADERSHIFT_COMMAND))) /**< \brief SDO segmented upload response*/
+#define SDOSERVICE_ABORTTRANSFER ((UINT8) (((UINT8) 0x04) << (SDOHEADERSHIFT_COMMAND))) /**< \brief SDO abort*/
+/** @}*/
+
+
+/**
+ * \addtogroup SdoHeaderData SDO Header and Data
+ * @{
+ */
+/**
+ * Structure to handle the basic SDO header
+ */
+typedef struct MBX_STRUCT_PACKED_START
+{
+/*ET9300 Project Handler :(#if MBX_16BIT_ACCESS) lines 101 to 128 deleted*/
+ UINT8 Sdo[4]; /**< \brief 32Bit SDO header buffer*/
+/*ET9300 Project Handler :(#if BIG_ENDIAN_16BIT) lines 130 to 135 deleted*/
+ #define SDOHEADER_COMMANDOFFSET 0 /**< \brief Memory offset for the command*/
+ #define SDOHEADER_INDEXLOOFFSET 1 /**< \brief Memory offset for the low Byte of the object index*/
+ #define SDOHEADER_INDEXHIOFFSET 2 /**< \brief Memory offset for the high Byte of the object index*/
+ #define SDOHEADER_SUBINDEXOFFSET 3 /**< \brief Memory offset for subindex*/
+ #define SDOHEADER_COMMANDMASK 0xFF /**< \brief Mask to get the command Byte*/
+ #define SDOHEADER_INDEXLOSHIFT 0 /**< \brief Shift to get the low Byte of the object index*/
+ #define SDOHEADER_INDEXHIMASK 0xFF /**< \brief Mask to get the high byte of the object index*/
+ #define SDOHEADER_SUBINDEXSHIFT 0 /**< \brief Shift to get the subindex*/
+}MBX_STRUCT_PACKED_END
+TINITSDOHEADER;
+
+
+#define INITSDO_HEADER_SIZE 4 /**< \brief Size of the SDO header*/
+
+
+/**
+ *Complete SDO datagram including mailbox header, CoE header and SDO header
+ */
+typedef struct MBX_STRUCT_PACKED_START
+{
+ TMBXHEADER MbxHeader; /**< \brief Mailbox header*/
+ TCOEHEADER CoeHeader; /**< \brief CoE header*/
+ TINITSDOHEADER SdoHeader; /**< \brief SDO header*/
+}MBX_STRUCT_PACKED_END
+TINITSDOMBX;
+
+
+#define MAX_EXPEDITED_DATA 4 /**< \brief Maximum number of Bytes handled via an expedited transfer*/
+#define MIN_SEGMENTED_DATA ((UINT16) 7) /**< \brief Minimum number of Bytes required for a segmented transfer*/
+#define EXPEDITED_FRAME_SIZE ( COE_HEADER_SIZE + INITSDO_HEADER_SIZE + (MAX_EXPEDITED_DATA) ) /**< \brief Size of an expedited mailbox datagram*/
+#define DOWNLOAD_NORM_REQ_SIZE ( COE_HEADER_SIZE + INITSDO_HEADER_SIZE + 4 ) /**< \brief Size of an normal download request*/
+/* HBu 06.02.06: names of defines changed */
+/* HBu 21.03.06: the SDO_Download-Response has to have always 8 bytes */
+#define DOWNLOAD_NORM_RES_SIZE ( COE_HEADER_SIZE + INITSDO_HEADER_SIZE + 4 ) /**< \brief Frame size of an normal download response*/
+#define UPLOAD_NORM_RES_SIZE ( COE_HEADER_SIZE + INITSDO_HEADER_SIZE + 4 ) /**< \brief Frame size of an normal upload response*/
+#define SEGMENT_NORM_HEADER_SIZE ( COE_HEADER_SIZE + 1 ) /**< \brief Minimum SDO header size*/
+#define SEGMENT_NORM_RES_SIZE ( (SEGMENT_NORM_HEADER_SIZE) + (MIN_SEGMENTED_DATA) ) /**< \brief Minimum SDO size*/
+#define SEGMENT_MBX_SIZE ( MBX_HEADER_SIZE + (SEGMENT_NORM_HEADER_SIZE) )/**< \brief Minimum mailbox datagram*/
+
+
+/**
+ * Segmented SDO header including data
+ */
+typedef struct MBX_STRUCT_PACKED_START
+{
+/*ET9300 Project Handler :(#if MBX_16BIT_ACCESS) lines 183 to 209 deleted*/
+ UINT8 SegHeader; /**< \brief 8Bit header buffer*/
+ #define SEGHEADER_MASK ((UINT8) 0xFF) /**< \brief SDO header mask*/
+ #define SEGHEADER_NOMOREFOLLOWS ((UINT8) 0x01) /**< \brief More segments follow flag*/
+ #define SEGHEADER_SEGDATASIZE ((UINT8) 0x0E) /**< \brief Segmented data size*/
+ #define SEGHEADER_TOGGLE ((UINT8) 0x10) /**< \brief Toogle flag*/
+ #define SEGHEADER_COMMAND ((UINT8) 0xE0) /**< \brief Command identifier*/
+ #define SEGHEADERSHIFT_SEGDATASIZE ((UINT8) 1) /**< \brief Shift for Segmented data size*/
+ #define SEGHEADERSHIFT_TOGGLE ((UINT8) 4) /**< \brief Shift for toggle flag*/
+ #define SEGHEADERSHIFT_COMMAND ((UINT8) 5) /**< \brief Shift for command identifier*/
+ UINT8 Data[(MAX_MBX_DATA_SIZE)-(SEGMENT_NORM_HEADER_SIZE)]; /**< \brief Data buffer*/
+}MBX_STRUCT_PACKED_END
+TSDOSEGHEADERDATA;
+
+
+/**
+ *Expedited download request
+ */
+typedef struct MBX_STRUCT_PACKED_START
+{
+ TMBXHEADER MbxHeader; /**< \brief Mailbox header*/
+ TCOEHEADER CoeHeader; /**< \brief CoE header*/
+ TINITSDOHEADER SdoHeader; /**< \brief SDO header*/
+ UINT16 Data[(MAX_EXPEDITED_DATA) >> 1]; /**< \brief Data buffer*/
+}MBX_STRUCT_PACKED_END
+TINITSDODOWNLOADEXPREQMBX;
+
+/**
+ *Normal download request
+ */
+typedef struct MBX_STRUCT_PACKED_START
+{
+ TMBXHEADER MbxHeader; /**< \brief Mailbox header*/
+ TCOEHEADER CoeHeader; /**< \brief CoE header*/
+ TINITSDOHEADER SdoHeader; /**< \brief SDO header*/
+ UINT16 CompleteSize[2]; /**< \brief Complete object size*/
+ UINT16 Data[(((MAX_MBX_DATA_SIZE)-(DOWNLOAD_NORM_REQ_SIZE)) >> 1)]; /**< \brief Data buffer*/
+}MBX_STRUCT_PACKED_END
+TINITSDODOWNLOADNORMREQMBX;
+
+
+/**
+ *Expedited and normal download response:
+ */
+typedef struct MBX_STRUCT_PACKED_START
+{
+ TMBXHEADER MbxHeader; /**< \brief Mailbox header*/
+ TCOEHEADER CoeHeader; /**< \brief CoE header*/
+ TINITSDOHEADER SdoHeader; /**< \brief SDO header*/
+}MBX_STRUCT_PACKED_END
+TINITSDODOWNLOADRESMBX;
+
+
+/**
+ *Segmented download request
+ */
+typedef struct MBX_STRUCT_PACKED_START
+{
+ TMBXHEADER MbxHeader; /**< \brief Mailbox header*/
+ TCOEHEADER CoeHeader; /**< \brief CoE header*/
+ TSDOSEGHEADERDATA SdoHeader; /**< \brief SDO header (data is included in header)*/
+}MBX_STRUCT_PACKED_END
+TDOWNLOADSDOSEGREQMBX;
+
+
+/**
+ *Segmented download response
+ */
+typedef struct MBX_STRUCT_PACKED_START
+{
+ TMBXHEADER MbxHeader; /**< \brief Mailbox header*/
+ TCOEHEADER CoeHeader; /**< \brief CoE header*/
+ UINT8 SegHeader; /**< \brief SDO header*/
+}MBX_STRUCT_PACKED_END
+TDOWNLOADSDOSEGRESMBX;
+
+
+/**
+ *Expedited and normal upload request
+ */
+typedef struct MBX_STRUCT_PACKED_START
+{
+ TMBXHEADER MbxHeader; /**< \brief Mailbox header*/
+ TCOEHEADER CoeHeader; /**< \brief CoE header*/
+ TINITSDOHEADER SdoHeader; /**< \brief SDO header*/
+}MBX_STRUCT_PACKED_END
+TINITSDOUPLOADREQMBX;
+
+
+/**
+ *Expedited upload response
+ */
+typedef struct MBX_STRUCT_PACKED_START
+{
+ TMBXHEADER MbxHeader; /**< \brief Mailbox header*/
+ TCOEHEADER CoeHeader; /**< \brief CoE header*/
+ TINITSDOHEADER SdoHeader; /**< \brief SDO header*/
+ UINT16 Data[((MAX_EXPEDITED_DATA) >> 1)]; /**< \brief Data buffer*/
+}MBX_STRUCT_PACKED_END
+TINITSDOUPLOADEXPRESMBX;
+
+
+/**
+ *Normal upload response
+ */
+typedef struct MBX_STRUCT_PACKED_START
+{
+ TMBXHEADER MbxHeader; /**< \brief Mailbox header*/
+ TCOEHEADER CoeHeader; /**< \brief CoE header*/
+ TINITSDOHEADER SdoHeader; /**< \brief SDO header*/
+ UINT16 CompleteSize[2]; /**< \brief Complete object size*/
+ UINT16 Data[(((MAX_MBX_DATA_SIZE)-(UPLOAD_NORM_RES_SIZE)) >> 1)]; /**< \brief Data buffer*/
+}MBX_STRUCT_PACKED_END
+TINITSDOUPLOADNORMRESMBX;
+
+
+/**
+ *Segmented upload request
+ */
+typedef struct MBX_STRUCT_PACKED_START
+{
+ TMBXHEADER MbxHeader; /**< \brief Mailbox header*/
+ TCOEHEADER CoeHeader; /**< \brief CoE header*/
+ UINT8 SegHeader; /**< \brief SDO header*/
+}MBX_STRUCT_PACKED_END
+TUPLOADSDOSEGREQMBX;
+
+/**
+ *Segmented upload response
+ */
+typedef struct MBX_STRUCT_PACKED_START
+{
+ TMBXHEADER MbxHeader; /**< \brief Mailbox header*/
+ TCOEHEADER CoeHeader; /**< \brief CoE header*/
+ TSDOSEGHEADERDATA SdoHeader; /**< \brief SDO header (data is included in header)*/
+}MBX_STRUCT_PACKED_END
+TUPLOADSDOSEGRESMBX;
+
+
+/**
+ *Abort request
+ */
+typedef struct MBX_STRUCT_PACKED_START
+{
+ TMBXHEADER MbxHeader; /**< \brief Mailbox header*/
+ TCOEHEADER CoeHeader; /**< \brief CoE header*/
+ TINITSDOHEADER SdoHeader; /**< \brief SDO header*/
+ UINT32 AbortCode; /**< \brief SDO abort code*/
+}MBX_STRUCT_PACKED_END
+TABORTSDOTRANSFERREQMBX;
+
+
+#define ABORT_NORM_RES_SIZE (SIZEOF(TABORTSDOTRANSFERREQMBX) - SIZEOF(TMBXHEADER))/**< \brief Size of the SDO Abort datagram (without the mailbox header)*/
+/** @}*/
+
+
+/**
+ * \addtogroup SDOAbort SDO Abort Codes
+ * @{
+ */
+#define ABORT_NOERROR 0x00000000 /**< \brief No SDO error*/
+#define ABORT_TOGGLE_BIT_NOT_CHANGED 0x05030000 /**< \brief Toggle bit not changed*/
+#define ABORT_SDO_PROTOCOL_TIMEOUT 0x05040000 /**< \brief SDO timeout*/
+#define ABORT_COMMAND_SPECIFIER_UNKNOWN 0x05040001 /**< \brief Command specifier unknown*/
+#define ABORT_OUT_OF_MEMORY 0x05040005 /**< \brief Out of memory*/
+#define ABORT_UNSUPPORTED_ACCESS 0x06010000 /**< \brief Unsupported Access*/
+#define ABORT_WRITE_ONLY_ENTRY 0x06010001 /**< \brief Write only entry*/
+#define ABORT_READ_ONLY_ENTRY 0x06010002 /**< \brief Read only entry*/
+#define ABORT_ENTRY_CANT_BE_WRITTEN_SI0_NOT_0 0x06010003 /**< \brief Entry can not be written because Subindex0 is not 0*/
+#define ABORT_COMPLETE_ACCESS_NOT_SUPPORTED 0x06010004 /**< \brief The object can not be accessed via complete access*/
+#define ABORT_OBJECT_NOT_EXISTING 0x06020000 /**< \brief Object not existing*/
+#define ABORT_OBJECT_CANT_BE_PDOMAPPED 0x06040041 /**< \brief Object can not be mapped to PDO*/
+#define ABORT_MAPPED_OBJECTS_EXCEED_PDO 0x06040042 /**< \brief Mapped Object exceeds PDO*/
+#define ABORT_PARAM_IS_INCOMPATIBLE 0x06040043 /**< \brief Parameter is incompatible*/
+#define ABORT_INTERNAL_DEVICE_INCOMPATIBILITY 0x06040047 /**< \brief Device incompatibility*/
+#define ABORT_HARDWARE_ERROR 0x06060000 /**< \brief Hardware error*/
+#define ABORT_PARAM_LENGTH_ERROR 0x06070010 /**< \brief Parameter length error*/
+#define ABORT_PARAM_LENGTH_TOO_LONG 0x06070012 /**< \brief Parameter is too long*/
+#define ABORT_PARAM_LENGTH_TOO_SHORT 0x06070013 /**< \brief Parameter is too short*/
+#define ABORT_SUBINDEX_NOT_EXISTING 0x06090011 /**< \brief Subindex (Entry) not exists*/
+#define ABORT_VALUE_EXCEEDED 0x06090030 /**< \brief Value exceeds*/
+#define ABORT_VALUE_TOO_GREAT 0x06090031 /**< \brief Value is too great*/
+#define ABORT_VALUE_TOO_SMALL 0x06090032 /**< \brief Value is too small*/
+#define ABORT_MODULE_ID_LIST_NOT_MATCH 0x06090033 /**< \brief Detected Module Ident List (0xF030) and Configured Module Ident list (0xF050) does not match*/
+#define ABORT_MAX_VALUE_IS_LESS_THAN_MIN_VALUE 0x06090036 /**< \brief Value is less than minimum value*/
+#define ABORT_GENERAL_ERROR 0x08000000 /**< \brief General error*/
+#define ABORT_DATA_CANNOT_BE_READ_OR_STORED 0x08000020 /**< \brief Data can not be read or written*/
+#define ABORT_DATA_CANNOT_BE_READ_OR_STORED_BECAUSE_OF_LOCAL_CONTROL 0x08000021 /**< \brief Data can not be accessed because of local control*/
+#define ABORT_DATA_CANNOT_BE_READ_OR_STORED_IN_THIS_STATE 0x08000022 /**< \brief Data can not be read or written in the current state*/
+#define ABORT_NO_OBJECT_DICTIONARY_IS_PRESENT 0x08000023 /**< \brief Object is not in the object dictionary*/
+
+
+/**
+ * \addtogroup SDOAbortIndex SDO Abort Codes Identifier
+ * @{
+ * Internal the SDO abort codes are handled in an array.
+ */
+#define ABORTIDX_TOGGLE_BIT_NOT_CHANGED 0x01 /**< \brief Index of "Toggle bit not changed"*/
+#define ABORTIDX_SDO_PROTOCOL_TIMEOUT 0x02 /**< \brief Index of "SDO timeout"*/
+#define ABORTIDX_COMMAND_SPECIFIER_UNKNOWN 0x03 /**< \brief Index of "Command specifier unknown"*/
+#define ABORTIDX_OUT_OF_MEMORY 0x04 /**< \brief Index of "Out of memory"*/
+#define ABORTIDX_UNSUPPORTED_ACCESS 0x05 /**< \brief Index of "Unsupported Access"*/
+#define ABORTIDX_WRITE_ONLY_ENTRY 0x06 /**< \brief Index of "Write only entry"*/
+#define ABORTIDX_READ_ONLY_ENTRY 0x07 /**< \brief Index of "Read only entry"*/
+#define ABORTIDX_OBJECT_NOT_EXISTING 0x08 /**< \brief Index of "Object not existing"*/
+#define ABORTIDX_OBJECT_CANT_BE_PDOMAPPED 0x09 /**< \brief Index of "Object can not be mapped to PDO"*/
+#define ABORTIDX_MAPPED_OBJECTS_EXCEED_PDO 0x0A /**< \brief Index of "Mapped Object exceeds PDO"*/
+#define ABORTIDX_PARAM_IS_INCOMPATIBLE 0x0B /**< \brief Index of "Parameter is incompatible"*/
+#define ABORTIDX_INTERNAL_DEVICE_INCOMPATIBILITY 0x0C /**< \brief Index of "Device incompatibility"*/
+#define ABORTIDX_HARDWARE_ERROR 0x0D /**< \brief Index of "Hardware error"*/
+#define ABORTIDX_PARAM_LENGTH_ERROR 0x0E /**< \brief Index of "Parameter length error"*/
+#define ABORTIDX_PARAM_LENGTH_TOO_LONG 0x0F /**< \brief Index of "Parameter is too long"*/
+#define ABORTIDX_PARAM_LENGTH_TOO_SHORT 0x10 /**< \brief Index of "Parameter is too short"*/
+#define ABORTIDX_SUBINDEX_NOT_EXISTING 0x11 /**< \brief Index of "Subindex (Entry) not exists"*/
+#define ABORTIDX_VALUE_EXCEEDED 0x12 /**< \brief Index of "Value exceeds"*/
+#define ABORTIDX_VALUE_TOO_GREAT 0x13 /**< \brief Index of "Value is too great"*/
+#define ABORTIDX_VALUE_TOO_SMALL 0x14 /**< \brief Index of "Value is too small"*/
+#define ABORTIDX_MODULE_ID_LIST_NOT_MATCH 0x15 /**< \brief Index of "Unequal Module Id list"*/
+#define ABORTIDX_MAX_VALUE_IS_LESS_THAN_MIN_VALUE 0x16 /**< \brief Index of "Value is less than minimum value"*/
+#define ABORTIDX_GENERAL_ERROR 0x17 /**< \brief Index of "General error"*/
+#define ABORTIDX_DATA_CANNOT_BE_READ_OR_STORED 0x18 /**< \brief Index of "Data can not be read or written"*/
+#define ABORTIDX_DATA_CANNOT_BE_ACCESSED_BECAUSE_OF_LOCAL_CONTROL 0x19 /**< \brief Index of "Data can not be accessed because of local control"*/
+#define ABORTIDX_IN_THIS_STATE_DATA_CANNOT_BE_READ_OR_STORED 0x1A /**< \brief Index of "Data can not be read or written in the current state"*/
+#define ABORTIDX_NO_OBJECT_DICTIONARY_IS_PRESENT 0x1B /**< \brief Index of "Object is not in the object dictionary"*/
+#define ABORTIDX_ENTRY_CANT_BE_WRITTEN_SI0_NOT_0 0x1C /**< \brief Index of "Entry can not be written because Subindex0 is not 0"*/
+#define ABORTIDX_COMPLETE_ACCESS_NOT_SUPPORTED 0x1D /**< \brief The object can not be accessed via complete access*/
+#define ABORTIDX_WORKING 0xFF /**< \brief Index of application is handling the SDO request*/
+/** @}*/
+/** @}*/
+
+
+/**
+ *\addtogroup SdoServices SDO Services
+ * @{
+ */
+#define SDOINFOSERVICE_OBJDICTIONARYLIST_Q 0x01 /**< \brief SDO Info Get object list request*/
+#define SDOINFOSERVICE_OBJDICTIONARYLIST_S 0x02 /**< \brief SDO Info Get object list response*/
+#define SDOINFOSERVICE_OBJDESCRIPTION_Q 0x03 /**< \brief SDO Info Get object description request*/
+#define SDOINFOSERVICE_OBJDESCRIPTION_S 0x04 /**< \brief SDO Info Get object description response*/
+#define SDOINFOSERVICE_ENTRYDESCRIPTION_Q 0x05 /**< \brief SDO Info Get entry description request*/
+#define SDOINFOSERVICE_ENTRYDESCRIPTION_S 0x06 /**< \brief SDO Info Get entry description request*/
+#define SDOINFOSERVICE_ERROR_Q 0x07 /**< \brief SDO Info Error*/
+#define SDOINFOSERVICE_INCOMPLETE 0x80 /**< \brief SDO Info Incomplete flag*/
+/** @}*/
+
+
+/**
+ *\addtogroup SdoHeaderData SDO Header and Data
+ * @{
+ */
+/**
+ * SDO Info Object list
+ */
+typedef struct MBX_STRUCT_PACKED_START
+{
+ UINT16 ListType; /**< \brief List type variable*/
+ #define INFO_LIST_TYPE_LENGTH 0 /**< \brief Length of all list types*/
+ #define INFO_LIST_TYPE_ALL 1 /**< \brief All objects*/
+ #define INFO_LIST_TYPE_RXPDO 2 /**< \brief Only RxPDO mappable objects*/
+ #define INFO_LIST_TYPE_TXPDO 3 /**< \brief Only TxPDO mappable objects*/
+ #define INFO_LIST_TYPE_BACKUP 4 /**< \brief Only backup objects*/
+ #define INFO_LIST_TYPE_SET 5 /**< \brief Only setting objects*/
+ #define INFO_LIST_TYPE_MAX 5 /**< \brief Max list identifier*/
+}MBX_STRUCT_PACKED_END
+TSDOINFOLIST;
+
+
+/**
+ * Object description
+ */
+typedef struct MBX_STRUCT_PACKED_START
+{
+ UINT16 DataType; /**< \brief Object data type*/
+ UINT16 ObjFlags; /**< \brief Object flags (including object code and max subindex)*/
+
+ /*Object Code and MaxSubindex will be set manually in the object dictionary. The value is always created in little endian format*/
+ #define OBJFLAGS_MAXSUBINDEXMASK 0x00FF /**< \brief Max subindex mask*/
+ #define OBJFLAGS_MAXSUBINDEXSHIFT 0 /**< \brief Max subindex shift*/
+ #define OBJFLAGS_OBJCODEMASK 0x0F00 /**< \brief Mask Object code mask*/
+ #define OBJFLAGS_OBJCODESHIFT 8 /**< \brief Object code shift*/
+
+ #define OBJCODE_VAR 0x07 /**< \brief Object code VARIABLE*/
+ #define OBJCODE_ARR 0x08 /**< \brief Object code ARRAY*/
+ #define OBJCODE_REC 0x09 /**< \brief Object code RECORD*/
+
+// char Name[]; // rest of mailbox data
+}MBX_STRUCT_PACKED_END
+TSDOINFOOBJDESC;
+
+
+#define SDO_INFO_OBJ_DESC_SIZE SIZEOF(TSDOINFOOBJDESC) /**< \brief Object description size*/
+
+
+/**
+ * SDO Info object description service data
+ */
+typedef struct MBX_STRUCT_PACKED_START
+{
+ UINT16 Index; /**< \brief Object index*/
+ TSDOINFOOBJDESC Res; /**< \brief Description data*/
+}MBX_STRUCT_PACKED_END
+TSDOINFOOBJ;
+
+
+#define SDO_INFO_OBJ_DESC_RES_SIZE SIZEOF(TSDOINFOOBJ)/**< \brief Size of the object description service data*/
+
+
+/**
+ * SDO Info entry description
+ */
+typedef struct MBX_STRUCT_PACKED_START
+{
+ UINT16 DataType; /**< \brief Entry data type*/
+ UINT16 BitLength; /**< \brief Entry bit size*/
+ UINT16 ObjAccess; /**< \brief Entry access rights*/
+ /**<
+ Bit 0: Read Access in Pre-Op
+ Bit 1: Read Access in Safe-Op
+ Bit 2: Read Access in Op
+ Bit 3: Write Access in Pre-Op
+ Bit 4: Write Access in Safe-Op
+ Bit 5: Write Access in Op
+ Bit 6: mappable in RxPDO
+ Bit 7: mappable in TxPDO
+ Bit 8: entry will be included in backup
+ Bit 9: entry will be included in settings*/
+
+ #define ACCESS_READWRITE 0x003F /**< \brief Read/write in all states*/
+ #define ACCESS_READ 0x0007 /**< \brief Read only in all states*/
+ #define ACCESS_READ_PREOP 0x0001 /**< \brief Read only in PreOP*/
+ #define ACCESS_READ_SAFEOP 0x0002 /**< \brief Read only in SafeOP*/
+ #define ACCESS_READ_OP 0x0004 /**< \brief Read only in OP*/
+ #define ACCESS_WRITE 0x0038 /**< \brief Write only in all states*/
+ #define ACCESS_WRITE_PREOP 0x0008 /**< \brief Write only in PreOP*/
+ #define ACCESS_WRITE_SAFEOP 0x0010 /**< \brief Write only in SafeOP*/
+ #define ACCESS_WRITE_OP 0x0020 /**< \brief Write only in OP*/
+ #define OBJACCESS_NOPDOMAPPING 0x0000 /**< \brief Not PDO mappable*/
+ #define OBJACCESS_RXPDOMAPPING 0x0040 /**< \brief Mappable in RxPDOs*/
+ #define OBJACCESS_TXPDOMAPPING 0x0080 /**< \brief Mappable in TxPDOs*/
+ #define OBJACCESS_BACKUP 0x0100 /**< \brief Backup entry*/
+ #define OBJACCESS_SETTINGS 0x0200 /**< \brief Setting Entry*/
+ #define OBJACCESS_SAFEINPUTS 0x0400 /**< \brief Safe input*/
+ #define OBJACCESS_SAFEOUTPUTS 0x0800 /**< \brief Safe output*/
+ #define OBJACCESS_SAFEPARAMETER 0x1000 /**< \brief Safe parameter*/
+}MBX_STRUCT_PACKED_END
+TSDOINFOENTRYDESC;
+
+
+/**
+ * SDO Info entry description service data
+ */
+typedef struct MBX_STRUCT_PACKED_START
+{
+ UINT16 Index; /**< \brief Index of the parent object*/
+ UINT16 Info; /**< \brief Info data including the subindex and identifier for the payload data*/
+/*ET9300 Project Handler :(#if BIG_ENDIAN_FORMAT) lines 565 to 570 deleted*/
+ #define ENTRY_MASK_SUBINDEX 0x00FF /**< \brief Subindex mask*/
+ #define ENTRY_SUBINDEX_SHIFT 0 /**< \brief Subindex shift*/
+ #define ENTRY_MASK_VALUEINFO 0xFF00 /**< \brief Value info mask*/
+ #define ENTRY_VALUEINFO_SHIFT 8 /**< \brief Value info shift*/
+
+ TSDOINFOENTRYDESC Res; /**< \brief Entry description data*/
+}MBX_STRUCT_PACKED_END
+TSDOINFOENTRY;
+
+
+/**
+ * SDO info Error
+ */
+typedef struct MBX_STRUCT_PACKED_START
+{
+ UINT32 ErrorCode; /**< \brief SDO Info error code*/
+}MBX_STRUCT_PACKED_END
+TSDOINFOERROR;
+
+
+#define SDO_INFO_ERROR_SIZE SIZEOF(TSDOINFOERROR)/**< \brief SDO Info error size*/
+
+
+/**
+ *SDO Info header
+ */
+typedef struct MBX_STRUCT_PACKED_START
+{
+ UINT16 InfoHead; /**< \brief Opcode, Incomplete flag and 8 reserved bits*/
+/*ET9300 Project Handler :(#if BIG_ENDIAN_FORMAT) lines 601 to 606 deleted*/
+ #define INFOHEAD_OPCODE_MASK 0x007F /**< \brief Opcode mask*/
+ #define INFOHEAD_OPCODE_SHIFT 0 /**< \brief Opcode shift*/
+ #define INFOHEADER_INCOMPLETE_MASK 0x0080 /**< \brief Incomplete mask*/
+ #define INFOHEADER_INCOMPLETE_SHIFT 0 /**< \brief Incomplete shift, the incomplete value "SDOINFOSERVICE_INCOMPLETE" is defined as a UINT8 => no shift required*/
+
+ UINT16 FragmentsLeft; /**< \brief Number of fragments which will follow*/
+
+ union MBX_STRUCT_PACKED_START
+ {
+ TSDOINFOLIST List;/**< \brief List data*/
+ TSDOINFOOBJ Obj;/**< \brief Object Description data*/
+ TSDOINFOENTRY Entry;/**< \brief Entry description data*/
+ TSDOINFOERROR Error;/**< \brief Error data*/
+ UINT16 Data[1];/**< \brief Unspecified data*/
+ }MBX_STRUCT_PACKED_END
+ Data;/**< \brief Service data*/
+
+}MBX_STRUCT_PACKED_END
+TSDOINFOHEADER;
+
+
+/**
+ * SDO Info complete datagram
+ */
+typedef struct MBX_STRUCT_PACKED_START
+{
+ TMBXHEADER MbxHeader; /**< \brief Mailbox header*/
+ TCOEHEADER CoeHeader; /**< \brief CoE header*/
+ TSDOINFOHEADER SdoHeader; /**< \brief SDO Info header and data*/
+}MBX_STRUCT_PACKED_END
+TSDOINFORMATION;
+
+
+#define SIZEOF_SDOINFOHEAD 4 /**< \brief SDO Info header size*/
+#define SIZEOF_SDOINFO ( (COE_HEADER_SIZE) + (SIZEOF_SDOINFOHEAD )) /**< \brief SDO Info and CoE Size*/
+#define SIZEOF_SDOINFOSTRUCT ( (MBX_HEADER_SIZE) + (COE_HEADER_SIZE) + (SIZEOF_SDOINFOHEAD) ) /**< \brief Complete SDO Info datagram size*/
+#define SIZEOF_SDOINFOLISTHEAD 2 /**< \brief SDO Info list header size*/
+#define SIZEOF_SDOINFOLISTSTRUCT (( COE_HEADER_SIZE) + (SIZEOF_SDOINFOHEAD) + (SIZEOF_SDOINFOLISTHEAD) ) /**< \brief Complete SDO Info list size*/
+#define SIZEOF_SDOINFOOBJSTRUCT ( (COE_HEADER_SIZE) + (SIZEOF_SDOINFOHEAD) + (SDO_INFO_OBJ_DESC_RES_SIZE) ) /**< \brief Complete SDO Info object description response size*/
+#define SIZEOF_SDOINFOENTRYREQHEAD 4 /**< \brief SDO Info entry description request size*/
+#define SIZEOF_SDOINFOENTRYREQSTRUCT ( (COE_HEADER_SIZE) + (SIZEOF_SDOINFOHEAD) + (SIZEOF_SDOINFOENTRYREQHEAD) ) /**< \brief SDO Info entry description request size*/
+#define SIZEOF_SDOINFOERRORSTRUCT ( (COE_HEADER_SIZE) + (SIZEOF_SDOINFOHEAD) + (SDO_INFO_ERROR_SIZE) ) /**< \brief SDO Info error size*/
+
+
+#define SDO_INFO_HEADER_BYTE_SIZE ((SIZEOF_SDOINFOSTRUCT)+(SIZEOF_SDOINFOLISTHEAD)) /**< \brief SDO Info size*/
+/** @}*/
+
+
+/**
+ * \addtogroup SdoPendingHandler SDO Pending Response
+ * @{
+ * If this feature is enabled (SDO_RES_INTERFACE 1) a SDO request may set to pending and is completed afterwards.
+ * This can be used to forward the read/write request an additional thread, uController.
+ */
+#define SDO_PENDING_WRITE 0x1 /**< \brief SDO write request is pending*/
+#define SDO_PENDING_SEG_WRITE 0x2 /**< \brief SDO segmented write request is pending*/
+#define SDO_PENDING_READ 0x3 /**< \brief SDO read request is pending*/
+#define SDO_PENDING_SEG_READ 0x4 /**< \brief SDO segmented read request is pending*/
+/** @}*/
+
+
+#endif //_SDOSRV_H_
+
+/*-----------------------------------------------------------------------------------------
+------
+------ Global Variables
+------
+-----------------------------------------------------------------------------------------*/
+#if defined(_SDOSERV_) && (_SDOSERV_ == 1)
+ #define PROTO
+#else
+ #define PROTO extern
+#endif
+
+/**
+ * \addtogroup SdoPendingHandler SDO Pending Response
+ *@{
+ */
+PROTO UINT8 u8PendingSdo; /**< \brief Identifier for the pending SDO service (see SDO_PENDING_XXX defines)*/
+PROTO BOOL bStoreCompleteAccess; /**< \brief Indicates if the pending SDO service is an complete access*/
+PROTO UINT8 u8StoreSubindex; /**< \brief Contains the subindex for the pending SDO request*/
+PROTO UINT16 u16StoreIndex; /**< \brief Contains the Index for the pending SDO request*/
+PROTO UINT32 u32StoreDataSize; /**< \brief Complete data size to be handled*/
+PROTO UINT16 MBXMEM *pStoreData; /**< \brief Pointer to the buffer to be handled*/
+PROTO UINT8 (* pSdoPendFunc)( UINT16 Index, UINT8 Subindex, UINT32 Size, UINT16 MBXMEM * pData, UINT8 bCompleteAccess ); /**< \brief Function pointer for the SDO pending request handler*/
+/** @}*/
+
+
+PROTO MEM_ADDR VARMEM aSdoInfoHeader[GET_MEM_SIZE(SDO_INFO_HEADER_BYTE_SIZE)]; /**< \brief SDO Info buffer*/
+
+
+/**
+ * \addtogroup SegmentedSdo Segmented SDO
+ * @{
+ */
+PROTO UINT16 VARMEM * VARMEM pSdoSegData; /**< \brief Pointer to the buffer handling to full object/entry data*/
+PROTO UINT16 VARMEM nSdoInfoFragmentsLeft; /**< \brief Number of fragments which need to be transmitted*/
+/** @}*/
+
+
+/*-----------------------------------------------------------------------------------------
+------
+------ Global Functions
+------
+-----------------------------------------------------------------------------------------*/
+PROTO UINT8 SDOS_SdoInfoInd(TSDOINFORMATION MBXMEM *pSdoInfoInd);
+PROTO UINT8 SDOS_SdoInd(TINITSDOMBX MBXMEM *pSdoInd);
+
+PROTO void SDOS_SdoRes(UINT8 abort, UINT32 objLength, UINT16 MBXMEM *pData);
+PROTO void SDOS_ClearPendingResponse(void);
+
+
+#undef PROTO
+/** @}*/