/* File: drvV1495.h * Author: Hovanes Egiyan, Jefferson Lab * Date: 27-Aug-2012 * * Purpose: * This module provides the driver support for the asyn device support layer * for the Coincidence Reference Design V1495 module. * * Acknowledgements: * This driver module is based on SIS38XX driver by Mark Rivers. * To understand the functions refer to CAEN Technical Manual * Mod. V1495 General Purpose VME Board Revision #13 07/16/12 * */ /*******************/ /* System includes */ /*******************/ // #include // #include // #include // #include /******************/ /* EPICS includes */ /******************/ // #include // #include // #include // #include // #include // #include // #include // #include // #include /*******************/ /* Custom includes */ /*******************/ #include "drvV1495CR.h" static const char *driverName="asynV1495CR"; int dummyInt = vmeOpenDefaultWindows(); /***************/ /* Definitions */ /***************/ /*Constructor */ drvV1495CR::drvV1495CR( const char* portName, char* baseAddr ) : asynPortDriver( portName, 1, NUM_V1495CR_PARAMS, asynUInt32DigitalMask | asynInt32Mask | asynDrvUserMask , asynUInt32DigitalMask | asynInt32Mask , ASYN_CANBLOCK, 1, 0, 0 ), // 0, 1, 0, 0 ), exists_(false), bAddr_(baseAddr) { static const char* functionName="drvV1495CR"; this->eventId_ = epicsEventCreate( epicsEventEmpty ); // Uncomment this line to enable asynTraceFlow during the constructor pasynTrace->setTraceMask(pasynUserSelf, 0x11); createParam( V1495CRGeoAddressString, asynParamUInt32Digital, &V1495CRGeoAddress_ ) ; /* uint32, RO */ createParam( V1495CRResetModuleString, asynParamInt32 , &V1495CRResetModule_ ); /* int32, WO */ createParam( V1495CRFirmwareString, asynParamUInt32Digital, &V1495CRFirmware_ ) ; /* uint32, RO */ createParam( V1495CRScratch16String, asynParamUInt32Digital, &V1495CRScratch16_ ) ; /* uint32, RW */ createParam( V1495CRScratch32String, asynParamUInt32Digital, &V1495CRScratch32_ ) ; /* uint32, RW */ createParam( V1495CRStatusAString, asynParamUInt32Digital, &V1495CRStatusA_) ; /* uint32, RO */ createParam( V1495CRStatusBString, asynParamUInt32Digital, &V1495CRStatusB_) ; /* uint32, RO */ createParam( V1495CRStatusCString, asynParamUInt32Digital, &V1495CRStatusC_) ; /* uint32, RO */ createParam( V1495CRMaskAString, asynParamUInt32Digital, &V1495CRMaskA_) ; /* uint32, RO */ createParam( V1495CRMaskBString, asynParamUInt32Digital, &V1495CRMaskB_) ; /* uint32, RO */ createParam( V1495CRMaskCString, asynParamUInt32Digital, &V1495CRMaskC_) ; /* uint32, RO */ createParam( V1495CRGateWidthString, asynParamUInt32Digital, &V1495CRGateWidth_) ; /* uint32, RW */ createParam( V1495CRControlCString, asynParamUInt32Digital, &V1495CRControlC_) ; /* uint32, RW */ createParam( V1495CRModeString, asynParamUInt32Digital, &V1495CRMode_) ; /* uint32, RW */ createParam( V1495CRScratchString, asynParamUInt32Digital, &V1495CRScratch_) ; /* uint32, RW */ createParam( V1495CRControlGString, asynParamUInt32Digital, &V1495CRControlG_) ; /* uint32, WO */ createParam( V1495CRControlDString, asynParamUInt32Digital, &V1495CRControlD_) ; /* uint32, RW */ createParam( V1495CRDataDString, asynParamUInt32Digital, &V1495CRDataD_) ; /* uint32, RW */ createParam( V1495CRControlEString, asynParamUInt32Digital, &V1495CRControlE_) ; /* uint32, RW */ createParam( V1495CRDataEString, asynParamUInt32Digital, &V1495CRDataE_) ; /* uint32, RW */ createParam( V1495CRControlFString, asynParamUInt32Digital, &V1495CRControlF_) ; /* uint32, RW */ createParam( V1495CRDataFString, asynParamUInt32Digital, &V1495CRDataF_) ; /* uint32, RW */ createParam( V1495CRRevisionString, asynParamUInt32Digital, &V1495CRRevision_) ; /* uint32, RW */ createParam( V1495CRControlPDLString, asynParamUInt32Digital, &V1495CRControlPDL_) ; /* uint32, RW */ createParam( V1495CRDataPDLString, asynParamUInt32Digital, &V1495CRDataPDL_) ; /* uint32, RW */ createParam( V1495CRIDCodeDString, asynParamUInt32Digital, &V1495CRIDCodeD_) ; /* uint32, RO */ createParam( V1495CRIDCodeEString, asynParamUInt32Digital, &V1495CRIDCodeE_) ; /* uint32, RO */ createParam( V1495CRIDCodeFString, asynParamUInt32Digital, &V1495CRIDCodeF_) ; /* uint32, RO */ // This address is not kept since the V1495 driver is taking care of // the conversion from VME to local address. The registration will // only make sure the VME base address is available volatile V1495_REGS* localAddr; int status = 0; #ifdef VXWORKS // Use EPICS utilities to register VME board with a specified address that work with VxWorks // This does not work with our VME Linux driver at this point status = devRegisterAddress( "drvV1495CR", V1495_ADDRESS_TYPE, (unsigned int)bAddr_, V1495_BOARD_SIZE, (volatile void **)&localAddr ); if ( status ) { asynPrint( pasynUserSelf, ASYN_TRACE_ERROR, "%s:%s: %s, Can't register VME address %p\n", driverName, functionName, portName, baseAddr ); return; } asynPrint( pasynUserSelf, ASYN_TRACE_FLOW, "%s:%s: Registered VME address: %p to local address: %p size: 0x%X\n", driverName, functionName, baseAddr, localAddr, V1495_BOARD_SIZE ); #endif /* Create the thread that reads the values from the registers in the background */ status = (asynStatus)(epicsThreadCreate( portName, epicsThreadPriorityMedium, epicsThreadGetStackSize(epicsThreadStackMedium), (EPICSTHREADFUNC)::readRegisters, this ) == NULL); if ( status ) { printf( "%s:%s: epicsThreadCreate failure\n", driverName, functionName ); return; } exists_ = true; return; } asynStatus drvV1495CR::writeUInt32Digital( asynUser* pasynUser, epicsUInt32 value, epicsUInt32 mask ) { int command = pasynUser->reason; char drvStat = 0 ; asynStatus aStat = asynError; static const char* functionName = "writeUInt32Digital"; printf("Now inside %s , command is %d, mask is %d, value is %d \n", functionName, command, mask, value ); if ( !exists_ ) return asynError; // V1495 commands if ( command == V1495CRResetModule_ ) { /* Reset module */ drvStat = v1495_reset_module( bAddr_ ); if( drvStat == v1495_OK ) // aStat = asynSuccess; aStat = setUIntDigitalParam( V1495CRResetModule_, 0, mask ); printf( "aStat in after setUIntDigitalParam is %d \n", aStat ); } else if ( command == V1495CRScratch16_ ) { aStat = setUIntDigitalParam( command, value, mask ); if( aStat == asynSuccess ) { drvStat = v1495_set_scratch16( bAddr_, value & mask ); if( drvStat != v1495CR_OK ) aStat = asynError; } } else if ( command == V1495CRScratch32_ ) { aStat = setUIntDigitalParam( command, value, mask ); if( aStat == asynSuccess ) { drvStat = v1495_set_scratch32( bAddr_, value & mask ); if( drvStat != v1495CR_OK ) aStat = asynError; } } // V1495CR specific commands else if ( command == V1495CRMaskA_ ) { aStat = setUIntDigitalParam( command, value, mask ); if( aStat == asynSuccess ) { drvStat = v1495cr_set_a_mask( bAddr_, value & mask ); if( drvStat != v1495CR_OK ) aStat = asynError; } } else if ( command == V1495CRMaskB_ ) { aStat = setUIntDigitalParam( command, value, mask ); if( aStat == asynSuccess ) { drvStat = v1495cr_set_b_mask( bAddr_, value & mask ); if( drvStat != v1495CR_OK ) aStat = asynError; } } else if ( command == V1495CRMaskC_ ) { aStat = setUIntDigitalParam( command, value, mask ); if( aStat == asynSuccess ) { drvStat = v1495cr_set_c_mask( bAddr_, value & mask ); if( drvStat != v1495CR_OK ) aStat = asynError; } } else if ( command == V1495CRGateWidth_ ) { aStat = setUIntDigitalParam( command, value, mask ); if( aStat == asynSuccess ) { drvStat = v1495cr_set_gate_width( bAddr_, value & mask ); if( drvStat != v1495CR_OK ) aStat = asynError; } } else if ( command == V1495CRControlC_ ) { aStat = setUIntDigitalParam( command, value, mask ); if( aStat == asynSuccess ) { drvStat = v1495cr_set_c_ctrl( bAddr_, value & mask ); if( drvStat != v1495CR_OK ) aStat = asynError; } } else if ( command == V1495CRMode_ ) { aStat = setUIntDigitalParam( command, value, mask ); if( aStat == asynSuccess ) { drvStat = v1495cr_set_mode( bAddr_, value & mask ); if( drvStat != v1495CR_OK ) aStat = asynError; } } else if ( command == V1495CRScratch_ ) { aStat = setUIntDigitalParam( command, value, mask ); if( aStat == asynSuccess ) { drvStat = v1495cr_set_scratch( bAddr_, value & mask ); if( drvStat != v1495CR_OK ) aStat = asynError; } } else if ( command == V1495CRControlG_ ) { aStat = setUIntDigitalParam( command, value, mask ); if( aStat == asynSuccess ) { drvStat = v1495cr_set_g_ctrl( bAddr_, value & mask ); if( drvStat != v1495CR_OK ) aStat = asynError; } } else if ( command == V1495CRControlD_ ) { aStat = setUIntDigitalParam( command, value, mask ); if( aStat == asynSuccess ) { drvStat = v1495cr_set_d_ctrl( bAddr_, value & mask ); if( drvStat != v1495CR_OK ) aStat = asynError; } } else if ( command == V1495CRDataD_ ) { aStat = setUIntDigitalParam( command, value, mask ); if( aStat == asynSuccess ) { drvStat = v1495cr_set_d_data( bAddr_, value & mask ); if( drvStat != v1495CR_OK ) aStat = asynError; } } else if ( command == V1495CRControlE_ ) { aStat = setUIntDigitalParam( command, value, mask ); if( aStat == asynSuccess ) { drvStat = v1495cr_set_e_ctrl( bAddr_, value & mask ); if( drvStat != v1495CR_OK ) aStat = asynError; } } else if ( command == V1495CRDataE_ ) { aStat = setUIntDigitalParam( command, value, mask ); if( aStat == asynSuccess ) { drvStat = v1495cr_set_e_data( bAddr_, value & mask ); if( drvStat != v1495CR_OK ) aStat = asynError; } } else if ( command == V1495CRControlF_ ) { aStat = setUIntDigitalParam( command, value, mask ); if( aStat == asynSuccess ) { drvStat = v1495cr_set_e_ctrl( bAddr_, value & mask ); if( drvStat != v1495CR_OK ) aStat = asynError; } } else if ( command == V1495CRDataF_ ) { aStat = setUIntDigitalParam( command, value, mask ); if( aStat == asynSuccess ) { drvStat = v1495cr_set_f_data( bAddr_, value & mask ); if( drvStat != v1495CR_OK ) aStat = asynError; } } else if ( command == V1495CRRevision_ ) { aStat = setUIntDigitalParam( command, value, mask ); if( aStat == asynSuccess ) { drvStat = v1495cr_set_revision( bAddr_, value & mask ); if( drvStat != v1495CR_OK ) aStat = asynError; } } else if ( command == V1495CRControlPDL_ ) { aStat = setUIntDigitalParam( command, value, mask ); if( aStat == asynSuccess ) { drvStat = v1495cr_set_pdl_ctrl( bAddr_, value & mask ); if( drvStat != v1495CR_OK ) aStat = asynError; } } else if ( command == V1495CRDataPDL_ ) { aStat = setUIntDigitalParam( command, value, mask ); if( aStat == asynSuccess ) { drvStat = v1495cr_set_pdl_data( bAddr_, value & mask ); if( drvStat != v1495CR_OK ) aStat = asynError; } } if( aStat == asynSuccess ) { printf( "Calling callbacks after setting \n "); aStat = callParamCallbacks(); } return aStat; } asynStatus drvV1495CR::writeInt32 ( asynUser *pasynUser, epicsInt32 value ) { int command = pasynUser->reason; char drvStat = 0 ; asynStatus aStat = asynError; static const char* functionName = "writeInt32"; printf("Now inside %s , command is %d, value is %d \n", functionName, command, value ); if ( !exists_ ) return asynError; // V1495 commands if ( command == V1495CRResetModule_ ) { /* Reset module */ drvStat = v1495_reset_module( bAddr_ ); if( drvStat == v1495_OK ) aStat = setIntegerParam( V1495CRResetModule_, 0 ); printf( "aStat in after setIntegerParam is %d \n", aStat ); } if( aStat == asynSuccess ) { printf( "Calling callbacks after setting \n "); aStat = callParamCallbacks(); } return aStat; } /* Report parameters */ void drvV1495CR::report( FILE *fp, int details ) { if ( details > 0 ) { // fprintf(fp, " Scratch Content = 0x%x\n", V1495CRSratch_ ); } // Call the base class method asynPortDriver::report( fp, details ); return; } // This function reads the registers and calls the callbacks // It is supposed to run in a separate thread for each board // Because the registers are read here we do not need to read // in our new readUInt32Digital function, just call the base version in // case the SCAN field is set to some fixed rate scanning. // The values read here will be moved to th appropriate records. void drvV1495CR::readRegisters( void ) { char drvStat = 0; asynStatus aStat = asynError; epicsUInt32 allBits = ~0; // Set updating time to value in seconds double updateTime = 0.5; // while( taskDelay(sysClkRateGet()) ) { while( 1 ) { epicsEventWaitWithTimeout( this->eventId_, updateTime ); // usleep( 100000 ); // if (run) epicsEventWaitWithTimeout(this->eventId, updateTime); // else epicsEventWait(this->eventId); // /* run could have changed while we were waiting */ // getIntegerParam(P_Run, &run); // if (!run) continue; { // Read geo address register epicsUInt16 tmpValue; drvStat = v1495_get_geo_address( bAddr_, &tmpValue ); if( drvStat == 0 ) aStat = setUIntDigitalParam( V1495CRGeoAddress_ , tmpValue, LO16_MASK ); } { // Read firmware register epicsUInt16 tmpValue; drvStat = v1495_get_fw_revision( bAddr_, &tmpValue ); if( drvStat == 0 ) aStat = setUIntDigitalParam( V1495CRFirmware_, tmpValue, LO16_MASK ); } { // Read scratch16 register epicsUInt16 tmpValue; drvStat = v1495_get_scratch16( bAddr_, &tmpValue ); if( drvStat == 0 ) aStat = setUIntDigitalParam( V1495CRScratch16_, tmpValue, LO16_MASK ); } { // Read scratch32 register epicsUInt32 tmpValue; drvStat = v1495_get_scratch32( bAddr_, &tmpValue ); if( drvStat == 0 ) aStat = setUIntDigitalParam( V1495CRScratch32_, tmpValue, allBits ); } { // Read port A status register epicsUInt32 tmpValue; drvStat = v1495cr_get_a_status( bAddr_, &tmpValue ); if( drvStat == 0 ) aStat = setUIntDigitalParam( V1495CRStatusA_, tmpValue, allBits ); } { // Read port B status register epicsUInt32 tmpValue; drvStat = v1495cr_get_b_status( bAddr_, &tmpValue ); if( drvStat == 0 ) aStat = setUIntDigitalParam( V1495CRStatusB_, tmpValue, allBits ); } { // Read port C status register epicsUInt32 tmpValue; drvStat = v1495cr_get_c_status( bAddr_, &tmpValue ); if( drvStat == 0 ) aStat = setUIntDigitalParam( V1495CRStatusC_, tmpValue, allBits ); } { // Read port A mask register epicsUInt32 tmpValue; drvStat = v1495cr_get_a_mask( bAddr_, &tmpValue ); if( drvStat == 0 ) aStat = setUIntDigitalParam( V1495CRStatusA_, tmpValue, allBits ); } { // Read port B mask register epicsUInt32 tmpValue; drvStat = v1495cr_get_b_mask( bAddr_, &tmpValue ); if( drvStat == 0 ) aStat = setUIntDigitalParam( V1495CRStatusB_, tmpValue, allBits ); } { // Read port C mask register epicsUInt32 tmpValue; drvStat = v1495cr_get_c_mask( bAddr_, &tmpValue ); if( drvStat == 0 ) aStat = setUIntDigitalParam( V1495CRStatusC_, tmpValue, allBits ); } { // Read gate width epicsUInt16 tmpValue; drvStat = v1495cr_get_gate_width( bAddr_, &tmpValue ); if( drvStat == 0 ) aStat = setUIntDigitalParam( V1495CRGateWidth_, tmpValue, LO16_MASK ); } { // Read Port C Control register epicsUInt32 tmpValue; drvStat = v1495cr_get_c_ctrl( bAddr_, &tmpValue ); if( drvStat == 0 ) aStat = setUIntDigitalParam( V1495CRControlC_, tmpValue, LO16_MASK ); } { // Read mode register epicsUInt16 tmpValue; drvStat = v1495cr_get_mode( bAddr_, &tmpValue ); if( drvStat == 0 ) aStat = setUIntDigitalParam( V1495CRMode_, tmpValue, LO16_MASK ); } { // Read scratch register epicsUInt16 tmpValue; drvStat = v1495cr_get_scratch( bAddr_, &tmpValue ); if( drvStat == 0 ) aStat = setUIntDigitalParam( V1495CRScratch_, tmpValue, LO16_MASK ); } { // Read Port G Control register epicsUInt16 tmpValue; drvStat = v1495cr_get_g_ctrl( bAddr_, &tmpValue ); if( drvStat == 0 ) aStat = setUIntDigitalParam( V1495CRControlG_, tmpValue, LO16_MASK ); } { // Read Port D Control register epicsUInt32 tmpValue; drvStat = v1495cr_get_d_ctrl( bAddr_, &tmpValue ); if( drvStat == 0 ) aStat = setUIntDigitalParam( V1495CRControlD_, tmpValue, LO16_MASK ); } { // Read Port D data register epicsUInt32 tmpValue; drvStat = v1495cr_get_d_data( bAddr_, &tmpValue ); if( drvStat == 0 ) aStat = setUIntDigitalParam( V1495CRDataD_, tmpValue, allBits ); } { // Read Port E Control register epicsUInt32 tmpValue; drvStat = v1495cr_get_e_ctrl( bAddr_, &tmpValue ); if( drvStat == 0 ) aStat = setUIntDigitalParam( V1495CRControlE_, tmpValue, LO16_MASK ); } { // Read Port E data register epicsUInt32 tmpValue; drvStat = v1495cr_get_e_data( bAddr_, &tmpValue ); if( drvStat == 0 ) aStat = setUIntDigitalParam( V1495CRDataE_, tmpValue, allBits ); } { // Read Port F Control register epicsUInt32 tmpValue; drvStat = v1495cr_get_f_ctrl( bAddr_, &tmpValue ); if( drvStat == 0 ) aStat = setUIntDigitalParam( V1495CRControlF_, tmpValue, LO16_MASK ); } { // Read Port F data register epicsUInt32 tmpValue; drvStat = v1495cr_get_f_data( bAddr_, &tmpValue ); if( drvStat == 0 ) aStat = setUIntDigitalParam( V1495CRDataF_, tmpValue, allBits ); } { // Read Revision register epicsUInt16 tmpValue; drvStat = v1495cr_get_revision( bAddr_, &tmpValue ); if( drvStat == 0 ) aStat = setUIntDigitalParam( V1495CRRevision_, tmpValue, LO16_MASK ); } { // Read PDL Control register epicsUInt16 tmpValue; drvStat = v1495cr_get_pdl_ctrl( bAddr_, &tmpValue ); if( drvStat == 0 ) aStat = setUIntDigitalParam( V1495CRControlPDL_, tmpValue, LO16_MASK ); } { // Read PDL Data register epicsUInt16 tmpValue; drvStat = v1495cr_get_pdl_data( bAddr_, &tmpValue ); if( drvStat == 0 ) aStat = setUIntDigitalParam( V1495CRDataPDL_, tmpValue, LO16_MASK ); } { // Read Port D ID Code register epicsUInt16 tmpValue; drvStat = v1495cr_get_d_idcode( bAddr_, &tmpValue ); if( drvStat == 0 ) aStat = setUIntDigitalParam( V1495CRIDCodeD_, tmpValue, LO16_MASK ); } { // Read Port E ID Code register epicsUInt16 tmpValue; drvStat = v1495cr_get_e_idcode( bAddr_, &tmpValue ); if( drvStat == 0 ) aStat = setUIntDigitalParam( V1495CRIDCodeE_, tmpValue, LO16_MASK ); } { // Read Port F ID Code register epicsUInt16 tmpValue; drvStat = v1495cr_get_f_idcode( bAddr_, &tmpValue ); if( drvStat == 0 ) aStat = setUIntDigitalParam( V1495CRIDCodeF_, tmpValue, LO16_MASK ); } // printf( "Calling callbacks \n"); callParamCallbacks(); } } void readRegisters( void *drvPvt ) { drvV1495CR* pPvt = (drvV1495CR *)drvPvt; pPvt->readRegisters(); } extern "C" { char* drvV1495CRConfig( const char *portName, int baseAddr ) { drvV1495CR* pV1495CR = new drvV1495CR( portName, (char*)baseAddr ); return reinterpret_cast( pV1495CR ); } epicsUInt16 drvV1495CRGetScratch( int baseAddress ) { epicsUInt16 scratchValue; v1495cr_get_scratch( (char*)baseAddress, &scratchValue ); printf( "Scratch value is 0x%x \n", scratchValue ); return scratchValue; } epicsUInt16 drvV1495CRSetScratch( int baseAddress, epicsUInt16 val ) { v1495cr_set_scratch( (char*)baseAddress, val ); return val; } /* iocsh config function */ static const iocshArg drvV1495CRConfigArg0 = { "Asyn port name", iocshArgString}; static const iocshArg drvV1495CRConfigArg1 = { "Base address", iocshArgInt}; static const iocshArg * const drvV1495CRConfigArgs[] = { &drvV1495CRConfigArg0, &drvV1495CRConfigArg1 }; static const iocshFuncDef drvV1495CRConfigFuncDef = {"drvV1495CRConfig", 2, drvV1495CRConfigArgs}; static void drvV1495CRConfigCallFunc(const iocshArgBuf *args) { drvV1495CRConfig( args[0].sval, args[1].ival ); } // iocsh SetScratch and GetScratch functions static const iocshArg drvV1495CRScratchArg0 = { "Base adrress ", iocshArgInt}; static const iocshArg drvV1495CRScratchArg1 = { "Value ", iocshArgInt}; static const iocshArg * const drvV1495CRScratchArgs[] = { &drvV1495CRScratchArg0, &drvV1495CRScratchArg1, }; static const iocshFuncDef drvV1495CRSetScratchFuncDef = {"drvV1495CRSetScratch", 2, drvV1495CRScratchArgs}; static const iocshFuncDef drvV1495CRGetScratchFuncDef = {"drvV1495CRGetScratch", 1, drvV1495CRScratchArgs}; static void drvV1495CRSetScratchCallFunc( const iocshArgBuf *args) { drvV1495CRSetScratch( args[0].ival, args[1].ival ); } static void drvV1495CRGetScratchCallFunc( const iocshArgBuf *args) { drvV1495CRGetScratch( args[0].ival ); } void drvV1495CRRegister(void) { iocshRegister( &drvV1495CRConfigFuncDef,drvV1495CRConfigCallFunc ); iocshRegister( &drvV1495CRSetScratchFuncDef,drvV1495CRSetScratchCallFunc ); iocshRegister( &drvV1495CRGetScratchFuncDef,drvV1495CRGetScratchCallFunc ); } epicsExportRegistrar( drvV1495CRRegister ); } // extern "C"