Experimental Physics and Industrial Control System
Dear EPICS Community,
I'm trying to put into waveform record an array of STRINGs.
caget returns:
[nerses@halld-sc src]$ caget halltesthv:boardNames
halltesthv:boardNames 16
\340\032\276\b\034\034\276\b\350\270\254\b\001 \350\270\254\b\001 \b
P\300\302\b\214\301\302\b\350\270\254\b\001 \350\270\254\b\001 \b
0\206\303\bl\207\303\b\350\270\254\b\001 \350\270\254\b\001 \b
\210\256\304\b\304\257\304\b\350\270\254\b\001 \350\270\254\b\001
Instead I should get NULL-es for all elements, but 1 should be A1932 and
6 and 10th elements should be A1535.
In the device support I'm printing the val field and it displayed correctly.
As I understood from waveform code and manual the VAL field is a void
pointer which should be supplied by user.
For a case of array of STRINGs it could have different organizations. Like:
1) elements delimited by NULLes
aaa\0bbbbbb\0cc\0...
2) each element of array has a fixed length chars and the names then
padded with NULL-es like below
aaa\0\0\0\0\0\0\0bbbbbb\0\0\0\0cc\0\0\0\0\0\0\0\0
Neither, way worked for me.
Is the problem comes from type of record which is INST_IO and it should
be "Soft Channel" one?
How to correctly put STRING array, so caget and other client tools would
be able correctly read and display them?
If somebody could share the working example that would be sufficient.
With thanks in advance,
Nerses
P.S. Below, You'll find the parts of my configuration.
This is my dbd defining among other things the waveform record.
[nerses@halld-sc src]$ cat HVCAENx527Include.dbd
include "base.dbd"
registrar(CAENx527ConfigureCreateRegister)
registrar(CAENx527DbLoadRecordsRegister)
device( ai, INST_IO, devCAENx527chAi, "CAEN x527 generic
HV Channel" )
device( ao, INST_IO, devCAENx527chAo, "CAEN x527 generic
HV Channel" )
device( bi, INST_IO, devCAENx527chBi, "CAEN x527 generic
HV Channel" )
device( bo, INST_IO, devCAENx527chBo, "CAEN x527 generic
HV Channel" )
device( longin, INST_IO, devCAENx527chLongin, "CAEN x527 generic
HV Channel" )
device( longout, INST_IO, devCAENx527chLongout, "CAEN x527 generic
HV Channel" )
device( mbbi, INST_IO, devCAENx527chMBBi, "CAEN x527 generic
HV Channel" )
device( mbbo, INST_IO, devCAENx527chMBBo, "CAEN x527 generic
HV Channel" )
device( stringin, INST_IO, devCAENx527chStringin, "CAEN x527 generic
HV Channel" )
device( stringout, INST_IO, devCAENx527chStringout, "CAEN x527 generic
HV Channel" )
device( waveform, INST_IO, devCAENx527Waveform, "CAEN x527 generic
HV Mainframe" )
driver( drvCAENx527 )
My record is configured like this:
record( waveform, "$(PSNAME):boardNames")
{
field(DESC, "Board type names")
field(DTYP, "CAEN x527 generic HV Mainframe")
field(SCAN, "Passive")
field(PINI, "YES")
field(FTVL, "STRING")
field(INP, "@$(PSNAME) boardNames")
}
And the device support routine is shown below.
[nerses@halld-sc src]$ cat HVCAENx527Waveform.c
/*
* Copyright (c) 2012 Nerses Gevorgyan <[email protected]> 2012
*
* Permission is hereby granted, free of charge, to any person
* obtaining a copy of this software and associated documentation
* files (the "Software"), to deal in the Software without
* restriction, including without limitation the rights to use,
* copy, modify, merge, publish, distribute, sublicense, and/or sell
* copies of the Software, and to permit persons to whom the
* Software is furnished to do so, subject to the following
* conditions:
*
* The above copyright notice and this permission notice shall be
* included in all copies or substantial portions of the Software.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES
* OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
* NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT
* HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY,
* WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
* FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
* OTHER DEALINGS IN THE SOFTWARE.
*
* HVCAENx527chWaveform.c:
* Waveform record and output record device support routines.
*/
#include "HVCAENx527.h"
#include <waveformRecord.h>
/*
* devCAENx527Waveform
*/
char *names;
static long
init_record_waveform( waveformRecord *pior)
{
int i;
char mf[64];
char arg[64];
struct instio *pinstio;
if( pior->inp.type != INST_IO)
{
printf( "%s: waveform INP field type should be INST_IO\n",
pior->name);
return( S_db_badField);
}
/* parse device dependent option string and set data pointer */
pinstio = &(pior->inp.value.instio);
sscanf(pinstio->string, "%s %s", mf, arg);
if( mf[0] == '\0' || arg[0] == '\0' )
{
printf( "%s: Invalid device parameters: \"%s\"\n", pior->name,
pinstio->string);
return(-1);
}
for(i=0; i < MAX_CRATES; i++)
printf("i = %d name = %s pinstio->string = %s mf = %s arg =
%s\n",i, Crate[i].name, pinstio->string, mf, arg);
i = 0;
while( i < MAX_CRATES && strcmp(Crate[i].name, mf) != 0) i++;
if (i>=MAX_CRATES) {
printf( "%s: Create not found: \"%s\"\n", pior->name,
pinstio->string);
return(-1);
}
pior->dpvt = (void*) &Crate[i];
names = (char*)malloc(MAX_BOARD_NAME * MAX_SLOTS);
printf("crate = %x dpvt = %x\n", &Crate[i], pior->dpvt);
return(0);
}
static long
read_waveform( waveformRecord *pior)
{
#if SCAN_SERVER == 0
void *pval;
#endif
HVCRATE *cr;
HVSLOT *sl;
int i,j;
int size;
cr = (HVCRATE*) pior->dpvt;
pior->nelm = (cr->nsl<MAX_SLOTS)? cr->nsl:MAX_SLOTS;
/*size = 64; /* sizeof(Crate.name); */
/*names = calloc(pior->nelm, size); /* nelm * 64 bytes each */
j = 0;
for (i=0; i<pior->nelm; i++) {
sl = &cr->hvchmap[i];
PDEBUG(2) printf("%d %s\n", i, sl->slname);
strcpy((names+j), (char*)sl->slname);
j += strlen(sl->slname);
}
pior->val = (void*) names;
pior->nord = pior->nelm;
pior->udf = FALSE;
PDEBUG(2) printf( "DEBUG: get name = %s ...\n", pior->val);
return(0);
}
struct { /* waveform dset */
long number;
DEVSUPFUN dev_report;
DEVSUPFUN init;
DEVSUPFUN init_record; /*returns: (-1,0)=>(failure,success)*/
DEVSUPFUN get_ioint_info;
DEVSUPFUN read_wf; /*returns: (-1,0)=>(failure,success)*/
} devCAENx527Waveform =
{
5,
NULL,
NULL,
init_record_waveform,
NULL,
read_waveform,
};
#include <epicsExport.h>
epicsExportAddress(dset,devCAENx527Waveform);
/*
* $Log: HVCAENx527/HVCAENx527App/src/HVCAENx527chStringio.c $
* Revision 1.8 2007/06/01 13:32:58CST Ru Igarashi (igarasr)
* Member moved from EPICS/HVCAENx527App/src/HVCAENx527chStringio.c in
project e:/MKS_Home/archive/cs/epics_local/drivers/CAENx527HV/project.pj
to HVCAENx527/HVCAENx527App/src/HVCAENx527chStringio.c in project
e:/MKS_Home/archive/cs/epics_local/drivers/CAENx527HV/project.pj.
*/
And the header file contains the structures used throughout program.
[nerses@halld-sc src]$ cat HVCAENx527.h
/* $Header: HVCAENx527/HVCAENx527App/src/HVCAENx527.h 1.13 2007/06/01
13:32:57CST Ru Igarashi (igarasr) Exp Ru Igarashi (igarasr)(2007/06/01
13:32:58CST) $
*/
#include <stdio.h>
#include <string.h>
#include <dbDefs.h>
#include <dbAccess.h>
#include <recSup.h>
#include <devSup.h>
#include <callback.h>
#include <errlog.h>
#include <sys/time.h>
#include <CAENHVWrapper.h>
#define EVNTNO_UPDATE 10
#define EVNTNO_T1 11
#define EVNTNO_T2 12
#define EVNTNO_T3 13
/* Turn on (1) or off (0) scan server mode */
/* This may be needed if the CAEN driver can't handle asynchronous
monitoring of parameters, i.e. a get for one channel is mixed up
with the get for another. */
/* Update: This definitely is needed. */
#define SCAN_SERVER 1
typedef struct ParProp
{
char pname[16];
union
{
float f;
long l;
double d;
} pval;
union
{
float f;
long l;
double d;
} pvalset;
unsigned long Type, Mode;
float Minval, Maxval;
unsigned short Unit; /* engineering unit */
short Exp; /* exponent of numbers, e.g. +3 = kilo */
char Onstate[32], Offstate[32]; /* Labels associated with state */
struct HVChan *hvchan;
/* EPICS-related variables */
char PVname[32];
/* "period" is here for future implementation */
double period; /* desired scan period, -1 == not scanned */
int evntno; /* EPICS event number, -1 == not scanned */
struct dbAddr PVaddr;
CALLBACK pcallback;
} PARPROP;
typedef struct HVChan
{
unsigned short *crate, slot, chan; /* crate, slot, channel number */
char chaddr[16];
char chname[16];
/* The Channel Name is an oddball parameter. The CAEN driver
treats it separately from other channel parameters, so
we're treating its scan parameters specially here, too */
double chname_period;
int chname_evntno;
short npar;
PARPROP *pplist; /* parameters list */
struct HVCrate *hvcrate; /* crate data connector */
/* EPICS-related variables */
short epicsenabled; /* 1 = PV exists, 0 = no PV */
} HVCHAN;
typedef struct HVSlot
{
char slname[64];
short nchan;
HVCHAN **hvchan; /* channel list */
} HVSLOT;
typedef struct CrateScanList
{
char pname[16];
double period; /* default desired scan period, -1 == not scanned */
int evntno; /* default EPICS event number, -1 == not scanned */
/* RU! consider putting the channel number lists here */
struct CrateScanList *next;
} CRATESCANLIST;
typedef struct HVCrate
{
char name[64];
char IPaddr[64];
char username[9];
char password[33];
unsigned short crate; /* crate number */
short nsl; /* max number of slots in crate */
short nchan; /* total number of channels (#slot * #nchperslot) */
HVCHAN *hvchan; /* list of HV channels controlled by this crate */
HVSLOT *hvchmap; /* slot X chan lookup table of *hvchan */
CRATESCANLIST *csl;
short connected;
} HVCRATE;
extern HVCRATE Crate[MAX_CRATES];
extern short DEBUG;
#define PDEBUG(LEVEL) if( DEBUG >= LEVEL)
/*
DEBUG level guideline
0 - none
1 - not repeated initialization and shutdown messages,
messages about the crate and slots that appear only once
during run-time
2 - messages about the crate that appear once per crate scan
3 - messages about channels that appear only once during run-time
4 - messages about channel parameters that appear only once
during run-time
5 - messages about channels that appear once per crate scan
6 - messages about channels parameters that appear once per crate scan
10 - all messages
*/
float ScanChannelsPeriod;
int ConnectCrate( char *name);
void CAENx527ConfigureCreate(char *name, char *addr, char *username,
char* password);
void Shutdown();
void *CAENx527ParseDevArgs( char *saddr);
void *CAENx527GetChParVal( PARPROP *pp);
int CAENx527SetChParVal( PARPROP *pp);
char *CAENx527GetChName( HVCHAN *hvch);
int CAENx527SetChName( HVCHAN *hvch, char *chname);
short CAENx527mbbi2state( PARPROP *pp);
void CAENx527mbbi2bits( PARPROP *pp, char *bits, short nbits);
char *CAENx527GetParUnit( PARPROP *pp, char *fieldval);
/*
* $Log: HVCAENx527/HVCAENx527App/src/HVCAENx527.h $
* Revision 1.13 2007/06/01 13:32:57CST Ru Igarashi (igarasr)
* Member moved from EPICS/HVCAENx527App/src/HVCAENx527.h in project
e:/MKS_Home/archive/cs/epics_local/drivers/CAENx527HV/project.pj to
HVCAENx527/HVCAENx527App/src/HVCAENx527.h in project
e:/MKS_Home/archive/cs/epics_local/drivers/CAENx527HV/project.pj.
*/
- Replies:
- Re: How to get array of strings from waveform record? Andrew Johnson
- Navigate by Date:
- Prev:
GE Fanuc reflective memory under RTEMS Ralph Lange
- Next:
Re: How to get array of strings from waveform record? Andrew Johnson
- 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
- Navigate by Thread:
- Prev:
GE Fanuc reflective memory under RTEMS Ralph Lange
- Next:
Re: How to get array of strings from waveform record? Andrew Johnson
- 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