Files
epics-base/src/rec/recScan.c
1995-04-19 18:58:50 +00:00

2422 lines
84 KiB
C
Raw Blame History

This file contains invisible Unicode characters
This file contains invisible Unicode characters that are indistinguishable to humans but may be processed differently by a computer. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
/* recScan.c */
/*
* Original Author: Ned D. Arnold
* Date: 07-18-94
*
* Experimental Physics and Industrial Control System (EPICS)
*
* Copyright 1991, the Regents of the University of California,
* and the University of Chicago Board of Governors.
*
* This software was produced under U.S. Government contracts:
* (W-7405-ENG-36) at the Los Alamos National Laboratory,
* and (W-31-109-ENG-38) at Argonne National Laboratory.
*
* Initial development by:
* The Controls and Automation Group (AT-8)
* Ground Test Accelerator
* Accelerator Technology Division
* Los Alamos National Laboratory
*
* Co-developed with
* The Controls and Computing Group
* Accelerator Systems Division
* Advanced Photon Source
* Argonne National Laboratory
*
*
* Modification Log:
* -----------------
* .01 07-18-94 nda significantly expanded functionality from prototype
* .02 08-18-94 nda Starting with R3.11.6, dbGetField locks the record
* before fetching the data. This can cause deadlocks
* within a database. Change all dbGetField() to dbGet()
* .03 08-23-94 nda added code for checking/adjusting linear scan
* params (it gets a little messy !)
* .04 08-25-94 nda Added check of scan positions vs Positioner Control
* Limits
* .05 08-29-94 nda Added "viewScanPos" that puts desired positions
* in D1 array any time a scan parameter is changed
* .06 10-03-94 nda added code for enumerated string .CMND. Changed
* .EXSC to a SHORT in record definition. Added VERSION
* for .VERS field (1.06) to keep track of version.
* .07 10-21-94 nda changed linear scan parameter algorithms so changing
* start/end modifies step/width unless frozen. This
* seems more intuitive.
* .08 12-06-94 nda added support for .FFO .When set to 1, frzFlag values
* are saved in recPvtStruct. Restored when FFO set to 0.
* .09 02-02-95 nda fixed order of posting monitors to be what people
* expect (i.e. .cpt, .pxdv, .dxcv)
* .10 02-10-95 nda fixed on-the-fly so 1st step is to end position
* .11 02-21-95 nda added "Return To Start" flag. If set, positioners
* will be commanded to the start pos after the scan.
* .12 03-02-95 nda added positioner readback arrays (PxRA). These arrays
* will contain actual readback positions (if RxPV are
* defined. If not, the desired positions will be loaded
* into them.
* .13 03-02-95 nda Post .val field when a new point is complete during a
* scan. This will assist in poin by point plots.
* .14 03-02-95 nda Bug fix on filling PxRA's. ALWAYS CALL CHCK_MOTORS.
* .15 03-15-95 nda If no readback PV (RxPV) is specified, copy desired
* value (PxDV) to current value (RxCV). Now, plotting
* programs can always monitor RxCV.
* .16 04-03-95 nda If PV field = DESC, change to VAL
*/
#define VERSION 1.16
#include <vxWorks.h>
#include <types.h>
#include <stdioLib.h>
#include <lstLib.h>
#include <string.h>
#include <math.h>
#include <tickLib.h>
#include <semLib.h>
#include <taskLib.h>
#include <alarm.h>
#include <cvtTable.h>
#include <dbDefs.h>
#include <dbAccess.h>
#include <dbScan.h>
#include <dbDefs.h>
#include <dbFldTypes.h>
#include <devSup.h>
#include <errMdef.h>
#include <recSup.h>
#include <special.h>
#include <choiceScan.h>
#include <scanRecord.h>
#include <callback.h>
#include <taskwd.h>
/* Create RSET - Record Support Entry Table*/
#define report NULL
#define initialize NULL
static long init_record();
static long process();
static long special();
static long get_value();
static long cvt_dbaddr();
static long get_array_info();
static long put_array_info();
static long get_units();
static long get_precision();
static long get_enum_str();
static long get_enum_strs();
static long put_enum_str();
static long get_graphic_double();
static long get_control_double();
static long get_alarm_double();
struct rset scanRSET={
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
};
struct p_limits {
DBRctrlDouble
float value;
};
struct recPvtStruct {
CALLBACK doPutsCallback;/* do output links callback structure */
struct scanRecord *pscan; /* ptr to record which needs work done */
short phase; /* what to do to the above record */
short validRbPvs; /* at least 1 valid Readback PV name */
short validDtPvs; /* at least 1 valid Detector Trig PV */
short validDataBuf; /* which data array buffer is valid */
float *pdet1Fill; /* points to data array to be filled */
float *pdet1DataA; /* points to data array A */
float *pdet1DataB; /* points to data array B */
float *pdet2Fill;
float *pdet2DataA;
float *pdet2DataB;
float *pdet3Fill;
float *pdet3DataA;
float *pdet3DataB;
float *pdet4Fill;
float *pdet4DataA;
float *pdet4DataB;
struct p_limits *pP1Limits;
struct p_limits *pP2Limits;
struct p_limits *pP3Limits;
struct p_limits *pP4Limits;
short pffo; /* previouss state of ffo */
short fpts; /* backup copy of all freeze flags */
short p1fs;
short p1fi;
short p1fc;
short p1fe;
short p1fw;
short p2fs;
short p2fi;
short p2fc;
short p2fe;
short p2fw;
short p3fs;
short p3fi;
short p3fc;
short p3fe;
short p3fw;
short p4fs;
short p4fi;
short p4fc;
short p4fe;
short p4fw;
unsigned long tickStart; /* used to time the scan */
unsigned char scanErr;
unsigned char nptsCause; /* who caused the "# of points to change:
0-operator; 1-4 Positioners*/
};
/* the following structure must match EXACTLY with the order and type of
fields defined in scanRecord.h for each positioner (even including
the "Created Pad"s */
struct linScanParms {
float p_sp; /* Start Position */
unsigned short p_fs; /* Freeze Start Pos */
char p76 [2]; /* Created Pad */
float p_si; /* Step Increment */
unsigned short p_fi; /* Freeze Step Inc */
char p77 [2]; /* Created Pad */
float p_cp; /* Center Position */
unsigned short p_fc; /* Freeze Center Pos */
char p78 [2]; /* Created Pad */
float p_ep; /* End Position */
unsigned short p_fe; /* Freeze End Pos */
char p79 [2]; /* Created Pad */
float p_wd; /* Scan Width */
unsigned short p_fw; /* Freeze Width */
char p80 [2]; /* Created Pad */
};
/***************************
Declare constants
***************************/
#define DEF_WF_SIZE 100
#define PVN_SIZE 40
#define NUM_DYN_PVS 14
#define MIN_MON 3 /* # of ticks between monitor postings. 3 = 50 ms */
#define A_BUFFER 0
#define B_BUFFER 1
#define IDLE 0
#define MOVE_MOTORS 1
#define CHCK_MOTORS 2
#define TRIG_DETCTRS 3
#define READ_DETCTRS 4
#define CLEAR_MSG 0
#define CHECK_LIMITS 1
/* forward declarations */
static void checkMonitors();
static void lookupPVs();
static void initScan();
static void contScan();
static void endScan();
static void doPuts();
static void adjLinParms();
static void changedNpts();
static void checkScanLimits();
static void drawPos1Scan();
static void saveFrzFlags();
static void resetFrzFlags();
static void restoreFrzFlags();
/* variables ... */
long scanRecDebug=0;
long viewScanPos=0;
static long init_record(pscan,pass)
struct scanRecord *pscan;
int pass;
{
struct recPvtStruct *precPvt = (struct recPvtStruct *)pscan->rpvt;
long status = 0;
if (pass==0) {
pscan->vers = VERSION;
if(pscan->mpts < 100) pscan->mpts = DEF_WF_SIZE;
pscan->p1db = calloc(1, sizeof(struct dbAddr));
pscan->p2db = calloc(1, sizeof(struct dbAddr));
pscan->p3db = calloc(1, sizeof(struct dbAddr));
pscan->p4db = calloc(1, sizeof(struct dbAddr));
pscan->r1db = calloc(1, sizeof(struct dbAddr));
pscan->r2db = calloc(1, sizeof(struct dbAddr));
pscan->r3db = calloc(1, sizeof(struct dbAddr));
pscan->r4db = calloc(1, sizeof(struct dbAddr));
pscan->t1db = calloc(1, sizeof(struct dbAddr));
pscan->t2db = calloc(1, sizeof(struct dbAddr));
pscan->d1db = calloc(1, sizeof(struct dbAddr));
pscan->d2db = calloc(1, sizeof(struct dbAddr));
pscan->d3db = calloc(1, sizeof(struct dbAddr));
pscan->d4db = calloc(1, sizeof(struct dbAddr));
pscan->p1pa = (float *) calloc(pscan->mpts, sizeof(float));
pscan->p2pa = (float *) calloc(pscan->mpts, sizeof(float));
pscan->p3pa = (float *) calloc(pscan->mpts, sizeof(float));
pscan->p4pa = (float *) calloc(pscan->mpts, sizeof(float));
pscan->p1ra = (float *) calloc(pscan->mpts, sizeof(float));
pscan->p2ra = (float *) calloc(pscan->mpts, sizeof(float));
pscan->p3ra = (float *) calloc(pscan->mpts, sizeof(float));
pscan->p4ra = (float *) calloc(pscan->mpts, sizeof(float));
/* First time through, rpvt needs initialized */
pscan->rpvt = calloc(1, sizeof(struct recPvtStruct));
precPvt = (struct recPvtStruct *)pscan->rpvt;
precPvt->pdet1DataA = (float *) calloc(pscan->mpts, sizeof(float));
precPvt->pdet1DataB = (float *) calloc(pscan->mpts, sizeof(float));
precPvt->pdet2DataA = (float *) calloc(pscan->mpts, sizeof(float));
precPvt->pdet2DataB = (float *) calloc(pscan->mpts, sizeof(float));
precPvt->pdet3DataA = (float *) calloc(pscan->mpts, sizeof(float));
precPvt->pdet3DataB = (float *) calloc(pscan->mpts, sizeof(float));
precPvt->pdet4DataA = (float *) calloc(pscan->mpts, sizeof(float));
precPvt->pdet4DataB = (float *) calloc(pscan->mpts, sizeof(float));
precPvt->pP1Limits = (struct p_limits *)calloc(1, sizeof(struct p_limits));
precPvt->pP2Limits = (struct p_limits *)calloc(1, sizeof(struct p_limits));
precPvt->pP3Limits = (struct p_limits *)calloc(1, sizeof(struct p_limits));
precPvt->pP4Limits = (struct p_limits *)calloc(1, sizeof(struct p_limits));
/* initialize array fill pointers to buffer A, consider B_BUFFER valid */
precPvt->pdet1Fill = precPvt->pdet1DataA;
precPvt->pdet2Fill = precPvt->pdet2DataA;
precPvt->pdet3Fill = precPvt->pdet3DataA;
precPvt->pdet4Fill = precPvt->pdet4DataA;
precPvt->validDataBuf = B_BUFFER;
pscan->d1da = precPvt->pdet1DataB;
pscan->d2da = precPvt->pdet2DataB;
pscan->d3da = precPvt->pdet3DataB;
pscan->d4da = precPvt->pdet4DataB;
return(0);
}
callbackSetCallback(doPuts, &precPvt->doPutsCallback);
callbackSetPriority(pscan->prio, &precPvt->doPutsCallback);
precPvt->pscan = pscan;
lookupPVs(pscan);
/* initialize all linear scan fields */
precPvt->nptsCause = 0; /* resolve all positioner parameters */
changedNpts(pscan);
if(pscan->ffo) {
saveFrzFlags(pscan);
resetFrzFlags(pscan);
}
/* init field values */
pscan->exsc = 0;
pscan->pxsc = 0;
return(0);
}
static long process(pscan)
struct scanRecord *pscan;
{
struct recPvtStruct *precPvt = (struct recPvtStruct *)pscan->rpvt;
long status = 0;
/* Begin Scan cycle or continue scan cycle */
if ((pscan->pxsc == 0) && (pscan->exsc == 1)) {
if(scanRecDebug) {
precPvt->tickStart = tickGet();
}
pscan->cpt = 0; /* reset point counter */
initScan(pscan);
sprintf(pscan->smsg,"Scanning ...");
db_post_events(pscan,&pscan->smsg,DBE_VALUE);
}
else if ((pscan->pxsc == 1) && (pscan->exsc == 0)) {
sprintf(pscan->smsg,"Scan aborted by operator");
db_post_events(pscan,&pscan->smsg,DBE_VALUE);
endScan(pscan);
}
else if (pscan->exsc == 1) {
contScan(pscan);
}
checkMonitors(pscan);
/* do forward link on last scan aquisition */
if ((pscan->pxsc == 1) && (pscan->exsc == 0)) {
recGblFwdLink(pscan); /* process the forward scan link record */
if(scanRecDebug) {
printf("Scan Time = %.2f ms\n",
(float)((tickGet()-(precPvt->tickStart))*16.67));
}
}
pscan->pxsc = pscan->exsc;
recGblResetAlarms(pscan);
recGblGetTimeStamp(pscan);
pscan->pact = FALSE;
return(status);
}
static long special(paddr,after)
struct dbAddr *paddr;
int after;
{
struct scanRecord *pscan = (struct scanRecord *)(paddr->precord);
struct recPvtStruct *precPvt = (struct recPvtStruct *)pscan->rpvt;
int special_type = paddr->special;
long status;
unsigned char prevAlrt;
if(!after) {
precPvt->pffo = pscan->ffo; /* save previous ffo flag */
return(0);
}
switch(special_type) {
case(SPC_MOD):
if(paddr->pfield==(void *)&pscan->exsc) {
pscan->alrt = 0;
db_post_events(pscan,&pscan->alrt, DBE_VALUE);
scanOnce(pscan);
return(0);
} else if(paddr->pfield==(void *)&pscan->cmnd) {
if(pscan->cmnd == CLEAR_MSG) {
sprintf(pscan->smsg,"");
db_post_events(pscan,&pscan->smsg,DBE_VALUE);
}
else if(pscan->cmnd == CHECK_LIMITS) {
prevAlrt = pscan->alrt;
pscan->alrt = 0;
checkScanLimits(pscan);
db_post_events(pscan,&pscan->smsg,DBE_VALUE);
if(pscan->alrt != prevAlrt) {
db_post_events(pscan,&pscan->alrt,DBE_VALUE);
}
}
return(0);
} else if((paddr->pfield >= (void *)pscan->p1pv) &&
(paddr->pfield <= (void *)pscan->d4pv)) {
lookupPVs(pscan);
return(0);
} else if(paddr->pfield==(void *)&pscan->prio) {
callbackSetPriority(pscan->prio, &precPvt->doPutsCallback);
return(0);
}
break;
case(SPC_SC_S): /* linear scan parameter change */
case(SPC_SC_I):
case(SPC_SC_E):
case(SPC_SC_C):
case(SPC_SC_W):
/* resolve linear scan parameters affected by this fields change */
prevAlrt = pscan->alrt;
pscan->alrt = 0;
sprintf(pscan->smsg,"");
adjLinParms(paddr);
db_post_events(pscan,&pscan->smsg,DBE_VALUE);
if(pscan->alrt != prevAlrt) {
db_post_events(pscan,&pscan->alrt,DBE_VALUE);
}
if(viewScanPos) {
drawPos1Scan(pscan);
}
break;
case(SPC_SC_N):
/* adjust all linear scan parameters per new # of steps */
if(pscan->npts > pscan->mpts) {
pscan->npts = pscan->mpts;
db_post_events(pscan,&pscan->npts,DBE_VALUE);
}
prevAlrt = pscan->alrt;
pscan->alrt = 0;
sprintf(pscan->smsg,"");
precPvt->nptsCause = 0; /* resolve all positioner parameters */
changedNpts(pscan);
db_post_events(pscan,&pscan->smsg,DBE_VALUE);
if(pscan->alrt != prevAlrt) {
db_post_events(pscan,&pscan->alrt,DBE_VALUE);
}
if(viewScanPos) {
drawPos1Scan(pscan);
}
break;
case(SPC_SC_FFO):
/* Freeze Flag Override field */
if((pscan->ffo) && (!precPvt->pffo)) {
saveFrzFlags(pscan);
resetFrzFlags(pscan);
}
else if(!pscan->ffo && precPvt->pffo) /* only on 1->0 */
restoreFrzFlags(pscan);
break;
case(SPC_SC_F):
/* Freeze Flag Override field */
if(pscan->ffo)
resetFrzFlags(pscan);
break;
default:
/* recGblDbaddrError(S_db_badChoice,paddr,"scan: special");
return(S_db_badChoice);
*/
}
return(0);
}
static long cvt_dbaddr(paddr)
struct dbAddr *paddr;
{
struct scanRecord *pscan=(struct scanRecord *)paddr->precord;
/* all arrays are <currently> floats */
if (paddr->pfield == &(pscan->p1pa)) {
paddr->pfield = (void *)(pscan->p1pa);
} else if (paddr->pfield == &(pscan->p2pa)) {
paddr->pfield = (void *)(pscan->p2pa);
} else if (paddr->pfield == &(pscan->p3pa)) {
paddr->pfield = (void *)(pscan->p3pa);
} else if (paddr->pfield == &(pscan->p4pa)) {
paddr->pfield = (void *)(pscan->p4pa);
} else if (paddr->pfield == &(pscan->p1ra)) {
paddr->pfield = (void *)(pscan->p1ra);
} else if (paddr->pfield == &(pscan->p2ra)) {
paddr->pfield = (void *)(pscan->p2ra);
} else if (paddr->pfield == &(pscan->p3ra)) {
paddr->pfield = (void *)(pscan->p3ra);
} else if (paddr->pfield == &(pscan->p4ra)) {
paddr->pfield = (void *)(pscan->p4ra);
} else if (paddr->pfield == &(pscan->d1da)) {
paddr->pfield = (void *)(pscan->d1da);
} else if (paddr->pfield == &(pscan->d2da)) {
paddr->pfield = (void *)(pscan->d2da);
} else if (paddr->pfield == &(pscan->d3da)) {
paddr->pfield = (void *)(pscan->d3da);
} else if (paddr->pfield == &(pscan->d4da)) {
paddr->pfield = (void *)(pscan->d4da);
}
paddr->no_elements = pscan->mpts;
paddr->field_type = DBF_FLOAT;
paddr->field_size = sizeof(float);
paddr->dbr_field_type = DBF_FLOAT;
return(0);
}
static long get_array_info(paddr,no_elements,offset)
struct dbAddr *paddr;
long *no_elements;
long *offset;
{
struct scanRecord *pscan=(struct scanRecord *)paddr->precord;
struct recPvtStruct *precPvt = (struct recPvtStruct *)pscan->rpvt;
/* if the paddr has a double buffer pointer, update it now */
if ((paddr->pfield == precPvt->pdet1DataA) ||
(paddr->pfield == precPvt->pdet1DataB)) {
paddr->pfield = (void *)(pscan->d1da);
*no_elements = pscan->mpts;
*offset = 0;
} else if ((paddr->pfield == precPvt->pdet2DataA) ||
(paddr->pfield == precPvt->pdet2DataB)) {
paddr->pfield = (void *)(pscan->d2da);
*no_elements = pscan->mpts;
*offset = 0;
} else if ((paddr->pfield == precPvt->pdet3DataA) ||
(paddr->pfield == precPvt->pdet3DataB)) {
paddr->pfield = (void *)(pscan->d3da);
*no_elements = pscan->mpts;
*offset = 0;
} else if ((paddr->pfield == precPvt->pdet4DataA) ||
(paddr->pfield == precPvt->pdet4DataB)) {
paddr->pfield = (void *)(pscan->d4da);
*no_elements = pscan->mpts;
*offset = 0;
} else if (paddr->pfield == pscan->p1pa) {
*no_elements = pscan->mpts;
*offset = 0;
} else if (paddr->pfield == pscan->p2pa) {
*no_elements = pscan->mpts;
*offset = 0;
} else if (paddr->pfield == pscan->p3pa) {
*no_elements = pscan->mpts;
*offset = 0;
} else if (paddr->pfield == pscan->p4pa) {
*no_elements = pscan->mpts;
*offset = 0;
} else if (paddr->pfield == pscan->p1ra) {
*no_elements = pscan->mpts;
*offset = 0;
} else if (paddr->pfield == pscan->p2ra) {
*no_elements = pscan->mpts;
*offset = 0;
} else if (paddr->pfield == pscan->p3ra) {
*no_elements = pscan->mpts;
*offset = 0;
} else if (paddr->pfield == pscan->p4ra) {
*no_elements = pscan->mpts;
*offset = 0;
} else {
*no_elements = 0;
*offset = 0;
}
return(0);
}
static long put_array_info(paddr,nNew)
struct dbAddr *paddr;
long nNew;
{
struct scanRecord *pscan=(struct scanRecord *)paddr->precord;
if(nNew < pscan->npts) {
sprintf(pscan->smsg,"Pts in Table < # of Steps");
db_post_events(pscan,&pscan->smsg,DBE_VALUE);
if(!pscan->alrt) {
pscan->alrt = 1;
db_post_events(pscan,&pscan->alrt,DBE_VALUE);
}
}else {
sprintf(pscan->smsg,"");
db_post_events(pscan,&pscan->smsg,DBE_VALUE);
if(pscan->alrt) {
pscan->alrt = 0;
db_post_events(pscan,&pscan->alrt,DBE_VALUE);
}
}
return(0);
}
static long get_enum_str(paddr,pstring)
struct dbAddr *paddr;
char *pstring;
{
struct scanRecord *pscan=(struct scanRecord *)paddr->precord;
if(paddr->pfield==(void *)&pscan->cmnd)
{
sprintf(pstring, "%d",pscan->cmnd);
}
else
{
strcpy(pstring,"No string");
}
return(0);
}
static long get_enum_strs(paddr,pes)
struct dbAddr *paddr;
struct dbr_enumStrs *pes;
{
struct scanRecord *pscan=(struct scanRecord *)paddr->precord;
if(paddr->pfield==(void *)&pscan->cmnd)
{
memset(pes->strs,'\0',sizeof(pes->strs));
strncpy(pes->strs[0],"0-Clear Msg",sizeof("0-Clear Msg"));
strncpy(pes->strs[1],"1-Check Limits",sizeof("1-Check Limits"));
pes->no_str = 2;
}
else
{
strcpy(pes->strs[0],"No string");
pes->no_str=1;
}
return(0);
}
static long put_enum_str(paddr,pstring)
struct dbAddr *paddr;
char *pstring;
{
struct scanRecord *pscan=(struct scanRecord *)paddr->precord;
if(paddr->pfield==(void *)&pscan->cmnd)
{
if(sscanf(pstring,"%i",&pscan->cmnd)<=0)
return(S_db_badChoice);
}
else
{
return(S_db_badChoice);
}
return(0);
}
static long get_value(pscan,pvdes)
struct scanRecord *pscan;
struct valueDes *pvdes;
{
pvdes->field_type = DBF_DOUBLE;
pvdes->no_elements=1;
(double *)(pvdes->pvalue) = &pscan->p1dv;
return(0);
}
static long get_units(paddr,units)
struct dbAddr *paddr;
char *units;
{
struct scanRecord *pscan=(struct scanRecord *)paddr->precord;
return(0);
}
static long get_precision(paddr,precision)
struct dbAddr *paddr;
long *precision;
{
struct scanRecord *pscan=(struct scanRecord *)paddr->precord;
if ((paddr->pfield >= (void *)&pscan->p1sm) &&
(paddr->pfield <= (void *)&pscan->p1pa)) {
*precision = pscan->p1pr;
}
else if((paddr->pfield >= (void *)&pscan->p2sm) &&
(paddr->pfield <= (void *)&pscan->p2pa)) {
*precision = pscan->p2pr;
}
else if((paddr->pfield >= (void *)&pscan->p3sm) &&
(paddr->pfield <= (void *)&pscan->p3pa)) {
*precision = pscan->p3pr;
}
else if((paddr->pfield >= (void *)&pscan->p4sm) &&
(paddr->pfield <= (void *)&pscan->p4pa)) {
*precision = pscan->p4pr;
}
else if((paddr->pfield >= (void *)&pscan->d1cv) &&
(paddr->pfield <= (void *)&pscan->d1da)) {
*precision = pscan->d1pr;
}
else if((paddr->pfield >= (void *)&pscan->d2cv) &&
(paddr->pfield <= (void *)&pscan->d2da)) {
*precision = pscan->d2pr;
}
else if((paddr->pfield >= (void *)&pscan->d3cv) &&
(paddr->pfield <= (void *)&pscan->d3da)) {
*precision = pscan->d3pr;
}
else if((paddr->pfield >= (void *)&pscan->d4cv) &&
(paddr->pfield <= (void *)&pscan->d4da)) {
*precision = pscan->d4pr;
}
else {
*precision = 2;
}
return(0);
}
static long get_graphic_double(paddr,pgd)
struct dbAddr *paddr;
struct dbr_grDouble *pgd;
{
struct scanRecord *pscan=(struct scanRecord *)paddr->precord;
if (((paddr->pfield >= (void *)&pscan->p1sm) &&
(paddr->pfield <= (void *)&pscan->p1pa)) ||
(paddr->pfield == pscan->p1pa)) {
pgd->upper_disp_limit = pscan->p1hr;
pgd->lower_disp_limit = pscan->p1lr;
}
else if(((paddr->pfield >= (void *)&pscan->p2sm) &&
(paddr->pfield <= (void *)&pscan->p2pa)) ||
(paddr->pfield == pscan->p2pa)) {
pgd->upper_disp_limit = pscan->p2hr;
pgd->lower_disp_limit = pscan->p2lr;
}
else if(((paddr->pfield >= (void *)&pscan->p3sm) &&
(paddr->pfield <= (void *)&pscan->p3pa)) ||
(paddr->pfield == pscan->p3pa)) {
pgd->upper_disp_limit = pscan->p3hr;
pgd->lower_disp_limit = pscan->p3lr;
}
else if(((paddr->pfield >= (void *)&pscan->p4sm) &&
(paddr->pfield <= (void *)&pscan->p4pa)) ||
(paddr->pfield == pscan->p4pa)) {
pgd->upper_disp_limit = pscan->p4hr;
pgd->lower_disp_limit = pscan->p4lr;
}
else if(((paddr->pfield >= (void *)&pscan->d1cv) &&
(paddr->pfield <= (void *)&pscan->d1da)) ||
(paddr->pfield == pscan->d1da)) {
pgd->upper_disp_limit = pscan->d1hr;
pgd->lower_disp_limit = pscan->d1lr;
}
else if(((paddr->pfield >= (void *)&pscan->d2cv) &&
(paddr->pfield <= (void *)&pscan->d2da)) ||
(paddr->pfield == pscan->d2da)) {
pgd->upper_disp_limit = pscan->d2hr;
pgd->lower_disp_limit = pscan->d2lr;
}
else if(((paddr->pfield >= (void *)&pscan->d3cv) &&
(paddr->pfield <= (void *)&pscan->d3da)) ||
(paddr->pfield == pscan->d3da)) {
pgd->upper_disp_limit = pscan->d3hr;
pgd->lower_disp_limit = pscan->d3lr;
}
else if(((paddr->pfield >= (void *)&pscan->d4cv) &&
(paddr->pfield <= (void *)&pscan->d4da)) ||
(paddr->pfield == pscan->d4da)) {
pgd->upper_disp_limit = pscan->d4hr;
pgd->lower_disp_limit = pscan->d4lr;
}
else recGblGetGraphicDouble(paddr,pgd);
return(0);
}
static long get_control_double(paddr,pcd)
struct dbAddr *paddr;
struct dbr_ctrlDouble *pcd;
{
struct scanRecord *pscan=(struct scanRecord *)paddr->precord;
recGblGetControlDouble(paddr,pcd);
return(0);
}
static long get_alarm_double(paddr,pad)
struct dbAddr *paddr;
struct dbr_alDouble *pad;
{
recGblGetAlarmDouble(paddr,pad);
return(0);
}
static void checkMonitors(pscan)
struct scanRecord *pscan;
{
struct recPvtStruct *precPvt = (struct recPvtStruct *)pscan->rpvt;
unsigned long now;
/* If last posting time is > MIN_MON, check to see if any dynamic fields
have changed (also post monitors on end of scan)*/
now=tickGet();
if(((now - pscan->tolp) > MIN_MON) ||
((pscan->pxsc == 1) && (pscan->exsc == 0))) {
pscan->tolp = now;
if(fabs(pscan->d1lv - pscan->d1cv) > 0) {
db_post_events(pscan,&pscan->d1cv, DBE_VALUE);
pscan->d1lv = pscan->d1cv;
}
if(fabs(pscan->d2lv - pscan->d2cv) > 0) {
db_post_events(pscan,&pscan->d2cv, DBE_VALUE);
pscan->d2lv = pscan->d2cv;
}
if(fabs(pscan->d3lv - pscan->d3cv) > 0) {
db_post_events(pscan,&pscan->d3cv, DBE_VALUE);
pscan->d3lv = pscan->d3cv;
}
if(fabs(pscan->d4lv - pscan->d4cv) > 0) {
db_post_events(pscan,&pscan->d4cv, DBE_VALUE);
pscan->d4lv = pscan->d4cv;
}
if(pscan->pcpt != pscan->cpt) {
db_post_events(pscan,&pscan->cpt, DBE_VALUE);
pscan->pcpt = pscan->cpt;
}
if(fabs(pscan->p1lv - pscan->p1dv) > 0) {
db_post_events(pscan,&pscan->p1dv, DBE_VALUE);
pscan->p1lv = pscan->p1dv;
}
if(fabs(pscan->r1lv - pscan->r1cv) > 0) {
db_post_events(pscan,&pscan->r1cv, DBE_VALUE);
pscan->r1lv = pscan->r1cv;
}
if(fabs(pscan->p2lv - pscan->p2dv) > 0) {
db_post_events(pscan,&pscan->p2dv, DBE_VALUE);
pscan->p2lv = pscan->p2dv;
}
if(fabs(pscan->r2lv - pscan->r2cv) > 0) {
db_post_events(pscan,&pscan->r2cv, DBE_VALUE);
pscan->r2lv = pscan->r2cv;
}
if(fabs(pscan->p3lv - pscan->p3dv) > 0) {
db_post_events(pscan,&pscan->p3dv, DBE_VALUE);
pscan->p3lv = pscan->p3dv;
}
if(fabs(pscan->r3lv - pscan->r3cv) > 0) {
db_post_events(pscan,&pscan->r3cv, DBE_VALUE);
pscan->r3lv = pscan->r3cv;
}
if(fabs(pscan->p4lv - pscan->p4dv) > 0) {
db_post_events(pscan,&pscan->p4dv, DBE_VALUE);
pscan->p4lv = pscan->p4dv;
}
if(fabs(pscan->r4lv - pscan->r4cv) > 0) {
db_post_events(pscan,&pscan->r4cv, DBE_VALUE);
pscan->r4lv = pscan->r4cv;
}
/* Post a monitor on VAL to indicate new point */
if(pscan->exsc) {
db_post_events(pscan,&pscan->val, DBE_VALUE);
}
}
if (pscan->pxsc != pscan->exsc)
db_post_events(pscan,&pscan->exsc, DBE_VALUE);
/* if this is the end of a scan, post data arrays */
if ((pscan->pxsc == 1) && (pscan->exsc == 0)) {
db_post_events(pscan,pscan->p1pa, DBE_VALUE);
db_post_events(pscan,pscan->p2pa, DBE_VALUE);
db_post_events(pscan,pscan->p3pa, DBE_VALUE);
db_post_events(pscan,pscan->p4pa, DBE_VALUE);
db_post_events(pscan,pscan->p1ra, DBE_VALUE);
db_post_events(pscan,pscan->p2ra, DBE_VALUE);
db_post_events(pscan,pscan->p3ra, DBE_VALUE);
db_post_events(pscan,pscan->p4ra, DBE_VALUE);
/* For the following arrays that are "double buffered", it is
currently necessary to post_events on both buffers because
of the way channel access determines "monitors" .
These arrays are posted even if the PV names are not valid,
because they might have changed from valid to non-valid and
the data needs updates. (remember, nothing will happen if
no one has a monitor set */
db_post_events(pscan,precPvt->pdet1DataA, DBE_VALUE);
db_post_events(pscan,precPvt->pdet1DataB, DBE_VALUE);
db_post_events(pscan,precPvt->pdet2DataA, DBE_VALUE);
db_post_events(pscan,precPvt->pdet2DataB, DBE_VALUE);
db_post_events(pscan,precPvt->pdet3DataA, DBE_VALUE);
db_post_events(pscan,precPvt->pdet3DataB, DBE_VALUE);
db_post_events(pscan,precPvt->pdet4DataA, DBE_VALUE);
db_post_events(pscan,precPvt->pdet4DataB, DBE_VALUE);
/* post alert if changed */
if(precPvt->scanErr) {
pscan->alrt = precPvt->scanErr;
db_post_events(pscan,&pscan->alrt, DBE_VALUE);
}
}
}
static void lookupPVs(pscan)
struct scanRecord *pscan;
{
struct recPvtStruct *precPvt = (struct recPvtStruct *)pscan->rpvt;
char *ppvn[PVN_SIZE];
char *pdesc = ".DESC";
char *pval = ".VAL";
char *pdot;
struct dbAddr **ppdbAddr; /* ptr to a ptr to dbAddr */
long *paddrValid;
long prevValid;
short i;
/* Look up all reassignable PV Names */
*ppvn = &pscan->p1pv[0];
ppdbAddr = (struct dbAddr **)&pscan->p1db;
paddrValid = &pscan->p1nv;
for(i=0;i<NUM_DYN_PVS; i++, *ppvn += PVN_SIZE, ppdbAddr++, paddrValid++) {
prevValid = *paddrValid;
/* If PV field name = DESC, change to VAL */
pdot = strrchr(*ppvn, '.');
if(pdot!=NULL) {
if(strncmp(pdot, pdesc, 5) == 0) {
strcpy(pdot, pval);
db_post_events(pscan, *ppvn, DBE_VALUE);
}
}
*paddrValid = dbNameToAddr(*ppvn, *ppdbAddr);
if(*paddrValid != prevValid) {
db_post_events(pscan, paddrValid, DBE_VALUE);
}
}
/* determine if any valid readbacks or det trigs to save time later */
if(!pscan->r1nv || !pscan->r2nv || !pscan->r3nv || !pscan->r4nv) {
precPvt->validRbPvs = 1;
}
else {
precPvt->validRbPvs = 0;
}
if(!pscan->t1nv || !pscan->t2nv) {
precPvt->validDtPvs = 1;
}
else {
precPvt->validDtPvs = 0;
}
}
static void initScan(pscan)
struct scanRecord *pscan;
{
struct recPvtStruct *precPvt = (struct recPvtStruct *)pscan->rpvt;
long status;
long nRequest = 1;
long options = 0;
/* Figure out starting positions for each positioner */
if(pscan->p1sm == REC_SCAN_MO_TAB) {
pscan->p1dv = pscan->p1pa[0];
}
else {
pscan->p1dv = pscan->p1sp;
pscan->p1pa[pscan->cpt] = pscan->p1dv;
}
if(pscan->p2sm == REC_SCAN_MO_TAB) {
pscan->p2dv = pscan->p2pa[0];
}
else {
pscan->p2dv = pscan->p2sp;
pscan->p2pa[pscan->cpt] = pscan->p2dv;
}
if(pscan->p3sm == REC_SCAN_MO_TAB) {
pscan->p3dv = pscan->p3pa[0];
}
else {
pscan->p3dv = pscan->p3sp;
pscan->p3pa[pscan->cpt] = pscan->p3dv;
}
if(pscan->p4sm == REC_SCAN_MO_TAB) {
pscan->p4dv = pscan->p4pa[0];
}
else {
pscan->p4dv = pscan->p4sp;
pscan->p4pa[pscan->cpt] = pscan->p4dv;
}
precPvt->phase = MOVE_MOTORS;
/* request callback to do dbPutFields */
callbackRequest(&precPvt->doPutsCallback);
return;
}
static void contScan(pscan)
struct scanRecord *pscan;
{
struct recPvtStruct *precPvt = (struct recPvtStruct *)pscan->rpvt;
long status;
long nRequest = 1;
long options = 0;
long abortScan = 0;
if(scanRecDebug > 4) {
printf("contScan; phase = %d\n", (int)precPvt->phase);
}
switch (precPvt->phase) {
case TRIG_DETCTRS:
/* request callback to do dbPutFields to detector trigger fields */
callbackRequest(&precPvt->doPutsCallback);
return;
case CHCK_MOTORS:
/* motors have stopped. Check readbacks and deadbands */
/* Also fill in PxRA (readback array) from RxCV or PxDV */
if(!pscan->r1nv) {
status = dbGet(pscan->r1db, DBR_FLOAT, &(pscan->r1cv),
&options, &nRequest, NULL);
pscan->p1ra[pscan->cpt] = pscan->r1cv;
if((pscan->r1dl > 0) &&
(fabs(pscan->p1dv - pscan->r1cv) > pscan->r1dl)) {
sprintf(pscan->smsg,"SCAN Aborted: P1 Readback > delta");
db_post_events(pscan,&pscan->smsg,DBE_VALUE);
precPvt->scanErr = 1;
abortScan = 1;
}
} else {
pscan->r1cv = pscan->p1dv;
pscan->p1ra[pscan->cpt] = pscan->p1dv;
}
if(!pscan->r2nv) {
nRequest = 1;
status = dbGet(pscan->r2db, DBR_FLOAT, &(pscan->r2cv),
&options, &nRequest, NULL);
pscan->p2ra[pscan->cpt] = pscan->r2cv;
if((pscan->r2dl > 0) &&
(fabs(pscan->p2dv - pscan->r2cv) > pscan->r2dl)) {
sprintf(pscan->smsg,"SCAN Aborted: P2 Readback > delta");
db_post_events(pscan,&pscan->smsg,DBE_VALUE);
precPvt->scanErr = 1;
abortScan = 1;
}
} else { /* no readback PV, stuff with desired value */
pscan->r2cv = pscan->p2dv;
pscan->p2ra[pscan->cpt] = pscan->p2dv;
}
if(!pscan->r3nv) {
nRequest = 1;
status = dbGet(pscan->r3db, DBR_FLOAT, &(pscan->r3cv),
&options, &nRequest, NULL);
pscan->p3ra[pscan->cpt] = pscan->r3cv;
if((pscan->r3dl > 0) &&
(fabs(pscan->p3dv - pscan->r3cv) > pscan->r3dl)) {
sprintf(pscan->smsg,"SCAN Aborted: P3 Readback > delta");
db_post_events(pscan,&pscan->smsg,DBE_VALUE);
precPvt->scanErr = 1;
abortScan = 1;
}
} else { /* no readback PV, stuff with desired value */
pscan->r3cv = pscan->p3dv;
pscan->p3ra[pscan->cpt] = pscan->p3dv;
}
if(!pscan->r4nv) {
nRequest = 1;
status = dbGet(pscan->r4db, DBR_FLOAT, &(pscan->r4cv),
&options, &nRequest, NULL);
pscan->p4ra[pscan->cpt] = pscan->r4cv;
if((pscan->r4dl > 0) &&
(fabs(pscan->p4dv - pscan->r4cv) > pscan->r4dl)) {
sprintf(pscan->smsg,"SCAN Aborted: P4 Readback > delta");
db_post_events(pscan,&pscan->smsg,DBE_VALUE);
precPvt->scanErr = 1;
abortScan = 1;
}
} else { /* no readback PV, stuff with desired value */
pscan->r4cv = pscan->p4dv;
pscan->p4ra[pscan->cpt] = pscan->p4dv;
}
if(abortScan) {
endScan(pscan);
return;
}
if(precPvt->validDtPvs) {
/* request callback to do dbPutFields to detector trigger fields */
precPvt->phase = TRIG_DETCTRS;
callbackRequest(&precPvt->doPutsCallback);
return;
}
/* if no validDtPvs, fall through to READ_DETCTRS */
case READ_DETCTRS:
/* read each valid detector PV, place data in buffered array */
status = 0;
if(!pscan->d1nv) {
/* dbAddr is valid */
nRequest = 1;
status |= dbGet(pscan->d1db, DBR_FLOAT, &(pscan->d1cv),
&options, &nRequest, NULL);
} else pscan->d1cv = 0;
if(!pscan->d2nv) {
nRequest = 1;
status |= dbGet(pscan->d2db, DBR_FLOAT,
&(pscan->d2cv), &options, &nRequest, NULL);
} else pscan->d2cv = 0;
if(!pscan->d3nv) {
nRequest = 1;
status |= dbGet(pscan->d3db, DBR_FLOAT, &(pscan->d3cv),
&options, &nRequest, NULL);
} else pscan->d3cv = 0;
if(!pscan->d4nv) {
nRequest = 1;
status |= dbGet(pscan->d4db, DBR_FLOAT, &(pscan->d4cv),
&options, &nRequest, NULL);
} else pscan->d4cv = 0;
/* store the data using the Fill pointer */
precPvt->pdet1Fill[pscan->cpt] = pscan->d1cv;
precPvt->pdet2Fill[pscan->cpt] = pscan->d2cv;
precPvt->pdet3Fill[pscan->cpt] = pscan->d3cv;
precPvt->pdet4Fill[pscan->cpt] = pscan->d4cv;
pscan->udf=0;
pscan->cpt++;
/* Has number of points been reached ? */
if(pscan->cpt < (pscan->npts)) {
/* determine next desired position for each positioner */
if(pscan->p1sm == REC_SCAN_MO_LIN) {
pscan->p1dv = pscan->p1dv + pscan->p1si;
pscan->p1pa[pscan->cpt] = pscan->p1dv;
}
else if(pscan->p1sm == REC_SCAN_MO_TAB) {
pscan->p1dv = pscan->p1pa[pscan->cpt];
}
else {
/* this is on-the-fly, so set to end position */
pscan->p1dv = pscan->p1ep;
pscan->p1pa[pscan->cpt] = pscan->p1dv;
}
if(pscan->p2sm == REC_SCAN_MO_LIN) {
pscan->p2dv = pscan->p2dv + pscan->p2si;
pscan->p2pa[pscan->cpt] = pscan->p2dv;
}
else if(pscan->p2sm == REC_SCAN_MO_TAB) {
pscan->p2dv = pscan->p2pa[pscan->cpt];
}
else {
/* this is on-the-fly, so set to end position */
pscan->p2dv = pscan->p2ep;
pscan->p2pa[pscan->cpt] = pscan->p2dv;
}
if(pscan->p3sm == REC_SCAN_MO_LIN) {
pscan->p3dv = pscan->p3dv + pscan->p3si;
pscan->p3pa[pscan->cpt] = pscan->p3dv;
}
else if(pscan->p3sm == REC_SCAN_MO_TAB) {
pscan->p3dv = pscan->p3pa[pscan->cpt];
}
else {
/* this is on-the-fly, so set to end position */
pscan->p3dv = pscan->p3ep;
pscan->p3pa[pscan->cpt] = pscan->p3dv;
}
if(pscan->p4sm == REC_SCAN_MO_LIN) {
pscan->p4dv = pscan->p4dv + pscan->p4si;
pscan->p4pa[pscan->cpt] = pscan->p4dv;
}
else if(pscan->p4sm == REC_SCAN_MO_TAB) {
pscan->p4dv = pscan->p4pa[pscan->cpt];
}
else {
/* this is on-the-fly, so set to end position */
pscan->p4dv = pscan->p4ep;
pscan->p4pa[pscan->cpt] = pscan->p4dv;
}
/* request callback to move motors to new positions */
precPvt->phase = MOVE_MOTORS;
callbackRequest(&precPvt->doPutsCallback);
return;
}
else {
endScan(pscan); /* scan is successfully complete */
sprintf(pscan->smsg,"SCAN Complete");
db_post_events(pscan,&pscan->smsg,DBE_VALUE);
precPvt->scanErr = 0;
return;
}
}
}
static void endScan(pscan)
struct scanRecord *pscan;
{
struct recPvtStruct *precPvt = (struct recPvtStruct *)pscan->rpvt;
int counter;
/* Done with scan. Do we want to fill the remainder of the
array with 0 or something ? */
/* It turns out that medm plots the whole array, so for it
to look right the remainder of the arrays will be filled
with the last values. This will cause medm to plot the
same point over and over again, but it will look correct */
counter = pscan->cpt;
if(scanRecDebug) {
printf("endScan(): Fill Counter - %d\n",counter);
}
while (counter < pscan->mpts) {
precPvt->pdet1Fill[counter] = pscan->d1cv;
precPvt->pdet2Fill[counter] = pscan->d2cv;
precPvt->pdet3Fill[counter] = pscan->d3cv;
precPvt->pdet4Fill[counter] = pscan->d4cv;
if(pscan->p1sm != REC_SCAN_MO_TAB) {
pscan->p1pa[counter] = pscan->p1dv;
}
if(pscan->p2sm != REC_SCAN_MO_TAB) {
pscan->p2pa[counter] = pscan->p2dv;
}
if(pscan->p3sm != REC_SCAN_MO_TAB) {
pscan->p3pa[counter] = pscan->p3dv;
}
if(pscan->p4sm != REC_SCAN_MO_TAB) {
pscan->p4pa[counter] = pscan->p4dv;
}
if(!pscan->r1nv)
pscan->p1ra[counter] = pscan->r1cv;
else
pscan->p1ra[counter] = pscan->p1dv;
if(!pscan->r2nv)
pscan->p2ra[counter] = pscan->r2cv;
else
pscan->p2ra[counter] = pscan->p2dv;
if(!pscan->r3nv)
pscan->p3ra[counter] = pscan->r3cv;
else
pscan->p3ra[counter] = pscan->p3dv;
if(!pscan->r4nv)
pscan->p4ra[counter] = pscan->r4cv;
else
pscan->p4ra[counter] = pscan->p4dv;
counter++;
}
/* Switch the array pointers to the valid data */
if(precPvt->validDataBuf == A_BUFFER) {
pscan->d1da = precPvt->pdet1DataB;
pscan->d2da = precPvt->pdet2DataB;
pscan->d3da = precPvt->pdet3DataB;
pscan->d4da = precPvt->pdet4DataB;
/* Switch the Fill pointers for the next scan */
precPvt->pdet1Fill = precPvt->pdet1DataA;
precPvt->pdet2Fill = precPvt->pdet2DataA;
precPvt->pdet3Fill = precPvt->pdet3DataA;
precPvt->pdet4Fill = precPvt->pdet4DataA;
precPvt->validDataBuf = B_BUFFER;
}
else {
pscan->d1da = precPvt->pdet1DataA;
pscan->d2da = precPvt->pdet2DataA;
pscan->d3da = precPvt->pdet3DataA;
pscan->d4da = precPvt->pdet4DataA;
/* Switch the Fill pointers for the next scan */
precPvt->pdet1Fill = precPvt->pdet1DataB;
precPvt->pdet2Fill = precPvt->pdet2DataB;
precPvt->pdet3Fill = precPvt->pdet3DataB;
precPvt->pdet4Fill = precPvt->pdet4DataB;
precPvt->validDataBuf = A_BUFFER;
}
pscan->exsc = 0; /* done with scan */
/* if the "Return To Start: flag is set, command positioners
to their start positions via initScan */
if(pscan->rtst) {
initScan(pscan);
}
return;
}
/******************************************************************************
*
* This is the code that is executed by the callback task to initiate the next
* step in the scan or trigger detectors (does dbPutFields for the reassignable
* links). It is done with a separate task so one need not worry about lock
* sets.
*
*****************************************************************************/
void doPuts(precPvt)
struct recPvtStruct *precPvt;
{
static long status;
static long nRequest = 1;
if(scanRecDebug > 4) {
printf("DoPuts; phase = %d\n", (int)precPvt->phase);
}
switch (precPvt->phase) {
case MOVE_MOTORS:
/* next processing of records means motors have stopped */
/* Schedule the next phase as CHCK_MOTORS */
/* This needs to come before moving motors */
precPvt->phase = CHCK_MOTORS;
/* for each valid positioner, write the desired position */
if(!precPvt->pscan->p1nv) {
status = dbPutField(precPvt->pscan->p1db,DBR_FLOAT,
&(precPvt->pscan->p1dv), 1);
}
if(!precPvt->pscan->p2nv) {
status = dbPutField(precPvt->pscan->p2db,DBR_FLOAT,
&(precPvt->pscan->p2dv), 1);
}
if(!precPvt->pscan->p3nv) {
status = dbPutField(precPvt->pscan->p3db,DBR_FLOAT,
&(precPvt->pscan->p3dv), 1);
}
if(!precPvt->pscan->p4nv) {
status = dbPutField(precPvt->pscan->p4db,DBR_FLOAT,
&(precPvt->pscan->p4dv), 1);
}
break;
case TRIG_DETCTRS:
/* Schedule the next phase */
precPvt->phase = READ_DETCTRS;
/* for each valid detector trigger, write the desired value */
if(!precPvt->pscan->t1nv) {
status = dbPutField(precPvt->pscan->t1db,DBR_FLOAT,
&(precPvt->pscan->t1cd), 1);
}
if(!precPvt->pscan->t2nv) {
status = dbPutField(precPvt->pscan->t2db,DBR_FLOAT,
&(precPvt->pscan->t2cd), 1);
}
break;
default:
}
}
/* routine to resolve and adjust linear scan definition.
* Might get complicated !!!
*/
static void adjLinParms(paddr)
struct dbAddr *paddr;
{
struct scanRecord *pscan = (struct scanRecord *)(paddr->precord);
struct recPvtStruct *precPvt = (struct recPvtStruct *)pscan->rpvt;
struct linScanParms *pParms;
int special_type = paddr->special;
int i;
/* determine which positioner */
if ((paddr->pfield >= (void *)&pscan->p1sp) &&
(paddr->pfield <= (void *)&pscan->p1fw)) {
pParms = (struct linScanParms *)&pscan->p1sp;
i=1;
}
else if((paddr->pfield >= (void *)&pscan->p2sp) &&
(paddr->pfield <= (void *)&pscan->p2fw)) {
pParms = (struct linScanParms *)&pscan->p2sp;
i=2;
}
else if((paddr->pfield >= (void *)&pscan->p3sp) &&
(paddr->pfield <= (void *)&pscan->p3fw)) {
pParms = (struct linScanParms *)&pscan->p3sp;
i=3;
}
else if((paddr->pfield >= (void *)&pscan->p4sp) &&
(paddr->pfield <= (void *)&pscan->p4fw)) {
pParms = (struct linScanParms *)&pscan->p4sp;
i=4;
}
else {
return;
}
switch(special_type) {
case(SPC_SC_S): /* start position changed */
/* if step increment/center/width are not frozen, change them */
if(!pParms->p_fi && !pParms->p_fc && !pParms->p_fw) {
pParms->p_si = (pParms->p_ep - pParms->p_sp)/(pscan->npts - 1);
db_post_events(pscan,&pParms->p_si,DBE_VALUE);
pParms->p_cp = (pParms->p_ep + pParms->p_sp)/2;
db_post_events(pscan,&pParms->p_cp,DBE_VALUE);
pParms->p_wd = (pParms->p_ep - pParms->p_sp);
db_post_events(pscan,&pParms->p_wd,DBE_VALUE);
return;
/* if end/center are not frozen, change them */
} else if(!pParms->p_fe && !pParms->p_fc) {
pParms->p_ep = pParms->p_sp +
((pscan->npts - 1) * pParms->p_si);
db_post_events(pscan,&pParms->p_ep,DBE_VALUE);
pParms->p_cp = (pParms->p_ep + pParms->p_sp)/2;
db_post_events(pscan,&pParms->p_cp,DBE_VALUE);
return;
/* if step increment/end/width are not frozen, change them */
} else if(!pParms->p_fi && !pParms->p_fe && !pParms->p_fw) {
pParms->p_wd = (pParms->p_cp - pParms->p_sp) * 2;
db_post_events(pscan,&pParms->p_wd,DBE_VALUE);
pParms->p_si = pParms->p_wd/(pscan->npts - 1);
db_post_events(pscan,&pParms->p_si,DBE_VALUE);
pParms->p_ep = (pParms->p_sp + pParms->p_wd);
db_post_events(pscan,&pParms->p_ep,DBE_VALUE);
return;
/* if # of points/center/width are not frozen, change them */
} else if(!pscan->fpts && !pParms->p_fc && !pParms->p_fw) {
pscan->npts = ((pParms->p_ep - pParms->p_sp)/(pParms->p_si)) + 1;
if(pscan->npts > pscan->mpts) {
pscan->npts = pscan->mpts;
sprintf(pscan->smsg,"P%1d Request Exceeded Maximum Points !",i);
/* adjust changed field to be consistent */
pParms->p_sp = pParms->p_ep-(pParms->p_si * (pscan->npts - 1));
db_post_events(pscan,&pParms->p_sp,DBE_VALUE);
pscan->alrt = 1;
}
db_post_events(pscan,&pscan->npts,DBE_VALUE);
pParms->p_cp = (pParms->p_ep + pParms->p_sp)/2;
db_post_events(pscan,&pParms->p_cp,DBE_VALUE);
pParms->p_wd = (pParms->p_ep - pParms->p_sp);
db_post_events(pscan,&pParms->p_wd,DBE_VALUE);
precPvt->nptsCause = i; /* indicate cause of # of points changed */
changedNpts(pscan);
return;
/* if # of points/end/width are not frozen, change them */
} else if(!pscan->fpts && !pParms->p_fe && !pParms->p_fw) {
pscan->npts = ((pParms->p_cp - pParms->p_sp)*2/(pParms->p_si)) + 1;
if(pscan->npts > pscan->mpts) {
pscan->npts = pscan->mpts;
sprintf(pscan->smsg,"P%1d Request Exceeded Maximum Points !",i);
/* adjust changed field to be consistent */
pParms->p_sp=pParms->p_cp-((pParms->p_si*(pscan->npts - 1))/2);
db_post_events(pscan,&pParms->p_sp,DBE_VALUE);
pscan->alrt = 1;
}
db_post_events(pscan,&pscan->npts,DBE_VALUE);
pParms->p_ep = pParms->p_sp + ((pscan->npts - 1) * pParms->p_si);
db_post_events(pscan,&pParms->p_cp,DBE_VALUE);
pParms->p_wd = (pParms->p_ep - pParms->p_sp);
db_post_events(pscan,&pParms->p_wd,DBE_VALUE);
precPvt->nptsCause = i; /* indicate cause of # of points changed */
changedNpts(pscan);
return;
/* if center/end are not frozen, change them */
} else if(!pParms->p_fc && !pParms->p_fe) {
pParms->p_ep = pParms->p_sp + ((pscan->npts - 1) * pParms->p_si);
db_post_events(pscan,&pParms->p_ep,DBE_VALUE);
pParms->p_cp = (pParms->p_ep + pParms->p_sp)/2;
db_post_events(pscan,&pParms->p_cp,DBE_VALUE);
return;
} else { /* too constrained !! */
pParms->p_sp = pParms->p_ep - ((pscan->npts - 1) * pParms->p_si);
db_post_events(pscan,&pParms->p_sp,DBE_VALUE);
sprintf(pscan->smsg,"P%1d SCAN Parameters Too Constrained !",i);
pscan->alrt = 1;
return;
}
break;
case(SPC_SC_I): /* step increment changed */
/* if end/center/width are not frozen, change them */
if(!pParms->p_fe && !pParms->p_fc && !pParms->p_fw) {
pParms->p_ep = pParms->p_sp + ((pscan->npts - 1) * pParms->p_si);
db_post_events(pscan,&pParms->p_ep,DBE_VALUE);
pParms->p_cp = (pParms->p_ep + pParms->p_sp)/2;
db_post_events(pscan,&pParms->p_cp,DBE_VALUE);
pParms->p_wd = (pParms->p_ep - pParms->p_sp);
db_post_events(pscan,&pParms->p_wd,DBE_VALUE);
return;
/* if start/center/width are not frozen, change them */
} else if(!pParms->p_fs && !pParms->p_fc && !pParms->p_fw) {
pParms->p_sp = pParms->p_ep - ((pscan->npts - 1) * pParms->p_si);
db_post_events(pscan,&pParms->p_sp,DBE_VALUE);
pParms->p_cp = (pParms->p_ep + pParms->p_sp)/2;
db_post_events(pscan,&pParms->p_cp,DBE_VALUE);
pParms->p_wd = (pParms->p_ep - pParms->p_sp);
db_post_events(pscan,&pParms->p_wd,DBE_VALUE);
return;
/* if start/end/width are not frozen, change them */
} else if(!pParms->p_fs && !pParms->p_fe && !pParms->p_fw) {
pParms->p_sp = pParms->p_cp - ((pscan->npts - 1) * pParms->p_si)/2;
db_post_events(pscan,&pParms->p_sp,DBE_VALUE);
pParms->p_ep = pParms->p_sp + ((pscan->npts - 1) * pParms->p_si);
db_post_events(pscan,&pParms->p_ep,DBE_VALUE);
pParms->p_wd = (pParms->p_ep - pParms->p_sp);
db_post_events(pscan,&pParms->p_wd,DBE_VALUE);
return;
/* if # of points is not frozen, change it */
} else if(!pscan->fpts) {
pscan->npts = ((pParms->p_ep - pParms->p_sp)/(pParms->p_si)) + 1;
if(pscan->npts > pscan->mpts) {
pscan->npts = pscan->mpts;
sprintf(pscan->smsg,"P%1d Request Exceeded Maximum Points !",i);
/* adjust changed field to be consistent */
pParms->p_si = (pParms->p_ep - pParms->p_sp)/(pscan->npts - 1);
db_post_events(pscan,&pParms->p_si,DBE_VALUE);
pscan->alrt = 1;
}
db_post_events(pscan,&pscan->npts,DBE_VALUE);
precPvt->nptsCause = i; /* indicate cause of # of points changed */
changedNpts(pscan);
return;
} else { /* too constrained !! */
pParms->p_si = (pParms->p_ep - pParms->p_sp)/(pscan->npts - 1);
db_post_events(pscan,&pParms->p_si,DBE_VALUE);
sprintf(pscan->smsg,"P%1d SCAN Parameters Too Constrained !",i);
pscan->alrt = 1;
return;
}
break;
case(SPC_SC_E): /* end position changed */
/* if step increment/center/width are not frozen, change them */
if(!pParms->p_fi && !pParms->p_fc && !pParms->p_fw) {
pParms->p_si = (pParms->p_ep - pParms->p_sp)/(pscan->npts - 1);
db_post_events(pscan,&pParms->p_si,DBE_VALUE);
pParms->p_cp = (pParms->p_ep + pParms->p_sp)/2;
db_post_events(pscan,&pParms->p_cp,DBE_VALUE);
pParms->p_wd = (pParms->p_ep - pParms->p_sp);
db_post_events(pscan,&pParms->p_wd,DBE_VALUE);
return;
/* if start/center/width are not frozen, change them */
} else if(!pParms->p_fs && !pParms->p_fc && !pParms->p_fw) {
pParms->p_sp = pParms->p_ep - ((pscan->npts - 1) * pParms->p_si);
db_post_events(pscan,&pParms->p_sp,DBE_VALUE);
pParms->p_cp = (pParms->p_ep + pParms->p_sp)/2;
db_post_events(pscan,&pParms->p_cp,DBE_VALUE);
pParms->p_wd = (pParms->p_ep - pParms->p_sp);
db_post_events(pscan,&pParms->p_wd,DBE_VALUE);
return;
/* if step start/width/increment are not frozen, change them */
} else if(!pParms->p_fs && !pParms->p_fw && !pParms->p_fi) {
pParms->p_wd = (pParms->p_ep - pParms->p_cp) * 2;
db_post_events(pscan,&pParms->p_wd,DBE_VALUE);
pParms->p_sp = pParms->p_ep - pParms->p_wd;
db_post_events(pscan,&pParms->p_sp,DBE_VALUE);
pParms->p_si = (pParms->p_ep - pParms->p_sp)/(pscan->npts - 1);
db_post_events(pscan,&pParms->p_si,DBE_VALUE);
return;
/* if # of points/start/width are not frozen, change them */
} else if(!pscan->fpts && !pParms->p_fs && !pParms->p_fw) {
pscan->npts=(((pParms->p_ep - pParms->p_cp)*2)/(pParms->p_si)) + 1;
if(pscan->npts > pscan->mpts) {
pscan->npts = pscan->mpts;
sprintf(pscan->smsg,"P%1d Request Exceeded Maximum Points !",i);
/* adjust changed field to be consistent */
pParms->p_ep=pParms->p_cp+(pParms->p_si * (pscan->npts - 1)/2);
db_post_events(pscan,&pParms->p_ep,DBE_VALUE);
pscan->alrt = 1;
}
db_post_events(pscan,&pscan->npts,DBE_VALUE);
pParms->p_wd = (pParms->p_ep - pParms->p_cp) * 2;
db_post_events(pscan,&pParms->p_wd,DBE_VALUE);
pParms->p_sp = pParms->p_ep - pParms->p_wd;
db_post_events(pscan,&pParms->p_sp,DBE_VALUE);
precPvt->nptsCause = i; /* indicate cause of # of points changed */
changedNpts(pscan);
return;
/* if # of points/center/width are not frozen, change them */
} else if(!pscan->fpts && !pParms->p_fc && !pParms->p_fw) {
pscan->npts = ((pParms->p_ep - pParms->p_sp)/(pParms->p_si)) + 1;
if(pscan->npts > pscan->mpts) {
pscan->npts = pscan->mpts;
sprintf(pscan->smsg,"P%1d Request Exceeded Maximum Points !",i);
/* adjust changed field to be consistent */
pParms->p_ep=pParms->p_sp + (pParms->p_si * (pscan->npts - 1));
db_post_events(pscan,&pParms->p_ep,DBE_VALUE);
pscan->alrt = 1;
}
db_post_events(pscan,&pscan->npts,DBE_VALUE);
pParms->p_cp = (pParms->p_ep + pParms->p_sp)/2;
db_post_events(pscan,&pParms->p_cp,DBE_VALUE);
pParms->p_wd = (pParms->p_ep - pParms->p_sp);
db_post_events(pscan,&pParms->p_wd,DBE_VALUE);
precPvt->nptsCause = i; /* indicate cause of # of points changed */
changedNpts(pscan);
return;
/* if start/center are not frozen, change them */
} else if(!pParms->p_fs && !pParms->p_fc) {
pParms->p_sp = pParms->p_ep - ((pscan->npts - 1) * pParms->p_si);
db_post_events(pscan,&pParms->p_sp,DBE_VALUE);
pParms->p_cp = (pParms->p_ep + pParms->p_sp)/2;
db_post_events(pscan,&pParms->p_cp,DBE_VALUE);
return;
} else { /* too constrained !! */
pParms->p_ep = pParms->p_sp + ((pscan->npts - 1) * pParms->p_si);
db_post_events(pscan,&pParms->p_ep,DBE_VALUE);
sprintf(pscan->smsg,"P%1d SCAN Parameters Too Constrained !",i);
pscan->alrt = 1;
return;
}
break;
case(SPC_SC_C): /* center position changed */
/* if start/end are not frozen, change them */
if(!pParms->p_fs && !pParms->p_fe) {
pParms->p_sp = pParms->p_cp - ((pscan->npts - 1) * pParms->p_si)/2;
db_post_events(pscan,&pParms->p_sp,DBE_VALUE);
pParms->p_ep = pParms->p_sp + ((pscan->npts - 1) * pParms->p_si);
db_post_events(pscan,&pParms->p_ep,DBE_VALUE);
return;
/* if start/inc/width are not frozen, change them */
} else if(!pParms->p_fs && !pParms->p_fi && !pParms->p_fw) {
pParms->p_wd = (pParms->p_ep - pParms->p_cp)*2;
db_post_events(pscan,&pParms->p_wd,DBE_VALUE);
pParms->p_sp = pParms->p_ep - pParms->p_wd;
db_post_events(pscan,&pParms->p_sp,DBE_VALUE);
pParms->p_si = (pParms->p_ep - pParms->p_sp)/(pscan->npts - 1);
db_post_events(pscan,&pParms->p_si,DBE_VALUE);
return;
/* if end/inc/width are not frozen, change them */
} else if(!pParms->p_fe && !pParms->p_fi && !pParms->p_fw) {
pParms->p_wd = (pParms->p_cp - pParms->p_sp)*2;
db_post_events(pscan,&pParms->p_wd,DBE_VALUE);
pParms->p_ep = pParms->p_sp + pParms->p_wd;
db_post_events(pscan,&pParms->p_ep,DBE_VALUE);
pParms->p_si = (pParms->p_ep - pParms->p_sp)/(pscan->npts - 1);
db_post_events(pscan,&pParms->p_si,DBE_VALUE);
return;
/* if # of points/start/width are not frozen, change them */
} else if(!pscan->fpts && !pParms->p_fs && !pParms->p_fw) {
pscan->npts=(((pParms->p_ep - pParms->p_cp)*2)/(pParms->p_si)) + 1;
if(pscan->npts > pscan->mpts) {
pscan->npts = pscan->mpts;
sprintf(pscan->smsg,"P%1d Request Exceeded Maximum Points !",i);
/* adjust changed field to be consistent */
pParms->p_cp=pParms->p_ep-(pParms->p_si * (pscan->npts - 1)/2);
db_post_events(pscan,&pParms->p_cp,DBE_VALUE);
pscan->alrt = 1;
}
db_post_events(pscan,&pscan->npts,DBE_VALUE);
pParms->p_wd = (pParms->p_ep - pParms->p_cp) * 2;
db_post_events(pscan,&pParms->p_wd,DBE_VALUE);
pParms->p_sp = pParms->p_ep - pParms->p_wd;
db_post_events(pscan,&pParms->p_sp,DBE_VALUE);
precPvt->nptsCause = i; /* indicate cause of # of points changed */
changedNpts(pscan);
return;
/* if # of points/end/width are not frozen, change them */
} else if(!pscan->fpts && !pParms->p_fe && !pParms->p_fw) {
pscan->npts=(((pParms->p_cp - pParms->p_sp)*2)/(pParms->p_si)) + 1;
if(pscan->npts > pscan->mpts) {
pscan->npts = pscan->mpts;
sprintf(pscan->smsg,"P%1d Request Exceeded Maximum Points !",i);
/* adjust changed field to be consistent */
pParms->p_cp=pParms->p_sp+(pParms->p_si * (pscan->npts - 1)/2);
db_post_events(pscan,&pParms->p_cp,DBE_VALUE);
pscan->alrt = 1;
}
db_post_events(pscan,&pscan->npts,DBE_VALUE);
pParms->p_wd = (pParms->p_cp - pParms->p_sp) * 2;
db_post_events(pscan,&pParms->p_wd,DBE_VALUE);
pParms->p_ep = pParms->p_sp + pParms->p_wd;
db_post_events(pscan,&pParms->p_ep,DBE_VALUE);
precPvt->nptsCause = i; /* indicate cause of # of points changed */
changedNpts(pscan);
return;
} else { /* too constrained !! */
pParms->p_cp = pParms->p_sp + ((pscan->npts - 1) * pParms->p_si)/2;
db_post_events(pscan,&pParms->p_cp,DBE_VALUE);
sprintf(pscan->smsg,"P%1d SCAN Parameters Too Constrained !",i);
pscan->alrt = 1;
return;
}
break;
case(SPC_SC_W): /* width position changed */
/* if step start/inc/end are not frozen, change them */
if(!pParms->p_fs && !pParms->p_fi && !pParms->p_fe) {
pParms->p_si = pParms->p_wd/(pscan->npts - 1);
db_post_events(pscan,&pParms->p_si,DBE_VALUE);
pParms->p_sp = pParms->p_cp - ((pscan->npts - 1) * pParms->p_si)/2;
db_post_events(pscan,&pParms->p_sp,DBE_VALUE);
pParms->p_ep = pParms->p_sp + ((pscan->npts - 1) * pParms->p_si);
db_post_events(pscan,&pParms->p_ep,DBE_VALUE);
return;
/* if center/end/inc are not frozen, change them */
} else if(!pParms->p_fc && !pParms->p_fe && !pParms->p_fi) {
pParms->p_si = pParms->p_wd/(pscan->npts - 1);
db_post_events(pscan,&pParms->p_si,DBE_VALUE);
pParms->p_ep = pParms->p_sp + ((pscan->npts - 1) * pParms->p_si);
db_post_events(pscan,&pParms->p_ep,DBE_VALUE);
pParms->p_cp = (pParms->p_ep + pParms->p_sp)/2;
db_post_events(pscan,&pParms->p_cp,DBE_VALUE);
return;
/* if start/center/inc are not frozen, change them */
} else if(!pParms->p_fs && !pParms->p_fc && !pParms->p_fi) {
pParms->p_si = pParms->p_wd/(pscan->npts - 1);
db_post_events(pscan,&pParms->p_si,DBE_VALUE);
pParms->p_sp = pParms->p_ep - ((pscan->npts - 1) * pParms->p_si);
db_post_events(pscan,&pParms->p_sp,DBE_VALUE);
pParms->p_cp = (pParms->p_ep + pParms->p_sp)/2;
db_post_events(pscan,&pParms->p_cp,DBE_VALUE);
return;
/* if # of points/start/end are not frozen, change them */
} else if(!pscan->fpts && !pParms->p_fs && !pParms->p_fe) {
pscan->npts = (pParms->p_wd/pParms->p_si) + 1;
if(pscan->npts > pscan->mpts) {
pscan->npts = pscan->mpts;
sprintf(pscan->smsg,"P%1d Request Exceeded Maximum Points !",i);
/* adjust changed field to be consistent */
pParms->p_wd = (pParms->p_si * (pscan->npts - 1));
db_post_events(pscan,&pParms->p_wd,DBE_VALUE);
pscan->alrt = 1;
}
db_post_events(pscan,&pscan->npts,DBE_VALUE);
pParms->p_sp = pParms->p_cp - ((pscan->npts - 1) * pParms->p_si)/2;
db_post_events(pscan,&pParms->p_sp,DBE_VALUE);
pParms->p_ep = pParms->p_sp + ((pscan->npts - 1) * pParms->p_si);
db_post_events(pscan,&pParms->p_ep,DBE_VALUE);
precPvt->nptsCause = i; /* indicate cause of # of points changed */
changedNpts(pscan);
return;
/* if # of points/center/end are not frozen, change them */
} else if(!pscan->fpts && !pParms->p_fc && !pParms->p_fe) {
pscan->npts = (pParms->p_wd/pParms->p_si) + 1;
if(pscan->npts > pscan->mpts) {
pscan->npts = pscan->mpts;
sprintf(pscan->smsg,"P%1d Request Exceeded Maximum Points !",i);
/* adjust changed field to be consistent */
pParms->p_wd = (pParms->p_si * (pscan->npts - 1));
db_post_events(pscan,&pParms->p_wd,DBE_VALUE);
pscan->alrt = 1;
}
db_post_events(pscan,&pscan->npts,DBE_VALUE);
pParms->p_ep = pParms->p_sp + ((pscan->npts - 1) * pParms->p_si);
db_post_events(pscan,&pParms->p_ep,DBE_VALUE);
pParms->p_cp = (pParms->p_ep + pParms->p_sp)/2;
db_post_events(pscan,&pParms->p_cp,DBE_VALUE);
precPvt->nptsCause = i; /* indicate cause of # of points changed */
changedNpts(pscan);
return;
/* if # of points/start/center are not frozen, change them */
} else if(!pscan->fpts && !pParms->p_fs && !pParms->p_fc) {
pscan->npts = (pParms->p_wd/pParms->p_si) + 1;
if(pscan->npts > pscan->mpts) {
pscan->npts = pscan->mpts;
sprintf(pscan->smsg,"P%1d Request Exceeded Maximum Points !",i);
/* adjust changed field to be consistent */
pParms->p_wd = (pParms->p_si * (pscan->npts - 1));
db_post_events(pscan,&pParms->p_wd,DBE_VALUE);
pscan->alrt = 1;
}
db_post_events(pscan,&pscan->npts,DBE_VALUE);
pParms->p_sp = pParms->p_ep - ((pscan->npts - 1) * pParms->p_si);
db_post_events(pscan,&pParms->p_sp,DBE_VALUE);
pParms->p_cp = (pParms->p_ep + pParms->p_sp)/2;
db_post_events(pscan,&pParms->p_cp,DBE_VALUE);
precPvt->nptsCause = i; /* indicate cause of # of points changed */
changedNpts(pscan);
return;
} else { /* too constrained !! */
pParms->p_wd = (pParms->p_ep - pParms->p_sp);
db_post_events(pscan,&pParms->p_wd,DBE_VALUE);
sprintf(pscan->smsg,"P%1d SCAN Parameters Too Constrained !",i);
pscan->alrt = 1;
return;
}
break;
default:
return;
}
}
/* This routine attempts to bring all linear scan parameters into
* "consistency". It is used at init and when the # of pts changes.
* If the number of points changed because of a change in a Positioner's
* scan parameters, that positioner is skipped to make sure that there is
* no conflict with that logic.
*
*/
static void changedNpts(pscan)
struct scanRecord *pscan;
{
struct recPvtStruct *precPvt = (struct recPvtStruct *)pscan->rpvt;
struct linScanParms *pParms;
int i;
unsigned short freezeState = 0;
/* for each positioner, calculate scan params as best as we can */
for(i=1; i <= 4; i++) {
/* Skip the positioner that caused this */
if(i == precPvt->nptsCause) i++;
if(i==1)
pParms = (struct linScanParms *)&pscan->p1sp;
else if(i==2)
pParms = (struct linScanParms *)&pscan->p2sp;
else if(i==3)
pParms = (struct linScanParms *)&pscan->p3sp;
else if(i==4)
pParms = (struct linScanParms *)&pscan->p4sp;
else
return;
/* develop freezeState switching word ... */
/* START_FRZ | STEP_FRZ | END_FRZ | CENTER_FRZ | WIDTH_FRZ */
freezeState = (pParms->p_fs << 4) |
(pParms->p_fi << 3) |
(pParms->p_fe << 2) |
(pParms->p_fc << 1) |
(pParms->p_fw);
if(scanRecDebug) {
printf("Freeze State of P%1d = 0x%hx \n",i,freezeState);
}
switch(freezeState) {
case(0): /* end/center/width unfrozen, change them */
case(8):
case(16):
case(24):
pParms->p_ep = pParms->p_sp + ((pscan->npts - 1) * pParms->p_si);
db_post_events(pscan,&pParms->p_ep,DBE_VALUE);
pParms->p_cp = (pParms->p_ep + pParms->p_sp)/2;
db_post_events(pscan,&pParms->p_cp,DBE_VALUE);
pParms->p_wd = (pParms->p_ep - pParms->p_sp);
db_post_events(pscan,&pParms->p_wd,DBE_VALUE);
break;
case(4): /* start/center/width are not frozen, change them */
case(12):
pParms->p_sp = pParms->p_ep - ((pscan->npts - 1) * pParms->p_si);
db_post_events(pscan,&pParms->p_sp,DBE_VALUE);
pParms->p_cp = (pParms->p_ep + pParms->p_sp)/2;
db_post_events(pscan,&pParms->p_cp,DBE_VALUE);
pParms->p_wd = (pParms->p_ep - pParms->p_sp);
db_post_events(pscan,&pParms->p_wd,DBE_VALUE);
break;
case(2): /* if center is frozen, but not width/start/end , ... */
case(10):
pParms->p_sp = pParms->p_cp - ((pscan->npts - 1) * pParms->p_si)/2;
db_post_events(pscan,&pParms->p_sp,DBE_VALUE);
pParms->p_ep = pParms->p_sp + ((pscan->npts - 1) * pParms->p_si);
db_post_events(pscan,&pParms->p_ep,DBE_VALUE);
pParms->p_wd = (pParms->p_ep - pParms->p_sp);
db_post_events(pscan,&pParms->p_wd,DBE_VALUE);
break;
case(1): /* if center or width is frozen, but not inc , ... */
case(3):
case(5): /* if end/center or end/width are frozen, but not inc, */
case(6):
case(7):
case(17): /* if start/center or start/width are frozen, but not inc*/
case(18):
case(19):
case(20):
case(21):
case(22):
case(23):
pParms->p_si = (pParms->p_ep - pParms->p_sp)/(pscan->npts - 1);
db_post_events(pscan,&pParms->p_si,DBE_VALUE);
break;
/* The following freezeStates are known to be "Too Constrained" */
/* 9,11,13,14,15,25,26,27,28,29,30,31 */
default: /* too constrained !! */
sprintf(pscan->smsg,"P%1d SCAN Parameters Too Constrained !",i);
pscan->alrt = 1;
break;
}
}
}
static void checkScanLimits(pscan)
struct scanRecord *pscan;
{
struct recPvtStruct *precPvt = (struct recPvtStruct *)pscan->rpvt;
/* for each valid positioner, fetch control limits */
long status;
long nRequest = 1;
long options = DBR_CTRL_DOUBLE;
long abortScan = 0;
int i;
double value;
/* for each valid positioner, fetch control limits */
if(!pscan->p1nv) {
status = dbGet(pscan->p1db, DBR_FLOAT, precPvt->pP1Limits,
&options, &nRequest, NULL);
}
if(!pscan->p2nv) {
nRequest = 1;
status = dbGet(pscan->p2db, DBR_FLOAT, precPvt->pP2Limits,
&options, &nRequest, NULL);
}
if(!pscan->p3nv) {
nRequest = 1;
status = dbGet(pscan->p3db, DBR_FLOAT, precPvt->pP3Limits,
&options, &nRequest, NULL);
}
if(!pscan->p4nv) {
nRequest = 1;
status = dbGet(pscan->p4db, DBR_FLOAT, precPvt->pP4Limits,
&options, &nRequest, NULL);
}
if(scanRecDebug) {
if(!pscan->p1nv)
printf("P1 Control Limits : %.4f %.4f\n",
precPvt->pP1Limits->lower_ctrl_limit,
precPvt->pP1Limits->upper_ctrl_limit);
if(!pscan->p2nv)
printf("P2 Control Limits : %.4f %.4f\n",
precPvt->pP2Limits->lower_ctrl_limit,
precPvt->pP2Limits->upper_ctrl_limit);
if(!pscan->p3nv)
printf("P3 Control Limits : %.4f %.4f\n",
precPvt->pP3Limits->lower_ctrl_limit,
precPvt->pP3Limits->upper_ctrl_limit);
if(!pscan->p4nv)
printf("P4 Control Limits : %.4f %.4f\n",
precPvt->pP4Limits->lower_ctrl_limit,
precPvt->pP4Limits->upper_ctrl_limit);
}
/* check each point of scan against control limits. */
/* Stop on first error */
for(i=0; i<pscan->npts; i++) {
if(!pscan->p1nv) {
/* determine next desired position for each positioner */
if(pscan->p1sm == REC_SCAN_MO_LIN) {
value = pscan->p1sp + (i * pscan->p1si);
}
else if(pscan->p1sm == REC_SCAN_MO_TAB) {
value = pscan->p1pa[i];
}
else {
/* this is on-the-fly, so set to end position */
if(i == 0) value = pscan->p1sp;
else value = pscan->p1sp + pscan->p1si;
}
if(value < precPvt->pP1Limits->lower_ctrl_limit) {
sprintf(pscan->smsg,"P1 Value < LO_Limit @ point %1d",i);
pscan->alrt = 1;
return;
}
else if(value > precPvt->pP1Limits->upper_ctrl_limit) {
sprintf(pscan->smsg,"P1 Value > HI_Limit @ point %1d",i);
pscan->alrt = 1;
return;
}
}
if(!pscan->p2nv) {
/* determine next desired position for each positioner */
if(pscan->p2sm == REC_SCAN_MO_LIN) {
value = pscan->p2sp + (i * pscan->p2si);
}
else if(pscan->p2sm == REC_SCAN_MO_TAB) {
value = pscan->p2pa[i];
}
else {
/* this is on-the-fly, so set to end position */
if(i == 0) value = pscan->p2sp;
else value = pscan->p2sp + pscan->p2si;
}
if(value < precPvt->pP2Limits->lower_ctrl_limit) {
sprintf(pscan->smsg,"P2 Value < LO_Limit @ point %1d",i);
pscan->alrt = 1;
return;
}
else if(value > precPvt->pP2Limits->upper_ctrl_limit) {
sprintf(pscan->smsg,"P2 Value > HI_Limit @ point %1d",i);
pscan->alrt = 1;
return;
}
}
if(!pscan->p3nv) {
/* determine next desired position for each positioner */
if(pscan->p3sm == REC_SCAN_MO_LIN) {
value = pscan->p3sp + (i * pscan->p3si);
}
else if(pscan->p3sm == REC_SCAN_MO_TAB) {
value = pscan->p3pa[i];
}
else {
/* this is on-the-fly, so set to end position */
if(i == 0) value = pscan->p3sp;
else value = pscan->p3sp + pscan->p3si;
}
if(value < precPvt->pP3Limits->lower_ctrl_limit) {
sprintf(pscan->smsg,"P3 Value < LO_Limit @ point %1d",i);
pscan->alrt = 1;
return;
}
else if(value > precPvt->pP3Limits->upper_ctrl_limit) {
sprintf(pscan->smsg,"P3 Value > HI_Limit @ point %1d",i);
pscan->alrt = 1;
return;
}
}
if(!pscan->p4nv) {
/* determine next desired position for each positioner */
if(pscan->p4sm == REC_SCAN_MO_LIN) {
value = pscan->p4sp + (i * pscan->p4si);
}
else if(pscan->p4sm == REC_SCAN_MO_TAB) {
value = pscan->p4pa[i];
}
else {
/* this is on-the-fly, so set to end position */
if(i == 0) value = pscan->p4sp;
else value = pscan->p4sp + pscan->p4si;
}
if(value < precPvt->pP4Limits->lower_ctrl_limit) {
sprintf(pscan->smsg,"P4 Value < LO_Limit @ point %1d",i);
pscan->alrt = 1;
return;
}
else if(value > precPvt->pP4Limits->upper_ctrl_limit) {
sprintf(pscan->smsg,"P4 Value > HI_Limit @ point %1d",i);
pscan->alrt = 1;
return;
}
}
}
/* No errors if we made it here ... */
sprintf(pscan->smsg,"SCAN Values within limits");
}
/* This routine fills the position 1 array with the scan positions
* and fills the detector 1 array with 1's. If the detector 1 array
* is plotted against the position 1 array, a plot is generated
* showing the scan range specified. This provides a graphical
* view of the scan range while changing scan paramters.
*
*/
static void drawPos1Scan(pscan)
struct scanRecord *pscan;
{
struct recPvtStruct *precPvt = (struct recPvtStruct *)pscan->rpvt;
struct linScanParms *pParms;
int i;
unsigned short freezeState = 0;
float desValue;
desValue = pscan->p1sp;
for(i=0; i<pscan->npts; i++) {
pscan->p1pa[i] = desValue + (i * pscan->p1si);
pscan->d1da[i] = 1;
}
/* fill array with last position */
for(i=i; i<pscan->mpts;i++) {
pscan->p1pa[i] = pscan->p1pa[i-1];
pscan->d1da[i] = 1;
}
db_post_events(pscan,pscan->p1pa, DBE_VALUE);
db_post_events(pscan,precPvt->pdet1DataA, DBE_VALUE);
db_post_events(pscan,precPvt->pdet1DataB, DBE_VALUE);
}
static void saveFrzFlags(pscan)
struct scanRecord *pscan;
{
struct recPvtStruct *precPvt = (struct recPvtStruct *)pscan->rpvt;
/* save state of each freeze flag */
precPvt->fpts = pscan->fpts;
precPvt->p1fs = pscan->p1fs;
precPvt->p1fi = pscan->p1fi;
precPvt->p1fc = pscan->p1fc;
precPvt->p1fe = pscan->p1fe;
precPvt->p1fw = pscan->p1fw;
precPvt->p2fs = pscan->p2fs;
precPvt->p2fi = pscan->p2fi;
precPvt->p2fc = pscan->p2fc;
precPvt->p2fe = pscan->p2fe;
precPvt->p2fw = pscan->p2fw;
precPvt->p3fs = pscan->p3fs;
precPvt->p3fi = pscan->p3fi;
precPvt->p3fc = pscan->p3fc;
precPvt->p3fe = pscan->p3fe;
precPvt->p3fw = pscan->p3fw;
precPvt->p4fs = pscan->p4fs;
precPvt->p4fi = pscan->p4fi;
precPvt->p4fc = pscan->p4fc;
precPvt->p4fe = pscan->p4fe;
precPvt->p4fw = pscan->p4fw;
}
static void resetFrzFlags(pscan)
struct scanRecord *pscan;
{
struct recPvtStruct *precPvt = (struct recPvtStruct *)pscan->rpvt;
/* reset each frzFlag, post monitor if changed */
if(pscan->fpts) {
pscan->fpts = 0;
db_post_events(pscan,&pscan->fpts, DBE_VALUE);
}
if(pscan->p1fs) {
pscan->p1fs = 0;
db_post_events(pscan,&pscan->p1fs, DBE_VALUE);
}
if(pscan->p1fi) {
pscan->p1fi = 0;
db_post_events(pscan,&pscan->p1fi, DBE_VALUE);
}
if(pscan->p1fc) {
pscan->p1fc = 0;
db_post_events(pscan,&pscan->p1fc, DBE_VALUE);
}
if(pscan->p1fe) {
pscan->p1fe = 0;
db_post_events(pscan,&pscan->p1fe, DBE_VALUE);
}
if(pscan->p1fw) {
pscan->p1fw = 0;
db_post_events(pscan,&pscan->p1fw, DBE_VALUE);
}
if(pscan->p2fs) {
pscan->p2fs = 0;
db_post_events(pscan,&pscan->p2fs, DBE_VALUE);
}
if(pscan->p2fi) {
pscan->p2fi = 0;
db_post_events(pscan,&pscan->p2fi, DBE_VALUE);
}
if(pscan->p2fc) {
pscan->p2fc = 0;
db_post_events(pscan,&pscan->p2fc, DBE_VALUE);
}
if(pscan->p2fe) {
pscan->p2fe = 0;
db_post_events(pscan,&pscan->p2fe, DBE_VALUE);
}
if(pscan->p2fw) {
pscan->p2fw = 0;
db_post_events(pscan,&pscan->p2fw, DBE_VALUE);
}
if(pscan->p3fs) {
pscan->p3fs = 0;
db_post_events(pscan,&pscan->p3fs, DBE_VALUE);
}
if(pscan->p3fi) {
pscan->p3fi = 0;
db_post_events(pscan,&pscan->p3fi, DBE_VALUE);
}
if(pscan->p3fc) {
pscan->p3fc = 0;
db_post_events(pscan,&pscan->p3fc, DBE_VALUE);
}
if(pscan->p3fe) {
pscan->p3fe = 0;
db_post_events(pscan,&pscan->p3fe, DBE_VALUE);
}
if(pscan->p3fw) {
pscan->p3fw = 0;
db_post_events(pscan,&pscan->p3fw, DBE_VALUE);
}
if(pscan->p4fs) {
pscan->p4fs = 0;
db_post_events(pscan,&pscan->p4fs, DBE_VALUE);
}
if(pscan->p4fi) {
pscan->p4fi = 0;
db_post_events(pscan,&pscan->p4fi, DBE_VALUE);
}
if(pscan->p4fc) {
pscan->p4fc = 0;
db_post_events(pscan,&pscan->p4fc, DBE_VALUE);
}
if(pscan->p4fe) {
pscan->p4fe = 0;
db_post_events(pscan,&pscan->p4fe, DBE_VALUE);
}
if(pscan->p4fw) {
pscan->p4fw = 0;
db_post_events(pscan,&pscan->p4fw, DBE_VALUE);
}
}
/* Restores Freeze Flags to the state they were in */
static void restoreFrzFlags(pscan)
struct scanRecord *pscan;
{
struct recPvtStruct *precPvt = (struct recPvtStruct *)pscan->rpvt;
/* restore state of each freeze flag, post if changed */
pscan->fpts = precPvt->fpts;
if(pscan->fpts) {
db_post_events(pscan,&pscan->fpts, DBE_VALUE);
}
pscan->p1fs = precPvt->p1fs;
if(pscan->p1fs) {
db_post_events(pscan,&pscan->p1fs, DBE_VALUE);
}
pscan->p1fi = precPvt->p1fi;
if(pscan->p1fi) {
db_post_events(pscan,&pscan->p1fi, DBE_VALUE);
}
pscan->p1fc = precPvt->p1fc;
if(pscan->p1fc) {
db_post_events(pscan,&pscan->p1fc, DBE_VALUE);
}
pscan->p1fe = precPvt->p1fe;
if(pscan->p1fe) {
db_post_events(pscan,&pscan->p1fe, DBE_VALUE);
}
pscan->p1fw = precPvt->p1fw;
if(pscan->p1fw) {
db_post_events(pscan,&pscan->p1fw, DBE_VALUE);
}
pscan->p2fs = precPvt->p2fs;
if(pscan->p2fs) {
db_post_events(pscan,&pscan->p2fs, DBE_VALUE);
}
pscan->p2fi = precPvt->p2fi;
if(pscan->p2fi) {
db_post_events(pscan,&pscan->p2fi, DBE_VALUE);
}
pscan->p2fc = precPvt->p2fc;
if(pscan->p2fc) {
db_post_events(pscan,&pscan->p2fc, DBE_VALUE);
}
pscan->p2fe = precPvt->p2fe;
if(pscan->p2fe) {
db_post_events(pscan,&pscan->p2fe, DBE_VALUE);
}
pscan->p2fw = precPvt->p2fw;
if(pscan->p2fw) {
db_post_events(pscan,&pscan->p2fw, DBE_VALUE);
}
pscan->p3fs = precPvt->p3fs;
if(pscan->p3fs) {
db_post_events(pscan,&pscan->p3fs, DBE_VALUE);
}
pscan->p3fi = precPvt->p3fi;
if(pscan->p3fi) {
db_post_events(pscan,&pscan->p3fi, DBE_VALUE);
}
pscan->p3fc = precPvt->p3fc;
if(pscan->p3fc) {
db_post_events(pscan,&pscan->p3fc, DBE_VALUE);
}
pscan->p3fe = precPvt->p3fe;
if(pscan->p3fe) {
db_post_events(pscan,&pscan->p3fe, DBE_VALUE);
}
pscan->p3fw = precPvt->p3fw;
if(pscan->p3fw) {
db_post_events(pscan,&pscan->p3fw, DBE_VALUE);
}
pscan->p4fs = precPvt->p4fs;
if(pscan->p4fs) {
db_post_events(pscan,&pscan->p4fs, DBE_VALUE);
}
pscan->p4fi = precPvt->p4fi;
if(pscan->p4fi) {
db_post_events(pscan,&pscan->p4fi, DBE_VALUE);
}
pscan->p4fc = precPvt->p4fc;
if(pscan->p4fc) {
db_post_events(pscan,&pscan->p4fc, DBE_VALUE);
}
pscan->p4fe = precPvt->p4fe;
if(pscan->p4fe) {
db_post_events(pscan,&pscan->p4fe, DBE_VALUE);
}
pscan->p4fw = precPvt->p4fw;
if(pscan->p4fw) {
db_post_events(pscan,&pscan->p4fw, DBE_VALUE);
}
}