# Chapter 8: A Tiny Interpreter ## Sample code - Directory: `docs/os-on-arduino/code/08_interpreter` ```bash uv run pio run -d 08_interpreter -t upload uv run pio device monitor -b 115200 ``` ## Source code The sketch for this chapter. Click a file name to expand. The code is mirrored automatically from the manuscript repository, so what you see here is always current. :::{dropdown} `src/main.cpp` — 53 lines :icon: code [Open on GitHub](https://github.com/iory/learning-os-from-arduino/blob/main/docs/os-on-arduino/code/08_interpreter/src/main.cpp) ```{literalinclude} ../../../../code/08_interpreter/src/main.cpp :language: cpp :linenos: ``` ::: :::{dropdown} `include/interpreter.h` — 36 lines :icon: code [Open on GitHub](https://github.com/iory/learning-os-from-arduino/blob/main/docs/os-on-arduino/code/08_interpreter/include/interpreter.h) ```{literalinclude} ../../../../code/08_interpreter/include/interpreter.h :language: cpp :linenos: ``` ::: :::{dropdown} `include/os_display.h` — 18 lines :icon: code [Open on GitHub](https://github.com/iory/learning-os-from-arduino/blob/main/docs/os-on-arduino/code/08_interpreter/include/os_display.h) ```{literalinclude} ../../../../code/08_interpreter/include/os_display.h :language: cpp :linenos: ``` ::: :::{dropdown} `include/os_fault.h` — 46 lines :icon: code [Open on GitHub](https://github.com/iory/learning-os-from-arduino/blob/main/docs/os-on-arduino/code/08_interpreter/include/os_fault.h) ```{literalinclude} ../../../../code/08_interpreter/include/os_fault.h :language: cpp :linenos: ``` ::: :::{dropdown} `include/os_kernel.h` — 75 lines :icon: code [Open on GitHub](https://github.com/iory/learning-os-from-arduino/blob/main/docs/os-on-arduino/code/08_interpreter/include/os_kernel.h) ```{literalinclude} ../../../../code/08_interpreter/include/os_kernel.h :language: cpp :linenos: ``` ::: :::{dropdown} `include/servo_pwm.h` — 61 lines :icon: code [Open on GitHub](https://github.com/iory/learning-os-from-arduino/blob/main/docs/os-on-arduino/code/08_interpreter/include/servo_pwm.h) ```{literalinclude} ../../../../code/08_interpreter/include/servo_pwm.h :language: cpp :linenos: ``` ::: :::{dropdown} `include/shell.h` — 23 lines :icon: code [Open on GitHub](https://github.com/iory/learning-os-from-arduino/blob/main/docs/os-on-arduino/code/08_interpreter/include/shell.h) ```{literalinclude} ../../../../code/08_interpreter/include/shell.h :language: cpp :linenos: ``` ::: :::{dropdown} `src/interpreter.cpp` — 288 lines :icon: code [Open on GitHub](https://github.com/iory/learning-os-from-arduino/blob/main/docs/os-on-arduino/code/08_interpreter/src/interpreter.cpp) ```{literalinclude} ../../../../code/08_interpreter/src/interpreter.cpp :language: cpp :linenos: ``` ::: :::{dropdown} `src/os_display.cpp` — 162 lines :icon: code [Open on GitHub](https://github.com/iory/learning-os-from-arduino/blob/main/docs/os-on-arduino/code/08_interpreter/src/os_display.cpp) ```{literalinclude} ../../../../code/08_interpreter/src/os_display.cpp :language: cpp :linenos: ``` ::: :::{dropdown} `src/os_fault.cpp` — 170 lines :icon: code [Open on GitHub](https://github.com/iory/learning-os-from-arduino/blob/main/docs/os-on-arduino/code/08_interpreter/src/os_fault.cpp) ```{literalinclude} ../../../../code/08_interpreter/src/os_fault.cpp :language: cpp :linenos: ``` ::: :::{dropdown} `src/os_kernel.cpp` — 241 lines :icon: code [Open on GitHub](https://github.com/iory/learning-os-from-arduino/blob/main/docs/os-on-arduino/code/08_interpreter/src/os_kernel.cpp) ```{literalinclude} ../../../../code/08_interpreter/src/os_kernel.cpp :language: cpp :linenos: ``` ::: :::{dropdown} `src/shell.cpp` — 237 lines :icon: code [Open on GitHub](https://github.com/iory/learning-os-from-arduino/blob/main/docs/os-on-arduino/code/08_interpreter/src/shell.cpp) ```{literalinclude} ../../../../code/08_interpreter/src/shell.cpp :language: cpp :linenos: ``` ::: ## On the board ```{figure} ../_static/ch08_interpreter.gif :name: fig-ch08-interpreter :width: 100% Typing commands into the interpreter: `PRINT` reaches `[Print]` and `FORWARD` reaches `[Motor]`. ``` ## In the simulator Without the board, the same firmware running in the {doc}`simulator <../getting-started/simulator>` looks like this. ```{figure} ../_static/sim_ch08_led.gif :name: fig-ch08-sim :width: 80% The `LED` task keeps inverting L every 500 ms, so it is stopped with `kill 1` first; then the interpreter runs `run LED 13 1` (on) and `run LED 13 0` (off). Without stopping the `LED` task, its next inversion would overwrite the command. (Recorded in the simulator.) ``` ## Improved version: `08_interpreter_v2` (not in the book) Chapter 8 uses the same LED matrix display as chapter 7, and it is just as hard to read (see the improved version in {doc}`ch07`). [`code/08_interpreter_v2`](https://github.com/iory/build-your-own-arduino-rtos/tree/main/code/08_interpreter_v2) adds the display and the shell `top` command of chapter 7's [`07_led_matrix_v2`](https://github.com/iory/build-your-own-arduino-rtos/tree/main/code/07_led_matrix_v2). The interpreter and the kernel are the same as the book's. It is not in the book's repository, so get it from this site's repository and flash it (if you already cloned it for chapter 7's improved version, only the upload line is needed, in `build-your-own-arduino-rtos/code`): ```bash git clone https://github.com/iory/build-your-own-arduino-rtos.git cd build-your-own-arduino-rtos/code uv sync uv run pio run -d 08_interpreter_v2 -t upload uv run pio device monitor -b 115200 ``` | Rows | Content (12 dots = 100%, updated every 0.5 s) | |---|---| | 0–1 | Total CPU load (everything except idle) | | 2 | Blank | | 3–7 | CPU% of LED / Shell / Display / Light / Heavy | Chapter 8's own tasks (LED, Shell, Display) barely use the CPU: the LED task and the interpreter's `FORWARD` / `TURN` / `DELAY` all wait with `os_sleep()`, which hands the CPU to other tasks. To make the bars move, v2 adds chapter 7's Light (uses 20 ms of CPU, then sleeps 60 ms) and Heavy (computes without sleeping) after the book's three tasks. LED, Shell and Display keep their task numbers, so `kill 1` → `run LED 13 1` works as in the book. ```{raw} html ``` Values read from `top` on a real UNO R4 WiFi: | Action | Total CPU | What you see | |---|---|---| | After boot | ~60% | Bars on Light (16%) and Heavy (40%) | | `kill 5` | ~24% | Heavy's bar disappears and the total shrinks | | `kill 4` | ~4% | Only Shell, drawing `top`, is left | | `exec 4` / `exec 5` | Back to normal | | ```{note} While a script runs with `run`, the `top` screen stops updating: it is redrawn while the shell waits for input, so it resumes when the script ends. The matrix keeps updating because the display task draws it. ``` ## Pitfalls (Collected from reader questions — ask via [GitHub Issues](https://github.com/iory/build-your-own-arduino-rtos/issues).)