1
0
mirror of https://github.com/f4exb/sdrangel.git synced 2025-02-03 09:44:01 -05:00

FT8 demod: isolate call1, all2 and locator in callback

This commit is contained in:
f4exb 2023-01-08 23:15:31 +01:00
parent 6594bf209e
commit 23e01ea064
4 changed files with 108 additions and 243 deletions

View File

@ -406,181 +406,23 @@ public:
// bits being one. measured from reconstructed correct // bits being one. measured from reconstructed correct
// codewords, into ft8bits, then python bprob.py. // codewords, into ft8bits, then python bprob.py.
// from ft8-n4 // from ft8-n4
float apriori174[] = { double apriori174[] = {
0.47, 0.47, 0.32, 0.29, 0.37, 0.52, 0.36, 0.40, 0.42, 0.42, 0.53, 0.44,
0.32, 0.44, 0.39, 0.46, 0.39, 0.38, 0.42, 0.43, 0.45, 0.51, 0.42, 0.48,
0.29, 0.31, 0.45, 0.47, 0.53, 0.59, 0.41, 0.03, 0.50, 0.30, 0.26, 0.40,
0.37, 0.65, 0.34, 0.49, 0.46, 0.49, 0.69, 0.40, 0.45, 0.45, 0.60, 0.46,
0.52, 0.43, 0.49, 0.56, 0.45, 0.55, 0.51, 0.46, 0.37, 0.55, 0.52, 0.56,
0.36, 0.55, 0.50, 0.01, 0.19, 0.70, 0.88, 0.75, 0.75, 0.74, 0.73, 0.18,
0.40, 0.71, 0.35, 0.60, 0.58, 0.36, 0.60, 0.38, 0.50, 0.02, 0.01, 0.98,
0.42, 0.48, 0.49, 0.54, 0.50, 0.49, 0.53, 0.50, 0.49, 0.49, 0.51, 0.51,
0.42, 0.51, 0.47, 0.50, 0.53, 0.51, 0.46, 0.51, 0.51, 0.48, 0.51, 0.52,
0.53, 0.50, 0.52, 0.51, 0.50, 0.49, 0.53, 0.52, 0.50, 0.46, 0.47, 0.48,
0.44, 0.52, 0.50, 0.49, 0.51, 0.49, 0.49, 0.50, 0.50, 0.50, 0.50, 0.51,
0.44, 0.50, 0.49, 0.49, 0.55, 0.49, 0.51, 0.48, 0.55, 0.49, 0.48, 0.50,
0.39, 0.51, 0.50, 0.51, 0.50, 0.51, 0.53, 0.49, 0.54, 0.50, 0.48, 0.49,
0.46, 0.46, 0.51, 0.51, 0.52, 0.49, 0.51, 0.49, 0.51, 0.50, 0.49, 0.50,
0.39, 0.50, 0.47, 0.49, 0.52, 0.49, 0.51, 0.49, 0.48, 0.52, 0.48, 0.49,
0.38, 0.47, 0.50, 0.48, 0.50, 0.49, 0.51, 0.51, 0.51, 0.49,
0.42,
0.43,
0.45,
0.51,
0.42,
0.48,
0.31,
0.45,
0.47,
0.53,
0.59,
0.41,
0.03,
0.50,
0.30,
0.26,
0.40,
0.65,
0.34,
0.49,
0.46,
0.49,
0.69,
0.40,
0.45,
0.45,
0.60,
0.46,
0.43,
0.49,
0.56,
0.45,
0.55,
0.51,
0.46,
0.37,
0.55,
0.52,
0.56,
0.55,
0.50,
0.01,
0.19,
0.70,
0.88,
0.75,
0.75,
0.74,
0.73,
0.18,
0.71,
0.35,
0.60,
0.58,
0.36,
0.60,
0.38,
0.50,
0.02,
0.01,
0.98,
0.48,
0.49,
0.54,
0.50,
0.49,
0.53,
0.50,
0.49,
0.49,
0.51,
0.51,
0.51,
0.47,
0.50,
0.53,
0.51,
0.46,
0.51,
0.51,
0.48,
0.51,
0.52,
0.50,
0.52,
0.51,
0.50,
0.49,
0.53,
0.52,
0.50,
0.46,
0.47,
0.48,
0.52,
0.50,
0.49,
0.51,
0.49,
0.49,
0.50,
0.50,
0.50,
0.50,
0.51,
0.50,
0.49,
0.49,
0.55,
0.49,
0.51,
0.48,
0.55,
0.49,
0.48,
0.50,
0.51,
0.50,
0.51,
0.50,
0.51,
0.53,
0.49,
0.54,
0.50,
0.48,
0.49,
0.46,
0.51,
0.51,
0.52,
0.49,
0.51,
0.49,
0.51,
0.50,
0.49,
0.50,
0.50,
0.47,
0.49,
0.52,
0.49,
0.51,
0.49,
0.48,
0.52,
0.48,
0.49,
0.47,
0.50,
0.48,
0.50,
0.49,
0.51,
0.51,
0.51,
0.49,
}; };
class FT8 class FT8
@ -3772,38 +3614,41 @@ void entry(
// decodes from previous runs, for subtraction. // decodes from previous runs, for subtraction.
std::vector<cdecode> prevdecs; std::vector<cdecode> prevdecs;
for (int i = 0; i < nprevdecs; i++)
{ for (int i = 0; i < nprevdecs; i++) {
prevdecs.push_back(xprevdecs[i]); prevdecs.push_back(xprevdecs[i]);
} }
std::vector<float> samples(nsamples); std::vector<float> samples(nsamples);
for (int i = 0; i < nsamples; i++)
{ for (int i = 0; i < nsamples; i++) {
samples[i] = xsamples[i]; samples[i] = xsamples[i];
} }
if (min_hz < 0) if (min_hz < 0) {
{
min_hz = 0; min_hz = 0;
} }
if (max_hz > rate / 2)
{ if (max_hz > rate / 2) {
max_hz = rate / 2; max_hz = rate / 2;
} }
float per = (max_hz - min_hz) / nthreads;
float per = (max_hz - min_hz) / nthreads;
std::vector<FT8 *> thv; std::vector<FT8 *> thv;
for (int i = 0; i < nthreads; i++) for (int i = 0; i < nthreads; i++)
{ {
float hz0 = min_hz + i * per; float hz0 = min_hz + i * per;
if (i > 0 || overlap_edges)
if (i > 0 || overlap_edges) {
hz0 -= overlap; hz0 -= overlap;
}
float hz1 = min_hz + (i + 1) * per; float hz1 = min_hz + (i + 1) * per;
if (i != nthreads - 1 || overlap_edges)
if (i != nthreads - 1 || overlap_edges) {
hz1 += overlap; hz1 += overlap;
}
hz0 = std::max(hz0, 0.0f); hz0 = std::max(hz0, 0.0f);
hz1 = std::min(hz1, (rate / 2.0f) - 50); hz1 = std::min(hz1, (rate / 2.0f) - 50);
@ -3823,9 +3668,7 @@ void entry(
); );
int npasses = nprevdecs > 0 ? npasses_two : npasses_one; int npasses = nprevdecs > 0 ? npasses_two : npasses_one;
ft8->th_ = new std::thread([ft8, npasses] () { ft8->go(npasses); }); ft8->th_ = new std::thread([ft8, npasses] () { ft8->go(npasses); });
thv.push_back(ft8); thv.push_back(ft8);
} }

View File

@ -248,24 +248,25 @@ void remember_call(std::string call)
// 1 bit: swap // 1 bit: swap
// 2 bits: 1 RRR, 2 RR73, 3 73 // 2 bits: 1 RRR, 2 RR73, 3 73
// 1 bit: 1 means CQ // 1 bit: 1 means CQ
std::string unpack_4(int a77[]) std::string unpack_4(int a77[], std::string& call1str, std::string& call2str, std::string& locstr)
{ {
(void) locstr;
// 38 possible characters: // 38 possible characters:
const char *chars = " 0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZ/"; const char *chars = " 0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZ/";
long long n58 = un(a77, 12, 58); long long n58 = un(a77, 12, 58);
char call[16]; char call[16];
for (int i = 0; i < 11; i++) for (int i = 0; i < 11; i++)
{ {
call[10 - i] = chars[n58 % 38]; call[10 - i] = chars[n58 % 38];
n58 = n58 / 38; n58 = n58 / 38;
} }
call[11] = '\0'; call[11] = '\0';
remember_call(call); remember_call(call);
if (un(a77, 73, 1) == 1) if (un(a77, 73, 1) == 1) {
{
return std::string("CQ ") + call; return std::string("CQ ") + call;
} }
@ -273,38 +274,38 @@ std::string unpack_4(int a77[])
// 12-bit hash // 12-bit hash
hashes_mu.lock(); hashes_mu.lock();
std::string ocall; std::string ocall;
if (hashes12.count(x12) > 0)
{ if (hashes12.count(x12) > 0) {
ocall = hashes12[x12]; ocall = hashes12[x12];
} } else {
else
{
ocall = "<...12>"; ocall = "<...12>";
} }
hashes_mu.unlock(); hashes_mu.unlock();
int swap = un(a77, 70, 1); int swap = un(a77, 70, 1);
std::string msg; std::string msg;
if (swap) if (swap)
{ {
msg = std::string(call) + " " + ocall; msg = std::string(call) + " " + ocall;
call1str = call;
call2str = ocall;
} }
else else
{ {
msg = std::string(ocall) + " " + call; msg = std::string(ocall) + " " + call;
call1str = ocall;
call2str = call;
} }
int suffix = un(a77, 71, 2); int suffix = un(a77, 71, 2);
if (suffix == 1)
{ if (suffix == 1) {
msg += " RRR"; msg += " RRR";
} } else if (suffix == 2) {
else if (suffix == 2)
{
msg += " RR73"; msg += " RR73";
} } else if (suffix == 3) {
else if (suffix == 3)
{
msg += " 73"; msg += " 73";
} }
@ -314,7 +315,7 @@ std::string unpack_4(int a77[])
// //
// i3=1 // i3=1
// //
std::string unpack_1(int a77[]) std::string unpack_1(int a77[], std::string& call1str, std::string& call2str, std::string& locstr)
{ {
// type 1: // type 1:
// 28 call1 // 28 call1
@ -342,24 +343,26 @@ std::string unpack_1(int a77[])
i += 3; i += 3;
assert((i3 == 1 || i3 == 2) && i == 77); assert((i3 == 1 || i3 == 2) && i == 77);
std::string call1text = trim(unpackcall(call1)); call1str = trim(unpackcall(call1));
std::string call2text = trim(unpackcall(call2)); call2str = trim(unpackcall(call2));
std::string gridtext = unpackgrid(grid, ir, i3); locstr = unpackgrid(grid, ir, i3);
remember_call(call1text); remember_call(call1str);
remember_call(call2text); remember_call(call2str);
const char *pr = (i3 == 1 ? "/R" : "/P"); const char *pr = (i3 == 1 ? "/R" : "/P");
return call1text + (rover1 ? pr : "") + " " + call2text + (rover2 ? pr : "") + " " + gridtext; return call1str + (rover1 ? pr : "") + " " + call2str + (rover2 ? pr : "") + " " + locstr;
} }
// free text // free text
// 71 bits, 13 characters, each one of 42 choices. // 71 bits, 13 characters, each one of 42 choices.
// reversed. // reversed.
// details from wsjt-x's packjt77.f90 // details from wsjt-x's packjt77.f90
std::string unpack_0_0(int a77[]) std::string unpack_0_0(int a77[], std::string& call1str, std::string& call2str, std::string& locstr)
{ {
(void) call2str;
(void) locstr;
// the 42 possible characters. // the 42 possible characters.
const char *cc = " 0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZ+-./?"; const char *cc = " 0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZ+-./?";
__int128 x = un(a77, 0, 71); __int128 x = un(a77, 0, 71);
@ -369,6 +372,7 @@ std::string unpack_0_0(int a77[])
msg[13 - 1 - i] = cc[x % 42]; msg[13 - 1 - i] = cc[x % 42];
x = x / 42; x = x / 42;
} }
call1str = msg;
return msg; return msg;
} }
@ -390,8 +394,9 @@ const char *ru_states[] = {
// 1 R // 1 R
// 3 RST 529 to 599 // 3 RST 529 to 599
// 13 state/province/serialnumber // 13 state/province/serialnumber
std::string unpack_3(int a77[]) std::string unpack_3(int a77[], std::string& call1str, std::string& call2str, std::string& locstr)
{ {
(void) locstr;
int i = 0; int i = 0;
int tu = a77[i]; int tu = a77[i];
i += 1; i += 1;
@ -406,8 +411,8 @@ std::string unpack_3(int a77[])
int serial = un(a77, i, 13); int serial = un(a77, i, 13);
i += 13; i += 13;
std::string call1text = unpackcall(call1); call1str = trim(unpackcall(call1));
std::string call2text = unpackcall(call2); call2str = trim(unpackcall(call2));
rst = 529 + 10 * rst; rst = 529 + 10 * rst;
@ -431,7 +436,7 @@ std::string unpack_3(int a77[])
{ {
msg += "TU; "; msg += "TU; ";
} }
msg += call1text + " " + call2text + " "; msg += call1str + " " + call2str + " ";
if (r) if (r)
{ {
msg += "R "; msg += "R ";
@ -443,8 +448,8 @@ std::string unpack_3(int a77[])
} }
msg += serialstr; msg += serialstr;
remember_call(call1text); remember_call(call1str);
remember_call(call2text); remember_call(call2str);
return msg; return msg;
} }
@ -464,8 +469,9 @@ const char *sections[] = {
// i3 = 0, n3 = 3 or 4: ARRL Field Day // i3 = 0, n3 = 3 or 4: ARRL Field Day
// 0.3 WA9XYZ KA1ABC R 16A EMA 28 28 1 4 3 7 71 ARRL Field Day // 0.3 WA9XYZ KA1ABC R 16A EMA 28 28 1 4 3 7 71 ARRL Field Day
// 0.4 WA9XYZ KA1ABC R 32A EMA 28 28 1 4 3 7 71 ARRL Field Day // 0.4 WA9XYZ KA1ABC R 32A EMA 28 28 1 4 3 7 71 ARRL Field Day
std::string unpack_0_3(int a77[], int n3) std::string unpack_0_3(int a77[], int n3, std::string& call1str, std::string& call2str, std::string& locstr)
{ {
(void) locstr;
int i = 0; int i = 0;
int call1 = un(a77, i, 28); int call1 = un(a77, i, 28);
i += 28; i += 28;
@ -474,8 +480,11 @@ std::string unpack_0_3(int a77[], int n3)
int R = un(a77, i, 1); int R = un(a77, i, 1);
i += 1; i += 1;
int n_transmitters = un(a77, i, 4); int n_transmitters = un(a77, i, 4);
if (n3 == 4)
if (n3 == 4) {
n_transmitters += 16; n_transmitters += 16;
}
i += 4; i += 4;
int clss = un(a77, i, 3); // class int clss = un(a77, i, 3); // class
i += 3; i += 3;
@ -483,19 +492,24 @@ std::string unpack_0_3(int a77[], int n3)
i += 7; i += 7;
std::string msg; std::string msg;
msg += unpackcall(call1); call1str = trim(unpackcall(call1));
msg += call1str;
msg += " "; msg += " ";
msg += unpackcall(call2); call2str = trim(unpackcall(call2));
msg += call2str;
msg += " "; msg += " ";
if (R)
if (R) {
msg += "R "; msg += "R ";
}
{ {
char tmp[16]; char tmp[16];
sprintf(tmp, "%d%c ", n_transmitters + 1, clss + 'A'); sprintf(tmp, "%d%c ", n_transmitters + 1, clss + 'A');
msg += tmp; msg += tmp;
} }
if (section - 1 >= 0 && section - 1 < (int)(sizeof(sections) / sizeof(sections[0])))
{ if (section - 1 >= 0 && section - 1 < (int)(sizeof(sections) / sizeof(sections[0]))) {
msg += sections[section - 1]; msg += sections[section - 1];
} }
@ -508,7 +522,7 @@ std::string unpack_0_3(int a77[], int n3)
// CRC and LDPC have already been checked. // CRC and LDPC have already been checked.
// details from wsjt-x's packjt77.f90 and 77bit.txt. // details from wsjt-x's packjt77.f90 and 77bit.txt.
// //
std::string unpack(int a77[]) std::string unpack(int a77[], std::string& call1, std::string& call2, std::string& loc)
{ {
int i3 = un(a77, 74, 3); int i3 = un(a77, 74, 3);
int n3 = un(a77, 71, 3); int n3 = un(a77, 71, 3);
@ -516,31 +530,31 @@ std::string unpack(int a77[])
if (i3 == 0 && n3 == 0) if (i3 == 0 && n3 == 0)
{ {
// free text // free text
return unpack_0_0(a77); return unpack_0_0(a77, call1, call2, loc);
} }
if (i3 == 0 && (n3 == 3 || n3 == 4)) if (i3 == 0 && (n3 == 3 || n3 == 4))
{ {
// ARRL Field Day // ARRL Field Day
return unpack_0_3(a77, n3); return unpack_0_3(a77, n3, call1, call2, loc);
} }
if (i3 == 1 || i3 == 2) if (i3 == 1 || i3 == 2)
{ {
// ordinary message // ordinary message
return unpack_1(a77); return unpack_1(a77, call1, call2, loc);
} }
if (i3 == 3) if (i3 == 3)
{ {
// RTTY Round-Up // RTTY Round-Up
return unpack_3(a77); return unpack_3(a77, call1, call2, loc);
} }
if (i3 == 4) if (i3 == 4)
{ {
// call that doesn't fit in 28 bits // call that doesn't fit in 28 bits
return unpack_4(a77); return unpack_4(a77, call1, call2, loc);
} }
char tmp[64]; char tmp[64];

View File

@ -23,7 +23,7 @@
namespace FT8 { namespace FT8 {
std::string unpack(int a91[]); std::string unpack(int a91[], std::string& call1str, std::string& call2str, std::string& locstr);
} // namespace FT8 } // namespace FT8

View File

@ -41,9 +41,13 @@ int hcb(
const char *comment, const char *comment,
float snr, float snr,
int pass, int pass,
int correct_bits) int correct_bits
)
{ {
std::string msg = FT8::unpack(a91); std::string call1;
std::string call2;
std::string loc;
std::string msg = FT8::unpack(a91, call1, call2, loc);
cycle_mu.lock(); cycle_mu.lock();
@ -58,14 +62,18 @@ int hcb(
cycle_mu.unlock(); cycle_mu.unlock();
printf("%d %3d %3d %5.2f %6.1f %s, %s\n", printf("%d %3d %3d %5.2f %6.1f %s [%s:%s:%s] (%s)\n",
pass, pass,
(int)snr, (int)snr,
correct_bits, correct_bits,
off - 0.5, off - 0.5,
hz0, hz0,
msg.c_str(), msg.c_str(),
comment); call1.c_str(),
call2.c_str(),
loc.c_str(),
comment
);
fflush(stdout); fflush(stdout);
return 2; // 2 => new decode, do subtract. return 2; // 2 => new decode, do subtract.