/* * acrootSub.c * * Created on: Mar 25, 2014 * Author: yqiang * * Modified on: * Nov 19, 2014: added beam current and gain, yqiang * */ #include #include #include #include #include #include #include #include #include #include #include "acrootManager.h" int acrootDebug; /* * Initialize record to kill IOC */ static long acrootKillInit(aSubRecord *record) { if (acrootDebug > 1) printf("Record %s called acrootKillInit(%p)\n", record->name, (void*) record); return 0; } /* * Process record to kill IOC */ static long acrootKillProcess(aSubRecord *record) { if (acrootDebug > 1) printf("Record %s called acrootKillProcess(%p)\n", record->name, (void*) record); epicsEnum16 killStatReq = *((epicsEnum16*) record->a); if (acrootDebug > 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 acrootDAQInit(aSubRecord *record) { if (acrootDebug > 1) printf("Record %s called acrootDAQInit(%p)\n", record->name, (void*) record); return 0; } /* * Process record to control DAQ */ static long acrootDAQProcess(aSubRecord *record) { if (acrootDebug > 1) printf("Record %s called acrootDAQProcess(%p)\n", record->name, (void*) record); epicsEnum16 daqStatReq = *((epicsEnum16*) record->a); char* file_dir = (char*) record->b; if (acrootDebug > 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, "ac_", "", ((long*) record->d)[0]); if (acrootDebug > 0) printf("Start recording ROOT files ...\n"); } else if (record != NULL && daqStatReq == 1) { CloseRootFile(); if (acrootDebug > 0) printf("ROOT file recording stopped\n"); } return 0; } /* * Initialize records to save AC data */ static long acrootDataInit(aSubRecord *record) { if (acrootDebug > 2) printf("Record %s called acrootDataInit(%p)\n", record->name, (void*) record); return 0; } /* * Process records to save AC data */ static long acrootDataProcess(aSubRecord *record) { if (acrootDebug > 2) printf("Record %s called acrootDataProcess(%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 to file if (!daq_state && posixTime.tv_sec > 0) { if (GetBufferSize() < 1000) { WriteRootFile(record->b, &posixTime, record->vala, record->noa, record->valf, record->valg); } else { printf("Buffer length exceeds 1000, exiting the program!"); return 1; } } if (acrootDebug > 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, "N9:raw_XP") == 0) printf("%s : %s.%s, value: %8.5f, current: %8.5f, gain: %d\n", (char*) record->b, timeString, nsTime, ((float*) record->vala)[0], ((float*) record->valf)[0], ((short*) record->valg)[0]); } // 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(float))); // copy updated beam current data to valf memcpy(record->valf, record->f, sizeof(float)); // copy updated gain to valg memcpy(record->valg, record->g, sizeof(short)); return 0; } // Register functions for EPICS IOC shell epicsExportAddress(int, acrootDebug); epicsRegisterFunction(acrootKillInit); epicsRegisterFunction(acrootKillProcess); epicsRegisterFunction(acrootDAQInit); epicsRegisterFunction(acrootDAQProcess); epicsRegisterFunction(acrootDataInit); epicsRegisterFunction(acrootDataProcess);