1
0
mirror of https://github.com/JvanKatwijk/qt-dab.git synced 2025-10-06 00:02:40 +02:00

Ctrl-I key

This commit is contained in:
Jan
2025-10-02 18:53:42 +02:00
parent d859bf9192
commit 5eeff10916
8 changed files with 188 additions and 203 deletions

View File

@@ -531,7 +531,7 @@ the *qt-dab-6.9.pro* file contains (much) more configuration options
than the *CMakeLists.txt* file that is used when using cmake. than the *CMakeLists.txt* file that is used when using cmake.
Note that the scheme presented below is applied when building the AppImage Note that the scheme presented below is applied when building the AppImage
on Ubuntu 20, and was tested on the "bullseye" system on the RPI. on Ubuntu 22, and was tested on the "bullseye" system on the RPI.
For other distributions (or later Ubuntu versions), names of library For other distributions (or later Ubuntu versions), names of library
packages may be different. Note that in all cases, the development versions (i.e. the versions with the include (".h") files) are required. packages may be different. Note that in all cases, the development versions (i.e. the versions with the include (".h") files) are required.

View File

@@ -4,25 +4,12 @@ HERE="$(dirname "$(readlink -f "${0}")")"
rmmod dvb_usb_rtl28xxu || true rmmod dvb_usb_rtl28xxu || true
cat > /tmp/10-rtl-sdr.rules <<\EOF cat > ./10-rtl-sdr.rules <<\EOF
SUBSYSTEM=="usb", ATTRS{idVendor}=="0bda", ATTRS{idProduct}=="2832", MODE="0666", SYMLINK+="rtl_sdr" SUBSYSTEM=="usb", ATTRS{idVendor}=="0bda", ATTRS{idProduct}=="2832", MODE="0666", SYMLINK+="rtl_sdr"
EOF EOF
mv /tmp/10-rtl-sdr.rules /etc/udev/rules.d/10-rtl-sdr.rules mv ./10-rtl-sdr.rules /etc/udev/rules.d/10-rtl-sdr.rules
cat > /tmp/52-airspy.rules <<\EOF
ATTR{idVendor}=="1d50", ATTR{idProduct}=="60a1", SYMLINK+="airspy-%k", MODE="660", GROUP="plugdev"
EOF
mv /tmp/52-airspy.rules /etc/udev/rules.d/52-airspy.rules
cat > /tmp/66-mirics.rules <<\EOF
SUBSYSTEM=="usb",ENV{DEVTYPE}=="usb_device",ATTRS{idVendor}=="1df7",ATTRS{idProduct}=="2500",MODE:="0666"
SUBSYSTEM=="usb",ENV{DEVTYPE}=="usb_device",ATTRS{idVendor}=="1df7",ATTRS{idProduct}=="3010",MODE:="0666"
SUBSYSTEM=="usb",ENV{DEVTYPE}=="usb_device",ATTRS{idVendor}=="1df7",ATTRS{idProduct}=="3000",MODE:="0666"
EOF
mv /tmp/66-mirics.rules /etc/udev/rules.d/66-mirics.rules
udevadm control --reload-rules udevadm control --reload-rules
udevadm trigger --attr-match=subsystem=usb udevadm trigger --attr-match=subsystem=usb

View File

@@ -1283,6 +1283,78 @@ uint8_t fibDecoder::serviceType (const int index) {
return currentConfig -> SC_C_table [index]. TMid; return currentConfig -> SC_C_table [index]. TMid;
} }
int fibDecoder::getNrComps (const uint32_t SId) {
for (auto &SId_element : currentConfig -> SId_table)
if (SId_element. SId == SId)
return SId_element. comps. size ();
return 0;
}
// required for ETI generation
int fibDecoder::nrChannels () {
return currentConfig -> subChannel_table. size ();
}
//
// for primary services we return the index of the first
// component, the secondary services, the index of the
// component with the matching SCIds
//
int fibDecoder::getServiceComp (const QString &service) {
// first we check to see if the service is a primary one
for (auto &serv : theEnsemble. primaries) {
if (serv. name != service)
continue;
for (auto & SId_element: currentConfig -> SId_table) {
if (SId_element. SId == serv. SId)
return SId_element. comps [0];
}
}
for (auto &serv : theEnsemble. secondaries) {
if (serv. name != service)
continue;
return getServiceComp_SCIds (serv. SId, serv. SCIds);
}
return -1;
}
//
// Find the component with the indicated number
int fibDecoder::getServiceComp (const uint32_t SId,
const int compnr) {
for (auto &SId_element : currentConfig -> SId_table) {
if (SId_element. SId == SId) {
return SId_element. comps [compnr];
}
}
return -1;
}
// Find the component with the indicated SCIds
int fibDecoder::getServiceComp_SCIds (const uint32_t SId,
const int SCIds) {
// fprintf (stderr, "Looking for serviceComp %X %d\n", SId, SCIds);
for (auto &SId_element : currentConfig -> SId_table) {
if (SId_element. SId != SId)
continue;
for (int i = 0; i < (int) SId_element. comps. size (); i ++) {
int index = SId_element. comps [i];
if (currentConfig -> SCIdsOf (index) == SCIds)
return index;
}
}
return -1;
}
//
//
bool fibDecoder::isPrimary (const QString &s) {
for (auto &serv : theEnsemble. primaries) {
if (s == serv. name)
return true;
}
return false;
}
void fibDecoder::audioData (const int index, audiodata &ad) { void fibDecoder::audioData (const int index, audiodata &ad) {
fibConfig::serviceComp_C &comp = currentConfig -> SC_C_table [index]; fibConfig::serviceComp_C &comp = currentConfig -> SC_C_table [index];
for (auto &serv : theEnsemble. primaries) { for (auto &serv : theEnsemble. primaries) {
@@ -1344,68 +1416,12 @@ fibConfig::serviceComp_C &comp = currentConfig -> SC_C_table [index];
pd. defined = true; pd. defined = true;
} }
int fibDecoder::getNrComps (const uint32_t SId) { uint16_t fibDecoder::getAnnouncing (uint16_t SId) {
for (auto &SId_element : currentConfig -> SId_table) for (auto &serv : currentConfig -> SId_table)
if (SId_element. SId == SId) if (serv. SId == SId)
return SId_element. comps. size (); return serv. announcing;
return 0; return 0;
} }
//
// for primary services we return the index of the first
// component, the secondary services, the index of the
// component with the matching SCIds
//
int fibDecoder::getServiceComp (const QString &service) {
// first we check to see if the service is a primary one
for (auto &serv : theEnsemble. primaries) {
if (serv. name != service)
continue;
for (auto & SId_element: currentConfig -> SId_table) {
if (SId_element. SId == serv. SId)
return SId_element. comps [0];
}
}
for (auto &serv : theEnsemble. secondaries) {
if (serv. name != service)
continue;
return getServiceComp_SCIds (serv. SId, serv. SCIds);
}
return -1;
}
int fibDecoder::getServiceComp (const uint32_t SId,
const int compnr) {
for (auto &SId_element : currentConfig -> SId_table) {
if (SId_element. SId == SId) {
return SId_element. comps [compnr];
}
}
return -1;
}
int fibDecoder::getServiceComp_SCIds (const uint32_t SId,
const int SCIds) {
// fprintf (stderr, "Looking for serviceComp %X %d\n", SId, SCIds);
for (auto &SId_element : currentConfig -> SId_table) {
if (SId_element. SId != SId)
continue;
for (int i = 0; i < (int) SId_element. comps. size (); i ++) {
int index = SId_element. comps [i];
if (currentConfig -> SCIdsOf (index) == SCIds)
return index;
}
}
return -1;
}
bool fibDecoder::isPrimary (const QString &s) {
for (auto &serv : theEnsemble. primaries) {
if (s == serv. name)
return true;
}
return false;
}
std::vector<int> fibDecoder::getFrequency (const QString &s) { std::vector<int> fibDecoder::getFrequency (const QString &s) {
std::vector<int> res; std::vector<int> res;
@@ -1416,20 +1432,17 @@ std::vector<int> res;
return res; return res;
} }
// required for ETI generation
int fibDecoder::nrChannels () {
return currentConfig -> subChannel_table. size ();
}
// //
// needed for generating eti files // needed for generating eti files
void fibDecoder::getChannelInfo (channel_data *d, const int n) { void fibDecoder::getChannelInfo (channel_data *d, const int n) {
fibConfig::subChannel *selected = &(currentConfig -> subChannel_table [n]);
d -> in_use = true; d -> in_use = true;
d -> id = currentConfig -> subChannel_table [n]. subChId; d -> id = selected -> subChId;
d -> start_cu = currentConfig -> subChannel_table [n]. startAddr; d -> start_cu = selected -> startAddr;
d -> protlev = currentConfig -> subChannel_table [n]. protLevel; d -> protlev = selected -> protLevel;
d -> size = currentConfig -> subChannel_table [n]. Length; d -> size = selected -> Length;
d -> bitrate = currentConfig -> subChannel_table [n]. bitRate; d -> bitrate = selected -> bitRate;
d -> uepFlag = currentConfig -> subChannel_table [n]. shortForm; d -> uepFlag = selected -> shortForm;
} }
int32_t fibDecoder::getCIFcount () { int32_t fibDecoder::getCIFcount () {
@@ -1456,13 +1469,6 @@ void fibDecoder::handleAnnouncement (uint16_t SId, uint16_t flags,
} }
} }
uint16_t fibDecoder::getAnnouncing (uint16_t SId) {
for (auto &serv : currentConfig -> SId_table)
if (serv. SId == SId)
return serv. announcing;
return 0;
}
int fibDecoder::freeSpace () { int fibDecoder::freeSpace () {
return currentConfig -> freeSpace (); return currentConfig -> freeSpace ();
} }

View File

@@ -44,25 +44,28 @@ public:
void connectChannel (); void connectChannel ();
void disconnectChannel (); void disconnectChannel ();
bool syncReached (); bool syncReached ();
//
uint16_t getAnnouncing (uint16_t); // The real interface
uint32_t getSId (int); uint32_t getSId (int);
uint8_t serviceType (int); uint8_t serviceType (int);
int getNrComps (const uint32_t);
//
// not well chosen name, "subChannels" are meant
int nrChannels ();
int getServiceComp (const QString &); int getServiceComp (const QString &);
int getServiceComp (const uint32_t, const int); int getServiceComp (const uint32_t, const int);
int getServiceComp_SCIds (const uint32_t, const int); int getServiceComp_SCIds (const uint32_t, const int);
bool isPrimary (const QString &); bool isPrimary (const QString &);
void audioData (const int, audiodata &); void audioData (const int, audiodata &);
void packetData (const int, packetdata &); void packetData (const int, packetdata &);
int getNrComps (const uint32_t); uint16_t getAnnouncing (uint16_t);
int nrChannels ();
std::vector<int> getFrequency (const QString &); std::vector<int> getFrequency (const QString &);
void getChannelInfo (channel_data *, const int); void getChannelInfo (channel_data *, const int);
int32_t getCIFcount (); int32_t getCIFcount ();
void getCIFcount (int16_t &, int16_t &); void getCIFcount (int16_t &, int16_t &);
uint32_t julianDate (); uint32_t julianDate ();
QList<contentType> contentPrint ();
int freeSpace (); int freeSpace ();
QList<contentType> contentPrint ();
protected: protected:
void processFIB (uint8_t *, uint16_t); void processFIB (uint8_t *, uint16_t);

View File

@@ -43,8 +43,10 @@
#define ALPHA 0.005f #define ALPHA 0.005f
static inline static inline
Complex normalize (const Complex &V) { Complex normalize (const Complex &V) {
DABFLOAT Length = jan_abs (V); DABFLOAT length = jan_abs (V);
return Length == 0.0f ? Complex (0.0, 0.0) : V / (DABFLOAT)Length; if (length < 0.001)
return Complex (0, 0);
return Complex (V) / length;
} }
ofdmDecoder::ofdmDecoder (RadioInterface *mr, ofdmDecoder::ofdmDecoder (RadioInterface *mr,
@@ -103,7 +105,7 @@ void ofdmDecoder::reset () {
angleVector [i] = M_PI_4; angleVector [i] = M_PI_4;
} }
meanValue = 1.0f; meanValue = 1.0f;
avgBit = 1.0f; avgBit = 10.0f;
} }
// //
void ofdmDecoder::processBlock_0 (std::vector <Complex> buffer) { void ofdmDecoder::processBlock_0 (std::vector <Complex> buffer) {
@@ -113,8 +115,6 @@ void ofdmDecoder::processBlock_0 (std::vector <Complex> buffer) {
// //
memcpy (phaseReference. data (), buffer. data (), memcpy (phaseReference. data (), buffer. data (),
T_u * sizeof (Complex)); T_u * sizeof (Complex));
Complex temp = Complex (0, 0);
} }
// //
// Just interested. In the ideal case the constellation of the // Just interested. In the ideal case the constellation of the
@@ -184,7 +184,7 @@ void limit_symmetrically (DABFLOAT &v, DABFLOAT limit) {
// //
// Decoder 4 is an interpretation of the so-called "Optimal 3" // Decoder 4 is an interpretation of the so-called "Optimal 3"
// version in the aforementioned paper. // version in the aforementioned paper.
// It is still experimental!!! // It does not work well
static inline static inline
Complex w (DABFLOAT kn) { Complex w (DABFLOAT kn) {
@@ -203,14 +203,34 @@ DABFLOAT IO (DABFLOAT x) {
return std::cyl_bessel_i (0.0f, x); return std::cyl_bessel_i (0.0f, x);
} }
Complex optimum3 (Complex S, Complex prevS, DABFLOAT sigmaSQ) {
Complex rr = Complex (0, 1) * conj (S);
S = S * conj (rr);
prevS = prevS * conj (rr);
DABFLOAT P1 = makeA (1, S, prevS) / sigmaSQ;
DABFLOAT P7 = makeA (7, S, prevS) / sigmaSQ;
DABFLOAT P3 = makeA (3, S, prevS) / sigmaSQ;
DABFLOAT P5 = makeA (5, S, prevS) / sigmaSQ;
DABFLOAT IO_P1 = IO (P1);
DABFLOAT IO_P7 = IO (P7);
DABFLOAT IO_P3 = IO (P3);
DABFLOAT IO_P5 = IO (P5);
DABFLOAT b1 = log ((IO_P1 + IO_P7) / (IO_P3 + IO_P5));
DABFLOAT b2 = log ((IO_P1 + IO_P3) / (IO_P5 + IO_P7));
return Complex (b1, b2);
}
void ofdmDecoder::decode (std::vector <Complex> &buffer, void ofdmDecoder::decode (std::vector <Complex> &buffer,
int32_t blkno, int32_t blkno,
std::vector<int16_t> &softbits, std::vector<int16_t> &softbits,
DABFLOAT snr) { DABFLOAT snr) {
DABFLOAT sum = 0; DABFLOAT sum = 0;
DABFLOAT bitSum = 0; static DABFLOAT bitSum = 10;
float oldSum = bitSum;
bitSum = 0;
memcpy (fft_buffer. data (), &((buffer. data ()) [T_g]), memcpy (fft_buffer. data (), &((buffer. data ()) [T_g]),
T_u * sizeof (Complex)); T_u * sizeof (Complex));
// first step: do the FFT // first step: do the FFT
@@ -224,11 +244,11 @@ DABFLOAT bitSum = 0;
int16_t index = myMapper. mapIn (i); int16_t index = myMapper. mapIn (i);
if (index < 0) if (index < 0)
index += T_u; index += T_u;
Complex fftBin = fft_buffer [index] * Complex current = fft_buffer [index];
normalize (conj (phaseReference [index])); Complex prevS = phaseReference [index];
Complex fftBin = current * normalize (conj (prevS));
conjVector [index] = fftBin; conjVector [index] = fftBin;
DABFLOAT binAbsLevel = jan_abs (fftBin); DABFLOAT binAbsLevel = jan_abs (fftBin);
Complex prevS = phaseReference [index];
// //
// updates // updates
@@ -292,44 +312,30 @@ DABFLOAT bitSum = 0;
sum += jan_abs (R1); sum += jan_abs (R1);
} }
else else {
if (this -> decoder == DECODER_3) { // decoder 3
softbits [i] = - real (fftBin) / binAbsLevel * softbits [i] = - real (fftBin) / binAbsLevel *
1.0 * MAX_VITERBI; 1.0 * MAX_VITERBI;
softbits [carriers + i] softbits [carriers + i]
= - imag (fftBin) / binAbsLevel * = - imag (fftBin) / binAbsLevel *
1.0 * MAX_VITERBI; 1.0 * MAX_VITERBI;
} }
else { // experimental decoder 4 // else // experimental decoder 3
DABFLOAT P1 = makeA (1, fftBin, prevS) / // Interesting experiment, but does not work properly
sigmaSQ_Vector [index]; // if (this -> decoder == DECODER_3) { // decoder 3
DABFLOAT P7 = makeA (7, fftBin, prevS) / // Complex res = optimum3 (current, prevS,
sigmaSQ_Vector [index]; // sigmaSQ_Vector [index]);
DABFLOAT P3 = makeA (3, fftBin, prevS) / // bitSum += abs (res);
sigmaSQ_Vector [index]; // DABFLOAT scaler = 64.0 / (oldSum / carriers) ;
DABFLOAT P5 = makeA (5, fftBin, prevS) / // DABFLOAT xx1 = - real (res) / scaler;
sigmaSQ_Vector [index]; // DABFLOAT xx2 = - imag (res) / scaler;
// limit_symmetrically (xx1, MAX_VITERBI);
DABFLOAT IO_P1 = IO (P1); // limit_symmetrically (xx2, MAX_VITERBI);
DABFLOAT IO_P7 = IO (P7); // softbits [i] = (int16_t)xx1;
DABFLOAT IO_P3 = IO (P3); // softbits [carriers + i] = (int16_t)xx2;
DABFLOAT IO_P5 = IO (P5); // }
DABFLOAT b1 = log ((IO_P1 + IO_P7) / (IO_P3 + IO_P5));
DABFLOAT b2 = log ((IO_P1 + IO_P3) / (IO_P5 + IO_P7));
bitSum += (abs (b1) + abs (b2)) / 2;
DABFLOAT scaler = 40 / avgBit;
int s1 = -real (fftBin) < 0 ? -1 : 1;
int s2 = -imag (fftBin) < 0 ? -1 : 1;
DABFLOAT xx1 = s1 * abs (b1) * scaler;
DABFLOAT xx2 = s2 * abs (b2) * scaler;
limit_symmetrically (xx1, MAX_VITERBI);
limit_symmetrically (xx2, MAX_VITERBI);
softbits [i] = (int16_t)xx1;
softbits [carriers + i] = (int16_t)xx2;
}
} }
avgBit = compute_avg (avgBit, bitSum / carriers, 0.1); avgBit = compute_avg (avgBit, bitSum / carriers, 0.1);
meanValue = compute_avg (meanValue, sum /carriers, 0.1); meanValue = compute_avg (meanValue, sum /carriers, 0.1);

View File

@@ -153,7 +153,7 @@ auto *buffer = dynVec (std::complex<float>, nrSamples);
dcReal = compute_avg (dcReal, real (v), Alpha); dcReal = compute_avg (dcReal, real (v), Alpha);
dcImag = compute_avg (dcImag, imag (v), Alpha); dcImag = compute_avg (dcImag, imag (v), Alpha);
v = std::complex<float> (real (v) - dcReal, imag (v) - dcImag); v = std::complex<float> (real (v) - dcReal, imag (v) - dcImag);
v = theEqualizer. equalize (v); // v = theEqualizer. equalize (v);
DABFLOAT real_V = abs (real (v)); DABFLOAT real_V = abs (real (v));
DABFLOAT imag_V = abs (imag (v)); DABFLOAT imag_V = abs (imag (v));
IQ_Real = compute_avg (IQ_Real, real_V, Alpha); IQ_Real = compute_avg (IQ_Real, real_V, Alpha);
@@ -164,6 +164,7 @@ auto *buffer = dynVec (std::complex<float>, nrSamples);
((IQ_Real + IQ_Imag) / 2)); ((IQ_Real + IQ_Imag) / 2));
teller = 0; teller = 0;
} }
// v = std::complex<float> (IQ_Real, IQ_Imag);
} }
// first: adjust frequency. We need Hz accuracy // first: adjust frequency. We need Hz accuracy

View File

@@ -1922,8 +1922,10 @@ bool RadioInterface::eventFilter (QObject *obj, QEvent *event) {
return true; return true;
} }
else // handling function keys else // handling function keys
if (handle_keyEvent (keyEvent -> key ())) if (QApplication::keyboardModifiers ().
return true; testFlag (Qt::ControlModifier)) {
return handle_keyEvent (keyEvent -> key ());
}
} }
// An option is to click - right hand mouse button - on a // An option is to click - right hand mouse button - on a
// service in the scanlist in order to add it to the // service in the scanlist in order to add it to the
@@ -4779,29 +4781,12 @@ void RadioInterface::focusInEvent (QFocusEvent *evt) {
// //
// This function is called whenever a key is touched // This function is called whenever a key is touched
// that is not the return key // that is not the return key
// as it turns out, our "beloved" windows does not let
// the Qt user catch the functon keys, we settle for Ctrl Ii
bool RadioInterface::handle_keyEvent (int theKey) { bool RadioInterface::handle_keyEvent (int theKey) {
switch (theKey) { if (theKey != Qt::Key_I)
case Qt::Key_F1: return false;
theEnsembleHandler -> activateWindow ();
theEnsembleHandler -> setFocus ();
return true;
case Qt::Key_F2:
configHandler_p -> activateWindow ();
configHandler_p -> setFocus ();
return true;
case Qt::Key_F3:
techWindow_p -> activateWindow ();
techWindow_p -> setFocus ();
return true;
case Qt::Key_F4:
this -> activateWindow ();
this -> setFocus ();
return true;
case Qt::Key_F6:
if (theEnsembleHandler -> hasFocus ()) { if (theEnsembleHandler -> hasFocus ()) {
this -> activateWindow (); this -> activateWindow ();
this -> setFocus (); this -> setFocus ();
@@ -4825,9 +4810,6 @@ bool RadioInterface::handle_keyEvent (int theKey) {
theEnsembleHandler -> setFocus (); theEnsembleHandler -> setFocus ();
return true; return true;
} }
else
return false; return false;
default:
return false;
}
} }