// // 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_rocbcal16.c -I ../rcm/monitor/ -lpthread -o shmem2epics_rocbcal16.exe // ./shmem2epics_rocbcal16.exe // // #include #include #include #include #include #define debug 0 //-------------------------------------------- #include "shmem_roc.h" static void shmem_get(); static int semid,shmid; static roc_shmem *shmem_ptr; void get_rates (); //-------------------------------------------- static const int NumSlots = 17; static const int StartSlot = 4; static const int EndSlot = 21; static const int NumCounters = 6; static const int NumThreads = 7; static const int modoffset = 12; // Structure for general system command char SystemCallStringArray[7][255]; // global array of strings to store system calls char SystemCallStringArrayLayers[4][2000]; // 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,channel,ichan,epicschan; int layer=1,sector=1; unsigned int update_f_old=0, update_d_old=0; // create a thread for each channel; pthread_t threads[NumThreads]; pthread_t array_threads[3]; int ThreadStatus = 0; while(1) { //--------------------------------------------------------------------------------------------------- // DISCR rates //--------------------------------------------------------------------------------------------------- unsigned int update_d=shmem_ptr->discr_scalers.update; if ( update_d != update_d_old) { // Write the epics arrays // Write the individual layer arrays sprintf(SystemCallStringArrayLayers[1],"caput -a BCAL:disc:scaler:D:S:L1:rate_wf 192 "); sprintf(SystemCallStringArrayLayers[2],"caput -a BCAL:disc:scaler:D:S:L2:rate_wf 192 "); sprintf(SystemCallStringArrayLayers[3],"caput -a BCAL:disc:scaler:D:S:L3:rate_wf 192 "); layer=1; sector=1; // Cope with the South side channels for (slot=1; slot<=12; slot++) { for (channel=0; channel<=3; channel++) { sprintf(SystemCallStringArrayLayers[1],"%s %2i",SystemCallStringArrayLayers[1],0); sprintf(SystemCallStringArrayLayers[2],"%s %2i",SystemCallStringArrayLayers[2],0); sprintf(SystemCallStringArrayLayers[3],"%s %2i",SystemCallStringArrayLayers[3],0); } } for (slot=4; slot<=21; slot++) { for (channel=0; channel<=15; channel++) { if (layer==1){ if (debug) sprintf(SystemCallStringArrayLayers[1],"%s |%2i %2i ",SystemCallStringArrayLayers[1],slot,channel); sprintf(SystemCallStringArrayLayers[1],"%s %2i",SystemCallStringArrayLayers[1],shmem_ptr->discr_scalers.counters[slot][channel]); } if (layer==2) { if (debug) sprintf(SystemCallStringArrayLayers[2],"%s |%2i %2i ",SystemCallStringArrayLayers[2],slot,channel); sprintf(SystemCallStringArrayLayers[2],"%s %2i",SystemCallStringArrayLayers[2],shmem_ptr->discr_scalers.counters[slot][channel]); } if (layer==3) { if (debug) sprintf(SystemCallStringArrayLayers[3],"%s |%2i %2i ",SystemCallStringArrayLayers[3],slot,channel); sprintf(SystemCallStringArrayLayers[3],"%s %2i",SystemCallStringArrayLayers[3],shmem_ptr->discr_scalers.counters[slot][channel]); } sector++; if (sector==5) { layer++; sector = 1; } if (layer==4) layer=1; } } // Cope with the South side channels for (slot=1; slot<=12; slot++) { for (channel=0; channel<=3; channel++) { sprintf(SystemCallStringArrayLayers[1],"%s %2i",SystemCallStringArrayLayers[1],0); sprintf(SystemCallStringArrayLayers[2],"%s %2i",SystemCallStringArrayLayers[2],0); sprintf(SystemCallStringArrayLayers[3],"%s %2i",SystemCallStringArrayLayers[3],0); } } ThreadStatus = pthread_create(&array_threads[0], NULL, SystemCall, (void *) &SystemCallStringArrayLayers[1]); ThreadStatus = pthread_create(&array_threads[1], NULL, SystemCall, (void *) &SystemCallStringArrayLayers[2]); ThreadStatus = pthread_create(&array_threads[2], NULL, SystemCall, (void *) &SystemCallStringArrayLayers[3]); // Wait for threads to complete pthread_join(array_threads[0],NULL); pthread_join(array_threads[1],NULL); pthread_join(array_threads[2],NULL); //--------------------------------------------------------------------------------------------------- update_d_old=update_d; //printf("\n Update: %lu us. , UI=%d TT=%d \n",update_f,sizeof(unsigned int), sizeof(time_t)); } usleep(100); } } //----------------------------------------------------------------------------------- // Shared memory //----------------------------------------------------------------------------------- static void shmem_get() { if ( (semid=semget( SEM_ID1, 1, 0) ) < 0 ) { printf("shmem: can not get semaphore \n"); fflush(stdout); } if ( (shmid=shmget(SHM_ID1,sizeof(roc_shmem), 0))<0) { printf("==> 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); } //----------------------------------------------------------------------------------- // General system command //----------------------------------------------------------------------------------- void *SystemCall( void *argptr) { char *mySystemCallStringArray; mySystemCallStringArray = (char *) argptr; char command[2000]; 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: */