Add two codeplug primitives - codeplugAllChannelsIndexSetUnused() (frees a
channel slot: clears the in-use bitmap bit, persists the header, fixes counts)
and codeplugZoneRemoveChannelFromZoneAndSave() (removes a channel from a zone's
list) - and wire two new Channel quick-menu items:
- 'new channel': allocates the first free slot, writes a blank 145.500 FM
channel, adds it to the current zone, reloads the zone and opens Channel
Details to edit it.
- 'Delete Channel': confirmation, then scrubs the channel from every real zone
before freeing the slot. Guards against deleting the last channel and honours
the read-only/APRS lock.
Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
The menu label 'Screen Dim' is a raw literal, and the shared menu code voices
labels through voicePromptsAppendLanguageString(), which derives the prompt
index from the pointer's offset within the language table and crashed on a
foreign pointer (v0.2.0 fixed only the value, not the label). That helper now
ignores pointers outside the language table.
Bump version to 0.3.0.
Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
Screen Dim passed a plain literal ('100%'/'50%'/...) to
voicePromptsAppendLanguageString(), which derives the prompt index from the
string's offset within the language table; a foreign pointer produced a garbage
index and crashed (only with voice on). Route the value through
voicePromptsAppendString() instead. Also move the 3-bit dim level's high bit off
legacy option bit 2 to bit 29 and clamp the level against the option arrays.
Bump version to 0.2.0.
Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
- Inactive segments now render in the background colour (off) instead of dimmed.
- The 7-seg renderer left the foreground on the last segment drawn (now the
background colour), which hid MHz; re-apply the frequency theme colour before
drawing MHz so it reappears and matches the digits.
- Move the TX frequency line down 1px for a little more RX/TX separation.
Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
Add SCREEN_DIM_15 (Off / 100 / 50 / 30 / 15). The value now needs 3 bits, so
repurpose the spare BIT_UNUSED_2 as BIT_SCREEN_DIM_2; existing codeplugs (bit 2
clear) keep their level, no reset.
Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
- New freetrxVersion.h with semver (MAJOR/MINOR/PATCH + string), currently 0.1.0.
- Firmware Info top line now shows "FreeTRX v0.1.0"; the git commit ID line is
unchanged. The version is also announced via voice prompt.
- CHANGELOG: promote the accumulated changes to a 0.1.0 section.
Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
- Splash screen and Firmware Info name now show "FreeTRX".
- Firmware-info credits: "Marcus DK1DA", a separator, and a thank-you to the
original OpenGD77 authors.
- README documents that this iteration is developed/tested only on the TYT
MD-UV380 and Retevis RT-3S, with a contact for testing other supported radios.
- CHANGELOG updated.
Hardware/tooling identifiers (build filename, MD-UV380 model IDs, hotspot
version string) intentionally left unchanged to avoid breaking flashing and
Pi-Star/MMDVM compatibility.
Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
Drop the built-in strike-through over the FM/DMR mode text when muted; the
header "M" (and red LED flash) are the mute indicators now.
Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
Treat the volume control at its minimum (lastVolume == -99, the firmware's
'muted' position) as effectively muted, so the red LED flash, the header M
and the built-in strike-through appear without an explicit SK2 mute.
Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
The private-call caller ID was drawn at a hardcoded y=16, which now collides
with the S-meter label row. Use DISPLAY_Y_POS_CONTACT (same as the group-call
contact line) so it clears the labels.
Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
Add a one-tap audio mute on the VFO and Channel screens:
- SK2 short-tap toggles mute via the built-in audioAmpMute()/audioAmpIsMuted().
The tap is only consumed by the existing "set TX TG to incoming" behaviour
while a DMR QSO is on screen, so mute works everywhere else.
- Header: a bold "M" is shown just left of the battery while muted (the
firmware's built-in strike-through over the mode text also still shows).
- LED: flashes red for 0.5s every 2s while muted (main loop), overriding the
normal RX/TX LED.
Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
Render the VFO/Channel frequency (and the SK1-held frequency view, which share
uiUtilityDisplayFrequency) as 7-segment "LED" digits instead of the normal font,
on colour displays.
- HX8353E_display.c: displayDrawFrequencySevenSeg() draws each digit's 7 segments
as filled rectangles; lit segments use the theme frequency colour, inactive
segments a dimmed (~3/8 intensity, same hue) version, giving the classic LED
look with faintly-visible "off" segments. The decimal point takes half a cell.
- Digits are 12 px wide (wider than the 8 px font) to fill the space toward the
"MHz" label; height follows the existing single/double-height frequency layout.
- Monochrome displays keep the normal font.
Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
Shift the contact/TG, CTCSS/DCS and squelch info lines down by a tunable
DISPLAY_MAIN_CONTENT_TOP_PAD (4px) on MD-UV380/DM1701, so they no longer sit
flush against the new S-meter label row. Frequency and everything below are
unchanged.
Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
Rework the header RSSI bar (uiUtilityDrawRSSIBarGraph) from a solid two-stage
bar into discrete blocks, one per S-level, on colour displays:
- 9 green blocks for S1..S9 (4 dB per S-unit) plus 6 red blocks for the S9+
region (10 dB per block, S9+10..S9+60), drawn with 2 px gaps so the header
background shows between them.
- Proportional fill: full blocks below the level, leading block partially filled
to reflect the exact signal.
- Bar height raised 4 -> 6 px; the FM/DMR mic-level bars follow the same height
so nothing is left behind when switching RX <-> TX.
- Scale labels below the blocks: S1/S3/S5/S7/S9 under the green zone and
+20/+40/+60 under the red, centred under their blocks (font_6x8). The label
row is blanked while transmitting.
Monochrome displays keep the original solid bar. Existing analog S9+ RSSI
compression is preserved, so calibration is unchanged.
Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
The radio hard-froze (needs battery pull) the instant it processed an incoming
DMR frame — repeater reply, or noise on a DMR channel. FM and DMR TX-without-a-
listening-repeater were fine. Cause: codec_interface.c invoked the AMBE codec
through hand-written inline assembler with no operands and no clobber list,
branching (BL) to an absolute address. That code's correctness depends entirely
on a specific compiler's register allocation; modern GNU toolchains (both ARM
GCC 10 and 14) miscompile it, corrupting state on the first codec call.
Port the official R20260504 (git ebd7100) rework: replace all five inline-asm
calls (2x decode, 2x encode, 1x ECC) with C function-pointer calls. Each call
reproduces the exact register/stack layout the assembler set up (AAPCS: args
1-4 -> r0-r3, args 5+ -> stack) and sets the Thumb bit on the target address.
Also drop the trailing semicolons from the AMBE_* address macros in codec.h so
they can be used in C expressions.
Builds cleanly with the GCC 14.2 Docker toolchain (no STM32CubeIDE needed) and
DMR RX/TX now works on the radio.
Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>