Changeset 10913 for fact/FADctrl
- Timestamp:
- 06/06/11 14:35:10 (13 years ago)
- Location:
- fact/FADctrl
- Files:
-
- 2 edited
Legend:
- Unmodified
- Added
- Removed
-
fact/FADctrl/FAD.cc
r10813 r10913 30 30 {"reset", &FAD::cmd_reset, true, 0, "", "Reset internal trigger counter"}, 31 31 {"runnumber", &FAD::cmd_runnumber, true, 1, "<n>", "Set runnumber"}, 32 {"roi", &FAD::cmd_roi, true, 2, "< channel range> <value>", "Set region-of-interestto value"},32 {"roi", &FAD::cmd_roi, true, 2, "<range> <value>", "Set ROI to for channel range to value"}, 33 33 {"dac", &FAD::cmd_dac, true, 2, "<range> <value>", "Set DAC numbers in range to value"}, 34 34 {"address", &FAD::cmd_address, true, 2, "<range> <value>", "Set addresses in range to value"}, 35 35 {"send", &FAD::cmd_send, true, 1, "<value>", "Send arbitrary data to board"}, 36 {"take", &FAD::cmd_take, true, 1, "<n> <dir>", "Start run with n events , write to directory"},37 {"acalib", &FAD::cmd_acalib, true, 0, "[n|inval idate|file]", "Perform or read amplitude calibration (n events)"},36 {"take", &FAD::cmd_take, true, 1, "<n> <dir>", "Start run with n events (n=0 -> unlimited)"}, 37 {"acalib", &FAD::cmd_acalib, true, 0, "[n|inval|file]", "Perform or read amplitude calibration (n events)"}, 38 38 //{"wmode", &FAD::cmd_wmode, 0, "<run|stop>", "Domino wave running or stopped during read out"}, 39 39 //{"rmode", &FAD::cmd_rmode, 0, "<first|stop>", "Readout start at first bin or stop position (DRS4)"}, … … 827 827 void FAD::EventThread() { 828 828 829 struct timeval Time , RunStart;829 struct timeval Time; 830 830 struct timeval LastUpdate; 831 831 struct FADBoard::BoardStatus S; 832 832 vector<unsigned long> EventNumbers(Boards.size()); 833 833 vector<bool> AcalibDone(Boards.size()); 834 map<unsigned int, class FADBoard *> ActiveBoards; 834 835 double Temp; 835 836 string IDString; 836 837 char Buffer[100]; 837 838 int Ret; 838 unsigned long long FileSize = 0; 839 struct stat FileStat; 840 float FileSizeMB = 0; 841 RunHeader FileRHeader; 839 842 840 843 gettimeofday(&LastUpdate, NULL); 841 RunStart = LastUpdate; // only to avoid 'uninitialized' warning from compiler842 844 843 845 // Create DIM event data and number services 844 int EventSize = sizeof(RunHeader)+ Boards.size()*sizeof(BoardStructure)+sizeof(EventHeader) + Boards.size()*(NChips*NChannels*NBins*sizeof(short) + NChips*sizeof(int)); 845 char *EventData = new char [EventSize]; 846 847 memset(EventData, 0, EventSize); 846 char *EventData = new char [sizeof(RunHeader)+ Boards.size()*sizeof(BoardStructure)+sizeof(EventHeader) + Boards.size()*(NChips*NChannels*NBins*sizeof(short) + NChips*sizeof(int))]; 848 847 849 848 DimService EventService(SERVER_NAME"/EventData", (char *) "C", NULL, 0); 850 849 DimService EventNumService(SERVER_NAME"/EventNumber", NumEvents); 851 852 // Calculate pointers to EventData array 850 DimService FileSizeService(SERVER_NAME"/FileSizeMB", FileSizeMB); 851 852 // Calculate pointers to EventData array (will be updated when active number of boards changes) 853 853 RunHeader *RHeader = (RunHeader *) EventData; 854 854 BoardStructure **BStruct = new BoardStructure * [Boards.size()]; 855 855 856 for (unsigned int i=0; i<Boards.size(); i++) BStruct[i] = ((BoardStructure *) (RHeader + 1)) + i; 856 857 EventHeader *EHeader = (EventHeader *) ((char *) (RHeader + 1) + Boards.size()*sizeof(BoardStructure)); … … 858 859 short *Data = (short *) (TriggerCell + NChips*Boards.size()); 859 860 860 // M0 RunHeader 861 // Fill fixed entries in M0 RunHeader 862 RHeader->MagicNum = MAGICNUM_CLOSED; 861 863 RHeader->DataFormat = DATA_FORMAT; 862 864 RHeader->RunHeaderSize = sizeof(RunHeader); … … 865 867 RHeader->SoftwareRevision = atoi(REVISION) * (strchr(REVISION, 'M')==NULL ? 1:-1); 866 868 RHeader->Identification = 0; 867 868 869 RHeader->Type = 0; // Run type: 0=data, 1=pedestal, 3=test 869 870 870 RHeader->RunNumber = -1; 871 871 RHeader->FileNumber = 0; 872 872 snprintf(RHeader->Description, sizeof(RHeader->Description), "FADctrl"); 873 874 RHeader->NBoards = Boards.size(); 873 RHeader->Events = 1; 874 RHeader->StartSecond = LastUpdate.tv_sec; 875 RHeader->StartMicrosecond = LastUpdate.tv_usec; 875 876 RHeader->NChips = NChips; 876 877 RHeader->NChannels = NChannels; … … 879 880 RHeader->NBytes = sizeof(short); 880 881 881 // M0 EventHeader882 EHeader->EventSize = Boards.size()*(NChips*NChannels*NBins*sizeof(short) + NChips*sizeof(int));883 884 882 // Update loop 885 883 while (!ExitRequest) { … … 896 894 IDString.append(string(Buffer, Ret)); 897 895 898 // If amplitude calibration mode, check if board finished procedure 896 // Active boards for DIM and data taking must only change when idle 897 if (Mode == idle) { 898 ActiveBoards.clear(); 899 for (unsigned int i=0; i<Boards.size(); i++) if (Boards[i]->Active) ActiveBoards[i] = Boards[i]; 900 RHeader->NBoards = ActiveBoards.size(); 901 902 // Calculate updated pointers to EventData array 903 for (unsigned int i=0; i<ActiveBoards.size(); i++) BStruct[i] = ((BoardStructure *) (RHeader + 1)) + i; 904 EHeader = (EventHeader *) ((char *) (RHeader + 1) + ActiveBoards.size()*sizeof(BoardStructure)); 905 TriggerCell = (int *) (EHeader + 1); 906 Data = (short *) (TriggerCell + NChips*ActiveBoards.size()); 907 } 908 909 // If amplitude calibration mode, check if all boards finished procedure 899 910 if (Mode == acalib) { 900 911 bool Done = true; … … 912 923 else for (unsigned int i=0; i<Boards.size(); i++) AcalibDone[i] = false; 913 924 914 // Update run and event header with current time925 // Update run and event header 915 926 gettimeofday(&Time, NULL); 916 917 RHeader->MagicNum = MAGICNUM_CLOSED;918 927 RHeader->EndSecond = Time.tv_sec; 919 928 RHeader->EndMicrosecond = Time.tv_usec; 920 929 930 EHeader->EventSize = RHeader->NBoards * (NChips*NChannels*NBins*sizeof(short) + NChips*sizeof(int)); 921 931 EHeader->Second = Time.tv_sec; 922 932 EHeader->Microsecond = Time.tv_usec; 923 933 924 // Close data file if requested or requested number of events reached925 if((IDString.find("stop")!=string::npos || NumEvents==NumEventsRequested) && Mode==datarun) {926 927 // Update run header928 RHeader->Events = NumEvents;929 RHeader->StartSecond = RunStart.tv_sec;930 RHeader->StartMicrosecond = RunStart.tv_usec;931 932 if (lseek(Datafile, 0, SEEK_SET) == -1) {933 Message(ERROR, "Could not rewind file to write updated run header (%s)", strerror(errno));934 }935 else if (write(Datafile, RHeader, sizeof(RunHeader)) != sizeof(RunHeader)) {936 Message(ERROR, "Could not write updated run header (%s)", strerror(errno));937 }938 939 // Close data file and terminate run940 if(close(Datafile) == -1) Message(ERROR, "Could not close data file (%s)", strerror(errno));941 else PrintMessage("Data file closed (size %.1f MByte).\n", FileSize/1024.0/1024);942 943 Datafile = -1;944 Mode = idle;945 Message(INFO, "Data run ended, mode set to IDLE");946 }947 948 // These values might have changed while close file949 RHeader->StartSecond = Time.tv_sec;950 RHeader->StartMicrosecond = Time.tv_usec;951 RHeader->Events = 1;952 953 934 // Check all boards that have new data 954 for (unsigned int Brd=0; Brd<Boards.size(); Brd++) { 955 // Identify board 935 for (unsigned int Brd=0; Brd<ActiveBoards.size(); Brd++) { 956 936 if (IDString.find(string("EVENT")+Boards[Brd]->Name) == string::npos) continue; 957 937 958 938 // Fill M0 BoardStructure 959 S = Boards[Brd]->GetStatus();939 S = ActiveBoards[Brd]->GetStatus(); 960 940 BStruct[Brd]->SerialNo = (U32) S.DNA; 961 941 BStruct[Brd]->NomFreq = S.Frequency; … … 978 958 memset(Data+Count, 0, NChips*NChannels*NBins*sizeof(short)); 979 959 980 Boards[Brd]->Lock();960 ActiveBoards[Brd]->Lock(); 981 961 for (unsigned int Chip=0; Chip<NChips; Chip++) for (unsigned int Chan=0; Chan<NChannels; Chan++) { 982 962 for (int i=0; i<S.ROI[Chip][Chan]; i++) { 983 if ( Boards[Brd]->ACalib.Time == -1) Data[Count++] =Boards[Brd]->Data[Chip][Chan][i];963 if (ActiveBoards[Brd]->ACalib.Time == -1) Data[Count++] = ActiveBoards[Brd]->Data[Chip][Chan][i]; 984 964 else { 985 Temp = ( Boards[Brd]->Data[Chip][Chan][i] -Boards[Brd]->ACalib.Baseline[Chip][Chan][(i+S.TriggerCell[Chip])%NBins]);986 Temp *= Boards[Brd]->ACalib.Gain[Chip][Chan][0]/Boards[Brd]->ACalib.Gain[Chip][Chan][(i+S.TriggerCell[Chip])%NBins];987 //Temp -= Boards[Brd]->ACalib.Secondary[Chip][Chan][i];965 Temp = (ActiveBoards[Brd]->Data[Chip][Chan][i] - ActiveBoards[Brd]->ACalib.Baseline[Chip][Chan][(i+S.TriggerCell[Chip])%NBins]); 966 Temp *= ActiveBoards[Brd]->ACalib.Gain[Chip][Chan][0]/ActiveBoards[Brd]->ACalib.Gain[Chip][Chan][(i+S.TriggerCell[Chip])%NBins]; 967 //Temp -= ActiveBoards[Brd]->ACalib.Secondary[Chip][Chan][i]; 988 968 Data[Count++] = (short) Temp; 989 969 } … … 991 971 Count += NBins - S.ROI[Chip][Chan]; 992 972 } 993 994 // Inform TCP/IP thread that data has been processed 973 ActiveBoards[Brd]->Unlock(); 974 } 975 976 // Inform TCP/IP thread of all boards that send data that processing is finished 977 for (unsigned int Brd=0; Brd<Boards.size(); Brd++) if (IDString.find(string("EVENT")+Boards[Brd]->Name) != string::npos) { 978 Boards[Brd]->Lock(); 995 979 Boards[Brd]->Continue = true; 996 980 Boards[Brd]->Unlock(); … … 999 983 Message(FATAL, "pthread_cond_signal() failed (%s)", strerror(Ret)); 1000 984 } 1001 } // Loop over boards985 } 1002 986 1003 987 // Check if DIM service should be updated 1004 988 if ((Time.tv_sec-LastUpdate.tv_sec)*1e6 + Time.tv_usec-LastUpdate.tv_usec > EventUpdateDelay*1e6) { 1005 989 gettimeofday(&LastUpdate, NULL); 1006 EventService.updateService(EventData, EventSize);990 EventService.updateService(EventData, sizeof(RunHeader) + sizeof(EventHeader) + ActiveBoards.size()*(sizeof(BoardStructure) + NChips*NChannels*NBins*sizeof(short) + NChips*sizeof(int))); 1007 991 EventNumService.updateService(); 992 if (Mode == datarun) FileSizeService.updateService(); 1008 993 } 1009 994 1010 // ===== Data writing === 1011 995 // ===== Data writing === 1012 996 if (Mode != datarun) continue; 1013 997 … … 1024 1008 if (CommonEventNum == numeric_limits<unsigned long>::max()) continue; 1025 1009 1026 // Write also run header if this is the first event 1027 int Offset; 1010 int Error = 0; 1011 1012 // Initialize run 1028 1013 if (NumEvents == 0) { 1029 RHeader->MagicNum = MAGICNUM_OPEN; 1030 RunStart = Time; 1031 Offset = 0; 1032 FileSize = 0; 1033 } 1034 else Offset = sizeof(RunHeader) + Boards.size()*sizeof(BoardStructure); 1014 FileSizeMB = 0; 1015 1016 FileRHeader = *RHeader; 1017 FileRHeader.MagicNum = MAGICNUM_OPEN; 1018 FileRHeader.StartSecond = Time.tv_sec; 1019 FileRHeader.StartMicrosecond = Time.tv_usec; 1020 1021 // Write run header and board structures 1022 if (write(Datafile, &FileRHeader, sizeof(RunHeader)) == -1) Error = errno; 1023 else if (write(Datafile, BStruct[0], FileRHeader.NBoards*sizeof(BoardStructure)) == -1) Error = errno; 1024 } 1025 1026 // Write event header, trigger cells and ADC data to file 1027 if (write(Datafile, EHeader, sizeof(EventHeader)+NChips*sizeof(int)+ActiveBoards.size()*NChips*NChannels*NBins*sizeof(short)) == -1) Error = errno; 1028 1029 NumEvents++; 1030 1031 // Write event header to file 1032 //if(write(Datafile, EHeader, sizeof(EventHeader)) != sizeof(EventHeader)) Error = true; 1033 1034 // Write trigger cells 1035 //for (unsigned int i=0; i<ActiveBoards.size(); i++) { 1036 //if(write(Datafile, TriggerCell + i*NChips, NChips*sizeof(int)) != NChips*sizeof(int)) Error = true; 1037 //} 1038 1039 // Write ADC data 1040 //unsigned int Bins = NChips*NChannels*NBins; 1041 //for (unsigned int i=0; i<ActiveBoards.size(); i++) { 1042 //if(write(Datafile, Data+i*Bins, Bins*sizeof(short)) != (ssize_t) (Bins*sizeof(short))) Error = true; 1043 //} 1035 1044 1036 // Write data to file 1037 if(write(Datafile, EventData+Offset, EventSize-Offset) != (ssize_t) EventSize-Offset) { 1038 Message(ERROR, "Could not write all data to file, terminating run, setting mode to IDLE (%s)", strerror(errno)); 1039 1040 // Close file if error 1045 // Update file size 1046 if (fstat(Datafile, &FileStat) == -1) Error = errno; 1047 else FileSizeMB = FileStat.st_size/1024.0/1024.0; 1048 1049 // Check for write errors and for correct file size 1050 if (Error !=0) { 1051 Message(ERROR, "Error writing to data data file (%s), terminating run, setting mode to IDLE", strerror(Error)); 1052 } 1053 else if ((size_t) FileStat.st_size != sizeof(RunHeader)+ FileRHeader.NBoards*sizeof(BoardStructure)+NumEvents*(sizeof(EventHeader) + FileRHeader.NBoards*(NChips*NChannels*NBins*sizeof(short) + NChips*sizeof(int)))) { 1054 Message(ERROR, "Could not write all data to file, terminating run, setting mode to IDLE"); 1055 Error = 1; 1056 } 1057 1058 // Close file if error 1059 if (Error != 0) { 1041 1060 if (close(Datafile) == -1) Message(ERROR, "Could not close data file (%s)", strerror(errno)); 1042 1061 Datafile = -1; … … 1045 1064 } 1046 1065 1047 NumEvents++; 1048 FileSize += EventSize-Offset; 1066 // Close data file if requested or requested number of events reached 1067 if(IDString.find("stop")!=string::npos || (NumEvents==NumEventsRequested && NumEventsRequested!=0)) { 1068 1069 // Update run header for writing 1070 FileRHeader.MagicNum = MAGICNUM_CLOSED; 1071 FileRHeader.Events = NumEvents; 1072 FileRHeader.EndSecond = Time.tv_sec; 1073 FileRHeader.EndMicrosecond = Time.tv_usec; 1074 1075 if (lseek(Datafile, 0, SEEK_SET) == -1) { 1076 Message(ERROR, "Could not rewind file to write updated run header (%s)", strerror(errno)); 1077 } 1078 else if (write(Datafile, &FileRHeader, sizeof(RunHeader)) != sizeof(RunHeader)) { 1079 Message(ERROR, "Could not write updated run header (%s)", strerror(errno)); 1080 } 1081 1082 // Close data file and terminate run 1083 if(close(Datafile) == -1) Message(ERROR, "Could not close data file (%s)", strerror(errno)); 1084 else PrintMessage("Data file closed (size %.1f MByte).\n", FileSizeMB); 1085 1086 Datafile = -1; 1087 Mode = idle; 1088 Message(INFO, "Data run ended, mode set to IDLE"); 1089 } 1049 1090 } 1050 1091 1051 1092 delete[] BStruct; 1052 1093 delete[] EventData; 1053 1054 1094 } 1055 1095 -
fact/FADctrl/History.txt
r10813 r10913 30 30 cancelled 31 31 25/5/2011 dcm_lock and dcm_ready bits were incorrectly evaluated. 32 3/6/2011 Raw data files will only contain boards active at the start of the run.
Note:
See TracChangeset
for help on using the changeset viewer.