From 92c0a239a27107be47047d49a11ac6ac20a5cd2a Mon Sep 17 00:00:00 2001 From: Light-Fighter-Manifesto Date: Thu, 5 Feb 2026 23:59:43 -0500 Subject: [PATCH] Add v1.0 image build system and configuration files - Add image/build.sh: Automated Pi image builder for ReticulumHF v1.0 - Add configs/: System configuration files (hostapd, dnsmasq, ALSA, radios DB) - Add scripts/wait-for-port: Service dependency utility - Update .gitignore: Exclude .claude/ and test files This release includes the complete build infrastructure for creating ReticulumHF Raspberry Pi images with pre-configured WiFi AP, web portal, and Reticulum gateway services. --- .gitignore | 7 + configs/asound.conf | 51 ++ configs/dnsmasq.conf | 21 + configs/hostapd-rfkill.conf | 2 + configs/hostapd.conf | 22 + configs/radios.json | 1251 +++++++++++++++++++++++++++++++++++ image/build.sh | 331 +++++++++ scripts/wait-for-port | 16 + 8 files changed, 1701 insertions(+) create mode 100644 configs/asound.conf create mode 100644 configs/dnsmasq.conf create mode 100644 configs/hostapd-rfkill.conf create mode 100644 configs/hostapd.conf create mode 100644 configs/radios.json create mode 100755 image/build.sh create mode 100644 scripts/wait-for-port diff --git a/.gitignore b/.gitignore index 3563380..24b52b5 100644 --- a/.gitignore +++ b/.gitignore @@ -25,3 +25,10 @@ ENV/ # Local configuration .env .env.local + +# Claude Code +.claude/ + +# Test files +test_*.py +*_test.py diff --git a/configs/asound.conf b/configs/asound.conf new file mode 100644 index 0000000..a5a2856 --- /dev/null +++ b/configs/asound.conf @@ -0,0 +1,51 @@ +# ReticulumHF ALSA Configuration +# Configures USB audio device (Digirig or similar) for freedvtnc2 +# +# This file should be installed to /etc/asound.conf + +# Disable the modem PCM type which causes "Unknown PCM cards.pcm.modem" error +# This is a known issue with ALSA when using USB audio devices +pcm.!modem { + type null +} + +ctl.!modem { + type null +} + +# Define USB audio as a named device +# freedvtnc2 uses PortAudio which will enumerate these devices +pcm.usbaudio { + type hw + card 1 + device 0 +} + +ctl.usbaudio { + type hw + card 1 +} + +# Software mixing for USB audio (allows multiple applications to use the device) +pcm.usbmix { + type dmix + ipc_key 1024 + slave { + pcm "usbaudio" + period_time 0 + period_size 1024 + buffer_size 4096 + } +} + +# Duplex device for simultaneous input/output +pcm.usbduplex { + type asym + playback.pcm "usbmix" + capture.pcm "usbaudio" +} + +# Default device - use built-in audio to avoid conflicts +# freedvtnc2 explicitly selects its device via PortAudio +defaults.pcm.card 0 +defaults.ctl.card 0 diff --git a/configs/dnsmasq.conf b/configs/dnsmasq.conf new file mode 100644 index 0000000..b987f7c --- /dev/null +++ b/configs/dnsmasq.conf @@ -0,0 +1,21 @@ +# ReticulumHF - dnsmasq configuration +# Provides DHCP for setup WiFi network + +# Only listen on wlan0 +interface=wlan0 +bind-interfaces + +# DHCP range for connected clients +dhcp-range=192.168.4.10,192.168.4.50,255.255.255.0,24h + +# Set gateway to Pi +dhcp-option=3,192.168.4.1 + +# Set DNS to Pi (for local resolution only) +dhcp-option=6,192.168.4.1 + +# Don't use upstream DNS - no internet through AP +no-resolv + +# Disable captive portal detection redirect +# (Let users manually browse to 192.168.4.1) diff --git a/configs/hostapd-rfkill.conf b/configs/hostapd-rfkill.conf new file mode 100644 index 0000000..7e918f5 --- /dev/null +++ b/configs/hostapd-rfkill.conf @@ -0,0 +1,2 @@ +[Service] +ExecStartPre=/usr/sbin/rfkill unblock wlan diff --git a/configs/hostapd.conf b/configs/hostapd.conf new file mode 100644 index 0000000..1acca92 --- /dev/null +++ b/configs/hostapd.conf @@ -0,0 +1,22 @@ +# ReticulumHF - WiFi Access Point configuration +# Creates "ReticulumHF-Setup" network + +interface=wlan0 +driver=nl80211 +ssid=ReticulumHF-Setup +hw_mode=g +channel=7 +wmm_enabled=0 +macaddr_acl=0 +auth_algs=1 +ignore_broadcast_ssid=0 + +# WPA2 security - default password: reticulumhf +wpa=2 +wpa_passphrase=reticulumhf +wpa_key_mgmt=WPA-PSK +rsn_pairwise=CCMP + +# Country code (US default - users can change) +country_code=US +ieee80211n=1 diff --git a/configs/radios.json b/configs/radios.json new file mode 100644 index 0000000..e9e151e --- /dev/null +++ b/configs/radios.json @@ -0,0 +1,1251 @@ +{ + "version": "1.4.0", + "updated": "2026-02-05", + "notes": "Audio settings for ReticulumHF Pi gateway. freedvtnc2 uses ALSA for audio I/O. Target RX level: -5 dB. ALC guidance varies by manufacturer.", + "alc_notes": { + "xiegu_reversed": "Xiegu G90/X6100 have REVERSED ALC - high ALC (90-100) = good signal. 0 ALC = bad.", + "xiegu_g106": "Xiegu G106 uses normal ALC - keep ≤50 for optimal linearity.", + "icom_sdr": "Icom SDR radios (IC-7300, IC-705, etc): Per Icom manual, keep audio 'within the ALC zone'. Minimal movement is ideal.", + "yaesu_zero": "Yaesu radios: Target ZERO ALC. Adjust until ALC meter just begins to move, then back off slightly.", + "kenwood_zero": "Kenwood radios: Target ZERO ALC. Control power via software audio level, not by driving ALC.", + "elecraft_bars": "Elecraft radios: Target 4 solid ALC bars with 5th bar flickering. Adjust MIC G for this." + }, + "radios": [ + { + "id": "xiegu_g90", + "manufacturer": "Xiegu", + "model": "G90", + "hamlib_id": 3088, + "baud_rate": 19200, + "ptt_method": "RTS", + "audio_interface": "external", + "audio_settings": { + "type": "digirig", + "rx_control": "Digirig ALSA mixer (Mic Capture) + Radio Menu 6", + "tx_control": "Digirig ALSA mixer (Speaker) + Radio Menu 5", + "radio_rx_menu": "Menu 6 (AUX OUT): 10-15", + "radio_tx_menu": "Menu 5 (AUX IN): 8-12", + "recommended_alsa_rx": 75, + "recommended_alsa_tx": 80, + "alc_target": "90-100", + "alc_reversed": true, + "alc_guidance": "G90 ALC is REVERSED: high ALC (90-100) = clean signal. 0 ALC = bad/no modulation. Adjust AUX IN (Menu 5) until ALC reads 90-100 during TX.", + "freedv_notes": "If freedvtnc2 shows input < -10 dB, increase AUX OUT (Menu 6) on radio" + }, + "serial_settings": { + "data_bits": 8, + "stop_bits": 1, + "parity": "none", + "handshake": "none", + "rts_state": "OFF", + "dtr_state": "OFF" + }, + "setup_guide": { + "steps": [ + {"setting": "AGC", "value": "OFF (AGC--)", "how": "Short press [AGC] button"}, + {"setting": "Mode", "value": "U-D (USB Digital)", "how": "Press Mode arrows until U-D"}, + {"setting": "RF Gain", "value": "50%", "how": "Long press [AGC], use VFO knob"}, + {"setting": "AUX IN", "value": "10", "how": "Long press [FUNC] → Menu 5"}, + {"setting": "AUX OUT", "value": "13", "how": "Long press [FUNC] → Menu 6"} + ], + "frequency": "24.930 MHz or any clear HF frequency", + "cable_note": "Use Digirig Mobile with USB 2.0 port (black, not blue)" + }, + "notes": "Blue USB cable uses FTDI chip. Black cables use Prolific - different driver.", + "tested": true, + "power_watts": 20 + }, + { + "id": "xiegu_g106", + "manufacturer": "Xiegu", + "model": "G106", + "hamlib_id": 3088, + "baud_rate": 19200, + "ptt_method": "RTS", + "audio_interface": "external", + "audio_settings": { + "type": "digirig_or_de19", + "connector": "8-pin Mini DIN (ACC port)", + "rx_control": "External interface (DE-19/Digirig) + software", + "tx_control": "External interface (DE-19/Digirig) + software", + "radio_rx_menu": "None - G106 has no internal audio level menus", + "radio_tx_menu": "None - G106 has no internal audio level menus", + "recommended_alsa_rx": 75, + "recommended_alsa_tx": 80, + "alc_target": "≤50", + "alc_reversed": false, + "alc_guidance": "G106 uses normal ALC (not reversed like G90). Keep ALC ≤50 for optimal linearity. Adjust ALSA Speaker level until ALC stays below 50.", + "freedv_notes": "Audio levels controlled entirely by external interface and Pi software. Same ACC pinout as G90." + }, + "serial_settings": { + "data_bits": 8, + "stop_bits": 1, + "parity": "none", + "handshake": "none", + "rts_state": "OFF", + "dtr_state": "OFF" + }, + "setup_guide": { + "steps": [ + {"setting": "Mode", "value": "U-D (USB Digital)", "how": "Press MODE button"}, + {"setting": "AGC", "value": "OFF", "how": "Menu setting"}, + {"setting": "CAT Baud", "value": "19200", "how": "Menu → CAT settings"} + ], + "note": "Requires DE-19 or Digirig. Same 8-pin mini DIN ACC port as G90.", + "sources": ["https://qrper.com/2023/06/an-in-depth-review-of-the-xiegu-g106-qrp-hf-transceiver/"] + }, + "notes": "5W QRP. No built-in USB audio - requires DE-19/Digirig. Same ACC pinout as G90.", + "tested": false, + "power_watts": 5 + }, + { + "id": "xiegu_x6100", + "manufacturer": "Xiegu", + "model": "X6100", + "hamlib_id": 3087, + "baud_rate": 19200, + "ptt_method": "CAT", + "audio_interface": "builtin", + "audio_settings": { + "type": "builtin_usb", + "connector": "USB-C (DEV port)", + "alsa_device": "USB Audio Device", + "rx_control": "Radio menu LINEOUTLV (no ALSA mixer)", + "tx_control": "Radio menu LINEINLV (no ALSA mixer)", + "radio_rx_menu": "RADIO SETTING1 → LINE OUT LV: 30-50", + "radio_tx_menu": "RADIO SETTING1 → LINEINLV: adjust for ALC ≤ 50", + "freedv_notes": "Built-in USB audio has no ALSA mixer controls. Adjust levels via radio menu. If input < -10 dB, increase LINE OUT LV." + }, + "serial_settings": { + "data_bits": 8, + "stop_bits": 1, + "parity": "none", + "handshake": "none", + "rts_state": "ON", + "dtr_state": "ON" + }, + "setup_guide": { + "steps": [ + {"setting": "Mode", "value": "USB-D", "how": "Touch mode selector → USB-D"}, + {"setting": "LINEINLV", "value": "Adjust for ALC ≤ 50", "how": "RADIO SETTING1 → LINEINLV"}, + {"setting": "LINE OUT LV", "value": "30-50", "how": "RADIO SETTING1 → LINE OUT LV"}, + {"setting": "AGC", "value": "OFF", "how": "Settings menu"}, + {"setting": "CAT", "value": "Enable", "how": "Settings → CAT"} + ], + "note": "Built-in USB audio via USB-C DEV port. Single cable for CAT + audio.", + "sources": ["https://oh8stn.org/blog/2022/03/05/xiegu-x6100-winlink-express-setup/"] + }, + "notes": "Portable SDR. Built-in USB audio. Requires Hamlib 4.4+. Keep ALC ≤ 50 for digital.", + "tested": false, + "power_watts": 10 + }, + { + "id": "icom_ic7300", + "manufacturer": "Icom", + "model": "IC-7300", + "hamlib_id": 3073, + "baud_rate": 115200, + "ptt_method": "CAT", + "audio_interface": "builtin", + "audio_settings": { + "type": "builtin_usb", + "alsa_device": "USB Audio CODEC", + "rx_control": "Radio menu only (no ALSA mixer)", + "tx_control": "Radio menu only (no ALSA mixer)", + "radio_rx_menu": "Menu → Connectors → ACC/USB AF Output Level: 30-50%", + "radio_tx_menu": "Menu → Connectors → USB MOD Level: 50%", + "freedv_notes": "Built-in USB audio has NO ALSA mixer controls. All levels via radio menu. If freedvtnc2 shows input < -10 dB, increase ACC/USB AF Output Level." + }, + "serial_settings": { + "data_bits": 8, + "stop_bits": 1, + "parity": "none", + "handshake": "none" + }, + "civ_address": "0x94", + "setup_guide": { + "steps": [ + {"setting": "Mode", "value": "USB-D", "how": "Press MODE, touch DATA to select USB-D"}, + {"setting": "DATA MOD", "value": "USB", "how": "Menu → Connectors → DATA MOD"}, + {"setting": "CI-V Baud Rate", "value": "115200", "how": "Menu → Connectors → CI-V → Baud Rate"}, + {"setting": "CI-V USB Port", "value": "Unlink from Remote", "how": "Menu → Connectors → CI-V"}, + {"setting": "ACC/USB AF Output", "value": "30-50%", "how": "Menu → Connectors → ACC/USB AF Output Level"}, + {"setting": "Filter Width", "value": "3000 Hz", "how": "Touch BW → set to 3.0k"} + ], + "note": "Built-in USB audio. No Digirig needed. Set ACC/USB AF Output Level for proper RX audio to Pi.", + "sources": ["https://wa7ewc.wordpress.com/2016/04/27/icom-ic-7300-digital-mode-settings/"] + }, + "notes": "Built-in USB audio - no external interface needed. Audio levels set via radio menu only.", + "tested": false, + "power_watts": 100 + }, + { + "id": "icom_ic705", + "manufacturer": "Icom", + "model": "IC-705", + "hamlib_id": 3085, + "baud_rate": 115200, + "ptt_method": "CAT", + "audio_interface": "builtin", + "audio_settings": { + "type": "builtin_usb", + "alsa_device": "USB Audio CODEC", + "rx_control": "Radio menu only (no ALSA mixer)", + "tx_control": "Radio menu only (no ALSA mixer)", + "radio_rx_menu": "SET → Connectors → USB AF Output Level: 30-50%", + "radio_tx_menu": "SET → Connectors → USB MOD Level: 50%", + "freedv_notes": "Built-in USB audio has NO ALSA mixer controls. If freedvtnc2 shows input < -10 dB, increase USB AF Output Level in radio menu." + }, + "serial_settings": { + "data_bits": 8, + "stop_bits": 1, + "parity": "none", + "handshake": "none" + }, + "civ_address": "0xA4", + "setup_guide": { + "steps": [ + {"setting": "Mode", "value": "USB-D", "how": "Press MODE → USB-D"}, + {"setting": "DATA MOD", "value": "USB", "how": "SET → Connectors → DATA MOD → USB"}, + {"setting": "USB AF Output Level", "value": "30-50%", "how": "SET → Connectors → USB AF Output Level"}, + {"setting": "CI-V Address", "value": "A4 (default)", "how": "SET → Connectors → CI-V → Address"}, + {"setting": "CI-V Baud Rate", "value": "Auto or 115200", "how": "SET → Connectors → CI-V"} + ], + "note": "Built-in USB audio. Set USB AF Output Level for proper RX audio to Pi.", + "sources": ["https://oh8stn.org/blog/2021/02/02/icom-ic-705-winlink-express-setup/"] + }, + "notes": "Built-in USB audio - no external interface needed. Portable QRP.", + "tested": false, + "power_watts": 10 + }, + { + "id": "icom_ic7100", + "manufacturer": "Icom", + "model": "IC-7100", + "hamlib_id": 3070, + "baud_rate": 19200, + "ptt_method": "CAT", + "audio_interface": "builtin", + "audio_settings": { + "type": "builtin_usb", + "alsa_device": "USB Audio CODEC", + "rx_control": "Radio menu only (no ALSA mixer)", + "tx_control": "Radio menu only (no ALSA mixer)", + "radio_rx_menu": "SET → Connectors → USB AF Output Level: 30-50%", + "radio_tx_menu": "SET → Connectors → USB MOD Level: 50%", + "freedv_notes": "Built-in USB audio has NO ALSA mixer controls. Adjust USB AF Output Level if input < -10 dB." + }, + "serial_settings": { + "data_bits": 8, + "stop_bits": 1, + "parity": "none", + "handshake": "none" + }, + "civ_address": "0x88", + "setup_guide": { + "steps": [ + {"setting": "Mode", "value": "USB-D", "how": "Touch MODE → USB-D"}, + {"setting": "USB AF Output Level", "value": "30-50%", "how": "SET → Connectors → USB AF Output Level"}, + {"setting": "CI-V Baud Rate", "value": "19200", "how": "SET → Connectors → CI-V Baud Rate"}, + {"setting": "DATA MOD", "value": "USB", "how": "SET → Connectors → DATA MOD"} + ], + "note": "Built-in USB audio. PTT via CAT (CI-V).", + "sources": ["https://support.hamradiodeluxe.com/support/solutions/articles/51000083391-ic-7100-usb-configuration"] + }, + "notes": "Built-in USB audio - no external interface needed.", + "tested": false, + "power_watts": 100 + }, + { + "id": "icom_ic718", + "manufacturer": "Icom", + "model": "IC-718", + "hamlib_id": 3013, + "baud_rate": 9600, + "ptt_method": "RTS", + "audio_interface": "external", + "audio_settings": { + "type": "digirig", + "rx_control": "Digirig ALSA mixer (Capture/Mic) + Radio AF Gain", + "tx_control": "Digirig ALSA mixer (Speaker/PCM) + Radio MIC Gain", + "radio_rx_menu": "AF Gain knob on front panel", + "radio_tx_menu": "MIC Gain knob on front panel", + "recommended_alsa_rx": 75, + "recommended_alsa_tx": 80, + "freedv_notes": "No built-in USB audio. Requires Digirig/SignaLink. Adjust radio AF Gain if input < -10 dB." + }, + "serial_settings": { + "data_bits": 8, + "stop_bits": 1, + "parity": "none", + "handshake": "none" + }, + "civ_address": "0x5E", + "setup_guide": { + "steps": [ + {"setting": "Mode", "value": "USB", "how": "Press USB button"}, + {"setting": "CI-V Baud", "value": "9600", "how": "Menu → CI-V → Baud"}, + {"setting": "CI-V Address", "value": "5E", "how": "Menu → CI-V → Address"} + ], + "note": "Requires external interface (Digirig). CAT PTT may not work - use VOX if needed." + }, + "notes": "Entry-level HF. No built-in USB audio - requires Digirig or SignaLink.", + "tested": false, + "power_watts": 100 + }, + { + "id": "icom_ic7200", + "manufacturer": "Icom", + "model": "IC-7200", + "hamlib_id": 3061, + "baud_rate": 19200, + "ptt_method": "CAT", + "audio_interface": "builtin", + "audio_settings": { + "type": "builtin_usb", + "alsa_device": "USB Audio CODEC", + "rx_control": "Radio menu only (no ALSA mixer)", + "tx_control": "Radio menu only (no ALSA mixer)", + "radio_rx_menu": "USB AF Output Level: 30-50%", + "radio_tx_menu": "USB MOD Level: 50%", + "freedv_notes": "Built-in USB audio. Adjust USB AF Output Level if input < -10 dB." + }, + "serial_settings": { + "data_bits": 8, + "stop_bits": 1, + "parity": "none", + "handshake": "none" + }, + "civ_address": "0x76", + "setup_guide": { + "steps": [ + {"setting": "Mode", "value": "USB-D", "how": "Press MODE → select USB-D"}, + {"setting": "USB AF Output Level", "value": "30-50%", "how": "Set mode → USB AF Output"}, + {"setting": "USB MOD Level", "value": "50%", "how": "Set mode → USB MOD"}, + {"setting": "CI-V Baud", "value": "19200", "how": "Set mode → CI-V"} + ], + "note": "Built-in USB audio. Rugged field radio." + }, + "notes": "Built-in USB audio - no external interface needed. Rugged field radio.", + "tested": false, + "power_watts": 100 + }, + { + "id": "icom_ic7610", + "manufacturer": "Icom", + "model": "IC-7610", + "hamlib_id": 3078, + "baud_rate": 115200, + "ptt_method": "CAT", + "audio_interface": "builtin", + "audio_settings": { + "type": "builtin_usb", + "alsa_device": "USB Audio CODEC", + "rx_control": "Radio menu only (no ALSA mixer)", + "tx_control": "Radio menu only (no ALSA mixer)", + "radio_rx_menu": "Menu → Connectors → ACC/USB AF Output Level: 30-50%", + "radio_tx_menu": "Menu → Connectors → USB MOD Level: 50%", + "freedv_notes": "Built-in USB audio. Adjust ACC/USB AF Output Level if input < -10 dB. Use USB 1 port." + }, + "serial_settings": { + "data_bits": 8, + "stop_bits": 1, + "parity": "none", + "handshake": "none" + }, + "civ_address": "0x98", + "setup_guide": { + "steps": [ + {"setting": "Mode", "value": "USB-D1", "how": "Touch SSB → USB-D1 for data mode"}, + {"setting": "ACC/USB AF Output", "value": "30-50%", "how": "Menu → Connectors → ACC/USB AF Output Level"}, + {"setting": "CI-V Baud Rate", "value": "115200", "how": "Menu → Connectors → CI-V → Baud Rate"}, + {"setting": "DATA MOD", "value": "USB", "how": "Menu → Connectors → DATA MOD"}, + {"setting": "USB Port", "value": "USB 1", "how": "Use USB 1 (closest to speaker) for CAT/audio"} + ], + "note": "Built-in USB audio. Use USB 1 port for CAT/audio.", + "sources": ["https://support.hamradiodeluxe.com/support/solutions/articles/51000083466-ic-7610-usb-setup-configuration"] + }, + "notes": "Built-in USB audio - no external interface needed. Dual-watch SDR flagship.", + "tested": false, + "power_watts": 100 + }, + { + "id": "yaesu_ft891", + "manufacturer": "Yaesu", + "model": "FT-891", + "hamlib_id": 1036, + "baud_rate": 38400, + "ptt_method": "RTS", + "ptt_on_delay_ms": 300, + "ptt_off_delay_ms": 200, + "audio_interface": "external", + "audio_settings": { + "type": "digirig", + "connector": "6-pin Mini DIN (DATA port)", + "rx_control": "Digirig ALSA mixer + Radio Menu 08-07", + "tx_control": "Digirig ALSA mixer + Radio Menu 08-08", + "radio_rx_menu": "Menu 08-07 (DATA OUT Level): 50", + "radio_tx_menu": "Menu 08-08 (DATA IN Level): 50", + "recommended_alsa_rx": 75, + "recommended_alsa_tx": 80, + "freedv_notes": "Requires Digirig/SignaLink. If input < -10 dB, increase Menu 08-07 (DATA OUT Level)." + }, + "serial_settings": { + "data_bits": 8, + "stop_bits": 2, + "parity": "none", + "handshake": "none", + "rts_state": "OFF", + "dtr_state": "OFF" + }, + "setup_guide": { + "steps": [ + {"setting": "Mode", "value": "DATA-U (shows D-U)", "how": "Press MODE until DATA"}, + {"setting": "Menu 05-06 (CAT Rate)", "value": "38400", "how": "Menu → 05-06"}, + {"setting": "Menu 08-01 (DATA Mode)", "value": "OTHERS", "how": "Menu → 08-01 (NOT PSK)"}, + {"setting": "Menu 08-07 (DATA OUT Level)", "value": "50", "how": "Menu → 08-07 (RX audio to Pi)"}, + {"setting": "Menu 08-08 (DATA IN Level)", "value": "50", "how": "Menu → 08-08 (TX audio from Pi)"}, + {"setting": "Menu 08-09 (DATA IN)", "value": "REAR", "how": "Menu → 08-09"}, + {"setting": "Menu 08-10 (DATA PTT)", "value": "RTS", "how": "Menu → 08-10"} + ], + "note": "Requires external interface. DATA port is 6-pin mini DIN.", + "sources": ["https://themodernham.com/ft-891-the-ultimate-digital-settings-menu-guide-for-digital-modes/"] + }, + "notes": "No built-in USB audio - requires Digirig or SignaLink.", + "tested": false, + "power_watts": 100 + }, + { + "id": "yaesu_ft991", + "manufacturer": "Yaesu", + "model": "FT-991/991A", + "hamlib_id": 1035, + "baud_rate": 38400, + "ptt_method": "RTS", + "ptt_on_delay_ms": 300, + "ptt_off_delay_ms": 200, + "audio_interface": "builtin", + "audio_settings": { + "type": "builtin_usb", + "alsa_device": "USB Audio CODEC (Silicon Labs)", + "rx_control": "Radio menu (limited ALSA control)", + "tx_control": "Radio menu (limited ALSA control)", + "radio_rx_menu": "Menu 067 (DATA OUT Level): 50", + "radio_tx_menu": "Menu 068 (DATA IN Level): 50", + "freedv_notes": "Built-in USB audio. If input < -10 dB, increase Menu 067 (DATA OUT Level)." + }, + "serial_settings": { + "data_bits": 8, + "stop_bits": 2, + "parity": "none", + "handshake": "none", + "rts_state": "OFF", + "dtr_state": "OFF" + }, + "setup_guide": { + "steps": [ + {"setting": "Mode", "value": "DATA-USB (shows D-U)", "how": "Press MODE until DATA-USB"}, + {"setting": "Menu 031 (CAT Rate)", "value": "38400", "how": "Menu → 031"}, + {"setting": "Menu 062 (DATA Mode)", "value": "OTHERS", "how": "Menu → 062 (NOT PSK)"}, + {"setting": "Menu 067 (DATA OUT Level)", "value": "50", "how": "Menu → 067 (RX audio to Pi)"}, + {"setting": "Menu 068 (DATA IN Level)", "value": "50", "how": "Menu → 068 (TX audio from Pi)"}, + {"setting": "Menu 071 (DATA PTT)", "value": "RTS", "how": "Menu → 071"} + ], + "note": "Built-in USB audio. Silicon Labs driver.", + "sources": ["https://www.n1rwy.org/?p=157/", "https://www.qsl.net/cm-arc/Yaesu%20FT991A%20Digital.pdf"] + }, + "notes": "Built-in USB audio - no external interface needed.", + "tested": false, + "power_watts": 100 + }, + { + "id": "yaesu_ft817", + "manufacturer": "Yaesu", + "model": "FT-817", + "hamlib_id": 1020, + "baud_rate": 9600, + "ptt_method": "RTS", + "ptt_on_delay_ms": 350, + "ptt_off_delay_ms": 250, + "audio_interface": "external", + "audio_settings": { + "type": "digirig", + "connector": "6-pin Mini DIN (DATA port)", + "rx_control": "Digirig ALSA mixer (Capture/Mic)", + "tx_control": "Digirig ALSA mixer (Speaker/PCM) + Radio Menu 25", + "radio_rx_menu": "No RX level menu - use Digirig ALSA and AF Gain knob", + "radio_tx_menu": "Menu 25 (DIG MIC): 50 (TX audio sensitivity)", + "recommended_alsa_rx": 75, + "recommended_alsa_tx": 80, + "freedv_notes": "Requires Digirig. Use DIG mode (not USB). Adjust AF Gain knob and ALSA Capture if input < -10 dB." + }, + "serial_settings": { + "data_bits": 8, + "stop_bits": 2, + "parity": "none", + "handshake": "none", + "rts_state": "OFF", + "dtr_state": "OFF" + }, + "setup_guide": { + "steps": [ + {"setting": "Mode", "value": "DIG", "how": "Press MODE until DIG shows"}, + {"setting": "Menu 25 (DIG MIC)", "value": "50", "how": "Menu → 25 (TX audio level)"}, + {"setting": "Menu 26 (DIG Mode)", "value": "USER-U", "how": "Menu → 26"}, + {"setting": "Menu 14 (CAT Rate)", "value": "9600", "how": "Menu → 14"}, + {"setting": "Menu 40 (PKT Rate)", "value": "1200", "how": "Menu → 40"} + ], + "note": "QRP legend. Use DIG mode. Connect to DATA port (6-pin mini-DIN).", + "sources": ["https://km1ndy.com/yaesu-818-digital-modes-wsjt-x-digirig-setup/", "https://oh8stn.org/blog/2018/02/01/yaesu-ft817-data-mode-settings/"] + }, + "notes": "QRP legend. Requires external interface. PKT rate must be 1200.", + "tested": false, + "power_watts": 5 + }, + { + "id": "yaesu_ft818", + "manufacturer": "Yaesu", + "model": "FT-818", + "hamlib_id": 1020, + "baud_rate": 9600, + "ptt_method": "RTS", + "ptt_on_delay_ms": 350, + "ptt_off_delay_ms": 250, + "audio_interface": "external", + "audio_settings": { + "type": "digirig", + "connector": "6-pin Mini DIN (DATA port)", + "rx_control": "Digirig ALSA mixer (Capture/Mic)", + "tx_control": "Digirig ALSA mixer (Speaker/PCM) + Radio Menu 25", + "radio_rx_menu": "No RX level menu - use Digirig ALSA and AF Gain knob", + "radio_tx_menu": "Menu 25 (DIG MIC): 50 (TX audio sensitivity)", + "recommended_alsa_rx": 75, + "recommended_alsa_tx": 80, + "freedv_notes": "Same as FT-817. Requires Digirig. Adjust AF Gain knob and ALSA Capture if input < -10 dB." + }, + "serial_settings": { + "data_bits": 8, + "stop_bits": 2, + "parity": "none", + "handshake": "none", + "rts_state": "OFF", + "dtr_state": "OFF" + }, + "setup_guide": { + "steps": [ + {"setting": "Mode", "value": "DIG-U", "how": "Press MODE until DIG"}, + {"setting": "Menu 25 (DIG MIC)", "value": "50", "how": "Menu → 25 (TX audio level)"}, + {"setting": "Menu 14 (DIG Mode)", "value": "USER-U", "how": "Menu → 14"}, + {"setting": "Menu 26 (CAT Rate)", "value": "9600", "how": "Menu → 26"}, + {"setting": "Menu 62 (CAT/Linear)", "value": "CAT", "how": "Menu → 62"} + ], + "note": "FT-817 successor. Same settings. Connect to DATA port for audio." + }, + "notes": "FT-817 successor. Requires external interface.", + "tested": true, + "power_watts": 6 + }, + { + "id": "yaesu_ft857", + "manufacturer": "Yaesu", + "model": "FT-857", + "hamlib_id": 1022, + "baud_rate": 9600, + "ptt_method": "RTS", + "ptt_on_delay_ms": 300, + "ptt_off_delay_ms": 200, + "audio_interface": "external", + "audio_settings": { + "type": "digirig", + "connector": "6-pin Mini DIN (DATA port)", + "rx_control": "Digirig ALSA mixer (Capture/Mic)", + "tx_control": "Digirig ALSA mixer (Speaker/PCM) + Radio Menu 37", + "radio_rx_menu": "No RX level menu - use Digirig ALSA and AF Gain knob", + "radio_tx_menu": "Menu 37 (DIG GAIN): 5-50 (start low, adjust up)", + "recommended_alsa_rx": 75, + "recommended_alsa_tx": 80, + "freedv_notes": "Requires Digirig. DIG GAIN default of 50 may be too high - start at 5-10." + }, + "serial_settings": { + "data_bits": 8, + "stop_bits": 2, + "parity": "none", + "handshake": "none", + "rts_state": "OFF", + "dtr_state": "OFF" + }, + "setup_guide": { + "steps": [ + {"setting": "Mode", "value": "DIG-U", "how": "Press MODE until DIG"}, + {"setting": "Menu 19 (CAT Rate)", "value": "9600", "how": "Menu → 19"}, + {"setting": "Menu 20 (CAT/Linear)", "value": "CAT", "how": "Menu → 20"}, + {"setting": "Menu 37 (DIG GAIN)", "value": "10", "how": "Menu → 37 (TX audio, start low)"}, + {"setting": "Menu 38 (DIG Mode)", "value": "USER-U", "how": "Menu → 38"} + ], + "note": "All-band mobile. Use DATA connector (6-pin mini-DIN) for audio." + }, + "notes": "Menu 19: CAT RATE. Menu 37: DIG GAIN (TX level). Requires external interface.", + "tested": false, + "power_watts": 100 + }, + { + "id": "yaesu_ft897", + "manufacturer": "Yaesu", + "model": "FT-897", + "hamlib_id": 1023, + "baud_rate": 9600, + "ptt_method": "RTS", + "ptt_on_delay_ms": 300, + "ptt_off_delay_ms": 200, + "audio_interface": "external", + "audio_settings": { + "type": "digirig", + "connector": "6-pin Mini DIN (DATA port)", + "rx_control": "Digirig ALSA mixer (Capture/Mic)", + "tx_control": "Digirig ALSA mixer (Speaker/PCM) + Radio Menu 37", + "radio_rx_menu": "No RX level menu - use Digirig ALSA and AF Gain knob", + "radio_tx_menu": "Menu 37 (DIG GAIN): 5-50 (start low, adjust up)", + "recommended_alsa_rx": 75, + "recommended_alsa_tx": 80, + "freedv_notes": "Same as FT-857. Requires Digirig. DIG GAIN default of 50 may be too high." + }, + "serial_settings": { + "data_bits": 8, + "stop_bits": 2, + "parity": "none", + "handshake": "none", + "rts_state": "OFF", + "dtr_state": "OFF" + }, + "setup_guide": { + "steps": [ + {"setting": "Mode", "value": "DIG-U", "how": "Press MODE until DIG"}, + {"setting": "Menu 19 (CAT Rate)", "value": "9600", "how": "Menu → 19"}, + {"setting": "Menu 20 (CAT/Linear)", "value": "CAT", "how": "Menu → 20"}, + {"setting": "Menu 37 (DIG GAIN)", "value": "10", "how": "Menu → 37 (TX audio, start low)"}, + {"setting": "Menu 38 (DIG Mode)", "value": "USER-U", "how": "Menu → 38"} + ], + "note": "Same settings as FT-857. Built-in battery option." + }, + "notes": "Menu 19: CAT RATE. Menu 37: DIG GAIN. Requires external interface.", + "tested": false, + "power_watts": 100 + }, + { + "id": "kenwood_ts590", + "manufacturer": "Kenwood", + "model": "TS-590SG", + "hamlib_id": 2037, + "baud_rate": 115200, + "ptt_method": "CAT", + "ptt_on_delay_ms": 250, + "ptt_off_delay_ms": 150, + "audio_interface": "builtin", + "audio_settings": { + "type": "builtin_usb", + "alsa_device": "USB Audio CODEC (PCM2903B)", + "rx_control": "Radio Menu 72 only (no ALSA mixer)", + "tx_control": "Radio Menu 71 only (no ALSA mixer)", + "radio_rx_menu": "Menu 72 (RX Audio): 5-7 (0-9 range)", + "radio_tx_menu": "Menu 71 (TX Audio): 1 (0-9 range, start low)", + "freedv_notes": "Built-in USB audio has NO useful ALSA mixer. All levels via radio Menu 71/72. Power cycle after changing Menu 68." + }, + "serial_settings": { + "data_bits": 8, + "stop_bits": 1, + "parity": "none", + "handshake": "none", + "rts_state": "OFF", + "dtr_state": "OFF" + }, + "setup_guide": { + "steps": [ + {"setting": "Mode", "value": "USB-DATA", "how": "Press MODE → USB, then press DATA key"}, + {"setting": "Menu 68 (USB Baud)", "value": "115200", "how": "Menu 68, then power cycle"}, + {"setting": "Menu 69 (USB Line)", "value": "USB", "how": "Menu 69 (select USB for audio)"}, + {"setting": "Menu 71 (TX Audio)", "value": "1", "how": "Menu 71 (start low, adjust up)"}, + {"setting": "Menu 72 (RX Audio)", "value": "6", "how": "Menu 72 (RX audio to Pi)"}, + {"setting": "Menu 29 (Data Filter)", "value": "2", "how": "Menu 29 (width+center mode)"} + ], + "note": "Built-in USB audio. MUST power cycle after changing baud rate. Use USB-DATA mode.", + "sources": ["https://sites.google.com/view/kc2rgw/home/kenwood-ts-590sg-digital-mode-setup", "https://www.kenwood.com/i/products/info/amateur/ts_590g/pdf/ts590_g_ft8_settings_en.pdf"] + }, + "notes": "Built-in USB audio. Menu 71/72 control levels (no ALSA mixer). Power cycle after Menu 68 change.", + "tested": false, + "power_watts": 100 + }, + { + "id": "kenwood_ts480", + "manufacturer": "Kenwood", + "model": "TS-480", + "hamlib_id": 2028, + "baud_rate": 57600, + "ptt_method": "RTS", + "ptt_on_delay_ms": 300, + "ptt_off_delay_ms": 200, + "audio_interface": "external", + "audio_settings": { + "type": "digirig", + "connector": "6-pin Mini DIN (DATA port)", + "rx_control": "Digirig ALSA mixer + Radio Menu 47", + "tx_control": "Digirig ALSA mixer + Radio Menu 46", + "radio_rx_menu": "Menu 47 (DATA AF Output): 4-5 (0-9 range)", + "radio_tx_menu": "Menu 46 (DATA AF Input): 4-5 (0-9 range)", + "recommended_alsa_rx": 75, + "recommended_alsa_tx": 80, + "freedv_notes": "Requires Digirig. PTT must use DTS pin (pin 3) for DATA audio. Menu 60 (DATA VOX) should be OFF." + }, + "serial_settings": { + "data_bits": 8, + "stop_bits": 1, + "parity": "none", + "handshake": "none", + "rts_state": "OFF", + "dtr_state": "OFF" + }, + "setup_guide": { + "steps": [ + {"setting": "Mode", "value": "USB", "how": "Press MODE"}, + {"setting": "Menu 46 (DATA AF In)", "value": "4", "how": "Menu 46 (TX audio level)"}, + {"setting": "Menu 47 (DATA AF Out)", "value": "4", "how": "Menu 47 (RX audio level)"}, + {"setting": "Menu 56 (Baud Rate)", "value": "57600", "how": "Menu 56"}, + {"setting": "Menu 60 (DATA VOX)", "value": "OFF", "how": "Menu 60 (use CAT PTT)"} + ], + "note": "Use 6-pin mini DIN DATA connector. PTT via DTS pin required for DATA audio." + }, + "notes": "No built-in USB audio - requires Digirig. Use DATA connector.", + "tested": false, + "power_watts": 100 + }, + { + "id": "kenwood_ts2000", + "manufacturer": "Kenwood", + "model": "TS-2000", + "hamlib_id": 2014, + "baud_rate": 57600, + "ptt_method": "RTS", + "ptt_on_delay_ms": 300, + "ptt_off_delay_ms": 200, + "audio_interface": "external", + "audio_settings": { + "type": "digirig", + "connector": "13-pin DIN (ACC2 port)", + "rx_control": "Digirig ALSA mixer + Radio Menu 50C", + "tx_control": "Digirig ALSA mixer + Radio Menu 50B", + "radio_rx_menu": "Menu 50C (Main AF Output): 4 (0-9 range)", + "radio_tx_menu": "Menu 50B (AF Input): 4 (0-9 range)", + "recommended_alsa_rx": 75, + "recommended_alsa_tx": 80, + "freedv_notes": "Requires Digirig. Use PTT pin 9 (mutes mic). CRITICAL: Menu 50F must be 1200 - setting to 9600 mutes ACC2 audio!" + }, + "serial_settings": { + "data_bits": 8, + "stop_bits": 1, + "parity": "none", + "handshake": "none", + "rts_state": "OFF", + "dtr_state": "OFF" + }, + "setup_guide": { + "steps": [ + {"setting": "Mode", "value": "USB", "how": "Press MODE → USB"}, + {"setting": "Menu 50A (Packet Filter)", "value": "OFF", "how": "Menu 50A"}, + {"setting": "Menu 50B (AF Input)", "value": "4", "how": "Menu 50B (TX audio)"}, + {"setting": "Menu 50C (Main AF Out)", "value": "4", "how": "Menu 50C (RX audio)"}, + {"setting": "Menu 50F (TNC Speed)", "value": "1200", "how": "Menu 50F (CRITICAL: 9600 mutes audio!)"}, + {"setting": "Menu 56 (Baud Rate)", "value": "57600", "how": "Menu 56"} + ], + "note": "Use ACC2 (13-pin DIN). PTT pin 9 mutes mic. Menu 50F=9600 will mute audio!" + }, + "notes": "No built-in USB audio - requires Digirig. Use ACC2 connector. Menu 50F MUST be 1200.", + "tested": false, + "power_watts": 100 + }, + { + "id": "elecraft_kx3", + "manufacturer": "Elecraft", + "model": "KX3", + "hamlib_id": 2045, + "baud_rate": 38400, + "ptt_method": "RTS", + "ptt_on_delay_ms": 250, + "ptt_off_delay_ms": 150, + "audio_interface": "external", + "audio_settings": { + "type": "external_usb_soundcard", + "connector": "3.5mm TRRS MIC jack (TX in) + 3.5mm Phones jack (RX out)", + "rx_control": "External soundcard ALSA + Radio AF menu", + "tx_control": "External soundcard ALSA + Radio MIC G menu", + "radio_rx_menu": "AF: 2-10 (audio volume)", + "radio_tx_menu": "MIC G: ~22 dB (adjust for 4-5 ALC bars)", + "recommended_alsa_rx": 75, + "recommended_alsa_tx": 50, + "freedv_notes": "No LINE IN - uses MIC input (may need attenuator). Set MIC G for 4-5 ALC bars. KXUSB cable is serial only." + }, + "serial_settings": { + "data_bits": 8, + "stop_bits": 1, + "parity": "none", + "handshake": "none", + "rts_state": "OFF", + "dtr_state": "OFF" + }, + "setup_guide": { + "steps": [ + {"setting": "Mode", "value": "DATA A", "how": "Tap MODE until DATA A"}, + {"setting": "CONFIG:RS232", "value": "38400", "how": "Hold MENU → RS232"}, + {"setting": "MIC G", "value": "~22 dB", "how": "Adjust for 4-5 ALC bars during TX"}, + {"setting": "AF", "value": "5", "how": "RX audio volume"} + ], + "note": "Requires external USB soundcard. MIC input (no LINE IN). Set audio for 4-5 ALC bars.", + "sources": ["https://www.qsoshack.com/data-mode-communication-on-the-elecraft-kx3/"] + }, + "notes": "Portable. Requires external USB soundcard. KXUSB is serial only. ALC target: 4-5 bars.", + "tested": false, + "power_watts": 15 + }, + { + "id": "elecraft_kx2", + "manufacturer": "Elecraft", + "model": "KX2", + "hamlib_id": 2044, + "baud_rate": 38400, + "ptt_method": "RTS", + "ptt_on_delay_ms": 250, + "ptt_off_delay_ms": 150, + "audio_interface": "external", + "audio_settings": { + "type": "external_usb_soundcard", + "connector": "3.5mm TRRS MIC jack (TX in) + 3.5mm Phones jack (RX out)", + "rx_control": "External soundcard ALSA + Radio AF menu", + "tx_control": "External soundcard ALSA + Radio MIC G menu", + "radio_rx_menu": "AF: 2-10 (audio volume)", + "radio_tx_menu": "MIC G: 18-22 dB (adjust for 4-5 ALC bars)", + "recommended_alsa_rx": 75, + "recommended_alsa_tx": 50, + "freedv_notes": "Same as KX3. No LINE IN - uses MIC input (may need 10k/1k attenuator). Set MIC G for 4-5 ALC bars." + }, + "serial_settings": { + "data_bits": 8, + "stop_bits": 1, + "parity": "none", + "handshake": "none", + "rts_state": "OFF", + "dtr_state": "OFF" + }, + "setup_guide": { + "steps": [ + {"setting": "Mode", "value": "DATA A", "how": "Tap MODE until DATA A"}, + {"setting": "CONFIG:RS232", "value": "38400", "how": "Hold MENU → RS232"}, + {"setting": "MIC G", "value": "18-22 dB", "how": "Adjust for 4-5 ALC bars during TX"}, + {"setting": "AF", "value": "5", "how": "RX audio volume"} + ], + "note": "Same as KX3. Requires external USB soundcard. MIC input only.", + "sources": ["https://k0pir.us/elecraft-kx2-and-wsjt-x-easy-setup/"] + }, + "notes": "Ultra-portable. Same as KX3. Requires external USB soundcard. ALC target: 4-5 bars.", + "tested": false, + "power_watts": 12 + }, + { + "id": "elecraft_k3", + "manufacturer": "Elecraft", + "model": "K3/K3S", + "hamlib_id": 2029, + "baud_rate": 38400, + "ptt_method": "RTS", + "ptt_on_delay_ms": 250, + "ptt_off_delay_ms": 150, + "audio_interface": "external", + "audio_settings": { + "type": "external_usb_soundcard", + "connector": "3.5mm LINE IN (rear, mono) + 3.5mm LINE OUT (rear, stereo)", + "impedance": "600 ohm", + "rx_control": "External soundcard ALSA + Radio MIC knob (when MIC SEL=LINE)", + "tx_control": "External soundcard ALSA + Radio MIC knob (when MIC SEL=LINE)", + "radio_rx_menu": "MIC knob: ~30 (when MIC SEL=LINE)", + "radio_tx_menu": "MAIN:MIC SEL: LINE (required for digital)", + "recommended_alsa_rx": 75, + "recommended_alsa_tx": 80, + "freedv_notes": "Has LINE IN/OUT (better than KX2/KX3). Set MIC SEL to LINE. Adjust for 4 bars solid + 5th flickering." + }, + "serial_settings": { + "data_bits": 8, + "stop_bits": 1, + "parity": "none", + "handshake": "none", + "rts_state": "OFF", + "dtr_state": "OFF" + }, + "setup_guide": { + "steps": [ + {"setting": "Mode", "value": "DATA A", "how": "Tap MD until DATA A"}, + {"setting": "MAIN:MIC SEL", "value": "LINE", "how": "MUST be LINE for digital"}, + {"setting": "CONFIG:RS232", "value": "38400 (3)", "how": "CONFIG → RS232 → 3"}, + {"setting": "CONFIG:PTT-KEY", "value": "RTS", "how": "Match software PTT setting"}, + {"setting": "MIC knob", "value": "~30", "how": "Adjust for 4-5 ALC bars"} + ], + "note": "Has LINE IN/OUT (600 ohm). K3S has optional USB audio. Set MIC SEL to LINE.", + "sources": ["https://vk2rh.com/k3-and-digital-modes/"] + }, + "notes": "CONFIG:RS232: 0=4800, 1=9600, 2=19200, 3=38400. Set MIC SEL to LINE.", + "tested": false, + "power_watts": 100 + }, + { + "id": "elecraft_k4", + "manufacturer": "Elecraft", + "model": "K4", + "hamlib_id": 2047, + "baud_rate": 38400, + "ptt_method": "CAT", + "ptt_on_delay_ms": 200, + "ptt_off_delay_ms": 150, + "audio_interface": "builtin", + "audio_settings": { + "type": "builtin_usb", + "alsa_device": "USB AUDIO CODEC", + "rx_control": "Radio menu (
)", + "tx_control": "Radio menu ()", + "radio_rx_menu": "
→ SOUNDCARD, adjust level", + "radio_tx_menu": " → SOUNDCARD, start at 15%", + "freedv_notes": "Built-in USB audio. Set LINE OUT source to SOUNDCARD. Adjust for 4-5 ALC bars." + }, + "serial_settings": { + "data_bits": 8, + "stop_bits": 1, + "parity": "none", + "handshake": "none", + "rts_state": "OFF", + "dtr_state": "OFF" + }, + "setup_guide": { + "steps": [ + {"setting": "Mode", "value": "DATA A", "how": "Tap MODE until DATA A"}, + {"setting": "TX Audio Source", "value": "SOUNDCARD", "how": " → SOUNDCARD"}, + {"setting": "RX Audio Source", "value": "SOUNDCARD", "how": "
→ SOUNDCARD"}, + {"setting": "LINE IN Level", "value": "15%", "how": "Adjust for 4-5 ALC bars"}, + {"setting": "Serial Baud", "value": "38400", "how": "Menu → Serial → Baud Rate"} + ], + "note": "Built-in USB audio ('USB AUDIO CODEC'). Set sources to SOUNDCARD.", + "sources": ["https://www.wt8p.com/configuring-elecraft-k4d-for-ft8/"] + }, + "notes": "Built-in USB audio. Latest Elecraft flagship. ALC target: 4-5 bars.", + "tested": false, + "power_watts": 100 + }, + { + "id": "qrplabs_qdx", + "manufacturer": "QRP Labs", + "model": "QDX", + "hamlib_id": 2052, + "baud_rate": 9600, + "ptt_method": "CAT", + "ptt_on_delay_ms": 200, + "ptt_off_delay_ms": 150, + "audio_interface": "builtin", + "audio_settings": { + "type": "builtin_usb_fixed", + "alsa_device": "QRP Labs QDX Transceiver", + "rx_control": "FIXED - no adjustment possible", + "tx_control": "FIXED - no adjustment possible", + "radio_rx_menu": "None - digital USB audio at fixed level", + "radio_tx_menu": "None - digital USB audio at fixed level", + "freedv_notes": "QDX has FIXED audio levels - no mixer controls. Set all OS volume to 100%. Audio level does NOT affect RF power (QDX synthesizes from frequency)." + }, + "serial_settings": { + "data_bits": 8, + "stop_bits": 1, + "parity": "none", + "handshake": "none", + "rts_state": "OFF", + "dtr_state": "OFF" + }, + "setup_guide": { + "steps": [ + {"setting": "Mode", "value": "USB (fixed)", "how": "QDX is USB-only, no mode change"}, + {"setting": "PTT Method", "value": "CAT", "how": "Use CAT PTT (not VOX)"}, + {"setting": "Rig Selection", "value": "Kenwood TS-440S", "how": "QDX emulates TS-440"}, + {"setting": "Volume", "value": "100%", "how": "Set OS and software volume to exactly 100%"} + ], + "note": "All-in-one digital radio. Single USB for CAT + audio. FIXED audio levels - set volume to 100%.", + "sources": ["https://qrp-labs.com/qdx.html"] + }, + "notes": "QRP digital kit. TS-440 emulation. FIXED audio levels - no mixer. Set volume to 100%.", + "tested": false, + "power_watts": 5 + }, + { + "id": "trusdx", + "manufacturer": "DL2MAN", + "model": "(tr)uSDX", + "hamlib_id": 2028, + "baud_rate": 115200, + "ptt_method": "VOX", + "audio_interface": "external", + "requires_external_audio": true, + "audio_settings": { + "type": "digirig", + "connector": "3.5mm TRS MIC jack + 3.5mm TRS Headphone jack", + "rx_control": "Digirig ALSA mixer + Radio Menu 1.1 (Volume)", + "tx_control": "Digirig ALSA mixer + Radio Menu 3.3 (TX Drive)", + "radio_rx_menu": "Menu 1.1 (Volume): 8-10 (1-15 range, 6dB steps)", + "radio_tx_menu": "Menu 3.3 (TX Drive): 4 (0-8 range, 6dB steps)", + "recommended_alsa_rx": 75, + "recommended_alsa_tx": 80, + "freedv_notes": "USB provides CAT only - requires Digirig for audio. Enable VOX (Menu 3.1: ON). Adjust Noise Gate (Menu 3.2) for reliable VOX trigger." + }, + "serial_settings": { + "data_bits": 8, + "stop_bits": 1, + "parity": "none", + "handshake": "none", + "dtr_state": "ON", + "rts_state": "OFF" + }, + "setup_guide": { + "steps": [ + {"setting": "Mode", "value": "USB", "how": "Select USB mode"}, + {"setting": "Menu 1.1 (Volume)", "value": "8-10", "how": "RX audio level"}, + {"setting": "Menu 3.1 (VOX)", "value": "ON", "how": "Enable VOX for PTT"}, + {"setting": "Menu 3.2 (Noise Gate)", "value": "Adjust", "how": "Set for reliable VOX trigger"}, + {"setting": "Menu 3.3 (TX Drive)", "value": "4", "how": "TX audio level"}, + {"setting": "Rig Selection", "value": "Kenwood TS-480", "how": "In software"} + ], + "note": "USB is CAT only - requires Digirig for audio. TS-480 emulation. Enable VOX.", + "sources": ["https://dl2man.de/4-trusdx-manual/", "https://oh8stn.org/blog/2023/03/24/qrp-nvis-data-modes-go-kit-trusdx/"] + }, + "notes": "QRP kit. TS-480 emulation. USB=CAT only. Requires external audio interface. Enable VOX.", + "tested": true, + "power_watts": 5 + }, + { + "id": "ubitx", + "manufacturer": "HF Signals", + "model": "uBITX", + "hamlib_id": 1020, + "baud_rate": 38400, + "ptt_method": "CAT", + "audio_interface": "external", + "requires_external_audio": true, + "audio_settings": { + "type": "digirig_or_signalink", + "connector": "6.35mm (1/4\") MIC jack (TX) + 3.5mm Headphone jack (RX)", + "rx_control": "External interface ALSA + Radio volume knob", + "tx_control": "External interface ALSA", + "radio_rx_menu": "Volume knob on front panel", + "radio_tx_menu": "None - adjust via external interface", + "recommended_alsa_rx": 75, + "recommended_alsa_tx": 50, + "freedv_notes": "Requires SignaLink/EasyDigi/Digirig. KD8CEC firmware recommended for CAT. Add ferrites on audio cables for 14MHz+." + }, + "serial_settings": { + "data_bits": 8, + "stop_bits": 2, + "parity": "none", + "handshake": "none" + }, + "setup_guide": { + "steps": [ + {"setting": "Mode", "value": "USB", "how": "Mode selector (firmware dependent)"}, + {"setting": "Rig Selection", "value": "Yaesu FT-817", "how": "uBITX emulates FT-817"}, + {"setting": "Baud Rate", "value": "38400", "how": "8N2 (2 stop bits)"}, + {"setting": "PTT Method", "value": "CAT", "how": "In software settings"} + ], + "note": "KD8CEC firmware recommended. FT-817 emulation. Requires external audio interface.", + "sources": ["https://ubitx.net/category/digital-modes/"] + }, + "notes": "QRP kit. FT-817 emulation. Requires external audio interface. KD8CEC firmware recommended.", + "tested": false, + "power_watts": 10 + }, + { + "id": "icom_ic9700", + "manufacturer": "Icom", + "model": "IC-9700", + "hamlib_id": 3081, + "baud_rate": 19200, + "ptt_method": "CAT", + "audio_interface": "builtin", + "audio_settings": { + "type": "builtin_usb", + "alsa_device": "USB Audio CODEC", + "rx_control": "Radio menu only (no ALSA mixer)", + "tx_control": "Radio menu only (no ALSA mixer)", + "radio_rx_menu": "SET → Connectors → USB AF/IF Output → AF Output Level: 30-50%", + "radio_tx_menu": "SET → Connectors → USB MOD Level: 30%", + "freedv_notes": "Built-in USB audio for VHF/UHF/1.2GHz. Adjust USB AF Output Level if input < -10 dB." + }, + "serial_settings": { + "data_bits": 8, + "stop_bits": 1, + "parity": "none", + "handshake": "none" + }, + "civ_address": "0xA2", + "setup_guide": { + "steps": [ + {"setting": "Mode", "value": "USB-D", "how": "Press MODE → USB-D"}, + {"setting": "DATA MOD", "value": "USB", "how": "SET → Connectors → DATA MOD → USB"}, + {"setting": "USB MOD Level", "value": "30%", "how": "SET → Connectors → USB MOD Level"}, + {"setting": "CI-V Address", "value": "A2h (default)", "how": "SET → Connectors → CI-V → Address"}, + {"setting": "CI-V Baud Rate", "value": "19200", "how": "SET → Connectors → CI-V Baud Rate"}, + {"setting": "USB SEND", "value": "USB (A) RTS", "how": "SET → Connectors → USB SEND"}, + {"setting": "Inhibit Timer", "value": "OFF", "how": "SET → Connectors → Inhibit Timer at USB Connection"} + ], + "note": "VHF/UHF/1.2GHz SDR. Built-in USB audio. CI-V address A2h.", + "sources": [ + "https://www.w6pql.com/misc/wsjtx_and_the_ic9700.htm", + "https://github.com/n4af/TR4W/wiki/Icom-CI-V-Information", + "https://github.com/Hamlib/Hamlib/blob/master/include/hamlib/riglist.h" + ] + }, + "notes": "VHF/UHF/1.2GHz all-mode SDR. Built-in USB audio. Hamlib ID 3081, CI-V A2h verified.", + "tested": false, + "power_watts": 100 + }, + { + "id": "yaesu_ft710", + "manufacturer": "Yaesu", + "model": "FT-710", + "hamlib_id": 1049, + "baud_rate": 38400, + "ptt_method": "CAT", + "audio_interface": "builtin", + "audio_settings": { + "type": "builtin_usb", + "alsa_device": "USB Audio CODEC", + "rx_control": "Radio menu only (no ALSA mixer)", + "tx_control": "Radio menu only (no ALSA mixer)", + "radio_rx_menu": "RADIO SETTING → MODE PSK/DATA → RPORT GAIN: 10", + "radio_tx_menu": "RADIO SETTING → MODE PSK/DATA → USB MOD GAIN: 50", + "freedv_notes": "Built-in USB audio. Direct-sampling SDR. Adjust RPORT GAIN if input < -10 dB." + }, + "serial_settings": { + "data_bits": 8, + "stop_bits": 2, + "parity": "none", + "handshake": "none", + "rts_state": "OFF", + "dtr_state": "OFF" + }, + "setup_guide": { + "steps": [ + {"setting": "Mode", "value": "DATA-U", "how": "Press MODE until DATA-U"}, + {"setting": "CAT-1 RATE", "value": "38400", "how": "RADIO SETTING → CAT-1 RATE"}, + {"setting": "DATA Mode", "value": "OTHERS", "how": "RADIO SETTING → MODE PSK/DATA → DATA MODE"}, + {"setting": "MOD SOURCE", "value": "REAR", "how": "RADIO SETTING → MODE PSK/DATA → MOD SOURCE"}, + {"setting": "RPTT SELECT", "value": "RTS", "how": "RADIO SETTING → MODE PSK/DATA → RPTT SELECT"}, + {"setting": "USB MOD GAIN", "value": "50", "how": "RADIO SETTING → MODE PSK/DATA → USB MOD GAIN"} + ], + "note": "Entry-level SDR. Built-in USB audio. Two virtual COM ports via USB.", + "sources": [ + "https://www.yaesu.com/Files/4CB893D7-1018-01AF-FA97E9E9AD48B50C/FT-710_CAT_OM_ENG_2306-C.pdf", + "https://www.dxlabsuite.com/dxlabwiki/TranceiverControlYaesu", + "https://github.com/Hamlib/Hamlib/blob/master/include/hamlib/riglist.h" + ] + }, + "notes": "Entry-level direct-sampling SDR. Built-in USB audio. Hamlib ID 1049 verified from riglist.h.", + "tested": false, + "power_watts": 100 + }, + { + "id": "yaesu_ftdx10", + "manufacturer": "Yaesu", + "model": "FTDX10", + "hamlib_id": 1042, + "baud_rate": 38400, + "ptt_method": "CAT", + "audio_interface": "builtin", + "audio_settings": { + "type": "builtin_usb", + "alsa_device": "USB Audio CODEC", + "rx_control": "Radio menu only (no ALSA mixer)", + "tx_control": "Radio menu only (no ALSA mixer)", + "radio_rx_menu": "RADIO SETTING → MODE PSK/DATA → RPORT GAIN: 10", + "radio_tx_menu": "RADIO SETTING → MODE PSK/DATA → USB DATA LEVEL: 50", + "alc_target": "Zero", + "alc_reversed": false, + "alc_guidance": "Target ZERO ALC. Adjust USB DATA LEVEL until ALC meter just begins to move, then back off slightly.", + "freedv_notes": "Built-in USB audio. Some users report internal soundcard distortion - external interface may improve quality." + }, + "serial_settings": { + "data_bits": 8, + "stop_bits": 2, + "parity": "none", + "handshake": "rts_on", + "rts_state": "ON", + "dtr_state": "OFF" + }, + "setup_guide": { + "steps": [ + {"setting": "Mode", "value": "DATA-U", "how": "Press MODE until DATA-U"}, + {"setting": "CAT Rate", "value": "38400", "how": "RADIO SETTING → CAT → CAT RATE"}, + {"setting": "DATA Mode", "value": "OTHERS", "how": "RADIO SETTING → MODE PSK/DATA → DATA MODE"}, + {"setting": "DATA MODE SOURCE", "value": "REAR", "how": "RADIO SETTING → MODE PSK/DATA → DATA MODE SOURCE"}, + {"setting": "RPORT GAIN", "value": "10", "how": "RADIO SETTING → MODE PSK/DATA → RPORT GAIN"}, + {"setting": "USB DATA LEVEL", "value": "50", "how": "RADIO SETTING → MODE PSK/DATA → USB DATA LEVEL"} + ], + "note": "Hybrid SDR with built-in USB audio. Two virtual COM ports via USB. RTS handshake required.", + "sources": [ + "https://www.dxlabsuite.com/dxlabwiki/TranceiverControlYaesu", + "https://www.wirelessgirl.net/Projects/FTDX101D_WSJT_Settings.html", + "https://github.com/Hamlib/Hamlib/blob/master/include/hamlib/riglist.h" + ] + }, + "notes": "Hybrid direct-sampling SDR. Built-in USB audio. Hamlib ID 1042 verified. 2 stop bits, RTS handshake.", + "tested": false, + "power_watts": 100 + }, + { + "id": "elecraft_k4d", + "manufacturer": "Elecraft", + "model": "K4D", + "hamlib_id": 2047, + "baud_rate": 38400, + "ptt_method": "RTS", + "ptt_on_delay_ms": 200, + "ptt_off_delay_ms": 150, + "audio_interface": "builtin", + "audio_settings": { + "type": "builtin_usb", + "alsa_device": "USB AUDIO CODEC", + "rx_control": "Radio menu (
)", + "tx_control": "Radio menu ()", + "radio_rx_menu": "
→ SOUNDCARD, use LEFT channel", + "radio_tx_menu": " → SOUNDCARD, start at 15%", + "alc_target": "4-5 bars", + "alc_reversed": false, + "alc_guidance": "Target 4 solid ALC bars with 5th bar flickering. Adjust LINE IN for this.", + "freedv_notes": "Built-in USB audio. Use LEFT channel input/output to avoid mixing issues with dual RX." + }, + "serial_settings": { + "data_bits": 8, + "stop_bits": 1, + "parity": "none", + "handshake": "none", + "rts_state": "OFF", + "dtr_state": "OFF" + }, + "setup_guide": { + "steps": [ + {"setting": "Mode", "value": "DATA A", "how": "Tap MODE until DATA A"}, + {"setting": "TX Audio Source", "value": "SOUNDCARD", "how": " → SOUNDCARD"}, + {"setting": "RX Audio Source", "value": "SOUNDCARD", "how": "
→ SOUNDCARD"}, + {"setting": "LINE IN Level", "value": "15%", "how": "Adjust for 4-5 ALC bars"}, + {"setting": "Serial Baud", "value": "38400", "how": "Menu → Serial USB-PCn → Baud Rate"}, + {"setting": "Split Operation", "value": "Fake It", "how": "In software settings"} + ], + "note": "Remote-head version of K4. RTS PTT recommended over CAT. Uses same Hamlib ID as K4.", + "sources": [ + "https://www.wt8p.com/configuring-elecraft-k4d-for-ft8/", + "https://ftp.elecraft.com/K4/Manuals%20Downloads/K4%20Built-In%20Operating%20Manual%20rev%20D6/K4BuiltInOperatingManualrevD6.html", + "https://github.com/Hamlib/Hamlib/blob/master/include/hamlib/riglist.h" + ] + }, + "notes": "K4 remote-head version. Hamlib ID 2047 (same as K4). RTS PTT, 38400 baud, LEFT channel audio.", + "tested": false, + "power_watts": 100 + } + ] +} diff --git a/image/build.sh b/image/build.sh new file mode 100755 index 0000000..0161773 --- /dev/null +++ b/image/build.sh @@ -0,0 +1,331 @@ +#!/bin/bash +# ReticulumHF Pi Image Build Script +# Creates a custom Raspberry Pi OS Bookworm image with ReticulumHF pre-installed +# +# WiFi AP: Uses hostapd + dnsmasq (proven stable solution) +# Base OS: Raspberry Pi OS Bookworm Lite (64-bit) +# +# Usage: ./build.sh [base-image.img] + +set -e + +SCRIPT_DIR="$(cd "$(dirname "${BASH_SOURCE[0]}")" && pwd)" +PROJECT_DIR="$(dirname "$SCRIPT_DIR")" +BUILD_DIR="$PROJECT_DIR/build" +OUTPUT_DIR="$PROJECT_DIR/output" +MOUNT_DIR="$BUILD_DIR/mnt" +LOOP_DEV="" + +cleanup() { + echo "Cleaning up..." + sudo fuser -k "$MOUNT_DIR" 2>/dev/null || true + sleep 1 + if [ -f "$MOUNT_DIR/etc/ld.so.preload.bak" ]; then + sudo mv "$MOUNT_DIR/etc/ld.so.preload.bak" "$MOUNT_DIR/etc/ld.so.preload" 2>/dev/null || true + fi + sudo umount "$MOUNT_DIR/dev/pts" 2>/dev/null || true + sudo umount "$MOUNT_DIR/dev" 2>/dev/null || true + sudo umount "$MOUNT_DIR/proc" 2>/dev/null || true + sudo umount "$MOUNT_DIR/sys" 2>/dev/null || true + sudo umount "$MOUNT_DIR/boot/firmware" 2>/dev/null || true + sudo umount "$MOUNT_DIR" 2>/dev/null || true + if [ -n "$LOOP_DEV" ]; then + sudo losetup -d "$LOOP_DEV" 2>/dev/null || true + fi +} + +trap cleanup EXIT + +BASE_IMAGE="${1:-bookworm-lite.img}" +OUTPUT_IMAGE="reticulumhf_v1.0.img" + +echo "============================================" +echo "ReticulumHF Pi Image Builder" +echo "============================================" +echo "Base image: $BASE_IMAGE" +echo "Output: $OUTPUT_IMAGE" +echo "Approach: Bookworm + hostapd/dnsmasq" +echo "" + +mkdir -p "$BUILD_DIR" "$OUTPUT_DIR" + +if [ ! -f "$BASE_IMAGE" ]; then + echo "Error: Base image not found: $BASE_IMAGE" + echo "" + echo "Download Raspberry Pi OS Lite Bookworm (64-bit) from:" + echo "https://www.raspberrypi.com/software/operating-systems/" + exit 1 +fi + +echo "[1/10] Copying base image..." +cp "$BASE_IMAGE" "$BUILD_DIR/$OUTPUT_IMAGE" + +echo "[2/10] Expanding image (adding 3GB for software)..." +dd if=/dev/zero bs=1M count=3072 >> "$BUILD_DIR/$OUTPUT_IMAGE" + +echo "[3/10] Setting up loop device..." +LOOP_DEV=$(sudo losetup -fP --show "$BUILD_DIR/$OUTPUT_IMAGE") +echo "Loop device: $LOOP_DEV" + +echo "[4/10] Resizing partition..." +sudo parted -s "$LOOP_DEV" resizepart 2 100% +sudo e2fsck -fy "${LOOP_DEV}p2" 2>/dev/null || echo "Warning: e2fsck returned non-zero" +sudo resize2fs -f "${LOOP_DEV}p2" + +echo "[5/10] Mounting filesystems..." +mkdir -p "$MOUNT_DIR" +sudo mount "${LOOP_DEV}p2" "$MOUNT_DIR" +sudo mkdir -p "$MOUNT_DIR/boot/firmware" +sudo mount "${LOOP_DEV}p1" "$MOUNT_DIR/boot/firmware" + +sudo mount --bind /dev "$MOUNT_DIR/dev" +sudo mount --bind /dev/pts "$MOUNT_DIR/dev/pts" +sudo mount -t proc proc "$MOUNT_DIR/proc" +sudo mount -t sysfs sysfs "$MOUNT_DIR/sys" + +echo "[6/10] Preparing chroot environment..." + +if [ -f /usr/bin/qemu-aarch64-static ]; then + sudo cp /usr/bin/qemu-aarch64-static "$MOUNT_DIR/usr/bin/" +fi + +# Use public DNS (not host's - may be Tailscale/VPN which won't work in chroot) +echo "nameserver 1.1.1.1" | sudo tee "$MOUNT_DIR/etc/resolv.conf" > /dev/null +echo "nameserver 8.8.8.8" | sudo tee -a "$MOUNT_DIR/etc/resolv.conf" > /dev/null + +if [ -f "$MOUNT_DIR/etc/ld.so.preload" ]; then + sudo cp "$MOUNT_DIR/etc/ld.so.preload" "$MOUNT_DIR/etc/ld.so.preload.bak" + sudo sed -i 's/^/#DISABLED /g' "$MOUNT_DIR/etc/ld.so.preload" +fi + +echo "[7/10] Installing ReticulumHF files..." + +sudo mkdir -p "$MOUNT_DIR/opt/reticulumhf" +sudo cp -r "$PROJECT_DIR/setup-portal" "$MOUNT_DIR/opt/reticulumhf/" +sudo cp -r "$PROJECT_DIR/configs" "$MOUNT_DIR/opt/reticulumhf/" +sudo cp -r "$PROJECT_DIR/scripts" "$MOUNT_DIR/opt/reticulumhf/" + +sudo cp "$PROJECT_DIR/services/"*.service "$MOUNT_DIR/etc/systemd/system/" + +# Install ALSA configuration for USB audio (fixes freedvtnc2 "Unknown PCM" errors) +sudo cp "$PROJECT_DIR/configs/asound.conf" "$MOUNT_DIR/etc/asound.conf" + +# Install wait-for-port utility (used by service files, replaces netcat dependency) +sudo cp "$PROJECT_DIR/scripts/wait-for-port" "$MOUNT_DIR/usr/local/bin/" +sudo chmod +x "$MOUNT_DIR/usr/local/bin/wait-for-port" + +sudo ln -sf /etc/systemd/system/reticulumhf-firstboot.service \ + "$MOUNT_DIR/etc/systemd/system/multi-user.target.wants/reticulumhf-firstboot.service" + +# Enable rnsd service (will be started by first-boot, then auto-start on subsequent boots) +sudo ln -sf /etc/systemd/system/reticulumhf-rnsd.service \ + "$MOUNT_DIR/etc/systemd/system/multi-user.target.wants/reticulumhf-rnsd.service" + +# Enable portal service +sudo ln -sf /etc/systemd/system/reticulumhf-portal.service \ + "$MOUNT_DIR/etc/systemd/system/multi-user.target.wants/reticulumhf-portal.service" + +# Enable wlan0 static IP service (runs before hostapd) +sudo ln -sf /etc/systemd/system/reticulumhf-wlan.service \ + "$MOUNT_DIR/etc/systemd/system/multi-user.target.wants/reticulumhf-wlan.service" + +# Install hostapd rfkill override (unblock WiFi before starting hostapd) +sudo mkdir -p "$MOUNT_DIR/etc/systemd/system/hostapd.service.d" +sudo cp "$PROJECT_DIR/configs/hostapd-rfkill.conf" "$MOUNT_DIR/etc/systemd/system/hostapd.service.d/rfkill.conf" + +echo "[8/10] Running installation in chroot..." + +cat << 'CHROOT_SCRIPT' | sudo tee "$MOUNT_DIR/tmp/install.sh" +#!/bin/bash +set -e + +echo "============================================" +echo "ReticulumHF Chroot Installation" +echo "============================================" + +# Set hostname +echo "reticulumhf" > /etc/hostname +sed -i 's/127.0.1.1.*/127.0.1.1\treticulumhf/' /etc/hosts + +# Create pi user +echo "[1/9] Creating pi user..." +if ! id pi &>/dev/null; then + useradd -m -s /bin/bash -G sudo,dialout,audio,video,plugdev,netdev,gpio,i2c,spi pi +fi +echo "pi:reticulumhf" | chpasswd +mkdir -p /home/pi/.config +touch /home/pi/.config/user-dirs.locale +chown -R pi:pi /home/pi/.config + +# Enable SSH +echo "[2/9] Enabling SSH..." +systemctl enable ssh + +# Disable first-boot wizard +echo "[3/9] Disabling first-boot wizard..." +systemctl disable userconfig 2>/dev/null || true +systemctl disable piwiz 2>/dev/null || true +systemctl mask userconfig 2>/dev/null || true +systemctl mask piwiz 2>/dev/null || true +apt-get remove -y piwiz userconf-pi 2>/dev/null || true +mkdir -p /etc/skel/.config +touch /etc/skel/.config/user-dirs.locale + +# Install system packages +echo "[4/9] Installing system packages..." +# Force IPv4 to avoid IPv6 connectivity issues with RPi repos +echo 'Acquire::ForceIPv4 "true";' > /etc/apt/apt.conf.d/99force-ipv4 +apt-get update +apt-get install -y \ + python3 python3-pip python3-venv python3-dev python3-flask pipx \ + git build-essential cmake \ + portaudio19-dev alsa-utils \ + libhamlib-utils libhamlib-dev \ + hostapd dnsmasq \ + iptables \ + fake-hwclock + +# Configure fake-hwclock to preserve time across reboots +# This fixes the "wrong date on first boot" issue for Pi without RTC +echo "[4.1/9] Configuring fake-hwclock..." +systemctl enable fake-hwclock + +# Configure hostapd (WiFi AP) +echo "[5/9] Configuring hostapd..." +cat > /etc/hostapd/hostapd.conf << 'HOSTAPD' +interface=wlan0 +driver=nl80211 +ssid=ReticulumHF +hw_mode=g +channel=7 +wmm_enabled=0 +macaddr_acl=0 +auth_algs=1 +ignore_broadcast_ssid=0 +wpa=2 +wpa_passphrase=reticulumhf +wpa_key_mgmt=WPA-PSK +wpa_pairwise=TKIP +rsn_pairwise=CCMP +HOSTAPD + +# Point hostapd to config +sed -i 's|^#DAEMON_CONF=.*|DAEMON_CONF="/etc/hostapd/hostapd.conf"|' /etc/default/hostapd 2>/dev/null || true +echo 'DAEMON_CONF="/etc/hostapd/hostapd.conf"' >> /etc/default/hostapd + +# Configure dnsmasq (DHCP + DNS for AP) +echo "[6/9] Configuring dnsmasq..." +cat > /etc/dnsmasq.d/reticulumhf.conf << 'DNSMASQ' +interface=wlan0 +dhcp-range=192.168.4.2,192.168.4.20,255.255.255.0,24h +address=/reticulumhf.local/192.168.4.1 +DNSMASQ + +# Configure static IP for wlan0 +cat >> /etc/dhcpcd.conf << 'DHCPCD' + +# ReticulumHF WiFi AP static IP +interface wlan0 +static ip_address=192.168.4.1/24 +nohook wpa_supplicant +DHCPCD + +# Enable IP forwarding (for internet sharing later if connected via ethernet) +echo "net.ipv4.ip_forward=1" >> /etc/sysctl.conf + +# Tell NetworkManager to not manage wlan0 (we use hostapd for AP mode) +mkdir -p /etc/NetworkManager/conf.d +cat > /etc/NetworkManager/conf.d/unmanaged-wlan0.conf << 'NMCONF' +[keyfile] +unmanaged-devices=interface-name:wlan0 +NMCONF + +# Disable hostapd and dnsmasq from auto-starting +# First-boot script will start them after verifying everything +systemctl disable hostapd +systemctl disable dnsmasq + +# Build codec2 from source +echo "[7/9] Building codec2 from source..." +cd /tmp +rm -rf codec2 +git clone https://github.com/drowe67/codec2.git +cd codec2 +mkdir -p build_linux && cd build_linux +cmake .. -DCMAKE_BUILD_TYPE=Release +make -j$(nproc) +make install +ldconfig +cd / +rm -rf /tmp/codec2 +echo "codec2 installed:" +ldconfig -p | grep codec2 + +# Install Python packages for pi user +echo "[8/9] Installing Python packages for pi user..." +export HOME=/home/pi +mkdir -p /home/pi/.local/bin +chown -R pi:pi /home/pi + +sudo -u pi bash -c 'export PATH="$PATH:/home/pi/.local/bin"; pipx install rns' +sudo -u pi bash -c 'export PATH="$PATH:/home/pi/.local/bin"; pipx install nomadnet' +# Install freedvtnc2-lfm fork with command interface (port 8002) +sudo -u pi bash -c 'export PATH="$PATH:/home/pi/.local/bin"; pipx install git+https://github.com/LFManifesto/freedvtnc2.git' +sudo -u pi bash -c 'export PATH="$PATH:/home/pi/.local/bin"; pipx runpip freedvtnc2 install audioop-lts' || true + +# Set permissions +echo "[9/9] Setting permissions..." +chown -R pi:pi /opt/reticulumhf +chmod +x /opt/reticulumhf/scripts/*.sh + +# Clean up +apt-get clean +rm -rf /var/lib/apt/lists/* + +echo "" +echo "============================================" +echo "Chroot installation complete!" +echo "============================================" +CHROOT_SCRIPT + +sudo chmod +x "$MOUNT_DIR/tmp/install.sh" +sudo chroot "$MOUNT_DIR" /tmp/install.sh + +sudo rm -f "$MOUNT_DIR/tmp/install.sh" +sudo rm -f "$MOUNT_DIR/usr/bin/qemu-aarch64-static" + +echo "[9/10] Restoring ld.so.preload and unmounting..." + +if [ -f "$MOUNT_DIR/etc/ld.so.preload.bak" ]; then + sudo mv "$MOUNT_DIR/etc/ld.so.preload.bak" "$MOUNT_DIR/etc/ld.so.preload" +fi + +sudo umount "$MOUNT_DIR/dev/pts" 2>/dev/null || true +sudo umount "$MOUNT_DIR/dev" 2>/dev/null || true +sudo umount "$MOUNT_DIR/proc" 2>/dev/null || true +sudo umount "$MOUNT_DIR/sys" 2>/dev/null || true +sudo umount "$MOUNT_DIR/boot/firmware" 2>/dev/null || true +sudo umount "$MOUNT_DIR" 2>/dev/null || true +sudo losetup -d "$LOOP_DEV" 2>/dev/null || true +LOOP_DEV="" + +echo "[10/10] Compressing image..." +mv "$BUILD_DIR/$OUTPUT_IMAGE" "$OUTPUT_DIR/" +cd "$OUTPUT_DIR" +xz -T0 "$OUTPUT_IMAGE" + +echo "" +echo "============================================" +echo "Build complete!" +echo "============================================" +echo "Output: $OUTPUT_DIR/${OUTPUT_IMAGE}.xz" +echo "" +echo "Image contains:" +echo " - Hostname: reticulumhf" +echo " - User: pi / Password: reticulumhf" +echo " - SSH: enabled" +echo " - WiFi AP: ReticulumHF (hostapd + dnsmasq)" +echo " - codec2, RNS, NomadNet, freedvtnc2: pre-installed" +echo "" +echo "Flash to SD card with Raspberry Pi Imager" +echo "" diff --git a/scripts/wait-for-port b/scripts/wait-for-port new file mode 100644 index 0000000..f1f28b6 --- /dev/null +++ b/scripts/wait-for-port @@ -0,0 +1,16 @@ +#!/bin/bash +# Wait for a TCP port to be listening +# Usage: wait-for-port [port] [timeout_seconds] + +PORT=${1:-8001} +TIMEOUT=${2:-30} + +for i in $(seq 1 $TIMEOUT); do + if python3 -c "import socket; s=socket.socket(); s.settimeout(1); exit(0 if s.connect_ex(('127.0.0.1', $PORT))==0 else 1)" 2>/dev/null; then + exit 0 + fi + sleep 1 +done + +echo "Port $PORT not ready after ${TIMEOUT}s" >&2 +exit 1