See Notes for device, build, and resource information
The first phase Proof of Concept repo on GitHub
- Python 3
- Hamlib Python bindings for CAT/radio-control scripts
You will need to obtain the Audiowide-Regular.ttf font from Google and place it in the fonts subdirectory.
Install Hamlib on Debian/Raspberry Pi OS:
sudo apt install python3-hamlibIf your platform does not provide python3-hamlib, use pip:
pip install hamlibpython3 radio_app.pypython3 display_demo.pyNOTE: the configuration file ft818_cat_demo_config.json is set up for a radio connected to /dev/ttyUSB0 with a baud rate of 9600. You may need to adjust these settings for your radio and connection.
If you are using the LDG Z-817 tuner, you will need to adjust the configuration file baud rate to 4800.
python3 ft818_radio_app.pyThis app uses Hamlib to control FT-818 features from the 4 HAT buttons.
- Button 1: force full display refresh
- Button 2: band up
- Button 3: cycle tuning step
- Button 4: shutdown (same as pressing all 4 buttons)
- Button 1+2: band up
- Button 3+4: band down
- Button 1+3: frequency increment (by current tuning step)
- Button 2+4: frequency decrement (by current tuning step)
- All 4 buttons: shutdown
Display protection policy:
- full-screen refresh no faster than every 3.0 seconds
- partial refresh no faster than every 0.5 seconds
- automatic full-screen refresh after 5 seconds of inactivity when 2 or more partial refreshes have occurred
Run it with:
python3 ft818_radio_app.pyft818_radio_app.py is the current runtime entry point for the FT-818 app. It loads configuration, opens the Hamlib rig, constructs the display and radio state objects, and then runs the main loop that ties input handling, CAT polling, and ePaper refreshes together. In the current prototype, GPIO buttons are the active input source, but they should be treated as one replaceable input module rather than a permanent architectural requirement.
flowchart LR
config["ft818_config.json\nradio / polling / ft818_app settings"]
hamlib["Hamlib Rig\nexternal CAT control"]
subgraph app["ft818_radio_app.py"]
main["main()"]
controller["FT818RigController\nHamlib write + refresh wrapper"]
end
subgraph poller["ft818_poller.py"]
pollerFns["load_config()\nbuild_rig()\npoll_radio()\nfreq_to_band()"]
end
subgraph state["radio.py"]
radio["Radio\nobservable UI state model"]
end
subgraph input["button_state_manager.py"]
buttons["ButtonStateManager\nGPIO button reader"]
end
subgraph futureInput["future input options"]
touch["touchscreen UI"]
encoder["rotary encoder"]
remote["remote / network control"]
auto["status-only / automation"]
end
subgraph commands["radio_command_handler.py"]
buttonState["ButtonState"]
handler["RadioCommandHandler\ncurrent command dispatcher"]
end
subgraph displayFile["radio_display.py"]
display["RadioDisplay\nrender + refresh policy"]
end
subgraph epdFile["lib/epd2in7_V2.py"]
epd["EPD\nWaveshare display driver"]
end
main -->|loads| config
main -->|uses| pollerFns
pollerFns -->|creates and polls| hamlib
main -->|creates| controller
main -->|creates| radio
main -->|creates| display
main -->|creates| handler
main -->|creates| buttons
main -->|instantiates| epd
controller -->|wraps| hamlib
controller -->|reuses poll helpers| pollerFns
controller -->|updates snapshot| radio
buttons -->|current implementation returns| buttonState
buttonState -->|translated into commands by| handler
touch -->|future commands| handler
encoder -->|future commands| handler
remote -->|future commands| handler
auto -->|future commands or no commands| handler
handler -->|dispatches actions to| controller
handler -->|can request refresh/shutdown via| display
handler -->|fallback state updates| radio
radio -->|observer notifications| display
display -->|draws through| epd
At runtime, the current main loop reads GPIO button states through ButtonStateManager, routes them through RadioCommandHandler, applies CAT commands through FT818RigController, refreshes the shared Radio snapshot from Hamlib poll data, and lets RadioDisplay redraw the ePaper panel when the observable state changes.
The important architectural boundary is between input generation and command execution. Buttons are just one way to generate commands. A future hardware revision could replace them with a touchscreen, a rotary encoder, remote control, or even a display-only status mode while still keeping the same radio-state, polling, and display layers.
