Introduce Doxyfile + fix modules documentation

pull/29/head
D.R.racer 2021-06-25 11:39:37 +02:00
parent 3020f01062
commit c2a2c75be1
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));