An experiment in running a local language model inside a Casio graphing calculator. It is an offline, stateless chat application for the Casio fx-CG50 family: a .g3a add-in provides the interface and model weights are streamed from calculator storage as text is generated token by token.
This is a research project, not a trustworthy assistant. Both included models can hallucinate, invent facts, repeat themselves, or misunderstand a prompt. Do not use their output for schoolwork, medical, legal, safety, or other important decisions.
Some time ago I was given a Casio fx-CG50. From the first day I had it, I wanted to put some kind of AI on it.
At first I explored the obvious external routes: connecting an ESP32, using a Raspberry Pi, or making the calculator speak to another device. Those paths were not useful for the goal. The calculator USB interface is exposed to a PC as mass storage for moving files, not as a general serial/network interface that could turn the calculator into an internet client.
I then investigated running a local model directly on the calculator. That looked almost impossible at first: the available working-memory budget is only around half a megabyte for this runtime, while even a very small usable model needs megabytes of weights. The breakthrough was separating those two things: the weights do not live in RAM. They live in the calculator's 16 MB user storage and are read in small blocks while the SH7305 executes the model.
After removing unused add-ins, my calculator had roughly 13–14 MB available. That was enough to experiment with a compact conversational model, although the price is very slow inference. This repository records the real results, including the failed paths, instead of pretending a calculator is a modern phone.
| Model | Intended use | Download size on calculator | Practical quality | Release |
|---|---|---|---|---|
| TinyTalk v1 Q4 | Fastest compact conversational demo | ~2.27 MB including add-in/assets | Small chat model; often hallucinates | v0.8.1 |
| NanoLM Q4-20K CG4 | Larger experimental assistant | ~13.29 MB including add-in/assets | Better breadth than TinyTalk, but still hallucinates and is much slower | v0.10.0 |
Both models are English-first. Every prompt is independent: there is no conversation history or persistent context. The UI streams output as it is generated, shows a timer while it is thinking, and lets the user stop a generation with F6.
Download a matching release package from the GitHub Releases page. Copy the .g3a and every asset from that package to the root of calculator storage; then safely eject the calculator.
- TinyTalk v0.8.1:
CasioLLM-v0.8.1.g3a,TINYTLK.BIN,TINYTLK.TOK, andTINYTLK.PFX. - NanoLM v0.10.0:
CasioLLM-v0.10.0.g3a,NANOLM.CG4,NANOLM.IDX,NANOLM.PFX,NANOLM.TOK, andNANOLM.TRI.
Do not mix assets from different model releases. Each release directory has a SHA256SUMS file for integrity checks. Casio's standard installation route is to copy .g3a files to the root of calculator storage over USB mass-storage mode. Casio's fx-CG50 guide documents the general add-in workflow.
The add-in is only the program and UI. The model is external data in the calculator's storage flash:
- Model weights are pruned where appropriate and quantized to signed 4-bit values (Q4), with small per-group scales.
- The tokenizer, index/trie, and a fixed-prefix cache are separate files.
- During inference, the runtime opens the model file and streams only the blocks needed for the current matrix operation into a bounded buffer.
- RAM holds activations, the KV cache for the short context window, tokenizer state, UI, and I/O buffers—not all weights at once.
NanoLM uses the newer CG4 container so its weights can be read in a layout suited to the calculator's SH4 processor. This is why a model can occupy about 12.18 MB of flash without requiring 12.18 MB of RAM. It also explains the latency: every generated token requires a large amount of storage I/O and integer matrix arithmetic on calculator hardware.
This repository is built for the color Casio Prizm / fx-CG .g3a add-in platform, not for ordinary scientific calculators or the fx-9860 family. Storage, add-in ABI, display, and processor family all matter; free space alone is not enough.
| Calculator family | Storage stated by manufacturer | Status | TinyTalk | NanoLM |
|---|---|---|---|---|
| fx-CG50 | 16 MB | Physically tested | Yes, needs ~2.27 MB free | Yes, needs ~13.29 MB free |
| Graph 90+E (regional fx-CG50 variant) | 16 MB class | Same target family; not physically tested in this project | Expected, verify first | Expected only with ~13.3 MB free |
| fx-CG10 / fx-CG20 | 16 MB | Same legacy CG/Prizm family; untested here | Plausible, device test required | Plausible, device test required |
| fx-CG50 AU | 4.5 MB maximum storage in Casio manual | Not tested | May fit only if sufficient space is actually free | No |
| fx-9860G / fx-9750G family | 3 MB or less depending on model | Different platform / insufficient storage | No | No |
| fx-CG100 / Graph Math+ | Varies | No supported unmodified .g3a target in this project |
No | No |
Casio specifies 16 MB storage for the fx-CG50 and fx-CG10/20 families, and the fx-CG50 hardware guide lists 16 MB for the normal fx-CG50 but 4.5 MB for the AU edition. The values above are storage capacity, not RAM. fx-CG50 hardware guide, fx-CG10/20 hardware guide, Casio comparison chart.
The NanoLM build's measured static working set is about 479 KB before stack and runtime overhead, so it should be treated as a roughly 512 KB working-RAM target. This has been validated on an fx-CG50 only. Compatibility claims for other CG devices are deliberately marked as expected/plausible rather than guaranteed until they are physically run.
The original aim was a conversational model—not a tiny story generator. I looked at TinyStories and then screened conversational/instruction candidates including TinyTalk v1/v2, Doge-20M-Instruct, Stentor-12M-Instruct, Asena_ESP32_MAX, GuppyLM-9M, i3-22m, TinyChat15M, Pin variants, and NanoLM. At this scale, labels such as “Instruct” are not enough: many candidates could start but gave irrelevant replies to ordinary conversation.
TinyTalk v1 was retained because it is genuinely small and conversational. NanoLM was retained because the unquantized local checkpoint gave relatively better answers and fit the available flash only after vocabulary pruning and aggressive Q4 quantization. The important caveat is that the quantized calculator form loses some distinctions that exist in the PC checkpoint. For example, technical definitions such as CPU can become less reliable after Q4 conversion. That is a real measured trade-off, not a UI bug.
NanoLM is therefore still an experimental candidate: it is broader than TinyTalk, but larger, slower, and far from reliable. TinyTalk is faster and more compact, but its small conversational model frequently makes things up.
| Prompt | Build | First token | Complete reply | Reply |
|---|---|---|---|---|
hi |
v0.7.0 initial | 9.382 s | 34.296 s | Hi! I'm Sarah. Nice to meet you! |
hi |
v0.8.1 optimized | 5.695 s | 27.078 s | Same text |
how are you |
v0.8.1 optimized | 8.187 s | 32.382 s | I'm doing well, thank you. How are you? |
im doing well too |
v0.8.1 optimized | 9.492 s | 23.164 s | That's good to be yourself. |
For the controlled hi comparison, TinyTalk v0.8.1 reduces first-token latency by 39.3% and total time by 21.0% without changing the 50-prompt local regression output. See docs/tinytalk-v0.8.1-final-results.md.
These are host regression timings, not calculator wall-clock times. They prove that v0.10.0 preserves the old generated token sequence while making the runtime faster. A complete clean physical v0.10.0 NanoLM timing run was not available, so no invented calculator time is reported.
| Prompt | v0.9 first | v0.10 first | v0.9 total | v0.10 total | Output relation |
|---|---|---|---|---|---|
Hello! How are you today? |
242 ms | 85 ms | 1007 ms | 664 ms | Exact |
What is a dog? |
187 ms | 54 ms | 960 ms | 664 ms | Exact |
What is water? |
171 ms | 54 ms | 960 ms | 687 ms | Exact |
What is the capital of France? |
242 ms | 101 ms | 406 ms | 226 ms | Exact |
| 50-prompt aggregate | — | — | 46.095 s | 30.791 s | 50/50 exact |
That is a 33.2% aggregate host-runtime reduction. The underlying changes are an exact four-position causal prefill, Q4 layout/inner-loop work, fixed-prefix caching, storage buffering, and cooperative scheduling. The details and verification gates are in docs/nanolm-v0.10.0-exact-batched-ultra.md.
releases/: self-contained versioned builds. Each preserved release includes its.g3a, model assets, source snapshot, checksums, and test evidence.runtime/: current fxSDK/gint source and host-side conversion / verification utilities.benchmarks/: machine-readable exact comparison data.docs/: physical measurements, acceleration notes, model-search outcomes, and limitations.add-ins/: recoverable Casio and game add-ins removed from the test calculator to make room for the experiment.
The code is GPL-3.0. NanoLM is a modified derivative of Mxode/NanoLM-25M-Instruct-v1.1, whose card declares GPL-3.0. See MODEL_ATTRIBUTION.md for the exact derivative work and limitations.