Introduce Doxyfile + fix modules documentation
parent
f6e5d4ae76
commit
c15b1d59c4
|
|
@ -7,7 +7,7 @@
|
||||||
///
|
///
|
||||||
/// Which state machines are high-level? Those which are being initiated either by a command over the serial line or from a button
|
/// Which state machines are high-level? Those which are being initiated either by a command over the serial line or from a button
|
||||||
/// - they report their progress to the printer
|
/// - they report their progress to the printer
|
||||||
/// - they can be composed of other sub automatons
|
/// - they can be composed of other sub automata
|
||||||
|
|
||||||
namespace logic {
|
namespace logic {
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -3,12 +3,12 @@
|
||||||
#include <stdint.h>
|
#include <stdint.h>
|
||||||
#include "debouncer.h"
|
#include "debouncer.h"
|
||||||
|
|
||||||
/// Buttons are built on top of the raw ADC API
|
|
||||||
/// This layer should contain debouncing of buttons and their logical interpretation
|
|
||||||
|
|
||||||
namespace modules {
|
namespace modules {
|
||||||
|
|
||||||
|
/// The buttons namespace provides all necessary facilities related to the logical model of the physical buttons device the MMU unit.
|
||||||
namespace buttons {
|
namespace buttons {
|
||||||
|
|
||||||
|
/// A model of a single button, performs automatic debouncing on top of the raw ADC API
|
||||||
struct Button : public debounce::Debouncer {
|
struct Button : public debounce::Debouncer {
|
||||||
inline constexpr Button()
|
inline constexpr Button()
|
||||||
: debounce::Debouncer(debounce) {}
|
: debounce::Debouncer(debounce) {}
|
||||||
|
|
@ -18,12 +18,14 @@ private:
|
||||||
constexpr static const uint16_t debounce = 100;
|
constexpr static const uint16_t debounce = 100;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
/// Enum of buttons - used also as indices in an array of buttons to keep the code size tight.
|
||||||
enum {
|
enum {
|
||||||
Left = 0,
|
Left = 0,
|
||||||
Middle,
|
Middle,
|
||||||
Right
|
Right
|
||||||
};
|
};
|
||||||
|
|
||||||
|
/// A model of the 3 buttons on the MMU unit
|
||||||
class Buttons {
|
class Buttons {
|
||||||
constexpr static const uint8_t N = 3; ///< number of buttons currently supported
|
constexpr static const uint8_t N = 3; ///< number of buttons currently supported
|
||||||
constexpr static const uint8_t adc = 1; ///< ADC index - will be some define or other constant later on
|
constexpr static const uint8_t adc = 1; ///< ADC index - will be some define or other constant later on
|
||||||
|
|
@ -31,11 +33,11 @@ class Buttons {
|
||||||
public:
|
public:
|
||||||
inline constexpr Buttons() = default;
|
inline constexpr Buttons() = default;
|
||||||
|
|
||||||
/// State machine step - reads the ADC, processes debouncing, updates states of individual buttons
|
/// Performs one step of the state machine - reads the ADC, processes debouncing, updates states of individual buttons
|
||||||
void Step();
|
void Step();
|
||||||
|
|
||||||
/// @returns true if button at index is pressed
|
/// @returns true if button at index is pressed
|
||||||
/// @@TODO add range checking if necessary
|
/// @param index of the button to check
|
||||||
inline bool ButtonPressed(uint8_t index) const { return buttons[index].Pressed(); }
|
inline bool ButtonPressed(uint8_t index) const { return buttons[index].Pressed(); }
|
||||||
|
|
||||||
/// @returns true if any of the button is pressed
|
/// @returns true if any of the button is pressed
|
||||||
|
|
@ -55,6 +57,7 @@ private:
|
||||||
static int8_t DecodeADC(uint16_t rawADC);
|
static int8_t DecodeADC(uint16_t rawADC);
|
||||||
};
|
};
|
||||||
|
|
||||||
|
/// The one and only instance of Buttons in the FW
|
||||||
extern Buttons buttons;
|
extern Buttons buttons;
|
||||||
|
|
||||||
} // namespace buttons
|
} // namespace buttons
|
||||||
|
|
|
||||||
|
|
@ -1,15 +1,17 @@
|
||||||
/// A generic debouncing algorithm
|
|
||||||
|
|
||||||
#pragma once
|
#pragma once
|
||||||
#include <stdint.h>
|
#include <stdint.h>
|
||||||
|
|
||||||
namespace modules {
|
namespace modules {
|
||||||
|
|
||||||
|
/// The debounce namespace provides a generic debouncing algorithm.
|
||||||
namespace debounce {
|
namespace debounce {
|
||||||
|
|
||||||
/// Implements debouncing on 2-state logic variables (true/false, high/low, on/off, pressed/unpressed)
|
/// Implements debouncing on 2-state logic variables (true/false, high/low, on/off, pressed/unpressed)
|
||||||
/// Intentionally not modelled as a template to avoid code bloat
|
/// Intentionally not modelled as a template to avoid code bloat
|
||||||
class Debouncer {
|
class Debouncer {
|
||||||
public:
|
public:
|
||||||
|
/// @param debounceTimeout initial debounce timeout in milliseconds @@TODO
|
||||||
|
/// - after what time of having a pressed level the debouncer considers the level stable enough to report the Pressed state.
|
||||||
inline constexpr Debouncer(uint8_t debounceTimeout)
|
inline constexpr Debouncer(uint8_t debounceTimeout)
|
||||||
: timeLastChange(0)
|
: timeLastChange(0)
|
||||||
, debounceTimeout(debounceTimeout) {}
|
, debounceTimeout(debounceTimeout) {}
|
||||||
|
|
|
||||||
|
|
@ -3,8 +3,11 @@
|
||||||
#include "debouncer.h"
|
#include "debouncer.h"
|
||||||
|
|
||||||
namespace modules {
|
namespace modules {
|
||||||
|
|
||||||
|
/// The finda namespace provides all necessary facilities related to the logical model of the FINDA device the MMU unit.
|
||||||
namespace finda {
|
namespace finda {
|
||||||
|
|
||||||
|
/// A model of the FINDA - basically acts as a button with pre-set debouncing
|
||||||
class FINDA : protected debounce::Debouncer {
|
class FINDA : protected debounce::Debouncer {
|
||||||
public:
|
public:
|
||||||
/// time interval for debouncing @@TODO specify units
|
/// time interval for debouncing @@TODO specify units
|
||||||
|
|
@ -14,10 +17,14 @@ public:
|
||||||
|
|
||||||
inline constexpr FINDA()
|
inline constexpr FINDA()
|
||||||
: debounce::Debouncer(debounce) {};
|
: debounce::Debouncer(debounce) {};
|
||||||
|
|
||||||
|
/// Performs one step of the state machine - reads the ADC, processes debouncing, updates states of FINDA
|
||||||
void Step();
|
void Step();
|
||||||
|
|
||||||
using debounce::Debouncer::Pressed;
|
using debounce::Debouncer::Pressed;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
/// The one and only instance of FINDA in the FW
|
||||||
extern FINDA finda;
|
extern FINDA finda;
|
||||||
|
|
||||||
} // namespace finda
|
} // namespace finda
|
||||||
|
|
|
||||||
|
|
@ -2,21 +2,25 @@
|
||||||
#include <stdint.h>
|
#include <stdint.h>
|
||||||
#include "debouncer.h"
|
#include "debouncer.h"
|
||||||
|
|
||||||
/// External module - model of printer's fsensor
|
|
||||||
|
|
||||||
namespace modules {
|
namespace modules {
|
||||||
|
|
||||||
|
/// The fsensor namespace provides all necessary facilities related to the logical model of the printer's filamens sensor device.
|
||||||
namespace fsensor {
|
namespace fsensor {
|
||||||
|
|
||||||
/// the debouncer is probably not necessary, but it has all the necessary functionality for modelling of the fsensor
|
/// External module - model of printer's filament sensor
|
||||||
|
/// The debouncer is probably not necessary, but it has all the necessary functionality for modelling of the filament sensor
|
||||||
class FSensor : protected debounce::Debouncer {
|
class FSensor : protected debounce::Debouncer {
|
||||||
public:
|
public:
|
||||||
inline constexpr FSensor()
|
inline constexpr FSensor()
|
||||||
: debounce::Debouncer(debounce)
|
: debounce::Debouncer(debounce)
|
||||||
, reportedFSensorState(false) {};
|
, reportedFSensorState(false) {};
|
||||||
|
|
||||||
|
/// Performs one step of the state machine - processes a change-of-state message if any arrived
|
||||||
void Step();
|
void Step();
|
||||||
|
|
||||||
using debounce::Debouncer::Pressed;
|
using debounce::Debouncer::Pressed;
|
||||||
|
|
||||||
|
/// Records a change of state of filament sensor when arrived via communication
|
||||||
void ProcessMessage(bool on);
|
void ProcessMessage(bool on);
|
||||||
|
|
||||||
private:
|
private:
|
||||||
|
|
@ -25,7 +29,8 @@ private:
|
||||||
bool reportedFSensorState; ///< reported state that came from the printer via a communication message
|
bool reportedFSensorState; ///< reported state that came from the printer via a communication message
|
||||||
};
|
};
|
||||||
|
|
||||||
|
/// The one and only instance of printer's filament sensor in the FW
|
||||||
extern FSensor fsensor;
|
extern FSensor fsensor;
|
||||||
|
|
||||||
} // namespace finda
|
} // namespace fsensor
|
||||||
} // namespace modules
|
} // namespace modules
|
||||||
|
|
|
||||||
|
|
@ -2,16 +2,35 @@
|
||||||
#include <stdint.h>
|
#include <stdint.h>
|
||||||
|
|
||||||
namespace modules {
|
namespace modules {
|
||||||
|
|
||||||
|
/// The globals namespace provides all necessary facilities related to keeping track of global state of the firmware.
|
||||||
namespace globals {
|
namespace globals {
|
||||||
|
|
||||||
|
/// Globals keep track of global state variables in the firmware.
|
||||||
|
/// So far only Active slot and Filament loaded variables are used.
|
||||||
class Globals {
|
class Globals {
|
||||||
public:
|
public:
|
||||||
|
/// Initializes the global storage hive - basically looks into EEPROM to gather information.
|
||||||
void Init();
|
void Init();
|
||||||
|
|
||||||
|
/// @returns active filament slot on the MMU unit
|
||||||
|
/// Slots are numbered 0-4
|
||||||
uint8_t ActiveSlot() const;
|
uint8_t ActiveSlot() const;
|
||||||
|
|
||||||
|
/// Sets the active slot, usually after some command/operation.
|
||||||
|
/// Also updates the EEPROM records accordingly
|
||||||
|
/// @param newActiveSlot the new slot index to set
|
||||||
void SetActiveSlot(uint8_t newActiveSlot);
|
void SetActiveSlot(uint8_t newActiveSlot);
|
||||||
|
|
||||||
|
/// @returns true if filament is considered as loaded
|
||||||
|
/// @@TODO this may change meaning slightly as the MMU is primarily concerned
|
||||||
|
/// about whether a piece of filament is stock up of a PTFE tube.
|
||||||
|
/// If that's true, we cannot move the selector.
|
||||||
bool FilamentLoaded() const;
|
bool FilamentLoaded() const;
|
||||||
|
|
||||||
|
/// Sets the filament loaded flag value, usually after some command/operation.
|
||||||
|
/// Also updates the EEPROM records accordingly
|
||||||
|
/// @param newFilamentLoaded new state
|
||||||
void SetFilamentLoaded(bool newFilamentLoaded);
|
void SetFilamentLoaded(bool newFilamentLoaded);
|
||||||
|
|
||||||
private:
|
private:
|
||||||
|
|
@ -19,6 +38,7 @@ private:
|
||||||
bool filamentLoaded;
|
bool filamentLoaded;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
/// The one and only instance of global state variables
|
||||||
extern Globals globals;
|
extern Globals globals;
|
||||||
|
|
||||||
} // namespace globals
|
} // namespace globals
|
||||||
|
|
|
||||||
|
|
@ -1,15 +1,15 @@
|
||||||
#pragma once
|
#pragma once
|
||||||
#include <stdint.h>
|
#include <stdint.h>
|
||||||
|
|
||||||
/// Idler model
|
|
||||||
/// Handles asynchronnous Engaging / Disengaging operations
|
|
||||||
/// Keeps track of idler's current state
|
|
||||||
|
|
||||||
namespace modules {
|
namespace modules {
|
||||||
|
|
||||||
|
/// The idler namespace provides all necessary facilities related to the logical model of the idler device of the MMU unit.
|
||||||
namespace idler {
|
namespace idler {
|
||||||
|
|
||||||
|
/// The Idler model handles asynchronnous Engaging / Disengaging operations and keeps track of idler's current state.
|
||||||
class Idler {
|
class Idler {
|
||||||
public:
|
public:
|
||||||
|
/// Internal states of idler's state machine
|
||||||
enum {
|
enum {
|
||||||
Ready = 0, // intentionally set as zero in order to allow zeroing the Idler structure upon startup -> avoid explicit initialization code
|
Ready = 0, // intentionally set as zero in order to allow zeroing the Idler structure upon startup -> avoid explicit initialization code
|
||||||
Moving,
|
Moving,
|
||||||
|
|
@ -23,15 +23,20 @@ public:
|
||||||
, currentSlot(0)
|
, currentSlot(0)
|
||||||
, currentlyEngaged(false) {}
|
, currentlyEngaged(false) {}
|
||||||
|
|
||||||
// public operations on the idler
|
/// Plan engaging of the idler to a specific filament slot
|
||||||
|
/// @param slot index to be activated
|
||||||
/// @retuns false in case an operation is already underway
|
/// @returns false in case an operation is already underway
|
||||||
bool Engage(uint8_t slot);
|
bool Engage(uint8_t slot);
|
||||||
/// @retuns false in case an operation is already underway
|
|
||||||
|
/// Plan disengaging of the idler, i.e. parking the idler
|
||||||
|
/// @returns false in case an operation is already underway
|
||||||
bool Disengage();
|
bool Disengage();
|
||||||
/// @retuns false in case an operation is already underway
|
|
||||||
|
/// Plan homing of the idler axis
|
||||||
|
/// @returns false in case an operation is already underway
|
||||||
bool Home();
|
bool Home();
|
||||||
|
|
||||||
|
/// Performs one step of the state machine according to currently planned operation
|
||||||
/// @returns true if the idler is ready to accept new commands (i.e. it has finished the last operation)
|
/// @returns true if the idler is ready to accept new commands (i.e. it has finished the last operation)
|
||||||
bool Step();
|
bool Step();
|
||||||
|
|
||||||
|
|
@ -62,6 +67,7 @@ private:
|
||||||
bool currentlyEngaged;
|
bool currentlyEngaged;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
/// The one and only instance of Idler in the FW
|
||||||
extern Idler idler;
|
extern Idler idler;
|
||||||
|
|
||||||
} // namespace idler
|
} // namespace idler
|
||||||
|
|
|
||||||
|
|
@ -2,18 +2,22 @@
|
||||||
|
|
||||||
#include <stdint.h>
|
#include <stdint.h>
|
||||||
|
|
||||||
/// We have 5 pairs of LEDs
|
namespace modules {
|
||||||
/// In each pair there is a green and a red LED
|
|
||||||
|
/// @brief The leds namespace provides all necessary facilities related to the logical model of the sets of LEDs on the MMU unit.
|
||||||
|
///
|
||||||
|
/// We have 5 pairs of LEDs. In each pair there is a green and a red LED.
|
||||||
///
|
///
|
||||||
/// A typical scenario in the past was visualization of error states.
|
/// A typical scenario in the past was visualization of error states.
|
||||||
/// The combination of colors with blinking frequency had a specific meaning.
|
/// The combination of colors with blinking frequency had a specific meaning.
|
||||||
///
|
///
|
||||||
/// The physical connection is not important on this level (i.e. how and what shall be sent into the shift registers)
|
/// The physical connection is not important on this level (i.e. how and what shall be sent into the shift registers).
|
||||||
|
///
|
||||||
namespace modules {
|
/// LEDS are physically connected to a pair of shift registers along with some other signals.
|
||||||
|
/// The physical write operations are handled by hal::shr16.
|
||||||
namespace leds {
|
namespace leds {
|
||||||
|
|
||||||
/// Mode of LED
|
/// Enum of LED modes
|
||||||
/// blink0 and blink1 allow for interlaced blinking of LEDs (one is on and the other off)
|
/// blink0 and blink1 allow for interlaced blinking of LEDs (one is on and the other off)
|
||||||
enum Mode {
|
enum Mode {
|
||||||
off,
|
off,
|
||||||
|
|
@ -22,20 +26,29 @@ enum Mode {
|
||||||
blink1 ///< start blinking at odd periods
|
blink1 ///< start blinking at odd periods
|
||||||
};
|
};
|
||||||
|
|
||||||
|
/// Enum of LEDs color - green or red
|
||||||
enum Color {
|
enum Color {
|
||||||
green = 0,
|
green = 0,
|
||||||
red = 1
|
red = 1
|
||||||
};
|
};
|
||||||
|
|
||||||
/// a single LED
|
/// A single LED
|
||||||
class LED {
|
class LED {
|
||||||
public:
|
public:
|
||||||
constexpr inline LED() = default;
|
constexpr inline LED() = default;
|
||||||
|
|
||||||
|
/// Sets the mode of the LED
|
||||||
|
/// @param mode to set
|
||||||
void SetMode(leds::Mode mode);
|
void SetMode(leds::Mode mode);
|
||||||
|
|
||||||
|
/// @returns the currently active mode of the LED
|
||||||
inline leds::Mode Mode() const { return (leds::Mode)state.mode; }
|
inline leds::Mode Mode() const { return (leds::Mode)state.mode; }
|
||||||
|
|
||||||
/// @returns true if the LED shines
|
/// @returns true if the LED shines
|
||||||
|
/// @param oddPeriod LEDs class operates this parameter based on blinking period based on elapsed real time
|
||||||
bool Step(bool oddPeriod);
|
bool Step(bool oddPeriod);
|
||||||
|
|
||||||
|
/// @returns true if the LED shines
|
||||||
inline bool On() const { return state.on; }
|
inline bool On() const { return state.on; }
|
||||||
|
|
||||||
private:
|
private:
|
||||||
|
|
@ -50,7 +63,7 @@ private:
|
||||||
State state;
|
State state;
|
||||||
};
|
};
|
||||||
|
|
||||||
/// main LED API
|
/// The main LEDs API takes care of the whole set of LEDs
|
||||||
class LEDs {
|
class LEDs {
|
||||||
public:
|
public:
|
||||||
constexpr inline LEDs() = default;
|
constexpr inline LEDs() = default;
|
||||||
|
|
@ -58,25 +71,46 @@ public:
|
||||||
/// step LED automaton
|
/// step LED automaton
|
||||||
void Step();
|
void Step();
|
||||||
|
|
||||||
|
/// @returns the number of LED pairs
|
||||||
inline constexpr uint8_t LedPairsCount() const { return ledPairs; }
|
inline constexpr uint8_t LedPairsCount() const { return ledPairs; }
|
||||||
|
|
||||||
|
/// Sets the mode of a LED in a pair
|
||||||
|
/// @param slot index of filament slot (index of the LED pair)
|
||||||
|
/// @param color green or red LED
|
||||||
|
/// @param mode to set
|
||||||
inline void SetMode(uint8_t slot, Color color, Mode mode) {
|
inline void SetMode(uint8_t slot, Color color, Mode mode) {
|
||||||
SetMode(slot * 2 + color, mode);
|
SetMode(slot * 2 + color, mode);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// Sets the mode of a LED in a pair
|
||||||
|
/// @param index - raw index of the LED in the internal leds array
|
||||||
|
/// @param mode to set
|
||||||
inline void SetMode(uint8_t index, Mode mode) {
|
inline void SetMode(uint8_t index, Mode mode) {
|
||||||
leds[index].SetMode(mode);
|
leds[index].SetMode(mode);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// @returns the currently active mode of a LED in a pair
|
||||||
|
/// @param slot index of filament slot (index of the LED pair)
|
||||||
|
/// @param color green or red LED
|
||||||
inline leds::Mode Mode(uint8_t slot, Color color) {
|
inline leds::Mode Mode(uint8_t slot, Color color) {
|
||||||
return Mode(slot * 2 + color);
|
return Mode(slot * 2 + color);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// @returns the currently active mode of a LED
|
||||||
|
/// @param index - raw index of the LED in the internal leds array
|
||||||
inline leds::Mode Mode(uint8_t index) {
|
inline leds::Mode Mode(uint8_t index) {
|
||||||
return leds[index].Mode();
|
return leds[index].Mode();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// @returns true if a LED is shining
|
||||||
|
/// @param index - raw index of the LED in the internal leds array
|
||||||
inline bool LedOn(uint8_t index) const {
|
inline bool LedOn(uint8_t index) const {
|
||||||
return leds[index].On();
|
return leds[index].On();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// @returns true if a LED is shining
|
||||||
|
/// @param slot index of filament slot (index of the LED pair)
|
||||||
|
/// @param color green or red LED
|
||||||
inline bool LedOn(uint8_t slot, Color color) const {
|
inline bool LedOn(uint8_t slot, Color color) const {
|
||||||
return leds[slot * 2 + color].On();
|
return leds[slot * 2 + color].On();
|
||||||
}
|
}
|
||||||
|
|
@ -97,6 +131,7 @@ private:
|
||||||
LED leds[ledPairs * 2];
|
LED leds[ledPairs * 2];
|
||||||
};
|
};
|
||||||
|
|
||||||
|
/// The one and only instance of FINDA in the FW
|
||||||
extern LEDs leds;
|
extern LEDs leds;
|
||||||
|
|
||||||
} // namespace LEDs
|
} // namespace LEDs
|
||||||
|
|
|
||||||
|
|
@ -1,4 +1,3 @@
|
||||||
/// @author Marek Bel
|
|
||||||
#include "permanent_storage.h"
|
#include "permanent_storage.h"
|
||||||
#include "../hal/eeprom.h"
|
#include "../hal/eeprom.h"
|
||||||
#include "globals.h"
|
#include "globals.h"
|
||||||
|
|
@ -57,7 +56,6 @@ void Init() {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/// @brief Erase the whole EEPROM
|
|
||||||
void EraseAll() {
|
void EraseAll() {
|
||||||
for (uint16_t i = 0; i < ee::EEPROM::End(); i++) {
|
for (uint16_t i = 0; i < ee::EEPROM::End(); i++) {
|
||||||
ee::EEPROM::UpdateByte(i, static_cast<uint8_t>(eepromEmpty));
|
ee::EEPROM::UpdateByte(i, static_cast<uint8_t>(eepromEmpty));
|
||||||
|
|
|
||||||
|
|
@ -1,98 +1,101 @@
|
||||||
/// Permanent storage implementation
|
|
||||||
/// This is the logic/wear levelling/data structure on top of the raw EEPROM API
|
|
||||||
/// @author Marek Bel
|
|
||||||
/// Extracted and refactored from MM-control-01
|
|
||||||
#pragma once
|
#pragma once
|
||||||
|
|
||||||
#include "../hal/eeprom.h"
|
#include "../hal/eeprom.h"
|
||||||
|
|
||||||
namespace modules {
|
namespace modules {
|
||||||
|
|
||||||
|
/// @brief The permanent_storage namespace provides all necessary facilities related to permanently storing data (into EEPROM) on the MMU unit.
|
||||||
|
///
|
||||||
|
/// It uses some clever logic/wear levelling/data structure on top of the raw EEPROM API.
|
||||||
|
/// The code was originally written by Marek Bel for the previous MMU firmware.
|
||||||
namespace permanent_storage {
|
namespace permanent_storage {
|
||||||
|
|
||||||
void Init();
|
/// Initialization of the permanent storage hive
|
||||||
void EraseAll();
|
void Init();
|
||||||
|
|
||||||
/// @brief Read manipulate and store bowden length
|
/// Erase the whole EEPROM
|
||||||
///
|
void EraseAll();
|
||||||
/// Value is stored independently for each filament.
|
|
||||||
/// Active filament is deduced from active_extruder global variable.
|
|
||||||
class BowdenLength {
|
|
||||||
public:
|
|
||||||
static uint16_t get();
|
|
||||||
static const uint8_t stepSize = 10u; ///< increase()/decrease() bowden length step size
|
|
||||||
BowdenLength();
|
|
||||||
bool increase();
|
|
||||||
bool decrease();
|
|
||||||
~BowdenLength();
|
|
||||||
|
|
||||||
private:
|
/// @brief Read manipulate and store bowden length
|
||||||
uint8_t filament; ///< Selected filament
|
///
|
||||||
uint16_t length; ///< Selected filament bowden length
|
/// Value is stored independently for each filament.
|
||||||
|
/// Active filament is deduced from active_extruder global variable.
|
||||||
|
class BowdenLength {
|
||||||
|
public:
|
||||||
|
static uint16_t get();
|
||||||
|
static const uint8_t stepSize = 10u; ///< increase()/decrease() bowden length step size
|
||||||
|
BowdenLength();
|
||||||
|
bool increase();
|
||||||
|
bool decrease();
|
||||||
|
~BowdenLength();
|
||||||
|
|
||||||
|
private:
|
||||||
|
uint8_t filament; ///< Selected filament
|
||||||
|
uint16_t length; ///< Selected filament bowden length
|
||||||
|
};
|
||||||
|
|
||||||
|
/// @brief Read and store last filament loaded to nozzle
|
||||||
|
///
|
||||||
|
/// 800(data) + 3(status) EEPROM cells are used to store 4 bit value frequently
|
||||||
|
/// to spread wear between more cells to increase durability.
|
||||||
|
///
|
||||||
|
/// Expected worst case durability scenario:
|
||||||
|
/// @n Print has 240mm height, layer height is 0.1mm, print takes 10 hours,
|
||||||
|
/// filament is changed 5 times each layer, EEPROM endures 100 000 cycles
|
||||||
|
/// @n Cell written per print: 240/0.1*5/800 = 15
|
||||||
|
/// @n Cell written per hour : 15/10 = 1.5
|
||||||
|
/// @n Fist cell failure expected: 100 000 / 1.5 = 66 666 hours = 7.6 years
|
||||||
|
///
|
||||||
|
/// Algorithm can handle one cell failure in status and one cell in data.
|
||||||
|
/// Status use 2 of 3 majority vote.
|
||||||
|
/// If bad data cell is detected, status is switched to next key.
|
||||||
|
/// Key alternates between begin to end and end to begin write order.
|
||||||
|
/// Two keys are needed for each start point and direction.
|
||||||
|
/// If two data cells fails, area between them is unavailable to write.
|
||||||
|
/// If this is first and last cell, whole storage is disabled.
|
||||||
|
/// This vulnerability can be avoided by adding additional keys
|
||||||
|
/// and start point in the middle of the EEPROM.
|
||||||
|
///
|
||||||
|
/// It would be possible to implement twice as efficient algorithm, if
|
||||||
|
/// separate EEPROM erase and EEPROM write commands would be available and
|
||||||
|
/// if write command would allow to be invoked twice between erases to update
|
||||||
|
/// just one nibble. Such commands are not available in AVR Libc, and possibility
|
||||||
|
/// to use write command twice is not documented in atmega32U4 datasheet.
|
||||||
|
///
|
||||||
|
class FilamentLoaded {
|
||||||
|
public:
|
||||||
|
static bool get(uint8_t &filament);
|
||||||
|
static bool set(uint8_t filament);
|
||||||
|
|
||||||
|
private:
|
||||||
|
enum Key {
|
||||||
|
KeyFront1,
|
||||||
|
KeyReverse1,
|
||||||
|
KeyFront2,
|
||||||
|
KeyReverse2,
|
||||||
|
BehindLastKey,
|
||||||
};
|
};
|
||||||
|
static_assert(BehindLastKey - 1 <= 0xf, "Key doesn't fit into a nibble.");
|
||||||
|
static uint8_t getStatus();
|
||||||
|
static bool setStatus(uint8_t status);
|
||||||
|
static int16_t getIndex();
|
||||||
|
static void getNext(uint8_t &status, int16_t &index);
|
||||||
|
static void getNext(uint8_t &status);
|
||||||
|
};
|
||||||
|
|
||||||
/// @brief Read and store last filament loaded to nozzle
|
/// @brief Read and increment drive errors
|
||||||
///
|
///
|
||||||
/// 800(data) + 3(status) EEPROM cells are used to store 4 bit value frequently
|
/// (Motor power rail voltage loss)
|
||||||
/// to spread wear between more cells to increase durability.
|
class DriveError {
|
||||||
///
|
public:
|
||||||
/// Expected worst case durability scenario:
|
static uint16_t get();
|
||||||
/// @n Print has 240mm height, layer height is 0.1mm, print takes 10 hours,
|
static void increment();
|
||||||
/// filament is changed 5 times each layer, EEPROM endures 100 000 cycles
|
|
||||||
/// @n Cell written per print: 240/0.1*5/800 = 15
|
|
||||||
/// @n Cell written per hour : 15/10 = 1.5
|
|
||||||
/// @n Fist cell failure expected: 100 000 / 1.5 = 66 666 hours = 7.6 years
|
|
||||||
///
|
|
||||||
/// Algorithm can handle one cell failure in status and one cell in data.
|
|
||||||
/// Status use 2 of 3 majority vote.
|
|
||||||
/// If bad data cell is detected, status is switched to next key.
|
|
||||||
/// Key alternates between begin to end and end to begin write order.
|
|
||||||
/// Two keys are needed for each start point and direction.
|
|
||||||
/// If two data cells fails, area between them is unavailable to write.
|
|
||||||
/// If this is first and last cell, whole storage is disabled.
|
|
||||||
/// This vulnerability can be avoided by adding additional keys
|
|
||||||
/// and start point in the middle of the EEPROM.
|
|
||||||
///
|
|
||||||
/// It would be possible to implement twice as efficient algorithm, if
|
|
||||||
/// separate EEPROM erase and EEPROM write commands would be available and
|
|
||||||
/// if write command would allow to be invoked twice between erases to update
|
|
||||||
/// just one nibble. Such commands are not available in AVR Libc, and possibility
|
|
||||||
/// to use write command twice is not documented in atmega32U4 datasheet.
|
|
||||||
///
|
|
||||||
class FilamentLoaded {
|
|
||||||
public:
|
|
||||||
static bool get(uint8_t &filament);
|
|
||||||
static bool set(uint8_t filament);
|
|
||||||
|
|
||||||
private:
|
private:
|
||||||
enum Key {
|
static uint8_t getL();
|
||||||
KeyFront1,
|
static void setL(uint8_t lowByte);
|
||||||
KeyReverse1,
|
static uint8_t getH();
|
||||||
KeyFront2,
|
static void setH(uint8_t highByte);
|
||||||
KeyReverse2,
|
};
|
||||||
BehindLastKey,
|
|
||||||
};
|
|
||||||
static_assert(BehindLastKey - 1 <= 0xf, "Key doesn't fit into a nibble.");
|
|
||||||
static uint8_t getStatus();
|
|
||||||
static bool setStatus(uint8_t status);
|
|
||||||
static int16_t getIndex();
|
|
||||||
static void getNext(uint8_t &status, int16_t &index);
|
|
||||||
static void getNext(uint8_t &status);
|
|
||||||
};
|
|
||||||
|
|
||||||
/// @brief Read and increment drive errors
|
|
||||||
///
|
|
||||||
/// (Motor power rail voltage loss)
|
|
||||||
class DriveError {
|
|
||||||
public:
|
|
||||||
static uint16_t get();
|
|
||||||
static void increment();
|
|
||||||
|
|
||||||
private:
|
|
||||||
static uint8_t getL();
|
|
||||||
static void setL(uint8_t lowByte);
|
|
||||||
static uint8_t getH();
|
|
||||||
static void setH(uint8_t highByte);
|
|
||||||
};
|
|
||||||
|
|
||||||
} // namespace permanent_storage
|
} // namespace permanent_storage
|
||||||
} // namespace modules
|
} // namespace modules
|
||||||
|
|
|
||||||
|
|
@ -1,14 +1,15 @@
|
||||||
#pragma once
|
#pragma once
|
||||||
|
|
||||||
#include <stdint.h>
|
#include <stdint.h>
|
||||||
|
|
||||||
/// MMU protocol implementation
|
namespace modules {
|
||||||
|
|
||||||
|
/// @brief The MMU communication protocol implementation and related stuff.
|
||||||
|
///
|
||||||
/// See description of the new protocol in the MMU 2021 doc
|
/// See description of the new protocol in the MMU 2021 doc
|
||||||
/// @@TODO possibly add some checksum to verify the correctness of messages
|
/// @@TODO possibly add some checksum to verify the correctness of messages
|
||||||
|
|
||||||
namespace modules {
|
|
||||||
namespace protocol {
|
namespace protocol {
|
||||||
|
|
||||||
|
/// Definition of request message codes
|
||||||
enum class RequestMsgCodes : uint8_t {
|
enum class RequestMsgCodes : uint8_t {
|
||||||
unknown = 0,
|
unknown = 0,
|
||||||
Query = 'Q',
|
Query = 'Q',
|
||||||
|
|
@ -25,6 +26,7 @@ enum class RequestMsgCodes : uint8_t {
|
||||||
Cut = 'K'
|
Cut = 'K'
|
||||||
};
|
};
|
||||||
|
|
||||||
|
/// Definition of response message parameter codes
|
||||||
enum class ResponseMsgParamCodes : uint8_t {
|
enum class ResponseMsgParamCodes : uint8_t {
|
||||||
unknown = 0,
|
unknown = 0,
|
||||||
Processing = 'P',
|
Processing = 'P',
|
||||||
|
|
@ -34,30 +36,34 @@ enum class ResponseMsgParamCodes : uint8_t {
|
||||||
Rejected = 'R'
|
Rejected = 'R'
|
||||||
};
|
};
|
||||||
|
|
||||||
/// A request message
|
/// A request message - requests are being sent by the printer into the MMU.
|
||||||
/// Requests are being sent by the printer into the MMU
|
|
||||||
/// It is the same structure as the generic Msg
|
|
||||||
struct RequestMsg {
|
struct RequestMsg {
|
||||||
RequestMsgCodes code;
|
RequestMsgCodes code; ///< code of the request message
|
||||||
uint8_t value;
|
uint8_t value; ///< value of the request message
|
||||||
|
|
||||||
|
/// @param code of the request message
|
||||||
|
/// @param value of the request message
|
||||||
inline RequestMsg(RequestMsgCodes code, uint8_t value)
|
inline RequestMsg(RequestMsgCodes code, uint8_t value)
|
||||||
: code(code)
|
: code(code)
|
||||||
, value(value) {}
|
, value(value) {}
|
||||||
};
|
};
|
||||||
|
|
||||||
/// A response message
|
/// A response message - responses are being sent from the MMU into the printer as a response to a request message.
|
||||||
/// Responses are being sent from the MMU into the printer as a response to a request message
|
|
||||||
struct ResponseMsg {
|
struct ResponseMsg {
|
||||||
RequestMsg request; ///< response is always preceeded by the request message
|
RequestMsg request; ///< response is always preceeded by the request message
|
||||||
ResponseMsgParamCodes paramCode; ///< parameters of reply
|
ResponseMsgParamCodes paramCode; ///< code of the parameter
|
||||||
uint8_t paramValue; ///< parameters of reply
|
uint8_t paramValue; ///< value of the parameter
|
||||||
|
|
||||||
|
/// @param request the source request message this response is a reply to
|
||||||
|
/// @param paramCode code of the parameter
|
||||||
|
/// @param paramValue value of the parameter
|
||||||
inline ResponseMsg(RequestMsg request, ResponseMsgParamCodes paramCode, uint8_t paramValue)
|
inline ResponseMsg(RequestMsg request, ResponseMsgParamCodes paramCode, uint8_t paramValue)
|
||||||
: request(request)
|
: request(request)
|
||||||
, paramCode(paramCode)
|
, paramCode(paramCode)
|
||||||
, paramValue(paramValue) {}
|
, paramValue(paramValue) {}
|
||||||
};
|
};
|
||||||
|
|
||||||
/// Message decoding return value
|
/// Message decoding return values
|
||||||
enum class DecodeStatus : uint_fast8_t {
|
enum class DecodeStatus : uint_fast8_t {
|
||||||
MessageCompleted, ///< message completed and successfully lexed
|
MessageCompleted, ///< message completed and successfully lexed
|
||||||
NeedMoreData, ///< message incomplete yet, waiting for another byte to come
|
NeedMoreData, ///< message incomplete yet, waiting for another byte to come
|
||||||
|
|
@ -65,8 +71,9 @@ enum class DecodeStatus : uint_fast8_t {
|
||||||
};
|
};
|
||||||
|
|
||||||
/// Protocol class is responsible for creating/decoding messages in Rx/Tx buffer
|
/// Protocol class is responsible for creating/decoding messages in Rx/Tx buffer
|
||||||
|
///
|
||||||
/// Beware - in the decoding more, it is meant to be a statefull instance which works through public methods
|
/// Beware - in the decoding more, it is meant to be a statefull instance which works through public methods
|
||||||
/// processing one input byte per call
|
/// processing one input byte per call.
|
||||||
class Protocol {
|
class Protocol {
|
||||||
public:
|
public:
|
||||||
inline Protocol()
|
inline Protocol()
|
||||||
|
|
@ -91,18 +98,22 @@ public:
|
||||||
|
|
||||||
/// Encode generic response Command Accepted or Rejected
|
/// Encode generic response Command Accepted or Rejected
|
||||||
/// @param msg source request message for this response
|
/// @param msg source request message for this response
|
||||||
|
/// @param ar code of response parameter
|
||||||
|
/// @param txbuff where to format the message
|
||||||
/// @returns number of bytes written into txbuff
|
/// @returns number of bytes written into txbuff
|
||||||
static uint8_t EncodeResponseCmdAR(const RequestMsg &msg, ResponseMsgParamCodes ar, uint8_t *txbuff);
|
static uint8_t EncodeResponseCmdAR(const RequestMsg &msg, ResponseMsgParamCodes ar, uint8_t *txbuff);
|
||||||
|
|
||||||
/// Encode response to Read FINDA query
|
/// Encode response to Read FINDA query
|
||||||
/// @param msg source request message for this response
|
/// @param msg source request message for this response
|
||||||
/// @param findaValue 1/0 (on/off) status of FINDA
|
/// @param findaValue 1/0 (on/off) status of FINDA
|
||||||
|
/// @param txbuff where to format the message
|
||||||
/// @returns number of bytes written into txbuff
|
/// @returns number of bytes written into txbuff
|
||||||
static uint8_t EncodeResponseReadFINDA(const RequestMsg &msg, uint8_t findaValue, uint8_t *txbuff);
|
static uint8_t EncodeResponseReadFINDA(const RequestMsg &msg, uint8_t findaValue, uint8_t *txbuff);
|
||||||
|
|
||||||
/// Encode response to Version query
|
/// Encode response to Version query
|
||||||
/// @param msg source request message for this response
|
/// @param msg source request message for this response
|
||||||
/// @param value version number (0-255)
|
/// @param value version number (0-255)
|
||||||
|
/// @param txbuff where to format the message
|
||||||
/// @returns number of bytes written into txbuff
|
/// @returns number of bytes written into txbuff
|
||||||
static uint8_t EncodeResponseVersion(const RequestMsg &msg, uint8_t value, uint8_t *txbuff);
|
static uint8_t EncodeResponseVersion(const RequestMsg &msg, uint8_t value, uint8_t *txbuff);
|
||||||
|
|
||||||
|
|
@ -110,6 +121,7 @@ public:
|
||||||
/// @param msg source request message for this response
|
/// @param msg source request message for this response
|
||||||
/// @param code status of operation (Processing, Error, Finished)
|
/// @param code status of operation (Processing, Error, Finished)
|
||||||
/// @param value related to status of operation(e.g. error code or progress)
|
/// @param value related to status of operation(e.g. error code or progress)
|
||||||
|
/// @param txbuff where to format the message
|
||||||
/// @returns number of bytes written into txbuff
|
/// @returns number of bytes written into txbuff
|
||||||
static uint8_t EncodeResponseQueryOperation(const RequestMsg &msg, ResponseMsgParamCodes code, uint8_t value, uint8_t *txbuff);
|
static uint8_t EncodeResponseQueryOperation(const RequestMsg &msg, ResponseMsgParamCodes code, uint8_t value, uint8_t *txbuff);
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -1,15 +1,15 @@
|
||||||
#pragma once
|
#pragma once
|
||||||
#include <stdint.h>
|
#include <stdint.h>
|
||||||
|
|
||||||
/// Selector model
|
|
||||||
/// Handles asynchronnous move operations between filament individual slots
|
|
||||||
/// Keeps track of selector's current state
|
|
||||||
|
|
||||||
namespace modules {
|
namespace modules {
|
||||||
|
|
||||||
|
/// The selector namespace provides all necessary facilities related to the logical model of the selector device of the MMU unit.
|
||||||
namespace selector {
|
namespace selector {
|
||||||
|
|
||||||
|
/// The selector model - handles asynchronnous move operations between filament individual slots and keeps track of selector's current state.
|
||||||
class Selector {
|
class Selector {
|
||||||
public:
|
public:
|
||||||
|
/// Internal states of selector's state machine
|
||||||
enum {
|
enum {
|
||||||
Ready = 0,
|
Ready = 0,
|
||||||
Moving,
|
Moving,
|
||||||
|
|
@ -21,13 +21,16 @@ public:
|
||||||
, plannedSlot(0)
|
, plannedSlot(0)
|
||||||
, currentSlot(0) {}
|
, currentSlot(0) {}
|
||||||
|
|
||||||
// public operations on the selector
|
/// Plan move of the selector to a specific filament slot
|
||||||
|
/// @param slot index to move to
|
||||||
/// @retuns false in case an operation is already underway
|
/// @returns false in case an operation is already underway
|
||||||
bool MoveToSlot(uint8_t slot);
|
bool MoveToSlot(uint8_t slot);
|
||||||
/// @retuns false in case an operation is already underway
|
|
||||||
|
/// Plan homing of the selector's axis
|
||||||
|
/// @returns false in case an operation is already underway
|
||||||
bool Home();
|
bool Home();
|
||||||
|
|
||||||
|
/// Performs one step of the state machine according to currently planned operation.
|
||||||
/// @returns true if the selector is ready to accept new commands (i.e. it has finished the last operation)
|
/// @returns true if the selector is ready to accept new commands (i.e. it has finished the last operation)
|
||||||
bool Step();
|
bool Step();
|
||||||
|
|
||||||
|
|
@ -51,6 +54,7 @@ private:
|
||||||
uint8_t currentSlot;
|
uint8_t currentSlot;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
/// The one and only instance of Selector in the FW
|
||||||
extern Selector selector;
|
extern Selector selector;
|
||||||
|
|
||||||
} // namespace selector
|
} // namespace selector
|
||||||
|
|
|
||||||
|
|
@ -2,6 +2,8 @@
|
||||||
#include <stdint.h>
|
#include <stdint.h>
|
||||||
|
|
||||||
namespace modules {
|
namespace modules {
|
||||||
|
|
||||||
|
/// The time namespace provides all necessary facilities related to measuring real elapsed time for the whole firmware.
|
||||||
namespace time {
|
namespace time {
|
||||||
|
|
||||||
/// A basic time tracking class
|
/// A basic time tracking class
|
||||||
|
|
@ -11,6 +13,8 @@ class Timebase {
|
||||||
public:
|
public:
|
||||||
constexpr inline Timebase()
|
constexpr inline Timebase()
|
||||||
: ms(0) {}
|
: ms(0) {}
|
||||||
|
|
||||||
|
/// Initializes the Timebase class - sets the timers and prepares the internal variables.
|
||||||
void Init();
|
void Init();
|
||||||
|
|
||||||
/// @returns current milliseconds elapsed from the initialization of this class
|
/// @returns current milliseconds elapsed from the initialization of this class
|
||||||
|
|
@ -22,6 +26,7 @@ private:
|
||||||
static void ISR();
|
static void ISR();
|
||||||
};
|
};
|
||||||
|
|
||||||
|
/// The one and only instance of Selector in the FW
|
||||||
extern Timebase timebase;
|
extern Timebase timebase;
|
||||||
|
|
||||||
} // namespace time
|
} // namespace time
|
||||||
|
|
|
||||||
|
|
@ -107,7 +107,7 @@ TEST_CASE("unload_to_finda::unload_without_FINDA_trigger", "[unload_to_finda]")
|
||||||
REQUIRE(ff.State() == logic::UnloadToFinda::WaitingForFINDA);
|
REQUIRE(ff.State() == logic::UnloadToFinda::WaitingForFINDA);
|
||||||
|
|
||||||
// no changes to FINDA during unload - we'll pretend it never triggers
|
// no changes to FINDA during unload - we'll pretend it never triggers
|
||||||
REQUIRE(!WhileCondition(
|
REQUIRE_FALSE(WhileCondition(
|
||||||
ff,
|
ff,
|
||||||
[&](int) { return mf::finda.Pressed(); },
|
[&](int) { return mf::finda.Pressed(); },
|
||||||
50000));
|
50000));
|
||||||
|
|
|
||||||
Loading…
Reference in New Issue