FreeTRX/flash.sh
Marcus Kida a8c2038552 Channels: translate the add/delete menu strings; flash.sh rebuilds packs
Add delete_channel and keep_one_channel to the language table (after mute) and
fill all 20 language files (13 translated, English fallback for the rest), with
correct single-byte ISO-8859 accents. Wire them into the Delete Channel label,
confirmation and last-channel guard. The new strings land on empty voice-table
slots, so they play as silence (no crash, no .vpr regeneration).

flash.sh now always rebuilds the .gla language packs so edits to the language
files are actually picked up (previously a stale pack was re-flashed).

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
2026-07-10 12:47:27 +02:00

106 lines
4.6 KiB
Bash

#!/usr/bin/env bash
#
# flash.sh — flash the OpenGD77 firmware to an MD-UV380 / DM-1701 in DFU mode,
# optionally merging a secondary language and the DMR (AMBE codec) donor firmware.
#
# The radio's language slot #1 is always English. This script injects ONE
# secondary language (slot #2) via the loader's -L option. Re-flash with a
# different language to change it.
#
# Usage:
# ./flash.sh # defaults: model MD-UV380, language German
# ./flash.sh -L French # flash with French as the secondary language
# ./flash.sh -m DM-1701 -L Italian
# ./flash.sh -L none # English only, no secondary language
# ./flash.sh -s /path/donor.bin # (re)register the DMR codec donor firmware
# ./flash.sh --list-languages # show available languages and exit
# ./flash.sh -l # list attached DFU devices and exit
#
set -euo pipefail
REPO_DIR="$(cd "$(dirname "${BASH_SOURCE[0]}")" && pwd)"
FW_DIR="$REPO_DIR/MDUV380_firmware"
LOADER="$FW_DIR/tools/opengd77_stm32_firmware_loader.py"
FIRMWARE="$FW_DIR/build/OpenMDUV380.bin"
LANG_SRC="$FW_DIR/application/include/user_interface/languages/src"
# ---- defaults -------------------------------------------------------------
MODEL="MD-UV380" # or: DM-1701, MD-9600, MD-2017, MD-380
LANGUAGE="German" # a language name (see --list-languages), or "none"
DONOR="" # official V26.45 firmware; empty = use the saved one
usage() { sed -n '3,25p' "${BASH_SOURCE[0]}" | sed 's/^# \{0,1\}//'; exit "${1:-0}"; }
lc() { printf '%s' "$1" | tr '[:upper:]' '[:lower:]'; } # lowercase (bash 3.2 safe)
# ---- parse args -----------------------------------------------------------
while [[ $# -gt 0 ]]; do
case "$1" in
-m|--model) MODEL="$2"; shift 2 ;;
-L|--lang|--language) LANGUAGE="$2"; shift 2 ;;
-s|--source|--donor) DONOR="$2"; shift 2 ;;
-f|--firmware) FIRMWARE="$2"; shift 2 ;;
-l|--list) python3 "$LOADER" -l; exit $? ;;
--list-languages)
echo "Available languages (pass to -L):"
( cd "$LANG_SRC" && ls *.gla 2>/dev/null | sed 's/\.gla$//' ) \
|| ls "$LANG_SRC"/../*.h 2>/dev/null | xargs -n1 basename | sed 's/\.h$//'
echo " none (English only)"
exit 0 ;;
-h|--help) usage 0 ;;
*) echo "Unknown option: $1" >&2; usage 1 ;;
esac
done
# ---- sanity checks --------------------------------------------------------
[[ -f "$LOADER" ]] || { echo "!! Loader not found: $LOADER" >&2; exit 1; }
[[ -f "$FIRMWARE" ]] || { echo "!! Firmware not found: $FIRMWARE (run ./build-firmware.sh first)" >&2; exit 1; }
# ---- resolve / build the language file ------------------------------------
LANG_ARGS=()
if [[ -n "$LANGUAGE" && "$(lc "$LANGUAGE")" != "none" ]]; then
# Always (re)build the .gla language packs so edits to the *.h language files
# are picked up. (They're built from the .h sources by languages_builder; a
# stale pack would otherwise show blank/old strings on the radio.)
echo "==> Building language (.gla) files..."
( cd "$LANG_SRC" && gcc -w -I../ -o languages_builder languages_builder.c && ./languages_builder >/dev/null )
# Case-insensitive match of the requested name to an actual <Name>.gla file.
GLA=""
for f in "$LANG_SRC"/*.gla; do
base="$(basename "$f" .gla)"
if [[ "$(lc "$base")" == "$(lc "$LANGUAGE")" ]]; then GLA="$f"; break; fi
done
if [[ -z "$GLA" ]]; then
echo "!! Unknown language '$LANGUAGE'. Available:" >&2
( cd "$LANG_SRC" && ls *.gla | sed 's/\.gla$//' | sed 's/^/ /' ) >&2
exit 1
fi
echo "==> Secondary language: $(basename "$GLA" .gla)"
LANG_ARGS=(-L "$GLA")
else
echo "==> Secondary language: none (English only)"
fi
# ---- donor firmware (DMR / AMBE codec) ------------------------------------
DONOR_ARGS=()
if [[ -n "$DONOR" ]]; then
[[ -f "$DONOR" ]] || { echo "!! Donor firmware not found: $DONOR" >&2; exit 1; }
echo "==> DMR donor (this run): $DONOR"
DONOR_ARGS=(-s "$DONOR")
elif grep -qi 'sourcestm32firmware *= *..*' "$HOME/.gd77firmwareloader.ini" 2>/dev/null; then
saved="$(grep -i 'sourcestm32firmware' "$HOME/.gd77firmwareloader.ini" | cut -d= -f2- | xargs)"
echo "==> DMR donor: using saved donor -> $saved"
else
echo "==> DMR donor: NONE registered — firmware will flash as FM-only."
echo " (pass -s /path/to/official_V26.45.bin once to enable DMR)"
fi
# ---- flash ----------------------------------------------------------------
echo "==> Model: $MODEL"
echo "==> Firmware: $FIRMWARE"
echo "==> Make sure the radio is in DFU mode (power on holding PTT + SK1)."
echo
set -x
exec python3 "$LOADER" -m "$MODEL" \
"${DONOR_ARGS[@]+"${DONOR_ARGS[@]}"}" \
"${LANG_ARGS[@]+"${LANG_ARGS[@]}"}" \
-f "$FIRMWARE"