diff --git a/src/std/rec/Makefile b/src/std/rec/Makefile index d16b20b93..c2d44ddb9 100644 --- a/src/std/rec/Makefile +++ b/src/std/rec/Makefile @@ -11,71 +11,43 @@ SRC_DIRS += $(STDDIR)/rec -DBDINC += aaiRecord -DBDINC += aaoRecord -DBDINC += aiRecord -DBDINC += aoRecord -DBDINC += aSubRecord -DBDINC += biRecord -DBDINC += boRecord -DBDINC += calcRecord -DBDINC += calcoutRecord -DBDINC += compressRecord -DBDINC += dfanoutRecord -DBDINC += eventRecord -DBDINC += fanoutRecord -DBDINC += histogramRecord -DBDINC += longinRecord -DBDINC += longoutRecord -DBDINC += lsiRecord -DBDINC += mbbiRecord -DBDINC += mbbiDirectRecord -DBDINC += mbboRecord -DBDINC += mbboDirectRecord -DBDINC += permissiveRecord -DBDINC += printfRecord -DBDINC += selRecord -DBDINC += seqRecord -DBDINC += stateRecord -DBDINC += stringinRecord -DBDINC += stringoutRecord -DBDINC += subRecord -DBDINC += subArrayRecord -DBDINC += waveformRecord +stdRecords += aaiRecord +stdRecords += aaoRecord +stdRecords += aiRecord +stdRecords += aoRecord +stdRecords += aSubRecord +stdRecords += biRecord +stdRecords += boRecord +stdRecords += calcRecord +stdRecords += calcoutRecord +stdRecords += compressRecord +stdRecords += dfanoutRecord +stdRecords += eventRecord +stdRecords += fanoutRecord +stdRecords += histogramRecord +stdRecords += longinRecord +stdRecords += longoutRecord +stdRecords += lsiRecord +stdRecords += lsoRecord +stdRecords += mbbiRecord +stdRecords += mbbiDirectRecord +stdRecords += mbboRecord +stdRecords += mbboDirectRecord +stdRecords += permissiveRecord +stdRecords += printfRecord +stdRecords += selRecord +stdRecords += seqRecord +stdRecords += stateRecord +stdRecords += stringinRecord +stdRecords += stringoutRecord +stdRecords += subRecord +stdRecords += subArrayRecord +stdRecords += waveformRecord +DBDINC += $(stdRecords) DBD += stdRecords.dbd -stdRecords_DBD = $(patsubst %,%.dbd,$(DBDINC)) +stdRecords_DBD = $(patsubst %,%.dbd,$(stdRecords)) -dbRecStd_SRCS += aaiRecord.c -dbRecStd_SRCS += aaoRecord.c -dbRecStd_SRCS += aiRecord.c -dbRecStd_SRCS += aoRecord.c -dbRecStd_SRCS += aSubRecord.c -dbRecStd_SRCS += biRecord.c -dbRecStd_SRCS += boRecord.c -dbRecStd_SRCS += calcRecord.c -dbRecStd_SRCS += calcoutRecord.c -dbRecStd_SRCS += compressRecord.c -dbRecStd_SRCS += dfanoutRecord.c -dbRecStd_SRCS += eventRecord.c -dbRecStd_SRCS += fanoutRecord.c -dbRecStd_SRCS += histogramRecord.c -dbRecStd_SRCS += longinRecord.c -dbRecStd_SRCS += longoutRecord.c -dbRecStd_SRCS += lsiRecord.c -dbRecStd_SRCS += mbbiRecord.c -dbRecStd_SRCS += mbbiDirectRecord.c -dbRecStd_SRCS += mbboRecord.c -dbRecStd_SRCS += mbboDirectRecord.c -dbRecStd_SRCS += permissiveRecord.c -dbRecStd_SRCS += printfRecord.c -dbRecStd_SRCS += selRecord.c -dbRecStd_SRCS += seqRecord.c -dbRecStd_SRCS += stateRecord.c -dbRecStd_SRCS += stringinRecord.c -dbRecStd_SRCS += stringoutRecord.c -dbRecStd_SRCS += subRecord.c -dbRecStd_SRCS += subArrayRecord.c -dbRecStd_SRCS += waveformRecord.c +dbRecStd_SRCS += $(patsubst %,%.c,$(stdRecords)) diff --git a/src/std/rec/lsoRecord.c b/src/std/rec/lsoRecord.c new file mode 100644 index 000000000..271a0c3f9 --- /dev/null +++ b/src/std/rec/lsoRecord.c @@ -0,0 +1,322 @@ +/*************************************************************************\ +* Copyright (c) 2012 UChicago Argonne LLC, as Operator of Argonne +* National Laboratory. +* EPICS BASE is distributed subject to a Software License Agreement found +* in file LICENSE that is included with this distribution. +\*************************************************************************/ + +/* Long String Output record type */ +/* + * Author: Andrew Johnson + * Date: 2012-11-28 + */ + + +#include +#include +#include + +#include "dbDefs.h" +#include "errlog.h" +#include "alarm.h" +#include "cantProceed.h" +#include "dbAccess.h" +#include "dbEvent.h" +#include "dbFldTypes.h" +#include "devSup.h" +#include "errMdef.h" +#include "menuIvoa.h" +#include "menuOmsl.h" +#include "menuPost.h" +#include "menuYesNo.h" +#include "recSup.h" +#include "recGbl.h" +#include "special.h" +#define GEN_SIZE_OFFSET +#include "lsoRecord.h" +#undef GEN_SIZE_OFFSET +#include "epicsExport.h" + +static void monitor(lsoRecord *); +static long writeValue(lsoRecord *); + +static long init_record(lsoRecord *prec, int pass) +{ + lsodset *pdset; + + if (pass == 0) { + size_t sizv = prec->sizv; + + if (sizv < 16) { + sizv = 16; /* Enforce a minimum size for the VAL field */ + prec->sizv = sizv; + } + + prec->val = callocMustSucceed(1, sizv, "lso::init_record"); + prec->len = 0; + prec->oval = callocMustSucceed(1, sizv, "lso::init_record"); + prec->olen = 0; + return 0; + } + + dbLoadLink(&prec->siml, DBF_USHORT, &prec->simm); + + pdset = (lsodset *) prec->dset; + if (!pdset) { + recGblRecordError(S_dev_noDSET, prec, "lso: init_record"); + return S_dev_noDSET; + } + + /* must have a write_string function defined */ + if (pdset->number < 5 || !pdset->write_string) { + recGblRecordError(S_dev_missingSup, prec, "lso: init_record"); + return S_dev_missingSup; + } + + dbLoadLinkLS(&prec->dol, prec->val, prec->sizv, &prec->len); + + if (pdset->init_record) { + long status = pdset->init_record(prec); + + if (status) + return status; + } + + if (prec->len) { + strcpy(prec->oval, prec->val); + prec->olen = prec->len; + prec->udf = FALSE; + } + + return 0; +} + +static long process(lsoRecord *prec) +{ + int pact = prec->pact; + lsodset *pdset = (lsodset *) prec->dset; + long status = 0; + + if (!pdset || !pdset->write_string) { + prec->pact = TRUE; + recGblRecordError(S_dev_missingSup, prec, "lso: write_string"); + return S_dev_missingSup; + } + + if (!pact && prec->omsl == menuOmslclosed_loop) + if (!dbGetLinkLS(&prec->dol, prec->val, prec->sizv, &prec->len)) + prec->udf = FALSE; + + if (prec->udf) + recGblSetSevr(prec, UDF_ALARM, INVALID_ALARM); + + if (prec->nsev < INVALID_ALARM ) + status = writeValue(prec); /* write the new value */ + else { + switch (prec->ivoa) { + case menuIvoaContinue_normally: + status = writeValue(prec); /* write the new value */ + break; + + case menuIvoaDon_t_drive_outputs: + break; + + case menuIvoaSet_output_to_IVOV: + if (!prec->pact) { + size_t size = prec->sizv - 1; + + strncpy(prec->val, prec->ivov, size); + prec->val[size] = 0; + prec->len = strlen(prec->val) + 1; + } + status = writeValue(prec); /* write the new value */ + break; + + default: + status = -1; + recGblRecordError(S_db_badField, prec, + "lso:process Bad IVOA choice"); + } + } + + /* Asynchronous if device support set pact */ + if (!pact && prec->pact) + return status; + + prec->pact = TRUE; + recGblGetTimeStamp(prec); + + monitor(prec); + + /* Wrap up */ + recGblFwdLink(prec); + prec->pact = FALSE; + return status; +} + +static long cvt_dbaddr(DBADDR *paddr) +{ + lsoRecord *prec = (lsoRecord *) paddr->precord; + int fieldIndex = dbGetFieldIndex(paddr); + + if (fieldIndex == lsoRecordVAL) { + paddr->pfield = prec->val; + paddr->special = SPC_MOD; + } + else if (fieldIndex == lsoRecordOVAL) { + paddr->pfield = prec->oval; + paddr->special = SPC_NOMOD; + } + else { + errlogPrintf("lsoRecord::cvt_dbaddr called for %s.%s\n", + prec->name, paddr->pfldDes->name); + return -1; + } + + paddr->no_elements = 1; + paddr->field_type = DBF_STRING; + paddr->dbr_field_type = DBF_STRING; + paddr->field_size = prec->sizv; + return 0; +} + +static long get_array_info(DBADDR *paddr, long *no_elements, long *offset) +{ + lsoRecord *prec = (lsoRecord *) paddr->precord; + int fieldIndex = dbGetFieldIndex(paddr); + + if (fieldIndex == lsoRecordVAL) + *no_elements = prec->len; + else if (fieldIndex == lsoRecordOVAL) + *no_elements = prec->olen; + else + return -1; + + *offset = 0; + return 0; +} + +static long put_array_info(DBADDR *paddr, long nNew) +{ + lsoRecord *prec = (lsoRecord *) paddr->precord; + + if (nNew == prec->sizv) + --nNew; /* truncated string */ + prec->val[nNew] = 0; /* ensure data is terminated */ + + return 0; +} + +static long special(DBADDR *paddr, int after) +{ + lsoRecord *prec = (lsoRecord *) paddr->precord; + + if (!after) + return 0; + + /* We set prec->len here and not in put_array_info() + * because that does not get called if the put was + * done using a DBR_STRING type. + */ + prec->len = strlen(prec->val) + 1; + db_post_events(prec, &prec->len, DBE_VALUE | DBE_LOG); + + return 0; +} + +static void monitor(lsoRecord *prec) +{ + epicsUInt16 events = recGblResetAlarms(prec); + + if (prec->len != prec->olen || + memcmp(prec->oval, prec->val, prec->len)) { + events |= DBE_VALUE | DBE_LOG; + memcpy(prec->oval, prec->val, prec->len); + } + + if (prec->len != prec->olen) { + prec->olen = prec->len; + db_post_events(prec, &prec->len, DBE_VALUE | DBE_LOG); + } + + if (prec->mpst == menuPost_Always) + events |= DBE_VALUE; + if (prec->apst == menuPost_Always) + events |= DBE_LOG; + + if (events) + db_post_events(prec, prec->val, events); +} + +static long writeValue(lsoRecord *prec) +{ + long status; + lsodset *pdset = (lsodset *) prec->dset; + + if (prec->pact) + goto write; + + status = dbGetLink(&prec->siml, DBR_USHORT, &prec->simm, 0, 0); + if (status) + return(status); + + switch (prec->simm) { + case menuYesNoNO: +write: + status = pdset->write_string(prec); + break; + + case menuYesNoYES: + recGblSetSevr(prec, SIMM_ALARM, prec->sims); + status = dbPutLink(&prec->siol,DBR_STRING, prec->val,1); + break; + + default: + recGblSetSevr(prec, SOFT_ALARM, INVALID_ALARM); + status = -1; + } + + return status; +} + +/* Create Record Support Entry Table*/ + +#define report NULL +#define initialize NULL +/* init_record */ +/* process */ +/* special */ +#define get_value NULL +/* cvt_dbaddr */ +/* get_array_info */ +/* put_array_info */ +#define get_units NULL +#define get_precision NULL +#define get_enum_str NULL +#define get_enum_strs NULL +#define put_enum_str NULL +#define get_graphic_double NULL +#define get_control_double NULL +#define get_alarm_double NULL + +rset lsoRSET = { + RSETNUMBER, + report, + initialize, + init_record, + process, + special, + get_value, + cvt_dbaddr, + get_array_info, + put_array_info, + get_units, + get_precision, + get_enum_str, + get_enum_strs, + put_enum_str, + get_graphic_double, + get_control_double, + get_alarm_double +}; +epicsExportAddress(rset, lsoRSET); diff --git a/src/std/rec/lsoRecord.dbd b/src/std/rec/lsoRecord.dbd new file mode 100644 index 000000000..48ddea810 --- /dev/null +++ b/src/std/rec/lsoRecord.dbd @@ -0,0 +1,112 @@ +#************************************************************************* +# Copyright (c) 2012 UChicago Argonne LLC, as Operator of Argonne +# National Laboratory. +# EPICS BASE is distributed subject to a Software License Agreement found +# in file LICENSE that is included with this distribution. +#************************************************************************* + +recordtype(lso) { + include "dbCommon.dbd" + %#include "devSup.h" + % + %/* Declare Device Support Entry Table */ + %typedef struct lsodset { + % long number; + % DEVSUPFUN report; + % DEVSUPFUN init; + % DEVSUPFUN init_record; + % DEVSUPFUN get_ioint_info; + % DEVSUPFUN write_string; + %} lsodset; + % + field(VAL,DBF_NOACCESS) { + prompt("Current Value") + asl(ASL0) + pp(TRUE) + special(SPC_DBADDR) + extra("char *val") + } + field(OVAL,DBF_NOACCESS) { + prompt("Previous Value") + special(SPC_DBADDR) + interest(3) + extra("char *oval") + } + field(SIZV,DBF_USHORT) { + prompt("Size of buffers") + promptgroup(GUI_OUTPUT) + special(SPC_NOMOD) + interest(1) + initial("41") + } + field(LEN,DBF_ULONG) { + prompt("Length of VAL") + special(SPC_NOMOD) + } + field(OLEN,DBF_ULONG) { + prompt("Length of OVAL") + special(SPC_NOMOD) + interest(3) + } + field(DOL,DBF_INLINK) { + prompt("Desired Output Link") + promptgroup(GUI_OUTPUT) + interest(1) + } + field(IVOA,DBF_MENU) { + prompt("INVALID Output Action") + promptgroup(GUI_OUTPUT) + interest(2) + menu(menuIvoa) + } + field(IVOV,DBF_STRING) { + prompt("INVALID Output Value") + promptgroup(GUI_OUTPUT) + interest(2) + size(40) + } + field(OMSL,DBF_MENU) { + prompt("Output Mode Select") + promptgroup(GUI_OUTPUT) + interest(1) + menu(menuOmsl) + } + field(OUT,DBF_OUTLINK) { + prompt("Output Specification") + promptgroup(GUI_OUTPUT) + interest(1) + } + field(MPST,DBF_MENU) { + prompt("Post Value Monitors") + promptgroup(GUI_DISPLAY) + interest(1) + menu(menuPost) + } + field(APST,DBF_MENU) { + prompt("Post Archive Monitors") + promptgroup(GUI_DISPLAY) + interest(1) + menu(menuPost) + } + field(SIML,DBF_INLINK) { + prompt("Sim Mode link") + promptgroup(GUI_INPUTS) + interest(1) + } + field(SIMM,DBF_MENU) { + prompt("Simulation Mode") + interest(1) + menu(menuYesNo) + } + field(SIMS,DBF_MENU) { + prompt("Sim mode Alarm Svrty") + promptgroup(GUI_INPUTS) + interest(2) + menu(menuAlarmSevr) + } + field(SIOL,DBF_OUTLINK) { + prompt("Sim Output Specifctn") + promptgroup(GUI_INPUTS) + interest(1) + } +}