129 lines
6.4 KiB
C++
129 lines
6.4 KiB
C++
#include "mmu2_error_converter.h"
|
|
#include "mmu2/error_codes.h"
|
|
#include "mmu2/errors_list.h"
|
|
#include "language.h"
|
|
#include <stdio.h>
|
|
|
|
namespace MMU2 {
|
|
|
|
// we don't have a constexpr find_if in C++17/STL yet
|
|
template <class InputIt, class UnaryPredicate>
|
|
constexpr InputIt find_if_cx(InputIt first, InputIt last, UnaryPredicate p) {
|
|
for (; first != last; ++first) {
|
|
if (p(*first)) {
|
|
return first;
|
|
}
|
|
}
|
|
return last;
|
|
}
|
|
|
|
// Making a constexpr FindError should instruct the compiler to optimize the ConvertMMUErrorCode
|
|
// in such a way that no searching will ever be done at runtime.
|
|
// A call to FindError then compiles to a single instruction even on the AVR.
|
|
static constexpr uint16_t FindErrorIndex(uint32_t pec) {
|
|
constexpr uint32_t errorCodesSize = sizeof(errorCodes) / sizeof(errorCodes[0]);
|
|
constexpr auto errorCodesEnd = errorCodes + errorCodesSize;
|
|
auto i = find_if_cx(errorCodes, errorCodesEnd, [pec](uint16_t ed) -> bool {
|
|
return ed == pec;
|
|
});
|
|
return i != errorCodesEnd ? *i : errorCodes[errorCodesSize - 1];
|
|
}
|
|
|
|
const uint16_t MMUErrorCodeIndex(uint16_t ec) {
|
|
switch (ec) {
|
|
case (uint16_t)ErrorCode::FINDA_DIDNT_SWITCH_ON:
|
|
return FindErrorIndex(ERR_MECHANICAL_FINDA_DIDNT_TRIGGER);
|
|
case (uint16_t)ErrorCode::FINDA_DIDNT_SWITCH_OFF:
|
|
return FindErrorIndex(ERR_MECHANICAL_FINDA_DIDNT_GO_OFF);
|
|
case (uint16_t)ErrorCode::FSENSOR_DIDNT_SWITCH_ON:
|
|
return FindErrorIndex(ERR_MECHANICAL_FSENSOR_DIDNT_TRIGGER);
|
|
case (uint16_t)ErrorCode::FSENSOR_DIDNT_SWITCH_OFF:
|
|
return FindErrorIndex(ERR_MECHANICAL_FSENSOR_DIDNT_GO_OFF);
|
|
case (uint16_t)ErrorCode::STALLED_PULLEY:
|
|
case (uint16_t)ErrorCode::MOVE_PULLEY_FAILED:
|
|
return FindErrorIndex(ERR_MECHANICAL_PULLEY_CANNOT_MOVE);
|
|
case (uint16_t)ErrorCode::HOMING_SELECTOR_FAILED:
|
|
return FindErrorIndex(ERR_MECHANICAL_SELECTOR_CANNOT_HOME);
|
|
case (uint16_t)ErrorCode::MOVE_SELECTOR_FAILED:
|
|
return FindErrorIndex(ERR_MECHANICAL_SELECTOR_CANNOT_MOVE);
|
|
case (uint16_t)ErrorCode::HOMING_IDLER_FAILED:
|
|
return FindErrorIndex(ERR_MECHANICAL_IDLER_CANNOT_HOME);
|
|
case (uint16_t)ErrorCode::MMU_NOT_RESPONDING:
|
|
return FindErrorIndex(ERR_MECHANICAL_IDLER_CANNOT_MOVE);
|
|
case (uint16_t)ErrorCode::PROTOCOL_ERROR:
|
|
return FindErrorIndex(ERR_CONNECT_COMMUNICATION_ERROR);
|
|
case (uint16_t)ErrorCode::FILAMENT_ALREADY_LOADED:
|
|
return FindErrorIndex(ERR_SYSTEM_FILAMENT_ALREADY_LOADED);
|
|
case (uint16_t)ErrorCode::INVALID_TOOL:
|
|
return FindErrorIndex(ERR_SYSTEM_INVALID_TOOL);
|
|
case (uint16_t)ErrorCode::QUEUE_FULL:
|
|
return FindErrorIndex(ERR_SYSTEM_QUEUE_FULL);
|
|
case (uint16_t)ErrorCode::VERSION_MISMATCH:
|
|
return FindErrorIndex(ERR_SYSTEM_FW_UPDATE_NEEDED);
|
|
case (uint16_t)ErrorCode::INTERNAL:
|
|
return FindErrorIndex(ERR_SYSTEM_FW_RUNTIME_ERROR);
|
|
case (uint16_t)ErrorCode::FINDA_VS_EEPROM_DISREPANCY:
|
|
return FindErrorIndex(ERR_SYSTEM_UNLOAD_MANUALLY);
|
|
}
|
|
|
|
// // TMC-related errors - multiple of these can occur at once
|
|
// // - in such a case we report the first which gets found/converted into Prusa-Error-Codes (usually the fact, that one TMC has an issue is serious enough)
|
|
// // By carefully ordering the checks here we can prioritize the errors being reported to the user.
|
|
if (ec & (uint16_t)ErrorCode::TMC_PULLEY_BIT) {
|
|
if (ec & (uint16_t)ErrorCode::TMC_IOIN_MISMATCH)
|
|
return FindErrorIndex(ERR_ELECTRICAL_PULLEY_TMC_DRIVER_ERROR);
|
|
if (ec & (uint16_t)ErrorCode::TMC_RESET)
|
|
return FindErrorIndex(ERR_ELECTRICAL_PULLEY_TMC_DRIVER_RESET);
|
|
if (ec & (uint16_t)ErrorCode::TMC_UNDERVOLTAGE_ON_CHARGE_PUMP)
|
|
return FindErrorIndex(ERR_ELECTRICAL_PULLEY_TMC_UNDERVOLTAGE_ERROR);
|
|
if (ec & (uint16_t)ErrorCode::TMC_SHORT_TO_GROUND)
|
|
return FindErrorIndex(ERR_ELECTRICAL_PULLEY_TMC_DRIVER_SHORTED);
|
|
if (ec & (uint16_t)ErrorCode::TMC_OVER_TEMPERATURE_WARN)
|
|
return FindErrorIndex(ERR_TEMPERATURE_PULLEY_WARNING_TMC_TOO_HOT);
|
|
if (ec & (uint16_t)ErrorCode::TMC_OVER_TEMPERATURE_ERROR)
|
|
return FindErrorIndex(ERR_TEMPERATURE_PULLEY_TMC_OVERHEAT_ERROR);
|
|
} else if (ec & (uint16_t)ErrorCode::TMC_SELECTOR_BIT) {
|
|
if (ec & (uint16_t)ErrorCode::TMC_IOIN_MISMATCH)
|
|
return FindErrorIndex(ERR_ELECTRICAL_SELECTOR_TMC_DRIVER_ERROR);
|
|
if (ec & (uint16_t)ErrorCode::TMC_RESET)
|
|
return FindErrorIndex(ERR_ELECTRICAL_SELECTOR_TMC_DRIVER_RESET);
|
|
if (ec & (uint16_t)ErrorCode::TMC_UNDERVOLTAGE_ON_CHARGE_PUMP)
|
|
return FindErrorIndex(ERR_ELECTRICAL_SELECTOR_TMC_UNDERVOLTAGE_ERROR);
|
|
if (ec & (uint16_t)ErrorCode::TMC_SHORT_TO_GROUND)
|
|
return FindErrorIndex(ERR_ELECTRICAL_SELECTOR_TMC_DRIVER_SHORTED);
|
|
if (ec & (uint16_t)ErrorCode::TMC_OVER_TEMPERATURE_WARN)
|
|
return FindErrorIndex(ERR_TEMPERATURE_SELECTOR_WARNING_TMC_TOO_HOT);
|
|
if (ec & (uint16_t)ErrorCode::TMC_OVER_TEMPERATURE_ERROR)
|
|
return FindErrorIndex(ERR_TEMPERATURE_SELECTOR_TMC_OVERHEAT_ERROR);
|
|
} else if (ec & (uint16_t)ErrorCode::TMC_IDLER_BIT) {
|
|
if (ec & (uint16_t)ErrorCode::TMC_IOIN_MISMATCH)
|
|
return FindErrorIndex(ERR_ELECTRICAL_IDLER_TMC_DRIVER_ERROR);
|
|
if (ec & (uint16_t)ErrorCode::TMC_RESET)
|
|
return FindErrorIndex(ERR_ELECTRICAL_IDLER_TMC_DRIVER_RESET);
|
|
if (ec & (uint16_t)ErrorCode::TMC_UNDERVOLTAGE_ON_CHARGE_PUMP)
|
|
return FindErrorIndex(ERR_ELECTRICAL_IDLER_TMC_UNDERVOLTAGE_ERROR);
|
|
if (ec & (uint16_t)ErrorCode::TMC_SHORT_TO_GROUND)
|
|
return FindErrorIndex(ERR_ELECTRICAL_IDLER_TMC_DRIVER_SHORTED);
|
|
if (ec & (uint16_t)ErrorCode::TMC_OVER_TEMPERATURE_WARN)
|
|
return FindErrorIndex(ERR_TEMPERATURE_IDLER_WARNING_TMC_TOO_HOT);
|
|
if (ec & (uint16_t)ErrorCode::TMC_OVER_TEMPERATURE_ERROR)
|
|
return FindErrorIndex(ERR_TEMPERATURE_IDLER_TMC_OVERHEAT_ERROR);
|
|
}
|
|
|
|
// // if nothing got caught, return a generic error
|
|
// return FindError(ERR_OTHER);
|
|
}
|
|
|
|
void TranslateErr(uint16_t ec, char *dst, size_t dstSize) {
|
|
uint16_t ei = MMUErrorCodeIndex(ec);
|
|
// just to prevent the compiler from stripping the data structures from the final binary for now
|
|
*dst = errorButtons[ei];
|
|
snprintf(
|
|
dst, dstSize, "%S %S",
|
|
static_cast<const char * const>(pgm_read_ptr(&errorTitles[ei])),
|
|
static_cast<const char * const>(pgm_read_ptr(&errorDescs[ei]))
|
|
);
|
|
}
|
|
|
|
} // namespace MMU2
|