Graphing Scientific Calculator Based on the ESP32
Summary
NumOS is an open-source operating system for graphing scientific calculators based on the ESP32-S3 microcontroller, featuring a Giac-backed CAS engine and LVGL 9.x interface.
View Cached Full Text
Cached at: 05/18/26, 12:55 PM
El-EnderJ/NeoCalculator
Source: https://github.com/El-EnderJ/NeoCalculator
π’ NumOS
Open-Source Scientific Graphing Calculator OS
ESP32-S3 N16R8 Β· ILI9341 IPS 320Γ240 Β· LVGL 9.x Β· CAS Engine Β· Natural Display V.P.A.M.
Technical Status: Major Architectural Refactor
We are currently migrating the core math engine to Giac and implementing STIX Two Math for LaTeX-quality rendering. If you are compiling frommain, you might experience UI glitches. For a stable experience, please check the Releases section.
Table of Contents
- Webpage
- What is NumOS?
- Key Features
- System Architecture
- CAS Engine
- Hardware
- Quick Start
- User Manual β EquationsApp
- Project Structure
- Build Stats
- Critical Hardware Fixes
- Project Status
- Technology Stack
- Comparison with Commercial Calculators
- Documentation
- Contributing
What is NumOS?
NumOS is an open-source scientific and graphing calculator operating system built on the ESP32-S3 N16R8 microcontroller (16 MB Flash QIO + 8 MB PSRAM OPI). The project aims to become the best open-source calculator in the world, rivalling the Casio fx-991EX ClassWiz, the NumWorks, the TI-84 Plus CE, and the HP Prime G2.
NumOS delivers:
- Giac-backed CAS Engine β Symbolic math now runs through Giac C++ via
src/math/giac/GiacBridge.cpp(The Big Switch). Legacy CAS-S3 modules remain documented as historical milestones and optional local tooling. - Natural Display V.P.A.M. β Formulae rendered as they appear on paper: real stacked fractions, radical symbols (β), genuine superscripts, 2D navigation with a structural smart cursor.
- Modern LVGL 9.x Interface β Smooth transitions, animated splash screen, NumWorks-style launcher.
Recent launcher refactor: the launcher now uses LVGL Flex
ROW_WRAP(dynamic rows) with fixed card sizing instead of a static grid descriptor. Seedocs/UI_CHANGES.mdfor developer migration notes anddocs/fluid2d_plan.mdfor an example app (Fluid2D) integrated into the new APPS[] schema. - Custom Numeric Math Engine β Complete pipeline: Tokenizer β Shunting-Yard Parser β RPN Evaluator + Visual AST, implemented from scratch in C++17.
- Modular App Architecture β Each application is a self-contained module with explicit lifecycle (
begin/end/load/handleKey), orchestrated bySystemApp.
Key Features
| Feature | Description |
|---|---|
| Giac CAS Backend | Symbolic evaluation through GiacBridge with UART parser/eval flow validated on hardware. Migration milestones completed: -DDOUBLEVAL, 64 KB loop stack, real-style complex_mode(false) with preserved i^2=-1 behavior |
| Unified Calculus App | Symbolic d/dx differentiation (17 rules) and numerical/symbolic \int dx integration (Slagle heuristic: table lookup, linearity, u-substitution, integration by parts/LIATE), tab-based mode switching, automatic simplification, and detailed step-by-step output |
| EquationsApp | Solves linear, quadratic, and 2Γ2 systems (linear + non-linear via Sylvester resultant) with full step-by-step display |
| Bridge Designer | Real-time structural bridge simulator with Verlet integration physics, stress analysis (greenβred beam visualisation), snap-to-grid editor, wood/steel/cable materials, and truck/car load testing β PSRAM-backed, 60 Hz fixed timestep |
| Particle Lab | Powder-Toy-class sandbox: 30+ materials (Sand, Water, Lava, LN2, Wire, Iron, Titan, C4, Clone), spark electronics with Joule heating, phase transitions, reaction matrix (Water+Lava=Stone+Steam), Bresenham line tool, material palette overlay, LittleFS save/load |
| Settings App | System-wide toggles for complex number output (ON/OFF), decimal precision selector (6/8/10/12 digits), and angle-mode display |
| Natural Display | Real fractions, radicals, exponents, 2D cursors β mathematical rendering as it appears on paper |
| Graphing: y=f(x) | Real-time function plotter with zoom, pan, and value table |
| 85+ CAS Unit Tests | Comprehensive test suite for the CAS, enable/disable via compile-time flag |
| PSRAMAllocator | CAS uses PSRAMAllocator<T> to isolate memory usage in the 8 MB PSRAM OPI |
| Variables AβZ + Ans | Persistent storage via LittleFS β 216 bytes in /vars.dat |
| SerialBridge | Full calculator control from PC via Serial Monitor without physical hardware |
| SerialBridge Debug | Immediate byte echo, 5-second heartbeat, 8-event circular buffer |
Photo gallery
Neural Network Simulator:
Fluid 2D Simulator:
Periodic Table (Chemistry App):
Grapher App:
Steps (Equations App) (WIP, still in development, Alpha):
Calculus App:
Probability (Gaussian Distribution):
Python App:
Bridge Designer:
Circuit Simulator (Circuit Core, Alpha):
Particle Lab (Powder Toy like):
Optics Lab:
System Architecture
flowchart TB
subgraph esp[ESP32-S3 N16R8]
main["main.cpp: setup() β PSRAM, TFT, LVGL, Splash, SystemApp; loop(): lv_timer_handler(), app.update(), serial.poll()"]
system["SystemApp (Dispatcher)"]
main --> system
end
subgraph apps[Applications]
mm["MainMenu (LVGL)"]
calc["CalculationApp (Natural VPAM, History)"]
grapher["GrapherApp (y=f(x), Zoom & Pan)"]
eq["EquationsApp (CAS)"]
calculus["CalculusApp (d/dx, β«dx)"]
settings["SettingsApp"]
end
system --> mm
system --> calc
system --> grapher
system --> eq
system --> calculus
system --> settings
math["Math Engine: Tokenizer Β· Parser Β· Evaluator Β· ExprNode Β· VariableContext Β· EquationSolver"]
procas["CAS Engine: CASInt Β· CASRational Β· SymExpr DAG Β· SymSimplify Β· SymDiff Β· SymIntegrate"]
system --> math
math --> procas
display["Display Layer: DisplayDriver Β· LVGL flush DMA Β· ILI9341 @ 10 MHz"]
input["Input Layer: KeyMatrix 5x10 Β· SerialBridge Β· LvglKeypad Β· LittleFS"]
system --> display
system --> input
display -->|SPI @ 10 MHz| ili["ILI9341 IPS 3.2 in β 320x240 Β· 16 bpp"]
ili -.-> esp
CAS Engine
The CAS (Computer Algebra System) now uses Giac C++ as the canonical symbolic backend. The migration is routed through src/math/giac/GiacBridge.cpp and consumed by the UART command path in src/input/SerialBridge.cpp.
Legacy CAS-S3 internals documented below remain as historical milestones and optional local components, but symbolic truth for current backend flows comes from Giac.
Giac Migration Milestones
- Big Switch complete: custom symbolic backend replaced by Giac as canonical CAS.
- Embedded numeric stabilization complete with
-DDOUBLEVAL. - Stack stabilization complete with
-DARDUINO_LOOP_STACK_SIZE=65536. - Real-style defaults complete:
complex_mode(false)and preserved imaginary unit behavior (i^2 = -1). - UART command path certified on hardware for
sum,int,solve, andsimplify.
CAS Pipeline (Derivatives)
flowchart TB
user["User input (CalculusApp): x^3 + sin(x)"]
user --> me["Math Engine: Parser + Tokenizer"]
me --> af["ASTFlattener: MathAST β SymExpr DAG"]
af --> sd["SymDiff β d/dx: 3x^2 + cos(x)"]
sd --> ss["SymSimplify (8-pass fixed-point)"]
ss --> sea["SymExprToAST: SymExpr β MathAST (Natural Display)"]
sea --> canvas["MathCanvas renders: 3x^2 + cos(x)"]
CAS Pipeline (Integrals)
flowchart TB
userInt["User input (CalculusApp, β«dx mode): x Β· cos(x)"]
userInt --> af2["ASTFlattener β SymExpr DAG"]
af2 --> sint["SymIntegrate (Slagle): table β linearity β u-sub β parts (LIATE)"]
sint --> ss2["SymSimplify"]
ss2 --> conv["SymExprToAST::convertIntegral()"]
conv --> canvas2["MathCanvas renders: xΒ·sin(x) + cos(x) + C"]
CAS Components
| Module | File | Responsibility |
|---|---|---|
CASInt | cas/CASInt.h | Hybrid BigInt: int64_t fast-path + mbedtls_mpi on overflow |
CASRational | cas/CASRational.h/.cpp | Overflow-safe exact fraction (num/den with auto-GCD) |
PSRAMAllocator<T> | cas/PSRAMAllocator.h | STL allocator β ps_malloc/ps_free for PSRAM |
SymExpr DAG | cas/SymExpr.h/.cpp | Immutable symbolic tree with hash (_hash) and weight (_weight) |
ConsTable | cas/ConsTable.h | PSRAM hash-consing table: deduplication of identical nodes |
SymExprArena | cas/SymExprArena.h | PSRAM bump allocator (16 blocks Γ 64 KB) + integrated ConsTable |
ASTFlattener | cas/ASTFlattener.h/.cpp | MathAST (VPAM) β SymExpr DAG with hash-consing |
SymDiff | cas/SymDiff.h/.cpp | Symbolic differentiation: 17 rules (chain, product, quotient, trig, exp, log) |
SymIntegrate | cas/SymIntegrate.h/.cpp | Slagle integration: table, linearity, u-substitution, parts (LIATE) |
SymSimplify | cas/SymSimplify.h/.cpp | Multi-pass simplifier (8 iterations, fixed-point, trig/log/exp) |
SymPoly | cas/SymPoly.h/.cpp | Univariable symbolic polynomial with CASRational coefficients |
SymPolyMulti | cas/SymPolyMulti.h/.cpp | Multivariable polynomial + Sylvester resultant |
SingleSolver | cas/SingleSolver.h/.cpp | Single-variable equation: linear / quadratic / Newton-Raphson |
SystemSolver | cas/SystemSolver.h/.cpp | 2Γ2 system: Gaussian elimination + non-linear (resultant) |
OmniSolver | cas/OmniSolver.h/.cpp | Analytic variable isolation: inverses, roots, trig |
HybridNewton | cas/HybridNewton.h/.cpp | Newton-Raphson with symbolic Jacobian and 16-seed multi-start |
CASStepLogger | cas/CASStepLogger.h/.cpp | StepVec in PSRAM β detailed steps (INFO/FORMULA/RESULT/ERROR) |
SymToAST | cas/SymToAST.h/.cpp | Bridge: SolveResult β MathAST Natural Display |
SymExprToAST | cas/SymExprToAST.h/.cpp | Bridge: SymExpr β MathAST. Includes convertIntegral() (+C) |
CAS Tests β 53 Unit Tests
| Phase | Tests | Coverage |
|---|---|---|
| A β Foundations | 1β18 | Rational: add, subtract, multiply, divide, simplification. SymPoly: arithmetic, derivation, normalisation. |
| B β ASTFlattener | 19β32 | ASTβSymPoly conversion for simple polynomials, constants, trig functions, powers. |
| C β SingleSolver | 33β44 | Linear (single solution), quadratic (2 real roots, repeated root, negative discriminant), steps. |
| D β SystemSolver | 45β53 | 2Γ2 determined system, indeterminate (infinite solutions), incompatible system. |
# platformio.ini β enable tests:
build_flags = ... -DCAS_RUN_TESTS
build_src_filter = +<*> +<../tests/CASTest.cpp>
Hardware
| Component | Specification |
|---|---|
| MCU | ESP32-S3 N16R8 CAM β Dual-core Xtensa LX7 @ 240 MHz |
| Flash | 16 MB QIO (default_16MB.csv) |
| PSRAM | 8 MB OPI (qio_opi β critical to prevent boot panic) |
| Display | ILI9341 IPS TFT 3.2β β 320Γ240 px β SPI @ 10 MHz (verified) |
| SPI Bus | FSPI (SPI2): MOSI=13, SCLK=12, CS=10, DC=4, RST=5 |
| Backlight | GPIO 45 β hardwired to 3.3V (pinMode(45, INPUT)) |
| Keyboard | 5Γ10 matrix (Phase 7) β Rows OUTPUT: GPIO 1,2,41,42,40 Β· Cols INPUT_PULLUP: GPIO 6,7,8β¦ |
| Storage | LittleFS on dedicated partition β persistent AβZ variables |
| USB | Native USB-CDC on S3 β 115 200 baud |
Full Pinout
ILI9341 Display
| Signal | GPIO | Notes |
|---|---|---|
| MOSI | 13 | FSPI Data In |
| SCLK | 12 | FSPI Clock |
| CS | 10 | Chip Select (active LOW) |
| DC | 4 | Data/Command |
| RST | 5 | Reset |
| BL | 45 | Hardwired to 3.3V β always INPUT |
5Γ10 Keyboard Matrix (driver Keyboard, Phase 7)
| Row | GPIO | Role | Column | GPIO | Role |
|---|---|---|---|---|---|
| ROW 0 | 1 | OUTPUT | COL 0 | 6 | INPUT_PULLUP |
| ROW 1 | 2 | OUTPUT | COL 1 | 7 | INPUT_PULLUP |
| ROW 2 | 41 | OUTPUT | COL 2 | 8 | INPUT_PULLUP |
| ROW 3 | 42 | OUTPUT | COL 3β9 | 3,15,16,17,18,21,47 | not yet wired |
| ROW 4 | 40 | OUTPUT | β | β | β |
β GPIO 4/5 conflict resolved (2026-03-02): Keyboard columns C0 and C1 reassigned from GPIO 4/5 (
TFT_DC/TFT_RST) to GPIO 6/7. The three currently wired columns use GPIO 6, 7, and 8 β no display conflict.
Quick Start
Requirements
- PlatformIO IDE (VS Code extension)
- USB drivers for ESP32-S3 (no external driver needed on Windows 11+)
- Python 3.x (PlatformIO installs it automatically)
Build and Flash
git clone https://github.com/your-user/numOS.git
cd numOS
# Build only
pio run -e esp32s3_n16r8
# Build and flash to ESP32-S3
pio run -e esp32s3_n16r8 --target upload
# Open serial monitor (115 200 baud)
pio device monitor
Serial Keyboard Control (SerialBridge)
With the Serial Monitor open, type characters to control the calculator:
| Key | Action | Key | Action | |
|---|---|---|---|---|
w | β Up | z | ENTER / Confirm | |
s | β Down | x | DEL / Delete | |
a | β Left | c | AC / Clear | |
d | β Right | h | MODE / Return to menu | |
0β9 | Digits | +-*/^.() | Operators | |
S | SHIFT | r | β SQRT | |
t | sin | g | GRAPH | |
e | = (equation) | R | SHOW STEPS |
Note: lowercase
s= DOWN; uppercaseS= SHIFT. Disable CapsLock before use.
User Manual β EquationsApp
The EquationsApp solves single-variable polynomial equations and 2Γ2 systems (linear and non-linear), displaying complete solution steps via the CAS engine.
Access
- From the Launcher, select Equations with ββ and press ENTER.
- The mode-selection screen appears.
Mode 1: Single-Variable Equation
- Select Equation (1 var) with ββ and press ENTER.
- The editor opens. Type your equation with the
=sign:x^2 - 5x + 6 = 0β xβ=2, xβ=32x + 3 = 7β x=2x^2 = -1β no real solution (Ξ < 0)
- Press ENTER to solve.
- The result screen shows:
- Linear: a single solution
x = value - Quadratic: discriminant Ξ and up to 2 solutions
xβ,xβ - No real solution: negative discriminant message
- Linear: a single solution
- Press SHOW STEPS (
R) to view detailed steps:- Normalised equation
- Discriminant value Ξ = bΒ² β 4ac
- Quadratic formula applied
- Computed roots
- Press MODE (
h) to return to the main menu.
Mode 2: 2Γ2 System
- Select System (2Γ2) and press ENTER.
- Two fields appear: Eq 1 and Eq 2.
- Type the first equation in
xandy, press ENTER. - Type the second equation, press ENTER.
- Example:
2x + y = 5/x - y = 1β x=2, y=1
- Type the first equation in
- Press ENTER to solve. Displays
x = value, y = value. - Press SHOW STEPS to view the full Gaussian elimination.
- Press MODE to return.
EquationsApp Keys
| Key | Action |
|---|---|
| β β β β | Navigate selection / cursor in editor |
| ENTER | Confirm mode / Solve equation |
| DEL | Delete character |
| AC | Clear field |
| SHOW STEPS | View detailed steps (from result screen) |
| MODE | Return to main menu |
Project Structure
numOS/
βββ src/
β βββ main.cpp # Arduino entry point (setup/loop)
β βββ SystemApp.cpp/.h # Central orchestrator and LVGL launcher
β βββ Config.h # Global ESP32-S3 pinout
β βββ lv_conf.h # LVGL 9.x configuration
β βββ HardwareTest.cpp # Interactive keyboard test (inline)
β βββ apps/
β β βββ CalculationApp.cpp/.h # Natural V.P.A.M. calculator
β β βββ GrapherApp.cpp/.h # y=f(x) graphing plotter
β β βββ EquationsApp.cpp/.h # CAS β Equation solver
β β βββ CalculusApp.cpp/.h # CAS β Unified symbolic derivatives + integrals
β β βββ BridgeDesignerApp.cpp/.h # Bridge structural simulator (Verlet physics)
β β βββ CircuitCoreApp.cpp/.h # Circuit simulator (MNA, 30 components)
β β βββ Fluid2DApp.cpp/.h # 2D fluid dynamics (Navier-Stokes)
β β βββ ParticleLabApp.cpp/.h # Powder-Toy sandbox (30+ materials, electronics)
β β βββ ParticleEngine.cpp/.h # Cellular automata engine (LUT, spark cycle)
β β βββ SettingsApp.cpp/.h # Settings: complex roots, precision, angle mode
β βββ display/
β β βββ DisplayDriver.cpp/.h # TFT_eSPI FSPI + LVGL init + DMA flush
β βββ input/
β β βββ KeyCodes.h # KeyCode enum (48 keys)
β β βββ KeyMatrix.cpp/.h # 5Γ10 hardware driver with debounce
β β βββ SerialBridge.cpp/.h # Virtual keyboard via Serial
β β βββ LvglKeypad.cpp/.h # LVGL indev keypad adapter
β βββ math/
β β βββ Tokenizer.cpp/.h # Lexical analyser
β β βββ Parser.cpp/.h # Shunting-Yard β RPN / Visual AST
β β βββ Evaluator.cpp/.h # Numerical RPN evaluator
β β βββ ExprNode.h # Expression tree (Natural Display)
β β βββ MathAST.h # V.P.A.M. tree: NodeRow/NodeFrac/NodePowβ¦
β β βββ CursorController.h/.cpp # MathAST editing cursor
β β βββ EquationSolver.cpp/.h # Numerical Newton-Raphson
β β βββ VariableContext.cpp/.h # Variables AβZ + Ans
β β βββ VariableManager.h/.cpp # Persistent ExactVal storage
β β βββ StepLogger.cpp/.h # Parser step logger
β β βββ cas/ # β
Complete CAS Engine
β β βββ CASInt.h # Hybrid BigInt (int64 + mbedtls_mpi)
β β βββ CASRational.h/.cpp # Overflow-safe exact fraction
β β βββ ConsTable.h # Hash-consing PSRAM (dedup)
β β βββ PSRAMAllocator.h # STL allocator for PSRAM OPI
β β βββ SymExpr.h/.cpp # Immutable DAG with hash + weight
β β βββ SymExprArena.h # Bump allocator + ConsTable
β β βββ SymDiff.h/.cpp # Symbolic differentiation (17 rules)
β β βββ SymIntegrate.h/.cpp # Slagle integration (table/u-sub/parts)
β β βββ SymSimplify.h/.cpp # Fixed-point simplifier (8 passes)
β β βββ SymPoly.h/.cpp # Univariable symbolic polynomial
β β βββ SymPolyMulti.h/.cpp # Multivariable polynomial + resultant
β β βββ ASTFlattener.h/.cpp # MathAST β SymExpr DAG
β β βββ SingleSolver.h/.cpp # Analytic linear + quadratic solver
β β βββ SystemSolver.h/.cpp # 2Γ2 system (linear + NL resultant)
β β βββ OmniSolver.h/.cpp # Analytic variable isolation
β β βββ HybridNewton.h/.cpp # Newton-Raphson with symbolic Jacobian
β β βββ CASStepLogger.h/.cpp # Steps in PSRAM (StepVec)
β β βββ SymToAST.h/.cpp # SolveResult β visual MathAST
β β βββ SymExprToAST.h/.cpp # SymExpr β MathAST (+C, β«)
β βββ ui/
β βββ MainMenu.cpp/.h # LVGL launcher grid 3ΓN
β βββ MathRenderer.h/.cpp # 2D MathCanvas renderer
β βββ StatusBar.h/.cpp # LVGL status bar
β βββ GraphView.cpp/.h # Graph widget
β βββ Icons.h # App icon bitmaps
β βββ Theme.h # Colour palette and UI constants
βββ tests/
β βββ CASTest.h/.cpp # CAS unit tests
β βββ HardwareTest.cpp # TFT + physical keyboard test
β βββ TokenizerTest_temp.cpp # Tokenizer test
βββ docs/
β βββ CAS_UPGRADE_ROADMAP.md # β
CAS roadmap (6 phases, complete)
β βββ ROADMAP.md # Phase history + future plan
β βββ PROJECT_BIBLE.md # Master software architecture
β βββ MATH_ENGINE.md # Math engine + CAS in detail
β βββ HARDWARE.md # ESP32-S3 pinout, wiring, and bring-up
β βββ CONSTRUCCION.md # Physical assembly guide
β βββ DIMENSIONES_DISEΓO.md # 3D chassis specifications
βββ platformio.ini # PlatformIO configuration
βββ wokwi.toml # Wokwi simulator (optional)
βββ diagram.json # Wokwi circuit diagram
Build Stats
Compiled with
pio run -e esp32s3_n16r8in production mode (CAS tests disabled)
| Resource | Used | Total | Percentage |
|---|---|---|---|
| RAM (data + bss) | 97 192 B | 327 680 B | 29.7 % |
| Flash (program storage) | 1 518 269 B | 6 553 600 B | 23.2 % |
Flash saved vs test mode: β39 444 B when deactivating -DCAS_RUN_TESTS.
To enable or disable CAS tests, edit platformio.ini:
; ---- Production mode (default) ----
; -DCAS_RUN_TESTS β commented out
; ---- Test mode β uncomment these two lines ----
; -DCAS_RUN_TESTS
; +<../tests/CASTest.cpp> β in build_src_filter
Critical Hardware Fixes
Issues discovered and resolved during bring-up. Essential for any fork or new build:
| # | Problem | Symptom | Solution |
|---|---|---|---|
| β | Flash OPI Panic | Boot β Guru Meditation: Illegal instruction | memory_type = qio_opi + flash_mode = qio |
| β‘ | SPI StoreProhibited | Crash in TFT_eSPI::begin() at address 0x10 | -DUSE_FSPI_PORT β SPI_PORT=2 β REG_SPI_BASE(2)=0x60024000 |
| β’ | Display noise | Horizontal lines and visual artefacts | Reduce SPI to 10 MHz: -DSPI_FREQUENCY=10000000 |
| β£ | LVGL black screen | lv_timer_handler() invokes flush but no image appears | Buffers via heap_caps_malloc(MALLOC_CAP_DMA|MALLOC_CAP_8BIT) β never ps_malloc |
| β€ | GPIO 45 BL short | Display stops responding on backlight init | pinMode(45, INPUT) β the pin is hardwired to 3.3V |
| β₯ | Serial CDC lost | Output invisible in Serial Monitor on connect | while(!Serial && millis()-t0 < 3000) + monitor_rts=0 in platformio.ini |
Project Status
| Phase | Description | Status |
|---|---|---|
| Phase 1 | Math Engine β Tokenizer, Shunting-Yard Parser, RPN Evaluator, ExprNode, VariableContext | β Complete |
| Phase 2 | Natural Display V.P.A.M. β fractions, radicals, exponents, smart 2D cursor | β Complete |
| Phase 3 | Launcher 3.0, SerialBridge, CalculationApp history, GrapherApp zoom/pan | β Complete |
| Phase 4 | LVGL 9.x β ESP32-S3 HW bring-up, DMA, animated splash screen, icon launcher | β Complete |
| Phase 5 | CAS-Lite Engine (SymPoly, SingleSolver, SystemSolver, 53 tests) + EquationsApp UI (legacy milestone) | β Complete |
| CAS | CAS-S3 internal milestones: BigNum, hash-consed DAG, SymDiff 17 rules, SymIntegrate Slagle, SymSimplify 8-pass, OmniSolver | β Complete |
| Giac Migration | Big Switch to Giac: GiacBridge integration, UART parser/eval flow, -DDOUBLEVAL, 64 KB loop stack, real-mode defaults with i preserved | β Complete |
| Phase 6 | Statistics, Regression, Sequences, Probability, Matrices, Bridge Designer | β Complete |
| Simulations | ParticleLab (30+ materials, electronics), CircuitCore (SPICE), Fluid2D (Navier-Stokes) | β Complete |
| Phase 7 | Complex numbers, base conversions | π² Planned |
| Phase 8 | Physical keyboard, custom PCB, rechargeable battery, 3D enclosure, WiFi OTA | π² Planned |
Technology Stack
| Layer | Technology | Version |
|---|---|---|
| MCU Framework | Arduino on ESP-IDF 5.x | PlatformIO espressif32 6.12.0 |
| UI / Graphics | LVGL | 9.5.0 |
| TFT Driver | TFT_eSPI | 2.5.43 |
| Filesystem | LittleFS | ESP-IDF built-in |
| Language | C++17 | lambdas, std::function, std::unique_ptr |
| CAS Memory | PSRAMAllocator STL custom | PSRAM OPI 8 MB |
| Build System | PlatformIO | 6.12.0 |
| Simulation | Wokwi | wokwi.toml |
Comparison with Commercial Calculators
| Feature | NumOS | NumWorks | TI-84 Plus CE | HP Prime G2 |
|---|---|---|---|---|
| Open Source | β MIT | β MIT | β | β |
| Natural Display | β | β | β | β |
| Symbolic CAS | β Pro | β SymPy | β | β |
| Symbolic derivatives | β | β | β | β |
| Symbolic integrals | β | β | β | β |
| Solution steps | β | β | β | β |
| Colour graphing | β | β | β | β |
| Multi-function graphing | π² | β | β | β |
| Statistics & Regression | β | β | β | β |
| Matrices | π² | β | β | β |
| Complex numbers | π² | β | β | β |
| Scripting / Python | β NeoLanguage + Python | β | β TI-BASIC | β HP PPL |
| WiFi / Connectivity | π² | β | β | β |
| Rechargeable battery | π² | β | β | β |
| Estimated HW cost | ~β¬15-20 | β¬79 | β¬149 | β¬179 |
| Platform | ESP32-S3 | STM32F730 | Zilog eZ80 | ARM Cortex-A7 |
π NumOS already surpasses the TI-84 in CAS capability and cost, and is on track to match the NumWorks.
Documentation
| Document | Description |
|---|---|
| ROADMAP.md | Complete phase history, milestones, and detailed future plan |
| PROJECT_BIBLE.md | Master architecture, modules, code conventions, and development guides |
| CAS_UPGRADE_ROADMAP.md | Full roadmap for the 6-phase CAS upgrade |
| MATH_ENGINE.md | Math engine + CAS: design, algorithms, pipeline, and examples |
| HARDWARE.md | ESP32-S3 pinout, complete wiring, critical bugs, and bring-up notes |
| CONSTRUCCION.md | Physical assembly guide, 3D printing, and hardware testing |
| DIMENSIONES_DISEΓO.md | Dimensional specifications for the 3D chassis |
Support the Project β
The EV grant graciously covers the core hardware prototyping. However, I have set a β¬500 goal on Ko-fi to fund the crucial βinvisibleβ infrastructure of NumOS.
Your support directly funds:
- ** AI & Dev Tools:** Subscriptions for Claude/Copilot to accelerate C++ optimization and the Giac engine porting.
- Digital Presence: Domain hosting (
neocalculator.tech/numos.org) and backend web services. - Beta Shipping: Sending physical beta units to expert contributors globally to accelerate community development.
Every contribution keeps me focused on the mission and ensures NumOS stays independent and open-source.
Contributing
NumOS is an open-source project that aspires to grow with a community. Contributions are welcome!
- Fork the repository.
- Create a branch:
git checkout -b feature/descriptive-name - Follow the code conventions of the project.
- Verify the build passes:
pio run -e esp32s3_n16r8 - If you add math logic, include tests in
tests/. - Open a Pull Request with a clear description of your changes.
Areas Where Help Is Most Needed
| Module | Description |
|---|---|
| Sequences App | Arithmetic and geometric sequences, Nth term, partial sums |
| Settings App | |
| Advanced CAS | |
| Better UI/UX | General improvement on UI and UX for real product release |
| Matrices | Matrix editor, determinant, inverse, multiplication |
| Physical keyboard | β
GPIO 4/5 conflict resolved β Keyboard driver 5Γ10 implemented (Phase 7) |
| Custom PCB | KiCad schematic with integrated ESP32-S3 + TP4056 charger |
This project was developed with AI assistance (Claude/Copilot) for code generation, guided by the authorβs systems architecture decisions. All design choices like DAG structure, memory management, parser design, were made and validated by the author.
License & Intellectual Property
Software (Firmware)
The NeoCalculator firmware (NumOS) is licensed under the GNU GPL v3. We are proud to build upon the Giac engine by Bernard Parisse. In accordance with the GPL v3, all software source code in this repository is open for study, modification, and redistribution.
Hardware & Industrial Design
All rights reserved. The hardware design, including but not limited to:
- PCB Schematics and Layouts (KiCad files, Gerbers).
- Industrial Design and 3D Models (STL, STEP, CAD files).
- The βExam Keyβ security architecture.
Are proprietary and the intellectual property of Juan RamΓ³n. No commercial use or reproduction of the hardware is permitted without express authorization.
Note on Hardware IP: This proprietary status is a necessary measure for now. Our primary goal is to maintain the strict hardware control required to eventually achieve official βExam Legalβ certification and to protect the projectβs integrity from low-quality, unauthorized clones. Once the ecosystem is mature and certified, we plan to evaluate open-hardware licensing models.
Built with β€οΈ and a lot of C++17
NumOS, The best open-source scientific calculator for ESP32-S3
Last updated: May 2026
Similar Articles
Designing a Scientific Calculator from scratch in FPGA
A detailed blog series documenting the design and implementation of a scientific calculator from scratch using FPGA, covering numerical methods, CPU architecture, microcode, and hardware prototyping.
I designed a nibble-oriented CPU in Verilog to build a scientific calculator
This project implements a fully functional scientific calculator in hardware using an FPGA, including a custom soft CPU, microcode firmware, and supporting tools. It provides a web-based simulator and open-source Verilog code.
ESP-EEG is an affordable 8-channel biosensing board
The Cerelog ESP-EEG is an affordable 8-channel biosensing board using the ADS1299 chip, offering cleaner signal with closed-loop active bias at a lower price point than OpenBCI. It supports open-source firmware and software like Brainflow, but has limitations such as USB-only connectivity and non-commercial use restrictions.
@charles_irl: another page for the @modal LLMEng Almanac: an explorer for low-precision floats, from bf16 to fp4 https://modal.com/llβ¦
A page from Modal's LLM Engineer's Almanac that provides an interactive explorer for understanding low-precision floating-point formats like bf16 and fp4.
A self-powered computer in actual credit-card size (~1mm thick)
A hobbyist built a functional self-powered computer that is literally the size of a credit card and about 1mm thick, using an ESP32, NFC, e-ink display, and custom flex PCB.