EPICS Controls Argonne National Laboratory

Experimental Physics and
Industrial Control System

1994  1995  1996  1997  1998  1999  2000  2001  2002  2003  2004  2005  2006  2007  2008  2009  2010  2011  2012  2013  2014  2015  2016  2017  2018  2019  2020  2021  2022  2023  2024  2025  <2026 Index 1994  1995  1996  1997  1998  1999  2000  2001  2002  2003  2004  2005  2006  2007  2008  2009  2010  2011  2012  2013  2014  2015  2016  2017  2018  2019  2020  2021  2022  2023  2024  2025  <2026
<== Date ==> <== Thread ==>

Subject: Re: How to output a calculated waveform using aSub record in EPICS
From: Varuna Crishan Meddage via Tech-talk <tech-talk at aps.anl.gov>
To: "Johnson, Andrew N." <anj at anl.gov>, "tech-talk at aps.anl.gov" <tech-talk at aps.anl.gov>, "Rivers, Mark L." <rivers at cars.uchicago.edu>
Date: Thu, 2 Apr 2026 20:45:19 +0000
Hi Andrew,

Yes I made a mistake. Thanks for clarification. Following record gave me the intended result.

record(acalcout, "$(acc):$(sys)_$(group):acq2106_calib_current") {
    field(INAA, "$(acc):$(sys)_$(group):acq2106_current CPP")
    field(INPB, "$(acc):$(sys)_$(group):acq2106_calibvalue_eslo CPP")
    field(INPC, "$(acc):$(sys)_$(group):acq2106_calibvalue_eoff CPP")
    field(CALC, "AA*B + C")
    field(NELM, "4096")
    field(PREC, 5) 
}

Varuna

From: Johnson, Andrew N. <anj at anl.gov>
Sent: Thursday, April 2, 2026 3:40 PM
To: Varuna Crishan Meddage <vmeddage at fnal.gov>; tech-talk at aps.anl.gov <tech-talk at aps.anl.gov>; Rivers, Mark L. <rivers at cars.uchicago.edu>
Subject: Re: How to output a calculated waveform using aSub record in EPICS
 
Please read the aCalcout documentation, input links A through L are used for scalar values, AA through LL are for arrays.

- Andrew


-- 

Complexity comes for free, Simplicity you have to work for.


On 4/2/26, 3:10 PM, "Varuna Crishan Meddage" <vmeddage at fnal.gov> wrote:

This Message Is From an External Sender
This message came from outside your organization.
 
 Hi Andrew/Mark,

I tried the following record

record(acalcout, "$(acc):$(sys)_$(group):acq2106_calib_current") {
    field(INPA, "$(acc):$(sys)_$(group):acq2106_current CP")
    field(INPB, "$(acc):$(sys)_$(group):acq2106_calibvalue_eslo")
    field(INPC, "$(acc):$(sys)_$(group):acq2106_calibvalue_eoff")
    field(CALC, "A*B + C") 
}


But output is just a scalar

iocdev1$ pvxget PIP2:CTRL_MPS:acq2106_calib_current
PIP2:CTRL_MPS:acq2106_calib_current
    value double = 5.065
    alarm.severity int32_t = 0
    alarm.status int32_t = 0
    alarm.message string = ""
    timeStamp.secondsPastEpoch int64_t = 1775160461
    timeStamp.nanoseconds int32_t = 170911106
    timeStamp.userTag int32_t = 0
    display.limitLow double = 0
    display.limitHigh double = 0
    display.description string = ""
    display.units string = ""
    display.precision int32_t = 0
    display.form.index int32_t = 0
    display.form.choices string[] = {7}["Default", "String", "Binary", "Decimal", "Hex", "Exponential", "Engineering"]
    control.limitLow double = 0
    control.limitHigh double = 0
    valueAlarm.lowAlarmLimit double = 0
    valueAlarm.lowWarningLimit double = 0
    valueAlarm.highWarningLimit double = 0
    valueAlarm.highAlarmLimit double = 0



From: Johnson, Andrew N. <anj at anl.gov>
Sent: Thursday, April 2, 2026 3:04 PM
To: Rivers, Mark L. <rivers at cars.uchicago.edu>; tech-talk at aps.anl.gov <tech-talk at aps.anl.gov>; Varuna Crishan Meddage <vmeddage at fnal.gov>
Subject: Re: How to output a calculated waveform using aSub record in EPICS
 
I agree with Mark. The acalcout record is provided in the synApps “calc” module, found here:

- Andrew


-- 

Complexity comes for free, Simplicity you have to work for.


On 4/2/26, 3:01 PM, "Tech-talk" <tech-talk-bounces at aps.anl.gov> wrote:

I think you can do this with an aCalcout record with no C code.

Mark


From: Tech-talk <tech-talk-bounces at aps.anl.gov> on behalf of Varuna Crishan Meddage via Tech-talk <tech-talk at aps.anl.gov>
Sent: Thursday, April 2, 2026 2:53 PM
To: tech-talk at aps.anl.gov <tech-talk at aps.anl.gov>
Subject: How to output a calculated waveform using aSub record in EPICS
 
Hi,

I want to perform some operation using elements in 3 EPICS records, where one record is a waveform and other two are subArrays. (As indicated below)

========================= Waveform record ================================

record(waveform, "$(acc):$(sys)_$(group):acq2106_current")
{
  field(INP, {pva:{pv:"acq2106_347:1:AI:WF:17", "proc": "CP"}})
  field(FTVL, "DOUBLE")
  field(NELM, "4096")
  field(SCAN, "1 second")
  }

======================== subArrary record 1 ==============================

record(subArray, "$(acc):$(sys)_$(group):acq2106_calibvalue_eslo") {
    field(DESC, "Extracted subset of WAVE")
    field(INP, {pva:{pv:"acq2106_347:1:AI:CAL:ESLO", "proc":"CP"}})
    field(FTVL, "DOUBLE")     
    field(MALM, "10")        
    field(NELM, "1")         
    field(INDX, "17")
    field(SCAN, "1 second")
}

==================== subArray record 2 ================================

record(subArray, "$(acc):$(sys)_$(group):acq2106_calibvalue_eoff") {
    field(DESC, "Extracted subset of WAVE")
    field(INP, {pva:{pv:"acq2106_347:1:AI:CAL:EOFF", "proc":"CP"}})
    field(FTVL, "DOUBLE")     
    field(MALM, "10") # If set this to 1, does not return the expected outcome       
    field(NELM, "1")         
    field(INDX, "17")
    field(SCAN, "1 second")
}

===================================================================

Here I am trying to loop over every element of the wave form and multiply each element by the single element of the subarray 1 and add the only element in the subarray 2 to the result (subarray 1 and subarray 2 have only one element)

So to achieve this goal, I created  aSub record (pasted below) and inside that I called the function named calibWave.c (pasted below).

========================== calibWave.c ==============================

#include <stddef.h>
#include <stdlib.h>
#include <string.h>
#include <ctype.h>
#include <unistd.h>
#include <stdio.h>
#include <math.h>
#include <ncurses.h>

#include "dbDefs.h"
#include "registryFunction.h"
#include "epicsExport.h"
#include "epicsExit.h"
#include "epicsThread.h"
#include "iocsh.h"
#include "aSubRecord.h"

static double calibWave(aSubRecord *prec)
{
 double *in  = (double*)prec->a;
 double *out = (double*)prec->vala;

 double eslo = *(double*)prec->b;
 double eoff = *(double*)prec->c;

 int n = prec->nea;

 for(int i = 0; i < n; i++) {
     out[i] = in[i] * eslo + eoff;
 }

 return 0;
}

EpicsRegisterFunction(calibWave);

====================================================================

==================== aSub record for the calculated waveform ===============

record(aSub, "$(acc):$(sys)_$(group):acq2106_calib_current") {
    field(INPA, "$(acc):$(sys)_$(group):acq2106_current CPP")
    field(INPB, "$(acc):$(sys)_$(group):acq2106_calibvalue_eslo CPP")
    field(INPC, "$(acc):$(sys)_$(group):acq2106_calibvalue_eoff CPP")
    field(FTA, "DOUBLE")
    field(FTB, "DOUBLE")
    field(FTC, "DOUBLE")
    field(NOA, "4096")
    field(NOB, "1")
    field(NOC, "1")
    field(FTVA, "DOUBLE")
    field(NOVA, "4096")
    field(SNAM, "calibWave")  
    field(SCAN, "1 second")
    field(PREC, 5)
}

===================================================================

But this aSub only returns a single number instead of a waveform (as indicated below)

=================== pvxget for asub record ==========================

PIP2:CTRL_MPS:acq2106_calib_current
    value int32_t = 4090
    alarm.severity int32_t = 0
    alarm.status int32_t = 0
    alarm.message string = ""
    timeStamp.secondsPastEpoch int64_t = 1775158362
    timeStamp.nanoseconds int32_t = 7852163
    timeStamp.userTag int32_t = 0
    display.limitLow int32_t = 0
    display.limitHigh int32_t = 0
    display.description string = ""
    display.units string = ""
    display.form.index int32_t = 0
    display.form.choices string[] = {7}["Default", "String", "Binary", "Decimal", "Hex", "Exponential", "Engineering"]
    control.limitLow int32_t = -2147483648
    control.limitHigh int32_t = 2147483647
    valueAlarm.lowAlarmLimit int32_t = 0
    valueAlarm.lowWarningLimit int32_t = 0
    valueAlarm.highWarningLimit int32_t = 0
    valueAlarm.highAlarmLimit int32_t = 0

====================================================================

I am not sure, where the problem happens (either calibWave.C function or aSub record ) or not sure whether aSub record is the best solution to achieve this goal.

Any help to debug this is highly appreciated.

============================================== Additional information ==============================================================

I am not 100% the way I created the custom calibWave. Function. Following are the steps, I followed.


************************************** content of waveCalib.dbd ********************************************
Function(calibWave)

***********************************************************************************************************


******************************************** Makefile content at src directory *******************************

TOP=../..

include $(TOP)/configure/CONFIG
#----------------------------------------
#  ADD MACRO DEFINITIONS AFTER THIS LINE
#=============================

#=============================
# Build the IOC application
PROD_IOC = XRM

# XRM.dbd will be created and installed
DBD += XRM.dbd

# XRM.dbd will be made up from these files:
XRM_DBD += base.dbd

# modified menuScan.dbd to include FNAL scan rates
XRM_DBD += menuScan.dbd

# waveCalib.dbd including the calibWave.c function
XRM_DBD += waveCalib.dbd  // ***********************************Addition

# Include dbd files from all support applications:
XRM_DBD += pvxsIoc.dbd
XRM_DBD += iocAdmin.dbd
XRM_DBD += aliveRecord.dbd
XRM_DBD += sseqRecord.dbd
XRM_DBD += sscanSupport.dbd
XRM_DBD += acnetPV.dbd
XRM_DBD += tcast.dbd
XRM_DBD += reccaster.dbd
XRM_DBD += asSupport.dbd
XRM_DBD += caPutJsonLog.dbd
XRM_DBD += sCalcoutRecord.dbd
XRM_DBD += calcSupport.dbd
XRM_DBD += aCalcoutRecord.dbd

# Add all the support libraries needed by this IOC
XRM_LIBS += devIocStats
XRM_LIBS += alive
XRM_LIBS += acnetPV
XRM_LIBS += calc
XRM_LIBS += pv seq
XRM_LIBS += sscan
XRM_LIBS += tcast
XRM_LIBS += reccaster
XRM_LIBS += autosave
XRM_LIBS += caPutLog
XRM_LIBS += pvxsIoc pvxs

# XRM_registerRecordDeviceDriver.cpp derives from XRM.dbd
XRM_SRCS += XRM_registerRecordDeviceDriver.cpp
XRM_SRCS += CopyArray.c
XRM_SRCS += calibWave.c // *************************** Addition

# Build the main IOC entry point on workstation OSs.
XRM_SRCS_DEFAULT += XRMMain.cpp
XRM_SRCS_vxWorks += -nil-

# Add header files:
#USR_INCLUDES += -I/usr/include

#
# Finally link to the EPICS Base libraries
XRM_LIBS += $(EPICS_BASE_IOC_LIBS)

#===========================

include $(TOP)/configure/RULES
#----------------------------------------
#  ADD RULES AFTER THIS LINE
USR_CXXFLAGS_DEFAULT += -fno-operator-names -pedantic
USR_CXXFLAGS += -W -Wall

**************************************************************************************************************

After compilng the project successfully, I checked the XRM.dbd file at .dbd directory and I can that it contains the line

Function(calibWave)

================================================== End of Additional Information ====================


Thanks
Varuna Meddage




References:
How to output a calculated waveform using aSub record in EPICS Varuna Crishan Meddage via Tech-talk
Re: How to output a calculated waveform using aSub record in EPICS Mark Rivers via Tech-talk
Re: How to output a calculated waveform using aSub record in EPICS Johnson, Andrew N. via Tech-talk
Re: How to output a calculated waveform using aSub record in EPICS Varuna Crishan Meddage via Tech-talk
Re: How to output a calculated waveform using aSub record in EPICS Johnson, Andrew N. via Tech-talk

Navigate by Date:
Prev: Re: How to output a calculated waveform using aSub record in EPICS Johnson, Andrew N. via Tech-talk
Next: Re: How to output a calculated waveform using aSub record in EPICS Peter Milne via Tech-talk
Index: 1994  1995  1996  1997  1998  1999  2000  2001  2002  2003  2004  2005  2006  2007  2008  2009  2010  2011  2012  2013  2014  2015  2016  2017  2018  2019  2020  2021  2022  2023  2024  2025  <2026
Navigate by Thread:
Prev: Re: How to output a calculated waveform using aSub record in EPICS Johnson, Andrew N. via Tech-talk
Next: Re: How to output a calculated waveform using aSub record in EPICS Peter Milne via Tech-talk
Index: 1994  1995  1996  1997  1998  1999  2000  2001  2002  2003  2004  2005  2006  2007  2008  2009  2010  2011  2012  2013  2014  2015  2016  2017  2018  2019  2020  2021  2022  2023  2024  2025  <2026
ANJ, 02 Apr 2026 · Home · News · About · Talk · Base · Modules · Extensions ·
· Distributions · Download · Documents · Links · Licensing ·