// // Mark Dalton October 2014 // // This program reads the scaler rates from the shared memory buffer, processes them in a way which is // detector system dependent and then publishes them to epics using a system call to caput. Each caput // call is run in a separate thread in order to minimze the impact of latency. The values are published // individually, summed in particular ways or writen to a waveform (array). Since his is particulr to // each detector, no attempt was made to make a general code and thus each roc runs a different executable. // The implementation is "quick and dirty" and is expected to be superseded by a more sophisticated // procedure in the future. // // Compile and run with the following: // // gcc shmem2epics_iocpulser2.c -I ../rcm/monitor/ -lpthread -o shmem2epics_iocpulser2.exe // ./shmem2epics_iocpulser2.exe // // #include #include #include #include #include //-------------------------------------------- #include "shmem_roc.h" static void shmem_get(); static int semid,shmid; static roc_shmem *shmem_ptr; void get_rates (); //-------------------------------------------- static const int NumSlots = 1; static const int StartSlot = 5; static const int EndSlot = 5; static const int NumChannels = 16; // Structure for epics data struct EpicsEvent{ char channelname[40]; int channelval; }; struct EpicsEvent EpicsEventArray[1][17]; // global aray of epics data void *CaputToEpics( void *argptr); // program to write epics data (run in a thread) //-------------------------------------------- int main() { shmem_get(); get_rates(); pthread_exit(NULL); } //----------------------------------------------------------------------------------- // get rates //----------------------------------------------------------------------------------- void get_rates () { int slot,ichan; unsigned int update_f_old=0, update_d_old=0; // create a thread for each channel; pthread_t threads[NumSlots][NumChannels]; while(1) { //--------------------------------------------------------------------------------------------------- // DISCR rates //--------------------------------------------------------------------------------------------------- unsigned int update_d=shmem_ptr->discr_scalers.update; if ( update_d != update_d_old) { //---- for(slot=StartSlot; slot<=EndSlot; slot++) { if (shmem_ptr->discr_scalers.counters[slot][16]==0) continue; // printf(" Fill slot=%d \n",slot); // for(ichan=0; ichan<16; ichan++) { // if( (ichan%4) == 0 ) printf("\n"); // printf("| %2d: %10.3f Hz ",ichan,shmem_ptr->discr_scalers.rates[slot][ichan]); // } printf("\n timer: %.3f sec. \n",shmem_ptr->discr_scalers.rates[slot][16]); // for(ichan=0; ichan<16; ichan++) { // if( (ichan%4) == 0 ) printf("\n"); // printf("| %2d: %08d ",ichan,shmem_ptr->discr_scalers.counters[slot][ichan]); // } printf("\n time: %lu us. \n",shmem_ptr->discr_scalers.counters[slot][16]); int ThreadStatus; char epicsname[255], epicsnamestem[255]; if (slot==5) sprintf(epicsnamestem,"pulser2:5"); for(ichan=0; ichandiscr_scalers.rates[slot][ichan]; // create a thread for each channel ThreadStatus = pthread_create(&threads[slotindex][ichan], NULL, CaputToEpics, (void *) &EpicsEventArray[slotindex][ichan]); if ( ThreadStatus !=0 ) { printf("Thread status %i\n",ThreadStatus); } } } // Wait for threads to complete for(slot=StartSlot; slot<=EndSlot; slot++) { int slotindex = slot-StartSlot; for(ichan=0; ichan shmem: shared memory 0x%x, size=%d get error=%d\n",SHM_ID1,sizeof(roc_shmem),shmid); fflush(stdout); exit(1); } if ( (shmem_ptr=(roc_shmem *) shmat (shmid, 0, 0))<0 ) { printf("==> shmem: shared memory attach error\n"); fflush(stdout); } printf("==> shmem: shared memory attached OK ptr=%p\n",shmem_ptr); fflush(stdout); //printf("===== wait semaphore ====== \n"); //fflush(stdout); //-- access to shmem -- //sem_wait(semid); // if (shmem_ptr) shmem_ptr->rol2_hist=1; //sem_post(semid); } //----------------------------------------------------------------------------------- // Write to epics with caput //----------------------------------------------------------------------------------- void *CaputToEpics( void *argptr) { struct EpicsEvent *myEpicsEvent; myEpicsEvent = (struct EpicsEvent *) argptr; char *channelname = myEpicsEvent->channelname; int channelval = myEpicsEvent->channelval; char command[255]; sprintf(command,"caput %s %i",channelname,channelval); //printf("%s\n",command); system(command); pthread_exit(NULL); } //----------------------------------------------------------------------------------- /* emacs * Local Variables: * mode:C++ * mode:font-lock * c-file-style: "stroustrup" * tab-width: 4 * End: */