82 lines
3.0 KiB
Markdown
82 lines
3.0 KiB
Markdown
# comodore-iec-emu — IEC listener PoC
|
|
|
|
A proof-of-concept Commodore **IEC listener** device on a Raspberry Pi Zero 2 W.
|
|
It behaves like a printer (default device address **4**): it never talks back, it
|
|
only **listens**, and it debug-prints in real time everything the C64 sends.
|
|
|
|
The timing-critical IEC handshake (ATN ack, per-bit sampling, EOI) runs in a
|
|
**Linux kernel module**; a **Python** userspace program decodes and pretty-prints.
|
|
See [`_plans/poc-listener-printer-PLAN.md`](_plans/poc-listener-printer-PLAN.md)
|
|
for the full design and [`_research/`](_research/) for the grounding research.
|
|
|
|
## Layout
|
|
|
|
```
|
|
kernel/ # the kernel module (real-time half) — builds on the Pi
|
|
iec_listener.c ISR, IRQ-off bit loop, listener state machine, /dev/iec0
|
|
iec_listener.h shared struct iec_record + ioctls (mirrors device.py)
|
|
iec_lines.h logical line layer, direct BCM register access (hot path)
|
|
iec_timing.h handshake timing constants
|
|
Makefile out-of-tree build + load/unload/overlay targets
|
|
dts/ device-tree overlay (pin reservation / pulls)
|
|
iecpoc/ # Python userspace (everything else) — host-testable
|
|
device.py /dev/iec0 record stream (wire format, replay)
|
|
decode.py command-byte + event decoder
|
|
petscii.py PETSCII -> display glyphs
|
|
log.py the annotated trace formatter (PLAN §8)
|
|
main.py CLI (--address, --raw, --logfile, --replay)
|
|
tests/ # host-runnable, no Pi/kernel needed
|
|
docs/ # wiring.md, kernel-notes.md
|
|
```
|
|
|
|
## Userspace (Phase 0 — works on any host)
|
|
|
|
```bash
|
|
python3 -m venv .venv && .venv/bin/pip install -e '.[dev]'
|
|
.venv/bin/pytest # run the tests
|
|
.venv/bin/python -m tests.fixtures # (re)generate the capture
|
|
.venv/bin/python -m iecpoc.main --replay tests/data/hello_world_session.bin
|
|
```
|
|
|
|
On the Pi, point it at the live device instead:
|
|
|
|
```bash
|
|
.venv/bin/python -m iecpoc.main --address 4 # reads /dev/iec0
|
|
```
|
|
|
|
Example trace (the `OPEN 1,4 / PRINT# / CLOSE` session, abbreviated):
|
|
|
|
```
|
|
[IDLE] waiting for ATN
|
|
[ATN] asserted -> DATA low (ack)
|
|
[CMD] $24 LISTEN 4 (addressed: ME)
|
|
[CMD] $60 DATA SA=0
|
|
[ATN] released -> LISTENER
|
|
[DATA] $48 'H'
|
|
...
|
|
[DATA] $0D <CR> <EOI>
|
|
[ATN] released -> not addressed -> IDLE
|
|
```
|
|
|
|
## Kernel module (on the Pi)
|
|
|
|
```bash
|
|
sudo apt install raspberrypi-kernel-headers
|
|
cd kernel && make
|
|
sudo insmod iec_listener.ko address=4 # creates /dev/iec0
|
|
sudo rmmod iec_listener # releases DATA on unload
|
|
```
|
|
|
|
See [`docs/wiring.md`](docs/wiring.md) for the level-shifter circuit and the
|
|
pre-C64 bring-up checklist, and [`docs/kernel-notes.md`](docs/kernel-notes.md)
|
|
for the resolved kernel real-time decisions.
|
|
|
|
## Status
|
|
|
|
- **Phase 0 (userspace + tests):** complete, runs on any host.
|
|
- **Phase 1 (kernel command phase):** skeleton present; needs Pi bring-up.
|
|
- **Phase 2 (data-phase reception):** the real experiment; tune timing on real
|
|
hardware.
|
|
|
|
See PLAN.md §9 for the phased milestones.
|