Roadmap

Apa yang sudah selesai, berikutnya, dan ke mana arah Aksa.

  • P0: scaffold, Makefile (native+wasm), test harness, CLI aksa tokens
  • P1a: locale loader + lexer (id/en, Unicode idents, E001–E003) + wasm demo page
  • P1b: parser → AST (recursive descent, panic-mode recovery, aksa ast)
  • P1c: semantic checker (aksa check; static E100–E111, runs before every aksa run)
  • P1d: bytecode VM, aksa run (cetak/tanya, functions, loops, localized runtime errors)
  • P1e: golden tests (40 ok + 36 error programs, tests/golden.sh in make test)
  • P2a: browser run (console via WASM hooks, inline async tanya, stop button, instruction-budget yield)
  • P2b: CodeMirror 6 editor (bun-bundled; locale-driven highlighting, live squiggles, error panel)
  • P2c: turtle canvas (animated draw, live speed slider, reset, id color names)
  • P3: hardware simulator (virtual board: 3 LEDs, button, slider, buzzer, fan; pin builtins + non-blocking tunggu; examples dropdown; headless CLI board for 10 golden tests)
  • P4: C emitter (aksa emit) + tiny value runtime + sim/esp32 HAL; differential tests (tests/diff.sh) prove emitted C compiles -Werror and matches the VM on all golden ok/err programs (E109 depth excluded)
  • P5: compile server (Bun + arduino-cli in Docker, ESP32) + browser flasher (esptool-js) + serial monitor; flash path untested on a real board
  • P5b: flash verified on real ESP32-C6. Terminal: make aksa-flash FILE=x.aksa (flash.sh: emit→sketch→arduino-cli upload), auto-runs. Browser (play/device.html): manual download-mode (BOOT+RESET) + esptool-js no_reset flashes reliably — fixed the "device has been lost".
  • P5 deferred: browser auto-reboot-to-run on C6 native-USB (RTS/DTR pulse doesn't reboot via USB-JTAG controller → user taps RESET after flashing); tanya on device (serial read in HAL); Pico/UF2; per-IP rate limit; build+test Docker image (no Docker locally)
  • P6g: reference-counted heap strings in emitted C (rt.c); loops that build text free per-iteration, no leak on device; tests/mem.sh (AK_LIVE=0) + ASan-clean corpus
  • P6a (language only): IDE split into language page (lessons+turtle) and device page (board+flash); 15 graded lessons (id+en), basic→middle→advanced; share via URL hash
  • P6c: drawing cursor renamed turtle→robot, arrow replaced with a robot character (rounded body, eyes, nose showing heading)
  • P6d: lessons split into one file per locale (lessons.id.js/lessons.en.js), lessons.js just assembles the map
  • P6e: all JS → strict TypeScript (web+server, bun-native); tsconfig + make typecheck
  • P6f: auto-detect chip on flash (esptool-js CHIP_NAME → board); compile targets esp32c3/esp32c6, bootloader at 0x0; others rejected
  • P6b: more locales; device lesson track after real-board testing. Pin map C6 DONE: 15 named starter components → GPIO (device/aksabot_c6.aksa + docs pinmap). ADC=0-6, avoid 8/9/12/13. C6 Super Mini user LED=GPIO15. TODO: C3 map
  • P7: on-device runtime — board is its own hotspot + editor + interpreter (make device, default C6). Tested on real C6: AP join, GPIO15 blink, ulangi, live analog stream, Stop. Program runs in its own task (16KB stack); output via stream buffer + /output poll; Stop = poll hook checked each loop back-edge + interruptible tunggu; OOM-safe task start (no busy wedge); runs cooler: loop() yields 1ms, CPU 160->80MHz, WiFi TX 8.5dBm (one near client)
  • Battery endpoint (device/aksa_device.ino): GET /bat returns 0–100% (no UI). Aksabot STANDARD: battery sense on GPIO6/ADC1_6, B+→100k→GPIO6→100k→GND +100nF, linear 3.3V=0%/4.2V=100%. Boards with a spare ADC reserve GPIO6; Starter keeps GPIO6 for mic (no battery)
  • P8: Aksabot (closed kit, ESP32-C6) — reuse P7 AP+editor+on-chip VM; board profile (named components via generated buat name = gpio preamble, Starter tier map done); 3 core builtins (atur/pin_pwm, sudut/servo_write, baca_jarak/pin_read_distance) + 2 Starter driver builtins (7-seg TM1637 write, NeoPixel color) + HAL (esp32/sim); hardware lesson track. v1 editor = text. NOTE: pin map is Starter-only; higher tiers may remap
  • Production order (Aksabot): 1 prototype from off-the-shelf modules → prove C6 software → prove curriculum with kids → PCB+casing → mass. No PCB before wiring+curriculum validated
  • Aksabot board rebuild (backup/kicad/aksabot, 2026-07-26): 260×170 → 120×120mm square (2 boards in one case bag). Fixed old board's wrong C6 pinout (power=RIGHT row), 15.24→15.5mm rows, 1x13+1x12→2×1x13. USB-C only, no battery (IO6=mic). ERC 0/0, DRC 0 err. Placed 24/27 by solving origins from measured courtyards (origin≠centre: 1x13 socket hangs 34mm down from pin 1). Added protection (F1 polyfuse 500mA splits +5V/+5VP, D4 Schottky clamp, R6/R7 220R on servo+PIR signals). Fixed: buzzer shorted to +3V3 by auto-router trunk landing on its other pin (ERC-invisible; comb() now clears foreign pins + check_nets.py guards). USB-C moved to top edge (joystick blocked it). 31 parts placed. TODO: fab package
  • LineFollower board design (backup/kicad): round 120mm PCB — C6, 8 IR sensors (6 ADC+2 digital, emitters ganged via 1 MOSFET), DRV8833+2×N20, 1×18650 w/ TP4056+DW01A/8205A protection + boost 5V + reverse/polyfuse guards. ERC+DRC clean; fixed C6 pinout (power=right row). Gen via gen_sch.py/gen_pcb.py
  • LineFollower 120mm rev (2026-07-25): 3mm sensors on BOTTOM face (legs ~12mm), female C6 sockets, 2-layer. Rolled back 136→120mm. TODO: 18650 holder footprint (BT1 placeholder), cosmetic silk, paper test-fit of caster/brackets/holder before ordering
  • LineFollower fab blockers (2026-07-25): SW1 → SS12D00 slide switch (own footprint in LineFollower.pretty + project fp-lib-table); 10 mounting holes Edge.Cuts circles → NPTH MountingHole footprints so they reach the drill file (T7C3.200). Parity 0 issues
  • LineFollower rear rework (2026-07-25): caster (12mm ball, 22mm body) overhung the rim — screws respaced 12→15mm, pulled to y=150. Freed the rear: BZ1→BOTTOM face (no 12mm gap on top once motor bodies counted; 0.35mm to caster, 9mm buzzer would ease it), BT1→(116,142), SW1 +1.75mm. Rerouted, DRC+parity clean
  • Aksabot copper routing (2026-07-27): all 26 nets, 271 segments/25 vias, GND poured both layers. DRC 0 unconnected / 0 parity (5 lib-mismatch warnings only). Ported route_pcb.py+router.py from LineFollower: POWER={+5V,/+5VP}, outline via GetBoardPolygonOutlines (arcs, not a polygon). ~18min
  • Fab minimums on both boards (2026-07-27): house wants >0.3mm track, >0.5mm clearance, >0.8mm drill incl. vias. Set in both .kicad_pro + router consts. Aksabot 0.4/0.5/0.8 tracks, via 1.4/0.8, DRC 0 err. LineFollower 0.35/0.5/0.7, via 1.3/0.8, 661 seg — 1 wire link left (/BTN_MODE), reordering only moves which net loses. TO-92_Inline→_Wide + CP_Radial_P2.00→P2.50 via new swap_fp.py. GND now routed as a tree AND poured (a 0.5mm pour leaves pads in pockets); starved thermals auto-tied from the DRC report
  • Single-layer tried and rejected (2026-07-27): B.Cu-only mode in router.py (ONE_LAYER const, GND routed not poured — tracks island a 1-layer pour). Best of 3 orderings needs 24 wire links, 5 on the fused +5V rail. KiCadRoutingTools plugin (rip-up/reroute, Rust A*) got 23 in 4min; its place_optimize halved airwire crossings 121→51 but routing got WORSE (34) and it scrambled 25 parts. 1-layer is not cheaper at JLC — 2-layer ships. Rails route first on 1 layer, not by span
  • LineFollower copper routing (2026-07-25): all 44 nets, GND poured both layers, DRC 0 errors / 0 unconnected. Own grid maze router (route_pcb.py + router.py; KiCad has none) — 45°/90° only via direction-state A* + turn cost, routed at 0.4mm clearance, F.Cu horizontal / B.Cu vertical grain. Rerun after any placement change (~1min)
  • LineFollower spec update (backup/kicad): 34mm wheels + screws flush to motor; front sensor array re-centered; battery sense on IO6 (SENS_DL→IO17, GET /bat); motor-noise parts (ferrite FB1+C_BST, motor caps C_M1/2) + MOTOR_NOISE.md; schematic redrawn as grouped wired blocks (power ports + bus labels). ERC clean.
  • LineFollower fab package (backup/kicad/LineFollower/fab, 2026-07-25): gerbers+Excellon zip, B&W fab/assembly/outline/schematic PDFs, BOM, pick-and-place CSV, FAB.md specs. Board 114.13×120mm, 2 layer, min track/drill 0.3mm. Regen via kicad-cli.
  • Parse-depth cap (PARSE_DEPTH_MAX=128, parser.c): deep nesting hits E109 once, no stack-overflow reboot. Capping the parser caps checker+compiler too. Measured ~0.7KB/level → worst case ~30KB, so device task stack 16→48KB. Golden err deep_nest
  • On-board editor UX (index_html.h): syntax highlight via transparent-textarea-over-<pre> overlay (regex: keywords/builtins/strings/numbers///comments, both locales), + auto-indent on Enter (copies indent, +2 after {). No library, self-contained. ponytail: keyword list hand-copied from locales.
  • Browser terminal scrollback cap (index_html.h): selama(benar) printers grew #out DOM unbounded → tab crawl. Keep last 4000 chars. Device ring already bounded (drops on full), so browser was the only leak.
  • On-board editor polish: Run/Stop disable states + grey styling; editor persists to localStorage (restore on load, save on edit); hot forever-loops auto-throttle in dev_poll (delay(1) per 10ms, tunable) so no tunggu needed to stay cool.
  • Timer/interrupt for precise timing: task separation is fine for the web+VM split (jitter-tolerant), but reading encoders / fixed-rate sampling / safety stops need hardware timer or external interrupt (INT0), not a FreeRTOS task
  • Block+text editor: drag-drop blocks that emit Aksa text side-by-side. Deferred until text editor v1 proves out
  • Docs site (docs.aksabot.com): static bosia app in docs/ — en + /id, language guide, builtins/errors/CLI reference, 15 lessons, Aksabot section, search, llms.txt, Cloudflare deploy
  • Web redesign: playful kid theme (Lilita One/Nunito, sky bg, bouncy buttons); both pages, mobile stack <800px; brand + canvas cursor use favicon robot (antenna ball = pen color)
  • Play deploy (play.aksabot.com): CI builds wasm (emsdk) + bundle, flattens play/+wasm/+locales/ into site/, Cloudflare Pages aksa-play
  • tunggu unit = seconds (kid-friendly); decimals for sub-second (0.1=100ms). seconds→ms ×1000 in all 3 runtimes (core/rt.c, device dev_wait, play/); en examples/docs/golden updated
  • Renamed id print builtin tulis→cetak (clearer "print"). One line in locales/id.json; runtimes dispatch on canonical print. Updated tests, golden .id, docs, lessons, highlighter regex