From 0053eaed054d2b861bd3c2336bd2a78e827644b3 Mon Sep 17 00:00:00 2001 From: jjl77 Date: Fri, 7 Feb 2020 14:25:32 -0800 Subject: [PATCH] Added status PVs and a generic modbus record --- ek9000App/Db/EK9000_Status.db | 158 ++++++++++++++++++++++++++ ek9000App/Db/Makefile | 1 + ek9000App/Db/coe_param_test.db | 7 ++ ek9000App/src/devEK9000.cpp | 195 ++++++++++++++++++++++++++++++++- ek9000App/src/devEK9000.dbd | 5 +- ek9000App/src/devEK9000.h | 2 +- iocBoot/iocEK9KTest/st.cmd | 2 +- 7 files changed, 361 insertions(+), 9 deletions(-) create mode 100644 ek9000App/Db/EK9000_Status.db diff --git a/ek9000App/Db/EK9000_Status.db b/ek9000App/Db/EK9000_Status.db new file mode 100644 index 0000000..c5f0a7c --- /dev/null +++ b/ek9000App/Db/EK9000_Status.db @@ -0,0 +1,158 @@ +# +# Various status PVs for the EK9k +# + +record(longin,"$(EK9K):AnalogOutputSize") +{ + field(EGU, "bytes") + field(INP, "@$(EK9K),0x1010") + field(DTYP, "EK9000ParamRO") +} + +record(longin,"$(EK9K):AnalogInputSize") +{ + field(EGU, "bytes") + field(INP, "@$(EK9K),0x1011") + field(DTYP, "EK9000ParamRO") +} + +record(longin,"$(EK9K):DigitalInputSize") +{ + field(EGU, "bits") + field(INP, "@$(EK9K),0x1012") + field(DTYP, "EK9000ParamRO") +} + +record(longin,"$(EK9K):DigitalOutputSize") +{ + field(EGU, "bits") + field(INP, "@$(EK9K),0x1013") + field(DTYP, "EK9000ParamRO") +} + +record(longin,"$(EK9K):WatchdogExpTime") +{ + field(SCAN, "10 second") + field(EGU, "ms") + field(INP, "@$(EK9K),0x1020") + field(DTYP, "EK9000ParamRO") +} + +record(longin,"$(EK9K):FallbacksTriggered") +{ + field(SCAN, "10 second") + field(INP, "@$(EK9K),0x1021") + field(DTYP, "EK9000ParamRO") +} + +record(longin,"$(EK9K):TCPConnections") +{ + field(SCAN, "10 second") + field(INP, "@$(EK9K),0x1022") + field(DTYP, "EK9000ParamRO") +} + +record(longin,"$(EK9K):HardwareVersion") +{ + field(PINI,"YES") + field(INP,"@$(EK9K),0x1030") + field(DTYP, "EK9000ParamRO") +} + +record(longin,"$(EK9K):SoftwareVersionMain") +{ + field(PINI,"YES") + field(INP,"@$(EK9K),0x1031") + field(DTYP, "EK9000ParamRO") +} + +record(longin,"$(EK9K):SoftwareVersionSub") +{ + field(PINI,"YES") + field(INP,"@$(EK9K),0x1032") + field(DTYP, "EK9000ParamRO") +} + +record(longin,"$(EK9K):SoftwareVersionBeta") +{ + field(PINI,"YES") + field(INP,"@$(EK9K),0x1033") + field(DTYP, "EK9000ParamRO") +} + +record(longin,"$(EK9K):SerialNumber") +{ + field(PINI,"YES") + field(INP,"@$(EK9K),0x1034") + field(DTYP, "EK9000ParamRO") +} + +record(longin,"$(EK9K):DayOfMfg") +{ + field(PINI,"YES") + field(INP,"@$(EK9K),0x1035") + field(DTYP, "EK9000ParamRO") +} + +record(longin,"$(EK9K):MonthOfMfg") +{ + field(PINI,"YES") + field(INP,"@$(EK9K),0x1036") + field(DTYP, "EK9000ParamRO") +} + +record(longin,"$(EK9K):YearOfMfg") +{ + field(PINI,"YES") + field(INP,"@$(EK9K),0x1037") + field(DTYP, "EK9000ParamRO") +} + +record(longin,"$(EK9K):EbusStatus") +{ + field(INP,"@$(EK9K),0x1040") + field(SCAN,"1 second") + field(LOLO, 0) + field(LOW, 0) + field(LSV, "MAJOR") + field(LLSV, "MAJOR") + field(DTYP, "EK9000ParamRO") +} + +record(longout,"$(EK9K):WatchdogTime") +{ + field(OUT,"@$(EK9K),0x1120") + field(DTYP, "EK9000ParamRW") + field(VAL, 1000) + field(PINI, "YES") +} + +record(longout,"$(EK9K):WatchdogType") +{ + field(OUT,"@$(EK9K),0x1122") + field(DTYP, "EK9000ParamRW") + field(VAL, 1) + field(PINI, "YES") +} + +record(longout,"$(EK9K):FallbackMode") +{ + field(OUT,"@$(EK9K),0x1123") + field(DTYP, "EK9000ParamRW") + field(VAL, 0) + field(PINI, "YES") +} + +record(longout,"$(EK9K):WriteLock") +{ + field(OUT,"@$(EK9K),0x1124") + field(DTYP, "EK9000ParamRW") + field(VAL, 1) + field(PINI, "YES") +} + +record(longout,"$(EK9K):EBusControl") +{ + field(OUT,"@$(EK9K),0x1140") + field(DTYP, "EK9000ParamRW") +} \ No newline at end of file diff --git a/ek9000App/Db/Makefile b/ek9000App/Db/Makefile index 9675458..47c60d0 100644 --- a/ek9000App/Db/Makefile +++ b/ek9000App/Db/Makefile @@ -7,6 +7,7 @@ DB += EL1001.template EL1034.template EL1134.template EL1804.template EL2008 DB += EL1001.substitutions EL1088.substitutions EL1382.substitutions EL2002.substitutions EL3002.substitutions EL3044.substitutions EL3101.substitutions EL3142.substitutions EL4002.substitutions EL4028.substitutions EL1002.substitutions EL1094.substitutions EL1702.substitutions EL2004.substitutions EL3004.substitutions EL3048.substitutions EL3102.substitutions EL3144.substitutions EL4004.substitutions EL4031.substitutions EL1004.substitutions EL1098.substitutions EL1712.substitutions EL2008.substitutions EL3008.substitutions EL3051.substitutions EL3104.substitutions EL3151.substitutions EL4008.substitutions EL4032.substitutions EL1008.substitutions EL1104.substitutions EL1722.substitutions EL2022.substitutions EL3012.substitutions EL3052.substitutions EL3111.substitutions EL3152.substitutions EL4011.substitutions EL4034.substitutions EL1012.substitutions EL1114.substitutions EL1804.substitutions EL2024.substitutions EL3014.substitutions EL3054.substitutions EL3112.substitutions EL3154.substitutions EL4012.substitutions EL4038.substitutions EL1014.substitutions EL1124.substitutions EL1808.substitutions EL2042.substitutions EL3021.substitutions EL3058.substitutions EL3114.substitutions EL3161.substitutions EL4014.substitutions EL1018.substitutions EL1134.substitutions EL1809.substitutions EL2084.substitutions EL3022.substitutions EL3061.substitutions EL3121.substitutions EL3162.substitutions EL4018.substitutions EL1024.substitutions EL1144.substitutions EL1814.substitutions EL2088.substitutions EL3024.substitutions EL3062.substitutions EL3122.substitutions EL3164.substitutions EL4021.substitutions EL1034.substitutions EL1184.substitutions EL1819.substitutions EL2124.substitutions EL3041.substitutions EL3064.substitutions EL3124.substitutions EL3174.substitutions EL4022.substitutions EL1084.substitutions EL1202.substitutions EL2001.substitutions EL3001.substitutions EL3042.substitutions EL3068.substitutions EL3141.substitutions EL4001.substitutions EL4024.substitutions DB+=coe_param_test.db +DB+=EK9000_Status.db include $(TOP)/configure/RULES #---------------------------------------- diff --git a/ek9000App/Db/coe_param_test.db b/ek9000App/Db/coe_param_test.db index 020785d..b9014a0 100644 --- a/ek9000App/Db/coe_param_test.db +++ b/ek9000App/Db/coe_param_test.db @@ -11,4 +11,11 @@ record(int64out,"TestTerm4:UserCalibrationGain") field(OUT, "@EK9K1,4,0x8000,0x18,int16") field(DTYP, "CoEParamInt16RW") #field(SCAN, "1 second") +} + +record(longin,"EK9K1:AnalogInputSize") +{ + field(INP, "@EK9K1,0x1011") + field(DTYP,"EK9000ParamRO") + field(SCAN,"1 second") } \ No newline at end of file diff --git a/ek9000App/src/devEK9000.cpp b/ek9000App/src/devEK9000.cpp index 456269f..04bd4a6 100644 --- a/ek9000App/src/devEK9000.cpp +++ b/ek9000App/src/devEK9000.cpp @@ -545,7 +545,7 @@ int CEK9000Device::CoEVerifyConnection(uint16_t termid) /* 1 for write and 0 for read */ /* LENGTH IS IN REGISTERS */ -int CEK9000Device::doCoEIO(int rw, uint16_t term, uint16_t index, uint16_t len, uint16_t *data, uint16_t subindex, uint32_t reallen) +int CEK9000Device::doCoEIO(int rw, uint16_t term, uint16_t index, uint16_t len, uint16_t *data, uint16_t subindex, uint16_t reallen) { /* write */ if (rw) @@ -904,7 +904,7 @@ struct SMsg_t void CEK9000Device::QueueCallback(void(*callback)(void*), void* rec) { - SMsg_t* msg = new SMsg_t; +// SMsg_t* msg = new SMsg_t; // this->queue->trySend(&msg, sizeof(callback)); } @@ -1547,12 +1547,20 @@ struct ek9k_coe_param_t } type; }; +struct ek9k_param_t +{ + CEK9000Device* ek9k; + int reg; + int len; +}; + struct ek9k_conf_pvt_t { ek9k_coe_param_t param; }; int CoE_ParseString(const char* str, ek9k_coe_param_t* param); +int EK9K_ParseString(const char* str, ek9k_param_t* param); //======================================================// @@ -1660,6 +1668,7 @@ static long ek9k_confli_read_record(void* prec) } dpvt->param.ek9k->Unlock(); + return 0; } //-----------------------------------------------------------------// @@ -1717,8 +1726,7 @@ static long ek9k_conflo_write_record(void* prec) { int64outRecord* precord = static_cast(prec); ek9k_conf_pvt_t* dpvt = static_cast(precord->dpvt); - uint32_t val = precord->val; - int ret = 0; + int ret; if(!dpvt || !dpvt->param.ek9k) return -1; @@ -1765,16 +1773,17 @@ static long ek9k_conflo_write_record(void* prec) } dpvt->param.ek9k->Unlock(); + return 0; } //-----------------------------------------------------------------// int CoE_ParseString(const char* str, ek9k_coe_param_t* param) { - size_t strl = strlen(str); + int strl = strlen(str); CEK9000Device* pcoupler = 0; CTerminal* pterm = 0; - int index, subindex, termid; + int termid; int i, bufcnt = 0; char buf[512]; char* buffers[5]; @@ -1837,5 +1846,179 @@ int CoE_ParseString(const char* str, ek9k_coe_param_t* param) param->subindex = strtol(buffers[3], 0, 16); if(errno != 0) return 1; + return 0; +} + +//-----------------------------------------------------------------// +// EK9K RO configuration/status +static long ek9k_ro_init(int pass); +static long ek9k_ro_init_record(void* prec); +static long ek9k_ro_read_record(void* pprec); + +struct +{ + long number; + DEVSUPFUN dev_report; + DEVSUPFUN init; + DEVSUPFUN init_record; /*returns: (-1,0)=>(failure,success)*/ + DEVSUPFUN get_ioint_info; + DEVSUPFUN write_longout;/*(-1,0)=>(failure,success*/ +} +devEK9000ConfigRO = +{ + 5, + NULL, + (DEVSUPFUN)ek9k_ro_init, + ek9k_ro_init_record, + NULL, + ek9k_ro_read_record, +}; + +epicsExportAddress(dset, devEK9000ConfigRO); + +static long ek9k_ro_init(int pass) +{ + return 0; +} + +static long ek9k_ro_init_record(void* prec) +{ + longinRecord* precord = static_cast(prec); + precord->dpvt = calloc(1, sizeof(ek9k_param_t)); + ek9k_param_t* dpvt = static_cast(precord->dpvt); + ek9k_param_t param; + + /* parse the string to obtain various info */ + if(EK9K_ParseString(precord->inp.value.instio.string, ¶m)) + { + Error("Maloformed modbus string in record %s\n", precord->name); + return 1; + } + *dpvt = param; + return 0; +} + +static long ek9k_ro_read_record(void* prec) +{ + longinRecord* precord = static_cast(prec); + ek9k_param_t* dpvt = static_cast(precord->dpvt); + CEK9000Device* dev = dpvt->ek9k; + uint16_t buf; + + if(!dev) return -1; + + dev->Lock(); + + dev->doEK9000IO(0, dpvt->reg, 1, &buf); + precord->val = buf; + + dev->Unlock(); + return 0; +} + +//-----------------------------------------------------------------// + +//-----------------------------------------------------------------// +// EK9K RW configuration +static long ek9k_rw_init(int pass); +static long ek9k_rw_init_record(void* prec); +static long ek9k_rw_write_record(void* pprec); + +struct +{ + long number; + DEVSUPFUN dev_report; + DEVSUPFUN init; + DEVSUPFUN init_record; /*returns: (-1,0)=>(failure,success)*/ + DEVSUPFUN get_ioint_info; + DEVSUPFUN write_longout;/*(-1,0)=>(failure,success*/ +} +devEK9000ConfigRW = +{ + 5, + NULL, + (DEVSUPFUN)ek9k_rw_init, + ek9k_rw_init_record, + NULL, + ek9k_rw_write_record, +}; + +epicsExportAddress(dset, devEK9000ConfigRW); + +static long ek9k_rw_init(int pass) +{ + return 0; +} + +static long ek9k_rw_init_record(void* prec) +{ + longoutRecord* precord = static_cast(prec); + precord->dpvt = calloc(1, sizeof(ek9k_param_t)); + ek9k_param_t* dpvt = static_cast(precord->dpvt); + ek9k_param_t param; + + /* parse the string to obtain various info */ + if(EK9K_ParseString(precord->out.value.instio.string, ¶m)) + { + Error("Maloformed modbus string in record %s\n", precord->name); + return 1; + } + *dpvt = param; + return 0; +} + +static long ek9k_rw_write_record(void* prec) +{ + longinRecord* precord = static_cast(prec); + ek9k_param_t* dpvt = static_cast(precord->dpvt); + CEK9000Device* dev = dpvt->ek9k; + uint16_t buf = precord->val; + + if(!dev) return -1; + + dev->Lock(); + + dev->doEK9000IO(1, dpvt->reg, 1, &buf); + + dev->Unlock(); + return 0; +} + +//-----------------------------------------------------------------// + +/* The string will be in the format EK9K,0x1002 */ +int EK9K_ParseString(const char* str, ek9k_param_t* param) +{ + char buf[512]; + const char *pek9k = 0, *preg = 0; + + memset(buf, 0, 512); + strncpy(buf, str, 512); + + if(!buf[0]) return 1; + pek9k = buf; + + /* Read until we hit a comma, then replace */ + int strl = strlen(buf); + for(int i = 0; i < strl; i++) + { + if(buf[i] == ',') + { + buf[i] = '\0'; + preg = &buf[i+1]; + break; + } + } + if(!preg) return 1; + + /* Find the coupler */ + param->ek9k = g_pDeviceMgr->FindDevice(pek9k); + param->reg = strtol(preg, 0, 16); + + if(!param->ek9k) + { + printf("Unable to find the specified coupler\n"); + return 1; + } return 0; } \ No newline at end of file diff --git a/ek9000App/src/devEK9000.dbd b/ek9000App/src/devEK9000.dbd index a28db7d..e27d150 100644 --- a/ek9000App/src/devEK9000.dbd +++ b/ek9000App/src/devEK9000.dbd @@ -28,4 +28,7 @@ device(int64out,INST_IO,devEK9KCoERW,"CoEParamInt64RW") device(int64out,INST_IO,devEK9KCoERW,"CoEParamInt32RW") device(int64out,INST_IO,devEK9KCoERW,"CoEParamInt16RW") device(int64out,INST_IO,devEK9KCoERW,"CoEParamInt8RW") -device(int64out,INST_IO,devEK9KCoERW,"CoEParamBoolRW") \ No newline at end of file +device(int64out,INST_IO,devEK9KCoERW,"CoEParamBoolRW") + +device(longin,INST_IO,devEK9000ConfigRO,"EK9000ParamRO") +device(longout,INST_IO,devEK9000ConfigRW,"EK9000ParamRW") \ No newline at end of file diff --git a/ek9000App/src/devEK9000.h b/ek9000App/src/devEK9000.h index a825a40..9a1c2a3 100644 --- a/ek9000App/src/devEK9000.h +++ b/ek9000App/src/devEK9000.h @@ -438,7 +438,7 @@ class CEK9000Device inline int doEK9000IO(int rw, uint16_t addr, uint16_t len, uint16_t *data); /* Do CoE I/O */ - inline int doCoEIO(int rw, uint16_t term, uint16_t index, uint16_t len, uint16_t *data, uint16_t subindex, uint32_t reallen = 0); + inline int doCoEIO(int rw, uint16_t term, uint16_t index, uint16_t len, uint16_t *data, uint16_t subindex, uint16_t reallen = 0); /* same as doEK9000IO except this only operates on the ek9000 itself, term is not used */ inline int doCouplerIO(int rw, uint16_t term, uint16_t len, uint16_t addr, uint16_t *data, uint16_t subindex = 0); diff --git a/iocBoot/iocEK9KTest/st.cmd b/iocBoot/iocEK9KTest/st.cmd index 604e415..298d6a6 100755 --- a/iocBoot/iocEK9KTest/st.cmd +++ b/iocBoot/iocEK9KTest/st.cmd @@ -30,6 +30,6 @@ cd "${TOP}/src/ek9000/iocBoot/${IOC}" dbLoadTemplate("example1.substitutions") dbLoadRecords("db/coe_param_test.db") - +dbLoadRecords("db/EK9000_Status.db","EK9K=EK9K1") iocInit