// // 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_rocstpsc2.c -I ../rcm/monitor/ -lpthread -o shmem2epics_rocstpsc2.exe // ./shmem2epics_rocstpsc2.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 = 3; static const int StartSlot = 4; static const int EndSlot = 6; static const int NumChannels = 16; // Structure for epics data struct EpicsEvent{ char channelname[40]; int channelval; }; struct EpicsEvent EpicsEventArray[3][17]; // global aray of epics data void *CaputToEpics( void *argptr); // program to write epics data (run in a thread) // Structure for general system command char SystemCallStringSTchannels[30][255]; char SystemCallStringPSCchannels[16][255]; char SystemCallStringArray[2][255]; // global array of strings to store system calls void *SystemCall( void *argptr); // program to preform a system call (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]; pthread_t array_threads[2]; while(1) { //--------------------------------------------------------------------------------------------------- // DISCR rates //--------------------------------------------------------------------------------------------------- unsigned int update_d=shmem_ptr->discr_scalers.update; if ( update_d != update_d_old) { //---- char epicsname[255], epicsnamestem[255]; int ThreadStatus; for(slot=StartSlot; slot<=EndSlot; slot++) { if (shmem_ptr->discr_scalers.counters[slot][16]==0) continue; if (slot==4) { sprintf(epicsnamestem,"ST:disc:scaler"); int slotindex = slot-StartSlot; for(ichan=0; ichan<16; ichan++) { sprintf(epicsname,"%s:%i",epicsnamestem,ichan+1); // Write data to global memery so that threads can use it sprintf(EpicsEventArray[slotindex][ichan].channelname,"%s",epicsname); EpicsEventArray[slotindex][ichan].channelval = shmem_ptr->discr_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); } } } if (slot==5) { sprintf(epicsnamestem,"ST:disc:scaler"); int slotindex = slot-StartSlot; for(ichan=0; ichan<14; ichan++) { sprintf(epicsname,"%s:%i",epicsnamestem,ichan+17); // Write data to global memery so that threads can use it sprintf(EpicsEventArray[slotindex][ichan].channelname,"%s",epicsname); EpicsEventArray[slotindex][ichan].channelval = shmem_ptr->discr_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); } } } if (slot==6) { sprintf(epicsnamestem,"PSC:disc:scaler"); int slotindex = slot-StartSlot; for(ichan=0; ichan<16; ichan++) { sprintf(epicsname,"%s:%i",epicsnamestem,ichan+1); // Write data to global memery so that threads can use it sprintf(EpicsEventArray[slotindex][ichan].channelname,"%s",epicsname); EpicsEventArray[slotindex][ichan].channelval = shmem_ptr->discr_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); } } } } // Write the waveforms (epics arrays) out sprintf(epicsname,"ST:disc:scaler:rate_wf"); sprintf(SystemCallStringArray[0],"caput -a %s 30 ",epicsname); int counter; for (counter = 0; counter <16; counter++) { sprintf(SystemCallStringArray[0],"%s %i",SystemCallStringArray[0],EpicsEventArray[0][counter].channelval); //sprintf(SystemCallStringArray[0],"%s %i",SystemCallStringArray[0],shmem_ptr->discr_scalers.rates[4][counter]); } for (counter = 0; counter <14; counter++) { sprintf(SystemCallStringArray[0],"%s %i",SystemCallStringArray[0],EpicsEventArray[1][counter].channelval); //sprintf(SystemCallStringArray[0],"%s %i",SystemCallStringArray[0],shmem_ptr->discr_scalers.rates[5][counter]); } //printf("%s\n",SystemCallStringArray[0]); ThreadStatus = pthread_create(&array_threads[0], NULL, SystemCall, (void *) &SystemCallStringArray[0]); sprintf(epicsname,"PSC:disc:scaler:rate_wf"); sprintf(SystemCallStringArray[1],"caput -a %s 16",epicsname); for (counter = 0; counter <16; counter++) { sprintf(SystemCallStringArray[1],"%s %i",SystemCallStringArray[1],EpicsEventArray[2][counter].channelval); //sprintf(SystemCallStringArray[1],"%s %i",SystemCallStringArray[1],shmem_ptr->discr_scalers.rates[6][counter]); } //printf("%s\n",SystemCallStringArray[1]); ThreadStatus = pthread_create(&array_threads[1], NULL, SystemCall, (void *) &SystemCallStringArray[1]); // 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); } //----------------------------------------------------------------------------------- // General system command //----------------------------------------------------------------------------------- void *SystemCall( void *argptr) { char *mySystemCallStringArray; mySystemCallStringArray = (char *) argptr; char command[255]; sprintf(command,"%s",mySystemCallStringArray); //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: */