| 
									
										
										
										
											2016-05-25 11:37:40 -04:00
										 |  |  | This document describes the overall code layout and major code flow of | 
					
						
							|  |  |  | Klipper. | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | Directory Layout | 
					
						
							|  |  |  | ================ | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | The **src/** directory contains the C source for the micro-controller | 
					
						
							| 
									
										
										
										
											2019-11-07 10:08:21 -05:00
										 |  |  | code. The **src/atsam/**, **src/atsamd/**, **src/avr/**, | 
					
						
							|  |  |  | **src/linux/**, **src/lpc176x/**, **src/pru/**, and **src/stm32/** | 
					
						
							| 
									
										
										
										
											2018-12-26 15:41:37 -05:00
										 |  |  | directories contain architecture specific micro-controller code. The | 
					
						
							|  |  |  | **src/simulator/** contains code stubs that allow the micro-controller | 
					
						
							|  |  |  | to be test compiled on other architectures. The **src/generic/** | 
					
						
							|  |  |  | directory contains helper code that may be useful across different | 
					
						
							|  |  |  | architectures. The build arranges for includes of "board/somefile.h" | 
					
						
							|  |  |  | to first look in the current architecture directory (eg, | 
					
						
							|  |  |  | src/avr/somefile.h) and then in the generic directory (eg, | 
					
						
							|  |  |  | src/generic/somefile.h). | 
					
						
							| 
									
										
										
										
											2016-05-25 11:37:40 -04:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2018-04-30 11:22:16 -04:00
										 |  |  | The **klippy/** directory contains the host software. Most of the host | 
					
						
							|  |  |  | software is written in Python, however the **klippy/chelper/** | 
					
						
							| 
									
										
										
										
											2018-11-17 14:56:15 -05:00
										 |  |  | directory contains some C code helpers. The **klippy/kinematics/** | 
					
						
							|  |  |  | directory contains the robot kinematics code. The **klippy/extras/** | 
					
						
							| 
									
										
										
										
											2018-04-30 11:22:16 -04:00
										 |  |  | directory contains the host code extensible "modules". | 
					
						
							| 
									
										
										
										
											2016-05-25 11:37:40 -04:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2016-07-26 10:58:33 -04:00
										 |  |  | The **lib/** directory contains external 3rd-party library code that | 
					
						
							|  |  |  | is necessary to build some targets. | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2016-05-25 11:37:40 -04:00
										 |  |  | The **config/** directory contains example printer configuration | 
					
						
							|  |  |  | files. | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | The **scripts/** directory contains build-time scripts useful for | 
					
						
							|  |  |  | compiling the micro-controller code. | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2018-03-28 13:01:24 -04:00
										 |  |  | The **test/** directory contains automated test cases. | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2016-05-25 11:37:40 -04:00
										 |  |  | During compilation, the build may create an **out/** directory. This | 
					
						
							|  |  |  | contains temporary build time objects. The final micro-controller | 
					
						
							| 
									
										
										
										
											2016-07-26 10:58:33 -04:00
										 |  |  | object that is built is **out/klipper.elf.hex** on AVR and | 
					
						
							|  |  |  | **out/klipper.bin** on ARM. | 
					
						
							| 
									
										
										
										
											2016-05-25 11:37:40 -04:00
										 |  |  | 
 | 
					
						
							|  |  |  | Micro-controller code flow | 
					
						
							|  |  |  | ========================== | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2016-07-26 10:58:33 -04:00
										 |  |  | Execution of the micro-controller code starts in architecture specific | 
					
						
							|  |  |  | code (eg, **src/avr/main.c**) which ultimately calls sched_main() | 
					
						
							|  |  |  | located in **src/sched.c**. The sched_main() code starts by running | 
					
						
							|  |  |  | all functions that have been tagged with the DECL_INIT() macro. It | 
					
						
							|  |  |  | then goes on to repeatedly run all functions tagged with the | 
					
						
							|  |  |  | DECL_TASK() macro. | 
					
						
							| 
									
										
										
										
											2016-05-25 11:37:40 -04:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2017-08-11 11:55:30 -04:00
										 |  |  | One of the main task functions is command_dispatch() located in | 
					
						
							|  |  |  | **src/command.c**. This function is called from the board specific | 
					
						
							| 
									
										
										
										
											2019-11-07 10:08:21 -05:00
										 |  |  | input/output code (eg, **src/avr/serial.c**, | 
					
						
							|  |  |  | **src/generic/serial_irq.c**) and it runs the command functions | 
					
						
							|  |  |  | associated with the commands found in the input stream. Command | 
					
						
							|  |  |  | functions are declared using the DECL_COMMAND() macro (see the | 
					
						
							|  |  |  | [protocol](Protocol.md) document for more information). | 
					
						
							| 
									
										
										
										
											2016-05-25 11:37:40 -04:00
										 |  |  | 
 | 
					
						
							|  |  |  | Task, init, and command functions always run with interrupts enabled | 
					
						
							|  |  |  | (however, they can temporarily disable interrupts if needed). These | 
					
						
							|  |  |  | functions should never pause, delay, or do any work that lasts more | 
					
						
							|  |  |  | than a few micro-seconds. These functions schedule work at specific | 
					
						
							|  |  |  | times by scheduling timers. | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2017-03-10 22:12:05 -05:00
										 |  |  | Timer functions are scheduled by calling sched_add_timer() (located in | 
					
						
							| 
									
										
										
										
											2016-05-25 11:37:40 -04:00
										 |  |  | **src/sched.c**). The scheduler code will arrange for the given | 
					
						
							|  |  |  | function to be called at the requested clock time. Timer interrupts | 
					
						
							| 
									
										
										
										
											2016-07-26 10:58:33 -04:00
										 |  |  | are initially handled in an architecture specific interrupt handler | 
					
						
							| 
									
										
										
										
											2017-03-27 16:38:01 -04:00
										 |  |  | (eg, **src/avr/timer.c**) which calls sched_timer_dispatch() located | 
					
						
							|  |  |  | in **src/sched.c**. The timer interrupt leads to execution of schedule | 
					
						
							|  |  |  | timer functions. Timer functions always run with interrupts | 
					
						
							| 
									
										
										
										
											2016-07-26 10:58:33 -04:00
										 |  |  | disabled. The timer functions should always complete within a few | 
					
						
							|  |  |  | micro-seconds. At completion of the timer event, the function may | 
					
						
							|  |  |  | choose to reschedule itself. | 
					
						
							| 
									
										
										
										
											2016-05-25 11:37:40 -04:00
										 |  |  | 
 | 
					
						
							|  |  |  | In the event an error is detected the code can invoke shutdown() (a | 
					
						
							|  |  |  | macro which calls sched_shutdown() located in **src/sched.c**). | 
					
						
							|  |  |  | Invoking shutdown() causes all functions tagged with the | 
					
						
							|  |  |  | DECL_SHUTDOWN() macro to be run. Shutdown functions always run with | 
					
						
							|  |  |  | interrupts disabled. | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | Much of the functionality of the micro-controller involves working | 
					
						
							|  |  |  | with General-Purpose Input/Output pins (GPIO). In order to abstract | 
					
						
							|  |  |  | the low-level architecture specific code from the high-level task | 
					
						
							| 
									
										
										
										
											2018-03-28 13:01:24 -04:00
										 |  |  | code, all GPIO events are implemented in architecture specific | 
					
						
							| 
									
										
										
										
											2016-07-26 10:58:33 -04:00
										 |  |  | wrappers (eg, **src/avr/gpio.c**). The code is compiled with gcc's | 
					
						
							|  |  |  | "-flto -fwhole-program" optimization which does an excellent job of | 
					
						
							|  |  |  | inlining functions across compilation units, so most of these tiny | 
					
						
							|  |  |  | gpio functions are inlined into their callers, and there is no | 
					
						
							|  |  |  | run-time cost to using them. | 
					
						
							| 
									
										
										
										
											2016-05-25 11:37:40 -04:00
										 |  |  | 
 | 
					
						
							|  |  |  | Klippy code overview | 
					
						
							|  |  |  | ==================== | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | The host code (Klippy) is intended to run on a low-cost computer (such | 
					
						
							|  |  |  | as a Raspberry Pi) paired with the micro-controller. The code is | 
					
						
							|  |  |  | primarily written in Python, however it does use CFFI to implement | 
					
						
							|  |  |  | some functionality in C code. | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | Initial execution starts in **klippy/klippy.py**. This reads the | 
					
						
							|  |  |  | command-line arguments, opens the printer config file, instantiates | 
					
						
							|  |  |  | the main printer objects, and starts the serial connection. The main | 
					
						
							| 
									
										
										
										
											2017-04-27 15:14:11 -04:00
										 |  |  | execution of G-code commands is in the process_commands() method in | 
					
						
							|  |  |  | **klippy/gcode.py**. This code translates the G-code commands into | 
					
						
							| 
									
										
										
										
											2016-05-25 11:37:40 -04:00
										 |  |  | printer object calls, which frequently translate the actions to | 
					
						
							|  |  |  | commands to be executed on the micro-controller (as declared via the | 
					
						
							|  |  |  | DECL_COMMAND macro in the micro-controller code). | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2016-11-11 20:22:39 -05:00
										 |  |  | There are four threads in the Klippy host code. The main thread | 
					
						
							| 
									
										
										
										
											2016-05-25 11:37:40 -04:00
										 |  |  | handles incoming gcode commands. A second thread (which resides | 
					
						
							| 
									
										
										
										
											2018-04-30 11:22:16 -04:00
										 |  |  | entirely in the **klippy/chelper/serialqueue.c** C code) handles | 
					
						
							|  |  |  | low-level IO with the serial port. The third thread is used to process | 
					
						
							|  |  |  | response messages from the micro-controller in the Python code (see | 
					
						
							| 
									
										
										
										
											2016-11-11 20:22:39 -05:00
										 |  |  | **klippy/serialhdl.py**). The fourth thread writes debug messages to | 
					
						
							|  |  |  | the log (see **klippy/queuelogger.py**) so that the other threads | 
					
						
							|  |  |  | never block on log writes. | 
					
						
							| 
									
										
										
										
											2017-04-10 17:47:38 -04:00
										 |  |  | 
 | 
					
						
							|  |  |  | Code flow of a move command | 
					
						
							|  |  |  | =========================== | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | A typical printer movement starts when a "G1" command is sent to the | 
					
						
							|  |  |  | Klippy host and it completes when the corresponding step pulses are | 
					
						
							|  |  |  | produced on the micro-controller. This section outlines the code flow | 
					
						
							| 
									
										
										
										
											2017-04-15 15:22:50 -04:00
										 |  |  | of a typical move command. The [kinematics](Kinematics.md) document | 
					
						
							|  |  |  | provides further information on the mechanics of moves. | 
					
						
							| 
									
										
										
										
											2017-04-10 17:47:38 -04:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2017-04-13 13:41:58 -04:00
										 |  |  | * Processing for a move command starts in gcode.py. The goal of | 
					
						
							|  |  |  |   gcode.py is to translate G-code into internal calls. Changes in | 
					
						
							|  |  |  |   origin (eg, G92), changes in relative vs absolute positions (eg, | 
					
						
							|  |  |  |   G90), and unit changes (eg, F6000=100mm/s) are handled here. The | 
					
						
							| 
									
										
										
										
											2019-11-07 10:39:17 -05:00
										 |  |  |   code path for a move is: `_process_data() -> _process_commands() -> | 
					
						
							| 
									
										
										
										
											2017-04-13 13:41:58 -04:00
										 |  |  |   cmd_G1()`. Ultimately the ToolHead class is invoked to execute the | 
					
						
							|  |  |  |   actual request: `cmd_G1() -> ToolHead.move()` | 
					
						
							| 
									
										
										
										
											2017-04-10 17:47:38 -04:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2017-04-27 12:02:15 -04:00
										 |  |  | * The ToolHead class (in toolhead.py) handles "look-ahead" and tracks | 
					
						
							| 
									
										
										
										
											2019-11-07 10:39:17 -05:00
										 |  |  |   the timing of printing actions. The main codepath for a move is: | 
					
						
							| 
									
										
										
										
											2017-04-13 13:41:58 -04:00
										 |  |  |   `ToolHead.move() -> MoveQueue.add_move() -> MoveQueue.flush() -> | 
					
						
							| 
									
										
										
										
											2019-11-07 10:39:17 -05:00
										 |  |  |   Move.set_junction() -> ToolHead._process_moves()`. | 
					
						
							| 
									
										
										
										
											2017-04-13 13:41:58 -04:00
										 |  |  |   * ToolHead.move() creates a Move() object with the parameters of the | 
					
						
							|  |  |  |   move (in cartesian space and in units of seconds and millimeters). | 
					
						
							| 
									
										
										
										
											2019-11-07 10:39:17 -05:00
										 |  |  |   * The kinematics class is given the opportunity to audit each move | 
					
						
							|  |  |  |   (`ToolHead.move() -> kin.check_move()`). The kinematics classes are | 
					
						
							|  |  |  |   located in the klippy/kinematics/ directory. The check_move() code | 
					
						
							|  |  |  |   may raise an error if the move is not valid. If check_move() | 
					
						
							|  |  |  |   completes successfully then the underlying kinematics must be able | 
					
						
							|  |  |  |   to handle the move. | 
					
						
							| 
									
										
										
										
											2017-04-27 12:02:15 -04:00
										 |  |  |   * MoveQueue.add_move() places the move object on the "look-ahead" | 
					
						
							| 
									
										
										
										
											2017-04-13 13:41:58 -04:00
										 |  |  |   queue. | 
					
						
							|  |  |  |   * MoveQueue.flush() determines the start and end velocities of each | 
					
						
							|  |  |  |   move. | 
					
						
							|  |  |  |   * Move.set_junction() implements the "trapezoid generator" on a | 
					
						
							|  |  |  |   move. The "trapezoid generator" breaks every move into three parts: | 
					
						
							|  |  |  |   a constant acceleration phase, followed by a constant velocity | 
					
						
							|  |  |  |   phase, followed by a constant deceleration phase. Every move | 
					
						
							|  |  |  |   contains these three phases in this order, but some phases may be of | 
					
						
							|  |  |  |   zero duration. | 
					
						
							| 
									
										
										
										
											2019-11-07 10:39:17 -05:00
										 |  |  |   * When ToolHead._process_moves() is called, everything about the | 
					
						
							|  |  |  |   move is known - its start location, its end location, its | 
					
						
							|  |  |  |   acceleration, its start/cruising/end velocity, and distance traveled | 
					
						
							|  |  |  |   during acceleration/cruising/deceleration. All the information is | 
					
						
							|  |  |  |   stored in the Move() class and is in cartesian space in units of | 
					
						
							|  |  |  |   millimeters and seconds. | 
					
						
							| 
									
										
										
										
											2018-06-19 00:50:59 -04:00
										 |  |  | 
 | 
					
						
							|  |  |  | * Klipper uses an | 
					
						
							|  |  |  |   [iterative solver](https://en.wikipedia.org/wiki/Root-finding_algorithm) | 
					
						
							|  |  |  |   to generate the step times for each stepper. For efficiency reasons, | 
					
						
							| 
									
										
										
										
											2019-11-07 10:39:17 -05:00
										 |  |  |   the stepper pulse times are generated in C code. The moves are first | 
					
						
							|  |  |  |   placed on a "trapezoid motion queue": `ToolHead._process_moves() -> | 
					
						
							|  |  |  |   trapq_append()` (in klippy/chelper/trapq.c). The step times are then | 
					
						
							|  |  |  |   generated: `ToolHead._process_moves() -> | 
					
						
							|  |  |  |   ToolHead._update_move_time() -> MCU_Stepper.generate_steps() -> | 
					
						
							|  |  |  |   itersolve_generate_steps() -> itersolve_gen_steps_range()` (in | 
					
						
							|  |  |  |   klippy/chelper/itersolve.c). The goal of the iterative solver is to | 
					
						
							|  |  |  |   find step times given a function that calculates a stepper position | 
					
						
							|  |  |  |   from a time. This is done by repeatedly "guessing" various times | 
					
						
							|  |  |  |   until the stepper position formula returns the desired position of | 
					
						
							|  |  |  |   the next step on the stepper. The feedback produced from each guess | 
					
						
							|  |  |  |   is used to improve future guesses so that the process rapidly | 
					
						
							|  |  |  |   converges to the desired time. The kinematic stepper position | 
					
						
							|  |  |  |   formulas are located in the klippy/chelper/ directory (eg, | 
					
						
							|  |  |  |   kin_cart.c, kin_corexy.c, kin_delta.c, kin_extruder.c). | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | * Note that the extruder is handled in its own kinematic class: | 
					
						
							|  |  |  |   `ToolHead._process_moves() -> PrinterExtruder.move()`. Since | 
					
						
							|  |  |  |   the Move() class specifies the exact movement time and since step | 
					
						
							|  |  |  |   pulses are sent to the micro-controller with specific timing, | 
					
						
							|  |  |  |   stepper movements produced by the extruder class will be in sync | 
					
						
							|  |  |  |   with head movement even though the code is kept separate. | 
					
						
							| 
									
										
										
										
											2018-06-19 00:50:59 -04:00
										 |  |  | 
 | 
					
						
							|  |  |  | * After the iterative solver calculates the step times they are added | 
					
						
							| 
									
										
										
										
											2019-11-07 10:39:17 -05:00
										 |  |  |   to an array: `itersolve_gen_steps_range() -> queue_append()` (in | 
					
						
							| 
									
										
										
										
											2018-06-19 00:50:59 -04:00
										 |  |  |   klippy/chelper/stepcompress.c). The array (struct | 
					
						
							|  |  |  |   stepcompress.queue) stores the corresponding micro-controller clock | 
					
						
							|  |  |  |   counter times for every step. Here the "micro-controller clock | 
					
						
							|  |  |  |   counter" value directly corresponds to the micro-controller's | 
					
						
							|  |  |  |   hardware counter - it is relative to when the micro-controller was | 
					
						
							|  |  |  |   last powered up. | 
					
						
							| 
									
										
										
										
											2017-04-10 17:47:38 -04:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2017-04-13 13:41:58 -04:00
										 |  |  | * The next major step is to compress the steps: `stepcompress_flush() | 
					
						
							| 
									
										
										
										
											2018-04-30 11:22:16 -04:00
										 |  |  |   -> compress_bisect_add()` (in klippy/chelper/stepcompress.c). This | 
					
						
							|  |  |  |   code generates and encodes a series of micro-controller "queue_step" | 
					
						
							|  |  |  |   commands that correspond to the list of stepper step times built in | 
					
						
							|  |  |  |   the previous stage. These "queue_step" commands are then queued, | 
					
						
							|  |  |  |   prioritized, and sent to the micro-controller (via | 
					
						
							|  |  |  |   stepcompress.c:steppersync and serialqueue.c:serialqueue). | 
					
						
							| 
									
										
										
										
											2017-04-10 17:47:38 -04:00
										 |  |  | 
 | 
					
						
							|  |  |  | * Processing of the queue_step commands on the micro-controller starts | 
					
						
							| 
									
										
										
										
											2018-04-30 11:22:16 -04:00
										 |  |  |   in src/command.c which parses the command and calls | 
					
						
							|  |  |  |   `command_queue_step()`. The command_queue_step() code (in | 
					
						
							|  |  |  |   src/stepper.c) just appends the parameters of each queue_step | 
					
						
							|  |  |  |   command to a per stepper queue. Under normal operation the | 
					
						
							|  |  |  |   queue_step command is parsed and queued at least 100ms before the | 
					
						
							|  |  |  |   time of its first step. Finally, the generation of stepper events is | 
					
						
							|  |  |  |   done in `stepper_event()`. It's called from the hardware timer | 
					
						
							|  |  |  |   interrupt at the scheduled time of the first step. The | 
					
						
							|  |  |  |   stepper_event() code generates a step pulse and then reschedules | 
					
						
							|  |  |  |   itself to run at the time of the next step pulse for the given | 
					
						
							|  |  |  |   queue_step parameters. The parameters for each queue_step command | 
					
						
							|  |  |  |   are "interval", "count", and "add". At a high-level, stepper_event() | 
					
						
							|  |  |  |   runs the following, 'count' times: `do_step(); next_wake_time = | 
					
						
							|  |  |  |   last_wake_time + interval; interval += add;` | 
					
						
							| 
									
										
										
										
											2017-04-10 17:47:38 -04:00
										 |  |  | 
 | 
					
						
							|  |  |  | The above may seem like a lot of complexity to execute a | 
					
						
							|  |  |  | movement. However, the only really interesting parts are in the | 
					
						
							|  |  |  | ToolHead and kinematic classes. It's this part of the code which | 
					
						
							|  |  |  | specifies the movements and their timings. The remaining parts of the | 
					
						
							|  |  |  | processing is mostly just communication and plumbing. | 
					
						
							| 
									
										
										
										
											2017-09-27 15:04:48 -04:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2018-03-28 13:01:24 -04:00
										 |  |  | Adding a host module | 
					
						
							|  |  |  | ==================== | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | The Klippy host code has a dynamic module loading capability. If a | 
					
						
							|  |  |  | config section named "[my_module]" is found in the printer config file | 
					
						
							|  |  |  | then the software will automatically attempt to load the python module | 
					
						
							|  |  |  | klippy/extras/my_module.py . This module system is the preferred | 
					
						
							|  |  |  | method for adding new functionality to Klipper. | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | The easiest way to add a new module is to use an existing module as a | 
					
						
							|  |  |  | reference - see **klippy/extras/servo.py** as an example. | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | The following may also be useful: | 
					
						
							|  |  |  | * Execution of the module starts in the module level `load_config()` | 
					
						
							|  |  |  |   function (for config sections of the form [my_module]) or in | 
					
						
							|  |  |  |   `load_config_prefix()` (for config sections of the form | 
					
						
							|  |  |  |   [my_module my_name]). This function is passed a "config" object and | 
					
						
							|  |  |  |   it must return a new "printer object" associated with the given | 
					
						
							|  |  |  |   config section. | 
					
						
							|  |  |  | * During the process of instantiating a new printer object, the config | 
					
						
							|  |  |  |   object can be used to read parameters from the given config | 
					
						
							|  |  |  |   section. This is done using `config.get()`, `config.getfloat()`, | 
					
						
							|  |  |  |   `config.getint()`, etc. methods. Be sure to read all values from the | 
					
						
							|  |  |  |   config during the construction of the printer object - if the user | 
					
						
							|  |  |  |   specifies a config parameter that is not read during this phase then | 
					
						
							|  |  |  |   it will be assumed it is a typo in the config and an error will be | 
					
						
							|  |  |  |   raised. | 
					
						
							|  |  |  | * Use the `config.get_printer()` method to obtain a reference to the | 
					
						
							|  |  |  |   main "printer" class. This "printer" class stores references to all | 
					
						
							|  |  |  |   the "printer objects" that have been instantiated. Use the | 
					
						
							|  |  |  |   `printer.lookup_object()` method to find references to other printer | 
					
						
							|  |  |  |   objects. Almost all functionality (even core kinematic modules) are | 
					
						
							|  |  |  |   encapsulated in one of these printer objects. Note, though, that | 
					
						
							|  |  |  |   when a new module is instantiated, not all other printer objects | 
					
						
							|  |  |  |   will have been instantiated. The "gcode" and "pins" modules will | 
					
						
							|  |  |  |   always be available, but for other modules it is a good idea to | 
					
						
							|  |  |  |   defer the lookup. | 
					
						
							| 
									
										
										
										
											2019-01-08 11:34:09 -05:00
										 |  |  | * Register event handlers using the `printer.register_event_handler()` | 
					
						
							|  |  |  |   method if the code needs to be called during "events" raised by | 
					
						
							|  |  |  |   other printer objects. Each event name is a string, and by | 
					
						
							|  |  |  |   convention it is the name of the main source module that raises the | 
					
						
							|  |  |  |   event along with a short name for the action that is occurring (eg, | 
					
						
							|  |  |  |   "klippy:connect"). The parameters passed to each event handler are | 
					
						
							|  |  |  |   specific to the given event (as are exception handling and execution | 
					
						
							|  |  |  |   context). Two common startup events are: | 
					
						
							|  |  |  |   * klippy:connect - This event is generated after all printer objects | 
					
						
							|  |  |  |     are instantiated. It is commonly used to lookup other printer | 
					
						
							|  |  |  |     objects, to verify config settings, and to perform an initial | 
					
						
							|  |  |  |     "handshake" with printer hardware. | 
					
						
							|  |  |  |   * klippy:ready - This event is generated after all connect handlers | 
					
						
							|  |  |  |     have completed successfully. It indicates the printer is | 
					
						
							|  |  |  |     transitioning to a state ready to handle normal operations. Do not | 
					
						
							|  |  |  |     raise an error in this callback. | 
					
						
							| 
									
										
										
										
											2018-03-28 13:01:24 -04:00
										 |  |  | * If there is an error in the user's config, be sure to raise it | 
					
						
							| 
									
										
										
										
											2019-01-08 11:34:09 -05:00
										 |  |  |   during the `load_config()` or "connect event" phases. Use either | 
					
						
							|  |  |  |   `raise config.error("my error")` or `raise printer.config_error("my | 
					
						
							|  |  |  |   error")` to report the error. | 
					
						
							| 
									
										
										
										
											2018-03-28 13:01:24 -04:00
										 |  |  | * Use the "pins" module to configure a pin on a micro-controller. This | 
					
						
							|  |  |  |   is typically done with something similar to | 
					
						
							|  |  |  |   `printer.lookup_object("pins").setup_pin("pwm", | 
					
						
							|  |  |  |   config.get("my_pin"))`. The returned object can then be commanded at | 
					
						
							|  |  |  |   run-time. | 
					
						
							|  |  |  | * If the module needs access to system timing or external file | 
					
						
							|  |  |  |   descriptors then use `printer.get_reactor()` to obtain access to the | 
					
						
							|  |  |  |   global "event reactor" class. This reactor class allows one to | 
					
						
							|  |  |  |   schedule timers, wait for input on file descriptors, and to "sleep" | 
					
						
							|  |  |  |   the host code. | 
					
						
							|  |  |  | * Do not use global variables. All state should be stored in the | 
					
						
							|  |  |  |   printer object returned from the `load_config()` function. This is | 
					
						
							|  |  |  |   important as otherwise the RESTART command may not perform as | 
					
						
							|  |  |  |   expected. Also, for similar reasons, if any external files (or | 
					
						
							| 
									
										
										
										
											2019-01-08 11:34:09 -05:00
										 |  |  |   sockets) are opened then be sure to register a "klippy:disconnect" | 
					
						
							|  |  |  |   event handler and close them from that callback. | 
					
						
							| 
									
										
										
										
											2018-03-28 13:01:24 -04:00
										 |  |  | * Avoid accessing the internal member variables (or calling methods | 
					
						
							|  |  |  |   that start with an underscore) of other printer objects. Observing | 
					
						
							|  |  |  |   this convention makes it easier to manage future changes. | 
					
						
							|  |  |  | * If submitting the module for inclusion in the main Klipper code, be | 
					
						
							|  |  |  |   sure to place a copyright notice at the top of the module. See the | 
					
						
							|  |  |  |   existing modules for the preferred format. | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2018-02-17 13:39:37 -05:00
										 |  |  | Adding new kinematics | 
					
						
							|  |  |  | ===================== | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | This section provides some tips on adding support to Klipper for | 
					
						
							|  |  |  | additional types of printer kinematics. This type of activity requires | 
					
						
							|  |  |  | excellent understanding of the math formulas for the target | 
					
						
							|  |  |  | kinematics. It also requires software development skills - though one | 
					
						
							| 
									
										
										
										
											2018-06-19 00:50:59 -04:00
										 |  |  | should only need to update the host software. | 
					
						
							| 
									
										
										
										
											2018-02-17 13:39:37 -05:00
										 |  |  | 
 | 
					
						
							|  |  |  | Useful steps: | 
					
						
							| 
									
										
										
										
											2018-04-23 18:23:39 -04:00
										 |  |  | 1. Start by studying the | 
					
						
							|  |  |  |    "[code flow of a move](#code-flow-of-a-move-command)" section and | 
					
						
							|  |  |  |    the [Kinematics document](Kinematics.md). | 
					
						
							| 
									
										
										
										
											2018-11-17 14:56:15 -05:00
										 |  |  | 2. Review the existing kinematic classes in the klippy/kinematics/ | 
					
						
							|  |  |  |    directory. The kinematic classes are tasked with converting a move | 
					
						
							|  |  |  |    in cartesian coordinates to the movement on each stepper. One | 
					
						
							| 
									
										
										
										
											2018-02-17 13:39:37 -05:00
										 |  |  |    should be able to copy one of these files as a starting point. | 
					
						
							| 
									
										
										
										
											2018-06-19 00:50:59 -04:00
										 |  |  | 3. Implement the C stepper kinematic position functions for each | 
					
						
							|  |  |  |    stepper if they are not already available (see kin_cart.c, | 
					
						
							|  |  |  |    kin_corexy.c, and kin_delta.c in klippy/chelper/). The function | 
					
						
							|  |  |  |    should call `move_get_coord()` to convert a given move time (in | 
					
						
							|  |  |  |    seconds) to a cartesian coordinate (in millimeters), and then | 
					
						
							|  |  |  |    calculate the desired stepper position (in millimeters) from that | 
					
						
							|  |  |  |    cartesian coordinate. | 
					
						
							| 
									
										
										
										
											2018-06-22 13:03:07 -04:00
										 |  |  | 4. Implement the `calc_position()` method in the new kinematics class. | 
					
						
							| 
									
										
										
										
											2018-07-03 13:33:48 -04:00
										 |  |  |    This method calculates the position of the toolhead in cartesian | 
					
						
							|  |  |  |    coordinates from the current position of each stepper. It does not | 
					
						
							|  |  |  |    need to be efficient as it is typically only called during homing | 
					
						
							|  |  |  |    and probing operations. | 
					
						
							| 
									
										
										
										
											2019-11-07 10:39:17 -05:00
										 |  |  | 5. Other methods. Implement the `check_move()`, `home()`, | 
					
						
							| 
									
										
										
										
											2019-11-12 11:41:41 -05:00
										 |  |  |    `set_position()`, and `get_steppers()` methods. These functions are | 
					
						
							|  |  |  |    typically used to provide kinematic specific checks. However, at | 
					
						
							|  |  |  |    the start of development one can use boiler-plate code here. | 
					
						
							| 
									
										
										
										
											2018-06-22 13:03:07 -04:00
										 |  |  | 6. Implement test cases. Create a g-code file with a series of moves | 
					
						
							| 
									
										
										
										
											2018-02-17 13:39:37 -05:00
										 |  |  |    that can test important cases for the given kinematics. Follow the | 
					
						
							|  |  |  |    [debugging documentation](Debugging.md) to convert this g-code file | 
					
						
							|  |  |  |    to micro-controller commands. This is useful to exercise corner | 
					
						
							|  |  |  |    cases and to check for regressions. | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2018-07-11 14:35:28 -04:00
										 |  |  | Porting to a new micro-controller | 
					
						
							|  |  |  | ================================= | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | This section provides some tips on porting Klipper's micro-controller | 
					
						
							|  |  |  | code to a new architecture. This type of activity requires good | 
					
						
							|  |  |  | knowledge of embedded development and hands-on access to the target | 
					
						
							|  |  |  | micro-controller. | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | Useful steps: | 
					
						
							|  |  |  | 1. Start by identifying any 3rd party libraries that will be used | 
					
						
							|  |  |  |    during the port. Common examples include "CMSIS" wrappers and | 
					
						
							|  |  |  |    manufacturer "HAL" libraries. All 3rd party code needs to be GNU | 
					
						
							|  |  |  |    GPLv3 compatible. The 3rd party code should be committed to the | 
					
						
							|  |  |  |    Klipper lib/ directory. Update the lib/README file with information | 
					
						
							|  |  |  |    on where and when the library was obtained. It is preferable to | 
					
						
							|  |  |  |    copy the code into the Klipper repository unchanged, but if any | 
					
						
							|  |  |  |    changes are required then those changes should be listed explicitly | 
					
						
							|  |  |  |    in the lib/README file. | 
					
						
							|  |  |  | 2. Create a new architecture sub-directory in the src/ directory and | 
					
						
							|  |  |  |    add initial Kconfig and Makefile support. Use the existing | 
					
						
							|  |  |  |    architectures as a guide. The src/simulator provides a basic | 
					
						
							|  |  |  |    example of a minimum starting point. | 
					
						
							|  |  |  | 3. The first main coding task is to bring up communication support to | 
					
						
							|  |  |  |    the target board. This is the most difficult step in a new port. | 
					
						
							|  |  |  |    Once basic communication is working, the remaining steps tend to be | 
					
						
							|  |  |  |    much easier. It is typical to use an RS-232 style serial port | 
					
						
							|  |  |  |    during initial development as these types of hardware devices are | 
					
						
							|  |  |  |    generally easier to enable and control. During this phase, make | 
					
						
							|  |  |  |    liberal use of helper code from the src/generic/ directory (check | 
					
						
							|  |  |  |    how src/simulator/Makefile includes the generic C code into the | 
					
						
							|  |  |  |    build). It is also necessary to define timer_read_time() (which | 
					
						
							|  |  |  |    returns the current system clock) in this phase, but it is not | 
					
						
							|  |  |  |    necessary to fully support timer irq handling. | 
					
						
							|  |  |  | 4. Get familiar with the the console.py tool (as described in the | 
					
						
							|  |  |  |    [debugging document](Debugging.md)) and verify connectivity to the | 
					
						
							|  |  |  |    micro-controller with it. This tool translates the low-level | 
					
						
							|  |  |  |    micro-controller communication protocol to a human readable form. | 
					
						
							|  |  |  | 5. Add support for timer dispatch from hardware interrupts. See | 
					
						
							|  |  |  |    Klipper | 
					
						
							|  |  |  |    [commit 970831ee](https://github.com/KevinOConnor/klipper/commit/970831ee0d3b91897196e92270d98b2a3067427f) | 
					
						
							|  |  |  |    as an example of steps 1-5 done for the LPC176x architecture. | 
					
						
							|  |  |  | 6. Bring up basic GPIO input and output support. See Klipper | 
					
						
							|  |  |  |    [commit c78b9076](https://github.com/KevinOConnor/klipper/commit/c78b90767f19c9e8510c3155b89fb7ad64ca3c54) | 
					
						
							|  |  |  |    as an example of this. | 
					
						
							|  |  |  | 7. Bring up additional peripherals - for example see Klipper commit | 
					
						
							|  |  |  |    [65613aed](https://github.com/KevinOConnor/klipper/commit/65613aeddfb9ef86905cb1dade9e773a02ef3c27), | 
					
						
							|  |  |  |    [c812a40a](https://github.com/KevinOConnor/klipper/commit/c812a40a3782415e454b04bf7bd2158a6f0ec8b5), | 
					
						
							|  |  |  |    and | 
					
						
							|  |  |  |    [c381d03a](https://github.com/KevinOConnor/klipper/commit/c381d03aad5c3ee761169b7c7bced519cc14da29). | 
					
						
							|  |  |  | 8. Create a sample Klipper config file in the config/ directory. Test | 
					
						
							|  |  |  |    the micro-controller with the main klippy.py program. | 
					
						
							|  |  |  | 9. Consider adding build test cases in the test/ directory. | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2017-09-27 15:04:48 -04:00
										 |  |  | Time | 
					
						
							|  |  |  | ==== | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | Fundamental to the operation of Klipper is the handling of clocks, | 
					
						
							|  |  |  | times, and timestamps. Klipper executes actions on the printer by | 
					
						
							|  |  |  | scheduling events to occur in the near future. For example, to turn on | 
					
						
							|  |  |  | a fan, the code might schedule a change to a GPIO pin in a 100ms. It | 
					
						
							|  |  |  | is rare for the code to attempt to take an instantaneous action. Thus, | 
					
						
							|  |  |  | the handling of time within Klipper is critical to correct operation. | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | There are three types of times tracked internally in the Klipper host | 
					
						
							|  |  |  | software: | 
					
						
							|  |  |  | * System time. The system time uses the system's monotonic clock - it | 
					
						
							|  |  |  |   is a floating point number stored as seconds and it is (generally) | 
					
						
							|  |  |  |   relative to when the host computer was last started. System times | 
					
						
							|  |  |  |   have limited use in the software - they are primarily used when | 
					
						
							|  |  |  |   interacting with the operating system. Within the host code, system | 
					
						
							|  |  |  |   times are frequently stored in variables named *eventtime* or | 
					
						
							|  |  |  |   *curtime*. | 
					
						
							|  |  |  | * Print time. The print time is synchronized to the main | 
					
						
							|  |  |  |   micro-controller clock (the micro-controller defined in the "[mcu]" | 
					
						
							|  |  |  |   config section). It is a floating point number stored as seconds and | 
					
						
							|  |  |  |   is relative to when the main mcu was last restarted. It is possible | 
					
						
							|  |  |  |   to convert from a "print time" to the main micro-controller's | 
					
						
							|  |  |  |   hardware clock by multiplying the print time by the mcu's statically | 
					
						
							|  |  |  |   configured frequency rate. The high-level host code uses print times | 
					
						
							| 
									
										
										
										
											2019-08-09 00:13:34 -04:00
										 |  |  |   to calculate almost all physical actions (eg, head movement, heater | 
					
						
							| 
									
										
										
										
											2017-09-27 15:04:48 -04:00
										 |  |  |   changes, etc.). Within the host code, print times are generally | 
					
						
							|  |  |  |   stored in variables named *print_time* or *move_time*. | 
					
						
							|  |  |  | * MCU clock. This is the hardware clock counter on each | 
					
						
							|  |  |  |   micro-controller. It is stored as an integer and its update rate is | 
					
						
							|  |  |  |   relative to the frequency of the given micro-controller. The host | 
					
						
							|  |  |  |   software translates its internal times to clocks before transmission | 
					
						
							|  |  |  |   to the mcu. The mcu code only ever tracks time in clock | 
					
						
							|  |  |  |   ticks. Within the host code, clock values are tracked as 64bit | 
					
						
							|  |  |  |   integers, while the mcu code uses 32bit integers. Within the host | 
					
						
							|  |  |  |   code, clocks are generally stored in variables with names containing | 
					
						
							|  |  |  |   *clock* or *ticks*. | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | Conversion between the different time formats is primarily implemented | 
					
						
							|  |  |  | in the **klippy/clocksync.py** code. | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | Some things to be aware of when reviewing the code: | 
					
						
							|  |  |  | * 32bit and 64bit clocks: To reduce bandwidth and to improve | 
					
						
							|  |  |  |   micro-controller efficiency, clocks on the micro-controller are | 
					
						
							|  |  |  |   tracked as 32bit integers. When comparing two clocks in the mcu | 
					
						
							|  |  |  |   code, the `timer_is_before()` function must always be used to ensure | 
					
						
							|  |  |  |   integer rollovers are handled properly. The host software converts | 
					
						
							|  |  |  |   32bit clocks to 64bit clocks by appending the high-order bits from | 
					
						
							|  |  |  |   the last mcu timestamp it has received - no message from the mcu is | 
					
						
							|  |  |  |   ever more than 2^31 clock ticks in the future or past so this | 
					
						
							|  |  |  |   conversion is never ambiguous. The host converts from 64bit clocks | 
					
						
							|  |  |  |   to 32bit clocks by simply truncating the high-order bits. To ensure | 
					
						
							|  |  |  |   there is no ambiguity in this conversion, the | 
					
						
							| 
									
										
										
										
											2018-04-30 11:22:16 -04:00
										 |  |  |   **klippy/chelper/serialqueue.c** code will buffer messages until | 
					
						
							|  |  |  |   they are within 2^31 clock ticks of their target time. | 
					
						
							| 
									
										
										
										
											2017-09-27 15:04:48 -04:00
										 |  |  | * Multiple micro-controllers: The host software supports using | 
					
						
							|  |  |  |   multiple micro-controllers on a single printer. In this case, the | 
					
						
							|  |  |  |   "MCU clock" of each micro-controller is tracked separately. The | 
					
						
							|  |  |  |   clocksync.py code handles clock drift between micro-controllers by | 
					
						
							|  |  |  |   modifying the way it converts from "print time" to "MCU clock". On | 
					
						
							|  |  |  |   secondary mcus, the mcu frequency that is used in this conversion is | 
					
						
							|  |  |  |   regularly updated to account for measured drift. |