Adds gfx_printBufferClipped: a variant of gfx_printBuffer that accepts
an explicit right-edge limit (max_x) and a vertical clip window
[clip_top_y, clip_bot_y]. Word-wrap fires when the next glyph would
exceed max_x. Pixels outside the clip window are suppressed without
affecting layout, so a negative start.y can be used to implement smooth
text scrolling.
gfx_printBuffer now delegates entirely to gfx_printBufferClipped with
clip_top_y=0 and clip_bot_y=CONFIG_SCREEN_HEIGHT-1. The old pixel guard
used strict > 0 comparisons, which excluded pixels at row 0 and column 0.
The new implementation renders those pixels; callers that relied on the
old exclusion will see a behaviour change.
Compared to a naive port of gfx_printBuffer, this implementation
addresses several correctness issues:
- Control characters '\n' and '\r' are checked before the glyph array
is indexed, avoiding undefined behaviour on fonts whose first codepoint
is at or above 0x20 (e.g. TomThumb, first=0x20), since '\n' (0x0A)
would produce a negative index.
- get_line_size uses <= instead of < when accumulating glyph widths so
that a glyph whose xAdvance exactly equals max_width is counted. The
render loop uses strict > to trigger wrap, so the old < mismatch caused
text_size.x to be under-reported by one glyph whenever a line was an
exact fit, and misplaced CENTER/RIGHT lines in that case.
- For TEXT_ALIGN_LEFT, line_size is recomputed on every '\n' before the
max_line_size comparison. Without this, max_line_size was stuck at the
first-line width for the entire call, so text_size.x was wrong whenever
a subsequent line was wider.
- saved_start_y is int16_t to match point_t.y, allowing correct
text_size.y computation when start.y is negative (scroll offset).
- text_size.y is computed as (start.y - saved_start_y) + line_h,
matching the sign fix introduced for gfx_printBuffer.
- Pixels above row 0 (py < 0) are suppressed before the uint16_t cast
passed to gfx_setPixel, preventing a silent wrap to a large row index.
- max_line_size tracks the widest line across all line breaks and wraps;
text_size.x reflects the widest line, not just the last.
Extend tests/unit/gfx_text.cpp with return-value tests covering:
single-line height, two-line height delta equals yAdvance, negative
start.y scroll offset, negative clip_top_y, exact-fit line width
(get_line_size <= boundary), max line width from a wider first line,
max line width from a wider second line (TEXT_ALIGN_LEFT regression),
glyph at clip_bot_y not skipped, and TEXT_ALIGN_RIGHT per-line reset.
Co-authored-by: GitHub Copilot <copilot@github.com>
Signed-off-by: Ryan Turner <ryan@turnrye.com>
Refactor the static helper get_line_size to accept an explicit max_width
parameter instead of the hardcoded CONFIG_SCREEN_WIDTH cap. All three
call sites in gfx_printBuffer are updated to pass CONFIG_SCREEN_WIDTH,
preserving existing behaviour.
Add gfx_measureText: a pure-computation function that simulates the same
word-wrap pass as gfx_printBufferClipped (to be added next) without
touching the display. It returns the total pixel height of the laid-out
text block and accepts a char_count limit so callers can compute the
y-coordinate of an arbitrary cursor position for scroll-offset
calculations.
Add tests/unit/gfx_text.cpp and register the gfx_text_test executable in
meson.build. The test suite covers single-line strings, multi-line
strings via explicit newlines, char_count truncation, and word-wrap
height growth.
Co-authored-by: GitHub Copilot <copilot@github.com>
Signed-off-by: Ryan Turner <ryan@turnrye.com>
Add a test that generates 10 consecutive RRC-shaped stream frames and
asserts the demodulator stays locked throughout.
Co-authored-by: GitHub Copilot <175728472+github-copilot[bot]@users.noreply.github.com>
Signed-off-by: Ryan Turner <ryan@turnrye.com>
Drop the redundant 'M17' prefix from namespace-level constants in
Constants.hpp (SYMBOL_RATE, FRAME_SYMBOLS, SYNCWORD_SYMBOLS,
FRAME_BYTES) and from private class constants in Modulator
(TX_SAMPLE_RATE, SAMPLES_PER_SYMBOL, FRAME_SAMPLES, RRC_GAIN,
RRC_OFFSET). Update all references in Demodulator, Modulator, and
the demodulator test.
Co-authored-by: GitHub Copilot <175728472+Copilot@users.noreply.github.com>
M17 protocol code is already namespaced in M17, so it's redundant to name every class M17*. This change removes the leading M17 from all of the namespaced things.
Co-authored-by: GitHub Copilot <175728472+Copilot@users.noreply.github.com>
Signed-off-by: Ryan Turner <ryan@turnrye.com>
Add classes oriented around handling metadata in the M17 protocol.
Create a class for reassembling text blocks from metadata in order to
assemble a multi-frame metadata text message.
Co-authored-by: Wojciech Kaczmarski <w.kaczmarski@teletra.pl>
Co-authored-by: Jim Ancona <jim@anconafamily.com>
Co-authored-by: Rick Schnicker <crs026@yahoo.com>
Co-authored-by: GitHub Copilot <noreply@github.com>
Signed-off-by: Ryan Turner <ryan@turnrye.com>
The unit test directory had a number of manual linux platform tests that aren't really unit tests. They aren't written with assertions and have no documented use. This change deletes these from the testing suite. In the future they could be added back in a different place, or automated tests in the form of true unit or integration tests could be added. But this clarifies that all suites in the unit test folder are actually automated unit tests, and only one unexectued test remains (related to code that is planned to be reintroduced in the future).
Signed-off-by: Ryan Turner <ryan@turnrye.com>
From the old UI check standby test, update it to be Catch2-based.
Register the test in meson.build and add it to clang_format.sh
Co-authored-by: GitHub Copilot <copilot@github.com>
Signed-off-by: Ryan Turner <ryan@turnrye.com>
The previous demodulator test relied on reading a binary test file from
disk and used '#define private public' to access private class members,
both of which were fragile and broke after an M17 refactor.
Rewrite the test to exercise the public Correlator and Synchronizer
classes directly using synthesised input signals, covering:
* peak correlation for a matching stream syncword
* DC-signal proportionality
* syncword detection and sampling index validity
* no trigger on an above-maximum threshold
Re-enable the test in meson.build and fix the executable definition
ordering (place it after m17_rrc_test).
Co-authored-by: GitHub Copilot <copilot@github.com>
Signed-off-by: Ryan Turner <ryan@turnrye.com>
Port all currently-enabled unit tests to Catch2: replace the custom
main() / printf error-reporting boilerplate with TEST_CASE and REQUIRE
macros. Add catch2_dep to unit_test_opts now that it is actually used.
Tests ported: M17_callsign, M17_golay, M17_rrc, M17_viterbi, cps,
convert_minmea_coord, linux_inputStream. The M17 demodulator test is
still in its pre-Catch2 form and remains disabled, as it needs
significant rework (not just porting to Catch2).
Co-authored-by: GitHub Copilot <copilot@github.com>
Signed-off-by: Ryan Turner <ryan@turnrye.com>
Rename cps.c and convert_minmea_coord.c to .cpp so they can be built
with the C++ compiler required for Catch2. File content is unchanged at
this point - the Catch2 port follows in the next commit. Also update the
source references in meson.build and the file list in clang_format.sh.
Co-authored-by: GitHub Copilot <copilot@github.com>
Signed-off-by: Ryan Turner <ryan@turnrye.com>
This change removes the old copyright header from project sources and
replaces it with a new simplified SPDX-compliant header. Note that files
that were missing the header but reasonably understood to be licensed
according to the root license were not corrected.
Signed-off-by: Ryan Turner <ryan@turnrye.com>
Update meson and cmake config to only include openrtx and platform paths.
Update files to use <..> for system and external libraries, ".." for
project files and new relative paths as necessary.
Did not attempt to fix areas where includes that should be <..> were
previously ".."
Inspired by #96, closes#359.
Acked-by: Silvano Seva <silseva@fastwebnet.it>
New DC block filter implementation using fixed-point math and guaranteeing
zero DC component on the output signal.
Signed-off-by: Silvano Seva <silseva@fastwebnet.it>
- added missing initialization of codec2 in voice prompts code
- discarding the voice prompt header as we only support 3200 bit rate
- fixed wrong offset in pick vpQueueStringTableEntry
- fixed bug in vpInit causing voiceprompts to hang