News feed

  • gr-m17 and the improved Codec 2 blocks

    After a long and painful process, gr-m17 now contains Codec2-mod blocks. The difference between those and the “stock” Codec2 encoder/decoder blocks is that ours are much faster and support internal state reset. They have been designed specifically for the LinHT. This is very important when you run a flowgraph and expect repeated streams (each received transmission – internal state reset, same with PTT key press event for transmission).

    Andreas OE3ANC – thanks for helping me out with this.

  • LinHT M17 reception stability tests

    Today, I decided to stress-test my LinHT Rev A prototype. The aim was to assess the battery life in the following conditions: minimal transmission time – mostly reception. I used a CC1200 hotspot connected to M17-KCW A as a solid M17 RF source (with stable traffic). The handheld’s backlight (including keypad) was kept on for the whole test duration. Stock Retevis C62 2S Li-ion battery was used, fully charged on the previous day (in the evening). A modified charger was used – I replaced the 0.47ohm resistor with a 0.33ohm one* (a stack of three 1ohm resistors) for increased charge current. Silicon thermal pads were used to allow the SoC to dissipate heat through the aluminum part of the chassis (see this entry for details).

    I started the test by switching the volume knob at 9:17 LT. The starting battery voltage was 8.05V.

    At 19:17 LT (t+10h), the battery was at 6.7V.

    htop – CPU utilization and process list

    # uptime
    19:18:14 up 10:02, 2 users, load average: 0.49, 0.50, 0.47
    # ./LinHT-utils/scripts/temp.sh
    40.85

    CPU slightly below 41 deg. C after 10 hours of continuous DSP work? I think this is a very good result. This would definitely not be possible without some DSP tweaks we introduced in the M17 GNU Radio flowgraph. I had to quickly reset the flowgraph in the first 30 minutes due to an unexpected segfault 🙂 The cause is yet to be found.

    Last but not least – big shout out to the rest of our team – Andreas OE3ANC and Vlastimil OK5VAS, and every financial contributor out there. Let’s keep this up 🙂

    *the values are taken off the top of my head – I believe they are correct. The idea is to slightly reduce the resistance to increase the current.

  • rpi-dashboard 1.0.0 is out

    GitHub: https://github.com/M17-Project/rpi-dashboard

    The dashboard works in conjunction with Jim N1ADJ’s M17 Go gateway: https://github.com/jancona/m17

    Let your CC1200 hotspot’s LEDs blink happily!

  • CARI specification updates

    The Common Amateur Radio Interface (CARI) protocol has been updated with important clarifications and formal refinements. The update removed ambiguities in device selection, command framing, and supervision telemetry data transfer. The control and supervision planes are now explicitly defined. No functional changes were introduced, the update improves clarity only, therefore the protocol’s version number has not been incremented.

    Full changelog is available on GitHub:

    https://github.com/M17-Project/CARI/blob/main/docs/commands.md

  • m17-texting tool

    m17-texting tool just received long-waiting bug fixes. The app supports UTF-8 encoding. Go ahead and give it a spin.

    GitHub: https://github.com/M17-Project/m17-texting

    And yes, it works flawlessly with Digirig!

  • LinHT update

    We have decided to assemble a set of Rev B prototypes in Czech Republic due to long lead times at PCBWay.

    All of the electronic components are already there. A small batch of 10 PCBs has been ordered today. Stay tuned for more news.

    Big shout out to Vlastimil OK5VAS for a substantial support in making some real progress here.

  • M17 on the orbit (again)?

    FOSM-1 satellite might be capable of M17 RX/TX:

    FOSM-1 is designed by an non-profit organisation Fédération Open Space Makers. This is a hamradio spacestation payload that should flight starting Q2. It has received IARU coordination.

    That’s amazing news!

    More details: https://db.satnogs.org/satellite/JDIR-9578-9095-6812-4322

  • libm17 and gr-m17 updates

    libm17 received a few polishes recently, bumping up its version to 1.1.9. Changes include:

    • improved Viterbi decoder (in terms of speed, memory use, and robustness)
    • slight speed improvement of the Golay decoder
    • improved symbol slicer (should be faster)
    • improved lat/lon/radius encoding
    • tiny API changes – using char* for callsigns now
    • stricter unit tests
    • cmake fix
    • various cosmetic clean-ups

    gr-m17 uses libm17 1.1.9 now. Running make should result with a clean compilation. Nice! We are in the process of adding Codec 2 Out of Tree blocks, as the built-in set of Codec2 blocks depends on libcodec2. The native blocks can not be reset externally, they are not meant for “repeated” use. For the LinHT, we need improved blocks – computationally optimized and externally resettable. This is what we provide within gr-m17’s dev branch. As soon as the work is done, the experimental dev branch will be merged with main.

    Stay tuned for more news.

  • Codec2 vs. ETSI ACELP – spectral distortion

    After a few days of tweaking Codec2 guts, one question appeared. How much worse the LSP quantizer in ACELP (EN 300 395-2) is, as compared to that in Codec2? Both use the same excitation->filter model. The latter has excellent spectral distortion, much below of what could be called “transparent”. I remember comparing it back in 2022, but the results were never published.

    Now, back to theory. As per Wai Chu “Speech Coding Algorithms”, the formant filter’s transparency criteria are as follows:

    • average spectral distortion of less than 1 dB
    • less than 2% outliers having a spectral distortion above 2 dB
    • no outliers with spectral distortion larger than 4 dB

    Spectral distortion is defined as a “distance metric” between frequency responses of two filters (we are using log magnitude spectra here):

    SD=1n1−n0∑n=n0n1−1[20log⁡H1(n)−20log⁡H0(n)]2SD=\sqrt{\frac{1}{n_1-n_0}\sum_{n=n_0}^{n_1-1}\left[20\log{H_1(n)} – 20\log{H_0(n)}\right]^2}

    HH (frequency responses) are based on discrete Fourier transforms of the measured and reference LPC filters. FFT bins are usually set to 256. Typically, at 8 kHz sample rate, n1=100n_1=100 and n0=4n_0=4, giving 125..3,125 Hz range. Distortion outside this band is not considered perceptually critical.

    Now back to Codec2 and ETSI ACELP. We are only going to focus on the 3,200 bps rate of the former (20 ms frames, 64 bits each). ACELP runs at around 4,567bps (30 ms frames, 137 bits each).

    Codec2’s bit allocation for quantized LSPs is generous at 5 bits per LSP, yielding 50 bits total. ACELP isn’t as generous, spending only about half of that – 26 bits only.

    Codec2 uses delta-encoded spectral frequencies in frequency domain – ω\omega. ACELP utilizes split vector quantizer with LSPs in cosine domain – cos(ω)cos(\omega).

    Let’s look at the spectral distortion of both codecs:

    Now, the cumulative distribution (probability of SD below given threshold) for both:

    Pretty much the same information, just from another angle. Both plots were generated using LibriSpeech English speech corpus.

    Conclusion? Codec2 outperforms ACELP in terms of formant reconstruction but ACELP offers much, much more sophisticated excitation model. Excitation is Codec2’s biggest weakness. I really hope to be able to propose a better model in the coming months.

  • Codec2-mod – statistical tests

    I have used N=200 random files from the LibriSpeech corpus to run a comparison between Codec2 and Codec2-mod. I used ViSQOL perceptual quality estimator to calculate the Mean Opinion Score (MOS) for original-decompressed pairs for both implementations. Results are shown in the table at the bottom of this post(copied verbatim from terminal).

    The few mismatches are most likely caused by slightly different floating point maths (comparisons and fast cosine and arc cosine functions). Those may diverge slightly given edge-case input signal vectors. Still, Codec2-mod is functionally bit-exact with reference Codec2 for almost all inputs.

    The +0.006 difference in MOS is not significant (and even imperceptible). This number does not signify any perceptual improvement. I’m pretty sure that the value would converge to 0.0, given enough samples. A close to zero value means that there is no regression (which is good!).

    This is the histogram for both implementations:

    (more…)