Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
63 changes: 43 additions & 20 deletions app/tool/bias.cxx
Original file line number Diff line number Diff line change
Expand Up @@ -5,16 +5,27 @@
*
* Only usable for HcalBackplane type targets.
*/
#include "pflib/HcalBackplane.h"
#include "pflib/Bias.h"

#include "pflib/HcalTarget.h"
#include "pftool.h"

ENABLE_LOGGING();

static void bias(const std::string& cmd, pflib::HcalBackplane* pft) {
std::ostream& operator<<(std::ostream& o, std::optional<int> val) {
if (val) {
o << std::setw(4) << val.value();
} else {
o << "????";
}
return o;
}

static void bias(const std::string& cmd, pflib::HcalTarget* pft) {
static int iboard = 0;
if (cmd == "STATUS") {
iboard = pftool::readline_int("Which board? ", iboard);
pflib::Bias bias = pft->bias(iboard);
pflib::Bias& bias = pft->bias(iboard);
double temp = bias.readTemp();
std::cout << "Board temperature: " << temp << " C" << std::endl;
for (int ch = 0; ch < 16; ch++) {
Expand All @@ -24,33 +35,37 @@ static void bias(const std::string& cmd, pflib::HcalBackplane* pft) {
}
if (cmd == "READ_SIPM") {
iboard = pftool::readline_int("Which board? ", iboard);
pflib::Bias bias = pft->bias(iboard);
pflib::Bias& bias = pft->bias(iboard);
int ich = pftool::readline_int(
"Which (zero-indexed) channel? (-1 for all) ", iboard);
if (ich == -1) {
for (int i = 0; i < 16; i++) {
std::cout << "Channel " << i << ": " << bias.readSiPM(i) << std::endl;
std::cout << "Channel " << std::setw(2) << i << ": " << bias.readSiPM(i)
<< std::endl;
}
} else {
std::cout << "Channel " << ich << ": " << bias.readSiPM(ich) << std::endl;
std::cout << "Channel " << std::setw(2) << ich << ": "
<< bias.readSiPM(ich) << std::endl;
}
}
if (cmd == "READ_LED") {
iboard = pftool::readline_int("Which board? ", iboard);
pflib::Bias bias = pft->bias(iboard);
pflib::Bias& bias = pft->bias(iboard);
int ich = pftool::readline_int(
"Which (zero-indexed) channel? (-1 for all) ", iboard);
if (ich == -1) {
for (int i = 0; i < 16; i++) {
std::cout << "Channel " << i << ": " << bias.readLED(i) << std::endl;
std::cout << "Channel " << std::setw(2) << i << ": " << bias.readLED(i)
<< std::endl;
}
} else {
std::cout << "Channel " << ich << ": " << bias.readLED(ich) << std::endl;
std::cout << "Channel " << std::setw(2) << ich << ": "
<< bias.readLED(ich) << std::endl;
}
}
if (cmd == "SET_SIPM") {
iboard = pftool::readline_int("Which board? ", iboard);
pflib::Bias bias = pft->bias(iboard);
pflib::Bias& bias = pft->bias(iboard);
int ich = pftool::readline_int(
"Which (zero-indexed) channel? (-1 for all) ", iboard);
uint16_t dac = pftool::readline_int("Which DAC value? ", 0);
Expand All @@ -64,7 +79,7 @@ static void bias(const std::string& cmd, pflib::HcalBackplane* pft) {
}
if (cmd == "SET_LED") {
iboard = pftool::readline_int("Which board? ", iboard);
pflib::Bias bias = pft->bias(iboard);
pflib::Bias& bias = pft->bias(iboard);
int ich = pftool::readline_int(
"Which (zero-indexed) channel? (-1 for all) ", iboard);
uint16_t dac = pftool::readline_int("Which DAC value? ", 0);
Expand All @@ -78,33 +93,41 @@ static void bias(const std::string& cmd, pflib::HcalBackplane* pft) {
}
if (cmd == "INIT") {
iboard = pftool::readline_int("Which board? ", iboard);
pflib::Bias bias = pft->bias(iboard);
bias.initialize();
pft->bias(iboard).initialize();
}
if (cmd == "READ_TEMP") {
iboard = pftool::readline_int("Which board? ", iboard);
pflib::Bias bias = pft->bias(iboard);
double temp = bias.readTemp();
double temp = pft->bias(iboard).readTemp();
std::cout << "Board temperature: " << temp << " C" << std::endl;
}
}

static void render(Target* tgt) {
auto hcal = dynamic_cast<pflib::HcalBackplane*>(tgt);
auto hcal = dynamic_cast<pflib::HcalTarget*>(tgt);
if (not hcal) {
pflib_log(error)
<< "BIAS menu of commands only availabe for HcalBackplane targets.";
pflib_log(error) << "BIAS menu of commands only availabe for Hcal targets.";
}
if (pftool::state.readout_config() != pftool::State::CFG_HCALFMC) {
std::cout << R"WARN(
We currently do not have the ability to readback the voltage settings
from the MAX5825 via the lpGBT. This means we cache the last value we
wrote to the board in the software.
A value of '????' means we haven't written to that channel of the board,
so we do not know what value that channel is set to.
In this case, either set the channel to the desired setting or check the
board manually with a multimeter.
)WARN" << std::endl;
}
}

static void bias_wrapper(const std::string& cmd, Target* tgt) {
auto hcal = dynamic_cast<pflib::HcalBackplane*>(tgt);
auto hcal = dynamic_cast<pflib::HcalTarget*>(tgt);
if (hcal) {
bias(cmd, hcal);
} else {
PFEXCEPTION_RAISE("NotImpl",
"The BIAS menu of commands is only available for "
"HcalBackplane targets.");
"Hcal targets.");
}
}

Expand Down
101 changes: 50 additions & 51 deletions include/pflib/Bias.h
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,7 @@

#include <unistd.h>

#include <optional>
#include <vector>

#include "pflib/I2C.h"
Expand Down Expand Up @@ -49,6 +50,14 @@ class MAX5825 {
*/
MAX5825(std::shared_ptr<I2C> i2c, uint8_t max_addr);

/**
* send the SW_RESET command to the MAX5825
*
* "All CODE, DAC, and Control Register values are returned to
* their power-on reset values"
*/
void reset();

/**
* Get the settings for the DACs on this MAX
*
Expand All @@ -59,8 +68,6 @@ class MAX5825 {
*/
std::vector<uint8_t> get(uint8_t channel);

void set(uint8_t channel, uint16_t data_bytes);

/**
* Write a setting for the DACs on this MAX
*
Expand All @@ -73,54 +80,20 @@ class MAX5825 {
* Since the chip expects the 12-bit settings to be the 12 MSBs
* from these two concatenated data words.
*/
// void set(uint8_t cmd, uint16_t data_bytes);

/**
* get by DAC index
*
* The per-DAC commands return the 12-bit settings as the 12 MSBs
* of two adjacent concatenated bits. We do this concatenation
* in this file as well as determine how many bytes to request
* depending on if we are requesting a single DAC (i_dac <= 7)
* or if we are requesting all DACs (i_dac > 7).
*
* The per-DAC commands use the 4 MSBs as a command the 4 LSBs
* to make the DAC selection. Using the commands defined as
* static constants in this class, the combination of i_dac and
* command is simply adding them together, which is done here.
*/
// std::vector<uint16_t> getByDAC(uint8_t i_dac, uint8_t cmd);
void set(uint8_t channel, uint16_t data_bytes);

/**
* set by DAC index
*
* The per-DAC commands expect the 12-bit settings as the 12 MSBs
* of the two adjacent concatenated data bytes. We do the shifting
* inside of this function, so the twelve_bit_setting should be the
* value you want the DAC to be set at.
* Set reference voltage
*
* The per-DAC commands use the 4 MSBs as a command the 4 LSBs
* to make the DAC selection. Using the commands defined as
* static constants in this class, the combination of i_dac and
* command is simply adding them together, which is done here.
* @param[in] level (0 - external, 1 - 2.5V, 2 - 2.048V, 3 - 4.096V)
*/
// void setByDAC(uint8_t i_dac, uint8_t cmd, uint16_t twelve_bit_setting);

/** Set reference voltage
* 0 - external
* 1 - 2.5V
* 2 - 2.048V
* 3 - 4.096V
*/
// void setRefVoltage(int level);
void setRefVoltage(int level);

private:
/// our connection
std::shared_ptr<I2C> i2c_;
/// our addr on the chip
uint8_t our_addr_;
/// our bus
// int bus_;
}; // MAX5825

/**
Expand All @@ -129,49 +102,75 @@ class MAX5825 {
* two handle the 16 SiPM bias voltages.
*
* Both the LED and SiPM bias voltages are indexed from 0 to 15.
* To convert from that index to a chip and DAC index on that chip,
* just use integer division and modulus.
* The conversion from that index to a chip and DAC index on that chip
* is done in this class.
*
* chip_index = int(index > 7)
* dac_index = index - 8*chip_index;
* The readback of the DAC settings in the MAX5825 seem to require
* a "repeated start" I2C transaction where the register to be read
* and the read command are sent before the next I2C stop.
* Originally pointed out by Lennart at Lund, this "repeated start"
* transaction *cannot* be done by the lpGBT, so *actual* readback
* of the DAC settings is not supported in fiberfull setups.
*/
class Bias {
public:
/// DAC chip addresses
static const int N_CHANNELS = 16;
static const uint8_t ADDR_LED_0;
static const uint8_t ADDR_LED_1;
static const uint8_t ADDR_SIPM_0;
static const uint8_t ADDR_SIPM_1;

public:
/**
* Wrap an I2C class for communicating with all the DAC chips.
* Wrap I2C objects for communicating with all the DAC chips.
*
* The bus is 4 + <board-number>, so we set the default to 4 for
* the case where we only have one board with bus number 0.
*
* @param[in] bias_i2c I2C object for interacting with MAX5825 bias DACs
* @param[in] board_i2c I2C object for talking with HGCROC board periferials
* @param[in] use_cache whether to use the software cache for readback (true)
* or not (false). This is necessary for readback to function on fiberless
* setups.
*/
Bias(std::shared_ptr<I2C> bias_i2c, std::shared_ptr<I2C> board_i2c);
Bias(std::shared_ptr<I2C> bias_i2c, std::shared_ptr<I2C> board_i2c,
bool use_cache);

/// dont copy construct this class
Bias(const Bias&) = delete;
/// dont copy assign this class
Bias& operator=(const Bias&) = delete;

/**
* Initialize to standard settings
* Reference voltage - 4.096V
*/
void initialize();

/**
* Read the temperature from the temp sensor on the HGCROC board
*/
double readTemp();

int readSiPM(uint8_t i_sipm);
int readLED(uint8_t i_led);
std::optional<int> readSiPM(uint8_t i_sipm);
std::optional<int> readLED(uint8_t i_led);
void setSiPM(uint8_t i_sipm, uint16_t code);
void setLED(uint8_t i_led, uint16_t code);

private:
/// I2C comms with bias DACs MAX5825
std::shared_ptr<I2C> i2c_bias_;
/// I2C comms with HGCROC board periferials
std::shared_ptr<I2C> i2c_board_;

/// LED bias chips
std::vector<MAX5825> led_;
/// SiPM bias chips
std::vector<MAX5825> sipm_;
/// whether to use the software cache of the settings
bool use_cache_;
/// cache of sipm settings
std::array<std::optional<int>, N_CHANNELS> sipm_cache_;
/// cache of led settings
std::array<std::optional<int>, N_CHANNELS> led_cache_;
}; // Bias

} // namespace pflib
Expand Down
16 changes: 12 additions & 4 deletions include/pflib/HcalBackplane.h
Original file line number Diff line number Diff line change
Expand Up @@ -5,15 +5,15 @@

#include "pflib/Bias.h"
#include "pflib/GPIO.h"
#include "pflib/HcalTarget.h"
#include "pflib/TRIG.h"
#include "pflib/Target.h"

namespace pflib {

/**
* representing an HcalBackplane
*/
class HcalBackplane : public Target {
class HcalBackplane : public HcalTarget {
public:
/// virtual destructor since we'll be holding this as a Target
virtual ~HcalBackplane() = default;
Expand All @@ -28,8 +28,12 @@ class HcalBackplane : public Target {
* @param[in] trig_lpgbt accessor to TRIG lpGBT
* @param[in] hgcroc_boards bit-mask saying if a board is active/enabled (1)
* or inactive/disabled (0) - the bit in position i represents board i
* @param[in] use_bias_cache use software cache of bias voltage settings
* instead of readback direct from chip, see Bias class for why this
* is necessary in fiberfull setups
*/
void init(lpGBT& daq_lpgbt, lpGBT& trig_lpgbt, int hgcroc_boards);
void init(lpGBT& daq_lpgbt, lpGBT& trig_lpgbt, int hgcroc_boards,
bool use_bias_cache);

/** number of boards */
virtual int nrocs() override { return nhgcroc_; }
Expand All @@ -56,7 +60,7 @@ class HcalBackplane : public Target {
virtual ECON& econ(int which) override;

/** Get an I2C interface for the given HGCROC board's bias bus */
Bias bias(int which);
Bias& bias(int which) override;

/** Get the GPIO object for debugging purposes */
virtual GPIO& gpio() { return *gpio_; }
Expand Down Expand Up @@ -101,6 +105,10 @@ class HcalBackplane : public Target {
struct HGCROCBoard {
ROC roc;
Bias bias;
/// constructor to forward constructor arguments to members
HGCROCBoard(std::shared_ptr<I2C> roc_i2c, uint8_t roc_addr,
const std::string& roc_typename, std::shared_ptr<I2C> bias_i2c,
std::shared_ptr<I2C> board_i2c, bool bias_use_cache);
};

/// the backplane can hold up to 4 HGCROC boards
Expand Down
21 changes: 21 additions & 0 deletions include/pflib/HcalTarget.h
Original file line number Diff line number Diff line change
@@ -0,0 +1,21 @@
#pragma once
#ifndef PFLIB_HCALTARGET_H
#define PFLIB_HCALTARGET_H

#include "pflib/Target.h"

namespace pflib {

class Bias;

/**
* An HcalTarget is a Target with access to the biasing chips
*/
class HcalTarget : public Target {
public:
virtual Bias& bias(int which) = 0;
};

} // namespace pflib

#endif
Loading