diff --git a/vmmTblApp/src/vmm3a.cpp b/vmmTblApp/src/vmm3a.cpp index 940dfadc1d04703e167d542fdd48fe57ae1e57a3..b835edae585640d60fcffb47a30443f2d8add8e0 100644 --- a/vmmTblApp/src/vmm3a.cpp +++ b/vmmTblApp/src/vmm3a.cpp @@ -56,7 +56,7 @@ void VMM3a::LoadDefault() { "stlc", "sbip", "srat", "sfrst", "slvsbc", "slvstp", "slvstk", "slvsdt", "slvsart", "slvstki", "slvsena", "slvs6b", "sL0enaV", "slh", "slxh", - "stgc", "reset1", "reset2" "nskipm_i", "sL0cktest", + "stgc", "reset1", "reset2", "nskipm_i", "sL0cktest", "sL0dckinv", "sL0ckinv", "sL0ena", "truncate_i", "nskip_i", "window_i", "rollover_i", "L0offset_i", "offset_i" }; @@ -108,7 +108,7 @@ vmmStatus VMM3a::setRegister(std::string feature, int val, int ch) { return status; } -vmmStatus VMM3a::getRegister(std::string feature, int val, unsigned short& result) { +vmmStatus VMM3a::getRegister(std::string feature, unsigned short& result) { vmmStatus status = vmmSuccess; if(vmm3aSettings->globalRegisters.find(feature)!=vmm3aSettings->globalRegisters.end()) result = vmm3aSettings->globalRegisters.at(feature); @@ -117,7 +117,7 @@ vmmStatus VMM3a::getRegister(std::string feature, int val, unsigned short& resul return status; } -vmmStatus VMM3a::getRegister(std::string feature, int val, int ch, unsigned short& result) { +vmmStatus VMM3a::getRegister(std::string feature, int ch, unsigned short& result) { vmmStatus status = vmmSuccess; if (ch >= 0 && ch < 64) { auto it = vmm3aSettings->channels[ch].find(feature); @@ -147,7 +147,7 @@ vmmStatus VMM3a::updateRegisterMap(std::string feature, int value) { } else if (value >= 64 && value <= 67) { //Attention: Starts at 1: 1=Pulser_DAC, 2=Threshold_DAC, 3=Bandgap_reference, 4=Temperature_sensor vmm3aSettings->globalRegisters.at("scmx") = 0; - vmm3aSettings->globalRegisters.at("sm5_sm0") = value-63; + vmm3aSettings->globalRegisters.at("sm5_sm0") = value - 63; } else status = vmmBadValue; } else { diff --git a/vmmTblApp/src/vmm3a.h b/vmmTblApp/src/vmm3a.h index f305f8a7118ccc787d5986a750742edd71e8a41d..9ff887223d75382149e85a16988568e874c74901 100644 --- a/vmmTblApp/src/vmm3a.h +++ b/vmmTblApp/src/vmm3a.h @@ -23,8 +23,8 @@ public: const VMM3aSettings& getVMM3aSettings() const; vmmStatus setRegister(std::string feature, int val); vmmStatus setRegister(std::string feature, int val, int ch); - vmmStatus getRegister(std::string feature, int val, unsigned short& result); - vmmStatus getRegister(std::string feature, int val, int ch, unsigned short& result); + vmmStatus getRegister(std::string feature, unsigned short& result); + vmmStatus getRegister(std::string feature, int ch, unsigned short& result); vmmStatus getInfo(const std::string& feature, std::string& result); vmmStatus setInfo(const std::string& feature, const std::string& value); diff --git a/vmmTblApp/src/vmm_config.cpp b/vmmTblApp/src/vmm_config.cpp new file mode 100644 index 0000000000000000000000000000000000000000..33337312fe5c08ea6365e47f94c807a352fbe19f --- /dev/null +++ b/vmmTblApp/src/vmm_config.cpp @@ -0,0 +1,289 @@ +#include "vmm_config.h" +#include <sstream> +#include <bitset> +#include <algorithm> + +#include "FrontEndBase.h" + +FENConfigModule::FENConfigModule(FrontEndBase& frontend) : pVMM3a(), pFEN(&frontend) { + // Retrieve the VMMSettings from the VMM instance + const auto& vmm3a_settings = pVMM3a.getVMM3aSettings(); + + // Access the globalRegisters member and print its contents + for (const auto& entry : vmm3a_settings.globalRegisters) { + std::cout << "Key: " << entry.first << ", Value: " << entry.second << std::endl; + } +} + +FENConfigModule::~FENConfigModule() { +} + +bool FENConfigModule::configVMM(int hybrid_index, int vmm_index, bool enableConfigCheck) +{ + bool result = true; + bool ok; + + std::vector<std::string> globalRegisters; + globalRegisters.clear(); + fillGlobalRegisters(globalRegisters, hybrid_index, vmm_index); + + std::cout << "Global Registers:" << std::endl; + for (const auto& reg : globalRegisters) { + std::cout << reg << std::endl; + } + + if(globalRegisters.size()!=3){ + std::cout << "ERROR Global SPI does not have 3 words" << std::endl; + return -1; + } + + std::vector<std::string> channelRegisters; + channelRegisters.clear(); + fillChRegisters(channelRegisters, hybrid_index, vmm_index); + if(channelRegisters.size() != 64){ + std::cout << "ERROR Channel registers do not have 64 values" << std::endl; + return -1; + } + + std::vector<std::string> globalRegisters2; + globalRegisters2.clear(); + fillGlobalRegisters2(globalRegisters2, hybrid_index, vmm_index); + if(globalRegisters2.size()!=3){ + std::cout << "ERROR Global SPI does not have 3 words" << std::endl; + return -1; + } + + int idx = hybrid_index * 2 + vmm_index; + std::string sVmmIndex = "99"; + if(idx < 10) sVmmIndex = "0" + std::to_string(idx); + else if(idx < 16) sVmmIndex = std::to_string(idx); + + bool g_use_config_check = true; + if(g_use_config_check) { + //reset I2C address 65 register 0 + if(enableConfigCheck) { + // TODO: Check with we need that (the enableConfigCheck is always false in the VMM code) + //uint32_t value = (1 << hybrid_index); + //ESS_WriteSc("sc_i2c_reset_config_check", 0x00000000, ok); + //ESS_WriteSc("sc_i2c_reset_config_check", value, ok); + //ESS_WriteSc("sc_i2c_reset_config_check", 0x00000000, ok); + } + } + + unsigned int firstGlobalRegSPI_2 = 0; + unsigned int lastGlobalRegSPI_2 = 2; + unsigned int firstChRegSPI = 3; + unsigned int lastChRegSPI = 66; + unsigned int firstGlobalRegSPI_1 = 67; + unsigned int lastGlobalRegSPI_1 = 69; + + // global SPI / VMM3: global bank 0 + for(unsigned int i = firstGlobalRegSPI_2; i <= lastGlobalRegSPI_2; i++) { + std::string param = "vmm_global_bank2_sp" + std::to_string(i - firstGlobalRegSPI_2) + sVmmIndex; + uint32_t value = std::stoul(globalRegisters2[i - firstGlobalRegSPI_2], nullptr, 2); + std::cout << "Param: " << param << " - Value: " << value << std::endl; + pFEN->user_reg_write(param, value); + } + + //channel SPI + for(unsigned int i = firstChRegSPI; i <= lastChRegSPI; i++) { + std::string param = "vmm_ch" + std::to_string(i - firstChRegSPI); + param += sVmmIndex; + param += std::string(2 - std::to_string(i - firstChRegSPI).length(), '0'); // Right justify with '0' + uint32_t value = std::stoul(channelRegisters[i - firstChRegSPI], nullptr, 2); + std::cout << "Param: " << param << " - Value: " << value << std::endl; + pFEN->user_reg_write(param, value); + } + + // global SPI / VMM3: global bank 1 + for(unsigned int i = firstGlobalRegSPI_1; i <= lastGlobalRegSPI_1; i++) { + std::string param = "vmm_global_bank1_sp" + std::to_string(i - firstGlobalRegSPI_1) + sVmmIndex; + uint32_t value = std::stoul(globalRegisters[i - firstGlobalRegSPI_1], nullptr, 2); + std::cout << "Param: " << param << " - Value: " << value << std::endl; + pFEN->user_reg_write(param, value); + } + + uint32_t value = (1 << idx); + pFEN->user_reg_write("sc_cfg_vmm", 0x00000000); + pFEN->user_reg_write("sc_cfg_vmm", value); + pFEN->user_reg_write("sc_cfg_vmm", 0x00000000); + + return result; +} + +void FENConfigModule::fillGlobalRegisters(std::vector<std::string>& global, int hybrid_index, int vmm_index) +{ + unsigned short result; + + global.clear(); + int sequence = 0; + + // GLOBAL SPI 0 + std::string spi0 = "00000000000000000000000000000000"; + + //[0,3] reserved + sequence += 4; + + // Function to replace a bit in the spi0 string with a value from VMM settings + auto replaceVMMBit = [&](int index, const std::string& settingName) { + // Convert value to '1' if it's not zero, otherwise '0' + pVMM3a.getRegister(settingName, result); + std::cout << "Setting Name: " << settingName << " Result: " << result << std::endl; + spi0[index] = '0' + (result != 0); + }; + + const std::vector<std::string> settings = {"slvs", "s32", "stcr", "ssart", "srec", "stlc", "sbip", "srat", "sfrst", + "slvsbc", "slvstp", "slvstk", "slvsdt", "slvsart", "slvstki", "slvsena", + "slvs6b", "slh", "slxh", "stgc", "reset1", "reset2"}; + + for (const auto& setting : settings) { + if (setting == "reset1") sequence += 5; //[25,29] not used + replaceVMMBit(sequence, setting); + sequence++; + } + + global.push_back(spi0); + + // GLOBAL SPI 1 + // Define a function to populate spi string based on VMM settings + auto populateSPI1 = [&](const std::vector<std::pair<std::string, int>>& settings) { + std::string spi; + int sequence = 0; + for (const auto& setting : settings) { + pVMM3a.getRegister(setting.first, result); + std::string binary_string = std::bitset<16>(result).to_string().substr(16 - setting.second); + + if (setting.first == "sdt") { + // Populate threshold DAC lowest 6 bits + for (int i = 4; i < 10; ++i) spi += binary_string[i]; + } else spi += binary_string; + sequence += setting.second; + } + + // Append '0' to the end of spi to reserve the last bit: [31] reserved + spi += '0'; + + // Push back the populated spi string to the global vector + global.push_back(spi); + }; + + // Populate SPI 1 settings + populateSPI1({{"sdt", 10},{"sdp10", 10}, {"sc10b", 2}, {"sc8b", 2}, + {"sc6b", 3}, {"s8b", 1}, {"s6b", 1}, {"s10b", 1}, + {"sdcks", 1}, {"sdcka", 1}, {"sdck6b", 1}, {"sdrv", 1}, + {"stpp", 1}}); + + // GLOBAL SPI 2 + // Define a function to populate spi string based on VMM settings + auto populateSPI2 = [&](const std::vector<std::pair<std::string, int>>& settings) { + std::string spi; + int sequence = 0; + + for (const auto& setting : settings) { + pVMM3a.getRegister(setting.first, result); + std::string binary_string = std::bitset<16>(result).to_string().substr(16 - setting.second); + if (setting.first == "sdt") { + // Populate threshold DAC highest 4 bits + for (int i = 0; i < 4; ++i) { + spi += binary_string[i]; + sequence++; + } + } else { + spi += binary_string; + sequence += setting.second; + } + } + // Push back the populated spi string to the global vector + global.push_back(spi); + }; + + // Populate SPI 2 settings + populateSPI2({{"sp", 1}, {"sdp", 1}, {"sbmx", 1}, {"sbft", 1}, {"sbfp", 1}, + {"sbfm", 1}, {"slg", 1}, {"sm5_sm0", 6}, {"scmx", 1}, {"sfa", 1}, + {"sfam", 1}, {"st", 2}, {"sfm", 1}, {"sg", 3}, {"sng", 1}, {"stot", 1}, + {"sttt", 1}, {"ssh", 1}, {"stc", 2}, {"sdt", 10}}); + +} + +void FENConfigModule::fillChRegisters(std::vector<std::string>& registers, int hybrid_index, int vmm_index) +{ + registers.clear(); + unsigned short result; + + auto populateRegisters = [&](const std::vector<std::pair<std::string, int>>& regs, int channel) { + std::string _reg = "00000000"; + int sequence = 8; + + for (const auto& reg : regs) { + pVMM3a.getRegister(reg.first, channel, result); + std::string binary_string = std::bitset<16>(result).to_string().substr(16 - reg.second); + if (reg.first == "sd" || reg.first == "sz10b" || + reg.first == "sz08b" || reg.first == "sz06b") { + //According to ATLAS software, has to be reversed + std::reverse(binary_string.begin(), binary_string.end()); + } + _reg += binary_string; + sequence += reg.second; + } + + // Append '0' to the end of spi to reserve the last bit: [31] reserved + _reg += "0"; + + // Push back the populated _reg string to the registers vector + registers.push_back(_reg); + }; + + std::vector<std::pair<std::string, int>> registers_map = {{"sc", 1}, {"sl", 1}, {"st", 1}, + {"sth", 1}, {"sm", 1}, {"smx", 1}, + {"sd", 5}, {"sz10b", 5}, {"sz08b", 4}, + {"sz06b", 3}}; + + for(int ch = 0; ch < CHANNELS_PER_VMM; ch++) { + populateRegisters(registers_map, ch); + } +} + +void FENConfigModule::fillGlobalRegisters2(std::vector<std::string>& global, int hybrid_index, int vmm_index) +{ + unsigned short result; + int sequence = 0; + + // GLOBAL SPI 0 + std::string spi0 = "00000000000000000000000000000000"; + //[0,30] not used + sequence+=31; + + // magic number on BCID [31] + pVMM3a.getRegister("nskipm_i", result); + spi0.replace(sequence, 1, std::to_string(result)); + + global.push_back(spi0); + + // GLOBAL SPI 1 + std::string spi1 = "00000000000000000000000000000000"; + pVMM3a.getRegister("sL0cktest", result); + // clocks when L0 core disabled [0] + spi1.replace(sequence, 1, std::to_string(result)); + sequence++; + + //invert DCK [1] + pVMM3a.getRegister("sL0dckinv", result); + spi1.replace(sequence, 1, std::to_string(result)); + sequence++; + + //invert BCCLK [2] + pVMM3a.getRegister("sL0ckinv", result); + spi1.replace(sequence, 1, std::to_string(result)); + sequence++; + + //L0 core + pVMM3a.getRegister("sL0ena", result); + spi1.replace(sequence, 1, std::to_string(result)); + sequence++; + + global.push_back(spi1); + + // GLOBAL SPI 2 + std::string spi2 = "00000000000000000000000000000000"; + global.push_back(spi2); +} diff --git a/vmmTblApp/src/vmm_config.h b/vmmTblApp/src/vmm_config.h new file mode 100644 index 0000000000000000000000000000000000000000..c0d6fc6b722c953ad925eae9c08edfcaeac9d1d3 --- /dev/null +++ b/vmmTblApp/src/vmm_config.h @@ -0,0 +1,24 @@ +#pragma once + +#include <vector> +#include <string> +#include <map> +#include <vector> +#include <memory> +#include <iostream> +#include "vmm3a.h" + +class FrontEndBase; + +class FENConfigModule { +public: + FENConfigModule(FrontEndBase& frontend); + ~FENConfigModule(); + bool configVMM(int hybrid_index, int vmm_index, bool enableConfigCheck=false); + void fillGlobalRegisters(std::vector<std::string>& global, int hybrid_index, int vmm_index); + void fillGlobalRegisters2(std::vector<std::string>& global, int hybrid_index, int vmm_index); + void fillChRegisters(std::vector<std::string>& registers, int hybrid_index, int vmm_index); +private: + VMM3a pVMM3a; + FrontEndBase *pFEN; +};