HERMES Modem
Hermes ARQ/Broadcast modem
Loading...
Searching...
No Matches
Functions | Variables
arq_protocol.c File Reference
#include "arq_protocol.h"
#include <string.h>
#include <stdio.h>
#include <stdatomic.h>
#include "../modem/freedv/freedv_api.h"
#include "../modem/framer.h"
#include "arq.h"
Include dependency graph for arq_protocol.c:

Functions

void init_model (void)
 
int arithmetic_encode (const char *msg, uint8_t *output)
 
int arithmetic_decode (uint8_t *input, int max_len, char *output, int max_output)
 
const arq_mode_timing_tarq_protocol_mode_timing (int freedv_mode)
 Look up mode timing entry for a FreeDV mode.
 
int arq_protocol_encode_hdr (uint8_t *buf, size_t buf_len, const arq_frame_hdr_t *hdr)
 Encode a parsed header into the first ARQ_FRAME_HDR_SIZE bytes of buf.
 
int arq_protocol_decode_hdr (const uint8_t *buf, size_t buf_len, arq_frame_hdr_t *hdr)
 Decode the ARQ header from the first bytes of buf.
 
uint8_t arq_protocol_bw_token_from_hz (int bw_hz)
 Map a configured bandwidth in Hz to an on-air BW token.
 
int arq_protocol_bw_hz_from_token (uint8_t bw_token)
 Map an on-air BW token back to Hz.
 
uint8_t arq_protocol_encode_snr (float snr_db)
 Encode a floating-point SNR (dB) into the snr_raw wire byte.
 
float arq_protocol_decode_snr (uint8_t snr_raw)
 Decode snr_raw wire byte back to float dB.
 
uint8_t arq_protocol_encode_ack_delay (uint32_t delay_ms)
 Encode ack_delay_ms to the 8-bit wire value (10ms units, max 2.55s).
 
uint32_t arq_protocol_decode_ack_delay (uint8_t raw)
 Decode the 8-bit wire ack_delay to milliseconds.
 
static int build_ctrl (uint8_t *buf, size_t buf_len, uint8_t subtype, uint8_t session_id, uint8_t tx_seq, uint8_t rx_ack_seq, uint8_t flags, uint8_t snr_raw, uint8_t ack_delay_raw, const uint8_t *payload, size_t payload_len)
 
int arq_protocol_build_ack (uint8_t *buf, size_t buf_len, uint8_t session_id, uint8_t rx_ack_seq, uint8_t flags, uint8_t snr_raw, uint8_t ack_delay_raw)
 ACK frame.
 
int arq_protocol_build_disconnect (uint8_t *buf, size_t buf_len, uint8_t session_id, uint8_t snr_raw)
 DISCONNECT frame.
 
int arq_protocol_build_keepalive (uint8_t *buf, size_t buf_len, uint8_t session_id, uint8_t snr_raw)
 KEEPALIVE frame.
 
int arq_protocol_build_keepalive_ack (uint8_t *buf, size_t buf_len, uint8_t session_id, uint8_t snr_raw)
 KEEPALIVE_ACK frame.
 
int arq_protocol_build_turn_req (uint8_t *buf, size_t buf_len, uint8_t session_id, uint8_t rx_ack_seq, uint8_t snr_raw)
 TURN_REQ frame.
 
int arq_protocol_build_turn_ack (uint8_t *buf, size_t buf_len, uint8_t session_id, uint8_t snr_raw)
 TURN_ACK frame.
 
int arq_protocol_build_mode_req (uint8_t *buf, size_t buf_len, uint8_t session_id, uint8_t snr_raw, int freedv_mode)
 MODE_REQ frame.
 
int arq_protocol_build_mode_ack (uint8_t *buf, size_t buf_len, uint8_t session_id, uint8_t snr_raw, int freedv_mode)
 MODE_ACK frame — accept peer's mode request.
 
int arq_protocol_build_data (uint8_t *buf, size_t buf_len, uint8_t session_id, uint8_t tx_seq, uint8_t rx_ack_seq, uint8_t flags, uint8_t snr_raw, uint8_t payload_valid, const uint8_t *payload, size_t payload_len)
 DATA frame — 8-byte header + payload bytes.
 
uint16_t arq_protocol_callsign_crc16 (const char *callsign)
 Compute CRC16-CCITT of an uppercase-normalised callsign.
 
static int encode_callsign_payload (const char *src, const char *dst, uint8_t *out, size_t out_cap)
 
static int decode_callsign_payload (const uint8_t *in, size_t in_len, char *src_out, char *dst_out)
 
static int encode_callsign_only_payload (const char *src, uint8_t *out, size_t out_cap)
 
static int decode_callsign_only_payload (const uint8_t *in, size_t in_len, char *src_out)
 
static int build_call_accept (uint8_t *buf, size_t buf_len, bool is_accept, uint8_t session_id, const char *src, const char *dst, int bw_hz)
 
int arq_protocol_build_call (uint8_t *buf, size_t buf_len, uint8_t session_id, const char *src, const char *dst, int bw_hz)
 Build a CALL frame.
 
int arq_protocol_build_accept (uint8_t *buf, size_t buf_len, uint8_t session_id, const char *src, const char *dst, int bw_hz)
 Build an ACCEPT frame.
 
static int parse_call_accept (const uint8_t *buf, size_t buf_len, uint8_t *session_id_out, char *src_out, char *dst_out, int *bw_hz_out)
 
int arq_protocol_parse_call (const uint8_t *buf, size_t buf_len, uint8_t *session_id_out, char *src_out, char *dst_out, int *bw_hz_out)
 Parse a CALL frame; extract callsigns.
 
int arq_protocol_parse_accept (const uint8_t *buf, size_t buf_len, uint8_t *session_id_out, char *src_out, char *dst_out, int *bw_hz_out)
 Parse an ACCEPT frame; same layout as CALL.
 
int arq_protocol_build_cq (uint8_t *buf, size_t buf_len, const char *src, int bw_hz)
 Build a compact DATAC13 CQ frame carrying source callsign and BW token.
 
int arq_protocol_parse_cq (const uint8_t *buf, size_t buf_len, char *src_out, int *bw_hz_out)
 Parse a compact DATAC13 CQ frame.
 

Variables

_Atomic int arq_call_retry_slots = ARQ_CALL_RETRY_SLOTS_DEFAULT
 
_Atomic int arq_accept_retry_slots = ARQ_ACCEPT_RETRY_SLOTS_DEFAULT
 
_Atomic int arq_data_retry_slots = ARQ_DATA_RETRY_SLOTS_DEFAULT
 
_Atomic int arq_disconnect_retry_slots = ARQ_DISCONNECT_RETRY_SLOTS_DEFAULT
 
const arq_mode_timing_t arq_mode_table []
 
const int arq_mode_table_count
 

Function Documentation

◆ arithmetic_decode()

int arithmetic_decode ( uint8_t *  input,
int  max_len,
char *  output,
int  max_output 
)
extern

◆ arithmetic_encode()

int arithmetic_encode ( const char *  msg,
uint8_t *  output 
)
extern

◆ arq_protocol_build_accept()

int arq_protocol_build_accept ( uint8_t *  buf,
size_t  buf_len,
uint8_t  session_id,
const char *  src,
const char *  dst,
int  bw_hz 
)

Build an ACCEPT frame.

Parameters
bufOutput buffer (caller-provided).
buf_lenSize of buf in bytes.
session_idARQ session identifier.
srcLocal callsign.
dstRemote callsign.
bw_hzAccepted bandwidth in Hz.

◆ arq_protocol_build_ack()

int arq_protocol_build_ack ( uint8_t *  buf,
size_t  buf_len,
uint8_t  session_id,
uint8_t  rx_ack_seq,
uint8_t  flags,
uint8_t  snr_raw,
uint8_t  ack_delay_raw 
)

ACK frame.

flags = ARQ_FLAG_HAS_DATA when IRS has pending TX data.

◆ arq_protocol_build_call()

int arq_protocol_build_call ( uint8_t *  buf,
size_t  buf_len,
uint8_t  session_id,
const char *  src,
const char *  dst,
int  bw_hz 
)

Build a CALL frame.

Parameters
bufOutput buffer (caller-provided).
buf_lenSize of buf in bytes.
session_idARQ session identifier.
srcLocal callsign.
dstRemote callsign.
bw_hzRequested bandwidth in Hz.
Returns
Total frame bytes (ARQ_CONTROL_FRAME_SIZE = 14) on success, -1 on error.

◆ arq_protocol_build_cq()

int arq_protocol_build_cq ( uint8_t *  buf,
size_t  buf_len,
const char *  src,
int  bw_hz 
)

Build a compact DATAC13 CQ frame carrying source callsign and BW token.

◆ arq_protocol_build_data()

int arq_protocol_build_data ( uint8_t *  buf,
size_t  buf_len,
uint8_t  session_id,
uint8_t  tx_seq,
uint8_t  rx_ack_seq,
uint8_t  flags,
uint8_t  snr_raw,
uint8_t  payload_valid,
const uint8_t *  payload,
size_t  payload_len 
)

DATA frame — 8-byte header + payload bytes.

Parameters
bufOutput buffer (caller-provided).
buf_lenSize of buf in bytes.
session_idARQ session identifier.
tx_seqTX sequence number.
rx_ack_seqLast seq received from peer (piggybacked ACK).
flagsARQ_FLAG_TURN_REQ | ARQ_FLAG_HAS_DATA (bitmask).
snr_rawLocal SNR encoded for wire.
payload_validNumber of valid bytes in the payload slot.
payloadPayload bytes (must be <= buf_len - ARQ_FRAME_HDR_SIZE).
payload_lenNumber of payload bytes.

◆ arq_protocol_build_disconnect()

int arq_protocol_build_disconnect ( uint8_t *  buf,
size_t  buf_len,
uint8_t  session_id,
uint8_t  snr_raw 
)

DISCONNECT frame.

◆ arq_protocol_build_keepalive()

int arq_protocol_build_keepalive ( uint8_t *  buf,
size_t  buf_len,
uint8_t  session_id,
uint8_t  snr_raw 
)

KEEPALIVE frame.

◆ arq_protocol_build_keepalive_ack()

int arq_protocol_build_keepalive_ack ( uint8_t *  buf,
size_t  buf_len,
uint8_t  session_id,
uint8_t  snr_raw 
)

KEEPALIVE_ACK frame.

◆ arq_protocol_build_mode_ack()

int arq_protocol_build_mode_ack ( uint8_t *  buf,
size_t  buf_len,
uint8_t  session_id,
uint8_t  snr_raw,
int  freedv_mode 
)

MODE_ACK frame — accept peer's mode request.

◆ arq_protocol_build_mode_req()

int arq_protocol_build_mode_req ( uint8_t *  buf,
size_t  buf_len,
uint8_t  session_id,
uint8_t  snr_raw,
int  freedv_mode 
)

MODE_REQ frame.

Parameters
bufOutput buffer (caller-provided).
buf_lenSize of buf in bytes.
session_idARQ session identifier.
snr_rawLocal SNR encoded for wire.
freedv_modeRequested payload FreeDV mode (FREEDV_MODE_DATAC*).

◆ arq_protocol_build_turn_ack()

int arq_protocol_build_turn_ack ( uint8_t *  buf,
size_t  buf_len,
uint8_t  session_id,
uint8_t  snr_raw 
)

TURN_ACK frame.

◆ arq_protocol_build_turn_req()

int arq_protocol_build_turn_req ( uint8_t *  buf,
size_t  buf_len,
uint8_t  session_id,
uint8_t  rx_ack_seq,
uint8_t  snr_raw 
)

TURN_REQ frame.

Parameters
bufOutput buffer (caller-provided).
buf_lenSize of buf in bytes.
session_idARQ session identifier.
rx_ack_seqLast seq received from current ISS (so ISS can flush pending retries).
snr_rawLocal SNR encoded for wire.

◆ arq_protocol_bw_hz_from_token()

int arq_protocol_bw_hz_from_token ( uint8_t  bw_token)

Map an on-air BW token back to Hz.

Returns
500/2300/2750 on success, or 0 if the token is invalid.

◆ arq_protocol_bw_token_from_hz()

uint8_t arq_protocol_bw_token_from_hz ( int  bw_hz)

Map a configured bandwidth in Hz to an on-air BW token.

Returns
ARQ_BW_TOKEN_* value, or ARQ_BW_TOKEN_NONE if unsupported.

◆ arq_protocol_callsign_crc16()

uint16_t arq_protocol_callsign_crc16 ( const char *  callsign)

Compute CRC16-CCITT of an uppercase-normalised callsign.

Used to encode/validate the DST field in CALL/ACCEPT frames.

◆ arq_protocol_decode_ack_delay()

uint32_t arq_protocol_decode_ack_delay ( uint8_t  raw)

Decode the 8-bit wire ack_delay to milliseconds.

◆ arq_protocol_decode_hdr()

int arq_protocol_decode_hdr ( const uint8_t *  buf,
size_t  buf_len,
arq_frame_hdr_t hdr 
)

Decode the ARQ header from the first bytes of buf.

Returns
0 on success, -1 if buf too short.

◆ arq_protocol_decode_snr()

float arq_protocol_decode_snr ( uint8_t  snr_raw)

Decode snr_raw wire byte back to float dB.

Returns
SNR in dB, or 0.0f if snr_raw == 0 (unknown).

◆ arq_protocol_encode_ack_delay()

uint8_t arq_protocol_encode_ack_delay ( uint32_t  delay_ms)

Encode ack_delay_ms to the 8-bit wire value (10ms units, max 2.55s).

◆ arq_protocol_encode_hdr()

int arq_protocol_encode_hdr ( uint8_t *  buf,
size_t  buf_len,
const arq_frame_hdr_t hdr 
)

Encode a parsed header into the first ARQ_FRAME_HDR_SIZE bytes of buf.

Returns
0 on success, -1 if buf_len < ARQ_FRAME_HDR_SIZE.

◆ arq_protocol_encode_snr()

uint8_t arq_protocol_encode_snr ( float  snr_db)

Encode a floating-point SNR (dB) into the snr_raw wire byte.

Returns
Encoded byte (0 if snr_db is out of range or unknown).

◆ arq_protocol_mode_timing()

const arq_mode_timing_t * arq_protocol_mode_timing ( int  freedv_mode)

Look up mode timing entry for a FreeDV mode.

Returns
Pointer to timing entry, or NULL if mode is unknown.

◆ arq_protocol_parse_accept()

int arq_protocol_parse_accept ( const uint8_t *  buf,
size_t  buf_len,
uint8_t *  session_id_out,
char *  src_out,
char *  dst_out,
int *  bw_hz_out 
)

Parse an ACCEPT frame; same layout as CALL.

◆ arq_protocol_parse_call()

int arq_protocol_parse_call ( const uint8_t *  buf,
size_t  buf_len,
uint8_t *  session_id_out,
char *  src_out,
char *  dst_out,
int *  bw_hz_out 
)

Parse a CALL frame; extract callsigns.

Parameters
bufInput frame buffer.
buf_lenSize of buf in bytes.
session_id_outReceives the session_id byte.
src_outBuffer for local (transmitting) callsign, CALLSIGN_MAX_SIZE bytes.
dst_outBuffer for remote callsign, CALLSIGN_MAX_SIZE bytes.
bw_hz_outReceives the requested bandwidth in Hz.
Returns
0 on success, -1 on parse error.

◆ arq_protocol_parse_cq()

int arq_protocol_parse_cq ( const uint8_t *  buf,
size_t  buf_len,
char *  src_out,
int *  bw_hz_out 
)

Parse a compact DATAC13 CQ frame.

◆ build_call_accept()

static int build_call_accept ( uint8_t *  buf,
size_t  buf_len,
bool  is_accept,
uint8_t  session_id,
const char *  src,
const char *  dst,
int  bw_hz 
)
static

◆ build_ctrl()

static int build_ctrl ( uint8_t *  buf,
size_t  buf_len,
uint8_t  subtype,
uint8_t  session_id,
uint8_t  tx_seq,
uint8_t  rx_ack_seq,
uint8_t  flags,
uint8_t  snr_raw,
uint8_t  ack_delay_raw,
const uint8_t *  payload,
size_t  payload_len 
)
static

◆ decode_callsign_only_payload()

static int decode_callsign_only_payload ( const uint8_t *  in,
size_t  in_len,
char *  src_out 
)
static

◆ decode_callsign_payload()

static int decode_callsign_payload ( const uint8_t *  in,
size_t  in_len,
char *  src_out,
char *  dst_out 
)
static

◆ encode_callsign_only_payload()

static int encode_callsign_only_payload ( const char *  src,
uint8_t *  out,
size_t  out_cap 
)
static

◆ encode_callsign_payload()

static int encode_callsign_payload ( const char *  src,
const char *  dst,
uint8_t *  out,
size_t  out_cap 
)
static

◆ init_model()

void init_model ( void  )
extern

◆ parse_call_accept()

static int parse_call_accept ( const uint8_t *  buf,
size_t  buf_len,
uint8_t *  session_id_out,
char *  src_out,
char *  dst_out,
int *  bw_hz_out 
)
static

Variable Documentation

◆ arq_accept_retry_slots

_Atomic int arq_accept_retry_slots = ARQ_ACCEPT_RETRY_SLOTS_DEFAULT

◆ arq_call_retry_slots

_Atomic int arq_call_retry_slots = ARQ_CALL_RETRY_SLOTS_DEFAULT

◆ arq_data_retry_slots

_Atomic int arq_data_retry_slots = ARQ_DATA_RETRY_SLOTS_DEFAULT

◆ arq_disconnect_retry_slots

_Atomic int arq_disconnect_retry_slots = ARQ_DISCONNECT_RETRY_SLOTS_DEFAULT

◆ arq_mode_table

const arq_mode_timing_t arq_mode_table[]
Initial value:
= {
{ FREEDV_MODE_DATAC13, 2.50f, 1.0f, 6.0f, 7.0f, 14 },
{ FREEDV_MODE_DATAC4, 5.80f, 1.0f, 12.0f, 13.0f, 54 },
{ FREEDV_MODE_DATAC3, 3.82f, 1.0f, 9.0f, 10.0f, 126 },
{ FREEDV_MODE_DATAC1, 4.81f, 1.0f, 11.0f, 12.0f, 510 },
}

◆ arq_mode_table_count

const int arq_mode_table_count
Initial value:
=
(int)(sizeof(arq_mode_table) / sizeof(arq_mode_table[0]))
const arq_mode_timing_t arq_mode_table[]
Definition arq_protocol.c:59