diff --git a/decode-reg.cc b/decode-reg.cc index 46ffa78..f540c65 100644 --- a/decode-reg.cc +++ b/decode-reg.cc @@ -25,7 +25,7 @@ static const char usage[] = R"(Simple FPGA Register Reader Usage: - decode-reg [-hv] -b -a + decode-reg [-hv] -q -b -a decode-reg [-hv] -r -b -a -c -n -p -s [-t ] [-e ] [-l] [-z ] [-i ] [-C ] [-d ] decode-reg [-hv] -x -b -a [-e] -c -m -k -t -s [-d ] @@ -103,7 +103,17 @@ int main(int argc, char *argv[]) ctl.write_params(); } else { - std::unique_ptr dec{new LnlsBpmAcqCore}; + std::string device_type = args.at("").asString(); + + std::unique_ptr dec; + if (device_type == "acq") { + dec = std::make_unique(); + } else if (device_type == "lamp") { + dec = std::make_unique(); + } else { + fprintf(stderr, "Unknown device: '%s'\n", device_type.c_str()); + return 1; + } dec->read(&bars, address); dec->print(stdout, verbose); } diff --git a/lamp.cc b/lamp.cc index 491cb94..4d45cfc 100644 --- a/lamp.cc +++ b/lamp.cc @@ -13,8 +13,77 @@ #include "util.h" #include "lamp.h" +#define MAX_NUM_CHAN 12 +#define REGISTERS_PER_CHAN 6 static const unsigned max_26bits = 0x3ffffff; -static const unsigned channel_distance = 4 * 6; /* 6 registers */ +static const unsigned channel_distance = 4 * REGISTERS_PER_CHAN; + +void LnlsRtmLampCore::read(const struct pcie_bars *bars, size_t address) +{ + bar4_read_v(bars, address, ®s, sizeof regs); +} + +void LnlsRtmLampCore::print(FILE *f, bool verbose) +{ + static const std::unordered_map printers({ + I("DAC_DATA_FROM_WB", "Use data from WB for DACs", PrinterType::boolean, "DAC data from RTM module input ports", "DAC data from Wishbone"), + /* per channel info */ + I("AMP_IFLAG_L", "Amplifier Left Current Limit Flag", PrinterType::boolean, "current under limit", "current over limit"), + I("AMP_TFLAG_L", "Amplifier Left Thermal Limit Flag", PrinterType::boolean, "temperature under limit", "temperature over limit"), + I("AMP_IFLAG_R", "Amplifier Right Current Limit Flag", PrinterType::boolean, "current under limit", "current over limit"), + I("AMP_TFLAG_R", "Amplifier Right Thermal Limit Flag", PrinterType::boolean, "temperature under limit", "temperature over limit"), + I("AMP_EN", "Amplifier Enable", PrinterType::boolean), + /* TODO: add test mode when it becomes a single value */ + I("PI_ENABLE", "PI Enable", PrinterType::boolean), + I("PI_KP", "PI KP Coefficient", PrinterType::value), + I("PI_TI", "PI TI Coefficient", PrinterType::value), + I("PI_SP", "PI Setpoint", PrinterType::value), + I("DAC", "DAC Data For Channel", PrinterType::value), + /* PI control */ + I("PI_OL_DAC_CNT_MAX", "PI open-loop DAC test mode period, in clock ticks", PrinterType::value), + I("PI_SP_LIM_INF", "PI open-loop DAC test mode inferior limit. The upper limit is the setpoint itself", PrinterType::value), + }); + + bool v = verbose; + unsigned indent = 0; + uint32_t t; + + auto print_reg = [f, v, &indent](const char *reg, unsigned offset) { + print_reg_impl(f, v, indent, reg, offset); + }; + auto print = [f, v, &indent](const char *name, uint32_t value) { + printers.at(name).print(f, v, indent, value); + }; + + print_reg("control register", RTMLAMP_OHWR_REGS_CTL); + t = regs.ctl; + print("DAC_DATA_FROM_WB", t & RTMLAMP_OHWR_REGS_CTL_DAC_DATA_FROM_WB); + + uint32_t p[MAX_NUM_CHAN * REGISTERS_PER_CHAN]; + memcpy(p, ®s.ch_0_sta, sizeof p); + for (unsigned i = 0; i < MAX_NUM_CHAN; i++) { + fprintf(f, "channel %u (starting at %02X):\n", + i, (unsigned)ACQ_CORE_CH0_DESC + 4*i*REGISTERS_PER_CHAN); + indent = 4; + + struct channel_registers channel_regs; + memcpy(&channel_regs, p + i*REGISTERS_PER_CHAN, sizeof channel_regs); + t = channel_regs.sta; + print("AMP_IFLAG_L", t & RTMLAMP_OHWR_REGS_CH_0_STA_AMP_IFLAG_L); + print("AMP_TFLAG_L", t & RTMLAMP_OHWR_REGS_CH_0_STA_AMP_TFLAG_L); + print("AMP_IFLAG_R", t & RTMLAMP_OHWR_REGS_CH_0_STA_AMP_IFLAG_R); + print("AMP_TFLAG_R", t & RTMLAMP_OHWR_REGS_CH_0_STA_AMP_TFLAG_R); + + t = channel_regs.ctl; + print("AMP_EN", t & RTMLAMP_OHWR_REGS_CH_0_CTL_AMP_EN); + print("PI_ENABLE", t & RTMLAMP_OHWR_REGS_CH_0_CTL_PI_ENABLE); + + print("PI_KP", (channel_regs.pi_kp & RTMLAMP_OHWR_REGS_CH_0_PI_KP_DATA_MASK) >> RTMLAMP_OHWR_REGS_CH_0_PI_KP_DATA_SHIFT); + print("PI_TI", (channel_regs.pi_ti & RTMLAMP_OHWR_REGS_CH_0_PI_TI_DATA_MASK) >> RTMLAMP_OHWR_REGS_CH_0_PI_TI_DATA_SHIFT); + print("PI_SP", (channel_regs.pi_sp & RTMLAMP_OHWR_REGS_CH_0_PI_SP_DATA_MASK) >> RTMLAMP_OHWR_REGS_CH_0_PI_SP_DATA_SHIFT); + print("DAC", (channel_regs.dac & RTMLAMP_OHWR_REGS_CH_0_DAC_DATA_MASK) >> RTMLAMP_OHWR_REGS_CH_0_DAC_DATA_SHIFT); + } +} void LnlsRtmLampController::encode_config() { diff --git a/lamp.h b/lamp.h index 76e6bde..661ff0b 100644 --- a/lamp.h +++ b/lamp.h @@ -13,19 +13,29 @@ #include "pcie.h" #include "util.h" +#include "decoders.h" #include "wb_rtmlamp_ohwr_regs.h" +struct channel_registers { + uint32_t sta, ctl, pi_kp, pi_ti, pi_sp, dac; +}; + +class LnlsRtmLampCore: public RegisterDecoder { + struct rtmlamp_ohwr_regs regs; + + public: + LnlsRtmLampCore() {} + void read(const struct pcie_bars *, size_t); + void print(FILE *, bool); +}; + class LnlsRtmLampController { const struct pcie_bars *bars; size_t addr; /* control registers */ - uint32_t ctl=0; - struct { - uint32_t - sta=0, /* sta is here to guarantee the struct layout */ - ctl=0, pi_kp=0, pi_ti=0, pi_sp=0, dac=0; - } channel_regs; + uint32_t ctl = 0; + struct channel_registers channel_regs{}; void encode_config();