Modules

Mesh

A LoRa radio and a GNSS receiver for the Kode Dot: messages that travel far and your position with no network, with the pins for your code.

The Mesh module sits on the back of the Kode Dot, over its top edge, with an antenna screwed on each of its two connectors
The Mesh module on a Kode Dot

What it is

The Mesh module lets the Kode Dot send messages to radios far away and know where it is. It needs no Wi-Fi and no phone, so it works where neither reaches, out in the hills or during a blackout. It carries two parts:

To see it work before writing code, install MeshKode. It turns the Kode Dot into a Meshtastic node, with chat, a map and the position of every node it hears. TBD: its listing on the marketplace. The radio is a NiceRF LoRa2021, with a Semtech LR2021 inside, and the receiver a Minewsemi ME31GR02.

How it is connected

The module comes in its own case and plugs into the header on the top edge. Inside, its board sits on the interposer, a passive adapter that carries every line straight through, so the GPIOs on this page are the header's own.

  1. Screw an antenna on each connector on top of the case. Both stand upright.
  2. Seat the module on the top edge of the Kode Dot. The pins enter the header and the case rests against the back.
  3. Open MeshKode, or your own app for the module. MeshKode shows the nodes it hears and, outdoors, your position.

The radio uses eight GPIOs: the SPI, a busy line, a reset and two DIOs. The receiver uses six: a UART at 115200 baud, a reset, a pulse per second and an I2C pair. All at 3.3 V. "Pin" is the header's pin, the same as J401's on the board, and the direction is the Kode Dot's:

GPIOPinSignalNote
GPIO83GNSS resetOutput, active low. No pull-up on the module: drive it high
GPIO94GNSS TXInput. The NMEA arrives here, at 115200 baud
GPIO105GNSS 1PPSInput. One pulse per second once the receiver has a fix
GPIO116GNSS RXOutput. Commands to the receiver
GPIO127LoRa resetOutput, active low. 10 kΩ pull-up
GPIO138LoRa DIO9Input. The radio's interrupt
GPIO149LoRa DIO8Input. Free
GPIO1517I2C SCLTo the receiver. 2.2 kΩ pull-up
GPIO1618I2C SDATo the receiver. 2.2 kΩ pull-up
GPIO1715LoRa MOSIOutput. SPI, to the radio
GPIO1816LoRa BUSYInput. High while the radio works: wait for it to drop before every command
GPIO1913LoRa MISOInput. SPI, from the radio
GPIO2014LoRa CSOutput, active low. 10 kΩ pull-up
GPIO2112LoRa SCKOutput. SPI clock

The labels the case prints beside the header, screen up and top edge towards you:

Row, left to rightLabels on the case
Screen side, pins 19 to 13V3 IO15 IO17 IO19 GND IO14 IO12 IO10 IO8 5V
Back side, pins 20 to 25V IO16 IO18 IO20 IO21 GND IO13 IO11 IO9 3V3

With the Kode Dot upright and the edge seen from above, left and right swap. The schematic and the KiCad sources are in hardware/mesh.

Specifications

The module:

ThingValue
PartKDMSH001, revision 1.0, issue of 2026-10-26. Same circuit as the 2026-10-07 issue; black solder mask, and the receiver's firmware named in the bill of materials
Mounts onThe Kode Dot's 20-pin header, through the interposer (KDINT001) inside the case
CaseTwo parts, base and lid, the same shape as the F*CK module's
Board41.9 × 44.7 mm, four layers
Supply3.3 V on pins 2 and 19, ground on 10 and 11. Under 0.25 A, adding the datasheets. The radio alone draws 142 mA transmitting at +22 dBm on 868 MHz, measured by NiceRF. TBD: the current measured on a board
5 VNot used
ValidatedOn boards of the 2026-09-14 issue: the GNSS over the UART, the pulse per second, the I2C and the radio answering over SPI, between 2026-09-29 and 2026-10-02. Two Kode Dots running MeshKode exchange text and voice. TBD: the same on the 2026-10-26 issue

The radio:

ThingValue
RadioNiceRF LoRa2021, with a Semtech LR2021 inside
Sub-GHz863–928 MHz on J501, which covers the 868 MHz and 915 MHz bands
2.4 GHzOn J502
PowerUp to +22 dBm on J501 and +12 dBm on J502, the limits of the LR2021 driver in RadioLib 7.7.1. On 868 MHz, with the amplifier settings Kode's certified firmware uses, 13.1–14.1 dBm measured. TBD: the power measured on J502
RF pathOne port per band, no RF switch. The radio's DIO7 is not connected
RegulatorLDO mode. The module does not bring out the DC-DC pins
MeshtasticMeshKode is a Meshtastic build with a driver for the LR2021. A stock Meshtastic image does not drive this radio
ConnectorsTBD: plain SMA or reverse-polarity SMA, by the connector Kode orders for production
AntennasTBD: which antennas ship with the module and how the case marks each port

Your country's rules say what you may transmit on each band, at what power and how often. The table says what the hardware can do.

The receiver:

ThingValue
ReceiverMinewsemi ME31GR02, with a Beken BK1661 inside
SystemsGPS, BeiDou (B1I and B1C), GLONASS, Galileo, QZSS and SBAS, on L1, per the part's datasheet
OutputNMEA over a UART at 115200 baud, and a pulse per second on GPIO10
AntennaA Quectel YPGS001AA chip antenna on the board, no connector for an external one
BackupA 0.22 F supercapacitor keeps the receiver's memory while the Kode Dot is off. TBD: for how long
I2CGPIO15 for SCL and GPIO16 for SDA. The receiver answers at 0x54 only with Minew's dual firmware, which prints $FWVER V5.26.35.5 at start-up. The 2026-10-26 issue names that firmware in the bill of materials; the boards reviewed on 2026-09-28 carried the standard one, V5.25.46.5. TBD: $FWVER on a board of this issue
Start-upTBD: the time to first fix, cold and warm, measured outdoors
While transmittingTBD: whether the receiver keeps its fix while the radio transmits

Gotchas

Example code

For the LoRa radio, the library is RadioLib, the one Meshtastic uses, with its LR2021 driver and the pins from the table. For the receiver's sentences any NMEA library works, and ESP-IDF ships an example, peripherals/uart/nmea0183_parser.

This example takes the receiver out of reset and copies everything it sends to the log. In idf.py monitor you will see NMEA sentences, lines starting with $, once a second. Indoors they come with empty fields until the receiver sees satellites.

/*
 * mesh_gnss.c - 2026-10-14 - from Kode with love
 *
 * Copies to the log what the GNSS receiver of the Mesh module says. Takes
 * the receiver out of reset with GPIO8 and opens its UART at 115200 baud on
 * GPIO9 and GPIO11. In the monitor you will see NMEA sentences, lines that
 * start with $, once a second; indoors they come with empty fields.
 */
#include <stdio.h>
#include "driver/gpio.h"
#include "driver/uart.h"
 
#define GNSS_RESET        GPIO_NUM_8    /* active low, no pull-up on the module */
#define GNSS_DATA_IN      GPIO_NUM_9    /* the NMEA arrives here */
#define GNSS_COMMAND_OUT  GPIO_NUM_11   /* commands to the receiver */
 
/* Takes the receiver out of reset and logs every byte it sends. */
void app_main(void)
{
    gpio_set_direction(GNSS_RESET, GPIO_MODE_OUTPUT);
    gpio_set_level(GNSS_RESET, 1);
 
    uart_config_t uart = {
        .baud_rate = 115200,
        .data_bits = UART_DATA_8_BITS,
        .parity = UART_PARITY_DISABLE,
        .stop_bits = UART_STOP_BITS_1,
        .source_clk = UART_SCLK_DEFAULT,
    };
    uart_driver_install(UART_NUM_1, 2048, 0, 0, NULL, 0);
    uart_param_config(UART_NUM_1, &uart);
    uart_set_pin(UART_NUM_1, GNSS_COMMAND_OUT, GNSS_DATA_IN, UART_PIN_NO_CHANGE, UART_PIN_NO_CHANGE);
 
    uint8_t text[256];
    while (1) {
        int length = uart_read_bytes(UART_NUM_1, text, sizeof(text), portMAX_DELAY);
        fwrite(text, 1, length, stdout);   /* every sentence brings its own line end */
    }
}

Compiled on the date in the header with ESP-IDF v6.1. TBD: a run on a module.

In the SDK