News feed

  • OpenRTX v0.4.5 released

    Changes include M17-related fixes.

    Full changelog: https://github.com/OpenRTX/OpenRTX/releases/tag/v0.4.5

    Give it a spin 😉

  • rpi-dashboard v1.2.0 is out

    It is strongly suggested to download the latest installer and run it. From now on, the installer checks for a newer version of itself on each run, so this manual download is needed only once.

    Dashboard:

    • security fixes: changing settings requires a password, shell injection and arbitrary file reading and writing through the config paths are fixed, CSRF protection on all forms
    • RF signal quality is now shown as bit error rate (BER), averaged over the whole voice stream, with color thresholds from a noise-limited test, and the M17 hostfile comes from the new source and is only downloaded when it has changed (thanks to Jim N1ADJ)
    • renamed a couple of menu entries
    • times use the configured timezone
    • the “Max. text messages” setting now works
    • expired map markers are removed
    • TX power is read from the config instead of being hardcoded
    • the reflector and radio status is now correct regardless of when the connection was made
    • added a “Device control” panel with reboot/shutdown buttons
    • the last element on each page no longer sits under the fixed footer

    The installer script:

    • the script automatically sets the modem type based on user input
    • the web server can write only config.php and files/, no longer the whole dashboard directory
    • nginx: it now blocks web access to the dashboard’s files/ directory

  • gr-m17 v1.0.0 is out

    Finally, after all these years, we have reached a point where everything seems to work. That’s the 1.0.0 reference point. I would like to express my sincere gratitude to Jean-Michel Friedt for all the help that he provided.

    Recent changes include:

    • Build: clean on GNU Radio 3.10, with the submodules updated (Codec2-mod, micro-ecc, libm17)
    • Dialogs: tidy, with hex key entry, all META types, and the decoder following the received stream
    • Encoder: correct SOT/EOT/SMS messages handling, a reliable stream loop, “continuous mode” (running without external message control, basically what we had before), multi-block Text Data, and SMS up to 821 bytes
    • Signing, scrambler, and AES now work end to end, and were checked independently against an external ECDSA reference, the spec’s LFSR polynomials, and Python’s cryptography AES
    • Decoder output is defined for unusable frames: Codec2 silence, chosen by listening (replacing invalid frames with zeros or inserting silence both sound worse)
    • Console output is readable and consistent (a lot of cleanups)
    • Categorization: we split the M17 part from Codec2

    Side effects (positive!):

    • Spec: the scrambler section was clarified, and the AES counter contradiction fixed
    • M17_Implementations: the LSF CRC bug in m17-coder-sym is now fixed

    Have fun!

  • M17 at HamExpo 2026, Le Mans

    Niall, F5VCV, has just sent us a photo from the ongoing HamExpo ham fair.

    From left to right: Niall F5VCV, Laurent F1OBK, and Jérôme F4HGI.

    It is always great to see people advocating M17 use! Merci beaucoup!

  • Updates

    • M17 Specification document. Bumped to 2.0.6. We found two problems. There are 369 bits at the output of the puncturer in BERT mode, one of them has to be discarded (the last one). Next, the maximum altitude that can be stored in the META GNSS position field was calculated incorrectly, the value is now fixed.
    • libm17. Viterbi decoder works faster now. All decoders are re-entrant (older API stayed). Caller can decide which way to choose.
    • T9 text entry. Faster execution. Memory optimizations should follow.

  • Codec2-mod and LinHT updates

    Let’s start with Codec2-mod. I brought back another 4kB of otherwise wasted space – complex FFT where real-valued counterpart can be used. Next, in-place FFTs removed – no hidden mallocs. Encoder phase estimation and using arctangent in the synthesis path – gone. I also thoroughly benchmarked the result versus vanilla Codec2 (damn, the repository is such a mess – why do they keep all of the non-codec stuff inside a “codec2” repo?). Code and results are here. See the tables in the readme for more details.

    LinHT Rev C boards have arrived! We are waiting for a few missing parts to show up and we will continue with assembly.

    Photos courtesy of Vlastimil, OK5VAS.

    Stay tuned.

  • Codec2 test suite

    I expanded my old Bash script a bit. It runs ViSQOL-based quality and compatibility tests for Codec2-mod vs. vanilla Codec2 (3200 mode), including cross-encoding between the two (this is the new addition).

    Here’s the script: https://github.com/M17-Project/Codec2-mod-eval

    You need to provide a set of WAV files for the script to work on. Using an English speech corpus such as LibriSpeech or any other from OpenSLR is a good idea.

    Have fun!

  • Circling back at authentication – M17 ECDSA stream signatures

    M17 is probably one of the very few modes allowing users to sign their data streams.

    In June 2024, I tested micro-ecc and ST CMOX library on a Module17. The results were published on Twitter:

    Finally some good news regarding digital signatures. I’ve been experimenting with ST’s CMOX library and just got 160-bit ECDSA to run on the Module17. It takes around 8.25ms to sign a 16-byte M17 voice stream digest. The signature can be appended to the voice stream.

    The MCU is STM32F405RGT6, clocked at 168 MHz.

    Signing with NIST-R P-256 (SECP256R1) curve takes 14.86 ms.

    If I remember correctly, CMOX library was used to get that 15ms result (secp256r1 curve). Micro-ecc yielded much worse execution times.

    Today, I improved the micro-ecc library using comb multiplication. Preliminary tests using Renode (as I don’t have any STM32 Nucleo with me, nor any OpenRTX target) are promising. The signing time reduced from 27 down to 14ms, without CMOX, at 100MHz (emulated STM32F411). That’s great, because CMOX library can not be used on microcontrollers other than the original STM32. The library checks the hardware it is executed on and silently corrupts data without even telling. Great, right? This optimization should allow us to run ECDSA efficiently, even on GD32 MCUs.

    The proposed code uses a uECC_COMB_MULT macro, so the user (developer) can select which calculation path to use – the original one or optimized.

    Getting rid of this roadblock should get us one step closer to having M17 authentication support in OpenRTX.

  • Codec2-mod updates

    You thought we gave up on Codec2 just because we have already improved it considerably? Wrong!

    After a short discussion with Silvano IU2KWO, an interesting proposal emerged: split the whole codec2_t structure into two separate, smaller encoder and decoder parts. That way you no longer have to push the whole structure on the stack and fill it up with FFT twiddle factors, if you only need to use one part of it. Now, if you want to encode or decode speech, just use either encoder or decoder. This simplifies things and optimizes memory usage further. This brings significant savings that are required by OpenRTX (and probably any implementation running on limited-resources MCUs). The old path using a large structure is still available (e.g. for duplex operation).

    On top of that, I also tweaked the KISS FFT internals to use built-in sincosf() calls instead of using standard sin() / cos(). Using doubles is generally not a great idea, unless you really have to do so. We do not, so I took one step further and eliminated all double-precision promotions that were hiding in the code. Yes, there were many such places, especially where M_PI was used, along with some other macros.

    The code is available in the split-no-double branch.

    I prepared a quick benchmark. The results are below.

    Codec2-mod branchcodec2_initcodec2_encoder_initcodec2_decoder_initcodec2_encodecodec2_decode
    main67.905––6.43711.804
    split-no-double8.9585.8243.1365.5558.559
    Speedup7.6x––1.2x1.4x
    Branches comparison. Times are average for a run of 1000, in milliseconds.

    An STM32F411 clocked at 100MHz was used for both tests with the code compiled using -Os flag (gcc 14.3.0).

    Next, using a set of 2,000 wave files, mostly 3 to 20 seconds long, I compared the vanilla Codec2 with our experimental branch. As the last time, I measured ViSQOL scores for both: original wave file -> encoder -> decoder -> decoded wave file. The average score of the new code is +0.005. That suggests the applied changes are inaudible (theoretically – real-life tests will follow). The test also calculated Hamming distance between the encoded files for both implementations – the no-double differs in less than 0.5% of the bits. This means that the new code does not generally agree with Codec2, but that does not make the bitstreams incompatible. Small rounding errors cause this but, as shown by the speech quality metric, all cancel out.

    ViSQOL score / Hamming distance checks (vanilla Codec2 vs Codec2-mod split-no-doubles branch).

    There is one more test that should be performed: encode samples with Codec2 and decode the bitstream with Codec2-mod, then switch the direction and listen to both files.

    Big shout out to Silvano IU2KWO for nudging me in the right direction.

  • Successful M17 transmission using an unmodified Retevis C62 running OpenRTX

    The moment has come! An experimental branch of OpenRTX (Andreas OE3ANC, Marko13, Andrej K8TUN, jki275 et al.) has reached a long-awaited milestone – a successful transmission of M17 signal using an unmodified Retevis C62. Marvellous work, guys!

    For now, the RF output power is limited due to our lack of understanding on how the calibration data is stored and used. The reverse-engineering work on that is pending. M17 reception does not work yet, but it is expected to be added soon. There is no settings persistence in this model yet.

    The most important thing is that the C62 radio is available at about $45 and does not require any hardware modifications to run the M17 mode. This is the game-changer we have all been waiting for. After adding the missing functionalities, this will easily become the go-to radio for everyday M17 use. On top of that, you get all the OpenRTX goodies, such as APRS support and voice prompts.

    At this point, I would like to thank everyone involved in this subproject – not only the devs who did some amazing coding work, but also our Ambassador, Mr. Amo Xu BD4VOW for acting as an excellent interface between us and the Chinese manufacturers.

    In the meantime, LinHT’s Revision B has been tagged on GitHub. We are working on the Revision C – an order for a test batch should be placed later this month. Big shout out to Vlastimil OK5VAS for his continuous help with this device 🙂

    And, as always, there’s more to follow!


    PS. We have a very important request. Since LLMs are being heavily used by journalists, bloggers, and other people publishing content on the Internet, some articles covering our activities might not be accurate. Every time you see an error, please take a moment to report it to the author(s). Thank you very much!