[feat](trx-rs): add FT2 decoder protocol support
Implement a distinct FT2 protocol path in the decoder stack and align\nits timing with the confirmed FT2 framing used by Decodium.\n\nCo-authored-by: OpenAI Codex <codex@openai.com> Signed-off-by: Stanislaw Grams <stanislawgrams@gmail.com>
This commit is contained in:
Vendored
+32
-1
@@ -14,6 +14,9 @@ extern "C"
|
||||
#define FT4_SYMBOL_PERIOD (0.048f) ///< FT4 symbol duration, defines tone deviation in Hz and symbol rate
|
||||
#define FT4_SLOT_TIME (7.5f) ///< FT4 slot period
|
||||
|
||||
#define FT2_SYMBOL_PERIOD (0.024f) ///< FT2 symbol duration (288 samples @ 12 kHz)
|
||||
#define FT2_SLOT_TIME (3.75f) ///< FT2 slot period
|
||||
|
||||
// Define FT8 symbol counts
|
||||
// FT8 message structure:
|
||||
// S D1 S D2 S
|
||||
@@ -38,6 +41,14 @@ extern "C"
|
||||
#define FT4_NUM_SYNC (4) ///< Number of sync groups
|
||||
#define FT4_SYNC_OFFSET (33) ///< Offset between sync groups
|
||||
|
||||
// FT2 reuses the FT4 channel structure with a shorter slot and symbol period.
|
||||
#define FT2_ND FT4_ND
|
||||
#define FT2_NR FT4_NR
|
||||
#define FT2_NN FT4_NN
|
||||
#define FT2_LENGTH_SYNC FT4_LENGTH_SYNC
|
||||
#define FT2_NUM_SYNC FT4_NUM_SYNC
|
||||
#define FT2_SYNC_OFFSET FT4_SYNC_OFFSET
|
||||
|
||||
// Define LDPC parameters
|
||||
#define FTX_LDPC_N (174) ///< Number of bits in the encoded message (payload with LDPC checksum bits)
|
||||
#define FTX_LDPC_K (91) ///< Number of payload bits (including CRC)
|
||||
@@ -52,9 +63,29 @@ extern "C"
|
||||
typedef enum
|
||||
{
|
||||
FTX_PROTOCOL_FT4,
|
||||
FTX_PROTOCOL_FT8
|
||||
FTX_PROTOCOL_FT8,
|
||||
FTX_PROTOCOL_FT2
|
||||
} ftx_protocol_t;
|
||||
|
||||
static inline float ftx_protocol_symbol_period(ftx_protocol_t protocol)
|
||||
{
|
||||
return (protocol == FTX_PROTOCOL_FT8)
|
||||
? FT8_SYMBOL_PERIOD
|
||||
: ((protocol == FTX_PROTOCOL_FT2) ? FT2_SYMBOL_PERIOD : FT4_SYMBOL_PERIOD);
|
||||
}
|
||||
|
||||
static inline float ftx_protocol_slot_time(ftx_protocol_t protocol)
|
||||
{
|
||||
return (protocol == FTX_PROTOCOL_FT8)
|
||||
? FT8_SLOT_TIME
|
||||
: ((protocol == FTX_PROTOCOL_FT2) ? FT2_SLOT_TIME : FT4_SLOT_TIME);
|
||||
}
|
||||
|
||||
static inline int ftx_protocol_uses_ft4_layout(ftx_protocol_t protocol)
|
||||
{
|
||||
return (protocol == FTX_PROTOCOL_FT4) || (protocol == FTX_PROTOCOL_FT2);
|
||||
}
|
||||
|
||||
/// Costas 7x7 tone pattern for synchronization
|
||||
extern const uint8_t kFT8_Costas_pattern[7];
|
||||
extern const uint8_t kFT4_Costas_pattern[4][4];
|
||||
|
||||
Vendored
+6
-5
@@ -189,8 +189,9 @@ static int ft4_sync_score(const ftx_waterfall_t* wf, const ftx_candidate_t* cand
|
||||
|
||||
int ftx_find_candidates(const ftx_waterfall_t* wf, int num_candidates, ftx_candidate_t heap[], int min_score)
|
||||
{
|
||||
int (*sync_fun)(const ftx_waterfall_t*, const ftx_candidate_t*) = (wf->protocol == FTX_PROTOCOL_FT4) ? ft4_sync_score : ft8_sync_score;
|
||||
int num_tones = (wf->protocol == FTX_PROTOCOL_FT4) ? 4 : 8;
|
||||
int (*sync_fun)(const ftx_waterfall_t*, const ftx_candidate_t*) =
|
||||
ftx_protocol_uses_ft4_layout(wf->protocol) ? ft4_sync_score : ft8_sync_score;
|
||||
int num_tones = ftx_protocol_uses_ft4_layout(wf->protocol) ? 4 : 8;
|
||||
|
||||
int heap_size = 0;
|
||||
ftx_candidate_t candidate;
|
||||
@@ -327,7 +328,7 @@ static void ftx_normalize_logl(float* log174)
|
||||
bool ftx_decode_candidate(const ftx_waterfall_t* wf, const ftx_candidate_t* cand, int max_iterations, ftx_message_t* message, ftx_decode_status_t* status)
|
||||
{
|
||||
float log174[FTX_LDPC_N]; // message bits encoded as likelihood
|
||||
if (wf->protocol == FTX_PROTOCOL_FT4)
|
||||
if (ftx_protocol_uses_ft4_layout(wf->protocol))
|
||||
{
|
||||
ft4_extract_likelihood(wf, cand, log174);
|
||||
}
|
||||
@@ -366,7 +367,7 @@ bool ftx_decode_candidate(const ftx_waterfall_t* wf, const ftx_candidate_t* cand
|
||||
// Reuse CRC value as a hash for the message (TODO: 14 bits only, should perhaps use full 16 or 32 bits?)
|
||||
message->hash = status->crc_calculated;
|
||||
|
||||
if (wf->protocol == FTX_PROTOCOL_FT4)
|
||||
if (ftx_protocol_uses_ft4_layout(wf->protocol))
|
||||
{
|
||||
// '[..] for FT4 only, in order to avoid transmitting a long string of zeros when sending CQ messages,
|
||||
// the assembled 77-bit message is bitwise exclusive-OR’ed with [a] pseudorandom sequence before computing the CRC and FEC parity bits'
|
||||
@@ -589,4 +590,4 @@ static void pack_bits(const uint8_t bit_array[], int num_bits, uint8_t packed[])
|
||||
++byte_idx;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
Vendored
+5
@@ -193,3 +193,8 @@ void ft4_encode(const uint8_t* payload, uint8_t* tones)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void ft2_encode(const uint8_t* payload, uint8_t* tones)
|
||||
{
|
||||
ft4_encode(payload, tones);
|
||||
}
|
||||
|
||||
Vendored
+6
@@ -34,6 +34,12 @@ void ft8_encode(const uint8_t* payload, uint8_t* tones);
|
||||
/// @param[out] tones - array of FT4_NN (105) bytes to store the generated tones (encoded as 0..3)
|
||||
void ft4_encode(const uint8_t* payload, uint8_t* tones);
|
||||
|
||||
/// Generate FT2 tone sequence from payload data.
|
||||
/// FT2 uses the FT4 framing with a doubled symbol rate.
|
||||
/// @param[in] payload - 10 byte array consisting of 77 bit payload
|
||||
/// @param[out] tones - array of FT2_NN (105) bytes to store the generated tones (encoded as 0..3)
|
||||
void ft2_encode(const uint8_t* payload, uint8_t* tones);
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
#endif
|
||||
|
||||
Reference in New Issue
Block a user