Files
motorBase/motorApp/SoftMotorSrc/devSoft.cc
T
2004-01-22 22:22:04 +00:00

308 lines
7.0 KiB
C++

/*
FILENAME... devSoft.cc
USAGE... Motor record device level support for Soft channel.
Version: $Revision: 1.8 $
Modified By: $Author: sluiter $
Last Modified: $Date: 2004-01-22 22:22:04 $
*/
/*
* 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.
*/
/*
NOTES...
- Can't call CA functions until after dbLockInitRecords() has
been called and initialized lock sets.
*/
#include <dbDefs.h>
#include <dbFldTypes.h>
#include <dbAccess.h>
#include <dbEvent.h>
#include <recSup.h>
#include "motorRecord.h"
#include "motor.h"
#include "devSoft.h"
#include "epicsExport.h"
#define STATIC static
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
};
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;
if (ptr->dinp_value == SOFTMOVE || ptr->dinp_value == HARDMOVE)
status.Bits.RA_DONE = 0;
else
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 TRUE to FALSE transition.
IF this soft motor's DMOV is FALSE.
This is a soft motor initiated move.
Set SOFTMOVE indicator.
ELSE
This is NOT a soft motor initiated move.
Set HARDMOVE indicator.
Set soft motor's DMOV FALSE.
Set PP TRUE.
ENDIF
ENDIF
Get DINP_VALUE via DINP link.
IF Get() succeeds and DINP_VALUE is true
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)
ptr->dinp_value = SOFTMOVE;
else if (mr->lock == menuYesNoNO)
{ /* Hard motor is moving independent of soft motor. */
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;
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);
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)
{
#ifdef __GNUG__
struct motorRecord *mr;
callbackGetUser((void *) mr, cbptr);
soft_process(mr);
#else
void *mr;
callbackGetUser(mr, cbptr);
soft_process((motorRecord *) mr);
#endif
}