From b49b55e958d349259c28eeab215592554ac22ca8 Mon Sep 17 00:00:00 2001 From: Jonathan Hanks <jonathan.hanks@ligo.org> Date: Wed, 2 Oct 2019 14:50:12 -0700 Subject: [PATCH] Updating standalone edc to detect its dcuid and handle more data types We can easily handle floats, int16, int32, so do so. --- src/epics/seq/standalone_edcu.cc | 267 ++++++++++++++++++++++++------- 1 file changed, 210 insertions(+), 57 deletions(-) diff --git a/src/epics/seq/standalone_edcu.cc b/src/epics/seq/standalone_edcu.cc index 9853b64ef..d16a57d52 100644 --- a/src/epics/seq/standalone_edcu.cc +++ b/src/epics/seq/standalone_edcu.cc @@ -18,6 +18,7 @@ of this distribution. #include <stdlib.h> #include <string.h> #include <stdio.h> +#include <stdint.h> #include <stdarg.h> #include <unistd.h> #include <time.h> @@ -27,6 +28,22 @@ of this distribution. #include <daqmap.h> +/* taken from channel.h in the daqd source + * find a way to do this better + */ +/* numbering must be contiguous */ +typedef enum +{ + _undefined = 0, + _16bit_integer = 1, + _32bit_integer = 2, + _64bit_integer = 3, + _32bit_float = 4, + _64bit_double = 5, + _32bit_complex = 6, + _32bit_uint = 7 +} daq_data_t; + extern "C" { #include "findSharedMemory.h" #include "crc.h" @@ -45,18 +62,29 @@ extern "C" { // **************************************************************************************** int checkFileCrc( const char* ); +typedef union edc_data_t +{ + int16_t data_int16; + int32_t data_int32; + float data_float32; + double data_float64; +} edc_data_t; + unsigned long daqFileCrc; typedef struct daqd_c { - int num_chans; - int con_chans; - int val_events; - int con_events; - float channel_value[ EDCU_MAX_CHANS ]; - char channel_name[ EDCU_MAX_CHANS ][ 64 ]; - int channel_status[ EDCU_MAX_CHANS ]; - long gpsTime; - long epicsSync; + int num_chans; + int con_chans; + int val_events; + int con_events; + daq_data_t channel_type[ EDCU_MAX_CHANS ]; + edc_data_t channel_value[ EDCU_MAX_CHANS ]; + char channel_name[ EDCU_MAX_CHANS ][ 64 ]; + int channel_status[ EDCU_MAX_CHANS ]; + long gpsTime; + long epicsSync; + char* prefix; + int dcuid; } daqd_c; int num_chans_index = -1; @@ -261,15 +289,96 @@ subscriptionHandler( struct event_handler_args args ) { return; } - if ( args.type == DBR_FLOAT ) + switch ( args.type ) + { + case DBR_SHORT: + { + int16_t val = *( (int16_t*)args.dbr ); + ( (edc_data_t*)( args.usr ) )->data_int16 = val; + } + break; + case DBR_LONG: + { + int32_t val = *( (int32_t*)args.dbr ); + ( (edc_data_t*)( args.usr ) )->data_int32 = val; + } + break; + case DBR_FLOAT: { float val = *( (float*)args.dbr ); - *( (float*)( args.usr ) ) = val; + ( (edc_data_t*)( args.usr ) )->data_float32 = val; } - else + break; + case DBR_DOUBLE: { + double val = *( (double*)args.dbr ); + ( (edc_data_t*)( args.usr ) )->data_float64 = val; + } + break; + default: printf( "Arg type unknown\n" ); + break; + } +} + +bool +valid_data_type( daq_data_t datatype ) +{ + switch ( datatype ) + { + case _undefined: + case _32bit_complex: + case _32bit_uint: + case _64bit_integer: + default: + return false; + case _16bit_integer: + case _32bit_integer: + case _32bit_float: + case _64bit_double: + return true; } + return true; +} + +int +daq_data_t_to_epics( daq_data_t datatype ) +{ + switch ( datatype ) + { + case _16bit_integer: + return DBR_SHORT; + case _32bit_integer: + return DBR_LONG; + case _32bit_float: + return DBR_FLOAT; + case _64bit_double: + return DBR_DOUBLE; + default: + throw std::runtime_error( "Unexpected data type given" ); + } +} + +bool +channel_is_edcu_special_chan( daqd_c* edc, const char* channel_name ) +{ + const char* dummy_prefix = ""; + const char* prefix = ( edc->prefix ? prefix : dummy_prefix ); + size_t pref_len = strlen( prefix ); + size_t name_len = strlen( channel_name ); + + if ( name_len <= pref_len ) + { + return false; + } + if ( strncmp( prefix, channel_name, pref_len ) != 0 ) + { + return false; + } + const char* remainder = channel_name + pref_len; + return ( strcmp( remainder, "EDCU_CHAN_CONN" ) == 0 || + strcmp( remainder, "EDCU_CHAN_CNT" ) == 0 || + strcmp( remainder, "EDCU_CHAN_NOCON" ) == 0 ); } int @@ -299,9 +408,27 @@ channel_parse_callback( char* channel_name, std::cerr << "EDC channels may only be 16Hz\n"; exit( 1 ); } - if ( params->datatype != 4 ) + if ( params->dcuid != edc->dcuid && edc->dcuid >= 0 ) { - std::cerr << "EDC channels may only be floats\n"; + std::cerr << "The edc can only have a single dcuid in its file\n"; + exit( 1 ); + } + if ( edc->dcuid < 0 ) + { + edc->dcuid = params->dcuid; + } + daq_data_t daq_data_type = static_cast< daq_data_t >( params->datatype ); + if ( !valid_data_type( daq_data_type ) ) + { + std::cerr << "Invalid data type given for " << channel_name << "\n"; + exit( 1 ); + } + if ( channel_is_edcu_special_chan( edc, channel_name ) && + daq_data_type != _32bit_integer ) + { + std::cerr << "The edcu special variables (EDCU_CHAN_CONN/CNT/NOCON) " + "must be 32 bit ints (" + << static_cast< int >( _32bit_integer ) << ")\n"; exit( 1 ); } strncpy( edc->channel_name[ edc->num_chans ], @@ -335,12 +462,18 @@ edcuCreateChanList( const char* pref, } daqd_edcu1.num_chans = 0; + daqd_edcu1.dcuid = -1; parseConfigFile( const_cast< char* >( daqfilename ), crc, channel_parse_callback, -1, (char*)0, reinterpret_cast< void* >( &daqd_edcu1 ) ); + if ( daqd_edcu1.num_chans < 1 ) + { + std::cerr << "No channels to record, aborting\n"; + exit( 1 ); + } xferInfo.crcLength = 4 * daqd_edcu1.num_chans; printf( "CRC data length = %d\n", xferInfo.crcLength ); @@ -387,7 +520,7 @@ edcuCreateChanList( const char* pref, daqd_edcu1.channel_name[ i ] ); } status = ca_create_subscription( - DBR_FLOAT, + daq_data_t_to_epics( daqd_edcu1.channel_type[ i ] ), 0, chid1, DBE_VALUE, @@ -414,31 +547,71 @@ edcuWriteData( int daqBlockNum, int daqreset ) // ************************************************************************** { - float* daqData; - int buf_size; - int ii; + char* daqData; + int buf_size; + int ii; if ( num_chans_index != -1 ) { - daqd_edcu1.channel_value[ num_chans_index ] = daqd_edcu1.num_chans; + daqd_edcu1.channel_value[ num_chans_index ].data_int32 = + daqd_edcu1.num_chans; } if ( con_chans_index != -1 ) { - daqd_edcu1.channel_value[ con_chans_index ] = daqd_edcu1.con_chans; + daqd_edcu1.channel_value[ con_chans_index ].data_int32 = + daqd_edcu1.con_chans; } if ( nocon_chans_index != -1 ) { - daqd_edcu1.channel_value[ nocon_chans_index ] = + daqd_edcu1.channel_value[ nocon_chans_index ].data_int32 = daqd_edcu1.num_chans - daqd_edcu1.con_chans; } buf_size = DAQ_DCU_BLOCK_SIZE * DAQ_NUM_SWING_BUFFERS; - daqData = (float*)( shmDataPtr + ( buf_size * daqBlockNum ) ); - memcpy( daqData, - daqd_edcu1.channel_value, - daqd_edcu1.num_chans * sizeof( float ) ); + daqData = (char*)( shmDataPtr + ( buf_size * daqBlockNum ) ); + for ( ii = 0; ii < daqd_edcu1.num_chans; ++ii ) + { + switch ( daqd_edcu1.channel_type[ ii ] ) + { + case _16bit_integer: + { + *reinterpret_cast< int16_t* >( daqData ) = + daqd_edcu1.channel_value[ ii ].data_int16; + daqData += sizeof( int16_t ); + break; + } + case _32bit_integer: + { + *reinterpret_cast< int32_t* >( daqData ) = + daqd_edcu1.channel_value[ ii ].data_int32; + daqData += sizeof( int32_t ); + break; + } + case _32bit_float: + { + *reinterpret_cast< float* >( daqData ) = + daqd_edcu1.channel_value[ ii ].data_float32; + daqData += sizeof( float ); + break; + } + case _64bit_double: + { + *reinterpret_cast< double* >( daqData ) = + daqd_edcu1.channel_value[ ii ].data_float64; + daqData += sizeof( double ); + break; + } + default: + std::cerr << "Unknown data type found, the edc does not know how " + "to layout the data, aborting\n"; + exit( 1 ); + } + } + // memcpy( daqData, + // daqd_edcu1.channel_value, + // daqd_edcu1.num_chans * sizeof( float ) ); dipc->dcuId = dcuId; dipc->crc = daqFileCrc; dipc->dataBlockSize = xferInfo.crcLength; @@ -546,47 +719,23 @@ main( int argc, char* argv[] ) { // Addresses for SDF EPICS records. // Initialize request for file load on startup. - long status; - int request; - int daqTrigger; - long ropts = 0; - long nvals = 1; - int rdstatus = 0; - char timestring[ 128 ]; - int ii; - int fivesectimer = 0; - long coeffFileCrc; - char modfilemsg[] = "Modified File Detected "; - struct stat st = { 0 }; - char filemsg[ 128 ]; - char logmsg[ 256 ]; - int pageNum = 0; - int pageNumDisp = 0; - int daqreset = 0; - char errMsg[ 64 ]; - int send_daq_reset = 0; + int send_daq_reset = 0; const char* daqsharedmemname = "edc_daq"; // const char* syncsharedmemname = "-"; const char* daqFile = "edc.ini"; const char* prefix = ""; - int mydcuid = 52; - char logfilename[ 256 ] = ""; - char edculogfilename[ 256 ] = ""; int delay_multiplier = 0; int cur_arg = 0; - while ( ( cur_arg = getopt( argc, argv, "b:d:i:w:p:h" ) ) != EOF ) + while ( ( cur_arg = getopt( argc, argv, "b:i:w:p:h" ) ) != EOF ) { switch ( cur_arg ) { case 'b': daqsharedmemname = optarg; break; - case 'd': - mydcuid = atoi( optarg ); - break; case 'i': daqFile = optarg; break; @@ -604,19 +753,21 @@ main( int argc, char* argv[] ) } } - printf( "My dcuid is %d\n", mydcuid ); - sleep( 2 ); + memset( (void*)&daqd_edcu1, 0, sizeof( daqd_edcu1 ) ); + // ********************************************** // // EDCU STUFF // ******************************************************************************************************** - for ( ii = 0; ii < EDCU_MAX_CHANS; ii++ ) + for ( int ii = 0; ii < EDCU_MAX_CHANS; ii++ ) + { daqd_edcu1.channel_status[ ii ] = 0xbad; + } edcuInitialize( daqsharedmemname, "-" ); - // edcuCreateChanFile(daqDir,daqFile,pref); edcuCreateChanList( prefix, daqFile, &daqFileCrc ); + std::cout << "The edc dcuid = " << daqd_edcu1.dcuid << "\n"; int datarate = daqd_edcu1.num_chans * 64 / 1000; // Start SPECT @@ -664,8 +815,10 @@ main( int argc, char* argv[] ) daqd_edcu1.gpsTime = now.sec; daqd_edcu1.epicsSync = cycle; - edcuWriteData( - daqd_edcu1.epicsSync, daqd_edcu1.gpsTime, mydcuid, send_daq_reset ); + edcuWriteData( daqd_edcu1.epicsSync, + daqd_edcu1.gpsTime, + daqd_edcu1.dcuid, + send_daq_reset ); cycle = ( cycle + 1 ) % 16; transmit_time = transmit_time + time_step; -- GitLab