From 1357a76e283f88f36417fc93fdb4e330c87d1fe4 Mon Sep 17 00:00:00 2001 From: Manfred Steiner Date: Sun, 20 Sep 2020 07:45:17 +0200 Subject: [PATCH] Init commit, transfer from SVN repository https://www.htl-mechatronik.at/svn/modbus/modbus Rev 22 --- .gitignore | 24 + LICENSE | 21 + README.md | 161 ++ java_modbusmaster/build.xml | 73 + java_modbusmaster/manifest.mf | 3 + java_modbusmaster/nbproject/build-impl.xml | 1768 +++++++++++++++++ .../nbproject/genfiles.properties | 8 + .../nbproject/project.properties | 83 + java_modbusmaster/nbproject/project.xml | 15 + java_modbusmaster/src/modbus/ModbusTest.java | 195 ++ .../src/modbus/frames/ModbusFrame.java | 77 + .../modbus/frames/ModbusFrameReadCoil.java | 29 + .../frames/ModbusFrameReadDiscreteInput.java | 26 + .../ModbusFrameReadHoldingRegisters.java | 26 + .../frames/ModbusFrameReadInputRegisters.java | 29 + .../frames/ModbusFrameWriteMultipleCoils.java | 36 + .../ModbusFrameWriteMultipleRegisters.java | 36 + .../frames/ModbusFrameWriteRegister.java | 34 + .../frames/ModbusFrameWriteSingleCoil.java | 29 + sure_modbusslave/Makefile | 133 ++ .../nbproject/Makefile-Release.mk | 102 + sure_modbusslave/nbproject/Makefile-impl.mk | 133 ++ .../nbproject/Makefile-variables.mk | 27 + .../nbproject/Package-Release.bash | 75 + sure_modbusslave/nbproject/configurations.xml | 85 + sure_modbusslave/nbproject/project.xml | 21 + sure_modbusslave/released/readme | 153 ++ sure_modbusslave/released/sure.elf.hex | 598 ++++++ sure_modbusslave/src/app.c | 420 ++++ sure_modbusslave/src/app.h | 42 + sure_modbusslave/src/global.h | 58 + sure_modbusslave/src/main.c | 68 + sure_modbusslave/src/sys.c | 1100 ++++++++++ sure_modbusslave/src/sys.h | 205 ++ sure_modbusslave/src/twi.c | 359 ++++ sure_modbusslave/src/twi.h | 53 + 36 files changed, 6305 insertions(+) create mode 100644 .gitignore create mode 100644 LICENSE create mode 100644 README.md create mode 100644 java_modbusmaster/build.xml create mode 100644 java_modbusmaster/manifest.mf create mode 100644 java_modbusmaster/nbproject/build-impl.xml create mode 100644 java_modbusmaster/nbproject/genfiles.properties create mode 100644 java_modbusmaster/nbproject/project.properties create mode 100644 java_modbusmaster/nbproject/project.xml create mode 100644 java_modbusmaster/src/modbus/ModbusTest.java create mode 100644 java_modbusmaster/src/modbus/frames/ModbusFrame.java create mode 100644 java_modbusmaster/src/modbus/frames/ModbusFrameReadCoil.java create mode 100644 java_modbusmaster/src/modbus/frames/ModbusFrameReadDiscreteInput.java create mode 100644 java_modbusmaster/src/modbus/frames/ModbusFrameReadHoldingRegisters.java create mode 100644 java_modbusmaster/src/modbus/frames/ModbusFrameReadInputRegisters.java create mode 100644 java_modbusmaster/src/modbus/frames/ModbusFrameWriteMultipleCoils.java create mode 100644 java_modbusmaster/src/modbus/frames/ModbusFrameWriteMultipleRegisters.java create mode 100644 java_modbusmaster/src/modbus/frames/ModbusFrameWriteRegister.java create mode 100644 java_modbusmaster/src/modbus/frames/ModbusFrameWriteSingleCoil.java create mode 100644 sure_modbusslave/Makefile create mode 100644 sure_modbusslave/nbproject/Makefile-Release.mk create mode 100644 sure_modbusslave/nbproject/Makefile-impl.mk create mode 100644 sure_modbusslave/nbproject/Makefile-variables.mk create mode 100644 sure_modbusslave/nbproject/Package-Release.bash create mode 100644 sure_modbusslave/nbproject/configurations.xml create mode 100644 sure_modbusslave/nbproject/project.xml create mode 100644 sure_modbusslave/released/readme create mode 100644 sure_modbusslave/released/sure.elf.hex create mode 100644 sure_modbusslave/src/app.c create mode 100644 sure_modbusslave/src/app.h create mode 100644 sure_modbusslave/src/global.h create mode 100644 sure_modbusslave/src/main.c create mode 100644 sure_modbusslave/src/sys.c create mode 100644 sure_modbusslave/src/sys.h create mode 100644 sure_modbusslave/src/twi.c create mode 100644 sure_modbusslave/src/twi.h diff --git a/.gitignore b/.gitignore new file mode 100644 index 0000000..1d927c0 --- /dev/null +++ b/.gitignore @@ -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 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 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 index 0000000..3f800f9 --- /dev/null +++ b/java_modbusmaster/build.xml @@ -0,0 +1,73 @@ + + + + + + + + + + + Builds, tests, and runs the project java_modbusmaster. + + + diff --git a/java_modbusmaster/manifest.mf b/java_modbusmaster/manifest.mf new file mode 100644 index 0000000..328e8e5 --- /dev/null +++ b/java_modbusmaster/manifest.mf @@ -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 index 0000000..c3a5098 --- /dev/null +++ b/java_modbusmaster/nbproject/build-impl.xml @@ -0,0 +1,1768 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + Must set src.dir + Must set test.src.dir + Must set build.dir + Must set dist.dir + Must set build.classes.dir + Must set dist.javadoc.dir + Must set build.test.classes.dir + Must set build.test.results.dir + Must set build.classes.excludes + Must set dist.jar + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + Must set javac.includes + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + No tests executed. + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + Must set JVM to use for profiling in profiler.info.jvm + Must set profiler agent JVM arguments in profiler.info.jvmargs.agent + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + Must select some files in the IDE or set javac.includes + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + To run this application from the command line without Ant, try: + + java -jar "${dist.jar.resolved}" + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + Must select one file in the IDE or set run.class + + + + Must select one file in the IDE or set run.class + + + + + + + + + + + + + + + + + + + + + + + Must select one file in the IDE or set debug.class + + + + + Must select one file in the IDE or set debug.class + + + + + Must set fix.includes + + + + + + + + + + This target only works when run from inside the NetBeans IDE. + + + + + + + + + Must select one file in the IDE or set profile.class + This target only works when run from inside the NetBeans IDE. + + + + + + + + + This target only works when run from inside the NetBeans IDE. + + + + + + + + + + + + + This target only works when run from inside the NetBeans IDE. + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + Must select one file in the IDE or set run.class + + + + + + Must select some files in the IDE or set test.includes + + + + + Must select one file in the IDE or set run.class + + + + + Must select one file in the IDE or set applet.url + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + Must select some files in the IDE or set javac.includes + + + + + + + + + + + + + + + + + + + + + + + + Some tests failed; see details above. + + + + + + + + + Must select some files in the IDE or set test.includes + + + + Some tests failed; see details above. + + + + Must select some files in the IDE or set test.class + Must select some method in the IDE or set test.method + + + + Some tests failed; see details above. + + + + + Must select one file in the IDE or set test.class + + + + Must select one file in the IDE or set test.class + Must select some method in the IDE or set test.method + + + + + + + + + + + + + + Must select one file in the IDE or set applet.url + + + + + + + + + Must select one file in the IDE or set applet.url + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/java_modbusmaster/nbproject/genfiles.properties b/java_modbusmaster/nbproject/genfiles.properties new file mode 100644 index 0000000..17f9a58 --- /dev/null +++ b/java_modbusmaster/nbproject/genfiles.properties @@ -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 index 0000000..8eb24e2 --- /dev/null +++ b/java_modbusmaster/nbproject/project.properties @@ -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 index 0000000..4fb0c72 --- /dev/null +++ b/java_modbusmaster/nbproject/project.xml @@ -0,0 +1,15 @@ + + + org.netbeans.modules.java.j2seproject + + + java_modbusmaster + + + + + + + + + diff --git a/java_modbusmaster/src/modbus/ModbusTest.java b/java_modbusmaster/src/modbus/ModbusTest.java new file mode 100644 index 0000000..d3ae87a --- /dev/null +++ b/java_modbusmaster/src/modbus/ModbusTest.java @@ -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=20 && b<127) + sb.append((char)b); + else + sb.append('.'); + } + return sb.toString(); + } + + public static void main(String[] args) throws Exception + { + List 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 index 0000000..8cdd146 --- /dev/null +++ b/java_modbusmaster/src/modbus/frames/ModbusFrame.java @@ -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 index 0000000..76892ea --- /dev/null +++ b/java_modbusmaster/src/modbus/frames/ModbusFrameReadCoil.java @@ -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 index 0000000..bf7effa --- /dev/null +++ b/java_modbusmaster/src/modbus/frames/ModbusFrameReadDiscreteInput.java @@ -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 index 0000000..67426b8 --- /dev/null +++ b/java_modbusmaster/src/modbus/frames/ModbusFrameReadHoldingRegisters.java @@ -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 index 0000000..139ecb7 --- /dev/null +++ b/java_modbusmaster/src/modbus/frames/ModbusFrameReadInputRegisters.java @@ -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 index 0000000..b37ee76 --- /dev/null +++ b/java_modbusmaster/src/modbus/frames/ModbusFrameWriteMultipleCoils.java @@ -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>1) | ((i0xffff) + 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; i0xffff) + 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 index 0000000..73717ac --- /dev/null +++ b/java_modbusmaster/src/modbus/frames/ModbusFrameWriteRegister.java @@ -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 index 0000000..8a24f9a --- /dev/null +++ b/java_modbusmaster/src/modbus/frames/ModbusFrameWriteSingleCoil.java @@ -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 index 0000000..9fd60f8 --- /dev/null +++ b/sure_modbusslave/Makefile @@ -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 index 0000000..ff3c2e3 --- /dev/null +++ b/sure_modbusslave/nbproject/Makefile-Release.mk @@ -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 index 0000000..37be8ce --- /dev/null +++ b/sure_modbusslave/nbproject/Makefile-impl.mk @@ -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=] [SUB=no] build" + @echo " make [CONF=] [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 index 0000000..491dab2 --- /dev/null +++ b/sure_modbusslave/nbproject/Makefile-variables.mk @@ -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 index 0000000..a01d43b --- /dev/null +++ b/sure_modbusslave/nbproject/Package-Release.bash @@ -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 index 0000000..b13401a --- /dev/null +++ b/sure_modbusslave/nbproject/configurations.xml @@ -0,0 +1,85 @@ + + + + + src/app.h + src/global.h + src/sys.h + src/twi.h + + + + + src/app.c + src/main.c + src/sys.c + src/twi.c + + + + + Makefile + + + Makefile + + + + LOCAL_SOURCES + GNU-AVR|GNU + + + + 5 + true + -Wall -Os -mmcu=atmega16 + + NETBEANS_ATMEGA16 + + 2 + + + 5 + + + 5 + + + 5 + + + ${CND_DISTDIR}/sure.elf + -mmcu=atmega16 -Wl,-Map=${CND_DISTDIR}/asuro.map,--cref + + + + + + + + + + + + + + + + + + + + + diff --git a/sure_modbusslave/nbproject/project.xml b/sure_modbusslave/nbproject/project.xml new file mode 100644 index 0000000..16dfa40 --- /dev/null +++ b/sure_modbusslave/nbproject/project.xml @@ -0,0 +1,21 @@ + + + org.netbeans.modules.cnd.makeproject + + + sure_modbusslave + c + + h + UTF-8 + + + + + Release + 1 + + + + + diff --git a/sure_modbusslave/released/readme b/sure_modbusslave/released/readme new file mode 100644 index 0000000..44431a0 --- /dev/null +++ b/sure_modbusslave/released/readme @@ -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 index 0000000..2ff572d --- /dev/null +++ b/sure_modbusslave/released/sure.elf.hex @@ -0,0 +1,598 @@ +:100000000C943C000C9459000C9459000C94590029 +:100010000C9459000C9459000C9459000C945900FC +:100020000C9459000C9459000C9459000C94660AD5 +:100030000C9459000C9459000C9459000C945900DC +:100040000C9459000C9459000C9459000C943F0BDB +:100050000C945900800CA90CB00CB50CC20CC90C46 +:10006000D70CE00CF00CFA0C050D0C0D290D2E0D23 +:10007000420D470D730D910D11241FBECFE5D4E045 +:10008000DEBFCDBF10E0A0E6B0E0ECEEF4E202C0CF +:1000900005900D92A83BB107D9F711E0A8EBB0E0AD +:1000A00001C01D92AF32B107E1F70E9497040C9492 +:1000B00074120C94000023ED30E0C90160E070E0A0 +:1000C00046E050E00E94A40D80E690E09093D400BA +:1000D0008093D30088E690E09093D6008093D5007B +:1000E00084E790E09093D8008093D7008FE39EE759 +:1000F000A5E081509040A040E1F700C000000895C5 +:10010000CF92DF92EF92FF920F931F93DF93CF93E3 +:100110000F92CDB7DEB782E00E94BC07D82E83E0F5 +:100120000E94BC078C0184E00E94BC07C82E85E0B9 +:100130000E94BC077C010E943A05863008F44BC03F +:100140000E943A05883008F444C07C2D60E0E62A1D +:10015000F72A97012150304087E0203D3807C8F545 +:100160003D2D20E0022B132B04301105A0F5C80112 +:100170008E0D9F1D01978430910568F589B344E089 +:1001800050E04E195F092FE030E002C03595279509 +:100190004A95E2F780958F7090E002C0959587951B +:1001A0000A95E2F782238983C70187709070B701AF +:1001B00023E0769567952A95E1F7009711F06F5F38 +:1001C0007F4F81E0AE014F5F5F4F0E94900980E05A +:1001D00007C063E001C062E081E80E941D0A8FEF62 +:1001E0000F90CF91DF911F910F91FF90EF90DF90D3 +:1001F000CF900895CF92DF92EF92FF920F931F93CB +:10020000DF93CF930F92CDB7DEB782E00E94BC0799 +:10021000D82E83E00E94BC078C0184E00E94BC07BA +:10022000C82E85E00E94BC077C010E943A058630FA +:1002300008F454C00E943A05883008F44DC07C2D63 +:1002400060E0E62AF72A97012150304087E0203D00 +:10025000380708F041C03D2D20E0022B132B02305F +:100260001105E0F5C8018E0D9F1D019782309105A3 +:10027000A8F583B3881F8827881F9E9B02C022E0B1 +:1002800001C020E0282B209530E002C0359527954D +:100290000A95E2F742E050E04E195F0983E090E0F2 +:1002A00002C0959587954A95E2F782238983C70115 +:1002B00087709070B70133E0769567953A95E1F7CE +:1002C000009711F06F5F7F4F82E0AE014F5F5F4F8D +:1002D0000E94900980E007C063E001C062E082E80C +:1002E0000E941D0A8FEF0F90CF91DF911F910F9108 +:1002F000FF90EF90DF90CF900895EF92FF920F93D1 +:100300001F93CF93DF9382E00E94BC07F82E83E017 +:100310000E94BC07EC0184E00E94BC07E82E85E047 +:100320000E94BC078C010E943A05863018F10E9499 +:100330003A058830E8F03E2D20E0022B132B98017F +:10034000215030402D37310598F45F2D40E04C2B83 +:100350005D2BCA01800F911F01978530910550F4E4 +:10036000602F660F83E021E00E94050980E007C04E +:1003700063E001C062E083E80E941D0A8FEFDF9115 +:10038000CF911F910F91FF90EF900895EF92FF9200 +:100390000F931F93CF93DF9382E00E94BC07E82E58 +:1003A00083E00E94BC07EC0184E00E94BC07F82EA9 +:1003B00085E00E94BC078C010E943A05863008F453 +:1003C0003FC00E943A058830C8F17F2D60E0602B65 +:1003D000712B9B01215030402D37310578F55E2D72 +:1003E00040E04C2B5D2B4433510540F4CA01860F8D +:1003F000971F019784339105D0F022C02FEF403F23 +:100400005207A8F0CA01A0E0B0E07B0100E010E0D4 +:100410008E0D9F1DA01FB11F0197A109B10980304A +:1004200020E0920721E0A20720E0B20748F4660F1F +:1004300084E020E00E94050980E007C063E001C07D +:1004400062E084E80E941D0A8FEFDF91CF911F9137 +:100450000F91FF90EF900895CF92DF92EF92FF926D +:100460000F931F93DF93CF9300D000D0CDB7DEB7AB +:1004700082E00E94BC07D82E83E00E94BC078C015A +:1004800084E00E94BC07C82E85E00E94BC077C0166 +:100490000E943A05863008F44FC00E943A05883021 +:1004A00008F448C03C2D20E0E22AF32AE114F104CC +:1004B00029F080E0E8168FEFF806E1F53D2D20E009 +:1004C000022B132B04301105B8F581E090E0002ECB +:1004D00002C0880F991F0A94E2F7D82E0E942505C2 +:1004E000E114F10429F09BB38D2D8095892302C07E +:1004F0008BB38D298BBB0E941F058BE291E0019786 +:10050000F1F700C00000E114F10421F089B38D215E +:10051000A9F403C089B38D2189F019820A83FB8273 +:100520001C8285E064E0AE014F5F5F4F0E9490093E +:1005300080E009C063E003C062E001C064E085E8D8 +:100540000E941D0A8FEF0F900F900F900F90CF9188 +:10055000DF911F910F91FF90EF90DF90CF90089562 +:10056000CF92DF92EF92FF920F931F93DF93CF937F +:1005700000D000D0CDB7DEB782E00E94BC07C82E05 +:1005800083E00E94BC078C0184E00E94BC07D82E47 +:1005900085E00E94BC077C010E943A05863020F16C +:1005A0000E943A058830F0F03C2D20E0022B132BFE +:1005B00005301105C8F47D2D60E06E297F29C80142 +:1005C0000E94B308C8010E94E30819820A839B8332 +:1005D0008C8386E064E0AE014F5F5F4F0E9490091C +:1005E00080E007C063E001C062E086E80E941D0A67 +:1005F0008FEF0F900F900F900F90CF91DF911F9181 +:100600000F91FF90EF90DF90CF900895AF92BF923F +:10061000CF92DF92EF92FF920F931F93DF93CF93CE +:1006200000D000D0CDB7DEB782E00E94BC07B82E64 +:1006300083E00E94BC078C0184E00E94BC07A82EC6 +:1006400085E00E94BC077C0186E00E94BC07D82E92 +:1006500087E00E94BC07C82E0E943A05863008F445 +:1006600067C00E943A058A3008F460C03A2D20E045 +:10067000E22AF32A97012150304087E0203D3807D5 +:1006800008F054C03B2D20E0022B132B0430110541 +:1006900008F04EC098012E0D3F1D215030402430EF +:1006A000310508F045C09D2D913009F041C08C2DD9 +:1006B00080958F7020E090E004C0220F331F2160EE +:1006C0009F5F492F50E030E04E155F05B0F3002EDC +:1006D00002C0220F331F0A94E2F7B22E90E0002EE0 +:1006E00002C0880F991F0A94E2F7D22ED8220E94E6 +:1006F00025058BB3807F8D298BBB8BE291E0019721 +:10070000F1F700C000000E941F0589B38B218D15F1 +:1007100089F419820A831B82EC828FE064E0AE01C7 +:100720004F5F5F4F0E94900980E009C063E003C003 +:1007300062E001C064E08FE80E941D0A8FEF0F9015 +:100740000F900F900F90CF91DF911F910F91FF901D +:10075000EF90DF90CF90BF90AF9008959F92AF92AF +:10076000BF92CF92DF92EF92FF920F931F93DF938E +:10077000CF9300D000D00F92CDB7DEB782E00E94B9 +:10078000BC07A82E83E00E94BC078C0184E00E9475 +:10079000BC07982E85E00E94BC077C0186E00E9481 +:1007A000BC07B82E0E943A05863008F44FC00E945C +:1007B0003A058A3008F448C0392D20E02E293F2917 +:1007C000A901415050404B375105F0F55A2D40E0FA +:1007D0007A01E02AF12AC701820F931F0197853021 +:1007E0009105A0F54B2D50E0C901880F991F4817BE +:1007F000590771F5F982EA821B822C8320E019C027 +:1008000087010F5F1F4F822F895F2D830E94BC07D6 +:10081000A82E2D81822F885F0E94BC07DA2CCC2461 +:10082000B601682B792BC7010E94B3082D812E5F7A +:1008300078012B1528F380E164E0AE014F5F5F4F34 +:100840000E94900980E009C063E003C062E001C03B +:1008500064E080E90E941D0A8FEF0F900F900F90C7 +:100860000F900F90CF91DF911F910F91FF90EF901C +:10087000DF90CF90BF90AF909F90089581E00E944D +:1008800095058823F1F10E943A05833010F480E841 +:1008900035C080E00E94BC07009799F181E00E947A +:1008A000BC078430D9F0853038F4823089F0833049 +:1008B00090F4813011F509C08630B1F0863088F0AF +:1008C0008F30A9F08031C9F415C00E94800019C092 +:1008D0000E94FA0016C00E947D0113C00E94C6014A +:1008E00010C00E942C020DC00E94B0020AC00E94DB +:1008F000060307C00E94AE0304C0805861E00E9456 +:100900001D0A8091170190911801009719F080E05D +:1009100061E002C080E060E00E9409070895089548 +:1009200008950895089508950895089508950E94DA +:10093000C8040E94440C0E945B0078940E94F70453 +:100940000E943E04FBCF9091E1008091E000981757 +:1009500091F08091E000E82FF0E0E752FF4F228510 +:100960008F5F8093E0008091E000803210F0109261 +:10097000E00030E002C02EEF3FEFC90108955D9B1B +:10098000FECF8CB9282F332727FD3095932F08955C +:1009900029ED30E0C90160E070E04CE350E00E94D6 +:1009A000A40D109204011092030183E480930501C9 +:1009B00085E98CBF8AE083BF82E089BF88BF8CE075 +:1009C00089B910BC1BB88EE880BD88E98AB98FE070 +:1009D0008BBB18BA9FEF9ABB84B38F7384BB97BB52 +:1009E0008FEB94E063EA74E00E94AB0D08950895E4 +:1009F0008F3F09F08F5F08959C018FEF2F3F3807DD +:100A000011F02F5F3F4FC9010895FC01862F90819F +:100A10009F3F11F09F5F01C09FEF90830895FC01FD +:100A2000862F208131819FEF2F3F390719F02F5FEB +:100A30003F4F02C02FEF3FEF318320830895809115 +:100A4000D90087FF01C0789408959091D9008FB79D +:100A50008078892B8093D900F894089500D08DE791 +:100A600090E0EDB7FEB7928381830E94220E0F9033 +:100A70000F9008959091E1008091E000981730F078 +:100A80008091E1009091E000891B08958091E10040 +:100A90009091E000805E891B0895EF92FF921F9372 +:100AA000CF93DF93182F0E9425050E943A0518174F +:100AB00068F4E091E000E10FE03208F0E052F0E08D +:100AC000E752FF4F8285C82FD0E002C0CFEFDFEFA3 +:100AD0000E941F05CE01DF91CF911F91FF90EF90F3 +:100AE00008950E94250501C08CB15F99FDCF109239 +:100AF000E0001092E1001092E2000E941F050895AC +:100B00000F931F93182F0E9425050091DF008091FD +:100B1000DF00812B8093DF000E941F05102381E0FE +:100B200009F480E01F910F9108950F931F93182FE0 +:100B30000E9425050091DF009091DF00812F8095B4 +:100B400089238093DF000E941F05102381E009F4B0 +:100B500080E01F910F9108959091DF00982381E02C +:100B600009F480E008958091C60090E001968370BA +:100B700090708093C6002BB32F702BBB382F8752F9 +:100B80009F4FFC0186A988BB80910E0190E0032E47 +:100B900002C0959587950A94E2F780FDC79A2BB31A +:100BA00080E890E002C0959587953A95E2F7282B6A +:100BB0002BBB0895843070F46F5F633108F060E000 +:100BC000E82FF0E0A62FB0E0AB56BF4F8C91E75274 +:100BD000FF4F86AB0895E82FF0E0E370F070E75226 +:100BE000FF4F66AB089510921301662369F0909150 +:100BF0000E0121E030E002C0220F331F8A95E2F798 +:100C0000922B90930E01089590910E0121E030E017 +:100C100002C0220F331F8A95E2F7209529232093E3 +:100C20000E010895EF92FF921F93CF93DF931092DE +:100C30001301E82EE7017E01F92EE70113E024C03D +:100C4000682F60536A3068F0982F9156963018F4E8 +:100C5000682F675506C0982F9154963020F4682F5E +:100C60006753812F0CC08D3219F4812F60E107C0CA +:100C7000803219F4812F63E102C0812F61E10E946B +:100C8000DA0511501F3F19F089918823C9F6DF91C9 +:100C9000CF911F91FF90EF900895DF93CF9300D0F5 +:100CA00000D00F92CDB7DEB700D000D000D0EDB7A6 +:100CB000FEB731969E012F5F3F4FADB7BEB712967C +:100CC0003C932E93119720E830E033832283282F22 +:100CD000392FC901B7E280319B0710F08FE097E20E +:100CE000958384830E94680E8DB79EB706960FB6D3 +:100CF000F8949EBF0FBE8DBFCE0101960E941206D2 +:100D00000F900F900F900F900F90CF91DF9108955B +:100D1000DF93CF9300D000D00F92CDB7DEB7282F4E +:100D2000392FC9012CEF8931920714F489E19CEF26 +:100D300000D000D000D0EDB7FEB731969E012F5FF6 +:100D40003F4FADB7BEB712963C932E93119720E854 +:100D500030E033832283B7E280319B0714F08FE0C9 +:100D600097E2958384830E94680E8DB79EB706969E +:100D70000FB6F8949EBF0FBE8DBFCE0101960E94A4 +:100D800012060F900F900F900F900F90CF91DF9160 +:100D900008950F931F93DF93CF9300D000D00F924D +:100DA000CDB7DEB700D000D000D0EDB7FEB731969A +:100DB0008E010F5F1F4FADB7BEB712961C930E93F7 +:100DC000119724E830E033832283958384830E9443 +:100DD000680E8DB79EB706960FB6F8949EBF0FBEED +:100DE0008DBFC8010E9412060F900F900F900F90B8 +:100DF0000F90CF91DF911F910F910895882329F0D3 +:100E000080EF8BBB8FEF88BB08958FE08BBB18BA48 +:100E10000895DF93CF9300D0CDB7DEB7843000F5CF +:100E20006A8389830E9425056A818981662361F02E +:100E30009BB321E030E002C0220F331F8A95E2F716 +:100E4000209529232BBB0AC09BB321E030E002C0D0 +:100E5000220F331F8A95E2F7922B9BBB0E941F053E +:100E60000F900F90CF91DF9108951F938430B8F4C5 +:100E700021E030E002C0220F331F8A95E2F7122FE3 +:100E80000E9425058BB3812329F08BB3109518237D +:100E90001BBB03C08BB3812B8BBB0E941F051F9113 +:100EA000089580E008950895DF93CF93CDB7DEB71E +:100EB0002E970FB6F894DEBF0FBECDBFFE01319660 +:100EC0002EE0DF011D922A95E9F7282F392FD9014D +:100ED0002EE001900D922150E1F72E960FB6F89476 +:100EE000DEBF0FBECDBFCF91DF9108959FEF9093EE +:100EF0000C0190910D0121E030E002C0220F331F60 +:100F00008A95E2F7922B90930D01089580E00E945C +:100F10004D0590910B01992379F4209107013091AF +:100F200008012115310541F4823011F0882321F4A4 +:100F300081E080930A01089580910601882321F0C1 +:100F400081E090E00E94760780910701909108016E +:100F5000009721F083E090E00E94760780E00E94F5 +:100F60004D058230910521F084E090E00E947607E3 +:100F700081E080930901089590910B01992341F03C +:100F800090910B01891720F40E944D059C0102C02D +:100F90002FEF3FEFC90108951F9380910B01882324 +:100FA00029F10E94250510910B010E943A0518179E +:100FB00018F00E9471050BC08091E00020910B0198 +:100FC00090E0820F911D8F7190708093E0001092DD +:100FD0000B01809105018091DA009091DB00A091D6 +:100FE000DC00B091DD0082B70E941F051F910895BB +:100FF00090E06827792748E021E030EACB01969518 +:10100000879560FF04C0BC016227732701C0BC0143 +:101010004150A1F7CB010895EF92FF920F931F93D8 +:10102000DF93CF93CDB7DEB7A0970FB6F894DEBFAE +:101030000FBECDBF8C017FEF803F970708F454C0EF +:101040007E010894E11CF11C80E2D7011D928A9573 +:10105000E9F74091D3005091D4002091D500309110 +:10106000D6008091D7009091D800EDB7FEB73C979D +:101070000FB6F894FEBF0FBEEDBF3196ADB7BEB749 +:101080001296FC92EE92119760E270E07383628395 +:1010900069E870E0758364835783468331872087CE +:1010A000938782870E94370E005F1F4F000F111F2A +:1010B000FE01E00FF11F2281332727FD30950E0D31 +:1010C0001F1DF8018081992787FD9095982F88270B +:1010D000282B392B6DB77EB7645F7F4F0FB6F8941E +:1010E0007EBF0FBE6DBF31C08433910560F56623AE +:1010F000D9F00E9425058091190180FF0AC0ACEB50 +:10110000B0E0E9E1F1E08AE001900D928150E1F771 +:1011100009C0ACEBB0E0E8EAF0E08AE001900D92A3 +:101120008150E1F70E941F050033110530F0F801EE +:10113000EE0FFF1FE25AFF4F03C0F801EE0FFF1F33 +:101140002081318102C02FEF3FEFC901A0960FB679 +:10115000F894DEBF0FBECDBFCF91DF911F910F91ED +:10116000FF90EF9008959C01CB012330310520F4CE +:10117000709324016093230122303105B9F02330AC +:10118000310538F42115310559F021303105D1F4FC +:101190000AC02330310569F02430310599F40EC0BE +:1011A0000E94C90608950E944D0608950E9488066F +:1011B00008958093110190931201089580930F0177 +:1011C0009093100108958330910528F42091230114 +:1011D0003091240118C08330910521F084309105AD +:1011E00081F405C0309112012091110104C03091A9 +:1011F000100120910F01932F80E030E0282B392B34 +:1012000002C02FEF3FEFC90108959F92AF92BF92A6 +:10121000CF92DF92EF92FF920F931F93CF93DF93C2 +:10122000082FE62E6A01922E80E090E061E00E9495 +:101230000C0882E06FEF7FEF0E94F807BC01802F5F +:101240000E94F807EC01609127017091280182E06B +:1012500090E00E94F60D6091270170912801802F87 +:1012600090E00E94F60D8E2DBE010E94F807182F07 +:10127000092F60912701709128018E2D90E00E9426 +:10128000F60DC0E0D0E0FF2427C0992019F00E949D +:10129000E30803C060E00E940C08B82EA92E892F35 +:1012A000612F702F0E94F8078C01609127017091C7 +:1012B00028018A2D90E00E94F60D8B2DB8010E9426 +:1012C000F807182F092F60912701709128018B2DA5 +:1012D00090E00E94F60D2196CE018C0D9D1DCE153D +:1012E000DF0598F26091270170912801812F90E02D +:1012F0000E94F60D6091270170912801802F90E0E7 +:101300000E94F60D0E94CC07DF91CF911F910F91A3 +:10131000FF90EF90DF90CF90BF90AF909F90089597 +:101320006F927F928F929F92AF92BF92CF92DF92F5 +:10133000EF92FF920F931F93DF93CF930F92CDB74E +:10134000DEB7E82EF62EB42EA52E82E06FEF7FEFEB +:101350000E94F807BC018E2D0E94F8076C018E2DAB +:1013600085508983823028F08F2DB6010E94F807BE +:101370006C01C501092F1A2D662477248F2C99241E +:101380000AC0F80181918F01B6010E94F8076C0133 +:101390000894611C711C6814790498F3609127010A +:1013A0007091280182E090E00E94F60D6091270183 +:1013B000709128018E2D90E00E94F60DF981F23097 +:1013C00040F060912701709128018F2D90E00E94DC +:1013D000F60DC501092F1A2DEE24FF2409C0F801CE +:1013E00081918F0190E00E94F60D0894E11CF11CA0 +:1013F0006091270170912801E814F90480F38C2D85 +:1014000090E00E94F60D60912701709128018D2DCA +:1014100090E00E94F60D0E94CC070F90CF91DF91D3 +:101420001F910F91FF90EF90DF90CF90BF90AF9002 +:101430009F908F907F906F900895EF92FF920F93FF +:101440001F93F82E162F82E06FEF7FEF0E94F807B0 +:101450009C018F2DB9010E94F8079C01812FB901D1 +:101460000E94F807E82E092F2091270130912801CA +:1014700082E090E0B9010E94F60D209127013091A1 +:1014800028018F2D90E0B9010E94F60D20912701CF +:1014900030912801812F90E0B9010E94F60D6091F2 +:1014A0002701709128018E2D90E00E94F60D609129 +:1014B000270170912801802F90E00E94F60D0E9474 +:1014C000CC071F910F91FF90EF9008951F920F92FC +:1014D0000FB60F9211241F932F933F934F935F9357 +:1014E0006F937F938F939F93AF93BF93EF93FF93EC +:1014F00082B78091DA009091DB00A091DC00B0917E +:10150000DD00809105011CB1123579F48091BB009A +:10151000803459F428E088E190E00FB6F894A8955B +:1015200081BD0FBE21BDA895FFCF1093BB0083E402 +:10153000809305012091030130910401223031058F +:1015400011F12330310538F421153105B1F1213085 +:10155000310549F504C02330310529F520C082E06A +:1015600090E090930401809303018FEF9FEF90939D +:1015700008018093070181E0809306011092090120 +:1015800010920A011AC01092BB00809106018823B4 +:10159000A1F0809106018F5F809306010EC081E06B +:1015A000809309010AC082E090E00E94760781E002 +:1015B00090E0909304018093030120910301309106 +:1015C00004012230310509F043C060910701709198 +:1015D0000801812F0E94F80790930801809307016A +:1015E0008091E100E82FF0E0E752FF4F12878F5F14 +:1015F0008093E1008091E100803210F01092E100D0 +:101600009091E1008091E0009817D9F48091E10079 +:10161000882311F48FE103C08091E1008150809311 +:10162000E1008091E2008F3F09F08F5F8093E2003C +:1016300085E090E00E9476071092060181E0809399 +:101640000901E091E100F0E0E752FF4F128605C08A +:101650001092060181E080930901FF91EF91BF9103 +:10166000AF919F918F917F916F915F914F913F913A +:101670002F911F910F900FBE0F901F9018951F92E2 +:101680000F920FB60F9211242F933F934F935F93B6 +:101690006F937F938F939F93AF93BF93EF93FF933A +:1016A0008091DA009091DB00A091DC00B091DD0028 +:1016B0000196A11DB11D8093DA009093DB00A093E9 +:1016C000DC00B093DD0080910501882361F18091F9 +:1016D0000501815080930501809105018D3108F04D +:1016E0005DC080910301909104018230910531F435 +:1016F00083E090E0909304018093030180910301C3 +:10170000909104018330910511F40E948607809125 +:1017100005018091DA009091DB00A091DC00B0918E +:10172000DD0082B73BC080910301909104018230BB +:10173000910539F080910301909104018330910566 +:1017400039F580910A018823A9F0809105018091E3 +:10175000DA009091DB00A091DC00B091DD0082B74F +:101760008091060180930B011092060181E00E9496 +:1017700080050CC080E090E00E9476078091060111 +:1017800080930B01109206010E94CC0710920A016F +:1017900081E090E090930401809303018091BA006E +:1017A0008F5F8093BA00853008F45DC01092BA0054 +:1017B0008091B9008F5F8093B9008091B800882331 +:1017C00041F08091DE008F3F09F08F5F8093DE0053 +:1017D0004AC081E08093B80078949091B90090FF5E +:1017E00005C00E945F0C0E948F043BC091FF0DC09A +:1017F00080911301813019F00E94B30503C08BB3AF +:101800008F708BBB0E9490042CC092FF12C08091FD +:101810000C01882359F080910C01815080930C01B8 +:1018200080910C01882311F410920D010E94910403 +:1018300018C093FF03C00E94920413C094FF03C01A +:101840000E9493040EC095FF03C00E94940409C037 +:1018500096FF03C00E94950404C097FF02C00E9437 +:1018600096041092B800FF91EF91BF91AF919F91B4 +:101870008F917F916F915F914F913F912F910F9039 +:101880000FBE0F901F90189525E131E0C90160E06F +:1018900070E040E150E00E94A40D16BE82E180B9E4 +:1018A00081E081B984E086BF089584EA86BF089507 +:1018B00084E986BF089506B607FEFDCF089521B1DD +:1018C000287F8091170190911801009749F080912D +:1018D00017019091180101979093180180931701B7 +:1018E000E0911501F0911601E231F10508F025C1F2 +:1018F000E65DFF4FEE0FFF1F0590F491E02D099478 +:1019000082E090E090931601809315011092D1002F +:101910008091C7008E7F8093C70020911901269582 +:1019200030911A01379533273795832F822B2091D9 +:101930001A01922F96950196282F220F2093C70007 +:10194000292F220F881F8827881F822B8093C80089 +:1019500008958AEF90E09093180180931701E8C0F2 +:1019600084EA86BF83E090E03FC08091D20081503E +:101970008093D200283019F0203109F0ABC084E008 +:1019800090E0ACC080E983B984E886BF85E090E050 +:101990002BC08091D20081508093D200283119F45D +:1019A00086E090E09BC0203209F094C095C0809101 +:1019B000D10083B984E886BF8AE08093D2000DC04D +:1019C0008091D20081508093D200283219F488E0AF +:1019D00090E084C0203209F07DC087E090E07EC0B6 +:1019E00084EA86BF89E090E0909316018093150108 +:1019F0008AE094C08091D20081508093D20020313F +:101A000009F068C08AE090E069C081E983B984E8A0 +:101A100086BF8BE090E0E8CF8091D2008150809328 +:101A2000D200203479F48091D100E82FF0E0EE0F5D +:101A3000FF1FE753FF4F11821082813001F18CE0CC +:101A400090E04CC0283309F447C0283409F042C064 +:101A500043C084EC86BF8DE090E0C6CF8091D20079 +:101A600081508093D2002035A9F583B1E091D10057 +:101A7000F0E0EE0FFF1FE753FF4F108281838EE0EF +:101A800090E02CC084E886BF8FE090E0ADCF8091DD +:101A9000D20081508093D2002835E1F44091D100EA +:101AA000E42FF0E023B1EE0FFF1FE753FF4F30E0CC +:101AB00080819181822B932B91838083842F8F5FF0 +:101AC0008093D100843018F482E090E007C080E178 +:101AD00090E004C08823B9F581E090E0909316016E +:101AE0008093150108958091C70081608093C7009D +:101AF0000E942505A9E1B1E0E7ECF0E08AE0019061 +:101B00000D928150E1F70E941F0584E986BF81E1B3 +:101B100090E0909316018093150184E68093D200A3 +:101B200008958091D20081508093D200882359F487 +:101B30001092160110921501089581E090E09093A3 +:101B40001601809315010895DC0101C06D93415089 +:101B50005040E0F708950F931F93CF93DF938C01CC +:101B6000EB01009711F42097C9F181E090E06EE05D +:101B700070E00E947210FC019C01009789F180E8DE +:101B80008383209771F0D387C28781E88383809114 +:101B9000250190912601009721F4F0932601E0930E +:101BA000250101151105E1F011870087838182600D +:101BB00083838091270190912801009789F4F09305 +:101BC0002801E09327018091290190912A01009733 +:101BD00039F4F0932A01E093290102C020E030E0BB +:101BE000C901DF91CF911F910F9108950F931F931A +:101BF000CF93DF938C01EB018B8181FF1BC082FFB0 +:101C00000DC02E813F818C819D812817390764F496 +:101C1000E881F9810193F983E88306C0E885F985B5 +:101C2000802F0995009731F48E819F8101969F83C3 +:101C30008E8302C00FEF1FEFC801DF91CF911F917C +:101C40000F910895A0E0B0E0E8E2FEE00C944D12A0 +:101C5000FE01359661917191809127019091280143 +:101C6000AF010E948B0E2096E2E00C946912AEE068 +:101C7000B0E0EDE3FEE00C944B120D891E898F89D4 +:101C8000988D26E02C831A83098397FF02C080E099 +:101C900090E801979E838D839E01255E3F4FCE0184 +:101CA0000196698D7A8DA9010E948B0E4D815E810E +:101CB00057FD0AC02F813885421753070CF49A014B +:101CC000020F131FF80110822E96E4E00C946712A5 +:101CD000AEE0B0E0EEE6FEE00C944B120D891E89FA +:101CE00086E08C831A8309838FEF9FE79E838D8321 +:101CF0009E01275E3F4FCE0101966F89788DA90125 +:101D00000E948B0EEF81F885E00FF11F10822E9656 +:101D1000E4E00C946712ACE0B0E0E1E9FEE00C9482 +:101D20003D126C011B018A01FC011782168283811E +:101D300081FFD1C12E010894411C511CF6019381F1 +:101D4000F10193FD859193FF81911F01882309F48F +:101D5000BEC1853239F493FD859193FF81911F01B6 +:101D6000853229F490E0B6010E94F60DE7CFEE240B +:101D7000FF2420E02032B0F48B3269F08C3228F45A +:101D8000803251F0833271F40BC08D3239F08033E0 +:101D900049F421602CC02260246029C0286027C03B +:101DA000206125C027FD2CC0382F30533A3098F4DD +:101DB00026FF08C08E2D880FE82EEE0CEE0CE80EE4 +:101DC000E30E15C08F2D880FF82EFF0CFF0CF80EB8 +:101DD000F30E20620CC08E3221F426FD78C12064FF +:101DE00006C08C3611F4206802C0883649F4F1012F +:101DF00093FD859193FF81911F01882309F0BACF4C +:101E0000982F9554933018F09052933028F40C5F2B +:101E10001F4FFFE3F9830DC0833631F0833771F034 +:101E2000833509F060C022C0F801808189830E5F8C +:101E30001F4F420171E0A72EB12C16C062E0662E42 +:101E4000712C600E711EF8018080918026FF03C006 +:101E50006E2D70E002C06FEF7FEFC4012C870E94EF +:101E6000D4115C0183012C852F7717C052E0652EB9 +:101E7000712C600E711EF8018080918026FF03C0D6 +:101E80006E2D70E002C06FEF7FEFC4012C870E94BF +:101E9000C9115C012C852068830123FD20C008C086 +:101EA00080E290E0B6012C870E94F60DFA942C8512 +:101EB0008F2D90E0A816B90698F311C0F40127FD04 +:101EC000859127FF81914F0190E0B6012C870E94F8 +:101ED000F60D2C85F110FA940894A108B108A1140C +:101EE000B10461F7F1C0843611F0893649F527FF56 +:101EF00008C0F80160817181828193810C5F1F4F5E +:101F000009C0F80160817181882777FD8095982F3D +:101F10000E5F1F4F4FE6B42EB22297FF09C0909577 +:101F20008095709561957F4F8F4F9F4FF0E8BF2A46 +:101F3000A2012AE030E00E94DF11782E741845C01B +:101F4000853731F43FEEB32EB2222AE030E025C0CF +:101F500099EFB92EB2228F36C1F0803720F4883540 +:101F600009F0B5C00DC0803721F0883709F0AFC047 +:101F700002C020E1B22AB4FE0BC084E0B82A08C037 +:101F8000B4FE09C0E6E0BE2A06C028E030E005C085 +:101F900020E130E002C020E132E0B7FE08C0F801E5 +:101FA00060817181828193810C5F1F4F07C0F801AE +:101FB0006081718180E090E00E5F1F4FA2010E945E +:101FC000DF11782E7418FFE7BF22B6FE0BC02EEF8C +:101FD000B2227E1438F4B4FE07C0B2FC05C08FEE06 +:101FE000B82202C0A72C01C0AE2C8B2D90E0B4FE0D +:101FF0000DC0FE01E70DF11D2081203319F4E9EE3B +:10200000BE2209C0A394B2FE06C004C086789070B8 +:10201000009709F0A3948B2C9924B3FC14C0B0FE54 +:102020000FC0AF1428F4E72CEF0CEA18AF2C08C04F +:10203000E72C06C080E290E0B6010E94F60DA39462 +:10204000AF14C0F304C0AF1410F4FA1801C0FF2499 +:1020500084FE0FC080E390E0B6010E94F60D82FE80 +:102060001FC081FE03C088E590E010C088E790E0C3 +:102070000DC0C40186789070009791F081FC02C079 +:1020800080E201C08BE2B7FC8DE290E0B6010E94D5 +:10209000F60D06C080E390E0B6010E94F60DEA94CA +:1020A0007E14C0F37A94F201E70DF11D808190E077 +:1020B000B6010E94F60D7720A9F706C080E290E0F5 +:1020C000B6010E94F60DFA94FF20C1F737CEF60153 +:1020D0002681378102C02FEF3FEFC9012C96E2E144 +:1020E0000C945912EF92FF920F931F93CF93DF93AB +:1020F000689F8001699F100D789F100D1124C80101 +:102100000E949610E82EE7017E01F92EE701209744 +:1021100031F08E2D60E070E0A8010E94A40D7E01D8 +:10212000CE01CDB7DEB7E6E00C946512CF93DF9316 +:102130008230910510F482E090E0E0912D01F09161 +:102140002E0140E050E020E030E026C06081718147 +:1021500068177907E0F06817790781F48281938125 +:102160002115310531F0D90113969C938E93129766 +:102170002BC090932E0180932D0126C0411551054F +:1021800019F06417750718F4AB01E901DF019F012D +:1021900072816381E72FF62F3097C1F64115510503 +:1021A00001F1481B590B4430510580F412968D9172 +:1021B0009C911397209719F09B838A8304C0909376 +:1021C0002E0180932D01FD01329646C0FD01E40FE2 +:1021D000F51F819391934250504011965C934E931A +:1021E0003BC020912B0130912C012115310541F488 +:1021F0002091B4003091B50030932C0120932B0135 +:102200002091B6003091B7002115310541F42DB76A +:102210003EB74091B2005091B300241B350BE091C2 +:102220002B01F0912C01E217F307A0F42E1B3F0BBA +:102230002817390778F0AC014E5F5F4F2417350738 +:1022400048F04E0F5F1F50932C0140932B01819358 +:10225000919302C0E0E0F0E0CF01DF91CF910895CB +:10226000CF93DF93009709F491C0FC01329713825A +:10227000128260912D0170912E016115710581F41A +:1022800020813181280F391F80912B0190912C01E1 +:102290008217930799F5F0932C01E0932B0176C0F8 +:1022A000DB0180E090E002C0CD01D901AE17BF078D +:1022B00048F412962D913C91139721153105A1F701 +:1022C000CD0121C0B383A283EF01499159919E01B1 +:1022D000240F351FA217B30779F42D913C91119764 +:1022E000240F351F2E5F3F4F3183208312962D918F +:1022F0003C91139733832283009729F4F0932E01A6 +:10230000E0932D0143C0DC011396FC93EE931297EA +:102310004D915D91A40FB51FEA17FB0769F4208169 +:102320003181240F351F2E5F3F4FEC013983288305 +:10233000228133813B832A83E0E0F0E002C0FB018D +:10234000BC01DB0112968D919C9113970097B9F710 +:102350009B012E5F3F4F8D919C911197820F931F90 +:1023600040912B0150912C014817590779F430976F +:1023700029F410922E0110922D0102C013821282B4 +:102380002250304030932C0120932B01DF91CF91CC +:102390000895FC010590615070400110D8F78095B8 +:1023A00090958E0F9F1F0895FC0161507040019021 +:1023B0000110D8F7809590958E0F9F1F0895FA0110 +:1023C000AA27283051F1203181F1E8946F936E7F74 +:1023D0006E5F7F4F8F4F9F4FAF4FB1E03ED0B4E065 +:1023E0003CD0670F781F891F9A1FA11D680F791FA6 +:1023F0008A1F911DA11D6A0F711D811D911DA11DB7 +:1024000020D009F468943F912AE0269F11243019C6 +:10241000305D3193DEF6CF010895462F4770405D61 +:102420004193B3E00FD0C9F7F6CF462F4F70405D10 +:102430004A3318F0495D31FD4052419302D0A9F76B +:10244000EACFB4E0A6959795879577956795BA9565 +:10245000C9F700976105710508959B01AC010A2E2B +:1024600006945795479537952795BA95C9F7620F02 +:10247000731F841F951FA01D08952F923F924F92A6 +:102480005F926F927F928F929F92AF92BF92CF9204 +:10249000DF92EF92FF920F931F93CF93DF93CDB70D +:1024A000DEB7CA1BDB0B0FB6F894DEBF0FBECDBF85 +:1024B00009942A88398848885F846E847D848C8456 +:1024C0009B84AA84B984C884DF80EE80FD800C815F +:1024D0001B81AA81B981CE0FD11D0FB6F894DEBF42 +:0C24E0000FBECDBFED010895F894FFCFB2 +:1024EC00312E3628313029004A616E2020392032B5 +:1024FC003031340030373A35393A3339000A0D006F +:10250C002534640025303478005625732028257333 +:10251C002025732900003F065B4F666D7D077F6F9A +:10252C00777C585E797140080000FF7FFF7FFF7F4A +:08253C00FF7F20002F010000C9 +:00000001FF diff --git a/sure_modbusslave/src/app.c b/sure_modbusslave/src/app.c new file mode 100644 index 0000000..a5f63f1 --- /dev/null +++ b/sure_modbusslave/src/app.c @@ -0,0 +1,420 @@ +#include "global.h" + +#include +#include + +#include +#include +#include + +#include "app.h" +#include "twi.h" +#include "sys.h" + +// Defines, nur in app.c sichtbar +// ... + +//globale Variablen nur in app.c sichtbar +// ... + +//globale Strukturvariable, ueberall sichtbar +volatile struct App app; + + +void app_init (void) +{ + memset((void *)&app, 0, sizeof(app)); + app.version = "1.6(10)"; + app.versionDate = __DATE__; + app.versionTime = __TIME__; + _delay_ms(150); +} + +//-------------------------------------------------------- + +// 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) +int8_t app_modbus_handleReadCoil () +{ + // Modbus_Application_Protocol_V1_1b3.pdf, page 12 + uint8_t exceptionCode; + uint16_t address = sys_modbus_getByte(2)<<8 | sys_modbus_getByte(3); + uint16_t quantity = sys_modbus_getByte(4)<<8 | sys_modbus_getByte(5); + if (sys_uart_available()<6) + exceptionCode = 2; + else if (sys_uart_available()<8) + exceptionCode = 3; + else if (quantity <1 || quantity>0x7d0) + exceptionCode = 3; + else if (address<0 || address>3 || quantity<1 || (address+quantity-1)>3) + exceptionCode = 2; + else + { + exceptionCode = 0; + uint8_t data = (~PINA) & 0x0f; + data >>= address; + uint8_t mask = 0x0f >> (4-quantity); + data &= mask; + quantity = (quantity % 8) ? (quantity/8+1) : quantity/8; + sys_modbus_sendResponse(1, quantity, (uint8_t *)&data); + return 0; + } + + sys_modbus_sendError(0x81, exceptionCode); + return -1; +} + +// 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) +int8_t app_modbus_handleReadDicreteInput () +{ + uint8_t exceptionCode; + uint16_t address = sys_modbus_getByte(2)<<8 | sys_modbus_getByte(3); + uint16_t quantity = sys_modbus_getByte(4)<<8 | sys_modbus_getByte(5); + if (sys_uart_available()<6) + exceptionCode = 2; + else if (sys_uart_available()<8) + exceptionCode = 3; + else if (quantity <1 || quantity>0x7d0) + exceptionCode = 3; + else if (address<0 || address>1 || quantity<1 || (address+quantity-1)>1) + exceptionCode = 2; + else + { + exceptionCode = 0; + uint8_t data = ~( ((PINC & 0x80)!=0) | ((PINC & 0x40)!=0)<<1); + data >>= address; + uint8_t mask = 0x03 >> (2-quantity); + data &= mask; + quantity = (quantity % 8) ? (quantity/8+1) : quantity/8; + sys_modbus_sendResponse(2, quantity, (uint8_t *)&data); + return 0; + } + + sys_modbus_sendError(0x82, exceptionCode); + return -1; +} + +// 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 digit 3 and 2 (high byte, low byte) +// Address 4: 7-segement digit 1 and 0 (high byte, low byte) +int8_t app_modbus_handleReadHoldingRegisters () +{ + uint8_t exceptionCode; + uint16_t address = sys_modbus_getByte(2)<<8 | sys_modbus_getByte(3); + uint16_t quantity = sys_modbus_getByte(4)<<8 | sys_modbus_getByte(5); + if (sys_uart_available()<6) + exceptionCode = 2; + else if (sys_uart_available()<8) + exceptionCode = 3; + else if (quantity <1 || quantity>0x7d) + exceptionCode = 3; + else if (quantity<1 || (address+quantity-1)>4) + exceptionCode = 2; + else + { + exceptionCode = 0; + sys_modbus_sendRegisters(3, quantity*2, address, 1); + return 0; + } + + sys_modbus_sendError(0x83, exceptionCode); + return -1; +} + + +// 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/32 -> temperature in celsius degree (two's complement) +// +// Address 0xfff0..0xffff -> version string of this software -> "V1.0 (Oct 13 2013 13:17:58)" +// +int8_t app_modbus_handleReadInputRegister () // function code 0x04 +{ + uint8_t exceptionCode; + uint16_t address = sys_modbus_getByte(2)<<8 | sys_modbus_getByte(3); + uint16_t quantity = sys_modbus_getByte(4)<<8 | sys_modbus_getByte(5); + if (sys_uart_available()<6) + exceptionCode = 2; + else if (sys_uart_available()<8) + exceptionCode = 3; + else if (quantity <1 || quantity>0x7d) + exceptionCode = 3; + else if (address<0 || quantity<1 || (address<=0x33 && (address+quantity-1)>0x33) || + (address>=0xfff0 && ((uint32_t)address+quantity-1)>0xffff)) + + exceptionCode = 2; + else + { + sys_modbus_sendRegisters(4, quantity*2, address, 0); + return 0; + } + + sys_modbus_sendError(0x84, exceptionCode); + return -1; +} + +// 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) +int8_t app_modbus_handleWriteSingleCoil () +{ + uint8_t exceptionCode; + uint16_t address = sys_modbus_getByte(2)<<8 | sys_modbus_getByte(3); + uint16_t value = sys_modbus_getByte(4)<<8 | sys_modbus_getByte(5); + if (sys_uart_available()<6) + exceptionCode = 2; + else if (sys_uart_available()<8) + exceptionCode = 3; + else if (value != 0x0000 && value != 0xff00) + exceptionCode = 3; + else if (address<0 || address>3) + exceptionCode = 2; + else + { + exceptionCode = 0; + uint8_t mask = 1 << address; + sys_cli(); + if (value) + PORTA &= ~mask; + else + PORTA |= mask; + sys_sei(); + _delay_us(100); + if (value) + exceptionCode = (PINA & mask) != 0 ? 4 : 0; + else + exceptionCode = (PINA & mask) == 0 ? 4 : 0; + + if (exceptionCode == 0) + { + uint8_t data[4] = { address>>8, address&0xff, value>>8, 0 }; + sys_modbus_sendResponse(5, 4, (uint8_t *)&data); + return 0; + } + } + + sys_modbus_sendError(0x85, exceptionCode); + return -1; +} + +// 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) +int8_t app_modbus_handleWriteSingleRegister () // function code 6 +{ + uint8_t exceptionCode; + uint16_t address = sys_modbus_getByte(2)<<8 | sys_modbus_getByte(3); + uint16_t value = sys_modbus_getByte(4)<<8 | sys_modbus_getByte(5); + if (sys_uart_available()<6) + exceptionCode = 2; + else if (sys_uart_available()<8) + exceptionCode = 3; + else if (address>4) + exceptionCode = 2; + else + { + sys_modbus_setHoldingRegister(address, value); + value = sys_modbus_getHoldingRegister(address); + uint8_t data[4] = { address>>8, address&0xff, value>>8, value&0xff }; + sys_modbus_sendResponse(6, 4, (uint8_t *)&data); + return 0; + } + + sys_modbus_sendError(0x86, exceptionCode); + return -1; +} + +// 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) +int8_t app_modbus_handleWriteMultipleCoils () +{ + uint8_t exceptionCode; + uint16_t address = sys_modbus_getByte(2)<<8 | sys_modbus_getByte(3); + uint16_t quantity = sys_modbus_getByte(4)<<8 | sys_modbus_getByte(5); + uint8_t length = sys_modbus_getByte(6); + uint8_t value = sys_modbus_getByte(7); + if (sys_uart_available()<6) + exceptionCode = 2; + else if (sys_uart_available()<10) + exceptionCode = 3; + else if (quantity <1 || quantity>0x7d0) + exceptionCode = 3; + else if (address<0 || address>3 || (address+quantity-1)>3 || length != 1) + exceptionCode = 2; + else + { + exceptionCode = 0; + value = (~value) & 0x0f; // leds ar 0 active + uint8_t i, mask; + for (i=0, mask=0; i>8, address&0xff, quantity>>8, quantity&0xff }; + sys_modbus_sendResponse(0x0f, 4, (uint8_t *)&data); + return 0; + } + } + + sys_modbus_sendError(0x8f, exceptionCode); + return -1; +} + +// 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) + +int8_t app_modbus_handleWriteMultipleRegisters () +{ + uint8_t exceptionCode; + uint16_t address = sys_modbus_getByte(2)<<8 | sys_modbus_getByte(3); + uint16_t quantity = sys_modbus_getByte(4)<<8 | sys_modbus_getByte(5); + uint8_t length = sys_modbus_getByte(6); + if (sys_uart_available()<6) + exceptionCode = 2; + else if (sys_uart_available()<10) + exceptionCode = 3; + else if (quantity <1 || quantity>0x7b) + exceptionCode = 3; + else if ((address+quantity-1)>4) + exceptionCode = 2; + else if (length != (quantity*2)) + exceptionCode = 4; + else + { + exceptionCode = 0; + uint8_t data[4] = { address>>8, address&0xff, quantity>>8, quantity&0xff }; + uint8_t i; + for (i=0; i not specified in protocol specification + + else if (sys_modbus_getByte(0) == 0) + ; // broadcast, do not send any response + + else + { + uint8_t functionCode = sys_modbus_getByte(1); + switch (functionCode) + { + case 0x01: app_modbus_handleReadCoil(); break; + case 0x02: app_modbus_handleReadDicreteInput(); break; + case 0x03: app_modbus_handleReadHoldingRegisters(); break; + case 0x04: app_modbus_handleReadInputRegister(); break; + case 0x05: app_modbus_handleWriteSingleCoil(); break; + case 0x06: app_modbus_handleWriteSingleRegister(); break; + case 0x0f: app_modbus_handleWriteMultipleCoils(); break; + case 0x10: app_modbus_handleWriteMultipleRegisters(); break; + default: sys_modbus_sendError(functionCode+0x80, 0x01); break; + } + } + } + +// if (sys.modbus.state == Idle) +// sys_setLed(3,1); +// else +// sys_setLed(3,0); +// +// if (sys.modbus.state == CtrlAndWait || sys.modbus.state == Reception) +// sys_setLed(2,1); +// else +// sys_setLed(2,0); + +// if (sys.modbus.err.errorFlags) +// { +// sys_setLed(1,1); +// //char s[5]; +// //sprintf(s, " %02x", sys.modbus.err.errorFlags); +// //sys_7seg_setString(s); +// } +// else +// sys_setLed(1,0); + + if (twi.errTimer>0) + sys_setLed(0,1); + else + sys_setLed(0,0); + + +#ifdef GLOBAL_LOG + while (sys_log_getSize()>0) + { + struct Sys_LogEntry le = sys_log_next(); + printf(" line %3d: received = %3d crc=%04x byteTimer=%d state=%d err=%d avail=%d frameLength=%d tick_0us66=%8lu\n", + le.line, le.received, le.crc, le.byteTimer, le.state, le.error, le.available, le.frameLength, (uint32_t)le.tick100us*150 + le.tcnt0); + } +#endif +} + +//-------------------------------------------------------- + +void app_task_1ms (void) { } +void app_task_2ms (void) {} +void app_task_4ms (void) {} +void app_task_8ms (void) {} +void app_task_16ms (void) {} +void app_task_32ms (void) {} +void app_task_64ms (void) {} +void app_task_128ms (void) {} + + + diff --git a/sure_modbusslave/src/app.h b/sure_modbusslave/src/app.h new file mode 100644 index 0000000..a7f451b --- /dev/null +++ b/sure_modbusslave/src/app.h @@ -0,0 +1,42 @@ +#ifndef APP_H_INCLUDED +#define APP_H_INCLUDED + +// Deklaration Strukturvariablentyp + + +struct App +{ + char *version; + char *versionDate; + char *versionTime; +}; + + +// Deklaration Strukturvariablen +extern volatile struct App app; + +// globale Defines +#define APP_EVENT_MODBUS 0x01 +#define APP_EVENT_1 0x02 +#define APP_EVENT_2 0x04 +#define APP_EVENT_3 0x08 +#define APP_EVENT_4 0x10 +#define APP_EVENT_5 0x20 +#define APP_EVENT_6 0x40 +#define APP_EVENT_7 0x80 + + +// Funktionsdeklarationen +void app_init (void); +void app_main (void); + +void app_task_1ms (void); +void app_task_2ms (void); +void app_task_4ms (void); +void app_task_8ms (void); +void app_task_16ms (void); +void app_task_32ms (void); +void app_task_64ms (void); +void app_task_128ms (void); + +#endif // APP_H_INCLUDED diff --git a/sure_modbusslave/src/global.h b/sure_modbusslave/src/global.h new file mode 100644 index 0000000..cf8b134 --- /dev/null +++ b/sure_modbusslave/src/global.h @@ -0,0 +1,58 @@ +#ifndef GLOBAL_H_INCLUDED +#define GLOBAL_H_INCLUDED + +// globale Defines... +#ifdef NETBEANS_ATMEGA16 + #define F_CPU 12000000UL + #define SURE + #ifndef __AVR_ATmega16__ + #define __AVR_ATmega16__ + #endif +#else + #ifdef NETBEANS_ATMEGA328P + #define F_CPU 12000000UL + #define ASURO + #ifndef __AVR_ATmega328P__ + #define __AVR_ATmega328P__ + #endif + #elif NETBEANS_ATMEGA328 + #define F_CPU 12000000UL + #define ASURO + #ifndef __AVR_ATmega328__ + #define __AVR_ATmega328__ + #endif + #else + #ifdef __AVR_ATmega16__ + #define SURE + #elif __AVR_ATmega328P__ + #define ASURO + #elif __AVR_ATmega328__ + #define ASURO + #else + #error "Kein gueltiger uC-Typ gewaehlt" + #endif + #endif +#endif + +#define GLOBAL_UART_BITRATE 57600 +#define GLOBAL_UART_EVENPARITY 0 +#define GLOBAL_UART_STOPBITS 2 +#define GLOBAL_UART_RECBUFSIZE 32 + +#define GLOBAL_MODBUS_SLAVEADDRESS 2 +//#define GLOBAL_MODBUS_TIMERFACT 1 +#define GLOBAL_MODBUS_TIMERFACT 10 +#define GLOBAL_MODBUS_TIMER35 (385000*GLOBAL_MODBUS_TIMERFACT/GLOBAL_UART_BITRATE + 1) +#define GLOBAL_MODBUS_TIMER15 (165000*GLOBAL_MODBUS_TIMERFACT/GLOBAL_UART_BITRATE + 1) +#define GLOBAL_MODBUS_ERRORTIME 255 + +//#define GLOBAL_LOG +//#define GLOBAL_LOG_SIZE 16 + +//#define GLOBAL_SURE_LCD + +#ifndef SURE +#undef GLOBAL_SURE_LCD +#endif + +#endif // GLOBAL_H_INCLUDED diff --git a/sure_modbusslave/src/main.c b/sure_modbusslave/src/main.c new file mode 100644 index 0000000..4b83a4c --- /dev/null +++ b/sure_modbusslave/src/main.c @@ -0,0 +1,68 @@ +//*********************************************************************** +// Vorlage PRT Level 3 +// ---------------------------------------------------------------------- +// Beinhaltet: +// UART-Support, Timer, Task-System, 7-Segment-Support, LCD-Support +// ---------------------------------------------------------------------- +// Author: SX +// Version: 1 (2012) +//*********************************************************************** + +#include "global.h" + +#include +#include + +#include +#include +#include + +#include "sys.h" +#include "twi.h" +#include "app.h" + +// Defines, nur in main.c sichtbar +// ... + +// globale Variable, nur in main.c sichtbar +// ... + +// Konstante, die im Flash abgelegt werden +//const char MAIN_WELCOME[] = "\n\rProgramm ?? "; +//const char MAIN_DATE[] = __DATE__; +//const char MAIN_TIME[] = __TIME__; + + +int main (void) +{ + sys_init(); + twi_init(); + app_init(); + + //printf("%s %s %s\n\r", MAIN_WELCOME, MAIN_DATE, MAIN_TIME); + +#ifdef SURE +#ifdef GLOBAL_SURE_LCD + printf("LCD "); + if (sys.lcd.status==1) + { + printf("detected and ready to use\n"); + sys_lcd_putString("?? - "); + sys_lcd_putString(MAIN_TIME); + } + else + printf("not ready (status=%d)\n", sys.lcd.status); +#endif // GLOBAL_SURE_LCD +#endif //SURE + //sys_newline(); + + // Interrupt-System jetzt einschalten + sei(); + + while (1) + { + sys_main(); + app_main(); + } + return 0; +} diff --git a/sure_modbusslave/src/sys.c b/sure_modbusslave/src/sys.c new file mode 100644 index 0000000..bc142e5 --- /dev/null +++ b/sure_modbusslave/src/sys.c @@ -0,0 +1,1100 @@ +#include "global.h" + +#include +#include +#include +#include + +#include +#include +#include +#include + +#include "sys.h" +#include "app.h" +#include "twi.h" + +// Defines, nur in sys.c sichtbar +#ifdef ASURO +#define SYS_UART_BYTE_RECEIVED (UCSR0A & (1<=GLOBAL_UART_RECBUFSIZE) + sys.uart.rpos_u8 = 0; + return (int) c; +} + + +int sys_uart_putch (char c, FILE *f) +{ + while (!SYS_UART_UDR_IS_EMPTY); + SYS_UDR = c; + return (int)c; +} + + +uint8_t sys_uart_available (void) +{ + return sys.uart.wpos_u8 >= sys.uart.rpos_u8 + ? sys.uart.wpos_u8 - sys.uart.rpos_u8 + : ((int16_t)sys.uart.wpos_u8) + GLOBAL_UART_RECBUFSIZE - sys.uart.rpos_u8; +} + + +//---------------------------------------------------------------------------- + +int16_t sys_uart_getBufferByte (uint8_t pos) +{ + int16_t value; + sys_cli(); + + if (pos >= sys_uart_available()) + value = -1; + else + { + uint8_t bufpos = sys.uart.rpos_u8 + pos; + if (bufpos >= GLOBAL_UART_RECBUFSIZE) + bufpos -= GLOBAL_UART_RECBUFSIZE; + value = sys.uart.rbuffer_u8[bufpos]; + } + + sys_sei(); + return value; +} + + +void sys_uart_flush (void) +{ + uint8_t dummy; + + sys_cli(); + while (SYS_UART_BYTE_RECEIVED) + dummy = SYS_UDR; + + sys.uart.rpos_u8 = 0; + sys.uart.wpos_u8 = 0; + sys.uart.errcnt_u8 = 0; + sys_sei(); +} + + +//**************************************************************************** +// Event Handling +//**************************************************************************** + +Sys_Event sys_setEvent (Sys_Event event) +{ + uint8_t eventIsPending = 0; + sys_cli(); + if (sys.eventFlag & event) + eventIsPending = 1; + sys.eventFlag |= event; + sys_sei(); + + return eventIsPending; +} + + +Sys_Event sys_clearEvent (Sys_Event event) +{ + uint8_t eventIsPending = 0; + sys_cli(); + if (sys.eventFlag & event) + eventIsPending = 1; + sys.eventFlag &= ~event; + sys_sei(); + + return eventIsPending; +} + + +Sys_Event sys_isEventPending (Sys_Event event) +{ + return (sys.eventFlag & event) != 0; +} + + + +//**************************************************************************** +// 7 Segment Handling for Sure DEM2 Board +//**************************************************************************** + +#ifdef SURE + +const uint8_t sys_mask_seg7[19] = { 0x00, + 0x3f, 0x06, 0x5b, 0x4f, 0x66, 0x6d, 0x7d, 0x07, + 0x7f, 0x6f, 0x77, 0x7c, 0x58, 0x5e, 0x79, 0x71, + 0x40, 0x08}; + +void sys_7seg_refresh () +{ + static uint8_t refresh = 0; + + refresh = (refresh + 1) % 4; + PORTA &= ~0xf0; + //PORTB = sys_mask_seg7[sys.seg7.digit_u8[refresh]]; + PORTB = sys.seg7.digit_u8[refresh]; + if (sys.seg7.point_u8 & (1<> refresh); +} + + +void sys_7seg_setDigit (uint8_t index, uint8_t digitValue) +{ + if (index>3) return; +#ifdef GLOBAL_SURE_LCD + sys.lcd.status = 0; // switch of LCD - PORTB used for 7seg +#endif + digitValue++; + if (digitValue >= sizeof(sys_mask_seg7)) + digitValue = 0; // -> digit is switched off + sys.seg7.digit_u8[index] = sys_mask_seg7[digitValue]; +} + +void sys_7seg_setDigitLeds (uint8_t index, uint8_t value) +{ + sys.seg7.digit_u8[index%4] = value; +} + + + +void sys_7seg_setPoint (uint8_t index, uint8_t pointState) +{ +#ifdef SURE + sys.lcd.status = 0; // switch of LCD - PORTB used for 7seg +#endif + if (pointState) + sys.seg7.point_u8 |= (1<=0 && *str; i--) + { + if (*str>='0' && *str<='9') + sys_7seg_setDigit(i, *str-'0'); + else if (*str>='a' && *str<='f') + sys_7seg_setDigit(i, *str-'a'+10); + else if (*str>='A' && *str<='F') + sys_7seg_setDigit(i, *str-'A'+10); + else if (*str=='-') + sys_7seg_setDigit(i, SYS_SEG7_DIGIT_MINUS); + else if (*str==' ') + sys_7seg_setDigit(i, SYS_SEG7_DIGIT_OFF); + else + sys_7seg_setDigit(i, SYS_SEG7_DIGIT_UNDERLINE); + str++; + } +} + +void sys_7seg_showUnsignedDecimal (uint16_t value) +{ + char s[5]; + if (value>9999) + value = 9999; + sprintf(s, "%4d", value); + sys_7seg_setString(s); +} + +void sys_7seg_showSignedDecimal (int16_t value) +{ + char s[5]; + if (value>9999) + value = 9999; + else if (value<-999) + value =-999; + sprintf(s, "%4d", value); + sys_7seg_setString(s); +} + +void sys_7seg_showHex (uint16_t value) +{ + char s[5]; + sprintf(s, "%04x", value); + sys_7seg_setString(s); +} + +#endif // SURE + + +//**************************************************************************** +// LCD Handling (only for SURE Board) +//**************************************************************************** + +#ifdef SURE +#ifdef GLOBAL_SURE_LCD + +void sys_lcd_init (void) +{ + uint8_t i; + + //_delay_ms(16); + sys.lcd.status = 0; + for (i=0; i<4; i++) + { + sys_lcd_setRegister(SYS_LCD_CMD_SET_FUNCTION | 0x18); // 8 Bit, 2 Zeilen, 5x7 + if (i==0) _delay_ms(5); else _delay_us(100); + } + + sys_lcd_setRegister(SYS_LCD_CMD_DISPLAY_ON_OFF | 0x04); // display on, cursor off + if (!sys_lcd_isReady(50)) { sys.lcd.status = -1; return; } + + sys_lcd_setRegister(SYS_LCD_CMD_DISPLAY_ON_OFF | 0x04); // display on, cursor off + if (!sys_lcd_isReady(50)) { sys.lcd.status = -3; return; } + + sys_lcd_setRegister(SYS_LCD_CMD_DISPLAY_CLEAR); + if (!sys_lcd_isReady(1200)) { sys.lcd.status = -4; return; } + + sys.lcd.status = 1; +} + + +uint8_t sys_lcd_isReady (uint16_t us) +{ + if (sys.lcd.status<0) return 0; + + uint8_t busy; + PORTB = 0xff; + DDRB = 0x00; // Direction Port LCD-Data to Input + do + { + SYS_LCD_SET_RW; + SYS_LCD_CLR_RS; + _delay_us(1); + SYS_LCD_SET_E; + _delay_us(SYS_LCD_PULSE_LENGTH); + sys.lcd.data = PINB; + busy = sys.lcd.data & SYS_LCD_BUSY_FLAG; + SYS_LCD_CLR_E; + SYS_LCD_CLR_RW; + us = (us>=11) ? us-11 : 0; + } + while (us>0 && busy); + + if (sys.lcd.status== 1 && busy) + sys.lcd.status = -5; + + DDRB = 0xff; // Direction Port LCD-Data to Input + + return busy == 0; +} + + +void sys_lcd_setRegister (uint8_t cmd) +{ + PORTD &= ~0x1c; // E=0, R/W=0, RS=0 + PORTB = cmd; + DDRB = 0xff; // Direction Port LCD-Data to Output + SYS_LCD_SET_E; + _delay_us(SYS_LCD_PULSE_LENGTH); + SYS_LCD_CLR_E; + _delay_us(1); +} + + +void sys_lcd_waitOnReady (void) +{ + if(sys_lcd_isReady(50)==0) + sys.lcd.status = -6; +} + + +void sys_lcd_setDisplayOff (void) +{ + sys_lcd_waitOnReady(); + sys_lcd_setRegister(SYS_LCD_CMD_DISPLAY_ON_OFF); // display off + sys_lcd_waitOnReady(); +} + + +void sys_lcd_setDisplayOn (void) +{ + sys_lcd_waitOnReady(); + sys_lcd_setRegister(SYS_LCD_CMD_DISPLAY_ON_OFF | 0x04); // display on + sys_lcd_waitOnReady(); +} + + +void sys_lcd_clear (void) +{ + sys_lcd_waitOnReady(); + sys_lcd_setRegister(SYS_LCD_CMD_DISPLAY_CLEAR); + while (!sys_lcd_isReady(1200)); +} + + +void sys_lcd_setDRAddr (uint8_t address) +{ + sys_lcd_waitOnReady(); + sys_lcd_setRegister(SYS_LCD_CMD_SET_DDRAM_ADDR | address); + sys_lcd_waitOnReady(); +} + + +// 1.Line->rowIndex=0, 1.Column->colIndex=0 +void sys_lcd_setCursorPosition (uint8_t rowIndex, uint8_t columnIndex) +{ + if (sys.lcd.status!=1 || rowIndex>1) return; + if (rowIndex) + sys_lcd_setDRAddr(0x40 + columnIndex); + else + sys_lcd_setDRAddr(columnIndex); +} + + +inline void sys_lcd_putc (char c, FILE *stream) +{ + sys_lcd_putchar(c); +} + + +void sys_lcd_putchar (int character) +{ + if (sys.lcd.status!=1) return; + sys_lcd_waitOnReady(); + + DDRB = 0xff; + PORTB = (uint8_t) character; + SYS_LCD_SET_RS; + SYS_LCD_CLR_RW; + SYS_LCD_SET_E; + _delay_us(SYS_LCD_PULSE_LENGTH); + SYS_LCD_CLR_E; + _delay_us(10); + DDRB = 0x00; +} + + +void sys_lcd_putString (const char * str) +{ + while (*str && sys.lcd.status==1) + { + sys_lcd_putchar(*str++); + } + sys_lcd_waitOnReady(); +} + +#endif // GLOBAL_SURE_LCD +#endif // SURE + + +//**************************************************************************** +// LED Handling +//**************************************************************************** + +#ifdef SURE + +void sys_setAllLeds (uint8_t ledState) +{ + if (ledState) + { + PORTA = 0xf0; + PORTB = 0xff; + } + else + { + PORTA = 0x0f; + PORTB = 0x00; + } +} + + +void sys_setLed (uint8_t index, uint8_t ledState) +{ + if (index>3) return; + sys_cli(); + if (ledState) + PORTA &= ~(1<3) return; + uint8_t mask = (1<=sys.log.rpos ? sys.log.wpos-sys.log.rpos : sys.log.wpos + GLOBAL_LOG_SIZE - sys.log.rpos; + sys_sei(); + return size; +} + +void sys_log (uint16_t line, int16_t receivedByte, uint8_t byteTimer, uint16_t tick100us, uint8_t tcnt0) +{ + sys_cli(); + uint8_t size = sys.log.wpos>=sys.log.rpos ? sys.log.wpos-sys.log.rpos : sys.log.wpos + GLOBAL_LOG_SIZE - sys.log.rpos; + if (sizeline = line; + p->tcnt0 = tcnt0; + p->crc = sys.modbus.crc; + p->tick100us = tick100us; + p->byteTimer = byteTimer; + p->state = sys.modbus.state; + p->available = sys_uart_available(); + p->error = sys.modbus.err.errorFlags; + p->received = receivedByte; + p->frameLength = sys.modbus.frameLength; + if (sys.log.wpos>=GLOBAL_LOG_SIZE) + sys.log.wpos = 0; + } + sys_sei(); +} + +struct Sys_LogEntry sys_log_next () +{ + struct Sys_LogEntry rv; + memset((void *)&rv, 0, sizeof(rv)); + sys_cli(); + uint8_t size = sys.log.wpos>=sys.log.rpos ? sys.log.wpos-sys.log.rpos : sys.log.wpos + GLOBAL_LOG_SIZE - sys.log.rpos; + if (size>0) + { + rv = sys.log.data[sys.log.rpos++]; + if (sys.log.rpos>=GLOBAL_LOG_SIZE) + sys.log.rpos = 0; + } + sys_sei(); + return rv; +} +#else + +inline uint8_t sys_log_getSize (void) { return 0; } +inline void sys_log (uint16_t line, int16_t receivedByte, uint8_t byteTimer, uint16_t tick100us, uint8_t tcnt0) {} +struct Sys_LogEntry sys_log_next () +{ + struct Sys_LogEntry rv; + memset((void *)&rv, 0, sizeof(rv)); + return rv; +} + +#endif + +// ------------------------------------ +// Modbus functions +// ------------------------------------ + +void sys_modbus_setError (enum Sys_ModbusError typ) +{ + sys.modbus.err.timer = GLOBAL_MODBUS_ERRORTIME; + sys.modbus.err.errorFlags |= (1<0) + { + sys_modbus_setError(FrameBufferFull); + } + if (sys.modbus.crc != 0x0000) + { + sys_modbus_setError(WrongCRC); + } + if (sys_uart_getBufferByte(0) != GLOBAL_MODBUS_SLAVEADDRESS) + { + sys_modbus_setError(wrongAddress); + } + sys.modbus.frameNotOkFlag = 1; + } +} + + + +int16_t sys_modbus_getByte (uint8_t index) +{ + if (!sys.modbus.checkedFrameLength) + return -1; + + if (index >= sys.modbus.checkedFrameLength) + return -1; + + return sys_uart_getBufferByte(index); +} + +void sys_modbus_freeFrame (void) +{ + //printf("checkedFrameLength = %d\n", sys.modbus.checkedFrameLength); + if (sys.modbus.checkedFrameLength) + { + sys_cli(); + if (sys.modbus.checkedFrameLength >= sys_uart_available()) + sys_uart_flush(); + else + { + uint16_t pos = (uint16_t)sys.uart.rpos_u8 + sys.modbus.checkedFrameLength; + while (pos >= GLOBAL_UART_RECBUFSIZE) + pos -= GLOBAL_UART_RECBUFSIZE; + sys.uart.rpos_u8 = pos; + } + sys.modbus.checkedFrameLength = 0; + sys_log(__LINE__, -1, sys.modbus.byteTimer, sys.tick100us, TCNT0); + sys_sei(); + } +} + +uint16_t sys_modbus_updateCRC (uint8_t b, uint16_t crc) +{ + //uint16_t crc = sys.modbus.crc; + uint8_t i; + crc = crc ^ (uint16_t)b; + for (i=0; i<8; i++) + { + if (crc & 0x0001) + crc = (crc >> 1) ^ 0xa001; + else + crc = crc >> 1; + } + return crc; + //sys.modbus.crc = crc; +} + + +// address 0x0000..0x002F; Atmega I/O register +// address 0x0030..0x0033; LM75A registers +// address 0xfff0..0xffff: version string of app.c +uint16_t sys_modbus_getInputRegister (uint16_t address, uint8_t newRequest) +{ + static Twi_Lm75 lm75; + static Twi_Lm75 lm75NotValid = { 0, 0, {0x7fff, 0x7fff, 0x7fff, 0x7fff}}; + + if (address>=0xfff0) + { + char s[32]; + memset((void *)&s, 0, sizeof(s)); + snprintf(s, 32, "V%s (%s %s)", app.version, app.versionDate, app.versionTime); + address = (address - 0xfff0)*2; + return s[address]<<8 | s[address+1]; + } + + if (address<0 || address>0x33) + return 0xffff; + + if (newRequest) + { + sys_cli(); + + if (twi.lm75.valid) + lm75 = twi.lm75; + else + lm75 = lm75NotValid; + sys_sei(); + } + if (address>=0x30) + return *( (volatile uint16_t*)(lm75.reg + (address-0x30)) ); + + return *((volatile uint16_t *)(address*2) ); +} + +// address 0: 7-segment show hex 0 .. FFFF +// address 1: 7-segemnt show unsigned decimal 0..9999 +// address 2: 7-segment show signed decimal -999 .. 9999 +// address 3: 7-segement set digit 3 and 2 (high byte, low byte) +// address 4: 7-segement set digit 1 and 0 (high byte, low byte) +void sys_modbus_setHoldingRegister (uint16_t address, uint16_t value) +{ + if (address>=0 && address<=2) + twi.holdingRegs.seg7value = value; + + switch (address) + { + case 0: sys_7seg_showHex(value); return; + case 1: sys_7seg_showUnsignedDecimal(value); return; + case 2: sys_7seg_showSignedDecimal((int16_t)value); return; + + case 3: + sys_7seg_setDigitLeds(2, value&0xff); + sys_7seg_setDigitLeds(3, value>>8); + break; + + case 4: + sys_7seg_setDigitLeds(0, value&0xff); + sys_7seg_setDigitLeds(1, value>>8); + break; + + } +} + +// address 0: 7-segment show hex 0 .. FFFF +// address 1: 7-segemnt show unsigned decimal 0..9999 +// address 2: 7-segment show signed decimal -999 .. 9999 +// address 3: 7-segement set digit 3 and 2 (high byte, low byte) +// address 4: 7-segement set digit 1 and 0 (high byte, low byte) +uint16_t sys_modbus_getHoldingRegister (uint16_t address) +{ + if (address==0 || address==1 || address==2) + return twi.holdingRegs.seg7value; + + switch (address) + { + case 0: case 1: case 2: return twi.holdingRegs.seg7value; + case 3: return sys.seg7.digit_u8[3]<<8 | sys.seg7.digit_u8[2]; + case 4: return sys.seg7.digit_u8[1]<<8 | sys.seg7.digit_u8[0]; + } + + return 0xffff; +} + + +void sys_modbus_sendRegisters (uint8_t functionCode, uint8_t size, uint16_t startAddress, uint8_t typ) +{ + uint16_t crc = 0xffff; + uint16_t i; + //volatile uint8_t *p = (volatile uint8_t *)startAddress; + sys_modbus_getInputRegister(0, 1); + crc = sys_modbus_updateCRC(GLOBAL_MODBUS_SLAVEADDRESS, crc); + crc = sys_modbus_updateCRC(functionCode, crc); + putchar(GLOBAL_MODBUS_SLAVEADDRESS); + putchar(functionCode); + crc = sys_modbus_updateCRC(size, crc); + putchar(size); + for (i=0; i>8, crc); + putchar(value>>8); + crc = sys_modbus_updateCRC(value&0xff, crc); + putchar(value&0xff); + } + + putchar((uint8_t)(crc&0xff)); + putchar((uint8_t)(crc>>8)); + + sys_modbus_freeFrame(); +} + + +void sys_modbus_sendResponse (uint8_t functionCode, uint8_t size, uint8_t data[]) +{ + uint16_t crc = 0xffff; + uint16_t i; + uint8_t *p; + crc = sys_modbus_updateCRC(GLOBAL_MODBUS_SLAVEADDRESS, crc); + crc = sys_modbus_updateCRC(functionCode, crc); + if (functionCode != 5 && functionCode != 6) + crc = sys_modbus_updateCRC(size, crc); + for (i=0, p=data; i>8)); + + sys_modbus_freeFrame(); +} + + +void sys_modbus_sendError (uint8_t functionCode, uint8_t exceptionCode) +{ + uint16_t crc = 0xffff; + crc = sys_modbus_updateCRC(GLOBAL_MODBUS_SLAVEADDRESS, crc); + crc = sys_modbus_updateCRC(functionCode, crc); + crc = sys_modbus_updateCRC(exceptionCode, crc); + + putchar(GLOBAL_MODBUS_SLAVEADDRESS); + putchar(functionCode); + putchar(exceptionCode); + putchar((uint8_t)(crc&0xff)); + putchar((uint8_t)(crc>>8)); + + sys_modbus_freeFrame(); +} + + +// ------------------------------------ +// Interrupt Service Routinen +// ------------------------------------ + +ISR (SYS_UART_RECEIVE_VECTOR) +{ + static uint8_t lastChar; + uint8_t tcnt0 = TCNT0; + uint16_t tick100us = (uint16_t) sys.tick100us; + uint8_t byteTimer = sys.modbus.byteTimer; + uint8_t c = SYS_UDR; + + if (c=='R' && lastChar=='@') + { + wdt_enable(WDTO_15MS); + wdt_reset(); + while(1) {}; + } + + lastChar = c; // for reset detection, accept "@R" only outside modbus frame + sys.modbus.byteTimer = GLOBAL_MODBUS_TIMER35; + + switch (sys.modbus.state) + { + case Init: + break; + + case Idle: + sys.modbus.state = Reception; + sys.modbus.crc = 0xffff; + sys.modbus.frameLength = 1; + sys.modbus.frameNotOkFlag = 0; + sys.modbus.frameOk = 0; + break; + + case Reception: + lastChar = 0; // for reset detection, do not accept "@R" inside modbus frame + if (sys.modbus.frameLength>0) + sys.modbus.frameLength++; + break; + + case CtrlAndWait: + sys.modbus.frameNotOkFlag = 1; + break; + + case Emission: + sys_modbus_setError(WrongState); + sys.modbus.state = Idle; + break; + + default: + sys_modbus_setError(WrongState); + sys.modbus.state = Idle; + break; + } + + if (sys.modbus.state == Reception) + { + sys.modbus.crc = sys_modbus_updateCRC(c, sys.modbus.crc); + sys.uart.rbuffer_u8[sys.uart.wpos_u8++] = c; + if (sys.uart.wpos_u8 >= GLOBAL_UART_RECBUFSIZE) + sys.uart.wpos_u8 = 0; + if (sys.uart.wpos_u8 == sys.uart.rpos_u8) + { + sys.uart.wpos_u8 == 0 ? sys.uart.wpos_u8 = GLOBAL_UART_RECBUFSIZE-1 : sys.uart.wpos_u8--; + sys.uart.errcnt_u8 = sys_inc8BitCnt(sys.uart.errcnt_u8); + sys_modbus_setError(BufferOverflow); + sys.modbus.frameLength = 0; + sys.modbus.frameNotOkFlag = 1; + } + sys.uart.rbuffer_u8[sys.uart.wpos_u8] = 0; + } + else + { + sys.modbus.frameLength = 0; + sys.modbus.frameNotOkFlag = 1; + } + + sys_log(__LINE__, c, byteTimer, tick100us, tcnt0); +} + + +// Timer 0 Output/Compare Interrupt +// called every 100us +ISR (SYS_TIMER0_VECTOR) +{ + static uint8_t cnt100us = 0; + static uint8_t cnt500us = 0; + static uint8_t busy = 0; + sys.tick100us++; + + if (sys.modbus.byteTimer>0) + { + sys.modbus.byteTimer--; + if (sys.modbus.byteTimer < GLOBAL_MODBUS_TIMER15) + { + if (sys.modbus.state == Reception) + sys.modbus.state = CtrlAndWait; + if (sys.modbus.state == CtrlAndWait) + sys_modbus_checkFrame(); + sys_log(__LINE__, -1, sys.modbus.byteTimer, sys.tick100us, TCNT0); + } + } + else if (sys.modbus.state == Reception || sys.modbus.state == CtrlAndWait) + { + if (sys.modbus.frameOk) + { + sys_log(__LINE__, -1, sys.modbus.byteTimer, sys.tick100us, TCNT0); + sys.modbus.checkedFrameLength = sys.modbus.frameLength; + sys.modbus.frameLength = 0; + sys_setEvent(APP_EVENT_MODBUS); + } + else + { + sys_modbus_setError(FrameError); + sys.modbus.checkedFrameLength = sys.modbus.frameLength; + sys.modbus.frameLength = 0; + sys_modbus_freeFrame(); + //sys_log(__LINE__, -1, sys.modbus.byteTimer, sys.tick100us, TCNT0); + } + sys.modbus.frameOk = 0; + sys.modbus.state = Idle; + } + else + sys.modbus.state = Idle; + + cnt100us++; + if (cnt100us>=5) + { + cnt100us = 0; + cnt500us++; + if (busy) + sys.taskErr_u8 = sys_inc8BitCnt(sys.taskErr_u8); + else + { + busy = 1; + sei(); + if (cnt500us & 0x01) + { + twi_task_1ms(); + app_task_1ms(); + } + else if (cnt500us & 0x02) + { +#ifdef SURE + if (sys.lcd.status != 1) + sys_7seg_refresh(); + else + PORTA &= ~0xf0; // disable 7-Segment +#endif + app_task_2ms(); + } + else if (cnt500us & 0x04) + { + if (sys.modbus.err.timer>0) + { + if (!--sys.modbus.err.timer) + sys.modbus.err.errorFlags = 0; + } + app_task_4ms(); + } + else if (cnt500us & 0x08) app_task_8ms(); + else if (cnt500us & 0x10) app_task_16ms(); + else if (cnt500us & 0x20) app_task_32ms(); + else if (cnt500us & 0x40) app_task_64ms(); + else if (cnt500us & 0x80) app_task_128ms(); + busy = 0; + } + } + +} diff --git a/sure_modbusslave/src/sys.h b/sure_modbusslave/src/sys.h new file mode 100644 index 0000000..5bcdee2 --- /dev/null +++ b/sure_modbusslave/src/sys.h @@ -0,0 +1,205 @@ +#ifndef SYS_H_INCLUDED +#define SYS_H_INCLUDED + +#if GLOBAL_UART_RECBUFSIZE > 255 + #error "GLOBAL_UART_RECBUFSIZE darf nicht groesser als 255 sein" +#endif + +// Neue Datentypen +typedef uint8_t Sys_Event; + +// Deklaration Strukturvariablentyp + +enum Sys_ModbusState { Init, Idle, Reception, CtrlAndWait, Emission }; + +struct Sys_LogEntry +{ + uint16_t line; + uint16_t tick100us; + uint16_t crc; + uint8_t tcnt0; + uint8_t byteTimer; + int16_t received; + uint8_t state; + uint8_t error; + uint8_t available; + uint8_t frameLength; +}; + +#ifdef GLOBAL_LOG +struct Sys_Log +{ + uint8_t wpos, rpos; + struct Sys_LogEntry data[GLOBAL_LOG_SIZE]; +}; +#endif + +enum Sys_ModbusError { FrameError, FrameBufferFull, WrongState, WrongCRC, wrongAddress, BufferOverflow, NN6, NN7 }; + +struct Sys_ModbusErrors +{ + uint8_t timer; + uint8_t errorFlags; +}; + + + +struct Sys_Modbus +{ + enum Sys_ModbusState state; + uint8_t byteTimer; // decremented to 0 every 100us, 1 char needs 190,972us + uint8_t frameLength; + uint16_t crc; + uint8_t frameNotOkFlag; + uint8_t frameOk; + uint8_t checkedFrameLength; + struct Sys_ModbusErrors err; +}; + + +struct Sys_Uart +{ + uint8_t rpos_u8; + uint8_t wpos_u8; + uint8_t errcnt_u8; + uint8_t rbuffer_u8[GLOBAL_UART_RECBUFSIZE]; +}; + +struct Sys_Seg7 +{ + uint8_t point_u8; + uint8_t digit_u8[4]; +}; + +struct Sys_Lcd +{ + int8_t status; // 0=not initialized, 1=ready, <0->error + uint8_t data; +}; + +struct Sys +{ + uint8_t flags_u8; + uint32_t tick100us; + uint8_t taskErr_u8; + Sys_Event eventFlag; + struct Sys_Uart uart; + struct Sys_Modbus modbus; +#ifdef GLOBAL_LOG + struct Sys_Log log; +#endif + +#ifdef SURE + struct Sys_Seg7 seg7; + struct Sys_Lcd lcd; +#endif +}; + +// Deklaration Strukturvariablen +extern volatile struct Sys sys; + + +// globale Defines +// SYS_FLAG_SREG_I must have same position as I-Bit in Status-Register!! +#define SYS_FLAG_SREG_I 0x80 +#define SYS_FLAG_7SEG_ENABLED 0x01 +#define SYS_FLAG_LCD_ENABLED 0x02 +#define SYS_SEG7_DIGIT_MINUS 0x10 +#define SYS_SEG7_DIGIT_UNDERLINE 0x11 +#define SYS_SEG7_DIGIT_OFF 0x13 + +#ifdef SURE + +// LCD-Display 2x20 Zeichen, 5x8 Pixel/Zeichen +// Controller KS0076B +// Data: Port B (Bit 7:0) +// RS=PD2, RW=PD3, E=PD4, VO (Kontrast) ueber Poti und OC1A(=PD5) + +#define SYS_LCD_PULSE_LENGTH 15 +#define SYS_LCD_SET_RS PORTD |= 0x04; // Signal RS=1 +#define SYS_LCD_CLR_RS PORTD &= ~0x04; // Signal RS=0 +#define SYS_LCD_SET_RW PORTD |= 0x08; // Signal RW=1 +#define SYS_LCD_CLR_RW PORTD &= ~0x08; // Signal RW=0 +#define SYS_LCD_SET_E PORTD |= 0x10; // Signal E=1 +#define SYS_LCD_CLR_E PORTD &= ~0x10; // Signal E=0 + +#define SYS_LCD_CMD_DISPLAY_CLEAR 0x01 // Display clear +#define SYS_LCD_CMD_CURSOR_HOME 0x02 // Move cursor digit 1 +#define SYS_LCD_CMD_SET_ENTRY_MODE 0x04 // Entry Mode Set +#define SYS_LCD_CMD_DISPLAY_ON_OFF 0x08 // Display on/off +#define SYS_LCD_CMD_SHIFT 0x10 // Display shift +#define SYS_LCD_CMD_SET_FUNCTION 0x20 // 4/8 Bits... +#define SYS_LCD_CMD_SET_CGRAM_ADDR 0x40 // Character Generator ROM +#define SYS_LCD_CMD_SET_DDRAM_ADDR 0x80 // Display Data RAM +#define SYS_LCD_BUSY_FLAG 0x80 + +#endif // SURE + + +// Funktionsdeklarationen +void sys_init (void); +void sys_main (void); + +void sys_sei (void); +void sys_cli (void); + +uint8_t sys_inc8BitCnt (uint8_t count); +int8_t sys_inc8BitCntAndReturn (uint8_t *count, int8_t retValue); +uint16_t sys_inc16BitCnt (uint16_t count); +int8_t sys_inc16BitCntAndReturn (uint16_t *count, int8_t retValue); + +void sys_newline (void); + +Sys_Event sys_setEvent (Sys_Event event); +Sys_Event sys_clearEvent (Sys_Event event); +Sys_Event sys_isEventPending (Sys_Event event); + +uint8_t sys_uart_available (void); +int16_t sys_uart_getBufferByte (uint8_t pos); +void sys_uart_flush (void); + +int16_t sys_modbus_getByte (uint8_t index); +void sys_modbus_sendResponse (uint8_t functionCode, uint8_t size, uint8_t data[]); +void sys_modbus_sendRegisters (uint8_t functionCode, uint8_t size, uint16_t startAddress, uint8_t typ); +void sys_modbus_sendError (uint8_t functionCode, uint8_t exceptionCode); +void sys_modbus_freeFrame (void); +void sys_7seg_showUnsignedDecimal (uint16_t value); +void sys_7seg_showSignedDecimal (int16_t value); +uint16_t sys_modbus_getInputRegister (uint16_t address, uint8_t newRequest); +void sys_modbus_setHoldingRegister (uint16_t address, uint16_t value); +uint16_t sys_modbus_getHoldingRegister (uint16_t address); + +struct Sys_LogEntry sys_log_next (void); +uint8_t sys_log_getSize (void); + +#ifdef SURE +void sys_setAllLeds (uint8_t ledState); +void sys_setLed (uint8_t index, uint8_t ledState); +void sys_toggleLed (uint8_t index); +void sys_7seg_setDigit (uint8_t index, uint8_t digitValue); +void sys_7seg_setDigitLeds (uint8_t index, uint8_t value); +void sys_7seg_setPoint (uint8_t index, uint8_t pointState); +void sys_7seg_setString (const char *str); +void sys_7seg_showDecimal (uint16_t value); +void sys_7seg_showHex (uint16_t value); + +void sys_lcd_init (void); +void sys_lcd_setRegister (uint8_t cmd); +void sys_lcd_setData (uint8_t addr, uint8_t data); +uint8_t sys_lcd_isReady (uint16_t us); +void sys_lcd_setDisplayOn (void); +void sys_lcd_setDisplayOff (void); +void sys_lcd_clear (void); +void sys_lcd_setCursorPosition (uint8_t rowIndex, uint8_t columnIndex); +void sys_lcd_putchar (int character); +void sys_lcd_putString (const char * str); +#endif + +#ifdef ASURO +void sys_setGreenLed (uint8_t ledState); +void sys_setRedLed (uint8_t ledState); +void sys_toggleGreenLed (void); +void sys_toggleRedLed (void); +#endif + +#endif // SYS_H_INCLUDED diff --git a/sure_modbusslave/src/twi.c b/sure_modbusslave/src/twi.c new file mode 100644 index 0000000..dc62ff5 --- /dev/null +++ b/sure_modbusslave/src/twi.c @@ -0,0 +1,359 @@ + +#include "global.h" +#include +#include +#include +#include +#include + +#include +#include +#include + +#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<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< 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<>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 index 0000000..8f55bd7 --- /dev/null +++ b/sure_modbusslave/src/twi.h @@ -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 -- 2.39.5