diff --git a/FPGA_firmware/hit20v3.qsf b/FPGA_firmware/hit20v3.qsf index f8f3285..d4d9150 100644 --- a/FPGA_firmware/hit20v3.qsf +++ b/FPGA_firmware/hit20v3.qsf @@ -664,5 +664,5 @@ set_instance_assignment -name POST_FIT_CONNECT_TO_SLD_NODE_ENTITY_PORT crc[11] - set_instance_assignment -name POST_FIT_CONNECT_TO_SLD_NODE_ENTITY_PORT crc[21] -to auto_signaltap_0|vcc -section_id auto_signaltap_0 set_instance_assignment -name POST_FIT_CONNECT_TO_SLD_NODE_ENTITY_PORT crc[25] -to auto_signaltap_0|vcc -section_id auto_signaltap_0 set_instance_assignment -name POST_FIT_CONNECT_TO_SLD_NODE_ENTITY_PORT crc[31] -to auto_signaltap_0|gnd -section_id auto_signaltap_0 -set_instance_assignment -name PARTITION_HIERARCHY root_partition -to | -section_id Top -set_global_assignment -name SLD_FILE db/stp2_auto_stripped.stp \ No newline at end of file +set_global_assignment -name SLD_FILE db/stp2_auto_stripped.stp +set_instance_assignment -name PARTITION_HIERARCHY root_partition -to | -section_id Top \ No newline at end of file diff --git a/data_analyser/hitreader.h b/data_analyser/hitreader.h new file mode 100644 index 0000000..af72780 --- /dev/null +++ b/data_analyser/hitreader.h @@ -0,0 +1,601 @@ +/****************************************************************************** +* Copyright * +* Scintillating Fibre Beam Profile Monitor Software by Michal Dziewiecki, * +* Blake Leverington and Liqing Qin is licensed under CC BY 4.0 * +* https://creativecommons.org/licenses/by/4.0/ * +* funded by the Deutsche Forschungsgemeinschaft * +* (DFG, German Research Foundation) Projektnummer 419255448 * +* Project Leader: B.Leverington * +******************************************************************************* +* Create Date - 2019 * +* Author: M.Dziewiecki * +* Module - hitreader.h * +* Edited by L.Qin on 01. Feb. 2024 * +******************************************************************************/ + +// This is an object interface for reading HIT data files for testbeam 2024Feb/Aug with the new FPGA firmware. +// See HIT documentation for details and examples. +/* + .L hitreader.c + + Hitdata data; + data.readFile(“my_file.da2”); //to load whole file at once – forget it! See below. + data.readFile(“my_file.da2”,1000,100,10) //to read 100 frames starting from frame 1000 and incrementing by 10 (i.e. frame 1000, 1010, 1020, ... 1990 will be read) + //Reading 10 000 frames is reasonable. Reading 100 000 frames made my VM beg for memory. + + data.nrFrames //to see how many frames you have + data.frames[0].nrBoards //to see how many boards you had in the system + data.frames[0].boards[0].nrChannels //to see how many channels you have in board 0 + data.frames[10].boards[0].data[100] //get signal value for frame 10, board 0, channel 100 + data.frames[10].boards[0].syncframe.local_ctr //get the local synchro counter for frame 10, board 0 + //same for .global_ctr, .sma_state, .dummy, .device_nr, .data_ok + + */ + +//*********************** Helper ************************* + +#include +#include +#define DATASOURCE string("2024_08_08") + + +using namespace std; + +// #define debug(str) std::cout << "HIT DEBUG: " << str << endl; +#define debug(str) + +//*********************** Fpgasframe ************************* + /* reg results has 32*4 bits + WORDS 163 [31:16]MeanXleftshift [15:0] Sigma0; + 164 [31:16]MaxY; [15:0] STATUS; + 165 for debug; + 166 for debut; + + results[1][0] <= bkg_sub_on; + results[1][1] <= has_cluster; + results[1][2] <= no_cluster; + results[2][31:16] <= {7'b0,Windowleft}; + results[2][15:0] <= {7'b0,Windowright}; + for status register: + STATUS_BKG_SUB_ON 0x0001 + STATUS_HAS_CLUSTER 0x0002 + STATUS_NO_CLUSTER 0x0004 + */ + +class Fpgasframe +{ +public: + Fpgasframe() + { + debug("Fpgasframe()"); + + Position = Sigma = Peak = Status = 0; + Dummy0 = Dummy1 = 0; + BKG_SUB_ON = Status & 0x0001; + HAS_CLUSTER = Status & 0x0002; + NO_CLUSTER = Status & 0x0004; + Windowleft = (Dummy0 & 0xFFFF0000)>>16; + Windowright = (Dummy0 & 0x0000FFFF); + }; + + ~Fpgasframe() + { + debug("~Fpgasframe()"); + }; + + int sizeInFile() + { + return 16; + }; + + int read(std::ifstream *file) + { + char buffer[16]; + file->read(buffer, 16); + if (file->fail()) + return 1; + Position = *(unsigned short *)(buffer + 0)*0.05; + Sigma = *(unsigned short *)(buffer + 2)*0.05; + Peak = *(unsigned short *)(buffer + 4); + Status = *(unsigned short *)(buffer + 6); + Dummy0 = *(int *)(buffer + 8); + Dummy1 = *(int *)(buffer + 12); + BKG_SUB_ON = (Status & 0x0001)>>0; + HAS_CLUSTER = (Status & 0x0002)>>1; + NO_CLUSTER = (Status & 0x0004)>>2; + Windowright = (Dummy0 & 0xFFFF0000)>>16; + Windowleft = (Dummy0 & 0x0000FFFF); + //std::cout << "Fpgasframe:" << Position << " " << Sigma << " " << Peak << " " << Status << " " << Dummy0 << " " << Dummy1 << std::endl; + return 0; + }; + + int write(std::ofstream *file) + { + char buffer[16]; + *(unsigned short *)(buffer + 0) = Position/0.05; + *(unsigned short *)(buffer + 2) = Sigma/0.05; + *(unsigned short *)(buffer + 4) = Peak; + *(unsigned short *)(buffer + 6) = Status; + *(int *)(buffer + 8) = Dummy0; + *(int *)(buffer + 12) = Dummy1; + + file->write(buffer, 16); + + if (file->fail()) + return 1; + + return 0; + } + + double Position; + double Sigma; + unsigned short Peak; + unsigned short Status; + unsigned short Windowleft; + unsigned short Windowright; + unsigned short BKG_SUB_ON; + unsigned short HAS_CLUSTER; + unsigned short NO_CLUSTER; + int Dummy0; + int Dummy1; +}; + +//*********************** Syncframe ************************* +class Syncframe +{ +public: + Syncframe() + { + debug("Syncframe()"); + + local_ctr = global_ctr = 0; + sma_state = dummy = 0; + device_nr = -1; + data_ok = 0; + }; + + ~Syncframe() + { + debug("~Syncframe()"); + }; + + int sizeInFile() + { + return 16; + }; + + int read(std::ifstream *file) + { + char buffer[16]; + file->read(buffer, 16); + if (file->fail()) + return 1; + local_ctr = *(unsigned short *)(buffer + 0); + global_ctr = *(unsigned short *)(buffer + 2); + sma_state = *(unsigned short *)(buffer + 4); + dummy = *(unsigned short *)(buffer + 6); + device_nr = *(int *)(buffer + 8); + data_ok = *(int *)(buffer + 12); + // std::cout << "Syncframe:" << local_ctr << " " << global_ctr << " " << sma_state << " " << dummy << " " << device_nr << " " << data_ok << std::endl; + + return 0; + }; + + int write(std::ofstream *file) + { + char buffer[16]; + *(unsigned short *)(buffer + 0) = local_ctr; + *(unsigned short *)(buffer + 2) = global_ctr; + *(unsigned short *)(buffer + 4) = sma_state; + *(unsigned short *)(buffer + 6) = dummy; + *(int *)(buffer + 8) = device_nr; + *(int *)(buffer + 12) = data_ok; + + file->write(buffer, 16); + + if (file->fail()) + return 1; + + return 0; + } + + unsigned short local_ctr; + unsigned short global_ctr; + unsigned short sma_state; + unsigned short dummy; + int device_nr; + unsigned int data_ok; +}; + +//*********************** Sensorframe ************************* +class Boardframe +{ +public: + Boardframe(int nr_channels = 0) + { + debug("Boardframe()"); + + data = NULL; + resize(nr_channels); + }; + + Boardframe(const Boardframe &in) + { + debug("Boardframe(Boardframe&)"); + + data = NULL; + resize(in.nrChannels); + for (int i = 0; i < nrChannels; i++) + data[i] = in.data[i]; + syncframe = in.syncframe; + fpgas = in.fpgas; + }; + + Boardframe &operator=(const Boardframe &in) + { + debug("Boardframe::operator=="); + + resize(in.nrChannels); // creates an array called data of length nrChannels + for (int i = 0; i < nrChannels; i++) + data[i] = in.data[i]; + syncframe = in.syncframe; + fpgas = in.fpgas; + return *this; + }; + + ~Boardframe() + { + debug("~Boardframe()"); + + if (data) + delete[] data; + }; + + void resize(int nr_channels) + { + if (data) + delete[] data; + nrChannels = nr_channels; + if (nrChannels) + data = new signed short[nrChannels]; + else + data = NULL; + }; + + int sizeInFile() + { + return syncframe.sizeInFile() + nrChannels * 2 + fpgas.sizeInFile(); + }; + + int read(std::ifstream *file) + { + if (syncframe.read(file) == 1) // get the syncframe before the board data + return 1; + // I must be already resized at this point! + file->read((char *)data, 2 * nrChannels); + if (file->fail()) + return 1; + if (fpgas.read(file) == 1) // get the fpgasframe after the board data + return 1; + // for print data out + /* std::cout<< "data[" << nrChannels << "]: "; + for (int i = 0;iwrite(reinterpret_cast(data), 2 * nrChannels); + + if (file->fail()) + return 1; + + if (!fpgas.write(file)) + return 1; + + return 0; + } + + signed short &operator[](int index) + { + return data[index]; + }; + + Syncframe syncframe; + int nrChannels; + signed short *data; + Fpgasframe fpgas; +}; + +//*********************** Fullframe ************************* +class Fullframe +{ +public: + Fullframe(int nr_boards = 0) + { + debug("Fullframe()"); + boards = NULL; + resize(nr_boards); + }; + + Fullframe(const Fullframe &in) + { + debug("Fullframe(Fullframe&)"); + boards = NULL; + resize(in.nrBoards); + for (int i = 0; i < nrBoards; i++) + boards[i] = in.boards[i]; + }; + + Fullframe &operator=(const Fullframe &in) + { + debug("Fullframe::operator=="); + resize(in.nrBoards); + for (int i = 0; i < nrBoards; i++) + boards[i] = in.boards[i]; + + return *this; + }; + + ~Fullframe() + { + debug("~Fullframe()"); + if (boards) + delete[] boards; + }; + + void resize(int nr_boards) + { + if (boards) + delete[] boards; + nrBoards = nr_boards; + if (nrBoards) + boards = new Boardframe[nrBoards]; + else + boards = NULL; + } + + int sizeInFile() + { + int sum_size = 0; + if (boards) + { + for (int i = 0; i < nrBoards; i++) + sum_size += boards[i].sizeInFile(); + return 2 + nrBoards * 2 + sum_size; + } + // return 2 + 4*2 + (16 +320*2)+(16+128*2)*3; + // return 2 + nrBoards*2 + nrBoards * boards[0].sizeInFile(); + else + return 1; // no boards, makes no sense... + }; + + int read(std::ifstream *file) + { + // Read number of boards + unsigned short nr_boards; + file->read((char *)&nr_boards, 2); + if (file->fail() || nr_boards > 6) + { + std::cerr << "Unrealistic number of board to be read:" << nr_boards << std::endl; + return 1; + } + // std::cout << " nr_boards: " << nr_boards << std::endl; + // Read channel counts + unsigned short *channel_counts = new unsigned short[nr_boards]; + file->read((char *)channel_counts, nr_boards * 2); + if (file->fail()) + { + delete[] channel_counts; + return 1; + } + + // Read board frames + resize(nr_boards); + for (int board_nr = 0; board_nr < nr_boards; board_nr++) + { + // std::cout << " channel_counts[" << board_nr << "]: "<< channel_counts[board_nr] << std::endl; + + boards[board_nr].resize(channel_counts[board_nr]); + if (boards[board_nr].read(file) == 1) // read the board + { + delete[] channel_counts; + return 1; + } + } + + delete[] channel_counts; + return 0; + }; + + int write(std::ofstream *file) + { + // write nrboards + file->write((char *)&nrBoards, 2); + unsigned short *channel_counts = new unsigned short[nrBoards]; + for (int board_nr = 0; board_nr < nrBoards; board_nr++) + { + channel_counts[board_nr] = boards[board_nr].nrChannels; + } + file->write((char *)channel_counts, nrBoards * 2); + for (int board_nr = 0; board_nr < nrBoards; board_nr++) + { + if (boards[board_nr].write(file) == 1) // write the board + { + delete[] channel_counts; + return 1; + } + } + delete[] channel_counts; + return 0; + }; + + TGraph *plot(int board_nr) + { + + auto g = new TGraph(); + for (int i = 0; i < boards[board_nr].nrChannels; ++i) + { + g->SetPoint(i, i, boards[board_nr].data[i]); + } + g->Draw(); + + return g; + } + + int nrChannels() + { + int result = 0; + for (int board_nr = 0; board_nr < nrBoards; board_nr++) + result += boards[board_nr].nrChannels; + return result; + }; + + signed short &operator[](int index) + { + for (int board_nr = 0; board_nr < nrBoards; board_nr++) + { + if (index >= boards[board_nr].nrChannels) + index -= boards[board_nr].nrChannels; + else + return boards[board_nr][index]; + } + + std::cerr << " ### Fullframe::operator[]: index out of range!" << std::endl; + // return (*NULL); //this will cause crash (intended). + return boards[nrBoards][index]; + }; + + int nrBoards; + Boardframe *boards; +}; + +//*********************** Hitdata ************************* + +class Hitdata +{ +public: + Hitdata(int nr_frames = 0) + { + frames = NULL; + resize(nr_frames); + }; + + Hitdata(const Hitdata &in) + { + frames = NULL; + resize(in.nrFrames); + for (int i = 0; i < nrFrames; i++) + frames[i] = in.frames[i]; + }; + + Hitdata &operator=(const Hitdata &in) + { + resize(in.nrFrames); + for (int i = 0; i < nrFrames; i++) + frames[i] = in.frames[i]; + + return *this; + }; + + ~Hitdata() + { + if (nrFrames) + delete[] frames; + }; + + void resize(int nr_frames) + { + if (nrFrames) + delete[] frames; + nrFrames = nr_frames; + if (nrFrames) + frames = new Fullframe[nrFrames]; + else + frames = NULL; + }; + + // Read data from a given file. + // first_frame is the number of first frame to be read + // nr_frames is the maximum number of frames to be read + //-1 to read all of them + // increment allows you reading once every nth sample + // Return number of frames read or 0 in case of failure + int readFile(char *filename, int first_frame = 0, int nr_frames = -1, int increment = 1) + { + std::ifstream file; + // Open the file + file.open(filename, ios_base::in | ios_base::binary); + if (!file.is_open()) + { + std::cerr << " ### Hitdata: File could not be open!" << std::endl; + return 1; // file could not be opened + } + + // Read first record to find board configuration + Fullframe sampleframe; + if (sampleframe.read(&file) == 1) + { + std::cerr << " ### Hitdata: First frame could not be read!" << std::endl; + file.close(); + return 1; + } + + // Check file size + file.seekg(0, std::ios::beg); + std::streamsize fsize = file.tellg(); + file.seekg(0, std::ios::end); + fsize = file.tellg() - fsize; + + // Determine real frames to read + unsigned int max_frames = (fsize / sampleframe.sizeInFile() - first_frame) / increment; + if ((nr_frames == -1) || (max_frames < nr_frames)) + nr_frames = max_frames; + + std::cout << " Hitdata: Nr frames to be read: " << nr_frames << std::endl; + + // Read! + resize(nr_frames); // make an array called frames of size nr_frames #####!!!! + file.seekg(first_frame * sampleframe.sizeInFile(), std::ios::beg); + for (long int frame_nr = 0; frame_nr < nr_frames; frame_nr++) + { + /* if ((frame_nr%100) == 0) + std::cout << " Frame " << frame_nr << std::endl;*/ + + file.seekg((first_frame + frame_nr * increment) * sampleframe.sizeInFile(), std::ios::beg); + if (frames[frame_nr].read(&file) == 1) // read the next frame + { + std::cerr << " ### Hitdata: Frame " << frame_nr << " could not be read!" << std::endl; + file.close(); // read error, finish! + // frames = frame_nr; //Kinky! We decrease nr_frames, but the actual array size remains unchanged! + ///???? I don't know what the above line does. + return frame_nr; + } + // std::cout << frames[frame_nr].nrBoards << std::endl; + } + + // Finished + file.close(); + return nr_frames; + }; + + Fullframe &operator[](int index) + { + if (index < nrFrames) + return frames[index]; + else + { + std::cerr << " ### Hitdata::operator[]: index out of range!" << std::endl; + // return (*NULL); //this will cause crash (intended). + return frames[index]; + } + }; + + int nrFrames; + Fullframe *frames; +};