Mercury Modem
Mercury ARQ/Broadcast modem
Loading...
Searching...
No Matches
Macros | Functions | Variables
arq_fsm.c File Reference
#include "arq_fsm.h"
#include "../modem/modem_mfsk.h"
#include "arq_protocol.h"
#include "arq_timing.h"
#include "arq.h"
#include <limits.h>
#include <stdlib.h>
#include <string.h>
#include <strings.h>
#include <stdint.h>
#include <stdio.h>
#include "../common/hermes_log.h"
#include "../common/virtual_clock.h"
#include "../modem/framer.h"
#include "../modem/freedv/freedv_api.h"
Include dependency graph for arq_fsm.c:

Macros

#define LOG_COMP   "arq-fsm"
 
#define INT_BUFFER_SIZE   4096
 
#define ARQ_CAR_PEER_LOST_MS   240000
 
#define ARQ_CAR_END_WAIT_MS   180000
 

Functions

const char * arq_conn_state_name (arq_conn_state_t s)
 Human-readable name for a connection state (for log output).
 
const char * arq_event_name (arq_event_id_t ev)
 Human-readable name for an event (for log output).
 
static uint16_t car_seed (const arq_session_t *sess, bool is_caller)
 
static void car_set_seed (arq_session_t *sess, uint16_t seed)
 
static void car_connect_callee (arq_session_t *sess, const arq_event_t *ev)
 
void arq_fsm_set_callbacks (const arq_fsm_callbacks_t *cbs)
 Register FSM action callbacks (call once before first dispatch).
 
void arq_fsm_set_timing (arq_timing_ctx_t *timing)
 Register timing context for recording (call once at init).
 
void arq_fsm_init (arq_session_t *sess)
 Initialise a session structure to DISCONNECTED state.
 
void arq_fsm_release (arq_session_t *sess)
 
int arq_fsm_timeout_ms (const arq_session_t *sess, uint64_t now)
 Return milliseconds until the next deadline, or INT_MAX if idle.
 
static void car_stop (arq_session_t *sess)
 
static bool fsm_connected_carousel (arq_session_t *sess, const arq_event_t *ev)
 
static void car_begin_disconnect (arq_session_t *sess, uint64_t now)
 
static void sess_enter (arq_session_t *sess, arq_conn_state_t new_state, uint64_t deadline_ms, arq_event_id_t deadline_event)
 
static void send_frame (int ptype, int mode, size_t len, const uint8_t *frame, int burst_remaining)
 
static uint64_t deadline_from_s (float seconds)
 
static uint64_t retry_deadline_from_s (const arq_session_t *sess, float seconds)
 
static int session_tx_backlog (const arq_session_t *sess)
 
static int session_tx_read (arq_session_t *sess, uint8_t *buf, size_t len)
 
int arq_call_carrier (const arq_session_t *sess)
 The carrier the next CALL goes out on: the control mode for the first ARQ_CALL_FAST_SLOTS, then MFSK and the control mode alternately.
 
static int accept_level (const arq_session_t *sess)
 
static void send_call_accept (arq_session_t *sess, bool is_accept)
 
static int session_ctl_mode (const arq_session_t *sess)
 
static void send_disconnect_frame (arq_session_t *sess)
 
static bool peer_is_transmitting (const arq_session_t *sess)
 
static void enter_idle_after_call (arq_session_t *sess)
 
static void notify_session_ended (arq_session_t *sess)
 
static void send_disconnect_reply (arq_session_t *sess)
 
bool arq_fsm_expect_pattern (const arq_session_t *sess, uint64_t now)
 Whether a pattern can arrive now (the modem's detector runs only then).
 
static void car_io_keydown (void *ctx, const car_frame_t *fr, int n)
 
static void car_io_bind_rx (void *ctx, int mode)
 
static void car_io_pattern (void *ctx, int kind)
 
static bool car_io_peer_keyed (void *ctx)
 
static size_t car_io_tx_read (void *ctx, uint8_t *buf, size_t max)
 
static size_t car_io_tx_pending (void *ctx)
 
static void car_io_deliver (void *ctx, const uint8_t *buf, size_t len)
 
static void car_io_tx_confirmed (void *ctx, size_t len)
 
static uint16_t session_nonce (void)
 
static void car_io_end (void *ctx)
 
static void car_io_trace (void *ctx, const char *line)
 
static int session_max_level (void)
 
static int session_start_level (float snr_db)
 
static void car_start (arq_session_t *sess, bool is_caller, uint64_t now)
 
static bool car_fail_closed (arq_session_t *sess, uint64_t now)
 
static bool car_disconnect_must_wait (arq_session_t *sess, const arq_event_t *ev, uint64_t now)
 
static bool car_drained (const arq_session_t *sess)
 
static void fsm_disconnected (arq_session_t *sess, const arq_event_t *ev)
 
static void fsm_listening (arq_session_t *sess, const arq_event_t *ev)
 
static void fsm_calling (arq_session_t *sess, const arq_event_t *ev)
 
static void fsm_accepting (arq_session_t *sess, const arq_event_t *ev)
 
static void fire_deferred_connect (arq_session_t *sess)
 
static bool disconnect_must_wait (arq_session_t *sess)
 
static void fsm_disconnecting (arq_session_t *sess, const arq_event_t *ev)
 
static void fsm_connected (arq_session_t *sess, const arq_event_t *ev)
 
static bool is_session_bound_rx_event (arq_event_id_t id)
 
void arq_fsm_dispatch (arq_session_t *sess, const arq_event_t *ev)
 Dispatch an event through both FSM levels.
 

Variables

static arq_fsm_callbacks_t g_cbs
 
static arq_timing_ctx_t * g_timing
 

Macro Definition Documentation

◆ ARQ_CAR_END_WAIT_MS

#define ARQ_CAR_END_WAIT_MS   180000

◆ ARQ_CAR_PEER_LOST_MS

#define ARQ_CAR_PEER_LOST_MS   240000

◆ INT_BUFFER_SIZE

#define INT_BUFFER_SIZE   4096

◆ LOG_COMP

#define LOG_COMP   "arq-fsm"

Function Documentation

◆ accept_level()

static int accept_level ( const arq_session_t *  sess)
static

◆ arq_call_carrier()

int arq_call_carrier ( const arq_session_t *  sess)

The carrier the next CALL goes out on: the control mode for the first ARQ_CALL_FAST_SLOTS, then MFSK and the control mode alternately.

◆ arq_conn_state_name()

const char * arq_conn_state_name ( arq_conn_state_t  s)

Human-readable name for a connection state (for log output).

◆ arq_event_name()

const char * arq_event_name ( arq_event_id_t  ev)

Human-readable name for an event (for log output).

◆ arq_fsm_dispatch()

void arq_fsm_dispatch ( arq_session_t *  sess,
const arq_event_t *  event 
)

Dispatch an event through both FSM levels.

Runs transition logic, calls action callbacks, and updates deadlines. Must be called from the single ARQ event-loop thread (no locking inside).

Parameters
sessActive session.
eventEvent to process.

◆ arq_fsm_expect_pattern()

bool arq_fsm_expect_pattern ( const arq_session_t *  sess,
uint64_t  now 
)

Whether a pattern can arrive now (the modem's detector runs only then).

◆ arq_fsm_init()

void arq_fsm_init ( arq_session_t *  sess)

Initialise a session structure to DISCONNECTED state.

Parameters
sessSession to initialise.

◆ arq_fsm_release()

void arq_fsm_release ( arq_session_t *  sess)

◆ arq_fsm_set_callbacks()

void arq_fsm_set_callbacks ( const arq_fsm_callbacks_t *  cbs)

Register FSM action callbacks (call once before first dispatch).

◆ arq_fsm_set_timing()

void arq_fsm_set_timing ( arq_timing_ctx_t *  timing)

Register timing context for recording (call once at init).

Parameters
timingPointer to the arq_timing_ctx_t to record into.

◆ arq_fsm_timeout_ms()

int arq_fsm_timeout_ms ( const arq_session_t *  sess,
uint64_t  now 
)

Return milliseconds until the next deadline, or INT_MAX if idle.

Used by the event loop's blocking wait to set a poll timeout.

Parameters
sessActive session.
nowCurrent monotonic time in milliseconds.
Returns
Milliseconds to wait (0 = fire immediately, INT_MAX = no deadline).

◆ car_begin_disconnect()

static void car_begin_disconnect ( arq_session_t *  sess,
uint64_t  now 
)
static

◆ car_connect_callee()

static void car_connect_callee ( arq_session_t *  sess,
const arq_event_t *  ev 
)
static

◆ car_disconnect_must_wait()

static bool car_disconnect_must_wait ( arq_session_t *  sess,
const arq_event_t *  ev,
uint64_t  now 
)
static

◆ car_drained()

static bool car_drained ( const arq_session_t *  sess)
static

◆ car_fail_closed()

static bool car_fail_closed ( arq_session_t *  sess,
uint64_t  now 
)
static

◆ car_io_bind_rx()

static void car_io_bind_rx ( void *  ctx,
int  mode 
)
static

◆ car_io_deliver()

static void car_io_deliver ( void *  ctx,
const uint8_t *  buf,
size_t  len 
)
static

◆ car_io_end()

static void car_io_end ( void *  ctx)
static

◆ car_io_keydown()

static void car_io_keydown ( void *  ctx,
const car_frame_t *  fr,
int  n 
)
static

◆ car_io_pattern()

static void car_io_pattern ( void *  ctx,
int  kind 
)
static

◆ car_io_peer_keyed()

static bool car_io_peer_keyed ( void *  ctx)
static

◆ car_io_trace()

static void car_io_trace ( void *  ctx,
const char *  line 
)
static

◆ car_io_tx_confirmed()

static void car_io_tx_confirmed ( void *  ctx,
size_t  len 
)
static

◆ car_io_tx_pending()

static size_t car_io_tx_pending ( void *  ctx)
static

◆ car_io_tx_read()

static size_t car_io_tx_read ( void *  ctx,
uint8_t *  buf,
size_t  max 
)
static

◆ car_seed()

static uint16_t car_seed ( const arq_session_t *  sess,
bool  is_caller 
)
static

◆ car_set_seed()

static void car_set_seed ( arq_session_t *  sess,
uint16_t  seed 
)
static

◆ car_start()

static void car_start ( arq_session_t *  sess,
bool  is_caller,
uint64_t  now 
)
static

◆ car_stop()

static void car_stop ( arq_session_t *  sess)
static

◆ deadline_from_s()

static uint64_t deadline_from_s ( float  seconds)
static

◆ disconnect_must_wait()

static bool disconnect_must_wait ( arq_session_t *  sess)
static

◆ enter_idle_after_call()

static void enter_idle_after_call ( arq_session_t *  sess)
static

◆ fire_deferred_connect()

static void fire_deferred_connect ( arq_session_t *  sess)
static

◆ fsm_accepting()

static void fsm_accepting ( arq_session_t *  sess,
const arq_event_t *  ev 
)
static

◆ fsm_calling()

static void fsm_calling ( arq_session_t *  sess,
const arq_event_t *  ev 
)
static

◆ fsm_connected()

static void fsm_connected ( arq_session_t *  sess,
const arq_event_t *  ev 
)
static

◆ fsm_connected_carousel()

static bool fsm_connected_carousel ( arq_session_t *  sess,
const arq_event_t *  ev 
)
static

◆ fsm_disconnected()

static void fsm_disconnected ( arq_session_t *  sess,
const arq_event_t *  ev 
)
static

◆ fsm_disconnecting()

static void fsm_disconnecting ( arq_session_t *  sess,
const arq_event_t *  ev 
)
static

◆ fsm_listening()

static void fsm_listening ( arq_session_t *  sess,
const arq_event_t *  ev 
)
static

◆ is_session_bound_rx_event()

static bool is_session_bound_rx_event ( arq_event_id_t  id)
static

◆ notify_session_ended()

static void notify_session_ended ( arq_session_t *  sess)
static

◆ peer_is_transmitting()

static bool peer_is_transmitting ( const arq_session_t *  sess)
static

◆ retry_deadline_from_s()

static uint64_t retry_deadline_from_s ( const arq_session_t *  sess,
float  seconds 
)
static

◆ send_call_accept()

static void send_call_accept ( arq_session_t *  sess,
bool  is_accept 
)
static

◆ send_disconnect_frame()

static void send_disconnect_frame ( arq_session_t *  sess)
static

◆ send_disconnect_reply()

static void send_disconnect_reply ( arq_session_t *  sess)
static

◆ send_frame()

static void send_frame ( int  ptype,
int  mode,
size_t  len,
const uint8_t *  frame,
int  burst_remaining 
)
static

◆ sess_enter()

static void sess_enter ( arq_session_t *  sess,
arq_conn_state_t  new_state,
uint64_t  deadline_ms,
arq_event_id_t  deadline_event 
)
static

◆ session_ctl_mode()

static int session_ctl_mode ( const arq_session_t *  sess)
static

◆ session_max_level()

static int session_max_level ( void  )
static

◆ session_nonce()

static uint16_t session_nonce ( void  )
static

◆ session_start_level()

static int session_start_level ( float  snr_db)
static

◆ session_tx_backlog()

static int session_tx_backlog ( const arq_session_t *  sess)
static

◆ session_tx_read()

static int session_tx_read ( arq_session_t *  sess,
uint8_t *  buf,
size_t  len 
)
static

Variable Documentation

◆ g_cbs

arq_fsm_callbacks_t g_cbs
static

◆ g_timing

arq_timing_ctx_t* g_timing
static