Prusa-Firmware-MMU/src/main.dox

128 lines
5.7 KiB
Plaintext

///@mainpage Prusa Multi Material Unit for the MK4
///@section intro_sec Introduction
///
/// This is the new firmware for the Multi Material Unit (MMU).
///
///@subsection Motivation
///
/// The key motivation for developing a new firmware structure were as follows:
/// - adding a possibility of reporting the MMU's state even during running commands - the architecture of the original MM-control-01 project
/// didn't allow to achieve this requirement
/// - while being able to report the internal state of the MMU, the printer should be able to describe the error states clearly on its LCD without
/// leaving the user to rely on some blinking LEDs
/// - modular design prepared for possible future upgrades
///
///@section project_sec Project structure
///
/// - cmake
/// - lib
/// - src
/// - tests
/// - utils
///
///@section architecture_sec Firmware architecture
///
/// The whole firmware is composed of simple state machines which run all at once - it is a kind of simple cooperative multi-tasking
/// while not eating up any significant resources by deploying generic task switching solutions like RTOS or similar.
/// The general rule is to avoid waiting inside these state machines, no state machine is allowed to block execution of others.
/// That implies making separate waiting states which only check for some condition to be true before proceeding further.
///
/// The firmware is separated into 4 layers:
/// - HAL is responsible for talking to the physical hardware, in our case an AVR processor and its peripherals, TMC2130 stepper drivers, shift registers etc.
/// - modules are the components abstracted of the real hardware and/or connection. A typical example are the buttons, LEDs, Idler, Selector etc.
/// - logic layer is the application logic - this layer provides the sequences and logical relations between modules thus forming the behavior of the MMU.
/// - main is the top layer, it is responsible for initialization of the whole firmware and performing the main loop, where the stepping of all the automata is located.
///
/// The whole architecture becomes obvious from the following picture:
///
///@dot
///digraph architecture {
/// node [shape=record, fontname=Helvetica, fontsize=10];
/// subgraph cluster_main { label="main"
/// main [ URL="\ref main"];
/// }
/// subgraph cluster_logic { label="logic"
/// logic [ URL="\ref logic"];
/// }
///
/// subgraph cluster_modules { label="modules"
/// buttons [ URL="\ref buttons"];
/// debouncer [ URL="\ref debouncer"];
/// finda [ URL="\ref finda"];
/// fsensor [ URL="\ref fsensor"];
/// globals [ URL="\ref globals"];
/// idler [ URL="\ref idler"];
/// leds [ URL="\ref leds"];
/// selector [ URL="\ref selector"];
/// motion [ URL="\ref motion"];
/// permanent_storage [ URL="\ref permanent_storage"];
/// protocol [ URL="\ref protocol"];
/// timebase [ URL="\ref timebase"];
/// }
/// subgraph cluster_hal { label="hal"
/// adc [ URL="\ref adc"];
/// cpu [ URL="\ref cpu"];
/// eeprom [ URL="\ref eeprom"];
/// gpio [ URL="\ref gpio"];
/// shr16 [ URL="\ref shr16"];
/// spi [ URL="\ref spi"];
/// timers [ URL="\ref timers"];
/// tmc2130 [ URL="\ref tmc2130"];
/// usart [ URL="\ref usart"];
/// watchdog [ URL="\ref watchdog"];
/// }
/// main -> logic [ arrowhead="open" ];
///
/// logic -> buttons [ arrowhead="open" ];
/// logic -> finda [ arrowhead="open" ];
/// logic -> fsensor [ arrowhead="open" ];
/// logic -> globals [ arrowhead="open" ];
/// logic -> idler [ arrowhead="open" ];
/// logic -> leds [ arrowhead="open" ];
/// logic -> motion [ arrowhead="open" ];
/// logic -> permanent_storage [ arrowhead="open" ];
/// logic -> protocol [ arrowhead="open" ];
/// logic -> selector [ arrowhead="open" ];
/// logic -> timebase [ arrowhead="open" ];
///
/// selector -> motion [ arrowhead="open" ];
/// idler -> motion [ arrowhead="open" ];
/// buttons -> debouncer [ arrowhead="open" ];
/// finda -> debouncer [ arrowhead="open" ];
/// fsensor -> debouncer [ arrowhead="open" ];
///
/// buttons -> adc [ arrowhead="open" ];
/// finda -> adc [ arrowhead="open" ];
/// fsensor [ arrowhead="open" ];
/// globals -> permanent_storage [ arrowhead="open" ];
/// leds -> shr16 [ arrowhead="open" ];
/// motion -> tmc2130 [ arrowhead="open" ];
/// permanent_storage -> eeprom [ arrowhead="open" ];
/// protocol -> usart [ arrowhead="open" ];
/// timebase -> timers [ arrowhead="open" ];
///}
///@enddot
///
/// Sidenote: due to avr-gcc 5.4 limitations we cannot use proper Singleton patterns but have to rely on global variables of each state machine.
///
///@section protocol_sec Protocol description
///
/// The communication protocol between the printer and the MMU has only been extended to minimize the influence on existing MMU interface implementation.
/// However, the backwards compatibility has not been kept and at least some changes are necessary.
/// The good news is that the Slicer's MMU code is fully backwards compatible.
///
///
///@section tests_sec Tests and quality assurance
///
///@subsection unit_sec Unit tests
///
/// The firmware architecture was designed with unit testing in mind, thus each firmware layer has only the least amount of necessary dependencies to surrounding code.
/// This approach greatly simplified the definition of unit testing procedures with only a small amount stubs necessary.
///
/// Each firmware layer has its own subdirectory, the directory tree follows the firmware structure
///
/// The usage of stubs at each layer
///
///@subsection integration_sec Integration tests
///