Introduce Doxyfile + fix modules documentation

pull/37/head
D.R.racer 2021-06-25 11:39:37 +02:00 committed by DRracer
parent f6e5d4ae76
commit c15b1d59c4
15 changed files with 2734 additions and 140 deletions

2494
Doxyfile Normal file

File diff suppressed because it is too large Load Diff

View File

@ -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 {

View File

@ -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

View File

@ -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) {}

View File

@ -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

View File

@ -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

View File

@ -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

View File

@ -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

View File

@ -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

View File

@ -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));

View File

@ -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

View File

@ -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);

View File

@ -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

View File

@ -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

View File

@ -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));