From: Adrian Weber Date: Thu, 19 Apr 2018 14:42:54 +0000 (+0200) Subject: new Version of devTrbNet X-Git-Url: https://jspc29.x-matter.uni-frankfurt.de/git/?a=commitdiff_plain;h=631db837a011bd08f741584e4a789d3a527bc558;p=epics.git new Version of devTrbNet --- diff --git a/Trbnet/devTrbnet/Documentation_TrbNet_SlowControl.pdf b/Trbnet/devTrbnet/Documentation_TrbNet_SlowControl.pdf new file mode 100644 index 0000000..8714b86 Binary files /dev/null and b/Trbnet/devTrbnet/Documentation_TrbNet_SlowControl.pdf differ diff --git a/Trbnet/devTrbnet/TrbnetApp/Db/trbADC.substitutions b/Trbnet/devTrbnet/TrbnetApp/Db/trbADC.substitutions new file mode 100644 index 0000000..8ae8fed --- /dev/null +++ b/Trbnet/devTrbnet/TrbnetApp/Db/trbADC.substitutions @@ -0,0 +1,36 @@ +file $(TOP)/TrbnetApp/Db/trbADC.template { +#TrbSc:0 | DiRICH:1 | Combiner:2 | PowerVoltage:3 | PowerCurrent: 4 + {TRBADDR=0x8300, REGADDR=ADC_1, TRBADDRWave=0x1218} + {TRBADDR=0x8300, REGADDR=ADC_1, TRBADDRWave=0x1214} + {TRBADDR=0x8300, REGADDR=ADC_1, TRBADDRWave=0x1240} + {TRBADDR=0x8300, REGADDR=ADC_1, TRBADDRWave=0x1223} + {TRBADDR=0x8300, REGADDR=ADC_1, TRBADDRWave=0x1226} + {TRBADDR=0x8300, REGADDR=ADC_1, TRBADDRWave=0x1232} +# {TRBADDR=0x8300, REGADDR=ADC_1, TRBADDRWave=0x} +# {TRBADDR=0x8300, REGADDR=ADC_1, TRBADDRWave=0x} + {TRBADDR=0x8300, REGADDR=ADC_1, TRBADDRWave=0x1237} + {TRBADDR=0x8300, REGADDR=ADC_1, TRBADDRWave=0x1215} + {TRBADDR=0x8300, REGADDR=ADC_1, TRBADDRWave=0x1229} + {TRBADDR=0x8300, REGADDR=ADC_1, TRBADDRWave=0x1241} + + {TRBADDR=0x8300, REGADDR=ADC_1, TRBADDRWave=0x1225} + {TRBADDR=0x8300, REGADDR=ADC_1, TRBADDRWave=0x1234} + {TRBADDR=0x8300, REGADDR=ADC_1, TRBADDRWave=0x1235} + {TRBADDR=0x8300, REGADDR=ADC_1, TRBADDRWave=0x1231} + {TRBADDR=0x8300, REGADDR=ADC_1, TRBADDRWave=0x1213} + {TRBADDR=0x8300, REGADDR=ADC_1, TRBADDRWave=0x1239} + {TRBADDR=0x8300, REGADDR=ADC_1, TRBADDRWave=0x1227} + {TRBADDR=0x8300, REGADDR=ADC_1, TRBADDRWave=0x1217} + {TRBADDR=0x8300, REGADDR=ADC_1, TRBADDRWave=0x1236} + {TRBADDR=0x8300, REGADDR=ADC_1, TRBADDRWave=0x1228} + {TRBADDR=0x8300, REGADDR=ADC_1, TRBADDRWave=0x1238} + {TRBADDR=0x8300, REGADDR=ADC_1, TRBADDRWave=0x1233} + + {TRBADDR=0x8300, REGADDR=ADC_2, TRBADDRWave=0x8300} + {TRBADDR=0x8300, REGADDR=ADC_3, TRBADDRWave=0x8300} + {TRBADDR=0x8300, REGADDR=ADC_4, TRBADDRWave=0x8300} + + {TRBADDR=0x8300, REGADDR=ADC_2, TRBADDRWave=0x8301} + {TRBADDR=0x8300, REGADDR=ADC_3, TRBADDRWave=0x8301} + {TRBADDR=0x8300, REGADDR=ADC_4, TRBADDRWave=0x8301} +} diff --git a/Trbnet/devTrbnet/TrbnetApp/Db/trbADC.template b/Trbnet/devTrbnet/TrbnetApp/Db/trbADC.template new file mode 100644 index 0000000..2980084 --- /dev/null +++ b/Trbnet/devTrbnet/TrbnetApp/Db/trbADC.template @@ -0,0 +1,91 @@ +record (waveform,"HADES:RICH:DiRICH:$(TRBADDRWave):$(REGADDR)") +{ + field( DESC, "Waveform of ADCs.") + field( SCAN , "5 second") + field( DTYP, "devTrbnet" ) + field( INP, "@TrbNet $(TRBADDRWave) $(REGADDR)" ) + field( NELM, "10") + field( FTVL, "DOUBLE") + field( FLNK, "HADES:RICH:DiRICH:$(TRBADDRWave):$(REGADDR):Testfan_") +} + +record(dfanout, "HADES:RICH:DiRICH:$(TRBADDRWave):$(REGADDR):Testfan_") +{ + field(OUTA, "HADES:RICH:DiRICH:$(TRBADDRWave):$(REGADDR):SubArray_0.PROC") + field(OUTB, "HADES:RICH:DiRICH:$(TRBADDRWave):$(REGADDR):SubArray_1.PROC") + field(OUTC, "HADES:RICH:DiRICH:$(TRBADDRWave):$(REGADDR):SubArray_2 PP") + field(OUTD, "HADES:RICH:DiRICH:$(TRBADDRWave):$(REGADDR):SubArray_3 PP") + field(OUTE, "HADES:RICH:DiRICH:$(TRBADDRWave):$(REGADDR):SubArray_4 PP") + #field(FLNK, "HADES:RICH:DiRICH:$(TRBADDRWave):RREG:$(REGADDR):SubArray.PROC") +} + +record(subArray, "HADES:RICH:DiRICH:$(TRBADDRWave):$(REGADDR):SubArray_0") +{ + field(DESC, "lower half") + field(DTYP, "Soft Channel") + field(MALM, "10") + field(INDX, "0") +# field(EGU, "mV ") + field(FTVL, "DOUBLE") + field(NELM, "1") + field(INP, "HADES:RICH:DiRICH:$(TRBADDRWave):$(REGADDR).VAL") +} + +record(subArray, "HADES:RICH:DiRICH:$(TRBADDRWave):$(REGADDR):SubArray_1") +{ + field(DESC, "lower half") + field(DTYP, "Soft Channel") + field(MALM, "10") + field(INDX, "1") +# field(EGU, "mV ") + field(FTVL, "DOUBLE") + field(NELM, "1") + field(INP, "HADES:RICH:DiRICH:$(TRBADDRWave):$(REGADDR).VAL") +} + + +record(subArray, "HADES:RICH:DiRICH:$(TRBADDRWave):$(REGADDR):SubArray_2") +{ + field(DESC, "lower half") + field(DTYP, "Soft Channel") + field(MALM, "10") + field(INDX, "2") +# field(EGU, "mV ") + field(FTVL, "DOUBLE") + field(NELM, "1") + field(INP, "HADES:RICH:DiRICH:$(TRBADDRWave):$(REGADDR).VAL") +} + +record(subArray, "HADES:RICH:DiRICH:$(TRBADDRWave):$(REGADDR):SubArray_3") +{ + field(DESC, "lower half") + field(DTYP, "Soft Channel") + field(MALM, "10") + field(INDX, "3") +# field(EGU, "mV ") + field(FTVL, "DOUBLE") + field(NELM, "1") + field(INP, "HADES:RICH:DiRICH:$(TRBADDRWave):$(REGADDR).VAL") +} + +record(subArray, "HADES:RICH:DiRICH:$(TRBADDRWave):$(REGADDR):SubArray_4") +{ + field(DESC, "lower half") + field(DTYP, "Soft Channel") + field(MALM, "10") + field(INDX, "4") +# field(EGU, "mV ") + field(FTVL, "DOUBLE") + field(NELM, "1") + field(INP, "HADES:RICH:DiRICH:$(TRBADDRWave):$(REGADDR).VAL") +} + +#record(subArray, "HADES:RICH:DiRICH:$(TRBADDRWave):$(REGADDR):SubArray2") +#{ +# field(DESC, "Upper half") +# field(DTYP, "Soft Channel") +# field(INP, "HADES:RICH:DiRICH:$(TRBADDRWave):$(REGADDR)") +# field(FTVL, "DOUBLE") +# field(MALM, "1024") +#} + diff --git a/Trbnet/devTrbnet/TrbnetApp/Db/trbExample.substitutions b/Trbnet/devTrbnet/TrbnetApp/Db/trbExample.substitutions index 8d80e32..216963d 100644 --- a/Trbnet/devTrbnet/TrbnetApp/Db/trbExample.substitutions +++ b/Trbnet/devTrbnet/TrbnetApp/Db/trbExample.substitutions @@ -1,7 +1,3 @@ -file trbExample.template { -{TRBADDR=0x0200, REGADDR=0xc804} -{TRBADDR=0x0201, REGADDR=0xc804} -{TRBADDR=0x0202, REGADDR=0xc804} -{TRBADDR=0x0203, REGADDR=0xc804} +file TrbnetApp/Db/trbExample.template { + {P=HAD:RICH:, TRBADDR=0x2220, REGADDR="3V8", TRBADDRWave=0x2220} } - diff --git a/Trbnet/devTrbnet/TrbnetApp/Db/trbExample.template b/Trbnet/devTrbnet/TrbnetApp/Db/trbExample.template index 16d6e0e..bc57368 100644 --- a/Trbnet/devTrbnet/TrbnetApp/Db/trbExample.template +++ b/Trbnet/devTrbnet/TrbnetApp/Db/trbExample.template @@ -1,10 +1,62 @@ -record( longin, "TRB:$(TRBADDR):READREGISTER:$(REGADDR)" ) { +#record( longin, "Adrian:Test:TRB:$(TRBADDR):READREGISTER:$(REGADDR)" ) { +# field( SCAN , "5 second") +# field( DTYP, "devTrbnet" ) +# field( INP, "@TrbNet $(TRBADDR) $(REGADDR)" ) +# field( FTVL, "FLOAT") +# #field( FLNK, "TRB:$(TRBADDR):Get_Temperature") +#} + +#record( calc, "TRB:$(TRBADDR):Get_Temperature" ) { +# field( DESC , "Get Bits 31 to 20" ) +# field( INPA , "TRB:$(TRBADDR):READREGISTER:0x00" ) +# field(CALC, "floor(A/1048576)") #roundoff e.g. 5/2=2 ; 2^20 is 1048576 +#} + + +#record (waveform,"$(P)DiRICH:$(TRBADDRWave):READREGISTER:$(REGADDR)") +record (waveform,"$(P)DiRICH:$(TRBADDRWave):RREG:$(REGADDR)") +{ + field( DESC, "Waveform of DiRich Temperatures.") + field( SCAN , "5 second") field( DTYP, "devTrbnet" ) - field( INP, "@$(TRBADDR) $(REGADDR)" ) + field( INP, "@TrbNet $(TRBADDRWave) $(REGADDR)" ) + field( NELM, "200") + field( FTVL, "DOUBLE") + field( FLNK, "$(P)DiRICH:$(TRBADDRWave):RREG:$(REGADDR):Calc_") } -record( longout, "TRB:$(TRBADDR):WRITEREGISTER:$(REGADDR)" ) { - field( DTYP, "devTrbnet" ) - field( OUT, "@$(TRBADDR) $(REGADDR)" ) +record(calcout, "$(P)DiRICH:$(TRBADDRWave):RREG:$(REGADDR):Calc_") +{ + field(INPA, "$(P)DiRICH:$(TRBADDRWave):RREG:$(REGADDR).NELM") + field(CALC, "A/2") + field(OUT, "$(P)DiRICH:$(TRBADDRWave):RREG:$(REGADDR):Testfan_.VAL PP") + #field(FLNK, "$(P)DiRICH:$(TRBADDRWave):RREG:$(REGADDR):Testfan_.PROC") + +} + +record(dfanout, "$(P)DiRICH:$(TRBADDRWave):RREG:$(REGADDR):Testfan_") +{ + field(OUTA, "$(P)DiRICH:$(TRBADDRWave):RREG:$(REGADDR):SubArray.NELM PP") + field(OUTB, "$(P)DiRICH:$(TRBADDRWave):RREG:$(REGADDR):SubArray2.INDX") + field(OUTC, "$(P)DiRICH:$(TRBADDRWave):RREG:$(REGADDR):SubArray2.NELM PP") + #field(FLNK, "$(P)DiRICH:$(TRBADDRWave):RREG:$(REGADDR):SubArray.PROC") +} + +record(subArray, "$(P)DiRICH:$(TRBADDRWave):RREG:$(REGADDR):SubArray") +{ + field(DESC, "lower half") + field(DTYP, "Soft Channel") + field(MALM, "1024") + field(INDX, "0") + field(FTVL, "DOUBLE") + field(INP, "$(P)DiRICH:$(TRBADDRWave):RREG:$(REGADDR).VAL") +} + +record(subArray, "$(P)DiRICH:$(TRBADDRWave):RREG:$(REGADDR):SubArray2") +{ + field(DESC, "Upper half") + field(DTYP, "Soft Channel") + field(INP, "$(P)DiRICH:$(TRBADDRWave):RREG:$(REGADDR)") + field(FTVL, "DOUBLE") + field(MALM, "1024") } - \ No newline at end of file diff --git a/Trbnet/devTrbnet/TrbnetApp/src/devTrbnet.c b/Trbnet/devTrbnet/TrbnetApp/src/devTrbnet.c index a287d8b..9609ddd 100644 --- a/Trbnet/devTrbnet/TrbnetApp/src/devTrbnet.c +++ b/Trbnet/devTrbnet/TrbnetApp/src/devTrbnet.c @@ -1,302 +1,885 @@ -/******************************************************************************* - * Copyright (C) 2013 Florian Feldbauer - * - Helmholtz-Institut Mainz - * - * This file is part of devTrbnet - * - * devTrbnet is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; either version 3 of the License, or - * (at your option) any later version. - * - * devTrbnet is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. - * - ******************************************************************************/ - -/****** I N C L U D E S *******************************************************/ - -/* ANSI C includes */ -#include -#include -#include - -/* EPICS includes */ -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include - -/* local includes */ -#include "trberror.h" -#include "trbnet.h" - -/****** D E F I N I T I O N S **************************************************/ -static long initLi( longinRecord* prec ); -static long initLo( longoutRecord* prec ); -static long initWaveform( waveformRecord* prec ); -static long processLi( longinRecord* prec ); -static long processLo( longoutRecord* prec ); -static long processWaveform( waveformRecord* prec ); - -typedef struct { - long number; - DEVSUPFUN dev_report; - DEVSUPFUN init; - DEVSUPFUN init_record; - DEVSUPFUN get_ioint_info; - DEVSUPFUN process; -} dev_dset_trbnet_t; - -typedef struct { - epicsUInt16 trb_addr; - epicsUInt16 reg_addr; -} trbnet_info_t; - -/****** G L O B A L S **********************************************************/ -dev_dset_trbnet_t dev_trbnet_li = { 6, NULL, NULL, initLi, NULL, processLi }; -dev_dset_trbnet_t dev_trbnet_lo = { 6, NULL, NULL, initLo, NULL, processLo }; -dev_dset_trbnet_t dev_trbnet_waveform = { 6, NULL, NULL, initWaveform, NULL, processWaveform }; - -/****** L O C A L S ************************************************************/ -static bool _trb_connected = false; - -/****** F U N C T I O N S ******************************************************/ - -epicsExportAddress( dset, dev_trbnet_li ); -epicsExportAddress( dset, dev_trbnet_lo ); -epicsExportAddress( dset, dev_trbnet_waveform ); - -/*----- Common initialization for all records ---------------------------------*/ -static long initCommon( dbCommon* prec, DBLINK* plink ) { - - trbnet_info_t *pinfo; - epicsUInt32 trb_addr_buf = 0; - epicsUInt32 reg_addr_buf = 0; - - if ( sscanf( plink->value.instio.string, "%x %x", &trb_addr_buf, ®_addr_buf ) != 2 ) { - fprintf( stderr, "\033[31;1m%s: Invalid value of INP/OUT field '%s'\033[0m\n", - prec->name, plink->value.instio.string ); - return -1; - } - if ( 0xffff < trb_addr_buf ) { - fprintf( stderr, "\033[31;1m%s: Invalid trb address '%x'\033[0m\n", - prec->name, trb_addr_buf ); - return -1; - } - if ( 0xffff < reg_addr_buf ) { - fprintf( stderr, "\033[31;1m%s: Invalid register address '%x'\033[0m\n", - prec->name, reg_addr_buf ); - return -1; - } - - pinfo = callocMustSucceed( 1, sizeof(*pinfo), "devTrbnet::initCommon" ); - pinfo->trb_addr = (epicsUInt16)( trb_addr_buf & 0xffff ); - pinfo->reg_addr = (epicsUInt16)( reg_addr_buf & 0xffff ); - - prec->dpvt = pinfo; - prec->udf = FALSE; - - return 0; -} - -/*----- initialization of longin records --------------------------------------*/ -static long initLi( longinRecord* prec ) { - long status = 0; - prec->pact = (epicsUInt8)true; /* disable record */ - - status = initCommon( (dbCommon *)prec, &prec->inp ); - prec->pact = (epicsUInt8)false; /* enable record */ - - return status; -} - -/*----- initialization of longout records -------------------------------------*/ -static long initLo( longoutRecord* prec ) { - long status = 0; - prec->pact = (epicsUInt8)true; /* disable record */ - - status = initCommon( (dbCommon *)prec, &prec->out ); - prec->pact = (epicsUInt8)false; /* enable record */ - - return status; -} - -/*----- initialization of waveform records ------------------------------------*/ -static long initWaveform( waveformRecord* prec ) { - long status = 0; - prec->pact = (epicsUInt8)true; /* disable record */ - - if ( DBF_ULONG != prec->ftvl ) { - fprintf( stderr, "\033[31;1m%s: Invalid field type of value\033[0m\n", prec->name ); - return -1; - } - - status = initCommon( (dbCommon *)prec, &prec->inp ); - prec->pact = (epicsUInt8)false; /* enable record */ - - return status; -} - -/*----- process routine of longin records -------------------------------------*/ -static long processLi( longinRecord* prec ) { - trbnet_info_t* pinfo = (trbnet_info_t*)prec->dpvt; - epicsUInt32 data[2] = { 0 }; - int trb_stat = 0; - - if( !_trb_connected ){ - if( init_ports() == -1 ) { - fprintf( stderr, "\033[31;1m%s: init_ports failed:\n%d %s\033[0m\n", - prec->name, trb_errno, trb_strerror() ); - recGblSetSevr( prec, COMM_ALARM, INVALID_ALARM ); - return -1; - } - _trb_connected = true; - } - - trb_stat = trb_register_read( pinfo->trb_addr, pinfo->reg_addr, data, 2 ); - if ( -1 == trb_stat ) { - /* first try failed, do it again */ - if( init_ports() == -1 ) { - fprintf( stderr, "\033[31;1m%s: init_ports failed:\n%d %s\033[0m\n", - prec->name, trb_errno, trb_strerror() ); - recGblSetSevr( prec, COMM_ALARM, INVALID_ALARM ); - return -1; - } - trb_stat = trb_register_read( pinfo->trb_addr, pinfo->reg_addr, data, 2 ); - if ( -1 == trb_stat ) { - /* second try failed, return error */ - fprintf( stderr, "\033[31;1m%s: read_register failed: %d %s\033[0m\n", - prec->name, trb_errno, trb_strerror() ); - recGblSetSevr( prec, READ_ALARM, INVALID_ALARM ); - _trb_connected = false; - return -1; - } - } - /* Check Status-Bits */ - if ( TRB_STATUS_WARNING == trb_errno ) { - fprintf( stderr, "%s: Warning: Status-Bit(s) have been set:\n%s\n", - prec->name, trb_termstr( trb_term ) ); - return -1; - } - - prec->val = data[1]; - return 0; -} - -/*----- process routine of longout records ------------------------------------*/ -static long processLo( longoutRecord* prec ) { - trbnet_info_t* pinfo = (trbnet_info_t*)prec->dpvt; - epicsUInt32 value = prec->val; - int trb_stat = 0; - - if( !_trb_connected ) { - if( init_ports() == -1 ) { - fprintf( stderr, "\033[31;1m%s: init_ports failed:\n%d %s\033[0m\n", - prec->name, trb_errno, trb_strerror() ); - recGblSetSevr( prec, COMM_ALARM, INVALID_ALARM ); - return -1; - } - _trb_connected = true; - } - - trb_stat = trb_register_write( pinfo->trb_addr, pinfo->reg_addr, value ); - if ( -1 == trb_stat ) { - /* first try failed, do it again */ - if( init_ports() == -1 ) { - fprintf( stderr, "\033[31;1m%s: init_ports failed:\n%d %s\033[0m\n", - prec->name, trb_errno, trb_strerror() ); - recGblSetSevr( prec, COMM_ALARM, INVALID_ALARM ); - return -1; - } - trb_stat = trb_register_write( pinfo->trb_addr, pinfo->reg_addr, value ); - if ( -1 == trb_stat ) { - /* second try failed, return error */ - fprintf( stderr, "\033[31;1m%s: write_register failed: %d %s\033[0m\n", - prec->name, trb_errno, trb_strerror() ); - recGblSetSevr( prec, WRITE_ALARM, INVALID_ALARM ); - _trb_connected = false; - return -1; - } - } - if ( TRB_STATUS_WARNING == trb_errno ) { - fprintf( stderr, "%s: Warning: Status-Bit(s) have been set:\n%s\n", - prec->name, trb_termstr( trb_term ) ); - return -1; - } - - return 0; -} - -/*----- process routine of waveform records -----------------------------------*/ -static long processWaveform( waveformRecord* prec ) { - trbnet_info_t *pinfo = (trbnet_info_t*)prec->dpvt; - epicsUInt32 *pvalue = (epicsUInt32*)prec->bptr; - epicsUInt32 *pdata_buf; - epicsUInt32 count = prec->nelm; - int trb_stat = 0; - int i = 0; - - if( !_trb_connected ) { - if( init_ports() == -1 ) { - fprintf( stderr, "\033[31;1m%s: init_ports failed:\n%d %s\033[0m\n", - prec->name, trb_errno, trb_strerror() ); - recGblSetSevr( prec, COMM_ALARM, INVALID_ALARM ); - return -1; - } - _trb_connected = true; - } - - pdata_buf = callocMustSucceed( count, sizeof(epicsUInt32), "devTrbnet::processWaveform" ); - - trb_stat = trb_register_read( pinfo->trb_addr, pinfo->reg_addr, pdata_buf, count ); - if ( -1 == trb_stat ) { - /* first try failed, do it again */ - if( init_ports() == -1 ) { - fprintf( stderr, "\033[31;1m%s: init_ports failed:\n%d %s\033[0m\n", - prec->name, trb_errno, trb_strerror() ); - recGblSetSevr( prec, COMM_ALARM, INVALID_ALARM ); - return -1; - } - trb_stat = trb_register_read( pinfo->trb_addr, pinfo->reg_addr, pdata_buf, count ); - if ( -1 == trb_stat ) { - fprintf( stderr, "\033[31;1m%s: read_register failed: %d %s\033[0m\n", - prec->name, trb_errno, trb_strerror() ); - free( pdata_buf ); - recGblSetSevr( prec, READ_ALARM, INVALID_ALARM ); - _trb_connected = false; - return -1; - } - } - if ( TRB_STATUS_WARNING == trb_errno ) { - fprintf( stderr, "%s: Warning: Status-Bit(s) have been set:\n%s\n", - prec->name, trb_termstr( trb_term ) ); - return -1; - } - - if ( trb_stat > prec->nelm ) trb_stat = prec->nelm; - for( ; i < trb_stat; i++ ) pvalue[i] = pdata_buf[i]; - - prec->nord = trb_stat; - - free( pdata_buf ); - return 0; -} - +/****** I N C L U D E S *******************************************************/ + +/* ANSI C includes */ +#include +#include +#include +#include +#include + +/* EPICS includes */ +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +/* local includes */ +#include "trberror.h" +#include "trbnet.h" + + +#define LINELENGTH 250 + +#define NumberOfBoards 1 + +#define __Name 0 +#define __Scale 1 +#define __Unit 2 +#define __Format 3 +#define __Start 4 +#define __Bits 5 +#define __Rate 6 +#define __ErrorFlag 7 +#define __InvertFlag 8 +#define __Value 9 + +/****** D E F I N I T I O N S **************************************************/ +static long initLi( longinRecord* prec ); +static long initLo( longoutRecord* prec ); +static long initWaveform( waveformRecord* prec ); +static long processLi( longinRecord* prec ); +static long processLo( longoutRecord* prec ); +static long processWaveform( waveformRecord* prec ); + +typedef struct { + long number; + DEVSUPFUN dev_report; + DEVSUPFUN init; + DEVSUPFUN init_record; + DEVSUPFUN get_ioint_info; + DEVSUPFUN process; +} dev_dset_trbnet_t; + +typedef struct { + epicsUInt16 trb_addr; + char* reg_name_buf; + char* reg_name_buf_nbr; + epicsUInt16 reg_addr; + //char entity_name[20]; +} trbnet_info_t; + +typedef struct{ + epicsUInt16 regAddr; + char *name; + float scale; + char *unit; + char *format; + int start; + int bits; + int rate; + char *errorflag; + char *invertflag; + int value; +}field_struct; + +typedef struct{ + epicsUInt16 regAddr; + char *name; + char *purpose; + field_struct *field; + int size; + int used; + int value; +}reg_struct; + +typedef struct{ + epicsUInt16 address; + char *name; + reg_struct *Reg; + size_t size; + size_t used; +}trb_struct; + +/****** G L O B A L S **********************************************************/ +dev_dset_trbnet_t dev_trbnet_li = { 6, NULL, NULL, initLi, NULL, processLi }; +dev_dset_trbnet_t dev_trbnet_lo = { 6, NULL, NULL, initLo, NULL, processLo }; +dev_dset_trbnet_t dev_trbnet_waveform = { 6, NULL, NULL, initWaveform, NULL, processWaveform }; +trb_struct *trb; +int databaseSet = 0; + +/****** L O C A L S ************************************************************/ +static bool _trb_connected = false; + +/****** F U N C T I O N S ******************************************************/ + +epicsExportAddress( dset, dev_trbnet_li ); +epicsExportAddress( dset, dev_trbnet_lo ); +epicsExportAddress( dset, dev_trbnet_waveform ); + +/*----- TEST FUNKTION ---------------------------------------------------------*/ +int trb_register_readTESTFUNKTION( uint16_t trb_addr, + uint16_t addr, + uint32_t *data, + unsigned int dsize) +{ + int status = 0; + if (trb_addr== 0) { + if (addr== 0) { + data[0] = 0; + //data[1]=21400000; + data[1] = 557842432; + } + return 2; + } + else if(trb_addr == 1) { + data[0] = 0; + data[1] = 557842432; + data[2] = 1; + data[3] = 557845532; + data[4] = 2; + data[5] = 557823451; + data[6] = 3; + data[7] = 557733332; + data[8] = 4; + data[9] = 667823451; + data[10] = 5; + data[11] = 598733332; + return 12; + } else { + return -1; + } +} + +int PadiwaSendCmd(uint32_t cmd, uint32_t board, uint32_t chain) { + + uint32_t c[] = { cmd,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,1<Reg[RegNumb].field = (field_struct *)malloc(sizeof(field_struct)); // 1 field + trb->Reg[RegNumb].used = 0; + trb->Reg[RegNumb].size = 1; + //Init with start values + trb->Reg[RegNumb].field[trb->Reg[RegNumb].used].regAddr = trb->Reg[RegNumb].regAddr; + trb->Reg[RegNumb].field[trb->Reg[RegNumb].used].name = NULL; + trb->Reg[RegNumb].field[trb->Reg[RegNumb].used].scale = 1; + trb->Reg[RegNumb].field[trb->Reg[RegNumb].used].unit = NULL; + trb->Reg[RegNumb].field[trb->Reg[RegNumb].used].format = NULL; + trb->Reg[RegNumb].field[trb->Reg[RegNumb].used].start = 0; + trb->Reg[RegNumb].field[trb->Reg[RegNumb].used].bits = 32; + trb->Reg[RegNumb].field[trb->Reg[RegNumb].used].rate = -1; + trb->Reg[RegNumb].field[trb->Reg[RegNumb].used].errorflag = NULL; + trb->Reg[RegNumb].field[trb->Reg[RegNumb].used].invertflag = NULL; + trb->Reg[RegNumb].field[trb->Reg[RegNumb].used].value = -1; +} + +void initReg(trb_struct *trb, size_t initialSize) { + trb->Reg = (reg_struct *)malloc(initialSize * sizeof(reg_struct)); + trb->used = 0; + trb->size = initialSize; + int i=0; + for ( i; i < initialSize; i++) { + initField(trb, i); // trb_struct; i01= Element of Register + } +} + +// Insert a new field. Only RegAddress is Set from default +void insertField(reg_struct *reg) { + if (reg->used == reg->size) { + reg->size++; + reg->field = (field_struct *)realloc(reg->field, reg->size * sizeof(field_struct)); + } + //Init with start values + reg->field[reg->used].regAddr = reg->regAddr; //set register Address + reg->field[reg->used].name = NULL; + reg->field[reg->used].scale = 1; + reg->field[reg->used].unit = NULL; + reg->field[reg->used].format = NULL; + reg->field[reg->used].start = 0; + reg->field[reg->used].bits = 32; + reg->field[reg->used].rate = -1; + reg->field[reg->used].errorflag = NULL; + reg->field[reg->used].invertflag = NULL; + reg->field[reg->used].value = -1; + reg->used++; +} + +int setFieldPropertyInt(reg_struct *reg,int fieldNmb, int element, int data) { + if (fieldNmb < reg->used) { + if (element == __Start){ //field start + reg->field[fieldNmb].start = data; + } else if (element == __Bits){ //field bits + reg->field[fieldNmb].bits = data; + } else if (element == __Rate){ //field rate + reg->field[fieldNmb].rate = data; + } else if (element == __Value){ //field ratevalue + reg->field[fieldNmb].value = data; + } else { + printf("Element does not Fit to a INT Type property.\n"); + } + return 0; + } else { + return 1; //Error + } +} + +int setFieldPropertyStr(reg_struct *reg,int fieldNmb, int element, char *data) { + if (fieldNmb < reg->used) { + if(element == __Name){ //field NAME + reg->field[fieldNmb].name =strdup(data); + } else if (element == __Unit){ //field UNIT + reg->field[fieldNmb].unit = strdup(data); + } else if (element == __Format){ //field format + reg->field[fieldNmb].format = strdup(data); + } else if (element == __ErrorFlag){ //field errorflag + reg->field[fieldNmb].errorflag = strdup(data); + } else if (element == __InvertFlag){//field invertflag + reg->field[fieldNmb].invertflag = strdup(data); + } else { + printf("Element does not Fit to a STRING Type property.\n"); + } + return 0; + } else { + return 1; //Error; Field does not exist + } +} + +int setFieldPropertyFloat(reg_struct *reg, int fieldNmb, int element, float data) { + if (fieldNmb < reg->used) { + if (element == __Scale){ //field SCALE + reg->field[fieldNmb].scale = data; + } else { + printf("Element does not Fit to a FLOAT Type property.\n"); + } + return 0; + } else { + return 1; //Error; Field does not exist + } +} + +void insertReg(trb_struct *trb, int element) { + if (trb->used == trb->size) { + trb->size++; + trb->Reg = (reg_struct *)realloc(trb->Reg, trb->size * sizeof(reg_struct)); + } + trb->Reg[trb->used].regAddr = element; + initField(trb, trb->used); + trb->used++; +} + +// free the allocated memory of the fields of each Register +void freeField(trb_struct *trb) { + int i=0; + for (i;iused;i++){ + free(trb->Reg[i].field); + trb->Reg[i].field = NULL; + trb->Reg[i].used = trb->Reg[i].size = 0; + } +} + +// free the allocated memory of each register +void freeReg(trb_struct *trb) { + freeField(trb); + free(trb->Reg); + trb->Reg = NULL; + trb->used = trb->size = 0; +} + +/*----- Common initialization for all records ---------------------------------*/ + +static long initCommon( dbCommon* prec, DBLINK* plink ) { + + trbnet_info_t *pinfo; + char entity_name_buf[20] = ""; + char Reg_name_buf[20] = ""; + epicsUInt32 trb_addr_buf = 0; + epicsUInt32 reg_addr_buf = 0; + + char linebuffer[LINELENGTH]; + + if ( sscanf( plink->value.instio.string, "%s %x %s", entity_name_buf, &trb_addr_buf, Reg_name_buf ) != 3 ) { + fprintf( stderr, "\033[31;1m%s: Invalid value of INP/OUT field '%s'\033[0m\n", + prec->name, plink->value.instio.string ); + return -1; + } + if ( 0xffff < trb_addr_buf ) { + fprintf( stderr, "\033[31;1m%s: Invalid trb address '%x'\033[0m\n", + prec->name, trb_addr_buf ); + return -1; + } + + pinfo = callocMustSucceed( 1, sizeof(*pinfo), "devTrbnet::initCommon" ); + pinfo->trb_addr = (epicsUInt16)( trb_addr_buf & 0xffff ); +// pinfo->reg_name_buf = strdup(Reg_name_buf); + prec->dpvt = pinfo; + prec->udf = FALSE; + int i=0; + + // check special cases that are not inb XMLS Database + char * pname; +// char reg_name_buf[30]; +// strcpy(reg_name_buf, pinfo->reg_name_buf); + pname = strtok(Reg_name_buf,"_"); + pinfo->reg_name_buf = strdup(pname); + + while (pname != NULL){ +// printf("Ausgabe: %s\n",pname); + pinfo->reg_name_buf_nbr = strdup(pname); + pname = strtok(NULL," "); + + } +//printf("test: %s\n",pinfo->reg_name_buf); +//printf("test2: %s\n",pinfo->reg_name_buf_nbr); +//----------------------------------------------------------------// + + + +// create Memory for each TrbBoard + if (databaseSet==0) + { + trb = (trb_struct *) malloc(NumberOfBoards * sizeof(trb_struct)); + + for(i=0;i") == 0){ + group_open = false; + } + if (strcmp(node,"") == 0){ + register_open = false; + } + if (strcmp(node,"") == 0){ + field_open = false; + } + + // analyse each part of one line of .xml document + while(ptr != NULL) { + + if (group_open==true && register_open==false && field_open==false) { + sscanf(ptr, "address=\"%x\"", &gaddress); + sscanf(ptr, "name=\"%[A-z,_0-9]\"", gname); + sscanf(ptr, "mode=\"%[A-z,_,0-9]\"", gmode); + } + if (register_open==true && group_open==true && field_open==false){ + if(sscanf(ptr, "address=\"%x\"", ®_addr_buf)==1){ + pinfo->reg_addr = (epicsUInt16)( (reg_addr_buf + gaddress) & 0xffff ); + for (i=0; i < NumberOfBoards; i++){ + trb[i].Reg[trb[i].used-1].regAddr = pinfo->reg_addr; + } + } + if(sscanf(ptr, "name=\"%[A-z,_0-9]\"", rname)==1){ + for (i=0; i < NumberOfBoards; i++){ + trb[i].Reg[trb[i].used-1].name = strdup(rname); + printf("RNAME: %s\n", rname); + } + } + + if(sscanf(ptr, "purpose=\"%[A-z,_0-9]\"", purpose)==1){ + for (i=0; i < NumberOfBoards; i++){ + trb[i].Reg[trb[i].used-1].purpose = strdup(purpose); + } + } + } + + if (field_open==true && group_open==true && register_open==true){ + if (strcmp(ptr,"/>\n") == 0){ + field_open=false; + } + if (sscanf(ptr, "name=\"%[A-z,_0-9]\"", fname)==1){ + for (i=0; i < NumberOfBoards; i++){ + trb[i].Reg[trb[i].used-1].field[trb[i].Reg[trb[i].used-1].used-1].name = strdup(fname); + printf(" FNAME: %s %i\n", rname,NumberOfBoards); + + } + } + if (sscanf(ptr, "format=\"%[A-z,_0-9]\"", fformat)==1){ + for (i=0; i < NumberOfBoards; i++){ + trb[i].Reg[trb[i].used-1].field[trb[i].Reg[trb[i].used-1].used-1].format = strdup(fformat); + } + } + if (sscanf(ptr, "bits=%*c%i%*c", &bits)==1){ + for (i=0; i < NumberOfBoards; i++){ + trb[i].Reg[trb[i].used-1].field[trb[i].Reg[trb[i].used-1].used-1].bits = bits; + } + } + if (sscanf(ptr, "start=%*c%i%*c", &start)==1){ + for (i=0; i < NumberOfBoards; i++){ + trb[i].Reg[trb[i].used-1].field[trb[i].Reg[trb[i].used-1].used-1].start = start; + } + } + if (sscanf(ptr, "rate=%*c%i%*c", &rate )==1){ + for (i=0; i < NumberOfBoards; i++){ + trb[i].Reg[trb[i].used-1].field[trb[i].Reg[trb[i].used-1].used-1].rate = rate; + } + } + if (sscanf(ptr, "unit=%*c%x%*c", &unit )==1){ + for (i=0; i < NumberOfBoards; i++){ + trb[i].Reg[trb[i].used-1].field[trb[i].Reg[trb[i].used-1].used-1].unit = unit; + } + } + if (sscanf(ptr, "scale=%*c%f%*c", &scale )==1){ + for (i=0; i < NumberOfBoards; i++){ + trb[i].Reg[trb[i].used-1].field[trb[i].Reg[trb[i].used-1].used-1].scale = scale; + } + } + } + + + ptr = strtok(NULL, delimiter); + }//end while2 + }//end while1 + + + fclose(fp); + databaseSet = 1; + } + if ( 0xffff < reg_addr_buf ) { + fprintf( stderr, "\033[31;1m%s: Invalid register address '%x'\033[0m\n",prec->name, reg_addr_buf ); + return -1; + } +printf("%i\n",__LINE__); +//----------------------------------------------------------------------// + + // Test the fields + printf("Register Addres: %i\n", trb[0].Reg[2].regAddr); // getAddr of Register[0] + printf("Number of registers: %i\n", trb[0].size); // print number of fields in Register + printf("Number of fields:%i\n", trb[0].Reg[1].size); // print name of field 1 in Register 0 + printf("Number of fields:%s\n", trb[0].Reg[2].field[0].name); // print name of field 1 in Register 0 + printf("%i\n", trb[0].used); // getAddr of Register[0] + +//---------------------------------------------------------------------------------------------// + /*free memory + for(i=0;ipact = (epicsUInt8)true; /* disable record */ + + status = initCommon( (dbCommon *)prec, &prec->inp ); + prec->pact = (epicsUInt8)false; /* enable record */ + + return status; +} + +/*----- initialization of longout records -------------------------------------*/ +static long initLo( longoutRecord* prec ) { + long status = 0; + prec->pact = (epicsUInt8)true; /* disable record */ + + status = initCommon( (dbCommon *)prec, &prec->out ); + prec->pact = (epicsUInt8)false; /* enable record */ + + return status; +} + +/*----- initialization of waveform records ------------------------------------*/ +static long initWaveform( waveformRecord* prec ) { + long status = 0; + prec->pact = (epicsUInt8)true; /* disable record */ + + if ( DBF_DOUBLE != prec->ftvl ) { + fprintf( stderr, "\033[31;1m%s: Invalid field type of value\033[0m\n", prec->name ); + return -1; + } + + status = initCommon( (dbCommon *)prec, &prec->inp ); + + prec->pact = (epicsUInt8)false; /* enable record */ + + return status; +} + +/*----- process routine of longin records -------------------------------------*/ +static long processLi( longinRecord* prec ) { + trbnet_info_t* pinfo = (trbnet_info_t*)prec->dpvt; + epicsUInt32 data[2] = { 0 }; + int trb_stat = 0; + + int j,k,i,address; + int search_stat = 0 ; + int trb_Nmb=0, reg_Nmb=0, field_Nmb=0; + + if( !_trb_connected ){ + if( init_ports() == -1 ) { + fprintf( stderr, "\033[31;1m%s: init_ports failed:\n%d %s\033[0m\n", + prec->name, trb_errno, trb_strerror() ); // could be a problem (prec->name) + recGblSetSevr( prec, COMM_ALARM, INVALID_ALARM ); + return -1; + } + _trb_connected = true; + } + + + + // READ Address from Database + for(i=0;ireg_name_buf) == 0){ + search_stat = 0; + } + else { + for(k=0;kreg_name_buf) == 0){ + address = trb[i].Reg[j].field[k].regAddr; + search_stat = 0; + trb_Nmb=i; reg_Nmb=j; field_Nmb=k; + } else { + search_stat = -1; + } + } + } + } + } + + if (search_stat){ + int data_size = 2; + trb_stat = trb_register_read( pinfo->trb_addr, address, data, data_size ); + //trb_stat = trb_register_readTESTFUNKTION( pinfo->trb_addr, address, data, data_size ); + + //--------------------------------------// + if ( -1 == trb_stat ) { + /* first try failed, do it again */ + if( init_ports() == -1 ) { + fprintf( stderr, "\033[31;1m%s: init_ports failed:\n%d %s\033[0m\n", + prec->name, trb_errno, trb_strerror() ); + recGblSetSevr( prec, COMM_ALARM, INVALID_ALARM ); + return -1; + } + trb_stat = trb_register_read( pinfo->trb_addr, address, data, data_size ); + if ( -1 == trb_stat ) { + /* second try failed, return error */ + fprintf( stderr, "\033[31;1m%s: read_register failed: %d %s\033[0m\n", + prec->name, trb_errno, trb_strerror() ); + recGblSetSevr( prec, READ_ALARM, INVALID_ALARM ); + _trb_connected = false; + return -1; + } + } + /* Check Status-Bits */ + if ( TRB_STATUS_WARNING == trb_errno ) { + fprintf( stderr, "%s: Warning: Status-Bit(s) have been set:\n%s\n", + prec->name, trb_termstr( trb_term ) ); + recGblSetSevr( prec, NULL, NULL); + return -1; + } + //------------------------------// + double output = -1; + epicsUInt32 start = pow(2, trb[trb_Nmb].Reg[reg_Nmb].field[field_Nmb].start); + epicsUInt32 end = pow(2, trb[trb_Nmb].Reg[reg_Nmb].field[field_Nmb].bits); + double scale = trb[trb_Nmb].Reg[reg_Nmb].field[field_Nmb].scale; + + for (i=0; i< data_size;i+=2){ + output = ((data[i+1]/start)%end )*scale; + prec->val = output; + } + //--------------------------------// + + } else { + printf("No Address Name %s found!\n", pinfo->reg_name_buf); + } + + return 0; +} + +//----- LONGOUT IS NOT IN USE!!!-----------------------------------------------// +/*----- process routine of longout records ------------------------------------*/ +static long processLo( longoutRecord* prec ) { + trbnet_info_t* pinfo = (trbnet_info_t*)prec->dpvt; + epicsUInt32 value = prec->val; + int trb_stat = 0; + + if( !_trb_connected ) { + if( init_ports() == -1 ) { + fprintf( stderr, "\033[31;1m%s: init_ports failed:\n%d %s\033[0m\n", + prec->name, trb_errno, trb_strerror() ); + recGblSetSevr( prec, COMM_ALARM, INVALID_ALARM ); + return -1; + } + _trb_connected = true; + } + + trb_stat = trb_register_write( pinfo->trb_addr, pinfo->reg_addr, value ); + if ( -1 == trb_stat ) { + /* first try failed, do it again */ + if( init_ports() == -1 ) { + fprintf( stderr, "\033[31;1m%s: init_ports failed:\n%d %s\033[0m\n", + prec->name, trb_errno, trb_strerror() ); + recGblSetSevr( prec, COMM_ALARM, INVALID_ALARM ); + return -1; + } + trb_stat = trb_register_write( pinfo->trb_addr, pinfo->reg_addr, value ); + if ( -1 == trb_stat ) { + /* second try failed, return error */ + fprintf( stderr, "\033[31;1m%s: write_register failed: %d %s\033[0m\n", + prec->name, trb_errno, trb_strerror() ); + recGblSetSevr( prec, WRITE_ALARM, INVALID_ALARM ); + _trb_connected = false; + return -1; + } + } + if ( TRB_STATUS_WARNING == trb_errno ) { + fprintf( stderr, "%s: Warning: Status-Bit(s) have been set:\n%s\n", + prec->name, trb_termstr( trb_term ) ); + return -1; + } + + return 0; +} + +/*----- process routine of waveform records -----------------------------------*/ +static long processWaveform( waveformRecord* prec ) { + printf("%i\n",__LINE__); + trbnet_info_t *pinfo = (trbnet_info_t*)prec->dpvt; + epicsUInt32 *pdata_buf; + epicsUInt32 count = 200;//prec->nelm; // equal to 100 boards + int trb_stat = 0; + int i = 0; +printf("%i\n",__LINE__); + + if( !_trb_connected ) { + if( init_ports() == -1 ) { + fprintf( stderr, "\033[31;1m%s: init_ports failed TEST:\n%d %s\033[0m\n", + prec->name, trb_errno, trb_strerror() ); // same as above + recGblSetSevr( prec, COMM_ALARM, INVALID_ALARM ); + return -1; + } + _trb_connected = true; + } + printf("%i\n",__LINE__); + pdata_buf = callocMustSucceed( count, sizeof(epicsUInt32), "devTrbnet::processWaveform" ); + printf("%i\n",__LINE__); + int j,k,address; + int search_stat = -1 ; + int trb_Nmb=0, reg_Nmb=0, field_Nmb=0; + + if (strcmp(pinfo->reg_name_buf, "ADC") == 0){ + search_stat = 1; +} else { +printf("%i\n",__LINE__); + for(i=0;i= 0){ printf("%i\n",__LINE__); + //run without doing smtng + } else { + printf("%i %i %i\n",i,j,__LINE__); + printf("trb %s \n",trb[i].Reg[j].name); + printf("pinfo %s \n",pinfo->reg_name_buf); + printf("comp %i \n",strcmp(trb[i].Reg[j].name,pinfo->reg_name_buf)); + if (strcmp(trb[i].Reg[j].name,pinfo->reg_name_buf) == 0){ + search_stat = 0; printf("%i %i %i\n",i,j,__LINE__); + } + else { + printf("%i\n",__LINE__); + for(k=0;kreg_name_buf)); + + if (strcmp(trb[i].Reg[j].field[k].name, pinfo->reg_name_buf) == 0){ + address = trb[i].Reg[j].field[k].regAddr; + search_stat = 0; + trb_Nmb=i; reg_Nmb=j; field_Nmb=k; + } else { + search_stat = -1; + } + } + } + }//search_stat end if + } + } + +} +printf("%i\n",__LINE__); + int data_size = 2; + unsigned int mode = 0; + + if (search_stat == 1){ + int channel[5] = {7,7,7,6,5}; + int resolution[5][4] = {{2,1,2,1},{2,2,2,1},{2,2,2,4},{2,2,2,2},{3,3,2,2}}; + double multiplier[5][4] = {{1.,1.,0.5,2.},{1.,1.,0.5,0.},{1.,1.,0.5,3.125},{1.,1.,0.5,0.5},{2.5,1.25,1.,0.5}}; + int cmd = 0; + + if (atoi(pinfo->reg_name_buf_nbr)>=0 && atoi(pinfo->reg_name_buf_nbr)<5) { + mode = atoi(pinfo->reg_name_buf_nbr); + } else { + mode = 0; + } + + //prec->nelm = 10; + //prec->bptr = realloc(prec->bptr, prec->nelm * dbValueSize(prec->ftvl)); + + double *pvalue = (epicsUInt32*)prec->bptr; + + + cmd = 0xc1830000 + ( resolution[mode][0] << 25); + int test = trb_register_write(pinfo->trb_addr,0xd41a,25); +//fprintf(stderr,"Test: %d %x\n", test,pinfo->trb_addr); + if (test==0){ // 0x8300 + PadiwaSendCmd(cmd,pinfo->trb_addr,channel[mode]); + usleep(5000); + cmd = 0xd1830000 + ( resolution[mode][1] << 25); + pvalue[0]= ((( PadiwaSendCmd(cmd,pinfo->trb_addr,channel[mode])>>19)&0xfff)*multiplier[mode][0]); + // fprintf(stderr," 1: %f \n",(double) ((( PadiwaSendCmd(cmd,pinfo->trb_addr,channel[mode])>>19)&0xfff)*multiplier[mode][0])); + usleep(5000); + cmd = 0xe1830000 + ( resolution[mode][2] << 25); + pvalue[1]= ((( PadiwaSendCmd(cmd,pinfo->trb_addr,channel[mode])>>19)&0xfff)*multiplier[mode][1]); + // fprintf(stderr," 2: %f \n",(double) ((( PadiwaSendCmd(cmd,pinfo->trb_addr,channel[mode])>>19)&0xfff)*multiplier[mode][1]) ); + usleep(1000); + cmd = 0xf1830000 + ( resolution[mode][3] << 25); + pvalue[2]= ((( PadiwaSendCmd(cmd,pinfo->trb_addr,channel[mode])>>19)&0xfff)*multiplier[mode][2]); + // fprintf(stderr," 3: %f \n",(double) ((( PadiwaSendCmd(cmd,pinfo->trb_addr,channel[mode])>>19)&0xfff)*multiplier[mode][2]) ); + usleep(5000); + pvalue[3]= ((( PadiwaSendCmd(0xf3930000,pinfo->trb_addr,channel[mode])>>19)&0xfff)*multiplier[mode][3]); + // fprintf(stderr," 4: %f \n",(double) (((PadiwaSendCmd(0xf3930000,pinfo->trb_addr,channel[mode])>>19)&0xfff)*multiplier[mode][3]) ); + usleep(5000); + pvalue[4]= ((( PadiwaSendCmd(0,pinfo->trb_addr,channel[mode])>>19)&0xfff)/16.); + // fprintf(stderr," 5: %3.2f \n", (double) (((PadiwaSendCmd(0,pinfo->trb_addr,channel[mode])>>19)&0xfff)/16.)); + + trb_register_write(pinfo->trb_addr,0xd41a,7); + } else {fprintf(stderr,"ERR in TEST");recGblSetSevr( prec, COMM_ALARM, INVALID_ALARM );} + + } else if (search_stat == 0) { + trb_stat = trb_register_read( pinfo->trb_addr, address, pdata_buf, count ); // + if ( -1 == trb_stat ) { + /* first try failed, do it again */ + if( init_ports() == -1 ) { + fprintf( stderr, "\033[31;1m%s: init_ports failed:\n%d %s\033[0m\n", + prec->name, trb_errno, trb_strerror() ); + recGblSetSevr( prec, COMM_ALARM, INVALID_ALARM ); + return -1; + } + trb_stat = trb_register_read( pinfo->trb_addr, address, pdata_buf, count ); + if ( -1 == trb_stat ) { + fprintf( stderr, "\033[31;1m%s: read_register failed: %d %s\033[0m\n", + prec->name, trb_errno, trb_strerror() ); + free( pdata_buf ); + if (trb_errno == 12){ + prec->nelm = prec->nelm * 2; + } + recGblSetSevr( prec, READ_ALARM, INVALID_ALARM ); + _trb_connected = false; + return -1; + } + } + if ( TRB_STATUS_WARNING == trb_errno ) { + fprintf( stderr, "%s: Warning: Status-Bit(s) have been set:\n%s\n", + prec->name, trb_termstr( trb_term ) ); + recGblSetSevr( prec, READ_ALARM, INVALID_ALARM ); + return -1; + } + + if ( trb_stat != prec->nelm ) { + prec->nelm = trb_stat; + prec->bptr = realloc(prec->bptr, prec->nelm * dbValueSize(prec->ftvl)); + } + + + double *pvalue = (epicsUInt32*)prec->bptr; + + + //---------------------------------------------------// + double output = -1; + epicsUInt32 start = pow(2, trb[trb_Nmb].Reg[reg_Nmb].field[field_Nmb].start); + epicsUInt32 end = pow(2, trb[trb_Nmb].Reg[reg_Nmb].field[field_Nmb].bits); + double scale = trb[trb_Nmb].Reg[reg_Nmb].field[field_Nmb].scale; + +/* for( i=0; i < trb_stat; i+=2 ) { + output = ((pdata_buf[i+1]/start)%end )*scale; + pvalue[i] = pdata_buf[i]; + pvalue[i+1] = output; + } +*/ + for( i=0; i<( prec->nelm/2); i+=1 ){ + output = ((pdata_buf[(i*2)+1]/start)%end ) * scale; + pvalue[i] = pdata_buf[i*2]; +// pvalue[i+(trb_stat/2)] = output; + pvalue[i+(prec->nelm/2)] = output; + } + + //---------------------------------------------------// + + } else { + printf("No Address Name %s found!\n", pinfo->reg_name_buf); + } + + +//--------------------------------// + prec->nord = prec->nelm; + + free( pdata_buf ); + + return 0; +} + diff --git a/Trbnet/devTrbnet/TrbnetApp/src/trberror.h b/Trbnet/devTrbnet/TrbnetApp/src/trberror.h new file mode 100644 index 0000000..e551116 --- /dev/null +++ b/Trbnet/devTrbnet/TrbnetApp/src/trberror.h @@ -0,0 +1,80 @@ +#ifndef TRBERROR_H +#define TRBERROR_H + +#include + +#ifdef __cplusplus +extern "C" { +#endif + +typedef enum { + TRB_NONE = 0, + TRB_TX_BUSY = 1, + TRB_FIFO_NOT_EMPTY = 2, + TRB_FIFO_TIMEOUT = 3, + TRB_FIFO_HEADERS = 4, + TRB_FIFO_SEQUENZ = 5, + TRB_FIFO_INVALID_MODE = 6, + TRB_FIFO_INCOMPLETE_PACKAGE = 7, + TRB_FIFO_INVALID_HEADER = 8, + TRB_FIFO_MISSING_TERM_HEADER = 9, + TRB_FAILED_WAIT_IS_VALID = 10, + TRB_FAILED_WAIT_IS_NOT_VALID = 11, + TRB_USER_BUFFER_OVF = 12, + TRB_INVALID_CHANNEL = 13, + TRB_INVALID_PKG_NUMBER = 14, + TRB_STATUS_ERROR = 15, + TRB_INVALID_ADDRESS = 16, + TRB_INVALID_LENGTH = 17, + TRB_ENDPOINT_NOT_REACHED = 18, + TRB_DMA_UNAVAILABLE = 19, + TRB_DMA_TIMEOUT = 20, + TRB_READMEM_INVALID_SIZE = 21, + TRB_HDR_DLEN = 22, + TRB_PEXOR_OPEN = 23, + TRB_SEMAPHORE = 24, + TRB_FIFO_SHARED_MEM = 25, + TRB_STATUS_WARNING = 26, + TRB_RPC_ERROR = 27, + TRB_PEXOR_DATA_ERROR = 28, + TRB_PEXOR_DEVICE_ERROR = 29, + TRB_PEXOR_DEVICE_TRB_TIMEOUT = 30, + TRB_PEXOR_DEVICE_POLLING_TIMEOUT = 31, + TRB_PEXOR_DEVICE_DMA_EMPTY = 32, + TRB_PEXOR_DEVICE_INVALID_DMA_SIZE = 33, + TRB_PEXOR_DEVICE_LOST_CREDENTIAL = 34, + TRB_PEXOR_DEVICE_FIFO_TRANSFER = 35, + TRB_TRB3_CMD_NOT_SUPPORTED = 36, + TRB_TRB3_SOCKET_ERROR = 37, + TRB_TRB3_SOCKET_TIMEOUT = 38, + TRB_TRB3_INCOMPLETE_UDP = 39, + TRB_TRB3_DATA_ERROR = 40, + TRB_TRB3_INVALID_UDP_HEADER = 41 +} TRB_ERROR; + +/* last TRBNet-TermPackage */ +typedef struct { + uint16_t status_common; + uint16_t status_channel; + uint16_t sequence; + uint8_t channel; +} TRB_TERM; + +extern int trb_errno; + +extern TRB_TERM trb_term; + +void trb_error(const char *s); + +const char* trb_strerror(); + + +const char* trb_errorstr(int trberrno); + +const char* trb_termstr(TRB_TERM term); + +#ifdef __cplusplus +} +#endif + +#endif diff --git a/Trbnet/devTrbnet/TrbnetApp/src/trbnet.h b/Trbnet/devTrbnet/TrbnetApp/src/trbnet.h new file mode 100644 index 0000000..f0478ee --- /dev/null +++ b/Trbnet/devTrbnet/TrbnetApp/src/trbnet.h @@ -0,0 +1,287 @@ +#ifndef TRBNET_H +#define TRBNET_H + +extern const char trbnet_version[]; + +#include +#include + +extern unsigned int trb_debug; + +#ifdef PEXOR +extern char pexor_deviceName[256]; +extern int pexor_dma; +#endif + +#ifdef __cplusplus +extern "C" { +#endif + +/* ---------------------------------------------------------------------- */ + +int init_ports(); + +int trb_register_read(uint16_t trb_address, + uint16_t reg_address, + uint32_t* data, + unsigned int dsize); + +int trb_registertime_read(uint16_t trb_address, + uint16_t reg_address, + uint32_t* data, + unsigned int dsize); + +int trb_register_read_mem(uint16_t trb_address, + uint16_t reg_address, + uint8_t option, + uint16_t size, + uint32_t* data, + unsigned int dsize); + +int trb_registertime_read_mem(uint16_t trb_address, + uint16_t reg_address, + uint8_t option, + uint16_t size, + uint32_t* data, + unsigned int dsize); + +int trb_register_write(uint16_t trb_address, + uint16_t reg_address, + uint32_t value); + +int trb_register_write_mem(uint16_t trb_address, + uint16_t reg_address, + uint8_t option, + const uint32_t* data, + uint16_t size); + +int trb_read_uid(uint16_t trb_address, + uint32_t* data, + unsigned int dsize); + +int trb_set_address(uint64_t uid, + uint8_t endpoint, + uint16_t trb_address); + + +int trb_ipu_data_read(uint8_t type, + uint8_t trg_info, + uint8_t trg_random, + uint16_t trg_number, + uint32_t* data, + unsigned int dsize); + +int trb_send_trigger(uint8_t type, + uint32_t info, + uint8_t random, + uint16_t number); + +int trb_send_trigger_rich(uint8_t input, + uint8_t type, + uint32_t info, + uint8_t random, + uint16_t number); + +int fpga_register_read(uint32_t reg_address, + uint32_t* value); + +int fpga_register_write(uint32_t reg_address, + uint32_t value); + +int trb_nettrace(uint16_t trb_address, + uint32_t *data, + unsigned int dsize); + +int trb_register_setbit(uint16_t trb_address, + uint16_t reg_address, + uint32_t bitMask); + +int trb_register_clearbit(uint16_t trb_address, + uint16_t reg_address, + uint32_t bitMask); + +int trb_register_loadbit(uint16_t trb_address, + uint16_t reg_address, + uint32_t bitMask, + uint32_t bitValue); + +#ifdef PEXOR +int fpga_register_read_mem(uint32_t reg_address, + uint32_t* data, + unsigned int size); + +int fpga_register_write_mem(uint32_t reg_address, + const uint32_t* data, + unsigned int size); +#endif + +int trb_fifo_flush(uint8_t channel); + +int network_reset(); + +int com_reset(); + +/* ---------------------------------------------------------------------- */ + +/* This library provides several function to access the trbnet on a + Etrax-Board. + +*/ + +/************************************************************************/ +/* In case of any error the gloabl varianble 'trb_errno' will be set, */ +/* see trberror.h for details. */ +/************************************************************************/ + + +/************************************************************************/ +/* int trb_register_read(uint16_t trb_address, + uint16_t reg_address, + uint32_t* data, + unsigned int dsize); + + trb_address: TRB-Address of the TRB-Endpoint + reg_address: Register-Address to be read from, broadcasts are supported + data: Pointer to a uint32_t Data-Buffer + dsize: Size of the Data-Buffer in units of 32bit-words + + ReturnValue: == -1 on error, trberrno will be set + >= 0 number of 32bit-words which were stored in Data-Buffer + + TRB-Channel used: slow control (3) + + reads the register reg_address of a TRB-Endpoint with address + trb_address. The received data is stored in the Data-Buffer data. + + The format of the Data-Buffer is: + first word: TRB-Address of the sender + second word: register value + + --> The size of the Data-Buffer must be at least >= 2 + +*/ + + +/************************************************************************/ +/* int trb_register_read_mem(uint16_t trb_address, + uint16_t reg_address, + uint8_t option, + uint16_t size, + uint32_t* data, + unsigned int dsize); + + trb_address: TRB-Address of the TRB-Endpoint + reg_address: Register-Address to be read from, broadcasts are supported + uint8_t option: + uint16_t size: Number of 32Bit-words to be read + data: Pointer to a uint32_t Data-Buffer + dsize: Size of the Data-Buffer in units of 32bit-words + + ReturnValue: == -1 on error, trberrno will be set + >= 0 number of 32bit-words which were stored in Data-Buffer + + TRB-Channel used: slow control (3) + + reads the register reg_address of a TRB-Endpoint with address + trb_address. The received data is stored in the Data-Buffer data. + + The format of the Data-Buffer is: + first word: TRB-Address of the sender (Lower 2Bytes), len (Upper 2bytes) + second word: register value + + --> The size of the Data-Buffer must be at least >= 2 + +*/ + + +/************************************************************************/ +/* int trb_register_write(uint16_t trb_address, + uint16_t reg_address, + uint32_t value); + + trb_address: TRB-Address of the TRB-Endpoint, broadcasts are supported + reg_address: Register-Address to be written to + value: 32bit-word to be writen to the register + + ReturnValue: == -1 on error, trberrno will be set + + TRB-Channel used: slow control (3) + + writes the value to the register reg_address of a TRB-Endpoint with address + trb_address. +*/ + +/************************************************************************/ +/* int trb_read_uid(uint16_t trb_address, + uint32_t* data, + unsigned int dsize); + + trb_address: TRB-Address of the TRB-Endpoint, broadcasts are supported + data: Pointer to a uint32_t Data-Buffer + dsize: Size of the Data-Buffer in units of 32bit-words + + ReturnValue: == -1 on error, trberrno will be set + >= 0 number of 32bit-words which were stored in Data-Buffer + + TRB-Channel used: slow control (3) + + reads the Unique-Id of a TRB-Endpoint with address trb_address. The + received data is stored in the Data-Buffer data. + + The format of the Data-Buffer is: + first word: UID High-32Bit Word + second word: UID Low-32Bit Word + third word: Endpoint Number + fourth word: TRB-Address of the sender + + --> The size of the Data-Buffer must be at least >= 4 + +*/ + +/************************************************************************/ +/* int trb_set_address(uint64_t uid, + uint8_t endpoint, + uint16_t trb_address); + + uint64_t uid: the UID of the Endpoint + uint8_t endpoint: Number of the TRBNet-Endpoint + uint16_t trb_address: the new TRB-Netaddress, broadcasts are not supported + + ReturnValue: == -1 on error, trberrno will be set + == 0 on success + + TRB-Channel used: slow control (3) + + sets a new TRB-Address trb_address of the give TRFNet-endpoint. +*/ + +/************************************************************************/ +/* int trb_ipu_data_read(uint8_t type, + uint8_t trg_info, + uint8_t trg_random, + uint16_t trg_number, + uint32_t* data, + unsigned int dsize); + + data: Pointer to a uint32_t Data-Buffer + dsize: Size of the Data-Buffer in units of 32bit-words + + ReturnValue: == -1 on error, trberrno will be set + >= 0 0 number of 32bit-words which were stored in Data-Buffer + + send a request to all TRBNet-Endpoints to readout the IPU-Data. The IPU + Datastream will be stored in the user DataBufer. +*/ + +/************************************************************************/ +/* int trb_send_trigger(uint8_t type, + uint32_t info, + uint8_t random, + uint16_t number); +*/ + +#ifdef __cplusplus +} +#endif + +#endif diff --git a/Trbnet/devTrbnet/configure/CONFIG_SITE b/Trbnet/devTrbnet/configure/CONFIG_SITE index 72b399d..e9e295e 100644 --- a/Trbnet/devTrbnet/configure/CONFIG_SITE +++ b/Trbnet/devTrbnet/configure/CONFIG_SITE @@ -19,7 +19,7 @@ CHECK_RELEASE = YES # Set this when you only want to compile this application # for a subset of the cross-compiled target architectures # that Base is built for. -#CROSS_COMPILER_TARGET_ARCHS = vxWorks-68040 +CROSS_COMPILER_TARGET_ARCHS = # To install files into a location other than $(TOP) define # INSTALL_LOCATION here. diff --git a/Trbnet/devTrbnet/configure/RELEASE b/Trbnet/devTrbnet/configure/RELEASE index 7c64f0e..943bc18 100644 --- a/Trbnet/devTrbnet/configure/RELEASE +++ b/Trbnet/devTrbnet/configure/RELEASE @@ -25,11 +25,14 @@ TEMPLATE_TOP=$(EPICS_BASE)/templates/makeBaseApp/top #SNCSEQ=$(EPICS_BASE)/../modules/soft/seq # Trbnet -TRBNET = /home/florian/trbsoft/trbnettools +TRBNET = /home/adrian/trb/trbnettools/libtrbnet/ # EPICS_BASE usually appears last so other apps can override stuff: -EPICS_BASE=/usr/Epics/base +EPICS_BASE=/home/epics/EPICS/EPICS-3.14.12.4/base # Set RULES here if you want to take build rules from somewhere # other than EPICS_BASE: #RULES=/path/to/epics/support/module/rules/x-y + +#EPICS_TRBNET_XML_PATH=/home/adrian/trb/daqtools/xml-db/database/ +#EPICS_TRBNET_XML_NAME=TrbNet diff --git a/Trbnet/devTrbnet/iocBoot/iocTrbnet/st.cmd b/Trbnet/devTrbnet/iocBoot/iocTrbnet/st.cmd index 29ca7fc..1f33260 100644 --- a/Trbnet/devTrbnet/iocBoot/iocTrbnet/st.cmd +++ b/Trbnet/devTrbnet/iocBoot/iocTrbnet/st.cmd @@ -1,6 +1,8 @@ -#!../../bin/linux-x86_64/Trbnet +#!../../bin/linux-arm/Trbnet < envPaths +epicsEnvSet("EPICS_TRBNET_XML_PATH","/home/adrian/trb/daqtools/xml-db/database/") +epicsEnvSet("EPICS_TRBNET_XML_NAME","MDC") cd ${TOP} @@ -9,10 +11,10 @@ dbLoadDatabase "dbd/Trbnet.dbd" Trbnet_registerRecordDeviceDriver pdbbase ## Load record instances -dbLoadRecords("db/trbExample.db") - +#dbLoadRecords("db/trbADC.db") +#dbLoadTemplate("TrbnetApp/Db/trbADC.substitutions") +dbLoadTemplate("TrbnetApp/Db/trbExample.substitutions") cd ${TOP}/iocBoot/${IOC} iocInit ## Start any sequence programs -#seq sncxxx,"user=florianHost"