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