Files
ipsc2hbpc/ipsc2hbp.toml.sample
Cort BuffingtonandClaude Opus 5.5 ec8bbfaedc HBP->IPSC: accept 53-byte DMRD, carry RSSI, set the slot bit; drop old RSSI encoding
DMRD bytes 53-54 (BER, RSSI) are optional on input: HBlink3 passes a
53-byte DMRD through unchanged. Accept anything from 53 bytes and read
byte 54 only when present; output is still 55 bytes.

DMRD byte 54 of a voice header or terminator now goes into the RSSI
field (bytes 52-53) of the VOICE_HEAD / VOICE_TERM built from it, as
8.8 fixed-point -dBm. No reading (53 bytes, 0, or a synthesized
HEAD/TERM) sends 0 as before. The terminator reading is cleared at the
end of each call so it cannot reach a later synthesized TERM.

Byte 31 bit 7 of VOICE_HEAD / VOICE_TERM is the timeslot (0x40 / 0xC0
in repeater captures); it was hardcoded 0x80 (TS2). The RSSI status
bit (bit 6) is left 0.

The old firmware RSSI encoding (-56 dB offset) is dropped: no repeater
using it is known. [ipsc] rssi_encoding_new is no longer read; configs
that still carry it load unchanged.

Tests: 53/55-byte input, RSSI round trip through the IPSC->HBP decoder,
slot bit, terminator reading not carried into the next call, legacy
key fixture, and a late-entry case where only the LC-error bit can
reject a corrupt burst E LC. parity_ref_gv.txt byte 31 corrected to
TS1.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-10-21 07:41:11 -05:00

239 lines
11 KiB
Plaintext
Raw Permalink Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
# ipsc2hbp.toml — configuration for ipsc2hbpc
#
# This file is config-compatible with the original Python ipsc2hbp: an existing
# ipsc2hbp.toml works unchanged. Copy this file to ipsc2hbp.toml (or
# /etc/ipsc2hbp/ipsc2hbp.toml) and edit for your deployment. The live config
# is gitignored.
[global]
# Logging verbosity: "DEBUG" | "INFO" | "WARNING" | "ERROR"
# DEBUG is very noisy (every burst frame). Use INFO for normal operation.
log_level = "INFO"
[ipsc]
# IPSC connection mode: "MASTER" (default) or "PEER"
#
# MASTER: ipsc2hbp acts as the IPSC master node. Repeaters register with it.
# Use this when you control the IPSC master role (the typical deployment).
#
# PEER: ipsc2hbp registers with an existing IPSC master (e.g., a repeater
# or c-Bridge configured as master, or another MOTOTRBO system you do not
# control) and joins the full IPSC mesh — it learns the other peers from the
# master and talks to them directly, peer-to-peer, the way IPSC delivers
# voice. All traffic on the IPSC system is visible and forwarded to HBP.
# Peer mode also enables passive capture of SYSTEM_MAP packets (0x9C/0x9D),
# which are logged at INFO with full hex when observed — useful for protocol
# research while running CPS against the repeater master.
mode = "MASTER"
# Peer mode only: address of the IPSC master to connect to.
# In master mode these fields are ignored.
# master_ip = "192.168.1.100"
# master_port = 50000
# IP address to bind the local IPSC UDP socket.
# In master mode: the address repeaters connect to (must match codeplug).
# In peer mode: the local source address for our outbound connection.
# Use "0.0.0.0" to bind on all interfaces.
bind_ip = "0.0.0.0"
bind_port = 50000
# Radio ID this translator presents on the IPSC network.
# In master mode: the ID repeaters see as the master node.
# In peer mode: the ID we register with to the master.
# Must be unique on the IPSC system. This is NOT the repeater's own radio ID.
ipsc_master_id = 9999999
# Optional: restrict which repeater radio IDs may register.
# TOML array of integers. Omit or leave empty ([]) to accept any radio ID.
# IPSC supports 15 peers maximum including the master, so at most 14 may connect.
# allowed_peer_ids = [3120000, 3120001]
allowed_peer_ids = []
# Optional: restrict which source IP addresses may register.
# TOML array of strings. Omit or leave empty ([]) to accept any source IP.
# allowed_peer_ips = ["192.168.1.100", "192.168.1.101"]
allowed_peer_ips = []
# IPSC HMAC-SHA1 authentication.
# Must match the auth key programmed in the repeater codeplug.
auth_enabled = false
# Auth key: up to 40 hex characters (20 bytes).
# Shorter keys are left-zero-padded to 40 hex chars automatically.
# Leave empty ("") when auth_enabled = false.
auth_key = ""
# Watchdog timeout (seconds): how long without a keep-alive before the
# peer/master is declared lost. Set generously for variable firewall timers.
# Minimum: 5. Recommended: 60.
keepalive_watchdog = 60
# Keepalive send interval (seconds) — peer mode only.
# How often ipsc2hbp sends MASTER_ALIVE_REQ to the master.
# 5 seconds matches the Motorola default interval.
# In master mode this field is unused; repeaters drive their own keepalives.
# keepalive_interval = 5
# Missed keepalive limit — peer mode only.
# How many consecutive MASTER_ALIVE_REQs can go unanswered before ipsc2hbp
# declares the master lost and re-registers. At keepalive_interval=5 and
# keepalive_missed_max=3, failure is detected within ~15 seconds.
# keepalive_missed_max = 3
# ---------------------------------------------------------------------------
# DMRlink confbridge.py timeslot compatibility
#
# In an IPSC GROUP_VOICE packet, the active timeslot is encoded in two places:
# • call_info byte 17, bit 5 (used for VOICE_HEAD and VOICE_TERM)
# • burst_type byte 30, bit 7 (used for SLOT_VOICE bursts: 0x0A=TS1, 0x8A=TS2)
#
# Real Motorola hardware always writes both fields consistently. DMRlink's
# confbridge.py, when translating a call from TS1 to TS2, rewrites call_info
# (byte 17) correctly but does NOT rewrite burst_type (byte 30). This causes
# ipsc2hbp to route SLOT_VOICE bursts to the wrong timeslot, producing a phantom
# stream on the incorrect TS while the real call forwards only the voice header.
#
# When ts_prefer_call_info = false (default): ipsc2hbp uses burst_type bit 7 for
# SLOT_VOICE TS determination, which is the correct protocol-defined source. A
# WARNING is logged once per session per affected TS whenever the two fields
# disagree, making the confbridge problem immediately visible in the log.
#
# When ts_prefer_call_info = true: ipsc2hbp uses call_info bit 5 for ALL burst
# types, including SLOT_VOICE. This works around confbridge's incomplete rewrite
# without requiring a DMRlink update. Set this if your IPSC source passes through
# DMRlink confbridge for timeslot translation. Remove or set false once confbridge
# is updated to rewrite both fields.
# ---------------------------------------------------------------------------
ts_prefer_call_info = false
# ---------------------------------------------------------------------------
# IPSC capability advertisement
#
# WARNING: These fields control what ipsc2hbp tells IPSC peers about its
# capabilities during registration and keepalive. Advertising capabilities
# that are not actually supported can confuse repeaters or cause unexpected
# behaviour. The safe defaults have been verified against real hardware.
#
# use_safe_defaults = true → all settings below are ignored; ipsc2hbp
# uses proven working values identical to its original behaviour.
#
# use_safe_defaults = false → ipsc2hbp advertises exactly what you
# configure below. Only change this if you have a specific reason and
# a wire capture to verify the result.
# ---------------------------------------------------------------------------
[ipsc.capabilities]
use_safe_defaults = true
# Radio mode advertised to IPSC peers.
# "DIGITAL" — digital repeater (default; correct for a standard MOTOTRBO system)
# "ANALOG" — analog repeater
# "NO_RADIO" — no radio / software application (e.g. a console or programming tool)
# "MIXED" — site handles both analog and digital (rare)
# radio_mode = "DIGITAL"
# Whether each timeslot is advertised as IPSC-linked.
# Peers use this to decide whether to attempt calls on each slot.
# ts1_linked = true
# ts2_linked = true
# FLAGS byte 2 — application capability flags.
# csbk = false # CSBK (control signalling) support
# rpt_mon = false # Repeater call monitoring
# con_app = false # 3rd-party console application (Motorola CPS / programming tool)
# FLAGS byte 3 — XNL/XCMP and call flags (AUTH and MASTER are always set automatically).
# xnl_con = false # XNL/XCMP connected (Motorola proprietary control protocol)
# xnl_master = false # XNL master device
# xnl_slave = false # XNL slave device
# data = false # Data calls supported
# voice = true # Voice calls supported
# FLAGS byte 1 — service/capability flags.
# All default false — only set these if you have a specific reason and a wire capture
# to verify the effect. Leave false for a standard repeater or bridge application.
# mnis = false # MNIS (Mobile Network Interface Service) capable
# ip_site_freq = false # IP Site Single Frequency
# slot1_phone = false # TS1 phone patch capable
# slot2_phone = false # TS2 phone patch capable
# virtual_peer = false # Software/virtual peer — signals this is not a physical repeater.
# # May affect how programming software and console apps interact with us.
# cps_avail = false # CPS Available / FirmwareNet
# FLAGS byte 0 — wireline/MNIS data service flags.
# Only relevant for MNIS data service devices. Leave all false for a standard
# repeater or software application.
# slot1_wireline = false # TS1 wireline/MNIS capable
# slot2_wireline = false # TS2 wireline/MNIS capable
# wireline_svc = false # Wireline data service active
# IPSC version field (8 hex characters = 4 bytes).
# Encodes two protocol type+version pairs: bytes 0-1 = main (type+version),
# bytes 2-3 = backward-compatible (type+version).
# Types: 0x01=IPSC, 0x02=CapacityPlus, 0x03=Application, 0x04=LinkedCapacityPlus
# Default "04020401" = IPSC v2 main / IPSC v1 compat (from DMRlink).
# Only change this if you have specific evidence from a wire capture.
# ipsc_version = "04020401"
[hbp]
# Upstream HBP master to connect to (BrandMeister, DMR+, FreeDMR, HBlink4).
master_ip = "127.0.0.1"
master_port = 62031
# HBP repeater ID sent in all HBP packets. Required — must be non-zero.
# Typically the radio ID of the primary repeater, or a unique ID for this system.
hbp_repeater_id = 3120000
# Passphrase for the HBP master (must match the master's configuration).
passphrase = "passw0rd"
# HBP connection mode:
# "TRACKING": Connect HBP only while an IPSC peer is registered.
# Disconnect when the repeater goes away. Recommended.
# "PERSISTENT": Keep the HBP connection up regardless of repeater state.
# Useful to keep the system visible on network dashboards.
# Requires hbp_repeater_id to be non-zero — the HBP connection
# is established at startup, before any repeater registers.
hbp_mode = "TRACKING"
# HBP->IPSC jitter buffer depth, in 60 ms TDMA slots (default 2 = 120 ms).
# Inbound voice is clocked out to IPSC at this delay, anchored to the first voice
# burst so every burst gets the full lead, giving the repeater a continuous 60 ms
# grid. (The voice header is forwarded immediately, and the terminator is held
# until the buffered tail drains, so the call tail is not clipped.) Deeper =
# absorbs more inbound jitter at the cost of that much added call-setup latency:
# 1 -> 60 ms (clean low-latency LAN link)
# 2 -> 120 ms (default; absorbs the jitter seen on typical paths)
# 3-8 -> 180-480 ms (marginal / high-latency RF backhaul — trade delay for
# reliability). PTT audio tolerates this; c-Bridge adds more.
jitter_buffer_depth = 2
# ---------------------------------------------------------------------------
# Options string — sent as RPTO after RPTC if non-empty.
# Used to subscribe to specific TGIDs on HBlink4 and compatible servers.
# Format: "TS1=tgid,tgid,...;TS2=tgid,tgid,..."
# Use "*" for all TGIDs on a slot. Leave empty to skip the RPTO step.
# Examples:
# options = "TS1=91,310;TS2=*"
# options = ""
# ---------------------------------------------------------------------------
options = ""
# ---------------------------------------------------------------------------
# RPTC announcement fields — sent to the HBP master during handshake.
# BrandMeister validates field widths strictly; fill these accurately.
# ---------------------------------------------------------------------------
callsign = "W1ABC"
rx_freq = "444000000" # Hz, 9 ASCII digits
tx_freq = "449000000" # Hz, 9 ASCII digits
tx_power = "25" # Watts, up to 2 digits
colorcode = "1" # DMR colour code (1–15)
latitude = "38.8500" # decimal degrees, up to 8 characters
longitude = "-097.6114" # decimal degrees, up to 9 characters
height = "10" # antenna height above ground, metres, up to 3 digits
location = "Smalltown KS"
description = "IPSC-HBP Bridge"
url = ""
software_id = "ipsc2hbp"
package_id = "duplex"