/* * asymRootSub.c * * Created on: October 30, 2025 * Author: Hovanes Egiyan * * */ #include #include #include #include #include #include #include #include #include #include #include "asymRootManager.h" int asymRootDebug = 0; /* * Initialize record to kill IOC */ static long asymRootKillInit( aSubRecord *record ) { if ( asymRootDebug > 1 ) printf( "Record %s called asymRootKillInit(%p)\n", record->name, (void*) record ); return 0; } /* * Process record to kill IOC */ static long asymRootKillProcess( aSubRecord *record ) { if ( asymRootDebug > 1 ) printf( "Record %s called asymRootKillProcess(%p)\n", record->name, (void*) record ); epicsEnum16 killStatReq = *((epicsEnum16*) record->a); if ( asymRootDebug > 1 ) printf( "Kill state is %d\n", killStatReq ); // If the record is set anything from 0, IOC will exit if ( record != NULL && killStatReq != 0 ) { printf( "Aborting IOC per external request!\n" ); abort(); } return 0; } /* * Initialize record to control DAQ */ static long asymRootDAQInit( aSubRecord *record ) { if ( asymRootDebug > 1 ) printf( "Record %s called asymRootDAQInit(%p)\n", record->name, (void*) record ); return 0; } /* * Process record to control DAQ */ static long asymRootDAQProcess( aSubRecord *record ) { if ( asymRootDebug > 1 ) printf( "Record %s called asymRootDAQProcess(%p)\n", record->name, (void*) record ); epicsEnum16 daqStatReq = *((epicsEnum16*) record->a); char* file_dir = (char*) record->b; if ( asymRootDebug > 1 ) printf( "DAQ state is %d, directory is %s \n", daqStatReq, file_dir ); if ( record != NULL && daqStatReq == 0 ) { // StartRootDAQ(file_dir, "ac_", "", ((long*) record->d)[0]); StartRootDAQ( file_dir, "asym_", "", ((long*) record->d)[0] ); if ( asymRootDebug > 0 ) printf( "Start recording ROOT files ...\n" ); } else if ( record != NULL && daqStatReq == 1 ) { CloseRootFile(); if ( asymRootDebug > 0 ) printf( "ROOT file recording stopped\n" ); } return 0; } /* * Initialize records to save ASYM data */ static long asymRootDataInit( aSubRecord *record ) { if ( asymRootDebug > 2 ) printf( "Record %s called asymRootDataInit(%p)\n", record->name, (void*) record ); return 0; } /* * Process records to save ASYM data */ static long asymRootDataProcess( aSubRecord *record ) { unsigned iElm; if ( asymRootDebug > 2 ) printf( "Record %s called asymRootDataProcess(%p)\n", record->name, (void*) record ); // daq_state: 0 = writing, 1 = stopped epicsEnum16 daq_state = *(epicsEnum16*) (record->c); // convert EPICS time to POSIX time struct timespec posixTime = { 0, 0 }; epicsTimeToTimespec( &posixTime, &record->time ); // save previous timestamp, posixTime, and data, vala, valf, valg, valh to file if ( !daq_state && posixTime.tv_sec > 0 ) { if ( GetBufferSize() < 1000 ) { WriteRootFile( record->b, &posixTime, record->vala, record->noa, (short*)record->valf, (float*)record->valg, (float*)record->valh ); } else { printf( "Buffer length exceeds 1000, exiting the program!" ); return 1; } } if ( asymRootDebug > 2 ) { struct tm tsLocal = *localtime( &posixTime.tv_sec ); char timeString[128]; // Reserve string for timestamp strftime( timeString, sizeof(timeString), "%Z %a %Y-%m-%d %H:%M:%S", &tsLocal ); char nsTime[64]; sprintf( nsTime, "%ld", posixTime.tv_nsec ); if ( strcmp( record->b, "mca2" ) == 0 ) { printf( "Channel %s : %s.%s, value: \n", (char*) record->b, timeString, nsTime ); for ( iElm = 0; iElm < record->nea; iElm++ ) { printf( " %ld ", ((long*) record->vala)[iElm] ); } printf( "OK \n\n\n" ); } } // update file name and size const char* file_name = GetFileName(); long file_size = GetFileSize(); strcpy( record->vald, file_name ); ((long*) record->vale)[0] = file_size; // copy updated data to vala memcpy( record->vala, record->a, record->noa * (sizeof(long)) ); // copy updated delay scheme data to valf memcpy( record->valf, record->f, sizeof(short) ); // copy updated sync frequency to valg memcpy( record->valg, record->g, sizeof(float) ); // copy updated stable time to valh memcpy( record->valh, record->h, sizeof(float) ); return 0; } // Register functions for EPICS IOC shell epicsExportAddress( int, asymRootDebug ); epicsRegisterFunction( asymRootKillInit ); epicsRegisterFunction( asymRootKillProcess ); epicsRegisterFunction( asymRootDAQInit ); epicsRegisterFunction( asymRootDAQProcess ); epicsRegisterFunction( asymRootDataInit ); epicsRegisterFunction( asymRootDataProcess );