#include "pulser.h" #define PULSER_ALL_BITS_32 (0xFFFFFFFF) #define PULSER_ALL_BITS_16 (0x0000FFFF) /* Mutex to guard flexio read/writes */ pthread_mutex_t pulserMutex = PTHREAD_MUTEX_INITIALIZER; #define PULSER_LOCK if( pthread_mutex_lock ( &pulserMutex )<0 ) perror( "pthread_mutex_lock" ); #define PULSER_UNLOCK if( pthread_mutex_unlock( &pulserMutex )<0 ) perror( "pthread_mutex_unlock" ); /* In the functions below base address is the VME base address of the board */ /* not the local address. The driver takes care of determining the address */ /* for the VME controller */ /* Macro to define the read-functions for uint32 parameters based on their symbolic name in the * pulser_REGS structure. The first parameter should be exactly * the element name of the structure to be accessed, the second parameter is there just * to make the token-pasting macro substitutions work. * If the pointer to the value variable is 0 then returns the number of elements, which is 1 for scalar */ #define PULSER_READ_PAR_UINT(name,mask,end) \ int16_t pulser_get##name( char* baseAddr, uint32_t* val ) { \ if( val == 0 ) return 1 ; \ pulser_REGS* pulser_regs; \ if ( pulser_getRegs( baseAddr, &pulser_regs ) == pulser_OK ) { \ PULSER_LOCK; \ *val = v1495_read_reg32( &( pulser_regs->name##end ) ); \ *val &= mask##end ; \ PULSER_UNLOCK; \ return pulser_OK; \ } \ return pulser_ERROR; \ } #define PULSER_READ_PAR_UINT_CHAN(name,mask,end) \ int16_t pulser_get##name( char* baseAddr, unsigned chan, uint32_t* val ) { \ if( val == 0 ) return 1 ; \ pulser_REGS* pulser_regs; \ if ( pulser_getRegs( baseAddr, &pulser_regs ) == pulser_OK ) { \ PULSER_LOCK; \ *val = v1495_read_reg32( &( pulser_regs->Pulsers[chan].name##end ) ); \ *val &= mask##end ; \ PULSER_UNLOCK; \ return pulser_OK; \ } \ return pulser_ERROR; \ } /* Macro to define the write-functions for uint32 parameters based on their symbolic name in the * pulser_REGS structure. The first parameter should be exactly * the element name of the structure to be accessed, the second parameter is there just * to make the token-pasting macro substitutions work. */ #define PULSER_WRITE_PAR_UINT(name,mask,end) \ int16_t pulser_set##name( char* baseAddr, uint32_t val ) { \ pulser_REGS* pulser_regs; \ if ( pulser_getRegs( baseAddr, &pulser_regs) == pulser_OK ) { \ printf("Writing 0x%x into parameter " #name " \n", val ); \ PULSER_LOCK; \ v1495_write_reg32( &(pulser_regs->name##end ), val & mask##end ); \ uint32_t readVal = v1495_read_reg32( &( pulser_regs->name##end ) ); \ printf("Checked that wrote 0x%x into parameter " #name " \n", readVal ); \ PULSER_UNLOCK; \ return pulser_OK; \ } \ return pulser_ERROR; \ } #define PULSER_WRITE_PAR_UINT_CHAN(name,mask,end) \ int16_t pulser_set##name( char* baseAddr, unsigned chan, uint32_t val ) { \ pulser_REGS* pulser_regs; \ if ( pulser_getRegs( baseAddr, &pulser_regs) == pulser_OK ) { \ printf("Writing 0x%x into parameter " #name " \n", val ); \ PULSER_LOCK; \ v1495_write_reg32( &(pulser_regs->Pulsers[chan].name##end ), val & mask##end ); \ uint32_t readVal = v1495_read_reg32( &( pulser_regs->Pulsers[chan].name##end ) ); \ printf("Checked that wrote 0x%x into parameter " #name " \n", readVal ); \ PULSER_UNLOCK; \ return pulser_OK; \ } \ return pulser_ERROR; \ } /* * Below we define the functions to access registers using the * macros defined above defined above. They do not do anything fancy, * simply read or write to 32 bit registers using unsigned int. */ /* Read function definitions with macros */ PULSER_READ_PAR_UINT(PulserId,PULSER_ALL_BITS_32,) PULSER_READ_PAR_UINT(FirmwareRev,PULSER_ALL_BITS_32,) PULSER_READ_PAR_UINT(DaughterBoardId,PULSER_ALL_BITS_32,) PULSER_READ_PAR_UINT(Jumpers,PULSER_ALL_BITS_32,) PULSER_READ_PAR_UINT(PulserStatusH,PULSER_ALL_BITS_32,) PULSER_READ_PAR_UINT(PulserStatusL,PULSER_ALL_BITS_32,) PULSER_READ_PAR_UINT(PulserStartMaskH,PULSER_ALL_BITS_32,) PULSER_READ_PAR_UINT(PulserStartMaskL,PULSER_ALL_BITS_32,) PULSER_READ_PAR_UINT(PulserStopMaskH,PULSER_ALL_BITS_32,) PULSER_READ_PAR_UINT(PulserStopMaskL,PULSER_ALL_BITS_32,) PULSER_READ_PAR_UINT(PulserGinMaskH,PULSER_ALL_BITS_32,) PULSER_READ_PAR_UINT(PulserGinMaskL,PULSER_ALL_BITS_32,) PULSER_READ_PAR_UINT(PulserStartStop,PULSER_ALL_BITS_32,) PULSER_READ_PAR_UINT(MasterOrDelay,PULSER_ALL_BITS_32,) PULSER_READ_PAR_UINT(MasterOrWidth,PULSER_ALL_BITS_32,) /* Write function definition with macros */ PULSER_WRITE_PAR_UINT(PulserStartMaskH,PULSER_ALL_BITS_32,) PULSER_WRITE_PAR_UINT(PulserStartMaskL,PULSER_ALL_BITS_32,) PULSER_WRITE_PAR_UINT(PulserStopMaskH,PULSER_ALL_BITS_32,) PULSER_WRITE_PAR_UINT(PulserStopMaskL,PULSER_ALL_BITS_32,) PULSER_WRITE_PAR_UINT(PulserGinMaskH,PULSER_ALL_BITS_32,) PULSER_WRITE_PAR_UINT(PulserGinMaskL,PULSER_ALL_BITS_32,) PULSER_WRITE_PAR_UINT(PulserStartStop,PULSER_ALL_BITS_32,) PULSER_WRITE_PAR_UINT(MasterOrDelay,PULSER_ALL_BITS_32,) PULSER_WRITE_PAR_UINT(MasterOrWidth,PULSER_ALL_BITS_32,) PULSER_READ_PAR_UINT_CHAN(Period,PULSER_ALL_BITS_32,) PULSER_READ_PAR_UINT_CHAN(Width,PULSER_ALL_BITS_32,) PULSER_READ_PAR_UINT_CHAN(NPulses,PULSER_ALL_BITS_32,) PULSER_WRITE_PAR_UINT_CHAN(Period,PULSER_ALL_BITS_32,) PULSER_WRITE_PAR_UINT_CHAN(Width,PULSER_ALL_BITS_32,) PULSER_WRITE_PAR_UINT_CHAN(NPulses,PULSER_ALL_BITS_32,) /* Return the address registers for pulser design after picking it out */ /* of the structure for all of the V1495 registers */ epicsInt16 pulser_getRegs( char* baseAddr, pulser_REGS** regs ) { V1495_REGS* v1495_regs; if( v1495_get_regs( baseAddr, &v1495_regs ) == v1495_OK ) { /* Overlay the CR register structure over FPGA ACCESS REGISTERS */ *regs = (pulser_REGS*)v1495_regs->user_fpga_acc; /* printf( "Registers are at 0x%x\n", *regs ); */ return pulser_OK; } return pulser_ERROR; }