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
|
||||
/// - 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 {
|
||||
|
||||
|
|
|
|||
|
|
@ -3,12 +3,12 @@
|
|||
#include <stdint.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 {
|
||||
|
||||
/// The buttons namespace provides all necessary facilities related to the logical model of the physical buttons device the MMU unit.
|
||||
namespace buttons {
|
||||
|
||||
/// A model of a single button, performs automatic debouncing on top of the raw ADC API
|
||||
struct Button : public debounce::Debouncer {
|
||||
inline constexpr Button()
|
||||
: debounce::Debouncer(debounce) {}
|
||||
|
|
@ -18,12 +18,14 @@ private:
|
|||
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 {
|
||||
Left = 0,
|
||||
Middle,
|
||||
Right
|
||||
};
|
||||
|
||||
/// A model of the 3 buttons on the MMU unit
|
||||
class Buttons {
|
||||
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
|
||||
|
|
@ -31,11 +33,11 @@ class Buttons {
|
|||
public:
|
||||
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();
|
||||
|
||||
/// @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(); }
|
||||
|
||||
/// @returns true if any of the button is pressed
|
||||
|
|
@ -55,6 +57,7 @@ private:
|
|||
static int8_t DecodeADC(uint16_t rawADC);
|
||||
};
|
||||
|
||||
/// The one and only instance of Buttons in the FW
|
||||
extern Buttons buttons;
|
||||
|
||||
} // namespace buttons
|
||||
|
|
|
|||
|
|
@ -1,15 +1,17 @@
|
|||
/// A generic debouncing algorithm
|
||||
|
||||
#pragma once
|
||||
#include <stdint.h>
|
||||
|
||||
namespace modules {
|
||||
|
||||
/// The debounce namespace provides a generic debouncing algorithm.
|
||||
namespace debounce {
|
||||
|
||||
/// 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
|
||||
class Debouncer {
|
||||
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)
|
||||
: timeLastChange(0)
|
||||
, debounceTimeout(debounceTimeout) {}
|
||||
|
|
|
|||
|
|
@ -3,8 +3,11 @@
|
|||
#include "debouncer.h"
|
||||
|
||||
namespace modules {
|
||||
|
||||
/// The finda namespace provides all necessary facilities related to the logical model of the FINDA device the MMU unit.
|
||||
namespace finda {
|
||||
|
||||
/// A model of the FINDA - basically acts as a button with pre-set debouncing
|
||||
class FINDA : protected debounce::Debouncer {
|
||||
public:
|
||||
/// time interval for debouncing @@TODO specify units
|
||||
|
|
@ -14,10 +17,14 @@ public:
|
|||
|
||||
inline constexpr FINDA()
|
||||
: debounce::Debouncer(debounce) {};
|
||||
|
||||
/// Performs one step of the state machine - reads the ADC, processes debouncing, updates states of FINDA
|
||||
void Step();
|
||||
|
||||
using debounce::Debouncer::Pressed;
|
||||
};
|
||||
|
||||
/// The one and only instance of FINDA in the FW
|
||||
extern FINDA finda;
|
||||
|
||||
} // namespace finda
|
||||
|
|
|
|||
|
|
@ -2,21 +2,25 @@
|
|||
#include <stdint.h>
|
||||
#include "debouncer.h"
|
||||
|
||||
/// External module - model of printer's fsensor
|
||||
|
||||
namespace modules {
|
||||
|
||||
/// The fsensor namespace provides all necessary facilities related to the logical model of the printer's filamens sensor device.
|
||||
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 {
|
||||
public:
|
||||
inline constexpr FSensor()
|
||||
: debounce::Debouncer(debounce)
|
||||
, reportedFSensorState(false) {};
|
||||
|
||||
/// Performs one step of the state machine - processes a change-of-state message if any arrived
|
||||
void Step();
|
||||
|
||||
using debounce::Debouncer::Pressed;
|
||||
|
||||
/// Records a change of state of filament sensor when arrived via communication
|
||||
void ProcessMessage(bool on);
|
||||
|
||||
private:
|
||||
|
|
@ -25,7 +29,8 @@ private:
|
|||
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;
|
||||
|
||||
} // namespace finda
|
||||
} // namespace fsensor
|
||||
} // namespace modules
|
||||
|
|
|
|||
|
|
@ -2,16 +2,35 @@
|
|||
#include <stdint.h>
|
||||
|
||||
namespace modules {
|
||||
|
||||
/// The globals namespace provides all necessary facilities related to keeping track of global state of the firmware.
|
||||
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 {
|
||||
public:
|
||||
/// Initializes the global storage hive - basically looks into EEPROM to gather information.
|
||||
void Init();
|
||||
|
||||
/// @returns active filament slot on the MMU unit
|
||||
/// Slots are numbered 0-4
|
||||
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);
|
||||
|
||||
/// @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;
|
||||
|
||||
/// 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);
|
||||
|
||||
private:
|
||||
|
|
@ -19,6 +38,7 @@ private:
|
|||
bool filamentLoaded;
|
||||
};
|
||||
|
||||
/// The one and only instance of global state variables
|
||||
extern Globals globals;
|
||||
|
||||
} // namespace globals
|
||||
|
|
|
|||
|
|
@ -1,15 +1,15 @@
|
|||
#pragma once
|
||||
#include <stdint.h>
|
||||
|
||||
/// Idler model
|
||||
/// Handles asynchronnous Engaging / Disengaging operations
|
||||
/// Keeps track of idler's current state
|
||||
|
||||
namespace modules {
|
||||
|
||||
/// The idler namespace provides all necessary facilities related to the logical model of the idler device of the MMU unit.
|
||||
namespace idler {
|
||||
|
||||
/// The Idler model handles asynchronnous Engaging / Disengaging operations and keeps track of idler's current state.
|
||||
class Idler {
|
||||
public:
|
||||
/// Internal states of idler's state machine
|
||||
enum {
|
||||
Ready = 0, // intentionally set as zero in order to allow zeroing the Idler structure upon startup -> avoid explicit initialization code
|
||||
Moving,
|
||||
|
|
@ -23,15 +23,20 @@ public:
|
|||
, currentSlot(0)
|
||||
, currentlyEngaged(false) {}
|
||||
|
||||
// public operations on the idler
|
||||
|
||||
/// @retuns false in case an operation is already underway
|
||||
/// Plan engaging of the idler to a specific filament slot
|
||||
/// @param slot index to be activated
|
||||
/// @returns false in case an operation is already underway
|
||||
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();
|
||||
/// @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();
|
||||
|
||||
/// 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)
|
||||
bool Step();
|
||||
|
||||
|
|
@ -62,6 +67,7 @@ private:
|
|||
bool currentlyEngaged;
|
||||
};
|
||||
|
||||
/// The one and only instance of Idler in the FW
|
||||
extern Idler idler;
|
||||
|
||||
} // namespace idler
|
||||
|
|
|
|||
|
|
@ -2,18 +2,22 @@
|
|||
|
||||
#include <stdint.h>
|
||||
|
||||
/// We have 5 pairs of LEDs
|
||||
/// In each pair there is a green and a red LED
|
||||
namespace modules {
|
||||
|
||||
/// @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.
|
||||
/// 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)
|
||||
|
||||
namespace modules {
|
||||
/// The physical connection is not important on this level (i.e. how and what shall be sent into the shift registers).
|
||||
///
|
||||
/// 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 {
|
||||
|
||||
/// Mode of LED
|
||||
/// Enum of LED modes
|
||||
/// blink0 and blink1 allow for interlaced blinking of LEDs (one is on and the other off)
|
||||
enum Mode {
|
||||
off,
|
||||
|
|
@ -22,20 +26,29 @@ enum Mode {
|
|||
blink1 ///< start blinking at odd periods
|
||||
};
|
||||
|
||||
/// Enum of LEDs color - green or red
|
||||
enum Color {
|
||||
green = 0,
|
||||
red = 1
|
||||
};
|
||||
|
||||
/// a single LED
|
||||
/// A single LED
|
||||
class LED {
|
||||
public:
|
||||
constexpr inline LED() = default;
|
||||
|
||||
/// Sets the mode of the LED
|
||||
/// @param mode to set
|
||||
void SetMode(leds::Mode mode);
|
||||
|
||||
/// @returns the currently active mode of the LED
|
||||
inline leds::Mode Mode() const { return (leds::Mode)state.mode; }
|
||||
|
||||
/// @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);
|
||||
|
||||
/// @returns true if the LED shines
|
||||
inline bool On() const { return state.on; }
|
||||
|
||||
private:
|
||||
|
|
@ -50,7 +63,7 @@ private:
|
|||
State state;
|
||||
};
|
||||
|
||||
/// main LED API
|
||||
/// The main LEDs API takes care of the whole set of LEDs
|
||||
class LEDs {
|
||||
public:
|
||||
constexpr inline LEDs() = default;
|
||||
|
|
@ -58,25 +71,46 @@ public:
|
|||
/// step LED automaton
|
||||
void Step();
|
||||
|
||||
/// @returns the number of LED pairs
|
||||
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) {
|
||||
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) {
|
||||
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) {
|
||||
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) {
|
||||
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 {
|
||||
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 {
|
||||
return leds[slot * 2 + color].On();
|
||||
}
|
||||
|
|
@ -97,6 +131,7 @@ private:
|
|||
LED leds[ledPairs * 2];
|
||||
};
|
||||
|
||||
/// The one and only instance of FINDA in the FW
|
||||
extern LEDs leds;
|
||||
|
||||
} // namespace LEDs
|
||||
|
|
|
|||
|
|
@ -1,4 +1,3 @@
|
|||
/// @author Marek Bel
|
||||
#include "permanent_storage.h"
|
||||
#include "../hal/eeprom.h"
|
||||
#include "globals.h"
|
||||
|
|
@ -57,7 +56,6 @@ void Init() {
|
|||
}
|
||||
}
|
||||
|
||||
/// @brief Erase the whole EEPROM
|
||||
void EraseAll() {
|
||||
for (uint16_t i = 0; i < ee::EEPROM::End(); i++) {
|
||||
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
|
||||
|
||||
#include "../hal/eeprom.h"
|
||||
|
||||
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 {
|
||||
|
||||
void Init();
|
||||
void EraseAll();
|
||||
/// Initialization of the permanent storage hive
|
||||
void Init();
|
||||
|
||||
/// @brief Read manipulate and store 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();
|
||||
/// Erase the whole EEPROM
|
||||
void EraseAll();
|
||||
|
||||
private:
|
||||
uint8_t filament; ///< Selected filament
|
||||
uint16_t length; ///< Selected filament bowden length
|
||||
/// @brief Read manipulate and store 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
|
||||
///
|
||||
/// 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);
|
||||
/// @brief Read and increment drive errors
|
||||
///
|
||||
/// (Motor power rail voltage loss)
|
||||
class DriveError {
|
||||
public:
|
||||
static uint16_t get();
|
||||
static void increment();
|
||||
|
||||
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 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);
|
||||
};
|
||||
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 modules
|
||||
|
|
|
|||
|
|
@ -1,14 +1,15 @@
|
|||
#pragma once
|
||||
|
||||
#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
|
||||
/// @@TODO possibly add some checksum to verify the correctness of messages
|
||||
|
||||
namespace modules {
|
||||
namespace protocol {
|
||||
|
||||
/// Definition of request message codes
|
||||
enum class RequestMsgCodes : uint8_t {
|
||||
unknown = 0,
|
||||
Query = 'Q',
|
||||
|
|
@ -25,6 +26,7 @@ enum class RequestMsgCodes : uint8_t {
|
|||
Cut = 'K'
|
||||
};
|
||||
|
||||
/// Definition of response message parameter codes
|
||||
enum class ResponseMsgParamCodes : uint8_t {
|
||||
unknown = 0,
|
||||
Processing = 'P',
|
||||
|
|
@ -34,30 +36,34 @@ enum class ResponseMsgParamCodes : uint8_t {
|
|||
Rejected = 'R'
|
||||
};
|
||||
|
||||
/// A request message
|
||||
/// Requests are being sent by the printer into the MMU
|
||||
/// It is the same structure as the generic Msg
|
||||
/// A request message - requests are being sent by the printer into the MMU.
|
||||
struct RequestMsg {
|
||||
RequestMsgCodes code;
|
||||
uint8_t value;
|
||||
RequestMsgCodes code; ///< code of the request message
|
||||
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)
|
||||
: code(code)
|
||||
, value(value) {}
|
||||
};
|
||||
|
||||
/// A response message
|
||||
/// Responses are being sent from the MMU into the printer as a response to a request message
|
||||
/// A response message - responses are being sent from the MMU into the printer as a response to a request message.
|
||||
struct ResponseMsg {
|
||||
RequestMsg request; ///< response is always preceeded by the request message
|
||||
ResponseMsgParamCodes paramCode; ///< parameters of reply
|
||||
uint8_t paramValue; ///< parameters of reply
|
||||
ResponseMsgParamCodes paramCode; ///< code of the parameter
|
||||
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)
|
||||
: request(request)
|
||||
, paramCode(paramCode)
|
||||
, paramValue(paramValue) {}
|
||||
};
|
||||
|
||||
/// Message decoding return value
|
||||
/// Message decoding return values
|
||||
enum class DecodeStatus : uint_fast8_t {
|
||||
MessageCompleted, ///< message completed and successfully lexed
|
||||
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
|
||||
///
|
||||
/// 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 {
|
||||
public:
|
||||
inline Protocol()
|
||||
|
|
@ -91,18 +98,22 @@ public:
|
|||
|
||||
/// Encode generic response Command Accepted or Rejected
|
||||
/// @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
|
||||
static uint8_t EncodeResponseCmdAR(const RequestMsg &msg, ResponseMsgParamCodes ar, uint8_t *txbuff);
|
||||
|
||||
/// Encode response to Read FINDA query
|
||||
/// @param msg source request message for this response
|
||||
/// @param findaValue 1/0 (on/off) status of FINDA
|
||||
/// @param txbuff where to format the message
|
||||
/// @returns number of bytes written into txbuff
|
||||
static uint8_t EncodeResponseReadFINDA(const RequestMsg &msg, uint8_t findaValue, uint8_t *txbuff);
|
||||
|
||||
/// Encode response to Version query
|
||||
/// @param msg source request message for this response
|
||||
/// @param value version number (0-255)
|
||||
/// @param txbuff where to format the message
|
||||
/// @returns number of bytes written into 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 code status of operation (Processing, Error, Finished)
|
||||
/// @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
|
||||
static uint8_t EncodeResponseQueryOperation(const RequestMsg &msg, ResponseMsgParamCodes code, uint8_t value, uint8_t *txbuff);
|
||||
|
||||
|
|
|
|||
|
|
@ -1,15 +1,15 @@
|
|||
#pragma once
|
||||
#include <stdint.h>
|
||||
|
||||
/// Selector model
|
||||
/// Handles asynchronnous move operations between filament individual slots
|
||||
/// Keeps track of selector's current state
|
||||
|
||||
namespace modules {
|
||||
|
||||
/// The selector namespace provides all necessary facilities related to the logical model of the selector device of the MMU unit.
|
||||
namespace selector {
|
||||
|
||||
/// The selector model - handles asynchronnous move operations between filament individual slots and keeps track of selector's current state.
|
||||
class Selector {
|
||||
public:
|
||||
/// Internal states of selector's state machine
|
||||
enum {
|
||||
Ready = 0,
|
||||
Moving,
|
||||
|
|
@ -21,13 +21,16 @@ public:
|
|||
, plannedSlot(0)
|
||||
, currentSlot(0) {}
|
||||
|
||||
// public operations on the selector
|
||||
|
||||
/// @retuns false in case an operation is already underway
|
||||
/// Plan move of the selector to a specific filament slot
|
||||
/// @param slot index to move to
|
||||
/// @returns false in case an operation is already underway
|
||||
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();
|
||||
|
||||
/// 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)
|
||||
bool Step();
|
||||
|
||||
|
|
@ -51,6 +54,7 @@ private:
|
|||
uint8_t currentSlot;
|
||||
};
|
||||
|
||||
/// The one and only instance of Selector in the FW
|
||||
extern Selector selector;
|
||||
|
||||
} // namespace selector
|
||||
|
|
|
|||
|
|
@ -2,6 +2,8 @@
|
|||
#include <stdint.h>
|
||||
|
||||
namespace modules {
|
||||
|
||||
/// The time namespace provides all necessary facilities related to measuring real elapsed time for the whole firmware.
|
||||
namespace time {
|
||||
|
||||
/// A basic time tracking class
|
||||
|
|
@ -11,6 +13,8 @@ class Timebase {
|
|||
public:
|
||||
constexpr inline Timebase()
|
||||
: ms(0) {}
|
||||
|
||||
/// Initializes the Timebase class - sets the timers and prepares the internal variables.
|
||||
void Init();
|
||||
|
||||
/// @returns current milliseconds elapsed from the initialization of this class
|
||||
|
|
@ -22,6 +26,7 @@ private:
|
|||
static void ISR();
|
||||
};
|
||||
|
||||
/// The one and only instance of Selector in the FW
|
||||
extern Timebase timebase;
|
||||
|
||||
} // namespace time
|
||||
|
|
|
|||
|
|
@ -107,7 +107,7 @@ TEST_CASE("unload_to_finda::unload_without_FINDA_trigger", "[unload_to_finda]")
|
|||
REQUIRE(ff.State() == logic::UnloadToFinda::WaitingForFINDA);
|
||||
|
||||
// no changes to FINDA during unload - we'll pretend it never triggers
|
||||
REQUIRE(!WhileCondition(
|
||||
REQUIRE_FALSE(WhileCondition(
|
||||
ff,
|
||||
[&](int) { return mf::finda.Pressed(); },
|
||||
50000));
|
||||
|
|
|
|||
Loading…
Reference in New Issue