EPICS Controls Argonne National Laboratory

Experimental Physics and
Industrial Control System

1994  1995  1996  1997  1998  1999  2000  2001  2002  2003  2004  2005  2006  2007  2008  2009  2010  2011  <20122013  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  <20122013  2014  2015  2016  2017  2018  2019  2020  2021  2022  2023  2024 
<== Date ==> <== Thread ==>

Subject: How to get array of strings from waveform record?
From: Nerses Gevorgyan <[email protected]>
To: [email protected]
Date: Tue, 14 Feb 2012 12:08:34 -0500
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  <20122013  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  <20122013  2014  2015  2016  2017  2018  2019  2020  2021  2022  2023  2024 
ANJ, 18 Nov 2013 Valid HTML 4.01! · Home · News · About · Base · Modules · Extensions · Distributions · Download ·
· Search · EPICS V4 · IRMIS · Talk · Bugs · Documents · Links · Licensing ·