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})
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}
${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
)
+++ /dev/null
-#include <cstdio>
-#include <cstring>
-#include <csignal>
-#include <unistd.h>
-#include <iostream>
-#include <fstream>
-#include <vector>
-#include <chrono>
-#include <array>
-#include <sys/stat.h>
-
-//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<uint32_t,1025*505*256> 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<std::string> 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<uint32_t> mimFraCntNewVec;
- std::vector<uint32_t> 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<std::string> 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<std::string> values;
-
- buf = fgetc(iPipe);
-
- while(!foundFrame && buf != EOF)
- {
- char c = static_cast<char>(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<size; i++)
- {
- uint32_t data = static_cast<uint32_t>(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<seconds>(stop - Data::start);
- file << "TIME(s):" << '\t' << duration.count() << '\n';
-
- file << "COMMENT:\t<insert comment here>\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<std::string> 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;
- }
-}
#include <iostream>
+#include <vector>
+#include <unistd.h>
+
+#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<uint32_t>(((r&0xff)<<24)+((d&0xff)<<16)+(r&0xff00)+MIM_I2C_ADD_LSB)
+#define GEN_PAYLOAD_RD(r) static_cast<uint32_t>(((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<uint32_t>(((r&0xff00)<<8)+MIM_I2C_ADD_LSB)
+#define GEN_ADD_MSB(r) static_cast<uint32_t>(((r&0xff)<<16)+MIM_I2C_ADD_MSB)
+#define GEN_WR(d) static_cast<uint32_t>(((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<uint32_t> 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<uint32_t> 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;
+}
-#include <iostream>
-#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
--- /dev/null
+#include <cstdio>
+#include <cstring>
+#include <csignal>
+#include <unistd.h>
+#include <stdio.h>
+#include <math.h>
+#include <iostream>
+#include <fstream>
+#include <vector>
+#include <chrono>
+#include <array>
+#include <sys/stat.h>
+
+//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<unsigned,1024*504*256> 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<std::string> 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<std::string> 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<std::string> values;
+
+ buf = fgetc(iPipe);
+
+ while(!foundFrame && buf != EOF)
+ {
+ char c = static_cast<char>(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<int>(std::pow(2.0,static_cast<double>(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<microseconds>(stop-start);
+
+ for(int mimTra = 0;
+ mimTra<maxCounts;
+ mimTra++)
+ {
+ 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<size; i++)
+ {
+ uint32_t data = static_cast<uint32_t>(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<int>(std::pow(2.0,static_cast<double>(modPulse)));
+
+ int modFound = -1;
+
+ const int modN = 2;
+ std::vector<int> 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<size; i++)
+ {
+ uint32_t data = static_cast<uint32_t>(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<seconds>(stop - Data::start);
+ file << "TIME(s):" << '\t' << duration.count() << '\n';
+
+ file << "COMMENT:\t<insert comment here>\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<std::string> 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;
+ }
+}
}
+
sub mimosis_register_read
{
my ( $fpga, $mimosis_reg, $singleaccess) = @_;
}
-
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));
{
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);
{
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'};
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;
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);
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 = @_;
}
+
+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 <command> 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';
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 );
#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 );
$maskall_mask, $unmaskall_mask, $hline_mask,
$vline_mask, $square_mask, $printall_mask );
+#analyse
+my ( $vcasnAn, $threadsAn );
my @ARGV_bak = @ARGV;
"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,
}
},
},
+ analyse => {
+ options => {
+ "vcasn" => \$vcasnAn,
+ "threads|t" => \$threadsAn,
+ 'help|h' => {
+ handler => \&Mimosis::help_analyse,
+ }
+ },
+ },
mask => {
options => {
"region|r=s" => \$region_mask,
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',
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};
$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;
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' )
if df.loc[i][j] != 0:
xS.append(j)
- print(xS)
+# print(xS)
if sum(df.loc[i][0:255]) != 0: