# HG changeset patch # User Heinz Junkes # Date 1439544643 -7200 # Node ID bd6bb22c65330f4b68db9cfd0e79248d000de7c0 First import diff -r 000000000000 -r bd6bb22c6533 Makefile --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/Makefile Fri Aug 14 11:30:43 2015 +0200 @@ -0,0 +1,31 @@ +# Makefile at top of application tree +TOP = . +include $(TOP)/configure/CONFIG + +# Directories to build, any order +DIRS += configure +DIRS += $(wildcard *Sup) +DIRS += $(wildcard *App) +DIRS += $(wildcard *Top) +DIRS += $(wildcard iocBoot) + +# The build order is controlled by these dependency rules: + +# All dirs except configure depend on configure +$(foreach dir, $(filter-out configure, $(DIRS)), \ + $(eval $(dir)_DEPEND_DIRS += configure)) + +# Any *App dirs depend on all *Sup dirs +$(foreach dir, $(filter %App, $(DIRS)), \ + $(eval $(dir)_DEPEND_DIRS += $(filter %Sup, $(DIRS)))) + +# Any *Top dirs depend on all *Sup and *App dirs +$(foreach dir, $(filter %Top, $(DIRS)), \ + $(eval $(dir)_DEPEND_DIRS += $(filter %Sup %App, $(DIRS)))) + +# iocBoot depends on all *App dirs +iocBoot_DEPEND_DIRS += $(filter %App,$(DIRS)) + +# Add any additional dependency rules here: + +include $(TOP)/configure/RULES_TOP diff -r 000000000000 -r bd6bb22c6533 configure/CONFIG --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/configure/CONFIG Fri Aug 14 11:30:43 2015 +0200 @@ -0,0 +1,29 @@ +# CONFIG - Load build configuration data +# +# Do not make changes to this file! + +# Allow user to override where the build rules come from +RULES = $(EPICS_BASE) + +# RELEASE files point to other application tops +include $(TOP)/configure/RELEASE +-include $(TOP)/configure/RELEASE.$(EPICS_HOST_ARCH).Common +ifdef T_A +-include $(TOP)/configure/RELEASE.Common.$(T_A) +-include $(TOP)/configure/RELEASE.$(EPICS_HOST_ARCH).$(T_A) +endif + +CONFIG = $(RULES)/configure +include $(CONFIG)/CONFIG + +# Override the Base definition: +INSTALL_LOCATION = $(TOP) + +# CONFIG_SITE files contain other build configuration settings +include $(TOP)/configure/CONFIG_SITE +-include $(TOP)/configure/CONFIG_SITE.$(EPICS_HOST_ARCH).Common +ifdef T_A + -include $(TOP)/configure/CONFIG_SITE.Common.$(T_A) + -include $(TOP)/configure/CONFIG_SITE.$(EPICS_HOST_ARCH).$(T_A) +endif + diff -r 000000000000 -r bd6bb22c6533 configure/CONFIG_SITE --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/configure/CONFIG_SITE Fri Aug 14 11:30:43 2015 +0200 @@ -0,0 +1,36 @@ +# CONFIG_SITE + +# Make any application-specific changes to the EPICS build +# configuration variables in this file. +# +# Host/target specific settings can be specified in files named +# CONFIG_SITE.$(EPICS_HOST_ARCH).Common +# CONFIG_SITE.Common.$(T_A) +# CONFIG_SITE.$(EPICS_HOST_ARCH).$(T_A) + +# CHECK_RELEASE controls the consistency checking of the support +# applications pointed to by the RELEASE* files. +# Normally CHECK_RELEASE should be set to YES. +# Set CHECK_RELEASE to NO to disable checking completely. +# Set CHECK_RELEASE to WARN to perform consistency checking but +# continue building even if conflicts are found. +CHECK_RELEASE = YES + +# Set this when you only want to compile this application +# for a subset of the cross-compiled target architectures +# that Base is built for. +#CROSS_COMPILER_TARGET_ARCHS = vxWorks-ppc32 + +# To install files into a location other than $(TOP) define +# INSTALL_LOCATION here. +#INSTALL_LOCATION= + +# Set this when the IOC and build host use different paths +# to the install location. This may be needed to boot from +# a Microsoft FTP server say, or on some NFS configurations. +#IOCS_APPL_TOP = + +# For application debugging purposes, override the HOST_OPT and/ +# or CROSS_OPT settings from base/configure/CONFIG_SITE +#HOST_OPT = NO +#CROSS_OPT = NO diff -r 000000000000 -r bd6bb22c6533 configure/Makefile --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/configure/Makefile Fri Aug 14 11:30:43 2015 +0200 @@ -0,0 +1,8 @@ +TOP=.. + +include $(TOP)/configure/CONFIG + +TARGETS = $(CONFIG_TARGETS) +CONFIGS += $(subst ../,,$(wildcard $(CONFIG_INSTALLS))) + +include $(TOP)/configure/RULES diff -r 000000000000 -r bd6bb22c6533 configure/RELEASE --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/configure/RELEASE Fri Aug 14 11:30:43 2015 +0200 @@ -0,0 +1,39 @@ +# RELEASE - Location of external support modules +# +# IF YOU MAKE ANY CHANGES to this file you must subsequently +# do a "gnumake rebuild" in this application's top level +# directory. +# +# The build process does not check dependencies against files +# that are outside this application, thus you should do a +# "gnumake rebuild" in the top level directory after EPICS_BASE +# or any other external module pointed to below is rebuilt. +# +# Host- or target-specific settings can be given in files named +# RELEASE.$(EPICS_HOST_ARCH).Common +# RELEASE.Common.$(T_A) +# RELEASE.$(EPICS_HOST_ARCH).$(T_A) +# +# This file should ONLY define paths to other support modules, +# or include statements that pull in similar RELEASE files. +# Build settings that are NOT module paths should appear in a +# CONFIG_SITE file. + +TEMPLATE_TOP=$(EPICS_BASE)/templates/makeBaseApp/top + +HOME=/home/epics/ +MODULES=$(HOME)/EPICS/modules +SUPPORT=$(HOME)/EPICS/support + +# If using the sequencer, point SNCSEQ at its top directory: +SNCSEQ=$(MODULES)/seq-2.2.2 +ASYN=$(SUPPORT)/asyn4-26 +STREAM=$(SUPPORT)/stream +EUROTHERM2K=$(SUPPORT)/eurotherm2k-1-18 + +# EPICS_BASE usually appears last so other apps can override stuff: +EPICS_BASE=$(HOME)/EPICS/base + +# Set RULES here if you want to take build rules from somewhere +# other than EPICS_BASE: +#RULES=/path/to/epics/support/module/rules/x-y diff -r 000000000000 -r bd6bb22c6533 configure/RULES --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/configure/RULES Fri Aug 14 11:30:43 2015 +0200 @@ -0,0 +1,6 @@ +# RULES + +include $(CONFIG)/RULES + +# Library should be rebuilt because LIBOBJS may have changed. +$(LIBNAME): ../Makefile diff -r 000000000000 -r bd6bb22c6533 configure/RULES.ioc --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/configure/RULES.ioc Fri Aug 14 11:30:43 2015 +0200 @@ -0,0 +1,2 @@ +#RULES.ioc +include $(CONFIG)/RULES.ioc diff -r 000000000000 -r bd6bb22c6533 configure/RULES_DIRS --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/configure/RULES_DIRS Fri Aug 14 11:30:43 2015 +0200 @@ -0,0 +1,2 @@ +#RULES_DIRS +include $(CONFIG)/RULES_DIRS diff -r 000000000000 -r bd6bb22c6533 configure/RULES_TOP --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/configure/RULES_TOP Fri Aug 14 11:30:43 2015 +0200 @@ -0,0 +1,3 @@ +#RULES_TOP +include $(CONFIG)/RULES_TOP + diff -r 000000000000 -r bd6bb22c6533 iocBoot/Makefile --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/iocBoot/Makefile Fri Aug 14 11:30:43 2015 +0200 @@ -0,0 +1,6 @@ +TOP = .. +include $(TOP)/configure/CONFIG +DIRS += $(wildcard *ioc*) +DIRS += $(wildcard as*) +include $(CONFIG)/RULES_DIRS + diff -r 000000000000 -r bd6bb22c6533 iocBoot/iockstm/Makefile --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/iocBoot/iockstm/Makefile Fri Aug 14 11:30:43 2015 +0200 @@ -0,0 +1,5 @@ +TOP = ../.. +include $(TOP)/configure/CONFIG +ARCH = linux-x86_64 +TARGETS = envPaths +include $(TOP)/configure/RULES.ioc diff -r 000000000000 -r bd6bb22c6533 iocBoot/iockstm/pid.txt --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/iocBoot/iockstm/pid.txt Fri Aug 14 11:30:43 2015 +0200 @@ -0,0 +1,1 @@ +2436 diff -r 000000000000 -r bd6bb22c6533 iocBoot/iockstm/st.cmd --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/iocBoot/iockstm/st.cmd Fri Aug 14 11:30:43 2015 +0200 @@ -0,0 +1,73 @@ +#!../../bin/linux-arm/kstm + +## You may have to change kstm to something else +## everywhere it appears in this file + +< envPaths + +epicsEnvSet EUROTH01_INET 141.14.128.45:4001 +epicsEnvSet EUROTH01_LINK EUROTH_01 + +epicsEnvSet EUROTH02_INET 141.14.128.45:4002 +epicsEnvSet EUROTH02_LINK EUROTH_02 + +epicsEnvSet MTM_INET 141.14.128.45:4004 +epicsEnvSet MTM_LINK MTM + +epicsEnvSet M1900_INET 141.14.128.45:4003 +epicsEnvSet M1900_LINK M1900 + +epicsEnvSet PGC2_MC_INET 141.14.128.45:4005 +epicsEnvSet PGC2_MC_LINK PGC2_MC + +epicsEnvSet PGC2_PC_INET 141.14.128.45:4006 +epicsEnvSet PGC2_PC_LINK PGC2_PC + +cd "${TOP}" + +epicsEnvSet "STREAM_PROTOCOL_PATH", "$(TOP)/db" + +## Register all support components +dbLoadDatabase("dbd/kstm.dbd",0,0) +kstm_registerRecordDeviceDriver(pdbbase) + +drvAsynIPPortConfigure(${EUROTH01_LINK}, ${EUROTH01_INET}, 0, 0, 0) +drvAsynIPPortConfigure(${EUROTH02_LINK}, ${EUROTH02_INET}, 0, 0, 0) +drvAsynIPPortConfigure(${MTM_LINK}, ${MTM_INET}, 0, 0, 0) +drvAsynIPPortConfigure(${M1900_LINK}, ${M1900_INET}, 0, 0, 0) +drvAsynIPPortConfigure(${PGC2_MC_LINK}, ${PGC2_MC_INET}, 0, 0, 0) +drvAsynIPPortConfigure(${PGC2_PC_LINK}, ${PGC2_PC_INET}, 0, 0, 0) + +# Set asyn trace IO format +#define ASYN_TRACEIO_NODATA 0x0000 +#define ASYN_TRACEIO_ASCII 0x0001 +#define ASYN_TRACEIO_ESCAPE 0x0002 +#define ASYN_TRACEIO_HEX 0x0004 +#asynSetTraceIOMask ${PGC2_MC_LINK} 0 1 + +# Set asyn trace masks +# ASYN_TRACE_ERROR 0x0001 +# ASYN_TRACEIO_DEVICE 0x0002 +# ASYN_TRACEIO_FILTER 0x0004 +# ASYN_TRACEIO_DRIVER 0x0008 +# ASYN_TRACE_FLOW 0x0010 +#asynSetTraceMask ${PGC2_MC_LINK} 0 8 + +epicsEnvSet ("streamDebug","1") + +## Load record instances +dbLoadRecords("db/misc.db","P=FHI4KSTM, Q=MISC") + +#dbLoadRecords("db/dht.db","P=FHI4KSTM, Q=DHT") + +dbLoadTemplate("db/4kStmEuro.sub") + +dbLoadRecords("db/mtm.db","PORT=MTM, P=FHI4KSTM, Q=MTM") +dbLoadRecords("db/M1900.db","PORT=M1900, P=FHI4KSTM, Q=M1900") +dbLoadRecords("db/pgc2.db","PORT=PGC2_MC, P=FHI4KSTM, Q=PGC2_MC") +dbLoadRecords("db/pgc2.db","PORT=PGC2_PC, P=FHI4KSTM, Q=PGC2_PC") + +iocInit() + +## Start any sequence programs +#seq snckstm,"user=heinz" diff -r 000000000000 -r bd6bb22c6533 kstmApp/Db/4kStmEuro.sub --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/kstmApp/Db/4kStmEuro.sub Fri Aug 14 11:30:43 2015 +0200 @@ -0,0 +1,20 @@ +# Macros: +# P Device prefix +# Q Device suffix +# PORT Asyn port name +# GAD Global address number, normally 0 +# LAD Local address number, normally 1 +# SPMAX Maximum setpoint +# RRMAX Maximum ramp rate +# SPCMD Setpoint command, set to 'write' for floating point +# PREC Setpoint precision +# EGU Engineering units for ramp rate, default is C/s +# name object and gui association name +# gda_name Name to export to gda as +# gda_desc Description for gda +file db/eurotherm2k.template +{ +pattern { P, Q, PORT, GAD, LAD, SPMAX, RRMAX, SPCMD, PREC, EGU, name, gda_name, gda_desc } + { "FHI4KSTM:", "EUROTH01", "EUROTH_01", "0", "1", "1000", "1", "writeint", "0", "C/s", "", "", "" } + { "FHI4KSTM:", "EUROTH02", "EUROTH_02", "0", "1", "1000", "1", "writeint", "0", "C/s", "", "", "" } +} diff -r 000000000000 -r bd6bb22c6533 kstmApp/Db/M1900.db --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/kstmApp/Db/M1900.db Fri Aug 14 11:30:43 2015 +0200 @@ -0,0 +1,9 @@ +record(ai, "$(P):$(Q):temp") +{ +field(SCAN, "5 second") +field(DTYP,"stream") +field(INP,"@M1900.proto read $(PORT) -1") +field(EGU,"K") +field(HOPR,"400") +field(LOPR,"0") +} diff -r 000000000000 -r bd6bb22c6533 kstmApp/Db/M1900.proto --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/kstmApp/Db/M1900.proto Fri Aug 14 11:30:43 2015 +0200 @@ -0,0 +1,2 @@ +Terminator = CR NUL; +read { out "T"; in "T"; in "%f"; } diff -r 000000000000 -r bd6bb22c6533 kstmApp/Db/Makefile --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/kstmApp/Db/Makefile Fri Aug 14 11:30:43 2015 +0200 @@ -0,0 +1,35 @@ +TOP=../.. +include $(TOP)/configure/CONFIG +#---------------------------------------- +# ADD MACRO DEFINITIONS AFTER THIS LINE + +#---------------------------------------------------- +# Optimization of db files using dbst (DEFAULT: NO) +#DB_OPT = YES + +#---------------------------------------------------- +# Create and install (or just install) into /db +# databases, templates, substitutions like this +#DB += xxx.db +DB += dht.db +DB += misc.db +DB += mtm.db + +DB += 4kStmEuro.sub +DB += eurotherm2k.proto +DB += eurotherm2k.template + +DB += pgc2.db +DB += pgc2.proto + +DB += M1900.db +DB += M1900.proto + +#---------------------------------------------------- +# If .db template is not named *.template add +# _template = + +include $(TOP)/configure/RULES +#---------------------------------------- +# ADD RULES AFTER THIS LINE + diff -r 000000000000 -r bd6bb22c6533 kstmApp/Db/dht.db --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/kstmApp/Db/dht.db Fri Aug 14 11:30:43 2015 +0200 @@ -0,0 +1,8 @@ +record(sub,"$(P):$(Q):R_temp") +{ + field(INAM,"dbSubReadDHTInit") + field(SNAM,"dbSubReadDHTProcess") + field(SCAN,"5 second") + field(INPA,"3") +} + diff -r 000000000000 -r bd6bb22c6533 kstmApp/Db/eurotherm2k.proto --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/kstmApp/Db/eurotherm2k.proto Fri Aug 14 11:30:43 2015 +0200 @@ -0,0 +1,96 @@ +## \file +## Stream Device Protocol for eurotherm 2000 series EI Bisynch +## \param GAD = First char of address, e.g. address = 1, GAD = 0, address = 12, GAD = 1 +## \param LAD = Second char of address, e.g. address = 1, LAD = 1, address = 12, LAD = 2 + +locktimeout = 5000; + +## Unfortunately, this is designed with a checksum terminator. +OutTerminator = ""; +replytimeout = 200; +## Setting a small readtimeout means that we can get data without needing a terminator +readtimeout = 100; +extrainput = Ignore; + +#STX = "\x02" +#ETX = "\x03" +#EOT = "\x04" +#ENQ = "\x05" +#ACK = "\x06" + +## Read value +## \code +## send: [EOT](GAD)(GAD)(LAD)(LAD)(CHAN)(C1)(C2)[ENQ] +## reply: [STX](CHAN)(C1)(C2)[ETX](BCC) +## \endcode +## - $1 = GAD +## - $2 = LAD +## - $3 = command mnemonic +############################################################################# +read { InTerminator = "\x03"; out "\x04\$1\$1\$2\$2\$3\x05"; in "\x02\$3%f"; } + +## Read value, but in hex +readhex { InTerminator = "\x03"; out "\x04\$1\$1\$2\$2\$3\x05"; in "\x02\$3>%x"; } + +## NOTE: we rely on readtimeout for the in commands. +## Could use maxInput, but that screws up record initialisation (once inTerminator is set it can't be overwritten in the \@init handler) +## +## Write value +## \code +## send: [EOT](GAD)(GAD)(LAD)(LAD)[STX](CHAN)(C1)(C2)[ETX](BCC) +## reply: [ACK] or [NAK], discarded as no terminator +## \endcode +## - $1 = GAD +## - $2 = LAD +## - $3 = command mnemonic +## - $4 = device prefix, \$(P)\$(Q) +############################################################################# +write { InTerminator = ""; out "\x04\$1\$1\$2\$2\x02\$3%f\x03%6"; in "\x06"; @init{ read; }; @mismatch{ in "%(\$4:ERR.PROC)r"; }; } + +## Write a value in int rather than float +writeint { InTerminator = ""; out "\x04\$1\$1\$2\$2\x02\$3%i\x03%6"; in "\x06"; @init{ read; }; @mismatch{ in "%(\$4:ERR.PROC)r"; }; } + + +### \brief Controller configuration mode +## +## This mode enable setting a number of controller configuration settings +## (see Communications Handbook PDF pages 5-25 onwards) +## +## We set the mode by sending a command 'IM2' and get out of the mode with the command 'IM0' +## While in configuration mode the controller makes itself address 0 so any configuration commands +## have to be sent to address = 0 +setConfMode { InTerminator = ""; out "\x04\$1\$1\$2\$2\x02IM2\x03%6"; in "\x06"; @mismatch{ in "%(\$3:ERR.PROC)r"; }; } + +## Escape from the configuration mode in to normal operation mode +clearConfMode { InTerminator = ""; out "\x040000\x02IM0\x03%6"; in "\x06"; @mismatch{ in "%(\$1:ERR.PROC)r"; }; } + +## Get the current mode of the controller: 0=normal mode, 2=configuration mode +getConfMode { InTerminator = "\x03"; out "\x0400%(\$1:ADDR.VAL)i%(\$1:ADDR.VAL)iIM\x05"; in "\x02IM%i."; } + +## \brief Set device precision. +## +## The number of decimal places in the controller is also the precision the data is returned when communicating over serial. +## This parameter can only be set when in Configuration Mode (see above) +setDecPlaces { InTerminator = ""; out "\x0400%(\$1:ADDR.VAL)i%(\$1:ADDR.VAL)i\x02QD%i\x03%6"; in "\x06"; @mismatch{ in "%(\$1:ERR.PROC)r"; }; } + +## Read the number of decimal places used in the controller +getDecPlaces { InTerminator = "\x03"; out "\x0400%(\$1:ADDR.VAL)i%(\$1:ADDR.VAL)iQD\x05"; in "\x02QD%i."; } + +## The ramp rate time unit. Note this parameter can only be set when in Configuration Mode +setRampRateUnit { InTerminator = ""; out "\x0400%(\$1:ADDR.VAL)i%(\$1:ADDR.VAL)i\x02QJ%i\x03%6"; in "\x06"; @mismatch{ in "%(\$1:ERR.PROC)r"; }; } + +## Read out the ramp rate time unit +getRampRateUnit { InTerminator = "\x03"; out "\x0400%(\$1:ADDR.VAL)i%(\$1:ADDR.VAL)iQJ\x05"; in "\x02QJ%i."; } + +## \brief Write any ASCII string command to the device. +## +## It will read the device address (although only the LAD part) from another record: \$1:ADDR.VAL +addrWrite { InTerminator = ""; out "\x0400%(\$1:ADDR.VAL)i%(\$1:ADDR.VAL)i\x02%s\x03%6"; in "\x06"; @mismatch{ in "%(\$1:ERR.PROC)r"; }; } + +## \brief Read back any ASCII string paramter from the device. +## +## This will also read the device address from an external record. +addrRead { InTerminator = "\x03"; out "\x0400%(\$1:ADDR.VAL)i%(\$1:ADDR.VAL)i%s\x05"; in "\x02%(\$1:ADDR:RESP.VAL)6c"; } + + + diff -r 000000000000 -r bd6bb22c6533 kstmApp/Db/eurotherm2k.template --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/kstmApp/Db/eurotherm2k.template Fri Aug 14 11:30:43 2015 +0200 @@ -0,0 +1,510 @@ +#! Generated by VisualDCT v2.6 +#! DBDSTART +#! DBD("../../example/dbd/example.dbd") +#! DBDEND + + +# % macro, P, Device prefix +# % macro, Q, Device suffix +# % macro, PORT, Asyn port name +# % macro, GAD, Global address number, normally 0 +# % macro, LAD, Local address number, normally 1 +# % macro, SPMAX, Maximum setpoint +# % macro, RRMAX, Maximum ramp rate +# % macro, SPCMD, Setpoint command, set to 'write' for floating point +# % macro, PREC, Setpoint precision +# % macro, EGU, Engineering units for ramp rate, default is C/s +# % macro, name, object and gui association name +# % macro, gda_name, Name to export to gda as +# % macro, gda_desc, Description for gda +# % gdatag,template,eurotherm2k,$(gda_name=),$(gda_desc=) +# % gui, $(name=), edmembed, eurotherm2k_embed.edl, eurotherm=$(P)$(Q) +# % gui, $(name=), edm, eurotherm2k.edl, eurotherm=$(P)$(Q) +# % autosave 2 SCAN +record(seq, "$(P)$(Q):UPDATE") { + field(DESC, "Update Temp Params") + field(DOL1, "1") + field(DOL2, "1") + field(DOL3, "1") + field(DOL4, "1") + field(LNK1, "$(P)$(Q):SP:RBV.PROC") + field(LNK2, "$(P)$(Q):RR:RBV.PROC") + field(LNK3, "$(P)$(Q):O:RBV.PROC") + field(LNK4, "$(P)$(Q):PV:RBV.PROC") + field(SCAN, "1 second") + field(PINI, "YES") + field(DOL5, "1") + field(LNK5, "$(P)$(Q):MAN:RBV_AI.PROC") +} + +# % autosave 2 SCAN +record(seq, "$(P)$(Q):PID") { + field(DESC, "Update PID Params") + field(DOL1, "1") + field(DOL2, "1") + field(DOL3, "1") + field(LNK1, "$(P)$(Q):P:RBV.PROC") + field(LNK2, "$(P)$(Q):I:RBV.PROC") + field(LNK3, "$(P)$(Q):D:RBV.PROC") + field(SCAN, "10 second") + field(PINI, "YES") +} + +#% gdatag,pv,rw,$(gda_name=),SP +record(ao, "$(P)$(Q):SP") { + field(DESC, "Setpoint") + field(DTYP, "stream") + field(FLNK, "$(P)$(Q):SP:RBV") + field(OUT, "@eurotherm2k.proto $(SPCMD=writeint)($(GAD),$(LAD),S1,$(P)$(Q)) $(PORT)") + field(PREC, "$(PREC=0)") + field(EGU, "C") + field(DRVH, "$(SPMAX=1000)") + field(DRVL, "0") + field(PINI, "YES") + field(SDIS, "$(P)$(Q):DISABLE") +} + +# % gdatag,pv,ro,$(gda_name=),SPRBV +# % archiver 10 Monitor +record(ai, "$(P)$(Q):SP:RBV") { + field(DESC, "Setpoint Readback") + field(DTYP, "stream") + field(INP, "@eurotherm2k.proto read($(GAD),$(LAD),S1) $(PORT)") + field(PREC, "$(PREC=0)") + field(EGU, "C") + field(SDIS, "$(P)$(Q):DISABLE") +} + +#% gdatag,pv,rw,$(gda_name=),RR +record(ao, "$(P)$(Q):RR") { + field(DESC, "Ramprate") + field(DTYP, "stream") + field(FLNK, "$(P)$(Q):RR:RBV") + field(OUT, "@eurotherm2k.proto write($(GAD),$(LAD),RR,$(P)$(Q)) $(PORT)") + field(PREC, "3") + field(EGU, "$(EGU=C/s)") + field(DRVH, "$(RRMAX=1)") + field(DRVL, "0") + field(PINI, "YES") + field(SDIS, "$(P)$(Q):DISABLE") +} + +# % gdatag,pv,ro,$(gda_name=),RRRBV +# % archiver 10 Monitor +record(ai, "$(P)$(Q):RR:RBV") { + field(DESC, "Ramprate Readback") + field(DTYP, "stream") + field(INP, "@eurotherm2k.proto read($(GAD),$(LAD),RR) $(PORT)") + field(PREC, "3") + field(EGU, "$(EGU=C/s)") + field(SDIS, "$(P)$(Q):DISABLE") +} + +#% gdatag,pv,rw,$(gda_name=),O +record(ao, "$(P)$(Q):O") { + field(DESC, "Output") + field(DTYP, "stream") + field(FLNK, "$(P)$(Q):O:RBV") + field(OUT, "@eurotherm2k.proto write($(GAD),$(LAD),OP,$(P)$(Q)) $(PORT)") + field(PREC, "1") + field(EGU, "%") + field(DRVH, "100") + field(DRVL, "-100") + field(PINI, "YES") + field(SDIS, "$(P)$(Q):DISABLE") +} + +# % gdatag,pv,ro,$(gda_name=),ORBV +# % archiver 1 Monitor +record(ai, "$(P)$(Q):O:RBV") { + field(DESC, "Ouptut Readback") + field(DTYP, "stream") + field(INP, "@eurotherm2k.proto read($(GAD),$(LAD),OP) $(PORT)") + field(PREC, "1") + field(EGU, "%") + field(SDIS, "$(P)$(Q):DISABLE") +} + +# % gdatag,pv,ro,$(gda_name=),PVRBV +# % archiver 1 Monitor +record(ai, "$(P)$(Q):PV:RBV") { + field(DESC, "Temperature Readback") + field(DTYP, "stream") + field(INP, "@eurotherm2k.proto read($(GAD),$(LAD),PV) $(PORT)") + field(PREC, "1") + field(EGU, "C") + field(SDIS, "$(P)$(Q):DISABLE") +} + +#% gdatag,pv,rw,$(gda_name=),P +record(ao, "$(P)$(Q):P") { + field(DESC, "P Param") + field(DTYP, "stream") + field(FLNK, "$(P)$(Q):P:RBV") + field(OUT, "@eurotherm2k.proto writeint($(GAD),$(LAD),XP,$(P)$(Q)) $(PORT)") + field(PREC, "0") + field(VAL, "150") + field(PINI, "YES") + field(SDIS, "$(P)$(Q):DISABLE") +} + +# % gdatag,pv,ro,$(gda_name=),PRBV +# % archiver 10 Monitor +record(ai, "$(P)$(Q):P:RBV") { + field(DESC, "P Param Readback") + field(DTYP, "stream") + field(INP, "@eurotherm2k.proto read($(GAD),$(LAD),XP) $(PORT)") + field(PREC, "0") + field(SDIS, "$(P)$(Q):DISABLE") +} + +#% gdatag,pv,rw,$(gda_name=),I +record(ao, "$(P)$(Q):I") { + field(DESC, "I Param") + field(DTYP, "stream") + field(FLNK, "$(P)$(Q):I:RBV") + field(OUT, "@eurotherm2k.proto writeint($(GAD),$(LAD),TI,$(P)$(Q)) $(PORT)") + field(PREC, "0") + field(VAL, "28") + field(PINI, "YES") + field(SDIS, "$(P)$(Q):DISABLE") +} + +# % gdatag,pv,ro,$(gda_name=),IRBV +# % archiver 10 Monitor +record(ai, "$(P)$(Q):I:RBV") { + field(DESC, "I Param Readback") + field(DTYP, "stream") + field(INP, "@eurotherm2k.proto read($(GAD),$(LAD),TI) $(PORT)") + field(PREC, "0") + field(SDIS, "$(P)$(Q):DISABLE") +} + +#% gdatag,pv,rw,$(gda_name=),D +record(ao, "$(P)$(Q):D") { + field(DESC, "D Param") + field(DTYP, "stream") + field(FLNK, "$(P)$(Q):D:RBV") + field(OUT, "@eurotherm2k.proto writeint($(GAD),$(LAD),TD,$(P)$(Q)) $(PORT)") + field(PREC, "0") + field(VAL, "4") + field(PINI, "YES") + field(SDIS, "$(P)$(Q):DISABLE") +} + +# % gdatag,pv,ro,$(gda_name=),DRBV +# % archiver 10 Monitor +record(ai, "$(P)$(Q):D:RBV") { + field(DESC, "D Param Readback") + field(DTYP, "stream") + field(INP, "@eurotherm2k.proto read($(GAD),$(LAD),TD) $(PORT)") + field(PREC, "0") + field(SDIS, "$(P)$(Q):DISABLE") +} + +# % gdatag,pv,rw,$(gda_name=),ERR +record(mbbi, "$(P)$(Q):ERR") { + field(DESC, "Error message") + field(DTYP, "stream") + field(INP, "@eurotherm2k.proto readhex($(GAD),$(LAD),EE) $(PORT)") + field(ZRVL, "0") + field(ZRST, "No Error") + field(ONVL, "1") + field(ONST, "Invalid Param") + field(TWVL, "2") + field(TWST, "Read Only") + field(THVL, "7") + field(THST, "Incorrect Msg") + field(FRVL, "8") + field(FRST, "Limit Error") + field(PINI, "YES") + field(SDIS, "$(P)$(Q):DISABLE") +} + +# % gdatag,binary,rw,$(gda_name=),DISABLE +record(bo, "$(P)$(Q):DISABLE") { + field(DESC, "Disable comms") + field(PINI, "YES") + field(VAL, "1") + field(OMSL, "supervisory") + field(ZNAM, "Enabled") + field(ONAM, "Disabled") +} + +record(bo, "$(P)$(Q):MAN") { + field(DESC, "Manual mode enable") + field(DTYP, "stream") + field(SDIS, "$(P)$(Q):DISABLE") + field(FLNK, "$(P)$(Q):MAN:RBV_AI") + field(OUT, "@eurotherm2k.proto writeint($(GAD),$(LAD),mA,$(P)$(Q)) $(PORT)") + field(ZNAM, "Automatic") + field(ONAM, "Manual") + field(PINI, "YES") +} + +record(ai, "$(P)$(Q):MAN:RBV_AI") { + field(DESC, "Manual mode readback") + field(DTYP, "stream") + field(SDIS, "$(P)$(Q):DISABLE") + field(INP, "@eurotherm2k.proto read($(GAD),$(LAD),mA) $(PORT)") + field(FLNK, "$(P)$(Q):MAN:RBV") +} + +# % archiver 10 Monitor +record(bi, "$(P)$(Q):MAN:RBV") { + field(DESC, "Manual mode readback") + field(DTYP, "Soft Channel") + field(INP, "$(P)$(Q):MAN:RBV_AI") + field(ZNAM, "Automatic") + field(ONAM, "Manual") +} + +record(mbbi, "$(P)$(Q):CONF:MODE") { + field(DTYP, "stream") + field(INP, "@eurotherm2k.proto getConfMode($(P)$(Q)) $(PORT)") + field(ZRVL, "0") + field(ONVL, "2") + field(ZRST, "operational") + field(ONST, "configuration") +} + +record(longin, "$(P)$(Q):ADDR") { + field(FLNK, "$(P)$(Q):CONF:DLY") +} + +record(longout, "$(P)$(Q):ADDR:DEVICE") { + field(VAL, "$(LAD)") + field(OUT, "$(P)$(Q):ADDR PP") +} + +record(bo, "$(P)$(Q):CONF:SETMODE") { + field(DTYP, "stream") + field(FLNK, "$(P)$(Q):CONF:ZEROADDR") + field(OUT, "@eurotherm2k.proto setConfMode($(GAD),$(LAD),$(P)$(Q)) $(PORT)") + field(ZNAM, "0") + field(ONAM, "1") +} + +record(bo, "$(P)$(Q):CONF:CLEARMODE") { + field(DTYP, "stream") + field(FLNK, "$(P)$(Q):ADDR:DEVICE") + field(OUT, "@eurotherm2k.proto clearConfMode($(P)$(Q)) $(PORT)") + field(ZNAM, "0") + field(ONAM, "1") +} + +record(longout, "$(P)$(Q):CONF:ZEROADDR") { + field(VAL, "0") + field(OUT, "$(P)$(Q):ADDR PP") +} + +record(stringout, "$(P)$(Q):ADDR:WR") { + field(DESC, "write cmd") + field(DTYP, "stream") + field(OUT, "@eurotherm2k.proto addrWrite($(P)$(Q)) $(PORT)") + field(PINI, "NO") +} + +record(stringout, "$(P)$(Q):ADDR:RD") { + field(DESC, "Read parameter") + field(DTYP, "stream") + field(OUT, "@eurotherm2k.proto addrRead($(P)$(Q)) $(PORT)") +} + +record(stringin, "$(P)$(Q):ADDR:RESP") { + field(DESC, "Read response") +} + +record(mbbi, "$(P)$(Q):CONF:DECP") { + field(DTYP, "stream") + field(INP, "@eurotherm2k.proto getDecPlaces($(P)$(Q)) $(PORT)") + field(ZRVL, "0") + field(ONVL, "1") + field(ZRST, "nnnn.") + field(ONST, "nnn.n") + field(DESC, "decimal places") + field(TWVL, "2") + field(TWST, "nn.nn") +} + +record(mbbo, "$(P)$(Q):CONF:SET:DECP") { + field(DESC, "decimal places") + field(DTYP, "stream") + field(OUT, "@eurotherm2k.proto setDecPlaces($(P)$(Q)) $(PORT)") + field(ZRVL, "0") + field(ONVL, "1") + field(TWVL, "2") + field(ZRST, "nnnn.") + field(ONST, "nnn.n") + field(TWST, "nn.nn") +} + +record(fanout, "$(P)$(Q):CONF:READ") { + field(FLNK, "$(P)$(Q):CONF:DECP") + field(LNK1, "$(P)$(Q):CONF:RREGU") +} + +record(mbbi, "$(P)$(Q):CONF:RREGU") { + field(DTYP, "stream") + field(INP, "@eurotherm2k.proto getRampRateUnit($(P)$(Q)) $(PORT)") + field(ZRVL, "0") + field(ONVL, "1") + field(ZRST, "sec") + field(ONST, "min") + field(DESC, "decimal places") + field(TWVL, "2") + field(TWST, "hour") +} + +record(mbbo, "$(P)$(Q):CONF:SET:RREGU") { + field(DESC, "decimal places") + field(DTYP, "stream") + field(OUT, "@eurotherm2k.proto setRampRateUnit($(P)$(Q)) $(PORT)") + field(ZRVL, "0") + field(ONVL, "1") + field(TWVL, "2") + field(ZRST, "sec") + field(ONST, "min") + field(TWST, "hour") +} + + +record(seq, "$(P)$(Q):CONF:DLY") { + field(SELM, "Specified") + field(SELL, "1") + field(DLY1, "5.0") + field(DOL1, "1") + field(LNK1, "$(P)$(Q):CONF:MODE.PROC CA MS") +} + +#! Further lines contain data used by VisualDCT +#! View(206,1478,1.1) +#! Record("$(P)$(Q):UPDATE",960,222,0,0,"$(P)$(Q):UPDATE") +#! Field("$(P)$(Q):UPDATE.LNK1",16777215,1,"$(P)$(Q):UPDATE.LNK1") +#! Link("$(P)$(Q):UPDATE.LNK1","$(P)$(Q):SP:RBV.PROC") +#! Field("$(P)$(Q):UPDATE.LNK2",16777215,1,"$(P)$(Q):UPDATE.LNK2") +#! Link("$(P)$(Q):UPDATE.LNK2","$(P)$(Q):RR:RBV.PROC") +#! Field("$(P)$(Q):UPDATE.LNK3",16777215,1,"$(P)$(Q):UPDATE.LNK3") +#! Link("$(P)$(Q):UPDATE.LNK3","$(P)$(Q):O:RBV.PROC") +#! Field("$(P)$(Q):UPDATE.LNK4",16777215,1,"$(P)$(Q):UPDATE.LNK4") +#! Link("$(P)$(Q):UPDATE.LNK4","$(P)$(Q):PV:RBV.PROC") +#! Field("$(P)$(Q):UPDATE.LNK5",16777215,1,"$(P)$(Q):UPDATE.LNK5") +#! Link("$(P)$(Q):UPDATE.LNK5","$(P)$(Q):MAN:RBV_AI.PROC") +#! Record("$(P)$(Q):PID",1080,1258,0,1,"$(P)$(Q):PID") +#! Field("$(P)$(Q):PID.LNK1",16777215,1,"$(P)$(Q):PID.LNK1") +#! Link("$(P)$(Q):PID.LNK1","$(P)$(Q):P:RBV.PROC") +#! Field("$(P)$(Q):PID.LNK2",16777215,1,"$(P)$(Q):PID.LNK2") +#! Link("$(P)$(Q):PID.LNK2","$(P)$(Q):I:RBV.PROC") +#! Field("$(P)$(Q):PID.LNK3",16777215,1,"$(P)$(Q):PID.LNK3") +#! Link("$(P)$(Q):PID.LNK3","$(P)$(Q):D:RBV.PROC") +#! Record("$(P)$(Q):SP",1200,224,0,0,"$(P)$(Q):SP") +#! Field("$(P)$(Q):SP.FLNK",16777215,1,"$(P)$(Q):SP.FLNK") +#! Link("$(P)$(Q):SP.FLNK","$(P)$(Q):SP:RBV") +#! Field("$(P)$(Q):SP.SDIS",16777215,1,"$(P)$(Q):SP.SDIS") +#! Link("$(P)$(Q):SP.SDIS","$(P)$(Q):DISABLE.VAL") +#! Record("$(P)$(Q):SP:RBV",1480,240,0,0,"$(P)$(Q):SP:RBV") +#! Field("$(P)$(Q):SP:RBV.PROC",16777215,0,"$(P)$(Q):SP:RBV.PROC") +#! Field("$(P)$(Q):SP:RBV.SDIS",16777215,1,"$(P)$(Q):SP:RBV.SDIS") +#! Link("$(P)$(Q):SP:RBV.SDIS","$(P)$(Q):DISABLE.VAL") +#! Record("$(P)$(Q):RR",1180,564,0,0,"$(P)$(Q):RR") +#! Field("$(P)$(Q):RR.FLNK",16777215,1,"$(P)$(Q):RR.FLNK") +#! Link("$(P)$(Q):RR.FLNK","$(P)$(Q):RR:RBV") +#! Field("$(P)$(Q):RR.SDIS",16777215,1,"$(P)$(Q):RR.SDIS") +#! Link("$(P)$(Q):RR.SDIS","$(P)$(Q):DISABLE.VAL") +#! Record("$(P)$(Q):RR:RBV",1500,500,0,0,"$(P)$(Q):RR:RBV") +#! Field("$(P)$(Q):RR:RBV.PROC",16777215,0,"$(P)$(Q):RR:RBV.PROC") +#! Field("$(P)$(Q):RR:RBV.SDIS",16777215,1,"$(P)$(Q):RR:RBV.SDIS") +#! Link("$(P)$(Q):RR:RBV.SDIS","$(P)$(Q):DISABLE.VAL") +#! Record("$(P)$(Q):O",1180,824,0,0,"$(P)$(Q):O") +#! Field("$(P)$(Q):O.FLNK",16777215,1,"$(P)$(Q):O.FLNK") +#! Link("$(P)$(Q):O.FLNK","$(P)$(Q):O:RBV") +#! Field("$(P)$(Q):O.SDIS",16777215,1,"$(P)$(Q):O.SDIS") +#! Link("$(P)$(Q):O.SDIS","$(P)$(Q):DISABLE.VAL") +#! Record("$(P)$(Q):O:RBV",1480,740,0,0,"$(P)$(Q):O:RBV") +#! Field("$(P)$(Q):O:RBV.PROC",16777215,0,"$(P)$(Q):O:RBV.PROC") +#! Field("$(P)$(Q):O:RBV.SDIS",16777215,1,"$(P)$(Q):O:RBV.SDIS") +#! Link("$(P)$(Q):O:RBV.SDIS","$(P)$(Q):DISABLE.VAL") +#! Record("$(P)$(Q):PV:RBV",1460,980,0,0,"$(P)$(Q):PV:RBV") +#! Field("$(P)$(Q):PV:RBV.PROC",16777215,0,"$(P)$(Q):PV:RBV.PROC") +#! Field("$(P)$(Q):PV:RBV.SDIS",16777215,1,"$(P)$(Q):PV:RBV.SDIS") +#! Link("$(P)$(Q):PV:RBV.SDIS","$(P)$(Q):DISABLE.VAL") +#! Record("$(P)$(Q):P",1320,1231,0,0,"$(P)$(Q):P") +#! Field("$(P)$(Q):P.FLNK",16777215,1,"$(P)$(Q):P.FLNK") +#! Link("$(P)$(Q):P.FLNK","$(P)$(Q):P:RBV") +#! Field("$(P)$(Q):P.SDIS",16777215,1,"$(P)$(Q):P.SDIS") +#! Link("$(P)$(Q):P.SDIS","$(P)$(Q):DISABLE.VAL") +#! Record("$(P)$(Q):P:RBV",1580,1234,0,0,"$(P)$(Q):P:RBV") +#! Field("$(P)$(Q):P:RBV.PROC",16777215,0,"$(P)$(Q):P:RBV.PROC") +#! Field("$(P)$(Q):P:RBV.SDIS",16777215,1,"$(P)$(Q):P:RBV.SDIS") +#! Link("$(P)$(Q):P:RBV.SDIS","$(P)$(Q):DISABLE.VAL") +#! Record("$(P)$(Q):I",1300,1511,0,0,"$(P)$(Q):I") +#! Field("$(P)$(Q):I.FLNK",16777215,1,"$(P)$(Q):I.FLNK") +#! Link("$(P)$(Q):I.FLNK","$(P)$(Q):I:RBV") +#! Field("$(P)$(Q):I.SDIS",16777215,1,"$(P)$(Q):I.SDIS") +#! Link("$(P)$(Q):I.SDIS","$(P)$(Q):DISABLE.VAL") +#! Record("$(P)$(Q):I:RBV",1580,1514,0,0,"$(P)$(Q):I:RBV") +#! Field("$(P)$(Q):I:RBV.PROC",16777215,0,"$(P)$(Q):I:RBV.PROC") +#! Field("$(P)$(Q):I:RBV.SDIS",16777215,1,"$(P)$(Q):I:RBV.SDIS") +#! Link("$(P)$(Q):I:RBV.SDIS","$(P)$(Q):DISABLE.VAL") +#! Record("$(P)$(Q):D",1300,1731,0,0,"$(P)$(Q):D") +#! Field("$(P)$(Q):D.FLNK",16777215,1,"$(P)$(Q):D.FLNK") +#! Link("$(P)$(Q):D.FLNK","$(P)$(Q):D:RBV") +#! Field("$(P)$(Q):D.SDIS",16777215,1,"$(P)$(Q):D.SDIS") +#! Link("$(P)$(Q):D.SDIS","$(P)$(Q):DISABLE.VAL") +#! Record("$(P)$(Q):D:RBV",1560,1734,0,0,"$(P)$(Q):D:RBV") +#! Field("$(P)$(Q):D:RBV.PROC",16777215,0,"$(P)$(Q):D:RBV.PROC") +#! Field("$(P)$(Q):D:RBV.SDIS",16777215,1,"$(P)$(Q):D:RBV.SDIS") +#! Link("$(P)$(Q):D:RBV.SDIS","$(P)$(Q):DISABLE.VAL") +#! Record("$(P)$(Q):ERR",1480,2234,0,0,"$(P)$(Q):ERR") +#! Field("$(P)$(Q):ERR.SDIS",16777215,1,"$(P)$(Q):ERR.SDIS") +#! Link("$(P)$(Q):ERR.SDIS","$(P)$(Q):DISABLE.VAL") +#! Record("$(P)$(Q):DISABLE",1920,1040,0,1,"$(P)$(Q):DISABLE") +#! Field("$(P)$(Q):DISABLE.VAL",16777215,0,"$(P)$(Q):DISABLE.VAL") +#! Record("$(P)$(Q):MAN",1300,1971,0,1,"$(P)$(Q):MAN") +#! Field("$(P)$(Q):MAN.FLNK",16777215,1,"$(P)$(Q):MAN.FLNK") +#! Link("$(P)$(Q):MAN.FLNK","$(P)$(Q):MAN:RBV_AI") +#! Field("$(P)$(Q):MAN.SDIS",16777215,1,"$(P)$(Q):MAN.SDIS") +#! Link("$(P)$(Q):MAN.SDIS","$(P)$(Q):DISABLE.VAL") +#! Record("$(P)$(Q):MAN:RBV_AI",1560,1954,0,0,"$(P)$(Q):MAN:RBV_AI") +#! Field("$(P)$(Q):MAN:RBV_AI.SDIS",16777215,1,"$(P)$(Q):MAN:RBV_AI.SDIS") +#! Link("$(P)$(Q):MAN:RBV_AI.SDIS","$(P)$(Q):DISABLE.VAL") +#! Field("$(P)$(Q):MAN:RBV_AI.FLNK",16777215,1,"$(P)$(Q):MAN:RBV_AI.FLNK") +#! Link("$(P)$(Q):MAN:RBV_AI.FLNK","$(P)$(Q):MAN:RBV") +#! Field("$(P)$(Q):MAN:RBV_AI.VAL",16777215,1,"$(P)$(Q):MAN:RBV_AI.VAL") +#! Field("$(P)$(Q):MAN:RBV_AI.PROC",16777215,0,"$(P)$(Q):MAN:RBV_AI.PROC") +#! Record("$(P)$(Q):MAN:RBV",1920,1934,0,0,"$(P)$(Q):MAN:RBV") +#! Field("$(P)$(Q):MAN:RBV.INP",16777215,0,"$(P)$(Q):MAN:RBV.INP") +#! Link("$(P)$(Q):MAN:RBV.INP","$(P)$(Q):MAN:RBV_AI.VAL") +#! Record("$(P)$(Q):CONF:MODE",420,1660,0,1,"$(P)$(Q):CONF:MODE") +#! Field("$(P)$(Q):CONF:MODE.PROC",16777215,1,"$(P)$(Q):CONF:MODE.PROC") +#! Record("$(P)$(Q):ADDR",720,1370,0,1,"$(P)$(Q):ADDR") +#! Field("$(P)$(Q):ADDR.VAL",16777215,0,"$(P)$(Q):ADDR.VAL") +#! Field("$(P)$(Q):ADDR.FLNK",16777215,1,"$(P)$(Q):ADDR.FLNK") +#! Link("$(P)$(Q):ADDR.FLNK","$(P)$(Q):CONF:DLY") +#! Record("$(P)$(Q):ADDR:DEVICE",420,1436,0,0,"$(P)$(Q):ADDR:DEVICE") +#! Field("$(P)$(Q):ADDR:DEVICE.OUT",16777215,1,"$(P)$(Q):ADDR:DEVICE.OUT") +#! Link("$(P)$(Q):ADDR:DEVICE.OUT","$(P)$(Q):ADDR.VAL") +#! Record("$(P)$(Q):CONF:SETMODE",120,1154,0,1,"$(P)$(Q):CONF:SETMODE") +#! Field("$(P)$(Q):CONF:SETMODE.FLNK",16777215,1,"$(P)$(Q):CONF:SETMODE.FLNK") +#! Link("$(P)$(Q):CONF:SETMODE.FLNK","$(P)$(Q):CONF:ZEROADDR") +#! Record("$(P)$(Q):CONF:CLEARMODE",120,1394,0,1,"$(P)$(Q):CONF:CLEARMODE") +#! Field("$(P)$(Q):CONF:CLEARMODE.FLNK",16777215,1,"$(P)$(Q):CONF:CLEARMODE.FLNK") +#! Link("$(P)$(Q):CONF:CLEARMODE.FLNK","$(P)$(Q):ADDR:DEVICE") +#! Record("$(P)$(Q):CONF:ZEROADDR",420,1256,0,0,"$(P)$(Q):CONF:ZEROADDR") +#! Field("$(P)$(Q):CONF:ZEROADDR.OUT",16777215,1,"$(P)$(Q):CONF:ZEROADDR.OUT") +#! Link("$(P)$(Q):CONF:ZEROADDR.OUT","$(P)$(Q):ADDR.VAL") +#! Record("$(P)$(Q):ADDR:WR",40,908,0,1,"$(P)$(Q):ADDR:WR") +#! Record("$(P)$(Q):ADDR:RD",260,921,0,1,"$(P)$(Q):ADDR:RD") +#! Record("$(P)$(Q):ADDR:RESP",460,930,0,1,"$(P)$(Q):ADDR:RESP") +#! Record("$(P)$(Q):CONF:DECP",360,438,0,0,"$(P)$(Q):CONF:DECP") +#! Record("$(P)$(Q):CONF:SET:DECP",660,418,0,1,"$(P)$(Q):CONF:SET:DECP") +#! Record("$(P)$(Q):CONF:READ",20,556,0,1,"$(P)$(Q):CONF:READ") +#! Field("$(P)$(Q):CONF:READ.FLNK",16777215,1,"$(P)$(Q):CONF:READ.FLNK") +#! Link("$(P)$(Q):CONF:READ.FLNK","$(P)$(Q):CONF:DECP") +#! Field("$(P)$(Q):CONF:READ.LNK1",16777215,1,"$(P)$(Q):CONF:READ.LNK1") +#! Link("$(P)$(Q):CONF:READ.LNK1","$(P)$(Q):CONF:RREGU") +#! Record("$(P)$(Q):CONF:RREGU",360,658,0,0,"$(P)$(Q):CONF:RREGU") +#! Record("$(P)$(Q):CONF:SET:RREGU",660,658,0,1,"$(P)$(Q):CONF:SET:RREGU") +#! Record("$(P)$(Q):CONF:DLY",760,1674,0,1,"$(P)$(Q):CONF:DLY") +#! Field("$(P)$(Q):CONF:DLY.LNK1",16777215,0,"$(P)$(Q):CONF:DLY.LNK1") +#! Link("$(P)$(Q):CONF:DLY.LNK1","$(P)$(Q):CONF:MODE.PROC") diff -r 000000000000 -r bd6bb22c6533 kstmApp/Db/misc.db --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/kstmApp/Db/misc.db Fri Aug 14 11:30:43 2015 +0200 @@ -0,0 +1,9 @@ +record(calc, "$(P):$(Q):graphUpdate") +{ +field(DESC, "Just a counter to update graphs") +field(SCAN, "1 second") +field(INPA, "$(P):$(Q):graphUpdate.VAL NPP NMS") +field(INPB, "1") +field(CALC, "B?A+B:B") +field(EGU, "rels") +} diff -r 000000000000 -r bd6bb22c6533 kstmApp/Db/mtm.db --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/kstmApp/Db/mtm.db Fri Aug 14 11:30:43 2015 +0200 @@ -0,0 +1,36 @@ +record(ai, "$(P):$(Q):thickness") +{ +field(SCAN, "I/O Intr") +field(DTYP,"stream") +field(INP,"@mtm.proto read($(P):$(Q):sampleNr) $(PORT) -1") +field(EGU,"nm") +field(HOPR,"10") +field(LOPR,"-15") +field (FLNK,"$(P):$(Q):thicknessAVG") +} + +record(longin, "$(P):$(Q):sampleNr") +{ + field (FLNK,"$(P):$(Q):sampleNrMDN") +} + +record(compress,"$(P):$(Q):thicknessAVG") +{ + field(DESC, "thickness average") + field(INP,"$(P):$(Q):thickness.VAL NPP NMS") + field(ALG,"N to 1 Average") + field(NSAM,"1") + field(N,"10") + field(HOPR,"10") + field(LOPR,"-25") + field(EGU,"nm") +} + +record(compress,"$(P):$(Q):sampleNrMDN") +{ + field(DESC, "thickness average") + field(INP,"$(P):$(Q):sampleNr.VAL NPP NMS") + field(ALG,"N to 1 Median") + field(NSAM,"1") + field(N,"10") +} diff -r 000000000000 -r bd6bb22c6533 kstmApp/Db/mtm.proto --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/kstmApp/Db/mtm.proto Fri Aug 14 11:30:43 2015 +0200 @@ -0,0 +1,2 @@ +Terminator = CR NUL LF; +read { in "%(\$1)d,%f"; } diff -r 000000000000 -r bd6bb22c6533 kstmApp/Db/pgc2.db --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/kstmApp/Db/pgc2.db Fri Aug 14 11:30:43 2015 +0200 @@ -0,0 +1,42 @@ +record(ai, "$(P):$(Q):dumm") +{ +field(SCAN, "I/O Intr") +field(DTYP,"stream") +field(INP,"@pgc2.proto read($(P):$(Q)) $(PORT) -1") +field(EGU,"mBar") +field(HOPR,"1") +field(LOPR,"1E-11") +field(TPRO,"1") +} + +record(calc, "$(P):$(Q):pressure1") +{ +field(CALC,"A*10^B") +field(EGU,"mBar") +field(HOPR,"1") +field(LOPR,"1E-11") +} + +record(calc, "$(P):$(Q):pressure2") +{ +field(CALC,"A*10^B") +field(EGU,"mBar") +field(HOPR,"1") +field(LOPR,"1E-11") +} + +record(calc, "$(P):$(Q):pressure3") +{ +field(CALC,"A*10^B") +field(EGU,"mBar") +field(HOPR,"1") +field(LOPR,"1E-11") +} + +record(calc, "$(P):$(Q):pressure4") +{ +field(CALC,"A*10^B") +field(EGU,"mBar") +field(HOPR,"1") +field(LOPR,"1E-11") +} diff -r 000000000000 -r bd6bb22c6533 kstmApp/Db/pgc2.proto --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/kstmApp/Db/pgc2.proto Fri Aug 14 11:30:43 2015 +0200 @@ -0,0 +1,4 @@ +Terminator = CR NUL LF; +read { ExtraInput = Ignore; + in "::::%(\$1:pressure1.A)f%(\$1:pressure1.B)d %(\$1:pressure2.A)f%(\$1:pressure2.B)d %(\$1:pressure3.A)f%(\$1:pressure3.B)d %(\$1:pressure4.A)f%(\$1:pressure4.B)d %f"; +} diff -r 000000000000 -r bd6bb22c6533 kstmApp/Makefile --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/kstmApp/Makefile Fri Aug 14 11:30:43 2015 +0200 @@ -0,0 +1,8 @@ +TOP = .. +include $(TOP)/configure/CONFIG +DIRS := $(DIRS) $(filter-out $(DIRS), $(wildcard *src*)) +DIRS := $(DIRS) $(filter-out $(DIRS), $(wildcard *Src*)) +DIRS := $(DIRS) $(filter-out $(DIRS), $(wildcard *db*)) +DIRS := $(DIRS) $(filter-out $(DIRS), $(wildcard *Db*)) +include $(TOP)/configure/RULES_DIRS + diff -r 000000000000 -r bd6bb22c6533 kstmApp/src/Makefile --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/kstmApp/src/Makefile Fri Aug 14 11:30:43 2015 +0200 @@ -0,0 +1,55 @@ +TOP=../.. + +include $(TOP)/configure/CONFIG +#---------------------------------------- +# ADD MACRO DEFINITIONS AFTER THIS LINE +#============================= + +#============================= +# Build the IOC application + +PROD_IOC = kstm +# kstm.dbd will be created and installed +DBD += kstm.dbd + +# kstm.dbd will be made up from these files: +kstm_DBD += base.dbd + +# Include dbd files from all support applications: +#kstm_DBD += xxx.dbd +kstm_DBD += dbSubReadDHT.dbd +kstm_DBD += asyn.dbd +kstm_DBD += drvAsynIPPort.dbd +kstm_DBD += stream.dbd + +# Add all the support libraries needed by this IOC +#kstm_LIBS += xxx +kstm_LIBS += stream +kstm_LIBS += asyn + +# kstm_registerRecordDeviceDriver.cpp derives from kstm.dbd +kstm_SRCS += kstm_registerRecordDeviceDriver.cpp + +#Link locally-provided code into the IOC application +kstm_SRCS += common_dht_read.c +kstm_SRCS += pi_2_mmio.c +kstm_SRCS += pi_2_dht_read.c +kstm_SRCS += dbSubReadDHT.c +#kstm_SRCS += dbSubReadADC.c + +# Build the main IOC entry point on workstation OSs. +kstm_SRCS_DEFAULT += kstmMain.cpp +kstm_SRCS_vxWorks += -nil- + +# Add support from base/src/vxWorks if needed +#kstm_OBJS_vxWorks += $(EPICS_BASE_BIN)/vxComLibrary + +# Finally link to the EPICS Base libraries +kstm_LIBS += $(EPICS_BASE_IOC_LIBS) + +#=========================== + +include $(TOP)/configure/RULES +#---------------------------------------- +# ADD RULES AFTER THIS LINE + diff -r 000000000000 -r bd6bb22c6533 kstmApp/src/common_dht_read.c --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/kstmApp/src/common_dht_read.c Fri Aug 14 11:30:43 2015 +0200 @@ -0,0 +1,67 @@ +// Copyright (c) 2014 Adafruit Industries +// Author: Tony DiCola + +// 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. +#include +#include +#include +#include +#include + +#include "common_dht_read.h" + +void busy_wait_milliseconds(uint32_t millis) { + // Set delay time period. + struct timeval deltatime; + deltatime.tv_sec = millis / 1000; + deltatime.tv_usec = (millis % 1000) * 1000; + struct timeval walltime; + // Get current time and add delay to find end time. + gettimeofday(&walltime, NULL); + struct timeval endtime; + timeradd(&walltime, &deltatime, &endtime); + // Tight loop to waste time (and CPU) until enough time as elapsed. + while (timercmp(&walltime, &endtime, <)) { + gettimeofday(&walltime, NULL); + } +} + +void sleep_milliseconds(uint32_t millis) { + struct timespec sleep; + sleep.tv_sec = millis / 1000; + sleep.tv_nsec = (millis % 1000) * 1000000L; +// while (clock_nanosleep(CLOCK_MONOTONIC, 0, &sleep, &sleep) && errno == EINTR); + while (nanosleep(&sleep, &sleep) && errno == EINTR); +} + +void set_max_priority(void) { + struct sched_param sched; + memset(&sched, 0, sizeof(sched)); + // Use FIFO scheduler with highest priority for the lowest chance of the kernel context switching. + sched.sched_priority = sched_get_priority_max(SCHED_FIFO); + sched_setscheduler(0, SCHED_FIFO, &sched); +} + +void set_default_priority(void) { + struct sched_param sched; + memset(&sched, 0, sizeof(sched)); + // Go back to default scheduler with default 0 priority. + sched.sched_priority = 0; + sched_setscheduler(0, SCHED_OTHER, &sched); +} diff -r 000000000000 -r bd6bb22c6533 kstmApp/src/common_dht_read.h --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/kstmApp/src/common_dht_read.h Fri Aug 14 11:30:43 2015 +0200 @@ -0,0 +1,51 @@ +// Copyright (c) 2014 Adafruit Industries +// Author: Tony DiCola + +// 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. +#ifndef COMMON_DHT_READ_H +#define COMMON_DHT_READ_H + +#include + +// Define errors and return values. +#define DHT_ERROR_TIMEOUT -1 +#define DHT_ERROR_CHECKSUM -2 +#define DHT_ERROR_ARGUMENT -3 +#define DHT_ERROR_GPIO -4 +#define DHT_SUCCESS 0 + +// Define sensor types. +#define DHT11 11 +#define DHT22 22 +#define AM2302 22 + +// Busy wait delay for most accurate timing, but high CPU usage. +// Only use this for short periods of time (a few hundred milliseconds at most)! +void busy_wait_milliseconds(uint32_t millis); + +// General delay that sleeps so CPU usage is low, but accuracy is potentially bad. +void sleep_milliseconds(uint32_t millis); + +// Increase scheduling priority and algorithm to try to get 'real time' results. +void set_max_priority(void); + +// Drop scheduling priority back to normal/default. +void set_default_priority(void); + +#endif diff -r 000000000000 -r bd6bb22c6533 kstmApp/src/dbSubReadADC.c --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/kstmApp/src/dbSubReadADC.c Fri Aug 14 11:30:43 2015 +0200 @@ -0,0 +1,66 @@ +#include +#include + +#include +#include +#include +#include +#include + +#include "pi_2_dht_read.h" + +int dbSubReadDHTDebug; + +static long dbSubReadDHTInit(subRecord *precord) +{ + if (dbSubReadDHTDebug) + printf("Record %s called dbSubReadDHTInit(%p)\n", + precord->name, (void*) precord); + return 0; +} + +static long dbSubReadDHTProcess(subRecord *precord) +{ +char cmd[256]; +char buf[256]; +double dumm; + + if (dbSubReadDHTDebug) + printf("Record %s called dbSubReadDHTProcess(%p)\n", + precord->name, (void*) precord); + + + pi_2_dht_read(int type, int pin, float* humidity, float* temperature) + + + precord->val = dumm; + printf(" val = %lf\n", precord->val ); + + return 0; +} + +static long myAsubInit(aSubRecord *precord) +{ + if (mySubDebug) + printf("Record %s called myAsubInit(%p)\n", + precord->name, (void*) precord); + return 0; +} + +static long myAsubProcess(aSubRecord *precord) +{ + if (mySubDebug) + printf("Record %s called myAsubProcess(%p)\n", + precord->name, (void*) precord); + return 0; +} + +/* Register these symbols for use by IOC code: */ + +epicsExportAddress(int, mySubDebug); +epicsRegisterFunction(mySubInit); +epicsRegisterFunction(mySubProcess); + + + + diff -r 000000000000 -r bd6bb22c6533 kstmApp/src/dbSubReadDHT.c --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/kstmApp/src/dbSubReadDHT.c Fri Aug 14 11:30:43 2015 +0200 @@ -0,0 +1,46 @@ +#include +#include + +#include +#include +#include +#include +#include + +#include "pi_2_dht_read.h" + +int dbSubReadDHTDebug = 1; + +static long dbSubReadDHTInit(subRecord *precord) +{ + if (dbSubReadDHTDebug) + printf("Record %s called dbSubReadDHTInit(%p)\n", + precord->name, (void*) precord); + return 0; +} + +static long dbSubReadDHTProcess(subRecord *precord) +{ +float humidity, temperature; +int type = 22; +int ret; +int pin = 7; + + if (dbSubReadDHTDebug) + printf("Record %s called dbSubRreadHTProcess(%p)\n", + precord->name, (void*) precord); + + ret = pi_2_dht_read(type, pin, &humidity, &temperature); + printf(" ret : %d, humidity = %f, temperature = %f\n", ret, humidity, temperature); + precord->val = (double)temperature; + printf(" val = %lf\n", precord->val ); + + return 0; +} + +/* Register these symbols for use by IOC code: */ + +epicsExportAddress(int, dbSubReadDHTDebug); +epicsRegisterFunction(dbSubReadDHTInit); +epicsRegisterFunction(dbSubReadDHTProcess); + diff -r 000000000000 -r bd6bb22c6533 kstmApp/src/dbSubReadDHT.dbd --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/kstmApp/src/dbSubReadDHT.dbd Fri Aug 14 11:30:43 2015 +0200 @@ -0,0 +1,3 @@ +variable(dbSubReadDHTDebug) +function(dbSubReadDHTInit) +function(dbSubReadDHTProcess) diff -r 000000000000 -r bd6bb22c6533 kstmApp/src/kstmMain.cpp --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/kstmApp/src/kstmMain.cpp Fri Aug 14 11:30:43 2015 +0200 @@ -0,0 +1,23 @@ +/* kstmMain.cpp */ +/* Author: Marty Kraimer Date: 17MAR2000 */ + +#include +#include +#include +#include +#include + +#include "epicsExit.h" +#include "epicsThread.h" +#include "iocsh.h" + +int main(int argc,char *argv[]) +{ + if(argc>=2) { + iocsh(argv[1]); + epicsThreadSleep(.2); + } + iocsh(NULL); + epicsExit(0); + return(0); +} diff -r 000000000000 -r bd6bb22c6533 kstmApp/src/pi_2_dht_read.c --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/kstmApp/src/pi_2_dht_read.c Fri Aug 14 11:30:43 2015 +0200 @@ -0,0 +1,162 @@ +// Copyright (c) 2014 Adafruit Industries +// Author: Tony DiCola + +// 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. +#include +#include + +#include "pi_2_dht_read.h" +#include "pi_2_mmio.h" + +// This is the only processor specific magic value, the maximum amount of time to +// spin in a loop before bailing out and considering the read a timeout. This should +// be a high value, but if you're running on a much faster platform than a Raspberry +// Pi or Beaglebone Black then it might need to be increased. +#define DHT_MAXCOUNT 32000 + +// Number of bit pulses to expect from the DHT. Note that this is 41 because +// the first pulse is a constant 50 microsecond pulse, with 40 pulses to represent +// the data afterwards. +#define DHT_PULSES 41 + +int pi_2_dht_read(int type, int pin, float* humidity, float* temperature) { + // Validate humidity and temperature arguments and set them to zero. + if (humidity == NULL || temperature == NULL) { + return DHT_ERROR_ARGUMENT; + } + *temperature = 0.0f; + *humidity = 0.0f; + + // Initialize GPIO library. + if (pi_2_mmio_init() < 0) { + return DHT_ERROR_GPIO; + } + + // Store the count that each DHT bit pulse is low and high. + // Make sure array is initialized to start at zero. + int pulseCounts[DHT_PULSES*2] = {0}; + + // Set pin to output. + pi_2_mmio_set_output(pin); + + // Bump up process priority and change scheduler to try to try to make process more 'real time'. + set_max_priority(); + + // Set pin high for ~500 milliseconds. + pi_2_mmio_set_high(pin); + sleep_milliseconds(500); + + // The next calls are timing critical and care should be taken + // to ensure no unnecssary work is done below. + + // Set pin low for ~20 milliseconds. + pi_2_mmio_set_low(pin); + busy_wait_milliseconds(20); + + // Set pin at input. + pi_2_mmio_set_input(pin); + // Need a very short delay before reading pins or else value is sometimes still low. +volatile int i; + for (i = 0; i < 50; ++i) { + } + + // Wait for DHT to pull pin low. + uint32_t count = 0; + while (pi_2_mmio_input(pin)) { + if (++count >= DHT_MAXCOUNT) { + // Timeout waiting for response. + set_default_priority(); + return DHT_ERROR_TIMEOUT; + } + } + + // Record pulse widths for the expected result bits. + int j; + for ( j=0; j < DHT_PULSES*2; j+=2) { + // Count how long pin is low and store in pulseCounts[i] + while (!pi_2_mmio_input(pin)) { + if (++pulseCounts[i] >= DHT_MAXCOUNT) { + // Timeout waiting for response. + set_default_priority(); + return DHT_ERROR_TIMEOUT; + } + } + // Count how long pin is high and store in pulseCounts[i+1] + while (pi_2_mmio_input(pin)) { + if (++pulseCounts[i+1] >= DHT_MAXCOUNT) { + // Timeout waiting for response. + set_default_priority(); + return DHT_ERROR_TIMEOUT; + } + } + } + + // Done with timing critical code, now interpret the results. + + // Drop back to normal priority. + set_default_priority(); + + // Compute the average low pulse width to use as a 50 microsecond reference threshold. + // Ignore the first two readings because they are a constant 80 microsecond pulse. + uint32_t threshold = 0; + int k; + for (k=2; i < DHT_PULSES*2; k+=2) { + threshold += pulseCounts[k]; + } + threshold /= DHT_PULSES-1; + + // Interpret each high pulse as a 0 or 1 by comparing it to the 50us reference. + // If the count is less than 50us it must be a ~28us 0 pulse, and if it's higher + // then it must be a ~70us 1 pulse. + uint8_t data[5] = {0}; + int l; + for ( l=3; l < DHT_PULSES*2; l+=2) { + int index = (l-3)/16; + data[index] <<= 1; + if (pulseCounts[l] >= threshold) { + // One bit for long pulse. + data[index] |= 1; + } + // Else zero bit for short pulse. + } + + // Useful debug info: + //printf("Data: 0x%x 0x%x 0x%x 0x%x 0x%x\n", data[0], data[1], data[2], data[3], data[4]); + + // Verify checksum of received data. + if (data[4] == ((data[0] + data[1] + data[2] + data[3]) & 0xFF)) { + if (type == DHT11) { + // Get humidity and temp for DHT11 sensor. + *humidity = (float)data[0]; + *temperature = (float)data[2]; + } + else if (type == DHT22) { + // Calculate humidity and temp for DHT22 sensor. + *humidity = (data[0] * 256 + data[1]) / 10.0f; + *temperature = ((data[2] & 0x7F) * 256 + data[3]) / 10.0f; + if (data[2] & 0x80) { + *temperature *= -1.0f; + } + } + return DHT_SUCCESS; + } + else { + return DHT_ERROR_CHECKSUM; + } +} diff -r 000000000000 -r bd6bb22c6533 kstmApp/src/pi_2_dht_read.h --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/kstmApp/src/pi_2_dht_read.h Fri Aug 14 11:30:43 2015 +0200 @@ -0,0 +1,32 @@ +// Copyright (c) 2014 Adafruit Industries +// Author: Tony DiCola + +// 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. +#ifndef PI_2_DHT_READ_H +#define PI_2_DHT_READ_H + +#include "../common_dht_read.h" + +// Read DHT sensor connected to GPIO pin (using BCM numbering). Humidity and temperature will be +// returned in the provided parameters. If a successfull reading could be made a value of 0 +// (DHT_SUCCESS) will be returned. If there was an error reading the sensor a negative value will +// be returned. Some errors can be ignored and retried, specifically DHT_ERROR_TIMEOUT or DHT_ERROR_CHECKSUM. +int pi_2_dht_read(int sensor, int pin, float* humidity, float* temperature); + +#endif diff -r 000000000000 -r bd6bb22c6533 kstmApp/src/pi_2_mmio.c --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/kstmApp/src/pi_2_mmio.c Fri Aug 14 11:30:43 2015 +0200 @@ -0,0 +1,71 @@ +// Copyright (c) 2014 Adafruit Industries +// Author: Tony DiCola +// Based on code from Gert van Loo & Dom: http://elinux.org/RPi_Low-level_peripherals#GPIO_Code_examples + +// 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. +#include +#include +#include +#include +#include +#include +#include +#include + +#include "pi_2_mmio.h" + +#define GPIO_BASE_OFFSET 0x200000 +#define GPIO_LENGTH 4096 + +volatile uint32_t* pi_2_mmio_gpio = NULL; + +int pi_2_mmio_init(void) { + if (pi_2_mmio_gpio == NULL) { + // Check for GPIO and peripheral addresses from device tree. + // Adapted from code in the RPi.GPIO library at: + // http://sourceforge.net/p/raspberry-gpio-python/ + FILE *fp = fopen("/proc/device-tree/soc/ranges", "rb"); + if (fp == NULL) { + return MMIO_ERROR_OFFSET; + } + fseek(fp, 4, SEEK_SET); + unsigned char buf[4]; + if (fread(buf, 1, sizeof(buf), fp) != sizeof(buf)) { + return MMIO_ERROR_OFFSET; + } + uint32_t peri_base = buf[0] << 24 | buf[1] << 16 | buf[2] << 8 | buf[3] << 0; + uint32_t gpio_base = peri_base + GPIO_BASE_OFFSET; + fclose(fp); + + int fd = open("/dev/mem", O_RDWR | O_SYNC); + if (fd == -1) { + // Error opening /dev/mem. Probably not running as root. + return MMIO_ERROR_DEVMEM; + } + // Map GPIO memory to location in process space. + pi_2_mmio_gpio = (uint32_t*)mmap(NULL, GPIO_LENGTH, PROT_READ | PROT_WRITE, MAP_SHARED, fd, gpio_base); + close(fd); + if (pi_2_mmio_gpio == MAP_FAILED) { + // Don't save the result if the memory mapping failed. + pi_2_mmio_gpio = NULL; + return MMIO_ERROR_MMAP; + } + } + return MMIO_SUCCESS; +} diff -r 000000000000 -r bd6bb22c6533 kstmApp/src/pi_2_mmio.h --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/kstmApp/src/pi_2_mmio.h Fri Aug 14 11:30:43 2015 +0200 @@ -0,0 +1,62 @@ +// Copyright (c) 2014 Adafruit Industries +// Author: Tony DiCola +// Based on code from Gert van Loo & Dom: http://elinux.org/RPi_Low-level_peripherals#GPIO_Code_examples + +// 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. + +// Simple fast memory-mapped GPIO library for the Raspberry Pi. +#ifndef PI_2_MMIO_H +#define PI_2_MMIO_H + +#include + +#define MMIO_SUCCESS 0 +#define MMIO_ERROR_DEVMEM -1 +#define MMIO_ERROR_MMAP -2 +#define MMIO_ERROR_OFFSET -3 + +volatile uint32_t* pi_2_mmio_gpio; + +int pi_2_mmio_init(void); + +static inline void pi_2_mmio_set_input(const int gpio_number) { + // Set GPIO register to 000 for specified GPIO number. + *(pi_2_mmio_gpio+((gpio_number)/10)) &= ~(7<<(((gpio_number)%10)*3)); +} + +static inline void pi_2_mmio_set_output(const int gpio_number) { + // First set to 000 using input function. + pi_2_mmio_set_input(gpio_number); + // Next set bit 0 to 1 to set output. + *(pi_2_mmio_gpio+((gpio_number)/10)) |= (1<<(((gpio_number)%10)*3)); +} + +static inline void pi_2_mmio_set_high(const int gpio_number) { + *(pi_2_mmio_gpio+7) = 1 << gpio_number; +} + +static inline void pi_2_mmio_set_low(const int gpio_number) { + *(pi_2_mmio_gpio+10) = 1 << gpio_number; +} + +static inline uint32_t pi_2_mmio_input(const int gpio_number) { + return *(pi_2_mmio_gpio+13) & (1 << gpio_number); +} + +#endif