diff --git a/CMakeLists.txt b/CMakeLists.txt index 29ddef2..2d2d940 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -11,7 +11,7 @@ # Chu-Ping Yu # -cmake_minimum_required(VERSION 3.16.0) +cmake_minimum_required(VERSION 3.21.0) project(RICOM LANGUAGES C CXX) set(CMAKE_CXX_STANDARD 17) @@ -77,14 +77,15 @@ if (WIN32) file(COPY ${SDL2_LIB_DIR}/SDL2_image.dll DESTINATION ${BUILD_DIR}) file(COPY ${FFTW3_DIR}/libfftw3f-3.dll DESTINATION ${BUILD_DIR}) file(COPY ${FFTW3_DIR}/libfftw3f-3.lib DESTINATION ${BUILD_DIR}) + set(CMAKE_EXE_LINKER_FLAGS "${CMAKE_EXE_LINKER_FLAGS} /STACK:10485760") endif (WIN32) add_executable(RICOM src/main.cpp) target_sources( RICOM PRIVATE - imgui/misc/cpp/imgui_stdlib.cpp - imgui/imgui_draw.cpp - imgui/imgui_tables.cpp +imgui/misc/cpp/imgui_stdlib.cpp +imgui/imgui_draw.cpp +imgui/imgui_tables.cpp imgui/imgui_widgets.cpp imgui/backends/imgui_impl_opengl3.cpp imgui/backends/imgui_impl_sdl.cpp @@ -93,6 +94,8 @@ target_sources( RICOM PRIVATE src/FileConnector.cpp src/ProgressMonitor.cpp src/Ricom.cpp + src/cameras/CheetahInterface.cpp + src/cameras/CheetahWrapper.cpp src/cameras/TimepixInterface.cpp src/cameras/TimepixWrapper.cpp src/cameras/MerlinInterface.cpp @@ -106,7 +109,21 @@ target_sources( RICOM PRIVATE src/RunGUI.cpp ) -target_include_directories( RICOM PUBLIC +## cpr +include(FetchContent) +FetchContent_Declare(cpr GIT_REPOSITORY https://github.com/libcpr/cpr.git + GIT_TAG 0817715923c9705e68994eb52ef9df3f6845beba) # The commit hash for 1.10.x. Replace with the latest from: https://github.com/libcpr/cpr/releases +set(CPR_ENABLE_SSL OFF) +FetchContent_MakeAvailable(cpr) +target_link_libraries(RICOM PRIVATE cpr::cpr) +##json +# include(FetchContent) +# FetchContent_Declare(json URL https://github.com/nlohmann/json/releases/download/v3.11.2/json.tar.xz) +# FetchContent_MakeAvailable(json) +# target_link_libraries(RICOM PRIVATE nlohmann_json::nlohmann_json) +set(JSON_BuildTests OFF CACHE INTERNAL "") + +target_include_directories( RICOM PRIVATE imgui imgui/backends imgui/misc/cpp @@ -119,9 +136,15 @@ target_include_directories( RICOM PUBLIC find_package(OpenGL REQUIRED) -target_link_libraries(RICOM PUBLIC ${OPENGL_LIBRARIES}) + + +target_link_libraries(RICOM PRIVATE ${OPENGL_LIBRARIES}) if (WIN32) - target_link_libraries(RICOM PUBLIC SDL2main SDL2 SDL2_image libfftw3f-3 ${CMAKE_DL_LIBS}) + target_link_libraries(RICOM PRIVATE SDL2main SDL2 SDL2_image libfftw3f-3 ${CMAKE_DL_LIBS}) + add_custom_command(TARGET RICOM POST_BUILD + COMMAND ${CMAKE_COMMAND} -E copy -t $ $ + COMMAND_EXPAND_LISTS + ) else () - target_link_libraries(RICOM PUBLIC SDL2main SDL2 SDL2_image fftw3f ${CMAKE_DL_LIBS}) + target_link_libraries(RICOM PRIVATE SDL2main SDL2 SDL2_image fftw3f ${CMAKE_DL_LIBS}) endif (WIN32) \ No newline at end of file diff --git a/src/Camera.cpp b/src/Camera.cpp index 7c61622..e974453 100644 --- a/src/Camera.cpp +++ b/src/Camera.cpp @@ -14,6 +14,7 @@ #include "Camera.h" #include "MerlinInterface.h" #include "TimepixInterface.h" +#include "CheetahInterface.h" using namespace CAMERA; @@ -38,6 +39,7 @@ Default_configurations::Default_configurations() hws_ptr = &hws[0]; hws[MERLIN] = Camera(); hws[TIMEPIX] = Camera(); + hws[CHEETAH] = Camera(); }; CAMERA::Camera_BASE &Default_configurations::operator[](unsigned int index) diff --git a/src/Camera.h b/src/Camera.h index 1ea2301..f6a3046 100644 --- a/src/Camera.h +++ b/src/Camera.h @@ -22,12 +22,15 @@ // Only forward declaration for Ricom class class Ricom; + + namespace CAMERA { enum Camera_model { MERLIN, TIMEPIX, + CHEETAH, MODELS_COUNT }; @@ -93,14 +96,14 @@ namespace CAMERA void read_frame_com( std::vector &dose_map, std::vector &sumx_map, std::vector &sumy_map, - std::vector &stem_map, bool b_stem, + std::vector &stem_map, bool &b_stem, std::array &offset, std::array &radius, int &processor_line, int &preprocessor_line, size_t &first_frame, size_t &end_frame ); void read_frame_com_cbed( std::vector &dose_map, std::vector &sumx_map, std::vector &sumy_map, - std::vector &stem_map, bool b_stem, + std::vector &stem_map, bool &b_stem, std::array &offset, std::array &radius, std::vector &frame, std::array, 3> &frame_id_plot_cbed, int &processor_line, int &preprocessor_line, size_t &first_frame, size_t &end_frame diff --git a/src/Ricom.cpp b/src/Ricom.cpp index 68537e4..9865dd4 100644 --- a/src/Ricom.cpp +++ b/src/Ricom.cpp @@ -1190,10 +1190,12 @@ void Ricom::run_reconstruction(RICOM::modes mode) // Template specializations, necessary to avoid linker error template void Ricom::run_reconstruction(RICOM::modes); template void Ricom::run_reconstruction(RICOM::modes); +template void Ricom::run_reconstruction(RICOM::modes); template void Ricom::process_data(CAMERA::Camera *camera_spec); template void Ricom::process_data(CAMERA::Camera *camera_spec); template void Ricom::process_data(CAMERA::Camera *camera_spec); template void Ricom::process_data(CAMERA::Camera *camera_spec); +template void Ricom::process_data(CAMERA::Camera *camera_spec); // Helper functions void Ricom::reset_limits() @@ -1236,6 +1238,11 @@ enum CAMERA::Camera_model Ricom::select_mode_by_file(const char *filename) mode = RICOM::FILE; return CAMERA::MERLIN; } + else if (std::filesystem::path(filename).extension() == ".tpx3") + { + mode = RICOM::FILE; + return CAMERA::CHEETAH; + } else { return CAMERA::TIMEPIX; @@ -1252,6 +1259,9 @@ void RICOM::run_ricom(Ricom *r, RICOM::modes mode) case CAMERA::TIMEPIX: r->run_reconstruction(mode); break; + case CAMERA::CHEETAH: + r->run_reconstruction(mode); + break; default: break; } diff --git a/src/Ricom.h b/src/Ricom.h index 5b40205..67db077 100644 --- a/src/Ricom.h +++ b/src/Ricom.h @@ -44,6 +44,7 @@ #include "SocketConnector.h" #include "ProgressMonitor.h" #include "MerlinInterface.h" +#include "CheetahInterface.h" #include "TimepixInterface.h" #include "Camera.h" #include "GuiUtils.h" diff --git a/src/RunGUI.cpp b/src/RunGUI.cpp index 4184302..9bddc75 100644 --- a/src/RunGUI.cpp +++ b/src/RunGUI.cpp @@ -163,7 +163,7 @@ int run_gui(Ricom *ricom, CAMERA::Default_configurations &hardware_configuration // create a file browser instances ImGui::FileBrowser openFileDialog; openFileDialog.SetTitle("Open .mib or .t3p file"); - openFileDialog.SetTypeFilters({".mib", ".t3p"}); + openFileDialog.SetTypeFilters({".mib", ".t3p", ".tpx3"}); ImGui::FileBrowser saveFileDialog(ImGuiFileBrowserFlags_EnterNewFilename | ImGuiFileBrowserFlags_CreateNewDir); saveFileDialog.SetTitle("Save image as .png"); ImGui::FileBrowser saveDataDialog(ImGuiFileBrowserFlags_EnterNewFilename | ImGuiFileBrowserFlags_CreateNewDir); @@ -181,6 +181,11 @@ int run_gui(Ricom *ricom, CAMERA::Default_configurations &hardware_configuration // Merlin Settings (to send to the Camera) struct MerlinSettings merlin_settings; + // Cheetah Setting (to send to the server) + CheetahComm cheetah_comm; + ricom->socket.connect_socket(); + + // INI file settings to restore previous session settings // Appearance int font_index = 0; @@ -211,6 +216,11 @@ int run_gui(Ricom *ricom, CAMERA::Default_configurations &hardware_configuration // Timepix Settings ImGuiINI::check_ini_setting(ini_cfg, "Timepix", "nx", hardware_configurations[CAMERA::MERLIN].nx_cam); ImGuiINI::check_ini_setting(ini_cfg, "Timepix", "ny", hardware_configurations[CAMERA::MERLIN].ny_cam); + // Cheetah Settings + ImGuiINI::check_ini_setting(ini_cfg, "Cheetah", "nx", hardware_configurations[CAMERA::CHEETAH].nx_cam); + ImGuiINI::check_ini_setting(ini_cfg, "Cheetah", "ny", hardware_configurations[CAMERA::CHEETAH].ny_cam); + ImGuiINI::check_ini_setting(ini_cfg, "Merlin", "data_port", ricom->socket.port); + ImGuiINI::check_ini_setting(ini_cfg, "Merlin", "ip", ricom->socket.ip); const char *cmaps[] = {"Parula", "Heat", "Jet", "Turbo", "Hot", "Gray", "Magma", "Inferno", "Plasma", "Viridis", "Cividis", "Github", "HSV"}; bool b_redraw = false; @@ -343,6 +353,15 @@ int run_gui(Ricom *ricom, CAMERA::Default_configurations &hardware_configuration ini_cfg["Timepix"]["ny"] = std::to_string(hardware_configurations[CAMERA::TIMEPIX].ny_cam); } + ImGui::Text("Cheetah Camera"); + if (ImGui::DragScalar("nx Cheetah", ImGuiDataType_U16, &hardware_configurations[CAMERA::CHEETAH].nx_cam, 1, &drag_min_pos)) + { + ini_cfg["Cheetah"]["nx"] = std::to_string(hardware_configurations[CAMERA::CHEETAH].nx_cam); + } + if (ImGui::DragScalar("ny Cheetah", ImGuiDataType_U16, &hardware_configurations[CAMERA::CHEETAH].ny_cam, 1, &drag_min_pos)) + { + ini_cfg["Cheetah"]["ny"] = std::to_string(hardware_configurations[CAMERA::CHEETAH].ny_cam); + } ImGui::EndMenu(); } if (ImGui::BeginMenu("Additional Imaging Modes")) @@ -562,6 +581,57 @@ int run_gui(Ricom *ricom, CAMERA::Default_configurations &hardware_configuration } } + if (ImGui::CollapsingHeader("Stream reconstruction", ImGuiTreeNodeFlags_DefaultOpen)){ + + if (ImGui::Button("Preview", ImVec2(-1.0f, 0.0f))) + { + cheetah_comm.stop(); + ricom->b_continuous = true; + cheetah_comm.tpx3_det_config(); + cheetah_comm.tpx3_cam_init(); + cheetah_comm.tpx3_destination(); + + + // ricom->socket.connect_socket(); + // ricom->socket.flush_socket(); + b_started = true; + b_restarted = true; + run_thread = std::thread(RICOM::run_ricom, ricom, RICOM::TCP); + run_thread.detach(); + std::this_thread::sleep_for(std::chrono::milliseconds(500)); + cheetah_comm.start(); + // RICOM::run_ricom(ricom, RICOM::TCP); + GENERIC_WINDOW("RICOM").set_data(ricom->nx, ricom->ny, &ricom->ricom_data); + } + + if (ImGui::Button("Acquire", ImVec2(-1.0f, 0.0f))) + { + cheetah_comm.stop(); + ricom->b_continuous = false; + cheetah_comm.tpx3_det_config(); + cheetah_comm.tpx3_cam_init(); + cheetah_comm.tpx3_destination(); + + run_thread = std::thread(RICOM::run_ricom, ricom, RICOM::TCP); + run_thread.detach(); + std::this_thread::sleep_for(std::chrono::milliseconds(500)); + cheetah_comm.start(); + GENERIC_WINDOW("RICOM").set_data(ricom->nx, ricom->ny, &ricom->ricom_data); + } + + if (ImGui::Button("Stop", ImVec2(-1.0f, 0.0f))) + { + cheetah_comm.stop(); + ricom->rc_quit = true; + ricom->b_continuous = false; + // b_redraw = true; + } + + ImGui::Checkbox("Cumulative Mode", &ricom->b_cumulative); + + } + + if (ImGui::CollapsingHeader("File reconstruction", ImGuiTreeNodeFlags_DefaultOpen)) { diff --git a/src/SocketConnector.cpp b/src/SocketConnector.cpp index 1cde7e6..0259053 100644 --- a/src/SocketConnector.cpp +++ b/src/SocketConnector.cpp @@ -19,11 +19,11 @@ int SocketConnector::read_data(char *buffer, int data_size) while (bytes_payload_total < data_size) { - int bytes_payload_count = recv(rc_socket, + int bytes_payload_count = recv(client_socket, &buffer[bytes_payload_total], data_size - bytes_payload_total, 0); - + std::cout << bytes_payload_count << std::endl; if (bytes_payload_count == -1) { perror("Error reading Data!"); @@ -48,7 +48,7 @@ void SocketConnector::flush_socket() while (true) { - int bytes_count = recv(rc_socket, &buffer[0], 1, 0); + int bytes_count = recv(client_socket, &buffer[0], 1, 0); if (bytes_count <= 0) { @@ -60,6 +60,52 @@ void SocketConnector::flush_socket() close_socket(); } +void SocketConnector::accept_socket(){ + client_socket = -1; + socklen_t addrlen = sizeof(c_address); + while (client_socket == -1) { + client_socket = accept(rc_socket, (struct sockaddr*)&c_address, &addrlen); + } +} + +void SocketConnector::init_listen(){ + int bindResult = bind(rc_socket, (struct sockaddr*)&address, sizeof(address)); + if (bindResult == -1) { + handle_socket_errors("binding the Socket"); + } + + int listenResult = listen(rc_socket, 1); // Queue up to 5 pending connections + if (listenResult == -1) { + handle_socket_errors("listening on the Socket"); + } + else + { + b_connected = true; + } +} + +void SocketConnector::init_connect(){ + // Connecting socket to the port + int error_counter = 0; + while (true) + { + if (connect(rc_socket, (struct sockaddr *)&address, sizeof(address)) == SOCKET_ERROR) + { + if (error_counter < 1) + { + handle_socket_errors("connecting to Socket"); + } + error_counter++; + } + else + { + std::cout << "Connected by " << inet_ntoa(address.sin_addr) << "\n"; + b_connected = true; + break; + } + } +} + void SocketConnector::connect_socket() { #ifdef WIN32 @@ -72,6 +118,7 @@ void SocketConnector::connect_socket() // Creating socket file descriptor rc_socket = socket(AF_INET, SOCK_STREAM, 0); + if (rc_socket == INVALID_SOCKET) { handle_socket_errors("intitializing Socket"); @@ -86,26 +133,13 @@ void SocketConnector::connect_socket() address.sin_addr.s_addr = inet_addr(ip.c_str()); address.sin_port = htons(port); - std::cout << "Waiting for incoming connection..." << std::endl; - - // Connecting socket to the port - int error_counter = 0; - while (true) + if (socket_type == Socket_type::CLIENT) { - if (connect(rc_socket, (struct sockaddr *)&address, sizeof(address)) == SOCKET_ERROR) - { - if (error_counter < 1) - { - handle_socket_errors("connecting to Socket"); - } - error_counter++; - } - else - { - std::cout << "Connected by " << inet_ntoa(address.sin_addr) << "\n"; - b_connected = true; - break; - } + init_connect(); + } + else if (socket_type == Socket_type::SERVER) + { + init_listen(); } } @@ -125,6 +159,7 @@ void SocketConnector::handle_socket_errors(const std::string &raised_at) void SocketConnector::close_socket() { closesocket(rc_socket); + b_connected = false; WSACleanup(); } #else @@ -137,5 +172,6 @@ void SocketConnector::handle_socket_errors(const std::string &raised_at) void SocketConnector::close_socket() { close(rc_socket); + b_connected = false; } #endif diff --git a/src/SocketConnector.h b/src/SocketConnector.h index d4e3866..99c7c75 100644 --- a/src/SocketConnector.h +++ b/src/SocketConnector.h @@ -33,10 +33,13 @@ #include #include +enum Socket_type {SERVER,CLIENT}; class SocketConnector { public: SOCKET rc_socket; + SOCKET client_socket; + Socket_type socket_type; bool b_connected; std::string ip; @@ -47,13 +50,18 @@ class SocketConnector void flush_socket(); void connect_socket(); void close_socket(); + void accept_socket(); SocketConnector() : rc_socket(INVALID_SOCKET), b_connected(false), ip("127.0.0.1"), - port(6342){}; + // port(6342){}; // merlin + port(8451){}; // cheetah private: struct sockaddr_in address; + struct sockaddr_in c_address; + void init_connect(); + void init_listen(); #ifdef WIN32 WSADATA w; const char opt = 1; @@ -62,4 +70,4 @@ class SocketConnector #endif void handle_socket_errors(const std::string &raised_at); }; -#endif // SOCKET_CONNECTOR_H \ No newline at end of file +#endif // SOCKET_CONNECTOR_H diff --git a/src/cameras/CheetahInterface.cpp b/src/cameras/CheetahInterface.cpp new file mode 100644 index 0000000..8e7503c --- /dev/null +++ b/src/cameras/CheetahInterface.cpp @@ -0,0 +1,444 @@ +/* Copyright (C) 2021 Thomas Friedrich, Chu-Ping Yu, + * University of Antwerp - All Rights Reserved. + * You may use, distribute and modify + * this code under the terms of the GPL3 license. + * You should have received a copy of the GPL3 license with + * this file. If not, please visit: + * https://www.gnu.org/licenses/gpl-3.0.en.html + * + * Authors: + * Thomas Friedrich + * Chu-Ping Yu + */ + +#include "CheetahInterface.h" + +const bool b_false = false; +const bool b_true = true; +std::vector dummy_frame(1); +std::array, 3> dummy_frame_id_plot_cbed; + +void CheetahInterface::read_frame_com( + std::vector &dose_map, + std::vector &sumx_map, std::vector &sumy_map, + std::vector &stem_map, bool &b_stem, + std::array &offset, std::array &radius, + int &processor_line, int &preprocessor_line) +{ + real_read(dose_map, sumx_map, sumy_map, stem_map, b_stem, offset, radius, dummy_frame, dummy_frame_id_plot_cbed, processor_line, preprocessor_line, b_false); +} + +void CheetahInterface::read_frame_com( + std::vector &dose_map, + std::vector &sumx_map, std::vector &sumy_map, + std::vector &stem_map, bool &b_stem, + std::array &offset, std::array &radius, + std::vector &frame, std::array, 3> &frame_id_plot_cbed, + int &processor_line, int &preprocessor_line) +{ + real_read(dose_map, sumx_map, sumy_map, stem_map, b_stem, offset, radius, frame, frame_id_plot_cbed, processor_line, preprocessor_line, b_true); +} + +void CheetahInterface::real_read( + std::vector &dose_map, + std::vector &sumx_map, + std::vector &sumy_map, + std::vector &stem_map, + bool &b_stem, + std::array &offset, + std::array &radius, + std::vector &frame, std::array, 3> &frame_id_plot_cbed, + int &processor_line, int &preprocessor_line, bool b_cbed) +{ + if (!read_started) + { + reset(); + read_started = true; + switch (mode) + { + case MODE_FILE: + read_guy = std::thread(&CheetahInterface::read_file, this, &file, &processor_line); + break; + case MODE_TCP: + socket->accept_socket(); + read_guy = std::thread(&CheetahInterface::read_socket, this, socket, &processor_line); + break; + } + read_guy.detach(); + } + + if (!proc_started) + { + proc_started = true; + proc_guy = std::thread(&CheetahInterface::process_buffer, this, &dose_map, &sumx_map, &sumy_map, &stem_map, &b_stem, &offset, &radius, &frame, &frame_id_plot_cbed, &processor_line, &preprocessor_line, &b_cbed); + proc_guy.detach(); + } + + if (finish & read_guy.joinable()) + { + read_guy.join(); + } + if (finish & proc_guy.joinable()) + { + proc_guy.join(); + } +} + +void CheetahInterface::read_file(FileConnector *file, int *bc) +{ + int buffer_id; + while (*bc != -1) + { + if (n_buffer_filled < (n_buffer + n_buffer_processed)) + { + buffer_id = n_buffer_filled % n_buffer; + file->read_data((char *)&buffer[buffer_id], sizeof(buffer[buffer_id])); + ++n_buffer_filled; + } + else + { + std::this_thread::sleep_for(std::chrono::milliseconds(1)); + } + } +} + +void CheetahInterface::read_socket(SocketConnector *socket, int *bc) +{ + while (*bc != -1) + { + if (n_buffer_filled < (n_buffer + n_buffer_processed)) + { + int buffer_id = n_buffer_filled % n_buffer; + socket->read_data((char *)&buffer[buffer_id], sizeof(buffer[buffer_id])); + ++n_buffer_filled; + // std::cout << n_buffer_filled << std::endl; + } + else + { + std::this_thread::sleep_for(std::chrono::milliseconds(1)); + printf("read wait\n"); + } + } + std::cout << "n_buffer_filled" << std::endl; +} + +void CheetahInterface::process_buffer( + std::vector *dose_map, + std::vector *sumx_map, + std::vector *sumy_map, + std::vector *stem_map, + bool *b_stem, + std::array *offset, + std::array *radius, + std::vector *frame, std::array, 3> *frame_id_plot_cbed, + int *processor_line, int *preprocessor_line, bool *b_cbed) +{ + int type; + int buffer_id; + + while (*processor_line != -1) + { + // std::cout << n_buffer_filled << "," << n_buffer_processed << std::endl; + if (n_buffer_processed < n_buffer_filled) + { + buffer_id = n_buffer_processed % n_buffer; + for (int j = 0; j < preloc_size; j++) + { + type = which_type(&buffer[buffer_id][j], stem_map); + if ((type == 2) & rise_fall[chip_id] & (line_count[chip_id] != 0)) + { + // if (*b_cbed) + // { + // process_event( + // &buffer[buffer_id][j], + // dose_map, sumx_map, sumy_map, + // stem_map, b_stem, + // offset, radius, frame, frame_id_plot_cbed); + // } + // else + // { + // process_event( + // &buffer[buffer_id][j], + // dose_map, sumx_map, sumy_map, + // stem_map, b_stem, + // offset, radius); + // } + process_event( + &buffer[buffer_id][j], + dose_map, sumx_map, sumy_map, + stem_map, b_stem, + offset, radius); + } + } + ++n_buffer_processed; + *preprocessor_line = total_line; + } + else + { + std::this_thread::sleep_for(std::chrono::milliseconds(1)); + // printf("slow read\n"); + } + } +} + +int CheetahInterface::which_type(uint64_t *packet, std::vector *stem_map) +{ + // if ( (*packet & ((1 << 32) - 1) == tpx_header) ) { + if ((*packet & 0xFFFFFFFF) == tpx_header) + { + chip_id = (*packet >> 32) & 0xff; + return 0; + } // header + else if (*packet >> 60 == 0x6) + { + process_tdc(packet, stem_map); + return 1; + } // TDC + else if (*packet >> 60 == 0xb) + { + return 2; + } // event + else + { + return 3; + } // unknown +} + +void CheetahInterface::process_tdc(uint64_t *packet, std::vector *stem_map) +{ + if (((*packet >> 56) & 0x0F) == 15) + { + rise_fall[chip_id] = true; + rise_t[chip_id] = (((*packet >> 9) & 0x7FFFFFFFF) % 8589934592); + } + else if (((*packet >> 56) & 0x0F) == 10) + { + rise_fall[chip_id] = false; + fall_t[chip_id] = ((*packet >> 9) & 0x7FFFFFFFF) % 8589934592; + ++line_count[chip_id]; + // line_count[chip_id] %= scan_y; + + if ((line_count[chip_id] <= line_count[0]) & + (line_count[chip_id] <= line_count[1]) & + (line_count[chip_id] <= line_count[2]) & + (line_count[chip_id] <= line_count[3])) + { total_line = line_count[chip_id]; } + + if ((line_count[chip_id] >= line_count[0]) & + (line_count[chip_id] >= line_count[1]) & + (line_count[chip_id] >= line_count[2]) & + (line_count[chip_id] >= line_count[3])) + { + most_advanced_line = line_count[chip_id]; + if ( (most_advanced_line+3)%scan_y < (most_advanced_line+2)%scan_y ){ + std::fill( + (*stem_map).begin()+(((most_advanced_line+2)%scan_y)*scan_x), + (*stem_map).end(), 0); + } + else { + std::fill( + (*stem_map).begin()+(((most_advanced_line+2)%scan_y)*scan_x), + (*stem_map).begin()+(((most_advanced_line+2)%scan_y)*scan_x)+scan_x, 0); + } + } + + line_interval = (fall_t[chip_id] - rise_t[chip_id]) * 2; + dwell_time = line_interval / scan_x; + } +} + +void CheetahInterface::process_event( + uint64_t *packet, + std::vector *dose_map, + std::vector *sumx_map, + std::vector *sumy_map, + std::vector *stem_map, + bool *b_stem, + std::array *offset, + std::array *radius) +{ + uint64_t toa = (((*packet & 0xFFFF) << 14) + ((*packet >> 30) & 0x3FFF)) << 4; + probe_position = ( toa - (rise_t[chip_id] * 2)) / dwell_time; + if (probe_position < scan_x) + { + uint64_t pack_44 = (*packet >> 44); + probe_position += (line_count[chip_id] % scan_y) * scan_x; + + if (*b_stem){ + kx = (address_multiplier[chip_id] * + (((pack_44 & 0x0FE00) >> 8) + + ((pack_44 & 0x00007) >> 2)) + + address_bias_x[chip_id]); + ky = (address_multiplier[chip_id] * + (((pack_44 & 0x001F8) >> 1) + + (pack_44 & 0x00003)) + + address_bias_y[chip_id]); + + float d2 = ((float)kx - (*offset)[0]) * ((float)kx - (*offset)[0]) + ((float)ky - (*offset)[1]) * ((float)ky - (*offset)[1]); + if (d2 > (*radius)[0] && d2 <= (*radius)[1]) + { + (*stem_map)[probe_position]++; + } + else if (d2 < (*radius)[0]){ + ++(*dose_map)[probe_position]; + (*sumx_map)[probe_position] += kx; + (*sumy_map)[probe_position] += ky; + } + + + } + else + { + kx = (address_multiplier[chip_id] * + (((pack_44 & 0x0FE00) >> 8) + + ((pack_44 & 0x00007) >> 2)) + + address_bias_x[chip_id]); + ky = (address_multiplier[chip_id] * + (((pack_44 & 0x001F8) >> 1) + + (pack_44 & 0x00003)) + + address_bias_y[chip_id]); + ++(*dose_map)[probe_position]; + (*sumx_map)[probe_position] += kx; + (*sumy_map)[probe_position] += ky; + } + } +} + +void CheetahInterface::process_event( + uint64_t *packet, + std::vector *dose_map, + std::vector *sumx_map, + std::vector *sumy_map, + std::vector *stem_map, + bool *b_stem, + std::array *offset, + std::array *radius, + std::vector *frame, std::array, 3> *frame_id_plot_cbed) +{ + uint64_t toa = ((((*packet & 0xFFFF) << 14) + ((*packet >> 30) & 0x3FFF)) << 4); + probe_position = ( toa - (rise_t[chip_id] * 2)) / dwell_time; + if (probe_position < scan_x) + { + probe_position += (line_count[chip_id] % scan_y) * scan_x; + if ((*frame_id_plot_cbed)[2] == 1) + { + frame->assign(nx * ny, 0); + (*frame_id_plot_cbed)[0] = probe_position; + (*frame_id_plot_cbed)[2] = 0; + } + uint64_t pack_44 = (*packet >> 44); + kx = (address_multiplier[chip_id] * + (((pack_44 & 0x0FE00) >> 8) + + ((pack_44 & 0x00007) >> 2)) + + address_bias_x[chip_id]); + ky = (address_multiplier[chip_id] * + (((pack_44 & 0x001F8) >> 1) + + (pack_44 & 0x00003)) + + address_bias_y[chip_id]); + ++(*dose_map)[probe_position]; + (*sumx_map)[probe_position] += kx; + (*sumy_map)[probe_position] += ky; + if ((probe_position > (*frame_id_plot_cbed)[0] + 100) & (probe_position <= (*frame_id_plot_cbed)[0] + (*frame_id_plot_cbed)[1] + 100)) + { + ++((*frame)[kx + ky * nx]); + } + if (*b_stem) + { + float d2 = ((float)kx - (*offset)[0]) * ((float)kx - (*offset)[0]) + ((float)ky - (*offset)[1]) * ((float)ky - (*offset)[1]); + if (d2 > (*radius)[0] && d2 <= (*radius)[1]) + { + (*stem_map)[probe_position]++; + } + } + } +} + +void CheetahInterface::reset() +{ + read_started = false; + started = false; + finish = false; + n_buffer_filled = 0; + n_buffer_processed = 0; + for (int i = 0; i < 4; i++) + { + rise_fall[i] = false; + line_count[i] = 0; + } + total_line = 0; + most_advanced_line = 0; +} + +void CheetahInterface::init_interface(std::string &tpx3_path) +{ + mode = MODE_FILE; + file.path = tpx3_path; + file.open_file(); +}; + +void CheetahInterface::init_interface(SocketConnector *socket) +{ + mode = MODE_TCP; + this->socket = socket; + //socket->connect_socket(); +}; + +void CheetahInterface::close_interface() +{ + file.close_file(); +}; + +// ------------- CheetahComm -------------- // +void CheetahComm::tpx3_det_config() +{ + cpr::Response r = cpr::Get(cpr::Url{serverurl + "/detector/config"}); + nlohmann::json detectorConfig = nlohmann::json::parse(r.text); + detectorConfig["BiasVoltage"] = "100"; + detectorConfig["BiasEnabled"] = "True"; + detectorConfig["TriggerMode"] = "CONTINUOUS"; + detectorConfig["TriggerPeriod"] = "0.016"; + detectorConfig["ExposureTime"] = "0.016"; + detectorConfig["nTriggers"] = "999999999"; + std::string config_string = detectorConfig.dump(); + cpr::Response rr = cpr::Put( + cpr::Url{serverurl + "/detector/config"}, + cpr::Body{config_string}); + std::cout << "GET-detector config:" << r.text << std::endl; + std::cout << "PUT-detector config:" << rr.text << std::endl; +} + +void CheetahComm::tpx3_cam_init() +{ + cpr::Response bpc = cpr::Get(cpr::Url{serverurl + "/config/load?format=pixelconfig&file=/home/asi/Desktop/ricom/ricom/Factory_Settings.bpc"}); + cpr::Response dac = cpr::Get(cpr::Url{serverurl + "/config/load?format=dacs&file=/home/asi/Desktop/ricom/ricom/Factory_Settings.dacs"}); + std::cout << "GET-bpc:" << bpc.text << std::endl; + std::cout << "GET-dac:" << dac.text << std::endl; +} + +void CheetahComm::tpx3_destination() +{ + std::string destination = R"({ + "Raw": [{ + "Base": "tcp://connect@127.0.0.1:8451" + }] + })"; + + cpr::Response r = cpr::Put( + cpr::Url{serverurl + "/server/destination"}, + cpr::Body{destination}); + std::cout << "PUT-destination:" << r.text << std::endl; +} + +void CheetahComm::CheetahComm::start() +{ + cpr::Response r = cpr::Get(cpr::Url{serverurl + "/measurement/start"}); + std::cout << "Get-start:" << r.text << std::endl; +} +void CheetahComm::CheetahComm::stop() +{ + cpr::Response r = cpr::Get(cpr::Url{serverurl + "/measurement/stop"}); + std::cout << "Get-stop:" << r.text << std::endl; +} + +// ---------------------------------------- // + diff --git a/src/cameras/CheetahInterface.h b/src/cameras/CheetahInterface.h new file mode 100644 index 0000000..acdfdca --- /dev/null +++ b/src/cameras/CheetahInterface.h @@ -0,0 +1,194 @@ +/* Copyright (C) 2021 Thomas Friedrich, Chu-Ping Yu, + * University of Antwerp - All Rights Reserved. + * You may use, distribute and modify + * this code under the terms of the GPL3 license. + * You should have received a copy of the GPL3 license with + * this file. If not, please visit: + * https://www.gnu.org/licenses/gpl-3.0.en.html + * + * Authors: + * Thomas Friedrich + * Chu-Ping Yu + */ + +#ifndef CHEETAH_INTERFACE_H +#define CHEETAH_INTERFACE_H + +// #ifdef __GNUC__ +// #define PACK(__Declaration__) __Declaration__ __attribute__((__packed__)) +// #endif + +// #ifdef _MSC_VER +// #define PACK(__Declaration__) __pragma(pack(push, 1)) __Declaration__ __pragma(pack(pop)) +// #endif + +#define _USE_MATH_DEFINES +#include +#include +#include +#include +#include +#include +#include + +#include +#include + +#include "SocketConnector.h" +#include "FileConnector.h" + +namespace CheetahBuffer{ + const size_t PRELOC_SIZE = 1000*25; + const size_t N_BUFFER = 4; +} + +class CheetahInterface +{ +private: + SocketConnector *socket; + FileConnector file; + int sleep = 1; + // read buffer + std::thread read_guy; + bool read_started = false; + // process buffer + std::thread proc_guy; + bool proc_started = false; + int preloc_size = CheetahBuffer::PRELOC_SIZE; + int n_buffer = CheetahBuffer::N_BUFFER; + std::array, CheetahBuffer::N_BUFFER> buffer; + int n_buffer_filled=0; + int n_buffer_processed=0; + // header + int chip_id; + uint64_t tpx_header = 861425748; //(b'TPX3', 'little') + // TDC + uint64_t rise_t[4]; + uint64_t fall_t[4]; + bool rise_fall[4] = {false, false, false, false}; + int line_count[4]; + int total_line = 0; + int most_advanced_line = 0; + uint64_t line_interval; + uint64_t dwell_time; + bool started = false; + // event + uint64_t probe_position; + uint16_t kx; + uint16_t ky; + int address_multiplier[4] = {1,-1,-1,1}; + int address_bias_x[4] = {256, 511, 255, 0}; + int address_bias_y[4] = {0, 511, 511, 0}; + + // read methods + inline void read_file(FileConnector *file, int *bc); + inline void read_socket(SocketConnector *socket, int *bc); + + // process methods + void real_read( + std::vector &dose_map, + std::vector &sumx_map, std::vector &sumy_map, + std::vector &stem_map, bool &b_stem, + std::array &offset, std::array &radius, + std::vector &frame, std::array, 3> &frame_id_plot_cbed, + int &processor_line, int &preprocessor_line, bool b_cbed + ); + + inline void process_buffer( + std::vector *dose_map, + std::vector *sumx_map, + std::vector *sumy_map, + std::vector *stem_map, + bool *b_stem, + std::array *offset, + std::array *radius, + std::vector *frame, std::array, 3> *frame_id_plot_cbed, + int *processor_line, int *preprocessor_line, bool *b_cbed + ); + + int which_type(uint64_t *packet, std::vector *stem_map); + void process_tdc(uint64_t *packet, std::vector *stem_map); + void process_event( + uint64_t *packet, + std::vector *dose_map, + std::vector *sumx_map, + std::vector *sumy_map, + std::vector *stem_map, + bool* b_stem, + std::array *offset, + std::array *radius + ); + + void process_event( + uint64_t *packet, + std::vector *dose_map, + std::vector *sumx_map, + std::vector *sumy_map, + std::vector *stem_map, + bool* b_stem, + std::array *offset, + std::array *radius, + std::vector *frame, std::array, 3> *frame_id_plot_cbed + ); + inline void reset(); + +protected: + enum Mode + { + MODE_FILE, + MODE_TCP + }; + Mode mode; + int nx; + int ny; + int gs; + +public: + // scan + uint32_t scan_x; + uint32_t scan_y; + bool finish = false; + + void read_frame_com( + std::vector &dose_map, + std::vector &sumx_map, std::vector &sumy_map, + std::vector &stem_map, bool &b_stem, + std::array &offset, std::array &radius, + int &processor_line, int &preprocessor_line + ); + + void read_frame_com( + std::vector &dose_map, + std::vector &sumx_map, std::vector &sumy_map, + std::vector &stem_map, bool &b_stem, + std::array &offset, std::array &radius, + std::vector &frame, std::array, 3> &frame_id_plot_cbed, + int &processor_line, int &preprocessor_line + ); + + void init_interface(std::string &tpx3_path); + void init_interface(SocketConnector *socket); + void close_interface(); + +}; + +class CheetahComm +{ +private: + std::string serverip = "localhost"; + std::string serverport = "8080"; + std::string rawip = "127.0.0.1"; + std::string rawport = "8451"; + std::string serverurl = "http://" + serverip + ":" + serverport; + +public: + void tpx3_det_config(); + void tpx3_cam_init(); + void tpx3_destination(); + void tpx3_acq_init(); + void start(); + void stop(); +}; + + +#endif // CHEETAH_INTERFACE_H diff --git a/src/cameras/CheetahWrapper.cpp b/src/cameras/CheetahWrapper.cpp new file mode 100644 index 0000000..e76e239 --- /dev/null +++ b/src/cameras/CheetahWrapper.cpp @@ -0,0 +1,105 @@ +/* Copyright (C) 2021 Thomas Friedrich, Chu-Ping Yu, + * University of Antwerp - All Rights Reserved. + * You may use, distribute and modify + * this code under the terms of the GPL3 license. + * You should have received a copy of the GPL3 license with + * this file. If not, please visit: + * https://www.gnu.org/licenses/gpl-3.0.en.html + * + * Authors: + * Thomas Friedrich + * Chu-Ping Yu + */ + +#ifndef CHEETAH_WRAPPER_H +#define CHEETAH_WRAPPER_H + +#include "Camera.h" +#include "CheetahInterface.h" +#include "Ricom.h" + +using namespace CAMERA; + +// Default constructor and definition of default configurations +template <> +Camera::Camera() +{ + model = CHEETAH; + type = EVENT_BASED; + nx_cam = 512; + ny_cam = 512; + swap_endian = false; +}; +template <> +Camera::Camera(){}; + +// Constructor with camera_base as argument +template <> +Camera::Camera(Camera_BASE &cam) +{ + // Copy members of Camera_BASE for use in Ricom.cpp + type = cam.type; + model = cam.model; + nx_cam = cam.nx_cam; + ny_cam = cam.ny_cam; + swap_endian = cam.swap_endian; + u = cam.u; + v = cam.v; + group_size = cam.group_size; + // Assign additional members used in CheetahInterface.cpp + nx = cam.nx_cam; + ny = cam.ny_cam; + gs = cam.group_size; +}; +template <> +Camera::Camera(Camera_BASE &cam) { (void)cam; }; + +// read_frame_com method wrapper +template <> +void Camera::read_frame_com( + std::vector &dose_map, + std::vector &sumx_map, std::vector &sumy_map, + std::vector &stem_map, bool &b_stem, + std::array &offset, std::array &radius, + int &processor_line, int &preprocessor_line, size_t &first_frame, size_t &end_frame +) +{ + CheetahInterface::read_frame_com(dose_map, sumx_map, sumy_map, stem_map, b_stem, offset, radius, processor_line, preprocessor_line); +} + +// read_frame_com_cbed method wrapper +template <> +void Camera::read_frame_com_cbed( + std::vector &dose_map, + std::vector &sumx_map, std::vector &sumy_map, + std::vector &stem_map, bool &b_stem, + std::array &offset, std::array &radius, + std::vector &frame, std::array, 3> &frame_id_plot_cbed, + int &processor_line, int &preprocessor_line, size_t &first_frame, size_t &end_frame + ) +{ + CheetahInterface::read_frame_com(dose_map, sumx_map, sumy_map, stem_map, b_stem, offset, radius, frame, frame_id_plot_cbed, processor_line, preprocessor_line); +} + +// Run method wrapper +template <> +void Camera::run(Ricom *ricom) +{ + switch (ricom->mode) + { + case RICOM::FILE: + CheetahInterface::init_interface(ricom->file_path); + ricom->process_data(this); + close_interface(); + break; + case RICOM::TCP: + ricom->socket.socket_type = Socket_type::SERVER; + CheetahInterface::init_interface(&ricom->socket); + ricom->process_data(this); + close_interface(); + } +}; +template <> +void Camera::run(Ricom *ricom) { (void)ricom; }; + +#endif // CHEETAH_WRAPPER_H \ No newline at end of file diff --git a/src/cameras/TimepixInterface.cpp b/src/cameras/TimepixInterface.cpp index a10e5d2..ab14099 100644 --- a/src/cameras/TimepixInterface.cpp +++ b/src/cameras/TimepixInterface.cpp @@ -191,28 +191,31 @@ void TimepixInterface::process_event( (*sumy_map)[probe_position] += ky; (*sumx_map)[probe_position] += kx; - if (b_stem) + if (*b_stem) { float d2 = pow((float)kx - (*offset)[0], 2) + pow((float)ky - (*offset)[1], 2); if (d2 > (*radius)[0] && d2 <= (*radius)[1]) { (*stem_map)[probe_position]++; } - } - if ((probe_position_total / scan_x) > current_line){ - current_line++; - if ( (current_line+3)%scan_y < (current_line+2)%scan_y ){ - std::fill( - (*stem_map).begin()+(((current_line+2)%scan_y)*scan_x), - (*stem_map).end(), 0); - } - else { - std::fill( - (*stem_map).begin()+(((current_line+2)%scan_y)*scan_x), - (*stem_map).begin()+(((current_line+2)%scan_y)*scan_x)+scan_x, 0); + if ((probe_position_total / scan_x) > current_line){ + current_line++; + if ( (current_line+3)%scan_y < (current_line+2)%scan_y ){ + std::fill( + (*stem_map).begin()+(((current_line+2)%scan_y)*scan_x), + (*stem_map).end(), 0); + } + else { + std::fill( + (*stem_map).begin()+(((current_line+2)%scan_y)*scan_x), + (*stem_map).begin()+(((current_line+2)%scan_y)*scan_x)+scan_x, 0); + } } + + } + } void TimepixInterface::process_event( diff --git a/src/cameras/TimepixInterface.h b/src/cameras/TimepixInterface.h index 59c27d0..ac85263 100644 --- a/src/cameras/TimepixInterface.h +++ b/src/cameras/TimepixInterface.h @@ -41,10 +41,10 @@ PACK(struct e_event uint16_t tot; }); -const size_t PRELOC_SIZE = 1000*25; -const size_t N_BUFFER = 4; - - +namespace TimepixBuffer{ + const size_t PRELOC_SIZE = 1000*25; + const size_t N_BUFFER = 4; +} class TimepixInterface { @@ -57,9 +57,9 @@ class TimepixInterface // process buffer std::thread proc_guy; bool proc_started = false; - int preloc_size = PRELOC_SIZE; - int n_buffer = N_BUFFER; - std::array, N_BUFFER> buffer; + int preloc_size = TimepixBuffer::PRELOC_SIZE; + int n_buffer = TimepixBuffer::N_BUFFER; + std::array, TimepixBuffer::N_BUFFER> buffer; int n_buffer_filled=0; int n_buffer_processed=0; uint64_t current_line = 0; @@ -119,7 +119,6 @@ class TimepixInterface int nx; int ny; int dt; // unit: ns - uint32_t gs; public: void read_frame_com( diff --git a/src/cameras/TimepixWrapper.cpp b/src/cameras/TimepixWrapper.cpp index d97006f..e54b453 100644 --- a/src/cameras/TimepixWrapper.cpp +++ b/src/cameras/TimepixWrapper.cpp @@ -61,7 +61,7 @@ template <> void Camera::read_frame_com( std::vector &dose_map, std::vector &sumx_map, std::vector &sumy_map, - std::vector &stem_map, bool b_stem, + std::vector &stem_map, bool &b_stem, std::array &offset, std::array &radius, int &processor_line, int &preprocessor_line, size_t &first_frame, size_t &end_frame ) @@ -74,7 +74,7 @@ template <> void Camera::read_frame_com_cbed( std::vector &dose_map, std::vector &sumx_map, std::vector &sumy_map, - std::vector &stem_map, bool b_stem, + std::vector &stem_map, bool &b_stem, std::array &offset, std::array &radius, std::vector &frame, std::array, 3> &frame_id_plot_cbed, int &processor_line, int &preprocessor_line, size_t &first_frame, size_t &end_frame