Add empty EEPROM HAL implementation
parent
dfb57bcae5
commit
9e4bd97968
|
|
@ -188,6 +188,7 @@ target_sources(
|
||||||
src/hal/avr/cpu.cpp
|
src/hal/avr/cpu.cpp
|
||||||
src/hal/avr/usart.cpp
|
src/hal/avr/usart.cpp
|
||||||
src/hal/avr/shr16.cpp
|
src/hal/avr/shr16.cpp
|
||||||
|
src/hal/avr/eeprom.cpp
|
||||||
src/hal/adc.cpp
|
src/hal/adc.cpp
|
||||||
src/modules/protocol.cpp
|
src/modules/protocol.cpp
|
||||||
src/modules/buttons.cpp
|
src/modules/buttons.cpp
|
||||||
|
|
@ -197,6 +198,7 @@ target_sources(
|
||||||
src/modules/idler.cpp
|
src/modules/idler.cpp
|
||||||
src/modules/leds.cpp
|
src/modules/leds.cpp
|
||||||
src/modules/motion.cpp
|
src/modules/motion.cpp
|
||||||
|
src/modules/permanent_storage.cpp
|
||||||
src/modules/selector.cpp
|
src/modules/selector.cpp
|
||||||
src/logic/command_base.cpp
|
src/logic/command_base.cpp
|
||||||
src/logic/cut_filament.cpp
|
src/logic/cut_filament.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
|
||||||
|
|
@ -2,19 +2,19 @@
|
||||||
#include <stdint.h>
|
#include <stdint.h>
|
||||||
|
|
||||||
namespace hal {
|
namespace hal {
|
||||||
namespace EEPROM {
|
namespace eeprom {
|
||||||
|
|
||||||
/// EEPROM interface
|
/// EEPROM interface
|
||||||
void WriteByte(const uint8_t *addr, uint8_t value);
|
extern void WriteByte(const uint8_t *addr, uint8_t value);
|
||||||
void UpdateByte(const uint8_t *addr, uint8_t value);
|
extern void UpdateByte(const uint8_t *addr, uint8_t value);
|
||||||
uint8_t ReadByte(const uint8_t *addr);
|
extern uint8_t ReadByte(const uint8_t *addr);
|
||||||
|
|
||||||
void WriteWord(const uint8_t *addr, uint16_t value);
|
extern void WriteWord(const uint8_t *addr, uint16_t value);
|
||||||
void UpdateWord(const uint8_t *addr, uint16_t value);
|
extern void UpdateWord(const uint8_t *addr, uint16_t value);
|
||||||
uint16_t ReadWord(const uint8_t *addr);
|
extern uint16_t ReadWord(const uint8_t *addr);
|
||||||
|
|
||||||
/// @returns physical end address of EEPROM memory end
|
/// @returns physical end address of EEPROM memory end
|
||||||
constexpr const uint16_t End();
|
extern constexpr const uint16_t End();
|
||||||
|
|
||||||
} // namespace EEPROM
|
} // namespace EEPROM
|
||||||
} // namespace hal
|
} // namespace hal
|
||||||
|
|
|
||||||
|
|
@ -7,348 +7,348 @@ namespace permanent_storage {
|
||||||
|
|
||||||
#define ARR_SIZE(ARRAY) (sizeof(ARRAY) / sizeof(ARRAY[0]))
|
#define ARR_SIZE(ARRAY) (sizeof(ARRAY) / sizeof(ARRAY[0]))
|
||||||
|
|
||||||
/// @brief EEPROM data layout
|
/// @brief EEPROM data layout
|
||||||
///
|
///
|
||||||
/// Do not remove, reorder or change size of existing fields.
|
/// Do not remove, reorder or change size of existing fields.
|
||||||
/// Otherwise values stored with previous version of firmware would be broken.
|
/// 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.
|
/// 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
|
/// Last byte in EEPROM is reserved for layoutVersion. If some field is repurposed, layoutVersion
|
||||||
/// needs to be changed to force an EEPROM erase.
|
/// needs to be changed to force an EEPROM erase.
|
||||||
struct eeprom_t {
|
struct eeprom_t {
|
||||||
uint8_t eepromLengthCorrection; ///< Legacy bowden length correction
|
uint8_t eepromLengthCorrection; ///< Legacy bowden length correction
|
||||||
uint16_t eepromBowdenLen[5]; ///< Bowden length for each filament
|
uint16_t eepromBowdenLen[5]; ///< Bowden length for each filament
|
||||||
uint8_t eepromFilamentStatus[3]; ///< Majority vote status of eepromFilament wear leveling
|
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 eepromFilament[800]; ///< Top nibble status, bottom nibble last filament loaded
|
||||||
uint8_t eepromDriveErrorCountH;
|
uint8_t eepromDriveErrorCountH;
|
||||||
uint8_t eepromDriveErrorCountL[2];
|
uint8_t eepromDriveErrorCountL[2];
|
||||||
} __attribute__((packed));
|
} __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
|
/// @brief EEPROM layout version
|
||||||
static const uint8_t layoutVersion = 0xff;
|
static const uint8_t layoutVersion = 0xff;
|
||||||
|
|
||||||
//d = 6.3 mm pulley diameter
|
//d = 6.3 mm pulley diameter
|
||||||
//c = pi * d pulley circumference
|
//c = pi * d pulley circumference
|
||||||
//FSPR = 200 full steps per revolution (stepper motor constant) (1.8 deg/step)
|
//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 pulley microstep resolution (uint8_t __res(AX_PUL))
|
||||||
//mres = 2 selector microstep resolution (uint8_t __res(AX_SEL))
|
//mres = 2 selector microstep resolution (uint8_t __res(AX_SEL))
|
||||||
//mres = 16 idler microstep resolution (uint8_t __res(AX_IDL))
|
//mres = 16 idler microstep resolution (uint8_t __res(AX_IDL))
|
||||||
//1 pulley ustep = (d*pi)/(mres*FSPR) = 49.48 um
|
//1 pulley ustep = (d*pi)/(mres*FSPR) = 49.48 um
|
||||||
|
|
||||||
static eeprom_t *const eepromBase = reinterpret_cast<eeprom_t *>(0); ///< First EEPROM address
|
static eeprom_t *const eepromBase = reinterpret_cast<eeprom_t *>(0); ///< First EEPROM address
|
||||||
static const uint16_t eepromEmpty = 0xffff; ///< EEPROM content when erased
|
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 eepromLengthCorrectionBase = 7900u; ///< legacy bowden length correction base (~391mm)
|
||||||
static const uint16_t eepromBowdenLenDefault = 8900u; ///< Default bowden length (~427 mm)
|
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 eepromBowdenLenMinimum = 6900u; ///< Minimum bowden length (~341 mm)
|
||||||
static const uint16_t eepromBowdenLenMaximum = 16000u; ///< Maximum bowden length (~792 mm)
|
static const uint16_t eepromBowdenLenMaximum = 16000u; ///< Maximum bowden length (~792 mm)
|
||||||
|
|
||||||
void Init() {
|
void Init() {
|
||||||
if (hal::EEPROM::ReadByte((const uint8_t *)hal::EEPROM::End()) != layoutVersion) {
|
if (hal::eeprom::ReadByte((const uint8_t *)hal::eeprom::End()) != layoutVersion) {
|
||||||
EraseAll();
|
EraseAll();
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
|
||||||
/// @brief Erase the whole EEPROM
|
/// @brief Erase the whole EEPROM
|
||||||
void EraseAll() {
|
void EraseAll() {
|
||||||
for (uint16_t i = 0; i < hal::EEPROM::End(); i++) {
|
for (uint16_t i = 0; i < hal::eeprom::End(); i++) {
|
||||||
hal::EEPROM::UpdateByte((uint8_t *)i, static_cast<uint8_t>(eepromEmpty));
|
hal::eeprom::UpdateByte((uint8_t *)i, static_cast<uint8_t>(eepromEmpty));
|
||||||
}
|
|
||||||
hal::EEPROM::UpdateByte((const uint8_t *)hal::EEPROM::End(), layoutVersion);
|
|
||||||
}
|
}
|
||||||
|
hal::eeprom::UpdateByte((const uint8_t *)hal::eeprom::End(), layoutVersion);
|
||||||
|
}
|
||||||
|
|
||||||
/// @brief Is filament number valid?
|
/// @brief Is filament number valid?
|
||||||
/// @retval true valid
|
/// @retval true valid
|
||||||
/// @retval false invalid
|
/// @retval false invalid
|
||||||
static bool validFilament(uint8_t filament) {
|
static bool validFilament(uint8_t filament) {
|
||||||
return filament < ARR_SIZE(eeprom_t::eepromBowdenLen);
|
return filament < ARR_SIZE(eeprom_t::eepromBowdenLen);
|
||||||
}
|
}
|
||||||
|
|
||||||
/// @brief Is bowden length in valid range?
|
/// @brief Is bowden length in valid range?
|
||||||
/// @param BowdenLength bowden length
|
/// @param BowdenLength bowden length
|
||||||
/// @retval true valid
|
/// @retval true valid
|
||||||
/// @retval false invalid
|
/// @retval false invalid
|
||||||
static bool validBowdenLen(const uint16_t BowdenLength) {
|
static bool validBowdenLen(const uint16_t BowdenLength) {
|
||||||
if ((BowdenLength >= eepromBowdenLenMinimum)
|
if ((BowdenLength >= eepromBowdenLenMinimum)
|
||||||
&& BowdenLength <= eepromBowdenLenMaximum) {
|
&& 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<uint16_t>(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;
|
return true;
|
||||||
}
|
}
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
/// @brief Set filament being loaded
|
/// @brief Get bowden length for active filament
|
||||||
///
|
///
|
||||||
/// Always fails, if it is not possible to store status.
|
/// Returns stored value, doesn't return actual value when it is edited by increase() / decrease() unless it is stored.
|
||||||
/// If it is not possible store filament, it tries all other
|
/// @return stored bowden length
|
||||||
/// keys. Fails if storing with all other keys failed.
|
uint16_t BowdenLength::get() {
|
||||||
///
|
uint8_t filament = 0 /*active_extruder*/; //@@TODO
|
||||||
/// @param filament bottom 4 bits are stored
|
if (validFilament(filament)) {
|
||||||
/// but only value 0 to 4 passes validation in FilamentLoaded::get()
|
uint16_t bowdenLength = hal::eeprom::ReadByte((const uint8_t *)&(eepromBase->eepromBowdenLen[filament]));
|
||||||
/// @retval true success
|
|
||||||
/// @retval false failed
|
if (eepromEmpty == bowdenLength) {
|
||||||
bool FilamentLoaded::set(uint8_t filament) {
|
const uint8_t LengthCorrectionLegacy = hal::eeprom::ReadByte(&(eepromBase->eepromLengthCorrection));
|
||||||
for (uint8_t i = 0; i < BehindLastKey - 1; ++i) {
|
if (LengthCorrectionLegacy <= 200) {
|
||||||
uint8_t status = getStatus();
|
bowdenLength = eepromLengthCorrectionBase + LengthCorrectionLegacy * 10;
|
||||||
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;
|
|
||||||
}
|
}
|
||||||
|
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<uint16_t>(index) >= ARR_SIZE(eeprom_t::eepromFilament)))
|
||||||
return false;
|
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
|
/// @brief Set filament being loaded
|
||||||
///
|
///
|
||||||
/// Get next available index following index input parameter to store filament in eepromFilament[].
|
/// Always fails, if it is not possible to store status.
|
||||||
/// If index would reach behind indexable space, status is updated to next and first index matching status indexing mode is returned.
|
/// If it is not possible store filament, it tries all other
|
||||||
/// @param [in,out] status
|
/// keys. Fails if storing with all other keys failed.
|
||||||
/// @param [in,out] index
|
///
|
||||||
void FilamentLoaded::getNext(uint8_t &status, int16_t &index) {
|
/// @param filament bottom 4 bits are stored
|
||||||
switch (status) {
|
/// but only value 0 to 4 passes validation in FilamentLoaded::get()
|
||||||
case KeyFront1:
|
/// @retval true success
|
||||||
case KeyFront2:
|
/// @retval false failed
|
||||||
++index;
|
bool FilamentLoaded::set(uint8_t filament) {
|
||||||
if ((index < 0) || (static_cast<uint16_t>(index) >= ARR_SIZE(eeprom_t::eepromFilament))) {
|
for (uint8_t i = 0; i < BehindLastKey - 1; ++i) {
|
||||||
getNext(status);
|
uint8_t status = getStatus();
|
||||||
index = ARR_SIZE(eeprom_t::eepromFilament) - 1;
|
int16_t index = getIndex();
|
||||||
}
|
getNext(status, index);
|
||||||
break;
|
if (!setStatus(status))
|
||||||
case KeyReverse1:
|
return false;
|
||||||
case KeyReverse2:
|
uint8_t filamentRaw = ((status << 4) & 0xf0) + (filament & 0x0f);
|
||||||
--index;
|
hal::eeprom::UpdateByte(&(eepromBase->eepromFilament[index]), filamentRaw);
|
||||||
if ((index < 0) || (static_cast<uint16_t>(index) >= ARR_SIZE(eeprom_t::eepromFilament))) {
|
if (filamentRaw == hal::eeprom::ReadByte(&(eepromBase->eepromFilament[index])))
|
||||||
getNext(status);
|
return true;
|
||||||
index = 0;
|
getNext(status);
|
||||||
}
|
if (!setStatus(status))
|
||||||
break;
|
return false;
|
||||||
default:
|
}
|
||||||
status = KeyFront1;
|
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<uint16_t>(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<uint16_t>(index) >= ARR_SIZE(eeprom_t::eepromFilament))) {
|
||||||
|
getNext(status);
|
||||||
index = 0;
|
index = 0;
|
||||||
break;
|
|
||||||
}
|
}
|
||||||
|
break;
|
||||||
|
default:
|
||||||
|
status = KeyFront1;
|
||||||
|
index = 0;
|
||||||
|
break;
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
|
||||||
/// @brief Get next status
|
/// @brief Get next status
|
||||||
///
|
///
|
||||||
/// Sets status to next indexing mode.
|
/// Sets status to next indexing mode.
|
||||||
///
|
///
|
||||||
/// @param [in,out] status
|
/// @param [in,out] status
|
||||||
void FilamentLoaded::getNext(uint8_t &status) {
|
void FilamentLoaded::getNext(uint8_t &status) {
|
||||||
switch (status) {
|
switch (status) {
|
||||||
case KeyFront1:
|
case KeyFront1:
|
||||||
status = KeyReverse1;
|
status = KeyReverse1;
|
||||||
break;
|
break;
|
||||||
case KeyReverse1:
|
case KeyReverse1:
|
||||||
status = KeyFront2;
|
status = KeyFront2;
|
||||||
break;
|
break;
|
||||||
case KeyFront2:
|
case KeyFront2:
|
||||||
status = KeyReverse2;
|
status = KeyReverse2;
|
||||||
break;
|
break;
|
||||||
case KeyReverse2:
|
case KeyReverse2:
|
||||||
status = KeyFront1;
|
status = KeyFront1;
|
||||||
break;
|
break;
|
||||||
default:
|
default:
|
||||||
status = KeyFront1;
|
status = KeyFront1;
|
||||||
break;
|
break;
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
|
||||||
uint16_t DriveError::get() {
|
uint16_t DriveError::get() {
|
||||||
return ((static_cast<uint16_t>(getH()) << 8) + getL());
|
return ((static_cast<uint16_t>(getH()) << 8) + getL());
|
||||||
|
}
|
||||||
|
|
||||||
|
void DriveError::increment() {
|
||||||
|
uint16_t errors = get();
|
||||||
|
if (errors < 0xffff) {
|
||||||
|
++errors;
|
||||||
|
setL(errors);
|
||||||
|
setH(errors >> 8);
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
|
||||||
void DriveError::increment() {
|
uint8_t DriveError::getL() {
|
||||||
uint16_t errors = get();
|
uint8_t first = hal::eeprom::ReadByte(&(eepromBase->eepromDriveErrorCountL[0]));
|
||||||
if (errors < 0xffff) {
|
uint8_t second = hal::eeprom::ReadByte(&(eepromBase->eepromDriveErrorCountL[1]));
|
||||||
++errors;
|
|
||||||
setL(errors);
|
|
||||||
setH(errors >> 8);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
uint8_t DriveError::getL() {
|
if (0xff == first && 0 == second)
|
||||||
uint8_t first = hal::EEPROM::ReadByte(&(eepromBase->eepromDriveErrorCountL[0]));
|
return 1;
|
||||||
uint8_t second = hal::EEPROM::ReadByte(&(eepromBase->eepromDriveErrorCountL[1]));
|
return (first > second) ? ++first : ++second;
|
||||||
|
}
|
||||||
|
|
||||||
if (0xff == first && 0 == second)
|
void DriveError::setL(uint8_t lowByte) {
|
||||||
return 1;
|
hal::eeprom::UpdateByte(&(eepromBase->eepromDriveErrorCountL[lowByte % 2]), lowByte - 1);
|
||||||
return (first > second) ? ++first : ++second;
|
}
|
||||||
}
|
|
||||||
|
|
||||||
void DriveError::setL(uint8_t lowByte) {
|
uint8_t DriveError::getH() {
|
||||||
hal::EEPROM::UpdateByte(&(eepromBase->eepromDriveErrorCountL[lowByte % 2]), lowByte - 1);
|
return (hal::eeprom::ReadByte(&(eepromBase->eepromDriveErrorCountH)) + 1);
|
||||||
}
|
}
|
||||||
|
|
||||||
uint8_t DriveError::getH() {
|
void DriveError::setH(uint8_t highByte) {
|
||||||
return (hal::EEPROM::ReadByte(&(eepromBase->eepromDriveErrorCountH)) + 1);
|
hal::eeprom::UpdateByte(&(eepromBase->eepromDriveErrorCountH), highByte - 1);
|
||||||
}
|
}
|
||||||
|
|
||||||
void DriveError::setH(uint8_t highByte) {
|
|
||||||
hal::EEPROM::UpdateByte(&(eepromBase->eepromDriveErrorCountH), highByte - 1);
|
|
||||||
}
|
|
||||||
|
|
||||||
} // namespace permanent_storage
|
} // namespace permanent_storage
|
||||||
} // namespace modules
|
} // namespace modules
|
||||||
|
|
|
||||||
Loading…
Reference in New Issue