kopia lustrzana https://github.com/kgoba/ft8_lib
Renaming constants to use less generic names
rodzic
3418b64b08
commit
74ff78663b
3
Makefile
3
Makefile
|
@ -1,4 +1,5 @@
|
|||
CXXFLAGS = -std=c++14 -I.
|
||||
CFLAGS = -O3
|
||||
CPPFLAGS = -std=c11 -I.
|
||||
LDFLAGS = -lm
|
||||
|
||||
TARGETS = gen_ft8 decode_ft8 test
|
||||
|
|
|
@ -221,7 +221,7 @@ int main(int argc, char **argv)
|
|||
|
||||
// Find top candidates by Costas sync score and localize them in time and frequency
|
||||
Candidate candidate_list[kMax_candidates];
|
||||
int num_candidates = find_sync(&power, kCostas_map, kMax_candidates, candidate_list, kMin_score);
|
||||
int num_candidates = find_sync(&power, kFT8_Costas_pattern, kMax_candidates, candidate_list, kMin_score);
|
||||
|
||||
// TODO: sort the candidates by strongest sync first?
|
||||
|
||||
|
@ -238,7 +238,7 @@ int main(int argc, char **argv)
|
|||
float time_sec = (cand->time_offset + (float)cand->time_sub / kTime_osr) / kFSK_dev;
|
||||
|
||||
float log174[FT8_N];
|
||||
extract_likelihood(&power, cand, kGray_map, log174);
|
||||
extract_likelihood(&power, cand, kFT8_Gray_map, log174);
|
||||
|
||||
for (int k = 100; k < 174; ++k)
|
||||
{
|
||||
|
|
|
@ -1,13 +1,13 @@
|
|||
#include "constants.h"
|
||||
|
||||
// Costas 7x7 tone pattern
|
||||
const uint8_t kCostas_map[7] = {3, 1, 4, 0, 6, 5, 2};
|
||||
const uint8_t kFT8_Costas_pattern[7] = {3, 1, 4, 0, 6, 5, 2};
|
||||
|
||||
// Gray code map
|
||||
const uint8_t kGray_map[8] = {0, 1, 3, 2, 5, 6, 4, 7};
|
||||
const uint8_t kFT8_Gray_map[8] = {0, 1, 3, 2, 5, 6, 4, 7};
|
||||
|
||||
// Parity generator matrix for (174,91) LDPC code, stored in bitpacked format (MSB first)
|
||||
const uint8_t kGenerator[FT8_M][FT8_K_BYTES] = {
|
||||
const uint8_t kFT8_LDPC_generator[FT8_M][FT8_K_BYTES] = {
|
||||
{0x83, 0x29, 0xce, 0x11, 0xbf, 0x31, 0xea, 0xf5, 0x09, 0xf2, 0x7f, 0xc0},
|
||||
{0x76, 0x1c, 0x26, 0x4e, 0x25, 0xc2, 0x59, 0x33, 0x54, 0x93, 0x13, 0x20},
|
||||
{0xdc, 0x26, 0x59, 0x02, 0xfb, 0x27, 0x7c, 0x64, 0x10, 0xa1, 0xbd, 0xc0},
|
||||
|
@ -94,7 +94,7 @@ const uint8_t kGenerator[FT8_M][FT8_K_BYTES] = {
|
|||
|
||||
// Column order (permutation) in which the bits in codeword are stored
|
||||
// (Not really used in FT8 v2 - instead the Nm, Mn and generator matrices are already permuted)
|
||||
const uint8_t kColumn_order[FT8_N] = {
|
||||
const uint8_t kFT8_LDPC_column_order[FT8_N] = {
|
||||
0, 1, 2, 3, 28, 4, 5, 6, 7, 8, 9, 10, 11, 34, 12, 32, 13, 14, 15, 16,
|
||||
17, 18, 36, 29, 43, 19, 20, 42, 21, 40, 30, 37, 22, 47, 61, 45, 44, 23, 41, 39,
|
||||
49, 24, 46, 50, 48, 26, 31, 33, 51, 38, 52, 59, 55, 66, 57, 27, 60, 35, 54, 58,
|
||||
|
@ -111,7 +111,7 @@ const uint8_t kColumn_order[FT8_N] = {
|
|||
// each number is an index into the codeword (1-origin).
|
||||
// the codeword bits mentioned in each row must xor to zero.
|
||||
// From WSJT-X's ldpc_174_91_c_reordered_parity.f90.
|
||||
const uint8_t kNm[FT8_M][7] = {
|
||||
const uint8_t kFT8_LDPC_Nm[FT8_M][7] = {
|
||||
{4, 31, 59, 91, 92, 96, 153},
|
||||
{5, 32, 60, 93, 115, 146, 0},
|
||||
{6, 24, 61, 94, 122, 151, 0},
|
||||
|
@ -201,7 +201,7 @@ const uint8_t kNm[FT8_M][7] = {
|
|||
// the numbers indicate which three parity
|
||||
// checks (rows in Nm) refer to the codeword bit.
|
||||
// 1-origin.
|
||||
const uint8_t kMn[FT8_N][3] = {
|
||||
const uint8_t kFT8_LDPC_Mn[FT8_N][3] = {
|
||||
{16, 45, 73},
|
||||
{25, 51, 62},
|
||||
{33, 58, 78},
|
||||
|
@ -377,7 +377,7 @@ const uint8_t kMn[FT8_N][3] = {
|
|||
{20, 44, 48},
|
||||
{42, 49, 57}};
|
||||
|
||||
const uint8_t kNrw[FT8_M] = {
|
||||
const uint8_t kFT8_LDPC_num_rows[FT8_M] = {
|
||||
7, 6, 6, 6, 7, 6, 7, 6, 6, 7, 6, 6, 7, 7, 6, 6,
|
||||
6, 7, 6, 7, 6, 7, 6, 6, 6, 7, 6, 6, 6, 7, 6, 6,
|
||||
6, 6, 7, 6, 6, 6, 7, 7, 6, 6, 6, 6, 7, 7, 6, 6,
|
||||
|
|
24
ft8/encode.c
24
ft8/encode.c
|
@ -3,7 +3,7 @@
|
|||
|
||||
#include <stdio.h>
|
||||
|
||||
#define TOPBIT (1 << (CRC_WIDTH - 1))
|
||||
#define TOPBIT (1 << (FT8_CRC_WIDTH - 1))
|
||||
|
||||
// Returns 1 if an odd number of bits are set in x, zero otherwise
|
||||
uint8_t parity8(uint8_t x)
|
||||
|
@ -24,7 +24,7 @@ uint8_t parity8(uint8_t x)
|
|||
void encode174(const uint8_t *message, uint8_t *codeword)
|
||||
{
|
||||
// Here we don't generate the generator bit matrix as in WSJT-X implementation
|
||||
// Instead we access the generator bits straight from the binary representation in kGenerator
|
||||
// Instead we access the generator bits straight from the binary representation in kFT8_LDPC_generator
|
||||
|
||||
// For reference:
|
||||
// codeword(1:K)=message
|
||||
|
@ -49,13 +49,13 @@ void encode174(const uint8_t *message, uint8_t *codeword)
|
|||
for (int i = 0; i < FT8_M; ++i)
|
||||
{ // do i=1,FT8_M
|
||||
// Fast implementation of bitwise multiplication and parity checking
|
||||
// Normally nsum would contain the result of dot product between message and kGenerator[i],
|
||||
// Normally nsum would contain the result of dot product between message and kFT8_LDPC_generator[i],
|
||||
// but we only compute the sum modulo 2.
|
||||
uint8_t nsum = 0;
|
||||
for (int j = 0; j < FT8_K_BYTES; ++j)
|
||||
{
|
||||
uint8_t bits = message[j] & kGenerator[i][j]; // bitwise AND (bitwise multiplication)
|
||||
nsum ^= parity8(bits); // bitwise XOR (addition modulo 2)
|
||||
uint8_t bits = message[j] & kFT8_LDPC_generator[i][j]; // bitwise AND (bitwise multiplication)
|
||||
nsum ^= parity8(bits); // bitwise XOR (addition modulo 2)
|
||||
}
|
||||
// Check if we need to set a bit in codeword
|
||||
if (nsum % 2)
|
||||
|
@ -93,14 +93,14 @@ uint16_t ft8_crc(uint8_t *message, int num_bits)
|
|||
if (idx_bit % 8 == 0)
|
||||
{
|
||||
// Bring the next byte into the remainder.
|
||||
remainder ^= (message[idx_byte] << (CRC_WIDTH - 8));
|
||||
remainder ^= (message[idx_byte] << (FT8_CRC_WIDTH - 8));
|
||||
++idx_byte;
|
||||
}
|
||||
|
||||
// Try to divide the current data bit.
|
||||
if (remainder & TOPBIT)
|
||||
{
|
||||
remainder = (remainder << 1) ^ CRC_POLYNOMIAL;
|
||||
remainder = (remainder << 1) ^ FT8_CRC_POLYNOMIAL;
|
||||
}
|
||||
else
|
||||
{
|
||||
|
@ -108,7 +108,7 @@ uint16_t ft8_crc(uint8_t *message, int num_bits)
|
|||
}
|
||||
}
|
||||
|
||||
return remainder & ((1 << CRC_WIDTH) - 1);
|
||||
return remainder & ((1 << FT8_CRC_WIDTH) - 1);
|
||||
}
|
||||
|
||||
// Generate FT8 tone sequence from payload data
|
||||
|
@ -142,9 +142,9 @@ void genft8(const uint8_t *payload, uint8_t *itone)
|
|||
// Message structure: S7 D29 S7 D29 S7
|
||||
for (int i = 0; i < 7; ++i)
|
||||
{
|
||||
itone[i] = kCostas_map[i];
|
||||
itone[36 + i] = kCostas_map[i];
|
||||
itone[72 + i] = kCostas_map[i];
|
||||
itone[i] = kFT8_Costas_pattern[i];
|
||||
itone[36 + i] = kFT8_Costas_pattern[i];
|
||||
itone[72 + i] = kFT8_Costas_pattern[i];
|
||||
}
|
||||
|
||||
int k = 7; // Skip over the first set of Costas symbols
|
||||
|
@ -183,7 +183,7 @@ void genft8(const uint8_t *payload, uint8_t *itone)
|
|||
i_byte++;
|
||||
}
|
||||
|
||||
itone[k] = kGray_map[bits3];
|
||||
itone[k] = kFT8_Gray_map[bits3];
|
||||
++k;
|
||||
}
|
||||
}
|
||||
|
|
36
ft8/ldpc.c
36
ft8/ldpc.c
|
@ -70,13 +70,13 @@ void ldpc_decode(float codeword[], int max_iters, uint8_t plain[], int *ok)
|
|||
{
|
||||
for (int j = 0; j < FT8_M; j++)
|
||||
{
|
||||
for (int ii1 = 0; ii1 < kNrw[j]; ii1++)
|
||||
for (int ii1 = 0; ii1 < kFT8_LDPC_num_rows[j]; ii1++)
|
||||
{
|
||||
int i1 = kNm[j][ii1] - 1;
|
||||
int i1 = kFT8_LDPC_Nm[j][ii1] - 1;
|
||||
float a = 1.0f;
|
||||
for (int ii2 = 0; ii2 < kNrw[j]; ii2++)
|
||||
for (int ii2 = 0; ii2 < kFT8_LDPC_num_rows[j]; ii2++)
|
||||
{
|
||||
int i2 = kNm[j][ii2] - 1;
|
||||
int i2 = kFT8_LDPC_Nm[j][ii2] - 1;
|
||||
if (i2 != i1)
|
||||
{
|
||||
a *= fast_tanh(-m[j][i2] / 2.0f);
|
||||
|
@ -90,7 +90,7 @@ void ldpc_decode(float codeword[], int max_iters, uint8_t plain[], int *ok)
|
|||
{
|
||||
float l = codeword[i];
|
||||
for (int j = 0; j < 3; j++)
|
||||
l += e[kMn[i][j] - 1][i];
|
||||
l += e[kFT8_LDPC_Mn[i][j] - 1][i];
|
||||
plain[i] = (l > 0) ? 1 : 0;
|
||||
}
|
||||
|
||||
|
@ -111,13 +111,13 @@ void ldpc_decode(float codeword[], int max_iters, uint8_t plain[], int *ok)
|
|||
{
|
||||
for (int ji1 = 0; ji1 < 3; ji1++)
|
||||
{
|
||||
int j1 = kMn[i][ji1] - 1;
|
||||
int j1 = kFT8_LDPC_Mn[i][ji1] - 1;
|
||||
float l = codeword[i];
|
||||
for (int ji2 = 0; ji2 < 3; ji2++)
|
||||
{
|
||||
if (ji1 != ji2)
|
||||
{
|
||||
int j2 = kMn[i][ji2] - 1;
|
||||
int j2 = kFT8_LDPC_Mn[i][ji2] - 1;
|
||||
l += e[j2][i];
|
||||
}
|
||||
}
|
||||
|
@ -141,9 +141,9 @@ static int ldpc_check(uint8_t codeword[])
|
|||
for (int j = 0; j < FT8_M; ++j)
|
||||
{
|
||||
uint8_t x = 0;
|
||||
for (int i = 0; i < kNrw[j]; ++i)
|
||||
for (int i = 0; i < kFT8_LDPC_num_rows[j]; ++i)
|
||||
{
|
||||
x ^= codeword[kNm[j][i] - 1];
|
||||
x ^= codeword[kFT8_LDPC_Nm[j][i] - 1];
|
||||
}
|
||||
if (x != 0)
|
||||
{
|
||||
|
@ -166,9 +166,9 @@ void bp_decode(float codeword[], int max_iters, uint8_t plain[], int *ok)
|
|||
// initialize messages to checks
|
||||
for (int i = 0; i < FT8_M; ++i)
|
||||
{
|
||||
for (int j = 0; j < kNrw[i]; ++j)
|
||||
for (int j = 0; j < kFT8_LDPC_num_rows[i]; ++j)
|
||||
{
|
||||
toc[i][j] = codeword[kNm[i][j] - 1];
|
||||
toc[i][j] = codeword[kFT8_LDPC_Nm[i][j] - 1];
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -208,14 +208,14 @@ void bp_decode(float codeword[], int max_iters, uint8_t plain[], int *ok)
|
|||
// Send messages from bits to check nodes
|
||||
for (int i = 0; i < FT8_M; ++i)
|
||||
{
|
||||
for (int j = 0; j < kNrw[i]; ++j)
|
||||
for (int j = 0; j < kFT8_LDPC_num_rows[i]; ++j)
|
||||
{
|
||||
int ibj = kNm[i][j] - 1;
|
||||
int ibj = kFT8_LDPC_Nm[i][j] - 1;
|
||||
toc[i][j] = zn[ibj];
|
||||
for (int kk = 0; kk < 3; ++kk)
|
||||
{
|
||||
// subtract off what the bit had received from the check
|
||||
if (kMn[ibj][kk] - 1 == i)
|
||||
if (kFT8_LDPC_Mn[ibj][kk] - 1 == i)
|
||||
{
|
||||
toc[i][j] -= tov[ibj][kk];
|
||||
break;
|
||||
|
@ -227,7 +227,7 @@ void bp_decode(float codeword[], int max_iters, uint8_t plain[], int *ok)
|
|||
// send messages from check nodes to variable nodes
|
||||
for (int i = 0; i < FT8_M; ++i)
|
||||
{
|
||||
for (int j = 0; j < kNrw[i]; ++j)
|
||||
for (int j = 0; j < kFT8_LDPC_num_rows[i]; ++j)
|
||||
{
|
||||
toc[i][j] = fast_tanh(-toc[i][j] / 2);
|
||||
}
|
||||
|
@ -237,11 +237,11 @@ void bp_decode(float codeword[], int max_iters, uint8_t plain[], int *ok)
|
|||
{
|
||||
for (int j = 0; j < 3; ++j)
|
||||
{
|
||||
int ichk = kMn[i][j] - 1; // kMn(:,j) are the checks that include bit j
|
||||
int ichk = kFT8_LDPC_Mn[i][j] - 1; // kFT8_LDPC_Mn(:,j) are the checks that include bit j
|
||||
float Tmn = 1.0f;
|
||||
for (int k = 0; k < kNrw[ichk]; ++k)
|
||||
for (int k = 0; k < kFT8_LDPC_num_rows[ichk]; ++k)
|
||||
{
|
||||
if (kNm[ichk][k] - 1 != i)
|
||||
if (kFT8_LDPC_Nm[ichk][k] - 1 != i)
|
||||
{
|
||||
Tmn *= toc[ichk][k];
|
||||
}
|
||||
|
|
Ładowanie…
Reference in New Issue