diff --git a/documentation/RELEASE_NOTES.md b/documentation/RELEASE_NOTES.md index b13db1787..ff3896a4e 100644 --- a/documentation/RELEASE_NOTES.md +++ b/documentation/RELEASE_NOTES.md @@ -16,6 +16,12 @@ should also be read to understand what has changed since earlier releases. +### Simulation Mode RAW Support for Output Record Types + +SIMM=RAW support has been added for the relevant output record types +(ao, bo, mbbo, mbboDirect). +RAW simulation mode will have those records do the appropriate conversion +and write RVAL to the location pointed to by SIOL. ### Fix `CHECK_RELEASE = WARN` @@ -1480,7 +1486,7 @@ editing and history. This functionality has now been restored, see Launchpad ### Constant link types Constant links can now hold 64-bit integer values, either as scalars or -arrays. Only base 10 is supported by the JSON parser though, the JSON standard + arrays. Only base 10 is supported by the JSON parser though, the JSON standard doesn't allow for hexadecimal numbers. ### Upgraded the YAJL JSON Library diff --git a/modules/database/src/std/rec/aoRecord.c b/modules/database/src/std/rec/aoRecord.c index a7a31ab7a..333a80c4e 100644 --- a/modules/database/src/std/rec/aoRecord.c +++ b/modules/database/src/std/rec/aoRecord.c @@ -37,7 +37,7 @@ #include "recGbl.h" #include "menuConvert.h" #include "menuOmsl.h" -#include "menuYesNo.h" +#include "menuSimm.h" #include "menuIvoa.h" #define GEN_SIZE_OFFSET @@ -561,14 +561,20 @@ static long writeValue(aoRecord *prec) } switch (prec->simm) { - case menuYesNoNO: + case menuSimmNO: status = pdset->write_ao(prec); break; - case menuYesNoYES: { + case menuSimmYES: + case menuSimmRAW: recGblSetSevr(prec, SIMM_ALARM, prec->sims); if (prec->pact || (prec->sdly < 0.)) { - status = dbPutLink(&prec->siol, DBR_DOUBLE, &prec->oval, 1); + if (prec->simm == menuSimmYES) + /* don't convert */ + status = dbPutLink(&prec->siol, DBR_DOUBLE, &prec->oval, 1); + else /* prec->simm == menuSimmRAW*/ + /* convert */ + status = dbPutLink(&prec->siol, DBR_LONG, &prec->rval, 1); prec->pact = FALSE; } else { /* !prec->pact && delay >= 0. */ epicsCallback *pvt = prec->simpvt; @@ -580,7 +586,6 @@ static long writeValue(aoRecord *prec) prec->pact = TRUE; } break; - } default: recGblSetSevr(prec, SOFT_ALARM, INVALID_ALARM); diff --git a/modules/database/src/std/rec/aoRecord.dbd.pod b/modules/database/src/std/rec/aoRecord.dbd.pod index 6f56478c2..ad40c75f7 100644 --- a/modules/database/src/std/rec/aoRecord.dbd.pod +++ b/modules/database/src/std/rec/aoRecord.dbd.pod @@ -263,8 +263,9 @@ processing. The following fields are used to operate the record in simulation mode. -If SIMM (fetched through SIML) is YES, the record is put in SIMS +If SIMM (fetched through SIML, if populated) is YES, the record is put in SIMS severity and the value is written through SIOL, without conversion. +If SIMM is RAW, the value is converted and RVAL is written. SSCN sets a different SCAN mechanism to use in simulation mode. SDLY sets a delay (in sec) that is used for asynchronous simulation processing. @@ -557,7 +558,7 @@ for more information on simulation mode and its fields. prompt("Simulation Mode") special(SPC_MOD) interest(1) - menu(menuYesNo) + menu(menuSimm) } field(SIMS,DBF_MENU) { prompt("Simulation Mode Severity") diff --git a/modules/database/src/std/rec/boRecord.c b/modules/database/src/std/rec/boRecord.c index ca254adde..b58b4d816 100644 --- a/modules/database/src/std/rec/boRecord.c +++ b/modules/database/src/std/rec/boRecord.c @@ -34,7 +34,7 @@ #include "special.h" #include "menuIvoa.h" #include "menuOmsl.h" -#include "menuYesNo.h" +#include "menuSimm.h" #define GEN_SIZE_OFFSET #include "boRecord.h" @@ -427,14 +427,18 @@ static long writeValue(boRecord *prec) } switch (prec->simm) { - case menuYesNoNO: + case menuSimmNO: status = pdset->write_bo(prec); break; - case menuYesNoYES: { + case menuSimmYES: + case menuSimmRAW: recGblSetSevr(prec, SIMM_ALARM, prec->sims); if (prec->pact || (prec->sdly < 0.)) { - status = dbPutLink(&prec->siol, DBR_USHORT, &prec->val, 1); + if (prec->simm == menuSimmYES) + status = dbPutLink(&prec->siol, DBR_USHORT, &prec->val, 1); + else /* prec->simm == menuSimmRAW */ + status = dbPutLink(&prec->siol, DBR_ULONG, &prec->rval, 1); prec->pact = FALSE; } else { /* !prec->pact && delay >= 0. */ epicsCallback *pvt = prec->simpvt; @@ -446,7 +450,6 @@ static long writeValue(boRecord *prec) prec->pact = TRUE; } break; - } default: recGblSetSevr(prec, SOFT_ALARM, INVALID_ALARM); diff --git a/modules/database/src/std/rec/boRecord.dbd.pod b/modules/database/src/std/rec/boRecord.dbd.pod index 1968f7652..618c53d82 100644 --- a/modules/database/src/std/rec/boRecord.dbd.pod +++ b/modules/database/src/std/rec/boRecord.dbd.pod @@ -182,8 +182,9 @@ The WPDT field is a private field for honoring seconds to hold HIGH. The following fields are used to operate the record in simulation mode. -If SIMM (fetched through SIML) is YES, the record is put in SIMS -severity and the value is written through SIOL. +If SIMM (fetched through SIML, if populated) is YES, the record is put +in SIMS severity and the unconverted value is written through SIOL. +If SIMM is RAW, the value is converted and RVAL is written. SSCN sets a different SCAN mechanism to use in simulation mode. SDLY sets a delay (in sec) that is used for asynchronous simulation processing. @@ -328,7 +329,7 @@ for more information on simulation mode and its fields. prompt("Simulation Mode") special(SPC_MOD) interest(1) - menu(menuYesNo) + menu(menuSimm) } field(SIMS,DBF_MENU) { prompt("Simulation Mode Severity") diff --git a/modules/database/src/std/rec/mbboDirectRecord.c b/modules/database/src/std/rec/mbboDirectRecord.c index 511f4b58b..c41cc6d7a 100644 --- a/modules/database/src/std/rec/mbboDirectRecord.c +++ b/modules/database/src/std/rec/mbboDirectRecord.c @@ -34,7 +34,7 @@ #include "special.h" #include "menuOmsl.h" #include "menuIvoa.h" -#include "menuYesNo.h" +#include "menuSimm.h" #define GEN_SIZE_OFFSET #include "mbboDirectRecord.h" @@ -359,14 +359,18 @@ static long writeValue(mbboDirectRecord *prec) } switch (prec->simm) { - case menuYesNoNO: + case menuSimmNO: status = pdset->write_mbbo(prec); break; - case menuYesNoYES: { + case menuSimmYES: + case menuSimmRAW: recGblSetSevr(prec, SIMM_ALARM, prec->sims); if (prec->pact || (prec->sdly < 0.)) { - status = dbPutLink(&prec->siol, DBR_ULONG, &prec->val, 1); + if (prec->simm == menuSimmYES) + status = dbPutLink(&prec->siol, DBR_LONG, &prec->val, 1); + else /* prec->simm == menuSimmRAW */ + status = dbPutLink(&prec->siol, DBR_ULONG, &prec->rval, 1); prec->pact = FALSE; } else { /* !prec->pact && delay >= 0. */ epicsCallback *pvt = prec->simpvt; @@ -378,7 +382,6 @@ static long writeValue(mbboDirectRecord *prec) prec->pact = TRUE; } break; - } default: recGblSetSevr(prec, SOFT_ALARM, INVALID_ALARM); diff --git a/modules/database/src/std/rec/mbboDirectRecord.dbd.pod b/modules/database/src/std/rec/mbboDirectRecord.dbd.pod index a87efbc04..7916b1685 100644 --- a/modules/database/src/std/rec/mbboDirectRecord.dbd.pod +++ b/modules/database/src/std/rec/mbboDirectRecord.dbd.pod @@ -223,6 +223,7 @@ The following fields are used to operate the record in simulation mode. If SIMM (fetched through SIML) is YES, the record is put in SIMS severity and the value is written through SIOL, without conversion. +If SIMM is RAW, the value is converted and RVAL is written. SSCN sets a different SCAN mechanism to use in simulation mode. SDLY sets a delay (in sec) that is used for asynchronous simulation processing. @@ -248,7 +249,7 @@ for more information on simulation mode and its fields. prompt("Simulation Mode") special(SPC_MOD) interest(1) - menu(menuYesNo) + menu(menuSimm) } field(SIMS,DBF_MENU) { prompt("Simulation Mode Severity") diff --git a/modules/database/src/std/rec/mbboRecord.c b/modules/database/src/std/rec/mbboRecord.c index 5acde7515..1de5d62bd 100644 --- a/modules/database/src/std/rec/mbboRecord.c +++ b/modules/database/src/std/rec/mbboRecord.c @@ -35,7 +35,7 @@ #include "special.h" #include "menuOmsl.h" #include "menuIvoa.h" -#include "menuYesNo.h" +#include "menuSimm.h" #define GEN_SIZE_OFFSET #include "mbboRecord.h" @@ -448,14 +448,18 @@ static long writeValue(mbboRecord *prec) } switch (prec->simm) { - case menuYesNoNO: + case menuSimmNO: status = pdset->write_mbbo(prec); break; - case menuYesNoYES: { + case menuSimmYES: + case menuSimmRAW: recGblSetSevr(prec, SIMM_ALARM, prec->sims); if (prec->pact || (prec->sdly < 0.)) { - status = dbPutLink(&prec->siol, DBR_USHORT, &prec->val, 1); + if (prec->simm == menuSimmYES) + status = dbPutLink(&prec->siol, DBR_USHORT, &prec->val, 1); + else /* prec->simm == menuSimmRAW */ + status = dbPutLink(&prec->siol, DBR_ULONG, &prec->rval, 1); prec->pact = FALSE; } else { /* !prec->pact && delay >= 0. */ epicsCallback *pvt = prec->simpvt; @@ -467,7 +471,6 @@ static long writeValue(mbboRecord *prec) prec->pact = TRUE; } break; - } default: recGblSetSevr(prec, SOFT_ALARM, INVALID_ALARM); diff --git a/modules/database/src/std/rec/mbboRecord.dbd.pod b/modules/database/src/std/rec/mbboRecord.dbd.pod index 8fcd26930..29a267f08 100644 --- a/modules/database/src/std/rec/mbboRecord.dbd.pod +++ b/modules/database/src/std/rec/mbboRecord.dbd.pod @@ -165,8 +165,9 @@ for converting VAL to RVAL. The following fields are used to operate the record in simulation mode. -If SIMM (fetched through SIML) is YES, the record is put in SIMS +If SIMM (fetched through SIML, if populated) is YES, the record is put in SIMS severity and the value is written through SIOL, without conversion. +If SIMM is RAW, the value is converted and RVAL is written. SSCN sets a different SCAN mechanism to use in simulation mode. SDLY sets a delay (in sec) that is used for asynchronous simulation processing. @@ -657,7 +658,7 @@ for more information on simulation mode and its fields. prompt("Simulation Mode") special(SPC_MOD) interest(1) - menu(menuYesNo) + menu(menuSimm) } field(SIMS,DBF_MENU) { prompt("Simulation Mode Severity") diff --git a/modules/database/test/std/rec/simmTest.c b/modules/database/test/std/rec/simmTest.c index 1f4193378..227f5c309 100644 --- a/modules/database/test/std/rec/simmTest.c +++ b/modules/database/test/std/rec/simmTest.c @@ -65,6 +65,10 @@ static char *rawSupp[] = { "bi", "mbbi", "mbbiDirect", + "ao", + "bo", + "mbbo", + "mbboDirect" }; static @@ -78,7 +82,10 @@ int hasRawSimmSupport(const char *rectype) { #define PVNAMELENGTH 60 static char nameVAL[PVNAMELENGTH]; static char nameB0[PVNAMELENGTH]; +static char nameONVL[PVNAMELENGTH]; static char nameRVAL[PVNAMELENGTH]; +static char nameROFF[PVNAMELENGTH]; +static char nameSHFT[PVNAMELENGTH]; static char nameSGNL[PVNAMELENGTH]; static char nameSIMM[PVNAMELENGTH]; static char nameSIML[PVNAMELENGTH]; @@ -100,7 +107,8 @@ static char nameSimvalLEN[PVNAMELENGTH]; static void setNames(const char *name) { - SETNAME(VAL); SETNAME(B0); SETNAME(RVAL); SETNAME(SGNL); + SETNAME(VAL); SETNAME(B0); SETNAME(ONVL); + SETNAME(RVAL); SETNAME(ROFF); SETNAME(SHFT); SETNAME(SGNL); SETNAME(SVAL); SETNAME(SIMM); SETNAME(SIML); SETNAME(SIOL); SETNAME(SIMS); SETNAME(SCAN); SETNAME(PROC); SETNAME(PACT); SETNAME(STAT); SETNAME(SEVR); SETNAME(TSE); @@ -401,6 +409,37 @@ void testSiolWrite(const char *name, testdbPutFieldOk(nameVAL, DBR_LONG, 1); testdbGetFieldEqual(nameSimval, DBR_USHORT, 1); + if (hasRawSimmSupport(name)) { + testDiag("in simmRAW, RVAL should be written to SIOL"); + testDiag("SIML overrides SIMM, disable it here"); + testdbPutFieldOk(nameSIML, DBR_STRING, ""); + testdbPutFieldOk(nameSIMM, DBR_STRING, "RAW"); + if (strcmp(name, "ao") == 0) { + testdbPutFieldOk(nameROFF, DBR_ULONG, 2); + testdbPutFieldOk(nameVAL, DBR_DOUBLE, 5.); + testdbGetFieldEqual(nameRVAL, DBR_LONG, 3); + testdbGetFieldEqual(nameSimval, DBR_DOUBLE, 3.); + } else if (strcmp(name, "bo") == 0) { + boRecord *prec; + prec = (boRecord *) testdbRecordPtr("bo"); + prec->mask = 0x55; + testdbPutFieldOk(nameVAL, DBR_USHORT, 1); + testdbGetFieldEqual(nameRVAL, DBR_ULONG, 0x55); + testdbGetFieldEqual(nameSimval, DBR_ULONG, 0x55); + } else if (strcmp(name, "mbbo") == 0) { + testdbPutFieldOk(nameONVL, DBR_ULONG, 5); + testdbPutFieldOk(nameVAL, DBR_UCHAR, 1); + testdbGetFieldEqual(nameRVAL, DBR_ULONG, 5); + testdbGetFieldEqual(nameSimval, DBR_UCHAR, 5); + } else if (strcmp(name, "mbboDirect") == 0) { + testdbPutFieldOk(nameSHFT, DBR_ULONG, 2); + testdbPutFieldOk(nameB0, DBR_UCHAR, 1); + testdbGetFieldEqual(nameRVAL, DBR_ULONG, 4); + testdbGetFieldEqual(nameSimval, DBR_UCHAR, 4); + } + testdbPutFieldOk(nameSIML, DBR_STRING, nameSimmode); + } + /* Set TSE to -2 (from device) and reprocess: timestamp is taken from IOC */ epicsTimeGetCurrent(&now); testdbPutFieldOk(nameTSE, DBR_SHORT, -2); @@ -518,7 +557,7 @@ void testAllRecTypes(void) MAIN(simmTest) { - testPlan(1176); + testPlan(1267); startSimmTestIoc("simmTest.db"); testSimmSetup();