forked from epics_driver_modules/motorBase
dcf7b37c89
Need to set USE_TYPED_RSET to avoid a warning whencompiling against Base R3.16.1 Older Bases don't know the #define, and R3.16.1 seems to need it.
334 lines
8.7 KiB
C++
334 lines
8.7 KiB
C++
/*
|
|
FILENAME... devSoft.cc
|
|
USAGE... Motor record device level support for Soft channel.
|
|
|
|
*/
|
|
|
|
/*
|
|
* Original Author: Ron Sluiter
|
|
* Date: 06/15/99
|
|
*
|
|
* Experimental Physics and Industrial Control System (EPICS)
|
|
*
|
|
* Copyright 1991, the University of Chicago Board of Governors.
|
|
*
|
|
* This software was produced under U.S. Government contract
|
|
* W-31-109-ENG-38 at Argonne National Laboratory.
|
|
*
|
|
* Beamline Controls & Data Acquisition Group
|
|
* Experimental Facilities Division
|
|
* Advanced Photon Source
|
|
* Argonne National Laboratory
|
|
*
|
|
* Modification Log:
|
|
* -----------------
|
|
*
|
|
* .00 02-06-02 rls - Don't process from events unless interruptAccept is TRUE.
|
|
* - When done transitions from false to true it is not
|
|
* communicated to the motor record until after the last
|
|
* readback update.
|
|
* - In soft_process(), call dbProcess() instead of directly
|
|
* calling motor record's process().
|
|
* - In soft_rdbl_func(), reset motor record's target to actual
|
|
* position after last readback if motion was not initiated
|
|
* by this record.
|
|
* .01 10-29-02 rls - LOCK field added to prevent synchronization due to
|
|
* changing readback.
|
|
* .02 06-16-03 rls Convert to R3.14.x.
|
|
* .03 08-03-05 rls - Added debug messages.
|
|
* - Fix compiler error with "gcc version 3.4.2 20041017 (Red
|
|
* Hat 3.4.2-6.fc3)".
|
|
*/
|
|
|
|
|
|
/*
|
|
NOTES...
|
|
- Can't call CA functions until after dbLockInitRecords() has been called and initialized lock sets.
|
|
*/
|
|
|
|
/* The following is needed to compile against Base R3.16.1 without a warning */
|
|
#define USE_TYPED_RSET
|
|
|
|
#include <dbDefs.h>
|
|
#include <dbFldTypes.h>
|
|
#include <dbAccess.h>
|
|
#include <dbEvent.h>
|
|
#include <recSup.h>
|
|
#include <stdarg.h>
|
|
|
|
#include "motorRecord.h"
|
|
#include "motor.h"
|
|
#include "devSoft.h"
|
|
|
|
#include "epicsExport.h"
|
|
#include "errlog.h"
|
|
|
|
/*----------------debugging-----------------*/
|
|
volatile int devSoftdebug = 0;
|
|
extern "C"
|
|
{epicsExportAddress(int, devSoftdebug);}
|
|
static inline void Debug(int level, const char *format, ...)
|
|
{
|
|
#ifdef DEBUG
|
|
if (level < devSoftdebug)
|
|
{
|
|
va_list pVar;
|
|
va_start(pVar, format);
|
|
vprintf(format, pVar);
|
|
va_end(pVar);
|
|
}
|
|
#endif
|
|
}
|
|
|
|
static CALLBACK_VALUE update(struct motorRecord *);
|
|
static long start(struct motorRecord *);
|
|
static RTN_STATUS build(motor_cmnd, double *, struct motorRecord *);
|
|
static RTN_STATUS end(struct motorRecord *);
|
|
static void soft_process(struct motorRecord *);
|
|
|
|
|
|
struct motor_dset devMotorSoft =
|
|
{
|
|
{8, NULL, (DEVSUPFUN) soft_init, (DEVSUPFUN) soft_init_record, NULL},
|
|
update,
|
|
start,
|
|
build,
|
|
end
|
|
};
|
|
|
|
extern "C" {epicsExportAddress(dset, devMotorSoft);}
|
|
|
|
static CALLBACK_VALUE update(struct motorRecord *mr)
|
|
{
|
|
struct soft_private *ptr = (struct soft_private *) mr->dpvt;
|
|
msta_field status;
|
|
|
|
#ifdef DMR_SOFTMOTOR_MODS
|
|
if (ptr->load_position)
|
|
{
|
|
mr->rmp = ptr->new_position;
|
|
mr->rep = ptr->new_position;
|
|
ptr->load_position = FALSE;
|
|
}
|
|
#endif
|
|
|
|
status.All = mr->msta;
|
|
|
|
Debug(5, "update(): dmov=%d for %s.\n", mr->dmov, mr->name);
|
|
|
|
if (ptr->dinp_value == SOFTMOVE || ptr->dinp_value == HARDMOVE)
|
|
{
|
|
Debug(5, "update(): DMOV=0 for %s.\n", mr->name);
|
|
status.Bits.RA_DONE = 0;
|
|
}
|
|
else
|
|
{
|
|
Debug(5, "update(): DMOV=1 for %s.\n", mr->name);
|
|
status.Bits.RA_DONE = 1;
|
|
}
|
|
mr->msta = status.All;
|
|
return(ptr->callback_flag);
|
|
}
|
|
|
|
|
|
static long start(struct motorRecord *mr)
|
|
{
|
|
return((long) OK);
|
|
}
|
|
|
|
|
|
static RTN_STATUS end(struct motorRecord *mr)
|
|
{
|
|
struct soft_private *ptr = (struct soft_private *) mr->dpvt;
|
|
|
|
if (ptr->default_done_behavior == YES)
|
|
{
|
|
msta_field status;
|
|
|
|
status.All = 0;
|
|
status.Bits.RA_DONE = 1;
|
|
mr->msta = status.All;
|
|
}
|
|
return(OK);
|
|
}
|
|
|
|
|
|
static RTN_STATUS build(motor_cmnd command, double *parms, struct motorRecord *mr)
|
|
{
|
|
const short int stop = 1;
|
|
long int status = 0;
|
|
|
|
switch (command)
|
|
{
|
|
case MOVE_ABS:
|
|
case MOVE_REL:
|
|
status = dbPutLink(&mr->out, DBR_DOUBLE, &mr->dval, 1);
|
|
break;
|
|
|
|
case STOP_AXIS:
|
|
status = dbPutLink(&mr->stoo, DBR_SHORT, &stop, 1);
|
|
break;
|
|
|
|
case SET_HIGH_LIMIT:
|
|
case SET_LOW_LIMIT:
|
|
status = OK;
|
|
break;
|
|
|
|
case LOAD_POS:
|
|
{
|
|
struct soft_private *ptr = (struct soft_private *) mr->dpvt;
|
|
msta_field msta;
|
|
|
|
#ifdef DMR_SOFTMOTOR_MODS
|
|
ptr->load_position = TRUE;
|
|
ptr->new_position = *parms;
|
|
#endif
|
|
msta.All = 0;
|
|
msta.Bits.RA_DONE = 1;
|
|
mr->msta = msta.All;
|
|
callbackRequest(&ptr->callback);
|
|
}
|
|
break;
|
|
|
|
default:
|
|
status = ERROR;
|
|
}
|
|
return(status == 0 ? OK : ERROR);
|
|
}
|
|
|
|
|
|
/*
|
|
FUNCTION... void soft_dinp_func(struct motorRecord *, short)
|
|
USAGE... Update soft channel device input links and
|
|
process soft channel motor record when done moving.
|
|
LOGIC...
|
|
IF DINP link value is FALSE.
|
|
IF this soft motor's DMOV is FALSE.
|
|
This is a soft motor initiated move.
|
|
Set SOFTMOVE indicator.
|
|
ELSE IF LOCK field set to NO.
|
|
This is NOT a soft motor initiated move.
|
|
Set HARDMOVE indicator.
|
|
Set soft motor's DMOV FALSE.
|
|
Set PostProcess (PP) TRUE.
|
|
ENDIF
|
|
ELSE
|
|
IF DINP state is HARDMOVE.
|
|
Set PostProcess (PP) True.
|
|
Set DINP state to DONE.
|
|
Process soft channel record.
|
|
ENDIF
|
|
*/
|
|
void soft_dinp_func(struct motorRecord *mr, short newdinp)
|
|
{
|
|
struct soft_private *ptr = (struct soft_private *) mr->dpvt;
|
|
|
|
if (interruptAccept != TRUE)
|
|
return;
|
|
|
|
/* Test for hard motor started moving or initialization. */
|
|
if (newdinp == 0)
|
|
{
|
|
if (mr->dmov == FALSE)
|
|
{
|
|
Debug(5, "soft_dinp_func(): SOFTMOVE set for %s.\n", mr->name);
|
|
ptr->dinp_value = SOFTMOVE;
|
|
}
|
|
else if (mr->lock == menuYesNoNO)
|
|
{ /* Hard motor is moving independent of soft motor. */
|
|
Debug(5, "soft_dinp_func(): HARDMOVE set for %s.\n", mr->name);
|
|
ptr->dinp_value = HARDMOVE;
|
|
mr->dmov = FALSE;
|
|
db_post_events(mr, &mr->dmov, DBE_VAL_LOG);
|
|
mr->pp = TRUE;
|
|
db_post_events(mr, &mr->pp, DBE_VAL_LOG);
|
|
}
|
|
}
|
|
else /* Hard motor is done moving. */
|
|
{
|
|
if (ptr->dinp_value == HARDMOVE)
|
|
mr->pp = TRUE;
|
|
ptr->dinp_value = DONE;
|
|
Debug(5, "soft_dinp_func(): Done moving set for %s.\n", mr->name);
|
|
soft_process(mr); /* Process in case there is no readback callback. */
|
|
}
|
|
}
|
|
|
|
|
|
void soft_rinp_func(struct motorRecord *mr, long newrinp)
|
|
{
|
|
if (interruptAccept != TRUE)
|
|
return;
|
|
|
|
mr->rmp = newrinp;
|
|
soft_process(mr);
|
|
}
|
|
|
|
|
|
void soft_rdbl_func(struct motorRecord *mr, double newrdbl)
|
|
{
|
|
struct soft_private *ptr = (struct soft_private *) mr->dpvt;
|
|
|
|
if (interruptAccept != TRUE)
|
|
return;
|
|
|
|
newrdbl = newrdbl / mr->mres;
|
|
mr->rmp = NINT(newrdbl);
|
|
|
|
Debug(5, "soft_rdbl_func(): updated RMP = %d for %s.\n", mr->rmp, mr->name);
|
|
|
|
if (ptr->initialized == false)
|
|
{
|
|
/* Reset Target to Actual position. */
|
|
unsigned short mask = (DBE_VALUE | DBE_LOG);
|
|
|
|
mr->dmov = FALSE;
|
|
db_post_events(mr, &mr->dmov, mask);
|
|
mr->pp = TRUE;
|
|
db_post_events(mr, &mr->pp, mask);
|
|
|
|
ptr->dinp_value = DONE;
|
|
ptr->initialized = true;
|
|
}
|
|
soft_process(mr);
|
|
}
|
|
|
|
|
|
/*
|
|
FUNCTION... static void soft_process(struct motorRecord *)
|
|
USAGE... Process the soft channel motor record.
|
|
LOGIC...
|
|
Lock soft channel record - call dbScanLock().
|
|
Set call back flag to CALLBACK_DATA so readback will get updated.
|
|
Process soft channel record - call process().
|
|
Unlock soft channel record - call dbScanUnlock().
|
|
*/
|
|
|
|
static void soft_process(struct motorRecord *mr)
|
|
{
|
|
struct soft_private *ptr = (struct soft_private *) mr->dpvt;
|
|
|
|
dbScanLock((struct dbCommon *) mr);
|
|
ptr->callback_flag = CALLBACK_DATA;
|
|
dbProcess((struct dbCommon *) mr); /* Process the soft channel record. */
|
|
ptr->callback_flag = NOTHING_DONE;
|
|
dbScanUnlock((struct dbCommon *) mr);
|
|
}
|
|
|
|
|
|
/*
|
|
FUNCTION... void soft_motor_callback(CALLBACK *)
|
|
USAGE... Process motor record after the following events:
|
|
- LOAD_POS motor command.
|
|
LOGIC...
|
|
*/
|
|
|
|
void soft_motor_callback(CALLBACK *cbptr)
|
|
{
|
|
void *mr;
|
|
|
|
callbackGetUser(mr, cbptr);
|
|
soft_process((motorRecord *) mr);
|
|
}
|
|
|