Skip to content

Latest commit

 

History

7 Commits

Folders and files

NameName
Last commit message
Last commit date
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 

Repository files navigation

FujiATC

An Air Traffic viewer for Atari 8-bit computers, powered by FujiNet.

Tested on real hardware: stock 130XE and 800XL with GTIA2RGB FPGA companion board.

FujiATC in 40-col GTIA2RGB mode FujiATC Options in 40-col GTIA2RGB mode FujiATC in 80-col GTIA2RGB mode


Features

  • Live worldwide air traffic on a PPI radar scope - up to 15 aircraft, stable target numbers (slots keyed by the icao24 airframe id), nearest first, ground traffic distinguished from airborne.
  • Colour-coded altitude bands on GTIA2RGB (80x23, per-cell colours, icon font with real directional aircraft glyphs), monochrome GR.0 rendering on stock video.
  • Range zoom 5-120 nm, fading trails, range rings, centre-airport runway overlay with true headings and lengths.
  • Follow mode: lock the scope onto one aircraft and it stays centred as it flies, so it never slips off the edge of range.
  • Target selection with a detail block: callsign, type, squawk, exact altitude with climb/descend trend, ground speed, track, distance and 16-wind bearing from the centre.
  • Emergency squawks (7500/7600/7700) in blinking red + POKEY two-tone alarm; contact gained/lost beeps (mutable).
  • METAR for the centre station on the bottom row.
  • 4 location profiles stored on the FujiNet (appkeys), centre by ICAO code (resolved online, runways fetched along) or raw lat/lon.
  • Two data sources: direct (adsb.fi, zero infrastructure - the default) or a lightweight fujiatc-server relay (~5 s refresh, sub-kilobyte polls); see Data sources.

Four .xex variants

Each release ships four builds. They all run on any XL/XE - a wrong pick is harmless (no FPGA detected -> standard 40 columns). The split selects the display driver and reserves extended-RAM support:

File Best for Display
fujiatc-xeg2r.xex 130XE (128 KB) + GTIA2RGB 80-col colour + rainbow
fujiatc-xe.xex any 128 KB machine, stock video 40-col GR.0
fujiatc-xlg2r.xex 64 KB machine + GTIA2RGB 80-col colour + rainbow
fujiatc-xl.xex 64 KB machine (800XL/65XE/1200XL) 40-col GR.0

Rule of thumb: have a GTIA2RGB? take a *g2r build. Have 128 KB? take an xe* build. Otherwise fujiatc-xl.xex. (The 128 KB banks are reserved for upcoming replay/cache features.)

Requirements

  • Atari XL/XE with 64 KB RAM
  • FujiNet with a recent firmware (developed and tested against 1.6.1), configured WiFi, and an SD card if you want the configuration to survive a power cycle (appkeys live on SD)
  • optional: GTIA2RGB FPGA extension for 80-column colour
  • internet access from the FujiNet (both sources are reachable over HTTPS; no accounts, no API keys)

Quick start

  1. Boot fujiatc-*.xex (FujiNet CONFIG, SIDE, your favourite loader).
  2. The radar starts around the built-in default location. Press OPTION, then E, type your airport's 4-letter ICAO code and RETURN - the coordinates and runway layout are fetched online.
  3. Press S to save, ESC to return. Done - traffic appears within one poll (~10 s).

Keys (radar screen)

Key Action
+ / - zoom in / out (range 5/10/15/20/30/40/60/80/120 nm)
R refresh now
SPACE select next target (nearest-first order)
L follow: lock the scope onto the selected aircraft
1-9 A-F select the target with that slot number
0 clear selection
M sound on/off
OPTION locations & configuration screen
HELP or ? help page
SELECT at boot force 40 columns this session (emergency override)

A * in the status corner means an SIO transfer is in progress (input is queued during it); the spinning arrow means idle time between polls.

Locations & configuration screen (OPTION)

Four profiles, A-D. Each holds a label, coordinates, range and the centre airport's runway geometry.

Key Action
A-D activate a profile (or park the cursor on an empty slot)
E set the active profile from an ICAO code - coordinates and runways resolved online (aviationweather.gov)
L set it from raw lat/lon (decimal degrees, e.g. 50.0777 19.7848), then a label
N cycle source: DIRECT (adsb.fi) / SERVER / RECEIVER (128 KB only)
H server or receiver host (empty = default public server)
V 40/80 column video mode (GTIA2RGB only; switches live)
S save everything to FujiNet appkeys
ESC / any console key back to the radar

Settings persist only after S (and need an SD card in the FujiNet).

Data sources

DIRECT (default). The Atari talks straight to adsb.fi open data over N:HTTPS and scans the JSON body itself; airport/METAR lookups go to aviationweather.gov. Zero infrastructure, ~11 s refresh (deliberately gentle toward the free community API).

SERVER. A tiny relay (server/) fetches and caches adsb.fi and serves a compact ~0.5 KB binary blob instead of multi-kilobyte JSON. The Atari polls it every ~5 s: fresher picture, denser trails, snappier UI, and a fraction of the WiFi airtime.

A public instance runs at fujiatc.rustybits.pl - it is the built-in default, so switching the source to SERVER (N, then S) is all it takes. Fair use welcome; note the instance logs client IP addresses for abuse protection (see the privacy note in server/README.md). To run your own, see the same README - one Python file, stdlib only, docker-compose optional. Enter its address with H: a bare hostname is spoken to over HTTPS, a host:port form over plain HTTP (handy on the LAN).

RECEIVER (128 KB machines only). Point the Atari straight at a local dump1090-fa / readsb / tar1090 aircraft.json over plain HTTP on the LAN - no server, no internet. Set the source to RECEIVER (N) and the host with H (a bare IP gets /data/aircraft.json appended; a host with a path is used as-is). 64 KB machines don't carry this code - they use the server's receiver source instead (see server/README.md).

All sources fill the same aircraft model - every screen feature works identically with any of them.

How it works

Transport

fujinet-lib over the N: device. The traffic poll opens one HTTPS GET and consumes the raw body through a ~300-byte streaming JSON scanner (direct mode) or a fixed-layout binary blob (server mode). The FujiNet firmware's JSON parse/query channel is deliberately NOT used for traffic: on real SIO it proved unreliable for big documents (the scalar-query path is fine and still serves the airport resolver).

Hard-won SIO rules

Rules inherited from FujiGPT and re-verified on FujiATC's own hardware tests:

  1. Never read more than STATUS reports waiting. A read from an empty N: buffer is NAKed (error 144) on real hardware.
  2. No WSYNC-heavy DLI during a long SIO data frame - it delays SERIN long enough to drop a byte at 19200 baud, the OS silently retries, and FujiNet reads are not idempotent. FujiATC's 40-column screen gates its rainbow DLI off around transfers; the 80-column Mode 3 screen needs no DLI at all (colour is data), which kills the whole conflict.
  3. Rotate N: units between requests (N1..N4) so an aborted transfer's leftover bytes can never bleed into the next one.
  4. Sample the keyboard between chunks - a pending key ends the body scan early; the slot TTLs cover the missed remainder.

Display

  • 80 columns (GTIA2RGB): COL80 Mode 3 - per-cell chroma+luma attributes, the full Atari palette per character. The FPGA is probed at boot ($D01E returns $0A), the OS charset is uploaded in ATASCII order and overlaid with the radar's icon glyphs (aircraft arrows in 8 headings, trail dots, runway segments). Every mode F line carries its own LMS and the layout skips the 4 KB ANTIC boundary, so no wrap hazards.
  • 40 columns: direct writes to the OS GR.0 screen; on GTIA2RGB the HRBICOLOR override gives hi-res text real colour and the rainbow title DLI works FujiGPT-style.
  • The keyboard is read via the K: handler vector directly - cc65's conio cursor handling corrupts screen bytes through OLDADR.

Configuration storage

FujiNet appkeys, creator id 0x484A 'HJ', app id 0x02 (FujiGPT holds 0x01 - the two coexist). Key 0: header (active profile, video mode, source). Keys 1-4: one profile each (label, lat/lon, range, runway geometry). Key 5: server host. All profiles are held in RAM; S writes everything.

Memory map (g2r builds)

Region Contents
$0480-$06FF page 4-6 scratch: devicespec, parse fields, METAR
$2000-$9640 program + C stack
$9800-$AF53 COL80 Mode 3 screen + display list
$B000-$B7FF loaded constants (icons, tables) + network buffer
$B800-$BC1F aircraft table, config, trails
$BC20+ OS GR.0 screen (the 40-column fallback, kept intact)

The 64 KB budget is essentially full - that is what the xe* banks are for, next.

Building

Windows: build.bat <variant>, Linux/macOS: ./build.sh <variant|all> with xeg2r / xe / xlg2r / xl. Needs cc65 (CC65_HOME or on PATH); fujinet-lib 4.11.2 downloads automatically on first build. Output lands in bin/.

Server

See server/README.md: endpoints, deployment (bare Python / docker compose / docker compose behind Traefik), environment variables, the private dashboard and the privacy note.

Roadmap

  • Follow mode (lock the scope onto one aircraft) + flight routes
  • Own ADS-B receivers as server sources (readsb aircraft.json, SBS)
  • 128 KB features: traffic replay, map/zoom caches
  • Coastline map layer (server-side, Natural Earth)

Credits

Credits for original idea go to k6lcm - check out his nes-radar and c64u-radar

Traffic data: adsb.fi community feeders. Airport, runway and METAR data: aviationweather.gov. Network/display groundwork: FujiGPT (same author).

HanJammer / Rusty Bits 2026

About

An Air Traffic viewer for Atari 8-bit computers, powered by FujiNet.

Resources

Stars

0 stars

Watchers

0 watching

Forks

Releases

Packages

Contributors

Languages