1
0
mirror of https://github.com/f4exb/sdrangel.git synced 2025-05-31 22:32:24 -04:00

FT8 demod: unwanted dependencies removal and unpacking reorganization

This commit is contained in:
f4exb 2023-01-11 04:49:16 +01:00
parent 60debc5d83
commit 508da7da9c
8 changed files with 103 additions and 58 deletions

View File

@ -28,6 +28,7 @@ add_library(ft8 SHARED
) )
target_link_libraries(ft8 target_link_libraries(ft8
Boost::disable_autolinking
${FFTW3F_LIBRARIES} ${FFTW3F_LIBRARIES}
Qt::Core Qt::Core
sdrbase sdrbase

View File

@ -22,7 +22,7 @@
#ifndef FFT_H #ifndef FFT_H
#define FFT_H #define FFT_H
#include <mutex> #include <QMutex>
#include <vector> #include <vector>
#include <complex> #include <complex>
#include <fftw3.h> #include <fftw3.h>
@ -84,8 +84,8 @@ public:
private: private:
void fft_stats(); void fft_stats();
std::mutex plansmu; QMutex plansmu;
std::mutex plansmu2; QMutex plansmu2;
Plan *plans[1000]; Plan *plans[1000];
int nplans; int nplans;
// MEASURE=0, ESTIMATE=64, PATIENT=32 // MEASURE=0, ESTIMATE=64, PATIENT=32

View File

@ -22,7 +22,7 @@
#define ft8_h #define ft8_h
#include <thread> #include <thread>
#include <mutex> #include <QMutex>
#include "fft.h" #include "fft.h"
#include "export.h" #include "export.h"
@ -281,10 +281,10 @@ public:
int pass_; int pass_;
float down_hz_; float down_hz_;
std::mutex cb_mu_; QMutex cb_mu_;
CallbackInterface *cb_; // call-back interface CallbackInterface *cb_; // call-back interface
std::mutex hack_mu_; QMutex hack_mu_;
int hack_size_; int hack_size_;
int hack_off_; int hack_off_;
int hack_len_; int hack_len_;

View File

@ -19,10 +19,9 @@
// along with this program. If not, see <http://www.gnu.org/licenses/>. // // along with this program. If not, see <http://www.gnu.org/licenses/>. //
/////////////////////////////////////////////////////////////////////////////////// ///////////////////////////////////////////////////////////////////////////////////
#include <string> #include <string>
#include <mutex>
#include <map>
#include <string.h> #include <string.h>
#include <assert.h> #include <assert.h>
#include "unpack.h" #include "unpack.h"
#include "util.h" #include "util.h"
@ -32,9 +31,9 @@ namespace FT8 {
// turn bits into a 128-bit integer. // turn bits into a 128-bit integer.
// most significant bit first. // most significant bit first.
// //
__int128 un(int a77[], int start, int len) boost::multiprecision::int128_t Packing::un128(int a77[], int start, int len)
{ {
__int128 x = 0; boost::multiprecision::int128_t x = 0;
assert(len < (int)sizeof(x) * 8 && start >= 0 && start + len <= 77); assert(len < (int)sizeof(x) * 8 && start >= 0 && start + len <= 77);
for (int i = 0; i < len; i++) for (int i = 0; i < len; i++)
@ -46,11 +45,25 @@ __int128 un(int a77[], int start, int len)
return x; return x;
} }
std::mutex hashes_mu; //
std::map<int, std::string> hashes12; // turn bits into a 64-bit integer.
std::map<int, std::string> hashes22; // most significant bit first.
//
uint64_t Packing::un64(int a77[], int start, int len)
{
uint64_t x = 0;
int ihashcall(std::string call, int m) assert(len < (int)sizeof(x) * 8 && start >= 0 && start + len <= 63);
for (int i = 0; i < len; i++)
{
x <<= 1;
x |= a77[start + i];
}
return x;
}
int Packing::ihashcall(std::string call, int m)
{ {
while (call.size() > 0 && call[0] == ' ') while (call.size() > 0 && call[0] == ' ')
call.erase(0, 1); call.erase(0, 1);
@ -77,14 +90,10 @@ int ihashcall(std::string call, int m)
return x; return x;
} }
#define NGBASE (180 * 180)
#define NTOKENS 2063592
#define MAX22 4194304
// //
// turn 28 bits of packed call into the call // turn 28 bits of packed call into the call
// //
std::string unpackcall(int x) std::string Packing::unpackcall(int x)
{ {
char tmp[64]; char tmp[64];
@ -167,7 +176,7 @@ std::string unpackcall(int x)
// 77-bit version, from inspection of packjt77.f90. // 77-bit version, from inspection of packjt77.f90.
// ir is the bit after the two 28+1-bit callee/caller. // ir is the bit after the two 28+1-bit callee/caller.
// i3 is the message type, usually 1. // i3 is the message type, usually 1.
std::string unpackgrid(int ng, int ir, int i3) std::string Packing::unpackgrid(int ng, int ir, int i3)
{ {
(void) i3; (void) i3;
@ -229,7 +238,7 @@ std::string unpackgrid(int ng, int ir, int i3)
return tmp; return tmp;
} }
void remember_call(std::string call) void Packing::remember_call(std::string call)
{ {
hashes_mu.lock(); hashes_mu.lock();
if (call.size() >= 3 && call[0] != '<') if (call.size() >= 3 && call[0] != '<')
@ -248,12 +257,12 @@ 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& call1str, std::string& call2str, std::string& locstr) std::string Packing::unpack_4(int a77[], std::string& call1str, std::string& call2str, std::string& locstr)
{ {
(void) 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 = un64(a77, 12, 58);
char call[16]; char call[16];
for (int i = 0; i < 11; i++) for (int i = 0; i < 11; i++)
@ -266,11 +275,11 @@ std::string unpack_4(int a77[], std::string& call1str, std::string& call2str, st
remember_call(call); remember_call(call);
if (un(a77, 73, 1) == 1) { if (un64(a77, 73, 1) == 1) {
return std::string("CQ ") + call; return std::string("CQ ") + call;
} }
int x12 = un(a77, 0, 12); int x12 = un64(a77, 0, 12);
// 12-bit hash // 12-bit hash
hashes_mu.lock(); hashes_mu.lock();
std::string ocall; std::string ocall;
@ -283,7 +292,7 @@ std::string unpack_4(int a77[], std::string& call1str, std::string& call2str, st
hashes_mu.unlock(); hashes_mu.unlock();
int swap = un(a77, 70, 1); int swap = un64(a77, 70, 1);
std::string msg; std::string msg;
if (swap) if (swap)
@ -299,7 +308,7 @@ std::string unpack_4(int a77[], std::string& call1str, std::string& call2str, st
call2str = call; call2str = call;
} }
int suffix = un(a77, 71, 2); int suffix = un64(a77, 71, 2);
if (suffix == 1) { if (suffix == 1) {
msg += " RRR"; msg += " RRR";
@ -315,7 +324,7 @@ std::string unpack_4(int a77[], std::string& call1str, std::string& call2str, st
// //
// i3=1 // i3=1
// //
std::string unpack_1(int a77[], std::string& call1str, std::string& call2str, std::string& locstr) std::string Packing::unpack_1(int a77[], std::string& call1str, std::string& call2str, std::string& locstr)
{ {
// type 1: // type 1:
// 28 call1 // 28 call1
@ -327,19 +336,19 @@ std::string unpack_1(int a77[], std::string& call1str, std::string& call2str, st
// 3 type // 3 type
int i = 0; int i = 0;
int call1 = un(a77, i, 28); int call1 = un64(a77, i, 28);
i += 28; i += 28;
int rover1 = a77[i]; int rover1 = a77[i];
i += 1; i += 1;
int call2 = un(a77, i, 28); int call2 = un64(a77, i, 28);
i += 28; i += 28;
int rover2 = a77[i]; int rover2 = a77[i];
i += 1; i += 1;
int ir = a77[i]; int ir = a77[i];
i += 1; i += 1;
int grid = un(a77, i, 15); int grid = un64(a77, i, 15);
i += 15; i += 15;
int i3 = un(a77, i, 3); int i3 = un64(a77, i, 3);
i += 3; i += 3;
assert((i3 == 1 || i3 == 2) && i == 77); assert((i3 == 1 || i3 == 2) && i == 77);
@ -359,17 +368,17 @@ std::string unpack_1(int a77[], std::string& call1str, std::string& call2str, st
// 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& call1str, std::string& call2str, std::string& locstr) std::string Packing::unpack_0_0(int a77[], std::string& call1str, std::string& call2str, std::string& locstr)
{ {
(void) call2str; (void) call2str;
(void) locstr; (void) locstr;
// the 42 possible characters. // the 42 possible characters.
const char *cc = " 0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZ+-./?"; const char *cc = " 0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZ+-./?";
__int128 x = un(a77, 0, 71); boost::multiprecision::int128_t x = un128(a77, 0, 71);
std::string msg = "0123456789123"; std::string msg = "0123456789123";
for (int i = 0; i < 13; i++) for (int i = 0; i < 13; i++)
{ {
msg[13 - 1 - i] = cc[x % 42]; msg[13 - 1 - i] = cc[(int) (x % 42)];
x = x / 42; x = x / 42;
} }
call1str = msg; call1str = msg;
@ -377,7 +386,7 @@ std::string unpack_0_0(int a77[], std::string& call1str, std::string& call2str,
} }
// ARRL RTTY Round-Up states/provinces // ARRL RTTY Round-Up states/provinces
const char *ru_states[] = { const char *Packing::ru_states[] = {
"AL", "AK", "AZ", "AR", "CA", "CO", "CT", "DE", "FL", "GA", "AL", "AK", "AZ", "AR", "CA", "CO", "CT", "DE", "FL", "GA",
"HI", "ID", "IL", "IN", "IA", "KS", "KY", "LA", "ME", "MD", "HI", "ID", "IL", "IN", "IA", "KS", "KY", "LA", "ME", "MD",
"MA", "MI", "MN", "MS", "MO", "MT", "NE", "NV", "NH", "NJ", "MA", "MI", "MN", "MS", "MO", "MT", "NE", "NV", "NH", "NJ",
@ -394,21 +403,21 @@ 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& call1str, std::string& call2str, std::string& locstr) std::string Packing::unpack_3(int a77[], std::string& call1str, std::string& call2str, std::string& locstr)
{ {
(void) locstr; (void) locstr;
int i = 0; int i = 0;
int tu = a77[i]; int tu = a77[i];
i += 1; i += 1;
int call1 = un(a77, i, 28); int call1 = un64(a77, i, 28);
i += 28; i += 28;
int call2 = un(a77, i, 28); int call2 = un64(a77, i, 28);
i += 28; i += 28;
int r = a77[i]; int r = a77[i];
i += 1; i += 1;
int rst = un(a77, i, 3); int rst = un64(a77, i, 3);
i += 3; i += 3;
int serial = un(a77, i, 13); int serial = un64(a77, i, 13);
i += 13; i += 13;
call1str = trim(unpackcall(call1)); call1str = trim(unpackcall(call1));
@ -455,7 +464,7 @@ std::string unpack_3(int a77[], std::string& call1str, std::string& call2str, st
} }
// ARRL Field Day sections // ARRL Field Day sections
const char *sections[] = { const char *Packing::sections[] = {
"AB ", "AK ", "AL ", "AR ", "AZ ", "BC ", "CO ", "CT ", "DE ", "EB ", "AB ", "AK ", "AL ", "AR ", "AZ ", "BC ", "CO ", "CT ", "DE ", "EB ",
"EMA", "ENY", "EPA", "EWA", "GA ", "GTA", "IA ", "ID ", "IL ", "IN ", "EMA", "ENY", "EPA", "EWA", "GA ", "GTA", "IA ", "ID ", "IL ", "IN ",
"KS ", "KY ", "LA ", "LAX", "MAR", "MB ", "MDC", "ME ", "MI ", "MN ", "KS ", "KY ", "LA ", "LAX", "MAR", "MB ", "MDC", "ME ", "MI ", "MN ",
@ -469,26 +478,26 @@ 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& call1str, std::string& call2str, std::string& locstr) std::string Packing::unpack_0_3(int a77[], int n3, std::string& call1str, std::string& call2str, std::string& locstr)
{ {
(void) locstr; (void) locstr;
int i = 0; int i = 0;
int call1 = un(a77, i, 28); int call1 = un64(a77, i, 28);
i += 28; i += 28;
int call2 = un(a77, i, 28); int call2 = un64(a77, i, 28);
i += 28; i += 28;
int R = un(a77, i, 1); int R = un64(a77, i, 1);
i += 1; i += 1;
int n_transmitters = un(a77, i, 4); int n_transmitters = un64(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 = un64(a77, i, 3); // class
i += 3; i += 3;
int section = un(a77, i, 7); // ARRL section int section = un64(a77, i, 7); // ARRL section
i += 7; i += 7;
std::string msg; std::string msg;
@ -522,10 +531,10 @@ std::string unpack_0_3(int a77[], int n3, std::string& call1str, std::string& ca
// 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& call1, std::string& call2, std::string& loc) std::string Packing::unpack(int a77[], std::string& call1, std::string& call2, std::string& loc)
{ {
int i3 = un(a77, 74, 3); int i3 = un64(a77, 74, 3);
int n3 = un(a77, 71, 3); int n3 = un64(a77, 71, 3);
if (i3 == 0 && n3 == 0) if (i3 == 0 && n3 == 0)
{ {

View File

@ -22,10 +22,42 @@
#define unpack_h #define unpack_h
#include <string> #include <string>
#include <map>
#include <boost/multiprecision/cpp_int.hpp>
#include <QMutex>
namespace FT8 { namespace FT8 {
std::string unpack(int a91[], std::string& call1str, std::string& call2str, std::string& locstr); class Packing
{
public:
std::string unpack(int a91[], std::string& call1str, std::string& call2str, std::string& locstr);
private:
boost::multiprecision::int128_t un128(int a77[], int start, int len);
uint64_t un64(int a77[], int start, int len);
int ihashcall(std::string call, int m);
std::string unpackcall(int x);
std::string unpackgrid(int ng, int ir, int i3);
void remember_call(std::string call);
std::string unpack_4(int a77[], std::string& call1str, std::string& call2str, std::string& locstr);
std::string unpack_1(int a77[], std::string& call1str, std::string& call2str, std::string& locstr);
std::string unpack_0_0(int a77[], std::string& call1str, std::string& call2str, std::string& locstr);
std::string unpack_3(int a77[], std::string& call1str, std::string& call2str, std::string& locstr);
std::string unpack_0_3(int a77[], int n3, std::string& call1str, std::string& call2str, std::string& locstr);
QMutex hashes_mu;
std::map<int, std::string> hashes12;
std::map<int, std::string> hashes22;
static const int NGBASE = (180 * 180);
static const int NTOKENS = 2063592;
static const int MAX22 = 4194304;
static const char *ru_states[];
static const char *sections[];
};
} // namespace FT8 } // namespace FT8

View File

@ -18,12 +18,12 @@
// You should have received a copy of the GNU General Public License // // You should have received a copy of the GNU General Public License //
// along with this program. If not, see <http://www.gnu.org/licenses/>. // // along with this program. If not, see <http://www.gnu.org/licenses/>. //
/////////////////////////////////////////////////////////////////////////////////// ///////////////////////////////////////////////////////////////////////////////////
#include <sys/time.h>
#include <assert.h> #include <assert.h>
#include <math.h> #include <math.h>
#include <complex> #include <complex>
#include <string> #include <string>
#include <algorithm> #include <algorithm>
#include "util/timeutil.h" #include "util/timeutil.h"
#include "util.h" #include "util.h"
@ -32,9 +32,6 @@ namespace FT8 {
double now() double now()
{ {
return TimeUtil::nowus() / 1000000.0; return TimeUtil::nowus() / 1000000.0;
// struct timeval tv;
// gettimeofday(&tv, 0);
// return tv.tv_sec + tv.tv_usec / 1000000.0;
} }
// //

View File

@ -15,6 +15,9 @@
// along with this program. If not, see <http://www.gnu.org/licenses/>. // // along with this program. If not, see <http://www.gnu.org/licenses/>. //
/////////////////////////////////////////////////////////////////////////////////// ///////////////////////////////////////////////////////////////////////////////////
#ifndef SDRBASE_UTIL_TIMEUTIL_H_
#define SDRBASE_UTIL_TIMEUTIL_H_
#include <chrono> #include <chrono>
#include <stdint.h> #include <stdint.h>
@ -26,3 +29,5 @@ public:
static uint64_t nowms(); //!< returns the current epoch in milliseconds static uint64_t nowms(); //!< returns the current epoch in milliseconds
static uint64_t nowus(); //!< returns the current epoch in microseconds static uint64_t nowus(); //!< returns the current epoch in microseconds
}; };
#endif // SDRBASE_UTIL_TIMEUTIL_H_

View File

@ -53,6 +53,7 @@ public:
private: private:
QMutex cycle_mu; QMutex cycle_mu;
std::map<std::string, bool> cycle_already; std::map<std::string, bool> cycle_already;
FT8::Packing packing;
}; };
@ -69,7 +70,7 @@ int TestFT8Callback::hcb(
std::string call1; std::string call1;
std::string call2; std::string call2;
std::string loc; std::string loc;
std::string msg = FT8::unpack(a91, call1, call2, loc); std::string msg = packing.unpack(a91, call1, call2, loc);
cycle_mu.lock(); cycle_mu.lock();