1994 1995 1996 1997 1998 1999 2000 2001 2002 2003 2004 2005 2006 2007 2008 2009 2010 2011 2012 2013 2014 2015 2016 <2017> 2018 2019 2020 2021 2022 2023 2024 | Index | 1994 1995 1996 1997 1998 1999 2000 2001 2002 2003 2004 2005 2006 2007 2008 2009 2010 2011 2012 2013 2014 2015 2016 <2017> 2018 2019 2020 2021 2022 2023 2024 |
<== Date ==> | <== Thread ==> |
---|
Subject: | new Scaler driver |
From: | 梁雅翔 <[email protected]> |
To: | tech-talk <[email protected]> |
Date: | Thu, 21 Sep 2017 22:39:41 +0800 (GMT+08:00) |
Hi all,
I am trying to modified drvScaler974.cpp( driver of 974 scaler ) to drvScalerCT08E.cpp in std of synapps.
CT08E was a new scaler( http://www.tsuji-denshi.co.jp/english/download.html ), which has not driver in std.
In a word, I want to write the driver of CT08E base on drvScaler974.cpp in std-3-4.
The command was uncomplex. I modified the relevant command, such as clear,start and stop. But command of new scaler about "set timer", "get value of channel" was much different from 974scaler.
The new scaler command about "set timer": If I sent TPR%d(%d was millsecond), the scaler would set the timer.
The new scaler command about "get value of channel": If I sent RDAL, I should get 9 number(channel 0-7 and the timer), whose format was 0000000000 000000000 0000000000 0000000000 0000000000 0000000000 0000000000 0000000000 0000000000, nine 10 bit number divide by space. And the laset number(timer) continue increase until it equal the set time which TPR command set.
Rebuild std and ioc was ok, the ioc could run with no error except the write/read.
I am using base 3.15.2, Synapps5_8, std-3-4, Centos 7(64).
The driver file and output was following.How could I do it to achieve these function?
Could you give me some suggestion.
Thank you,
Liang yx
The content of drvScalerCT08E.cpp which I modified.
***************************************************************
#include <stdlib.h>
#include <stddef.h>
#include <string.h>
#include <stdio.h>
#include <math.h>
/******************/
/* EPICS includes */
/******************/
#include <asynPortDriver.h>
#include <asynOctetSyncIO.h>
#include <epicsEvent.h>
#include <epicsThread.h>
#include <epicsTime.h>
#include <epicsExport.h>
#include <errlog.h>
#include <iocsh.h>
#include "devScalerAsyn.h"
#define MAX_CHANNELS 8 //////////////////////////chang 4 to 8
#define timeOut 0.1
static const char *driverName= "ScalerCT08E"; // >- Scaler974 change to CT08E
class ScalerCT08E:public asynPortDriver
{
public:
ScalerCT08E(const char *portName, const char *serialPort, int serialAddr, int poll);
virtual asynStatus writeInt32(asynUser *pasynUser, epicsInt32 value);
virtual asynStatus readInt32Array(asynUser *pasynUser,epicsInt32 *value, size_t nElements, size_t *nIn);
virtual void report(FILE *fp, int details);
void eventThread();
private:
int scalerReset;
int scalerChannels;
int scalerRead;
int scalerReadSingle;
int scalerPreset;
int scalerArm;
int scalerDone;
double polltime;
epicsEventId eventId;
asynUser *pasynUserScaler;
asynStatus sendCommand(const char *command, char *statusString, size_t maxStatusLen, size_t *statusLen);
asynStatus sendCommand(const char *command, char *statusString, size_t maxStatusLen, size_t *statusLen,
char *response, size_t maxResponseLen, size_t *responseLen);
};
static void eventThreadC(void *pPvt)
{
ScalerCT08E *pScalerCT08E = (ScalerCT08E *)pPvt;
pScalerCT08E->eventThread();
}
ScalerCT08E::ScalerCT08E(const char *portName, const char *serialPort, int serialAddr, int poll)
:asynPortDriver(portName, MAX_CHANNELS, 7,
asynInt32Mask | asynInt32ArrayMask | asynDrvUserMask,
asynInt32Mask,
/* Should also be ASYN_CANBLOCK, but device support does not work with asynchronous devices */
ASYN_MULTIDEVICE,1,0,0)
{
int i;
asynStatus status;
static const char *functionName="ScalerCT08E";
if (poll==0) poll=100;
this->polltime=poll / 1000.;
this->eventId = epicsEventCreate(epicsEventEmpty);
status = pasynOctetSyncIO->connect(serialPort, serialAddr, &this->pasynUserScaler, NULL);
if (status != asynSuccess) {
asynPrint(this->pasynUserSelf, ASYN_TRACE_ERROR,
"%s:%s: error connecting to port %s address %d\n",
driverName, functionName, serialPort, serialAddr);
return;
}
createParam(SCALER_RESET_COMMAND_STRING, asynParamInt32, &this->scalerReset);
createParam(SCALER_CHANNELS_COMMAND_STRING, asynParamInt32, &this->scalerChannels);
createParam(SCALER_READ_COMMAND_STRING, asynParamInt32Array,&this->scalerRead);
createParam(SCALER_READ_SINGLE_COMMAND_STRING, asynParamInt32, &this->scalerReadSingle);
createParam(SCALER_PRESET_COMMAND_STRING, asynParamInt32, &this->scalerPreset);
createParam(SCALER_ARM_COMMAND_STRING, asynParamInt32, &this->scalerArm);
createParam(SCALER_DONE_COMMAND_STRING, asynParamInt32, &this->scalerDone);
setIntegerParam(scalerChannels, MAX_CHANNELS);
setIntegerParam(scalerDone, 1);
for (i=0; i<MAX_CHANNELS; i++) setIntegerParam(i, scalerReadSingle, 0);
epicsThreadCreate("ScalerCT08E",
epicsThreadPriorityMedium,
epicsThreadGetStackSize(epicsThreadStackMedium),
(EPICSTHREADFUNC)eventThreadC,this);
}
asynStatus ScalerCT08E::sendCommand(const char *command, char *statusString, size_t maxStatusLen, size_t *statusLen)
{
return sendCommand(command, statusString, maxStatusLen, statusLen, NULL, 0, NULL);
}
asynStatus ScalerCT08E::sendCommand(const char *command, char *statusString, size_t maxStatusLen, size_t *statusLen,
char *response, size_t maxResponseLen, size_t *responseLen)
{
size_t nWrite;
asynStatus status;
double timeout = 1.0;
int eomReason;
static const char *functionName = "sendCommand";
if (response != NULL) {
status = pasynOctetSyncIO->writeRead(this->pasynUserScaler, command, strlen(command),
response, maxResponseLen, timeout, &nWrite, responseLen, &eomReason);
if (status != asynSuccess) goto done;
status = pasynOctetSyncIO->read(this->pasynUserScaler,
statusString, maxStatusLen, timeout, statusLen, &eomReason);
} else {
status = pasynOctetSyncIO->writeRead(this->pasynUserScaler, command, strlen(command),
statusString, maxStatusLen, timeout, &nWrite, statusLen, &eomReason);
}
done:
if (status != asynSuccess) {
asynPrint(this->pasynUserSelf, ASYN_TRACE_ERROR,
"%s:%s: writing command %s, error=%s\n",
driverName, functionName, command, this->pasynUserScaler->errorMessage);
}
return(status);
}
asynStatus ScalerCT08E::writeInt32(asynUser *pasynUser, epicsInt32 value)
{
int function = pasynUser->reason;
char response[512]; //increase the number 256 ->512
size_t responseLen;
asynStatus status = asynSuccess;
static const char *functionName="writeInt32";
setIntegerParam(function, value);
if(function==this->scalerReset)
{
this->sendCommand("STOP", response, sizeof(response), &responseLen);
this->sendCommand("CLAL", response, sizeof(response), &responseLen); // i think here is the command, so I changed CLEAR_ALL to CLAL
asynPrint(pasynUser, ASYN_TRACE_FLOW, "%s:%s scalerReset\n",driverName, functionName);
}
else if(function==this->scalerArm)
{
if(value !=0)
{
/* Start counting */
this->sendCommand("STRT", response, sizeof(response), &responseLen); // START TO STRT
setIntegerParam(scalerDone, 0);
epicsEventSignal(this->eventId);
}
else
{
/* Stop counting */
status = this->sendCommand("STOP", response, sizeof(response), &responseLen);
setIntegerParam(scalerDone, 1);
}
asynPrint(pasynUser, ASYN_TRACE_FLOW, "%s:%s scalerArm=%d\n", driverName, functionName,value);
}
else if(function==this->scalerPreset) // modified a lot
{
int m; // m means millsecond
char newstr[40];
sprintf(newstr,"TPR%d",m);
this->sendCommand(newstr, response, sizeof(response), &responseLen);
asynPrint(pasynUser, ASYN_TRACE_FLOW, "%s;%s scalerPreset channel", driverName, functionName);
// setIntegerParam(scalerDone, 0);
/*
int m,n;
char newstr[20];
n=(int)log10(double(value));
m=(int)(value/pow(10.0,n));
sprintf(newstr, "SET_COUNT_PRESET %d,%d", m, n);
this->sendCommand(newstr, response, sizeof(response), &responseLen);
asynPrint(pasynUser, ASYN_TRACE_FLOW, "%s;%s scalerPreset channel", driverName, functionName);
*/
}
else
{
asynPrint(pasynUser,ASYN_TRACE_ERROR,"%s:%s got illegal function %d\n", driverName, functionName, function);
}
callParamCallbacks();
return(status);
}
asynStatus ScalerCT08E::readInt32Array(asynUser *pasynUser, epicsInt32 *value, size_t maxChannel, size_t *nIn)
{
static const char *functionName="readInt32Array";
int function = pasynUser->reason;
int temp;
int i;
if (maxChannel > MAX_CHANNELS) maxChannel = MAX_CHANNELS;
*nIn = maxChannel;
if (function==scalerRead)
{
for (i=0; i<(int)maxChannel; i++)
{
getIntegerParam(i, scalerReadSingle, &temp);
value[i] = temp;
}
asynPrint(pasynUser, ASYN_TRACEIO_DRIVER,
"%s:%s: value=%d %d %d %d\n",
driverName, functionName, value[0], value[1], value[2], value[3]);
} else {
asynPrint(pasynUser,ASYN_TRACE_ERROR,"%s:%s got illegal function %d\n", driverName, functionName, function);
return(asynError);
}
return(asynSuccess);
}
void ScalerCT08E::report(FILE *fp, int details)
{
asynPortDriver::report(fp, details);
}
void ScalerCT08E::eventThread()
{
int done, presetCount;
char response[100], statusString[20];
size_t responseLen, statusLen;
int counts[MAX_CHANNELS];
int i;
asynStatus status;
static const char *functionName="eventThread";
while(1) // SHOW_COUNTS need to change a lot,later
{
epicsEventWait(this->eventId);
while(1)
{
status = this->sendCommand("RDAL", statusString, sizeof(statusString), &statusLen,
response, sizeof(response), &responseLen);
sscanf(response, "%d %d %d %d %d %d %d %d %d",
&counts[0], &counts[1], &counts[2], &counts[3], &counts[4], &counts[5], &counts[6], &counts[7], &counts[8]); //counts[8] was the timer
asynPrint(this->pasynUserSelf, ASYN_TRACEIO_DRIVER,
"%s:%s status=%d, counts=%d %d %d %d %d %d %d %d %d\n",
driverName, functionName, status, counts[0], counts[1], counts[2], counts[3], counts[4], counts[5], counts[6], counts[7], counts[8] ); // I think here should be changed, I added "%d".
this->lock();
/* Get value of done in case scaler was stopped by scalerArm(0) */
getIntegerParam(scalerDone, &done);
getIntegerParam(scalerPreset, &presetCount);
if (!done && (counts[0] >= presetCount)) done = 1;
setIntegerParam(scalerDone, done);
for (i=0; i<MAX_CHANNELS; i++) {
setIntegerParam(i, scalerReadSingle, counts[i]);
callParamCallbacks(i, i);
}
this->unlock();
if (done) break;
epicsThreadSleep(this->polltime);
}
}
}
extern "C" int initScalerCT08E(const char *portName, const char *serialPort, int serialAddr, int poll)
{
new ScalerCT08E(portName, serialPort, serialAddr, poll);
return(asynSuccess);
}
/* iocsh function */
static const iocshArg initArg0 = {"Port Name", iocshArgString};
static const iocshArg initArg1 = {"Scaler Port", iocshArgString};
static const iocshArg initArg2 = {"GPIB address", iocshArgString};
static const iocshArg initArg3 = {"Poll", iocshArgInt};
static const iocshArg *const initArgs[] = {&initArg0,
&initArg1,
&initArg2,
&initArg3
};
static const iocshFuncDef initFuncDef = {"initScalerCT08E",4, initArgs}; // 4 means 4 channel? I have 8 channel, maybe not ,just the number of args.
static void initCallFunc(const iocshArgBuf *args)
{
initScalerCT08E(args[0].sval, args[1].sval, args[2].ival, args[3].ival); //init command
}
void ScalerCT08ERegister(void)
{
iocshRegister(&initFuncDef,initCallFunc);
}
extern "C" {
epicsExportRegistrar(ScalerCT08ERegister);
}
The information of start IOC :
************************************************************
Successfully locked memory using mlockAll
# Linux startup script
# For devIocStats
#epicsEnvSet("ENGINEER","engineer")
#epicsEnvSet("LOCATION","location")
#epicsEnvSet("GROUP","group")
< envPaths
epicsEnvSet("ARCH","linux-x86_64")
epicsEnvSet("IOC","iocLinux")
epicsEnvSet("TOP","/opt/synApps_5_8/support/xxx-5-8-3")
epicsEnvSet("SUPPORT","/opt/synApps_5_8/support")
epicsEnvSet("EPICS_BASE","/opt/base")
epicsEnvSet("ALIVE","/opt/synApps_5_8/support/alive-1-0")
epicsEnvSet("ALLEN_BRADLEY","/opt/synApps_5_8/support/allenBradley-2-3")
epicsEnvSet("AREA_DETECTOR","/opt/synApps_5_8/support/areaDetector-R2-0")
epicsEnvSet("ADCORE","/opt/synApps_5_8/support/areaDetector-R2-0/ADCore-R2-2")
epicsEnvSet("ADBINARIES","/opt/synApps_5_8/support/areaDetector-R2-0/ADBinaries-R2-2")
epicsEnvSet("ASYN","/opt/synApps_5_8/support/asyn-4-32")
epicsEnvSet("AUTOSAVE","/opt/synApps_5_8/support/autosave-5-6-1")
epicsEnvSet("BUSY","/opt/synApps_5_8/support/busy-1-6-1")
epicsEnvSet("CALC","/opt/synApps_5_8/support/calc-3-4-2-1")
epicsEnvSet("CAMAC","/opt/synApps_5_8/support/camac-2-7")
epicsEnvSet("CAPUTRECORDER","/opt/synApps_5_8/support/caputRecorder-1-6")
epicsEnvSet("DAC128V","/opt/synApps_5_8/support/dac128V-2-8")
epicsEnvSet("DELAYGEN","/opt/synApps_5_8/support/delaygen-1-1-1")
epicsEnvSet("DEVIOCSTATS","/opt/synApps_5_8/support/devIocStats-3-1-13")
epicsEnvSet("DXP","/opt/synApps_5_8/support/dxp-3-4")
epicsEnvSet("IP","/opt/synApps_5_8/support/ip-2-17")
epicsEnvSet("IP330","/opt/synApps_5_8/support/ip330-2-8")
epicsEnvSet("IPAC","/opt/synApps_5_8/support/ipac-2-13")
epicsEnvSet("IPUNIDIG","/opt/synApps_5_8/support/ipUnidig-2-10")
epicsEnvSet("LOVE","/opt/synApps_5_8/support/love-3-2-5")
epicsEnvSet("MCA","/opt/synApps_5_8/support/mca-7-6")
epicsEnvSet("MEASCOMP","/opt/synApps_5_8/support/measComp-1-1")
epicsEnvSet("MODBUS","/opt/synApps_5_8/support/modbus-2-7")
epicsEnvSet("MOTOR","/opt/synApps_5_8/support/motor-6-9")
epicsEnvSet("OPTICS","/opt/synApps_5_8/support/optics-2-9-3")
epicsEnvSet("QUADEM","/opt/synApps_5_8/support/quadEM-5-0")
epicsEnvSet("SNCSEQ","/opt/synApps_5_8/support/seq-2-2-3")
epicsEnvSet("SOFTGLUE","/opt/synApps_5_8/support/softGlue-2-4-3")
epicsEnvSet("SSCAN","/opt/synApps_5_8/support/sscan-2-10-1")
epicsEnvSet("STD","/opt/synApps_5_8/support/std-3-4")
epicsEnvSet("STREAM","/opt/synApps_5_8/support/stream-2-6a")
epicsEnvSet("VAC","/opt/synApps_5_8/support/vac-1-5-1")
epicsEnvSet("VME","/opt/synApps_5_8/support/vme-2-8-2")
epicsEnvSet("XXX","/opt/synApps_5_8/support/xxx-5-8-3")
epicsEnvSet(("STREAM_PROTOCOL_PATH","/opt/synApps_5_8/support/xxx-5-8-3")
# save_restore.cmd needs the full path to the startup directory, which
# envPaths currently does not provide
epicsEnvSet(STARTUP,/opt/synApps_5_8/support/xxx-5-8-3/iocBoot/iocLinux)
# Increase size of buffer for error logging from default 1256
errlogInit(20000)
# Specify largest array CA will transport
# Note for N doubles, need N*8 bytes+some overhead
epicsEnvSet EPICS_CA_MAX_ARRAY_BYTES 64010
################################################################################
# Tell EPICS all about the record types, device-support modules, drivers,
# etc. in the software we just loaded (xxx.munch)
dbLoadDatabase("../../dbd/iocxxxLinux.dbd")
iocxxxLinux_registerRecordDeviceDriver(pdbbase)
### save_restore setup
#< save_restore.cmd
# Access Security
dbLoadRecords("/opt/synApps_5_8/support/xxx-5-8-3/xxxApp/Db/Security_Control.db","P=xxx:")
asSetFilename("/opt/synApps_5_8/support/xxx-5-8-3/iocBoot/accessSecurity.acf")
asSetSubstitutions("P=xxx:")
# trap listener
#dbLoadRecords("$(CAPUTRECORDER)/caputRecorderApp/Db/caputPoster.db","P=xxx:,N=300")
#doAfterIocInit("registerCaputRecorderTrapListener('xxx:caputRecorderCommand')")
# GUI database
#dbLoadRecords("$(CAPUTRECORDER)/caputRecorderApp/Db/caputRecorder.db","P=xxx:,N=300")
# soft scaler for testing
#< softScaler.cmd
# user-assignable ramp/tweak
###dbLoadRecords("$(STD)/stdApp/Db/ramp_tweak.db","P=xxx:,Q=rt1")
drvAsynIPPortConfigure("CT08E", "192.168.1.123:7777", 0, 0, 0)
asynOctetSetInputEos("CT08E",0,"\r\n")
asynOctetSetOutputEos("CT08E",0,"\r\n")
asynSetTraceIOMask("CTStarting iocInit
iocRun: All initialization complete
08E",0,0x2)
asynSetTraceMask("CT08E",0,255)
asynOctetConnect("CT08E","CT08E")
#asynOctetWriteRead("CT08E","INIT")
#asynSetTraceIOMask("CT08E",-1,0x9)
initScalerCT08E("serialCT08E","CT08E",0,100) ####
### Stuff for user programming ###
###< calc.cmd
# 4-step measurement
#dbLoadRecords("$(STD)/stdApp/Db/4step.db", "P=xxx:,Q=4step:")
# Miscellaneous PV's, such as burtResult
dbLoadRecords("/opt/synApps_5_8/support/std-3-4/stdApp/Db/misc.db","P=xxx:")
dbLoadRecords("/opt/synApps_5_8/support/std-3-4/stdApp/Db/scaler.db","P=xxx:,S=scaler1,OUT=@asyn(serialCT08E 0 0),DTYP=Asyn Scaler,FREQ=10,TP=1,TP1=0.5,PR1=1,CONT=1")
###############################################################################
iocInit
############################################################################
## EPICS R3.15.2 $Date: Thu 2015-05-14 14:09:28 +0200$
## EPICS Base built Oct 16 2016
############################################################################
###############################################################################
# Report states of database CA links
dbcar(*,1)
CA links in all records
Total 0 CA links; 0 connected, 0 not connected.
0 can't read, 0 can't write. (0 disconnects, 0 writes prohibited)
I used scaler.opi.
After I pressed the "Count" button, the output of IOC:
*************************************************************************
epics> 2017/09/21 17:40:18.298 CT08E asynManager::queueLockPort locking port
2017/09/21 17:40:18.298 CT08E asynManager::queueLockPort created queueLockPortPvt=0x7f6a2c047880