From d4b1d81fe336bd499c32dd1dea713d4821fdbb3a Mon Sep 17 00:00:00 2001 From: Maps Date: Thu, 4 Apr 2024 17:55:28 +0200 Subject: [PATCH] finished scurve scans. some stuff, like scan for subsubevents is still missing --- cpp/CMakeLists.txt | 32 +- cpp/main.cxx | 556 -------------------------- cpp/mimosis.cxx | 189 +++++---- cpp/mimosis.hpp | 113 +----- cpp/scurve-scan.cxx | 843 +++++++++++++++++++++++++++++++++++++++ scripts/Mimosis.pm | 464 ++++++++++++--------- scripts/cli/mimosis | 249 +++++++----- scripts/pulse/fit-raw.py | 2 +- 8 files changed, 1417 insertions(+), 1031 deletions(-) delete mode 100644 cpp/main.cxx create mode 100644 cpp/scurve-scan.cxx diff --git a/cpp/CMakeLists.txt b/cpp/CMakeLists.txt index 8ce1275..cc0f005 100644 --- a/cpp/CMakeLists.txt +++ b/cpp/CMakeLists.txt @@ -1,10 +1,24 @@ cmake_minimum_required(VERSION 3.9 FATAL_ERROR) -project(mimosis-scurves +project(mimosis LANGUAGES C CXX ) -add_executable(mimosis-scurves main.cxx) +set(SCURVE_EXE "scurve-scan") +set(MIMOSIS_LIB "mimosis") + + +add_executable( + ${SCURVE_EXE} ${SCURVE_EXE}.cxx +) + + +add_library( + ${MIMOSIS_LIB} SHARED + ${MIMOSIS_LIB}.cxx +) + + if(TRBNETTOOLS_DIR) message(${TRBNETTOOLS_DIR}) @@ -12,18 +26,24 @@ else() message("TRBNETTOOLS_DIR not provided. Using /d/jspc85/bgutsche/trbnettools") set(TRBNETTOOLS_DIR "/d/jspc85/bgutsche/trbnettools") endif() + set(TRBNET_LIB_DIR ${TRBNETTOOLS_DIR}/libtrbnet/) set(TRBNET_INCLUDE_DIR ${TRBNETTOOLS_DIR}/libtrbnet/) + + if(DABC_DIR) message(${DABC_DIR}) else() message("DABC_DIR not provided. Using /d/jspc37/soft/trb3/dabc") set(DABC_DIR "/d/jspc37/soft/trb3/dabc") endif() + set(DABC_LIB_DIR ${DABC_DIR}/lib/) set(DABC_INCLUDE_DIR ${DABC_DIR}/include/) + + include_directories( ${TRBNET_INCLUDE_DIR} ${DABC_INCLUDE_DIR} @@ -34,9 +54,15 @@ link_directories( ${DABC_LIB_DIR} ) -target_link_libraries(mimosis-scurves + +target_link_libraries(${SCURVE_EXE} PRIVATE trbnet PRIVATE DabcBase PRIVATE DabcHadaq PRIVATE DabcMbs + PRIVATE ${MIMOSIS_LIB} +) + +target_link_libraries(${MIMOSIS_LIB} + PRIVATE trbnet ) diff --git a/cpp/main.cxx b/cpp/main.cxx deleted file mode 100644 index 1343f40..0000000 --- a/cpp/main.cxx +++ /dev/null @@ -1,556 +0,0 @@ -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include - -//Necessary for readout handler -#include "hadaq/api.h" - -//Necessary to control mimosis and trbnet -#include "trbnet.h" - - -using namespace std::chrono; - -//Enum to make access to the information vector more clear -enum params {STATE, YLOW, YHIG, XLOW, XHIG, REGION, VCASN, VPHFINE}; - - -//Collection of data related variables used throughout the programm. -namespace Data -{ - //Main data array holds counts of pulses for every pixel and VPH_FINE - std::array dataArray; - - - int dataFraCnt = 0; - int limitFra = 500; - - short vphfine; - - //Boundaries within pulses were done - int yLow, yHig, xLow, xHig; - int yLowMax = 504, yHigMax = 0, xLowMax = 1024, xHigMax = 0; - int sLowMax = 255, sHigMax = 0; - - //Directory where data and METADATA will be put. - std::string dataDir; - - //Current state of the programm. - std::string state; - - //Keep track of VCASN to put in METADATA later. - std::vector vcasnVec; - - //Measure time of execution of the programm and put - //information in METADATA - decltype(high_resolution_clock::now()) start; - - //Keep track whether mimosis frame counter was not incremented by 1, - //which would indicate droped frames in the R/O. - std::vector mimFraCntNewVec; - std::vector mimFraCntOldVec; -}; - - - -//Name of PID file. -const std::string pidName = "/tmp/hldprint-pid"; - - - -//Write PID to PID-file -void write_pid(void) -{ - int pid = (int)getpid(); - - FILE *pidFile = fopen(pidName.c_str(), "w"); - - if(pidFile == nullptr) { - std::printf("ERROR: Couldn't open file.\n"); - std::exit(-1); - } - - fprintf(pidFile, "%d",pid); - - fclose(pidFile); -} - - - -//Open a pipe and wait for commands and informations -//from controller script -std::vector await_params() -{ - //Receiving pipe for informations from controller - std::string pipeName = "/tmp/scurveipipe"; - - FILE *iPipe = fopen(pipeName.c_str(), "r"); - - if(iPipe == nullptr) { - std::printf("ERROR: Couldn't open file.\n"); - std::exit(-1); - } - - - //Read from pipe char by char until full frame is reached. - //Frames start with START and end with END. - //Information is delimited by '-' characters. - int buf; - bool foundFrame = false, foundSta = false, foundEnd = false; - std::string word; - - //Staore all informations, without START and END, in values vector. - std::vector values; - - buf = fgetc(iPipe); - - while(!foundFrame && buf != EOF) - { - char c = static_cast(buf); - - if(c == '-') { - values.push_back(word); - word = ""; - } else { - word += c; - } - - if(word == "START") { foundSta = true; } - if(word == "END") { foundEnd = true; } - - buf = fgetc(iPipe); - - if(foundSta && foundEnd) { - foundFrame = true; - break; - } - } - - //Delete "START" from first position - values.erase(values.begin()); - - // for (const auto& i: values) - // std::cout << i << '\n'; - - fclose(iPipe); - - //Return the whole array. - return values; -} - - - -//Open a pipe to transmit an acknowledgement to the -//controller script -int send_ack() -{ - //Transmitting pipe to acknowledge receiving and processing of informations - //A simple 'ACK' indicates the controller successful operation - std::string pipeName = "/tmp/scurveapipe"; - - FILE *iPipe = fopen(pipeName.c_str(), "w"); - - if(iPipe == nullptr) { - std::printf("ERROR: Couldn't open file.\n"); - std::exit(-1); - } - - std::string msg("ACK"); - fputs(msg.c_str(),iPipe); - fclose(iPipe); - return 0; -} - - - -//Writing contents of Data::dataArr to file. -void write_data(std::string reg, std::string vcasn) -{ - //For each VCASN a new sub dir is created and a csv file with - //the same name holds the data. - std::string subDir = Data::dataDir + "/" + reg + "-" + vcasn; - - mkdir(subDir.c_str(), S_IRWXU | S_IRWXG | S_IROTH | S_IXOTH); - - std::string fileName = subDir + "/" + reg + "-" + vcasn + ".csv"; - - - //Buffered ofstream increases performance. - //One could also dump the whole array as binary file, but this complicates - //Post processing a bit. - //Another option would be to include root and use TTree's. - std::ofstream file(fileName); - char buffer[1000000]; - file.rdbuf()->pubsetbuf(buffer, sizeof(buffer)); - - //Only write relevant data between boundaries of scan. - for(int y = Data::yLowMax; y <= Data::yHigMax; y++) { - - for(int x = Data::xLowMax; x <= Data::xHigMax; x++) { - - for(int s = Data::sLowMax; s <= Data::sHigMax; s++) { - - uint32_t v = Data::dataArray[(y*1024+x)*255+s]; - file << v << '\t'; - - //Reset data to 0 - Data::dataArray[(y*1024+x)*255+s] = 0; - } - file << '\n'; - } - } - file.close(); -} - - - -//Decodeing of mimosis words into pixels -bool decode_pixel(const uint32_t& word, int& column, int& row, const int& region) -{ - const unsigned long pixelcode = (word >> 6) & 0x3ff; - - unsigned long side = 0, topdown = 0; - - if((pixelcode&3) == 0x1 || (pixelcode&3) == 0x2) side = 1; - if((pixelcode&3) == 0x3 || (pixelcode&3) == 0x2) topdown = 1; - - row = (pixelcode>>2)*2 + topdown; - column = (((word>>3)&0x7) + region*8)*2 + side; - - return true; -} - - - -//Main data taking procedure. -void take_data(std::string src) -{ - hadaq::ReadoutHandle ref = hadaq::ReadoutHandle::Connect(src.c_str()); - if (ref.null()) return; - hadaq::RawEvent *evnt = nullptr; - - bool takeData = false; - int region = 0, column, row; - short vphfine; - - while (true) - { - evnt = ref.NextEvent(1.,-1); - if (!evnt) continue; - hadaq::RawSubevent* sub = nullptr; - - while ((sub = evnt->NextSubevent(sub)) != nullptr) - { - unsigned headersNow = 0; - uint32_t mimFraCntNew = 0; - uint32_t mimFraCntOld = 0; - bool fraFirst = true; - uint32_t pulseMsg = 0; - unsigned size = sub->GetNrOfDataWords(); - - for( unsigned i = 0; i(sub->Data(i)); - - if((data & 0xFF000000) == 0xFE000000) { - - headersNow++; - - if(headersNow == 1) { - - mimFraCntNew = (data & 0xFF0000) >> 16; - mimFraCntNew += (data & 0xFF) << 8; - - } else if(headersNow == 2) { - - mimFraCntNew += data & 0xFF0000; - mimFraCntNew += (data & 0xFF) << 24; - - if(mimFraCntNew-mimFraCntOld != 1 && !fraFirst) { - Data::mimFraCntNewVec.push_back(mimFraCntNew); - Data::mimFraCntOldVec.push_back(mimFraCntOld); - std::printf("Found skipped mimosis frame counter:\nOld:\t%u\nNew:\t%u\n",mimFraCntOld,mimFraCntNew); - } - mimFraCntOld = mimFraCntNew; - fraFirst = false; - - } else if(headersNow == 3) { - - pulseMsg = (data & 0xFF0000) >> 16; - pulseMsg += (data & 0xFF) << 8; - - // std::printf("%u\t%x\n",size, sub->Data(i)); - - } else if(headersNow == 4) { - - pulseMsg += data & 0xFF0000; - pulseMsg += (data & 0xFF) << 24; - vphfine = ( pulseMsg & 0xFF000000 ) >> 24; - - // std::printf("%u\t%x\n",size, sub->Data(i)); - // std::printf("%x\n", pulseMsg); - - if( ( ( 0x00c00000 & pulseMsg ) == 0x00c00000 ) && - (vphfine == Data::vphfine)) { - - takeData = true; - Data::dataFraCnt++; - - if(Data::dataFraCnt >= Data::limitFra) { - takeData = false; - Data::dataFraCnt = 0; - goto ENDFUNC; - } - - Data::sLowMax = vphfine < Data::sLowMax ? vphfine : Data::sLowMax; - Data::sHigMax = vphfine > Data::sHigMax ? vphfine : Data::sHigMax; - - } else if( ( 0x00c00000 & pulseMsg ) == 0x00400000 ) { - - takeData = false; - goto ENDFUNC; - - } else if( ( 0x00c00000 & pulseMsg ) == 0x00000000 ) { - takeData = false; - //Idle - } - } - - } else if((data & 0xFF000000) == 0xFF000000) { - - headersNow = 0; - - } else { - - headersNow = 0; - - if( takeData ) { - - if( (data & 0xFF000000) == 0xFD000000 ) { - const int tmp = (data>>16) & 0xFF; - if(tmp > 63) continue; - region = tmp; - - } else { - - decode_pixel(data>>16,column,row,region); - if(column >= Data::xLow && - column <= Data::xHig && - row >= Data::yLow && - row < Data::yHig ) { - Data::dataArray[(row*1024+column)*255+vphfine] += 1; - // printf("%d %d %d %d\n",row, column, vphfine, Data::dataArray[(row*1024+column)*255+vphfine]); - } - } - - if((data & 0x0000FF00) != 0x0000FC00) { - - decode_pixel(data&0xFFFF,column,row,region); - - if(column >= Data::xLow && - column <= Data::xHig && - row >= Data::yLow && - row < Data::yHig ) { - Data::dataArray[(row*1024+column)*255+vphfine] += 1; - } - } - } - } - } - } - } - ENDFUNC: - ref.Disconnect(); -} - - - -//Keep track of maximum values of boundaries of scan. -void find_edge() -{ - using namespace Data; - yLowMax = yLow < yLowMax ? yLow : yLowMax; - yHigMax = yHig > yHigMax ? yHig : yHigMax; - xLowMax = xLow < xLowMax ? xLow : xLowMax; - xHigMax = xHig > xHigMax ? xHig : xHigMax; -} - - - -//Write the METADATA file and put into dataDir. -void write_meta() -{ - std::string fileName = Data::dataDir + "/METADATA"; - - std::ofstream file(fileName); - - file << "START:" << '\t' << Data::dataDir << '\n'; - - file << "VCASN:"; - for(const auto& i: Data::vcasnVec) { - file << '\t' << i; - } - file << '\n'; - - file << "YMIN:" << '\t' << Data::yLowMax << '\n'; - file << "YMAX:" << '\t' << Data::yHigMax << '\n'; - file << "XMIN:" << '\t' << Data::xLowMax << '\n'; - file << "XMAX:" << '\t' << Data::xHigMax << '\n'; - file << "SMIN:" << '\t' << Data::sLowMax << '\n'; - file << "SMAX:" << '\t' << Data::sHigMax << '\n'; - - file << "EXITSTATE:" << '\t' << Data::state << '\n'; - - auto stop = high_resolution_clock::now(); - auto duration = duration_cast(stop - Data::start); - file << "TIME(s):" << '\t' << duration.count() << '\n'; - - file << "COMMENT:\t\n"; - - file.close(); -} - - - -//Signal handler for clean exit at CTRL-C. -//Data will be dumped and marked with 'INTERRUPTED', -//if current state was a data taking state. -void signal_handler( int signum ) -{ - std::cout << "Interrupt signal (" << signum << ") received Cleaning up...\n"; - - if(Data::state == "TAKEDATA" || - Data::state == "WAITDAQ" || - Data::state == "FIT") { - - std::string lastReg = "INTERRUPTED"; - std::string lastVca = "INTERRUPTED"; - write_data(lastReg, lastVca); - std::cout << "Remining data indicated by INTERRUPTED flags.\n"; - - } else { - } - - //Remove pid file - remove(pidName.c_str()); - - write_meta(); - - std::exit(signum); -} - - - -//main. Make initialization and then enter main loop. -int main(int argc, char* argv[]) -{ - //Read stream url - std::string src = argv[1]; - - - //Initialize trbnet for this run - int trbnetState = init_ports(); - - - //Start clock to report execution time METADATA - Data::start = high_resolution_clock::now(); - - - //Generate the PID file - write_pid(); - - - //Register signal SIGINT and signal handler - signal(SIGINT, signal_handler); - - - //Declare stateVec, that will hold the - //informations passed from control script - std::vector stateVec; - - - //Create main data dir by time stamp - std::time_t time = std::time(0); - std::tm* now = std::localtime(&time); - - Data::dataDir = std::to_string(now->tm_year + 1900) + '-' - + std::to_string(now->tm_mon + 1) + '-' - + std::to_string(now->tm_mday) + '-' - + std::to_string(now->tm_hour) + '-' - + std::to_string(now->tm_min); - - mkdir(Data::dataDir.c_str(), S_IRWXU | S_IRWXG | S_IROTH | S_IXOTH); - - - //Initialize data array with 0's - for(int y = 0; y <= 505; y++) - for(int x = 0; x <= 1025; x++) - for(int s = 0; s <= 256; s++) - Data::dataArray[(y*1024+x)*255+s] = 0; - - - //Main control loop. After init phase, - //wait for commands from control script - AWAIT: - stateVec = await_params(); - Data::state = stateVec[params::STATE]; - - if(Data::state == "TAKEDATA") { - - Data::yLow = std::stoi(stateVec[params::YLOW], nullptr, 10); - Data::yHig = Data::yLow + std::stoi(stateVec[params::YHIG], nullptr, 10); - Data::xLow = std::stoi(stateVec[params::XLOW], nullptr, 10); - Data::xHig = std::stoi(stateVec[params::XHIG], nullptr, 10); - - std::printf("Take data: "); - std::printf("%4d %4d %4d %4d\n", Data::yLow, Data::yHig, Data::xLow, Data::xHig); - find_edge(); - send_ack(); - take_data(src); - goto AWAIT; - - } else if(Data::state == "WAITDAQ") { - - // std::printf("At WAITDAQ.\n"); - send_ack(); - goto AWAIT; - - } else if(Data::state == "FIT") { - - std::string regStr = stateVec[params::REGION]; - std::string vcaStr = stateVec[params::VCASN]; - Data::vcasnVec.push_back(vcaStr); - std::printf("Write data: %s %s\n",regStr.c_str(),vcaStr.c_str()); - write_data(regStr,vcaStr); - send_ack(); - goto AWAIT; - - } else if(Data::state == "DONE") { - - std::printf("Done.\n"); - send_ack(); - - remove(pidName.c_str()); - - write_meta(); - - return 0; - - } else { - - //Never happend so far, but just in case, - //exit cleanly and remove pid file - std::printf("Received garbage. Exiting.\n"); - - remove(pidName.c_str()); - - return 1; - } -} diff --git a/cpp/mimosis.cxx b/cpp/mimosis.cxx index c5e434a..c1d9f2b 100644 --- a/cpp/mimosis.cxx +++ b/cpp/mimosis.cxx @@ -1,116 +1,141 @@ #include +#include +#include + +#include "mimosis.hpp" #include "trbnet.h" -/* Make sure the right libraries are used, to get trbnet c - * code working (from trbnettools use trbnetd/libtrbnet.*). - * Also set DAQOPSERVER like usual. - * */ +#define MIM_I2C_INSTR (0x11<<1) +#define MIM_I2C_ADD_LSB (0x12<<1) +#define MIM_I2C_ADD_MSB (0x13<<1) +#define MIM_I2C_WR (0x14<<1) +#define MIM_I2C_RD (0x15<<1) -namespace mimosis -{ +#define TRB_REG_ADDR 0xde01 +#define TRB_REG_READ 0xde04 +#define TRB_OPTION 0 - void register_write(const int& fpga, const int& mim_reg, const int& mim_data, const bool& singleaccess) noexcept - { - const uint32_t addr = 0x12; - const uint32_t cmd = mim_reg >> 8; - const uint32_t data = ((mim_reg & 0xff) << 8 ) + mim_data; +#define I2C_EXEC 0x1 - if( singleaccess ) - { +#define GEN_PAYLOAD_WR(r,d) static_cast(((r&0xff)<<24)+((d&0xff)<<16)+(r&0xff00)+MIM_I2C_ADD_LSB) +#define GEN_PAYLOAD_RD(r) static_cast(((r&0xff)<<16)+(r&0xff00)+MIM_I2C_ADD_LSB) - { - const uint32_t com = (( mim_reg >> 8 ) << 16 ) + ( addr << 1); - const uint32_t arr[3] = { 0x010, com, 0x1}; - trb_register_write_mem(fpga, 0xde01, 0, arr, 3); - } +#define GEN_ADD_LSB(r) static_cast(((r&0xff00)<<8)+MIM_I2C_ADD_LSB) +#define GEN_ADD_MSB(r) static_cast(((r&0xff)<<16)+MIM_I2C_ADD_MSB) +#define GEN_WR(d) static_cast(((d&0xff)<<16)+MIM_I2C_WR) - { - const uint32_t com = ( mim_reg << 16 ) + ( (addr + 1) << 1); - const uint32_t arr[3] = { 0x010, com, 0x1}; - trb_register_write_mem(fpga, 0xde01, 0, arr, 3); - } +#ifndef SLEEPVAL +#define SLEEPVAL 1000 +#endif - { - const uint32_t com = ( mim_data << 16 ) + ( (addr + 2) << 1); - const uint32_t arr[3] = { 0x010, com, 0x1}; - trb_register_write_mem(fpga, 0xde01, 0, arr, 3); - } - } - else if ( !singleaccess ) + + +void mimosis::register_write( + const uint16_t& fpga, + const uint16_t& mim_reg, + const uint16_t& mim_data, + const bool& singleAccess +) noexcept { + + if( singleAccess ) { + + std::vector payload = { + GEN_ADD_LSB(mim_reg), + GEN_ADD_MSB(mim_reg), + GEN_WR(mim_data) }; + + for (auto i: payload) { - const uint32_t com = ( data << 16 ) + ( cmd << 8 ) + ( addr << 1); - const uint32_t arr[3] = { 0x001, com, 0x1}; - trb_register_write_mem(fpga, 0xde01, 0, arr, 3); + const uint32_t arr[3] = { 0x010, i, I2C_EXEC}; + trb_register_write_mem(fpga, TRB_REG_ADDR, TRB_OPTION, arr, 3); + usleep(SLEEPVAL); } + + } else if ( !singleAccess ) { + + const uint32_t arr[3] = { 0x001, GEN_PAYLOAD_WR(mim_reg,mim_data), I2C_EXEC }; + + trb_register_write_mem( fpga, TRB_REG_ADDR, TRB_OPTION, arr, 3); + usleep(SLEEPVAL); } +} - int register_read(const int& fpga, const int& mim_reg, const bool& singleaccess) noexcept - { - const uint32_t addr = 0x12; - const uint32_t cmd = mim_reg >> 8; - const uint32_t data = mim_reg & 0xff; - if( singleaccess ) +int mimosis::register_read(const int& fpga, const int& mim_reg, const bool& singleAccess) noexcept +{ + if( singleAccess ) { + + std::vector payload = { + GEN_ADD_LSB(mim_reg), + GEN_ADD_MSB(mim_reg)}; + + for (auto i: payload) { - return 0; + const uint32_t arr[3] = { 0x010, i, I2C_EXEC}; + trb_register_write_mem(fpga, TRB_REG_ADDR, TRB_OPTION, arr, 3); + usleep(SLEEPVAL); } - else if( !singleaccess ) + + } else if( !singleAccess ) { + { - { - const uint32_t com = ( data << 16 ) + ( cmd << 8 ) + ( addr << 1); - const uint32_t arr[3] = { 0x0, com, 0x1 }; - trb_register_write_mem(fpga, 0xde01, 0, arr, 3); - } - - { - const uint32_t com = ( 0x15 << 1); - const uint32_t arr[3] = { 0x110, com, 0x1 }; - trb_register_write_mem(fpga, 0xde01, 0, arr, 3); - } - - const uint32_t size = 2; - uint32_t res[size]; - trb_register_read(fpga, 0xde04, res, size); - return res[1]; + const uint32_t arr[3] = { 0x0, GEN_PAYLOAD_RD(mim_reg), I2C_EXEC }; + trb_register_write_mem(fpga, TRB_REG_ADDR, 0, arr, 3); + } + + usleep(SLEEPVAL); + + { + const uint32_t arr[3] = { 0x110, MIM_I2C_RD, I2C_EXEC }; + trb_register_write_mem(fpga, TRB_REG_ADDR, 0, arr, 3); } - return 0; - } + usleep(SLEEPVAL); - void instr_write(const int& fpga, const int& cmd) noexcept - { - const uint32_t com = ( cmd << 8 ) + ( 0x11 << 1 ); - const uint32_t arr[3] = { 0x0, com, 0x1 }; - trb_register_write_mem(fpga, 0xde01, 0, arr, 3 ); + const int size = 2; + uint32_t res[size]; + trb_register_read(fpga, TRB_REG_READ, res, size); + + return res[1] & 0x00ff; } -}; + usleep(SLEEPVAL); + + return -1; +} -namespace adc + +void mimosis::instr_write(const int& fpga, const int& cmd) noexcept { + const uint32_t com = (cmd<<8) + MIM_I2C_INSTR; + const uint32_t arr[3] = { 0x0, com, 0x1 }; + trb_register_write_mem(fpga, TRB_REG_ADDR, 0, arr, 3 ); + usleep(SLEEPVAL); +} - void write(const int& fpga, const int& addr, const int& cmd, const int& data) noexcept - { - const uint32_t com = (data << 16) + (cmd << 8) + 0x80 + addr; - const uint32_t arr[2] = { 0x001, com }; - trb_register_write_mem(fpga, 0xd681, 0, arr, 2 ); - } - int read(const int& fpga, const int& addr, const int& cmd) noexcept - { - const uint32_t com = (cmd << 8) + 0x80 + addr; - const uint32_t arr[2] = { 0x101, com }; - trb_register_write_mem(fpga, 0xd681, 0, arr, 2 ); +void adc::write(const int& fpga, const int& addr, const int& cmd, const int& data) noexcept +{ + const uint32_t com = (data << 16) + (cmd << 8) + 0x80 + addr; + const uint32_t arr[2] = { 0x001, com }; + trb_register_write_mem(fpga, 0xd681, 0, arr, 2 ); +} - uint32_t res[2]; - trb_register_read(fpga, 0xd684, res, 2); - return res[1]; - } -}; +int adc::read(const int& fpga, const int& addr, const int& cmd) noexcept +{ + const uint32_t com = (cmd << 8) + 0x80 + addr; + const uint32_t arr[2] = { 0x101, com }; + trb_register_write_mem(fpga, 0xd681, 0, arr, 2 ); + + uint32_t res[2]; + trb_register_read(fpga, 0xd684, res, 2); + + return res[1] & 0x00ff; +} diff --git a/cpp/mimosis.hpp b/cpp/mimosis.hpp index c5e434a..62397dc 100644 --- a/cpp/mimosis.hpp +++ b/cpp/mimosis.hpp @@ -1,116 +1,23 @@ -#include -#include "trbnet.h" - -/* Make sure the right libraries are used, to get trbnet c - * code working (from trbnettools use trbnetd/libtrbnet.*). - * Also set DAQOPSERVER like usual. - * */ +#ifndef MIMOSIS_HPP +#define MIMOSIS_HPP namespace mimosis { + void register_write(const uint16_t& fpga, const uint16_t& mim_reg, const uint16_t& mim_data, const bool& singleaccess) noexcept; - void register_write(const int& fpga, const int& mim_reg, const int& mim_data, const bool& singleaccess) noexcept - { - const uint32_t addr = 0x12; - const uint32_t cmd = mim_reg >> 8; - const uint32_t data = ((mim_reg & 0xff) << 8 ) + mim_data; - - if( singleaccess ) - { - - { - const uint32_t com = (( mim_reg >> 8 ) << 16 ) + ( addr << 1); - const uint32_t arr[3] = { 0x010, com, 0x1}; - trb_register_write_mem(fpga, 0xde01, 0, arr, 3); - } - - { - const uint32_t com = ( mim_reg << 16 ) + ( (addr + 1) << 1); - const uint32_t arr[3] = { 0x010, com, 0x1}; - trb_register_write_mem(fpga, 0xde01, 0, arr, 3); - } - - { - const uint32_t com = ( mim_data << 16 ) + ( (addr + 2) << 1); - const uint32_t arr[3] = { 0x010, com, 0x1}; - trb_register_write_mem(fpga, 0xde01, 0, arr, 3); - } - - } - else if ( !singleaccess ) - { - const uint32_t com = ( data << 16 ) + ( cmd << 8 ) + ( addr << 1); - const uint32_t arr[3] = { 0x001, com, 0x1}; - trb_register_write_mem(fpga, 0xde01, 0, arr, 3); - } - } - - - int register_read(const int& fpga, const int& mim_reg, const bool& singleaccess) noexcept - { - const uint32_t addr = 0x12; - const uint32_t cmd = mim_reg >> 8; - const uint32_t data = mim_reg & 0xff; - - if( singleaccess ) - { - return 0; - } - else if( !singleaccess ) - { - { - const uint32_t com = ( data << 16 ) + ( cmd << 8 ) + ( addr << 1); - const uint32_t arr[3] = { 0x0, com, 0x1 }; - trb_register_write_mem(fpga, 0xde01, 0, arr, 3); - } - - { - const uint32_t com = ( 0x15 << 1); - const uint32_t arr[3] = { 0x110, com, 0x1 }; - trb_register_write_mem(fpga, 0xde01, 0, arr, 3); - } - - const uint32_t size = 2; - uint32_t res[size]; - trb_register_read(fpga, 0xde04, res, size); - return res[1]; - } - return 0; - } - - - void instr_write(const int& fpga, const int& cmd) noexcept - { - const uint32_t com = ( cmd << 8 ) + ( 0x11 << 1 ); - const uint32_t arr[3] = { 0x0, com, 0x1 }; - trb_register_write_mem(fpga, 0xde01, 0, arr, 3 ); - } + int register_read(const int& fpga, const int& mim_reg, const bool& singleaccess) noexcept; + void instr_write(const int& fpga, const int& cmd) noexcept; }; + namespace adc { + void write(const int& fpga, const int& addr, const int& cmd, const int& data) noexcept; - void write(const int& fpga, const int& addr, const int& cmd, const int& data) noexcept - { - const uint32_t com = (data << 16) + (cmd << 8) + 0x80 + addr; - const uint32_t arr[2] = { 0x001, com }; - trb_register_write_mem(fpga, 0xd681, 0, arr, 2 ); - } - - - int read(const int& fpga, const int& addr, const int& cmd) noexcept - { - const uint32_t com = (cmd << 8) + 0x80 + addr; - const uint32_t arr[2] = { 0x101, com }; - trb_register_write_mem(fpga, 0xd681, 0, arr, 2 ); - - uint32_t res[2]; - trb_register_read(fpga, 0xd684, res, 2); - - return res[1]; - } - + int read(const int& fpga, const int& addr, const int& cmd) noexcept; }; + +#endif //MIMOSIS_HPP diff --git a/cpp/scurve-scan.cxx b/cpp/scurve-scan.cxx new file mode 100644 index 0000000..824dc99 --- /dev/null +++ b/cpp/scurve-scan.cxx @@ -0,0 +1,843 @@ +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +//Necessary for readout handler +#include "hadaq/api.h" + +//Necessary to control mimosis and trbnet +#include "trbnet.h" + +//Necessary for mimosis specific functions +#include "mimosis.hpp" + +#define FPGA 0xa000 + +#define VPHFINE 0x0046 + +#define SUPERINDEX(x,y,s) ((y*1024+x)*256+s) + +using namespace std::chrono; + +//Enum to make access to the information vector more clear +enum params { + STATE, + YSTA, + YEND, + YTRA, + XLOW, + XHIG, + VPHSTA, + VPHEND, + VPHSTEP, + COUNTS, + MOD, + REGION, + VCASN, + SINGLEACCESS +}; + + +//Collection of data related variables used throughout the programm. +namespace Data +{ + std::string source; + //Main data array holds counts of pulses for every pixel and VPH_FINE + std::array dataArray; + + //Current state of the programm. + std::string state; + + //Boundaries within pulses were done + int yLowMax = 503, yHigMax = 0, xLowMax = 1023, xHigMax = 0; + + //Directory where data and METADATA will be put. + std::string dataDir; + + //Keep track of VCASN to put in METADATA later. + std::vector vcasnVec; + + bool singleAccess = true; + //Measure time of execution of the programm and put + //information in METADATA + decltype(high_resolution_clock::now()) start; +}; + + + +namespace Stats +{ + int totalFrames = 0; + int totalFramesSkipped = 0; +}; + + +//Name of PID file. +const std::string pidName = "/tmp/hldprint-pid"; + + + +void mimosis_sec_write(uint16_t fpga, uint16_t reg, uint16_t data, bool sa) +{ + uint16_t readVal = mimosis::register_read( fpga, reg, sa); + + int cnt = 0; + + while (readVal!= data) + { + mimosis::register_write( fpga, reg, data, sa ); + readVal = mimosis::register_read( fpga, reg, sa ); + + cnt++; + + if(cnt >= 1000) + { + std::printf("Cannot write 0x%04x to 0x%04x.\nExiting.\n",data, reg); + std::exit(-1); + break; + } + } +} + + + +//Write PID to PID-file +void write_pid(void) +{ + int pid = (int)getpid(); + + FILE *pidFile = fopen(pidName.c_str(), "w"); + + if(pidFile == nullptr) { + std::printf("ERROR: Couldn't open file.\n"); + std::exit(-1); + } + + fprintf(pidFile, "%d",pid); + + fclose(pidFile); +} + + + +//Open a pipe and wait for commands and informations +//from controller script +std::vector await_params() +{ + //Receiving pipe for informations from controller + std::string pipeName = "/tmp/scurveipipe"; + + FILE *iPipe = fopen(pipeName.c_str(), "r"); + + if(iPipe == nullptr) { + std::printf("ERROR: Couldn't open file.\n"); + std::exit(-1); + } + + + //Read from pipe char by char until full frame is reached. + //Frames start with START and end with END. + //Information is delimited by '-' characters. + int buf; + bool foundFrame = false, foundSta = false, foundEnd = false; + std::string word; + + //Staore all informations, without START and END, in values vector. + std::vector values; + + buf = fgetc(iPipe); + + while(!foundFrame && buf != EOF) + { + char c = static_cast(buf); + + if(c == '-') { + values.push_back(word); + word = ""; + } else { + word += c; + } + + if(word == "START") { foundSta = true; } + if(word == "END") { foundEnd = true; } + + buf = fgetc(iPipe); + + if(foundSta && foundEnd) { + foundFrame = true; + break; + } + } + + //Delete "START" from first position + values.erase(values.begin()); + + // for (const auto& i: values) + // std::cout << i << '\n'; + + fclose(iPipe); + + //Return the whole array. + return values; +} + + + +//Open a pipe to transmit an acknowledgement to the +//controller script +int send_ack() +{ + //Transmitting pipe to acknowledge receiving and processing of informations + //A simple 'ACK' indicates the controller successful operation + std::string pipeName = "/tmp/scurveapipe"; + + FILE *iPipe = fopen(pipeName.c_str(), "w"); + + if(iPipe == nullptr) { + std::printf("ERROR: Couldn't open file.\n"); + std::exit(-1); + } + + std::string msg("ACK"); + fputs(msg.c_str(),iPipe); + fclose(iPipe); + return 0; +} + + + +//Writing contents of Data::dataArr to file. +void write_data(std::string reg, std::string vcasn) +{ + //For each VCASN a new sub dir is created and a csv file with + //the same name holds the data. + std::string subDir = Data::dataDir + "/" + reg + "-" + vcasn; + + mkdir(subDir.c_str(), S_IRWXU | S_IRWXG | S_IROTH | S_IXOTH); + + std::string fileName = subDir + "/" + reg + "-" + vcasn + ".csv"; + + //Buffered ofstream increases performance. + //One could also dump the whole array as binary file, but this complicates + //Post processing a bit. + //Another option would be to include root and use TTree's. + std::ofstream file(fileName); + char buffer[1000000]; + file.rdbuf()->pubsetbuf(buffer, sizeof(buffer)); + + // std::printf("%d %d %d %d\n", Data::yLowMax, Data::yHigMax, Data::xLowMax, Data::xHigMax); + + //Only write relevant data between boundaries of scan. + for(int y = Data::yLowMax; y <= Data::yHigMax; y++) { + + for(int x = Data::xLowMax; x <= Data::xHigMax; x++) { + + for(int s = 0; s <= 255; s++) { + + auto v = Data::dataArray[SUPERINDEX(x,y,s)]; + + file << v << '\t'; + // file << s << '\t'; + + //Reset data to 0 + Data::dataArray[SUPERINDEX(x,y,s)] = 0; + } + file << '\n'; + } + } + file.close(); +} + + + +//Decodeing of mimosis words into pixels +void decode_pixel(const uint32_t& word, unsigned int& column, unsigned int& row, unsigned int& region) +{ + unsigned int pixelcode = (word >> 6) & 0x3ff; + + unsigned int side = 0, topdown = 0; + + if((pixelcode&3) == 0x1 || (pixelcode&3) == 0x2) side = 1; + if((pixelcode&3) == 0x3 || (pixelcode&3) == 0x2) topdown = 1; + + row = (pixelcode>>2)*2 + topdown; + column = (((word>>3)&0x7) + region*8)*2 + side; +} + + + +//Main data taking procedure. +void loop_vph( + int yLow, int yHig, + int xLow, int xHig, + int vphSta, int vphEnd, int vphTra, + int maxCounts, int mod, int exp) +{ +#ifdef DEBUG + std::printf("loop_vph(): yLow(%4d) yHig(%4d) xLow(%4d) xHig(%4d) vphSta(%4d) vphEnd(%4d) vphTra(%4d) maxCounts(%4d) mod(%8d)\n", + yLow,yHig,xLow,xHig,vphSta,vphEnd,vphTra,maxCounts,mod); +#endif + + int pulse = static_cast(std::pow(2.0,static_cast(exp))); + + hadaq::ReadoutHandle ref = hadaq::ReadoutHandle::Connect(Data::source.c_str()); + if (ref.null()) return; + hadaq::RawEvent *evnt = nullptr; + + for(int vphfine = vphSta; + vphfine <= vphEnd; + vphfine += vphTra) + // for(int vphfine = vphSta; + // vphfine <= vphEnd; + // vphfine++) + { + std::printf("Scan: %3d\r",vphfine); + fflush(stdout); + + //Set VPH_FINE + mimosis_sec_write( FPGA, VPHFINE, vphfine, Data::singleAccess ); + + auto start = high_resolution_clock::now(); + auto stop = high_resolution_clock::now(); + auto duration = duration_cast(stop-start); + + for(int mimTra = 0; + mimTraNextSubevent(sub)) != nullptr) + { + unsigned size = sub->GetNrOfDataWords(); + + int headerNow = 0; + + uint32_t mimFraCnt; + + unsigned region = 0, column = 0, row = 0; + + for( unsigned i = 0; i(sub->Data(i)); + + if((data & 0xFF000000) == 0xFE000000) { + + ++headerNow; + + if(headerNow == 1) { + + mimFraCnt = (data & 0xFF0000) >> 16; + mimFraCnt += (data & 0xFF) << 8; + + } else if(headerNow == 2) { + + mimFraCnt += data & 0xFF0000; + mimFraCnt += (data & 0xFF) << 24; + + } else if(headerNow == 3) { + } else if(headerNow == 4) { + } + + } else if((data & 0xFF000000) == 0xFF000000) { + + headerNow = 0; + mimTra++; + + } else { + + if( (data & 0xFF000000) == 0xFD000000 ) { + + int tmp = (data>>16) & 0xFF; + if(tmp > 63) continue; + region = tmp; + + } else { + + decode_pixel(data>>16,column,row,region); + + if(column >= xLow && + column <= xHig && + row >= yLow && + row < yHig && + mimFraCnt%pulse == mod) { + + // if (vphfine%vphTra == 0) + Data::dataArray[SUPERINDEX(column,row,vphfine)] += 1; + } + } + + if((data & 0x0000FF00) != 0x0000FC00) { + + decode_pixel(data&0xFFFF,column,row,region); + + if(column >= xLow && + column <= xHig && + row >= yLow && + row < yHig && + mimFraCnt%pulse == mod) { + + // if (vphfine%vphTra == 0) + Data::dataArray[SUPERINDEX(column,row,vphfine)] += 1; + } + } + } + + if(mimTra >= maxCounts) { + goto MAXCOUNTS; + } + + } // End loop over data in sub event + } // End loop over sub-events in event + } //End while duration + MAXCOUNTS: + ; + } + std::printf("\n"); + ref.Disconnect(); +} + + + +int find_mod( + int yLow, int yHig, + int xLow, int xHig, + int modPulse) +{ + int pulse = static_cast(std::pow(2.0,static_cast(modPulse))); + + int modFound = -1; + + const int modN = 2; + std::vector modVec(modN); + for(auto& i: modVec) { i = -1; } + int modInd = 0; + int modX = -1,modY = -1; + + //Set VPH_FINE to smth high, so pulses get visible + mimosis_sec_write( FPGA, VPHFINE, 0xff, Data::singleAccess ); + + hadaq::ReadoutHandle ref = hadaq::ReadoutHandle::Connect(Data::source.c_str()); + if (ref.null()) return -2; + hadaq::RawEvent *evnt = nullptr; + + uint32_t lastMimFraCnt; + + while(modFound == -1) + { + while(true) + { + evnt = ref.NextEvent(1.,-1); + if (!evnt) continue; + + hadaq::RawSubevent* sub = nullptr; + + while ((sub = evnt->NextSubevent(sub)) != nullptr) + { + unsigned size = sub->GetNrOfDataWords(); + int headerNow = 0; + uint32_t mimFraCnt; + unsigned region = 0, column = 0, row = 0; + + for( unsigned i = 0; i(sub->Data(i)); + + if((data & 0xFF000000) == 0xFE000000) { + + ++headerNow; + + if(headerNow == 1) { + + mimFraCnt = (data & 0xFF0000) >> 16; + mimFraCnt += (data & 0xFF) << 8; + + } else if(headerNow == 2) { + + mimFraCnt += data & 0xFF0000; + mimFraCnt += (data & 0xFF) << 24; + + } else if(headerNow == 3) { + } else if(headerNow == 4) { + } + + } else if((data & 0xFF000000) == 0xFF000000) { + + headerNow = 0; + + } else { + + if( (data & 0xFF000000) == 0xFD000000 ) { + + int tmp = (data>>16) & 0xFF; + if(tmp > 63) continue; + region = tmp; + + } else { + + decode_pixel(data>>16,column,row,region); + + if(column >= xLow && + column <= xHig && + row >= yLow && + row < yHig && + lastMimFraCnt != mimFraCnt && + modInd < modN && + (row == modY || modY == -1) && + (column == modX || modX == -1)) { + + modY = row; + modX = column; + + modVec[modInd] = mimFraCnt%pulse; + + modInd++; + + lastMimFraCnt = mimFraCnt; + + if(modInd == modN) { goto EVALMODS; } + } + } + + if((data & 0x0000FF00) != 0x0000FC00) { + + decode_pixel(data&0xFFFF,column,row,region); + + if(column >= xLow && + column <= xHig && + row >= yLow && + row < yHig && + lastMimFraCnt != mimFraCnt && + modInd < modN && + (row == modY || modY == -1) && + (column == modX || modX == -1)) { + + modY = row; + modX = column; + + modVec[modInd] = mimFraCnt%pulse; + + modInd++; + + lastMimFraCnt = mimFraCnt; + + if(modInd == modN) { goto EVALMODS; } + } + } + } + } // End loop over data in sub event + } // End loop over sub-events in event + } + + EVALMODS: + + int firstMod = modVec[0]; + int wrongMods = 0; + + for(int i = 1; i < modN; i++) { + if(modVec[i] != firstMod) { + wrongMods++; + } + } + + if(wrongMods > 0) { + modInd = 0; + continue; + } else if(wrongMods == 0) { + modFound = firstMod; + break; + } + } //End while mod not found + + ref.Disconnect(); + return modFound; +} + + + +void loop_rows( + int ySta, int yEnd, int yTra, + int xSta, int xEnd, + int vphSta, int vphEnd, int vphTra, + int maxCounts, int exp) +{ +#ifdef DEBUG + std::printf("loop_rows(): ySta(%4d) yEnd(%4d) yTra(%4d) xSta(%4d) xEnd(%4d) vphSta(%4d) vphEnd(%4d) vphTra(%4d) maxCounts(%8d) exp(%4d)\n", + ySta,yEnd,yTra,xSta,xEnd,vphSta,vphEnd,vphTra,maxCounts,exp); +#endif + + for(int yOff = ySta; + yOff <= yEnd; + yOff += yTra) + { + std::printf("Mark pixels: %d - %d, %d - %d\n", yOff, yOff+yTra-1, xSta, xEnd); + + int y = yOff; + + //Mark pixels for pulsing + for(; y < yOff + yTra && y <= yEnd; y++) + { + Data::yLowMax = y < Data::yLowMax ? y : Data::yLowMax; + Data::yHigMax = y > Data::yHigMax ? y : Data::yHigMax; + + int regAddY = y/8; + int regBitY = (1<<(y%8)); + int regWordY = (regAddY<<8)+0x84; + + mimosis_sec_write(FPGA, regWordY, regBitY, Data::singleAccess ); + + int regAddX; + int regBitX; + + int currRegX = xSta/16; + + int word82 = 0; + int word81 = 0; + + for (int x = xSta; x <= xEnd; x++) + { + Data::xLowMax = x < Data::xLowMax ? x : Data::xLowMax; + Data::xHigMax = x > Data::xHigMax ? x : Data::xHigMax; + + if((x/16) == currRegX && + x != xEnd) { + + if (x%2 == 1) { word82 |= (1<<((x/2)%8)); } + else if (x%2 == 0) { word81 |= (1<<((x/2)%8)); } + + } else { + + if(word82 == word81) { + + int addr = (currRegX<<8) + 0x83; + mimosis_sec_write( FPGA, addr, word81, Data::singleAccess ); + mimosis::instr_write( FPGA, 0x05 ); + mimosis_sec_write( FPGA, addr, 0, Data::singleAccess ); + + } else { + int addr81 = (currRegX<<8) + 0x81; + int addr82 = (currRegX<<8) + 0x82; + mimosis_sec_write( FPGA, addr81, word81, Data::singleAccess ); + mimosis_sec_write( FPGA, addr82, word82, Data::singleAccess ); + mimosis::instr_write( FPGA, 0x05 ); + mimosis_sec_write( FPGA, addr81, 0, Data::singleAccess ); + mimosis_sec_write( FPGA, addr82, 0, Data::singleAccess ); + } + currRegX = x/16; + + word81 = 0; + word82 = 0; + + if (x%2 == 1) { word82 = (1<<((x/2)%8)); } + else if (x%2 == 0) { word81 = (1<<((x/2)%8)); } + } + } + mimosis_sec_write(FPGA, regWordY, 0x0, Data::singleAccess ); + } + + int mod = find_mod(yOff, y, xSta, xEnd, exp); + + mimosis_sec_write( FPGA, VPHFINE, 0, Data::singleAccess ); + sleep(1); + + loop_vph(yOff, y, xSta, xEnd, vphSta, vphEnd, vphTra, maxCounts, mod, exp); + + mimosis::instr_write( FPGA, 0x3f ); + mimosis::instr_write( FPGA, 0x04 ); + mimosis::instr_write( FPGA, 0x3e ); + + //Set VPH_FINE back to zero, to get rid of peak at begining of scan + //Do it double, to be sure + mimosis_sec_write( FPGA, VPHFINE, 0, Data::singleAccess ); + } +} + + + +//Write the METADATA file and put into dataDir. +void write_meta() +{ + std::string fileName = Data::dataDir + "/METADATA"; + + std::ofstream file(fileName); + + file << "START:" << '\t' << Data::dataDir << '\n'; + + file << "VCASN:"; + for(const auto& i: Data::vcasnVec) { + file << '\t' << i; + } + file << '\n'; + + file << "YMIN:" << '\t' << Data::yLowMax << '\n'; + file << "YMAX:" << '\t' << Data::yHigMax << '\n'; + file << "XMIN:" << '\t' << Data::xLowMax << '\n'; + file << "XMAX:" << '\t' << Data::xHigMax << '\n'; + + file << "EXITSTATE:" << '\t' << Data::state << '\n'; + + auto stop = high_resolution_clock::now(); + auto duration = duration_cast(stop - Data::start); + file << "TIME(s):" << '\t' << duration.count() << '\n'; + + file << "COMMENT:\t\n"; + + file.close(); +} + + + +//Signal handler for clean exit at CTRL-C. +//Data will be dumped and marked with 'INTERRUPTED', +//if current state was a data taking state. +void signal_handler( int signum ) +{ + std::cout << "Interrupt signal (" << signum << ") received Cleaning up...\n"; + + if(Data::state == "TAKEDATA" || + Data::state == "WAITDAQ" || + Data::state == "FIT") { + + std::string lastReg = "INTERRUPTED"; + std::string lastVca = "INTERRUPTED"; + write_data(lastReg, lastVca); + std::cout << "Remining data indicated by INTERRUPTED flags.\n"; + + } else { + } + + //Set VPH_FINE back to zero, to get rid of peak at begining of scan + //Do it double, to be sure + mimosis_sec_write( FPGA, VPHFINE, 0, Data::singleAccess ); + + //Remove pid file + remove(pidName.c_str()); + + write_meta(); + + std::exit(signum); +} + + + +//main. Make initialization and then enter main loop. +int main(int argc, char* argv[]) +{ + //Read stream url + Data::source = argv[1]; + + + //Initialize trbnet for this run + int trbnetState = init_ports(); + + + //Start clock to report execution time METADATA + Data::start = high_resolution_clock::now(); + + + //Generate the PID file + write_pid(); + + + //Register signal SIGINT and signal handler + signal(SIGINT, signal_handler); + + + //Declare stateVec, that will hold the + //informations passed from control script + std::vector stateVec; + + + //Create main data dir by time stamp + std::time_t time = std::time(0); + std::tm* now = std::localtime(&time); + + Data::dataDir = std::to_string(now->tm_year + 1900) + '-' + + std::to_string(now->tm_mon + 1) + '-' + + std::to_string(now->tm_mday) + '-' + + std::to_string(now->tm_hour) + '-' + + std::to_string(now->tm_min); + + mkdir(Data::dataDir.c_str(), S_IRWXU | S_IRWXG | S_IROTH | S_IXOTH); + + + //Initialize data array with 0's + for(int y = 0; y < 504; y++) + for(int x = 0; x < 1024; x++) + for(int s = 0; s < 256; s++) + Data::dataArray[SUPERINDEX(x,y,s)] = 0; + + + //Main control loop. After init phase, + //wait for commands from control script + AWAIT: + stateVec = await_params(); + Data::state = stateVec[STATE]; + Data::singleAccess = stateVec[SINGLEACCESS] == "1"; + + if(Data::state == "TAKEDATA") { + + loop_rows( + std::stoi(stateVec[YSTA], nullptr, 10), + std::stoi(stateVec[YEND], nullptr, 10), + std::stoi(stateVec[YTRA], nullptr, 10), + std::stoi(stateVec[XLOW], nullptr, 10), + std::stoi(stateVec[XHIG], nullptr, 10), + std::stoi(stateVec[VPHSTA], nullptr, 10), + std::stoi(stateVec[VPHEND], nullptr, 10), + std::stoi(stateVec[VPHSTEP], nullptr, 10), + std::stoi(stateVec[COUNTS], nullptr, 10), + std::stoi(stateVec[MOD], nullptr, 10) + ); + + send_ack(); + + goto AWAIT; + + } else if(Data::state == "FIT") { + + std::string regStr = stateVec[REGION]; + std::string vcaStr = stateVec[VCASN]; + + Data::vcasnVec.push_back(vcaStr); + std::printf("Write data: %s %s\n",regStr.c_str(),vcaStr.c_str()); + + write_data(regStr,vcaStr); + send_ack(); + + goto AWAIT; + + } else if(Data::state == "DONE") { + + std::printf("Done.\n"); + send_ack(); + + remove(pidName.c_str()); + + write_meta(); + + return 0; + + } else { + + //Never happend so far, but just in case, + //exit cleanly and remove pid file + std::printf("Received garbage. Exiting.\n"); + + remove(pidName.c_str()); + + return 1; + } +} diff --git a/scripts/Mimosis.pm b/scripts/Mimosis.pm index 19f10c1..78b378e 100755 --- a/scripts/Mimosis.pm +++ b/scripts/Mimosis.pm @@ -122,6 +122,7 @@ sub mimosis_register_write_indirect } + sub mimosis_register_read { my ( $fpga, $mimosis_reg, $singleaccess) = @_; @@ -695,12 +696,55 @@ sub mimosis_dacscan_sf } - sub send_params_scurve { - my ($state, $yi, $rowTrain, $xLow, $xHig, $region, $vcasn, $vphfine) = @_; - $vphfine = defined $vphfine ? $vphfine : 0; - my $frameWr = "START-" . $state . "-" . $yi . "-" . $rowTrain . "-" . $xLow . "-" . $xHig . "-" . $region . "-" . $vcasn . "-" . $vphfine . "-END"; + my %params = @_; + my $state = $params{'state'}; + my $ySta = $params{'ySta'}; + my $yEnd = $params{'yEnd'}; + my $yTra = $params{'yTra'}; + my $xSta = $params{'xSta'}; + my $xEnd = $params{'xEnd'}; + my $setSta = $params{'setSta'}; + my $setEnd = $params{'setEnd'}; + my $setTra = $params{'setTra'}; + my $setCnt = $params{'setCnt'}; + my $mod = $params{'mod'}; + my $region = $params{'region'}; + my $vcasn= $params{'vcasn'}; + my $singleAccess = $params{'singleAccess'}; + + $state = defined $state ? $state : "DONE"; + $ySta = defined $ySta ? $ySta : 0; + $yEnd = defined $yEnd ? $yEnd : 0; + $yTra = defined $yTra ? $yTra : 0; + $xSta = defined $xSta ? $xSta : 0; + $xEnd = defined $xEnd ? $xEnd : 0; + $setSta = defined $setSta ? $setSta : 0; + $setEnd = defined $setEnd ? $setEnd : 0; + $setTra = defined $setTra ? $setTra : 1; + $setCnt = defined $setCnt ? $setCnt : 0; + $mod = defined $mod ? $mod : 3; + $region = defined $region ? $region : A; + $vcasn= defined $vcasn ? $vcasn : 0; + $singleAccess= defined $singleAccess ? $singleAccess : 0; + + my $frameWr = "START-" . + $state . "-" . + $ySta . "-" . + $yEnd . "-" . + $yTra . "-" . + $xSta . "-" . + $xEnd . "-" . + $setSta . "-" . + $setEnd . "-" . + $setTra . "-" . + $setCnt . "-" . + $mod . "-" . + $region . "-" . + $vcasn . "-" . + $singleAccess . "-END"; + my $pipeNameWr = "/tmp/scurveipipe"; my $fdPipeWr = POSIX::open($pipeNameWr, &POSIX::O_WRONLY); POSIX::write($fdPipeWr,$frameWr,length($frameWr)); @@ -713,7 +757,8 @@ sub kill_proc_by_pid_file { my ($pidName) = @_; - my $pidFile = POSIX::open($pidName, &POSIX::O_RDONLY) or die "hldprint already killed probably\n"; + my $pidFile = POSIX::open($pidName, &POSIX::O_RDONLY) + or die "hldprint already killed probably\n"; my $buf; my $bytes = POSIX::read($pidFile,$buf,10); POSIX::close($pidFile); @@ -748,150 +793,97 @@ sub mimosis_scan_region { my %params = @_; my $fpga = $params{'fpga'}; - my $pulseonly = $params{'pulseonly'}; - my $region = $params{'region'}; - my $ySta = $params{'firstrow'}; - my $yEnd = $params{'lastrow'}; - my $setSta = $params{'firstset'}; - my $setEnd = $params{'lastset'}; - my $setDiv = $params{'setdiv'}; - my $setTime = $params{'settime'}; my $slow = $params{'slow'}; my $a = $params{'a'}; - my $yTra = $params{'rowsatonce'}; - my $printset = $params{'printset'}; - my $printrow = $params{'printrow'}; - my $printall = $params{'printall'}; - my $analogAlimA = $params{'analogAlimA'}; - my $analogAlimB = $params{'analogAlimB'}; - my $analogDlimA = $params{'analogDlimA'}; - my $analogDlimB = $params{'analogDlimB'}; - my $modpulse = $params{'modpulse'}; - - defined $fpga or die "Mimosis::mimosis_scan_region: Must provide $fpga."; - defined $region or die "Mimosis::mimosis_scan_region: Must provide $region."; - - my %colLim = ( + my $region = $params{'region'}; + my $ySta = $params{'ySta'}; + my $yEnd = $params{'yEnd'}; + my $yTra = $params{'yTra'}; + my $xSta = $params{'xSta'}; + my $xEnd = $params{'xEnd'}; + my $setSta = $params{'setSta'}; + my $setEnd = $params{'setEnd'}; + my $setTra = $params{'setTra'}; + my $setCnt = $params{'setCnt'}; + my $analogalima = $params{'analogalima'}; + my $analogalimb = $params{'analogalimb'}; + my $analogdlima = $params{'analogdlima'}; + my $analogdlimb = $params{'analogdlimb'}; + my $mod = $params{'mod'}; + + defined $fpga or die "mimosis::mimosis_scan_region: must provide $fpga."; + defined $region or die "mimosis::mimosis_scan_region: must provide $region."; + + my %collim = ( 'A' => [ 0, 127 ], 'B' => [ 128, 511 ], 'C' => [ 512, 895 ], 'D' => [ 896, 1023 ] ); - %rowAdd = ( 'A' => 4, 'B' => 2, 'C' => 2, 'D' => 4 ); - - %regBitHash = ( 'A' => 0, 'B' => 1, 'C' => 2, 'D' => 3 ); - - my $regBit = $regBitHash{$region}; + %rowadd = ( 'A' => 4, 'B' => 2, 'C' => 2, 'D' => 4 ); + $slow = defined $slow ? $slow : 10000; + $a = defined $a ? $a : 0; $ySta = defined $ySta ? $ySta : 0; $yEnd = defined $yEnd ? $yEnd : 504; + $yTra = defined $yTra ? $yTra : $rowadd{$region}; + $xSta = defined $xSta ? $xSta : $collim{$region}[0]; + $xEnd = defined $xEnd ? $xEnd : $collim{$region}[1]; $setSta = defined $setSta ? $setSta : 0x0; $setEnd = defined $setEnd ? $setEnd : 0xff; - $setDiv = defined $setDiv ? $setDiv : 1; - $setTime = defined $setTime ? $setTime : 1000; - $slow = defined $slow ? $slow : 10000; - $a = defined $a ? $a : 0; - $yTra = defined $yTra ? $yTra : $rowAdd{$region}; - $printset = defined $printset ? 1 : 0; - $printrow = defined $printrow ? 1 : 0; - $printall = defined $printall ? 1 : 0; - $pixpulseA_A = defined $pixpulseA_A ? $pixpulseA_A : 25; - $pixpulseA_B = defined $pixpulseA_B ? $pixpulseA_B : 75; - $pixpulseD_A = defined $pixpulseD_A ? $pixpulseD_A : 0; - $pixpulseD_B = defined $pixpulseD_B ? $pixpulseD_B : 0; - $modpulse = defined $modpulse ? $modpulse : 3; - - Mimosis::mimosis_register_write( $fpga, 0x0020, 0x40, $a ); usleep($slow); #EN_PIXELMASK to 0 for pulse - Mimosis::mimosis_instr_write( $fpga, 0x3f ); usleep($slow); #INSTR select all pixels - Mimosis::mimosis_instr_write( $fpga, 0x04 ); usleep($slow); #INSTR reset mask - Mimosis::mimosis_instr_write( $fpga, 0x3e ); usleep($slow); #INSTR unselect all pixels - Mimosis::mimosis_register_write( $fpga, 0x0066, $pixpulseA_A & 0x00ff , $a ); usleep($slow); #analog pulsing pulse A, limit A - Mimosis::mimosis_register_write( $fpga, 0x0166, ( $pixpulseA_A & 0xff00 ) >> 8, $a ); usleep($slow); - Mimosis::mimosis_register_write( $fpga, 0x0076, $pixpulseA_B & 0x00ff , $a ); usleep($slow); # analog pulsing pulse A, limit B - Mimosis::mimosis_register_write( $fpga, 0x0176, ( $pixpulseA_B & 0xff00 ) >> 8, $a ); usleep($slow); - Mimosis::mimosis_register_write( $fpga, 0x0067, $pixpulseD_A & 0x00ff , $a ); usleep($slow); # analog pulsing pulse D, limit A - Mimosis::mimosis_register_write( $fpga, 0x0167, ( $pixpulseD_A & 0xff00 ) >> 8, $a ); usleep($slow); - Mimosis::mimosis_register_write( $fpga, 0x0077, $pixpulseD_B & 0x00ff , $a ); usleep($slow); # analog pulsing pulse D, limit B - Mimosis::mimosis_register_write( $fpga, 0x0177, ( $pixpulseD_B & 0xff00 ) >> 8, $a ); usleep($slow); - Mimosis::mimosis_register_write( $fpga, 0x007d, $modpulse, $a ); usleep($slow); #set modpulse. possible values: 1f/1, 1f/2, 1f/4, 1f/8, 1f/16, 1f/32, 1f/64, 1f/128 - - - for ( my $yOff = $ySta; - $yOff <= $yEnd; - $yOff+=$yTra ) { - - my $y = $yOff; - - for ( ; - $y < $yOff+$yTra && $y <= $yEnd; - $y+=1 ) { - - if( $printrow || $printall ) { printf("row: $y\n"); } - - my $regAdd = $y/8; - my $regBit = $y%8; - my $regWord = ( $regAdd << 8 ) + 0x84; - Mimosis::mimosis_register_write( $fpga, $regWord, ( 0x1 << $regBit ), $a ); usleep($slow); - Mimosis::mimosis_instr_write( $fpga, 0x27 ); usleep($slow); #INSTR select all pixels - Mimosis::mimosis_instr_write( $fpga, 0x05 ); usleep($slow); #INSTR set mask pulse - Mimosis::mimosis_register_write( $fpga, 0x4087, 0x0, $a ); usleep($slow); #unselect all pixels (register wise) - Mimosis::mimosis_instr_write( $fpga, 0x3e ); usleep($slow); #INSTR unselect all pixels - } - - unless($pulseonly) - { - my $yTraSend = $yEnd-$yOff<$yTra ? $yEnd-$yOff : $yTra; - send_params_scurve("TAKEDATA", $yOff, $yTraSend, $colLim{$region}[0], $colLim{$region}[1], $region, 0); - await_ack(); - - my $setCnt = 0; - for my $set (reverse ($setSta .. $setEnd) ) - { - $setCnt = $setCnt + 1; - if( ($setCnt-1)%$setDiv != 0) { next; } - - send_params_scurve("NEXTVPH", 0, 0, 0, 0, 0, 0, $set); - await_ack(); - - my $pulseMsg = ($set << 24) + 0x00c00000; - trb_register_write_mem( $fpga, 0xa209, 0, [ $pulseMsg ], 1 ); usleep($slow); - # Mimosis::mimosis_register_write( $fpga, 0x0046, $set, $a ); usleep($setTime); - Mimosis::mimosis_register_write( $fpga, 0x0046, $set, $a ); - - if( $printset || $printall ) { printf("set: $set\n"); } - } - - Mimosis::mimosis_instr_write( $fpga, 0x3f ); usleep($slow); - Mimosis::mimosis_instr_write( $fpga, 0x04 ); usleep($slow); #INSTR set mask pulse - Mimosis::mimosis_instr_write( $fpga, 0x3e ); usleep($slow); #INSTR set mask pulse - - trb_register_write_mem( $fpga, 0xa209, 0, [ 0x00400000 ], 1 ); usleep($slow); - send_params_scurve("WAITDAQ", 0, 0, 0, 0, 0, 0); - await_ack(); - trb_register_write_mem( $fpga, 0xa209, 0, [ 0x00000000 ], 1 ); usleep($slow); - } - } + $setTra = defined $setTra ? $setTra : 1; + $setCnt = defined $setCnt ? $setCnt : 4000; + $pixpulsea_a = defined $pixpulsea_a ? $pixpulsea_a : 25; + $pixpulsea_b = defined $pixpulsea_b ? $pixpulsea_b : 75; + $pixpulsed_a = defined $pixpulsed_a ? $pixpulsed_a : 0; + $pixpulsed_b = defined $pixpulsed_b ? $pixpulsed_b : 0; + $mod = defined $mod ? $mod : 3; + + Mimosis::mimosis_register_write( $fpga, 0x0020, 0x40, $a ); usleep($slow); #en_pixelmask to 0 for pulse + Mimosis::mimosis_instr_write( $fpga, 0x3f ); usleep($slow); #instr select all pixels + Mimosis::mimosis_instr_write( $fpga, 0x04 ); usleep($slow); #instr reset mask + Mimosis::mimosis_instr_write( $fpga, 0x3e ); usleep($slow); #instr unselect all pixels + Mimosis::mimosis_register_write( $fpga, 0x0066, $pixpulsea_a & 0x00ff , $a ); usleep($slow); #analog pulsing pulse a, limit a + Mimosis::mimosis_register_write( $fpga, 0x0166, ( $pixpulsea_a & 0xff00 ) >> 8, $a ); usleep($slow); + Mimosis::mimosis_register_write( $fpga, 0x0076, $pixpulsea_b & 0x00ff , $a ); usleep($slow); # analog pulsing pulse a, limit b + Mimosis::mimosis_register_write( $fpga, 0x0176, ( $pixpulsea_b & 0xff00 ) >> 8, $a ); usleep($slow); + Mimosis::mimosis_register_write( $fpga, 0x0067, $pixpulsed_a & 0x00ff , $a ); usleep($slow); # analog pulsing pulse d, limit a + Mimosis::mimosis_register_write( $fpga, 0x0167, ( $pixpulsed_a & 0xff00 ) >> 8, $a ); usleep($slow); + Mimosis::mimosis_register_write( $fpga, 0x0077, $pixpulsed_b & 0x00ff , $a ); usleep($slow); # analog pulsing pulse d, limit b + Mimosis::mimosis_register_write( $fpga, 0x0177, ( $pixpulsed_b & 0xff00 ) >> 8, $a ); usleep($slow); + Mimosis::mimosis_register_write( $fpga, 0x007d, $mod, $a ); usleep($slow); #set modpulse. possible values: 1f/1, 1f/2, 1f/4, 1f/8, 1f/16, 1f/32, 1f/64, 1f/128 + + send_params_scurve( + state => "TAKEDATA", + ySta => $ySta, + yEnd => $yEnd, + yTra => $yTra, + xSta => $xSta, + xEnd => $xEnd, + setSta => $setSta, + setEnd => $setEnd, + setTra => $setTra, + setCnt => $setCnt, + mod => $mod, + region => $region, + vcasn => 0, + singleAccess => $a + ); + await_ack(); } - -sub mimosis_scan_pixel +sub mimosis_pulse_region { my %params = @_; my $fpga = $params{'fpga'}; - my $x = $params{'x'}; - my $y = $params{'y'}; - my $add = $params{'add'}; - my $pulseonly = $params{'pulseonly'}; - my $setSta = $params{'firstset'}; - my $setEnd = $params{'lastset'}; - my $setDiv = $params{'setdiv'}; - my $setTime = $params{'settime'}; my $slow = $params{'slow'}; my $a = $params{'a'}; - my $printset = $params{'printset'}; - my $printall = $params{'printall'}; + my $region = $params{'region'}; + my $ySta = $params{'ySta'}; + my $yEnd = $params{'yEnd'}; + my $yTra = $params{'yTra'}; my $analogAlimA = $params{'analogAlimA'}; my $analogAlimB = $params{'analogAlimB'}; my $analogDlimA = $params{'analogDlimA'}; @@ -899,17 +891,15 @@ sub mimosis_scan_pixel my $modpulse = $params{'modpulse'}; defined $fpga or die "Mimosis::mimosis_scan_region: Must provide --fpga."; - defined $x or die "Mimosis::mimosis_scan_region: Must provide --x."; - defined $y or die "Mimosis::mimosis_scan_region: Must provide --y."; + defined $region or die "mimosis::mimosis_scan_region: must provide --region."; + + %rowadd = ( 'A' => 4, 'B' => 2, 'C' => 2, 'D' => 4 ); - $setSta = defined $setSta ? $setSta : 0x0; - $setEnd = defined $setEnd ? $setEnd : 0xff; - $setDiv = defined $setDiv ? $setDiv : 1; - $setTime = defined $setTime ? $setTime : 1000; $slow = defined $slow ? $slow : 10000; $a = defined $a ? $a : 0; - $printset = defined $printset ? 1 : 0; - $printall = defined $printall ? 1 : 0; + $ySta = defined $ySta ? $ySta : 0; + $yEnd = defined $yEnd ? $yEnd : 503; + $yTra = defined $yTra ? $yTra : $rowadd{$region}; $pixpulseA_A = defined $pixpulseA_A ? $pixpulseA_A : 25; $pixpulseA_B = defined $pixpulseA_B ? $pixpulseA_B : 75; $pixpulseD_A = defined $pixpulseD_A ? $pixpulseD_A : 0; @@ -918,12 +908,9 @@ sub mimosis_scan_pixel Mimosis::mimosis_register_write( $fpga, 0x0020, 0x40, $a ); usleep($slow); #EN_PIXELMASK to 0 for pulse - unless(defined $add) - { - Mimosis::mimosis_instr_write( $fpga, 0x3f ); usleep($slow); #INSTR select all pixels - Mimosis::mimosis_instr_write( $fpga, 0x04 ); usleep($slow); #INSTR reset mask - Mimosis::mimosis_instr_write( $fpga, 0x3e ); usleep($slow); #INSTR unselect all pixels - } + Mimosis::mimosis_instr_write( $fpga, 0x3f ); usleep($slow); #INSTR select all pixels + Mimosis::mimosis_instr_write( $fpga, 0x04 ); usleep($slow); #INSTR reset mask + Mimosis::mimosis_instr_write( $fpga, 0x3e ); usleep($slow); #INSTR unselect all pixels Mimosis::mimosis_register_write( $fpga, 0x0066, $pixpulseA_A & 0x00ff , $a ); usleep($slow); #analog pulsing pulse A, limit A Mimosis::mimosis_register_write( $fpga, 0x0166, ( $pixpulseA_A & 0xff00 ) >> 8, $a ); usleep($slow); @@ -935,59 +922,139 @@ sub mimosis_scan_pixel Mimosis::mimosis_register_write( $fpga, 0x0177, ( $pixpulseD_B & 0xff00 ) >> 8, $a ); usleep($slow); Mimosis::mimosis_register_write( $fpga, 0x007d, $modpulse, $a ); usleep($slow); #set modpulse. possible values: 1f/1, 1f/2, 1f/4, 1f/8, 1f/16, 1f/32, 1f/64, 1f/128 + for( my $yOff = $ySta; + $yOff <= $yEnd; + $yOff += $yTra) { - my $regAdd = $x/16; #region address - my $regBit = ($x/2)%8; #double column in region - my $regWord = $regAdd << 8; - if (($x%2 == 1)) { $regWord += 0x82; } - elsif (($x%2 == 0)) { $regWord += 0x81; } - Mimosis::mimosis_register_write( $fpga, $regWord, ( 0x1 << $regBit ), $a ); usleep($slow); - } - - { - my $regAdd = $y/8; - my $regBit = $y%8; - my $regWord = ( $regAdd << 8 ) + 0x84; - Mimosis::mimosis_register_write( $fpga, $regWord, ( 0x1 << $regBit ), $a ); usleep($slow); - } - - Mimosis::mimosis_instr_write( $fpga, 0x05 ); usleep($slow); #INSTR set mask pulse - Mimosis::mimosis_register_write( $fpga, 0x4087, 0x0, $a ); usleep($slow); #unselect all pixels (register wise) - - unless($pulseonly) - { - send_params_scurve("TAKEDATA", $y, 1, $x, $x+1, 0, 0); - await_ack(); - - my $setCnt = 0; - for my $set (reverse ($setSta .. $setEnd) ) - { - $setCnt = $setCnt + 1; - if( ($setCnt-1)%$setDiv != 0) { next; } - - my $pulseMsg = ($set << 24) + 0x00c00000; - trb_register_write_mem( $fpga, 0xa209, 0, [ $pulseMsg ], 1 ); usleep($slow); - Mimosis::mimosis_register_write( $fpga, 0x0046, $set, $a ); usleep($setTime); - - if( $printset || $printall ) { printf("set: $set\n"); } - } + my $y = $yOff; - unless(defined $add) + for(; ($y<$yOff+$yTra) && ($y <= $yEnd); $y+=1) { - Mimosis::mimosis_instr_write( $fpga, 0x3f ); usleep($slow); #INSTR select all pixels - Mimosis::mimosis_instr_write( $fpga, 0x04 ); usleep($slow); #INSTR reset mask + my $regAdd = $y/8; + my $regBit = $y%8; + my $regWord = ( $regAdd << 8 ) + 0x84; + Mimosis::mimosis_register_write( $fpga, $regWord, ( 0x1 << $regBit ), $a ); usleep($slow); + Mimosis::mimosis_instr_write( $fpga, 0x27 ); usleep($slow); #INSTR select all pixels + Mimosis::mimosis_instr_write( $fpga, 0x05 ); usleep($slow); #INSTR set mask pulse + Mimosis::mimosis_register_write( $fpga, 0x4087, 0x0, $a ); usleep($slow); #unselect all pixels (register wise) Mimosis::mimosis_instr_write( $fpga, 0x3e ); usleep($slow); #INSTR unselect all pixels } - - trb_register_write_mem( $fpga, 0xa209, 0, [ 0x00400000 ], 1 ); usleep($slow); - send_params_scurve("WAITDAQ", 0, 0, 0, 0, 0, 0); - await_ack(); - trb_register_write_mem( $fpga, 0xa209, 0, [ 0x00000000 ], 1 ); usleep($slow); } } +# sub mimosis_scan_pixel +# { +# my %params = @_; +# my $fpga = $params{'fpga'}; +# my $x = $params{'x'}; +# my $y = $params{'y'}; +# my $add = $params{'add'}; +# my $pulseonly = $params{'pulseonly'}; +# my $setSta = $params{'firstset'}; +# my $setEnd = $params{'lastset'}; +# my $setDiv = $params{'setdiv'}; +# my $setTime = $params{'settime'}; +# my $slow = $params{'slow'}; +# my $a = $params{'a'}; +# my $printall = $params{'printall'}; +# my $analogAlimA = $params{'analogAlimA'}; +# my $analogAlimB = $params{'analogAlimB'}; +# my $analogDlimA = $params{'analogDlimA'}; +# my $analogDlimB = $params{'analogDlimB'}; +# my $modpulse = $params{'modpulse'}; + +# defined $fpga or die "Mimosis::mimosis_scan_region: Must provide --fpga."; +# defined $x or die "Mimosis::mimosis_scan_region: Must provide --x."; +# defined $y or die "Mimosis::mimosis_scan_region: Must provide --y."; + +# $setSta = defined $setSta ? $setSta : 0x0; +# $setEnd = defined $setEnd ? $setEnd : 0xff; +# $setDiv = defined $setDiv ? $setDiv : 1; +# $setTime = defined $setTime ? $setTime : 1000; +# $slow = defined $slow ? $slow : 10000; +# $a = defined $a ? $a : 0; +# $printset = defined $printset ? 1 : 0; +# $printall = defined $printall ? 1 : 0; +# $pixpulseA_A = defined $pixpulseA_A ? $pixpulseA_A : 25; +# $pixpulseA_B = defined $pixpulseA_B ? $pixpulseA_B : 75; +# $pixpulseD_A = defined $pixpulseD_A ? $pixpulseD_A : 0; +# $pixpulseD_B = defined $pixpulseD_B ? $pixpulseD_B : 0; +# $modpulse = defined $modpulse ? $modpulse : 3; + +# Mimosis::mimosis_register_write( $fpga, 0x0020, 0x40, $a ); usleep($slow); #EN_PIXELMASK to 0 for pulse + +# unless(defined $add) +# { +# Mimosis::mimosis_instr_write( $fpga, 0x3f ); usleep($slow); #INSTR select all pixels +# Mimosis::mimosis_instr_write( $fpga, 0x04 ); usleep($slow); #INSTR reset mask +# Mimosis::mimosis_instr_write( $fpga, 0x3e ); usleep($slow); #INSTR unselect all pixels +# } + +# Mimosis::mimosis_register_write( $fpga, 0x0066, $pixpulseA_A & 0x00ff , $a ); usleep($slow); #analog pulsing pulse A, limit A +# Mimosis::mimosis_register_write( $fpga, 0x0166, ( $pixpulseA_A & 0xff00 ) >> 8, $a ); usleep($slow); +# Mimosis::mimosis_register_write( $fpga, 0x0076, $pixpulseA_B & 0x00ff , $a ); usleep($slow); # analog pulsing pulse A, limit B +# Mimosis::mimosis_register_write( $fpga, 0x0176, ( $pixpulseA_B & 0xff00 ) >> 8, $a ); usleep($slow); +# Mimosis::mimosis_register_write( $fpga, 0x0067, $pixpulseD_A & 0x00ff , $a ); usleep($slow); # analog pulsing pulse D, limit A +# Mimosis::mimosis_register_write( $fpga, 0x0167, ( $pixpulseD_A & 0xff00 ) >> 8, $a ); usleep($slow); +# Mimosis::mimosis_register_write( $fpga, 0x0077, $pixpulseD_B & 0x00ff , $a ); usleep($slow); # analog pulsing pulse D, limit B +# Mimosis::mimosis_register_write( $fpga, 0x0177, ( $pixpulseD_B & 0xff00 ) >> 8, $a ); usleep($slow); +# Mimosis::mimosis_register_write( $fpga, 0x007d, $modpulse, $a ); usleep($slow); #set modpulse. possible values: 1f/1, 1f/2, 1f/4, 1f/8, 1f/16, 1f/32, 1f/64, 1f/128 + +# { +# my $regAdd = $x/16; #region address +# my $regBit = ($x/2)%8; #double column in region +# my $regWord = $regAdd << 8; +# if (($x%2 == 1)) { $regWord += 0x82; } +# elsif (($x%2 == 0)) { $regWord += 0x81; } +# Mimosis::mimosis_register_write( $fpga, $regWord, ( 0x1 << $regBit ), $a ); usleep($slow); +# } + +# { +# my $regAdd = $y/8; +# my $regBit = $y%8; +# my $regWord = ( $regAdd << 8 ) + 0x84; +# Mimosis::mimosis_register_write( $fpga, $regWord, ( 0x1 << $regBit ), $a ); usleep($slow); +# } + +# Mimosis::mimosis_instr_write( $fpga, 0x05 ); usleep($slow); #INSTR set mask pulse +# Mimosis::mimosis_register_write( $fpga, 0x4087, 0x0, $a ); usleep($slow); #unselect all pixels (register wise) + +# unless($pulseonly) +# { +# send_params_scurve("TAKEDATA", $y, 1, $x, $x+1, 0, 0); +# await_ack(); + +# my $setCnt = 0; +# for my $set (reverse ($setSta .. $setEnd) ) +# { +# $setCnt = $setCnt + 1; +# if( ($setCnt-1)%$setDiv != 0) { next; } + +# my $pulseMsg = ($set << 24) + 0x00c00000; +# trb_register_write_mem( $fpga, 0xa209, 0, [ $pulseMsg ], 1 ); usleep($slow); +# Mimosis::mimosis_register_write( $fpga, 0x0046, $set, $a ); usleep($setTime); + +# if( $printset || $printall ) { printf("set: $set\n"); } +# } + +# unless(defined $add) +# { +# Mimosis::mimosis_instr_write( $fpga, 0x3f ); usleep($slow); #INSTR select all pixels +# Mimosis::mimosis_instr_write( $fpga, 0x04 ); usleep($slow); #INSTR reset mask +# Mimosis::mimosis_instr_write( $fpga, 0x3e ); usleep($slow); #INSTR unselect all pixels +# } + +# trb_register_write_mem( $fpga, 0xa209, 0, [ 0x00400000 ], 1 ); usleep($slow); +# send_params_scurve("WAITDAQ", 0, 0, 0, 0, 0, 0); +# await_ack(); +# trb_register_write_mem( $fpga, 0xa209, 0, [ 0x00000000 ], 1 ); usleep($slow); +# } +# } + + + sub mimosis_mask { my %params = @_; @@ -1312,6 +1379,33 @@ END_MESSAGE } + +sub help_analyse { + my $message = <<'END_MESSAGE'; + +usage: mimosis [GLOBAL OPTIONS] analyse [COMMAND OPTIONS] + +Analyse data from scurve scans. Needs to be executed from the run folder, where the METADATA file is. + +GLOBAL OPTIONS are: + -f, --fpga=HEX -> Hex address of the FPGA. Defaults to 0xa000. + -s, --slow=NUM -> Execute I2C commands with a pause of NUM microseconds in between. + -a, --singleaccess -> Select single access mode. + -h, --help -> Print this or specific help. + +COMMAND OPTIONS are: + --vcasn=NUM -> Analyse data from only the run where VCASN is NUM. + -t, --threads -> Number of threads to use. Defaults to 1. + + -h, --help -> Print this help. +END_MESSAGE + + print $message; + exit 0; +} + + + sub help_mask { my $message = <<'END_MESSAGE'; diff --git a/scripts/cli/mimosis b/scripts/cli/mimosis index c7ef7f5..5d2fffc 100755 --- a/scripts/cli/mimosis +++ b/scripts/cli/mimosis @@ -9,12 +9,34 @@ use Data::Dump qw(dump); use File::Copy; + $SIG{INT} = sub { Mimosis::kill_proc_by_pid_file("/tmp/hldprint-pid"); die "\nAbort.\n" }; + +my %dacs = ( + IBIAS => 0x0040, + ITHR => 0x0041, + IDB => 0x0042, + VRESET => 0x0043, + VPL => 0x0044, + VPH => 0x0045, + VPH_FINE => 0x0046, + VCASP => 0x0047, + VCASNA => 0x0048, + VCASNB => 0x0049, + VCASNC => 0x004a, + VCASND => 0x004b, + VCASN2 => 0x004c, + VCLIP => 0x004d, + IBUFBIAS => 0x004e + ); + + + #global my ( $fpga, $a, $slow ); @@ -27,9 +49,10 @@ my ( $ikf, $name, $imagefileonly, $cleanup_dacscan, $printall_dacscan ); #scurves my ( $pulseOnlySc, $regionSc, $xSc, $ySc, $addSc, $resetSc, $yStaSc, $yEndSc, $yStepSc, + $xStaSc, $xEndSc, $setStaSc, $setEndSc, $setStepSc, $vcasnSc, $vcasnStaSc, $vcasnEndSc, - $vcasnStepSc, $setTimeSc, $yTraSc, $printSetSc, $printDacSc, + $vcasnStepSc, $setCntSc, $yTraSc, $printSetSc, $printDacSc, $printRowSc, $printAllSc, $analogAlimASc, $analogAlimBSc, $analogDlimASc, $analogDlimBSc, $modpulseSc ); @@ -38,6 +61,8 @@ my ( $region_mask, $row_mask, $col_mask, $maskall_mask, $unmaskall_mask, $hline_mask, $vline_mask, $square_mask, $printall_mask ); +#analyse +my ( $vcasnAn, $threadsAn ); my @ARGV_bak = @ARGV; @@ -83,10 +108,12 @@ my $res = GetOptions ( "firstrow=s" => \$yStaSc, "lastrow=s" => \$yEndSc, "rowdiv=s" => \$yStepSc, + "firstcol=s" => \$xStaSc, + "lastcol=s" => \$xEndSc, "firstset=s" => \$setStaSc, "lastset=s" => \$setEndSc, "setdiv=s" => \$setStepSc, - "settime=s" => \$setTimeSc, + "setcounts=s" => \$setCntSc, "firstvcasn=s" => \$vcasnStaSc, "lastvcasn=s" => \$vcasnEndSc, "vcasndiv=s" => \$vcasnStepSc, @@ -106,6 +133,15 @@ my $res = GetOptions ( } }, }, + analyse => { + options => { + "vcasn" => \$vcasnAn, + "threads|t" => \$threadsAn, + 'help|h' => { + handler => \&Mimosis::help_analyse, + } + }, + }, mask => { options => { "region|r=s" => \$region_mask, @@ -235,24 +271,6 @@ elsif( $res->{subcommand}[0] eq 'dacscan' ) elsif( $res->{subcommand}[0] eq 'scurves' ) { - my %dacs = ( - IBIAS => 0x0040, - ITHR => 0x0041, - IDB => 0x0042, - VRESET => 0x0043, - VPL => 0x0044, - VPH => 0x0045, - VPH_FINE => 0x0046, - VCASP => 0x0047, - VCASNA => 0x0048, - VCASNB => 0x0049, - VCASNC => 0x004a, - VCASND => 0x004b, - VCASN2 => 0x004c, - VCLIP => 0x004d, - IBUFBIAS => 0x004e - ); - my %regCharToStr = ( A => 'VCASNA', B => 'VCASNB', @@ -260,6 +278,27 @@ elsif( $res->{subcommand}[0] eq 'scurves' ) D => 'VCASND' ); + if( defined $pulseOnlySc ) + { + Mimosis::mimosis_pulse_region( + fpga => $fpga, + slow => $slow, + a => $a, + region => $regionSc, + ySta => $yStaSc, + yEnd => $yEndSc, + yTra => $yTraSc, + xSta => $xStaSc, + xEnd => $xEndSc, + analogAlimA => $analogAlimASc, + analogAlimB => $analogAlimBSc, + analogDlimA => $analogDlimASc, + analogDlimB => $analogDlimBSc, + mod => $modpulseSc, + ); + exit 0; + } + if( defined $regionSc ) { my $vcasnStr = $regCharToStr{$regionSc}; @@ -268,10 +307,7 @@ elsif( $res->{subcommand}[0] eq 'scurves' ) $vcasnEndSc = defined $vcasnEndSc ? $vcasnEndSc : $vcasnStaSc; $vcasnStepSc = defined $vcasnStepSc ? $vcasnStepSc : 1; - unless($pulseOnlySc) - { - system("/d/jspc37/mimosis/analysis/mbs/dabc/build/bin/hldprint mbss://localhost:36789 &"); - } + system("/d/jspc37/mimosis/cpp/build/scurve-scan mbss://localhost:36789 &"); for ( my $vcasnSet = $vcasnStaSc; $vcasnSet <= $vcasnEndSc; @@ -285,103 +321,114 @@ elsif( $res->{subcommand}[0] eq 'scurves' ) fpga => $fpga, slow => $slow, a => $a, - pulseonly => $pulseOnlySc, - add => $addSc, region => $regionSc, - firstrow => $yStaSc, - lastrow => $yEndSc, - rowdiv => $yStepSc, - rowsatonce => $yTraSc, - firstset => $setStaSc, - lastset => $setEndSc, - setdiv => $setStepSc, - settime => $setTimeSc, - printset => $printSetSc, - printrow => $printRowSc, - printall => $printAllSc, + ySta => $yStaSc, + yEnd => $yEndSc, + yTra => $yTraSc, + xSta => $xStaSc, + xEnd => $xEndSc, + setSta => $setStaSc, + setEnd => $setEndSc, + setTra => $setStepSc, + setCnt => $setCntSc, analogAlimA => $analogAlimASc, analogAlimB => $analogAlimBSc, analogDlimA => $analogDlimASc, analogDlimB => $analogDlimBSc, - modpulse => $modpulseSc, + mod => $modpulseSc, ); - unless($pulseOnlySc) - { - Mimosis::send_params_scurve("FIT", 0,0,0,0,$regCharToStr{$regionSc},$vcasnSet); - Mimosis::await_ack(); - } - } - - unless($pulseOnlySc) - { - Mimosis::send_params_scurve("DONE", 0,0,0,0,0,0); + Mimosis::send_params_scurve( + state => "FIT", + region => $regCharToStr{$regionSc}, + vcasn => $vcasnSet + ); Mimosis::await_ack(); - Mimosis::kill_proc_by_pid_file("/tmp/hldprint-pid"); } + + Mimosis::send_params_scurve( state => "DONE" ); + Mimosis::await_ack(); + Mimosis::kill_proc_by_pid_file("/tmp/hldprint-pid"); exit 0; } elsif (defined $xSc && defined $ySc && defined $vcasnSc) { - my $vcasnVal = Mimosis::mimosis_register_read( $fpga, $dacs{$vcasnSc}, $a ); - $vcasnStaSc = defined $vcasnStaSc ? $vcasnStaSc : $vcasnVal; - $vcasnEndSc = defined $vcasnEndSc ? $vcasnEndSc : $vcasnStaSc; - $vcasnStepSc = defined $vcasnStepSc ? $vcasnStepSc : 1; - - unless($pulseOnlySc) - { - system("/d/jspc37/mimosis/analysis/mbs/dabc/build/bin/hldprint mbss://localhost:36789 &"); - } + # my $vcasnVal = Mimosis::mimosis_register_read( $fpga, $dacs{$vcasnSc}, $a ); + # $vcasnStaSc = defined $vcasnStaSc ? $vcasnStaSc : $vcasnVal; + # $vcasnEndSc = defined $vcasnEndSc ? $vcasnEndSc : $vcasnStaSc; + # $vcasnStepSc = defined $vcasnStepSc ? $vcasnStepSc : 1; + + # unless($pulseOnlySc) + # { + # system("/d/jspc37/mimosis/cpp/build/scurve-scan mbss://localhost:36789 &"); + # } + + # for ( my $vcasnSet = $vcasnStaSc; + # $vcasnSet <= $vcasnEndSc; + # $vcasnSet += $vcasnStepSc ) { + # #set vcasn + # Mimosis::mimosis_register_write( $fpga, $dacs{$vcasnSc}, $vcasnSet, $a ); usleep($slow); + + # if( $printDacSc || $printAllSc ) { printf("dac: $vcasnSet\n"); } + + # Mimosis::mimosis_scan_pixel( + # fpga => $fpga, + # slow => $slow, + # a => $a, + # x => $xSc, + # y => $ySc, + # pulseonly => $pulseOnlySc, + # firstset => $setStaSc, + # lastset => $setEndSc, + # setdiv => $setStepSc, + # settime => $setCntSc, + # printset => $printSetSc, + # printrow => $printRowSc, + # printall => $printAllSc, + # analogAlimA => $analogAlimASc, + # analogAlimB => $analogAlimBSc, + # analogDlimA => $analogDlimASc, + # analogDlimB => $analogDlimBSc, + # modpulse => $modpulseSc, + # ); + + # unless($pulseOnlySc) + # { + # Mimosis::send_params_scurve("FIT", 0,0,0,0,$vcasnSc,$vcasnSet); + # Mimosis::await_ack(); + # } + # } + + # unless($pulseOnlySc) + # { + # Mimosis::send_params_scurve("DONE", 0,0,0,0,0,0); + # Mimosis::await_ack(); + # Mimosis::kill_proc_by_pid_file("/tmp/hldprint-pid"); + # } + # exit 0; - for ( my $vcasnSet = $vcasnStaSc; - $vcasnSet <= $vcasnEndSc; - $vcasnSet += $vcasnStepSc ) { - #set vcasn - Mimosis::mimosis_register_write( $fpga, $dacs{$vcasnSc}, $vcasnSet, $a ); usleep($slow); + } else { - if( $printDacSc || $printAllSc ) { printf("dac: $vcasnSet\n"); } + print "Mimosis::mimosis_scan_region: Must provide --region A|B|C|D or --x X and --y Y.\n"; + exit 1; + } +} - Mimosis::mimosis_scan_pixel( - fpga => $fpga, - slow => $slow, - a => $a, - x => $xSc, - y => $ySc, - pulseonly => $pulseOnlySc, - firstset => $setStaSc, - lastset => $setEndSc, - setdiv => $setStepSc, - settime => $setTimeSc, - printset => $printSetSc, - printrow => $printRowSc, - printall => $printAllSc, - analogAlimA => $analogAlimASc, - analogAlimB => $analogAlimBSc, - analogDlimA => $analogDlimASc, - analogDlimB => $analogDlimBSc, - modpulse => $modpulseSc, - ); +elsif( $res->{subcommand}[0] eq 'analyse' ) +{ + my %regCharToStr = ( + A => 'VCASNA', + B => 'VCASNB', + C => 'VCASNC', + D => 'VCASND' + ); - unless($pulseOnlySc) - { - Mimosis::send_params_scurve("FIT", 0,0,0,0,$vcasnSc,$vcasnSet); - Mimosis::await_ack(); - } - } + open(FH, '<', 'METADATA') or die print "Cannot open METADATA. Is this a vild run dir?\n"; - unless($pulseOnlySc) - { - Mimosis::send_params_scurve("DONE", 0,0,0,0,0,0); - Mimosis::await_ack(); - Mimosis::kill_proc_by_pid_file("/tmp/hldprint-pid"); - } - exit 0; + # system("/d/jspc37/mimosis/scripts/pulse/plot-raw.py"); - } else { - print "Mimosis::mimosis_scan_region: Must provide --region A|B|C|D or --x X and --y Y.\n"; - exit 1; - } + exit 0; } elsif( $res->{subcommand}[0] eq 'mask' ) diff --git a/scripts/pulse/fit-raw.py b/scripts/pulse/fit-raw.py index 535e4ab..0a9636d 100644 --- a/scripts/pulse/fit-raw.py +++ b/scripts/pulse/fit-raw.py @@ -31,7 +31,7 @@ for i in range(len(df.loc[:])): if df.loc[i][j] != 0: xS.append(j) - print(xS) +# print(xS) if sum(df.loc[i][0:255]) != 0: -- 2.43.0