|
HERMES Modem
Hermes ARQ/Broadcast modem
|
#include <stdbool.h>#include <stddef.h>#include <stdint.h>

Go to the source code of this file.
Data Structures | |
| struct | arq_frame_hdr_t |
| struct | arq_mode_timing_t |
Macros | |
| #define | ARQ_PROTO_VERSION 3 /* v3: 8-byte header, no proto_ver field on wire */ |
| #define | ARQ_HDR_SUBTYPE_IDX 1 |
| #define | ARQ_HDR_FLAGS_IDX 2 |
| #define | ARQ_HDR_SESSION_IDX 3 |
| #define | ARQ_HDR_SEQ_IDX 4 |
| #define | ARQ_HDR_ACK_IDX 5 |
| #define | ARQ_HDR_SNR_IDX 6 |
| #define | ARQ_HDR_DELAY_IDX 7 |
| #define | ARQ_FRAME_HDR_SIZE 8 /* bytes 0-7 inclusive */ |
| #define | ARQ_CONNECT_SESSION_IDX 1 |
| #define | ARQ_CONNECT_PAYLOAD_IDX 2 |
| #define | ARQ_CONNECT_SESSION_MASK 0x7F |
| #define | ARQ_CONNECT_ACCEPT_FLAG 0x80 |
| #define | ARQ_CONTROL_FRAME_SIZE 14 |
| #define | ARQ_CONNECT_META_SIZE 2 /* framer byte + connect_meta byte */ |
| #define | ARQ_CONNECT_MAX_ENCODED (ARQ_CONTROL_FRAME_SIZE - ARQ_CONNECT_META_SIZE) |
| #define | ARQ_FLAG_TURN_REQ 0x80 /* bit 7: sender requests role turn */ |
| #define | ARQ_FLAG_HAS_DATA 0x40 /* bit 6: sender has data queued (IRS→ISS) */ |
| #define | ARQ_FLAG_LEN_HI |
| #define | ARQ_CHANNEL_GUARD_MS |
| #define | ARQ_ISS_POST_ACK_GUARD_MS |
| #define | ARQ_TURN_WAIT_AFTER_ACK_MS |
| #define | ARQ_ACCEPT_RX_WINDOW_MS |
| #define | ARQ_ACK_GUARD_S 1 /* extra slack added to retry interval */ |
| #define | ARQ_CALL_RETRY_SLOTS 4 /* CALL retries before giving up */ |
| #define | ARQ_ACCEPT_RETRY_SLOTS 4 /* ACCEPT retries before returning */ |
| #define | ARQ_DATA_RETRY_SLOTS 10 /* DATA retries before disconnect */ |
| #define | ARQ_DISCONNECT_RETRY_SLOTS 2 /* DISCONNECT frame retries */ |
| #define | ARQ_CONNECT_GRACE_SLOTS 2 /* extra wait slots for ACCEPT */ |
| #define | ARQ_CONNECT_BUSY_EXT_S 2 /* busy-extension guard after CALL */ |
| #define | ARQ_KEEPALIVE_INTERVAL_S 20 /* keepalive TX interval */ |
| #define | ARQ_KEEPALIVE_MISS_LIMIT 5 /* missed keepalives before disconnect */ |
| #define | ARQ_TURN_REQ_RETRIES 2 |
| #define | ARQ_MODE_REQ_RETRIES 2 |
| #define | ARQ_MODE_SWITCH_HYST_COUNT 1 /* SNR provides stability gate; 1 = immediate */ |
| #define | ARQ_STARTUP_MAX_S 8 /* DATAC13-only startup window */ |
| #define | ARQ_STARTUP_ACKS_REQUIRED 1 |
| #define | ARQ_PEER_PAYLOAD_HOLD_S 15 /* hold peer payload mode after activity */ |
| #define | ARQ_SNR_HYST_DB 1.0f |
| #define | ARQ_SNR_MIN_DATAC4_DB -4.0f /* target MPP SNR (codec2 README) */ |
| #define | ARQ_SNR_MIN_DATAC3_DB -1.0f |
| #define | ARQ_SNR_MIN_DATAC1_DB 3.0f |
| #define | ARQ_BACKLOG_MIN_DATAC3 56 |
| #define | ARQ_BACKLOG_MIN_DATAC1 126 |
| #define | ARQ_BACKLOG_MIN_BIDIR_UPGRADE 48 /* > DATAC4 payload capacity */ |
| #define | ARQ_LADDER_LEVELS 3 /* 0=DATAC4, 1=DATAC3, 2=DATAC1 */ |
| #define | ARQ_LADDER_UP_SUCCESSES 4 /* clean ACKs required to step up */ |
| #define | ARQ_RETRY_DOWNGRADE_THRESHOLD 2 /* consecutive retries to force downgrade */ |
| #define | ARQ_MODE_HOLD_AFTER_DOWNGRADE_S 15 /* hold lower mode after forced downgrade */ |
| #define | ARQ_DATA_LEN_FULL 0 |
Enumerations | |
| enum | arq_subtype_t { ARQ_SUBTYPE_CALL = 1 , ARQ_SUBTYPE_ACCEPT = 2 , ARQ_SUBTYPE_ACK = 3 , ARQ_SUBTYPE_DISCONNECT = 4 , ARQ_SUBTYPE_DATA = 5 , ARQ_SUBTYPE_KEEPALIVE = 6 , ARQ_SUBTYPE_KEEPALIVE_ACK = 7 , ARQ_SUBTYPE_MODE_REQ = 8 , ARQ_SUBTYPE_MODE_ACK = 9 , ARQ_SUBTYPE_TURN_REQ = 10 , ARQ_SUBTYPE_TURN_ACK = 11 } |
Functions | |
| 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_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. | |
| const arq_mode_timing_t * | arq_protocol_mode_timing (int freedv_mode) |
| Look up mode timing entry for a FreeDV mode. | |
| 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. | |
| int | arq_protocol_build_call (uint8_t *buf, size_t buf_len, uint8_t session_id, const char *src, const char *dst) |
| 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) |
| Build an ACCEPT frame. | |
| int | arq_protocol_parse_call (const uint8_t *buf, size_t buf_len, uint8_t *session_id_out, char *src_out, char *dst_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) |
| Parse an ACCEPT frame; same layout as CALL. | |
Variables | |
| const arq_mode_timing_t | arq_mode_table [] |
| const int | arq_mode_table_count |
| #define ARQ_ACCEPT_RETRY_SLOTS 4 /* ACCEPT retries before returning */ |
| #define ARQ_ACCEPT_RX_WINDOW_MS |
| #define ARQ_ACK_GUARD_S 1 /* extra slack added to retry interval */ |
| #define ARQ_BACKLOG_MIN_BIDIR_UPGRADE 48 /* > DATAC4 payload capacity */ |
| #define ARQ_BACKLOG_MIN_DATAC1 126 |
| #define ARQ_BACKLOG_MIN_DATAC3 56 |
| #define ARQ_CALL_RETRY_SLOTS 4 /* CALL retries before giving up */ |
| #define ARQ_CHANNEL_GUARD_MS |
| #define ARQ_CONNECT_ACCEPT_FLAG 0x80 |
| #define ARQ_CONNECT_BUSY_EXT_S 2 /* busy-extension guard after CALL */ |
| #define ARQ_CONNECT_GRACE_SLOTS 2 /* extra wait slots for ACCEPT */ |
| #define ARQ_CONNECT_MAX_ENCODED (ARQ_CONTROL_FRAME_SIZE - ARQ_CONNECT_META_SIZE) |
| #define ARQ_CONNECT_META_SIZE 2 /* framer byte + connect_meta byte */ |
| #define ARQ_CONNECT_PAYLOAD_IDX 2 |
| #define ARQ_CONNECT_SESSION_IDX 1 |
| #define ARQ_CONNECT_SESSION_MASK 0x7F |
| #define ARQ_CONTROL_FRAME_SIZE 14 |
| #define ARQ_DATA_LEN_FULL 0 |
| #define ARQ_DATA_RETRY_SLOTS 10 /* DATA retries before disconnect */ |
| #define ARQ_DISCONNECT_RETRY_SLOTS 2 /* DISCONNECT frame retries */ |
| #define ARQ_FLAG_HAS_DATA 0x40 /* bit 6: sender has data queued (IRS→ISS) */ |
| #define ARQ_FLAG_LEN_HI |
| #define ARQ_FLAG_TURN_REQ 0x80 /* bit 7: sender requests role turn */ |
| #define ARQ_FRAME_HDR_SIZE 8 /* bytes 0-7 inclusive */ |
| #define ARQ_HDR_ACK_IDX 5 |
| #define ARQ_HDR_DELAY_IDX 7 |
| #define ARQ_HDR_FLAGS_IDX 2 |
| #define ARQ_HDR_SEQ_IDX 4 |
| #define ARQ_HDR_SESSION_IDX 3 |
| #define ARQ_HDR_SNR_IDX 6 |
| #define ARQ_HDR_SUBTYPE_IDX 1 |
| #define ARQ_ISS_POST_ACK_GUARD_MS |
| #define ARQ_KEEPALIVE_INTERVAL_S 20 /* keepalive TX interval */ |
| #define ARQ_KEEPALIVE_MISS_LIMIT 5 /* missed keepalives before disconnect */ |
| #define ARQ_LADDER_LEVELS 3 /* 0=DATAC4, 1=DATAC3, 2=DATAC1 */ |
| #define ARQ_LADDER_UP_SUCCESSES 4 /* clean ACKs required to step up */ |
| #define ARQ_MODE_HOLD_AFTER_DOWNGRADE_S 15 /* hold lower mode after forced downgrade */ |
| #define ARQ_MODE_REQ_RETRIES 2 |
| #define ARQ_MODE_SWITCH_HYST_COUNT 1 /* SNR provides stability gate; 1 = immediate */ |
| #define ARQ_PEER_PAYLOAD_HOLD_S 15 /* hold peer payload mode after activity */ |
| #define ARQ_PROTO_VERSION 3 /* v3: 8-byte header, no proto_ver field on wire */ |
| #define ARQ_RETRY_DOWNGRADE_THRESHOLD 2 /* consecutive retries to force downgrade */ |
| #define ARQ_SNR_HYST_DB 1.0f |
| #define ARQ_SNR_MIN_DATAC1_DB 3.0f |
| #define ARQ_SNR_MIN_DATAC3_DB -1.0f |
| #define ARQ_SNR_MIN_DATAC4_DB -4.0f /* target MPP SNR (codec2 README) */ |
| #define ARQ_STARTUP_ACKS_REQUIRED 1 |
| #define ARQ_STARTUP_MAX_S 8 /* DATAC13-only startup window */ |
| #define ARQ_TURN_REQ_RETRIES 2 |
| #define ARQ_TURN_WAIT_AFTER_ACK_MS |
| enum arq_subtype_t |
| int arq_protocol_build_accept | ( | uint8_t * | buf, |
| size_t | buf_len, | ||
| uint8_t | session_id, | ||
| const char * | src, | ||
| const char * | dst | ||
| ) |
Build an ACCEPT frame.
| buf | Output buffer (caller-provided). |
| buf_len | Size of buf in bytes. |
| session_id | ARQ session identifier. |
| src | Local callsign. |
| dst | Remote callsign. |
| 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.
| int arq_protocol_build_call | ( | uint8_t * | buf, |
| size_t | buf_len, | ||
| uint8_t | session_id, | ||
| const char * | src, | ||
| const char * | dst | ||
| ) |
Build a CALL frame.
| buf | Output buffer (caller-provided). |
| buf_len | Size of buf in bytes. |
| session_id | ARQ session identifier. |
| src | Local callsign. |
| dst | Remote callsign. |
| 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.
| buf | Output buffer (caller-provided). |
| buf_len | Size of buf in bytes. |
| session_id | ARQ session identifier. |
| tx_seq | TX sequence number. |
| rx_ack_seq | Last seq received from peer (piggybacked ACK). |
| flags | ARQ_FLAG_TURN_REQ | ARQ_FLAG_HAS_DATA (bitmask). |
| snr_raw | Local SNR encoded for wire. |
| payload_valid | Number of valid bytes in the payload slot. |
| payload | Payload bytes (must be <= buf_len - ARQ_FRAME_HDR_SIZE). |
| payload_len | Number of payload bytes. |
| 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_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_mode_req | ( | uint8_t * | buf, |
| size_t | buf_len, | ||
| uint8_t | session_id, | ||
| uint8_t | snr_raw, | ||
| int | freedv_mode | ||
| ) |
MODE_REQ frame.
| buf | Output buffer (caller-provided). |
| buf_len | Size of buf in bytes. |
| session_id | ARQ session identifier. |
| snr_raw | Local SNR encoded for wire. |
| freedv_mode | Requested payload FreeDV mode (FREEDV_MODE_DATAC*). |
| 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_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.
| buf | Output buffer (caller-provided). |
| buf_len | Size of buf in bytes. |
| session_id | ARQ session identifier. |
| rx_ack_seq | Last seq received from current ISS (so ISS can flush pending retries). |
| snr_raw | Local SNR encoded for wire. |
| uint32_t arq_protocol_decode_ack_delay | ( | uint8_t | raw | ) |
Decode the 8-bit wire ack_delay to milliseconds.
| 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.
| 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).
| 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.
| uint8_t arq_protocol_encode_snr | ( | float | snr_db | ) |
Encode a floating-point SNR (dB) into the snr_raw wire byte.
| const arq_mode_timing_t * arq_protocol_mode_timing | ( | int | freedv_mode | ) |
Look up mode timing entry for a FreeDV mode.
| int arq_protocol_parse_accept | ( | const uint8_t * | buf, |
| size_t | buf_len, | ||
| uint8_t * | session_id_out, | ||
| char * | src_out, | ||
| char * | dst_out | ||
| ) |
Parse an ACCEPT frame; same layout as 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 | ||
| ) |
Parse a CALL frame; extract callsigns.
| buf | Input frame buffer. |
| buf_len | Size of buf in bytes. |
| session_id_out | Receives the session_id byte. |
| src_out | Buffer for local (transmitting) callsign, CALLSIGN_MAX_SIZE bytes. |
| dst_out | Buffer for remote callsign, CALLSIGN_MAX_SIZE bytes. |
|
extern |
|
extern |