仿真数字正弦波发生器程序

news2024/9/20 22:46:35

1)构建这个IOC程序的程序框架:

orangepi@orangepi5:/usr/local/EPICS/program/simScope$ ls
bin  configure  db  dbd  iocBoot  lib  Makefile  simScopeApp

2)修改configure下RELEASE文件,添加所需的支持模块,此IOC程序需要asyn模块支持,因此添加以下两行:

...

# Variables and paths to dependent modules:
#MODULES = /path/to/modules
#MYMODULE = $(MODULES)/my-module
SUPPORT=/usr/local/EPICS/synApps/support
ASYN=$(SUPPORT)/asyn

...

3) 进入simScopeApp/src/目录下,编写以下以下三个文件:

simScope.cpp  simScope.h  simScopeSupport.dbd

a) simScope.h:

#include <asynPortDriver.h>

#define NUM_VERT_SELECTIONS     4

/* drvInfo string*/
#define P_RunString                     "SCOPE_RUN"                     /* asynInt32 r/w start/stop backgroud thread */
#define P_MaxPointsString               "SCOPE_MAX_POINTS"              /* asynInt32 r/o max number of data points   */
#define P_TimePerDivString              "SCOPE_TIME_PER_DIV"            /* asynFloat64 r/w Time Per Div              */
#define P_TimePerDivSelectString        "SCOPE_TIME_PER_DIV_SELECT"     /* asynInt32 r/w   Time Per Div Choices      */
#define P_VertGainString                "SCOPE_VERT_GAIN"               /* asynFloat64 r/w Vert Gain                 */
#define P_VertGainSelectString          "SCOPE_VERT_GAIN_SELECT"        /* asynInt32 r/w Vert Gain Choices           */
#define P_VoltsPerDivString             "SCOPE_VOLTS_PER_DIV"           /* asynFloat64 r/w Volts Per Div             */
#define P_VoltsPerDivSelectString       "SCOPE_VOLTS_PER_DIV_SELECT"    /* asynInt32 r/w Volts Per Div Choices       */
#define P_VoltOffsetString              "SCOPE_VOLT_OFFSET"             /* asynFloat64 r/w Volt Offset               */
#define P_TriggerDelayString            "SCOPE_TRIGGER_DELAY"           /* asynFloat64 r/w Trigger Delay             */
#define P_NoiseAmplitudeString          "SCOPE_NOISE_AMPLITUDE"         /* asynFloat64 r/w Noise Amplitude           */
#define P_UpdateTimeString              "SCOPE_UPDATE_TIME"             /* asynFloat64 r/w Update Time               */
#define P_WaveformString                "SCOPE_WAVEFORM"                /* asynFloat64Array r/o waveform data array  */
#define P_TimeBaseString                "SCOPE_TIME_BASE"               /* asynFloat64Array r/o time base array      */
#define P_MinValueString                "SCOPE_MIN_VALUE"               /* asynFloat64 r/o min data */
#define P_MaxValueString                "SCOPE_MAX_VALUE"               /* asynFloat64 r/o max data */
#define P_MeanValueString               "SCOPE_MEAN_VALUE"              /* asynFloat64 r/o mean data */

class simScope : public asynPortDriver
{
public:
        simScope(const char * portName, int maxArraySize);
        /* There method overwritten from asynPortDriver */
        virtual asynStatus writeInt32(asynUser *pasynUser, epicsInt32 value);
        virtual asynStatus writeFloat64(asynUser *pasynUser, epicsFloat64 value);
        virtual asynStatus readFloat64Array(asynUser *pasynUser, epicsFloat64 *value, size_t nElements, size_t *nIn);
        virtual asynStatus readEnum(asynUser *pasynUser, char *strings[], int values[], int severties[], size_t nElements, size_t *nIn);

        void simTask(void);

protected:
        /* index for parameter in the parameter library */
        int P_Run;
        int P_MaxPoints;
        int P_TimePerDiv;
        int P_TimePerDivSelect;
        int P_VertGain;
        int P_VertGainSelect;
        int P_VoltsPerDiv;
        int P_VoltsPerDivSelect;
        int P_VoltOffset;
        int P_TriggerDelay;
        int P_NoiseAmplitude;
        int P_UpdateTime;
        int P_Waveform;
        int P_TimeBase;
        int P_MinValue;
        int P_MaxValue;
        int P_MeanValue;

private:
        /* event to send sigal to background thread */
        epicsEventId eventId_;
        /* waveform data array     */
        epicsFloat64 *pData_;
        /* waveform timebase array */
        epicsFloat64 *pTimeBase_;
        /* string array for Volts Per Div Choices*/
        char *voltsPerDivStrings_[NUM_VERT_SELECTIONS];
        /* value array for Volts Per Div Choices */
        int voltsPerDivValues_[NUM_VERT_SELECTIONS];
        /* severities array for Volts Per Div Choices */
        int voltsPerDivSeverities_[NUM_VERT_SELECTIONS];

        /* set Vert Gain */
        void setVertGain();
        /* set Volts Per Div according to voltsPerDivSelect */
        void setVoltsPerDiv();
        /* set Time Per Div according to TimePerDivSelect   */
        void setTimePerDiv();
};

b) simScope.cpp:

#include <stdlib.h>
#include <string.h>
#include <stdio.h>
#include <errno.h>
#include <math.h>

#include <epicsTypes.h>
#include <epicsTime.h>
#include <epicsThread.h>
#include <epicsString.h>
#include <epicsTimer.h>
#include <epicsMutex.h>
#include <epicsEvent.h>
#include <iocsh.h>

#include  "simScope.h"
#include <epicsExport.h>

#define FREQUENCY               1000    /* volt signal frequency */
#define AMPLITUDE               1.0     /* volt signal amplitude */
#define NUM_DIVISIONS           10      /* horizontal and vertical axis' divisions */
#define MIN_UPDATE_TIME         0.05    /* the min update time for the waveform data */

#define MAX_ENUM_STRING_SIZE    20
/* This driver's Name */
static const char * driverName = "simScope";

static int allVoltsPerDivSelections[NUM_VERT_SELECTIONS] = {1,2,5,10};
/* For C Call */
void simTask(void * pdrvPvt);

simScope::simScope(const char * portName, int maxPoints)
        :asynPortDriver(portName,
                        1,
                        asynInt32Mask | asynFloat64Mask | asynFloat64ArrayMask | asynEnumMask | asynDrvUserMask,
                        asynInt32Mask | asynFloat64Mask | asynFloat64ArrayMask | asynEnumMask,
                        0, /* asynFlags  */
                        1, /* autoconnect*/
                        0, /* Default priority   */
                        0) /* Default stack size */
{
        asynStatus status;
        int i;
        const char *functionName = "simScope";

        /* make sure the number of points at least 100 points */
        if (maxPoints < 100){
                maxPoints = 100;
        }
        printf("Come to Contruct the simScope instance\n");

        /* allocate space for waveform data */
        pData_ = (epicsFloat64 *)calloc( maxPoints, sizeof(epicsFloat64));
        /* allocate space for timebase */
        pTimeBase_ = (epicsFloat64 *)calloc(maxPoints, sizeof(epicsFloat64));
        /* set the interval between pTimeBase_ elements */
        for (i = 0; i < maxPoints; i++){ // the number of divisions is NUM_DIVISIONS
                pTimeBase_[i] = (epicsFloat64)i/ (maxPoints - 1)  * NUM_DIVISIONS ;
        }

        // create the event for sending signal to the background thread
        eventId_ = epicsEventCreate(epicsEventEmpty);

        printf("Come before create parameters\n");
        /* create the parameters for communicating with epics Records */
        createParam(P_RunString,                asynParamInt32,         &P_Run);
        createParam(P_MaxPointsString,          asynParamInt32,         &P_MaxPoints);
        createParam(P_TimePerDivString,         asynParamFloat64,       &P_TimePerDiv);
        createParam(P_TimePerDivSelectString,   asynParamInt32,         &P_TimePerDivSelect);
        createParam(P_VertGainString,           asynParamFloat64,       &P_VertGain);
        createParam(P_VertGainSelectString,     asynParamInt32,         &P_VertGainSelect);
        createParam(P_VoltsPerDivString,        asynParamFloat64,       &P_VoltsPerDiv);
        createParam(P_VoltsPerDivSelectString,  asynParamInt32,         &P_VoltsPerDivSelect);
        createParam(P_VoltOffsetString,         asynParamFloat64,       &P_VoltOffset);
        createParam(P_TriggerDelayString,       asynParamFloat64,       &P_TriggerDelay);
        createParam(P_NoiseAmplitudeString,     asynParamFloat64,       &P_NoiseAmplitude);
        createParam(P_UpdateTimeString,         asynParamFloat64,       &P_UpdateTime);
        createParam(P_WaveformString,           asynParamFloat64Array,  &P_Waveform);
        createParam(P_TimeBaseString,           asynParamFloat64Array,  &P_TimeBase);
        createParam(P_MinValueString,           asynParamFloat64,       &P_MinValue);
        createParam(P_MaxValueString,           asynParamFloat64,       &P_MaxValue);
        createParam(P_MeanValueString,          asynParamFloat64,       &P_MeanValue);

        /* alloc space for vert per divistion strings */
        for (i = 0; i < NUM_VERT_SELECTIONS; i++){
                voltsPerDivValues_[i] = 0;
                voltsPerDivSeverities_[i] = 0;
                voltsPerDivStrings_[i] = (char *)calloc(MAX_ENUM_STRING_SIZE,   sizeof(char));
        }

        setIntegerParam(P_MaxPoints,            maxPoints);
        setIntegerParam(P_Run,                  0);
        setIntegerParam(P_VertGainSelect,       10);
        /* set the arrays voltsPerDivValues_,  voltsPerDivString_ according to P_VertGainSelect parameter*/
        setVertGain();
        setDoubleParam(P_VoltsPerDiv,           1.0);
        setDoubleParam(P_VoltOffset,            0.0);
        setDoubleParam(P_TriggerDelay,          0.0);
        setDoubleParam(P_NoiseAmplitude,        0.1);
        setDoubleParam(P_UpdateTime,            1);
        setDoubleParam(P_TimePerDiv,            0.001);
        setDoubleParam(P_MinValue,              0.0);
        setDoubleParam(P_MaxValue,              0.0);
        setDoubleParam(P_MeanValue,             0.0);

        printf("Come after Create Parameters and set defaults for these parameters\n");
        printf("Come before create background thread\n");
        status = (asynStatus)(epicsThreadCreate("simScope",
                        epicsThreadPriorityMedium,
                        epicsThreadGetStackSize(epicsThreadStackMedium),
                        (EPICSTHREADFUNC)::simTask,
                        (void *)this) == NULL);
        printf("Come after create background thread\n");

        if (status){
                printf("%s:%s: epicsThreadCreate failure\n", driverName, functionName);
                return;
        }

        printf("Come to the end of contructing simScope Intances: portName: %s, maxPoints:%d\n", portName, maxPoints);
}

void simScope::setVertGain()
{
        epicsInt32 igain, i;
        double gain;

        // P_VertGainSelect for mbbo  to Vert Gain
        getIntegerParam(P_VertGainSelect,       &igain);
        gain =(epicsFloat64) igain;
        setDoubleParam(P_VertGain, gain);

        printf("VertGainSelect: %d, VertGain: %lf\n", igain, gain);

        for (i = 0; i < NUM_VERT_SELECTIONS; i++){
                epicsSnprintf(voltsPerDivStrings_[i], MAX_ENUM_STRING_SIZE, "%.2f",allVoltsPerDivSelections[i] / gain);
                voltsPerDivValues_[i] = (int)(allVoltsPerDivSelections[i] / gain * 1000 + 0.5);
                printf("%d: V/Div=%d, %s\n", i+1, voltsPerDivValues_[i], voltsPerDivStrings_[i]);
        }

        //doCallbacksEnum(voltsPerDivStrings_, voltsPerDivValues_, voltsPerDivSeverities_, NUM_VERT_SELECTIONS, P_VoltsPerDivSelect, 0);
        doCallbacksEnum(voltsPerDivStrings_, voltsPerDivValues_, voltsPerDivSeverities_, NUM_VERT_SELECTIONS, P_VoltsPerDivSelect, 0);
}




void simScope::setVoltsPerDiv()
{
        epicsInt32 mVPerDiv;

        getIntegerParam(P_VoltsPerDivSelect,    &mVPerDiv);
        setDoubleParam(P_VoltsPerDiv,           mVPerDiv / 1000.0);
        printf("VoltsPerDivSelect: %d, VoltsPerDiv: %lf\n", mVPerDiv, mVPerDiv/1000.0);
}


/*
 * P_TimePerDivSelect parameter is in micro second
 * P_TimePerDiv parameter is in second
 * */
void simScope::setTimePerDiv()
{
        epicsInt32 microSecPerDiv;

        getIntegerParam(P_TimePerDivSelect,     &microSecPerDiv);
        setDoubleParam(P_TimePerDiv,            microSecPerDiv / 1000000.0);
}

asynStatus simScope::writeInt32(asynUser * pasynUser, epicsInt32 value)
{
        int function = pasynUser->reason;
        asynStatus status = asynSuccess;
        const char * paramName;
        const char * functionName = "writeInt32";

        /* set the value for the parameter */
        status = (asynStatus) setIntegerParam(function, value);
        /*  get name of the parameter */
        getParamName(function, &paramName);

        if (function == P_Run){
                if (value) epicsEventSignal(eventId_);
        }
        else if (function == P_VertGainSelect){
                setVertGain();
        }
        else if (function == P_VoltsPerDivSelect){
                setVoltsPerDiv();
        }
        else if (function == P_TimePerDivSelect){
                setTimePerDiv(); // set P_TimePerDiv parameter according to P_TimePerDivSelect parameter
        }
        else{
        }

        status = (asynStatus) callParamCallbacks();

        if (status){
                epicsSnprintf(pasynUser->errorMessage, pasynUser->errorMessageSize, "%s:%s: status=%d, functino=%d,parameter name=%s, value=%d", driverName, functionName, status, function, paramName, value);
        }
        else{
                asynPrint(pasynUser, ASYN_TRACEIO_DRIVER, "%s:%s: function=%d,parameter name=%s, value=%d", driverName, functionName, function, paramName, value);
        }

        return status;
}

asynStatus simScope::writeFloat64(asynUser * pasynUser, epicsFloat64 value)
{
        int function = pasynUser->reason;
        asynStatus status;
        epicsInt32 run;
        const char * paramName;
        const char * functionName = "writeFloat64";

        status = (asynStatus)setDoubleParam(function, value);

        getParamName(function, &paramName);

        if (function == P_UpdateTime){
                if (value < MIN_UPDATE_TIME){
                        asynPrint(pasynUser, ASYN_TRACE_WARNING, "%s:%s warning, update time too small, changed from %f to %f\n", driverName, functionName, value, MIN_UPDATE_TIME);
                        value = MIN_UPDATE_TIME;
                        setDoubleParam(P_UpdateTime, value);
                }

                getIntegerParam(P_Run, &run);
        }
        else{
        }

        status = (asynStatus) callParamCallbacks();
        if (status){
                epicsSnprintf(pasynUser->errorMessage, pasynUser->errorMessageSize, "%s:%s: status=%d, function=%d, parameter name=%s, value=%f",
                                driverName, functionName, status, function, paramName, value);
        }
        else{
                asynPrint(pasynUser, ASYN_TRACEIO_DRIVER, "%s:%s: function=%d, parameter name = %s, value = %f\n", driverName, functionName, function, paramName, value);
        }

        return status;
}

asynStatus simScope::readFloat64Array(asynUser *pasynUser, epicsFloat64 *value , size_t nElements, size_t *nIn)
{
        int function = pasynUser->reason;
        size_t nCopy;
        epicsInt32 maxPoints;
        asynStatus status = asynSuccess;
        epicsTimeStamp timeStamp;
        const char *functionName = "readFloat64Array";
        const char * paramName;

        getTimeStamp(&timeStamp);
        pasynUser->timestamp = timeStamp;
        getIntegerParam(P_MaxPoints, &maxPoints);
        nCopy = maxPoints;
        getParamName(function, &paramName);

        if (nElements < nCopy) nCopy = nElements;
        if (function == P_Waveform){
                memcpy(value, pData_, nCopy * sizeof(epicsFloat64));
                * nIn = nCopy;
        }
        else if (function == P_TimeBase){
                memcpy(value, pTimeBase_, nCopy * sizeof(epicsFloat64));
                * nIn = nCopy;
        }

        if(status){
                epicsSnprintf(pasynUser->errorMessage, pasynUser->errorMessageSize, "%s:%s: status=%d, function=%d, parameter name=%s", driverName,  functionName, status, function, paramName);
        }
        else{
                asynPrint(pasynUser, ASYN_TRACEIO_DRIVER, "%s:%s: function=%d, parameter name=%s\n", driverName, functionName, function, paramName);
        }

        return status;
}

asynStatus simScope::readEnum(asynUser * pasynUser, char *strings[], int values[], int severities[], size_t nElements, size_t *nIn)
{
        int function = pasynUser->reason;
        size_t i;

        if (function == P_VoltsPerDivSelect){
                for (i = 0; ((i < NUM_VERT_SELECTIONS) && (i < nElements)); i++){
                        if (strings[i]) free(strings[i]);
                        strings[i] = epicsStrDup(voltsPerDivStrings_[i]);
                        values[i] = voltsPerDivValues_[i];
                        severities[i] = 0;
                }
        }
        else{
                *nIn = 0;
                return asynError;
        }

        *nIn = i;

        return asynSuccess;
}

void simScope::simTask()
{
        double timePerDiv, voltsPerDiv, voltOffset, triggerDelay, noiseAmplitude;
        double updateTime, minValue, maxValue, meanValue;
        double time, timeStep;
        double noise, yScale;
        epicsInt32 run, i, maxPoints;
        double pi = 3.1415926;

        printf("Enter in the simTask() functinon:\n");
        lock();

        printf("Enter in loop forever:\n");
        while (1){
                getDoubleParam(P_UpdateTime, &updateTime);
                getIntegerParam(P_Run, &run);

                printf("updateTime: %f, run: %d\n", updateTime, run);
                unlock();

                if (run) {
                        epicsEventWaitWithTimeout(eventId_, updateTime);
                }
                else{
                        printf("Wait for running signal\n");
                        epicsEventWait(eventId_);
                        printf("Receive the running signal\n");
                }

                lock();

                getIntegerParam(P_Run, &run);

                if (!run){
                        continue;
                }

                getIntegerParam(P_MaxPoints, &maxPoints);
                getDoubleParam(P_TimePerDiv, &timePerDiv);
                getDoubleParam(P_VoltsPerDiv, &voltsPerDiv);
                getDoubleParam(P_VoltOffset, &voltOffset);
                getDoubleParam(P_TriggerDelay, &triggerDelay);
                getDoubleParam(P_NoiseAmplitude, &noiseAmplitude);

                getDoubleParam(P_UpdateTime, &updateTime);
                printf("maxpoints:%d, timeperdiv:%f, voltsPerDiv:%f, voltoffset:%f, triggerdelay:%f, noiseampitude:%f, updatetime:%f\n",
                                maxPoints, timePerDiv, voltsPerDiv, voltOffset, triggerDelay, noiseAmplitude, updateTime);
                time = triggerDelay;
                timeStep = timePerDiv * NUM_DIVISIONS / maxPoints;
                minValue = 1e6;
                maxValue = -1e6;
                meanValue = 0.;

                yScale = 1.0 / voltsPerDiv;
                printf("timeStep:%f\n", timeStep);

                for (i = 0; i < maxPoints; i++){
                        noise = noiseAmplitude * (rand() / (double)RAND_MAX - 0.5);
                        pData_[i] = AMPLITUDE * (sin(time * FREQUENCY * 2 * pi)) + noise;
                        if (pData_[i] < minValue){
                                minValue = pData_[i];
                        }
                        if (pData_[i] > maxValue){
                                maxValue = pData_[i];
                        }
                        meanValue += pData_[i];
                        pData_[i] = NUM_DIVISIONS / 2 + yScale * (pData_[i] + voltOffset);
                        time += timeStep;
                }

                updateTimeStamp();
                meanValue = meanValue / maxPoints;

                setDoubleParam(P_MinValue, minValue);
                setDoubleParam(P_MaxValue, maxValue);
                setDoubleParam(P_MeanValue, meanValue);

                printf("min:%f, max:%f, mean:%f\n", minValue, maxValue, meanValue);
                callParamCallbacks();
                doCallbacksFloat64Array(pData_, maxPoints, P_Waveform, 0);
        }
}

void simTask(void * drvPvt)
{
        simScope * pPvt = (simScope *)drvPvt;
        pPvt->simTask();
}


extern "C"{
int simScopeConfigure(const char * portName, int maxPoints)
{
        new simScope(portName, maxPoints);
        return asynSuccess;
}

static const iocshArg initArg0 = {"portName", iocshArgString};
static const iocshArg initArg1 = {"max points", iocshArgInt};
static const iocshArg * const initArgs[] = {&initArg0, &initArg1};

static const iocshFuncDef initFuncDef = {"simScopeConfigure", 2, initArgs};

static void initCallFunc(const iocshArgBuf * args)
{
        simScopeConfigure(args[0].sval, args[1].ival);
}

void simScopeRegister(void)
{
        iocshRegister(&initFuncDef, initCallFunc);
}

epicsExportRegistrar(simScopeRegister);
}

c)  simScopeSupport.dbd:

registrar("simScopeRegister")

d) 修改所编写源文件目录下的Makefile文件,指定需要链接的库文件以及源文件及支持文件:

TOP=../..

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

#=============================
# Build the IOC application

PROD_IOC = simScope
# simScope.dbd will be created and installed
DBD += simScope.dbd

# simScope.dbd will be made up from these files:
simScope_DBD += base.dbd
simScope_DBD += simScopeSupport.dbd

# Include dbd files from all support applications:
simScope_DBD += asyn.dbd

# Add all the support libraries needed by this IOC
simScope_LIBS += asyn


simScope_SRCS += simScope.cpp
# simScope_registerRecordDeviceDriver.cpp derives from simScope.dbd
simScope_SRCS += simScope_registerRecordDeviceDriver.cpp

# Build the main IOC entry point on workstation OSs.
simScope_SRCS_DEFAULT += simScopeMain.cpp
simScope_SRCS_vxWorks += -nil-

# Add support from base/src/vxWorks if needed
#simScope_OBJS_vxWorks += $(EPICS_BASE_BIN)/vxComLibrary

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

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

include $(TOP)/configure/RULES
#----------------------------------------
#  ADD RULES AFTER THIS LINE

4) 3) 进入simScopeApp/Db/目录下下编写记录支持数据库文件simScope.db并且将其添加到相同路径下的Makefile文件中:

# These records control run/stop --> P_Run
record(bo, "$(P)$(R)Run")
{
        field(PINI,     "1")
        field(DTYP,     "asynInt32")
        field(OUT,      "@asyn($(PORT), $(ADDR), $(TIMEOUT))SCOPE_RUN")
        field(ZNAM,     "Stop")
        field(ONAM,     "Run")
}

record(bi, "$(P)$(R)Run_RBV")
{
        field(PINI,     "1")
        field(DTYP,     "asynInt32")
        field(INP,      "@asyn($(PORT), $(ADDR), $(TIMEOUT))SCOPE_RUN")
        field(ZNAM,     "Done")
        field(ONAM,     "Running")
        field(OSV,      "MINOR")
        field(SCAN,     "I/O Intr")
}

## This record is the number of points in the data array ---> P_MaxPoints
## readonly, set in startup
record(longin, "$(P)$(R)MaxPoints_RBV")
{
        field(PINI,     "1")
        field(DTYP,     "asynInt32")
        field(INP,      "@asyn($(PORT), $(ADDR), $(TIMEOUT))SCOPE_MAX_POINTS")
        field(SCAN,     "I/O Intr")
}

# There recrods are the choices for the Time Per Div Select ---> P_TimePerDivSelect
record(mbbo, "$(P)$(R)TimePerDivSelect")
{
        field(PINI,     "1")
        field(DTYP,     "asynInt32")
        field(OUT,      "@asyn($(PORT), $(ADDR), $(TIMEOUT))SCOPE_TIME_PER_DIV_SELECT")
        field(ZRST,     "0.01 msec")
        field(ZRVL,     "10")
        field(ONST,     "0.02 msec")
        field(ONVL,     "20")
        field(TWST,     "0.05 msec")
        field(TWVL,     "50")
        field(THST,     "0.1 msec")
        field(THVL,     "100")
        field(FRST,     "0.2 msec")
        field(FRVL,     "200")
        field(FVST,     "0.5 msec")
        field(FVVL,     "500")
        field(SXST,     "1 msec")
        field(SXVL,     "1000")
        field(SVST,     "2 msec")
        field(SVVL,     "2000")
        field(EIST,     "5 msec")
        field(EIVL,     "5000")
        field(NIST,     "10 msec")
        field(NIVL,     "10000")
        field(TEST,     "20 msec")
        field(TEVL,     "20000")
        field(ELST,     "50 msec")
        field(ELVL,     "50000")
        field(TVST,     "100 msec")
        field(TVVL,     "100000")
}
#
## P_TimePerDiv
record(ai, "$(P)$(R)TimePerDiv_RBV")
{
        field(PINI,     "1")
        field(DTYP,     "asynFloat64")
        field(INP,      "@asyn($(PORT), $(ADDR), $(TIMEOUT))SCOPE_TIME_PER_DIV")
        field(PREC,     "5")
        field(SCAN,     "I/O Intr")
}
#
## These records is for Vert Gain
## P_VertGainSelect
record(mbbo,    "$(P)$(R)VertGainSelect")
{
        field(PINI,     "1")
        field(DTYP,     "asynInt32")
        field(OUT,      "@asyn($(PORT), $(ADDR), $(TIMEOUT))SCOPE_VERT_GAIN_SELECT")
        field(ZRST,     "1 X")
        field(ZRVL,     "1")
        field(ONST,     "2 X")
        field(ONVL,     "2")
        field(TWST,     "5 X")
        field(TWVL,     "5")
        field(THST,     "10 X")
        field(THVL,     "10")
        field(FRST,     "100 X")
        field(FRVL,     "100")
}

# P_VertGain
record(ai,      "$(P)$(R)VertGain_RBV")
{
        field(PINI,     "1")
        field(INP,      "@asyn($(PORT), $(ADDR), $(TIMEOUT))SCOPE_VERT_GAIN")
        field(DTYP,     "asynFloat64")
        field(PREC,     "1")
        field(SCAN,     "I/O Intr")
}
#
#
record(mbbo, "$(P)$(R)VoltsPerDivSelect")
{
   field(PINI, "1")
   field(DTYP, "asynInt32")
   field(OUT,  "@asyn($(PORT),$(ADDR),$(TIMEOUT))SCOPE_VOLTS_PER_DIV_SELECT")
   field(ZRST, "Garbage")
   field(ZRVL, "0")
}
#
record(mbbi, "$(P)$(R)VoltsPerDivSelect_RBV")
{
   field(DTYP, "asynInt32")
   field(INP,  "@asyn($(PORT),$(ADDR),$(TIMEOUT))SCOPE_VOLTS_PER_DIV_SELECT")
   field(ZRST, "Garbage")
   field(ZRVL, "0")
   field(SCAN, "I/O Intr")
}
#
record(ai, "$(P)$(R)VoltsPerDiv_RBV")
{
   field(PINI, "1")
   field(DTYP, "asynFloat64")
   field(INP,  "@asyn($(PORT),$(ADDR),$(TIMEOUT))SCOPE_VOLTS_PER_DIV")
   field(PREC, "2")
   field(SCAN, "I/O Intr")
}
## This record to set the offset
## P_VoltOffset
record(ao,      "$(P)$(R)VoltOffset")
{
        field(PINI,     "1")
        field(DTYP,     "asynFloat64")
        field(OUT,      "@asyn($(PORT), $(ADDR), $(TIMEOUT))SCOPE_VOLT_OFFSET")
        field(PREC,     "3")
}

record(ai,      "$(P)$(R)VoltOffset_RBV")
{
        field(PINI,     "1")
        field(DTYP,     "asynFloat64")
        field(INP,      "@asyn($(PORT), $(ADDR), $(TIMEOUT))SCOPE_VOLT_OFFSET")
        field(PREC,     "3")
        field(SCAN,     "I/O Intr")
}

# This record to set trigger delay time
record(ao,      "$(P)$(R)TriggerDelay")
{
        field(PINI,     "1")
        field(DTYP,     "asynFloat64")
        field(OUT,      "@asyn($(PORT), $(ADDR), $(TIMEOUT))SCOPE_TRIGGER_DELAY")
        field(PREC,     "5")
}

record(ai,      "$(P)$(R)TriggerDelay_RBV")
{
        field(PINI,     "1")
        field(DTYP,     "asynFloat64")
        field(INP,      "@asyn($(PORT), $(ADDR), $(TIMEOUT))SCOPE_TRIGGER_DELAY")
        field(PREC,     "5")
        field(SCAN,     "I/O Intr")
}

# This record to control noise in the signal
# P_NoiseAmplitude
record(ao,      "$(P)$(R)NoiseAmplitude")
{
        field(PINI,     "1")
        field(DTYP,     "asynFloat64")
        field(OUT,      "@asyn($(PORT), $(ADDR), $(TIMEOUT))SCOPE_NOISE_AMPLITUDE")
        field(PREC,     "3")
}


record(ai,      "$(P)$(R)NoiseAmplitude_RBV")
{
        field(PINI,     "1")
        field(DTYP,     "asynFloat64")
        field(INP,      "@asyn($(PORT), $(ADDR), $(TIMEOUT))SCOPE_NOISE_AMPLITUDE")
        field(PREC,     "3")
        field(SCAN,     "I/O Intr")
}
#
# This record to control the update time
record(ao,      "$(P)$(R)UpdateTime")
{
        field(PINI,     "1")
        field(DTYP,     "asynFloat64")
        field(OUT,      "@asyn($(PORT), $(ADDR), $(TIMEOUT))SCOPE_UPDATE_TIME")
        field(PREC,     "3")
}

record(ai,      "$(P)$(R)UpdateTime_RBV")
{
        field(PINI,     "1")
        field(DTYP,     "asynFloat64")
        field(INP,      "@asyn($(PORT), $(ADDR), $(TIMEOUT))SCOPE_UPDATE_TIME")
        field(PREC,     "3")
        field(SCAN,     "I/O Intr")
}

# This record is waveform
record(waveform,        "$(P)$(R)Waveform_RBV")
{
        field(PINI,     "1")
        field(DTYP,     "asynFloat64ArrayIn")
        field(INP,      "@asyn($(PORT), $(ADDR), $(TIMEOUT))SCOPE_WAVEFORM")
        field(NELM,     "$(NPOINTS)")
        field(FTVL,     "DOUBLE")
        field(LOPR,     "0")
        field(HOPR,     "10")
        field(SCAN,     "I/O Intr")
}

# This record is time base
record(waveform,        "$(P)$(R)TimeBase_RBV")
{
        field(PINI,     "1")
        field(DTYP,     "asynFloat64ArrayIn")
        field(INP,      "@asyn($(PORT), $(ADDR), $(TIMEOUT))SCOPE_TIME_BASE")
        field(NELM,     "$(NPOINTS)")
        field(FTVL,     "DOUBLE")
        field(LOPR,     "0")
        field(HOPR,     "10")
        field(SCAN,     "I/O Intr")
}

# This record is min value
record(ai,      "$(P)$(R)MinValue_RBV")
{
        field(PINI,     "1")
        field(DTYP,     "asynFloat64")
        field(INP,      "@asyn($(PORT), $(ADDR), $(TIMEOUT))SCOPE_MIN_VALUE")
        field(PREC,     "4")
        field(SCAN,     "I/O Intr")
}


record(ai,      "$(P)$(R)MaxValue_RBV")
{
        field(PINI,     "1")
        field(DTYP,     "asynFloat64")
        field(INP,      "@asyn($(PORT), $(ADDR), $(TIMEOUT))SCOPE_MAX_VALUE")
        field(PREC,     "4")
        field(SCAN,     "I/O Intr")
}

record(ai,      "$(P)$(R)MeanValue_RBV")
{
        field(PINI,     "1")
        field(DTYP,     "asynFloat64")
        field(INP,      "@asyn($(PORT), $(ADDR), $(TIMEOUT))SCOPE_MEAN_VALUE")
        field(PREC,     "4")
        field(SCAN,     "I/O Intr")
}

Makefile中添加:DB += simScope.db

5)回到这个IOC的顶层目录,即:simScope,执行make命令,进行程序编译。

6)进入启动目录iocBoot/iocsimScope,修改启动脚本文件st.cmd:

#!../../bin/linux-aarch64/simScope

#- You may have to change simScope to something else
#- everywhere it appears in this file

< envPaths

cd "${TOP}"

## Register all support components
dbLoadDatabase "dbd/simScope.dbd"
simScope_registerRecordDeviceDriver pdbbase
simScopeConfigure("testSimScope", 1000)

## Load record instances
dbLoadRecords("db/simScope.db","P=SimScope:,R=Device1:,PORT=testSimScope,ADDR=0,TIMEOUT=1, NPOINTS=1000")

cd "${TOP}/iocBoot/${IOC}"
iocInit

7) 启动这个IOC程序:

../../bin/linux-aarch64/simScope st.cmd

8) 查看这个IOC下的所有加载记录:

epics> dbl
SimScope:Device1:TimePerDiv_RBV
SimScope:Device1:VertGain_RBV
SimScope:Device1:VoltsPerDiv_RBV
SimScope:Device1:VoltOffset_RBV
SimScope:Device1:TriggerDelay_RBV
SimScope:Device1:NoiseAmplitude_RBV
SimScope:Device1:UpdateTime_RBV
SimScope:Device1:MinValue_RBV
SimScope:Device1:MaxValue_RBV
SimScope:Device1:MeanValue_RBV
SimScope:Device1:VoltOffset
SimScope:Device1:TriggerDelay
SimScope:Device1:NoiseAmplitude
SimScope:Device1:UpdateTime
SimScope:Device1:Run_RBV
SimScope:Device1:Run
SimScope:Device1:MaxPoints_RBV
SimScope:Device1:VoltsPerDivSelect_RBV
SimScope:Device1:TimePerDivSelect
SimScope:Device1:VertGainSelect
SimScope:Device1:VoltsPerDivSelect
SimScope:Device1:Waveform_RBV
SimScope:Device1:TimeBase_RBV

9) 使用CSS显示以上运行的记录数据库:

在Settings区域,可以选择设置垂直增益,每个刻度电压值,电压偏移,触发延时,正弦波更新周期,以及每个水平刻度表示的时间量。

在User Operate区域中,可以启动/停止波形的产生。

在Running Status区域可以显示运行状态。

在Statics Info区域中显示波形数据的统计信息。

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.coloradmin.cn/o/1135609.html

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

ThinkPad电脑HDMI接口失灵如何解决?

ThinkPad电脑HDMI接口失灵如何解决&#xff1f; 如果平时正常使用的外接显示器&#xff0c;某天突然无法使用了&#xff0c;重新插拔依然无信号的话&#xff0c;可以打开系统的设备管理器&#xff08;快捷键winx&#xff09;&#xff0c;首先看一下监视器的识别情况&#xff0c…

人声分离神仙网站,用过都说好~

在生活中好听的音乐有千千万的&#xff0c;音乐是非常容易可以找到下载下来的&#xff0c;但是背景音乐相当不容易找的&#xff0c;我们看的某短视频的背景音乐我们觉得不错的&#xff0c;想要下载下来的时候&#xff0c;我们都会无从下手不知道如何才可以找到这个相关的背景音…

内网渗透-内网信息收集

内网信息收集 前言 当我们进行外网信息收集&#xff0c;漏洞探测以及漏洞利用后&#xff0c;获得了主机的权限后&#xff0c;我们需要扩大渗透的战果时&#xff0c;这是我们就要进行内网的渗透了&#xff0c;内网渗透最重要的还是前期的信息收集的操作了&#xff0c;就是我们的…

文件加密丨最值得收藏的3种方法

信息的安全性变得越来越重要。文件加密作为一种有效的信息安全保护手段&#xff0c;广泛应用于各类场景。 今天就分享3种值得小白收藏的文件加密的方法&#xff1a; 方法一 简单加密 简单加密是一种常见的文件加密方法&#xff0c;其原理是通过使用简单的加密算法和密钥&…

YUV格式详解

YUV 可以将亮度信息&#xff08;Y&#xff09;与色度信息&#xff08;UV&#xff09;分离&#xff0c;没有UV信息一样可以显示完整图像&#xff0c;只不过是黑白的,也是一种颜色编码方法&#xff0c;&#xff0c;YUV和RGB可以通过公式互相转换&#xff0c;图片中每一个像素的颜…

响应式网站建站源码系统+完整的搭建教程

互联网已成为人们生活中不可或缺的一部分。在这个信息爆炸的时代&#xff0c;企业和个人对网站的需求不再仅仅是展示信息&#xff0c;而是要求网站能够适应各种设备、屏幕尺寸和网络环境&#xff0c;以便更好地与用户进行互动。因此&#xff0c;响应式网站建设应运而生&#xf…

使用Jenkins触发gitlab的webhook

满足条件&#xff1a; 首先手动构建可以完成构建 例如&#xff1a; 打开项目点击配置 在“Build Triggers”栏勾选&#xff0c;Build when a change is pushed to GitLab. GitLab webhook &#xff1b;如下 复制URL链接&#xff0c;我的链接是&#xff1a;http://192.168.44…

23款奔驰E300L升级几何多光束大灯 车辆自检等功能

奔驰几何多光束大灯核心特点就是通过内部的84颗可独立控制的LED光源&#xff0c;行车远光灯会甄别对向驶来的车辆或者行人&#xff0c;并且动态的跟随目标&#xff0c;之后阴影话该区域&#xff0c;避免晃到车辆和行人。 奔驰升级几何多光束 LED 大灯&#xff08;MULTIBEAM LED…

TypeError: data.reduce is not a function:数据类型不匹配

错误展示&#xff1a; 错误分析&#xff1a; 首先来看看前端代码&#xff1a;我表格绑定的数据模型是tableData&#xff0c;而我tableData定义的是一个数组 其次看看后端给的数据&#xff1a; 传递的是一个对象&#xff0c;而不是一个数组&#xff01; 这样原因就找出了&…

Spring如何使用三级缓存解决循环依赖问题?

Spring框架中采用了"三级缓存"&#xff08;三级缓存是一种缓存解决循环依赖的数据结构&#xff09;来解决循环依赖问题&#xff0c;其中缓存包括singletonObjects、earlySingletonObjects和singletonFactories。 第一级缓存 - singletonObjects&#xff1a; 在Spr…

Qt跨平台(统信UOS)各种坑解决办法

记录Qt跨平台的坑&#xff0c;方便日后翻阅。 一、环境安装 本人用的是qt 5.14.2.直接在官网下载即可。地址&#xff1a;Index of /archive/qt/5.14/5.14.2 下载linux版本。 下载之后 添加可执行权限。 chmod 777 qt-opensource-linux-x64-5.14.2.run 然后执行。 出现坑1…

个头小却很能“打”!合合信息扫描全能王推出A4便携式打印机

过去&#xff0c;为了打印一份清晰工整的材料&#xff0c;人们往往需要到专门的打印店或办公室。处理文件。对于销售、物流人员、工程师、医生、媒体记者等出差频率较高的职业而言&#xff0c;打印是一项“不太友好”的需求。为解决移动打印难题&#xff0c;近期&#xff0c;合…

嵌入式学习笔记(63)指针到底是什么

3.1.1.指针变量和普通变量的区别 首先必须非常明确&#xff1a;指针的实质就是个变量&#xff0c;它跟普通变量没有任何本质区别。指针完整的名字叫指针变量&#xff0c;简称指针。 3.1.2.为什么需要指针 (1)指针的出现是为了实现间接访问。在汇编中都有间接访问&#xff08…

众和策略可靠吗?b股指数是什么代码?

可靠 B股指数&#xff08;BShare Index&#xff09;是指由上海证券买卖所和深圳证券买卖所一起编制的反映我国两个证券商场B股出资价值变化的指数。作为我国证券商场中的重要指数之一&#xff0c;许多出资者都想了解B股指数的代码是什么。 B股指数代码 B股指数代码是指B股买卖…

应届生如何找到适合自己的项目

去开源网站 搜索技术点项目, 按照星级排序 不要只是跟着敲代码 那样什么都学不到,脑子是停转的 要自己理解业务流程,然后自己先试着实现,简单的crud要会,复杂的肯定会遇到问题,这个时候再去参考他给的代码 选择以下比较通用的业务来深度耕耘 模块如何吃透 例如权限认证: 功能实…

MutationObserver详解

MutationObserver API 让我们能监听 DOM 树变化&#xff0c;该 API 设计用来替换掉在 DOM 3 事件规范中引入的 Mutation events。 Mutation events 是同步触发的&#xff0c;每次变动都会触发一次调用。 MutationObserver API 是异步触发的&#xff0c; DOM 的变动并不会马上触…

YOLOv5— Fruit Detection

&#x1f368; 本文为[&#x1f517;365天深度学习训练营学习记录博客 &#x1f366; 参考文章&#xff1a;365天深度学习训练营-第7周&#xff1a;咖啡豆识别&#xff08;训练营内部成员可读&#xff09; &#x1f356; 原作者&#xff1a;[K同学啊 | 接辅导、项目定制](https…

重庆助理工程师申请步骤及注意事项

目录 一、前言二、步骤1. 职称系统网址 2. 一定使用谷歌浏览器&#xff0c;其他白搭三、材料准备1.思想和工作-要手写签字并盖单位公章&#xff0c;无模板2.近五年年度考核-填优秀&#xff0c;并改单位公章&#xff0c;无模板 四、流程1.单位公示要公示5个工作日&#xff0c;再…

量化网络的注意事项

二&#xff0c;量化算术 模型量化过程可以分为两部分&#xff1a;将模型从 FP32 转换为 INT8&#xff0c;以及使用 INT8 进行推理。本节说明这两部分背后的算术原理。如果不了解基础算术原理&#xff0c;在考虑量化细节时通常会感到困惑。 2.1&#xff0c;定点和浮点 定点和…

【密评】商用密码应用安全性评估从业人员考核题库(十三)

商用密码应用安全性评估从业人员考核题库&#xff08;十三&#xff09; 国密局给的参考题库5000道只是基础题&#xff0c;后续更新完5000还会继续更其他高质量题库&#xff0c;持续学习&#xff0c;共同进步。 3001 单项选择题 在GM/T 0082 《可信密码模块保护轮廓》中&#x…