Commit 1357a76e283f88f36417fc93fdb4e330c87d1fe4
authorManfred Steiner <sx@htl-kaindorf.at>
Sun, 20 Sep 2020 05:45:17 +0000 (07:45 +0200)
committerManfred Steiner <sx@htl-kaindorf.at>
Sun, 20 Sep 2020 05:45:17 +0000 (07:45 +0200)
36 files changed:
.gitignore [new file with mode: 0644]
LICENSE [new file with mode: 0644]
README.md [new file with mode: 0644]
java_modbusmaster/build.xml [new file with mode: 0644]
java_modbusmaster/manifest.mf [new file with mode: 0644]
java_modbusmaster/nbproject/build-impl.xml [new file with mode: 0644]
java_modbusmaster/nbproject/genfiles.properties [new file with mode: 0644]
java_modbusmaster/nbproject/project.properties [new file with mode: 0644]
java_modbusmaster/nbproject/project.xml [new file with mode: 0644]
java_modbusmaster/src/modbus/ModbusTest.java [new file with mode: 0644]
java_modbusmaster/src/modbus/frames/ModbusFrame.java [new file with mode: 0644]
java_modbusmaster/src/modbus/frames/ModbusFrameReadCoil.java [new file with mode: 0644]
java_modbusmaster/src/modbus/frames/ModbusFrameReadDiscreteInput.java [new file with mode: 0644]
java_modbusmaster/src/modbus/frames/ModbusFrameReadHoldingRegisters.java [new file with mode: 0644]
java_modbusmaster/src/modbus/frames/ModbusFrameReadInputRegisters.java [new file with mode: 0644]
java_modbusmaster/src/modbus/frames/ModbusFrameWriteMultipleCoils.java [new file with mode: 0644]
java_modbusmaster/src/modbus/frames/ModbusFrameWriteMultipleRegisters.java [new file with mode: 0644]
java_modbusmaster/src/modbus/frames/ModbusFrameWriteRegister.java [new file with mode: 0644]
java_modbusmaster/src/modbus/frames/ModbusFrameWriteSingleCoil.java [new file with mode: 0644]
sure_modbusslave/Makefile [new file with mode: 0644]
sure_modbusslave/nbproject/Makefile-Release.mk [new file with mode: 0644]
sure_modbusslave/nbproject/Makefile-impl.mk [new file with mode: 0644]
sure_modbusslave/nbproject/Makefile-variables.mk [new file with mode: 0644]
sure_modbusslave/nbproject/Package-Release.bash [new file with mode: 0644]
sure_modbusslave/nbproject/configurations.xml [new file with mode: 0644]
sure_modbusslave/nbproject/project.xml [new file with mode: 0644]
sure_modbusslave/released/readme [new file with mode: 0644]
sure_modbusslave/released/sure.elf.hex [new file with mode: 0644]
sure_modbusslave/src/app.c [new file with mode: 0644]
sure_modbusslave/src/app.h [new file with mode: 0644]
sure_modbusslave/src/global.h [new file with mode: 0644]
sure_modbusslave/src/main.c [new file with mode: 0644]
sure_modbusslave/src/sys.c [new file with mode: 0644]
sure_modbusslave/src/sys.h [new file with mode: 0644]
sure_modbusslave/src/twi.c [new file with mode: 0644]
sure_modbusslave/src/twi.h [new file with mode: 0644]

diff --git a/.gitignore b/.gitignore
new file mode 100644 (file)
index 0000000..1d927c0
--- /dev/null
@@ -0,0 +1,24 @@
+# Netbeans Java with ant
+**/nbproject/private/
+**/build/
+**/dist/
+
+# Netbeans Java with Maven
+**/target/
+
+# Netbeans Java with Gradle
+**/.gradle/
+**/.nb-gradle/
+
+# Netbeans C/C++
+**/nbproject/private/
+**/build/
+**/dist/
+**/.dep.inc
+
+# Codeblocks/Structorizer
+**/bin/
+**/obj/
+*.depend
+*.layout
+
diff --git a/LICENSE b/LICENSE
new file mode 100644 (file)
index 0000000..7651f1d
--- /dev/null
+++ b/LICENSE
@@ -0,0 +1,21 @@
+MIT License
+
+Copyright (c) 2020 Manfred Steiner
+
+Permission is hereby granted, free of charge, to any person obtaining a copy
+of this software and associated documentation files (the "Software"), to deal
+in the Software without restriction, including without limitation the rights
+to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+copies of the Software, and to permit persons to whom the Software is
+furnished to do so, subject to the following conditions:
+
+The above copyright notice and this permission notice shall be included in all
+copies or substantial portions of the Software.
+
+THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
+SOFTWARE.
diff --git a/README.md b/README.md
new file mode 100644 (file)
index 0000000..77e92ed
--- /dev/null
+++ b/README.md
@@ -0,0 +1,161 @@
+# Sure Board as Modbus RTU Device
+
+## 
+
+## API
+
+See also: [sure_modbusslave/released/readme](sure_modbusslave/released/readme)
+
+Version: V1.6(10) (Jan  9 2014 07:59:39)
+Hex-File: https://www.htl-mechatronik.at/svn/modbus/sure_modbusslave/released/sure.elf.hex?p=22
+Serial interface: 57600 Bit/s, 8N2
+Subversion revision: 22
+Committed by: SX
+Implementation remarks: none
+Deviation from Modbus protocol
+  MODBUS over serial line specification and implementation guide V1.02
+  2.5.1.1 MODBUS message RTU framing: 
+    T1.5 = 2.8ms instead of 287us (11/57600*1.5=287us)
+    T3.5 = 6.8ms instead of 668us (11/57600*3.5=668us)
+  
+-----------------------------------------------------------------------------------------------
+
+Read coils (0x01): 4 LEDs PA0, PA1, PA2 and PA3
+  Address 0..3, Quantity 1..4
+    Address 0: LED PA0  (1=LED on, 0=LED off)
+    Address 1: LED PA1  (1=LED on, 0=LED off)
+    Address 2: LED PA2  (1=LED on, 0=LED off)
+    Address 3: LED PA3  (1=LED on, 0=LED off)
+
+-----------------------------------------------------------------------------------------------
+
+Read discrete inputs (0x02): push buttons SW1 and SW2
+  Address 0..1, Quantity 1..2
+    Address 0: SW1  (0=not pressed, 1=pressed)
+    Address 1: SW1  (0=not pressed, 1=pressed)
+
+-----------------------------------------------------------------------------------------------
+
+Read holding registers (0x03): read back registers for controlling the 7-segment display
+  Address: 0..4
+    Address 0: last written value to hold register addresss 0, 1 or 2
+    Address 1: last written value to hold register addresss 0, 1 or 2
+    Address 2: last written value to hold register addresss 0, 1 or 2
+    Address 3: 7-segement code for digit 3 and 2 (high byte, low byte)
+    Address 4: 7-segement code for digit 1 and 0 (high byte, low byte)
+
+  7-segment code: 0x80->point, 0x01->led a, 0x02->led b, ... 0x40->led g
+
+-----------------------------------------------------------------------------------------------
+
+Read input register (0x04): Atmega I/O register, temperature sensor, version string
+  Address: 0..0x3f, 0xfff0..0xffff
+    Address 0x00 .. 0x2f -> Atmega16 I/O registers (two 8 bit registers combined to 16 bit)
+                            example 1: Atmega I/O register TCNT1 on $4c -> modbus address 0x26
+                            example 2: Atmega I/O register PINC on $33 -> high byte of modbus address 0x19
+
+    Address 0x30 .. 0x33 -> LM75A registers  (value 0x7fff -> unvalid)
+                            modbus address 0x30: value/256 -> temperature in celsius degree (two's complement)
+    Address 0xfff0..0xffff -> version string of this software -> "V1.6(10) (Jan  9 2014 07:59:39)"
+
+-----------------------------------------------------------------------------------------------
+
+Write single coil (0x05)
+  Address: 0..3, value: 0x0000 or 0xff00
+    Address 0: LED PA0  (0xff00=LED on, 0x0000=LED off)
+    Address 1: LED PA1  (0xff00=LED on, 0x0000=LED off)
+    Address 2: LED PA2  (0xff00=LED on, 0x0000=LED off)
+    Address 3: LED PA3  (0xff00=LED on, 0x0000=LED off)
+
+----------------------------------------------------------------------------------------------
+
+Write single (hold) register (0x06): set values on 7-segment display
+  Address: 0..4
+    Address 0: 7-segment set value and show in hex format ("0000" .. "FFFF")
+    Address 1: 7-segment set value and show in unsigned decimal format "   0" .. "9999")
+    Address 2: 7-segment set Value and show in signed decimal format ("-999" .. "9999")
+    Address 3: 7-segement set digit 3 and 2 (value high byte, value low byte)
+    Address 4: 7-segement set digit 1 and 0 (value high byte, value low byte)
+
+----------------------------------------------------------------------------------------------
+
+Write multiple coils (0x0f): set one or more LEDs (one bit in value for one LED)
+  Address: 0..3, Quantity 1..4 (address+quantity<=4)
+    Address 0: LED PA0  (1=LED on, 0=LED off)
+    Address 1: LED PA1  (1=LED on, 0=LED off)
+    Address 2: LED PA2  (1=LED on, 0=LED off)
+    Address 3: LED PA3  (1=LED on, 0=LED off)
+
+----------------------------------------------------------------------------------------------
+
+Write multiple (hold) registers (0x10): set values on 7-segment display
+  Address: 0..4
+    Address 0: 7-segment set value and show in hex format ("0000" .. "FFFF")
+    Address 1: 7-segment set value and show in unsigned decimal format "   0" .. "9999")
+    Address 2: 7-segment set Value and show in signed decimal format ("-999" .. "9999")
+    Address 3: 7-segement set digit 3 and 2 (value high byte, value low byte)
+    Address 4: 7-segement set digit 1 and 0 (value high byte, value low byte)
+
+----------------------------------------------------------------------------------------------
+
+
+Examples:
+
+Modbus function code 0x01 (Read coil)
+-------------------------------------
+request:  02 01 00 00 00 04 3d fa
+response: 02 01 01 00 51 cc
+
+
+Modbus function code 0x02 (Read discrete Input)
+-------------------------------------------------
+request:  02 02 00 00 00 01 b9 f9
+response: 02 02 01 00 a1 cc
+
+
+Modbus function code 0x03 (Read holding register)
+--------------------------------------------------
+request:  02 03 00 00 00 05 85 fa
+response: 02 03 0a 00 00 00 00 00 00 00 00 00 00 ff ff ff ff ff ff ff ff ff ff 3b be
+
+
+Modbus function code 0x04 (Read input register)
+example 1: read temperature from LM75A
+--------------------------------------------------
+request:  02 04 00 30 00 01 31 f6
+response: 02 04 02 17 40 00 00 44 e4
+
+
+Modbus function code 0x04 (Read input register)
+example 2: read version string
+--------------------------------------------------
+request:  02 04 ff f0 00 10 c1 d2
+response: 02 04 20 56 31 2e 36 28 31 30 29 20 28 4a 61 6e 20 20 39 20 32 30 31 34 20 30 37 3a 35 39 3a 33 39 29 00 00 a0 02 9e 00 00 80 00 00 1f 1f 00 ff f0 00 20 00 08 00 08 00 00 ff 00 00 0c 04 1e 04 1e 00 1e 73 47
+response as string: V1.6(10) (Jan  9 2014 07:59:39)
+
+
+Modbus function code 0x05 (Write single coil)
+-----------------------------------------------
+request:  02 05 00 02 ff 00 2d c9
+response: 02 05 00 02 ff 00 2d c9
+
+
+Modbus function code 0x06 (Write single (hold) register)
+----------------------------------------------------------
+request:  02 06 00 02 00 0a a8 3e
+response: 02 06 00 02 00 0a a8 3e
+
+
+Modbus function code 0x0f (Write multiple coils)
+--------------------------------------------------
+request:  02 0f 00 00 00 04 01 06 fe 81
+response: 02 0f 04 00 00 00 04 c8 3c
+
+
+Modbus function code 0x10 (Write multiple (hold) registers)
+-------------------------------------------------------------
+request:  02 10 00 01 00 02 04 ff ff ff ff 3c b3
+response: 02 10 04 00 01 00 02 1b 91
+
+
diff --git a/java_modbusmaster/build.xml b/java_modbusmaster/build.xml
new file mode 100644 (file)
index 0000000..3f800f9
--- /dev/null
@@ -0,0 +1,73 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!-- You may freely edit this file. See commented blocks below for -->
+<!-- some examples of how to customize the build. -->
+<!-- (If you delete it and reopen the project it will be recreated.) -->
+<!-- By default, only the Clean and Build commands use this build script. -->
+<!-- Commands such as Run, Debug, and Test only use this build script if -->
+<!-- the Compile on Save feature is turned off for the project. -->
+<!-- You can turn off the Compile on Save (or Deploy on Save) setting -->
+<!-- in the project's Project Properties dialog box.-->
+<project name="java_modbusmaster" default="default" basedir=".">
+    <description>Builds, tests, and runs the project java_modbusmaster.</description>
+    <import file="nbproject/build-impl.xml"/>
+    <!--
+
+    There exist several targets which are by default empty and which can be 
+    used for execution of your tasks. These targets are usually executed 
+    before and after some main targets. They are: 
+
+      -pre-init:                 called before initialization of project properties
+      -post-init:                called after initialization of project properties
+      -pre-compile:              called before javac compilation
+      -post-compile:             called after javac compilation
+      -pre-compile-single:       called before javac compilation of single file
+      -post-compile-single:      called after javac compilation of single file
+      -pre-compile-test:         called before javac compilation of JUnit tests
+      -post-compile-test:        called after javac compilation of JUnit tests
+      -pre-compile-test-single:  called before javac compilation of single JUnit test
+      -post-compile-test-single: called after javac compilation of single JUunit test
+      -pre-jar:                  called before JAR building
+      -post-jar:                 called after JAR building
+      -post-clean:               called after cleaning build products
+
+    (Targets beginning with '-' are not intended to be called on their own.)
+
+    Example of inserting an obfuscator after compilation could look like this:
+
+        <target name="-post-compile">
+            <obfuscate>
+                <fileset dir="${build.classes.dir}"/>
+            </obfuscate>
+        </target>
+
+    For list of available properties check the imported 
+    nbproject/build-impl.xml file. 
+
+
+    Another way to customize the build is by overriding existing main targets.
+    The targets of interest are: 
+
+      -init-macrodef-javac:     defines macro for javac compilation
+      -init-macrodef-junit:     defines macro for junit execution
+      -init-macrodef-debug:     defines macro for class debugging
+      -init-macrodef-java:      defines macro for class execution
+      -do-jar:                  JAR building
+      run:                      execution of project 
+      -javadoc-build:           Javadoc generation
+      test-report:              JUnit report generation
+
+    An example of overriding the target for project execution could look like this:
+
+        <target name="run" depends="java_modbusmaster-impl.jar">
+            <exec dir="bin" executable="launcher.exe">
+                <arg file="${dist.jar}"/>
+            </exec>
+        </target>
+
+    Notice that the overridden target depends on the jar target and not only on 
+    the compile target as the regular run target does. Again, for a list of available 
+    properties which you can use, check the target you are overriding in the
+    nbproject/build-impl.xml file. 
+
+    -->
+</project>
diff --git a/java_modbusmaster/manifest.mf b/java_modbusmaster/manifest.mf
new file mode 100644 (file)
index 0000000..328e8e5
--- /dev/null
@@ -0,0 +1,3 @@
+Manifest-Version: 1.0
+X-COMMENT: Main-Class will be added automatically by build
+
diff --git a/java_modbusmaster/nbproject/build-impl.xml b/java_modbusmaster/nbproject/build-impl.xml
new file mode 100644 (file)
index 0000000..c3a5098
--- /dev/null
@@ -0,0 +1,1768 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!--
+*** GENERATED FROM project.xml - DO NOT EDIT  ***
+***         EDIT ../build.xml INSTEAD         ***
+
+For the purpose of easier reading the script
+is divided into following sections:
+
+  - initialization
+  - compilation
+  - jar
+  - execution
+  - debugging
+  - javadoc
+  - test compilation
+  - test execution
+  - test debugging
+  - applet
+  - cleanup
+
+        -->
+<project xmlns:if="ant:if" xmlns:j2seproject1="http://www.netbeans.org/ns/j2se-project/1" xmlns:j2seproject3="http://www.netbeans.org/ns/j2se-project/3" xmlns:jaxrpc="http://www.netbeans.org/ns/j2se-project/jax-rpc" xmlns:unless="ant:unless" basedir=".." default="default" name="java_modbusmaster-impl">
+    <fail message="Please build using Ant 1.8.0 or higher.">
+        <condition>
+            <not>
+                <antversion atleast="1.8.0"/>
+            </not>
+        </condition>
+    </fail>
+    <target depends="test,jar,javadoc" description="Build and test whole project." name="default"/>
+    <!-- 
+                ======================
+                INITIALIZATION SECTION 
+                ======================
+            -->
+    <target name="-pre-init">
+        <!-- Empty placeholder for easier customization. -->
+        <!-- You can override this target in the ../build.xml file. -->
+    </target>
+    <target depends="-pre-init" name="-init-private">
+        <property file="nbproject/private/config.properties"/>
+        <property file="nbproject/private/configs/${config}.properties"/>
+        <property file="nbproject/private/private.properties"/>
+    </target>
+    <target depends="-pre-init,-init-private" name="-init-user">
+        <property file="${user.properties.file}"/>
+        <!-- The two properties below are usually overridden -->
+        <!-- by the active platform. Just a fallback. -->
+        <property name="default.javac.source" value="1.6"/>
+        <property name="default.javac.target" value="1.6"/>
+    </target>
+    <target depends="-pre-init,-init-private,-init-user" name="-init-project">
+        <property file="nbproject/configs/${config}.properties"/>
+        <property file="nbproject/project.properties"/>
+    </target>
+    <target name="-init-modules-supported">
+        <condition property="modules.supported.internal" value="true">
+            <not>
+                <matches pattern="1\.[0-8](\..*)?" string="${javac.source}"/>
+            </not>
+        </condition>
+    </target>
+    <target depends="-init-modules-supported" if="modules.supported.internal" name="-init-macrodef-modulename">
+        <macrodef name="modulename" uri="http://www.netbeans.org/ns/j2se-project/3">
+            <attribute name="property"/>
+            <attribute name="sourcepath"/>
+            <sequential>
+                <loadresource property="@{property}" quiet="true">
+                    <javaresource classpath="@{sourcepath}" name="module-info.java" parentFirst="false"/>
+                    <filterchain>
+                        <stripjavacomments/>
+                        <linecontainsregexp>
+                            <regexp pattern="module .* \{"/>
+                        </linecontainsregexp>
+                        <tokenfilter>
+                            <linetokenizer/>
+                            <replaceregex flags="s" pattern="(\s*module\s+)(\S*)(\s*\{.*)" replace="\2"/>
+                        </tokenfilter>
+                        <striplinebreaks/>
+                    </filterchain>
+                </loadresource>
+            </sequential>
+        </macrodef>
+    </target>
+    <target depends="-init-modules-supported,-init-macrodef-modulename" if="modules.supported.internal" name="-init-source-module-properties">
+        <fail message="Java 9 support requires Ant 1.10.0 or higher.">
+            <condition>
+                <not>
+                    <antversion atleast="1.10.0"/>
+                </not>
+            </condition>
+        </fail>
+        <j2seproject3:modulename property="module.name" sourcepath="${src.dir}"/>
+        <condition property="named.module.internal">
+            <and>
+                <isset property="module.name"/>
+                <length length="0" string="${module.name}" when="greater"/>
+            </and>
+        </condition>
+        <condition property="unnamed.module.internal">
+            <not>
+                <isset property="named.module.internal"/>
+            </not>
+        </condition>
+        <property name="javac.modulepath" value=""/>
+        <property name="run.modulepath" value="${javac.modulepath}"/>
+        <property name="module.build.classes.dir" value="${build.classes.dir}"/>
+        <property name="debug.modulepath" value="${run.modulepath}"/>
+        <property name="javac.upgrademodulepath" value=""/>
+        <property name="run.upgrademodulepath" value="${javac.upgrademodulepath}"/>
+        <condition else="" property="javac.systemmodulepath.cmd.line.arg" value="--system '${javac.systemmodulepath}'">
+            <and>
+                <isset property="javac.systemmodulepath"/>
+                <length length="0" string="${javac.systemmodulepath}" when="greater"/>
+            </and>
+        </condition>
+        <property name="dist.jlink.dir" value="${dist.dir}/jlink"/>
+        <property name="dist.jlink.output" value="${dist.jlink.dir}/${application.title}"/>
+        <property name="module.name" value=""/>
+    </target>
+    <target depends="-pre-init,-init-private,-init-user,-init-project,-init-macrodef-property,-init-modules-supported" name="-do-init">
+        <property name="platform.java" value="${java.home}/bin/java"/>
+        <available file="${manifest.file}" property="manifest.available"/>
+        <condition property="splashscreen.available">
+            <and>
+                <not>
+                    <equals arg1="${application.splash}" arg2="" trim="true"/>
+                </not>
+                <available file="${application.splash}"/>
+            </and>
+        </condition>
+        <condition property="main.class.available">
+            <and>
+                <isset property="main.class"/>
+                <not>
+                    <equals arg1="${main.class}" arg2="" trim="true"/>
+                </not>
+            </and>
+        </condition>
+        <condition property="profile.available">
+            <and>
+                <isset property="javac.profile"/>
+                <length length="0" string="${javac.profile}" when="greater"/>
+                <not>
+                    <matches pattern="1\.[0-7](\..*)?" string="${javac.source}"/>
+                </not>
+            </and>
+        </condition>
+        <condition property="do.archive">
+            <or>
+                <not>
+                    <istrue value="${jar.archive.disabled}"/>
+                </not>
+                <istrue value="${not.archive.disabled}"/>
+            </or>
+        </condition>
+        <condition property="do.mkdist">
+            <and>
+                <isset property="do.archive"/>
+                <isset property="libs.CopyLibs.classpath"/>
+                <not>
+                    <istrue value="${mkdist.disabled}"/>
+                </not>
+                <not>
+                    <istrue value="${modules.supported.internal}"/>
+                </not>
+            </and>
+        </condition>
+        <condition property="do.archive+manifest.available">
+            <and>
+                <isset property="manifest.available"/>
+                <istrue value="${do.archive}"/>
+            </and>
+        </condition>
+        <condition property="do.archive+main.class.available">
+            <and>
+                <isset property="main.class.available"/>
+                <istrue value="${do.archive}"/>
+            </and>
+        </condition>
+        <condition property="do.archive+splashscreen.available">
+            <and>
+                <isset property="splashscreen.available"/>
+                <istrue value="${do.archive}"/>
+            </and>
+        </condition>
+        <condition property="do.archive+profile.available">
+            <and>
+                <isset property="profile.available"/>
+                <istrue value="${do.archive}"/>
+            </and>
+        </condition>
+        <condition property="have.tests">
+            <or>
+                <available file="${test.src.dir}"/>
+            </or>
+        </condition>
+        <condition property="have.sources">
+            <or>
+                <available file="${src.dir}"/>
+            </or>
+        </condition>
+        <condition property="netbeans.home+have.tests">
+            <and>
+                <isset property="netbeans.home"/>
+                <isset property="have.tests"/>
+            </and>
+        </condition>
+        <condition property="no.javadoc.preview">
+            <and>
+                <isset property="javadoc.preview"/>
+                <isfalse value="${javadoc.preview}"/>
+            </and>
+        </condition>
+        <property name="run.jvmargs" value=""/>
+        <property name="run.jvmargs.ide" value=""/>
+        <property name="javac.compilerargs" value=""/>
+        <property name="work.dir" value="${basedir}"/>
+        <condition property="no.deps">
+            <and>
+                <istrue value="${no.dependencies}"/>
+            </and>
+        </condition>
+        <property name="javac.debug" value="true"/>
+        <property name="javadoc.preview" value="true"/>
+        <property name="application.args" value=""/>
+        <property name="source.encoding" value="${file.encoding}"/>
+        <property name="runtime.encoding" value="${source.encoding}"/>
+        <property name="manifest.encoding" value="${source.encoding}"/>
+        <condition property="javadoc.encoding.used" value="${javadoc.encoding}">
+            <and>
+                <isset property="javadoc.encoding"/>
+                <not>
+                    <equals arg1="${javadoc.encoding}" arg2=""/>
+                </not>
+            </and>
+        </condition>
+        <property name="javadoc.encoding.used" value="${source.encoding}"/>
+        <property name="includes" value="**"/>
+        <property name="excludes" value=""/>
+        <property name="do.depend" value="false"/>
+        <condition property="do.depend.true">
+            <istrue value="${do.depend}"/>
+        </condition>
+        <path id="endorsed.classpath.path" path="${endorsed.classpath}"/>
+        <condition else="" property="endorsed.classpath.cmd.line.arg" value="-Xbootclasspath/p:'${toString:endorsed.classpath.path}'">
+            <and>
+                <isset property="endorsed.classpath"/>
+                <not>
+                    <equals arg1="${endorsed.classpath}" arg2="" trim="true"/>
+                </not>
+            </and>
+        </condition>
+        <condition else="" property="javac.profile.cmd.line.arg" value="-profile ${javac.profile}">
+            <isset property="profile.available"/>
+        </condition>
+        <condition else="false" property="jdkBug6558476">
+            <and>
+                <matches pattern="1\.[56]" string="${java.specification.version}"/>
+                <not>
+                    <os family="unix"/>
+                </not>
+            </and>
+        </condition>
+        <condition else="false" property="javac.fork">
+            <or>
+                <istrue value="${jdkBug6558476}"/>
+                <istrue value="${javac.external.vm}"/>
+            </or>
+        </condition>
+        <property name="jar.index" value="false"/>
+        <property name="jar.index.metainf" value="${jar.index}"/>
+        <property name="copylibs.rebase" value="true"/>
+        <available file="${meta.inf.dir}/persistence.xml" property="has.persistence.xml"/>
+        <condition property="junit.available">
+            <or>
+                <available classname="org.junit.Test" classpath="${run.test.classpath}"/>
+                <available classname="junit.framework.Test" classpath="${run.test.classpath}"/>
+            </or>
+        </condition>
+        <condition property="testng.available">
+            <available classname="org.testng.annotations.Test" classpath="${run.test.classpath}"/>
+        </condition>
+        <condition property="junit+testng.available">
+            <and>
+                <istrue value="${junit.available}"/>
+                <istrue value="${testng.available}"/>
+            </and>
+        </condition>
+        <condition else="testng" property="testng.mode" value="mixed">
+            <istrue value="${junit+testng.available}"/>
+        </condition>
+        <condition else="" property="testng.debug.mode" value="-mixed">
+            <istrue value="${junit+testng.available}"/>
+        </condition>
+        <property name="java.failonerror" value="true"/>
+    </target>
+    <target name="-post-init">
+        <!-- Empty placeholder for easier customization. -->
+        <!-- You can override this target in the ../build.xml file. -->
+    </target>
+    <target depends="-pre-init,-init-private,-init-user,-init-project,-do-init" name="-init-check">
+        <fail unless="src.dir">Must set src.dir</fail>
+        <fail unless="test.src.dir">Must set test.src.dir</fail>
+        <fail unless="build.dir">Must set build.dir</fail>
+        <fail unless="dist.dir">Must set dist.dir</fail>
+        <fail unless="build.classes.dir">Must set build.classes.dir</fail>
+        <fail unless="dist.javadoc.dir">Must set dist.javadoc.dir</fail>
+        <fail unless="build.test.classes.dir">Must set build.test.classes.dir</fail>
+        <fail unless="build.test.results.dir">Must set build.test.results.dir</fail>
+        <fail unless="build.classes.excludes">Must set build.classes.excludes</fail>
+        <fail unless="dist.jar">Must set dist.jar</fail>
+    </target>
+    <target name="-init-macrodef-property">
+        <macrodef name="property" uri="http://www.netbeans.org/ns/j2se-project/1">
+            <attribute name="name"/>
+            <attribute name="value"/>
+            <sequential>
+                <property name="@{name}" value="${@{value}}"/>
+            </sequential>
+        </macrodef>
+    </target>
+    <target depends="-init-ap-cmdline-properties,-init-source-module-properties" if="modules.supported.internal" name="-init-macrodef-javac-with-module">
+        <macrodef name="javac" uri="http://www.netbeans.org/ns/j2se-project/3">
+            <attribute default="${src.dir}" name="srcdir"/>
+            <attribute default="${build.classes.dir}" name="destdir"/>
+            <attribute default="${javac.classpath}" name="classpath"/>
+            <attribute default="${javac.modulepath}" name="modulepath"/>
+            <attribute default="${javac.upgrademodulepath}" name="upgrademodulepath"/>
+            <attribute default="${javac.processorpath}" name="processorpath"/>
+            <attribute default="${javac.processormodulepath}" name="processormodulepath"/>
+            <attribute default="${build.generated.sources.dir}/ap-source-output" name="apgeneratedsrcdir"/>
+            <attribute default="${includes}" name="includes"/>
+            <attribute default="${excludes}" name="excludes"/>
+            <attribute default="${javac.debug}" name="debug"/>
+            <attribute default="${empty.dir}" name="sourcepath" unless:set="named.module.internal"/>
+            <attribute default="${src.dir}" if:set="named.module.internal" name="sourcepath"/>
+            <attribute default="${empty.dir}" name="gensrcdir"/>
+            <element name="customize" optional="true"/>
+            <sequential>
+                <condition property="warn.excludes.internal">
+                    <and>
+                        <isset property="named.module.internal"/>
+                        <length length="0" string="@{excludes}" trim="true" when="greater"/>
+                    </and>
+                </condition>
+                <echo if:set="warn.excludes.internal" level="warning" message="The javac excludes are not supported in the JDK 9 Named Module."/>
+                <property location="${build.dir}/empty" name="empty.dir"/>
+                <mkdir dir="${empty.dir}"/>
+                <mkdir dir="@{apgeneratedsrcdir}"/>
+                <condition property="processormodulepath.set">
+                    <resourcecount count="0" when="greater">
+                        <path>
+                            <pathelement path="@{processormodulepath}"/>
+                        </path>
+                    </resourcecount>
+                </condition>
+                <javac debug="@{debug}" deprecation="${javac.deprecation}" destdir="@{destdir}" encoding="${source.encoding}" excludes="@{excludes}" fork="${javac.fork}" includeantruntime="false" includes="@{includes}" source="${javac.source}" sourcepath="@{sourcepath}" srcdir="@{srcdir}" target="${javac.target}" tempdir="${java.io.tmpdir}">
+                    <src>
+                        <dirset dir="@{gensrcdir}" erroronmissingdir="false">
+                            <include name="*"/>
+                        </dirset>
+                    </src>
+                    <classpath>
+                        <path path="@{classpath}"/>
+                    </classpath>
+                    <modulepath>
+                        <path path="@{modulepath}"/>
+                    </modulepath>
+                    <upgrademodulepath>
+                        <path path="@{upgrademodulepath}"/>
+                    </upgrademodulepath>
+                    <compilerarg line="${javac.systemmodulepath.cmd.line.arg}"/>
+                    <compilerarg line="${javac.profile.cmd.line.arg}"/>
+                    <compilerarg line="${javac.compilerargs}"/>
+                    <compilerarg if:set="processormodulepath.set" value="--processor-module-path"/>
+                    <compilerarg if:set="processormodulepath.set" path="@{processormodulepath}"/>
+                    <compilerarg unless:set="processormodulepath.set" value="-processorpath"/>
+                    <compilerarg path="@{processorpath}:${empty.dir}" unless:set="processormodulepath.set"/>
+                    <compilerarg line="${ap.processors.internal}"/>
+                    <compilerarg line="${annotation.processing.processor.options}"/>
+                    <compilerarg value="-s"/>
+                    <compilerarg path="@{apgeneratedsrcdir}"/>
+                    <compilerarg line="${ap.proc.none.internal}"/>
+                    <customize/>
+                </javac>
+            </sequential>
+        </macrodef>
+    </target>
+    <target depends="-init-ap-cmdline-properties,-init-source-module-properties" if="ap.supported.internal" name="-init-macrodef-javac-with-processors" unless="modules.supported.internal">
+        <macrodef name="javac" uri="http://www.netbeans.org/ns/j2se-project/3">
+            <attribute default="${src.dir}" name="srcdir"/>
+            <attribute default="${build.classes.dir}" name="destdir"/>
+            <attribute default="${javac.classpath}" name="classpath"/>
+            <attribute default="${javac.modulepath}" name="modulepath"/>
+            <attribute default="${javac.upgrademodulepath}" name="upgrademodulepath"/>
+            <attribute default="${javac.processorpath}" name="processorpath"/>
+            <attribute default="${build.generated.sources.dir}/ap-source-output" name="apgeneratedsrcdir"/>
+            <attribute default="${includes}" name="includes"/>
+            <attribute default="${excludes}" name="excludes"/>
+            <attribute default="${javac.debug}" name="debug"/>
+            <attribute default="${empty.dir}" name="sourcepath"/>
+            <attribute default="${empty.dir}" name="gensrcdir"/>
+            <element name="customize" optional="true"/>
+            <sequential>
+                <property location="${build.dir}/empty" name="empty.dir"/>
+                <mkdir dir="${empty.dir}"/>
+                <mkdir dir="@{apgeneratedsrcdir}"/>
+                <javac debug="@{debug}" deprecation="${javac.deprecation}" destdir="@{destdir}" encoding="${source.encoding}" excludes="@{excludes}" fork="${javac.fork}" includeantruntime="false" includes="@{includes}" source="${javac.source}" sourcepath="@{sourcepath}" srcdir="@{srcdir}" target="${javac.target}" tempdir="${java.io.tmpdir}">
+                    <src>
+                        <dirset dir="@{gensrcdir}" erroronmissingdir="false">
+                            <include name="*"/>
+                        </dirset>
+                    </src>
+                    <classpath>
+                        <path path="@{classpath}"/>
+                    </classpath>
+                    <compilerarg line="${endorsed.classpath.cmd.line.arg}"/>
+                    <compilerarg line="${javac.profile.cmd.line.arg}"/>
+                    <compilerarg line="${javac.compilerargs}"/>
+                    <compilerarg value="-processorpath"/>
+                    <compilerarg path="@{processorpath}:${empty.dir}"/>
+                    <compilerarg line="${ap.processors.internal}"/>
+                    <compilerarg line="${annotation.processing.processor.options}"/>
+                    <compilerarg value="-s"/>
+                    <compilerarg path="@{apgeneratedsrcdir}"/>
+                    <compilerarg line="${ap.proc.none.internal}"/>
+                    <customize/>
+                </javac>
+            </sequential>
+        </macrodef>
+    </target>
+    <target depends="-init-ap-cmdline-properties,-init-source-module-properties" name="-init-macrodef-javac-without-processors" unless="ap.supported.internal">
+        <macrodef name="javac" uri="http://www.netbeans.org/ns/j2se-project/3">
+            <attribute default="${src.dir}" name="srcdir"/>
+            <attribute default="${build.classes.dir}" name="destdir"/>
+            <attribute default="${javac.classpath}" name="classpath"/>
+            <attribute default="${javac.modulepath}" name="modulepath"/>
+            <attribute default="${javac.upgrademodulepath}" name="upgrademodulepath"/>
+            <attribute default="${javac.processorpath}" name="processorpath"/>
+            <attribute default="${build.generated.sources.dir}/ap-source-output" name="apgeneratedsrcdir"/>
+            <attribute default="${includes}" name="includes"/>
+            <attribute default="${excludes}" name="excludes"/>
+            <attribute default="${javac.debug}" name="debug"/>
+            <attribute default="${empty.dir}" name="sourcepath"/>
+            <attribute default="${empty.dir}" name="gensrcdir"/>
+            <element name="customize" optional="true"/>
+            <sequential>
+                <property location="${build.dir}/empty" name="empty.dir"/>
+                <mkdir dir="${empty.dir}"/>
+                <javac debug="@{debug}" deprecation="${javac.deprecation}" destdir="@{destdir}" encoding="${source.encoding}" excludes="@{excludes}" fork="${javac.fork}" includeantruntime="false" includes="@{includes}" source="${javac.source}" sourcepath="@{sourcepath}" srcdir="@{srcdir}" target="${javac.target}" tempdir="${java.io.tmpdir}">
+                    <src>
+                        <dirset dir="@{gensrcdir}" erroronmissingdir="false">
+                            <include name="*"/>
+                        </dirset>
+                    </src>
+                    <classpath>
+                        <path path="@{classpath}"/>
+                    </classpath>
+                    <compilerarg line="${endorsed.classpath.cmd.line.arg}"/>
+                    <compilerarg line="${javac.profile.cmd.line.arg}"/>
+                    <compilerarg line="${javac.compilerargs}"/>
+                    <customize/>
+                </javac>
+            </sequential>
+        </macrodef>
+    </target>
+    <target depends="-init-macrodef-javac-with-module,-init-macrodef-javac-with-processors,-init-macrodef-javac-without-processors" name="-init-macrodef-javac">
+        <macrodef name="depend" uri="http://www.netbeans.org/ns/j2se-project/3">
+            <attribute default="${src.dir}" name="srcdir"/>
+            <attribute default="${build.classes.dir}" name="destdir"/>
+            <attribute default="${javac.classpath}" name="classpath"/>
+            <sequential>
+                <depend cache="${build.dir}/depcache" destdir="@{destdir}" excludes="${excludes}" includes="${includes}" srcdir="@{srcdir}">
+                    <classpath>
+                        <path path="@{classpath}"/>
+                    </classpath>
+                </depend>
+            </sequential>
+        </macrodef>
+        <macrodef name="force-recompile" uri="http://www.netbeans.org/ns/j2se-project/3">
+            <attribute default="${build.classes.dir}" name="destdir"/>
+            <sequential>
+                <fail unless="javac.includes">Must set javac.includes</fail>
+                <pathconvert pathsep="${line.separator}" property="javac.includes.binary">
+                    <path>
+                        <filelist dir="@{destdir}" files="${javac.includes}"/>
+                    </path>
+                    <globmapper from="*.java" to="*.class"/>
+                </pathconvert>
+                <tempfile deleteonexit="true" property="javac.includesfile.binary"/>
+                <echo file="${javac.includesfile.binary}" message="${javac.includes.binary}"/>
+                <delete>
+                    <files includesfile="${javac.includesfile.binary}"/>
+                </delete>
+                <delete>
+                    <fileset file="${javac.includesfile.binary}"/>
+                </delete>
+            </sequential>
+        </macrodef>
+    </target>
+    <target if="${junit.available}" name="-init-macrodef-junit-init">
+        <condition else="false" property="nb.junit.batch" value="true">
+            <and>
+                <istrue value="${junit.available}"/>
+                <not>
+                    <isset property="test.method"/>
+                </not>
+            </and>
+        </condition>
+        <condition else="false" property="nb.junit.single" value="true">
+            <and>
+                <istrue value="${junit.available}"/>
+                <isset property="test.method"/>
+            </and>
+        </condition>
+    </target>
+    <target name="-init-test-properties">
+        <property name="test.binaryincludes" value="&lt;nothing&gt;"/>
+        <property name="test.binarytestincludes" value=""/>
+        <property name="test.binaryexcludes" value=""/>
+    </target>
+    <target depends="-init-modules-supported" if="modules.supported.internal" name="-init-macrodef-junit-prototype-with-module">
+        <macrodef name="junit-prototype" uri="http://www.netbeans.org/ns/j2se-project/3">
+            <attribute default="${includes}" name="includes"/>
+            <attribute default="${excludes}" name="excludes"/>
+            <element name="customizePrototype" optional="true"/>
+            <sequential>
+                <property name="junit.forkmode" value="perTest"/>
+                <junit dir="${work.dir}" errorproperty="tests.failed" failureproperty="tests.failed" fork="true" forkmode="${junit.forkmode}" showoutput="true" tempdir="${build.dir}">
+                    <syspropertyset>
+                        <propertyref prefix="test-sys-prop."/>
+                        <mapper from="test-sys-prop.*" to="*" type="glob"/>
+                    </syspropertyset>
+                    <classpath>
+                        <path path="${run.test.classpath}"/>
+                    </classpath>
+                    <modulepath>
+                        <path path="${run.test.modulepath}"/>
+                    </modulepath>
+                    <formatter type="brief" usefile="false"/>
+                    <formatter type="xml"/>
+                    <jvmarg line="${endorsed.classpath.cmd.line.arg}"/>
+                    <jvmarg value="-ea"/>
+                    <jvmarg line="${run.test.jvmargs}"/>
+                    <customizePrototype/>
+                </junit>
+            </sequential>
+        </macrodef>
+    </target>
+    <target depends="-init-modules-supported" name="-init-macrodef-junit-prototype-without-module" unless="modules.supported.internal">
+        <macrodef name="junit-prototype" uri="http://www.netbeans.org/ns/j2se-project/3">
+            <attribute default="${includes}" name="includes"/>
+            <attribute default="${excludes}" name="excludes"/>
+            <element name="customizePrototype" optional="true"/>
+            <sequential>
+                <property name="junit.forkmode" value="perTest"/>
+                <junit dir="${work.dir}" errorproperty="tests.failed" failureproperty="tests.failed" fork="true" forkmode="${junit.forkmode}" showoutput="true" tempdir="${build.dir}">
+                    <syspropertyset>
+                        <propertyref prefix="test-sys-prop."/>
+                        <mapper from="test-sys-prop.*" to="*" type="glob"/>
+                    </syspropertyset>
+                    <classpath>
+                        <path path="${run.test.classpath}"/>
+                    </classpath>
+                    <formatter type="brief" usefile="false"/>
+                    <formatter type="xml"/>
+                    <jvmarg line="${endorsed.classpath.cmd.line.arg}"/>
+                    <jvmarg value="-ea"/>
+                    <customizePrototype/>
+                </junit>
+            </sequential>
+        </macrodef>
+    </target>
+    <target depends="-init-test-properties,-init-macrodef-junit-prototype-with-module,-init-macrodef-junit-prototype-without-module" if="${nb.junit.single}" name="-init-macrodef-junit-single" unless="${nb.junit.batch}">
+        <macrodef name="junit" uri="http://www.netbeans.org/ns/j2se-project/3">
+            <attribute default="${includes}" name="includes"/>
+            <attribute default="${excludes}" name="excludes"/>
+            <attribute default="**" name="testincludes"/>
+            <attribute default="" name="testmethods"/>
+            <element name="customize" optional="true"/>
+            <sequential>
+                <j2seproject3:junit-prototype>
+                    <customizePrototype>
+                        <test methods="@{testmethods}" name="@{testincludes}" todir="${build.test.results.dir}"/>
+                        <customize/>
+                    </customizePrototype>
+                </j2seproject3:junit-prototype>
+            </sequential>
+        </macrodef>
+    </target>
+    <target depends="-init-test-properties,-init-macrodef-junit-prototype-with-module,-init-macrodef-junit-prototype-without-module" if="${nb.junit.batch}" name="-init-macrodef-junit-batch" unless="${nb.junit.single}">
+        <macrodef name="junit" uri="http://www.netbeans.org/ns/j2se-project/3">
+            <attribute default="${includes}" name="includes"/>
+            <attribute default="${excludes}" name="excludes"/>
+            <attribute default="**" name="testincludes"/>
+            <attribute default="" name="testmethods"/>
+            <element name="customize" optional="true"/>
+            <sequential>
+                <j2seproject3:junit-prototype>
+                    <customizePrototype>
+                        <batchtest todir="${build.test.results.dir}">
+                            <fileset dir="${test.src.dir}" excludes="@{excludes},${excludes}" includes="@{includes}">
+                                <filename name="@{testincludes}"/>
+                            </fileset>
+                            <fileset dir="${build.test.classes.dir}" excludes="@{excludes},${excludes},${test.binaryexcludes}" includes="${test.binaryincludes}">
+                                <filename name="${test.binarytestincludes}"/>
+                            </fileset>
+                        </batchtest>
+                        <customize/>
+                    </customizePrototype>
+                </j2seproject3:junit-prototype>
+            </sequential>
+        </macrodef>
+    </target>
+    <target depends="-init-macrodef-junit-init,-init-macrodef-junit-single, -init-macrodef-junit-batch" if="${junit.available}" name="-init-macrodef-junit"/>
+    <target if="${testng.available}" name="-init-macrodef-testng">
+        <macrodef name="testng" uri="http://www.netbeans.org/ns/j2se-project/3">
+            <attribute default="${includes}" name="includes"/>
+            <attribute default="${excludes}" name="excludes"/>
+            <attribute default="**" name="testincludes"/>
+            <attribute default="" name="testmethods"/>
+            <element name="customize" optional="true"/>
+            <sequential>
+                <condition else="" property="testng.methods.arg" value="@{testincludes}.@{testmethods}">
+                    <isset property="test.method"/>
+                </condition>
+                <union id="test.set">
+                    <fileset dir="${test.src.dir}" excludes="@{excludes},**/*.xml,${excludes}" includes="@{includes}">
+                        <filename name="@{testincludes}"/>
+                    </fileset>
+                </union>
+                <taskdef classname="org.testng.TestNGAntTask" classpath="${run.test.classpath}" name="testng"/>
+                <testng classfilesetref="test.set" failureProperty="tests.failed" listeners="org.testng.reporters.VerboseReporter" methods="${testng.methods.arg}" mode="${testng.mode}" outputdir="${build.test.results.dir}" suitename="java_modbusmaster" testname="TestNG tests" workingDir="${work.dir}">
+                    <xmlfileset dir="${build.test.classes.dir}" includes="@{testincludes}"/>
+                    <propertyset>
+                        <propertyref prefix="test-sys-prop."/>
+                        <mapper from="test-sys-prop.*" to="*" type="glob"/>
+                    </propertyset>
+                    <classpath>
+                        <path path="${run.test.classpath}"/>
+                    </classpath>
+                    <jvmarg line="${endorsed.classpath.cmd.line.arg}"/>
+                    <customize/>
+                </testng>
+            </sequential>
+        </macrodef>
+    </target>
+    <target name="-init-macrodef-test-impl">
+        <macrodef name="test-impl" uri="http://www.netbeans.org/ns/j2se-project/3">
+            <attribute default="${includes}" name="includes"/>
+            <attribute default="${excludes}" name="excludes"/>
+            <attribute default="**" name="testincludes"/>
+            <attribute default="" name="testmethods"/>
+            <element implicit="true" name="customize" optional="true"/>
+            <sequential>
+                <echo>No tests executed.</echo>
+            </sequential>
+        </macrodef>
+    </target>
+    <target depends="-init-macrodef-junit" if="${junit.available}" name="-init-macrodef-junit-impl">
+        <macrodef name="test-impl" uri="http://www.netbeans.org/ns/j2se-project/3">
+            <attribute default="${includes}" name="includes"/>
+            <attribute default="${excludes}" name="excludes"/>
+            <attribute default="**" name="testincludes"/>
+            <attribute default="" name="testmethods"/>
+            <element implicit="true" name="customize" optional="true"/>
+            <sequential>
+                <j2seproject3:junit excludes="@{excludes}" includes="@{includes}" testincludes="@{testincludes}" testmethods="@{testmethods}">
+                    <customize/>
+                </j2seproject3:junit>
+            </sequential>
+        </macrodef>
+    </target>
+    <target depends="-init-macrodef-testng" if="${testng.available}" name="-init-macrodef-testng-impl">
+        <macrodef name="test-impl" uri="http://www.netbeans.org/ns/j2se-project/3">
+            <attribute default="${includes}" name="includes"/>
+            <attribute default="${excludes}" name="excludes"/>
+            <attribute default="**" name="testincludes"/>
+            <attribute default="" name="testmethods"/>
+            <element implicit="true" name="customize" optional="true"/>
+            <sequential>
+                <j2seproject3:testng excludes="@{excludes}" includes="@{includes}" testincludes="@{testincludes}" testmethods="@{testmethods}">
+                    <customize/>
+                </j2seproject3:testng>
+            </sequential>
+        </macrodef>
+    </target>
+    <target depends="-init-macrodef-test-impl,-init-macrodef-junit-impl,-init-macrodef-testng-impl" name="-init-macrodef-test">
+        <macrodef name="test" uri="http://www.netbeans.org/ns/j2se-project/3">
+            <attribute default="${includes}" name="includes"/>
+            <attribute default="${excludes}" name="excludes"/>
+            <attribute default="**" name="testincludes"/>
+            <attribute default="" name="testmethods"/>
+            <sequential>
+                <j2seproject3:test-impl excludes="@{excludes}" includes="@{includes}" testincludes="@{testincludes}" testmethods="@{testmethods}">
+                    <customize>
+                        <jvmarg line="${run.jvmargs}"/>
+                        <jvmarg line="${run.jvmargs.ide}"/>
+                    </customize>
+                </j2seproject3:test-impl>
+            </sequential>
+        </macrodef>
+    </target>
+    <target depends="-init-macrodef-junit" if="${junit.available}" name="-init-macrodef-junit-debug-impl">
+        <macrodef name="test-debug-impl" uri="http://www.netbeans.org/ns/j2se-project/3">
+            <attribute default="${includes}" name="includes"/>
+            <attribute default="${excludes}" name="excludes"/>
+            <attribute default="**" name="testincludes"/>
+            <attribute default="" name="testmethods"/>
+            <element name="customizeDebuggee" optional="true"/>
+            <sequential>
+                <j2seproject3:junit excludes="@{excludes}" includes="@{includes}" testincludes="@{testincludes}" testmethods="@{testmethods}">
+                    <customize>
+                        <jvmarg value="-agentlib:jdwp=transport=${debug-transport},address=${jpda.address}"/>
+                        <customizeDebuggee/>
+                    </customize>
+                </j2seproject3:junit>
+            </sequential>
+        </macrodef>
+    </target>
+    <target if="${testng.available}" name="-init-macrodef-testng-debug">
+        <macrodef name="testng-debug" uri="http://www.netbeans.org/ns/j2se-project/3">
+            <attribute default="${main.class}" name="testClass"/>
+            <attribute default="" name="testMethod"/>
+            <element name="customize2" optional="true"/>
+            <sequential>
+                <condition else="-testclass @{testClass}" property="test.class.or.method" value="-methods @{testClass}.@{testMethod}">
+                    <isset property="test.method"/>
+                </condition>
+                <condition else="-suitename java_modbusmaster -testname @{testClass} ${test.class.or.method}" property="testng.cmd.args" value="@{testClass}">
+                    <matches pattern=".*\.xml" string="@{testClass}"/>
+                </condition>
+                <delete dir="${build.test.results.dir}" quiet="true"/>
+                <mkdir dir="${build.test.results.dir}"/>
+                <j2seproject3:debug classname="org.testng.TestNG" classpath="${debug.test.classpath}">
+                    <customizeDebuggee>
+                        <customize2/>
+                        <jvmarg value="-ea"/>
+                        <arg line="${testng.debug.mode}"/>
+                        <arg line="-d ${build.test.results.dir}"/>
+                        <arg line="-listener org.testng.reporters.VerboseReporter"/>
+                        <arg line="${testng.cmd.args}"/>
+                    </customizeDebuggee>
+                </j2seproject3:debug>
+            </sequential>
+        </macrodef>
+    </target>
+    <target depends="-init-macrodef-testng-debug" if="${testng.available}" name="-init-macrodef-testng-debug-impl">
+        <macrodef name="testng-debug-impl" uri="http://www.netbeans.org/ns/j2se-project/3">
+            <attribute default="${main.class}" name="testClass"/>
+            <attribute default="" name="testMethod"/>
+            <element implicit="true" name="customize2" optional="true"/>
+            <sequential>
+                <j2seproject3:testng-debug testClass="@{testClass}" testMethod="@{testMethod}">
+                    <customize2/>
+                </j2seproject3:testng-debug>
+            </sequential>
+        </macrodef>
+    </target>
+    <target depends="-init-macrodef-junit-debug-impl" if="${junit.available}" name="-init-macrodef-test-debug-junit">
+        <macrodef name="test-debug" uri="http://www.netbeans.org/ns/j2se-project/3">
+            <attribute default="${includes}" name="includes"/>
+            <attribute default="${excludes}" name="excludes"/>
+            <attribute default="**" name="testincludes"/>
+            <attribute default="" name="testmethods"/>
+            <attribute default="${main.class}" name="testClass"/>
+            <attribute default="" name="testMethod"/>
+            <sequential>
+                <j2seproject3:test-debug-impl excludes="@{excludes}" includes="@{includes}" testincludes="@{testincludes}" testmethods="@{testmethods}">
+                    <customizeDebuggee>
+                        <jvmarg line="${run.jvmargs}"/>
+                        <jvmarg line="${run.jvmargs.ide}"/>
+                    </customizeDebuggee>
+                </j2seproject3:test-debug-impl>
+            </sequential>
+        </macrodef>
+    </target>
+    <target depends="-init-macrodef-testng-debug-impl" if="${testng.available}" name="-init-macrodef-test-debug-testng">
+        <macrodef name="test-debug" uri="http://www.netbeans.org/ns/j2se-project/3">
+            <attribute default="${includes}" name="includes"/>
+            <attribute default="${excludes}" name="excludes"/>
+            <attribute default="**" name="testincludes"/>
+            <attribute default="" name="testmethods"/>
+            <attribute default="${main.class}" name="testClass"/>
+            <attribute default="" name="testMethod"/>
+            <sequential>
+                <j2seproject3:testng-debug-impl testClass="@{testClass}" testMethod="@{testMethod}">
+                    <customize2>
+                        <syspropertyset>
+                            <propertyref prefix="test-sys-prop."/>
+                            <mapper from="test-sys-prop.*" to="*" type="glob"/>
+                        </syspropertyset>
+                    </customize2>
+                </j2seproject3:testng-debug-impl>
+            </sequential>
+        </macrodef>
+    </target>
+    <target depends="-init-macrodef-test-debug-junit,-init-macrodef-test-debug-testng" name="-init-macrodef-test-debug"/>
+    <!--
+                pre NB7.2 profiling section; consider it deprecated
+            -->
+    <target depends="-profile-pre-init, init, -profile-post-init, -profile-init-macrodef-profile, -profile-init-check" if="profiler.info.jvmargs.agent" name="profile-init"/>
+    <target if="profiler.info.jvmargs.agent" name="-profile-pre-init">
+        <!-- Empty placeholder for easier customization. -->
+        <!-- You can override this target in the ../build.xml file. -->
+    </target>
+    <target if="profiler.info.jvmargs.agent" name="-profile-post-init">
+        <!-- Empty placeholder for easier customization. -->
+        <!-- You can override this target in the ../build.xml file. -->
+    </target>
+    <target if="profiler.info.jvmargs.agent" name="-profile-init-macrodef-profile">
+        <macrodef name="resolve">
+            <attribute name="name"/>
+            <attribute name="value"/>
+            <sequential>
+                <property name="@{name}" value="${env.@{value}}"/>
+            </sequential>
+        </macrodef>
+        <macrodef name="profile">
+            <attribute default="${main.class}" name="classname"/>
+            <element name="customize" optional="true"/>
+            <sequential>
+                <property environment="env"/>
+                <resolve name="profiler.current.path" value="${profiler.info.pathvar}"/>
+                <java classname="@{classname}" dir="${profiler.info.dir}" failonerror="${java.failonerror}" fork="true" jvm="${profiler.info.jvm}">
+                    <jvmarg line="${endorsed.classpath.cmd.line.arg}"/>
+                    <jvmarg value="${profiler.info.jvmargs.agent}"/>
+                    <jvmarg line="${profiler.info.jvmargs}"/>
+                    <env key="${profiler.info.pathvar}" path="${profiler.info.agentpath}:${profiler.current.path}"/>
+                    <arg line="${application.args}"/>
+                    <classpath>
+                        <path path="${run.classpath}"/>
+                    </classpath>
+                    <syspropertyset>
+                        <propertyref prefix="run-sys-prop."/>
+                        <mapper from="run-sys-prop.*" to="*" type="glob"/>
+                    </syspropertyset>
+                    <customize/>
+                </java>
+            </sequential>
+        </macrodef>
+    </target>
+    <target depends="-profile-pre-init, init, -profile-post-init, -profile-init-macrodef-profile" if="profiler.info.jvmargs.agent" name="-profile-init-check">
+        <fail unless="profiler.info.jvm">Must set JVM to use for profiling in profiler.info.jvm</fail>
+        <fail unless="profiler.info.jvmargs.agent">Must set profiler agent JVM arguments in profiler.info.jvmargs.agent</fail>
+    </target>
+    <!--
+                end of pre NB7.2 profiling section
+            -->
+    <target depends="-init-debug-args" name="-init-macrodef-nbjpda">
+        <macrodef name="nbjpdastart" uri="http://www.netbeans.org/ns/j2se-project/1">
+            <attribute default="${main.class}" name="name"/>
+            <attribute default="${debug.modulepath}" name="modulepath"/>
+            <attribute default="${debug.classpath}" name="classpath"/>
+            <attribute default="" name="stopclassname"/>
+            <sequential>
+                <nbjpdastart addressproperty="jpda.address" name="@{name}" stopclassname="@{stopclassname}" transport="${debug-transport}">
+                    <modulepath>
+                        <path path="@{modulepath}"/>
+                    </modulepath>
+                    <classpath>
+                        <path path="@{classpath}"/>
+                    </classpath>
+                </nbjpdastart>
+            </sequential>
+        </macrodef>
+        <macrodef name="nbjpdareload" uri="http://www.netbeans.org/ns/j2se-project/1">
+            <attribute default="${build.classes.dir}" name="dir"/>
+            <sequential>
+                <nbjpdareload>
+                    <fileset dir="@{dir}" includes="${fix.classes}">
+                        <include name="${fix.includes}*.class"/>
+                    </fileset>
+                </nbjpdareload>
+            </sequential>
+        </macrodef>
+    </target>
+    <target name="-init-debug-args">
+        <condition else="dt_socket" property="debug-transport-by-os" value="dt_shmem">
+            <os family="windows"/>
+        </condition>
+        <condition else="${debug-transport-by-os}" property="debug-transport" value="${debug.transport}">
+            <isset property="debug.transport"/>
+        </condition>
+    </target>
+    <target depends="-init-debug-args" name="-init-macrodef-debug">
+        <macrodef name="debug" uri="http://www.netbeans.org/ns/j2se-project/3">
+            <attribute default="${module.name}" name="modulename"/>
+            <attribute default="${main.class}" name="classname"/>
+            <attribute default="${debug.modulepath}" name="modulepath"/>
+            <attribute default="${debug.classpath}" name="classpath"/>
+            <element name="customizeDebuggee" optional="true"/>
+            <sequential>
+                <j2seproject1:java classname="@{classname}" classpath="@{classpath}" modulename="@{modulename}" modulepath="@{modulepath}">
+                    <customize>
+                        <jvmarg value="-agentlib:jdwp=transport=${debug-transport},address=${jpda.address}"/>
+                        <customizeDebuggee/>
+                    </customize>
+                </j2seproject1:java>
+            </sequential>
+        </macrodef>
+    </target>
+    <target depends="-init-source-module-properties" if="named.module.internal" name="-init-macrodef-java-with-module">
+        <macrodef name="java" uri="http://www.netbeans.org/ns/j2se-project/1">
+            <attribute default="${module.name}" name="modulename"/>
+            <attribute default="${main.class}" name="classname"/>
+            <attribute default="${run.modulepath}" name="modulepath"/>
+            <attribute default="${run.upgrademodulepath}" name="upgrademodulepath"/>
+            <attribute default="${run.classpath}" name="classpath"/>
+            <attribute default="jvm" name="jvm"/>
+            <element name="customize" optional="true"/>
+            <sequential>
+                <java classname="@{classname}" dir="${work.dir}" failonerror="${java.failonerror}" fork="true" module="@{modulename}">
+                    <classpath>
+                        <path path="@{classpath}"/>
+                    </classpath>
+                    <modulepath>
+                        <pathelement path="@{modulepath}"/>
+                        <pathelement location="${module.build.classes.dir}"/>
+                    </modulepath>
+                    <upgrademodulepath>
+                        <path path="@{upgrademodulepath}"/>
+                    </upgrademodulepath>
+                    <jvmarg value="-Dfile.encoding=${runtime.encoding}"/>
+                    <redirector errorencoding="${runtime.encoding}" inputencoding="${runtime.encoding}" outputencoding="${runtime.encoding}"/>
+                    <jvmarg line="${run.jvmargs}"/>
+                    <jvmarg line="${run.jvmargs.ide}"/>
+                    <syspropertyset>
+                        <propertyref prefix="run-sys-prop."/>
+                        <mapper from="run-sys-prop.*" to="*" type="glob"/>
+                    </syspropertyset>
+                    <customize/>
+                </java>
+            </sequential>
+        </macrodef>
+    </target>
+    <target depends="-init-source-module-properties" if="unnamed.module.internal" name="-init-macrodef-java-with-unnamed-module">
+        <macrodef name="java" uri="http://www.netbeans.org/ns/j2se-project/1">
+            <attribute default="" name="modulename"/>
+            <attribute default="${main.class}" name="classname"/>
+            <attribute default="${run.modulepath}" name="modulepath"/>
+            <attribute default="${run.upgrademodulepath}" name="upgrademodulepath"/>
+            <attribute default="${run.classpath}" name="classpath"/>
+            <attribute default="jvm" name="jvm"/>
+            <element name="customize" optional="true"/>
+            <sequential>
+                <java classname="@{classname}" dir="${work.dir}" failonerror="${java.failonerror}" fork="true">
+                    <classpath>
+                        <path path="@{classpath}"/>
+                    </classpath>
+                    <modulepath>
+                        <path path="@{modulepath}"/>
+                    </modulepath>
+                    <upgrademodulepath>
+                        <path path="@{upgrademodulepath}"/>
+                    </upgrademodulepath>
+                    <jvmarg value="-Dfile.encoding=${runtime.encoding}"/>
+                    <redirector errorencoding="${runtime.encoding}" inputencoding="${runtime.encoding}" outputencoding="${runtime.encoding}"/>
+                    <jvmarg line="${run.jvmargs}"/>
+                    <jvmarg line="${run.jvmargs.ide}"/>
+                    <syspropertyset>
+                        <propertyref prefix="run-sys-prop."/>
+                        <mapper from="run-sys-prop.*" to="*" type="glob"/>
+                    </syspropertyset>
+                    <customize/>
+                </java>
+            </sequential>
+        </macrodef>
+    </target>
+    <target depends="-init-source-module-properties" name="-init-macrodef-java-without-module" unless="modules.supported.internal">
+        <macrodef name="java" uri="http://www.netbeans.org/ns/j2se-project/1">
+            <attribute default="" name="modulename"/>
+            <attribute default="${main.class}" name="classname"/>
+            <attribute default="" name="modulepath"/>
+            <attribute default="${run.classpath}" name="classpath"/>
+            <attribute default="jvm" name="jvm"/>
+            <element name="customize" optional="true"/>
+            <sequential>
+                <java classname="@{classname}" dir="${work.dir}" failonerror="${java.failonerror}" fork="true">
+                    <jvmarg line="${endorsed.classpath.cmd.line.arg}"/>
+                    <jvmarg value="-Dfile.encoding=${runtime.encoding}"/>
+                    <redirector errorencoding="${runtime.encoding}" inputencoding="${runtime.encoding}" outputencoding="${runtime.encoding}"/>
+                    <jvmarg line="${run.jvmargs}"/>
+                    <jvmarg line="${run.jvmargs.ide}"/>
+                    <classpath>
+                        <path path="@{classpath}"/>
+                    </classpath>
+                    <syspropertyset>
+                        <propertyref prefix="run-sys-prop."/>
+                        <mapper from="run-sys-prop.*" to="*" type="glob"/>
+                    </syspropertyset>
+                    <customize/>
+                </java>
+            </sequential>
+        </macrodef>
+    </target>
+    <target depends="-init-macrodef-java-with-module, -init-macrodef-java-with-unnamed-module, -init-macrodef-java-without-module" name="-init-macrodef-java"/>
+    <target name="-init-macrodef-copylibs">
+        <macrodef name="copylibs" uri="http://www.netbeans.org/ns/j2se-project/3">
+            <attribute default="${manifest.file}" name="manifest"/>
+            <element name="customize" optional="true"/>
+            <sequential>
+                <property location="${build.classes.dir}" name="build.classes.dir.resolved"/>
+                <pathconvert property="run.classpath.without.build.classes.dir">
+                    <path path="${run.classpath}"/>
+                    <map from="${build.classes.dir.resolved}" to=""/>
+                </pathconvert>
+                <pathconvert pathsep=" " property="jar.classpath">
+                    <path path="${run.classpath.without.build.classes.dir}"/>
+                    <chainedmapper>
+                        <flattenmapper/>
+                        <filtermapper>
+                            <replacestring from=" " to="%20"/>
+                        </filtermapper>
+                        <globmapper from="*" to="lib/*"/>
+                    </chainedmapper>
+                </pathconvert>
+                <taskdef classname="org.netbeans.modules.java.j2seproject.copylibstask.CopyLibs" classpath="${libs.CopyLibs.classpath}" name="copylibs"/>
+                <copylibs compress="${jar.compress}" excludeFromCopy="${copylibs.excludes}" index="${jar.index}" indexMetaInf="${jar.index.metainf}" jarfile="${dist.jar}" manifest="@{manifest}" manifestencoding="UTF-8" rebase="${copylibs.rebase}" runtimeclasspath="${run.classpath.without.build.classes.dir}">
+                    <fileset dir="${build.classes.dir}" excludes="${dist.archive.excludes}"/>
+                    <manifest>
+                        <attribute name="Class-Path" value="${jar.classpath}"/>
+                        <customize/>
+                    </manifest>
+                </copylibs>
+            </sequential>
+        </macrodef>
+    </target>
+    <target name="-init-presetdef-jar">
+        <presetdef name="jar" uri="http://www.netbeans.org/ns/j2se-project/1">
+            <jar compress="${jar.compress}" index="${jar.index}" jarfile="${dist.jar}" manifestencoding="UTF-8">
+                <j2seproject1:fileset dir="${build.classes.dir}" excludes="${dist.archive.excludes}"/>
+            </jar>
+        </presetdef>
+    </target>
+    <target name="-init-ap-cmdline-properties">
+        <property name="annotation.processing.enabled" value="true"/>
+        <property name="annotation.processing.processors.list" value=""/>
+        <property name="annotation.processing.processor.options" value=""/>
+        <property name="annotation.processing.run.all.processors" value="true"/>
+        <property name="javac.processorpath" value="${javac.classpath}"/>
+        <property name="javac.test.processorpath" value="${javac.test.classpath}"/>
+        <condition property="ap.supported.internal" value="true">
+            <not>
+                <matches pattern="1\.[0-5](\..*)?" string="${javac.source}"/>
+            </not>
+        </condition>
+    </target>
+    <target depends="-init-ap-cmdline-properties" if="ap.supported.internal" name="-init-ap-cmdline-supported">
+        <condition else="" property="ap.processors.internal" value="-processor ${annotation.processing.processors.list}">
+            <isfalse value="${annotation.processing.run.all.processors}"/>
+        </condition>
+        <condition else="" property="ap.proc.none.internal" value="-proc:none">
+            <isfalse value="${annotation.processing.enabled}"/>
+        </condition>
+    </target>
+    <target depends="-init-ap-cmdline-properties,-init-ap-cmdline-supported" name="-init-ap-cmdline">
+        <property name="ap.cmd.line.internal" value=""/>
+    </target>
+    <target depends="-pre-init,-init-private,-init-user,-init-project,-do-init,-post-init,-init-check,-init-macrodef-property,-init-macrodef-javac,-init-macrodef-test,-init-macrodef-test-debug,-init-macrodef-nbjpda,-init-macrodef-debug,-init-macrodef-java,-init-presetdef-jar,-init-ap-cmdline" name="init"/>
+    <!--
+                ===================
+                COMPILATION SECTION
+                ===================
+            -->
+    <target name="-deps-jar-init" unless="built-jar.properties">
+        <property location="${build.dir}/built-jar.properties" name="built-jar.properties"/>
+        <delete file="${built-jar.properties}" quiet="true"/>
+    </target>
+    <target if="already.built.jar.${basedir}" name="-warn-already-built-jar">
+        <echo level="warn" message="Cycle detected: java_modbusmaster was already built"/>
+    </target>
+    <target depends="init,-deps-jar-init" name="deps-jar" unless="no.deps">
+        <mkdir dir="${build.dir}"/>
+        <touch file="${built-jar.properties}" verbose="false"/>
+        <property file="${built-jar.properties}" prefix="already.built.jar."/>
+        <antcall target="-warn-already-built-jar"/>
+        <propertyfile file="${built-jar.properties}">
+            <entry key="${basedir}" value=""/>
+        </propertyfile>
+    </target>
+    <target depends="init,-check-automatic-build,-clean-after-automatic-build" name="-verify-automatic-build"/>
+    <target depends="init" name="-check-automatic-build">
+        <available file="${build.classes.dir}/.netbeans_automatic_build" property="netbeans.automatic.build"/>
+    </target>
+    <target depends="init" if="netbeans.automatic.build" name="-clean-after-automatic-build">
+        <antcall target="clean">
+            <param name="no.dependencies" value="true"/>
+        </antcall>
+    </target>
+    <target depends="init,deps-jar" name="-pre-pre-compile">
+        <mkdir dir="${build.classes.dir}"/>
+    </target>
+    <target name="-pre-compile">
+        <!-- Empty placeholder for easier customization. -->
+        <!-- You can override this target in the ../build.xml file. -->
+    </target>
+    <target if="do.depend.true" name="-compile-depend">
+        <pathconvert property="build.generated.subdirs">
+            <dirset dir="${build.generated.sources.dir}" erroronmissingdir="false">
+                <include name="*"/>
+            </dirset>
+        </pathconvert>
+        <j2seproject3:depend srcdir="${src.dir}:${build.generated.subdirs}"/>
+    </target>
+    <target depends="init,deps-jar,-pre-pre-compile,-pre-compile, -copy-persistence-xml,-compile-depend" if="have.sources" name="-do-compile">
+        <j2seproject3:javac gensrcdir="${build.generated.sources.dir}"/>
+        <copy todir="${build.classes.dir}">
+            <fileset dir="${src.dir}" excludes="${build.classes.excludes},${excludes}" includes="${includes}"/>
+        </copy>
+    </target>
+    <target if="has.persistence.xml" name="-copy-persistence-xml">
+        <mkdir dir="${build.classes.dir}/META-INF"/>
+        <copy todir="${build.classes.dir}/META-INF">
+            <fileset dir="${meta.inf.dir}" includes="persistence.xml orm.xml"/>
+        </copy>
+    </target>
+    <target name="-post-compile">
+        <!-- Empty placeholder for easier customization. -->
+        <!-- You can override this target in the ../build.xml file. -->
+    </target>
+    <target depends="init,deps-jar,-verify-automatic-build,-pre-pre-compile,-pre-compile,-do-compile,-post-compile" description="Compile project." name="compile"/>
+    <target name="-pre-compile-single">
+        <!-- Empty placeholder for easier customization. -->
+        <!-- You can override this target in the ../build.xml file. -->
+    </target>
+    <target depends="init,deps-jar,-pre-pre-compile" name="-do-compile-single">
+        <fail unless="javac.includes">Must select some files in the IDE or set javac.includes</fail>
+        <j2seproject3:force-recompile/>
+        <j2seproject3:javac excludes="" gensrcdir="${build.generated.sources.dir}" includes="${javac.includes}, module-info.java" sourcepath="${src.dir}"/>
+    </target>
+    <target name="-post-compile-single">
+        <!-- Empty placeholder for easier customization. -->
+        <!-- You can override this target in the ../build.xml file. -->
+    </target>
+    <target depends="init,deps-jar,-verify-automatic-build,-pre-pre-compile,-pre-compile-single,-do-compile-single,-post-compile-single" name="compile-single"/>
+    <!--
+                ====================
+                JAR BUILDING SECTION
+                ====================
+            -->
+    <target depends="init" name="-pre-pre-jar">
+        <dirname file="${dist.jar}" property="dist.jar.dir"/>
+        <mkdir dir="${dist.jar.dir}"/>
+    </target>
+    <target name="-pre-jar">
+        <!-- Empty placeholder for easier customization. -->
+        <!-- You can override this target in the ../build.xml file. -->
+    </target>
+    <target depends="init,compile" name="-check-module-main-class">
+        <pathconvert property="main.class.file">
+            <string value="${main.class}"/>
+            <unpackagemapper from="*" to="*.class"/>
+        </pathconvert>
+        <condition property="do.module.main.class">
+            <and>
+                <isset property="main.class.available"/>
+                <available file="${build.classes.dir}/module-info.class"/>
+                <available file="${build.classes.dir}/${main.class.file}"/>
+                <isset property="libs.CopyLibs.classpath"/>
+                <available classname="org.netbeans.modules.java.j2seproject.moduletask.ModuleMainClass" classpath="${libs.CopyLibs.classpath}"/>
+            </and>
+        </condition>
+    </target>
+    <target depends="-check-module-main-class" if="do.module.main.class" name="-set-module-main-class">
+        <taskdef classname="org.netbeans.modules.java.j2seproject.moduletask.ModuleMainClass" classpath="${libs.CopyLibs.classpath}" name="modulemainclass"/>
+        <modulemainclass failonerror="false" mainclass="${main.class}" moduleinfo="${build.classes.dir}/module-info.class"/>
+    </target>
+    <target depends="init" if="do.archive" name="-do-jar-create-manifest" unless="manifest.available">
+        <tempfile deleteonexit="true" destdir="${build.dir}" property="tmp.manifest.file"/>
+        <touch file="${tmp.manifest.file}" verbose="false"/>
+    </target>
+    <target depends="init" if="do.archive+manifest.available" name="-do-jar-copy-manifest">
+        <tempfile deleteonexit="true" destdir="${build.dir}" property="tmp.manifest.file"/>
+        <copy encoding="${manifest.encoding}" file="${manifest.file}" outputencoding="UTF-8" tofile="${tmp.manifest.file}"/>
+    </target>
+    <target depends="init,-do-jar-create-manifest,-do-jar-copy-manifest" if="do.archive+main.class.available" name="-do-jar-set-mainclass">
+        <manifest encoding="UTF-8" file="${tmp.manifest.file}" mode="update">
+            <attribute name="Main-Class" value="${main.class}"/>
+        </manifest>
+    </target>
+    <target depends="init,-do-jar-create-manifest,-do-jar-copy-manifest" if="do.archive+profile.available" name="-do-jar-set-profile">
+        <manifest encoding="UTF-8" file="${tmp.manifest.file}" mode="update">
+            <attribute name="Profile" value="${javac.profile}"/>
+        </manifest>
+    </target>
+    <target depends="init,-do-jar-create-manifest,-do-jar-copy-manifest" if="do.archive+splashscreen.available" name="-do-jar-set-splashscreen">
+        <basename file="${application.splash}" property="splashscreen.basename"/>
+        <mkdir dir="${build.classes.dir}/META-INF"/>
+        <copy failonerror="false" file="${application.splash}" todir="${build.classes.dir}/META-INF"/>
+        <manifest encoding="UTF-8" file="${tmp.manifest.file}" mode="update">
+            <attribute name="SplashScreen-Image" value="META-INF/${splashscreen.basename}"/>
+        </manifest>
+    </target>
+    <target depends="init,-init-macrodef-copylibs,compile,-pre-pre-jar,-pre-jar,-do-jar-create-manifest,-do-jar-copy-manifest,-do-jar-set-mainclass,-do-jar-set-profile,-do-jar-set-splashscreen" if="do.mkdist" name="-do-jar-copylibs">
+        <j2seproject3:copylibs manifest="${tmp.manifest.file}"/>
+        <echo level="info">To run this application from the command line without Ant, try:</echo>
+        <property location="${dist.jar}" name="dist.jar.resolved"/>
+        <echo level="info">java -jar "${dist.jar.resolved}"</echo>
+    </target>
+    <target depends="init,compile,-pre-pre-jar,-pre-jar,-do-jar-create-manifest,-do-jar-copy-manifest,-do-jar-set-mainclass,-do-jar-set-profile,-do-jar-set-splashscreen" if="do.archive" name="-do-jar-jar" unless="do.mkdist">
+        <j2seproject1:jar manifest="${tmp.manifest.file}"/>
+        <property location="${build.classes.dir}" name="build.classes.dir.resolved"/>
+        <property location="${dist.jar}" name="dist.jar.resolved"/>
+        <condition else="${dist.jar.resolved}" property="jar.usage.message.class.path.replacement" value="">
+            <isset property="named.module.internal"/>
+        </condition>
+        <pathconvert property="run.classpath.with.dist.jar">
+            <path path="${run.classpath}"/>
+            <map from="${build.classes.dir.resolved}" to="${jar.usage.message.class.path.replacement}"/>
+        </pathconvert>
+        <pathconvert property="run.modulepath.with.dist.jar">
+            <path location="${dist.jar.resolved}"/>
+            <path path="${run.modulepath}"/>
+            <map from="${build.classes.dir.resolved}" to="${dist.jar.resolved}"/>
+        </pathconvert>
+        <condition else="${run.modulepath}" property="jar.usage.message.run.modulepath.with.dist.jar" value="${run.modulepath.with.dist.jar}">
+            <isset property="named.module.internal"/>
+        </condition>
+        <condition else="" property="jar.usage.message.module.path" value=" -p ${jar.usage.message.run.modulepath.with.dist.jar}">
+            <and>
+                <isset property="modules.supported.internal"/>
+                <length length="0" string="${jar.usage.message.run.modulepath.with.dist.jar}" when="greater"/>
+            </and>
+        </condition>
+        <condition else="" property="jar.usage.message.class.path" value=" -cp ${run.classpath.with.dist.jar}">
+            <length length="0" string="${run.classpath.with.dist.jar}" when="greater"/>
+        </condition>
+        <condition else="/${main.class}" property="jar.usage.message.main.class.class.selector" value="">
+            <isset property="do.module.main.class"/>
+        </condition>
+        <condition else=" ${main.class}" property="jar.usage.message.main.class" value=" -m ${module.name}${jar.usage.message.main.class.class.selector}">
+            <isset property="named.module.internal"/>
+        </condition>
+        <condition else="" property="jar.usage.message" value="To run this application from the command line without Ant, try:${line.separator}${platform.java}${jar.usage.message.module.path}${jar.usage.message.class.path}${jar.usage.message.main.class}">
+            <isset property="main.class.available"/>
+        </condition>
+        <condition else="debug" property="jar.usage.level" value="info">
+            <isset property="main.class.available"/>
+        </condition>
+        <echo level="${jar.usage.level}" message="${jar.usage.message}"/>
+    </target>
+    <target depends="-do-jar-copylibs" if="do.archive" name="-do-jar-delete-manifest">
+        <delete>
+            <fileset file="${tmp.manifest.file}"/>
+        </delete>
+    </target>
+    <target depends="init,compile,-pre-pre-jar,-pre-jar,-do-jar-create-manifest,-do-jar-copy-manifest,-do-jar-set-mainclass,-do-jar-set-profile,-do-jar-set-splashscreen,-do-jar-jar,-do-jar-delete-manifest" name="-do-jar-without-libraries"/>
+    <target depends="init,compile,-pre-pre-jar,-pre-jar,-do-jar-create-manifest,-do-jar-copy-manifest,-do-jar-set-mainclass,-do-jar-set-profile,-do-jar-set-splashscreen,-do-jar-copylibs,-do-jar-delete-manifest" name="-do-jar-with-libraries"/>
+    <target name="-post-jar">
+        <!-- Empty placeholder for easier customization. -->
+        <!-- You can override this target in the ../build.xml file. -->
+    </target>
+    <target depends="init,compile,-pre-jar,-set-module-main-class,-do-jar-without-libraries,-do-jar-with-libraries,-post-jar" name="-do-jar"/>
+    <target depends="init,compile,-pre-jar,-do-jar,-post-jar,deploy" description="Build JAR." name="jar"/>
+    <!--
+                =================
+                DEPLOY SECTION
+                =================
+            -->
+    <target name="-pre-deploy">
+        <!-- Empty placeholder for easier customization. -->
+        <!-- You can override this target in the ../build.xml file. -->
+    </target>
+    <target depends="init" name="-check-jlink">
+        <condition property="do.jlink.internal">
+            <and>
+                <istrue value="${do.jlink}"/>
+                <isset property="do.archive"/>
+                <isset property="named.module.internal"/>
+            </and>
+        </condition>
+    </target>
+    <target depends="init,-do-jar,-post-jar,-pre-deploy,-check-jlink" if="do.jlink.internal" name="-do-deploy">
+        <delete dir="${dist.jlink.dir}" failonerror="false" quiet="true"/>
+        <property name="jlink.launcher.name" value="${application.title}"/>
+        <condition else="${module.name}" property="jlink.add.modules" value="${module.name},${jlink.additionalmodules}">
+            <and>
+                <isset property="jlink.additionalmodules"/>
+                <length length="0" string="${jlink.additionalmodules}" when="greater"/>
+            </and>
+        </condition>
+        <condition property="jlink.do.strip.internal">
+            <and>
+                <isset property="jlink.strip"/>
+                <istrue value="${jlink.strip}"/>
+            </and>
+        </condition>
+        <condition property="jlink.do.additionalparam.internal">
+            <and>
+                <isset property="jlink.additionalparam"/>
+                <length length="0" string="${jlink.additionalparam}" when="greater"/>
+            </and>
+        </condition>
+        <condition property="jlink.do.launcher.internal">
+            <and>
+                <istrue value="${jlink.launcher}"/>
+                <isset property="main.class.available"/>
+            </and>
+        </condition>
+        <property name="platform.jlink" value="${jdk.home}/bin/jlink"/>
+        <property name="jlink.systemmodules.internal" value="${jdk.home}/jmods"/>
+        <exec executable="${platform.jlink}">
+            <arg value="--module-path"/>
+            <arg path="${jlink.systemmodules.internal}:${run.modulepath}:${dist.jar}"/>
+            <arg value="--add-modules"/>
+            <arg value="${jlink.add.modules}"/>
+            <arg if:set="jlink.do.strip.internal" value="--strip-debug"/>
+            <arg if:set="jlink.do.launcher.internal" value="--launcher"/>
+            <arg if:set="jlink.do.launcher.internal" value="${jlink.launcher.name}=${module.name}/${main.class}"/>
+            <arg if:set="jlink.do.additionalparam.internal" line="${jlink.additionalparam}"/>
+            <arg value="--output"/>
+            <arg value="${dist.jlink.output}"/>
+        </exec>
+    </target>
+    <target name="-post-deploy">
+        <!-- Empty placeholder for easier customization. -->
+        <!-- You can override this target in the ../build.xml file. -->
+    </target>
+    <target depends="-do-jar,-post-jar,-pre-deploy,-do-deploy,-post-deploy" name="deploy"/>
+    <!--
+                =================
+                EXECUTION SECTION
+                =================
+            -->
+    <target depends="init,compile" description="Run a main class." name="run">
+        <j2seproject1:java>
+            <customize>
+                <arg line="${application.args}"/>
+            </customize>
+        </j2seproject1:java>
+    </target>
+    <target name="-do-not-recompile">
+        <property name="javac.includes.binary" value=""/>
+    </target>
+    <target depends="init,compile-single" name="run-single">
+        <fail unless="run.class">Must select one file in the IDE or set run.class</fail>
+        <j2seproject1:java classname="${run.class}"/>
+    </target>
+    <target depends="init,compile-test-single" name="run-test-with-main">
+        <fail unless="run.class">Must select one file in the IDE or set run.class</fail>
+        <j2seproject1:java classname="${run.class}" classpath="${run.test.classpath}"/>
+    </target>
+    <!--
+                =================
+                DEBUGGING SECTION
+                =================
+            -->
+    <target depends="init" if="netbeans.home" name="-debug-start-debugger">
+        <j2seproject1:nbjpdastart name="${debug.class}"/>
+    </target>
+    <target depends="init" if="netbeans.home" name="-debug-start-debugger-main-test">
+        <j2seproject1:nbjpdastart classpath="${debug.test.classpath}" name="${debug.class}"/>
+    </target>
+    <target depends="init,compile" name="-debug-start-debuggee">
+        <j2seproject3:debug>
+            <customizeDebuggee>
+                <arg line="${application.args}"/>
+            </customizeDebuggee>
+        </j2seproject3:debug>
+    </target>
+    <target depends="init,compile,-debug-start-debugger,-debug-start-debuggee" description="Debug project in IDE." if="netbeans.home" name="debug"/>
+    <target depends="init" if="netbeans.home" name="-debug-start-debugger-stepinto">
+        <j2seproject1:nbjpdastart stopclassname="${main.class}"/>
+    </target>
+    <target depends="init,compile,-debug-start-debugger-stepinto,-debug-start-debuggee" if="netbeans.home" name="debug-stepinto"/>
+    <target depends="init,compile-single" if="netbeans.home" name="-debug-start-debuggee-single">
+        <fail unless="debug.class">Must select one file in the IDE or set debug.class</fail>
+        <j2seproject3:debug classname="${debug.class}"/>
+    </target>
+    <target depends="init,compile-single,-debug-start-debugger,-debug-start-debuggee-single" if="netbeans.home" name="debug-single"/>
+    <target depends="init,compile-test-single" if="netbeans.home" name="-debug-start-debuggee-main-test">
+        <fail unless="debug.class">Must select one file in the IDE or set debug.class</fail>
+        <j2seproject3:debug classname="${debug.class}" classpath="${debug.test.classpath}"/>
+    </target>
+    <target depends="init,compile-test-single,-debug-start-debugger-main-test,-debug-start-debuggee-main-test" if="netbeans.home" name="debug-test-with-main"/>
+    <target depends="init" name="-pre-debug-fix">
+        <fail unless="fix.includes">Must set fix.includes</fail>
+        <property name="javac.includes" value="${fix.includes}.java"/>
+    </target>
+    <target depends="init,-pre-debug-fix,compile-single" if="netbeans.home" name="-do-debug-fix">
+        <j2seproject1:nbjpdareload/>
+    </target>
+    <target depends="init,-pre-debug-fix,-do-debug-fix" if="netbeans.home" name="debug-fix"/>
+    <!--
+                =================
+                PROFILING SECTION
+                =================
+            -->
+    <!--
+                pre NB7.2 profiler integration
+            -->
+    <target depends="profile-init,compile" description="Profile a project in the IDE." if="profiler.info.jvmargs.agent" name="-profile-pre72">
+        <fail unless="netbeans.home">This target only works when run from inside the NetBeans IDE.</fail>
+        <nbprofiledirect>
+            <classpath>
+                <path path="${run.classpath}"/>
+            </classpath>
+        </nbprofiledirect>
+        <profile/>
+    </target>
+    <target depends="profile-init,compile-single" description="Profile a selected class in the IDE." if="profiler.info.jvmargs.agent" name="-profile-single-pre72">
+        <fail unless="profile.class">Must select one file in the IDE or set profile.class</fail>
+        <fail unless="netbeans.home">This target only works when run from inside the NetBeans IDE.</fail>
+        <nbprofiledirect>
+            <classpath>
+                <path path="${run.classpath}"/>
+            </classpath>
+        </nbprofiledirect>
+        <profile classname="${profile.class}"/>
+    </target>
+    <target depends="profile-init,compile-single" if="profiler.info.jvmargs.agent" name="-profile-applet-pre72">
+        <fail unless="netbeans.home">This target only works when run from inside the NetBeans IDE.</fail>
+        <nbprofiledirect>
+            <classpath>
+                <path path="${run.classpath}"/>
+            </classpath>
+        </nbprofiledirect>
+        <profile classname="sun.applet.AppletViewer">
+            <customize>
+                <arg value="${applet.url}"/>
+            </customize>
+        </profile>
+    </target>
+    <target depends="-init-macrodef-junit,profile-init,compile-test-single" if="profiler.info.jvmargs.agent" name="-profile-test-single-pre72">
+        <fail unless="netbeans.home">This target only works when run from inside the NetBeans IDE.</fail>
+        <nbprofiledirect>
+            <classpath>
+                <path path="${run.test.classpath}"/>
+            </classpath>
+        </nbprofiledirect>
+        <j2seproject3:junit excludes="${excludes}" includes="${includes}" testincludes="${profile.class}" testmethods="">
+            <customize>
+                <jvmarg value="-agentlib:jdwp=transport=${debug-transport},address=${jpda.address}"/>
+                <env key="${profiler.info.pathvar}" path="${profiler.info.agentpath}:${profiler.current.path}"/>
+                <jvmarg value="${profiler.info.jvmargs.agent}"/>
+                <jvmarg line="${profiler.info.jvmargs}"/>
+                <classpath>
+                    <path path="${run.test.classpath}"/>
+                </classpath>
+            </customize>
+        </j2seproject3:junit>
+    </target>
+    <!--
+                end of pre NB72 profiling section
+            -->
+    <target if="netbeans.home" name="-profile-check">
+        <condition property="profiler.configured">
+            <or>
+                <contains casesensitive="true" string="${run.jvmargs.ide}" substring="-agentpath:"/>
+                <contains casesensitive="true" string="${run.jvmargs.ide}" substring="-javaagent:"/>
+            </or>
+        </condition>
+    </target>
+    <target depends="-profile-check,-profile-pre72" description="Profile a project in the IDE." if="profiler.configured" name="profile" unless="profiler.info.jvmargs.agent">
+        <startprofiler/>
+        <antcall target="run"/>
+    </target>
+    <target depends="-profile-check,-profile-single-pre72" description="Profile a selected class in the IDE." if="profiler.configured" name="profile-single" unless="profiler.info.jvmargs.agent">
+        <fail unless="run.class">Must select one file in the IDE or set run.class</fail>
+        <startprofiler/>
+        <antcall target="run-single"/>
+    </target>
+    <target depends="-profile-test-single-pre72" description="Profile a selected test in the IDE." name="profile-test-single"/>
+    <target depends="-profile-check" description="Profile a selected test in the IDE." if="profiler.configured" name="profile-test" unless="profiler.info.jvmargs">
+        <fail unless="test.includes">Must select some files in the IDE or set test.includes</fail>
+        <startprofiler/>
+        <antcall target="test-single"/>
+    </target>
+    <target depends="-profile-check" description="Profile a selected class in the IDE." if="profiler.configured" name="profile-test-with-main">
+        <fail unless="run.class">Must select one file in the IDE or set run.class</fail>
+        <startprofiler/>
+        <antcall target="run-test-with-main"/>
+    </target>
+    <target depends="-profile-check,-profile-applet-pre72" if="profiler.configured" name="profile-applet" unless="profiler.info.jvmargs.agent">
+        <fail unless="applet.url">Must select one file in the IDE or set applet.url</fail>
+        <startprofiler/>
+        <antcall target="run-applet"/>
+    </target>
+    <!--
+                ===============
+                JAVADOC SECTION
+                ===============
+            -->
+    <target depends="init" if="have.sources" name="-javadoc-build">
+        <mkdir dir="${dist.javadoc.dir}"/>
+        <condition else="" property="javadoc.endorsed.classpath.cmd.line.arg" value="-J${endorsed.classpath.cmd.line.arg}">
+            <and>
+                <isset property="endorsed.classpath.cmd.line.arg"/>
+                <not>
+                    <equals arg1="${endorsed.classpath.cmd.line.arg}" arg2=""/>
+                </not>
+            </and>
+        </condition>
+        <condition else="" property="bug5101868workaround" value="*.java">
+            <matches pattern="1\.[56](\..*)?" string="${java.version}"/>
+        </condition>
+        <condition else="" property="javadoc.html5.cmd.line.arg" value="-html5">
+            <and>
+                <isset property="javadoc.html5"/>
+                <available file="${jdk.home}${file.separator}lib${file.separator}jrt-fs.jar"/>
+            </and>
+        </condition>
+        <javadoc additionalparam="-J-Dfile.encoding=${file.encoding} ${javadoc.additionalparam}" author="${javadoc.author}" charset="UTF-8" destdir="${dist.javadoc.dir}" docencoding="UTF-8" encoding="${javadoc.encoding.used}" failonerror="true" noindex="${javadoc.noindex}" nonavbar="${javadoc.nonavbar}" notree="${javadoc.notree}" private="${javadoc.private}" source="${javac.source}" splitindex="${javadoc.splitindex}" use="${javadoc.use}" useexternalfile="true" version="${javadoc.version}" windowtitle="${javadoc.windowtitle}">
+            <classpath>
+                <path path="${javac.classpath}"/>
+            </classpath>
+            <fileset dir="${src.dir}" excludes="${bug5101868workaround},${excludes}" includes="${includes}">
+                <filename name="**/*.java"/>
+            </fileset>
+            <fileset dir="${build.generated.sources.dir}" erroronmissingdir="false">
+                <include name="**/*.java"/>
+                <exclude name="*.java"/>
+            </fileset>
+            <arg line="${javadoc.endorsed.classpath.cmd.line.arg}"/>
+            <arg line="${javadoc.html5.cmd.line.arg}"/>
+        </javadoc>
+        <copy todir="${dist.javadoc.dir}">
+            <fileset dir="${src.dir}" excludes="${excludes}" includes="${includes}">
+                <filename name="**/doc-files/**"/>
+            </fileset>
+            <fileset dir="${build.generated.sources.dir}" erroronmissingdir="false">
+                <include name="**/doc-files/**"/>
+            </fileset>
+        </copy>
+    </target>
+    <target depends="init,-javadoc-build" if="netbeans.home" name="-javadoc-browse" unless="no.javadoc.preview">
+        <nbbrowse file="${dist.javadoc.dir}/index.html"/>
+    </target>
+    <target depends="init,-javadoc-build,-javadoc-browse" description="Build Javadoc." name="javadoc"/>
+    <!--
+                =========================
+                TEST COMPILATION SECTION
+                =========================
+            -->
+    <target depends="init,compile" if="have.tests" name="-pre-pre-compile-test">
+        <mkdir dir="${build.test.classes.dir}"/>
+    </target>
+    <target name="-pre-compile-test">
+        <!-- Empty placeholder for easier customization. -->
+        <!-- You can override this target in the ../build.xml file. -->
+    </target>
+    <target depends="-init-source-module-properties" if="named.module.internal" name="-init-test-javac-module-properties-with-module">
+        <j2seproject3:modulename property="test.module.name" sourcepath="${test.src.dir}"/>
+        <condition else="${empty.dir}" property="javac.test.sourcepath" value="${test.src.dir}">
+            <and>
+                <isset property="test.module.name"/>
+                <length length="0" string="${test.module.name}" when="greater"/>
+            </and>
+        </condition>
+        <condition else="--patch-module ${module.name}=${test.src.dir} --add-reads ${module.name}=ALL-UNNAMED" property="javac.test.compilerargs" value="--add-reads ${test.module.name}=ALL-UNNAMED">
+            <and>
+                <isset property="test.module.name"/>
+                <length length="0" string="${test.module.name}" when="greater"/>
+            </and>
+        </condition>
+    </target>
+    <target depends="-init-source-module-properties" if="named.module.internal" name="-init-test-run-module-properties">
+        <condition else="${module.name}" property="run.test.addexport.source.module.internal" value="${test.module.name}">
+            <and>
+                <isset property="test.module.name"/>
+                <length length="0" string="${test.module.name}" when="greater"/>
+            </and>
+        </condition>
+        <fileset dir="${build.test.classes.dir}" id="run.test.packages.internal" includes="**/*.class"/>
+        <property location="${build.test.classes.dir}" name="build.test.classes.dir.abs.internal"/>
+        <pathconvert pathsep=" " property="run.test.addexports.internal" refid="run.test.packages.internal">
+            <chainedmapper>
+                <regexpmapper from="^(.*)\Q${file.separator}\E.*\.class$$" to="\1"/>
+                <filtermapper>
+                    <uniqfilter/>
+                    <replacestring from="${build.test.classes.dir.abs.internal}" to=""/>
+                </filtermapper>
+                <cutdirsmapper dirs="1"/>
+                <packagemapper from="*" to="--add-exports ${run.test.addexport.source.module.internal}/*=ALL-UNNAMED"/>
+            </chainedmapper>
+        </pathconvert>
+        <condition else="--patch-module ${module.name}=${build.test.classes.dir} --add-modules ${module.name} --add-reads ${module.name}=ALL-UNNAMED ${run.test.addexports.internal}" property="run.test.jvmargs" value="--add-modules ${test.module.name} --add-reads ${test.module.name}=ALL-UNNAMED ${run.test.addexports.internal}">
+            <and>
+                <isset property="test.module.name"/>
+                <length length="0" string="${test.module.name}" when="greater"/>
+            </and>
+        </condition>
+    </target>
+    <target depends="-init-source-module-properties" name="-init-test-module-properties-without-module" unless="named.module.internal">
+        <property name="javac.test.sourcepath" value="${empty.dir}"/>
+        <property name="javac.test.compilerargs" value=""/>
+        <property name="run.test.jvmargs" value=""/>
+    </target>
+    <target depends="-init-test-javac-module-properties-with-module,-init-test-module-properties-without-module" name="-init-test-module-properties"/>
+    <target if="do.depend.true" name="-compile-test-depend">
+        <j2seproject3:depend classpath="${javac.test.classpath}" destdir="${build.test.classes.dir}" srcdir="${test.src.dir}"/>
+    </target>
+    <target depends="init,deps-jar,compile,-init-test-module-properties,-pre-pre-compile-test,-pre-compile-test,-compile-test-depend" if="have.tests" name="-do-compile-test">
+        <j2seproject3:javac apgeneratedsrcdir="${build.test.classes.dir}" classpath="${javac.test.classpath}" debug="true" destdir="${build.test.classes.dir}" modulepath="${javac.test.modulepath}" processorpath="${javac.test.processorpath}" sourcepath="${javac.test.sourcepath}" srcdir="${test.src.dir}">
+            <customize>
+                <compilerarg line="${javac.test.compilerargs}"/>
+            </customize>
+        </j2seproject3:javac>
+        <copy todir="${build.test.classes.dir}">
+            <fileset dir="${test.src.dir}" excludes="${build.classes.excludes},${excludes}" includes="${includes}"/>
+        </copy>
+    </target>
+    <target name="-post-compile-test">
+        <!-- Empty placeholder for easier customization. -->
+        <!-- You can override this target in the ../build.xml file. -->
+    </target>
+    <target depends="init,compile,-pre-pre-compile-test,-pre-compile-test,-do-compile-test,-post-compile-test" name="compile-test"/>
+    <target name="-pre-compile-test-single">
+        <!-- Empty placeholder for easier customization. -->
+        <!-- You can override this target in the ../build.xml file. -->
+    </target>
+    <target depends="init,deps-jar,compile,-init-test-module-properties,-pre-pre-compile-test,-pre-compile-test-single" if="have.tests" name="-do-compile-test-single">
+        <fail unless="javac.includes">Must select some files in the IDE or set javac.includes</fail>
+        <j2seproject3:force-recompile destdir="${build.test.classes.dir}"/>
+        <j2seproject3:javac apgeneratedsrcdir="${build.test.classes.dir}" classpath="${javac.test.classpath}" debug="true" destdir="${build.test.classes.dir}" excludes="" includes="${javac.includes}, module-info.java" modulepath="${javac.test.modulepath}" processorpath="${javac.test.processorpath}" sourcepath="${test.src.dir}" srcdir="${test.src.dir}">
+            <customize>
+                <compilerarg line="${javac.test.compilerargs}"/>
+            </customize>
+        </j2seproject3:javac>
+        <copy todir="${build.test.classes.dir}">
+            <fileset dir="${test.src.dir}" excludes="${build.classes.excludes},${excludes}" includes="${includes}"/>
+        </copy>
+    </target>
+    <target name="-post-compile-test-single">
+        <!-- Empty placeholder for easier customization. -->
+        <!-- You can override this target in the ../build.xml file. -->
+    </target>
+    <target depends="init,compile,-pre-pre-compile-test,-pre-compile-test-single,-do-compile-test-single,-post-compile-test-single" name="compile-test-single"/>
+    <!--
+                =======================
+                TEST EXECUTION SECTION
+                =======================
+            -->
+    <target depends="init" if="have.tests" name="-pre-test-run">
+        <mkdir dir="${build.test.results.dir}"/>
+    </target>
+    <target depends="init,compile-test,-init-test-run-module-properties,-pre-test-run" if="have.tests" name="-do-test-run">
+        <j2seproject3:test includes="${includes}" testincludes="**/*Test.java"/>
+    </target>
+    <target depends="init,compile-test,-pre-test-run,-do-test-run" if="have.tests" name="-post-test-run">
+        <fail if="tests.failed" unless="ignore.failing.tests">Some tests failed; see details above.</fail>
+    </target>
+    <target depends="init" if="have.tests" name="test-report"/>
+    <target depends="init" if="netbeans.home+have.tests" name="-test-browse"/>
+    <target depends="init,compile-test,-pre-test-run,-do-test-run,test-report,-post-test-run,-test-browse" description="Run unit tests." name="test"/>
+    <target depends="init" if="have.tests" name="-pre-test-run-single">
+        <mkdir dir="${build.test.results.dir}"/>
+    </target>
+    <target depends="init,compile-test-single,-init-test-run-module-properties,-pre-test-run-single" if="have.tests" name="-do-test-run-single">
+        <fail unless="test.includes">Must select some files in the IDE or set test.includes</fail>
+        <j2seproject3:test excludes="" includes="${test.includes}" testincludes="${test.includes}"/>
+    </target>
+    <target depends="init,compile-test-single,-pre-test-run-single,-do-test-run-single" if="have.tests" name="-post-test-run-single">
+        <fail if="tests.failed" unless="ignore.failing.tests">Some tests failed; see details above.</fail>
+    </target>
+    <target depends="init,compile-test-single,-init-test-run-module-properties,-pre-test-run-single,-do-test-run-single,-post-test-run-single" description="Run single unit test." name="test-single"/>
+    <target depends="init,compile-test-single,-pre-test-run-single" if="have.tests" name="-do-test-run-single-method">
+        <fail unless="test.class">Must select some files in the IDE or set test.class</fail>
+        <fail unless="test.method">Must select some method in the IDE or set test.method</fail>
+        <j2seproject3:test excludes="" includes="${javac.includes}" testincludes="${test.class}" testmethods="${test.method}"/>
+    </target>
+    <target depends="init,compile-test-single,-pre-test-run-single,-do-test-run-single-method" if="have.tests" name="-post-test-run-single-method">
+        <fail if="tests.failed" unless="ignore.failing.tests">Some tests failed; see details above.</fail>
+    </target>
+    <target depends="init,compile-test-single,-init-test-run-module-properties,-pre-test-run-single,-do-test-run-single-method,-post-test-run-single-method" description="Run single unit test." name="test-single-method"/>
+    <!--
+                =======================
+                TEST DEBUGGING SECTION
+                =======================
+            -->
+    <target depends="init,compile-test-single,-pre-test-run-single" if="have.tests" name="-debug-start-debuggee-test">
+        <fail unless="test.class">Must select one file in the IDE or set test.class</fail>
+        <j2seproject3:test-debug excludes="" includes="${javac.includes}" testClass="${test.class}" testincludes="${javac.includes}"/>
+    </target>
+    <target depends="init,compile-test-single,-pre-test-run-single" if="have.tests" name="-debug-start-debuggee-test-method">
+        <fail unless="test.class">Must select one file in the IDE or set test.class</fail>
+        <fail unless="test.method">Must select some method in the IDE or set test.method</fail>
+        <j2seproject3:test-debug excludes="" includes="${javac.includes}" testClass="${test.class}" testMethod="${test.method}" testincludes="${test.class}" testmethods="${test.method}"/>
+    </target>
+    <target depends="init,compile-test" if="netbeans.home+have.tests" name="-debug-start-debugger-test">
+        <j2seproject1:nbjpdastart classpath="${debug.test.classpath}" name="${test.class}"/>
+    </target>
+    <target depends="init,compile-test-single,-init-test-run-module-properties,-debug-start-debugger-test,-debug-start-debuggee-test" name="debug-test"/>
+    <target depends="init,compile-test-single,-init-test-run-module-properties,-debug-start-debugger-test,-debug-start-debuggee-test-method" name="debug-test-method"/>
+    <target depends="init,-pre-debug-fix,compile-test-single" if="netbeans.home" name="-do-debug-fix-test">
+        <j2seproject1:nbjpdareload dir="${build.test.classes.dir}"/>
+    </target>
+    <target depends="init,-pre-debug-fix,-do-debug-fix-test" if="netbeans.home" name="debug-fix-test"/>
+    <!--
+                =========================
+                APPLET EXECUTION SECTION
+                =========================
+            -->
+    <target depends="init,compile-single" name="run-applet">
+        <fail unless="applet.url">Must select one file in the IDE or set applet.url</fail>
+        <j2seproject1:java classname="sun.applet.AppletViewer">
+            <customize>
+                <arg value="${applet.url}"/>
+            </customize>
+        </j2seproject1:java>
+    </target>
+    <!--
+                =========================
+                APPLET DEBUGGING  SECTION
+                =========================
+            -->
+    <target depends="init,compile-single" if="netbeans.home" name="-debug-start-debuggee-applet">
+        <fail unless="applet.url">Must select one file in the IDE or set applet.url</fail>
+        <j2seproject3:debug classname="sun.applet.AppletViewer">
+            <customizeDebuggee>
+                <arg value="${applet.url}"/>
+            </customizeDebuggee>
+        </j2seproject3:debug>
+    </target>
+    <target depends="init,compile-single,-debug-start-debugger,-debug-start-debuggee-applet" if="netbeans.home" name="debug-applet"/>
+    <!--
+                ===============
+                CLEANUP SECTION
+                ===============
+            -->
+    <target name="-deps-clean-init" unless="built-clean.properties">
+        <property location="${build.dir}/built-clean.properties" name="built-clean.properties"/>
+        <delete file="${built-clean.properties}" quiet="true"/>
+    </target>
+    <target if="already.built.clean.${basedir}" name="-warn-already-built-clean">
+        <echo level="warn" message="Cycle detected: java_modbusmaster was already built"/>
+    </target>
+    <target depends="init,-deps-clean-init" name="deps-clean" unless="no.deps">
+        <mkdir dir="${build.dir}"/>
+        <touch file="${built-clean.properties}" verbose="false"/>
+        <property file="${built-clean.properties}" prefix="already.built.clean."/>
+        <antcall target="-warn-already-built-clean"/>
+        <propertyfile file="${built-clean.properties}">
+            <entry key="${basedir}" value=""/>
+        </propertyfile>
+    </target>
+    <target depends="init" name="-do-clean">
+        <delete dir="${build.dir}"/>
+        <delete dir="${dist.jlink.output}"/>
+        <delete dir="${dist.dir}" followsymlinks="false" includeemptydirs="true"/>
+    </target>
+    <target name="-post-clean">
+        <!-- Empty placeholder for easier customization. -->
+        <!-- You can override this target in the ../build.xml file. -->
+    </target>
+    <target depends="init,deps-clean,-do-clean,-post-clean" description="Clean build products." name="clean"/>
+    <target name="-check-call-dep">
+        <property file="${call.built.properties}" prefix="already.built."/>
+        <condition property="should.call.dep">
+            <and>
+                <not>
+                    <isset property="already.built.${call.subproject}"/>
+                </not>
+                <available file="${call.script}"/>
+            </and>
+        </condition>
+    </target>
+    <target depends="-check-call-dep" if="should.call.dep" name="-maybe-call-dep">
+        <ant antfile="${call.script}" inheritall="false" target="${call.target}">
+            <propertyset>
+                <propertyref prefix="transfer."/>
+                <mapper from="transfer.*" to="*" type="glob"/>
+            </propertyset>
+        </ant>
+    </target>
+</project>
diff --git a/java_modbusmaster/nbproject/genfiles.properties b/java_modbusmaster/nbproject/genfiles.properties
new file mode 100644 (file)
index 0000000..17f9a58
--- /dev/null
@@ -0,0 +1,8 @@
+build.xml.data.CRC32=1872cd09
+build.xml.script.CRC32=4e4a81f7
+build.xml.stylesheet.CRC32=f85dc8f2@1.89.1.48
+# This file is used by a NetBeans-based IDE to track changes in generated files such as build-impl.xml.
+# Do not edit this file. You may delete it but then the IDE will never regenerate such files for you.
+nbproject/build-impl.xml.data.CRC32=1872cd09
+nbproject/build-impl.xml.script.CRC32=306010fb
+nbproject/build-impl.xml.stylesheet.CRC32=3a2fa800@1.89.1.48
diff --git a/java_modbusmaster/nbproject/project.properties b/java_modbusmaster/nbproject/project.properties
new file mode 100644 (file)
index 0000000..8eb24e2
--- /dev/null
@@ -0,0 +1,83 @@
+annotation.processing.enabled=true
+annotation.processing.enabled.in.editor=false
+annotation.processing.processor.options=
+annotation.processing.processors.list=
+annotation.processing.run.all.processors=true
+annotation.processing.source.output=${build.generated.sources.dir}/ap-source-output
+build.classes.dir=${build.dir}/classes
+build.classes.excludes=**/*.java,**/*.form
+# This directory is removed when the project is cleaned:
+build.dir=build
+build.generated.dir=${build.dir}/generated
+build.generated.sources.dir=${build.dir}/generated-sources
+# Only compile against the classpath explicitly listed here:
+build.sysclasspath=ignore
+build.test.classes.dir=${build.dir}/test/classes
+build.test.results.dir=${build.dir}/test/results
+# Uncomment to specify the preferred debugger connection transport:
+#debug.transport=dt_socket
+debug.classpath=\
+    ${run.classpath}
+debug.modulepath=\
+    ${run.modulepath}
+debug.test.classpath=\
+    ${run.test.classpath}
+debug.test.modulepath=\
+    ${run.test.modulepath}
+# This directory is removed when the project is cleaned:
+dist.dir=dist
+dist.jar=${dist.dir}/java_modbusmaster.jar
+dist.javadoc.dir=${dist.dir}/javadoc
+excludes=
+includes=**
+jar.compress=false
+javac.classpath=
+# Space-separated list of extra javac options
+javac.compilerargs=
+javac.deprecation=false
+javac.modulepath=
+javac.processormodulepath=
+javac.processorpath=\
+    ${javac.classpath}
+javac.source=1.7
+javac.target=1.7
+javac.test.classpath=\
+    ${javac.classpath}:\
+    ${build.classes.dir}
+javac.test.modulepath=\
+    ${javac.modulepath}
+javac.test.processorpath=\
+    ${javac.test.classpath}
+javadoc.additionalparam=
+javadoc.author=false
+javadoc.encoding=${source.encoding}
+javadoc.noindex=false
+javadoc.nonavbar=false
+javadoc.notree=false
+javadoc.private=false
+javadoc.splitindex=true
+javadoc.use=true
+javadoc.version=false
+javadoc.windowtitle=
+main.class=modbus.ModbusTest
+manifest.file=manifest.mf
+meta.inf.dir=${src.dir}/META-INF
+mkdist.disabled=false
+platform.active=default_platform
+run.classpath=\
+    ${javac.classpath}:\
+    ${build.classes.dir}
+# Space-separated list of JVM arguments used when running the project.
+# You may also define separate properties like run-sys-prop.name=value instead of -Dname=value.
+# To set system properties for unit tests define test-sys-prop.name=value:
+run.jvmargs=
+run.modulepath=\
+    ${javac.modulepath}
+run.test.classpath=\
+    ${javac.test.classpath}:\
+    ${build.test.classes.dir}
+run.test.modulepath=\
+    ${javac.test.modulepath}
+source.encoding=UTF-8
+src.dir=src
+test.src.dir=test
diff --git a/java_modbusmaster/nbproject/project.xml b/java_modbusmaster/nbproject/project.xml
new file mode 100644 (file)
index 0000000..4fb0c72
--- /dev/null
@@ -0,0 +1,15 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<project xmlns="http://www.netbeans.org/ns/project/1">
+    <type>org.netbeans.modules.java.j2seproject</type>
+    <configuration>
+        <data xmlns="http://www.netbeans.org/ns/j2se-project/3">
+            <name>java_modbusmaster</name>
+            <source-roots>
+                <root id="src.dir"/>
+            </source-roots>
+            <test-roots>
+                <root id="test.src.dir"/>
+            </test-roots>
+        </data>
+    </configuration>
+</project>
diff --git a/java_modbusmaster/src/modbus/ModbusTest.java b/java_modbusmaster/src/modbus/ModbusTest.java
new file mode 100644 (file)
index 0000000..d3ae87a
--- /dev/null
@@ -0,0 +1,195 @@
+
+package modbus;
+
+import modbus.frames.ModbusFrame;
+import at.htlkaindorf.mechatronik.serial.SimpleSerial;
+import gnu.io.SerialPort;
+import java.io.BufferedInputStream;
+import java.io.BufferedOutputStream;
+import java.io.IOException;
+import java.util.Arrays;
+import java.util.List;
+import modbus.frames.ModbusFrameReadCoil;
+import modbus.frames.ModbusFrameReadDiscreteInput;
+import modbus.frames.ModbusFrameReadHoldingRegisters;
+import modbus.frames.ModbusFrameReadInputRegisters;
+import modbus.frames.ModbusFrameWriteSingleCoil;
+import modbus.frames.ModbusFrameWriteMultipleCoils;
+import modbus.frames.ModbusFrameWriteMultipleRegisters;
+import modbus.frames.ModbusFrameWriteRegister;
+
+
+/**
+ *
+ * @author sx
+ */
+public class ModbusTest
+{
+  private SimpleSerial serial;
+  private BufferedInputStream is;
+  private BufferedOutputStream os;
+  byte [] lastResponse;
+
+
+  public ModbusTest (String port) throws Exception
+  {
+    serial = new SimpleSerial(port);
+    serial.open();
+    serial.setSerialPortParams(57600, SerialPort.DATABITS_8, SerialPort.STOPBITS_1, SerialPort.PARITY_NONE);
+    is = new BufferedInputStream(serial.getInputStream());
+    os = new BufferedOutputStream(serial.getOutputStream());
+  }
+
+  public void close ()
+  {
+    if (serial != null)
+      serial.close();
+  }
+  
+  
+  private void sendModbusFrame (ModbusFrame requestFrame) throws IOException
+  {
+    os.write(requestFrame.getSlaveAddress());
+    os.write(requestFrame.getFuctionCode());
+    byte [] data = requestFrame.getData();
+    if (data != null)
+      os.write(data);
+    os.write(requestFrame.getCrcBytes());
+    os.flush();
+    
+    System.out.print(String.format("request:  %02x %02x", requestFrame.getSlaveAddress(), requestFrame.getFuctionCode()));
+    for (byte b : data)
+      System.out.print(String.format(" %02x", b<0? b+256 : b));
+    byte [] ba = requestFrame.getCrcBytes();
+    for (byte b : ba)
+      System.out.print(String.format(" %02x", b<0? b+256 : b));
+    System.out.println();    
+  }
+
+  private void readResponse() throws InterruptedException, IOException
+  {
+    Thread.sleep(500);
+    if (is.available()>0)
+    {
+      byte [] data = new byte [is.available()];
+      is.read(data);
+      lastResponse = data;
+      //String s = new String (data);
+      //System.out.println(s);
+      System.out.print("response:");
+      for (byte b : data)
+        System.out.print(String.format(" %02x", b));
+      System.out.println();
+    }
+  }
+
+
+  public byte[] getLastResponse()
+  {
+    return lastResponse;
+  }
+  
+  public String getLastResponseString (int startIndex)
+  {
+    StringBuilder sb = new StringBuilder();
+    for (int i=startIndex; i<lastResponse.length; i++)
+    {
+      byte b = lastResponse[i];
+      if (b==0)
+        break;
+      if (b>=20 && b<127)
+        sb.append((char)b);
+      else
+        sb.append('.');
+    }
+    return sb.toString();
+  }
+  
+  public static void main(String[] args) throws Exception
+  {
+    List<String> ports = SimpleSerial.findAvailableComms();
+    for (String port : ports)
+    {
+      ModbusTest mt = new ModbusTest(port);
+      try
+      {
+        ModbusFrame requestFrame;
+        System.out.println("Modbus function code 0x01 (Read coil)");
+        System.out.println("-------------------------------------");
+        requestFrame = new ModbusFrameReadCoil(2, 0, 4);
+        mt.sendModbusFrame(requestFrame);
+        mt.readResponse();
+        System.out.println("");
+        
+        System.out.println("\nModbus function code 0x02 (Read discrete Input)");
+        System.out.println("-------------------------------------------------");
+        requestFrame = new ModbusFrameReadDiscreteInput(2, 0, 1);
+        mt.sendModbusFrame(requestFrame);
+        mt.readResponse();
+        System.out.println("");
+        
+        System.out.println("\nModbus function code 0x03 (Read holding register)");
+        System.out.println("--------------------------------------------------");
+        requestFrame = new ModbusFrameReadHoldingRegisters(2, 0, 5);
+        mt.sendModbusFrame(requestFrame);
+        mt.readResponse();
+        System.out.println("");
+        
+        System.out.println("\nModbus function code 0x04 (Read input register)");
+        System.out.println("example 1: read temperature from LM75A");
+        System.out.println("--------------------------------------------------");
+        requestFrame = new ModbusFrameReadInputRegisters(2, 0x30, 1);
+        mt.sendModbusFrame(requestFrame);
+        mt.readResponse();
+        System.out.println("");
+        
+        System.out.println("\nModbus function code 0x04 (Read input register)");
+        System.out.println("example 2: read version string");
+        System.out.println("--------------------------------------------------");
+        requestFrame = new ModbusFrameReadInputRegisters(2, 0xfff0, 16);
+        mt.sendModbusFrame(requestFrame);
+        mt.readResponse();
+        System.out.println("response as string: " + mt.getLastResponseString(3));
+        System.out.println("");
+
+        System.out.println("\nModbus function code 0x05 (Write single coil)");
+        System.out.println("-----------------------------------------------");
+        requestFrame = new ModbusFrameWriteSingleCoil(2, 2, true);
+        mt.sendModbusFrame(requestFrame);
+        mt.readResponse();
+        System.out.println("");
+        
+        System.out.println("\nModbus function code 0x06 (Write single (hold) register)");
+        System.out.println("----------------------------------------------------------");
+        requestFrame = new ModbusFrameWriteRegister(2, 2, 10);
+        mt.sendModbusFrame(requestFrame);
+        mt.readResponse();
+        System.out.println("");
+
+        System.out.println("\nModbus function code 0x0f (Write multiple coils)");
+        System.out.println("--------------------------------------------------");
+        boolean [] data = new boolean[4];
+        data[0] = false; data[1] = true; data[2] = true; data[3] = false;
+        requestFrame = new ModbusFrameWriteMultipleCoils(2, 0, data);
+        mt.sendModbusFrame(requestFrame);
+        mt.readResponse();
+        System.out.println("");
+
+        System.out.println("\nModbus function code 0x10 (Write multiple (hold) registers)");
+        System.out.println("-------------------------------------------------------------");
+        int [] regValues = new int[2];
+        regValues[0] = 0xffff; regValues[1] = 0xffff; 
+        requestFrame = new ModbusFrameWriteMultipleRegisters(2, 1, regValues);
+        mt.sendModbusFrame(requestFrame);
+        mt.readResponse();
+        System.out.println("");
+      }
+      finally
+      {
+        mt.close();
+      }
+    }  
+  }
+
+
+}
diff --git a/java_modbusmaster/src/modbus/frames/ModbusFrame.java b/java_modbusmaster/src/modbus/frames/ModbusFrame.java
new file mode 100644 (file)
index 0000000..8cdd146
--- /dev/null
@@ -0,0 +1,77 @@
+/*
+ * To change this template, choose Tools | Templates
+ * and open the template in the editor.
+ */
+package modbus.frames;
+
+import java.nio.ByteBuffer;
+
+
+/**
+ *
+ * @author steiner
+ */
+public abstract class ModbusFrame
+{
+  private final int slaveAddress;
+  private final int fuctionCode;
+  protected byte [] data;
+  private int crc;
+
+  public ModbusFrame (int slaveAddress, int fuctionCode)
+  {
+    this.slaveAddress = slaveAddress;
+    this.fuctionCode = fuctionCode;
+  }
+
+  public int getSlaveAddress()
+  {
+    return slaveAddress;
+  }
+
+  public int getFuctionCode()
+  {
+    return fuctionCode;
+  }
+
+  public byte[] getData()
+  {
+    return data;
+  }
+
+
+  private void updateCrc (int b)
+  {
+    updateCrc((byte)(b>127 ? (byte)(b)-256 : (byte)b) );
+  }
+  
+  private void updateCrc (byte b)
+  {
+    int x = b<0 ? b+256 : b;
+    crc = crc ^ x;
+    for (int i=0; i<8; i++)
+    {
+      if ((crc & 0x0001)==0x0001)
+        crc = (crc >> 1) ^ 0xa001;
+      else
+        crc = crc >> 1;
+    }
+  }
+  
+  public byte[] getCrcBytes()
+  {
+    crc = 0xffff;
+    updateCrc(slaveAddress);
+    updateCrc(fuctionCode);
+    if (data!=null)
+    {
+      for (byte b : data)
+        updateCrc(b);
+    }
+    byte[] rv = new byte[2];
+    rv[0] = (byte) (crc);
+    rv[1] = (byte) (crc >> 8);
+    return rv;
+  }
+}
diff --git a/java_modbusmaster/src/modbus/frames/ModbusFrameReadCoil.java b/java_modbusmaster/src/modbus/frames/ModbusFrameReadCoil.java
new file mode 100644 (file)
index 0000000..76892ea
--- /dev/null
@@ -0,0 +1,29 @@
+/*
+ * To change this template, choose Tools | Templates
+ * and open the template in the editor.
+ */
+package modbus.frames;
+
+
+/**
+ * ReadCoil.
+ * Sure-Board: Address 0..3, Quantity 1..4
+ *             Address:        3   2   1   0  
+ *             Function LED: PA3 PA2 PA1 PA0
+ *             Value: 1=LED on, 0=LED off 
+ * @author steiner
+ */
+public class ModbusFrameReadCoil extends ModbusFrame
+{
+  public ModbusFrameReadCoil(int slaveAddress, int address, int quantity)
+  {
+    super(slaveAddress, 0x01);
+    byte [] ba = new byte [4];
+    ba[0] = (byte)(address>>8); 
+    ba[1] = (byte)(address); 
+    ba[2] = (byte)(quantity>>8); 
+    ba[3] = (byte)(quantity); 
+    data = ba;
+  }
+  
+}
diff --git a/java_modbusmaster/src/modbus/frames/ModbusFrameReadDiscreteInput.java b/java_modbusmaster/src/modbus/frames/ModbusFrameReadDiscreteInput.java
new file mode 100644 (file)
index 0000000..bf7effa
--- /dev/null
@@ -0,0 +1,26 @@
+
+package modbus.frames;
+
+
+/**
+ * ReadDiscreteInput.
+ * SureBoard: Address 0..1, Quantity 1..2
+ *            Address:  1    0
+ *            Function: SW2  SW1
+ *            Value:    0=not pressed, 1=pressed
+ * @author steiner
+ */
+public class ModbusFrameReadDiscreteInput extends ModbusFrame
+{
+  public ModbusFrameReadDiscreteInput(int slaveAddress, int address, int quantity)
+  {
+    super(slaveAddress, 0x02);
+    byte [] ba = new byte [4];
+    ba[0] = (byte)(address>>8); 
+    ba[1] = (byte)(address); 
+    ba[2] = (byte)(quantity>>8); 
+    ba[3] = (byte)(quantity); 
+    data = ba;
+  }
+  
+}
diff --git a/java_modbusmaster/src/modbus/frames/ModbusFrameReadHoldingRegisters.java b/java_modbusmaster/src/modbus/frames/ModbusFrameReadHoldingRegisters.java
new file mode 100644 (file)
index 0000000..67426b8
--- /dev/null
@@ -0,0 +1,26 @@
+
+package modbus.frames;
+
+
+/**
+ * ReadDiscreteInput.
+ * SureBoard: Address 0..1, Quantity 1..2
+ *            Address:  1    0
+ *            Function: SW2  SW1
+ *            Value:    0=not pressed, 1=pressed
+ * @author steiner
+ */
+public class ModbusFrameReadHoldingRegisters extends ModbusFrame
+{
+  public ModbusFrameReadHoldingRegisters(int slaveAddress, int address, int quantity)
+  {
+    super(slaveAddress, 0x03);
+    byte [] ba = new byte [4];
+    ba[0] = (byte)(address>>8); 
+    ba[1] = (byte)(address); 
+    ba[2] = (byte)(quantity>>8); 
+    ba[3] = (byte)(quantity); 
+    data = ba;
+  }
+  
+}
diff --git a/java_modbusmaster/src/modbus/frames/ModbusFrameReadInputRegisters.java b/java_modbusmaster/src/modbus/frames/ModbusFrameReadInputRegisters.java
new file mode 100644 (file)
index 0000000..139ecb7
--- /dev/null
@@ -0,0 +1,29 @@
+/*
+ * To change this template, choose Tools | Templates
+ * and open the template in the editor.
+ */
+package modbus.frames;
+
+
+/**
+ * ReadCoil.
+ * Sure-Board: Address 0..3, Quantity 1..4
+ *             Address:        3   2   1   0  
+ *             Function LED: PA3 PA2 PA1 PA0
+ *             Value: 1=LED on, 0=LED off 
+ * @author steiner
+ */
+public class ModbusFrameReadInputRegisters extends ModbusFrame
+{
+  public ModbusFrameReadInputRegisters(int slaveAddress, int registerStartAddress, int quantity)
+  {
+    super(slaveAddress, 0x04);
+    byte [] ba = new byte [4];
+    ba[0] = (byte)(registerStartAddress>>8); 
+    ba[1] = (byte)(registerStartAddress); 
+    ba[2] = (byte)(quantity>>8); 
+    ba[3] = (byte)(quantity); 
+    data = ba;
+  }
+  
+}
diff --git a/java_modbusmaster/src/modbus/frames/ModbusFrameWriteMultipleCoils.java b/java_modbusmaster/src/modbus/frames/ModbusFrameWriteMultipleCoils.java
new file mode 100644 (file)
index 0000000..b37ee76
--- /dev/null
@@ -0,0 +1,36 @@
+
+package modbus.frames;
+
+
+/**
+ * Write multiple coils or discrete outputs.
+ * SureBoard: Address 0..1, Quantity 1..2
+ *            Address:  1    0
+ *            Function: 
+ *            Value:    0=not pressed, 1=pressed
+ * @author steiner
+ */
+public class ModbusFrameWriteMultipleCoils extends ModbusFrame
+{
+  public ModbusFrameWriteMultipleCoils (int slaveAddress, int address, boolean [] values)
+  {
+    super(slaveAddress, 0x0f);
+    int quantity = values.length;
+    int length = (quantity%8)==0 ? quantity/8 : quantity/8+1;
+    byte [] ba = new byte [5+length];
+    ba[0] = (byte)(address>>8); 
+    ba[1] = (byte)(address); 
+    ba[2] = (byte)(quantity>>8); 
+    ba[3] = (byte)(quantity);
+    ba[4] = (byte)(length);
+    for (int i=0; i<values.length; i++)
+    {
+      int dataByte = 0;
+      for (int j=0; j<8; j++, i++)
+        dataByte = (dataByte>>1) | ((i<values.length && values[i]) ? 0x80 : 0x00);
+      ba[5+i%8] = (byte)dataByte;
+    }
+    data = ba;
+  }
+  
+}
diff --git a/java_modbusmaster/src/modbus/frames/ModbusFrameWriteMultipleRegisters.java b/java_modbusmaster/src/modbus/frames/ModbusFrameWriteMultipleRegisters.java
new file mode 100644 (file)
index 0000000..70d22e4
--- /dev/null
@@ -0,0 +1,36 @@
+
+package modbus.frames;
+
+
+/**
+ * Write multiple registers.
+ * SureBoard: 
+ * @author steiner
+ */
+public class ModbusFrameWriteMultipleRegisters extends ModbusFrame
+{
+  public ModbusFrameWriteMultipleRegisters (int slaveAddress, int address, int [] values)
+  {
+    super(slaveAddress, 0x10);
+    if (address<0 || address>0xffff)
+        throw new RuntimeException("address out of range 0..65535");
+    
+    int quantity = values.length;
+    int length = quantity*2;
+    byte [] ba = new byte [5+length];
+    ba[0] = (byte)(address>>8); 
+    ba[1] = (byte)(address); 
+    ba[2] = (byte)(quantity>>8); 
+    ba[3] = (byte)(quantity);
+    ba[4] = (byte)(length);
+    for (int i=0; i<values.length; i++)
+    {
+      if (values[i]<0 || values[i]>0xffff)
+        throw new RuntimeException("value[" + i + "] out of range 0..65535");
+      ba[2*i+5] = (byte)(values[i]>>8);
+      ba[2*i+1+5] = (byte)(values[i]&0xff);
+    }
+    data = ba;
+  }
+  
+}
diff --git a/java_modbusmaster/src/modbus/frames/ModbusFrameWriteRegister.java b/java_modbusmaster/src/modbus/frames/ModbusFrameWriteRegister.java
new file mode 100644 (file)
index 0000000..73717ac
--- /dev/null
@@ -0,0 +1,34 @@
+/*
+ * To change this template, choose Tools | Templates
+ * and open the template in the editor.
+ */
+package modbus.frames;
+
+
+/**
+ * ReadCoil.
+ * Sure-Board: Address 0..3, Value true/false
+ *             Address:        3   2   1   0  
+ *             Function LED: PA3 PA2 PA1 PA0
+ *             Value: true=LED on, false=LED off
+ * @author steiner
+ */
+public class ModbusFrameWriteRegister extends ModbusFrame
+{
+  public ModbusFrameWriteRegister(int slaveAddress, int address, int value)
+  {
+    super(slaveAddress, 0x06);
+    if (address<0 || address>0xffff)
+      throw new RuntimeException("address out of range");
+    if (value<0 || value>0xffff)
+      throw new RuntimeException("value out of range");
+
+    byte [] ba = new byte [4];
+    ba[0] = (byte)(address>>8); 
+    ba[1] = (byte)(address); 
+    ba[2] = (byte)(value>>8); 
+    ba[3] = (byte)(value); 
+    data = ba;
+  }
+  
+}
diff --git a/java_modbusmaster/src/modbus/frames/ModbusFrameWriteSingleCoil.java b/java_modbusmaster/src/modbus/frames/ModbusFrameWriteSingleCoil.java
new file mode 100644 (file)
index 0000000..8a24f9a
--- /dev/null
@@ -0,0 +1,29 @@
+/*
+ * To change this template, choose Tools | Templates
+ * and open the template in the editor.
+ */
+package modbus.frames;
+
+
+/**
+ * ReadCoil.
+ * Sure-Board: Address 0..3, Value true/false
+ *             Address:        3   2   1   0  
+ *             Function LED: PA3 PA2 PA1 PA0
+ *             Value: true=LED on, false=LED off
+ * @author steiner
+ */
+public class ModbusFrameWriteSingleCoil extends ModbusFrame
+{
+  public ModbusFrameWriteSingleCoil(int slaveAddress, int address, boolean on)
+  {
+    super(slaveAddress, 0x05);
+    byte [] ba = new byte [4];
+    ba[0] = (byte)(address>>8); 
+    ba[1] = (byte)(address); 
+    ba[2] = (byte)(on ? 0xff : 0); 
+    ba[3] = 0; 
+    data = ba;
+  }
+  
+}
diff --git a/sure_modbusslave/Makefile b/sure_modbusslave/Makefile
new file mode 100644 (file)
index 0000000..9fd60f8
--- /dev/null
@@ -0,0 +1,133 @@
+#
+#  There exist several targets which are by default empty and which can be 
+#  used for execution of your targets. These targets are usually executed 
+#  before and after some main targets. They are: 
+#
+#     .build-pre:              called before 'build' target
+#     .build-post:             called after 'build' target
+#     .clean-pre:              called before 'clean' target
+#     .clean-post:             called after 'clean' target
+#     .clobber-pre:            called before 'clobber' target
+#     .clobber-post:           called after 'clobber' target
+#     .all-pre:                called before 'all' target
+#     .all-post:               called after 'all' target
+#     .help-pre:               called before 'help' target
+#     .help-post:              called after 'help' target
+#
+#  Targets beginning with '.' are not intended to be called on their own.
+#
+#  Main targets can be executed directly, and they are:
+#  
+#     build                    build a specific configuration
+#     clean                    remove built files from a configuration
+#     clobber                  remove all built files
+#     all                      build all configurations
+#     help                     print help mesage
+#  
+#  Targets .build-impl, .clean-impl, .clobber-impl, .all-impl, and
+#  .help-impl are implemented in nbproject/makefile-impl.mk.
+#
+#  Available make variables:
+#
+#     CND_BASEDIR                base directory for relative paths
+#     CND_DISTDIR                default top distribution directory (build artifacts)
+#     CND_BUILDDIR               default top build directory (object files, ...)
+#     CONF                       name of current configuration
+#     CND_PLATFORM_${CONF}       platform name (current configuration)
+#     CND_ARTIFACT_DIR_${CONF}   directory of build artifact (current configuration)
+#     CND_ARTIFACT_NAME_${CONF}  name of build artifact (current configuration)
+#     CND_ARTIFACT_PATH_${CONF}  path to build artifact (current configuration)
+#     CND_PACKAGE_DIR_${CONF}    directory of package (current configuration)
+#     CND_PACKAGE_NAME_${CONF}   name of package (current configuration)
+#     CND_PACKAGE_PATH_${CONF}   path to package (current configuration)
+#
+# NOCDDL
+
+
+# Environment 
+MKDIR=mkdir
+CP=cp
+CCADMIN=CCadmin
+
+
+# build
+build: .build-post
+
+.build-pre:
+# Add your pre 'build' code here...
+
+.build-post: .build-impl
+# Add your post 'build' code here...
+       echo $(CND_BASEDIR)/$(CND_ARTIFACT_PATH_Release)
+       avr-objcopy -O ihex -R .eeprom -R .eesafe  $(CND_BASEDIR)/$(CND_ARTIFACT_PATH_Release)  $(CND_BASEDIR)/$(CND_ARTIFACT_PATH_Release).hex
+       avr-objcopy --no-change-warnings -j .eeprom --change-section-lma .eeprom=0 -O ihex  $(CND_BASEDIR)/$(CND_ARTIFACT_PATH_Release)  $(CND_BASEDIR)/$(CND_ARTIFACT_PATH_Release).eep.hex
+       avr-objdump -h -S  $(CND_BASEDIR)/$(CND_ARTIFACT_PATH_Release) >  $(CND_BASEDIR)/$(CND_ARTIFACT_PATH_Release).lss
+       avr-size --mcu=atmega16 --format=avr  $(CND_BASEDIR)/$(CND_ARTIFACT_PATH_Release)
+
+# clean
+clean: .clean-post
+
+.clean-pre:
+# Add your pre 'clean' code here...
+
+.clean-post: .clean-impl
+# Add your post 'clean' code here...
+       @-test -d `pwd`/dist || mkdir `pwd`/dist
+       -rm -f `pwd`/dist/*
+
+# clobber
+clobber: .clobber-post
+
+.clobber-pre:
+# Add your pre 'clobber' code here...
+
+.clobber-post: .clobber-impl
+# Add your post 'clobber' code here...
+
+
+# all
+all: .all-post
+
+.all-pre:
+# Add your pre 'all' code here...
+
+.all-post: .all-impl
+# Add your post 'all' code here...
+
+
+# build tests
+build-tests: .build-tests-post
+
+.build-tests-pre:
+# Add your pre 'build-tests' code here...
+
+.build-tests-post: .build-tests-impl
+# Add your post 'build-tests' code here...
+
+
+# run tests
+test: .test-post
+
+.test-pre:
+# Add your pre 'test' code here...
+
+.test-post: .test-impl
+# Add your post 'test' code here...
+
+
+# help
+help: .help-post
+
+.help-pre:
+# Add your pre 'help' code here...
+
+.help-post: .help-impl
+# Add your post 'help' code here...
+
+
+
+# include project implementation makefile
+include nbproject/Makefile-impl.mk
+
+# include project make variables
+include nbproject/Makefile-variables.mk
diff --git a/sure_modbusslave/nbproject/Makefile-Release.mk b/sure_modbusslave/nbproject/Makefile-Release.mk
new file mode 100644 (file)
index 0000000..ff3c2e3
--- /dev/null
@@ -0,0 +1,102 @@
+#
+# Generated Makefile - do not edit!
+#
+# Edit the Makefile in the project folder instead (../Makefile). Each target
+# has a -pre and a -post target defined where you can add customized code.
+#
+# This makefile implements configuration specific macros and targets.
+
+
+# Environment
+MKDIR=mkdir
+CP=cp
+GREP=grep
+NM=nm
+CCADMIN=CCadmin
+RANLIB=ranlib
+CC=avr-gcc
+CCC=avr-g++
+CXX=avr-g++
+FC=gfortran
+AS=as
+
+# Macros
+CND_PLATFORM=GNU-AVR-Linux-x86
+CND_DLIB_EXT=so
+CND_CONF=Release
+CND_DISTDIR=dist
+CND_BUILDDIR=build
+
+# Include project Makefile
+include Makefile
+
+# Object Directory
+OBJECTDIR=${CND_BUILDDIR}/${CND_CONF}/${CND_PLATFORM}
+
+# Object Files
+OBJECTFILES= \
+       ${OBJECTDIR}/src/app.o \
+       ${OBJECTDIR}/src/main.o \
+       ${OBJECTDIR}/src/sys.o \
+       ${OBJECTDIR}/src/twi.o
+
+
+# C Compiler Flags
+CFLAGS=-Wall -Os -mmcu=atmega16
+
+# CC Compiler Flags
+CCFLAGS=
+CXXFLAGS=
+
+# Fortran Compiler Flags
+FFLAGS=
+
+# Assembler Flags
+ASFLAGS=
+
+# Link Libraries and Options
+LDLIBSOPTIONS=
+
+# Build Targets
+.build-conf: ${BUILD_SUBPROJECTS}
+       "${MAKE}"  -f nbproject/Makefile-${CND_CONF}.mk ${CND_DISTDIR}/sure.elf
+
+${CND_DISTDIR}/sure.elf: ${OBJECTFILES}
+       ${MKDIR} -p ${CND_DISTDIR}
+       ${LINK.c} -o ${CND_DISTDIR}/sure.elf ${OBJECTFILES} ${LDLIBSOPTIONS} -mmcu=atmega16 -Wl,-Map=${CND_DISTDIR}/asuro.map,--cref
+
+${OBJECTDIR}/src/app.o: src/app.c 
+       ${MKDIR} -p ${OBJECTDIR}/src
+       ${RM} $@.d
+       $(COMPILE.c) -O2 -Wall -s -DNETBEANS_ATMEGA16 -Wall -Os -mmcu=atmega16 -MMD -MP -MF $@.d -o ${OBJECTDIR}/src/app.o src/app.c
+
+${OBJECTDIR}/src/main.o: src/main.c 
+       ${MKDIR} -p ${OBJECTDIR}/src
+       ${RM} $@.d
+       $(COMPILE.c) -O2 -Wall -s -DNETBEANS_ATMEGA16 -Wall -Os -mmcu=atmega16 -MMD -MP -MF $@.d -o ${OBJECTDIR}/src/main.o src/main.c
+
+${OBJECTDIR}/src/sys.o: src/sys.c 
+       ${MKDIR} -p ${OBJECTDIR}/src
+       ${RM} $@.d
+       $(COMPILE.c) -O2 -Wall -s -DNETBEANS_ATMEGA16 -Wall -Os -mmcu=atmega16 -MMD -MP -MF $@.d -o ${OBJECTDIR}/src/sys.o src/sys.c
+
+${OBJECTDIR}/src/twi.o: src/twi.c 
+       ${MKDIR} -p ${OBJECTDIR}/src
+       ${RM} $@.d
+       $(COMPILE.c) -O2 -Wall -s -DNETBEANS_ATMEGA16 -Wall -Os -mmcu=atmega16 -MMD -MP -MF $@.d -o ${OBJECTDIR}/src/twi.o src/twi.c
+
+# Subprojects
+.build-subprojects:
+
+# Clean Targets
+.clean-conf: ${CLEAN_SUBPROJECTS}
+       ${RM} -r ${CND_BUILDDIR}/${CND_CONF}
+       ${RM} ${CND_DISTDIR}/sure.elf
+
+# Subprojects
+.clean-subprojects:
+
+# Enable dependency checking
+.dep.inc: .depcheck-impl
+
+include .dep.inc
diff --git a/sure_modbusslave/nbproject/Makefile-impl.mk b/sure_modbusslave/nbproject/Makefile-impl.mk
new file mode 100644 (file)
index 0000000..37be8ce
--- /dev/null
@@ -0,0 +1,133 @@
+# 
+# Generated Makefile - do not edit! 
+# 
+# Edit the Makefile in the project folder instead (../Makefile). Each target
+# has a pre- and a post- target defined where you can add customization code.
+#
+# This makefile implements macros and targets common to all configurations.
+#
+# NOCDDL
+
+
+# Building and Cleaning subprojects are done by default, but can be controlled with the SUB
+# macro. If SUB=no, subprojects will not be built or cleaned. The following macro
+# statements set BUILD_SUB-CONF and CLEAN_SUB-CONF to .build-reqprojects-conf
+# and .clean-reqprojects-conf unless SUB has the value 'no'
+SUB_no=NO
+SUBPROJECTS=${SUB_${SUB}}
+BUILD_SUBPROJECTS_=.build-subprojects
+BUILD_SUBPROJECTS_NO=
+BUILD_SUBPROJECTS=${BUILD_SUBPROJECTS_${SUBPROJECTS}}
+CLEAN_SUBPROJECTS_=.clean-subprojects
+CLEAN_SUBPROJECTS_NO=
+CLEAN_SUBPROJECTS=${CLEAN_SUBPROJECTS_${SUBPROJECTS}}
+
+
+# Project Name
+PROJECTNAME=sure_modbusslave
+
+# Active Configuration
+DEFAULTCONF=Release
+CONF=${DEFAULTCONF}
+
+# All Configurations
+ALLCONFS=Release 
+
+
+# build
+.build-impl: .build-pre .validate-impl .depcheck-impl
+       @#echo "=> Running $@... Configuration=$(CONF)"
+       "${MAKE}" -f nbproject/Makefile-${CONF}.mk QMAKE=${QMAKE} SUBPROJECTS=${SUBPROJECTS} .build-conf
+
+
+# clean
+.clean-impl: .clean-pre .validate-impl .depcheck-impl
+       @#echo "=> Running $@... Configuration=$(CONF)"
+       "${MAKE}" -f nbproject/Makefile-${CONF}.mk QMAKE=${QMAKE} SUBPROJECTS=${SUBPROJECTS} .clean-conf
+
+
+# clobber 
+.clobber-impl: .clobber-pre .depcheck-impl
+       @#echo "=> Running $@..."
+       for CONF in ${ALLCONFS}; \
+       do \
+           "${MAKE}" -f nbproject/Makefile-$${CONF}.mk QMAKE=${QMAKE} SUBPROJECTS=${SUBPROJECTS} .clean-conf; \
+       done
+
+# all 
+.all-impl: .all-pre .depcheck-impl
+       @#echo "=> Running $@..."
+       for CONF in ${ALLCONFS}; \
+       do \
+           "${MAKE}" -f nbproject/Makefile-$${CONF}.mk QMAKE=${QMAKE} SUBPROJECTS=${SUBPROJECTS} .build-conf; \
+       done
+
+# build tests
+.build-tests-impl: .build-impl .build-tests-pre
+       @#echo "=> Running $@... Configuration=$(CONF)"
+       "${MAKE}" -f nbproject/Makefile-${CONF}.mk SUBPROJECTS=${SUBPROJECTS} .build-tests-conf
+
+# run tests
+.test-impl: .build-tests-impl .test-pre
+       @#echo "=> Running $@... Configuration=$(CONF)"
+       "${MAKE}" -f nbproject/Makefile-${CONF}.mk SUBPROJECTS=${SUBPROJECTS} .test-conf
+
+# dependency checking support
+.depcheck-impl:
+       @echo "# This code depends on make tool being used" >.dep.inc
+       @if [ -n "${MAKE_VERSION}" ]; then \
+           echo "DEPFILES=\$$(wildcard \$$(addsuffix .d, \$${OBJECTFILES}))" >>.dep.inc; \
+           echo "ifneq (\$${DEPFILES},)" >>.dep.inc; \
+           echo "include \$${DEPFILES}" >>.dep.inc; \
+           echo "endif" >>.dep.inc; \
+       else \
+           echo ".KEEP_STATE:" >>.dep.inc; \
+           echo ".KEEP_STATE_FILE:.make.state.\$${CONF}" >>.dep.inc; \
+       fi
+
+# configuration validation
+.validate-impl:
+       @if [ ! -f nbproject/Makefile-${CONF}.mk ]; \
+       then \
+           echo ""; \
+           echo "Error: can not find the makefile for configuration '${CONF}' in project ${PROJECTNAME}"; \
+           echo "See 'make help' for details."; \
+           echo "Current directory: " `pwd`; \
+           echo ""; \
+       fi
+       @if [ ! -f nbproject/Makefile-${CONF}.mk ]; \
+       then \
+           exit 1; \
+       fi
+
+
+# help
+.help-impl: .help-pre
+       @echo "This makefile supports the following configurations:"
+       @echo "    ${ALLCONFS}"
+       @echo ""
+       @echo "and the following targets:"
+       @echo "    build  (default target)"
+       @echo "    clean"
+       @echo "    clobber"
+       @echo "    all"
+       @echo "    help"
+       @echo ""
+       @echo "Makefile Usage:"
+       @echo "    make [CONF=<CONFIGURATION>] [SUB=no] build"
+       @echo "    make [CONF=<CONFIGURATION>] [SUB=no] clean"
+       @echo "    make [SUB=no] clobber"
+       @echo "    make [SUB=no] all"
+       @echo "    make help"
+       @echo ""
+       @echo "Target 'build' will build a specific configuration and, unless 'SUB=no',"
+       @echo "    also build subprojects."
+       @echo "Target 'clean' will clean a specific configuration and, unless 'SUB=no',"
+       @echo "    also clean subprojects."
+       @echo "Target 'clobber' will remove all built files from all configurations and,"
+       @echo "    unless 'SUB=no', also from subprojects."
+       @echo "Target 'all' will will build all configurations and, unless 'SUB=no',"
+       @echo "    also build subprojects."
+       @echo "Target 'help' prints this message."
+       @echo ""
+
diff --git a/sure_modbusslave/nbproject/Makefile-variables.mk b/sure_modbusslave/nbproject/Makefile-variables.mk
new file mode 100644 (file)
index 0000000..491dab2
--- /dev/null
@@ -0,0 +1,27 @@
+#
+# Generated - do not edit!
+#
+# NOCDDL
+#
+CND_BASEDIR=`pwd`
+CND_BUILDDIR=build
+CND_DISTDIR=dist
+# Release configuration
+CND_PLATFORM_Release=GNU-AVR-Linux-x86
+CND_ARTIFACT_DIR_Release=dist
+CND_ARTIFACT_NAME_Release=sure.elf
+CND_ARTIFACT_PATH_Release=dist/sure.elf
+CND_PACKAGE_DIR_Release=dist/Release/GNU-AVR-Linux-x86/package
+CND_PACKAGE_NAME_Release=suremodbusslave.tar
+CND_PACKAGE_PATH_Release=dist/Release/GNU-AVR-Linux-x86/package/suremodbusslave.tar
+#
+# include compiler specific variables
+#
+# dmake command
+ROOT:sh = test -f nbproject/private/Makefile-variables.mk || \
+       (mkdir -p nbproject/private && touch nbproject/private/Makefile-variables.mk)
+#
+# gmake command
+.PHONY: $(shell test -f nbproject/private/Makefile-variables.mk || (mkdir -p nbproject/private && touch nbproject/private/Makefile-variables.mk))
+#
+include nbproject/private/Makefile-variables.mk
diff --git a/sure_modbusslave/nbproject/Package-Release.bash b/sure_modbusslave/nbproject/Package-Release.bash
new file mode 100644 (file)
index 0000000..a01d43b
--- /dev/null
@@ -0,0 +1,75 @@
+#!/bin/bash -x
+
+#
+# Generated - do not edit!
+#
+
+# Macros
+TOP=`pwd`
+CND_PLATFORM=GNU-AVR-Linux-x86
+CND_CONF=Release
+CND_DISTDIR=dist
+CND_BUILDDIR=build
+NBTMPDIR=${CND_BUILDDIR}/${CND_CONF}/${CND_PLATFORM}/tmp-packaging
+TMPDIRNAME=tmp-packaging
+OUTPUT_PATH=${CND_DISTDIR}/sure.elf
+OUTPUT_BASENAME=sure.elf
+PACKAGE_TOP_DIR=suremodbusslave/
+
+# Functions
+function checkReturnCode
+{
+    rc=$?
+    if [ $rc != 0 ]
+    then
+        exit $rc
+    fi
+}
+function makeDirectory
+# $1 directory path
+# $2 permission (optional)
+{
+    mkdir -p "$1"
+    checkReturnCode
+    if [ "$2" != "" ]
+    then
+      chmod $2 "$1"
+      checkReturnCode
+    fi
+}
+function copyFileToTmpDir
+# $1 from-file path
+# $2 to-file path
+# $3 permission
+{
+    cp "$1" "$2"
+    checkReturnCode
+    if [ "$3" != "" ]
+    then
+        chmod $3 "$2"
+        checkReturnCode
+    fi
+}
+
+# Setup
+cd "${TOP}"
+mkdir -p ${CND_DISTDIR}/${CND_CONF}/${CND_PLATFORM}/package
+rm -rf ${NBTMPDIR}
+mkdir -p ${NBTMPDIR}
+
+# Copy files and create directories and links
+cd "${TOP}"
+makeDirectory "${NBTMPDIR}/suremodbusslave/bin"
+copyFileToTmpDir "${OUTPUT_PATH}" "${NBTMPDIR}/${PACKAGE_TOP_DIR}bin/${OUTPUT_BASENAME}" 0755
+
+
+# Generate tar file
+cd "${TOP}"
+rm -f ${CND_DISTDIR}/${CND_CONF}/${CND_PLATFORM}/package/suremodbusslave.tar
+cd ${NBTMPDIR}
+tar -vcf ../../../../${CND_DISTDIR}/${CND_CONF}/${CND_PLATFORM}/package/suremodbusslave.tar *
+checkReturnCode
+
+# Cleanup
+cd "${TOP}"
+rm -rf ${NBTMPDIR}
diff --git a/sure_modbusslave/nbproject/configurations.xml b/sure_modbusslave/nbproject/configurations.xml
new file mode 100644 (file)
index 0000000..b13401a
--- /dev/null
@@ -0,0 +1,85 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<configurationDescriptor version="88">
+  <logicalFolder name="root" displayName="root" projectFiles="true" kind="ROOT">
+    <logicalFolder name="HeaderFiles"
+                   displayName="Header Files"
+                   projectFiles="true">
+      <itemPath>src/app.h</itemPath>
+      <itemPath>src/global.h</itemPath>
+      <itemPath>src/sys.h</itemPath>
+      <itemPath>src/twi.h</itemPath>
+    </logicalFolder>
+    <logicalFolder name="ResourceFiles"
+                   displayName="Resource Files"
+                   projectFiles="true">
+    </logicalFolder>
+    <logicalFolder name="SourceFiles"
+                   displayName="Source Files"
+                   projectFiles="true">
+      <itemPath>src/app.c</itemPath>
+      <itemPath>src/main.c</itemPath>
+      <itemPath>src/sys.c</itemPath>
+      <itemPath>src/twi.c</itemPath>
+    </logicalFolder>
+    <logicalFolder name="TestFiles"
+                   displayName="Test Files"
+                   projectFiles="false"
+                   kind="TEST_LOGICAL_FOLDER">
+    </logicalFolder>
+    <logicalFolder name="ExternalFiles"
+                   displayName="Important Files"
+                   projectFiles="false"
+                   kind="IMPORTANT_FILES_FOLDER">
+      <itemPath>Makefile</itemPath>
+    </logicalFolder>
+  </logicalFolder>
+  <projectmakefile>Makefile</projectmakefile>
+  <confs>
+    <conf name="Release" type="1">
+      <toolsSet>
+        <remote-sources-mode>LOCAL_SOURCES</remote-sources-mode>
+        <compilerSet>GNU-AVR|GNU</compilerSet>
+      </toolsSet>
+      <compileType>
+        <cTool>
+          <developmentMode>5</developmentMode>
+          <stripSymbols>true</stripSymbols>
+          <commandLine>-Wall -Os -mmcu=atmega16</commandLine>
+          <preprocessorList>
+            <Elem>NETBEANS_ATMEGA16</Elem>
+          </preprocessorList>
+          <warningLevel>2</warningLevel>
+        </cTool>
+        <ccTool>
+          <developmentMode>5</developmentMode>
+        </ccTool>
+        <fortranCompilerTool>
+          <developmentMode>5</developmentMode>
+        </fortranCompilerTool>
+        <asmTool>
+          <developmentMode>5</developmentMode>
+        </asmTool>
+        <linkerTool>
+          <output>${CND_DISTDIR}/sure.elf</output>
+          <commandLine>-mmcu=atmega16 -Wl,-Map=${CND_DISTDIR}/asuro.map,--cref</commandLine>
+        </linkerTool>
+      </compileType>
+      <item path="src/app.c" ex="false" tool="0" flavor2="0">
+      </item>
+      <item path="src/app.h" ex="false" tool="3" flavor2="0">
+      </item>
+      <item path="src/global.h" ex="false" tool="3" flavor2="0">
+      </item>
+      <item path="src/main.c" ex="false" tool="0" flavor2="0">
+      </item>
+      <item path="src/sys.c" ex="false" tool="0" flavor2="0">
+      </item>
+      <item path="src/sys.h" ex="false" tool="3" flavor2="0">
+      </item>
+      <item path="src/twi.c" ex="false" tool="0" flavor2="0">
+      </item>
+      <item path="src/twi.h" ex="false" tool="3" flavor2="0">
+      </item>
+    </conf>
+  </confs>
+</configurationDescriptor>
diff --git a/sure_modbusslave/nbproject/project.xml b/sure_modbusslave/nbproject/project.xml
new file mode 100644 (file)
index 0000000..16dfa40
--- /dev/null
@@ -0,0 +1,21 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<project xmlns="http://www.netbeans.org/ns/project/1">
+    <type>org.netbeans.modules.cnd.makeproject</type>
+    <configuration>
+        <data xmlns="http://www.netbeans.org/ns/make-project/1">
+            <name>sure_modbusslave</name>
+            <c-extensions>c</c-extensions>
+            <cpp-extensions/>
+            <header-extensions>h</header-extensions>
+            <sourceEncoding>UTF-8</sourceEncoding>
+            <make-dep-projects/>
+            <sourceRootList/>
+            <confList>
+                <confElem>
+                    <name>Release</name>
+                    <type>1</type>
+                </confElem>
+            </confList>
+        </data>
+    </configuration>
+</project>
diff --git a/sure_modbusslave/released/readme b/sure_modbusslave/released/readme
new file mode 100644 (file)
index 0000000..44431a0
--- /dev/null
@@ -0,0 +1,153 @@
+Version: V1.6(10) (Jan  9 2014 07:59:39)
+Hex-File: https://www.htl-mechatronik.at/svn/modbus/sure_modbusslave/released/sure.elf.hex?p=22
+
+Serial interface: 57600 Bit/s, 8N2
+Subversion revision: 22
+Committed by: SX
+Implementation remarks: none
+Deviation from Modbus protocol
+  MODBUS over serial line specification and implementation guide V1.02
+  2.5.1.1 MODBUS message RTU framing: 
+    T1.5 = 2.8ms instead of 287us (11/57600*1.5=287us)
+    T3.5 = 6.8ms instead of 668us (11/57600*3.5=668us)
+  
+-----------------------------------------------------------------------------------------------
+
+Read coils (0x01): 4 LEDs PA0, PA1, PA2 and PA3
+  Address 0..3, Quantity 1..4
+    Address 0: LED PA0  (1=LED on, 0=LED off)
+    Address 1: LED PA1  (1=LED on, 0=LED off)
+    Address 2: LED PA2  (1=LED on, 0=LED off)
+    Address 3: LED PA3  (1=LED on, 0=LED off)
+
+-----------------------------------------------------------------------------------------------
+
+Read discrete inputs (0x02): push buttons SW1 and SW2
+  Address 0..1, Quantity 1..2
+    Address 0: SW1  (0=not pressed, 1=pressed)
+    Address 1: SW1  (0=not pressed, 1=pressed)
+
+-----------------------------------------------------------------------------------------------
+
+Read holding registers (0x03): read back registers for controlling the 7-segment display
+  Address: 0..4
+    Address 0: last written value to hold register addresss 0, 1 or 2
+    Address 1: last written value to hold register addresss 0, 1 or 2
+    Address 2: last written value to hold register addresss 0, 1 or 2
+    Address 3: 7-segement code for digit 3 and 2 (high byte, low byte)
+    Address 4: 7-segement code for digit 1 and 0 (high byte, low byte)
+
+  7-segment code: 0x80->point, 0x01->led a, 0x02->led b, ... 0x40->led g
+
+-----------------------------------------------------------------------------------------------
+
+Read input register (0x04): Atmega I/O register, temperature sensor, version string
+  Address: 0..0x3f, 0xfff0..0xffff
+    Address 0x00 .. 0x2f -> Atmega16 I/O registers (two 8 bit registers combined to 16 bit)
+                            example 1: Atmega I/O register TCNT1 on $4c -> modbus address 0x26
+                            example 2: Atmega I/O register PINC on $33 -> high byte of modbus address 0x19
+
+    Address 0x30 .. 0x33 -> LM75A registers  (value 0x7fff -> unvalid)
+                            modbus address 0x30: value/256 -> temperature in celsius degree (two's complement)
+    Address 0xfff0..0xffff -> version string of this software -> "V1.6(10) (Jan  9 2014 07:59:39)"
+
+-----------------------------------------------------------------------------------------------
+
+Write single coil (0x05)
+  Address: 0..3, value: 0x0000 or 0xff00
+    Address 0: LED PA0  (0xff00=LED on, 0x0000=LED off)
+    Address 1: LED PA1  (0xff00=LED on, 0x0000=LED off)
+    Address 2: LED PA2  (0xff00=LED on, 0x0000=LED off)
+    Address 3: LED PA3  (0xff00=LED on, 0x0000=LED off)
+
+----------------------------------------------------------------------------------------------
+
+Write single (hold) register (0x06): set values on 7-segment display
+  Address: 0..4
+    Address 0: 7-segment set value and show in hex format ("0000" .. "FFFF")
+    Address 1: 7-segment set value and show in unsigned decimal format "   0" .. "9999")
+    Address 2: 7-segment set Value and show in signed decimal format ("-999" .. "9999")
+    Address 3: 7-segement set digit 3 and 2 (value high byte, value low byte)
+    Address 4: 7-segement set digit 1 and 0 (value high byte, value low byte)
+
+----------------------------------------------------------------------------------------------
+
+Write multiple coils (0x0f): set one or more LEDs (one bit in value for one LED)
+  Address: 0..3, Quantity 1..4 (address+quantity<=4)
+    Address 0: LED PA0  (1=LED on, 0=LED off)
+    Address 1: LED PA1  (1=LED on, 0=LED off)
+    Address 2: LED PA2  (1=LED on, 0=LED off)
+    Address 3: LED PA3  (1=LED on, 0=LED off)
+
+----------------------------------------------------------------------------------------------
+
+Write multiple (hold) registers (0x10): set values on 7-segment display
+  Address: 0..4
+    Address 0: 7-segment set value and show in hex format ("0000" .. "FFFF")
+    Address 1: 7-segment set value and show in unsigned decimal format "   0" .. "9999")
+    Address 2: 7-segment set Value and show in signed decimal format ("-999" .. "9999")
+    Address 3: 7-segement set digit 3 and 2 (value high byte, value low byte)
+    Address 4: 7-segement set digit 1 and 0 (value high byte, value low byte)
+
+----------------------------------------------------------------------------------------------
+
+
+Examples:
+
+Modbus function code 0x01 (Read coil)
+-------------------------------------
+request:  02 01 00 00 00 04 3d fa
+response: 02 01 01 00 51 cc
+
+
+Modbus function code 0x02 (Read discrete Input)
+-------------------------------------------------
+request:  02 02 00 00 00 01 b9 f9
+response: 02 02 01 00 a1 cc
+
+
+Modbus function code 0x03 (Read holding register)
+--------------------------------------------------
+request:  02 03 00 00 00 05 85 fa
+response: 02 03 0a 00 00 00 00 00 00 00 00 00 00 ff ff ff ff ff ff ff ff ff ff 3b be
+
+
+Modbus function code 0x04 (Read input register)
+example 1: read temperature from LM75A
+--------------------------------------------------
+request:  02 04 00 30 00 01 31 f6
+response: 02 04 02 17 40 00 00 44 e4
+
+
+Modbus function code 0x04 (Read input register)
+example 2: read version string
+--------------------------------------------------
+request:  02 04 ff f0 00 10 c1 d2
+response: 02 04 20 56 31 2e 36 28 31 30 29 20 28 4a 61 6e 20 20 39 20 32 30 31 34 20 30 37 3a 35 39 3a 33 39 29 00 00 a0 02 9e 00 00 80 00 00 1f 1f 00 ff f0 00 20 00 08 00 08 00 00 ff 00 00 0c 04 1e 04 1e 00 1e 73 47
+response as string: V1.6(10) (Jan  9 2014 07:59:39)
+
+
+Modbus function code 0x05 (Write single coil)
+-----------------------------------------------
+request:  02 05 00 02 ff 00 2d c9
+response: 02 05 00 02 ff 00 2d c9
+
+
+Modbus function code 0x06 (Write single (hold) register)
+----------------------------------------------------------
+request:  02 06 00 02 00 0a a8 3e
+response: 02 06 00 02 00 0a a8 3e
+
+
+Modbus function code 0x0f (Write multiple coils)
+--------------------------------------------------
+request:  02 0f 00 00 00 04 01 06 fe 81
+response: 02 0f 04 00 00 00 04 c8 3c
+
+
+Modbus function code 0x10 (Write multiple (hold) registers)
+-------------------------------------------------------------
+request:  02 10 00 01 00 02 04 ff ff ff ff 3c b3
+response: 02 10 04 00 01 00 02 1b 91
+
diff --git a/sure_modbusslave/released/sure.elf.hex b/sure_modbusslave/released/sure.elf.hex
new file mode 100644 (file)
index 0000000..2ff572d
--- /dev/null
@@ -0,0 +1,598 @@
+:100000000C943C000C9459000C9459000C94590029\r
+:100010000C9459000C9459000C9459000C945900FC\r
+:100020000C9459000C9459000C9459000C94660AD5\r
+:100030000C9459000C9459000C9459000C945900DC\r
+:100040000C9459000C9459000C9459000C943F0BDB\r
+:100050000C945900800CA90CB00CB50CC20CC90C46\r
+:10006000D70CE00CF00CFA0C050D0C0D290D2E0D23\r
+:10007000420D470D730D910D11241FBECFE5D4E045\r
+:10008000DEBFCDBF10E0A0E6B0E0ECEEF4E202C0CF\r
+:1000900005900D92A83BB107D9F711E0A8EBB0E0AD\r
+:1000A00001C01D92AF32B107E1F70E9497040C9492\r
+:1000B00074120C94000023ED30E0C90160E070E0A0\r
+:1000C00046E050E00E94A40D80E690E09093D400BA\r
+:1000D0008093D30088E690E09093D6008093D5007B\r
+:1000E00084E790E09093D8008093D7008FE39EE759\r
+:1000F000A5E081509040A040E1F700C000000895C5\r
+:10010000CF92DF92EF92FF920F931F93DF93CF93E3\r
+:100110000F92CDB7DEB782E00E94BC07D82E83E0F5\r
+:100120000E94BC078C0184E00E94BC07C82E85E0B9\r
+:100130000E94BC077C010E943A05863008F44BC03F\r
+:100140000E943A05883008F444C07C2D60E0E62A1D\r
+:10015000F72A97012150304087E0203D3807C8F545\r
+:100160003D2D20E0022B132B04301105A0F5C80112\r
+:100170008E0D9F1D01978430910568F589B344E089\r
+:1001800050E04E195F092FE030E002C03595279509\r
+:100190004A95E2F780958F7090E002C0959587951B\r
+:1001A0000A95E2F782238983C70187709070B701AF\r
+:1001B00023E0769567952A95E1F7009711F06F5F38\r
+:1001C0007F4F81E0AE014F5F5F4F0E94900980E05A\r
+:1001D00007C063E001C062E081E80E941D0A8FEF62\r
+:1001E0000F90CF91DF911F910F91FF90EF90DF90D3\r
+:1001F000CF900895CF92DF92EF92FF920F931F93CB\r
+:10020000DF93CF930F92CDB7DEB782E00E94BC0799\r
+:10021000D82E83E00E94BC078C0184E00E94BC07BA\r
+:10022000C82E85E00E94BC077C010E943A058630FA\r
+:1002300008F454C00E943A05883008F44DC07C2D63\r
+:1002400060E0E62AF72A97012150304087E0203D00\r
+:10025000380708F041C03D2D20E0022B132B02305F\r
+:100260001105E0F5C8018E0D9F1D019782309105A3\r
+:10027000A8F583B3881F8827881F9E9B02C022E0B1\r
+:1002800001C020E0282B209530E002C0359527954D\r
+:100290000A95E2F742E050E04E195F0983E090E0F2\r
+:1002A00002C0959587954A95E2F782238983C70115\r
+:1002B00087709070B70133E0769567953A95E1F7CE\r
+:1002C000009711F06F5F7F4F82E0AE014F5F5F4F8D\r
+:1002D0000E94900980E007C063E001C062E082E80C\r
+:1002E0000E941D0A8FEF0F90CF91DF911F910F9108\r
+:1002F000FF90EF90DF90CF900895EF92FF920F93D1\r
+:100300001F93CF93DF9382E00E94BC07F82E83E017\r
+:100310000E94BC07EC0184E00E94BC07E82E85E047\r
+:100320000E94BC078C010E943A05863018F10E9499\r
+:100330003A058830E8F03E2D20E0022B132B98017F\r
+:10034000215030402D37310598F45F2D40E04C2B83\r
+:100350005D2BCA01800F911F01978530910550F4E4\r
+:10036000602F660F83E021E00E94050980E007C04E\r
+:1003700063E001C062E083E80E941D0A8FEFDF9115\r
+:10038000CF911F910F91FF90EF900895EF92FF9200\r
+:100390000F931F93CF93DF9382E00E94BC07E82E58\r
+:1003A00083E00E94BC07EC0184E00E94BC07F82EA9\r
+:1003B00085E00E94BC078C010E943A05863008F453\r
+:1003C0003FC00E943A058830C8F17F2D60E0602B65\r
+:1003D000712B9B01215030402D37310578F55E2D72\r
+:1003E00040E04C2B5D2B4433510540F4CA01860F8D\r
+:1003F000971F019784339105D0F022C02FEF403F23\r
+:100400005207A8F0CA01A0E0B0E07B0100E010E0D4\r
+:100410008E0D9F1DA01FB11F0197A109B10980304A\r
+:1004200020E0920721E0A20720E0B20748F4660F1F\r
+:1004300084E020E00E94050980E007C063E001C07D\r
+:1004400062E084E80E941D0A8FEFDF91CF911F9137\r
+:100450000F91FF90EF900895CF92DF92EF92FF926D\r
+:100460000F931F93DF93CF9300D000D0CDB7DEB7AB\r
+:1004700082E00E94BC07D82E83E00E94BC078C015A\r
+:1004800084E00E94BC07C82E85E00E94BC077C0166\r
+:100490000E943A05863008F44FC00E943A05883021\r
+:1004A00008F448C03C2D20E0E22AF32AE114F104CC\r
+:1004B00029F080E0E8168FEFF806E1F53D2D20E009\r
+:1004C000022B132B04301105B8F581E090E0002ECB\r
+:1004D00002C0880F991F0A94E2F7D82E0E942505C2\r
+:1004E000E114F10429F09BB38D2D8095892302C07E\r
+:1004F0008BB38D298BBB0E941F058BE291E0019786\r
+:10050000F1F700C00000E114F10421F089B38D215E\r
+:10051000A9F403C089B38D2189F019820A83FB8273\r
+:100520001C8285E064E0AE014F5F5F4F0E9490093E\r
+:1005300080E009C063E003C062E001C064E085E8D8\r
+:100540000E941D0A8FEF0F900F900F900F90CF9188\r
+:10055000DF911F910F91FF90EF90DF90CF90089562\r
+:10056000CF92DF92EF92FF920F931F93DF93CF937F\r
+:1005700000D000D0CDB7DEB782E00E94BC07C82E05\r
+:1005800083E00E94BC078C0184E00E94BC07D82E47\r
+:1005900085E00E94BC077C010E943A05863020F16C\r
+:1005A0000E943A058830F0F03C2D20E0022B132BFE\r
+:1005B00005301105C8F47D2D60E06E297F29C80142\r
+:1005C0000E94B308C8010E94E30819820A839B8332\r
+:1005D0008C8386E064E0AE014F5F5F4F0E9490091C\r
+:1005E00080E007C063E001C062E086E80E941D0A67\r
+:1005F0008FEF0F900F900F900F90CF91DF911F9181\r
+:100600000F91FF90EF90DF90CF900895AF92BF923F\r
+:10061000CF92DF92EF92FF920F931F93DF93CF93CE\r
+:1006200000D000D0CDB7DEB782E00E94BC07B82E64\r
+:1006300083E00E94BC078C0184E00E94BC07A82EC6\r
+:1006400085E00E94BC077C0186E00E94BC07D82E92\r
+:1006500087E00E94BC07C82E0E943A05863008F445\r
+:1006600067C00E943A058A3008F460C03A2D20E045\r
+:10067000E22AF32A97012150304087E0203D3807D5\r
+:1006800008F054C03B2D20E0022B132B0430110541\r
+:1006900008F04EC098012E0D3F1D215030402430EF\r
+:1006A000310508F045C09D2D913009F041C08C2DD9\r
+:1006B00080958F7020E090E004C0220F331F2160EE\r
+:1006C0009F5F492F50E030E04E155F05B0F3002EDC\r
+:1006D00002C0220F331F0A94E2F7B22E90E0002EE0\r
+:1006E00002C0880F991F0A94E2F7D22ED8220E94E6\r
+:1006F00025058BB3807F8D298BBB8BE291E0019721\r
+:10070000F1F700C000000E941F0589B38B218D15F1\r
+:1007100089F419820A831B82EC828FE064E0AE01C7\r
+:100720004F5F5F4F0E94900980E009C063E003C003\r
+:1007300062E001C064E08FE80E941D0A8FEF0F9015\r
+:100740000F900F900F90CF91DF911F910F91FF901D\r
+:10075000EF90DF90CF90BF90AF9008959F92AF92AF\r
+:10076000BF92CF92DF92EF92FF920F931F93DF938E\r
+:10077000CF9300D000D00F92CDB7DEB782E00E94B9\r
+:10078000BC07A82E83E00E94BC078C0184E00E9475\r
+:10079000BC07982E85E00E94BC077C0186E00E9481\r
+:1007A000BC07B82E0E943A05863008F44FC00E945C\r
+:1007B0003A058A3008F448C0392D20E02E293F2917\r
+:1007C000A901415050404B375105F0F55A2D40E0FA\r
+:1007D0007A01E02AF12AC701820F931F0197853021\r
+:1007E0009105A0F54B2D50E0C901880F991F4817BE\r
+:1007F000590771F5F982EA821B822C8320E019C027\r
+:1008000087010F5F1F4F822F895F2D830E94BC07D6\r
+:10081000A82E2D81822F885F0E94BC07DA2CCC2461\r
+:10082000B601682B792BC7010E94B3082D812E5F7A\r
+:1008300078012B1528F380E164E0AE014F5F5F4F34\r
+:100840000E94900980E009C063E003C062E001C03B\r
+:1008500064E080E90E941D0A8FEF0F900F900F90C7\r
+:100860000F900F90CF91DF911F910F91FF90EF901C\r
+:10087000DF90CF90BF90AF909F90089581E00E944D\r
+:1008800095058823F1F10E943A05833010F480E841\r
+:1008900035C080E00E94BC07009799F181E00E947A\r
+:1008A000BC078430D9F0853038F4823089F0833049\r
+:1008B00090F4813011F509C08630B1F0863088F0AF\r
+:1008C0008F30A9F08031C9F415C00E94800019C092\r
+:1008D0000E94FA0016C00E947D0113C00E94C6014A\r
+:1008E00010C00E942C020DC00E94B0020AC00E94DB\r
+:1008F000060307C00E94AE0304C0805861E00E9456\r
+:100900001D0A8091170190911801009719F080E05D\r
+:1009100061E002C080E060E00E9409070895089548\r
+:1009200008950895089508950895089508950E94DA\r
+:10093000C8040E94440C0E945B0078940E94F70453\r
+:100940000E943E04FBCF9091E1008091E000981757\r
+:1009500091F08091E000E82FF0E0E752FF4F228510\r
+:100960008F5F8093E0008091E000803210F0109261\r
+:10097000E00030E002C02EEF3FEFC90108955D9B1B\r
+:10098000FECF8CB9282F332727FD3095932F08955C\r
+:1009900029ED30E0C90160E070E04CE350E00E94D6\r
+:1009A000A40D109204011092030183E480930501C9\r
+:1009B00085E98CBF8AE083BF82E089BF88BF8CE075\r
+:1009C00089B910BC1BB88EE880BD88E98AB98FE070\r
+:1009D0008BBB18BA9FEF9ABB84B38F7384BB97BB52\r
+:1009E0008FEB94E063EA74E00E94AB0D08950895E4\r
+:1009F0008F3F09F08F5F08959C018FEF2F3F3807DD\r
+:100A000011F02F5F3F4FC9010895FC01862F90819F\r
+:100A10009F3F11F09F5F01C09FEF90830895FC01FD\r
+:100A2000862F208131819FEF2F3F390719F02F5FEB\r
+:100A30003F4F02C02FEF3FEF318320830895809115\r
+:100A4000D90087FF01C0789408959091D9008FB79D\r
+:100A50008078892B8093D900F894089500D08DE791\r
+:100A600090E0EDB7FEB7928381830E94220E0F9033\r
+:100A70000F9008959091E1008091E000981730F078\r
+:100A80008091E1009091E000891B08958091E10040\r
+:100A90009091E000805E891B0895EF92FF921F9372\r
+:100AA000CF93DF93182F0E9425050E943A0518174F\r
+:100AB00068F4E091E000E10FE03208F0E052F0E08D\r
+:100AC000E752FF4F8285C82FD0E002C0CFEFDFEFA3\r
+:100AD0000E941F05CE01DF91CF911F91FF90EF90F3\r
+:100AE00008950E94250501C08CB15F99FDCF109239\r
+:100AF000E0001092E1001092E2000E941F050895AC\r
+:100B00000F931F93182F0E9425050091DF008091FD\r
+:100B1000DF00812B8093DF000E941F05102381E0FE\r
+:100B200009F480E01F910F9108950F931F93182FE0\r
+:100B30000E9425050091DF009091DF00812F8095B4\r
+:100B400089238093DF000E941F05102381E009F4B0\r
+:100B500080E01F910F9108959091DF00982381E02C\r
+:100B600009F480E008958091C60090E001968370BA\r
+:100B700090708093C6002BB32F702BBB382F8752F9\r
+:100B80009F4FFC0186A988BB80910E0190E0032E47\r
+:100B900002C0959587950A94E2F780FDC79A2BB31A\r
+:100BA00080E890E002C0959587953A95E2F7282B6A\r
+:100BB0002BBB0895843070F46F5F633108F060E000\r
+:100BC000E82FF0E0A62FB0E0AB56BF4F8C91E75274\r
+:100BD000FF4F86AB0895E82FF0E0E370F070E75226\r
+:100BE000FF4F66AB089510921301662369F0909150\r
+:100BF0000E0121E030E002C0220F331F8A95E2F798\r
+:100C0000922B90930E01089590910E0121E030E017\r
+:100C100002C0220F331F8A95E2F7209529232093E3\r
+:100C20000E010895EF92FF921F93CF93DF931092DE\r
+:100C30001301E82EE7017E01F92EE70113E024C03D\r
+:100C4000682F60536A3068F0982F9156963018F4E8\r
+:100C5000682F675506C0982F9154963020F4682F5E\r
+:100C60006753812F0CC08D3219F4812F60E107C0CA\r
+:100C7000803219F4812F63E102C0812F61E10E946B\r
+:100C8000DA0511501F3F19F089918823C9F6DF91C9\r
+:100C9000CF911F91FF90EF900895DF93CF9300D0F5\r
+:100CA00000D00F92CDB7DEB700D000D000D0EDB7A6\r
+:100CB000FEB731969E012F5F3F4FADB7BEB712967C\r
+:100CC0003C932E93119720E830E033832283282F22\r
+:100CD000392FC901B7E280319B0710F08FE097E20E\r
+:100CE000958384830E94680E8DB79EB706960FB6D3\r
+:100CF000F8949EBF0FBE8DBFCE0101960E941206D2\r
+:100D00000F900F900F900F900F90CF91DF9108955B\r
+:100D1000DF93CF9300D000D00F92CDB7DEB7282F4E\r
+:100D2000392FC9012CEF8931920714F489E19CEF26\r
+:100D300000D000D000D0EDB7FEB731969E012F5FF6\r
+:100D40003F4FADB7BEB712963C932E93119720E854\r
+:100D500030E033832283B7E280319B0714F08FE0C9\r
+:100D600097E2958384830E94680E8DB79EB706969E\r
+:100D70000FB6F8949EBF0FBE8DBFCE0101960E94A4\r
+:100D800012060F900F900F900F900F90CF91DF9160\r
+:100D900008950F931F93DF93CF9300D000D00F924D\r
+:100DA000CDB7DEB700D000D000D0EDB7FEB731969A\r
+:100DB0008E010F5F1F4FADB7BEB712961C930E93F7\r
+:100DC000119724E830E033832283958384830E9443\r
+:100DD000680E8DB79EB706960FB6F8949EBF0FBEED\r
+:100DE0008DBFC8010E9412060F900F900F900F90B8\r
+:100DF0000F90CF91DF911F910F910895882329F0D3\r
+:100E000080EF8BBB8FEF88BB08958FE08BBB18BA48\r
+:100E10000895DF93CF9300D0CDB7DEB7843000F5CF\r
+:100E20006A8389830E9425056A818981662361F02E\r
+:100E30009BB321E030E002C0220F331F8A95E2F716\r
+:100E4000209529232BBB0AC09BB321E030E002C0D0\r
+:100E5000220F331F8A95E2F7922B9BBB0E941F053E\r
+:100E60000F900F90CF91DF9108951F938430B8F4C5\r
+:100E700021E030E002C0220F331F8A95E2F7122FE3\r
+:100E80000E9425058BB3812329F08BB3109518237D\r
+:100E90001BBB03C08BB3812B8BBB0E941F051F9113\r
+:100EA000089580E008950895DF93CF93CDB7DEB71E\r
+:100EB0002E970FB6F894DEBF0FBECDBFFE01319660\r
+:100EC0002EE0DF011D922A95E9F7282F392FD9014D\r
+:100ED0002EE001900D922150E1F72E960FB6F89476\r
+:100EE000DEBF0FBECDBFCF91DF9108959FEF9093EE\r
+:100EF0000C0190910D0121E030E002C0220F331F60\r
+:100F00008A95E2F7922B90930D01089580E00E945C\r
+:100F10004D0590910B01992379F4209107013091AF\r
+:100F200008012115310541F4823011F0882321F4A4\r
+:100F300081E080930A01089580910601882321F0C1\r
+:100F400081E090E00E94760780910701909108016E\r
+:100F5000009721F083E090E00E94760780E00E94F5\r
+:100F60004D058230910521F084E090E00E947607E3\r
+:100F700081E080930901089590910B01992341F03C\r
+:100F800090910B01891720F40E944D059C0102C02D\r
+:100F90002FEF3FEFC90108951F9380910B01882324\r
+:100FA00029F10E94250510910B010E943A0518179E\r
+:100FB00018F00E9471050BC08091E00020910B0198\r
+:100FC00090E0820F911D8F7190708093E0001092DD\r
+:100FD0000B01809105018091DA009091DB00A091D6\r
+:100FE000DC00B091DD0082B70E941F051F910895BB\r
+:100FF00090E06827792748E021E030EACB01969518\r
+:10100000879560FF04C0BC016227732701C0BC0143\r
+:101010004150A1F7CB010895EF92FF920F931F93D8\r
+:10102000DF93CF93CDB7DEB7A0970FB6F894DEBFAE\r
+:101030000FBECDBF8C017FEF803F970708F454C0EF\r
+:101040007E010894E11CF11C80E2D7011D928A9573\r
+:10105000E9F74091D3005091D4002091D500309110\r
+:10106000D6008091D7009091D800EDB7FEB73C979D\r
+:101070000FB6F894FEBF0FBEEDBF3196ADB7BEB749\r
+:101080001296FC92EE92119760E270E07383628395\r
+:1010900069E870E0758364835783468331872087CE\r
+:1010A000938782870E94370E005F1F4F000F111F2A\r
+:1010B000FE01E00FF11F2281332727FD30950E0D31\r
+:1010C0001F1DF8018081992787FD9095982F88270B\r
+:1010D000282B392B6DB77EB7645F7F4F0FB6F8941E\r
+:1010E0007EBF0FBE6DBF31C08433910560F56623AE\r
+:1010F000D9F00E9425058091190180FF0AC0ACEB50\r
+:10110000B0E0E9E1F1E08AE001900D928150E1F771\r
+:1011100009C0ACEBB0E0E8EAF0E08AE001900D92A3\r
+:101120008150E1F70E941F050033110530F0F801EE\r
+:10113000EE0FFF1FE25AFF4F03C0F801EE0FFF1F33\r
+:101140002081318102C02FEF3FEFC901A0960FB679\r
+:10115000F894DEBF0FBECDBFCF91DF911F910F91ED\r
+:10116000FF90EF9008959C01CB012330310520F4CE\r
+:10117000709324016093230122303105B9F02330AC\r
+:10118000310538F42115310559F021303105D1F4FC\r
+:101190000AC02330310569F02430310599F40EC0BE\r
+:1011A0000E94C90608950E944D0608950E9488066F\r
+:1011B00008958093110190931201089580930F0177\r
+:1011C0009093100108958330910528F42091230114\r
+:1011D0003091240118C08330910521F084309105AD\r
+:1011E00081F405C0309112012091110104C03091A9\r
+:1011F000100120910F01932F80E030E0282B392B34\r
+:1012000002C02FEF3FEFC90108959F92AF92BF92A6\r
+:10121000CF92DF92EF92FF920F931F93CF93DF93C2\r
+:10122000082FE62E6A01922E80E090E061E00E9495\r
+:101230000C0882E06FEF7FEF0E94F807BC01802F5F\r
+:101240000E94F807EC01609127017091280182E06B\r
+:1012500090E00E94F60D6091270170912801802F87\r
+:1012600090E00E94F60D8E2DBE010E94F807182F07\r
+:10127000092F60912701709128018E2D90E00E9426\r
+:10128000F60DC0E0D0E0FF2427C0992019F00E949D\r
+:10129000E30803C060E00E940C08B82EA92E892F35\r
+:1012A000612F702F0E94F8078C01609127017091C7\r
+:1012B00028018A2D90E00E94F60D8B2DB8010E9426\r
+:1012C000F807182F092F60912701709128018B2DA5\r
+:1012D00090E00E94F60D2196CE018C0D9D1DCE153D\r
+:1012E000DF0598F26091270170912801812F90E02D\r
+:1012F0000E94F60D6091270170912801802F90E0E7\r
+:101300000E94F60D0E94CC07DF91CF911F910F91A3\r
+:10131000FF90EF90DF90CF90BF90AF909F90089597\r
+:101320006F927F928F929F92AF92BF92CF92DF92F5\r
+:10133000EF92FF920F931F93DF93CF930F92CDB74E\r
+:10134000DEB7E82EF62EB42EA52E82E06FEF7FEFEB\r
+:101350000E94F807BC018E2D0E94F8076C018E2DAB\r
+:1013600085508983823028F08F2DB6010E94F807BE\r
+:101370006C01C501092F1A2D662477248F2C99241E\r
+:101380000AC0F80181918F01B6010E94F8076C0133\r
+:101390000894611C711C6814790498F3609127010A\r
+:1013A0007091280182E090E00E94F60D6091270183\r
+:1013B000709128018E2D90E00E94F60DF981F23097\r
+:1013C00040F060912701709128018F2D90E00E94DC\r
+:1013D000F60DC501092F1A2DEE24FF2409C0F801CE\r
+:1013E00081918F0190E00E94F60D0894E11CF11CA0\r
+:1013F0006091270170912801E814F90480F38C2D85\r
+:1014000090E00E94F60D60912701709128018D2DCA\r
+:1014100090E00E94F60D0E94CC070F90CF91DF91D3\r
+:101420001F910F91FF90EF90DF90CF90BF90AF9002\r
+:101430009F908F907F906F900895EF92FF920F93FF\r
+:101440001F93F82E162F82E06FEF7FEF0E94F807B0\r
+:101450009C018F2DB9010E94F8079C01812FB901D1\r
+:101460000E94F807E82E092F2091270130912801CA\r
+:1014700082E090E0B9010E94F60D209127013091A1\r
+:1014800028018F2D90E0B9010E94F60D20912701CF\r
+:1014900030912801812F90E0B9010E94F60D6091F2\r
+:1014A0002701709128018E2D90E00E94F60D609129\r
+:1014B000270170912801802F90E00E94F60D0E9474\r
+:1014C000CC071F910F91FF90EF9008951F920F92FC\r
+:1014D0000FB60F9211241F932F933F934F935F9357\r
+:1014E0006F937F938F939F93AF93BF93EF93FF93EC\r
+:1014F00082B78091DA009091DB00A091DC00B0917E\r
+:10150000DD00809105011CB1123579F48091BB009A\r
+:10151000803459F428E088E190E00FB6F894A8955B\r
+:1015200081BD0FBE21BDA895FFCF1093BB0083E402\r
+:10153000809305012091030130910401223031058F\r
+:1015400011F12330310538F421153105B1F1213085\r
+:10155000310549F504C02330310529F520C082E06A\r
+:1015600090E090930401809303018FEF9FEF90939D\r
+:1015700008018093070181E0809306011092090120\r
+:1015800010920A011AC01092BB00809106018823B4\r
+:10159000A1F0809106018F5F809306010EC081E06B\r
+:1015A000809309010AC082E090E00E94760781E002\r
+:1015B00090E0909304018093030120910301309106\r
+:1015C00004012230310509F043C060910701709198\r
+:1015D0000801812F0E94F80790930801809307016A\r
+:1015E0008091E100E82FF0E0E752FF4F12878F5F14\r
+:1015F0008093E1008091E100803210F01092E100D0\r
+:101600009091E1008091E0009817D9F48091E10079\r
+:10161000882311F48FE103C08091E1008150809311\r
+:10162000E1008091E2008F3F09F08F5F8093E2003C\r
+:1016300085E090E00E9476071092060181E0809399\r
+:101640000901E091E100F0E0E752FF4F128605C08A\r
+:101650001092060181E080930901FF91EF91BF9103\r
+:10166000AF919F918F917F916F915F914F913F913A\r
+:101670002F911F910F900FBE0F901F9018951F92E2\r
+:101680000F920FB60F9211242F933F934F935F93B6\r
+:101690006F937F938F939F93AF93BF93EF93FF933A\r
+:1016A0008091DA009091DB00A091DC00B091DD0028\r
+:1016B0000196A11DB11D8093DA009093DB00A093E9\r
+:1016C000DC00B093DD0080910501882361F18091F9\r
+:1016D0000501815080930501809105018D3108F04D\r
+:1016E0005DC080910301909104018230910531F435\r
+:1016F00083E090E0909304018093030180910301C3\r
+:10170000909104018330910511F40E948607809125\r
+:1017100005018091DA009091DB00A091DC00B0918E\r
+:10172000DD0082B73BC080910301909104018230BB\r
+:10173000910539F080910301909104018330910566\r
+:1017400039F580910A018823A9F0809105018091E3\r
+:10175000DA009091DB00A091DC00B091DD0082B74F\r
+:101760008091060180930B011092060181E00E9496\r
+:1017700080050CC080E090E00E9476078091060111\r
+:1017800080930B01109206010E94CC0710920A016F\r
+:1017900081E090E090930401809303018091BA006E\r
+:1017A0008F5F8093BA00853008F45DC01092BA0054\r
+:1017B0008091B9008F5F8093B9008091B800882331\r
+:1017C00041F08091DE008F3F09F08F5F8093DE0053\r
+:1017D0004AC081E08093B80078949091B90090FF5E\r
+:1017E00005C00E945F0C0E948F043BC091FF0DC09A\r
+:1017F00080911301813019F00E94B30503C08BB3AF\r
+:101800008F708BBB0E9490042CC092FF12C08091FD\r
+:101810000C01882359F080910C01815080930C01B8\r
+:1018200080910C01882311F410920D010E94910403\r
+:1018300018C093FF03C00E94920413C094FF03C01A\r
+:101840000E9493040EC095FF03C00E94940409C037\r
+:1018500096FF03C00E94950404C097FF02C00E9437\r
+:1018600096041092B800FF91EF91BF91AF919F91B4\r
+:101870008F917F916F915F914F913F912F910F9039\r
+:101880000FBE0F901F90189525E131E0C90160E06F\r
+:1018900070E040E150E00E94A40D16BE82E180B9E4\r
+:1018A00081E081B984E086BF089584EA86BF089507\r
+:1018B00084E986BF089506B607FEFDCF089521B1DD\r
+:1018C000287F8091170190911801009749F080912D\r
+:1018D00017019091180101979093180180931701B7\r
+:1018E000E0911501F0911601E231F10508F025C1F2\r
+:1018F000E65DFF4FEE0FFF1F0590F491E02D099478\r
+:1019000082E090E090931601809315011092D1002F\r
+:101910008091C7008E7F8093C70020911901269582\r
+:1019200030911A01379533273795832F822B2091D9\r
+:101930001A01922F96950196282F220F2093C70007\r
+:10194000292F220F881F8827881F822B8093C80089\r
+:1019500008958AEF90E09093180180931701E8C0F2\r
+:1019600084EA86BF83E090E03FC08091D20081503E\r
+:101970008093D200283019F0203109F0ABC084E008\r
+:1019800090E0ACC080E983B984E886BF85E090E050\r
+:101990002BC08091D20081508093D200283119F45D\r
+:1019A00086E090E09BC0203209F094C095C0809101\r
+:1019B000D10083B984E886BF8AE08093D2000DC04D\r
+:1019C0008091D20081508093D200283219F488E0AF\r
+:1019D00090E084C0203209F07DC087E090E07EC0B6\r
+:1019E00084EA86BF89E090E0909316018093150108\r
+:1019F0008AE094C08091D20081508093D20020313F\r
+:101A000009F068C08AE090E069C081E983B984E8A0\r
+:101A100086BF8BE090E0E8CF8091D2008150809328\r
+:101A2000D200203479F48091D100E82FF0E0EE0F5D\r
+:101A3000FF1FE753FF4F11821082813001F18CE0CC\r
+:101A400090E04CC0283309F447C0283409F042C064\r
+:101A500043C084EC86BF8DE090E0C6CF8091D20079\r
+:101A600081508093D2002035A9F583B1E091D10057\r
+:101A7000F0E0EE0FFF1FE753FF4F108281838EE0EF\r
+:101A800090E02CC084E886BF8FE090E0ADCF8091DD\r
+:101A9000D20081508093D2002835E1F44091D100EA\r
+:101AA000E42FF0E023B1EE0FFF1FE753FF4F30E0CC\r
+:101AB00080819181822B932B91838083842F8F5FF0\r
+:101AC0008093D100843018F482E090E007C080E178\r
+:101AD00090E004C08823B9F581E090E0909316016E\r
+:101AE0008093150108958091C70081608093C7009D\r
+:101AF0000E942505A9E1B1E0E7ECF0E08AE0019061\r
+:101B00000D928150E1F70E941F0584E986BF81E1B3\r
+:101B100090E0909316018093150184E68093D200A3\r
+:101B200008958091D20081508093D200882359F487\r
+:101B30001092160110921501089581E090E09093A3\r
+:101B40001601809315010895DC0101C06D93415089\r
+:101B50005040E0F708950F931F93CF93DF938C01CC\r
+:101B6000EB01009711F42097C9F181E090E06EE05D\r
+:101B700070E00E947210FC019C01009789F180E8DE\r
+:101B80008383209771F0D387C28781E88383809114\r
+:101B9000250190912601009721F4F0932601E0930E\r
+:101BA000250101151105E1F011870087838182600D\r
+:101BB00083838091270190912801009789F4F09305\r
+:101BC0002801E09327018091290190912A01009733\r
+:101BD00039F4F0932A01E093290102C020E030E0BB\r
+:101BE000C901DF91CF911F910F9108950F931F931A\r
+:101BF000CF93DF938C01EB018B8181FF1BC082FFB0\r
+:101C00000DC02E813F818C819D812817390764F496\r
+:101C1000E881F9810193F983E88306C0E885F985B5\r
+:101C2000802F0995009731F48E819F8101969F83C3\r
+:101C30008E8302C00FEF1FEFC801DF91CF911F917C\r
+:101C40000F910895A0E0B0E0E8E2FEE00C944D12A0\r
+:101C5000FE01359661917191809127019091280143\r
+:101C6000AF010E948B0E2096E2E00C946912AEE068\r
+:101C7000B0E0EDE3FEE00C944B120D891E898F89D4\r
+:101C8000988D26E02C831A83098397FF02C080E099\r
+:101C900090E801979E838D839E01255E3F4FCE0184\r
+:101CA0000196698D7A8DA9010E948B0E4D815E810E\r
+:101CB00057FD0AC02F813885421753070CF49A014B\r
+:101CC000020F131FF80110822E96E4E00C946712A5\r
+:101CD000AEE0B0E0EEE6FEE00C944B120D891E89FA\r
+:101CE00086E08C831A8309838FEF9FE79E838D8321\r
+:101CF0009E01275E3F4FCE0101966F89788DA90125\r
+:101D00000E948B0EEF81F885E00FF11F10822E9656\r
+:101D1000E4E00C946712ACE0B0E0E1E9FEE00C9482\r
+:101D20003D126C011B018A01FC011782168283811E\r
+:101D300081FFD1C12E010894411C511CF6019381F1\r
+:101D4000F10193FD859193FF81911F01882309F48F\r
+:101D5000BEC1853239F493FD859193FF81911F01B6\r
+:101D6000853229F490E0B6010E94F60DE7CFEE240B\r
+:101D7000FF2420E02032B0F48B3269F08C3228F45A\r
+:101D8000803251F0833271F40BC08D3239F08033E0\r
+:101D900049F421602CC02260246029C0286027C03B\r
+:101DA000206125C027FD2CC0382F30533A3098F4DD\r
+:101DB00026FF08C08E2D880FE82EEE0CEE0CE80EE4\r
+:101DC000E30E15C08F2D880FF82EFF0CFF0CF80EB8\r
+:101DD000F30E20620CC08E3221F426FD78C12064FF\r
+:101DE00006C08C3611F4206802C0883649F4F1012F\r
+:101DF00093FD859193FF81911F01882309F0BACF4C\r
+:101E0000982F9554933018F09052933028F40C5F2B\r
+:101E10001F4FFFE3F9830DC0833631F0833771F034\r
+:101E2000833509F060C022C0F801808189830E5F8C\r
+:101E30001F4F420171E0A72EB12C16C062E0662E42\r
+:101E4000712C600E711EF8018080918026FF03C006\r
+:101E50006E2D70E002C06FEF7FEFC4012C870E94EF\r
+:101E6000D4115C0183012C852F7717C052E0652EB9\r
+:101E7000712C600E711EF8018080918026FF03C0D6\r
+:101E80006E2D70E002C06FEF7FEFC4012C870E94BF\r
+:101E9000C9115C012C852068830123FD20C008C086\r
+:101EA00080E290E0B6012C870E94F60DFA942C8512\r
+:101EB0008F2D90E0A816B90698F311C0F40127FD04\r
+:101EC000859127FF81914F0190E0B6012C870E94F8\r
+:101ED000F60D2C85F110FA940894A108B108A1140C\r
+:101EE000B10461F7F1C0843611F0893649F527FF56\r
+:101EF00008C0F80160817181828193810C5F1F4F5E\r
+:101F000009C0F80160817181882777FD8095982F3D\r
+:101F10000E5F1F4F4FE6B42EB22297FF09C0909577\r
+:101F20008095709561957F4F8F4F9F4FF0E8BF2A46\r
+:101F3000A2012AE030E00E94DF11782E741845C01B\r
+:101F4000853731F43FEEB32EB2222AE030E025C0CF\r
+:101F500099EFB92EB2228F36C1F0803720F4883540\r
+:101F600009F0B5C00DC0803721F0883709F0AFC047\r
+:101F700002C020E1B22AB4FE0BC084E0B82A08C037\r
+:101F8000B4FE09C0E6E0BE2A06C028E030E005C085\r
+:101F900020E130E002C020E132E0B7FE08C0F801E5\r
+:101FA00060817181828193810C5F1F4F07C0F801AE\r
+:101FB0006081718180E090E00E5F1F4FA2010E945E\r
+:101FC000DF11782E7418FFE7BF22B6FE0BC02EEF8C\r
+:101FD000B2227E1438F4B4FE07C0B2FC05C08FEE06\r
+:101FE000B82202C0A72C01C0AE2C8B2D90E0B4FE0D\r
+:101FF0000DC0FE01E70DF11D2081203319F4E9EE3B\r
+:10200000BE2209C0A394B2FE06C004C086789070B8\r
+:10201000009709F0A3948B2C9924B3FC14C0B0FE54\r
+:102020000FC0AF1428F4E72CEF0CEA18AF2C08C04F\r
+:10203000E72C06C080E290E0B6010E94F60DA39462\r
+:10204000AF14C0F304C0AF1410F4FA1801C0FF2499\r
+:1020500084FE0FC080E390E0B6010E94F60D82FE80\r
+:102060001FC081FE03C088E590E010C088E790E0C3\r
+:102070000DC0C40186789070009791F081FC02C079\r
+:1020800080E201C08BE2B7FC8DE290E0B6010E94D5\r
+:10209000F60D06C080E390E0B6010E94F60DEA94CA\r
+:1020A0007E14C0F37A94F201E70DF11D808190E077\r
+:1020B000B6010E94F60D7720A9F706C080E290E0F5\r
+:1020C000B6010E94F60DFA94FF20C1F737CEF60153\r
+:1020D0002681378102C02FEF3FEFC9012C96E2E144\r
+:1020E0000C945912EF92FF920F931F93CF93DF93AB\r
+:1020F000689F8001699F100D789F100D1124C80101\r
+:102100000E949610E82EE7017E01F92EE701209744\r
+:1021100031F08E2D60E070E0A8010E94A40D7E01D8\r
+:10212000CE01CDB7DEB7E6E00C946512CF93DF9316\r
+:102130008230910510F482E090E0E0912D01F09161\r
+:102140002E0140E050E020E030E026C06081718147\r
+:1021500068177907E0F06817790781F48281938125\r
+:102160002115310531F0D90113969C938E93129766\r
+:102170002BC090932E0180932D0126C0411551054F\r
+:1021800019F06417750718F4AB01E901DF019F012D\r
+:1021900072816381E72FF62F3097C1F64115510503\r
+:1021A00001F1481B590B4430510580F412968D9172\r
+:1021B0009C911397209719F09B838A8304C0909376\r
+:1021C0002E0180932D01FD01329646C0FD01E40FE2\r
+:1021D000F51F819391934250504011965C934E931A\r
+:1021E0003BC020912B0130912C012115310541F488\r
+:1021F0002091B4003091B50030932C0120932B0135\r
+:102200002091B6003091B7002115310541F42DB76A\r
+:102210003EB74091B2005091B300241B350BE091C2\r
+:102220002B01F0912C01E217F307A0F42E1B3F0BBA\r
+:102230002817390778F0AC014E5F5F4F2417350738\r
+:1022400048F04E0F5F1F50932C0140932B01819358\r
+:10225000919302C0E0E0F0E0CF01DF91CF910895CB\r
+:10226000CF93DF93009709F491C0FC01329713825A\r
+:10227000128260912D0170912E016115710581F41A\r
+:1022800020813181280F391F80912B0190912C01E1\r
+:102290008217930799F5F0932C01E0932B0176C0F8\r
+:1022A000DB0180E090E002C0CD01D901AE17BF078D\r
+:1022B00048F412962D913C91139721153105A1F701\r
+:1022C000CD0121C0B383A283EF01499159919E01B1\r
+:1022D000240F351FA217B30779F42D913C91119764\r
+:1022E000240F351F2E5F3F4F3183208312962D918F\r
+:1022F0003C91139733832283009729F4F0932E01A6\r
+:10230000E0932D0143C0DC011396FC93EE931297EA\r
+:102310004D915D91A40FB51FEA17FB0769F4208169\r
+:102320003181240F351F2E5F3F4FEC013983288305\r
+:10233000228133813B832A83E0E0F0E002C0FB018D\r
+:10234000BC01DB0112968D919C9113970097B9F710\r
+:102350009B012E5F3F4F8D919C911197820F931F90\r
+:1023600040912B0150912C014817590779F430976F\r
+:1023700029F410922E0110922D0102C013821282B4\r
+:102380002250304030932C0120932B01DF91CF91CC\r
+:102390000895FC010590615070400110D8F78095B8\r
+:1023A00090958E0F9F1F0895FC0161507040019021\r
+:1023B0000110D8F7809590958E0F9F1F0895FA0110\r
+:1023C000AA27283051F1203181F1E8946F936E7F74\r
+:1023D0006E5F7F4F8F4F9F4FAF4FB1E03ED0B4E065\r
+:1023E0003CD0670F781F891F9A1FA11D680F791FA6\r
+:1023F0008A1F911DA11D6A0F711D811D911DA11DB7\r
+:1024000020D009F468943F912AE0269F11243019C6\r
+:10241000305D3193DEF6CF010895462F4770405D61\r
+:102420004193B3E00FD0C9F7F6CF462F4F70405D10\r
+:102430004A3318F0495D31FD4052419302D0A9F76B\r
+:10244000EACFB4E0A6959795879577956795BA9565\r
+:10245000C9F700976105710508959B01AC010A2E2B\r
+:1024600006945795479537952795BA95C9F7620F02\r
+:10247000731F841F951FA01D08952F923F924F92A6\r
+:102480005F926F927F928F929F92AF92BF92CF9204\r
+:10249000DF92EF92FF920F931F93CF93DF93CDB70D\r
+:1024A000DEB7CA1BDB0B0FB6F894DEBF0FBECDBF85\r
+:1024B00009942A88398848885F846E847D848C8456\r
+:1024C0009B84AA84B984C884DF80EE80FD800C815F\r
+:1024D0001B81AA81B981CE0FD11D0FB6F894DEBF42\r
+:0C24E0000FBECDBFED010895F894FFCFB2\r
+:1024EC00312E3628313029004A616E2020392032B5\r
+:1024FC003031340030373A35393A3339000A0D006F\r
+:10250C002534640025303478005625732028257333\r
+:10251C002025732900003F065B4F666D7D077F6F9A\r
+:10252C00777C585E797140080000FF7FFF7FFF7F4A\r
+:08253C00FF7F20002F010000C9\r
+:00000001FF\r
diff --git a/sure_modbusslave/src/app.c b/sure_modbusslave/src/app.c
new file mode 100644 (file)
index 0000000..a5f63f1
--- /dev/null
@@ -0,0 +1,420 @@
+#include "global.h"\r
+\r
+#include <stdio.h>\r
+#include <string.h>\r
+\r
+#include <avr/io.h>\r
+#include <avr/interrupt.h>\r
+#include <util/delay.h>\r
+\r
+#include "app.h"\r
+#include "twi.h"\r
+#include "sys.h"\r
+\r
+// Defines, nur in app.c sichtbar\r
+// ...\r
+\r
+//globale Variablen nur in app.c sichtbar\r
+// ...\r
+\r
+//globale Strukturvariable, ueberall sichtbar\r
+volatile struct App app;\r
+\r
+\r
+void app_init (void)\r
+{\r
+  memset((void *)&app, 0, sizeof(app));\r
+  app.version = "1.6(10)";\r
+  app.versionDate = __DATE__;\r
+  app.versionTime = __TIME__;\r
+  _delay_ms(150);\r
+}\r
+\r
+//--------------------------------------------------------\r
+\r
+// Read coils (0x01): 4 LEDs PA0, PA1, PA2 and PA3\r
+// Address 0..3, Quantity 1..4\r
+//   Address 0: LED PA0  (1=LED on, 0=LED off)\r
+//   Address 1: LED PA1  (1=LED on, 0=LED off)\r
+//   Address 2: LED PA2  (1=LED on, 0=LED off)\r
+//   Address 3: LED PA3  (1=LED on, 0=LED off)\r
+int8_t app_modbus_handleReadCoil ()\r
+{\r
+  // Modbus_Application_Protocol_V1_1b3.pdf, page 12\r
+  uint8_t exceptionCode;\r
+  uint16_t address = sys_modbus_getByte(2)<<8 | sys_modbus_getByte(3);\r
+  uint16_t quantity = sys_modbus_getByte(4)<<8 | sys_modbus_getByte(5);\r
+  if (sys_uart_available()<6)\r
+    exceptionCode = 2;\r
+  else if (sys_uart_available()<8)\r
+    exceptionCode = 3;\r
+  else if (quantity <1 || quantity>0x7d0)\r
+    exceptionCode = 3;\r
+  else if (address<0 || address>3 || quantity<1 || (address+quantity-1)>3)\r
+    exceptionCode = 2;\r
+  else\r
+  {\r
+    exceptionCode = 0;\r
+    uint8_t data = (~PINA) & 0x0f;\r
+    data >>= address;\r
+    uint8_t mask = 0x0f >> (4-quantity);\r
+    data &= mask;\r
+    quantity = (quantity % 8) ? (quantity/8+1) : quantity/8;\r
+    sys_modbus_sendResponse(1, quantity, (uint8_t *)&data);\r
+    return 0;  \r
+  }\r
+  \r
+  sys_modbus_sendError(0x81, exceptionCode);\r
+  return -1;\r
+}\r
+\r
+// Read discrete inputs (0x02): push buttons SW1 and SW2\r
+// Address 0..1, Quantity 1..2\r
+//   Address 0: SW1  (0=not pressed, 1=pressed)\r
+//   Address 1: SW1  (0=not pressed, 1=pressed)\r
+int8_t app_modbus_handleReadDicreteInput ()\r
+{\r
+  uint8_t exceptionCode;\r
+  uint16_t address = sys_modbus_getByte(2)<<8 | sys_modbus_getByte(3);\r
+  uint16_t quantity = sys_modbus_getByte(4)<<8 | sys_modbus_getByte(5);\r
+  if (sys_uart_available()<6)\r
+    exceptionCode = 2;\r
+  else if (sys_uart_available()<8)\r
+    exceptionCode = 3;\r
+  else if (quantity <1 || quantity>0x7d0)\r
+    exceptionCode = 3;\r
+  else if (address<0 || address>1 || quantity<1 || (address+quantity-1)>1)\r
+    exceptionCode = 2;\r
+  else\r
+  {\r
+    exceptionCode = 0;\r
+    uint8_t data = ~( ((PINC & 0x80)!=0) | ((PINC & 0x40)!=0)<<1);\r
+    data >>= address;\r
+    uint8_t mask = 0x03 >> (2-quantity);\r
+    data &= mask;\r
+    quantity = (quantity % 8) ? (quantity/8+1) : quantity/8;\r
+    sys_modbus_sendResponse(2, quantity, (uint8_t *)&data);\r
+    return 0;  \r
+  }\r
+  \r
+  sys_modbus_sendError(0x82, exceptionCode);\r
+  return -1;  \r
+}\r
+\r
+// Read holding registers (0x03): read back registers for controlling the 7-segment display\r
+// Address: 0..4\r
+//   Address 0: last written value to hold register addresss 0, 1 or 2\r
+//   Address 1: last written value to hold register addresss 0, 1 or 2\r
+//   Address 2: last written value to hold register addresss 0, 1 or 2\r
+//   Address 3: 7-segement digit 3 and 2 (high byte, low byte)\r
+//   Address 4: 7-segement digit 1 and 0 (high byte, low byte)\r
+int8_t app_modbus_handleReadHoldingRegisters ()\r
+{\r
+  uint8_t exceptionCode;\r
+  uint16_t address = sys_modbus_getByte(2)<<8 | sys_modbus_getByte(3);\r
+  uint16_t quantity = sys_modbus_getByte(4)<<8 | sys_modbus_getByte(5);\r
+  if (sys_uart_available()<6)\r
+    exceptionCode = 2;\r
+  else if (sys_uart_available()<8)\r
+    exceptionCode = 3;\r
+  else if (quantity <1 || quantity>0x7d)\r
+    exceptionCode = 3;\r
+  else if (quantity<1 || (address+quantity-1)>4)\r
+    exceptionCode = 2;\r
+  else\r
+  {\r
+    exceptionCode = 0;\r
+    sys_modbus_sendRegisters(3, quantity*2, address, 1);\r
+    return 0;  \r
+  }\r
+  \r
+  sys_modbus_sendError(0x83, exceptionCode);\r
+  return -1;  \r
+}\r
+\r
+\r
+// Read input register (0x04): Atmega I/O register, temperature sensor, version string\r
+// Address: 0..0x3f, 0xfff0..0xffff\r
+//   Address 0x00 .. 0x2f -> Atmega16 I/O registers (two 8 bit registers combined to 16 bit)\r
+//                           example 1: Atmega I/O register TCNT1 on $4c -> modbus address 0x26\r
+//                           example 2: Atmega I/O register PINC on $33 -> high byte of modbus address 0x19\r
+//\r
+//   Address 0x30 .. 0x33 -> LM75A registers (value 0x7fff -> unvalid)\r
+//                           modbus address 0x30: value/32 -> temperature in celsius degree (two's complement)\r
+//\r
+//   Address 0xfff0..0xffff -> version string of this software -> "V1.0 (Oct 13 2013 13:17:58)"\r
+//                           \r
+int8_t app_modbus_handleReadInputRegister () // function code 0x04\r
+{\r
+  uint8_t exceptionCode;\r
+  uint16_t address = sys_modbus_getByte(2)<<8 | sys_modbus_getByte(3);\r
+  uint16_t quantity = sys_modbus_getByte(4)<<8 | sys_modbus_getByte(5);\r
+  if (sys_uart_available()<6)\r
+    exceptionCode = 2;\r
+  else if (sys_uart_available()<8)\r
+    exceptionCode = 3;\r
+  else if (quantity <1 || quantity>0x7d)\r
+    exceptionCode = 3;\r
+  else if (address<0 || quantity<1 || (address<=0x33 && (address+quantity-1)>0x33) ||\r
+                                      (address>=0xfff0 && ((uint32_t)address+quantity-1)>0xffff))\r
+           \r
+    exceptionCode = 2;\r
+  else\r
+  {\r
+    sys_modbus_sendRegisters(4, quantity*2, address, 0);\r
+    return 0;  \r
+  }\r
+  \r
+  sys_modbus_sendError(0x84, exceptionCode);\r
+  return -1;  \r
+}\r
+\r
+// Write single coil (0x05)\r
+// Address: 0..3, value: 0x0000 or 0xff00\r
+//   Address 0: LED PA0  (0xff00=LED on, 0x0000=LED off)\r
+//   Address 1: LED PA1  (0xff00=LED on, 0x0000=LED off)\r
+//   Address 2: LED PA2  (0xff00=LED on, 0x0000=LED off)\r
+//   Address 3: LED PA3  (0xff00=LED on, 0x0000=LED off)\r
+int8_t app_modbus_handleWriteSingleCoil ()\r
+{\r
+  uint8_t exceptionCode;\r
+  uint16_t address = sys_modbus_getByte(2)<<8 | sys_modbus_getByte(3);\r
+  uint16_t value = sys_modbus_getByte(4)<<8 | sys_modbus_getByte(5);\r
+  if (sys_uart_available()<6)\r
+    exceptionCode = 2;\r
+  else if (sys_uart_available()<8)\r
+    exceptionCode = 3;\r
+  else if (value != 0x0000 && value != 0xff00)\r
+    exceptionCode = 3;\r
+  else if (address<0 || address>3)\r
+    exceptionCode = 2;\r
+  else\r
+  {\r
+    exceptionCode = 0;\r
+    uint8_t mask = 1 << address;\r
+    sys_cli();\r
+    if (value)\r
+      PORTA &= ~mask;\r
+    else\r
+      PORTA |= mask;\r
+    sys_sei();\r
+    _delay_us(100);\r
+    if (value)\r
+      exceptionCode = (PINA & mask) != 0 ? 4 : 0;\r
+    else\r
+      exceptionCode = (PINA & mask) == 0 ? 4 : 0;\r
+\r
+    if (exceptionCode == 0)    \r
+    {\r
+      uint8_t data[4] = { address>>8, address&0xff, value>>8, 0 };\r
+      sys_modbus_sendResponse(5, 4, (uint8_t *)&data);\r
+      return 0;  \r
+    }\r
+  }\r
+  \r
+  sys_modbus_sendError(0x85, exceptionCode);\r
+  return -1;  \r
+}\r
+\r
+// Write single (hold) register (0x06): set values on 7-segment display\r
+// Address: 0..4\r
+//   Address 0: 7-segment set value and show in hex format ("0000" .. "FFFF")\r
+//   Address 1: 7-segment set value and show in unsigned decimal format "   0" .. "9999")\r
+//   Address 2: 7-segment set Value and show in signed decimal format ("-999" .. "9999")\r
+//   Address 3: 7-segement set digit 3 and 2 (value high byte, value low byte)\r
+//   Address 4: 7-segement set digit 1 and 0 (value high byte, value low byte)\r
+int8_t app_modbus_handleWriteSingleRegister () // function code 6\r
+{\r
+  uint8_t exceptionCode;\r
+  uint16_t address = sys_modbus_getByte(2)<<8 | sys_modbus_getByte(3);\r
+  uint16_t value = sys_modbus_getByte(4)<<8 | sys_modbus_getByte(5);\r
+  if (sys_uart_available()<6)\r
+    exceptionCode = 2;\r
+  else if (sys_uart_available()<8)\r
+    exceptionCode = 3;\r
+  else if (address>4)\r
+    exceptionCode = 2;\r
+  else\r
+  {\r
+    sys_modbus_setHoldingRegister(address, value);\r
+    value = sys_modbus_getHoldingRegister(address);\r
+    uint8_t data[4] = { address>>8, address&0xff, value>>8, value&0xff };\r
+    sys_modbus_sendResponse(6, 4, (uint8_t *)&data);\r
+    return 0;  \r
+  }\r
+  \r
+  sys_modbus_sendError(0x86, exceptionCode);\r
+  return -1;  \r
+}\r
+\r
+// Write multiple coils (0x0f): set one or more LEDs (one bit in value for one LED)\r
+// Address: 0..3, Quantity 1..4 (address+quantity<=4)\r
+//   Address 0: LED PA0  (1=LED on, 0=LED off)\r
+//   Address 1: LED PA1  (1=LED on, 0=LED off)\r
+//   Address 2: LED PA2  (1=LED on, 0=LED off)\r
+//   Address 3: LED PA3  (1=LED on, 0=LED off)\r
+int8_t app_modbus_handleWriteMultipleCoils ()\r
+{\r
+  uint8_t exceptionCode;\r
+  uint16_t address = sys_modbus_getByte(2)<<8 | sys_modbus_getByte(3);\r
+  uint16_t quantity = sys_modbus_getByte(4)<<8 | sys_modbus_getByte(5);\r
+  uint8_t length = sys_modbus_getByte(6);\r
+  uint8_t value = sys_modbus_getByte(7);\r
+  if (sys_uart_available()<6)\r
+    exceptionCode = 2;\r
+  else if (sys_uart_available()<10)\r
+    exceptionCode = 3;\r
+  else if (quantity <1 || quantity>0x7d0)\r
+    exceptionCode = 3;\r
+  else if (address<0 || address>3 || (address+quantity-1)>3 || length != 1)\r
+    exceptionCode = 2;\r
+  else\r
+  {\r
+    exceptionCode = 0;\r
+    value = (~value) & 0x0f; // leds ar 0 active\r
+    uint8_t i, mask;\r
+    for (i=0, mask=0; i<quantity; i++)\r
+      mask = (mask<<1) | 0x01;\r
+    mask <<= address;\r
+    value = (value << address) & mask;\r
+    \r
+    sys_cli();\r
+    PORTA = (PORTA | value) & (0xf0 | value);\r
+    _delay_us(100);\r
+    sys_sei();\r
+    \r
+    if ((PINA & mask) != value)\r
+      exceptionCode = 4;\r
+\r
+    if (exceptionCode == 0)    \r
+    {\r
+      uint8_t data[4] = { address>>8, address&0xff, quantity>>8, quantity&0xff };\r
+      sys_modbus_sendResponse(0x0f, 4, (uint8_t *)&data);\r
+      return 0;  \r
+    }\r
+  }\r
+  \r
+  sys_modbus_sendError(0x8f, exceptionCode);\r
+  return -1;  \r
+}\r
+\r
+// Write multiple (hold) registers (0x10): set values on 7-segment display\r
+// Address: 0..4\r
+//   Address 0: 7-segment set value and show in hex format ("0000" .. "FFFF")\r
+//   Address 1: 7-segment set value and show in unsigned decimal format "   0" .. "9999")\r
+//   Address 2: 7-segment set Value and show in signed decimal format ("-999" .. "9999")\r
+//   Address 3: 7-segement set digit 3 and 2 (value high byte, value low byte)\r
+//   Address 4: 7-segement set digit 1 and 0 (value high byte, value low byte)\r
+\r
+int8_t app_modbus_handleWriteMultipleRegisters ()\r
+{\r
+  uint8_t exceptionCode;\r
+  uint16_t address = sys_modbus_getByte(2)<<8 | sys_modbus_getByte(3);\r
+  uint16_t quantity = sys_modbus_getByte(4)<<8 | sys_modbus_getByte(5);\r
+  uint8_t length = sys_modbus_getByte(6);\r
+  if (sys_uart_available()<6)\r
+    exceptionCode = 2;\r
+  else if (sys_uart_available()<10)\r
+    exceptionCode = 3;\r
+  else if (quantity <1 || quantity>0x7b)\r
+    exceptionCode = 3;\r
+  else if ((address+quantity-1)>4)\r
+    exceptionCode = 2;\r
+  else if (length != (quantity*2))\r
+    exceptionCode = 4;\r
+  else\r
+  {\r
+    exceptionCode = 0;\r
+    uint8_t data[4] = { address>>8, address&0xff, quantity>>8, quantity&0xff };\r
+    uint8_t i;\r
+    for (i=0; i<length; i+=2)\r
+    {\r
+      sys_modbus_setHoldingRegister(address++, (sys_modbus_getByte(i+7)<<8) | sys_modbus_getByte(i+8) );\r
+    } \r
+    sys_modbus_sendResponse(0x10, 4, (uint8_t *)&data);\r
+    return 0;  \r
+  }\r
+  \r
+  sys_modbus_sendError(0x90, exceptionCode);\r
+  return -1;  \r
+}\r
+\r
+//--------------------------------------------------------\r
+\r
+void app_main (void)\r
+{\r
+  if (sys_clearEvent(APP_EVENT_MODBUS))\r
+  {\r
+    if (sys_uart_available()<3)\r
+      sys_modbus_sendError(0x80, 0x01); // missing function code -> not specified in protocol specification\r
+    \r
+    else if (sys_modbus_getByte(0) == 0)\r
+      ; // broadcast, do not send any response\r
+    \r
+    else\r
+    {\r
+      uint8_t functionCode = sys_modbus_getByte(1);\r
+      switch (functionCode)\r
+      {\r
+        case 0x01: app_modbus_handleReadCoil(); break;\r
+        case 0x02: app_modbus_handleReadDicreteInput(); break;\r
+        case 0x03: app_modbus_handleReadHoldingRegisters(); break;\r
+        case 0x04: app_modbus_handleReadInputRegister(); break;\r
+        case 0x05: app_modbus_handleWriteSingleCoil(); break;\r
+        case 0x06: app_modbus_handleWriteSingleRegister(); break;\r
+        case 0x0f: app_modbus_handleWriteMultipleCoils(); break;\r
+        case 0x10: app_modbus_handleWriteMultipleRegisters(); break;\r
+        default:   sys_modbus_sendError(functionCode+0x80, 0x01); break;\r
+      }\r
+    }  \r
+  }\r
+  \r
+//  if (sys.modbus.state == Idle)\r
+//    sys_setLed(3,1);\r
+//  else\r
+//    sys_setLed(3,0);\r
+//  \r
+//  if (sys.modbus.state == CtrlAndWait || sys.modbus.state == Reception)\r
+//    sys_setLed(2,1);\r
+//  else\r
+//    sys_setLed(2,0);\r
+  \r
+//  if (sys.modbus.err.errorFlags)\r
+//  {\r
+//    sys_setLed(1,1);\r
+//    //char s[5];\r
+//    //sprintf(s, "  %02x", sys.modbus.err.errorFlags);\r
+//    //sys_7seg_setString(s);\r
+//  }\r
+//  else\r
+//    sys_setLed(1,0);\r
+  \r
+  if (twi.errTimer>0)\r
+    sys_setLed(0,1);\r
+  else\r
+    sys_setLed(0,0);\r
+  \r
+  \r
+#ifdef GLOBAL_LOG\r
+  while (sys_log_getSize()>0)\r
+  {\r
+    struct Sys_LogEntry le = sys_log_next();\r
+    printf(" line %3d: received = %3d  crc=%04x  byteTimer=%d  state=%d   err=%d  avail=%d  frameLength=%d  tick_0us66=%8lu\n",\r
+           le.line, le.received, le.crc, le.byteTimer, le.state, le.error, le.available, le.frameLength, (uint32_t)le.tick100us*150 + le.tcnt0);\r
+  }\r
+#endif\r
+}\r
+\r
+//--------------------------------------------------------\r
+\r
+void app_task_1ms (void) { }\r
+void app_task_2ms (void) {}\r
+void app_task_4ms (void) {}\r
+void app_task_8ms (void) {}\r
+void app_task_16ms (void) {}\r
+void app_task_32ms (void) {}\r
+void app_task_64ms (void) {}\r
+void app_task_128ms (void) {}\r
+\r
+\r
+\r
diff --git a/sure_modbusslave/src/app.h b/sure_modbusslave/src/app.h
new file mode 100644 (file)
index 0000000..a7f451b
--- /dev/null
@@ -0,0 +1,42 @@
+#ifndef APP_H_INCLUDED\r
+#define APP_H_INCLUDED\r
+\r
+// Deklaration Strukturvariablentyp\r
+\r
+\r
+struct App\r
+{\r
+  char *version;\r
+  char *versionDate;\r
+  char *versionTime;\r
+};\r
+\r
+\r
+// Deklaration Strukturvariablen\r
+extern volatile struct App app;\r
+\r
+// globale Defines\r
+#define APP_EVENT_MODBUS   0x01\r
+#define APP_EVENT_1   0x02\r
+#define APP_EVENT_2   0x04\r
+#define APP_EVENT_3   0x08\r
+#define APP_EVENT_4   0x10\r
+#define APP_EVENT_5   0x20\r
+#define APP_EVENT_6   0x40\r
+#define APP_EVENT_7   0x80\r
+\r
+\r
+// Funktionsdeklarationen\r
+void app_init (void);\r
+void app_main (void);\r
+\r
+void app_task_1ms   (void);\r
+void app_task_2ms   (void);\r
+void app_task_4ms   (void);\r
+void app_task_8ms   (void);\r
+void app_task_16ms  (void);\r
+void app_task_32ms  (void);\r
+void app_task_64ms  (void);\r
+void app_task_128ms (void);\r
+\r
+#endif // APP_H_INCLUDED\r
diff --git a/sure_modbusslave/src/global.h b/sure_modbusslave/src/global.h
new file mode 100644 (file)
index 0000000..cf8b134
--- /dev/null
@@ -0,0 +1,58 @@
+#ifndef GLOBAL_H_INCLUDED\r
+#define GLOBAL_H_INCLUDED\r
+\r
+// globale Defines...\r
+#ifdef NETBEANS_ATMEGA16\r
+  #define F_CPU 12000000UL\r
+  #define SURE\r
+  #ifndef __AVR_ATmega16__\r
+    #define __AVR_ATmega16__\r
+  #endif\r
+#else\r
+  #ifdef NETBEANS_ATMEGA328P\r
+    #define F_CPU 12000000UL\r
+    #define ASURO\r
+    #ifndef __AVR_ATmega328P__\r
+      #define __AVR_ATmega328P__\r
+    #endif\r
+  #elif NETBEANS_ATMEGA328\r
+    #define F_CPU 12000000UL\r
+    #define ASURO\r
+    #ifndef __AVR_ATmega328__\r
+      #define __AVR_ATmega328__\r
+    #endif\r
+  #else    \r
+    #ifdef __AVR_ATmega16__\r
+      #define SURE\r
+    #elif __AVR_ATmega328P__\r
+      #define ASURO\r
+    #elif __AVR_ATmega328__\r
+      #define ASURO\r
+    #else\r
+      #error "Kein gueltiger uC-Typ gewaehlt"\r
+    #endif\r
+  #endif\r
+#endif\r
+\r
+#define GLOBAL_UART_BITRATE    57600\r
+#define GLOBAL_UART_EVENPARITY     0\r
+#define GLOBAL_UART_STOPBITS       2\r
+#define GLOBAL_UART_RECBUFSIZE    32\r
+\r
+#define GLOBAL_MODBUS_SLAVEADDRESS 2\r
+//#define GLOBAL_MODBUS_TIMERFACT 1\r
+#define GLOBAL_MODBUS_TIMERFACT 10\r
+#define GLOBAL_MODBUS_TIMER35  (385000*GLOBAL_MODBUS_TIMERFACT/GLOBAL_UART_BITRATE + 1)\r
+#define GLOBAL_MODBUS_TIMER15  (165000*GLOBAL_MODBUS_TIMERFACT/GLOBAL_UART_BITRATE + 1)\r
+#define GLOBAL_MODBUS_ERRORTIME 255\r
+\r
+//#define GLOBAL_LOG\r
+//#define GLOBAL_LOG_SIZE 16\r
+\r
+//#define GLOBAL_SURE_LCD\r
+\r
+#ifndef SURE\r
+#undef GLOBAL_SURE_LCD\r
+#endif\r
+\r
+#endif // GLOBAL_H_INCLUDED\r
diff --git a/sure_modbusslave/src/main.c b/sure_modbusslave/src/main.c
new file mode 100644 (file)
index 0000000..4b83a4c
--- /dev/null
@@ -0,0 +1,68 @@
+//***********************************************************************\r
+// Vorlage PRT Level 3\r
+// ----------------------------------------------------------------------\r
+// Beinhaltet:\r
+// UART-Support, Timer, Task-System, 7-Segment-Support, LCD-Support\r
+// ----------------------------------------------------------------------\r
+// Author: SX \r
+// Version: 1 (2012)\r
+//***********************************************************************\r
+\r
+#include "global.h"\r
+\r
+#include <stdio.h>\r
+#include <string.h>\r
+\r
+#include <avr/io.h>\r
+#include <avr/interrupt.h>\r
+#include <util/delay.h>\r
+\r
+#include "sys.h"\r
+#include "twi.h"\r
+#include "app.h"\r
+\r
+// Defines, nur in main.c sichtbar\r
+// ...\r
+\r
+// globale Variable, nur in main.c sichtbar\r
+// ...\r
+\r
+// Konstante, die im Flash abgelegt werden\r
+//const char MAIN_WELCOME[] = "\n\rProgramm ?? ";\r
+//const char MAIN_DATE[] = __DATE__;\r
+//const char MAIN_TIME[] = __TIME__;\r
+\r
+\r
+int main (void)\r
+{\r
+  sys_init();\r
+  twi_init();\r
+  app_init();\r
+  \r
+  //printf("%s %s %s\n\r", MAIN_WELCOME, MAIN_DATE, MAIN_TIME);\r
+\r
+#ifdef SURE\r
+#ifdef GLOBAL_SURE_LCD\r
+  printf("LCD ");\r
+  if (sys.lcd.status==1)\r
+  {\r
+    printf("detected and ready to use\n");\r
+    sys_lcd_putString("?? - ");\r
+    sys_lcd_putString(MAIN_TIME);\r
+  }\r
+  else\r
+    printf("not ready (status=%d)\n", sys.lcd.status);\r
+#endif // GLOBAL_SURE_LCD\r
+#endif //SURE\r
+  //sys_newline();\r
+\r
+  // Interrupt-System jetzt einschalten\r
+  sei();\r
+\r
+  while (1)\r
+  {\r
+    sys_main();\r
+    app_main();\r
+  }\r
+  return 0;\r
+}\r
diff --git a/sure_modbusslave/src/sys.c b/sure_modbusslave/src/sys.c
new file mode 100644 (file)
index 0000000..bc142e5
--- /dev/null
@@ -0,0 +1,1100 @@
+#include "global.h"\r
+\r
+#include <stdio.h>\r
+#include <string.h>\r
+#include <ctype.h>\r
+#include <stdlib.h>\r
+\r
+#include <avr/io.h>\r
+#include <avr/interrupt.h>\r
+#include <avr/wdt.h>\r
+#include <util/delay.h>\r
+\r
+#include "sys.h"\r
+#include "app.h"\r
+#include "twi.h"\r
+\r
+// Defines, nur in sys.c sichtbar\r
+#ifdef ASURO\r
+#define SYS_UART_BYTE_RECEIVED (UCSR0A & (1<<RXC0))\r
+#define SYS_UART_UDR_IS_EMPTY (UCSR0A & (1<<UDRE0))\r
+#define SYS_UDR UDR0\r
+#define SYS_UART_RECEIVE_VECTOR USART_RX_vect\r
+#define SYS_TIMER0_VECTOR TIMER0_COMPA_vect\r
+#endif\r
+\r
+#ifdef SURE\r
+#define SYS_UART_BYTE_RECEIVED (UCSRA & (1<<RXC))\r
+#define SYS_UART_UDR_IS_EMPTY (UCSRA & (1<<UDRE))\r
+#define SYS_UDR UDR\r
+#define SYS_UART_RECEIVE_VECTOR USART_RXC_vect\r
+#define SYS_TIMER0_VECTOR TIMER0_COMP_vect\r
+#endif\r
+\r
+// globale Variablen nur in sys.c sichtbar\r
+// ...\r
+\r
+// globale Strukturvariable, ueberall sichtbar\r
+volatile struct Sys sys;\r
+\r
+// Deklaration von Funktionen\r
+int sys_uart_putch (char c, FILE *f);\r
+int sys_uart_getch (FILE *f);\r
+\r
+\r
+void sys_init (void)\r
+{\r
+  memset((void *)&sys, 0, sizeof(sys));\r
+  sys.modbus.state = Init;\r
+  sys.modbus.byteTimer = GLOBAL_MODBUS_TIMER35;\r
+\r
+#ifdef ASURO\r
+  // Timer 0 used in CTC mode (clear timer in compare match)\r
+  // Timer 0 used for task switching\r
+  OCR0A  = 149;            // TOV0 interrupt every 100us @ f=12MHz\r
+  TCCR0A = (1 << WGM01);   // CTC mode\r
+  TCCR0B = (1 << CS01);    // prescaler f=12MHz/8\r
+  TIMSK0 = (1 << OCIE0A);  // Timer Output Compare A Match Interrupt enabled\r
+  TIFR0  = (1 << OCF0A);   // clear Interrupt Request Bit\r
+\r
+  // init UART-Interface (Atmega328 - USART0)\r
+  UBRR0L = F_CPU/16/GLOBAL_UART_BITRATE-1;\r
+  UBRR0H = 0x00;\r
+  UCSR0A = 0x00;\r
+  UCSR0C = (1 << UCSZ01) | (1 << UCSZ00);\r
+  UCSR0B = (1 << RXCIE0) | (1 << TXEN0) | (1 << RXEN0);\r
+\r
+  PORTB &= ~0x01; // green LED off\r
+  DDRB |= 0x01;   // green LED port (PB0) is output\r
+  PORTD &= ~0x04; // red LED off\r
+  DDRD |= 0x04;   // red LED port (PD2) is output\r
+#endif\r
+\r
+#ifdef SURE\r
+  // Timer 0 used in CTC mode (clear timer in compare match)\r
+  OCR0  = 149; // TOV0 interrupt every 100us (12E6/8/150=10000Hz)\r
+  TCCR0 = (1 << WGM01) | (1 << CS01); // CTC mode with prescaler 8\r
+  TIMSK = (1 << OCIE0);\r
+  TIFR  = (1 << OCF0);\r
+\r
+  // init UART-Interface (Atmega328 - USART0)\r
+  UBRRL = F_CPU/16/GLOBAL_UART_BITRATE-1;\r
+  UBRRH = 0x00;\r
+  UCSRA = 0x00;\r
+  if (GLOBAL_UART_EVENPARITY)\r
+    UCSRC = (1<<URSEL) | (1 << UPM1) | (1 << UCSZ1) | (1 << UCSZ0); // even parity, 1 stopbit \r
+  else if (GLOBAL_UART_STOPBITS == 2)\r
+    UCSRC = (1<<URSEL) | (1 << USBS) | (1 << UCSZ1) | (1 << UCSZ0);\r
+  else\r
+    UCSRC = (1<<URSEL) | (1 << UCSZ1) | (1 << UCSZ0); // no parity, 1 stopbit\r
+  UCSRB = (1 << RXCIE) | (1 << TXEN) | (1 << RXEN);\r
+\r
+  PORTA  =  0x0f;  // all LEDs off\r
+  PORTB  =  0x00;  // all 7-Seg anodes off, LCD-DATA=0\r
+  DDRA   =  0xff;  // LEDs (PA3:0) and 7-Seg common cathode (PA7:0)\r
+  DDRC  &= ~0xc0;  // Push Buttons SW1 (PC7) and SW2 (PC6)\r
+  DDRB   =  0xff;  // 7-Seg Segment-Anode, LCD-Data\r
+\r
+#ifdef GLOBAL_SURE_LCD\r
+  PORTD &= ~0x1c;  // LCD: E=0, RW=0, RS=0\r
+  DDRD  |=  0x1c;  // LCD: E=PD4, RW=PD3, RS=PD2\r
+  sys_lcd_init();\r
+#endif // GLOBAL_SURE_LCD\r
+\r
+#endif\r
+\r
+  // Bibliotheksfunktionen printf(), gets()... anbinden\r
+  fdevopen(sys_uart_putch, sys_uart_getch);\r
+}\r
+\r
+\r
+void sys_main (void)\r
+{\r
+}\r
+\r
+//----------------------------------------------------------------------------\r
+\r
+uint8_t sys_inc8BitCnt (uint8_t count)\r
+{\r
+  return count<0xff ? count+1 : count;\r
+}\r
+\r
+\r
+uint16_t sys_inc16BitCnt (uint16_t count)\r
+{\r
+  return count<0xffff ? count+1 : count;\r
+}\r
+\r
+\r
+int8_t sys_inc8BitCntAndReturn (uint8_t *count, int8_t retValue)\r
+{\r
+  *count = (*count)<0xff ? (*count)+1 : (*count);\r
+  return retValue;\r
+}\r
+\r
+\r
+int8_t sys_inc16BitCntAndReturn (uint16_t *count, int8_t retValue)\r
+{\r
+  *count = (*count)<0xffff ? (*count)+1 : (*count);\r
+  return retValue;\r
+}\r
+\r
+\r
+void sys_sei (void)\r
+{\r
+  if (sys.flags_u8 & SYS_FLAG_SREG_I)\r
+    sei();\r
+}\r
+\r
+\r
+void sys_cli (void)\r
+{\r
+  sys.flags_u8 |= (SREG & 0x80);\r
+  cli();\r
+}\r
+\r
+\r
+void sys_newline (void)\r
+{\r
+  printf("\n\r");\r
+}\r
+\r
+//----------------------------------------------------------------------------\r
+\r
+int sys_uart_getch (FILE *f)\r
+{\r
+  if (sys.uart.wpos_u8 == sys.uart.rpos_u8) return _FDEV_EOF;\r
+  uint8_t c = sys.uart.rbuffer_u8[sys.uart.rpos_u8++];\r
+  if (sys.uart.rpos_u8>=GLOBAL_UART_RECBUFSIZE)\r
+    sys.uart.rpos_u8 = 0;\r
+  return (int) c;\r
+}\r
+\r
+\r
+int sys_uart_putch (char c, FILE *f)\r
+{\r
+  while (!SYS_UART_UDR_IS_EMPTY);\r
+  SYS_UDR = c;\r
+  return (int)c;\r
+}\r
+\r
+\r
+uint8_t sys_uart_available (void)\r
+{\r
+  return sys.uart.wpos_u8 >= sys.uart.rpos_u8\r
+           ? sys.uart.wpos_u8 - sys.uart.rpos_u8\r
+           : ((int16_t)sys.uart.wpos_u8) + GLOBAL_UART_RECBUFSIZE - sys.uart.rpos_u8;\r
+}\r
+\r
+\r
+//----------------------------------------------------------------------------\r
+\r
+int16_t sys_uart_getBufferByte (uint8_t pos)\r
+{\r
+  int16_t value;\r
+  sys_cli();\r
+\r
+  if (pos >= sys_uart_available())\r
+    value = -1;\r
+  else\r
+  {\r
+    uint8_t bufpos = sys.uart.rpos_u8 + pos;\r
+    if (bufpos >= GLOBAL_UART_RECBUFSIZE)\r
+      bufpos -= GLOBAL_UART_RECBUFSIZE;\r
+    value = sys.uart.rbuffer_u8[bufpos];\r
+  }\r
+\r
+  sys_sei();\r
+  return value;\r
+}\r
+\r
+\r
+void sys_uart_flush (void)\r
+{\r
+  uint8_t dummy;\r
+\r
+  sys_cli();\r
+  while (SYS_UART_BYTE_RECEIVED)\r
+    dummy = SYS_UDR;\r
+\r
+  sys.uart.rpos_u8 = 0;\r
+  sys.uart.wpos_u8 = 0;\r
+  sys.uart.errcnt_u8 = 0;\r
+  sys_sei();\r
+}\r
+\r
+\r
+//****************************************************************************\r
+// Event Handling\r
+//****************************************************************************\r
+\r
+Sys_Event sys_setEvent (Sys_Event event)\r
+{\r
+  uint8_t eventIsPending = 0;\r
+  sys_cli();\r
+  if (sys.eventFlag & event)\r
+      eventIsPending = 1;\r
+  sys.eventFlag |= event;\r
+  sys_sei();\r
+\r
+  return eventIsPending;\r
+}\r
+\r
+\r
+Sys_Event sys_clearEvent (Sys_Event event)\r
+{\r
+  uint8_t eventIsPending = 0;\r
+  sys_cli();\r
+  if (sys.eventFlag & event)\r
+    eventIsPending = 1;\r
+  sys.eventFlag &= ~event;\r
+  sys_sei();\r
+\r
+  return eventIsPending;\r
+}\r
+\r
+\r
+Sys_Event sys_isEventPending (Sys_Event event)\r
+{\r
+  return (sys.eventFlag & event) != 0;\r
+}\r
+\r
+\r
+\r
+//****************************************************************************\r
+// 7 Segment Handling for Sure DEM2 Board\r
+//****************************************************************************\r
+\r
+#ifdef SURE\r
+\r
+const uint8_t sys_mask_seg7[19] = { 0x00,\r
+                                    0x3f, 0x06, 0x5b, 0x4f, 0x66, 0x6d, 0x7d, 0x07,\r
+                                    0x7f, 0x6f, 0x77, 0x7c, 0x58, 0x5e, 0x79, 0x71,\r
+                                    0x40, 0x08};\r
+\r
+void sys_7seg_refresh ()\r
+{\r
+  static uint8_t refresh = 0;\r
+\r
+  refresh = (refresh + 1) % 4;\r
+  PORTA &= ~0xf0;\r
+  //PORTB = sys_mask_seg7[sys.seg7.digit_u8[refresh]];\r
+  PORTB = sys.seg7.digit_u8[refresh];\r
+  if (sys.seg7.point_u8 & (1<<refresh))\r
+    PORTB |= 0x80;\r
+  PORTA |= (0x80 >> refresh);\r
+}\r
+\r
+\r
+void sys_7seg_setDigit (uint8_t index, uint8_t digitValue)\r
+{\r
+  if (index>3) return;\r
+#ifdef GLOBAL_SURE_LCD\r
+  sys.lcd.status = 0; // switch of LCD - PORTB used for 7seg\r
+#endif\r
+  digitValue++;\r
+  if (digitValue >= sizeof(sys_mask_seg7))\r
+    digitValue = 0; // -> digit is switched off\r
+  sys.seg7.digit_u8[index] = sys_mask_seg7[digitValue];\r
+}\r
+\r
+void sys_7seg_setDigitLeds (uint8_t index, uint8_t value)\r
+{\r
+  sys.seg7.digit_u8[index%4] = value;\r
+}\r
+\r
+\r
+\r
+void sys_7seg_setPoint (uint8_t index, uint8_t pointState)\r
+{\r
+#ifdef SURE\r
+  sys.lcd.status = 0; // switch of LCD - PORTB used for 7seg\r
+#endif\r
+  if (pointState)\r
+    sys.seg7.point_u8 |= (1<<index);\r
+  else\r
+    sys.seg7.point_u8 &= ~(1<<index);\r
+}\r
+\r
+\r
+void sys_7seg_setString (const char *str)\r
+{\r
+  int8_t i;\r
+\r
+#ifdef SURE\r
+  sys.lcd.status = 0; // switch of LCD - PORTB used for 7seg\r
+#endif\r
+\r
+  for (i=3; i>=0 && *str; i--)\r
+  {\r
+    if (*str>='0' && *str<='9')\r
+      sys_7seg_setDigit(i, *str-'0');\r
+    else if (*str>='a' && *str<='f')\r
+      sys_7seg_setDigit(i, *str-'a'+10);\r
+    else if (*str>='A' && *str<='F')\r
+      sys_7seg_setDigit(i, *str-'A'+10);\r
+    else if (*str=='-')\r
+      sys_7seg_setDigit(i, SYS_SEG7_DIGIT_MINUS);\r
+    else if (*str==' ')\r
+      sys_7seg_setDigit(i, SYS_SEG7_DIGIT_OFF);\r
+    else\r
+      sys_7seg_setDigit(i, SYS_SEG7_DIGIT_UNDERLINE);\r
+    str++;\r
+  }\r
+}\r
+\r
+void sys_7seg_showUnsignedDecimal (uint16_t value)\r
+{\r
+  char s[5];\r
+  if (value>9999)\r
+    value = 9999;\r
+  sprintf(s, "%4d", value);\r
+  sys_7seg_setString(s);\r
+}\r
+\r
+void sys_7seg_showSignedDecimal (int16_t value)\r
+{\r
+  char s[5];\r
+  if (value>9999)\r
+    value = 9999;\r
+  else if (value<-999)\r
+    value =-999;\r
+  sprintf(s, "%4d", value);\r
+  sys_7seg_setString(s);\r
+}\r
+\r
+void sys_7seg_showHex (uint16_t value)\r
+{\r
+  char s[5];\r
+  sprintf(s, "%04x", value);\r
+  sys_7seg_setString(s);\r
+}\r
+\r
+#endif // SURE\r
+\r
+\r
+//****************************************************************************\r
+// LCD Handling (only for SURE Board)\r
+//****************************************************************************\r
+\r
+#ifdef SURE\r
+#ifdef GLOBAL_SURE_LCD\r
+\r
+void sys_lcd_init (void)\r
+{\r
+  uint8_t i;\r
+\r
+  //_delay_ms(16);\r
+  sys.lcd.status = 0;\r
+  for (i=0; i<4; i++)\r
+  {\r
+    sys_lcd_setRegister(SYS_LCD_CMD_SET_FUNCTION | 0x18); // 8 Bit, 2 Zeilen, 5x7\r
+    if (i==0) _delay_ms(5); else _delay_us(100);\r
+  }\r
+\r
+  sys_lcd_setRegister(SYS_LCD_CMD_DISPLAY_ON_OFF | 0x04); // display on, cursor off\r
+  if (!sys_lcd_isReady(50)) { sys.lcd.status = -1; return; }\r
+\r
+  sys_lcd_setRegister(SYS_LCD_CMD_DISPLAY_ON_OFF | 0x04); // display on, cursor off\r
+  if (!sys_lcd_isReady(50)) { sys.lcd.status = -3; return; }\r
+\r
+  sys_lcd_setRegister(SYS_LCD_CMD_DISPLAY_CLEAR);\r
+  if (!sys_lcd_isReady(1200)) { sys.lcd.status = -4; return; }\r
+\r
+  sys.lcd.status = 1;\r
+}\r
+\r
+\r
+uint8_t sys_lcd_isReady (uint16_t us)\r
+{\r
+  if (sys.lcd.status<0) return 0;\r
+\r
+  uint8_t busy;\r
+  PORTB = 0xff;\r
+  DDRB = 0x00;  // Direction Port LCD-Data to Input\r
+  do\r
+  {\r
+    SYS_LCD_SET_RW;\r
+    SYS_LCD_CLR_RS;\r
+    _delay_us(1);\r
+    SYS_LCD_SET_E;\r
+    _delay_us(SYS_LCD_PULSE_LENGTH);\r
+    sys.lcd.data = PINB;\r
+    busy = sys.lcd.data & SYS_LCD_BUSY_FLAG;\r
+    SYS_LCD_CLR_E;\r
+    SYS_LCD_CLR_RW;\r
+    us = (us>=11) ? us-11 : 0;\r
+  }\r
+  while (us>0 && busy);\r
+\r
+  if (sys.lcd.status== 1 && busy)\r
+    sys.lcd.status = -5;\r
+\r
+  DDRB = 0xff;  // Direction Port LCD-Data to Input\r
+\r
+  return busy == 0;\r
+}\r
+\r
+\r
+void sys_lcd_setRegister (uint8_t cmd)\r
+{\r
+  PORTD &= ~0x1c; //  E=0, R/W=0, RS=0\r
+  PORTB = cmd;\r
+  DDRB = 0xff;    // Direction Port LCD-Data to Output\r
+  SYS_LCD_SET_E;\r
+  _delay_us(SYS_LCD_PULSE_LENGTH);\r
+  SYS_LCD_CLR_E;\r
+  _delay_us(1);\r
+}\r
+\r
+\r
+void sys_lcd_waitOnReady (void)\r
+{\r
+  if(sys_lcd_isReady(50)==0)\r
+    sys.lcd.status = -6;\r
+}\r
+\r
+\r
+void sys_lcd_setDisplayOff (void)\r
+{\r
+  sys_lcd_waitOnReady();\r
+  sys_lcd_setRegister(SYS_LCD_CMD_DISPLAY_ON_OFF); // display off\r
+  sys_lcd_waitOnReady();\r
+}\r
+\r
+\r
+void sys_lcd_setDisplayOn (void)\r
+{\r
+  sys_lcd_waitOnReady();\r
+  sys_lcd_setRegister(SYS_LCD_CMD_DISPLAY_ON_OFF | 0x04); // display on\r
+  sys_lcd_waitOnReady();\r
+}\r
+\r
+\r
+void sys_lcd_clear (void)\r
+{\r
+  sys_lcd_waitOnReady();\r
+  sys_lcd_setRegister(SYS_LCD_CMD_DISPLAY_CLEAR);\r
+  while (!sys_lcd_isReady(1200));\r
+}\r
+\r
+\r
+void sys_lcd_setDRAddr (uint8_t address)\r
+{\r
+  sys_lcd_waitOnReady();\r
+  sys_lcd_setRegister(SYS_LCD_CMD_SET_DDRAM_ADDR | address);\r
+  sys_lcd_waitOnReady();\r
+}\r
+\r
+\r
+// 1.Line->rowIndex=0, 1.Column->colIndex=0\r
+void sys_lcd_setCursorPosition (uint8_t rowIndex, uint8_t columnIndex)\r
+{\r
+       if (sys.lcd.status!=1 || rowIndex>1) return;\r
+  if (rowIndex)\r
+    sys_lcd_setDRAddr(0x40 + columnIndex);\r
+  else\r
+    sys_lcd_setDRAddr(columnIndex);\r
+}\r
+\r
+\r
+inline void sys_lcd_putc (char c, FILE *stream)\r
+{\r
+  sys_lcd_putchar(c);\r
+}\r
+\r
+\r
+void sys_lcd_putchar (int character)\r
+{\r
+  if (sys.lcd.status!=1) return;\r
+  sys_lcd_waitOnReady();\r
+\r
+  DDRB = 0xff;\r
+  PORTB = (uint8_t) character;\r
+  SYS_LCD_SET_RS;\r
+  SYS_LCD_CLR_RW;\r
+  SYS_LCD_SET_E;\r
+  _delay_us(SYS_LCD_PULSE_LENGTH);\r
+  SYS_LCD_CLR_E;\r
+  _delay_us(10);\r
+  DDRB = 0x00;\r
+}\r
+\r
+\r
+void sys_lcd_putString (const char * str)\r
+{\r
+  while (*str && sys.lcd.status==1)\r
+  {\r
+    sys_lcd_putchar(*str++);\r
+  }\r
+  sys_lcd_waitOnReady();\r
+}\r
+\r
+#endif // GLOBAL_SURE_LCD\r
+#endif // SURE\r
+\r
+\r
+//****************************************************************************\r
+// LED Handling\r
+//****************************************************************************\r
+\r
+#ifdef SURE\r
+\r
+void sys_setAllLeds (uint8_t ledState)\r
+{\r
+  if (ledState)\r
+  {\r
+    PORTA = 0xf0;\r
+    PORTB = 0xff;\r
+  }\r
+  else\r
+  {\r
+    PORTA = 0x0f;\r
+    PORTB = 0x00;\r
+  }\r
+}\r
+\r
+\r
+void sys_setLed (uint8_t index, uint8_t ledState)\r
+{\r
+  if (index>3) return;\r
+  sys_cli();\r
+  if (ledState)\r
+    PORTA &= ~(1<<index);\r
+  else\r
+    PORTA |= (1<<index);\r
+  sys_sei();\r
+}\r
+\r
+\r
+void sys_toggleLed (uint8_t index)\r
+{\r
+  if (index>3) return;\r
+  uint8_t mask = (1<<index);\r
+  sys_cli();\r
+  if (PORTA & mask)\r
+    PORTA &= ~mask;\r
+  else\r
+    PORTA |= mask;\r
+  sys_sei();\r
+}\r
+\r
+#endif // SURE\r
+\r
+\r
+#ifdef ASURO\r
+\r
+void sys_setGreenLed (uint8_t ledState)\r
+{\r
+  if (ledState)\r
+    PORTB |= 0x01;\r
+  else\r
+    PORTB &= ~0x01;\r
+}\r
+\r
+\r
+void sys_setRedLed (uint8_t ledState)\r
+{\r
+  if (ledState)\r
+    PORTD |= 0x04;\r
+  else\r
+    PORTD &= ~0x04;\r
+}\r
+\r
+\r
+void sys_toggleGreenLed (void)\r
+{\r
+  PORTB ^= 0x01;\r
+}\r
+\r
+\r
+void sys_toggleRedLed (void)\r
+{\r
+  PORTD ^= 0x04;\r
+}\r
+\r
+#endif // ASURO\r
+\r
+\r
+// ------------------------------------\r
+// Log functions\r
+// ------------------------------------\r
+\r
+#ifdef GLOBAL_LOG\r
+\r
+uint8_t sys_log_getSize (void)\r
+{\r
+  sys_cli();\r
+  uint8_t size = sys.log.wpos>=sys.log.rpos ? sys.log.wpos-sys.log.rpos : sys.log.wpos + GLOBAL_LOG_SIZE - sys.log.rpos;\r
+  sys_sei();\r
+  return size;\r
+}\r
+\r
+void sys_log (uint16_t line, int16_t receivedByte, uint8_t byteTimer, uint16_t tick100us, uint8_t tcnt0)\r
+{\r
+  sys_cli();\r
+  uint8_t size = sys.log.wpos>=sys.log.rpos ? sys.log.wpos-sys.log.rpos : sys.log.wpos + GLOBAL_LOG_SIZE - sys.log.rpos;\r
+  if (size<GLOBAL_LOG_SIZE)\r
+  {\r
+    struct Sys_LogEntry *p = (struct Sys_LogEntry *)&sys.log.data[sys.log.wpos++];\r
+    p->line = line;\r
+    p->tcnt0 = tcnt0;\r
+    p->crc = sys.modbus.crc;\r
+    p->tick100us = tick100us;\r
+    p->byteTimer = byteTimer;\r
+    p->state = sys.modbus.state;\r
+    p->available = sys_uart_available();\r
+    p->error = sys.modbus.err.errorFlags;\r
+    p->received = receivedByte;\r
+    p->frameLength = sys.modbus.frameLength;\r
+    if (sys.log.wpos>=GLOBAL_LOG_SIZE)\r
+      sys.log.wpos = 0; \r
+  }\r
+  sys_sei();\r
+}\r
+\r
+struct Sys_LogEntry sys_log_next ()\r
+{\r
+  struct Sys_LogEntry rv;\r
+  memset((void *)&rv, 0, sizeof(rv));\r
+  sys_cli();\r
+  uint8_t size = sys.log.wpos>=sys.log.rpos ? sys.log.wpos-sys.log.rpos : sys.log.wpos + GLOBAL_LOG_SIZE - sys.log.rpos;\r
+  if (size>0)\r
+  {\r
+    rv = sys.log.data[sys.log.rpos++];\r
+    if (sys.log.rpos>=GLOBAL_LOG_SIZE)\r
+      sys.log.rpos = 0;         \r
+  }\r
+  sys_sei();\r
+  return rv;\r
+}\r
+#else\r
+\r
+inline uint8_t sys_log_getSize (void) { return 0; }\r
+inline void sys_log (uint16_t line, int16_t receivedByte, uint8_t byteTimer, uint16_t tick100us, uint8_t tcnt0) {}\r
+struct Sys_LogEntry sys_log_next ()\r
+{\r
+  struct Sys_LogEntry rv;\r
+  memset((void *)&rv, 0, sizeof(rv));\r
+  return rv;  \r
+}\r
+\r
+#endif\r
+\r
+// ------------------------------------\r
+// Modbus functions\r
+// ------------------------------------\r
+\r
+void sys_modbus_setError (enum Sys_ModbusError typ)\r
+{\r
+  sys.modbus.err.timer = GLOBAL_MODBUS_ERRORTIME;\r
+  sys.modbus.err.errorFlags |= (1<<typ);\r
+}\r
+\r
+\r
+void sys_modbus_checkFrame (void)\r
+{\r
+  uint8_t address = sys_uart_getBufferByte(0);\r
+\r
+  if (sys.modbus.checkedFrameLength==0 && sys.modbus.crc == 0x0000 &&\r
+      (address == GLOBAL_MODBUS_SLAVEADDRESS || address == 0))\r
+  {\r
+    sys.modbus.frameOk = 1;\r
+  }\r
+  else\r
+  {\r
+    if (sys.modbus.frameLength>0)\r
+    {\r
+      sys_modbus_setError(FrameBufferFull);\r
+    }\r
+    if (sys.modbus.crc != 0x0000)\r
+    {\r
+      sys_modbus_setError(WrongCRC);\r
+    }\r
+    if (sys_uart_getBufferByte(0) != GLOBAL_MODBUS_SLAVEADDRESS)\r
+    {\r
+      sys_modbus_setError(wrongAddress);\r
+    }\r
+    sys.modbus.frameNotOkFlag = 1;\r
+  }\r
+}\r
+\r
+\r
+\r
+int16_t sys_modbus_getByte (uint8_t index)\r
+{\r
+  if (!sys.modbus.checkedFrameLength)\r
+    return -1;\r
+  \r
+  if (index >= sys.modbus.checkedFrameLength)\r
+    return -1;\r
+  \r
+  return sys_uart_getBufferByte(index);\r
+}\r
+\r
+void sys_modbus_freeFrame (void)\r
+{\r
+  //printf("checkedFrameLength = %d\n", sys.modbus.checkedFrameLength);\r
+  if (sys.modbus.checkedFrameLength)\r
+  {\r
+    sys_cli();\r
+    if (sys.modbus.checkedFrameLength >= sys_uart_available())\r
+      sys_uart_flush();\r
+    else\r
+    {\r
+      uint16_t pos = (uint16_t)sys.uart.rpos_u8 + sys.modbus.checkedFrameLength;\r
+      while (pos >= GLOBAL_UART_RECBUFSIZE)\r
+        pos -= GLOBAL_UART_RECBUFSIZE;\r
+      sys.uart.rpos_u8 = pos;\r
+    }\r
+    sys.modbus.checkedFrameLength = 0;\r
+    sys_log(__LINE__, -1, sys.modbus.byteTimer, sys.tick100us, TCNT0);\r
+    sys_sei();\r
+  }\r
+}\r
+\r
+uint16_t sys_modbus_updateCRC (uint8_t b, uint16_t crc)\r
+{\r
+  //uint16_t crc = sys.modbus.crc;\r
+  uint8_t i;\r
+  crc = crc ^ (uint16_t)b;\r
+  for (i=0; i<8; i++)\r
+  {\r
+    if (crc & 0x0001)\r
+      crc = (crc >> 1) ^ 0xa001;\r
+    else\r
+      crc = crc >> 1;\r
+  }\r
+  return crc;\r
+  //sys.modbus.crc = crc;\r
+}\r
+\r
+\r
+// address 0x0000..0x002F; Atmega I/O register\r
+// address 0x0030..0x0033; LM75A registers \r
+// address 0xfff0..0xffff: version string of app.c\r
+uint16_t sys_modbus_getInputRegister (uint16_t address, uint8_t newRequest)\r
+{\r
+  static Twi_Lm75 lm75;\r
+  static Twi_Lm75 lm75NotValid = { 0, 0, {0x7fff, 0x7fff, 0x7fff, 0x7fff}};\r
+  \r
+  if (address>=0xfff0)\r
+  {\r
+    char s[32];\r
+    memset((void *)&s, 0, sizeof(s));\r
+    snprintf(s, 32, "V%s (%s %s)", app.version, app.versionDate, app.versionTime);\r
+    address = (address - 0xfff0)*2;\r
+    return s[address]<<8 | s[address+1];\r
+  }\r
+\r
+  if (address<0 || address>0x33)\r
+    return 0xffff;\r
+  \r
+  if (newRequest)\r
+  {\r
+    sys_cli();\r
+    \r
+    if (twi.lm75.valid)\r
+      lm75 = twi.lm75;\r
+    else\r
+      lm75 = lm75NotValid;\r
+    sys_sei();\r
+  }  \r
+  if (address>=0x30)\r
+    return *( (volatile uint16_t*)(lm75.reg + (address-0x30)) );\r
+  \r
+  return *((volatile uint16_t *)(address*2) );\r
+}\r
+\r
+// address 0: 7-segment show hex 0 .. FFFF\r
+// address 1: 7-segemnt show unsigned decimal 0..9999\r
+// address 2: 7-segment show signed decimal -999 .. 9999\r
+// address 3: 7-segement set digit 3 and 2 (high byte, low byte)\r
+// address 4: 7-segement set digit 1 and 0 (high byte, low byte)\r
+void sys_modbus_setHoldingRegister (uint16_t address, uint16_t value)\r
+{\r
+  if (address>=0 && address<=2)\r
+    twi.holdingRegs.seg7value = value;\r
+  \r
+  switch (address)\r
+  { \r
+    case 0: sys_7seg_showHex(value); return;\r
+    case 1: sys_7seg_showUnsignedDecimal(value); return;\r
+    case 2: sys_7seg_showSignedDecimal((int16_t)value); return;\r
+  \r
+    case 3:\r
+      sys_7seg_setDigitLeds(2, value&0xff);\r
+      sys_7seg_setDigitLeds(3, value>>8);\r
+      break;\r
+\r
+    case 4:\r
+      sys_7seg_setDigitLeds(0, value&0xff);\r
+      sys_7seg_setDigitLeds(1, value>>8);\r
+      break;\r
+      \r
+  }\r
+}\r
+\r
+// address 0: 7-segment show hex 0 .. FFFF\r
+// address 1: 7-segemnt show unsigned decimal 0..9999\r
+// address 2: 7-segment show signed decimal -999 .. 9999\r
+// address 3: 7-segement set digit 3 and 2 (high byte, low byte)\r
+// address 4: 7-segement set digit 1 and 0 (high byte, low byte)\r
+uint16_t sys_modbus_getHoldingRegister (uint16_t address)\r
+{\r
+  if (address==0 || address==1 || address==2)  \r
+    return twi.holdingRegs.seg7value;\r
+  \r
+  switch (address)\r
+  {\r
+    case 0: case 1: case 2: return twi.holdingRegs.seg7value;\r
+    case 3: return sys.seg7.digit_u8[3]<<8 | sys.seg7.digit_u8[2];\r
+    case 4: return sys.seg7.digit_u8[1]<<8 | sys.seg7.digit_u8[0];\r
+  }\r
+  \r
+  return 0xffff;\r
+}\r
+\r
+\r
+void sys_modbus_sendRegisters (uint8_t functionCode, uint8_t size, uint16_t startAddress, uint8_t typ)\r
+{\r
+  uint16_t crc = 0xffff;\r
+  uint16_t i;\r
+  //volatile uint8_t *p = (volatile uint8_t *)startAddress;\r
+  sys_modbus_getInputRegister(0, 1);\r
+  crc = sys_modbus_updateCRC(GLOBAL_MODBUS_SLAVEADDRESS, crc);\r
+  crc = sys_modbus_updateCRC(functionCode, crc);\r
+  putchar(GLOBAL_MODBUS_SLAVEADDRESS);\r
+  putchar(functionCode); \r
+  crc = sys_modbus_updateCRC(size, crc);\r
+  putchar(size);\r
+  for (i=0; i<size; i++)\r
+  {\r
+    uint16_t value = typ ? sys_modbus_getHoldingRegister(startAddress++) :\r
+                           sys_modbus_getInputRegister(startAddress++, 0);\r
+            \r
+    crc = sys_modbus_updateCRC(value>>8, crc);\r
+    putchar(value>>8);\r
+    crc = sys_modbus_updateCRC(value&0xff, crc);\r
+    putchar(value&0xff);\r
+  }\r
+  \r
+  putchar((uint8_t)(crc&0xff));\r
+  putchar((uint8_t)(crc>>8));\r
+  \r
+  sys_modbus_freeFrame();\r
+}\r
+\r
+\r
+void sys_modbus_sendResponse (uint8_t functionCode, uint8_t size, uint8_t data[])\r
+{\r
+  uint16_t crc = 0xffff;\r
+  uint16_t i;\r
+  uint8_t *p;\r
+  crc = sys_modbus_updateCRC(GLOBAL_MODBUS_SLAVEADDRESS, crc);\r
+  crc = sys_modbus_updateCRC(functionCode, crc);\r
+  if (functionCode != 5 && functionCode != 6)\r
+    crc = sys_modbus_updateCRC(size, crc);\r
+  for (i=0, p=data; i<size; i++)\r
+    crc = sys_modbus_updateCRC(*p++, crc);\r
+  putchar(GLOBAL_MODBUS_SLAVEADDRESS);\r
+  putchar(functionCode); \r
+  if (functionCode != 5 && functionCode != 6)\r
+    putchar(size);\r
+  for (i=0, p=data; i<size; i++)\r
+    putchar(*p++);\r
+  putchar((uint8_t)(crc&0xff));\r
+  putchar((uint8_t)(crc>>8));\r
+  \r
+  sys_modbus_freeFrame();\r
+}\r
+\r
+\r
+void sys_modbus_sendError (uint8_t functionCode, uint8_t exceptionCode)\r
+{\r
+  uint16_t crc = 0xffff;\r
+  crc = sys_modbus_updateCRC(GLOBAL_MODBUS_SLAVEADDRESS, crc);\r
+  crc = sys_modbus_updateCRC(functionCode, crc);\r
+  crc = sys_modbus_updateCRC(exceptionCode, crc);\r
+\r
+  putchar(GLOBAL_MODBUS_SLAVEADDRESS);\r
+  putchar(functionCode); \r
+  putchar(exceptionCode);\r
+  putchar((uint8_t)(crc&0xff));\r
+  putchar((uint8_t)(crc>>8));\r
+  \r
+  sys_modbus_freeFrame();\r
+}\r
+\r
+\r
+// ------------------------------------\r
+// Interrupt Service Routinen\r
+// ------------------------------------\r
+\r
+ISR (SYS_UART_RECEIVE_VECTOR)\r
+{\r
+  static uint8_t lastChar;\r
+  uint8_t tcnt0 = TCNT0;\r
+  uint16_t tick100us = (uint16_t) sys.tick100us;\r
+  uint8_t byteTimer = sys.modbus.byteTimer;\r
+  uint8_t c = SYS_UDR;\r
+\r
+  if (c=='R' && lastChar=='@')\r
+  {\r
+    wdt_enable(WDTO_15MS);\r
+    wdt_reset();\r
+    while(1) {};\r
+  }\r
+\r
+  lastChar = c; // for reset detection, accept "@R" only outside modbus frame\r
+  sys.modbus.byteTimer = GLOBAL_MODBUS_TIMER35;\r
+  \r
+  switch (sys.modbus.state)\r
+  {\r
+    case Init:\r
+      break;\r
+  \r
+    case Idle:\r
+      sys.modbus.state = Reception;\r
+      sys.modbus.crc = 0xffff;\r
+      sys.modbus.frameLength = 1;\r
+      sys.modbus.frameNotOkFlag = 0;\r
+      sys.modbus.frameOk = 0;\r
+      break;\r
+      \r
+    case Reception:\r
+      lastChar = 0; // for reset detection, do not accept "@R" inside modbus frame\r
+      if (sys.modbus.frameLength>0)\r
+        sys.modbus.frameLength++;\r
+      break;\r
+    \r
+    case CtrlAndWait:\r
+      sys.modbus.frameNotOkFlag = 1;\r
+      break;\r
+      \r
+    case Emission:\r
+      sys_modbus_setError(WrongState);\r
+      sys.modbus.state = Idle;\r
+      break;\r
+    \r
+    default:\r
+      sys_modbus_setError(WrongState);\r
+      sys.modbus.state = Idle;\r
+      break;\r
+  }\r
+  \r
+  if (sys.modbus.state == Reception)\r
+  {\r
+    sys.modbus.crc = sys_modbus_updateCRC(c, sys.modbus.crc);\r
+    sys.uart.rbuffer_u8[sys.uart.wpos_u8++] = c;\r
+    if (sys.uart.wpos_u8 >= GLOBAL_UART_RECBUFSIZE)\r
+      sys.uart.wpos_u8 = 0;\r
+    if (sys.uart.wpos_u8 == sys.uart.rpos_u8)\r
+    {\r
+      sys.uart.wpos_u8 == 0 ? sys.uart.wpos_u8 = GLOBAL_UART_RECBUFSIZE-1 : sys.uart.wpos_u8--;\r
+      sys.uart.errcnt_u8 = sys_inc8BitCnt(sys.uart.errcnt_u8);\r
+      sys_modbus_setError(BufferOverflow);\r
+      sys.modbus.frameLength = 0;\r
+      sys.modbus.frameNotOkFlag = 1;\r
+    }\r
+    sys.uart.rbuffer_u8[sys.uart.wpos_u8] = 0;\r
+  }\r
+  else\r
+  {\r
+    sys.modbus.frameLength = 0;\r
+    sys.modbus.frameNotOkFlag = 1;\r
+  }\r
+  \r
+  sys_log(__LINE__, c, byteTimer, tick100us, tcnt0);\r
+}\r
+\r
+\r
+// Timer 0 Output/Compare Interrupt\r
+// called every 100us\r
+ISR (SYS_TIMER0_VECTOR)\r
+{\r
+  static uint8_t cnt100us = 0;\r
+  static uint8_t cnt500us = 0;\r
+  static uint8_t busy = 0;\r
+  sys.tick100us++;\r
+  \r
+  if (sys.modbus.byteTimer>0)\r
+  {\r
+    sys.modbus.byteTimer--;\r
+    if (sys.modbus.byteTimer < GLOBAL_MODBUS_TIMER15)\r
+    {\r
+      if (sys.modbus.state == Reception)\r
+        sys.modbus.state = CtrlAndWait;\r
+      if (sys.modbus.state == CtrlAndWait)\r
+        sys_modbus_checkFrame();\r
+      sys_log(__LINE__, -1, sys.modbus.byteTimer, sys.tick100us, TCNT0);\r
+    }\r
+  }\r
+  else if (sys.modbus.state == Reception || sys.modbus.state == CtrlAndWait)\r
+  {\r
+    if (sys.modbus.frameOk)\r
+    {\r
+      sys_log(__LINE__, -1, sys.modbus.byteTimer, sys.tick100us, TCNT0);\r
+      sys.modbus.checkedFrameLength = sys.modbus.frameLength;\r
+      sys.modbus.frameLength = 0;\r
+      sys_setEvent(APP_EVENT_MODBUS);\r
+    }\r
+    else\r
+    {\r
+      sys_modbus_setError(FrameError);\r
+      sys.modbus.checkedFrameLength = sys.modbus.frameLength;\r
+      sys.modbus.frameLength = 0;\r
+      sys_modbus_freeFrame();\r
+      //sys_log(__LINE__, -1, sys.modbus.byteTimer, sys.tick100us, TCNT0);    \r
+    }\r
+    sys.modbus.frameOk = 0;\r
+    sys.modbus.state = Idle;\r
+  }\r
+  else\r
+    sys.modbus.state = Idle;\r
+  \r
+  cnt100us++;\r
+  if (cnt100us>=5)\r
+  {\r
+    cnt100us = 0;\r
+    cnt500us++;\r
+    if (busy)\r
+      sys.taskErr_u8 = sys_inc8BitCnt(sys.taskErr_u8);\r
+    else\r
+    {\r
+      busy = 1;\r
+      sei();\r
+      if      (cnt500us & 0x01)\r
+      {\r
+        twi_task_1ms();\r
+        app_task_1ms();\r
+      }\r
+      else if (cnt500us & 0x02)\r
+      {\r
+#ifdef SURE\r
+        if (sys.lcd.status != 1)\r
+          sys_7seg_refresh();\r
+        else\r
+          PORTA &= ~0xf0; // disable 7-Segment\r
+#endif\r
+        app_task_2ms();\r
+      }\r
+      else if (cnt500us & 0x04)\r
+      {  \r
+        if (sys.modbus.err.timer>0)\r
+        {\r
+          if (!--sys.modbus.err.timer)\r
+            sys.modbus.err.errorFlags = 0;\r
+        }\r
+        app_task_4ms();\r
+      }\r
+      else if (cnt500us & 0x08) app_task_8ms();\r
+      else if (cnt500us & 0x10) app_task_16ms();\r
+      else if (cnt500us & 0x20) app_task_32ms();\r
+      else if (cnt500us & 0x40) app_task_64ms();\r
+      else if (cnt500us & 0x80) app_task_128ms();\r
+      busy = 0;\r
+    }\r
+  }\r
+\r
+}\r
diff --git a/sure_modbusslave/src/sys.h b/sure_modbusslave/src/sys.h
new file mode 100644 (file)
index 0000000..5bcdee2
--- /dev/null
@@ -0,0 +1,205 @@
+#ifndef SYS_H_INCLUDED\r
+#define SYS_H_INCLUDED\r
+\r
+#if GLOBAL_UART_RECBUFSIZE > 255\r
+  #error "GLOBAL_UART_RECBUFSIZE darf nicht groesser als 255 sein"\r
+#endif\r
+\r
+// Neue Datentypen\r
+typedef uint8_t Sys_Event;\r
+\r
+// Deklaration Strukturvariablentyp\r
+\r
+enum Sys_ModbusState { Init, Idle, Reception, CtrlAndWait, Emission  };\r
+\r
+struct Sys_LogEntry\r
+{\r
+  uint16_t line;\r
+  uint16_t tick100us;\r
+  uint16_t crc;\r
+  uint8_t tcnt0;\r
+  uint8_t byteTimer;\r
+  int16_t received;\r
+  uint8_t state;\r
+  uint8_t error;\r
+  uint8_t available;\r
+  uint8_t frameLength;\r
+};\r
+\r
+#ifdef GLOBAL_LOG\r
+struct Sys_Log\r
+{\r
+  uint8_t wpos, rpos;\r
+  struct Sys_LogEntry data[GLOBAL_LOG_SIZE];\r
+};\r
+#endif\r
+\r
+enum Sys_ModbusError { FrameError, FrameBufferFull, WrongState, WrongCRC, wrongAddress, BufferOverflow, NN6, NN7 };\r
+\r
+struct Sys_ModbusErrors\r
+{\r
+  uint8_t timer;\r
+  uint8_t errorFlags;\r
+};\r
+\r
+\r
+\r
+struct Sys_Modbus\r
+{\r
+  enum Sys_ModbusState state;\r
+  uint8_t byteTimer; // decremented to 0 every 100us, 1 char needs 190,972us\r
+  uint8_t frameLength;\r
+  uint16_t crc;\r
+  uint8_t frameNotOkFlag;\r
+  uint8_t frameOk;\r
+  uint8_t checkedFrameLength;\r
+  struct Sys_ModbusErrors err;\r
+};\r
+\r
+\r
+struct Sys_Uart\r
+{\r
+  uint8_t rpos_u8;\r
+  uint8_t wpos_u8;\r
+  uint8_t errcnt_u8;\r
+  uint8_t rbuffer_u8[GLOBAL_UART_RECBUFSIZE];\r
+};\r
+\r
+struct Sys_Seg7\r
+{\r
+  uint8_t point_u8;\r
+  uint8_t digit_u8[4];\r
+};\r
+\r
+struct Sys_Lcd\r
+{\r
+  int8_t   status;  // 0=not initialized, 1=ready, <0->error\r
+  uint8_t  data;\r
+};\r
+\r
+struct Sys\r
+{\r
+  uint8_t  flags_u8;\r
+  uint32_t tick100us;\r
+  uint8_t  taskErr_u8;\r
+  Sys_Event  eventFlag;\r
+  struct Sys_Uart uart;\r
+  struct Sys_Modbus modbus;\r
+#ifdef GLOBAL_LOG  \r
+  struct Sys_Log log;  \r
+#endif  \r
+  \r
+#ifdef SURE\r
+  struct Sys_Seg7 seg7;\r
+  struct Sys_Lcd  lcd;\r
+#endif\r
+};\r
+\r
+// Deklaration Strukturvariablen\r
+extern volatile struct Sys sys;\r
+\r
+\r
+// globale Defines\r
+// SYS_FLAG_SREG_I must have same position as I-Bit in Status-Register!!\r
+#define SYS_FLAG_SREG_I          0x80\r
+#define SYS_FLAG_7SEG_ENABLED    0x01\r
+#define SYS_FLAG_LCD_ENABLED     0x02\r
+#define SYS_SEG7_DIGIT_MINUS     0x10\r
+#define SYS_SEG7_DIGIT_UNDERLINE 0x11\r
+#define SYS_SEG7_DIGIT_OFF       0x13\r
+\r
+#ifdef SURE\r
+\r
+// LCD-Display 2x20 Zeichen, 5x8 Pixel/Zeichen\r
+// Controller KS0076B\r
+// Data: Port B (Bit 7:0)\r
+// RS=PD2, RW=PD3, E=PD4, VO (Kontrast) ueber Poti und OC1A(=PD5)\r
+\r
+#define SYS_LCD_PULSE_LENGTH 15\r
+#define SYS_LCD_SET_RS   PORTD |=  0x04; // Signal RS=1\r
+#define SYS_LCD_CLR_RS   PORTD &= ~0x04; // Signal RS=0\r
+#define SYS_LCD_SET_RW   PORTD |=  0x08; // Signal RW=1\r
+#define SYS_LCD_CLR_RW   PORTD &= ~0x08; // Signal RW=0\r
+#define SYS_LCD_SET_E    PORTD |=  0x10; // Signal E=1 \r
+#define SYS_LCD_CLR_E    PORTD &= ~0x10; // Signal E=0 \r
+\r
+#define SYS_LCD_CMD_DISPLAY_CLEAR  0x01  // Display clear\r
+#define SYS_LCD_CMD_CURSOR_HOME    0x02  // Move cursor digit 1\r
+#define SYS_LCD_CMD_SET_ENTRY_MODE 0x04  // Entry Mode Set\r
+#define SYS_LCD_CMD_DISPLAY_ON_OFF 0x08  // Display on/off\r
+#define SYS_LCD_CMD_SHIFT          0x10  // Display shift\r
+#define SYS_LCD_CMD_SET_FUNCTION   0x20  // 4/8 Bits...\r
+#define SYS_LCD_CMD_SET_CGRAM_ADDR 0x40  // Character Generator ROM\r
+#define SYS_LCD_CMD_SET_DDRAM_ADDR 0x80  // Display Data RAM\r
+#define SYS_LCD_BUSY_FLAG          0x80\r
+\r
+#endif // SURE\r
+\r
+\r
+// Funktionsdeklarationen\r
+void     sys_init                 (void);\r
+void     sys_main                 (void);\r
+\r
+void     sys_sei                  (void);\r
+void     sys_cli                  (void);\r
+\r
+uint8_t  sys_inc8BitCnt           (uint8_t count);\r
+int8_t   sys_inc8BitCntAndReturn  (uint8_t *count, int8_t retValue);\r
+uint16_t sys_inc16BitCnt          (uint16_t count);\r
+int8_t   sys_inc16BitCntAndReturn (uint16_t *count, int8_t retValue);\r
+\r
+void     sys_newline              (void);\r
+\r
+Sys_Event  sys_setEvent             (Sys_Event event);\r
+Sys_Event  sys_clearEvent           (Sys_Event event);\r
+Sys_Event  sys_isEventPending       (Sys_Event event);\r
+\r
+uint8_t  sys_uart_available       (void);\r
+int16_t  sys_uart_getBufferByte   (uint8_t pos);\r
+void     sys_uart_flush           (void);\r
+\r
+int16_t  sys_modbus_getByte       (uint8_t index);\r
+void     sys_modbus_sendResponse  (uint8_t functionCode, uint8_t size, uint8_t data[]);\r
+void     sys_modbus_sendRegisters (uint8_t functionCode, uint8_t size, uint16_t startAddress, uint8_t typ);\r
+void     sys_modbus_sendError     (uint8_t functionCode, uint8_t exceptionCode);\r
+void     sys_modbus_freeFrame     (void);\r
+void     sys_7seg_showUnsignedDecimal (uint16_t value);\r
+void     sys_7seg_showSignedDecimal (int16_t value);\r
+uint16_t sys_modbus_getInputRegister (uint16_t address, uint8_t newRequest);\r
+void     sys_modbus_setHoldingRegister (uint16_t address, uint16_t value);\r
+uint16_t sys_modbus_getHoldingRegister (uint16_t address);\r
+\r
+struct Sys_LogEntry sys_log_next    (void);\r
+uint8_t             sys_log_getSize (void);\r
+\r
+#ifdef SURE\r
+void    sys_setAllLeds            (uint8_t ledState);\r
+void    sys_setLed                (uint8_t index, uint8_t ledState);\r
+void    sys_toggleLed             (uint8_t index);\r
+void    sys_7seg_setDigit         (uint8_t index, uint8_t digitValue);\r
+void    sys_7seg_setDigitLeds     (uint8_t index, uint8_t value);\r
+void    sys_7seg_setPoint         (uint8_t index, uint8_t pointState);\r
+void    sys_7seg_setString        (const char *str);\r
+void    sys_7seg_showDecimal      (uint16_t value);\r
+void    sys_7seg_showHex          (uint16_t value);\r
+\r
+void    sys_lcd_init              (void);\r
+void    sys_lcd_setRegister       (uint8_t cmd);\r
+void    sys_lcd_setData           (uint8_t addr, uint8_t data);\r
+uint8_t sys_lcd_isReady           (uint16_t us);\r
+void    sys_lcd_setDisplayOn      (void);\r
+void    sys_lcd_setDisplayOff     (void);\r
+void    sys_lcd_clear             (void);\r
+void    sys_lcd_setCursorPosition (uint8_t rowIndex, uint8_t columnIndex);\r
+void    sys_lcd_putchar           (int character);\r
+void    sys_lcd_putString         (const char * str);\r
+#endif\r
+\r
+#ifdef ASURO\r
+void sys_setGreenLed    (uint8_t ledState);\r
+void sys_setRedLed      (uint8_t ledState);\r
+void sys_toggleGreenLed (void);\r
+void sys_toggleRedLed   (void);\r
+#endif\r
+\r
+#endif // SYS_H_INCLUDED\r
diff --git a/sure_modbusslave/src/twi.c b/sure_modbusslave/src/twi.c
new file mode 100644 (file)
index 0000000..dc62ff5
--- /dev/null
@@ -0,0 +1,359 @@
+
+#include "global.h"
+#include <avr/io.h>
+#include <avr/interrupt.h>
+#include <util/delay.h>
+#include <util/twi.h>
+#include <compat/deprecated.h>
+
+#include <stdio.h>
+#include <string.h>
+#include <stdint.h>
+
+#include "twi.h"
+#include "sys.h"
+
+//#define uchar unsigned char
+//#define uint unsigned int
+#define TWI_FREQ 4
+#define TWI_TEMPREG_ADDR     0x00 // Address of Temperature sensor
+#define TWI_READ_LM75_ADDR   0x91 // Device address is 0. Read
+#define TWI_WRITE_LM75_ADDR  0x90 // Write
+//#define TWI_Stop() TWCR=_BV(TWINT)|_BV(TWSTO)|_BV(TWEN)
+//#define TWI_Start() TWCR=_BV(TWINT)|_BV(TWSTA)|_BV(TWEN)
+
+#define TWI_MSG_STARTDONE    0x08
+#define TWI_MSG_SLAW_ACK     0x18
+#define TWI_MSG_DATA_ACK     0x28
+#define TWI_MSG_SLAR_ACK     0x40
+#define TWI_MSG_DATARCV_ACK  0x50
+#define TWI_MSG_DATARCV_NACK 0x58
+
+volatile Twi twi;
+
+
+void twi_init (void)
+{
+  memset((void *)&twi, 0, sizeof(twi));
+  TWCR = 0x00; //disable twi
+  TWBR = 0x12; //set bit rate
+  TWSR = 0x01; //set prescale
+  TWCR = 0x04; //enable twi
+}
+
+
+
+
+inline void twi_start (void)
+{
+  TWCR = (1<<TWINT) | (1<<TWSTA) | (1<<TWEN);
+}
+
+inline void twi_stop (void)
+{
+  TWCR = (1<<TWINT) | (1<<TWSTO) | (1<<TWEN);
+}
+
+inline void twi_check (uint8_t timeout_ms)
+{
+  while ((TWCR & (1<<TWINT)) == 0);
+}
+
+
+void twi_task_1ms (void)
+{
+  static uint8_t timer;
+  static uint8_t pointerByte;
+  static Twi_Lm75 lm75;
+  uint8_t status = TWSR & 0xf8;
+  if (twi.errTimer>0)
+    twi.errTimer--;
+  
+  switch (twi.state)
+  {
+    case TWIInit:
+      twi.state = TWIStart;
+      pointerByte = 0;
+      lm75.valid = 0;
+      lm75.id = twi.lm75.id + 1;
+      break;
+      
+    case TWIError: 
+      twi.errTimer = TWI_TIMER;
+      twi.state = TWIInit;
+      break;
+      
+    case TWIStart:
+      TWCR = (1<<TWINT) | (1<<TWSTA) | (1<<TWEN); // start/repeated start condition
+      twi.state = TWIWaitOnStart;
+      timer = 10;
+      break;
+    case TWIWaitOnStart:
+      timer--;
+      if (status == 0x08 || status == 0x10) // start/repeated start condition has been transmitted
+        twi.state = LM75Write;
+      else if (timer == 0)
+        twi.state = TWIError;
+      break;
+      
+    case LM75Write:
+      TWDR = 0x90; // LM75 Device Address + Write
+      TWCR = (1<<TWINT) | (1<<TWEN); // send SlaveAddress+W (SLA-W)
+      twi.state = WaitOnLM75Write;
+      timer = 10;
+      break;
+
+    case WaitOnLM75Write:
+      timer--;
+      if (status == 0x18) // SlaveAddress+W (SLA-W) has been transmitted, Ack received
+        twi.state = WritePointer; 
+      else if (status == 0x20) // SlaveAddress+W (SLA-W) has been transmitted, NAck received
+        twi.state = TWIError;
+      else if (timer==0)
+        twi.state = TWIError;
+      break;
+    
+    case WritePointer:
+      TWDR = pointerByte;
+      TWCR = (1<<TWINT) | (1<<TWEN); // send data byte
+      timer = 10;
+      twi.state = WaitOnWritePointer; 
+      break;
+      
+    case WaitOnWritePointer:
+      timer--;
+      if (status == 0x28) // data byte has been transmitted, Ack received
+        twi.state = TWIRepeatedStart; 
+      else if (status == 0x20) // SlaveAddress+W (SLA-W) has been transmitted, NAck received
+        twi.state = WaitOnWritePointer; 
+      else if (timer==0)
+        twi.state = TWIError;
+      break;
+    
+    case TWIRepeatedStart:
+      TWCR = (1<<TWINT) | (1<<TWSTA) | (1<<TWEN); // send Repeated Start
+      twi.state = TWIWaitOnRepeatedStart; 
+      timer = 10;
+      break;
+      
+    case TWIWaitOnRepeatedStart:
+      timer--;
+      if (status == 0x10) // repeated start condition has been transmitted
+        twi.state = LM75Read;
+      else if (timer == 0)
+        twi.state = TWIError;
+      break;
+
+    case LM75Read:
+      TWDR = 0x91; // LM75 Device Address + Read
+      TWCR = (1<<TWINT) | (1<<TWEN); // send SlaveAddress+R (SLA-R)
+      twi.state = WaitOnLM75Read;
+      timer = 10;
+      break;
+     
+    case WaitOnLM75Read:
+      timer--;
+      if (status == 0x40) // SlaveAddress+R (SLA-R) has been transmitted, Ack received
+      {
+        lm75.reg[pointerByte] = 0;
+        if (pointerByte==1)
+          twi.state = ReadLow;  // pointer=1 -> Config Register -> 8Bit
+        else
+          twi.state = ReadHigh; // Temp, OS, Hyst Register -> 16 Bit
+      }
+      else if (status == 0x38) // Arbitration lost or NACK received
+        twi.state = TWIError;
+      else if (status == 0x48) // SlaveAddress+R (SLA-R) has been transmitted, NAck received
+        twi.state = TWIError;
+      else if (timer==0)
+        twi.state = TWIError;
+      break;
+
+    case ReadHigh:  
+      TWCR = (1<<TWINT) | (1<<TWEA) | (1<<TWEN); // read high byte and send ACK
+      twi.state = WaitOnReadHigh;
+      timer = 10;
+      break;
+      
+    case WaitOnReadHigh:
+      timer--;
+      if (status == 0x50) // data byte received, ACK has been sent
+      {
+        lm75.reg[pointerByte] = ((uint16_t)TWDR)<<8;
+        twi.state = ReadLow; 
+      }
+      else if (timer==0)
+        twi.state = TWIError;
+      break;
+
+    case ReadLow:
+      TWCR = (1<<TWINT) | (1<<TWEN); // read high byte and send NACK (Bit TWEA=0)
+      twi.state = WaitOnReadLow;
+      timer = 10;
+      break;
+   
+    case WaitOnReadLow:
+      timer--;
+      if (status == 0x58) // data byte received, NACK has been sent
+      {
+        lm75.reg[pointerByte] |= TWDR;
+        if (++pointerByte<=3)
+          twi.state = TWIStart;
+        else
+          twi.state = TWIStop;
+      }
+      else if (timer==0)
+        twi.state = TWIError;
+      break;
+      
+    case TWIStop:
+      //sys_7seg_showHex(lm75.id);
+      //sys_7seg_showHex(lm75.reg[0]);
+      lm75.valid = 1;
+      sys_cli();
+      twi.lm75 = lm75;
+      sys_sei();
+      TWCR = (1<<TWINT) | (1<<TWSTO) | (1<<TWEN); // send STOP condition
+      twi.state = TWIWait;
+      timer = 100;
+      break;
+    
+    case TWIWait:
+      timer--;
+      if (timer==0)
+        twi.state = TWIInit;
+      break;
+    
+    default:
+      twi.state = TWIError;
+      break;
+  }
+}
+
+//
+//int8_t twi_readFromLM75 (void)
+//{
+//  uint16_t errcnt;
+//
+//  _delay_ms(20);
+//
+//  errcnt = 10;
+//  while (twi.status_u8 != TWI_MSG_STARTDONE)
+//  {
+//    if (--errcnt==0) return -1;
+//    twi_start(); // Send START signal
+//    _delay_us(1);
+//    twi.status_u8 = TWSR & 0xf8;
+//  }
+//
+//  errcnt = 10000;
+//  while (twi.status_u8 != TWI_MSG_SLAW_ACK)
+//  {
+//    if (--errcnt==0) return -2;
+//    TWDR = TWI_WRITE_LM75_ADDR; // Device Address (write)
+//    TWCR = 0x84;
+//    _delay_us(1);
+//    twi.status_u8 = TWSR & 0xf8;
+//  }
+//
+//  errcnt = 10000;
+//  while (twi.status_u8 != TWI_MSG_SLAW_ACK)
+//  {
+//    if (--errcnt==0) return -3;
+//    TWDR = TWI_TEMPREG_ADDR; // Write LM75 address.
+//    TWCR = 0x84;
+//    _delay_us(1);
+//    twi.status_u8 = TWSR & 0xf8;
+//  }
+//
+//  errcnt = 10000;
+//  while (twi.status_u8 != 0x10)
+//  {
+//    if (--errcnt==0) return -4;
+//    twi_start(); // Send REPEATED START
+//    _delay_us(1);
+//    twi.status_u8 = TWSR & 0xf8;
+//  }
+//
+//  errcnt = 10000;
+//  while (twi.status_u8 != TWI_MSG_SLAR_ACK)
+//  {
+//    if (--errcnt==0) return -5;
+//    TWDR = TWI_READ_LM75_ADDR;
+//    TWCR = 0x84;
+//    _delay_us(1);
+//    twi.status_u8 = TWSR & 0xf8;
+//  }
+//
+//
+//  // DATA has been received. ACK has been sent.
+//  errcnt = 10000;
+//  twi.status_u8=0x00;
+//  while (twi.status_u8 != TWI_MSG_DATARCV_ACK)
+//  {
+//    if (--errcnt==0) return -6;
+//    TWCR = 0xc4; // Receive high 8-bit data. ACK has been sent.
+//    _delay_us(20);
+//    twi.lm75.tempHigh = TWDR;
+//    twi.status_u8 = TWSR & 0xf8;
+//  }
+//
+//  errcnt = 10000;
+//  while(twi.status_u8 != TWI_MSG_DATARCV_NACK)
+//  {
+//    if (--errcnt==0) return -7;
+//    twi.status_u8 = TWSR & 0xf8;
+//    TWCR = 0x84; // Receive low 8-bit data. nACK has been sent.
+//    _delay_us(10);
+//    twi.lm75.tempLow = TWDR;
+//  }
+//  twi_stop();
+//
+//  return 0;
+//}
+//
+//
+//void twi_readTemperature (void)
+//{
+//  uint16_t tempH,tempL;
+//  uint16_t cvalue;
+//  int8_t err;
+//
+//  err = twi_readFromLM75();
+//
+//  if (err != 0)
+//  {
+//    TWCR = 0x00; //disable twi
+//    TWCR = 0x04; //enable twi
+//  }
+//
+//  switch (err)
+//  {
+//    case 0:
+//      tempH = twi.lm75.tempHigh;
+//      tempL = twi.lm75.tempLow;
+//
+//      //Compute Centigrade
+//      cvalue = (tempH<<8) | tempL;
+//      twi.lm75.cent_buf[0] = ' ';
+//      if ((twi.lm75.cvalue & 0x80) == 1)
+//      {
+//        cvalue = ~cvalue + 1;
+//        twi.lm75.cent_buf[0] = '-';
+//      }
+//
+//      cvalue = cvalue>>5;
+//      cvalue = cvalue * 1.25;
+//      twi.lm75.cent_buf[1] = cvalue/100+48;
+//      twi.lm75.cent_buf[2] = (cvalue/10)%10 + '0';
+//      twi.lm75.cent_buf[3] = '.';
+//      twi.lm75.cent_buf[4] = cvalue%10 + '0';
+//      twi.lm75.cent_buf[5] = '\0';
+//
+//      twi.lm75.cvalue = cvalue;
+//      break;
+//
+//    default: sprintf((char *)twi.lm75.cent_buf, "err(%d)", err); break;
+//  }
+//}
diff --git a/sure_modbusslave/src/twi.h b/sure_modbusslave/src/twi.h
new file mode 100644 (file)
index 0000000..8f55bd7
--- /dev/null
@@ -0,0 +1,53 @@
+#ifndef TWI_H_INCLUDED
+#define TWI_H_INCLUDED
+
+#define TWI_TIMER 250;
+
+typedef struct
+{
+  unsigned int valid:1;
+  unsigned int id:15;
+  uint16_t reg[4];
+} Twi_Lm75;
+
+typedef struct
+{
+  uint16_t seg7value; // address 0 and 1
+} Twi_HoldingRegs;
+
+
+// valid  ... =1 if register values has been read from device
+// id     ... sequence number 0..32767, increased by every measurement cycle
+// reg[0] ... Temperature value in two's complement coding
+//            LM75: upper 9 Bit (lower 7 Bits are zero)
+//            LM75A (Sure-Board): upper 11 Bit (lower 5 Bits are zero)
+//            divide value by 256 to get value in celsius degree
+// reg[1] ... LM75/LM75A Config register (8 Bit)
+// reg[2] ... LM75/LM75A Alarm hysteresis THYS register 16 Bit (default 75 celsius)
+// reg[3] ... LM75/LM75A Alarm threshold TOS register 16 Bit (default 80 celsius)
+
+enum Twi_State { TWIInit, TWIError, TWIStart, TWIWaitOnStart,
+                 LM75Write, WaitOnLM75Write, WritePointer, WaitOnWritePointer,
+                 TWIRepeatedStart, TWIWaitOnRepeatedStart,
+                 LM75Read, WaitOnLM75Read, 
+                 ReadHigh, WaitOnReadHigh, ReadLow, WaitOnReadLow,
+                 TWIStop, TWIWait
+               };
+
+typedef struct
+{
+  enum Twi_State state;
+  uint16_t errTimer;  
+  Twi_Lm75 lm75;
+  Twi_HoldingRegs holdingRegs;
+} Twi;
+
+extern volatile Twi twi;
+
+void twi_init            (void);
+void twi_readTemperature (void);
+void twi_task_1ms (void);
+
+
+
+#endif // TWI_H_INCLUDED
\ No newline at end of file