Skip to content

Texas QSO Party Integration - #47

Open
kt3xradio wants to merge 14 commits into
WSJTX:masterfrom
kt3xradio:master
Open

Texas QSO Party Integration#47
kt3xradio wants to merge 14 commits into
WSJTX:masterfrom
kt3xradio:master

Conversation

@kt3xradio

Copy link
Copy Markdown

Texas QSO Party (TxQP) Contest Mode Implementation
Overview
This branch adds full support for the Texas QSO Party contest in FT8/FT4 modes, including exchange validation, auto-sequencing, and proper logging for popular contest loggers (N1MM, N3FJP).

Core Feature Implementation

  1. Protocol Layer (77-bit Message Format)

File: lib/77bit/packjt77.f90
Changes:
Added pack77_txqp() and pack77_txqpvar() subroutines (i3=3, n3=5)
Implemented 13-bit exchange encoding: 254 Texas counties (0-253), 50 US states (254-303), 13 Canadian provinces (304-316), DX (317)
Fixed validation regex to accept both-bracketed compound callsigns in exchanges
Added unpacking logic in unpack77() and unpack77var()
Arrays: txqp_counties(254), txqp_states(50), txqp_provinces(13)

  1. Configuration & UI

Files: Configuration.hpp, Configuration.cpp, Configuration.ui
Changes:
Added TXQP to SpecialOperatingActivity enum (index 10)
New UI controls: rbTxQP radio button, labTxQP label, TXQP_Exchange QLineEdit
Validation regex accepts: 224 TX counties + 50 states + 13 provinces + "DX"
Auto-uppercase input, saved to persistent settings

  1. Message Generation

File: widgets/mainwindow.cpp (genStdMsgs)
Changes:
TxQP exchange format: "+00 " + m_config.TXQP_Exchange()
Compound-callsign Tx4/Tx5 generation for both-compound scenarios
Bug Fixes (Compound Callsigns)

  1. Auto-Sequence & Logging

File: widgets/mainwindow.cpp
Issues Fixed:
a) TxQP exchanges (+00/R+00) now bypass early-return in processMessage()
b) TxQP messages added to auto_sequence() standard-message allowlist
c) CQ auto-reply enabled for TxQP regardless of "CQ: None" setting
d) Roger-exchange (R+00) correctly triggers ROGERS state
e) Compound-callsign CQ auto-respond: 8 fixes for bracketed detection
f) Both-compound Tx4/Tx5 generation ( call2 RR73/73)

  1. Protocol Fix (Compound-vs-Compound Exchanges)

File: lib/77bit/packjt77.f90
Issue: When both callsigns were compound, TxQP exchanges displayed as +00 DX but the both-bracketed guard rejected them on re-packing → is_standard_ = FALSE → auto-sequence/logging broke
Fix: Removed both-bracketed guard in pack77_txqp (line ~1456) and pack77_txqpvar (line ~1550). Exchange-token validation still prevents false positives.

  1. CQ Generation (Compound Calls)

File: widgets/mainwindow.cpp (genCQMsg)
Issue: "CQ with Frequency" for compound calls produced invalid CQ 025 → encoder crash
Fix: Compound calls always generate plain CQ (Type 4 protocol constraint)
Logging & ADIF Export

  1. Contest Logging

Files: logbook/logbook.cpp, widgets/logqso.cpp
Changes:
TxQP QSOs auto-log (no user prompt)
ADIF export includes contest_id:TEXAS-QSO-PARTY
Exchange written to 4 tags for cross-logger compatibility:
<app_n1mm_exchange1> → N1MM "Exch" column
/ → N1MM also accepts
<srx_string> / <stx_string> → N3FJP / ADIF-compliant loggers
→ general logging/awards

  1. Cabrillo Export

File: widgets/ExportCabrillo.cpp
Changes: Auto-populates CONTEST: header with "TEXAS-QSO-PARTY"

Validation
Windows package is fully operable. Confirmed integration with N1MM and export to correct fields.

bbayani1 and others added 14 commits July 13, 2026 20:10
Implements a new Special Operating Activity for the Texas QSO Party (TxQP)
across the message codec, configuration UI, message generation, logging,
and Cabrillo export.

- lib/77bit/packjt77.f90: new pack77_txqp / unpack (i3=3, n3=5) message
  type carrying two callsigns, an implied "+00" report, an optional Roger
  flag, and a 13-bit exchange index covering Texas counties, US states,
  Canadian provinces, and "DX"; adds county/state/province lookup tables.
- Configuration.hpp/.cpp/.ui: adds the TXQP enum value, the "Texas QSO
  Party" radio button (rbTxQP) and exchange field (TXQP_Exchange) with a
  validator, persistence, slots, and visibility handling.
- widgets/mainwindow.cpp: CQ TQP generation, TxQP standard-message
  exchange ("+00 <location>"), received-exchange parsing, QSO logging,
  and the on-air status label.
- logbook/logbook.cpp: ADIF contest_id TEXAS-QSO-PARTY and exchange fields.
- widgets/ExportCabrillo.cpp: default CONTEST header to TEXAS-QSO-PARTY.
- logbook.cpp: write <stx_string> for the TxQP sent exchange (county/
  state/province/DX). Previously only numeric serials were logged, so the
  sent exchange was dropped from the ADIF record.
- mainwindow.cpp: populate m_xSent from the configured TxQP exchange at
  log time so the sent exchange reaches the logger.
- packjt77.f90: add pack77_txqpvar and register it in the pack77var
  dispatcher so TxQP messages with compound (/prefix or /suffix)
  callsigns pack via the hashed-call path and round-trip correctly.
The original implementation had only 224 counties + 30 blank placeholders.
This commit replaces the county table with the complete, official Texas QSO
Party county list (all 254 counties).

Changes:
- lib/77bit/packjt77.f90: Updated txqp_tables() DATA statement with all
  254 official county abbreviations from the TxQP website
- Configuration.cpp: Updated TXQP_exchange_re validator regex to match
  all 254 official counties + 50 US states + 13 Canadian provinces + DX

Corrected abbreviations (examples):
- ARM → ARMS (Armstrong), AUS → AUST (Austin), BEXR → BEXA (Bexar)
- DALL → DALS (Dallas), and 100+ other corrections/additions

The full official county list is now encoded and validated correctly.
- pack77_txqpvar: accept bracketed <...> hashed compound calls as-is instead
  of rejecting them via chkcall, so prefix (9A/WT3STT) and suffix (KT3STT/VP9)
  callsigns round-trip through pack28var's 22-bit hash. Fixes exchange
  failing to send/receive with compound callsigns.
- genCQMsg: for compound/nonstandard callsigns, fall back to a plain
  'CQ <call>' when the frequency-prefixed CQ is enabled, since Type 4
  messages cannot carry a frequency/grid/contest word and would otherwise
  fail to encode.
The previous compound-call fix was applied to pack77_txqpvar, but the actual
FT8/FT4 transmit path (genft8/genft4 -> pack77) uses the non-var pack77_txqp,
which still ran chkcall() on the bracketed <call> token the app builds for a
compound MYCALL (e.g. 'K5ABC <9A/WT3STT> +00 HARR'). chkcall rejects the
brackets, so the message fell through to free text (i3=0) and the exchange was
sent/received as a plain text string.

Apply the same bracket-handling to pack77_txqp: a word wrapped in <...> is
accepted as-is and hashed by pack28 (22-bit), so prefix (9A/WT3STT) and suffix
(KT3STT/VP9) compound calls now encode as TxQP (i3=3 n3=5) and round-trip.
Verified full QSO flow: receiver learns the hash from the Type 4 Tx1 and then
resolves <9A/WT3STT> to the full call in the exchange. Standard calls and
non-TxQP messages are unaffected.
The TxQP exchange frame (i3=3, n3=5) packs two callsigns plus a
county/state/province/DX location with an implied +00 report. When BOTH
callsigns are compound/nonstandard they are displayed hashed and bracketed
(e.g. '<KT3STT/VP9> <9A/WT3STT> +00 DX'). pack77_txqp / pack77_txqpvar
rejected any input where both words were wrapped in <...>, so DecodedText's
stdmsg_ round-trip failed and is_standard_ was FALSE for these messages only.

That single asymmetry is why regular-call QSOs auto-sequenced and logged
correctly while compound-vs-compound QSOs did not: the standard
auto-sequence, state-transition and logging paths all key off
isStandardMessage(), and m_xRcvd (the received exchange used for logging)
was never populated.

Relaxing the both-bracketed guard in pack77_txqp and pack77_txqpvar lets
these exchanges pack as i3=3 again. The exchange-token validation
(valid county/state/province/DX with +00 or R+00) still guards against
false positives, and pack28/pack28var already hash both compound calls
into the frame. The equivalent RTTY guards in pack77_3/pack77_3var are
intentionally left unchanged.
The TxQP location multiplier (county / state / province / DX) was written
to the ADIF-standard <srx_string> (received) and <stx_string> (sent) fields.
N1MM only imports the <srx> and <stx> tags when receiving pushed QSO data,
so the exchange was being dropped on import.

Write the sent/received location to <stx>/<srx> instead. The received side
still also emits <state> for general logging/awards tracking, and the
ARRL Field Day <SRX_STRING> path is left unchanged.
…ross-tool compatibility

N1MM only imports the numeric <srx>/<stx> tags (non-standard behavior for
non-numeric contest exchange data), while N3FJP follows the ADIF standard
and expects non-numeric exchange data in <srx_string>/<stx_string>.

Now write the TxQP location multiplier to BOTH sets of tags:
- Sent: <stx> + <stx_string>
- Received: <srx> + <srx_string>

This ensures the exchange is correctly imported by both N1MM and N3FJP
(and other ADIF-compliant logging software). ADIF validators may flag a
warning (non-numeric data in numeric-only fields), but no data is lost.
The received TxQP location was landing in N1MM's 'Sect' column (from the
standard <state> tag) while the 'Exch' column stayed empty. Per N1MM's
technical docs, N1MM stores/restores its 'Exchange1' database field (the
Exch column) via its application-specific <app_n1mm_exchange1> ADIF tag,
not via <state>/<srx>. Add that tag (with the county/state/province/DX
location) to the TxQP received-exchange ADIF record so N1MM captures the
exchange in the correct field.

Standard tags are still written for other loggers: <srx> (numeric-style,
also accepted by N1MM), <srx_string> (N3FJP / ADIF-standard) and <state>
(general logging/awards).
Restore CI.yml to produce all install packages
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant