blob: 984dd49ec5e5319c49c34e29471d3fa80dc18967 [file]
#include "include/power_rail/max34451_status.hpp"
namespace max34451
{
void max34451BBRParser(const std::vector<uint8_t>& bbrArray,
std::ofstream& logFile)
{
constexpr uint8_t kFaultLogIndex = 1;
constexpr uint8_t kStatusCmlIndex = 10;
constexpr uint8_t kLogValidIndex = 254;
constexpr uint8_t kStatusWordMsbIndex = 13;
constexpr uint8_t kStatusWordLsbIndex = 12;
logFile << std::hex << std::setw(4) << std::setfill('0');
logFile << "FAULT LOG INDEX: " << static_cast<int>(bbrArray[kFaultLogIndex])
<< '\n';
getWordAndLog(logFile, bbrArray, 3, 2, "FAULT_LOG_COUNT: ");
getWordAndLog(logFile, bbrArray, 5, 4, "MFR_TIME_COUNT(LSW): ");
getWordAndLog(logFile, bbrArray, 7, 6, "MFR_TIME_COUNT(MSW): ");
logFile << "STATUS_CML: " << static_cast<int>(bbrArray[kStatusCmlIndex])
<< " " << parserStatusCml(bbrArray[kStatusCmlIndex]) << '\n';
logFile << parserStatusWord(
getWordAndLog(logFile, bbrArray, kStatusWordMsbIndex,
kStatusWordLsbIndex, "STATUS_WORD: "))
<< '\n';
constexpr uint8_t kVoutIoutStartIndex = 14;
constexpr uint8_t kVoutIoutEndIndex = 29;
for (uint8_t i = kVoutIoutStartIndex; i <= kVoutIoutEndIndex; ++i)
{
const uint8_t page = i - kVoutIoutStartIndex;
logFile << "Page " << static_cast<int>(page)
<< " STATUS_VOUT/STATUS_IOUT: " << static_cast<int>(bbrArray[i])
<< '\n';
logFile << "STATUS_VOUT: " << parserStatusVout(bbrArray[i]) << '\n';
logFile << "STATUS_IOUT: " << parserStatusIout(bbrArray[i]) << '\n';
}
constexpr uint8_t kMfrSpecificStartIndex = 30;
constexpr uint8_t kMfrSpecificEndIndex = 47;
for (uint8_t i = kMfrSpecificStartIndex; i <= kMfrSpecificEndIndex; ++i)
{
// NOLINTNEXTLINE(readability-avoid-nested-conditional-operator)
const uint8_t page = (i == 46) ? 255
: (i == 47) ? 0 // NOLINT
: i - kMfrSpecificStartIndex;
logFile << "Page " << static_cast<int>(page)
<< " STATUS_MFR_SPECIFIC: " << static_cast<int>(bbrArray[i])
<< " ";
parseStatusMfrSpecific(bbrArray[i], logFile);
}
constexpr uint8_t kTemperatureStartIndex = 48;
constexpr uint8_t kTemperatureEndIndex = 53;
for (uint8_t i = kTemperatureStartIndex; i <= kTemperatureEndIndex; ++i)
{
const uint8_t page = (i == 53) ? 0 : i - 32;
logFile << "Page " << static_cast<int>(page)
<< " STATUS_TEMPERATURE: " << static_cast<int>(bbrArray[i])
<< " " << parserStatusTemperature(bbrArray[i]) << '\n';
}
getWordAndLog(logFile, bbrArray, 55, 54, "CURRENT_CHANNELS: ");
constexpr uint8_t kReadVoutIoutStartIndex = 60;
constexpr uint8_t kReadVoutIoutEndIndex = 150;
constexpr uint8_t kReadVoutIoutStep = 6;
for (uint8_t i = kReadVoutIoutStartIndex; i <= kReadVoutIoutEndIndex;
i += kReadVoutIoutStep)
{
const uint8_t page = (i - kReadVoutIoutStartIndex) / kReadVoutIoutStep;
for (uint8_t k = 0; k <= 4; k += 2)
{
const uint8_t number = i + k;
const uint16_t readOut = (bbrArray[number + 1] << 8) |
bbrArray[number];
logFile << "Page " << static_cast<int>(page) << " T "
<< static_cast<int>(k / 2) << " READ_VOUT/READ_IOUT: 0x"
<< std::setw(4) << std::setfill('0') << readOut << std::dec
<< '\n';
logFile << "READ_VOUT: "
<< transferDirectDataFormat(1, readOut, 0, 0) << " mV"
<< '\n';
logFile << "READ_IOUT: "
<< transferDirectDataFormat(1, readOut, 2, 0) << " A"
<< '\n';
}
}
constexpr uint8_t kMfrPeakStartIndex = 164;
constexpr uint8_t kMfrPeakEndIndex = 194;
for (uint8_t i = kMfrPeakStartIndex; i <= kMfrPeakEndIndex; i += 2)
{
const uint8_t page = (i - kMfrPeakStartIndex) / 2;
getWordAndLog(logFile, bbrArray, i + 1, i,
"Page " + std::to_string(page) +
" MFR_VOUT_PEAK/MFR_IOUT_PEAK: ");
}
constexpr uint8_t kMfrVoutMinStartIndex = 196;
constexpr uint8_t kMfrVoutMinEndIndex = 226;
for (uint8_t i = kMfrVoutMinStartIndex; i <= kMfrVoutMinEndIndex; i += 2)
{
const uint8_t page = (i - kMfrVoutMinStartIndex) / 2;
logFile << transferDirectDataFormat(
1,
getWordAndLog(logFile, bbrArray, i + 1, i,
"Page " + std::to_string(page) +
" MFR_VOUT_MIN: "),
0, 0)
<< " mV" << '\n';
}
constexpr uint8_t kReadTempStartIndex = 232;
constexpr uint8_t kReadTempEndIndex = 240;
for (uint8_t i = kReadTempStartIndex; i <= kReadTempEndIndex; i += 2)
{
const uint8_t page = (i - kReadTempStartIndex) / 2 + 16;
logFile << transferDirectDataFormat(
1,
getWordAndLog(logFile, bbrArray, i + 1, i,
"Page " + std::to_string(page) +
" READ_TEMPERATURE_1: "),
2, 0)
<< " C" << '\n';
}
constexpr uint8_t kMfrTempPeakStartIndex = 242;
constexpr uint8_t kMfrTempPeakEndIndex = 250;
for (uint8_t i = kMfrTempPeakStartIndex; i <= kMfrTempPeakEndIndex; i += 2)
{
const uint8_t page = (i - kMfrTempPeakStartIndex) / 2 + 16;
getWordAndLog(logFile, bbrArray, i + 1, i,
"Page " + std::to_string(page) +
" MFR_TEMPERATURE_PEAK: ");
}
logFile << "LOG_VALID: 0x" << std::setw(2) << std::setfill('0')
<< static_cast<int>(bbrArray[kLogValidIndex]) << std::dec << '\n';
logFile << std::dec;
}
uint16_t getMfrChannelConfig(const Max34451Logger& logger)
{
const auto data = util::i2cReadBytes(logger.bus, logger.address,
logger.mfrChannelConfigReg, 2);
if (data.size() < 2)
{
lg2::error("Failed to read MFR_CHANNEL_CONFIG");
return 0;
}
return static_cast<uint16_t>(data[0]) |
(static_cast<uint16_t>(data[1]) << 8);
}
void setMfrChannelConfig(const Max34451Logger& logger, const uint16_t value)
{
util::i2cWriteByte(logger.bus, logger.address, logger.mfrChannelConfigReg,
value);
}
std::vector<uint8_t> getMfrPsenConfig(const Max34451Logger& logger)
{
return util::i2cReadBytes(logger.bus, logger.address,
logger.mfrPsenConfigReg, 4);
}
std::vector<uint8_t> getMfrPwmConfig(const Max34451Logger& logger)
{
return util::i2cReadBytes(logger.bus, logger.address,
logger.mfrPwmConfigReg, 4);
}
uint8_t getMfrNvFaultLog(const Max34451Logger& logger)
{
return util::i2cReadByte(logger.bus, logger.address,
logger.mfrNvFaultLogReg);
}
uint16_t getStatusMfrNvLogConfig(const Max34451Logger& logger)
{
const auto data = util::i2cReadBytes(logger.bus, logger.address,
logger.mfrNvLogConfigReg, 2);
if (data.size() < 2)
{
lg2::error("Failed to read STATUS_MFR_NV_LOG_CONFIG");
return 0;
}
return static_cast<uint16_t>(data[0]) |
(static_cast<uint16_t>(data[1]) << 8);
}
uint8_t getStatusCmlMax34451(const Max34451Logger& logger)
{
return util::i2cReadByte(logger.bus, logger.address, logger.statusCmlReg);
}
std::string parserStatusCmlMax34451(const uint8_t statusCmlMax34451)
{
if (statusCmlMax34451 == 0xff)
{
return "INVALID";
}
std::map<uint8_t, std::string> statusMap = {{7, "COMM_FAULT "},
{6, "DATA_FAULT "},
{2, "BACKUP_FAULT "},
{1, "MAIN_FAULT "},
{0, "FAULT_LOG_FULL "}};
std::string result;
for (const auto& [bit, status] : statusMap)
{
if ((statusCmlMax34451 & (1 << bit)) != 0)
{
result += status;
}
}
return result;
}
void getStatusMfrSpecific(const Max34451Logger& logger, std::ofstream& logFile)
{
const uint8_t statusMfrSpecific = util::i2cReadByte(
logger.bus, logger.address, logger.statusMfrSpecificReg);
logFile << "STATUS_MFR_SPECIFIC = 0x" << std::hex
<< static_cast<int>(statusMfrSpecific) << " ";
parseStatusMfrSpecific(statusMfrSpecific, logFile);
}
void parseStatusMfrSpecific(const uint8_t statusMfrSpecific,
std::ofstream& logFile)
{
if ((statusMfrSpecific & (1 << 7)) != 0)
{
logFile << "OFF ";
}
if ((statusMfrSpecific & (1 << 3)) != 0)
{
logFile << "MARGIN_FAULT ";
}
if ((statusMfrSpecific & (1 << 2)) != 0)
{
logFile << "POWER_GOOD# ";
}
logFile << '\n';
}
void getMax34451Status(const Max34451Logger& logger, std::ofstream& logFile)
{
logFile << "MAX34451 BUS:" << std::to_string(logger.bus)
<< " ADDR:" << std::hex << std::to_string(logger.address) << "\n";
auto logRailStatus = [&](const std::string& railName, uint8_t pageIndex) {
loadPage(logger.bus, logger.address, pageIndex);
logFile << railName << " Status:\n";
logFile << "STATUS_VOUT: "
<< parserStatusVout(getStatusVout(logger.bus, logger.address))
<< "\n";
logFile << "STATUS_IOUT: "
<< parserStatusIout(getStatusIout(logger.bus, logger.address))
<< "\n";
logFile << "STATUS_CML: "
<< parserStatusCmlMax34451(getStatusCmlMax34451(logger))
<< "\n";
logFile << "MFR_CHANNEL_CONFIG: " << std::hex
<< getMfrChannelConfig(logger) << "\n";
logFile << "READ_VOUT: "
<< transferDirectDataFormat(
1, getStatusByte(logger.bus, logger.address), 0, 0)
<< " mV\n";
logFile << "READ_IOUT: "
<< transferDirectDataFormat(
1, getStatusByte(logger.bus, logger.address), 2, 0)
<< " A\n";
logFile << "VOUT_OV_FAULT_LIMIT: "
<< transferDirectDataFormat(
1, getVoutOvFaultLimit(logger.bus, logger.address), 0, 0)
<< " mV\n";
logFile << "IOUT_OC_FAULT_LIMIT: "
<< transferDirectDataFormat(
1, getIoutOcFaultLimit(logger.bus, logger.address), 2, 0)
<< " A\n";
if (pageIndex < 12)
{
logFile << "MFR_PSEN_CONFIG: ";
for (const auto& psenConfig : getMfrPsenConfig(logger))
{
logFile << std::hex << static_cast<int>(psenConfig) << " ";
}
logFile << "\n";
}
getStatusMfrSpecific(logger, logFile);
logFile << "STATUS_MFR_NV_LOG_CONFIG = "
<< getStatusMfrNvLogConfig(logger) << "\n";
if (pageIndex < 8)
{
logFile << "MFR_PWM_CONFIG: ";
for (const auto& pwmConfig : getMfrPwmConfig(logger))
{
logFile << std::hex << static_cast<int>(pwmConfig) << " ";
}
logFile << "\n";
}
};
for (const auto& seqReg : logger.sequencerRegisters)
{
for (const auto& [page, railName] : seqReg[kPageToPowerRailMap].items())
{
const uint8_t pageIndex = util::parseDec(page);
logRailStatus(railName.get<std::string>(), pageIndex);
}
}
logFile << getPage255Config(logger) << '\n';
}
uint16_t getFaultStatus(const Max34451Logger& logger)
{
const auto statusWord = util::i2cReadBytes(logger.bus, logger.address,
logger.statusWordReg, 2);
return (statusWord[1] << 8) | statusWord[0];
}
std::string getStatusMfrSpecificMax34451Page255(const Max34451Logger& logger)
{
const uint8_t statusMfrSpecific = util::i2cReadByte(
logger.bus, logger.address, logger.statusMfrSpecificReg);
std::string result;
result += "STATUS_MFR_SPECIFIC = 0x" + std::to_string(statusMfrSpecific) +
" ";
std::map<uint8_t, std::string> statusMap = {{7, "LOCK "},
{6, "FAULT_INPUT "},
{5, "POR "},
{4, "WATCHDOG_INT "},
{3, "CONTROL# "}};
if (statusMfrSpecific != 0)
{
for (const auto& [bit, status] : statusMap)
{
if ((statusMfrSpecific & (1 << bit)) != 0)
{
result += status;
}
}
}
else
{
result += "STATUS_MFR_SPECIFIC INVALID";
}
return result;
}
std::string getPage255Config(const Max34451Logger& logger)
{
std::string result;
result += "get page255 status and config\n";
loadPage(logger.bus, logger.address, 255);
result += "ON_OFF_CONFIG = " +
std::to_string(getOnOffConfig(logger.bus, logger.address)) + "\n";
result += getStatusMfrSpecificMax34451Page255(logger) + "\n";
return result;
}
void runMax34451Logger(const std::filesystem::path& configFilePath,
const std::filesystem::path& logDirPath,
const bool logDetails)
{
std::filesystem::create_directories(logDirPath);
Max34451Logger logger;
logger.loadConfig(configFilePath.string());
const std::string logFilePath = logDirPath / (logger.source + ".log");
std::ofstream logFile(logFilePath);
unbindI2cDevice(logger.bus, logger.address);
usleep(1000000);
const uint16_t faultStatus = getStatusWord(logger.bus, logger.address);
if (faultStatus != 0x0000)
{
lg2::info("MAX34451: Fault detected! Status word: {FAULT}", "FAULT",
faultStatus);
logFile << "MAX34451: Fault detected! Status word: " << std::hex
<< faultStatus << '\n';
if (logDetails)
{
logFile << "[MAX34451 VR log]" << '\n';
getMax34451Status(logger, logFile);
}
forceMax34451Log(logger);
std::vector<uint8_t> max34451BB = getMax34451BB(logger);
if (!max34451BB.empty())
{
if (logDetails)
{
max34451BBRParser(max34451BB, logFile);
}
else
{
max34451PowerRailParser(logger, max34451BB, logFile);
}
}
clearMax34451BB(logger);
}
else
{
lg2::info("MAX34451: No fault detected.");
}
bindI2cDevice(logger.source, logger.bus, logger.address);
lg2::info("MAX34451: Status check completed.");
logFile.close();
}
} // namespace max34451
int main(int argc, char* argv[])
{
CLI::App app{"MAX34451 Status Checker"};
std::filesystem::path configFilePath;
std::filesystem::path logDirPath;
bool logDetails = false;
std::cout << "max34451 status" << '\n';
app.add_option("-c,--config", configFilePath, "Config file path")
->required()
->check(CLI::ExistingFile);
app.add_option("-l,--log", logDirPath, "Log directory path")->required();
app.add_flag("-d,--details", logDetails, "Enable detailed logging");
try
{
app.parse(argc, argv);
}
catch (const CLI::Error& e)
{
return app.exit(e);
}
max34451::runMax34451Logger(configFilePath, logDirPath, logDetails);
return EXIT_SUCCESS;
}