/*-----------------------------------------------------------------------** * file: devBrooks0254.c ** *------------------------------------------------------------------------** * devBrooks0254.c - Implement the Epics device support layer for BROOKS ** * using serial interface ** * ** * version: 1.0 ** * $Revision: 1.0 $ ** * created: 25-Apr-2011 H. Egiyan ** * institution: Jefferson Lab ** * ** *------------------------------------------------------------------------** */ /* * Original Author: H. Egiyan * * Experimental Physics and Industrial Control System (EPICS) * * Copyright 2011, * * NOTE: All device suport resides in this file * Implementation and assumption: * */ #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include /************** support for bi record *************************/ /* Create the dset for devBiBrooks0254 */ static long bi_init_record(); static long read_bi(); struct { long number; DEVSUPFUN report; DEVSUPFUN init; DEVSUPFUN init_record; DEVSUPFUN get_ioint_info; DEVSUPFUN read_bi; } devBiBrooks0254 = { 5, NULL, NULL, bi_init_record, NULL, read_bi }; epicsExportAddress( dset, devBiBrooks0254 ); static long bi_init_record( struct biRecord *pbi ) { devInfoBrooks0254* pdevInfo = NULL; pbi->dpvt = NULL; int err = common_init_record( (struct dbCommon *) pbi, &pdevInfo, "bi" ); if ( err || pdevInfo == NULL ) { recGblRecordError( S_db_noMemory, (void *)pbi, "devBiBrooks0254 (bi_init_record) no memory" ); return( S_db_noMemory ); } err = common_get_params( pdevInfo, pbi->inp.value.constantStr ); if ( err ) { recGblRecordError( err, (void *)pbi, "devBiBrooks0254 (init_record) bad parameters") ; return( err ); } return( 0 ); } static long read_bi( struct biRecord *pbi ) { devInfoBrooks0254* pdevInfo = (devInfoBrooks0254 *) pbi->dpvt; int status, intVal; if( pdevInfo != NULL ) { switch ( pdevInfo->port_type ) { case ( Global ): if( pdevInfo->param == GlobZeroSprs || pdevInfo->param == GlobClearSP || pdevInfo->param == GlobAudioBep ) { /* Standard global binary parameter for Brooks0254 driver */ status = brooksGetGlobPar( pdevInfo->chassis, pdevInfo->param, &intVal ); if( status == 0 ) { pbi->rval = intVal ; pbi->udf = 0 ; return 0; } } else if ( pdevInfo->param == GlobComStat ) { /* Check the communication with the chassis */ status = brooksGetCommStatus( pdevInfo->chassis, &intVal ); if( status == 0 ) { pbi->rval = intVal ; pbi->udf = 0 ; return 0; } } else { recGblRecordError( S_db_badChoice, (void *)pbi, "devBiBrooks0254 (read_bi) unknown parameter number"); return S_db_badChoice; } break; case ( Output ): if( pdevInfo->param == OutSetSours ) { status = brooksGetParBool( pdevInfo->chassis, pdevInfo->slot_no, pdevInfo->port_type, pdevInfo->param, &intVal ); if( status == 0 ) { pbi->rval = intVal ; return 0; } } else { recGblRecordError( S_db_badChoice, (void *)pbi, "devBiBrooks0254 (read_bi) unknown parameter number"); return S_db_badChoice; } break; default: recGblRecordError( S_db_badChoice, (void *)pbi, "devBiBrooks0254 (read_bi) unknown port type"); return S_db_badChoice; break; } } else { recGblRecordError( S_db_badField, (void *)pbi, "devBiBrooks0254 (read_bi) no info on channel" ) ; return S_db_badField; } if( recGblSetSevr( pbi, READ_ALARM, INVALID_ALARM ) && ( pbi->stat != READ_ALARM || pbi->sevr != INVALID_ALARM ) ) recGblRecordError( -1, (void *)pbi, "Brooks0254 Driver Error" ); return -1 ; } /************** support for bo record *************************/ /* Create the dset for devBoBrooks0254 */ static long bo_init_record(); static long write_bo(); struct { long number; DEVSUPFUN report; DEVSUPFUN init; DEVSUPFUN init_record; DEVSUPFUN get_ioint_info; DEVSUPFUN write_bo; } devBoBrooks0254 = { 5, NULL, NULL, bo_init_record, NULL, write_bo }; epicsExportAddress( dset, devBoBrooks0254 ); static long bo_init_record( struct boRecord *pbo ) { devInfoBrooks0254* pdevInfo = NULL; pbo->dpvt = NULL; int err = common_init_record( (struct dbCommon *) pbo, &pdevInfo, "bo" ); if ( err || pdevInfo == NULL ) { recGblRecordError( S_db_noMemory, (void *)pbo, "devBoBrooks0254 (bo_init_record) no memory" ); return( S_db_noMemory ); } err = common_get_params( pdevInfo, pbo->out.value.constantStr ); if ( err ) { recGblRecordError( err, (void *)pbo, "devBoBrooks0254 (init_record) bad parameters") ; return( err ); } /*! Read back the parameter value from the device on initialization!*/ int value; switch ( pdevInfo->port_type ) { case ( Global ): if( pdevInfo->param == GlobZeroSprs || pdevInfo->param == GlobClearSP || pdevInfo->param == GlobAudioBep ) { int status = brooksGetGlobPar( pdevInfo->chassis, pdevInfo->param, &value ); if( status == 0 ) pbo->rval = value ; } break; case ( Output ): if( pdevInfo->param == OutSetSours ) { int status = brooksGetParBool( pdevInfo->chassis, pdevInfo->slot_no, pdevInfo->port_type, pdevInfo->param, &value ); if( status == 0 ) pbo->rval = value ; } break; default: recGblRecordError( S_db_badChoice, (void *)pbo, "devBoBrooks0254 (init_bo) unknown port type"); return S_db_badChoice; break; } return 0; } static long write_bo( struct boRecord *pbo ) { int value = (int)pbo->rval; devInfoBrooks0254* pdevInfo = (devInfoBrooks0254 *) pbo->dpvt; int status = 0; if( pdevInfo != NULL ) { switch ( pdevInfo->port_type ) { case ( Global ): if( pdevInfo->param == GlobZeroSprs || pdevInfo->param == GlobClearSP || pdevInfo->param == GlobAudioBep ) { status = brooksSetGlobPar( pdevInfo->chassis, pdevInfo->param, value ); if( status == 0 ) return 0; } else if( pdevInfo->param == GlobComReset ) { if( value == 1 ) status = brooksResetCommPort( pdevInfo->chassis ); if( status == 0 ) return 0; } else if( pdevInfo->param == GlobBatchMode ) { status = brooksSetBatchMode( pdevInfo->chassis, value ); if( status == 0 ) return 0; } else { recGblRecordError( S_db_badChoice, (void *)pbo, "devBoBrooks0254 (write_bo) unknown parameter number"); return S_db_badChoice; } break; case ( Output ): if( pdevInfo->param == OutSetSours ) { status = brooksSetParBool( pdevInfo->chassis, pdevInfo->slot_no, pdevInfo->port_type, pdevInfo->param, value ); if( status == 0 ) return 0; } else { recGblRecordError( S_db_badChoice, (void *)pbo, "devBoBrooks0254 (write_bo) unknown parameter number"); return S_db_badChoice; } break; default: recGblRecordError( S_db_badChoice, (void *)pbo, "devBoBrooks0254 (write_bo) unknown port type"); return S_db_badChoice; break; } } else { recGblRecordError( S_db_badField, (void *)pbo, "devBoBrooks0254 (write_bo) no info on channel" ) ; return S_db_badField; } if( recGblSetSevr( pbo, WRITE_ALARM, INVALID_ALARM ) && (pbo->stat != WRITE_ALARM || pbo->sevr != INVALID_ALARM ) ) recGblRecordError( -1, (void *)pbo, "Brooks0254 driver Error" ); return -1; } /************** support for mbbi record *************************/ /* Create the dset for devMbbiBrooks0254 */ static long mbbi_init_record(); static long read_mbbi(); struct { long number; DEVSUPFUN report; DEVSUPFUN init; DEVSUPFUN mbbi_init_record; DEVSUPFUN get_ioint_info; DEVSUPFUN read_mbbi; } devMbbiBrooks0254 = { 5, NULL, NULL, mbbi_init_record, NULL, read_mbbi }; epicsExportAddress( dset, devMbbiBrooks0254 ); static long mbbi_init_record( struct mbbiRecord *pmbbi ) { devInfoBrooks0254* pdevInfo = NULL; pmbbi->dpvt = NULL; int err = common_init_record( (struct dbCommon *) pmbbi, &pdevInfo, "mbbi" ); if ( err || pdevInfo == NULL ) { recGblRecordError( S_db_noMemory, (void *)pmbbi, "devMbbiBrooks0254 (mbbi_init_record) no memory" ); return( S_db_noMemory ); } err = common_get_params( pdevInfo, pmbbi->inp.value.constantStr ); if ( err ) { recGblRecordError( err, (void *)pmbbi, "devMbbiBrooks0254 (init_record) bad parameters") ; return( err ); } return( 0 ); } static long read_mbbi( struct mbbiRecord *pmbbi ) { devInfoBrooks0254* pdevInfo = (devInfoBrooks0254 *) pmbbi->dpvt; int status, intVal; if( pdevInfo != NULL ) { switch ( pdevInfo->port_type ) { case ( Input ): if( pdevInfo->param == InPortType || pdevInfo->param == InDecPoint || pdevInfo->param == InTimeBase ) { status = brooksGetParInt( pdevInfo->chassis, pdevInfo->slot_no, pdevInfo->port_type, pdevInfo->param, &intVal ); if( status == 0 ) { /* pmbbi->val = 1<rval = intVal ; return 0; } } else { recGblRecordError( S_db_badChoice, (void *)pmbbi, "devMbbiBrooks0254 (read_mbbi) unknown parameter number"); return S_db_badChoice; } break; case ( Output ): if( pdevInfo->param == OutPortType || pdevInfo->param == OutFuncSP || pdevInfo->param == OutSetVOR ) { status = brooksGetParInt( pdevInfo->chassis, pdevInfo->slot_no, pdevInfo->port_type, pdevInfo->param, &intVal ); if( status == 0 ) { /* pmbbi->val = 1<rval = intVal ; return 0; } } else { recGblRecordError( S_db_badChoice, (void *)pmbbi, "devMbbiBrooks0254 (read_mbbi) unknown parameter number"); return S_db_badChoice; } break; default: recGblRecordError( S_db_badChoice, (void *)pmbbi, "devMbbiBrooks0254 (read_mbbi) unknown port type"); return S_db_badChoice; break; } } else { recGblRecordError( S_db_badField, (void *)pmbbi, "devMbbiBrooks0254 (read_mbbi) no info on channel" ) ; return S_db_badField; } if( recGblSetSevr( pmbbi, READ_ALARM, INVALID_ALARM ) && ( pmbbi->stat != READ_ALARM || pmbbi->sevr != INVALID_ALARM ) ) recGblRecordError( -1, (void *)pmbbi, "Brooks0254 Driver Error" ); return -1 ; } /************** support for mbbo record *************************/ /* Create the dset for devMbboBrooks0254 */ static long mbbo_init_record(); static long write_mbbo(); struct { long number; DEVSUPFUN report; DEVSUPFUN init; DEVSUPFUN init_record; DEVSUPFUN get_ioint_info; DEVSUPFUN write_mbbo; } devMbboBrooks0254 = { 5, NULL, NULL, mbbo_init_record, NULL, write_mbbo }; epicsExportAddress( dset, devMbboBrooks0254 ); static long mbbo_init_record( struct mbboRecord *pmbbo ) { devInfoBrooks0254* pdevInfo = NULL; pmbbo->dpvt = NULL; int err = common_init_record( (struct dbCommon *) pmbbo, &pdevInfo, "mbbo" ); if ( err || pdevInfo == NULL ) { recGblRecordError( S_db_noMemory, (void *)pmbbo, "devMbboBrooks0254 (mbbo_init_record) no memory" ); return( S_db_noMemory ); } err = common_get_params( pdevInfo, pmbbo->out.value.constantStr ); if ( err ) { recGblRecordError( err, (void *)pmbbo, "devMbboBrooks0254 (init_record) bad parameters") ; return( err ); } /*! Readback the values in the driver */ int status = 0; int value; switch ( pdevInfo->port_type ) { case ( Input ): if( pdevInfo->param == InPortType || pdevInfo->param == InDecPoint || pdevInfo->param == InTimeBase ) { status = brooksGetParInt( pdevInfo->chassis, pdevInfo->slot_no, pdevInfo->port_type, pdevInfo->param, &value ); if( status == 0 ) pmbbo->rval = value; } else { recGblRecordError( S_db_badChoice, (void *)pmbbo, "devMbboBrooks0254 (write_mbbo) unknown parameter number"); return S_db_badChoice; } break; case ( Output ): if( pdevInfo->param == OutPortType || pdevInfo->param == OutFuncSP || pdevInfo->param == OutSetVOR ) { status = brooksGetParInt( pdevInfo->chassis, pdevInfo->slot_no, pdevInfo->port_type, pdevInfo->param, &value ); if( status == 0 ) pmbbo->rval = value; } else { recGblRecordError( S_db_badChoice, (void *)pmbbo, "devMbboBrooks0254 (write_mbbo) unknown parameter number"); return S_db_badChoice; } break; default: recGblRecordError( S_db_badChoice, (void *)pmbbo, "devMbboBrooks0254 (write_mbbo) unknown port type"); return S_db_badChoice; } return( 0 ); } static long write_mbbo( struct mbboRecord *pmbbo ) { int value = (int)pmbbo->rval; devInfoBrooks0254* pdevInfo = (devInfoBrooks0254 *) pmbbo->dpvt; int status = 0; if( pdevInfo != NULL ) { switch ( pdevInfo->port_type ) { case ( Input ): if( pdevInfo->param == InPortType || pdevInfo->param == InDecPoint || pdevInfo->param == InTimeBase ) { status = brooksSetParInt( pdevInfo->chassis, pdevInfo->slot_no, pdevInfo->port_type, pdevInfo->param, value ); if( status == 0 ) return 0; } else { recGblRecordError( S_db_badChoice, (void *)pmbbo, "devMbboBrooks0254 (write_mbbo) unknown parameter number"); return S_db_badChoice; } break; case ( Output ): if( pdevInfo->param == OutPortType || pdevInfo->param == OutFuncSP || pdevInfo->param == OutSetVOR ) { status = brooksSetParInt( pdevInfo->chassis, pdevInfo->slot_no, pdevInfo->port_type, pdevInfo->param, value ); if( status == 0 ) return 0; } else { recGblRecordError( S_db_badChoice, (void *)pmbbo, "devMbboBrooks0254 (write_mbbo) unknown parameter number"); return S_db_badChoice; } break; default: recGblRecordError( S_db_badChoice, (void *)pmbbo, "devMbboBrooks0254 (write_mbbo) unknown port type"); return S_db_badChoice; } } else { recGblRecordError( S_db_badField, (void *)pmbbo, "devMbboBrooks0254 (write_mbbo) no info on channel" ) ; return S_db_badField; } if( recGblSetSevr( pmbbo, WRITE_ALARM, INVALID_ALARM ) && (pmbbo->stat != WRITE_ALARM || pmbbo->sevr != INVALID_ALARM ) ) recGblRecordError( -1, (void *)pmbbo, "Brooks0254 driver Error" ); return -1; } /************** support for mbbiDirect record *************************/ /* Create the dset for devMbbiDirectBrooks0254 */ static long mbbid_init_record(); static long read_mbbid(); struct { long number; DEVSUPFUN report; DEVSUPFUN init; DEVSUPFUN mbbid_init_record; DEVSUPFUN get_ioint_info; DEVSUPFUN read_mbbid; } devMbbiDirectBrooks0254 = { 5, NULL, NULL, mbbid_init_record, NULL, read_mbbid }; epicsExportAddress( dset, devMbbiDirectBrooks0254 ); static long mbbid_init_record( struct mbbiDirectRecord *pmbbid ) { devInfoBrooks0254* pdevInfo = NULL; pmbbid->dpvt = NULL; int err = common_init_record( (struct dbCommon *) pmbbid, &pdevInfo, "mbbiDirect" ); if ( err || pdevInfo == NULL ) { recGblRecordError( S_db_noMemory, (void *)pmbbid, "devMbbiDirectBrooks0254 (mbbid_init_record) no memory" ); return( S_db_noMemory ); } err = common_get_params( pdevInfo, pmbbid->inp.value.constantStr ); if ( err ) { recGblRecordError( err, (void *)pmbbid, "devMbbiDirectBrooks0254 (init_record) bad parameters") ; return( err ); } return( 0 ); } static long read_mbbid( struct mbbiDirectRecord *pmbbid ) { devInfoBrooks0254* pdevInfo = (devInfoBrooks0254 *) pmbbid->dpvt; int status, intVal; if( pdevInfo != NULL ) { switch ( pdevInfo->port_type ) { case ( Input ): if( pdevInfo->param == InMeasUnit ) { status = brooksGetParInt( pdevInfo->chassis, pdevInfo->slot_no, pdevInfo->port_type, pdevInfo->param, &intVal ); if( status == 0 ) { pmbbid->val = intVal ; return 2; } } else { recGblRecordError( S_db_badChoice, (void *)pmbbid, "devMbbiDirectBrooks0254 (read_mbbid) unknown parameter number"); return S_db_badChoice; } break; default: recGblRecordError( S_db_badChoice, (void *)pmbbid, "devMbbiDirectBrooks0254 (read_mbbid) unknown port type"); return S_db_badChoice; break; } } else { recGblRecordError( S_db_badField, (void *)pmbbid, "devMbbiDirectBrooks0254 (read_mbbid) no info on channel" ) ; return S_db_badField; } if( recGblSetSevr( pmbbid, READ_ALARM, INVALID_ALARM ) && ( pmbbid->stat != READ_ALARM || pmbbid->sevr != INVALID_ALARM ) ) recGblRecordError( -1, (void *)pmbbid, "Brooks0254 Driver Error" ); return -1 ; } /************** support for mbboDirect record *************************/ /* Create the dset for devMbboDirectBrooks0254 */ static long mbbod_init_record(); static long write_mbbod(); struct { long number; DEVSUPFUN report; DEVSUPFUN init; DEVSUPFUN init_record; DEVSUPFUN get_ioint_info; DEVSUPFUN write_mbbod; } devMbboDirectBrooks0254 = { 5, NULL, NULL, mbbod_init_record, NULL, write_mbbod }; epicsExportAddress( dset, devMbboDirectBrooks0254 ); static long mbbod_init_record( struct mbboDirectRecord *pmbbod ) { devInfoBrooks0254* pdevInfo = NULL; pmbbod->dpvt = NULL; int err = common_init_record( (struct dbCommon *) pmbbod, &pdevInfo, "mbboDirect" ); if ( err || pdevInfo == NULL ) { recGblRecordError( S_db_noMemory, (void *)pmbbod, "devMbboDirectBrooks0254 (mbbod_init_record) no memory" ); return( S_db_noMemory ); } err = common_get_params( pdevInfo, pmbbod->out.value.constantStr ); if ( err ) { recGblRecordError( err, (void *)pmbbod, "devMbboDirectBrooks0254 (init_record) bad parameters") ; return( err ); } int status; int value; switch ( pdevInfo->port_type ) { case ( Input ): if( pdevInfo->param == InMeasUnit ) { status = brooksGetParInt( pdevInfo->chassis, pdevInfo->slot_no, pdevInfo->port_type, pdevInfo->param, &value ); if( status == 0 ) pmbbod->rval = value; } else { recGblRecordError( S_db_badChoice, (void *)pmbbod, "devMbboDirectBrooks0254 (init_mbbod) unknown parameter number"); return S_db_badChoice; } break; default: recGblRecordError( S_db_badChoice, (void *)pmbbod, "devMbboDirectBrooks0254 (init_mbbod) unknown port type"); return S_db_badChoice; break; } return( 0 ); } static long write_mbbod( struct mbboDirectRecord *pmbbod ) { int value = (int)pmbbod->rval; devInfoBrooks0254* pdevInfo = (devInfoBrooks0254 *) pmbbod->dpvt; int status = 0; if( pdevInfo != NULL ) { switch ( pdevInfo->port_type ) { case ( Input ): if( pdevInfo->param == InMeasUnit ) { status = brooksSetParInt( pdevInfo->chassis, pdevInfo->slot_no, pdevInfo->port_type, pdevInfo->param, value ); if( status == 0 ) return 0; } else { recGblRecordError( S_db_badChoice, (void *)pmbbod, "devMbboDirectBrooks0254 (write_mbbod) unknown parameter number"); return S_db_badChoice; } break; default: recGblRecordError( S_db_badChoice, (void *)pmbbod, "devMbboDirectBrooks0254 (write_mbbod) unknown port type"); return S_db_badChoice; break; } } else { recGblRecordError( S_db_badField, (void *)pmbbod, "devMbboDirectBrooks0254 (write_mbbod) no info on channel" ) ; return S_db_badField; } if( recGblSetSevr( pmbbod, WRITE_ALARM, INVALID_ALARM ) && (pmbbod->stat != WRITE_ALARM || pmbbod->sevr != INVALID_ALARM ) ) recGblRecordError( -1, (void *)pmbbod, "Brooks0254 driver Error" ); return -1; } /************** support for ai record *************************/ /* Create the dset for devAiBrooks0254 */ static long ai_init_record(); static long read_ai(); /* static long brooks_ai_convert(); */ struct { long number; DEVSUPFUN report; DEVSUPFUN init; DEVSUPFUN init_record; DEVSUPFUN get_ioint_info; DEVSUPFUN read_ai; DEVSUPFUN special_linconv; } devAiBrooks0254 = { 6, NULL, NULL, ai_init_record, NULL, read_ai, NULL }; epicsExportAddress( dset, devAiBrooks0254 ); static long ai_init_record( struct aiRecord *pai ) { devInfoBrooks0254* pdevInfo = NULL; pai->dpvt = NULL; int err = common_init_record( (struct dbCommon *) pai, &pdevInfo, "ai" ); if ( err || pdevInfo == NULL ) { recGblRecordError( S_db_noMemory, (void *)pai, "devAiBrooks0254 (ai_init_record) no memory" ); return( S_db_noMemory ); } err = common_get_params( pdevInfo, pai->inp.value.constantStr ); if ( err ) { recGblRecordError( err, (void *)pai, "devAiBrooks0254 (init_record) bad parameters") ; return err; } return 0; } static long read_ai( struct aiRecord *pai ) { int status = 0; double dblVal; devInfoBrooks0254* pdevInfo = (devInfoBrooks0254 *) pai->dpvt; if( pdevInfo != NULL ) { switch ( pdevInfo->port_type ) { /* Data from Input ports */ case ( Input ): if( pdevInfo->param == InFulScale || /* Full scale of the PV */ pdevInfo->param == InGasFactr || /* Gas Factor */ pdevInfo->param == InNonResPV || /* Non-resettable totlizer */ pdevInfo->param == InTotlzrPV || /* Totalizer */ pdevInfo->param == InValuePV ) { /* Actual PV value */ status = brooksGetParDouble( pdevInfo->chassis, pdevInfo->slot_no, pdevInfo->port_type, pdevInfo->param, &dblVal ); if( status == 0 ) { pai->val = dblVal; return 2; /* Prevent transformation in record support */ } } else { recGblRecordError( S_db_badChoice, (void *)pai, "devBiBrooks0254 (read_ai) unknown parameter number"); return S_db_badChoice; } break; /* Data from Output ports */ case ( Output ): if( pdevInfo->param == OutSetRate || /* Flow rate SP */ pdevInfo->param == OutFulScale || /* Full scale of the setpoint */ pdevInfo->param == OutSetBatch || /* Batch set point */ pdevInfo->param == OutSetBlend ) { /* Blend mixing setpoint */ status = brooksGetParDouble( pdevInfo->chassis, pdevInfo->slot_no, pdevInfo->port_type, pdevInfo->param, &dblVal ); if( status == 0 ) { pai->val = dblVal; return 2; /* Prevent transformation in record support */ } } else { recGblRecordError( S_db_badChoice, (void *)pai, "devAiBrooks0254 (read_ai) unknown parameter number"); return S_db_badChoice; } break; default: recGblRecordError( S_db_badChoice, (void *)pai, "devAiBrooks0254 (read_ai) unknown port type"); return S_db_badChoice; break; } } else { recGblRecordError( S_db_badField, (void *)pai, "devAiBrooks0254 (read_ai) no info on channel" ) ; return S_db_badField; } if( recGblSetSevr( pai, READ_ALARM, INVALID_ALARM ) && ( pai->stat != READ_ALARM || pai->sevr != INVALID_ALARM ) ) recGblRecordError( -1, (void *)pai, "Brooks0254 Driver Error" ); return( -1 ); } /* Do the final conversion here ( assume that we already passed */ /* raw-to-analog conversion) using ESLO and EOFF fields */ /* static long brooks_ai_convert( struct aiRecord *pai ) { */ /* double val = pai->val; */ /* switch ( pai->linr ) { */ /* case menuConvertNO_CONVERSION: */ /* break; /\* do nothing*\/ */ /* case menuConvertLINEAR: */ /* case menuConvertSLOPE: */ /* val = ( val * pai->eslo ) + pai->eoff; */ /* break; */ /* } */ /* /\* apply smoothing algorithm *\/ */ /* if ( pai->smoo != 0.0 ) { */ /* if ( pai->init ) pai->val = val; /\* initial condition *\/ */ /* pai->val = val * ( 1.00 - pai->smoo ) + */ /* ( pai->val * pai->smoo ); */ /* } else { */ /* pai->val = val; */ /* } */ /* pai->udf = isnan( pai->val ); */ /* return 0; */ /* } */ /******** support for ao record *********************/ /* Create the dset for devAoBrooks0254 */ static long ao_init_record(); static long write_ao(); static long brooks_ao_convert(); struct { long number; DEVSUPFUN report; DEVSUPFUN init; DEVSUPFUN init_record; DEVSUPFUN get_ioint_info; DEVSUPFUN write_ao; DEVSUPFUN special_linconv; } devAoBrooks0254={ 6, NULL, NULL, ao_init_record, NULL, write_ao, NULL }; epicsExportAddress( dset,devAoBrooks0254 ); /* Device Support Routines for Brooks0254 analog output*/ static long ao_init_record( struct aoRecord *pao ) { devInfoBrooks0254* pdevInfo = NULL; pao->dpvt = NULL; int err = common_init_record( (struct dbCommon *) pao, &pdevInfo, "ao" ); if ( err || pdevInfo == NULL ) { recGblRecordError( S_db_noMemory, (void *)pao, "devAoBrooks0254 (ao_init_record) no memory" ); return( S_db_noMemory ); } err = common_get_params( pdevInfo, pao->out.value.constantStr ); if ( err ) { recGblRecordError( err, (void *)pao, "devAoBrooks0254 (init_record) bad parameters") ; return( err ); } int status; double value; switch ( pdevInfo->port_type ) { case ( Input ): if( pdevInfo->param == InFulScale || /* Full scale of the PV */ pdevInfo->param == InGasFactr ) { /* Gas Factor */ status = brooksGetParDouble( pdevInfo->chassis, pdevInfo->slot_no, pdevInfo->port_type, pdevInfo->param, &value ); if( status == 0 ) pao->val = value ; return 2; } else { recGblRecordError( S_db_badChoice, (void *)pao, "devAoBrooks0254 (init_ao) unknown parameter number"); return S_db_badChoice; } break; case ( Output ): if( pdevInfo->param == OutSetRate || /* Flow rate SP */ pdevInfo->param == OutFulScale || /* Full scale of the setpoint */ pdevInfo->param == OutSetBatch || /* Batch set point */ pdevInfo->param == OutSetBlend ) { /* Blend mixing setpoint */ status = brooksGetParDouble( pdevInfo->chassis, pdevInfo->slot_no, pdevInfo->port_type, pdevInfo->param, &value ); if( status == 0 ) pao->val = value; return 2; } else { recGblRecordError( S_db_badChoice, (void *)pao, "devAoBrooks0254 (init_ao) unknown parameter number"); return S_db_badChoice; } break; default: recGblRecordError( S_db_badChoice, (void *)pao, "devAoBrooks0254 (init_ao) unknown port type"); return S_db_badChoice; break; } return( 0 ); } static long write_ao( struct aoRecord *pao ) { devInfoBrooks0254* pdevInfo = (devInfoBrooks0254 *) pao->dpvt; double value; int status = brooks_ao_convert( pao, &value ); if( pdevInfo != NULL ) { switch ( pdevInfo->port_type ) { case ( Input ): if( pdevInfo->param == InFulScale || /* Full scale of the PV */ pdevInfo->param == InGasFactr ) { /* Gas Factor */ status = brooksSetParDouble( pdevInfo->chassis, pdevInfo->slot_no, pdevInfo->port_type, pdevInfo->param, value ); if( status == 0 ) return 0; } else { recGblRecordError( S_db_badChoice, (void *)pao, "devAoBrooks0254 (write_ao) unknown parameter number"); return S_db_badChoice; } break; case ( Output ): if( pdevInfo->param == OutSetRate || /* Flow rate SP */ pdevInfo->param == OutFulScale || /* Full scale of the setpoint */ pdevInfo->param == OutSetBatch || /* Batch set point */ pdevInfo->param == OutSetBlend ) { /* Blend mixing setpoint */ status = brooksSetParDouble( pdevInfo->chassis, pdevInfo->slot_no, pdevInfo->port_type, pdevInfo->param, value ); if( status == 0 ) return 0; } else { recGblRecordError( S_db_badChoice, (void *)pao, "devAoBrooks0254 (write_ao) unknown parameter number"); return S_db_badChoice; } break; default: recGblRecordError( S_db_badChoice, (void *)pao, "devAoBrooks0254 (write_ao) unknown port type"); return S_db_badChoice; break; } } else { recGblRecordError( S_db_badField, (void *)pao, "devAoBrooks0254 (write_ao) no info on channel" ) ; return S_db_badField; } if( recGblSetSevr( pao, WRITE_ALARM, INVALID_ALARM ) && ( pao->stat != WRITE_ALARM || pao->sevr != INVALID_ALARM ) ) recGblRecordError( -1, (void *)pao, "Brooks0254 driver Error" ); return -1; } /* Do the final conversion here, but assume that we already passed */ /* raw-to-engineering conversion using ESLO and EOFF fields */ static long brooks_ao_convert( struct aoRecord *pao, double* value ) { double tmpVal = pao->val; switch ( pao->linr ) { case menuConvertNO_CONVERSION: break; /* do nothing*/ case menuConvertLINEAR: case menuConvertSLOPE: if( fabs( pao->eslo ) > 1.0e-30 ) { tmpVal = ( tmpVal - pao->eoff ) / pao->eslo; } else { tmpVal = 0.0; } break; } pao->udf = isnan( tmpVal ); (*value) = tmpVal; return 0; } static void devBrooks0254_recDisable ( struct dbCommon *prec ) { printf( "Disabling record at 0x%x \n", (unsigned)prec ); prec->disa = TRUE; prec->disv = TRUE; /* Record disabled when DISA = DISV */ prec->disp = TRUE; /* Also disable putFields to this record*/ prec->stat = DISABLE_ALARM; /* Set the record status to DISABLE */ prec->sevr = INVALID_ALARM; /* Set severity to INVALID */ prec->diss = INVALID_ALARM; /* Also set DISS for completeness */ return; } /*end devBrooks0254_recDisable()*/ /* Function to reserve input information structure of records */ /* and assign the pointer to DPVT field of the record */ static int common_init_record( struct dbCommon *prec, devInfoBrooks0254 **ppdevInfo, char *type) { *ppdevInfo = (devInfoBrooks0254 *) calloc ( 1, sizeof( devInfoBrooks0254 ) + 1 ); prec->dpvt = (long *) (*ppdevInfo); if ( *ppdevInfo == NULL ) { devBrooks0254_recDisable( prec ); return ( ENOMEM ); } else { /* printf("Setting no error for %s\n", prec->name ); */ /* recGblSetSevr( prec, NO_ALARM, NO_ALARM ); */ } return 0; } /* A function to get the parameters (untit number and command) from the input field */ static int common_get_params( devInfoBrooks0254* pdevInfo, const char* str) { /* Get the command and chassis and slot numbers from the string */ int err = brooksInputSet( str ); if( ! err ) { pdevInfo->chassis = brooksInputChassis(); pdevInfo->slot_no = brooksInputCard(); pdevInfo->port_type = brooksInputPortType(); pdevInfo->param = brooksInputParameter(); } else { return( S_db_badField ); } /* printf( "Card is %d , signal is %d , parameter is %d \n ", */ /* pdevInfo->chassis, pdevInfo->slot_no, pdevInfo->command ); */ err = brooksCheckParams( pdevInfo ); return err; } static int brooksCheckParams( devInfoBrooks0254* pdevInfo ) { return OK; } /** * Returns the floor form of binary logarithm for a 128 bit integer. * −1 is returned if ''n'' is 0. */ /* static int floorLog2(unsigned int n) { */ /* if (n == 0) */ /* return -1; */ /* int pos = 0; */ /* if (n >= 1<<16) { n >>= 16; pos += 16; } */ /* if (n >= 1<< 8) { n >>= 8; pos += 8; } */ /* if (n >= 1<< 4) { n >>= 4; pos += 4; } */ /* if (n >= 1<< 2) { n >>= 2; pos += 2; } */ /* if (n >= 1<< 1) { pos += 1; } */ /* return pos; */ /* } */