17#include <boost/algorithm/string/predicate.hpp>
18#include <boost/tuple/tuple.hpp>
32UHAL_REGISTER_DERIVED_NODE(SI534xNode)
36 : SIChipSlave(i2c_master,
address)
41SI534xSlave::~SI534xSlave() {}
46SI534xSlave::read_config_id()
const
50 for (
size_t i(0); i < 8; ++i) {
51 char id_char =
static_cast<char>(read_clock_register(0x26b + i));
68SI534xSlave::seek_header(std::ifstream& file)
const
72 std::string design_id;
74 std::string config_line;
76 for (line_number = 1; std::getline(file, config_line); ++line_number) {
79 if (config_line.back() ==
'\r')
80 config_line.pop_back();
83 if (boost::starts_with(config_line,
"# Design ID:")) {
84 design_id = config_line.substr(13);
88 if (config_line[0] ==
'#')
92 if (config_line.length() == 0)
96 if (config_line ==
"Address,Data")
100 throw SI534xConfigError(
ERS_HERE,
"Incomplete file: End of file detected while seeking the header.");
104 TLOG_DEBUG(8) <<
"Found desing ID " << design_id;
115std::vector<SI534xSlave::RegisterSetting_t>
116SI534xSlave::read_config_section(std::ifstream& file, std::string tag)
const
122 bool section_found(
false);
124 std::vector<RegisterSetting_t> config;
125 std::string config_line;
126 uint32_t line_number;
127 for (line_number = 1; std::getline(file, config_line); ++line_number) {
130 if (config_line.back() ==
'\r')
131 config_line.pop_back();
134 if (config_line[0] ==
'#') {
139 if (boost::starts_with(config_line,
"# Start configuration " + tag)) {
140 section_found =
true;
144 if (boost::starts_with(config_line,
"# End configuration " + tag)) {
157 "Incomplete file: End of file detected before the end of " + tag +
" section.");
161 if (config_line.length() == 0)
165 if (!section_found && !tag.empty()) {
172 std::istringstream line_stream(config_line);
173 line_stream >> std::hex >>
address >> dummy >> std::hex >>
data;
175 std::stringstream debug_stream;
176 debug_stream << std::showbase << std::hex <<
"Address: " <<
address << dummy <<
" Data: " <<
data;
179 config.push_back(RegisterSetting_t(address, data));
188SI534xSlave::configure(
const std::string&
filename)
const
193 std::ifstream config_file(
filename);
194 std::string config_line;
195 std::string conf_design_id;
198 conf_design_id = seek_header(config_file);
199 std::ifstream::pos_type header_end = config_file.tellg();
208 std::vector<SI534xSlave::RegisterSetting_t> preamble, registers, postamble;
211 preamble = this->read_config_section(config_file,
"preamble");
212 registers = this->read_config_section(config_file,
"registers");
213 postamble = this->read_config_section(config_file,
"postamble");
214 }
catch (SI534xMissingConfigSectionError&) {
215 config_file.seekg(header_end);
217 registers = this->read_config_section(config_file,
"");
221 TLOG_DEBUG(8) <<
"Preamble size = " << preamble.size();
222 TLOG_DEBUG(8) <<
"Registers size = " << registers.size();
223 TLOG_DEBUG(8) <<
"PostAmble size = " << postamble.size();
228 this->write_clock_register(0x1E, 0x2);
229 }
catch (timing::I2CException& excp) {
233 std::this_thread::sleep_for(std::chrono::milliseconds(1000));
235 this->upload_config(preamble);
236 std::this_thread::sleep_for(std::chrono::milliseconds(300));
237 this->upload_config(registers);
238 this->upload_config(postamble);
240 std::string chip_design_id = this->read_config_id();
242 if (conf_design_id != chip_design_id) {
243 std::ostringstream message;
244 message <<
"Post-configuration check failed: Loaded design ID " << chip_design_id
245 <<
" does not match the configurationd design id " << conf_design_id << std::endl;
253SI534xSlave::upload_config(
const std::vector<SI534xSlave::RegisterSetting_t>& config)
const
256 size_t k(0), notify_percent(10);
257 size_t notify_every = (notify_percent < config.size() ? config.size() / notify_percent : 1);
259 for (
const auto& setting : config) {
260 std::stringstream debug_stream;
261 debug_stream << std::showbase << std::hex <<
"Writing to " << (uint32_t)setting.get<0>()
262 <<
" data " << (uint32_t)setting.get<1>();
265 uint32_t max_attempts(2), attempt(0);
266 while (attempt < max_attempts) {
274 this->write_clock_register(setting.get<0>(), setting.get<1>());
275 }
catch (
const std::exception& e) {
287 if ((k % notify_every) == 0) {
288 TLOG_DEBUG(9) << (k / notify_every) * notify_percent <<
"%";
295std::map<uint16_t, uint8_t>
296SI534xSlave::registers()
const
299 std::map<uint16_t, uint8_t> values;
301 for (uint8_t reg_addr = 0xc; reg_addr <= 0x12; reg_addr++) {
302 if (reg_addr > 0xf && reg_addr < 0x11) {
334 values[reg_addr] = read_clock_register(reg_addr);
343 SI534xSlave::get_info(timinghardwareinfo::TimingPLLMonitorData& mon_data)
const
345 mon_data.config_id = this->read_config_id();
351 uint8_t pll_reg_c = this->read_clock_register(0xc);
352 uint8_t pll_reg_d = this->read_clock_register(0xd);
353 uint8_t pll_reg_e = this->read_clock_register(0xe);
354 uint8_t pll_reg_f = this->read_clock_register(0xf);
355 uint8_t pll_reg_11 = this->read_clock_register(0x11);
356 uint8_t pll_reg_12 = this->read_clock_register(0x12);
358 mon_data.cal_pll =
dec_rng(pll_reg_f, 5);
359 mon_data.hold =
dec_rng(pll_reg_e, 5);
360 mon_data.lol =
dec_rng(pll_reg_e, 1);
361 mon_data.los =
dec_rng(pll_reg_d, 0, 4);
362 mon_data.los_xaxb =
dec_rng(pll_reg_c, 1);
363 mon_data.los_xaxb_flg =
dec_rng(pll_reg_11, 1);
365 mon_data.oof =
dec_rng(pll_reg_d, 4, 4);
366 mon_data.oof_sticky =
dec_rng(pll_reg_12, 4, 4);
368 mon_data.smbus_timeout =
dec_rng(pll_reg_c, 5);
369 mon_data.smbus_timeout_flg =
dec_rng(pll_reg_11, 5);
371 mon_data.sys_in_cal =
dec_rng(pll_reg_c, 0);
372 mon_data.sys_in_cal_flg =
dec_rng(pll_reg_11, 0);
374 mon_data.xaxb_err =
dec_rng(pll_reg_c, 3);
375 mon_data.xaxb_err_flg =
dec_rng(pll_reg_11, 3);
381SI534xSlave::get_status(
bool print_out)
const
384 status <<
"PLL configuration id : " << this->read_config_id() << std::endl;
386 std::map<std::string, uint32_t> pll_version;
387 pll_version[
"Part number"] = this->read_device_version();
388 pll_version[
"Device grade"] = this->read_clock_register(0x4);
389 pll_version[
"Device revision"] = this->read_clock_register(0x5);
393 std::map<std::string, uint32_t> pll_registers;
395 uint8_t pll_reg_c = this->read_clock_register(0xc);
396 uint8_t pll_reg_d = this->read_clock_register(0xd);
397 uint8_t pll_reg_e = this->read_clock_register(0xe);
398 uint8_t pll_reg_f = this->read_clock_register(0xf);
399 uint8_t pll_reg_11 = this->read_clock_register(0x11);
400 uint8_t pll_reg_12 = this->read_clock_register(0x12);
402 pll_registers[
"CAL_PLL"] =
dec_rng(pll_reg_f, 5);
403 pll_registers[
"HOLD"] =
dec_rng(pll_reg_e, 5);
404 pll_registers[
"LOL"] =
dec_rng(pll_reg_e, 1);
405 pll_registers[
"LOS"] =
dec_rng(pll_reg_d, 0, 4);
406 pll_registers[
"LOSXAXB"] =
dec_rng(pll_reg_c, 1);
407 pll_registers[
"LOSXAXB_FLG"] =
dec_rng(pll_reg_11, 1);
409 pll_registers[
"OOF"] =
dec_rng(pll_reg_d, 4, 4);
410 pll_registers[
"OOF (sticky)"] =
dec_rng(pll_reg_12, 4, 4);
412 pll_registers[
"SMBUS_TIMEOUT"] =
dec_rng(pll_reg_c, 5);
413 pll_registers[
"SMBUS_TIMEOUT_FLG"] =
dec_rng(pll_reg_11, 5);
415 pll_registers[
"SYSINCAL"] =
dec_rng(pll_reg_c, 0);
416 pll_registers[
"SYSINCAL_FLG"] =
dec_rng(pll_reg_11, 0);
418 pll_registers[
"XAXB_ERR"] =
dec_rng(pll_reg_c, 3);
419 pll_registers[
"XAXB_ERR_FLG"] =
dec_rng(pll_reg_11, 3);
430SI534xNode::SI534xNode(
const uhal::Node& node)
432 , SI534xSlave(this, this->get_slave_address(
"i2caddr"))
437SI534xNode::SI534xNode(
const SI534xNode& node)
439 , SI534xSlave(this, this->get_slave_address(
"i2caddr"))
444SI534xNode::~SI534xNode() {}
OpenCode I2C interface to a ipbus node.
#define TLOG_DEBUG(lvl,...)
std::string format_reg_table(T data, std::string title, std::vector< std::string > headers)
Format reg-value table.
uint8_t dec_rng(uint8_t word, uint8_t ibit, uint8_t nbits=1)
void throw_if_not_file(const std::string &path)
std::string format_reg_value(T reg_value, uint32_t base)
SI534xMissingConfigSectionError
< Namespace
Missing configuration std::string tag SI534xRegWriteRetry
< Namespace
void warning(const Issue &issue)
void error(const Issue &issue)