Keyboard shortcuts

Press or to navigate between chapters

Press S or / to search in the book

Press ? to show this help

Press Esc to hide this help

MeshCore Protocol Specification

Section 19: KISS Modem Protocol

Overview

The KISS (Keep It Simple, Stupid) modem protocol provides a serial interface to MeshCore LoRa radios. It follows the KA9Q/K3MC KISS TNC specification with MeshCore-specific SetHardware extensions for cryptographic operations, radio control, and telemetry.

Serial Configuration

  • Baud rate: 115200
  • Data bits: 8
  • Parity: None
  • Stop bits: 1
  • Flow control: None

Frame Format

┌──────┬───────────┬──────────────┬──────┐
│ FEND │ Type Byte │ Data (escaped)│ FEND │
│ 0xC0 │  1 byte   │ 0-510 bytes  │ 0xC0 │
└──────┴───────────┴──────────────┴──────┘

Special Bytes

ByteNameValueDescription
FENDFrame End0xC0Frame delimiter
FESCFrame Escape0xDBEscape character
TFENDTransposed FEND0xDCFESC + TFEND represents 0xC0 in data
TFESCTransposed FESC0xDDFESC + TFESC represents 0xDB in data

Byte Stuffing

To send a data byte of 0xC0 (FEND), emit: 0xDB 0xDC (FESC TFEND). To send a data byte of 0xDB (FESC), emit: 0xDB 0xDD (FESC TFESC).

Type Byte

  Bit:  7   6   5   4   3   2   1   0
      +---+---+---+---+---+---+---+---+
      |    Port (4)   |  Command (4)  |
      +---+---+---+---+---+---+---+---+

Port is 0 for single-port TNC (standard for MeshCore).

Standard KISS Commands (Host to TNC)

CommandValueDataDescription
DataFrame0x00Raw packetQueue packet for transmission
TXDELAY0x011 byteTransmitter keyup delay (× 10ms)
Persistence0x021 byteCSMA persistence (0-255)
SlotTime0x031 byteCSMA slot interval (× 10ms)
TXtail0x041 bytePost-TX hold time (× 10ms)
FullDuplex0x051 byte0=half, nonzero=full
SetHardware0x06Sub-cmd + dataMeshCore extensions
Return0xFFExit KISS mode (no-op)

TNC to Host

TypeValueDataDescription
DataFrame0x00Raw packetReceived packet from radio

Data frames carry raw MeshCore packets (up to 255 bytes, MAX_TRANS_UNIT).

SetHardware Extensions (0x06)

MeshCore extends the KISS protocol via the SetHardware command. The first data byte is a sub-command identifier.

Request Sub-commands (Host to TNC):

Sub-cmdValueDataDescription
GetIdentity0x01Get node’s Ed25519 public key
GetRandom0x02len(1)Get random bytes (1-64)
VerifySignature0x03pubkey(32)+sig(64)+dataVerify Ed25519 signature
SignData0x04dataEd25519 sign
EncryptData0x05key(32)+plaintextAES-128 encrypt
DecryptData0x06key(32)+mac(2)+ciphertextAES-128 decrypt with MAC
KeyExchange0x07remote_pub(32)X25519 ECDH
Hash0x08dataSHA-256 hash
SetRadio0x09freq(4)+bw(4)+sf(1)+cr(1)Set radio parameters
SetTxPower0x0Apower(1)Set TX power (dBm)
GetRadio0x0BGet radio parameters
GetTxPower0x0CGet TX power
GetCurrentRssi0x0DGet current RSSI
IsChannelBusy0x0ECheck if channel busy
GetAirtime0x0Fpkt_len(1)Estimate air time
GetNoiseFloor0x10Get noise floor
GetVersion0x11Get firmware version
GetStats0x12Get RX/TX statistics
GetBattery0x13Get battery voltage
GetMCUTemp0x14Get MCU temperature
GetSensors0x15perms(1)Get sensor data
GetDeviceName0x16Get device name
Ping0x17Ping
Reboot0x18Reboot device
SetSignalReport0x19enable(1)Enable/disable RxMeta
GetSignalReport0x1AGet signal report status

Response Sub-commands (TNC to Host):

Response codes: response = command | 0x80

Sub-cmdValueData
Identity0x81pubkey(32)
Random0x82random_bytes(1-64)
Verify0x83result(1): 0=invalid, 1=valid
Signature0x84signature(64)
Encrypted0x85mac(2)+ciphertext
Decrypted0x86plaintext
SharedSecret0x87secret(32)
HashResult0x88hash(32)
Radio0x8Bfreq(4)+bw(4)+sf(1)+cr(1)
TxPower0x8Cpower(1)
CurrentRssi0x8Drssi(1, signed)
ChannelBusy0x8Ebusy(1): 0=clear, 1=busy
Airtime0x8Fmillis(4)
NoiseFloor0x90dBm(2, signed)
Version0x91version(1)+reserved(1)
Stats0x92rx(4)+tx(4)+errors(4)
Battery0x93millivolts(2)
MCUTemp0x94temp(2, signed, tenths °C)
Sensors0x95CayenneLPP data
DeviceName0x96name(UTF-8)
Pong0x97
SignalReport0x9Astatus(1)
OK0xF0
Error0xF1error_code(1)
TxDone0xF8result(1): 0=fail, 1=success
RxMeta0xF9snr(1)+rssi(1)

Error Codes

CodeValueDescription
InvalidLength0x01Request data too short
InvalidParam0x02Invalid parameter value
NoCallback0x03Feature not available
MacFailed0x04MAC verification failed
UnknownCmd0x05Unknown sub-command
EncryptFailed0x06Encryption failed

Unsolicited Events

TxDone (0xF8): Sent after packet transmission. 0x01 = success, 0x00 = fail.

RxMeta (0xF9): Sent after each received data frame. Contains:

  • SNR: 1 byte, signed, × 4 for 0.25 dB precision
  • RSSI: 1 byte, signed, dBm

Data Format Notes

  • Maximum payload per frame: 255 bytes (MAX_TRANS_UNIT)
  • Frames larger than 255 unescaped bytes are silently dropped
  • All multi-byte integers are little-endian
  • Radio frequency is in Hz (e.g., 869618000)
  • Battery voltage in millivolts
  • MCU temperature in tenths of °C (e.g., 253 = 25.3°C)

Cross-References

Reference Implementation

  • docs/kiss_modem_protocol.md in the MeshCore repository