summaryrefslogtreecommitdiff
path: root/include/hybbx/tnc.h
diff options
context:
space:
mode:
authorinfo@mode42.com <info@mode42.com>2026-08-08 03:54:55 +0000
committerinfo@mode42.com <info@mode42.com>2026-08-08 03:54:55 +0000
commit20cb29c2f8c5c87bc590896854a20b1473ceb358 (patch)
tree2857f41513a56ad41af97b57362639298aa7f033 /include/hybbx/tnc.h
#2
Diffstat (limited to 'include/hybbx/tnc.h')
-rw-r--r--include/hybbx/tnc.h240
1 files changed, 240 insertions, 0 deletions
diff --git a/include/hybbx/tnc.h b/include/hybbx/tnc.h
new file mode 100644
index 0000000..9655aa8
--- /dev/null
+++ b/include/hybbx/tnc.h
@@ -0,0 +1,240 @@
+#ifndef HYBBX_TNC_H
+#define HYBBX_TNC_H
+
+/**
+ * Unified TNC / AX.25 link driver for HyBBX packet radio.
+ *
+ * Supported hardware profiles (see docs/TNCS.md):
+ * - Landolt TNC2C, classic TNC-2 / PK-TNC2 (TheFirmware)
+ * - AEA PK-232, MFJ-1278, Kantronics KPC
+ * - Generic TNC2-class controllers
+ *
+ * Not in packet_radio: BayCom/based SER12 / PC-COM TCM3105 — use MAX25
+ * bcpr (`max25e0`) then optional HyBBX baycom transport or [max25] attach.
+ * UN1TME = TNCs only.
+ *
+ * Host protocols: KISS, TNC2 host mode, 6PACK (DF6BU).
+ */
+
+#include "hybbx/ax25.h"
+#include "hybbx/packet_radio.h"
+#include "hybbx/types.h"
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+#define HYBBX_TNC2C_DEFAULT_HOST_BAUD HYBBX_PACKET_RADIO_DEFAULT_BAUD
+#define HYBBX_TNC2C_DEFAULT_RADIO_BAUD 1200u
+#define HYBBX_AFSK_RADIO_BAUD 1200u
+#define HYBBX_G3RUH_RADIO_BAUD 9600u
+#define HYBBX_TNC2C_CLOCK_4_9_MHZ 4.9f
+#define HYBBX_TNC2C_CLOCK_9_8_MHZ 9.8f
+#define HYBBX_TNC2C_CLOCK_10_MHZ 10.0f
+#define HYBBX_TNC2C_HOST_BAUD_MIN 300u
+#define HYBBX_TNC2C_HOST_BAUD_MAX 38400u
+#define HYBBX_TNC2C_DATA_BITS 7u
+
+typedef enum hybbx_tnc_serial_parity {
+ HYBBX_TNC_SERIAL_PARITY_UNSET = 0,
+ HYBBX_TNC_SERIAL_PARITY_NONE = 1,
+ HYBBX_TNC_SERIAL_PARITY_EVEN = 2,
+ HYBBX_TNC_SERIAL_PARITY_ODD = 3
+} hybbx_tnc_serial_parity_t;
+
+#define HYBBX_PACKET_RADIO_VIA_MAX 8
+
+typedef enum hybbx_tnc2c_modem {
+ HYBBX_TNC2C_MODEM_TCM3105 = 1,
+ HYBBX_TNC2C_MODEM_9600 = 2, /**< G3RUH-compatible 9600 baud FSK */
+ HYBBX_TNC2C_MODEM_19200 = 3
+} hybbx_tnc2c_modem_t;
+
+/**
+ * Over-the-air modulation standard.
+ * AFSK (Bell 202 / TCM3105 @ 1200) is the classic CB packet default.
+ * G3RUH FSK @ 9600 baud for higher throughput (requires compatible modem/TNC).
+ */
+typedef enum hybbx_packet_radio_modulation {
+ HYBBX_PACKET_RADIO_MOD_UNSET = 0,
+ HYBBX_PACKET_RADIO_MOD_AFSK = 1,
+ HYBBX_PACKET_RADIO_MOD_G3RUH_FSK = 2
+} hybbx_packet_radio_modulation_t;
+
+#define HYBBX_PACKET_RADIO_MOD_DEFAULT HYBBX_PACKET_RADIO_MOD_AFSK
+
+typedef enum hybbx_packet_radio_protocol {
+ HYBBX_PACKET_RADIO_PROTO_KISS = 1,
+ HYBBX_PACKET_RADIO_PROTO_HOSTMODE = 2,
+ HYBBX_PACKET_RADIO_PROTO_SIXPACK = 3
+} hybbx_packet_radio_protocol_t;
+
+typedef enum hybbx_packet_radio_tnc {
+ HYBBX_PACKET_RADIO_TNC_TNC2C = 1,
+ HYBBX_PACKET_RADIO_TNC_BAYCOM = 2,
+ HYBBX_PACKET_RADIO_TNC_PCCOM = 3,
+ HYBBX_PACKET_RADIO_TNC_GENERIC = 4,
+ HYBBX_PACKET_RADIO_TNC_TNC2 = 5,
+ HYBBX_PACKET_RADIO_TNC_PK232 = 6,
+ HYBBX_PACKET_RADIO_TNC_MFJ1278 = 7,
+ HYBBX_PACKET_RADIO_TNC_KANTRONICS = 8
+} hybbx_packet_radio_tnc_t;
+
+/** How HyBBX enters KISS mode on the host serial link. */
+typedef enum hybbx_kiss_entry {
+ HYBBX_KISS_ENTRY_UNSET = 0,
+ HYBBX_KISS_ENTRY_NONE = 1,
+ HYBBX_KISS_ENTRY_KISS_ON = 2,
+ HYBBX_KISS_ENTRY_ESC_AT_K = 3,
+ HYBBX_KISS_ENTRY_AUTO = 4
+} hybbx_kiss_entry_t;
+
+/** How HyBBX leaves KISS mode on shutdown. */
+typedef enum hybbx_kiss_exit {
+ HYBBX_KISS_EXIT_UNSET = 0,
+ HYBBX_KISS_EXIT_NONE = 1,
+ HYBBX_KISS_EXIT_KISS_OFF = 2,
+ HYBBX_KISS_EXIT_KISS_FRAME = 3,
+ HYBBX_KISS_EXIT_AUTO = 4
+} hybbx_kiss_exit_t;
+
+/**
+ * RF service band — drives safe duplex defaults.
+ * CB is half-duplex only (shared channel). Amateur may use full-duplex.
+ */
+typedef enum hybbx_packet_radio_band {
+ HYBBX_PACKET_RADIO_BAND_UNSET = 0,
+ HYBBX_PACKET_RADIO_BAND_CB = 1,
+ HYBBX_PACKET_RADIO_BAND_AMATEUR = 2
+} hybbx_packet_radio_band_t;
+
+/**
+ * Radio link duplex mode (distinct from host serial full-duplex).
+ * half = one direction at a time on the RF channel (CB / classic packet).
+ * full = TNC may key TX while receiving (amateur split / full-dup setups).
+ */
+typedef enum hybbx_packet_radio_duplex {
+ HYBBX_PACKET_RADIO_DUPLEX_UNSET = 0,
+ HYBBX_PACKET_RADIO_DUPLEX_HALF = 1,
+ HYBBX_PACKET_RADIO_DUPLEX_FULL = 2
+} hybbx_packet_radio_duplex_t;
+
+#define HYBBX_PACKET_RADIO_DUPLEX_DEFAULT HYBBX_PACKET_RADIO_DUPLEX_HALF
+
+typedef struct hybbx_tnc_params {
+ float clock_mhz;
+ hybbx_tnc2c_modem_t modem;
+ hybbx_packet_radio_modulation_t modulation;
+ unsigned int radio_baud;
+ unsigned int kiss_port;
+ unsigned int txdelay;
+ unsigned int persist;
+ unsigned int slot;
+ unsigned int txtail;
+ hybbx_packet_radio_band_t band;
+ hybbx_packet_radio_duplex_t duplex;
+ int fullduplex;
+ hybbx_kiss_entry_t kiss_entry;
+ hybbx_kiss_exit_t kiss_exit;
+ int host_connect_on_start;
+ unsigned int data_bits;
+ hybbx_tnc_serial_parity_t serial_parity;
+ unsigned int stop_bits;
+ int assert_modem_lines;
+} hybbx_tnc_params_t;
+
+typedef struct hybbx_packet_radio_config {
+ hybbx_packet_radio_device_type_t device_type;
+ char *device;
+ unsigned int baud;
+ hybbx_packet_radio_tnc_t tnc;
+ hybbx_packet_radio_protocol_t protocol;
+ hybbx_tnc_params_t params;
+ char *mycall;
+ char *dest_call;
+ char *via[HYBBX_PACKET_RADIO_VIA_MAX];
+ unsigned via_count;
+ char *circuit_host;
+ unsigned circuit_port;
+ char *link_id;
+ char *link_password;
+ char *link_role;
+ char *frequency_mhz;
+} hybbx_packet_radio_config_t;
+
+typedef struct hybbx_tnc hybbx_tnc_t;
+
+typedef void (*hybbx_tnc_ui_cb)(const uint8_t *payload, size_t len,
+ const hybbx_ax25_path_t *path,
+ void *userdata);
+
+/** Raw AX.25 frame from KISS/6PACK (before UI parsing). */
+typedef void (*hybbx_tnc_frame_cb)(const uint8_t *frame, size_t len,
+ void *userdata);
+
+hybbx_result_t hybbx_tnc_open(hybbx_tnc_t **out,
+ const hybbx_packet_radio_config_t *config,
+ hybbx_tnc_frame_cb frame_cb,
+ hybbx_tnc_ui_cb ui_cb,
+ void *rx_userdata);
+
+void hybbx_tnc_close(hybbx_tnc_t *tnc);
+
+hybbx_result_t hybbx_tnc_poll(hybbx_tnc_t *tnc);
+
+/** POSIX serial fd for poll/select; returns -1 when unavailable. */
+int hybbx_tnc_serial_fd(const hybbx_tnc_t *tnc);
+
+/** Send a raw AX.25 frame (already built) to the TNC. */
+hybbx_result_t hybbx_tnc_send_frame(hybbx_tnc_t *tnc,
+ const uint8_t *frame, size_t len);
+
+/** Build and send an AX.25 UI frame from text payload. */
+hybbx_result_t hybbx_tnc_send_ui(hybbx_tnc_t *tnc,
+ const uint8_t *payload, size_t len);
+
+/** Send bytes during host-mode connected converse. */
+hybbx_result_t hybbx_tnc_send_converse(hybbx_tnc_t *tnc,
+ const char *data, size_t len);
+
+int hybbx_tnc_host_connected(const hybbx_tnc_t *tnc);
+
+hybbx_packet_radio_duplex_t hybbx_tnc_duplex(const hybbx_tnc_t *tnc);
+hybbx_packet_radio_band_t hybbx_tnc_band(const hybbx_tnc_t *tnc);
+int hybbx_tnc_duplex_is_full(const hybbx_tnc_t *tnc);
+
+const char *hybbx_packet_radio_duplex_name(hybbx_packet_radio_duplex_t duplex);
+const char *hybbx_packet_radio_band_name(hybbx_packet_radio_band_t band);
+
+const char *hybbx_packet_radio_modulation_name(
+ hybbx_packet_radio_modulation_t modulation);
+
+int hybbx_packet_radio_modulation_is_g3ruh(
+ hybbx_packet_radio_modulation_t modulation);
+
+/** Apply g3ruh_fsk / modulation keys to modem, radio_baud, and timing. */
+hybbx_result_t hybbx_tnc_finalize_modulation(hybbx_packet_radio_config_t *cfg);
+
+/** Apply band/duplex rules and sync @p fullduplex for the TNC firmware. */
+hybbx_result_t hybbx_tnc_finalize_radio_duplex(hybbx_packet_radio_config_t *cfg);
+
+/** Apply profile-specific defaults (TNC2C, generic, …). */
+hybbx_result_t hybbx_tnc_profile_apply_defaults(hybbx_packet_radio_config_t *cfg);
+
+/** Apply host serial line defaults (TNC2C: 7E1 + RTS/DTR). */
+hybbx_result_t hybbx_tnc_finalize_serial_line(hybbx_packet_radio_config_t *cfg);
+
+/** Apply kiss_entry / kiss_exit defaults from TNC profile when unset. */
+hybbx_result_t hybbx_tnc_finalize_kiss_entry(hybbx_packet_radio_config_t *cfg);
+
+/** Apply CSMA defaults (Persist/SlotTime) from band when unset in INI. */
+hybbx_result_t hybbx_tnc_finalize_csma(hybbx_packet_radio_config_t *cfg);
+
+const char *hybbx_packet_radio_tnc_name(hybbx_packet_radio_tnc_t tnc);
+const char *hybbx_kiss_entry_name(hybbx_kiss_entry_t entry);
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif /* HYBBX_TNC_H */
git clone -b <branch> https://cgit.mode42.com/<repo>.git
git clone -b <branch> git://cgit.mode42.com/<repo>.git

info@mode42.com