diff --git a/CMakeLists.txt b/CMakeLists.txt index db9d487..5f56ff2 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -188,6 +188,7 @@ target_sources( src/hal/avr/cpu.cpp src/hal/avr/usart.cpp src/hal/avr/shr16.cpp + src/hal/avr/eeprom.cpp src/hal/adc.cpp src/modules/protocol.cpp src/modules/buttons.cpp @@ -197,6 +198,7 @@ target_sources( src/modules/idler.cpp src/modules/leds.cpp src/modules/motion.cpp + src/modules/permanent_storage.cpp src/modules/selector.cpp src/logic/command_base.cpp src/logic/cut_filament.cpp diff --git a/src/hal/avr/eeprom.cpp b/src/hal/avr/eeprom.cpp new file mode 100644 index 0000000..264d242 --- /dev/null +++ b/src/hal/avr/eeprom.cpp @@ -0,0 +1,11 @@ +#include "../eeprom.h" + +namespace hal { +namespace eeprom { + +uint8_t ReadByte(const uint8_t *addr) { + return 0; +} + +} // namespace eeprom +} // namespace hal diff --git a/src/hal/eeprom.h b/src/hal/eeprom.h index 8cffa0d..5b0aef2 100644 --- a/src/hal/eeprom.h +++ b/src/hal/eeprom.h @@ -2,19 +2,19 @@ #include namespace hal { -namespace EEPROM { +namespace eeprom { - /// EEPROM interface - void WriteByte(const uint8_t *addr, uint8_t value); - void UpdateByte(const uint8_t *addr, uint8_t value); - uint8_t ReadByte(const uint8_t *addr); +/// EEPROM interface +extern void WriteByte(const uint8_t *addr, uint8_t value); +extern void UpdateByte(const uint8_t *addr, uint8_t value); +extern uint8_t ReadByte(const uint8_t *addr); - void WriteWord(const uint8_t *addr, uint16_t value); - void UpdateWord(const uint8_t *addr, uint16_t value); - uint16_t ReadWord(const uint8_t *addr); +extern void WriteWord(const uint8_t *addr, uint16_t value); +extern void UpdateWord(const uint8_t *addr, uint16_t value); +extern uint16_t ReadWord(const uint8_t *addr); - /// @returns physical end address of EEPROM memory end - constexpr const uint16_t End(); +/// @returns physical end address of EEPROM memory end +extern constexpr const uint16_t End(); } // namespace EEPROM } // namespace hal diff --git a/src/modules/permanent_storage.cpp b/src/modules/permanent_storage.cpp index 038837c..df3740c 100644 --- a/src/modules/permanent_storage.cpp +++ b/src/modules/permanent_storage.cpp @@ -7,348 +7,348 @@ namespace permanent_storage { #define ARR_SIZE(ARRAY) (sizeof(ARRAY) / sizeof(ARRAY[0])) - /// @brief EEPROM data layout - /// - /// Do not remove, reorder or change size of existing fields. - /// Otherwise values stored with previous version of firmware would be broken. - /// It is possible to add fields in the end of this struct, ensuring that erased EEPROM is handled well. - /// Last byte in EEPROM is reserved for layoutVersion. If some field is repurposed, layoutVersion - /// needs to be changed to force an EEPROM erase. - struct eeprom_t { - uint8_t eepromLengthCorrection; ///< Legacy bowden length correction - uint16_t eepromBowdenLen[5]; ///< Bowden length for each filament - uint8_t eepromFilamentStatus[3]; ///< Majority vote status of eepromFilament wear leveling - uint8_t eepromFilament[800]; ///< Top nibble status, bottom nibble last filament loaded - uint8_t eepromDriveErrorCountH; - uint8_t eepromDriveErrorCountL[2]; - } __attribute__((packed)); +/// @brief EEPROM data layout +/// +/// Do not remove, reorder or change size of existing fields. +/// Otherwise values stored with previous version of firmware would be broken. +/// It is possible to add fields in the end of this struct, ensuring that erased EEPROM is handled well. +/// Last byte in EEPROM is reserved for layoutVersion. If some field is repurposed, layoutVersion +/// needs to be changed to force an EEPROM erase. +struct eeprom_t { + uint8_t eepromLengthCorrection; ///< Legacy bowden length correction + uint16_t eepromBowdenLen[5]; ///< Bowden length for each filament + uint8_t eepromFilamentStatus[3]; ///< Majority vote status of eepromFilament wear leveling + uint8_t eepromFilament[800]; ///< Top nibble status, bottom nibble last filament loaded + uint8_t eepromDriveErrorCountH; + uint8_t eepromDriveErrorCountL[2]; +} __attribute__((packed)); - // @@TODO static_assert(sizeof(eeprom_t) - 2 <= hal::EEPROM::End(), "eeprom_t doesn't fit into EEPROM available."); +// @@TODO static_assert(sizeof(eeprom_t) - 2 <= hal::EEPROM::End(), "eeprom_t doesn't fit into EEPROM available."); - /// @brief EEPROM layout version - static const uint8_t layoutVersion = 0xff; +/// @brief EEPROM layout version +static const uint8_t layoutVersion = 0xff; - //d = 6.3 mm pulley diameter - //c = pi * d pulley circumference - //FSPR = 200 full steps per revolution (stepper motor constant) (1.8 deg/step) - //mres = 2 pulley microstep resolution (uint8_t __res(AX_PUL)) - //mres = 2 selector microstep resolution (uint8_t __res(AX_SEL)) - //mres = 16 idler microstep resolution (uint8_t __res(AX_IDL)) - //1 pulley ustep = (d*pi)/(mres*FSPR) = 49.48 um +//d = 6.3 mm pulley diameter +//c = pi * d pulley circumference +//FSPR = 200 full steps per revolution (stepper motor constant) (1.8 deg/step) +//mres = 2 pulley microstep resolution (uint8_t __res(AX_PUL)) +//mres = 2 selector microstep resolution (uint8_t __res(AX_SEL)) +//mres = 16 idler microstep resolution (uint8_t __res(AX_IDL)) +//1 pulley ustep = (d*pi)/(mres*FSPR) = 49.48 um - static eeprom_t *const eepromBase = reinterpret_cast(0); ///< First EEPROM address - static const uint16_t eepromEmpty = 0xffff; ///< EEPROM content when erased - static const uint16_t eepromLengthCorrectionBase = 7900u; ///< legacy bowden length correction base (~391mm) - static const uint16_t eepromBowdenLenDefault = 8900u; ///< Default bowden length (~427 mm) - static const uint16_t eepromBowdenLenMinimum = 6900u; ///< Minimum bowden length (~341 mm) - static const uint16_t eepromBowdenLenMaximum = 16000u; ///< Maximum bowden length (~792 mm) +static eeprom_t *const eepromBase = reinterpret_cast(0); ///< First EEPROM address +static const uint16_t eepromEmpty = 0xffff; ///< EEPROM content when erased +static const uint16_t eepromLengthCorrectionBase = 7900u; ///< legacy bowden length correction base (~391mm) +static const uint16_t eepromBowdenLenDefault = 8900u; ///< Default bowden length (~427 mm) +static const uint16_t eepromBowdenLenMinimum = 6900u; ///< Minimum bowden length (~341 mm) +static const uint16_t eepromBowdenLenMaximum = 16000u; ///< Maximum bowden length (~792 mm) - void Init() { - if (hal::EEPROM::ReadByte((const uint8_t *)hal::EEPROM::End()) != layoutVersion) { - EraseAll(); - } +void Init() { + if (hal::eeprom::ReadByte((const uint8_t *)hal::eeprom::End()) != layoutVersion) { + EraseAll(); } +} - /// @brief Erase the whole EEPROM - void EraseAll() { - for (uint16_t i = 0; i < hal::EEPROM::End(); i++) { - hal::EEPROM::UpdateByte((uint8_t *)i, static_cast(eepromEmpty)); - } - hal::EEPROM::UpdateByte((const uint8_t *)hal::EEPROM::End(), layoutVersion); +/// @brief Erase the whole EEPROM +void EraseAll() { + for (uint16_t i = 0; i < hal::eeprom::End(); i++) { + hal::eeprom::UpdateByte((uint8_t *)i, static_cast(eepromEmpty)); } + hal::eeprom::UpdateByte((const uint8_t *)hal::eeprom::End(), layoutVersion); +} - /// @brief Is filament number valid? - /// @retval true valid - /// @retval false invalid - static bool validFilament(uint8_t filament) { - return filament < ARR_SIZE(eeprom_t::eepromBowdenLen); - } +/// @brief Is filament number valid? +/// @retval true valid +/// @retval false invalid +static bool validFilament(uint8_t filament) { + return filament < ARR_SIZE(eeprom_t::eepromBowdenLen); +} - /// @brief Is bowden length in valid range? - /// @param BowdenLength bowden length - /// @retval true valid - /// @retval false invalid - static bool validBowdenLen(const uint16_t BowdenLength) { - if ((BowdenLength >= eepromBowdenLenMinimum) - && BowdenLength <= eepromBowdenLenMaximum) { - return true; - } - return false; - } - - /// @brief Get bowden length for active filament - /// - /// Returns stored value, doesn't return actual value when it is edited by increase() / decrease() unless it is stored. - /// @return stored bowden length - uint16_t BowdenLength::get() { - uint8_t filament = 0 /*active_extruder*/; //@@TODO - if (validFilament(filament)) { - uint16_t bowdenLength = hal::EEPROM::ReadByte((const uint8_t *)&(eepromBase->eepromBowdenLen[filament])); - - if (eepromEmpty == bowdenLength) { - const uint8_t LengthCorrectionLegacy = hal::EEPROM::ReadByte(&(eepromBase->eepromLengthCorrection)); - if (LengthCorrectionLegacy <= 200) { - bowdenLength = eepromLengthCorrectionBase + LengthCorrectionLegacy * 10; - } - } - if (validBowdenLen(bowdenLength)) - return bowdenLength; - } - - return eepromBowdenLenDefault; - } - - /// @brief Construct BowdenLength object which allows bowden length manipulation - /// - /// To be created on stack, new value is permanently stored when object goes out of scope. - /// Active filament and associated bowden length is stored in member variables. - BowdenLength::BowdenLength() - : filament(/*active_extruder*/ 0) - , length(BowdenLength::get()) // @@TODO - { - } - - /// @brief Increase bowden length - /// - /// New value is not stored immediately. See ~BowdenLength() for storing permanently. - /// @retval true passed - /// @retval false failed, it is not possible to increase, new bowden length would be out of range - bool BowdenLength::increase() { - if (validBowdenLen(length + stepSize)) { - length += stepSize; - return true; - } - return false; - } - - /// @brief Decrease bowden length - /// - /// New value is not stored immediately. See ~BowdenLength() for storing permanently. - /// @retval true passed - /// @retval false failed, it is not possible to decrease, new bowden length would be out of range - bool BowdenLength::decrease() { - if (validBowdenLen(length - stepSize)) { - length -= stepSize; - return true; - } - return false; - } - - /// @brief Store bowden length permanently. - BowdenLength::~BowdenLength() { - if (validFilament(filament)) - hal::EEPROM::UpdateWord((const uint8_t *)&(eepromBase->eepromBowdenLen[filament]), length); - } - - /// @brief Get filament storage status - /// - /// Uses 2 out of 3 majority vote. - /// - /// @return status - /// @retval 0xff Uninitialized EEPROM or no 2 values agrees - - uint8_t FilamentLoaded::getStatus() { - if (hal::EEPROM::ReadByte(&(eepromBase->eepromFilamentStatus[0])) == hal::EEPROM::ReadByte(&(eepromBase->eepromFilamentStatus[1]))) - return hal::EEPROM::ReadByte(&(eepromBase->eepromFilamentStatus[0])); - if (hal::EEPROM::ReadByte(&(eepromBase->eepromFilamentStatus[0])) == hal::EEPROM::ReadByte(&(eepromBase->eepromFilamentStatus[2]))) - return hal::EEPROM::ReadByte(&(eepromBase->eepromFilamentStatus[0])); - if (hal::EEPROM::ReadByte(&(eepromBase->eepromFilamentStatus[1])) == hal::EEPROM::ReadByte(&(eepromBase->eepromFilamentStatus[2]))) - return hal::EEPROM::ReadByte(&(eepromBase->eepromFilamentStatus[1])); - return 0xff; - } - - /// @brief Set filament storage status - /// - /// @retval true Succeed - /// @retval false Failed - bool FilamentLoaded::setStatus(uint8_t status) { - for (uint8_t i = 0; i < ARR_SIZE(eeprom_t::eepromFilamentStatus); ++i) { - hal::EEPROM::UpdateByte(&(eepromBase->eepromFilamentStatus[i]), status); - } - if (getStatus() == status) - return true; - return false; - } - - /// @brief Get index of last valid filament - /// - /// Depending on status, it searches from the beginning or from the end of eepromFilament[] - /// for the first non-matching status. Previous index (of matching status, or out of array bounds) - /// is returned. - /// - /// @return index to eepromFilament[] of last valid value - /// it can be out of array range, if first item status doesn't match expected status - /// getNext(index, status) turns it to first valid index. - int16_t FilamentLoaded::getIndex() { - const uint8_t status = getStatus(); - int16_t index = -1; - switch (status) { - case KeyFront1: - case KeyFront2: - index = ARR_SIZE(eeprom_t::eepromFilament) - 1; // It is the last one, if no dirty index found - for (uint16_t i = 0; i < ARR_SIZE(eeprom_t::eepromFilament); ++i) { - if (status != (hal::EEPROM::ReadByte(&(eepromBase->eepromFilament[i])) >> 4)) { - index = i - 1; - break; - } - } - break; - case KeyReverse1: - case KeyReverse2: - index = 0; // It is the last one, if no dirty index found - for (int16_t i = (ARR_SIZE(eeprom_t::eepromFilament) - 1); i >= 0; --i) { - if (status != (hal::EEPROM::ReadByte(&(eepromBase->eepromFilament[i])) >> 4)) { - index = i + 1; - break; - } - } - break; - default: - break; - } - return index; - } - - /// @brief Get last filament loaded - /// @param [in,out] filament filament number 0 to 4 - /// @retval true success - /// @retval false failed - bool FilamentLoaded::get(uint8_t &filament) { - int16_t index = getIndex(); - if ((index < 0) || (static_cast(index) >= ARR_SIZE(eeprom_t::eepromFilament))) - return false; - const uint8_t rawFilament = hal::EEPROM::ReadByte(&(eepromBase->eepromFilament[index])); - filament = 0x0f & rawFilament; - if (filament > 4) - return false; - const uint8_t status = getStatus(); - if (!(status == KeyFront1 - || status == KeyReverse1 - || status == KeyFront2 - || status == KeyReverse2)) - return false; - if ((rawFilament >> 4) != status) - return false; +/// @brief Is bowden length in valid range? +/// @param BowdenLength bowden length +/// @retval true valid +/// @retval false invalid +static bool validBowdenLen(const uint16_t BowdenLength) { + if ((BowdenLength >= eepromBowdenLenMinimum) + && BowdenLength <= eepromBowdenLenMaximum) { return true; } + return false; +} - /// @brief Set filament being loaded - /// - /// Always fails, if it is not possible to store status. - /// If it is not possible store filament, it tries all other - /// keys. Fails if storing with all other keys failed. - /// - /// @param filament bottom 4 bits are stored - /// but only value 0 to 4 passes validation in FilamentLoaded::get() - /// @retval true success - /// @retval false failed - bool FilamentLoaded::set(uint8_t filament) { - for (uint8_t i = 0; i < BehindLastKey - 1; ++i) { - uint8_t status = getStatus(); - int16_t index = getIndex(); - getNext(status, index); - if (!setStatus(status)) - return false; - uint8_t filamentRaw = ((status << 4) & 0xf0) + (filament & 0x0f); - hal::EEPROM::UpdateByte(&(eepromBase->eepromFilament[index]), filamentRaw); - if (filamentRaw == hal::EEPROM::ReadByte(&(eepromBase->eepromFilament[index]))) - return true; - getNext(status); - if (!setStatus(status)) - return false; +/// @brief Get bowden length for active filament +/// +/// Returns stored value, doesn't return actual value when it is edited by increase() / decrease() unless it is stored. +/// @return stored bowden length +uint16_t BowdenLength::get() { + uint8_t filament = 0 /*active_extruder*/; //@@TODO + if (validFilament(filament)) { + uint16_t bowdenLength = hal::eeprom::ReadByte((const uint8_t *)&(eepromBase->eepromBowdenLen[filament])); + + if (eepromEmpty == bowdenLength) { + const uint8_t LengthCorrectionLegacy = hal::eeprom::ReadByte(&(eepromBase->eepromLengthCorrection)); + if (LengthCorrectionLegacy <= 200) { + bowdenLength = eepromLengthCorrectionBase + LengthCorrectionLegacy * 10; + } } + if (validBowdenLen(bowdenLength)) + return bowdenLength; + } + + return eepromBowdenLenDefault; +} + +/// @brief Construct BowdenLength object which allows bowden length manipulation +/// +/// To be created on stack, new value is permanently stored when object goes out of scope. +/// Active filament and associated bowden length is stored in member variables. +BowdenLength::BowdenLength() + : filament(/*active_extruder*/ 0) + , length(BowdenLength::get()) // @@TODO +{ +} + +/// @brief Increase bowden length +/// +/// New value is not stored immediately. See ~BowdenLength() for storing permanently. +/// @retval true passed +/// @retval false failed, it is not possible to increase, new bowden length would be out of range +bool BowdenLength::increase() { + if (validBowdenLen(length + stepSize)) { + length += stepSize; + return true; + } + return false; +} + +/// @brief Decrease bowden length +/// +/// New value is not stored immediately. See ~BowdenLength() for storing permanently. +/// @retval true passed +/// @retval false failed, it is not possible to decrease, new bowden length would be out of range +bool BowdenLength::decrease() { + if (validBowdenLen(length - stepSize)) { + length -= stepSize; + return true; + } + return false; +} + +/// @brief Store bowden length permanently. +BowdenLength::~BowdenLength() { + if (validFilament(filament)) + hal::eeprom::UpdateWord((const uint8_t *)&(eepromBase->eepromBowdenLen[filament]), length); +} + +/// @brief Get filament storage status +/// +/// Uses 2 out of 3 majority vote. +/// +/// @return status +/// @retval 0xff Uninitialized EEPROM or no 2 values agrees + +uint8_t FilamentLoaded::getStatus() { + if (hal::eeprom::ReadByte(&(eepromBase->eepromFilamentStatus[0])) == hal::eeprom::ReadByte(&(eepromBase->eepromFilamentStatus[1]))) + return hal::eeprom::ReadByte(&(eepromBase->eepromFilamentStatus[0])); + if (hal::eeprom::ReadByte(&(eepromBase->eepromFilamentStatus[0])) == hal::eeprom::ReadByte(&(eepromBase->eepromFilamentStatus[2]))) + return hal::eeprom::ReadByte(&(eepromBase->eepromFilamentStatus[0])); + if (hal::eeprom::ReadByte(&(eepromBase->eepromFilamentStatus[1])) == hal::eeprom::ReadByte(&(eepromBase->eepromFilamentStatus[2]))) + return hal::eeprom::ReadByte(&(eepromBase->eepromFilamentStatus[1])); + return 0xff; +} + +/// @brief Set filament storage status +/// +/// @retval true Succeed +/// @retval false Failed +bool FilamentLoaded::setStatus(uint8_t status) { + for (uint8_t i = 0; i < ARR_SIZE(eeprom_t::eepromFilamentStatus); ++i) { + hal::eeprom::UpdateByte(&(eepromBase->eepromFilamentStatus[i]), status); + } + if (getStatus() == status) + return true; + return false; +} + +/// @brief Get index of last valid filament +/// +/// Depending on status, it searches from the beginning or from the end of eepromFilament[] +/// for the first non-matching status. Previous index (of matching status, or out of array bounds) +/// is returned. +/// +/// @return index to eepromFilament[] of last valid value +/// it can be out of array range, if first item status doesn't match expected status +/// getNext(index, status) turns it to first valid index. +int16_t FilamentLoaded::getIndex() { + const uint8_t status = getStatus(); + int16_t index = -1; + switch (status) { + case KeyFront1: + case KeyFront2: + index = ARR_SIZE(eeprom_t::eepromFilament) - 1; // It is the last one, if no dirty index found + for (uint16_t i = 0; i < ARR_SIZE(eeprom_t::eepromFilament); ++i) { + if (status != (hal::eeprom::ReadByte(&(eepromBase->eepromFilament[i])) >> 4)) { + index = i - 1; + break; + } + } + break; + case KeyReverse1: + case KeyReverse2: + index = 0; // It is the last one, if no dirty index found + for (int16_t i = (ARR_SIZE(eeprom_t::eepromFilament) - 1); i >= 0; --i) { + if (status != (hal::eeprom::ReadByte(&(eepromBase->eepromFilament[i])) >> 4)) { + index = i + 1; + break; + } + } + break; + default: + break; + } + return index; +} + +/// @brief Get last filament loaded +/// @param [in,out] filament filament number 0 to 4 +/// @retval true success +/// @retval false failed +bool FilamentLoaded::get(uint8_t &filament) { + int16_t index = getIndex(); + if ((index < 0) || (static_cast(index) >= ARR_SIZE(eeprom_t::eepromFilament))) return false; - } + const uint8_t rawFilament = hal::eeprom::ReadByte(&(eepromBase->eepromFilament[index])); + filament = 0x0f & rawFilament; + if (filament > 4) + return false; + const uint8_t status = getStatus(); + if (!(status == KeyFront1 + || status == KeyReverse1 + || status == KeyFront2 + || status == KeyReverse2)) + return false; + if ((rawFilament >> 4) != status) + return false; + return true; +} - /// @brief Get next status and index - /// - /// Get next available index following index input parameter to store filament in eepromFilament[]. - /// If index would reach behind indexable space, status is updated to next and first index matching status indexing mode is returned. - /// @param [in,out] status - /// @param [in,out] index - void FilamentLoaded::getNext(uint8_t &status, int16_t &index) { - switch (status) { - case KeyFront1: - case KeyFront2: - ++index; - if ((index < 0) || (static_cast(index) >= ARR_SIZE(eeprom_t::eepromFilament))) { - getNext(status); - index = ARR_SIZE(eeprom_t::eepromFilament) - 1; - } - break; - case KeyReverse1: - case KeyReverse2: - --index; - if ((index < 0) || (static_cast(index) >= ARR_SIZE(eeprom_t::eepromFilament))) { - getNext(status); - index = 0; - } - break; - default: - status = KeyFront1; +/// @brief Set filament being loaded +/// +/// Always fails, if it is not possible to store status. +/// If it is not possible store filament, it tries all other +/// keys. Fails if storing with all other keys failed. +/// +/// @param filament bottom 4 bits are stored +/// but only value 0 to 4 passes validation in FilamentLoaded::get() +/// @retval true success +/// @retval false failed +bool FilamentLoaded::set(uint8_t filament) { + for (uint8_t i = 0; i < BehindLastKey - 1; ++i) { + uint8_t status = getStatus(); + int16_t index = getIndex(); + getNext(status, index); + if (!setStatus(status)) + return false; + uint8_t filamentRaw = ((status << 4) & 0xf0) + (filament & 0x0f); + hal::eeprom::UpdateByte(&(eepromBase->eepromFilament[index]), filamentRaw); + if (filamentRaw == hal::eeprom::ReadByte(&(eepromBase->eepromFilament[index]))) + return true; + getNext(status); + if (!setStatus(status)) + return false; + } + return false; +} + +/// @brief Get next status and index +/// +/// Get next available index following index input parameter to store filament in eepromFilament[]. +/// If index would reach behind indexable space, status is updated to next and first index matching status indexing mode is returned. +/// @param [in,out] status +/// @param [in,out] index +void FilamentLoaded::getNext(uint8_t &status, int16_t &index) { + switch (status) { + case KeyFront1: + case KeyFront2: + ++index; + if ((index < 0) || (static_cast(index) >= ARR_SIZE(eeprom_t::eepromFilament))) { + getNext(status); + index = ARR_SIZE(eeprom_t::eepromFilament) - 1; + } + break; + case KeyReverse1: + case KeyReverse2: + --index; + if ((index < 0) || (static_cast(index) >= ARR_SIZE(eeprom_t::eepromFilament))) { + getNext(status); index = 0; - break; } + break; + default: + status = KeyFront1; + index = 0; + break; } +} - /// @brief Get next status - /// - /// Sets status to next indexing mode. - /// - /// @param [in,out] status - void FilamentLoaded::getNext(uint8_t &status) { - switch (status) { - case KeyFront1: - status = KeyReverse1; - break; - case KeyReverse1: - status = KeyFront2; - break; - case KeyFront2: - status = KeyReverse2; - break; - case KeyReverse2: - status = KeyFront1; - break; - default: - status = KeyFront1; - break; - } +/// @brief Get next status +/// +/// Sets status to next indexing mode. +/// +/// @param [in,out] status +void FilamentLoaded::getNext(uint8_t &status) { + switch (status) { + case KeyFront1: + status = KeyReverse1; + break; + case KeyReverse1: + status = KeyFront2; + break; + case KeyFront2: + status = KeyReverse2; + break; + case KeyReverse2: + status = KeyFront1; + break; + default: + status = KeyFront1; + break; } +} - uint16_t DriveError::get() { - return ((static_cast(getH()) << 8) + getL()); +uint16_t DriveError::get() { + return ((static_cast(getH()) << 8) + getL()); +} + +void DriveError::increment() { + uint16_t errors = get(); + if (errors < 0xffff) { + ++errors; + setL(errors); + setH(errors >> 8); } +} - void DriveError::increment() { - uint16_t errors = get(); - if (errors < 0xffff) { - ++errors; - setL(errors); - setH(errors >> 8); - } - } +uint8_t DriveError::getL() { + uint8_t first = hal::eeprom::ReadByte(&(eepromBase->eepromDriveErrorCountL[0])); + uint8_t second = hal::eeprom::ReadByte(&(eepromBase->eepromDriveErrorCountL[1])); - uint8_t DriveError::getL() { - uint8_t first = hal::EEPROM::ReadByte(&(eepromBase->eepromDriveErrorCountL[0])); - uint8_t second = hal::EEPROM::ReadByte(&(eepromBase->eepromDriveErrorCountL[1])); + if (0xff == first && 0 == second) + return 1; + return (first > second) ? ++first : ++second; +} - if (0xff == first && 0 == second) - return 1; - return (first > second) ? ++first : ++second; - } +void DriveError::setL(uint8_t lowByte) { + hal::eeprom::UpdateByte(&(eepromBase->eepromDriveErrorCountL[lowByte % 2]), lowByte - 1); +} - void DriveError::setL(uint8_t lowByte) { - hal::EEPROM::UpdateByte(&(eepromBase->eepromDriveErrorCountL[lowByte % 2]), lowByte - 1); - } +uint8_t DriveError::getH() { + return (hal::eeprom::ReadByte(&(eepromBase->eepromDriveErrorCountH)) + 1); +} - uint8_t DriveError::getH() { - return (hal::EEPROM::ReadByte(&(eepromBase->eepromDriveErrorCountH)) + 1); - } - - void DriveError::setH(uint8_t highByte) { - hal::EEPROM::UpdateByte(&(eepromBase->eepromDriveErrorCountH), highByte - 1); - } +void DriveError::setH(uint8_t highByte) { + hal::eeprom::UpdateByte(&(eepromBase->eepromDriveErrorCountH), highByte - 1); +} } // namespace permanent_storage } // namespace modules