diff --git a/CMakeLists.txt b/CMakeLists.txt index d9f50f6..4bafa56 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -295,6 +295,12 @@ set (wsjt_FSRCS lib/timer_impl.f90 lib/timer_module.f90 lib/wavhdr.f90 + lib/js8b_module.f90 + lib/js8b_decode.f90 + lib/js8c_module.f90 + lib/js8c_decode.f90 + lib/js8d_module.f90 + lib/js8d_decode.f90 # remaining non-module sources lib/addit.f90 @@ -311,6 +317,7 @@ set (wsjt_FSRCS lib/azdist.f90 lib/badmsg.f90 lib/ft8/baseline.f90 + # lib/js8/baselinejs8.f90 lib/bpdecode40.f90 lib/bpdecode144.f90 lib/ft8/bpdecode174.f90 @@ -350,7 +357,6 @@ set (wsjt_FSRCS lib/ft8/extractmessage174.f90 lib/fano232.f90 lib/fast9.f90 - lib/fast_decode.f90 lib/fchisq.f90 lib/fchisq0.f90 lib/fchisq65.f90 @@ -361,7 +367,6 @@ set (wsjt_FSRCS lib/filbig.f90 lib/ft8/filt8.f90 lib/fitcal.f90 - lib/fix_contest_msg.f90 lib/flat1.f90 lib/flat1a.f90 lib/flat1b.f90 @@ -378,19 +383,16 @@ set (wsjt_FSRCS lib/freqcal.f90 lib/ft8/ft8apset.f90 lib/ft8/ft8b.f90 + # lib/js8/js8params.f90 + # lib/js8/js8b.f90 lib/ft8/ft8code.f90 lib/ft8/ft8_downsample.f90 + # lib/js8/js8_downsample.f90 lib/ft8/ft8sim.f90 - lib/gen4.f90 - lib/gen65.f90 - lib/gen9.f90 - lib/geniscat.f90 lib/ft8/genft8.f90 - lib/genmsk144.f90 - lib/genmsk40.f90 - lib/genqra64.f90 + lib/js8/genjs8.f90 lib/ft8/genft8refsig.f90 - lib/genwspr.f90 + # lib/js8/genjs8refsig.f90 lib/geodist.f90 lib/getlags.f90 lib/getmet4.f90 @@ -401,7 +403,6 @@ set (wsjt_FSRCS lib/ft8/h1.f90 lib/hash.f90 lib/hint65.f90 - lib/hspec.f90 lib/indexx.f90 lib/init_random_seed.f90 lib/interleave4.f90 @@ -414,6 +415,9 @@ set (wsjt_FSRCS lib/jtmsg.f90 lib/ldpcsim144.f90 lib/ft8/ldpcsim174.f90 + lib/js8/ldpcsim174js8b.f90 + lib/js8/ldpcsim174js8c.f90 + lib/js8/ldpcsim174js8d.f90 lib/ldpcsim40.f90 lib/libration.f90 lib/lorentzian.f90 @@ -423,20 +427,6 @@ set (wsjt_FSRCS lib/moondopjpl.f90 lib/morse.f90 lib/move.f90 - lib/msk144d2.f90 - lib/msk40decodeframe.f90 - lib/msk144decodeframe.f90 - lib/msk144sd.f90 - lib/msk40spd.f90 - lib/msk144spd.f90 - lib/msk40sync.f90 - lib/msk144sync.f90 - lib/msk40_freq_search.f90 - lib/msk144_freq_search.f90 - lib/mskrtd.f90 - lib/msk144signalquality.f90 - lib/msk144sim.f90 - lib/mskrtd.f90 lib/ft8/osd174.f90 lib/pctile.f90 lib/peakdt9.f90 @@ -466,6 +456,7 @@ set (wsjt_FSRCS lib/stdmsg.f90 lib/subtract65.f90 lib/ft8/subtractft8.f90 + # lib/js8/subtractjs8.f90 lib/sun.f90 lib/symspec.f90 lib/symspec2.f90 @@ -474,7 +465,9 @@ set (wsjt_FSRCS lib/sync64.f90 lib/sync65.f90 lib/ft8/sync8.f90 + # lib/js8/syncjs8.f90 lib/ft8/sync8d.f90 + # lib/js8/syncjs8d.f90 lib/sync9.f90 lib/sync9f.f90 lib/sync9w.f90 @@ -502,46 +495,24 @@ set (wsjt_FSRCS # temporary workaround for a gfortran v7.3 ICE on Fedora 27 64-bit set_source_files_properties (lib/slasubs.f PROPERTIES COMPILE_FLAGS -O2) -set (ka9q_CSRCS - lib/ftrsd/decode_rs.c - lib/ftrsd/encode_rs.c - lib/ftrsd/init_rs.c - ) -set_source_files_properties (${ka9q_CSRCS} PROPERTIES COMPILE_FLAGS -Wno-sign-compare) - -set (qra_CSRCS - lib/qra/qra64/qra64.c - lib/qra/qra64/qra64_subs.c - lib/qra/qracodes/npfwht.c - lib/qra/qracodes/pdmath.c - lib/qra/qracodes/qra12_63_64_irr_b.c - lib/qra/qracodes/qra13_64_64_irr_e.c - lib/qra/qracodes/qracodes.c - lib/qra/qracodes/normrnd.c - ) - set (sqlite3_CSRCS vendor/sqlite3/sqlite3.c ) set (wsjt_CSRCS - ${ka9q_CSRCS} - lib/ftrsd/ftrsdap.c lib/sgran.c lib/golay24_table.c lib/gran.c lib/igray.c lib/init_random_seed.c lib/ldpc32_table.c - lib/wsprd/nhash.c + lib/nhash.c lib/tab.c lib/tmoonsub.c lib/usleep.c lib/vit213.c lib/wisdom.c - lib/wrapkarn.c ${ldpc_CSRCS} - ${qra_CSRCS} ) set (wsjt_qt_UISRCS @@ -1026,6 +997,15 @@ target_link_libraries (wsjt_qtmm Qt5::Multimedia) add_executable (ldpcsim174 lib/ft8/ldpcsim174.f90 wsjtx.rc) target_link_libraries (ldpcsim174 wsjt_fort wsjt_cxx) +add_executable (ldpcsim174js8b lib/js8/ldpcsim174js8b.f90 wsjtx.rc) +target_link_libraries (ldpcsim174js8b wsjt_fort wsjt_cxx) + +add_executable (ldpcsim174js8c lib/js8/ldpcsim174js8c.f90 wsjtx.rc) +target_link_libraries (ldpcsim174js8c wsjt_fort wsjt_cxx) + +add_executable (ldpcsim174js8d lib/js8/ldpcsim174js8d.f90 wsjtx.rc) +target_link_libraries (ldpcsim174js8d wsjt_fort wsjt_cxx) + add_executable (js8 ${js8_FSRCS} ${js8_CXXSRCS} wsjtx.rc) if (${OPENMP_FOUND} OR APPLE) if (APPLE) diff --git a/Configuration.ui b/Configuration.ui index 58b5caf..9cc216d 100644 --- a/Configuration.ui +++ b/Configuration.ui @@ -890,56 +890,43 @@ text message. - - - - - - - Idle Timeout - - - - - - - - Disable automatic transmissions after: - - - tx_watchdog_spin_box - - - - - - - <html><head/><body><p>Number of minutes before unattended heartbeat transmissions are aborted.</p></body></html> - - - Disabled - - - minutes of inactivity - - - - - - 0 - - - 1440 - - - 1 - - - 60 - - - - + + + + Idle timeout - disable autoreply after: + + + tx_watchdog_spin_box + + + + + + + <html><head/><body><p>Number of minutes before unattended heartbeat transmissions are aborted.</p></body></html> + + + Disabled + + + minutes of inactivity + + + + + + 0 + + + 1440 + + + 1 + + + 60 + + @@ -4383,12 +4370,12 @@ soundcard changes - - + + + - diff --git a/Modulator.cpp b/Modulator.cpp index b80acc8..47e795c 100644 --- a/Modulator.cpp +++ b/Modulator.cpp @@ -71,7 +71,19 @@ void Modulator::start (unsigned symbolsLength, double framesPerSymbol, m_toneSpacing = toneSpacing; m_bFastMode=fastMode; m_TRperiod=TRperiod; - unsigned delay_ms = 1920 == m_nsps && 15 == m_period ? 500 : 250; // 1000; + unsigned delay_ms = 0; + if(m_TRperiod == JS8A_TX_SECONDS){ + delay_ms = JS8A_START_DELAY_MS; + } + else if(m_TRperiod == JS8B_TX_SECONDS){ + delay_ms = JS8B_START_DELAY_MS; + } + else if(m_TRperiod == JS8C_TX_SECONDS){ + delay_ms = JS8C_START_DELAY_MS; + } + else if(m_TRperiod == JS8D_TX_SECONDS){ + delay_ms = JS8D_START_DELAY_MS; + } // noise generator parameters if (m_addNoise) { diff --git a/Versions.cmake b/Versions.cmake index d828414..ed59e29 100644 --- a/Versions.cmake +++ b/Versions.cmake @@ -1,6 +1,6 @@ # Version number components -set (WSJTX_VERSION_MAJOR 1) -set (WSJTX_VERSION_MINOR 2) +set (WSJTX_VERSION_MAJOR 2) +set (WSJTX_VERSION_MINOR 0) set (WSJTX_VERSION_PATCH 0) set (WSJTX_RC 0) # release candidate number, comment out or zero for development versions set (WSJTX_VERSION_IS_RELEASE 0) # set to 1 for final release build diff --git a/bsj.mod b/bsj.mod new file mode 100644 index 0000000..aecd818 Binary files /dev/null and b/bsj.mod differ diff --git a/commons.h b/commons.h index 1dd17e8..759816a 100644 --- a/commons.h +++ b/commons.h @@ -7,19 +7,31 @@ #define RX_SAMPLE_RATE 12000 #define JS8_NUM_SYMBOLS 79 +#define JS8_ENABLE_JS8B 1 +#define JS8_ENABLE_JS8C 1 +#define JS8_ENABLE_JS8D 0 -#ifndef JS8_80HZ -#define JS8_80HZ 0 -#endif +#define JS8A_SYMBOL_SAMPLES 1920 +#define JS8A_TX_SECONDS 15 +#define JS8A_START_DELAY_MS 500 -#if JS8_80HZ -#define JS8_SYMBOL_SAMPLES 1200 // 480 // 600 // 1200 // 1920 -#define JS8_TX_SECONDS 10 // 5 // 6 // 10 // 15 -#define JS8_SYMBOL_STOP 32 // 12 // 16 // 32 // 50 // ??? no idea why this works... +#define JS8B_SYMBOL_SAMPLES 1200 +#define JS8B_TX_SECONDS 10 +#define JS8B_START_DELAY_MS 200 + +#define JS8C_SYMBOL_SAMPLES 600 +#define JS8C_TX_SECONDS 6 +#define JS8C_START_DELAY_MS 100 + +#define JS8D_IS_ULTRA 1 +#if JS8D_IS_ULTRA +#define JS8D_SYMBOL_SAMPLES 384 +#define JS8D_TX_SECONDS 4 +#define JS8D_START_DELAY_MS 100 #else -#define JS8_SYMBOL_SAMPLES 1920 -#define JS8_TX_SECONDS 15 -#define JS8_SYMBOL_STOP 50 +#define JS8D_SYMBOL_SAMPLES 4000 +#define JS8D_TX_SECONDS 30 +#define JS8D_START_DELAY_MS 100 #endif #ifndef TEST_FOX_WAVE_GEN diff --git a/decodedtext.cpp b/decodedtext.cpp index 6e183bf..9723ce1 100644 --- a/decodedtext.cpp +++ b/decodedtext.cpp @@ -15,7 +15,7 @@ namespace QRegularExpression words_re {R"(^(?:(?(?:CQ|DE|QRZ)(?:\s?DX|\s(?:[A-Z]{2}|\d{3}))|[A-Z0-9/]+)\s)(?:(?[A-Z0-9/]+)(?:\s(?[-+A-Z0-9]+)(?:\s(?(?:OOO|(?!RR73)[A-R]{2}[0-9]{2})))?)?)?)"}; } -DecodedText::DecodedText (QString const& the_string, bool contest_mode, QString const& my_grid) +DecodedText::DecodedText (QString const& the_string, bool contest_mode, QString const& my_grid, int submode) : string_ {the_string.left (the_string.indexOf (QChar::Nbsp))} // discard appended info , padding_ {string_.indexOf (" ") > 4 ? 2 : 0} // allow for seconds , contest_mode_ {contest_mode} @@ -25,6 +25,7 @@ DecodedText::DecodedText (QString const& the_string, bool contest_mode, QString , isHeartbeat_(false) , isAlt_(false) , bits_{0} + , submode_{submode} { if(message_.length() >= 1) { message_ = message_.left (21).remove (QRegularExpression {"[<>]"}); @@ -69,12 +70,13 @@ DecodedText::DecodedText (QString const& the_string, bool contest_mode, QString tryUnpack(); } -DecodedText::DecodedText (QString const& js8callmessage, int bits): +DecodedText::DecodedText (QString const& js8callmessage, int bits, int submode): frameType_(Varicode::FrameUnknown), message_(js8callmessage), isHeartbeat_(false), isAlt_(false), - bits_(bits) + bits_(bits), + submode_(submode) { is_standard_ = QRegularExpression("^(CQ|DE|QRZ)\\s").match(message_).hasMatch(); @@ -89,9 +91,13 @@ bool DecodedText::tryUnpack(){ bool unpacked = false; if(!unpacked){ - unpacked = tryUnpackData(); + unpacked = tryUnpackFastData(); } + if(!unpacked){ + unpacked = tryUnpackData(); + } + if(!unpacked){ unpacked = tryUnpackHeartbeat(); } @@ -115,6 +121,10 @@ bool DecodedText::tryUnpackHeartbeat(){ return false; } + if((bits_ & Varicode::JS8CallData) == Varicode::JS8CallData){ + return false; + } + bool isAlt = false; quint8 type = Varicode::FrameUnknown; quint8 bits3 = 0; @@ -159,6 +169,10 @@ bool DecodedText::tryUnpackCompound(){ return false; } + if((bits_ & Varicode::JS8CallData) == Varicode::JS8CallData){ + return false; + } + QStringList cmp; if(!parts.at(0).isEmpty()){ cmp.append(parts.at(0)); @@ -188,6 +202,10 @@ bool DecodedText::tryUnpackDirected(){ return false; } + if((bits_ & Varicode::JS8CallData) == Varicode::JS8CallData){ + return false; + } + quint8 type = Varicode::FrameUnknown; QStringList parts = Varicode::unpackDirectedMessage(m, &type); @@ -218,7 +236,11 @@ bool DecodedText::tryUnpackData(){ // data frames calls will always be 12+ chars and contain no spaces. if(m.length() < 12 || m.contains(' ')){ - return false; + return false; + } + + if((bits_ & Varicode::JS8CallData) == Varicode::JS8CallData){ + return false; } QString data = Varicode::unpackDataMessage(m); @@ -232,6 +254,33 @@ bool DecodedText::tryUnpackData(){ return true; } +bool DecodedText::tryUnpackFastData(){ + QString m = message().trimmed(); + + // data frames calls will always be 12+ chars and contain no spaces. + if(m.length() < 12 || m.contains(' ')){ + return false; + } + + if((bits_ & Varicode::JS8CallData) != Varicode::JS8CallData){ + return false; + } + + if(submode_ != Varicode::JS8CallFast && submode_ != Varicode::JS8CallTurbo && submode_ != Varicode::JS8CallUltra){ + return false; + } + + QString data = Varicode::unpackFastDataMessage(m); + + if(data.isEmpty()){ + return false; + } + + message_ = data; + frameType_ = Varicode::FrameData; + return true; +} + QStringList DecodedText::messageWords () const { if (is_standard_) diff --git a/decodedtext.h b/decodedtext.h index 896eb2c..7872ccb 100644 --- a/decodedtext.h +++ b/decodedtext.h @@ -30,14 +30,15 @@ class DecodedText { public: - explicit DecodedText (QString const& message, bool, QString const& my_grid); - explicit DecodedText (QString const& js8callmessage, int bits); + explicit DecodedText (QString const& message, bool, QString const& my_grid, int submode); + explicit DecodedText (QString const& js8callmessage, int bits, int submode); bool tryUnpack(); bool tryUnpackHeartbeat(); bool tryUnpackCompound(); bool tryUnpackDirected(); bool tryUnpackData(); + bool tryUnpackFastData(); quint8 frameType() const { return frameType_; } @@ -110,6 +111,7 @@ private: QString message_; bool is_standard_; int bits_; + int submode_; }; #endif // DECODEDTEXT_H diff --git a/js8.mod b/js8.mod new file mode 100644 index 0000000..71d9ef2 Binary files /dev/null and b/js8.mod differ diff --git a/js8a.mod b/js8a.mod new file mode 100644 index 0000000..76b704c Binary files /dev/null and b/js8a.mod differ diff --git a/js8params.mod b/js8params.mod new file mode 100644 index 0000000..ded98cc Binary files /dev/null and b/js8params.mod differ diff --git a/keyeater.cpp b/keyeater.cpp index 55bc57e..8f45f61 100644 --- a/keyeater.cpp +++ b/keyeater.cpp @@ -1,5 +1,20 @@ #include "keyeater.h" + +bool KeyPressEater::eventFilter(QObject *obj, QEvent *event){ + if (event->type() == QEvent::KeyPress) { + QKeyEvent *keyEvent = static_cast(event); + bool processed = false; + emit this->keyPressed(obj, keyEvent, &processed); + if(processed){ + return true; + } + } + + // standard event processing + return QObject::eventFilter(obj, event); +} + bool EscapeKeyPressEater::eventFilter(QObject *obj, QEvent *event){ if (event->type() == QEvent::KeyPress) { QKeyEvent *keyEvent = static_cast(event); diff --git a/keyeater.h b/keyeater.h index e51c53d..abb011e 100644 --- a/keyeater.h +++ b/keyeater.h @@ -5,6 +5,20 @@ #include #include +class KeyPressEater : public QObject +{ + Q_OBJECT +public: + KeyPressEater(){} + virtual ~KeyPressEater(){} + +protected: + bool eventFilter(QObject *obj, QEvent *event); + +public: + Q_SIGNAL void keyPressed(QObject *obj, QKeyEvent *evt, bool *pProcessed); +}; + class EscapeKeyPressEater : public QObject { Q_OBJECT diff --git a/lib/CQnnnCAT.txt b/lib/CQnnnCAT.txt deleted file mode 100644 index d7e92d0..0000000 --- a/lib/CQnnnCAT.txt +++ /dev/null @@ -1,39 +0,0 @@ -Before using the new "CQ nnn ..." feature in JTMSK mode, I suggest -performing the following tests of the necessary CAT control for your -radio. (I'm assuming that you already have some experience with -JTMSK.) - -TEST 1: --------------------------------------------------------------------------- -1. Start WSJT-X -2. Settings: "Enable VHF/UHF/Microwave features, "Rx frequency offset - with 'CQ nnn ...'", Split=Rig, or Split="Fake it" -3. Main screen settings: Band=50.280, mode=JTMSK, T/R=15 s -4. Activate CQRx, set CQ Rx=265 - ==> Rx dial should now read 50.265 and Tx6 should be queued -5. Click "Enable Tx" - ==> Tx sequences should occur at 50.280, Rx at 50.265 - -With most rigs, this test should work with Split configured as either -"Rig" or "Fake it". - -TEST 2: --------------------------------------------------------------------------- -1. Start WSJT-X -2. Settings: MyCall=K1JT, "Enable VHF/UHF/Microwave features, - "Rx frequency offset with 'CQ nnn ...'", Split=Rig or "Fake it" -4. Main screen settings: Band=50.280, mode=JTMSK, T/R=15 s -5. Open file 150826_120515.wav - ==> see decoded message "K1JT VE1SKY FN74" -6. Click "Monitor" to restart monitoring -7. Activate CQRx, set CQ Rx=265 - ==> Rx dial should now read 50.265; Tx6 should be queued -8. Click "Enable Tx" - ==> Tx sequences should occur at 50.280, Rx at 50.265 -9. After the start of a transmission, double-click on the decoded message - "K1JT VE1SKY FN74" - ==> Tx2 should be generated and queued; transmission will pause - briefly, Tx freq changed to 50.265, then Tx resumed. - -The test file is posted at -http://physics.princeton.edu/pulsar/K1JT/150826_120515.wav diff --git a/lib/DXped_Operations.txt b/lib/DXped_Operations.txt deleted file mode 100644 index 9dc268b..0000000 --- a/lib/DXped_Operations.txt +++ /dev/null @@ -1,186 +0,0 @@ - White Paper: FT8 for DXpeditions - ----------------------------------- - Joe Taylor, K1JT - October 27, 2017 - -Assumptions: - -1. WSJT-X will have two distinct options that enable the maximum-rate -QSO exchanges described below. Fox must select "Fox"; all Hounds must -select "Hound". - -2. There will be an announced basic dial frequency for each band, say -f0=14082 kHz for 20m. This is the basic Channel. - -3. Fox always transmits in the 1st sequence, 200-800 Hz above f0. - -4. Hounds call in 2nd sequence, 1000-5000 Hz above f0. Hounds -transmitting below f0+1000 Hz will not be answered. - -5. If found necessary, additional Channels may be defined in which -Hounds can transmit. (However, I suggest that CQ-by-call-area may -be easier to implement and use; and the software could be made to -prevent Hounds in the wrong area from transmitting.) - -6. Ideally, Fox and Hounds should all use CAT control configured with -*Split Operation* set to *Rig* or *Fake It*, and transceiver dial -frequencies should best be calibrated to within a few Hz. (WSJT-X -provides tools that make this fairly easy to do.) - - -When Fox is running a pileup, QSOs will look something like the -following exchanges. Here I've assumed the Fox callsign is KH1DX, -his locator AJ10: - ------------------------------------------------------------------------- - Fox Hounds ------------------------------------------------------------------------- -1. CQ KH1DX AJ10 -2. KH1DX K1ABC FN42, KH1DX W9XYZ EN37, ... -3. K1ABC KH1DX -13 -4. KH1DX K1ABC R-11 -5. K1ABC RR73; W9XYZ -17 -6. ... no copy from W9XYZ ... -7. W9XYZ KH1DX -17 -8. ... no copy from W9XYZ ... -9. G4AAA KH1DX -11 -10. KH1DX G4AAA R-03 -11. G4AAA RR73; DL3BBB -12 -12. KH1DX DL3BBB R-09 -13. DL3BBB RR73; DE -14. ... ------------------------------------------------------------------------- - -All messages except those containing "<...>" are standard FT8 messages -(i3bit=0, iFreeText=0). Hounds transmit only standard messages. - -Fox transmits standard messages and also special messages with -i3bit=1. The special messages contain a callsign whose completed QSO -is being acknowledged; a callsign for the next station to be worked; a -hash code corresponding to the Fox callsign; and a signal report. -Users will see the Fox callsign enclosed in angle brackets, . -The 72-bit message payload contains two 28-bit callsigns, a 10-bit -hash code, and a 6-bit signal report. If no call has been queued up -by Fox for the next QSO, the acknowledgment message takes the -abbreviated form shown in line 13 above. - -When a Hound receives a message with i3bit=1, the decoder interprets -the remaining 72 bits as described above. If the 10-bit hash code -matches that for Fox's callsign, the message is displayed as in the -QSO exchanges shown above. Otherwise the message is considered a -false decode and is not displayed. - - -Station Setup and Operation for FOX ------------------------------------ - -A wide Rx bandwidth (up to 5 kHz) is selected. The basic dial -frequency is set 1 kHz above f0 (thus 14083 kHz in my example) and the -audio TxFreq somewhere between -200 and -800 Hz. (Yes, negative -numbers are OK. *Split Operation* will reset the Tx dial frequency as -needed and will keep the generated Tx audio frequency between 1500 and -2000 Hz.) Hounds with audio TxFreq set to N Hz will be received by Fox -at N-1000 Hz. - -WSJT-X at Fox will maintain and display a list of all decoded Hounds -calling Fox in the past 2 to 4 Rx cycles. The list might look -something like this (but typically will be much longer): - ----------------------------- -Call Grid Rpt Freq ----------------------------- -AA2UK FM29 -11 240 -AD9H EN61 +02 1260 -K0TPP EM48 -15 1980 -N2BJ EN61 +11 540 -N4NDR EL98 -17 4620 -NX4E EM70 +00 3780 -ON3LA JN29 -10 3300 -PD9BG JO21 -21 2100 -PJ4/KA1XYZ FK60 -07 1020 -VE1SKY FN74 +03 1620 -WB2REM EL97 -13 3060 -... ----------------------------- - -Fox can choose to have the list sorted on any column. - -Fox selects a Hound to call next by clicking on a line. Or he can hit -"F1" to have the program select a caller according to one of these -criteria (maybe others as well?): - - - Weakest caller - - Strongest caller - - Strongest one below -N dB (with N selectable) - - Choose a call at random - - Random choice with S/N between snrMin and snrMax dB. - -After a particular Hound has been called, Fox's Auto-Sequencer looks -for a response containing "R+rpt" originating from that same callsign. -If such a message is received, Fox's next transmission will be the -special "acknowledge-and-call-next" type, with i3bit=1. If the -expected message is not received, as in example line 6 above, the -report is sent to the same station again. If the second attempt fails -and another Hound callsign has been queued up, the QSO is aborted and -the next Hound is called. - - -Station Setup and Operation for Hounds --------------------------------------- - -Dial frequency is set to f0, 14082 kHz in my example. Rx bandwidth and -displayed range on the Wide Graph can be anything convenient, say 200 -to 2600 Hz. (Signal from Fox will be expected between 200 and 800 -Hz.) Enter callsign and locator of Fox on WSJT-X main window as *DX -Call* and *DX Grid*. Choose a TxFreq offset of 1000 + 60*N for some N -in the range 1 to 80 (maybe even higher?). Move TxFreq as desired, -hoping to find a clear slot, by using Shift+F11 and Shift+F12. - - - Hit F1 to call Fox in your next Tx sequence. Yes, you must hit F1 - repeatedly, in order to keep calling. - - - The Auto-sequencer will watch for a decoded message that contains - "MyCall DXcall rpt" or "MyCall rpt". When one of these is - received, your next transmission will be "DXcall MyCall R+rpt", - sent automatically. - - - After you send the "R+rpt" message, AutoSeq will watch for a - message that starts with "MyCall RR73; ...". When that is - received, you're in his log, and you'll be prompted to log the QSO. - -Random thoughts ---------------- - -Fox's decoder has access to signals in a 4 kHz (maybe even 5 kHz?) -window. At 60 Hz intervals, that's enough for around 65 (or 80?) -non-overlapping Hound signals. If the pileup becomes too deep, more -spectrum might be used; but note that WSJT-X can't access more than 5 -kHz at one time. A better solution might be for Fox to call "CQ n -KH1DX AJ10", where n is a single digit indicating call area. The -decoder could then limit the list of eligible calls to those in the -specified call area. After decoding such a CQ, the software at Hound -could refuse to transmit unless MyCall falls in the specified call -area. (Other special CQ formats can be imagined that would limit the -eligible Hound callsigns even further.) - -We haven't thought much, yet, about logging issues for Fox. I imagine -we could do what's necessary to join a N1MM+ logging network, if that's -deemed desirable. - -A few questions: - -Q1: Should the Auto-Sequencer allow for other cases in which a QSO has -been initiated by Fox, but one of next two messages is not copied by -either Fox or Hound? For example, what if K1ABC does not copy message -#5? Should he keep sending his message "KH1DX K1ABC R-11" ? If Fox -receives this message again, should he acknowledge again? And poor -W9XYZ, who never received an acknowledgment, will probably keep -sending "KH1DX W9XYZ R-19", or whatever. If Fox eventually copies the -message, should the program remember that W9XYZ had been called, and -thus send him an acknowledgment? - -Q2: Should we provide a stack for several to-be-called callsigns, -rather than just one? Should re-ordering of calls in the stack be -permitted? - -Q3: Can we handle WSJT-X "Type 1" and "Type 2" compound callsigns, for -Hounds? diff --git a/lib/DXped_pseudo_code.txt b/lib/DXped_pseudo_code.txt deleted file mode 100644 index 081bfda..0000000 --- a/lib/DXped_pseudo_code.txt +++ /dev/null @@ -1,71 +0,0 @@ -Auto-Sequencing algorithm for DXpedition station: - -Start: - CQMsg = "CQ KH1DX" (or "CQ UP KH1DX", "CQ 116 KH1DX", etc.) - TxMsg = CQMsg - Ntry = 0 - QCALL = "" # Callsign of current QSO partner - go to Transmit - -Transmit: - TX # (... takes 13.6 s) - go to Receive - -Receive: - RX # (... takes ~14 s) - N = number of decodes # RxMsg[i], i=1,N - if(N == 0) - go to Transmit - J = index of a reply from current QCALL # RxMsg[J] = "KH1DX QCALL R" - - if(QCALL == "") # No QSO in progress - Select new QCALL # Op chooses a caller - if(QCALL == "") - TxMsg = CQMsg # No callers, we'll CQ again - else # QSO in progress - if(J >= 1) # Expected message was received - log the QSO with QCALL - QCALL = "" - Select new QCALL # Op chooses a new caller - if(QCALL != "") - TxMsg = "73 NOW QCALL " # Start a new QSO - else - TxMsg = "73 " + CQMsg # No callers, we'll CQ again - else - Ntry = Ntry + 1 # Expected msg not received - if(Ntry <= NtryMax) - go to Transmit # Ask for a repeat - else - QCALL = "" # Max tries exceeded, abort this QSO - Select new QCALL # Choose a new caller - if(QCALL != "") - TxMsg = "NIL NOW QCALL " # Start a new QSO - else - TxMsg = "NIL " + CQMSG # No callers, we'll CQ again - go to Transmit - - -Auto-Sequencing algorithm for those calling the DXpedition: - -Start: - TxMsg = "KH1DX MyCall" - InQSO = false - -Transmit: - TX # (... takes 13.6 s) - go to Receive - -Receive: - RX # (... takes ~14 s) - if(RxMsg[i] contains "MyCall ") - InQSO = true - TxMsg = "KH1DX MyCall R" - go to Transmit - - if(RxMsg[i] contains "") - TxEnable = false - go to Receive - - if(RxMsg[i] contains "CQ KH1DX") - TxEnable = true - go to Transmit diff --git a/lib/Fast_Modes.txt b/lib/Fast_Modes.txt deleted file mode 100644 index da6e27b..0000000 --- a/lib/Fast_Modes.txt +++ /dev/null @@ -1,395 +0,0 @@ - Fast Modes in WSJT-X - -------------------- - -####################################################################### - -IMPORTANT - IMPORTANT - IMPORTANT - IMPORTANT - IMPORTANT - IMPORTANT - -Third-party individuals (i.e., others not part of the WSJT development -team) have been compiling WSJT-X from the open source code and making -unauthorized "releases" of their builds. I do NOT reccommend use of -unauthorized builds on the air. If a program revision has been released -in an official way, you will see it listed here. - -If you operate with an unauthorized "rXXXX" code revisions in our -experimental code branch you have no idea what you've got. Quite -possibly, the program was built from an intermediate temporary "save" -of various files, and was not even supposed to produce a usable -program. Your observetions about what works or does not work are then -worse than useless -- they waste your time and ours. - -So please, PLEASE, *PLEASE*: use *authorized*, "released* revisions -of this still-in-development software, like the revisions described here. - -*ALSO:* If you choose to try an experimental release of JTMSK, please -accept the responsibility of reporting on your results. You can send -reports to the "wsjtgroup" reflector, wsjtgroup@yahoogroups.com, or -email them directly to me. All suggestions for improvements are -welcome! - -Bug reports should include details on how to reproduce the undesirable -program behavior. Reports on decoding performance are especially -useful when accompanied by example *.wav files with signals that -you think should have decoded, but did not. - -####################################################################### - -September 18, 2015 ------------------ - -New alpha release of experimental WSJT-X v1.6.1, r5910 ------------------------------------------------------- -Changes since revision 5889 include the following: - -1. Improved behavior for auto-QSY with "CQ nnn ..." feature. (May not -be exactly correct, yet, for all radios. Please report if you find -problems with your rig.) - -2. Allow optional use of Wide Graph in fast modes. - -3. Add UTC labels to Fast Graph spectrograms. - -4. Display correct DXCC entiry for "CQ nnn ..." messages. - -5. Implement "Save Decoded" for fast modes. - -6. Select Tx6 when "CQ Rx nnn" is enabled. - -7. Fix bug in setting of TRperiod after switch to ISCAT mode. - -8. Display proper symbol '&' in Tx messages in JTMSK mode. - - -To download this alpha release for Windows, paste the following link -into your browser: -http://physics.princeton.edu/pulsar/K1JT/wsjtx-1.6.1-r5910-win32.exe - - -- 73, Joe, K1JT - -####################################################################### - -September 12, 2015 ------------------ - -New alpha release of experimental WSJT-X v1.6.1, r5889 ------------------------------------------------------- - -A principal new feature in this release is designed to promote the use -of an agreed "calling frequency" for transmissions of the form - - CQ 265 K1ABC FN42 - -signifying that K1ABC will listen for replies on 50.265 (or 144.265, -or whatever) and will complete the QSO there. The feature uses the -rig-control features of WSJT-X to handle the necessary frequency -switching. - -########################################################################## -Changes since revision 5865 include the following: - -1. New features that allow automatic rig control when you transmit or -respond to messages of the form "CQ 265 K1ABC FN42" on an agreed -calling frequency. This feature should be especially useful for -meteor scatter. - -2. Yellow-highlighted "Tx" messages in the right text window are now -properly labeled with 6-digit UTC (hhmmss) in all fast modes. - -3. Fixed a bug (introduced in r5865) that inhibited transmitting in -JT4 mode. - -4. Fixed a bug that caused Wide Graph to continue issuing green -separator lines at short (e.g. 15 s) intervals after you have switched -to a slow mode. - -5. Fixed several more GUI appearance bugs associated with changing -modes or submodes. - -6. Fixed a bug in which double-clicking on the Fast Graph could cause -program crashes. - -7. Fixed a bug that sometimes caused "high tones" to be emitted in -JTMSK mode. - -####################################################################### -Here's a brief description of how to use the "CQ nnn ..." features. - -1. On program startup, go to the Settings | General tab and tick the -box labeled 'Rx frequency offset with "CQ nnn ..."' - -2. Select JTMSK mode and 50.280 (or your some other agreed calling -frequency) from the drop-down band menu. Remember that this menu is -not pre-populated with preferred frequencies for all modes on all -bands. Use Settings | Frequencies to add your desired modes and -frequencies to the list. - -3. Tick the unlabeled checkbox just under the "Report: spinner to -activate the "CQ Rx nnn" spinner. Set this control to your desired -QSO frequency in kHz above the nominal band edge. On 6 meters, for -example, "265" means "50.265". - -4. Your transceiver dial frequency should now show 50.265. Changes to -the "CQ Rx nnn" spinner value should be reflected immediately in the -transceiver dial frequency, the displayed value on the WSJT-X main -screen, and in Tx message #6, the "CQ nnn... " message. - -5. When you transmit the Tx6 message, the Tx frequency will be set at -the calling frequency. Otherwise (when receiving, or when -transmitting any of the messages Tx1 through Tx5) the offset frequency -(50.265 in my example) will be used. - -6. If you double-click on a received "CQ nnn ..." message on the -calling frequency, your rig will QSY to specified response frequency, -e.g. 50.265, for both Rx and Tx. - -7. To go back to listening on the calling frequency, uncheck the box -that activated the "CQ Rx nnn" spinner. - -####################################################################### - -Fair warning: I have not yet tested all possible combinations of -"Split Operation" configuration (i.e., "None", "Rig", and "Fake it"). -If you normally use Split operation, that should be OK for the "CQ -nnn ..." feature. - - -As always, please report any bugs that you find in r5889, including -pertinent details on your settings and the exact series of steps -required to reproduce the bug. - - -To download this alpha release for Windows, paste the following link -into your browser: -http://physics.princeton.edu/pulsar/K1JT/wsjtx-1.6.1-r5889-win32.exe - - - -- 73, Joe, K1JT - -####################################################################### - -New alpha release of experimental WSJT-X v1.6.1, r5865 ------------------------------------------------------- - -This alpha release of WSJT-X includes major improvements to the JTMSK -decoder. Changes since revision 5823 include the following: - -1. On-screen controls labeled "Rx nnnn Hz" and "F Tol" (Rx frequency -and tolerance) now function as expected in JTMSK mode. The frequency -search range can be up to 500 Hz, but note that sensitivity is -necessarily reduced for signals off frequency by more than about 250 -Hz. Normally you should leave Rx Freq set at 1500 Hz; suitable values -for F Tol are 100 to 500 Hz. - -2. The JTMSK decoder now makes good use of strong, short pings (as -short as 0.1 s) as well as weak pings several times longer. - -3. Improved calculation of S/N and frequency of decoded signals. - -4. Unified appearance of window titles on all non-modal windows. - -5. CW ID is disabled (for now, at least) when operating in any of the -WSJT fast modes. - -6. In WSPR mode, display of "Receiving ... " messages is -disabled when band-hopping is not in use. - -7. Fixed several bugs affecting status and visibility of certain -on-screen controls after changes in operating mode. - -8. Fixed a bug allowing display of duplicate decodes for the same -signal. - -9. Fixed a bug preventing compilation on 64-bit systems, and cleaned -up some harmless compiler warnings. - -####################################################################### - Summary Description of JTMSK Protocol - -JTMSK uses the same standard message structure as slow modes JT4, JT9, -and JT65. User information is "source encoded" to 72 bits. A 15-bit -CRC is appended and a convolutional code with constraint length K=13 -and rate r=1/2 is applied, making a total of (72+15+12)*2 = 198 -information bits. Three copies of the "Barker-11" code and three -even-parity bits are added for synchronization, making a total of -198+33+3 = 234 channel symbols. Modulation uses a constant-envelope, -continuous-phase "minimum-shift keying" (MSK) waveform, with tone -frequencies of 1000 and 2000 Hz. - -####################################################################### - -To download this alpha release for Windows, paste the following link -into your browser: -http://physics.princeton.edu/pulsar/K1JT/wsjtx-1.6.1-r5865-win32.exe - - -- 73, Joe, K1JT - -August 28, 2015 ---------------- - -New release of experimental WSJT-X v1.6.1, r5823 ------------------------------------------------- - -To download for Windows, paste the following link into your browser: -http://physics.princeton.edu/pulsar/K1JT/wsjtx-1.6.1-r5823-win32.exe - -This experimental version of WSJT-X introduces a new fast mode called -JTMSK. The letters MS, of course, imply meteor scatter; the three -letters MSK mean "Minimum Shift Keying", the modulation scheme used in -this mode. - -Revision 5823 also includes a number of (mostly minor) bug fixes -relative to r5789. - -IMPORTANT: If you choose to try JTMSK, please accept the -responsibility of reporting on your results. You can send reports to -the "wsjtgroup" reflector, wsjtgroup@yahoogroups.com or email them -directly to me. All suggestions for improvements are welcome! Bug -reports should include details on how to reproduce the undesirable -program behavior. - -The present JTMSK decoder has been optimized for short pings. It does -not yet do a wide search for proper frequency alignment; you and your -QSO partner need to be "on frequency" to within +/- 100 Hz or better. -The decoder does not (yet) attempt to make optimal use of weak, slowly -varying signals. These and other characteristics may be improved in -coming revisions. - -KNOWN BUG: At present you should use T/R sequence lengths 15 s in -JTMSK mode. If you have a program crash, open Windows Task Manager, -select the "Processes" tab, right-click on wsjtx.exe, and select "End -Process Tree". Then restart the program. - -I view JTMSK as a candidate for replacing both FSK441 and JTMS for all -meteor scatter work. JTMSK has the major advantage of including -strong forward error correction (FEC), similar in usage to the schemes -used for many years in JT4, JT9, and JT65. The structure of user -messages and the format of minimal QSOs is also identical to those -other modes. But JTMSK is very fast, transmitting its full encoded -message content in 0.117 s, in a 2 kHz bandwidth. JTMSK therefore -makes much better use of short pings than (for example) JT9H can do. - -The Tx waveform of JTMSK has been carefully designed to have a number -of desirable features. All messages are exactly the same length: 72 -bits of user information are followed by a 15-bit CRC and encoded into -198 channel bits with a convolutional code (constraint length K=13, -rate r=1/2). Three sequences of the "Barker-11" code are added, along -with three parity bits, making a total of 234 channel bits in each -message. The MSK symbols for these bits are transmitted at 2000 baud, -and the full encoded message is repeated every 117 ms. - -A summary description of modulation parameters for all WSJT(-X) modes -is shown in a table posted here: -http://physics.princeton.edu/pulsar/K1JT/wsjt_modes.txt and -illustrated graphically here: -http://physics.princeton.edu/pulsar/K1JT/wsjt_modes.pdf - - -- 73, Joe, K1jT - -August 15, 2015 ---------------- - -New release of experimental WSJT-X v1.6.1, r5789 - -Changes since WSJT-X v1.6.1, revision 5779: - -1. Major speedup (5x) of fast-JT9 decoder. -2. Corrected logic for Auto-Sequencing operation. -3. Stop after sending 73 five times in auto-sequence mode. -4. Add an "Auto-Level" control to Fast Graph window. -5. Send fast-mode decodes to PSKreporter web site. -6. Support automatic logging via JTAlert-X. -7. Send fast-mode output to file ALL.TXT. -8. Better definition of dB levels for fast-JT9 signals. -9. Rationalize the GUI behavior when changing mode, submode, fast/slow - status, and T/R period. -10. Correct a flaw in the display of multiple decodes in a single - fast-JT9 sequence. -11. Fix minor bugs reported by G3WDG, ND0B, OZ1PIF, and others. - -To download for Windows, paste the following link into your browser: -http://physics.princeton.edu/pulsar/K1JT/wsjtx-1.6.1-r5789-win32.exe - -Please keep in mind that this is an experimental version of WSJT-X. -Bug reports and other feedback will be much appreciated, and will help -to make the program better! - - -- 73, Joe, K1JT - - -August 11, 2015 ---------------- - -Since its origin in the dark ages (ca. 2001) WSJT has supported "fast" -modes (designed for meteor scatter, etc.) and "slow" modes (optimized -for EME and other weak-signal propagation types). The most recent new -mode, JT9, now has *both* fast and slow submodes. - -JT9A (the "original" JT9) is like JT65 and JT4: its T/R sequences are -one minute long, and its primary goal is best possible sensitivity for -very weak, approximately steady signals. The new experimental JT9 -submodes use the same message structure, encoding, and modulation type -(9-tone FSK) as JT9A, but wider tone spacing and (optionally) faster -keying rates. - -You can download an experimental version of WSJT-X (v1.6.1, r5779) here: -http://physics.princeton.edu/pulsar/K1JT/wsjtx-1.6.1-r5779-win32.exe - -The fast submodes currently being tested, JT9E - JT9H, have been found -highly effective for meteors and ionoscatter propagation on 6 and 10 -meters. Sensitivity is similar to ISCAT, or slightly better. -Decoding is much more reliable, because the JT9 protocol includes -strong forward error correction. Decoding results are like those for -all the WSJT "slow" modes: you should see messages exactly as they -were transmitted, or nothing at all. A potential side benefit is -automatic reporting of decodes to PSKreporter. - -For details on the modulation parameters of the JT9 submodes, see the -table posted at -http://physics.princeton.edu/pulsar/K1JT/wsjt_modes.txt. - -WSJT-X v1.6.1 r5779 has the following changes from r5769: - -1. Numerous bug fixes -2. Double-click on decoded message now behaves properly -3. Faster decoding (further optimization still to come) -4. Decoded text is highlighted as in WSJT-X slow modes -5. Optional auto-sequencing - -Fair warning: auto-sequencing is basically functional, but scarcely -tested. Please watch what it is doing, and tell us how you think it -should be improved! - -If you use WSJT-X also for other modes and other purposes, you may -want to save several different sets of configuration settings. In -that case it's convenient to use the "-r xxx" option and start the -program from a command-prompt window. For example: - -C:\Users\joe> cd \wsjt\wsjtx\bin -C:\WSJT\wsjtx\bin> wsjtx -r xxx - -... where "xxx" can be anything you like, for example "ISCAT", -"FAST9", etc. - -Proper configuration for the JT9 fast modes includes the following -settings: - -On the Settings | General tab: - - - check "Enable VHF/UHF/Microwave features" - -Main window settings: - - - Mode JT9 - - Tx 700 Hz - - Rx 700 Hz - - Sync 0 - - Submode G ... or E, F, and H (H not legal in US on 10m) - - Tick "Fast" - - T/R 30 s (also 5, 10, 15 s) - - FTol 500 - -Please keep in mind that this is an experimental version of WSJT-X. -It still has some rough edges, and no doubt some bugs. Your feedback -will be much appreciated, and will help to make the program better! - - -- 73, Joe, K1JT diff --git a/lib/Makefile b/lib/Makefile deleted file mode 100644 index c4d6279..0000000 --- a/lib/Makefile +++ /dev/null @@ -1,71 +0,0 @@ -CC = gcc -CXX = g++ -FC = gfortran - -FFLAGS = -O2 -fbounds-check -Wall -Wno-conversion -CFLAGS = -O2 -I. - -# Default rules -%.o: %.c - ${CC} ${CFLAGS} -c $< -%.o: %.f - ${FC} ${FFLAGS} -c $< -%.o: %.F - ${FC} ${FFLAGS} -c $< -%.o: %.f90 - ${FC} ${FFLAGS} -c $< -%.o: %.F90 - ${FC} ${FFLAGS} -c $< - -#all: qratest.exe tplt.exe -all: qra64d.exe - -OBJS1 = qratest.o qra64a.o ana64.o sync64a.o four2a.o smo.o smo121.o averms.o \ - timer_module.o packjt.o twkfreq.o spec64.o fmtmsg.o pctile.o \ - grid2deg.o deg2grid.o shell.o badmsg.o qra64_subs.o \ - qracodes.o npfwht.o pdmath.o qra12_63_64_irr_b.o \ - qra13_64_64_irr_e.o qra64.o image.o \ - zplt64a.o zplt64b.o lorentzian.o fchisq0.o peakup.o sync64.o - -qra64_subs.o: qra/qra64/qra64_subs.c - gcc -c -O2 -o qra64_subs.o qra/qra64/qra64_subs.c - -qracodes.o: qra/qracodes/qracodes.c - gcc -c -O2 -o qracodes.o qra/qracodes/qracodes.c - -qra64.o: qra/qra64/qra64.c - gcc -c -O2 -o qra64.o qra/qra64/qra64.c - -npfwht.o: qra/qracodes/npfwht.c - gcc -c -O2 -o npfwht.o qra/qracodes/npfwht.c - -pdmath.o: qra/qracodes/pdmath.c - gcc -c -O2 -o pdmath.o qra/qracodes/pdmath.c - -qra12_63_64_irr_b.o: qra/qracodes/qra12_63_64_irr_b.c - gcc -c -O2 -o qra12_63_64_irr_b.o qra/qracodes/qra12_63_64_irr_b.c - -qra13_64_64_irr_e.o: qra/qracodes/qra13_64_64_irr_e.c - gcc -c -O2 -o qra13_64_64_irr_e.o qra/qracodes/qra13_64_64_irr_e.c - -qratest.exe: $(OBJS1) - $(FC) -o qratest.exe $(OBJS1) C:\JTSDK\fftw3f\libfftw3f-3.dll - -OBJS2 = tplt.o zplt64.o image.o -tplt.exe: $(OBJS2) - $(FC) -o tplt.exe $(OBJS2) - -OBJS3 = qra64d.o sync64a.o four2a.o smo.o smo121.o averms.o \ - timer_module.o packjt.o twkfreq.o spec64.o fmtmsg.o pctile.o \ - grid2deg.o deg2grid.o shell.o badmsg.o qra64_subs.o \ - qracodes.o npfwht.o pdmath.o qra12_63_64_irr_b.o \ - qra13_64_64_irr_e.o qra64.o image.o \ - zplt64a.o zplt64b.o lorentzian.o fchisq0.o peakup.o sync64.o - -qra64d.exe: $(OBJS3) - $(FC) -o qra64d.exe $(OBJS3) C:\JTSDK\fftw3f\libfftw3f-3.dll - -.PHONY : clean - -clean: - $(RM) *.o qratest.exe tplt.exe diff --git a/lib/Makefile.MinGW b/lib/Makefile.MinGW deleted file mode 100644 index 1cdc665..0000000 --- a/lib/Makefile.MinGW +++ /dev/null @@ -1,153 +0,0 @@ -# Makefile for MinGW on Windows -# -# Needed libraries are located using the following variables: -# -# QT_DIR - point this at the root of your Qt installation -# FFTW3_DIR - point this at the fftw v3 installation directory -# -# e.g. -# make -f Makefile.MinGW \ -# QT_DIR=c:/Qt/5.2.1/mingw48_32 \ -# FFTW3_DIR = c:/fftw-3.3.3-dll32-2 -# -# Windows re-direct: -# C> make > junk1 2>&1 - -# Set paths -EXE_DIR = ..\\..\\wsjtx_install -QT_DIR = C:/wsjt-env/Qt5/5.2.1/mingw48_32 -FFTW3_DIR = .. - -INCPATH = -I${QT_DIR}/include/QtCore -I${QT_DIR}/include - -# Compilers -CC = gcc -CXX = g++ -FC = gfortran -AR = ar cr -RANLIB = ranlib -MKDIR = mkdir -p -CP = cp -RM = rm -f - -FFLAGS = -O2 -fbounds-check -Wall -Wno-precision-loss -fno-second-underscore -CFLAGS = -I. -fbounds-check -mno-stack-arg-probe - -# Default rules -%.o: %.c - ${CC} ${CFLAGS} -c $< -%.o: %.f - ${FC} ${FFLAGS} -c $< -%.o: %.F - ${FC} ${FFLAGS} -c $< -%.o: %.f90 - ${FC} ${FFLAGS} -c $< -%.o: %.F90 - ${FC} ${FFLAGS} -c $< - -all: libjt9.a libastro.a jt9.exe jt9code.exe jt65code.exe - -OBJS1 = prog_args.o options.o pctile.o graycode.o sort.o ssort.o chkmsg.o \ - unpackmsg.o igray.o unpackcall.o unpackgrid.o \ - fmtmsg.o grid2k.o unpacktext.o getpfx2.o packmsg.o deg2grid.o \ - packtext.o getpfx1.o packcall.o k2grid.o packgrid.o \ - nchar.o four2a.o grid2deg.o pfxdump.o f77_wisdom.o \ - symspec.o analytic.o db.o genjt9.o flat1.o smo.o \ - packbits.o unpackbits.o encode232.o interleave9.o \ - entail.o fano232.o gran.o sync9.o decode9.o \ - fil3.o decoder.o grid2n.o n2grid.o timer.o \ - softsym.o getlags.o afc9.o fchisq.o twkfreq.o downsam9.o \ - peakdt9.o symspec2.o stdmsg.o morse.o azdist.o geodist.o \ - fillcom.o chkss2.o zplot9.o flat2.o \ - jt65a.o symspec65.o flat65.o ccf65.o decode65a.o \ - filbig.o fil6521.o afc65b.o decode65b.o setup65.o \ - extract.o fchisq65.o demod64a.o chkhist.o interleave63.o ccf2.o \ - move.o indexx.o graycode65.o twkfreq65.o smo121.o \ - wrapkarn.o init_rs.o encode_rs.o decode_rs.o gen65.o fil4.o \ - flat3.o polfit.o determ.o baddata.o - -libjt9.a: $(OBJS1) - $(AR) libjt9.a $(OBJS1) - $(RANLIB) libjt9.a - -OBJS2 = jt9.o jt9a.o jt9b.o jt9c.o ipcomm.o sec_midn.o usleep.o -LIBS2 = -L${QT_DIR}/lib -lQt5Core -jt9.exe: $(OBJS2) libjt9.a - $(CXX) -o jt9.exe $(OBJS2) $(LIBS2) libjt9.a \ - -L$(FFTW3_DIR) -lfftw3f-3 $(shell $(FC) -print-file-name=lib$(FC).a) - -$(MKDIR) $(EXE_DIR) - $(CP) jt9.exe $(EXE_DIR) - -OBJS3 = jt9sim.o -jt9sim.exe: $(OBJS3) libjt9.a - $(FC) -o jt9sim.exe $(OBJS3) libjt9.a - -OBJS4 = jt9code.o -jt9code.exe: $(OBJS4) libjt9.a - $(FC) -o jt9code.exe $(OBJS4) libjt9.a - $(CP) jt9code.exe $(EXE_DIR) - -OBJS5 = jt65.o -jt65.exe: $(OBJS5) libjt9.a - $(FC) -o jt65.exe $(OBJS5) libjt9.a -L$(FFTW3_DIR) -lfftw3f-3 - -OBJS7 = astrosub.o astro0.o astro.o tm2.o grid2deg.o sun.o moondop.o \ - coord.o dot.o moon2.o tmoonsub.o toxyz.o geocentric.o \ - dcoord.o - -libastro.a: $(OBJS7) - $(AR) libastro.a $(OBJS7) - $(RANLIB) libastro.a - -OBJS6 = jt65code.o -jt65code.exe: $(OBJS6) libjt9.a - $(FC) -o jt65code.exe $(OBJS6) libjt9.a - $(CP) jt65code.exe $(EXE_DIR) - -sync9.o: sync9.f90 jt9sync.f90 - $(FC) $(FFLAGS) -c sync9.f90 - -spec9.o: spec9.f90 jt9sync.f90 - $(FC) $(FFLAGS) -c spec9.f90 - -peakdt9.o: peakdt9.f90 jt9sync.f90 - $(FC) $(FFLAGS) -c peakdt9.f90 - -jt9sim.o: jt9sim.f90 jt9sync.f90 - $(FC) $(FFLAGS) -c jt9sim.f90 - -genjt9.o: genjt9.f90 jt9sync.f90 - $(FC) $(FFLAGS) -c genjt9.f90 - -redsync.o: redsync.f90 jt9sync.f90 - $(FC) $(FFLAGS) -c redsync.f90 - -unpackmsg.o: unpackmsg.f90 - $(FC) -c -O0 -fbounds-check -Wall -Wno-precision-loss unpackmsg.f90 - -ipcomm.o: ipcomm.cpp - $(CXX) -c $(INCPATH) ipcomm.cpp - -sec_midn.o: sec_midn.f90 - $(FC) -c -fno-second-underscore sec_midn.f90 - -#rig_control.o: rig_control.c -# $(CC) -c -Wall -I..\..\..\hamlib-1.2.15.3\include rig_control.c - -tstrig.o: tstrig.c - $(CC) -c -Wall -I..\..\..\hamlib-1.2.15.3\include tstrig.c - -init_rs.o: init_rs.c - $(CC) -c -DBIGSYM=1 -o init_rs.o init_rs.c - -encode_rs.o: encode_rs.c - $(CC) -c -DBIGSYM=1 -o encode_rs.o encode_rs.c - -decode_rs.o: decode_rs.c - $(CC) -c -DBIGSYM=1 -o decode_rs.o decode_rs.c - - -.PHONY : clean - -clean: - $(RM) *.o libjt9.a wsjtx.exe jt9sim.exe jt9.exe jt65.exe diff --git a/lib/Makefile.MinGW.qt4 b/lib/Makefile.MinGW.qt4 deleted file mode 100644 index df90745..0000000 --- a/lib/Makefile.MinGW.qt4 +++ /dev/null @@ -1,122 +0,0 @@ -# Makefile for MinGW on Windows -# Windows re-direct: -# C> make > junk1 2>&1 - -# Set paths -EXE_DIR = ../../wsjtx_install -INCPATH = -I'c:/QtSDK/Desktop/Qt/4.7.4/mingw/include/QtCore' \ - -I'c:/QtSDK/Desktop/Qt/4.7.4/mingw/include' \ - -I'c:/QtSDK/Desktop/Qt/4.7.4/mingw/include/ActiveQt' \ - -I'release' -I'.' -I'c:/QtSDK/Desktop/Qt/4.7.4/mingw/mkspecs/win32-g++' - -# Compilers -CC = gcc -CXX = g++ -FC = g95 - -FFLAGS = -O2 -fbounds-check -Wall -Wno-precision-loss -fno-second-underscore -CFLAGS = -I. -fbounds-check -mno-stack-arg-probe - -# Default rules -%.o: %.c - ${CC} ${CFLAGS} -c $< -%.o: %.f - ${FC} ${FFLAGS} -c $< -%.o: %.F - ${FC} ${FFLAGS} -c $< -%.o: %.f90 - ${FC} ${FFLAGS} -c $< -%.o: %.F90 - ${FC} ${FFLAGS} -c $< - -all: libjt9.a jt9sim.exe jt9.exe jt9code.exe jt65.exe - -OBJS1 = pctile.o graycode.o sort.o ssort.o \ - unpackmsg.o igray.o unpackcall.o unpackgrid.o \ - grid2k.o unpacktext.o getpfx2.o packmsg.o deg2grid.o \ - packtext.o getpfx1.o packcall.o k2grid.o packgrid.o \ - nchar.o four2a.o grid2deg.o pfxdump.o f77_wisdom.o \ - symspec.o analytic.o db.o genjt9.o \ - packbits.o unpackbits.o encode232.o interleave9.o \ - entail.o fano232.o gran.o sync9.o decode9.o \ - fil3.o decoder.o grid2n.o n2grid.o timer.o \ - softsym.o getlags.o afc9.o fchisq.o twkfreq.o downsam9.o \ - peakdt9.o symspec2.o stdmsg.o morse.o azdist.o geodist.o \ - fillcom.o chkss2.o zplot9.o flat2.o \ - jt65a.o symspec65.o flat65.o ccf65.o decode65a.o \ - filbig.o fil6521.o afc65b.o decode65b.o setup65.o \ - extract.o fchisq65.o demod64a.o chkhist.o interleave63.o ccf2.o \ - move.o indexx.o graycode65.o twkfreq65.o smo121.o \ - wrapkarn.o init_rs.o encode_rs.o decode_rs.o gen65.o - -libjt9.a: $(OBJS1) - ar cr libjt9.a $(OBJS1) - ranlib libjt9.a - -OBJS2 = jt9.o jt9a.o jt9b.o jt9c.o ipcomm.o sec_midn.o usleep.o -LIBS2 = -L'c:/QtSDK/Desktop/Qt/4.7.4/mingw/lib' -lQtCore4 -jt9.exe: $(OBJS2) libjt9.a - $(CXX) -o jt9.exe $(OBJS2) $(LIBS2) libjt9.a ../libfftw3f_win.a \ - c:/MinGW/lib/libf95.a - mkdir -p $(EXE_DIR) - cp jt9.exe $(EXE_DIR) - -OBJS3 = jt9sim.o -jt9sim.exe: $(OBJS3) libjt9.a - $(FC) -o jt9sim.exe $(OBJS3) libjt9.a - -OBJS4 = jt9code.o -jt9code.exe: $(OBJS4) libjt9.a - $(FC) -o jt9code.exe $(OBJS4) libjt9.a - -OBJS5 = jt65.o -jt65.exe: $(OBJS5) libjt9.a - $(FC) -o jt65.exe $(OBJS5) libjt9.a ../libfftw3f_win.a - -sync9.o: sync9.f90 jt9sync.f90 - $(FC) $(FFLAGS) -c sync9.f90 - -spec9.o: spec9.f90 jt9sync.f90 - $(FC) $(FFLAGS) -c spec9.f90 - -peakdt9.o: peakdt9.f90 jt9sync.f90 - $(FC) $(FFLAGS) -c peakdt9.f90 - -jt9sim.o: jt9sim.f90 jt9sync.f90 - $(FC) $(FFLAGS) -c jt9sim.f90 - -genjt9.o: genjt9.f90 jt9sync.f90 - $(FC) $(FFLAGS) -c genjt9.f90 - -redsync.o: redsync.f90 jt9sync.f90 - $(FC) $(FFLAGS) -c redsync.f90 - -unpackmsg.o: unpackmsg.f90 - $(FC) -c -O0 -fbounds-check -Wall -Wno-precision-loss unpackmsg.f90 - -ipcomm.o: ipcomm.cpp - $(CXX) -c $(INCPATH) ipcomm.cpp - -sec_midn.o: sec_midn.f90 - $(FC) -c -fno-second-underscore sec_midn.f90 - -#rig_control.o: rig_control.c -# $(CC) -c -Wall -I..\..\..\hamlib-1.2.15.3\include rig_control.c - -tstrig.o: tstrig.c - $(CC) -c -Wall -I..\..\..\hamlib-1.2.15.3\include tstrig.c - -init_rs.o: init_rs.c - $(CC) -c -DBIGSYM=1 -o init_rs.o init_rs.c - -encode_rs.o: encode_rs.c - $(CC) -c -DBIGSYM=1 -o encode_rs.o encode_rs.c - -decode_rs.o: decode_rs.c - $(CC) -c -DBIGSYM=1 -o decode_rs.o decode_rs.c - - -.PHONY : clean - -clean: - rm -f *.o libjt9.a wsjtx.exe jt9sim.exe jt9.exe jt65.exe diff --git a/lib/Makefile.jt65 b/lib/Makefile.jt65 deleted file mode 100644 index 7409b5c..0000000 --- a/lib/Makefile.jt65 +++ /dev/null @@ -1,84 +0,0 @@ -# Set paths -EXE_DIR = ../../wsjtx_exp_install_latest -QT_DIR = /usr/include/qt5 -INCPATH = -I${QT_DIR} -I${QT_DIR}/QtCore - -CC = gcc -CXX = g++ -FC = gfortran -AR = ar cr -MKDIR = mkdir -p -CP = cp -RANLIB = ranlib -RM = rm -f - -FFLAGS = -I/opt/local/include -O3 -funroll-loops -Wall -Wno-conversion -fno-second-underscore -DUNIX -CFLAGS = -I. -fbounds-check -fPIE - -# Default rules -%.o: %.c - ${CC} ${CFLAGS} -c $< -%.o: %.f - ${FC} ${FFLAGS} -c $< -%.o: %.F - ${FC} ${FFLAGS} -c $< -%.o: %.f90 - ${FC} ${FFLAGS} -c $< -%.o: %.F90 - ${FC} ${FFLAGS} -c $< - -all: libjt9.a jt65 jt65sim t3 - -OBJS1 = astrosub.o astro0.o astro.o sun.o coord.o tmoonsub.o \ - fmtmsg.o deg2grid.o\ - prog_args.o options.o pctile.o graycode.o sort.o chkmsg.o \ - igray.o fftw3mod.o packjt.o\ - four2a.o grid2deg.o wisdom.o \ - symspec.o analytic.o db.o \ - encode232.o interleave9.o\ - entail.o fano232.o gran.o sync9.o \ - fil3.o decoder.o fqso_first.o \ - twkfreq.o symspec2.o shell.o sync65.o peakup.o slope.o xcor.o\ - chkss2.o zplot9.o flat1.o flat2.o \ - symspec65.o flat65.o ccf65.o decode65a.o \ - filbig.o fil6521.o afc65b.o decode65b.o setup65.o \ - extract.o fchisq65.o demod64a.o chkhist.o interleave63.o ccf2.o \ - move.o indexx.o graycode65.o twkfreq65.o smo.o smo121.o \ - wrapkarn.o init_rs.o encode_rs.o decode_rs.o gen65.o fil4.o \ - flat4.o determ.o baddata.o subtract65.o - -libjt9.a: $(OBJS1) - $(AR) libjt9.a $(OBJS1) - $(RANLIB) libjt9.a - -OBJS7 = jt65.o -jt65: $(OBJS7) libjt9.a libsfrsd.a - $(FC) -o jt65 $(OBJS7) -L. -L/opt/local/lib -L./sfrsd2 -ljt9 -lsfrsd -lfftw3f_threads -lfftw3f - $(CP) jt65 $(EXE_DIR) - -OBJS2 = jt65sim.o wavhdr.o -jt65sim: $(OBJS2) libjt9.a - $(FC) -o jt65sim $(OBJS2) -L. -L/opt/local/lib -ljt9 -lfftw3f - $(CP) jt65sim $(EXE_DIR) - -OBJS3 = t3.o -t3: $(OBJS3) libjt9.a - $(FC) -o t3 $(OBJS3) -L. -L/opt/local/lib -ljt9 - -OBJS6 = jt65code.o -jt65code: $(OBJS6) libjt9.a - $(FC) -o jt65code $(OBJS6) libjt9.a - -init_rs.o: init_rs.c - $(CC) -c -DBIGSYM=1 -o init_rs.o init_rs.c - -encode_rs.o: encode_rs.c - $(CC) -c -DBIGSYM=1 -o encode_rs.o encode_rs.c - -decode_rs.o: decode_rs.c - $(CC) -c -DBIGSYM=1 -o decode_rs.o decode_rs.c - -.PHONY : clean - -clean: - $(RM) *.o libjt9.a jt65 diff --git a/lib/Makefile.jt65_Win b/lib/Makefile.jt65_Win deleted file mode 100644 index 08a4d22..0000000 --- a/lib/Makefile.jt65_Win +++ /dev/null @@ -1,76 +0,0 @@ -# Set paths -EXE_DIR = C:/JTSDK/wsjtx_exp/install/Debug/bin -QT_DIR = /usr/include/qt5 -INCPATH = -I${QT_DIR} -I${QT_DIR}/QtCore - -CC = gcc -CXX = g++ -FC = gfortran -AR = ar cr -MKDIR = mkdir -p -CP = cp -RANLIB = ranlib -RM = rm -f - -FFLAGS = -O2 -Wall -Wno-conversion -fno-second-underscore -CFLAGS = -I. -fbounds-check -fPIE -DBIGSYM - -# Default rules -%.o: %.c - ${CC} ${CFLAGS} -c $< -%.o: %.f - ${FC} ${FFLAGS} -c $< -%.o: %.F - ${FC} ${FFLAGS} -c $< -%.o: %.f90 - ${FC} ${FFLAGS} -c $< -%.o: %.F90 - ${FC} ${FFLAGS} -c $< - -all: libjt9.a jt65 jt65sim - -OBJS1 = astrosub.o astro0.o astro.o sun.o coord.o tmoonsub.o \ - fmtmsg.o deg2grid.o\ - prog_args.o options.o pctile.o graycode.o sort.o chkmsg.o \ - igray.o fftw3mod.o packjt.o\ - four2a.o grid2deg.o wisdom.o \ - symspec.o analytic.o db.o \ - encode232.o interleave9.o \ - entail.o fano232.o gran.o sync9.o decjt9.o \ - fil3.o decoder.o timer.o exp_decode65.o fqso_first.o \ - twkfreq.o symspec2.o shell.o sync65.o peakup.o slope.o xcor.o\ - fillcom.o chkss2.o zplot9.o flat1.o flat2.o \ - jt65a.o symspec65.o flat65.o ccf65.o decode65a.o \ - filbig.o fil6521.o afc65b.o decode65b.o setup65.o \ - extract.o fchisq65.o demod64a.o chkhist.o interleave63.o ccf2.o \ - move.o indexx.o graycode65.o twkfreq65.o smo.o smo121.o \ - wrapkarn.o init_rs.o encode_rs.o decode_rs.o gen65.o fil4.o \ - flat4.o determ.o baddata.o subtract65.o - -libjt9.a: $(OBJS1) - $(AR) libjt9.a $(OBJS1) - $(RANLIB) libjt9.a - -OBJS7 = jt65.o -jt65: $(OBJS7) libjt9.a libsfrsd.a - $(FC) -o jt65 $(OBJS7) -L. -L./sfrsd2 -ljt9 -lsfrsd \ - C:\JTSDK\fftw3f\libfftw3f-3.dll - -OBJS2 = jt65sim.o wavhdr.o -jt65sim: $(OBJS2) libjt9.a - $(FC) -o jt65sim $(OBJS2) -L. -ljt9 C:\JTSDK\fftw3f\libfftw3f-3.dll - $(CP) jt65sim.exe $(EXE_DIR) - -init_rs.o: init_rs.c - $(CC) -c -DBIGSYM=1 -o init_rs.o init_rs.c - -encode_rs.o: encode_rs.c - $(CC) -c -DBIGSYM=1 -o encode_rs.o encode_rs.c - -decode_rs.o: decode_rs.c - $(CC) -c -DBIGSYM=1 -o decode_rs.o decode_rs.c - -.PHONY : clean - -clean: - $(RM) *.o libjt9.a jt65 diff --git a/lib/Makefile.jt65_osx b/lib/Makefile.jt65_osx deleted file mode 100644 index c831e70..0000000 --- a/lib/Makefile.jt65_osx +++ /dev/null @@ -1,74 +0,0 @@ -# Set paths -EXE_DIR = ../../wsjtx_install - -CC = clang -CXX = g++ -FC = gfortran -AR = ar cr -MKDIR = mkdir -p -CP = cp -RANLIB = ranlib -RM = rm -f - -FFLAGS = -I/opt/local/include -Wall -Wno-conversion -fno-second-underscore -DUNIX -CFLAGS = -I. -fbounds-check -fPIE - -# Default rules -%.o: %.c - ${CC} ${CFLAGS} -c $< -%.o: %.f - ${FC} ${FFLAGS} -c $< -%.o: %.F - ${FC} ${FFLAGS} -c $< -%.o: %.f90 - ${FC} ${FFLAGS} -c $< -%.o: %.F90 - ${FC} ${FFLAGS} -c $< - -all: libjt9.a jt65 jt65sim - -OBJS1 = astrosub.o astro0.o astro.o sun.o coord.o tmoonsub.o \ - fmtmsg.o deg2grid.o\ - prog_args.o options.o pctile.o graycode.o sort.o chkmsg.o \ - igray.o fftw3mod.o packjt.o\ - four2a.o grid2deg.o wisdom.o \ - symspec.o analytic.o db.o \ - encode232.o interleave9.o\ - entail.o fano232.o sgran.o gran.o sync9.o decjt9.o \ - fil3.o decoder.o timer.o exp_decode65.o fqso_first.o\ - twkfreq.o symspec2.o shell.o sync65.o peakup.o slope.o xcor.o\ - fillcom.o chkss2.o zplot9.o flat1.o flat2.o \ - jt65a.o symspec65.o flat65.o ccf65.o decode65a.o \ - filbig.o fil6521.o afc65b.o decode65b.o setup65.o \ - extract.o fchisq65.o demod64a.o chkhist.o interleave63.o ccf2.o \ - move.o indexx.o graycode65.o twkfreq65.o smo.o smo121.o \ - wrapkarn.o init_rs.o encode_rs.o decode_rs.o gen65.o fil4.o \ - flat4.o determ.o baddata.o subtract65.o - -libjt9.a: $(OBJS1) - $(AR) libjt9.a $(OBJS1) - $(RANLIB) libjt9.a - -OBJS7 = jt65.o -jt65: $(OBJS7) libjt9.a libftrsd.a - $(FC) -o jt65 $(OBJS7) -L. -L/opt/local/lib -L./ftrsd -ljt9 -lftrsd -lfftw3f_threads -lfftw3f - $(CP) jt65 $(EXE_DIR) - -OBJS2 = jt65sim.o wavhdr.o -jt65sim: $(OBJS2) libjt9.a - $(FC) -o jt65sim $(OBJS2) -L. -L/opt/local/lib -ljt9 -lfftw3f - $(CP) jt65sim $(EXE_DIR) - -init_rs.o: init_rs.c - $(CC) -c -DBIGSYM=1 -o init_rs.o init_rs.c - -encode_rs.o: encode_rs.c - $(CC) -c -DBIGSYM=1 -o encode_rs.o encode_rs.c - -decode_rs.o: decode_rs.c - $(CC) -c -DBIGSYM=1 -o decode_rs.o decode_rs.c - -.PHONY : clean - -clean: - $(RM) *.o libjt9.a jt65 diff --git a/lib/Makefile.jt9w b/lib/Makefile.jt9w deleted file mode 100644 index db7bd54..0000000 --- a/lib/Makefile.jt9w +++ /dev/null @@ -1,58 +0,0 @@ - -# Set paths -EXE_DIR = ..\\..\\wsjtx_install -QT_DIR = C:/wsjt-env/Qt5/5.2.1/mingw48_32 -FFTW3_DIR = .. - -INCPATH = -I${QT_DIR}/include/QtCore -I${QT_DIR}/include - -# Compilers -CC = gcc -CXX = g++ -FC = gfortran -AR = ar cr -RANLIB = ranlib -MKDIR = mkdir -p -CP = cp -RM = rm -f - -FFLAGS = -O2 -fbounds-check -Wall -Wno-conversion -CFLAGS = -O2 -I. - -# Default rules -%.o: %.c - ${CC} ${CFLAGS} -c $< -%.o: %.f - ${FC} ${FFLAGS} -c $< -%.o: %.F - ${FC} ${FFLAGS} -c $< -%.o: %.f90 - ${FC} ${FFLAGS} -c $< -%.o: %.F90 - ${FC} ${FFLAGS} -c $< - -all: jt9w - -OBJS1 = jt9w.o smo.o sync9w.o pctile.o shell.o lorentzian.o fchisq0.o \ - softsym9w.o four2a.o interleave9.o jt9fano.o fano232.o packjt.o \ - deg2grid.o grid2deg.o fmtmsg.o db.o decode9w.o - -jt9w: $(OBJS1) - $(FC) -o jt9w $(OBJS1) -lfftw3f - -OBJS2 = t1.o four2a.o db.o -t1: $(OBJS2) - $(FC) -o t1 $(OBJS2) -lfftw3f - -OBJS3 = t2.o four2a.o db.o -t2: $(OBJS3) - $(FC) -o t2 $(OBJS3) -lfftw3f - -OBJS4 = t3.o four2a.o db.o -t3: $(OBJS4) - $(FC) -o t3 $(OBJS4) -lfftw3f - -.PHONY : clean - -clean: - $(RM) *.o JTMSKcode JTMSKcode.exe diff --git a/lib/Makefile.jt9w_Win b/lib/Makefile.jt9w_Win deleted file mode 100644 index 28dbe30..0000000 --- a/lib/Makefile.jt9w_Win +++ /dev/null @@ -1,58 +0,0 @@ - -# Set paths -EXE_DIR = ..\\..\\wsjtx_install -QT_DIR = C:/wsjt-env/Qt5/5.2.1/mingw48_32 -FFTW3_DIR = .. - -INCPATH = -I${QT_DIR}/include/QtCore -I${QT_DIR}/include - -# Compilers -CC = gcc -CXX = g++ -FC = gfortran -AR = ar cr -RANLIB = ranlib -MKDIR = mkdir -p -CP = cp -RM = rm -f - -FFLAGS = -O2 -fbounds-check -Wall -Wno-conversion -CFLAGS = -O2 -I. - -# Default rules -%.o: %.c - ${CC} ${CFLAGS} -c $< -%.o: %.f - ${FC} ${FFLAGS} -c $< -%.o: %.F - ${FC} ${FFLAGS} -c $< -%.o: %.f90 - ${FC} ${FFLAGS} -c $< -%.o: %.F90 - ${FC} ${FFLAGS} -c $< - -all: jt9w - -OBJS1 = jt9w.o smo.o sync9w.o pctile.o shell.o lorentzian.o fchisq0.o \ - softsym9w.o four2a.o interleave9.o jt9fano.o fano232.o packjt.o \ - deg2grid.o grid2deg.o fmtmsg.o db.o decode9w.o - -jt9w: $(OBJS1) - $(FC) -o jt9w $(OBJS1) -lfftw3f - -OBJS2 = t1.o four2a.o db.o -t1: $(OBJS2) - $(FC) -o t1 $(OBJS2) -lfftw3f - -OBJS3 = t2.o four2a.o db.o -t2: $(OBJS3) - $(FC) -o t2 $(OBJS3) -lfftw3f - -OBJS4 = t3.o -t3: $(OBJS4) - $(FC) -o t3 $(OBJS4) -L. -ljt9 C:\JTSDK\fftw3f\libfftw3f-3.dll - -.PHONY : clean - -clean: - $(RM) *.o JTMSKcode JTMSKcode.exe diff --git a/lib/Makefile.jtsdk b/lib/Makefile.jtsdk deleted file mode 100644 index ce113a5..0000000 --- a/lib/Makefile.jtsdk +++ /dev/null @@ -1,137 +0,0 @@ -# Makefile for MinGW on Windows -# Windows re-direct: -# C> make > junk1 2>&1 - -# Set paths -EXE_DIR = ../../wsjtx_install - -INCPATH = -I'C:/JTSDK/Qt5/5.2.1/mingw48_32/include/QtCore' \ - -I'C:/JTSDK/Qt5/5.2.1/mingw48_32/include/' - -# Compilers -CC = c:/JTSDK/Qt5/Tools/mingw48_32/bin/gcc -FC = c:/JTSDK/Qt5/Tools/mingw48_32/bin/gfortran -CXX = c:/JTSDK/Qt5/Tools/mingw48_32/bin/g++ - -FFLAGS = -O3 -Wall -Wno-conversion -fno-second-underscore -DWIN32 -CFLAGS = -I. -DWIN32 - -# Default rules -%.o: %.c - ${CC} ${CFLAGS} -c $< -%.o: %.f - ${FC} ${FFLAGS} -c $< -%.o: %.F - ${FC} ${FFLAGS} -c $< -%.o: %.f90 - ${FC} ${FFLAGS} -c $< -%.o: %.F90 - ${FC} ${FFLAGS} -c $< - -all: libjt9.a libastro.a jt9.exe jt9code.exe jt65code.exe jt9sim.exe - -OBJS1 = pctile.o graycode.o sort.o chkmsg.o \ - unpackmsg.o igray.o unpackcall.o unpackgrid.o \ - grid2k.o unpacktext.o getpfx2.o packmsg.o deg2grid.o \ - packtext.o getpfx1.o packcall.o k2grid.o packgrid.o \ - nchar.o four2a.o grid2deg.o pfxdump.o wisdom.o \ - symspec.o analytic.o db.o genjt9.o flat1.o smo.o \ - packbits.o unpackbits.o encode232.o interleave9.o \ - entail.o fano232.o gran.o sync9.o jt9fano.o \ - fil3.o decoder.o grid2n.o n2grid.o timer.o \ - softsym.o getlags.o afc9.o fchisq.o twkfreq.o downsam9.o \ - peakdt9.o symspec2.o stdmsg.o morse.o azdist.o geodist.o \ - fillcom.o chkss2.o zplot9.o flat2.o \ - jt65a.o symspec65.o flat65.o ccf65.o decode65a.o \ - filbig.o fil6521.o afc65b.o decode65b.o setup65.o \ - extract.o fchisq65.o demod64a.o chkhist.o interleave63.o ccf2.o \ - move.o indexx.o graycode65.o twkfreq65.o smo121.o \ - wrapkarn.o init_rs.o encode_rs.o decode_rs.o gen65.o fil4.o \ - flat4.o polfit.o determ.o baddata.o prog_args.o \ - options.o fmtmsg.o decjt9.o - -libjt9.a: $(OBJS1) - ar cr libjt9.a $(OBJS1) - ranlib libjt9.a - -OBJS2 = jt9.o jt9a.o jt9b.o jt9c.o ipcomm.o sec_midn.o usleep.o -LIBS2 = -L'C:/JTSDK/Qt5/5.2.1/mingw48_32/lib' -lQt5Core -jt9.exe: $(OBJS2) libjt9.a - $(CXX) -o jt9.exe -static $(OBJS2) $(LIBS2) libjt9.a \ - C:\JTSDK\fftw3f\libfftw3f-3.dll -lgfortran -# mkdir -p $(EXE_DIR) - cp jt9.exe $(EXE_DIR) - -OBJS3 = jt9sim.o -jt9sim.exe: $(OBJS3) libjt9.a - $(FC) -o jt9sim.exe $(OBJS3) libjt9.a - -OBJS4 = jt9code.o -jt9code.exe: $(OBJS4) libjt9.a - $(FC) -o jt9code.exe $(OBJS4) libjt9.a - cp jt9code.exe $(EXE_DIR) - -OBJS5 = jt65.o -jt65.exe: $(OBJS5) libjt9.a - $(FC) -o jt65.exe $(OBJS5) libjt9.a ../libfftw3f_win.a - -OBJS7 = astrosub.o astro0.o astro.o tm2.o grid2deg.o sun.o moondop.o \ - coord.o dot.o moon2.o tmoonsub.o toxyz.o geocentric.o \ - dcoord.o - -libastro.a: $(OBJS7) - ar cr libastro.a $(OBJS7) - ranlib libastro.a - -OBJS6 = jt65code.o -jt65code.exe: $(OBJS6) libjt9.a - $(FC) -o jt65code.exe $(OBJS6) libjt9.a - cp jt65code.exe $(EXE_DIR) - -sync9.o: sync9.f90 jt9sync.f90 - $(FC) $(FFLAGS) -c sync9.f90 - -spec9.o: spec9.f90 jt9sync.f90 - $(FC) $(FFLAGS) -c spec9.f90 - -peakdt9.o: peakdt9.f90 jt9sync.f90 - $(FC) $(FFLAGS) -c peakdt9.f90 - -jt9sim.o: jt9sim.f90 jt9sync.f90 - $(FC) $(FFLAGS) -c jt9sim.f90 - -genjt9.o: genjt9.f90 jt9sync.f90 - $(FC) $(FFLAGS) -c genjt9.f90 - -redsync.o: redsync.f90 jt9sync.f90 - $(FC) $(FFLAGS) -c redsync.f90 - -unpackmsg.o: unpackmsg.f90 - $(FC) -c -O0 -fbounds-check -Wall -Wno-precision-loss unpackmsg.f90 - -ipcomm.o: ipcomm.cpp - $(CXX) -c $(INCPATH) ipcomm.cpp - -sec_midn.o: sec_midn.f90 - $(FC) -c -fno-second-underscore sec_midn.f90 - -#rig_control.o: rig_control.c -# $(CC) -c -Wall -I..\..\..\hamlib-1.2.15.3\include rig_control.c - -tstrig.o: tstrig.c - $(CC) -c -Wall -I..\..\..\hamlib-1.2.15.3\include tstrig.c - -init_rs.o: init_rs.c - $(CC) -c -DBIGSYM=1 -o init_rs.o init_rs.c - -encode_rs.o: encode_rs.c - $(CC) -c -DBIGSYM=1 -o encode_rs.o encode_rs.c - -decode_rs.o: decode_rs.c - $(CC) -c -DBIGSYM=1 -o decode_rs.o decode_rs.c - - -.PHONY : clean - -clean: - rm -f *.o libjt9.a wsjtx.exe jt9sim.exe jt9.exe jt65.exe diff --git a/lib/Makefile.linux b/lib/Makefile.linux deleted file mode 100644 index 14bc077..0000000 --- a/lib/Makefile.linux +++ /dev/null @@ -1,115 +0,0 @@ -# Set paths -EXE_DIR = ../../wsjtx_install -QT_DIR = /usr/include/qt5 -INCPATH = -I${QT_DIR} -I${QT_DIR}/QtCore - -CC = gcc -CXX = g++ -FC = gfortran -AR = ar cr -MKDIR = mkdir -p -CP = cp -RANLIB = ranlib -RM = rm -f - -FFLAGS = -O3 -funroll-loops -Wall -Wno-conversion -fno-second-underscore -DUNIX -CFLAGS = -I. -fbounds-check -fPIE - -# Default rules -%.o: %.c - ${CC} ${CFLAGS} -c $< -%.o: %.f - ${FC} ${FFLAGS} -c $< -%.o: %.F - ${FC} ${FFLAGS} -c $< -%.o: %.f90 - ${FC} ${FFLAGS} -c $< -%.o: %.F90 - ${FC} ${FFLAGS} -c $< - -all: libjt9.a jt9sim jt9 jt9code jt65code - -OBJS1 = astrosub.o astro0.o astro.o tm2.o sun.o moondop.o coord.o tmoonsub.o \ - fmtmsg.o geocentric.o moon2.o toxyz.o dot.o dcoord.o \ - prog_args.o options.o pctile.o graycode.o sort.o chkmsg.o \ - unpackmsg.o igray.o unpackcall.o unpackgrid.o \ - grid2k.o unpacktext.o getpfx2.o packmsg.o deg2grid.o \ - packtext.o getpfx1.o packcall.o k2grid.o packgrid.o \ - nchar.o four2a.o grid2deg.o pfxdump.o wisdom.o \ - symspec.o analytic.o db.o genjt9.o jt9fano.o \ - packbits.o unpackbits.o encode232.o interleave9.o \ - entail.o fano232.o gran.o sync9.o decjt9.o \ - fil3.o decoder.o grid2n.o n2grid.o timer.o \ - softsym.o peakdt9.o getlags.o afc9.o fchisq.o \ - twkfreq.o downsam9.o symspec2.o ipcomm.o sleep_msec.o \ - stdmsg.o sec_midn.o usleep.o azdist.o geodist.o morse.o \ - fillcom.o chkss2.o zplot9.o flat1.o flat2.o \ - jt65a.o symspec65.o flat65.o ccf65.o decode65a.o \ - filbig.o fil6521.o afc65b.o decode65b.o setup65.o \ - extract.o fchisq65.o demod64a.o chkhist.o interleave63.o ccf2.o \ - move.o indexx.o graycode65.o twkfreq65.o smo.o smo121.o \ - wrapkarn.o init_rs.o encode_rs.o decode_rs.o gen65.o fil4.o \ - flat4.o polfit.o determ.o baddata.o - -libjt9.a: $(OBJS1) - $(AR) libjt9.a $(OBJS1) - $(RANLIB) libjt9.a - -OBJS2 = jt9.o jt9a.o jt9b.o jt9c.o - -jt9: $(OBJS2) libjt9.a - $(CXX) -o jt9 $(OBJS2) -L. -ljt9 -lQt5Core -lfftw3f_threads -lfftw3f `$(FC) -print-file-name=libgfortran.so` - $(MKDIR) -p $(EXE_DIR) - $(CP) jt9 $(EXE_DIR) - -OBJS3 = jt9sim.o -jt9sim: $(OBJS3) libjt9.a - $(FC) -o jt9sim $(OBJS3) -L. -ljt9 - -OBJS4 = jt9code.o -jt9code: $(OBJS4) libjt9.a - $(FC) -o jt9code $(OBJS4) -L. -ljt9 - $(CP) jt9code $(EXE_DIR) - -OBJS6 = jt65code.o -jt65code: $(OBJS6) libjt9.a - $(FC) -o jt65code $(OBJS6) libjt9.a - $(CP) jt65code $(EXE_DIR) - -sync9.o: sync9.f90 jt9sync.f90 - $(FC) $(FFLAGS) -c sync9.f90 - -peakdf9.o: peakdf9.f90 jt9sync.f90 - $(FC) $(FFLAGS) -c peakdf9.f90 - -peakdt9.o: peakdt9.f90 jt9sync.f90 - $(FC) $(FFLAGS) -c peakdt9.f90 - -jt9sim.o: jt9sim.f90 jt9sync.f90 - $(FC) $(FFLAGS) -c jt9sim.f90 - -genjt9.o: genjt9.f90 jt9sync.f90 - $(FC) $(FFLAGS) -c genjt9.f90 - -redsync.o: redsync.f90 jt9sync.f90 - $(FC) $(FFLAGS) -c redsync.f90 - -ipcomm.o: ipcomm.cpp - $(CXX) -c $(INCPATH) -fPIE ipcomm.cpp - -sec_midn.o: sec_midn.f90 - $(FC) -c -fno-second-underscore sec_midn.f90 - -init_rs.o: init_rs.c - $(CC) -c -DBIGSYM=1 -o init_rs.o init_rs.c - -encode_rs.o: encode_rs.c - $(CC) -c -DBIGSYM=1 -o encode_rs.o encode_rs.c - -decode_rs.o: decode_rs.c - $(CC) -c -DBIGSYM=1 -o decode_rs.o decode_rs.c - -.PHONY : clean - -clean: - $(RM) *.o libjt9.a wsjtx jt9sim jt9 jt9code diff --git a/lib/Makefile.msk b/lib/Makefile.msk deleted file mode 100644 index 333b36c..0000000 --- a/lib/Makefile.msk +++ /dev/null @@ -1,71 +0,0 @@ - -# Set paths -EXE_DIR = ..\\..\\wsjtx_install -QT_DIR = C:/wsjt-env/Qt5/5.2.1/mingw48_32 -FFTW3_DIR = .. - -INCPATH = -I${QT_DIR}/include/QtCore -I${QT_DIR}/include - -# Compilers -CC = gcc -CXX = g++ -FC = gfortran -AR = ar cr -RANLIB = ranlib -MKDIR = mkdir -p -CP = cp -RM = rm -f - -FFLAGS = -O2 -fbounds-check -Wall -Wno-conversion -CFLAGS = -O2 -I. - -# Default rules -%.o: %.c - ${CC} ${CFLAGS} -c $< -%.o: %.f - ${FC} ${FFLAGS} -c $< -%.o: %.F - ${FC} ${FFLAGS} -c $< -%.o: %.f90 - ${FC} ${FFLAGS} -c $< -%.o: %.F90 - ${FC} ${FFLAGS} -c $< - -#all: jt9code JTMSKcode -all: jtmsk JTMSKcode - -OBJS4 = jt9code.o packjt.o fmtmsg.o gen9.o deg2grid.o grid2deg.o \ - entail.o encode232.o interleave9.o graycode.o igray.o -jt9code: $(OBJS4) - $(FC) -o jt9code $(OBJS4) - -OBJS5 = JTMSKcode.o packjt.o fmtmsg.o genmsk.o deg2grid.o grid2deg.o \ - entail.o nhash.o tab.o vit213.o -JTMSKcode: $(OBJS5) - $(FC) -o JTMSKcode $(OBJS5) - -OBJS6 = jtmsk.o jtmsk.o analytic.o four2a.o db.o mskdf.o pctile.o \ - sort.o tweak1.o syncmsk.o genmsk.o packjt.o fmtmsg.o indexx.o \ - deg2grid.o grid2deg.o entail.o nhash.o tab.o vit213.o -jtmsk: $(OBJS6) - $(FC) -o jtmsk $(OBJS6) -lfftw3f - -OBJS1 = t1.o four2a.o db.o -t1: $(OBJS1) - $(FC) -o t1 $(OBJS1) -lfftw3f - -OBJS2 = t2.o four2a.o db.o -t2: $(OBJS2) - $(FC) -o t2 $(OBJS2) -lfftw3f - -OBJS6 = t6.o four2a.o db.o -t6: $(OBJS6) - $(FC) -o t6 $(OBJS6) -lfftw3f - -nhash.o: wsprd/nhash.h wsprd/nhash.c - $(CC) -c -O2 wsprd/nhash.c - -.PHONY : clean - -clean: - $(RM) *.o JTMSKcode JTMSKcode.exe diff --git a/lib/Makefile.mskWin b/lib/Makefile.mskWin deleted file mode 100644 index 9d5e6e6..0000000 --- a/lib/Makefile.mskWin +++ /dev/null @@ -1,75 +0,0 @@ - -# Set paths -EXE_DIR = ..\\..\\wsjtx_install -QT_DIR = C:/wsjt-env/Qt5/5.2.1/mingw48_32 -FFTW3_DIR = .. - -INCPATH = -I${QT_DIR}/include/QtCore -I${QT_DIR}/include - -# Compilers -CC = gcc -CXX = g++ -FC = gfortran -AR = ar cr -RANLIB = ranlib -MKDIR = mkdir -p -CP = cp -RM = rm -f - -FFLAGS = -O2 -fbounds-check -Wall -Wno-conversion -CFLAGS = -O2 -I. - -# Default rules -%.o: %.c - ${CC} ${CFLAGS} -c $< -%.o: %.f - ${FC} ${FFLAGS} -c $< -%.o: %.F - ${FC} ${FFLAGS} -c $< -%.o: %.f90 - ${FC} ${FFLAGS} -c $< -%.o: %.F90 - ${FC} ${FFLAGS} -c $< - -#all: jt9code JTMSKcode.exe -all: jtmsk.exe JTMSKsim.exe JTMSKcode.exe fixwav.exe - -OBJS3 = JTMSKsim.o wavhdr.o gran.o four2a.o db.o -JTMSKsim.exe: $(OBJS3) - $(FC) -o JTMSKsim.exe $(OBJS3) C:\JTSDK\fftw3f\libfftw3f-3.dll - -OBJS4 = jt9code.o packjt.o fmtmsg.o gen9.o deg2grid.o grid2deg.o \ - entail.o encode232.o interleave9.o graycode.o igray.o -jt9code: $(OBJS4) - $(FC) -o jt9code $(OBJS4) - -OBJS5 = JTMSKcode.o packjt.o fmtmsg.o genmsk.o deg2grid.o grid2deg.o \ - entail.o tab.o vit213.o hashing.o nhash.o -JTMSKcode.exe: $(OBJS5) - $(FC) -o JTMSKcode.exe $(OBJS5) - -OBJS6 = jtmsk.o analytic.o four2a.o db.o pctile.o \ - shell.o tweak1.o syncmsk.o genmsk.o packjt.o fmtmsg.o indexx.o \ - deg2grid.o grid2deg.o entail.o hashing.o nhash.o tab.o vit213.o \ - mskdt.o rectify_msk.o timer.o jtmsk_decode.o genmsk_short.o \ - jtmsk_short.o golay24_table.o hash.o - -jtmsk.exe: $(OBJS6) - $(FC) -o jtmsk.exe $(OBJS6) C:\JTSDK\fftw3f\libfftw3f-3.dll - -OBJS1 = fixwav.o wavhdr.o -fixwav.exe: $(OBJS1) - $(FC) -o fixwav.exe $(OBJS1) - -OBJS2 = t2.o four2a.o db.o -t2: $(OBJS2) - $(FC) -o t2 $(OBJS2) C:\JTSDK\fftw3f\libfftw3f-3.dll - -OBJS6 = t6.o four2a.o db.o -t6: $(OBJS6) - $(FC) -o t6 $(OBJS6) C:\JTSDK\fftw3f\libfftw3f-3.dll - -.PHONY : clean - -clean: - $(RM) *.o JTMSKcode JTMSKcode.exe diff --git a/lib/allsim.f90 b/lib/allsim.f90 deleted file mode 100644 index 2d948b6..0000000 --- a/lib/allsim.f90 +++ /dev/null @@ -1,78 +0,0 @@ -program allsim - -! Generate simulated data for WSJT-X slow modes: JT4, JT9, JT65, QRA64, -! and WSPR. Also unmodulated carrier and 20 WPM CW. - - - use wavhdr - use packjt - parameter (NMAX=60*12000) - type(hdr) h - integer*2 iwave(NMAX) !Generated waveform (no noise) - integer itone(206) !Channel symbols (values 0-8) - integer icw(250) - integer*1 msgbits(87) - logical*1 bcontest - real*4 dat(NMAX) - character message*22,msgsent*22,arg*8,mygrid*6 - - nargs=iargc() - if(nargs.ne.1) then - print*,'Usage: allsim ' - go to 999 - endif - - call getarg(1,arg) - read(arg,*) snrdb !S/N in dB (2500 hz reference BW) - - message='CQ KA2ABC FN20' - mygrid='FN20 ' - bcontest=.false. - rmsdb=25. - rms=10.0**(0.05*rmsdb) - sig=10.0**(0.05*snrdb) - npts=NMAX - - call init_random_seed() !Seed Fortran RANDOM_NUMBER generator - call sgran() !Seed C rand generator (used in gran) - - h=default_header(12000,npts) - open(10,file='000000_0000.wav',access='stream',status='unknown') - do i=1,npts !Generate gaussian noise - dat(i)=gran() - enddo - - itone=0 - call addit(itone,12000,85,6912,400,sig,dat) !Unmodulated carrier - - call morse('CQ CQ DE KA2ABC KA2ABC',icw,ncw) -! print*,ncw -! write(*,3001) icw(1:ncw) -!3001 format(50i1) - call addcw(icw,ncw,600,sig,dat) !CW - - call genwspr(message,msgsent,itone) - call addit(itone,12000,86,8192,800,sig,dat) !WSPR (only 59 s of data) - - call gen9(message,0,msgsent,itone,itype) - call addit(itone,12000,85,6912,1000,sig,dat) !JT9 - - call gen4(message,0,msgsent,itone,itype) - call addit(itone,11025,206,2520,1200,sig,dat) !JT4 - - i3bit=0 ! ### TEMPORARY ??? ### - call genft8(message,mygrid,bcontest,i3bit,msgsent,msgbits,itone) - call addit(itone,12000,79,1920,1400,sig,dat) !FT8 - - call genqra64(message,0,msgsent,itone,itype) - call addit(itone,12000,84,6912,1600,sig,dat) !QRA64 - - call gen65(message,0,msgsent,itone,itype) - call addit(itone,11025,126,4096,1800,sig,dat) !JT65 - - iwave(1:npts)=nint(rms*dat(1:npts)) - - write(10) h,iwave(1:npts) - close(10) - -999 end program allsim diff --git a/lib/chkfft.txt b/lib/chkfft.txt deleted file mode 100644 index 970d7a7..0000000 --- a/lib/chkfft.txt +++ /dev/null @@ -1,124 +0,0 @@ - Brief Description of chkfft, by K1JT - ------------------------------------ - -Discrete Fourier transforms (DFTs) are found at the root of most -digital signal processing tasks. In WSJT and its sister programs the -transforms are done using the FFTW library, and subroutine four2 -provides a convenient interface to the library. Program chkfft is a -command-line utility offering a convenient way to test FFT execution -times under a variety of circumstances. - -To compile chkfft in Linux: - -$ gfortran -o chkfft chkfft.f90 four2a.f90 f77_wisdom.f90 gran.c -lfftw3f - -To compile chkfft in Windows (you may need to customize the hard-coded -path shown here for libfftw3f-3.dll): - -> gfortran -o chkfft chkfft.f90 four2a.f90 f77_wisdom.f90 gran.c \ - /JTSDK-QT/appsupport/runtime/libfftw3f-3.dll - -To see a brief usage message, type chkfft at the command prompt: - -$ chkfft - Usage: chkfft nr nw nc np - nfft: length of FFT - nfft=0: do lengths 2^n, n=2^4 to 2^23 - infile: name of file with nfft values, one per line - nr: 0/1 to not read (or read) wisdom - nw: 0/1 to not write (or write) wisdom - nc: 0/1 for real or complex data - np: 0-4 patience for finding best algorithm - -As an example, to measure the speed of a complex DFT of length 131072: - -####################################################################### -$ chkfft 131072 0 1 1 2 - -nfft: 131072 nr: 0 nw 1 nc: 1 np: 2 - - NFFT Time rms MHz MFlops iters tplan -------------------------------------------------------------- - 131072 0.0021948 0.00000032 59.72 5076.1 231 2.9 -####################################################################### - -Program output shows that on the test machine the average time for one -forward (or inverse) transform of length N=131072 is about 2.2 ms, -corresponding to slightly over 5 GFlops computing speed. The planning -time in FFTW was 2.9 s. - -Running the command again with parameter nr=1 will use the -"wisdom" already accumulated for complex N=131072 FFTs. The execution -speed will be essentially the same, but no planning time is required: - -####################################################################### -$ chkfft 131072 1 1 1 2 - -nfft: 131072 nr: 1 nw 1 nc: 1 np: 2 - - NFFT Time rms MHz MFlops iters tplan -------------------------------------------------------------- - 131072 0.0021575 0.00000032 60.75 5164.0 235 0.0 -####################################################################### - -Optimized algorithms can compute DFTs much faster for lengths that are -the product of small integers. Length N=131072 = 2^17 is a good -example, and FFTs should be very efficient. For comparison, look at -the speed for N=131071, a prime number. The average time is now about -7 times larger: - -####################################################################### -C:\JTSDK-QT\src\wsjtx\lib>chkfft 131071 1 1 1 2 - -nfft: 131071 nr: 1 nw 1 nc: 1 np: 2 - - NFFT Time rms MHz MFlops iters tplan -------------------------------------------------------------- - 131071 0.0153637 0.00000065 8.53 725.2 33 5.6 -####################################################################### - -Here's an example that measures execution times for all integral -power-of-2 lengths from 2^4 to 2^23: - -####################################################################### -$ chkfft 0 1 1 1 2 - -nfft: 0 nr: 1 nw 1 nc: 1 np: 2 - - n N=2^n Time rms MHz MFlops iters tplan ---------------------------------------------------------------- - 4 16 0.0000003 0.00000014 58.61 1172.2 1000000 0.0 - 5 32 0.0000004 0.00000016 89.19 2229.6 1000000 0.0 - 6 64 0.0000006 0.00000016 109.44 3283.2 866975 0.0 - 7 128 0.0000009 0.00000021 135.92 4757.1 538369 0.0 - 8 256 0.0000016 0.00000020 158.40 6335.8 313701 0.0 - 9 512 0.0000032 0.00000021 162.53 7313.8 160943 0.1 -10 1024 0.0000067 0.00000023 152.53 7626.5 75521 0.1 -11 2048 0.0000136 0.00000025 150.42 8273.3 37239 0.2 -12 4096 0.0000316 0.00000027 129.75 7784.8 16060 0.3 -13 8192 0.0000720 0.00000026 113.75 7393.8 7040 0.5 -14 16384 0.0001620 0.00000028 101.11 7078.0 3129 0.9 -15 32768 0.0003227 0.00000030 101.53 7615.1 1571 1.7 -16 65536 0.0010020 0.00000030 65.41 5232.5 506 4.1 -17 131072 0.0021575 0.00000032 60.75 5164.0 235 0.0 -18 262144 0.0053937 0.00000032 48.60 4374.2 94 3.6 -19 524288 0.0190668 0.00000034 27.50 2612.2 27 6.8 -20 1048576 0.0468001 0.00000035 22.41 2240.5 11 2.4 -21 2097152 0.0936012 0.00000036 22.41 2352.5 6 31.6 -22 4194304 0.1949997 0.00000037 21.51 2366.0 3 9.8 -23 8388608 0.4212036 0.00000038 19.92 2290.3 2 112.9 -####################################################################### - -Test data for all transforms is gaussian random noise of zero mean and -standard deviation 1. Tabulated values of "rms" are the -root-mean-square differences between the original data and the -back-transfmred data. - -File nfft.dat contains all numbers between 2^3 and 2^23 with no factor -greater than 7, followed by their factors. These numbers are good -choices for FFT lengths. File all_fft.out gives the result on one -machine of running the command - -$ chkfft nfft.dat 0 1 1 2 - -Take note: this task may take as much as 24 hours, or even more! diff --git a/lib/decoder.f90 b/lib/decoder.f90 index 79d8c9d..204fa1d 100644 --- a/lib/decoder.f90 +++ b/lib/decoder.f90 @@ -3,43 +3,42 @@ subroutine multimode_decoder(ss,id2,params,nfsample) !$ use omp_lib use prog_args use timer_module, only: timer - use jt4_decode - use jt65_decode - use jt9_decode use ft8_decode + use js8b_decode + use js8c_decode + use js8d_decode include 'jt9com.f90' include 'timer_common.inc' - type, extends(jt4_decoder) :: counting_jt4_decoder - integer :: decoded - end type counting_jt4_decoder - - type, extends(jt65_decoder) :: counting_jt65_decoder - integer :: decoded - end type counting_jt65_decoder - - type, extends(jt9_decoder) :: counting_jt9_decoder - integer :: decoded - end type counting_jt9_decoder - type, extends(ft8_decoder) :: counting_ft8_decoder integer :: decoded end type counting_ft8_decoder + type, extends(js8b_decoder) :: counting_js8b_decoder + integer :: decoded + end type counting_js8b_decoder + + type, extends(js8c_decoder) :: counting_js8c_decoder + integer :: decoded + end type counting_js8c_decoder + + type, extends(js8d_decoder) :: counting_js8d_decoder + integer :: decoded + end type counting_js8d_decoder + real ss(184,NSMAX) - logical baddata,newdat65,newdat9,single_decode,bVHF,bad0,newdat,ex + logical baddata,newdat65,newdat9,single_decode,bVHF,bad0,newdat integer*2 id2(NTMAX*12000) type(params_block) :: params - real*4 dd(NTMAX*12000) character(len=20) :: datetime character(len=12) :: mycall, hiscall character(len=6) :: mygrid, hisgrid save - type(counting_jt4_decoder) :: my_jt4 - type(counting_jt65_decoder) :: my_jt65 - type(counting_jt9_decoder) :: my_jt9 - type(counting_ft8_decoder) :: my_ft8 + type(counting_ft8_decoder) :: my_js8a + type(counting_js8b_decoder) :: my_js8b + type(counting_js8c_decoder) :: my_js8c + type(counting_js8d_decoder) :: my_js8d !cast C character arrays to Fortran character strings datetime=transfer(params%datetime, datetime) @@ -49,10 +48,10 @@ subroutine multimode_decoder(ss,id2,params,nfsample) hisgrid=transfer(params%hisgrid,hisgrid) ! initialize decode counts - my_jt4%decoded = 0 - my_jt65%decoded = 0 - my_jt9%decoded = 0 - my_ft8%decoded = 0 + my_js8a%decoded = 0 + my_js8b%decoded = 0 + my_js8c%decoded = 0 + my_js8d%decoded = 0 single_decode=iand(params%nexp_decode,32).ne.0 bVHF=iand(params%nexp_decode,64).ne.0 @@ -79,20 +78,55 @@ subroutine multimode_decoder(ss,id2,params,nfsample) endif endif - if(params%nmode.eq.8) then -! We're in FT8 mode - call timer('decft8 ',0) + if(params%nmode.eq.8 .and. params%nsubmode.eq.3) then +! We're in JS8 mode C + call timer('decjs8d ',0) newdat=params%newdat - call my_ft8%decode(ft8_decoded,id2,params%nQSOProgress,params%nfqso, & + call my_js8d%decode(js8d_decoded,id2,params%nQSOProgress,params%nfqso, & params%nftx,newdat,params%nutc,params%nfa,params%nfb, & params%nexp_decode,params%ndepth,logical(params%nagain), & logical(params%lft8apon),logical(params%lapcqonly),params%napwid, & mycall,mygrid,hiscall,hisgrid) - call timer('decft8 ',1) - if(nfox.gt.0) then - n30min=minval(n30fox(1:nfox)) - n30max=maxval(n30fox(1:nfox)) - endif + call timer('decjs8d ',1) + go to 800 + endif + + if(params%nmode.eq.8 .and. params%nsubmode.eq.2) then +! We're in JS8 mode C + call timer('decjs8c ',0) + newdat=params%newdat + call my_js8c%decode(js8c_decoded,id2,params%nQSOProgress,params%nfqso, & + params%nftx,newdat,params%nutc,params%nfa,params%nfb, & + params%nexp_decode,params%ndepth,logical(params%nagain), & + logical(params%lft8apon),logical(params%lapcqonly),params%napwid, & + mycall,mygrid,hiscall,hisgrid) + call timer('decjs8c ',1) + go to 800 + endif + + if(params%nmode.eq.8 .and. params%nsubmode.eq.1) then +! We're in JS8 mode B + call timer('decjs8b ',0) + newdat=params%newdat + call my_js8b%decode(js8b_decoded,id2,params%nQSOProgress,params%nfqso, & + params%nftx,newdat,params%nutc,params%nfa,params%nfb, & + params%nexp_decode,params%ndepth,logical(params%nagain), & + logical(params%lft8apon),logical(params%lapcqonly),params%napwid, & + mycall,mygrid,hiscall,hisgrid) + call timer('decjs8b ',1) + go to 800 + endif + + if(params%nmode.eq.8) then +! We're in JS8 mode A + call timer('decjs8a ',0) + newdat=params%newdat + call my_js8a%decode(js8a_decoded,id2,params%nQSOProgress,params%nfqso, & + params%nftx,newdat,params%nutc,params%nfa,params%nfb, & + params%nexp_decode,params%ndepth,logical(params%nagain), & + logical(params%lft8apon),logical(params%lapcqonly),params%napwid, & + mycall,mygrid,hiscall,hisgrid) + call timer('decjs8a ',1) go to 800 endif @@ -122,27 +156,7 @@ subroutine multimode_decoder(ss,id2,params,nfsample) ! id2(1:nz)=0 ! temporarily disabled as it can breaak the JT9 decoder, maybe others endif - if(params%nmode.eq.4 .or. params%nmode.eq.65) open(14,file=trim(temp_dir)// & - '/avemsg.txt',status='unknown') - if(params%nmode.eq.164) open(17,file=trim(temp_dir)//'/red.dat', & - status='unknown') - - if(params%nmode.eq.4) then - jz=52*nfsample - if(params%newdat) then - if(nfsample.eq.12000) call wav11(id2,jz,dd) - if(nfsample.eq.11025) dd(1:jz)=id2(1:jz) - endif - call my_jt4%decode(jt4_decoded,dd,jz,params%nutc,params%nfqso, & - params%ntol,params%emedelay,params%dttol,logical(params%nagain), & - params%ndepth,logical(params%nclearave),params%minsync, & - params%minw,params%nsubmode,mycall,hiscall, & - hisgrid,params%nlist,params%listutc,jt4_average) - go to 800 - endif - npts65=52*12000 - if(params%nmode.eq.164) npts65=54*12000 if(baddata(id2,npts65)) then nsynced=0 ndecoded=0 @@ -154,268 +168,25 @@ subroutine multimode_decoder(ss,id2,params,nfsample) newdat9=params%newdat !$call omp_set_dynamic(.true.) -!$omp parallel sections num_threads(2) copyin(/timer_private/) shared(ndecoded) if(.true.) !iif() needed on Mac -!$omp section - if(params%nmode.eq.65 .or. params%nmode.eq.164 .or. & - (params%nmode.eq.(65+9) .and. params%ntxmode.eq.65)) then -! We're in JT65 or QRA64 mode, or should do JT65 first - - if(newdat65) dd(1:npts65)=id2(1:npts65) - nf1=params%nfa - nf2=params%nfb - call timer('jt65a ',0) - call my_jt65%decode(jt65_decoded,dd,npts65,newdat65,params%nutc, & - nf1,nf2,params%nfqso,ntol65,params%nsubmode,params%minsync, & - logical(params%nagain),params%n2pass,logical(params%nrobust), & - ntrials,params%naggressive,params%ndepth,params%emedelay, & - logical(params%nclearave),mycall,hiscall, & - hisgrid,params%nexp_decode,params%nQSOProgress, & - logical(params%ljt65apon)) - call timer('jt65a ',1) - - else if(params%nmode.eq.9 .or. (params%nmode.eq.(65+9) .and. params%ntxmode.eq.9)) then -! We're in JT9 mode, or should do JT9 first - call timer('decjt9 ',0) - call my_jt9%decode(jt9_decoded,ss,id2,params%nfqso, & - newdat9,params%npts8,params%nfa,params%nfsplit,params%nfb, & - params%ntol,params%nzhsym,logical(params%nagain),params%ndepth, & - params%nmode,params%nsubmode,params%nexp_decode) - call timer('decjt9 ',1) - endif - -!$omp section - if(params%nmode.eq.(65+9)) then !Do the other mode (we're in dual mode) - if (params%ntxmode.eq.9) then - if(newdat65) dd(1:npts65)=id2(1:npts65) - nf1=params%nfa - nf2=params%nfb - call timer('jt65a ',0) - call my_jt65%decode(jt65_decoded,dd,npts65,newdat65,params%nutc, & - nf1,nf2,params%nfqso,ntol65,params%nsubmode,params%minsync, & - logical(params%nagain),params%n2pass,logical(params%nrobust), & - ntrials,params%naggressive,params%ndepth,params%emedelay, & - logical(params%nclearave),mycall,hiscall, & - hisgrid,params%nexp_decode,params%nQSOProgress, & - logical(params%ljt65apon)) - call timer('jt65a ',1) - else - call timer('decjt9 ',0) - call my_jt9%decode(jt9_decoded,ss,id2,params%nfqso, & - newdat9,params%npts8,params%nfa,params%nfsplit,params%nfb, & - params%ntol,params%nzhsym,logical(params%nagain), & - params%ndepth,params%nmode,params%nsubmode,params%nexp_decode) - call timer('decjt9 ',1) - end if - endif - -!$omp end parallel sections - -! JT65 is not yet producing info for nsynced, ndecoded. -800 ndecoded = my_jt4%decoded + my_jt65%decoded + my_jt9%decoded + my_ft8%decoded +800 ndecoded = my_js8a%decoded + my_js8b%decoded + my_js8c%decoded write(*,1010) nsynced,ndecoded 1010 format('',2i4) call flush(6) - if(params%nmode.eq.4 .or. params%nmode.eq.65) close(14) - return contains - subroutine jt4_decoded(this,snr,dt,freq,have_sync,sync,is_deep, & - decoded0,qual,ich,is_average,ave) - implicit none - class(jt4_decoder), intent(inout) :: this - integer, intent(in) :: snr - real, intent(in) :: dt - integer, intent(in) :: freq - logical, intent(in) :: have_sync - logical, intent(in) :: is_deep - character(len=1), intent(in) :: sync - character(len=22), intent(in) :: decoded0 - real, intent(in) :: qual - integer, intent(in) :: ich - logical, intent(in) :: is_average - integer, intent(in) :: ave - - character*22 decoded - character*3 cflags - - if(ich.eq.-99) stop !Silence compiler warning - if (have_sync) then - decoded=decoded0 - cflags=' ' - if(decoded.ne.' ') cflags='f ' - if(is_deep) then - cflags(1:2)='d1' - write(cflags(3:3),'(i1)') min(int(qual),9) - if(qual.ge.10.0) cflags(3:3)='*' - if(qual.lt.3.0) decoded(22:22)='?' - endif - if(is_average) then - write(cflags(2:2),'(i1)') min(ave,9) - if(ave.ge.10) cflags(2:2)='*' - endif - write(*,1000) params%nutc,snr,dt,freq,sync,decoded,cflags -1000 format(i4.4,i4,f5.1,i5,1x,'$',a1,1x,a22,1x,a3) - else - write(*,1000) params%nutc,snr,dt,freq - end if - - select type(this) - type is (counting_jt4_decoder) - this%decoded = this%decoded + 1 - end select - end subroutine jt4_decoded - - subroutine jt4_average (this, used, utc, sync, dt, freq, flip) - implicit none - class(jt4_decoder), intent(inout) :: this - logical, intent(in) :: used - integer, intent(in) :: utc - real, intent(in) :: sync - real, intent(in) :: dt - integer, intent(in) :: freq - logical, intent(in) :: flip - character(len=1) :: cused, csync - - cused = '.' - csync = '*' - if (used) cused = '$' - if (flip) csync = '$' - write(14,1000) cused,utc,sync,dt,freq,csync -1000 format(a1,i5.4,f6.1,f6.2,i6,1x,a1) - end subroutine jt4_average - - subroutine jt65_decoded(this,sync,snr,dt,freq,drift,nflip,width, & - decoded0,ft,qual,nsmo,nsum,minsync) - - use jt65_decode + subroutine js8_decoded (sync,snr,dt,freq,decoded,nap,qual) implicit none - class(jt65_decoder), intent(inout) :: this - real, intent(in) :: sync - integer, intent(in) :: snr - real, intent(in) :: dt - integer, intent(in) :: freq - integer, intent(in) :: drift - integer, intent(in) :: nflip - real, intent(in) :: width - character(len=22), intent(in) :: decoded0 - integer, intent(in) :: ft - integer, intent(in) :: qual - integer, intent(in) :: nsmo - integer, intent(in) :: nsum - integer, intent(in) :: minsync - - integer i,nap,nft - logical is_deep,is_average - character decoded*22,csync*2,cflags*3 - - if(width.eq.-9999.0) stop !Silence compiler warning -!$omp critical(decode_results) - decoded=decoded0 - cflags=' ' - is_deep=ft.eq.2 - - if(ft.ge.80) then !QRA64 mode - nft=ft-100 - csync=': ' - if(sync-3.4.ge.float(minsync) .or. nft.ge.0) csync=':*' - if(nft.lt.0) then - write(*,1009) params%nutc,snr,dt,freq,csync,decoded - else - write(*,1009) params%nutc,snr,dt,freq,csync,decoded,nft -1009 format(i4.4,i4,f5.1,i5,1x,a2,1x,a22,i2) - endif - go to 100 - endif - - if(ft.eq.0 .and. minsync.ge.0 .and. int(sync).lt.minsync) then - write(*,1010) params%nutc,snr,dt,freq - else - is_average=nsum.ge.2 - if(bVHF .and. ft.gt.0) then - cflags='f ' - if(is_deep) then - cflags(1:2)='d1' - write(cflags(3:3),'(i1)') min(qual,9) - if(qual.ge.10) cflags(3:3)='*' - if(qual.lt.3) decoded(22:22)='?' - endif - if(is_average) then - write(cflags(2:2),'(i1)') min(nsum,9) - if(nsum.ge.10) cflags(2:2)='*' - endif - nap=ishft(ft,-2) - if(nap.ne.0) then - write(cflags(1:3),'(a1,i1)') 'a',nap - endif - endif - csync='# ' - i=0 - if(bVHF .and. nflip.ne.0 .and. & - sync.ge.max(0.0,float(minsync))) then - csync='#*' - if(nflip.eq.-1) then - csync='##' - if(decoded.ne.' ') then - do i=22,1,-1 - if(decoded(i:i).ne.' ') exit - enddo - if(i.gt.18) i=18 - decoded(i+2:i+4)='OOO' - endif - endif - endif - write(*,1010) params%nutc,snr,dt,freq,csync,decoded,cflags -1010 format(i4.4,i4,f5.1,i5,1x,a2,1x,a22,1x,a3) - endif - -100 call flush(6) - -!$omp end critical(decode_results) - select type(this) - type is (counting_jt65_decoder) - this%decoded = this%decoded + 1 - end select - end subroutine jt65_decoded - - subroutine jt9_decoded (this, sync, snr, dt, freq, drift, decoded) - use jt9_decode - implicit none - - class(jt9_decoder), intent(inout) :: this - real, intent(in) :: sync - integer, intent(in) :: snr - real, intent(in) :: dt - real, intent(in) :: freq - integer, intent(in) :: drift - character(len=22), intent(in) :: decoded - - !$omp critical(decode_results) - write(*,1000) params%nutc,snr,dt,nint(freq),decoded -1000 format(i4.4,i4,f5.1,i5,1x,'@ ',1x,a22) - call flush(6) - !$omp end critical(decode_results) - select type(this) - type is (counting_jt9_decoder) - this%decoded = this%decoded + 1 - end select - end subroutine jt9_decoded - - subroutine ft8_decoded (this,sync,snr,dt,freq,decoded,nap,qual) - use ft8_decode - implicit none - - class(ft8_decoder), intent(inout) :: this real, intent(in) :: sync integer, intent(in) :: snr real, intent(in) :: dt real, intent(in) :: freq character(len=37), intent(in) :: decoded - character c1*12,c2*12,g2*4,w*4,ctmp*12 - integer i0,i1,i2,i3,i4,i5,i6,n30,nwrap + character c1*12,c2*12,g2*4,w*4 + integer i0,i1,i2,i3,i4,i5,n30,nwrap integer, intent(in) :: nap real, intent(in) :: qual character*2 annot @@ -488,12 +259,103 @@ contains call flush(6) + return + end subroutine js8_decoded + + subroutine js8a_decoded (this,sync,snr,dt,freq,decoded,nap,qual) + use ft8_decode + implicit none + + class(ft8_decoder), intent(inout) :: this + real, intent(in) :: sync + integer, intent(in) :: snr + real, intent(in) :: dt + real, intent(in) :: freq + character(len=37), intent(in) :: decoded + integer, intent(in) :: nap + real, intent(in) :: qual + save + + call js8_decoded(sync, snr, dt, freq, decoded, nap, qual) + select type(this) type is (counting_ft8_decoder) this%decoded = this%decoded + 1 end select return - end subroutine ft8_decoded + end subroutine js8a_decoded + + subroutine js8b_decoded (this,sync,snr,dt,freq,decoded,nap,qual) + use js8b_decode + implicit none + + class(js8b_decoder), intent(inout) :: this + real, intent(in) :: sync + integer, intent(in) :: snr + real, intent(in) :: dt + real, intent(in) :: freq + character(len=37), intent(in) :: decoded + integer, intent(in) :: nap + real, intent(in) :: qual + save + + call js8_decoded(sync, snr, dt, freq, decoded, nap, qual) + + select type(this) + type is (counting_js8b_decoder) + this%decoded = this%decoded + 1 + end select + + return + end subroutine js8b_decoded + + subroutine js8c_decoded (this,sync,snr,dt,freq,decoded,nap,qual) + use js8c_decode + implicit none + + class(js8c_decoder), intent(inout) :: this + real, intent(in) :: sync + integer, intent(in) :: snr + real, intent(in) :: dt + real, intent(in) :: freq + character(len=37), intent(in) :: decoded + integer, intent(in) :: nap + real, intent(in) :: qual + save + + call js8_decoded(sync, snr, dt, freq, decoded, nap, qual) + + select type(this) + type is (counting_js8c_decoder) + this%decoded = this%decoded + 1 + end select + + return + end subroutine js8c_decoded + + subroutine js8d_decoded (this,sync,snr,dt,freq,decoded,nap,qual) + use js8d_decode + implicit none + + class(js8d_decoder), intent(inout) :: this + real, intent(in) :: sync + integer, intent(in) :: snr + real, intent(in) :: dt + real, intent(in) :: freq + character(len=37), intent(in) :: decoded + integer, intent(in) :: nap + real, intent(in) :: qual + save + + call js8_decoded(sync, snr, dt, freq, decoded, nap, qual) + + select type(this) + type is (counting_js8d_decoder) + this%decoded = this%decoded + 1 + end select + + return + end subroutine js8d_decoded end subroutine multimode_decoder diff --git a/lib/dxped_fifo.f90 b/lib/dxped_fifo.f90 deleted file mode 100644 index 96f3492..0000000 --- a/lib/dxped_fifo.f90 +++ /dev/null @@ -1,23 +0,0 @@ -subroutine dxped_fifo(cx,gx,isnrx) - - parameter (NCALLS=268) - character*6 xcall(NCALLS) - character*4 xgrid(NCALLS) - integer isnr(NCALLS) - - character cx*6,gx*4 - common/dxpfifo/nc,isnr,xcall,xgrid - - if(nc.lt.NCALLS) then - nc=nc+1 - cx=xcall(nc) - gx=xgrid(nc) - isnrx=isnr(nc) - else - cx=' ' - gx=' ' - isnrx=0 - endif - - return -end subroutine dxped_fifo diff --git a/lib/fast_decode.f90 b/lib/fast_decode.f90 deleted file mode 100644 index eebb731..0000000 --- a/lib/fast_decode.f90 +++ /dev/null @@ -1,97 +0,0 @@ -subroutine fast_decode(id2,narg,ntrperiod,line,mycall_12, & - hiscall_12) - - parameter (NMAX=30*12000) - integer*2 id2(NMAX) - integer*2 id2a(NMAX) - integer*2 id2b(NMAX) - integer narg(0:14) - real dat(30*12000) - complex cdat(262145),cdat2(262145) - real psavg(450) - logical pick,first - character*6 cfile6 - character*80 line(100) - character*12 mycall_12,hiscall_12 - character*6 mycall,hiscall - data first/.true./,nutca/0/,nutcb/0/ - save npts,cdat,cdat2,id2a,id2b,nutca,nutcb - - if(first) then - id2a=0 - id2b=0 - first=.false. - endif - - mycall=mycall_12(1:6) - hiscall=hiscall_12(1:6) - nutc=narg(0) - ndat0=narg(1) - nsubmode=narg(2) - newdat=narg(3) - minsync=narg(4) - npick=narg(5) - t0=0.001*narg(6) - t1=0.001*narg(7) - tmid=0.5*(t0+t1) - maxlines=narg(8) - nmode=narg(9) - nrxfreq=narg(10) - ntol=narg(11) - nhashcalls=narg(12) - - line(1:100)(1:1)=char(0) - if(t0.gt.float(ntrperiod)) go to 900 - if(t0.gt.t1) go to 900 - - if(nmode.eq.102) then - call fast9(id2,narg,line) - go to 900 - endif - - if(newdat.eq.1) then - cdat2=cdat - ndat=ndat0 - call wav11(id2,ndat,dat) - nzz=11025*ntrperiod - if(ndat.lt.nzz) dat(ndat+1:nzz)=0.0 - ndat=min(ndat,30*11025) - call ana932(dat,ndat,cdat,npts) !Make downsampled analytic signal - endif - -! Now cdat() is the downsampled analytic signal. -! New sample rate = fsample = BW = 11025 * (9/32) = 3100.78125 Hz -! NB: npts, nsps, etc., are all reduced by 9/32 - - write(cfile6,'(i6.6)') nutc - nfreeze=1 - mousedf=0 - mousebutton=0 - mode4=1 - if(nsubmode.eq.1) mode4=2 - nafc=0 - ndebug=0 - t2=0. - ia=1 - ib=npts - pick=.false. - - if(npick.gt.0) then - pick=.true. - dt=1.0/11025.0 * (32.0/9.0) - ia=t0/dt + 1. - ib=t1/dt + 1. - t2=t0 - endif - jz=ib-ia+1 - line(1:100)(1:1)=char(0) - if(npick.eq.2) then - call iscat(cdat2(ia),jz,3,40,t2,pick,cfile6,minsync,ntol,NFreeze, & - MouseDF,mousebutton,mode4,nafc,ndebug,psavg,nmax,nlines,line) - else - call iscat(cdat(ia),jz,3,40,t2,pick,cfile6,minsync,ntol,NFreeze, & - MouseDF,mousebutton,mode4,nafc,ndebug,psavg,maxlines,nlines,line) - endif - -900 return -end subroutine fast_decode diff --git a/lib/fer b/lib/fer deleted file mode 100755 index 7a74bf2..0000000 --- a/lib/fer +++ /dev/null @@ -1,41 +0,0 @@ -#!/bin/bash - -# jt65 end-to-end simulator. Run enough cases to get a given -# number of successful decodes or a given number of errors -# For better performance, copy this script and jt65, jt65sim -# executables to a ramdisk and run from there. - -mode=C -spread=4.0 - -for i in `seq 0 21`; -do -nruns=0 -ndecodes=0 -ngood=0 -nbad=0 -snr=$((-25+$i)) -#while [ $[ $nruns - $ngood ] -lt 200 ] -#while [ $ngood -lt 200 ] -while [ $nruns -lt 1000 ] -do - rm 000000_0001.wav - ./jt65sim -m $mode -n 1 -d $spread -s \\$snr > /dev/null - rm decoded.txt - ./jt65 -m $mode -a 10 -f 1500 -n 1000 -s 000000_0001.wav > decoded.txt - if [ -e decoded.txt ]; then - nd=$( wc -l < decoded.txt ) - ng=$( grep "K1ABC" decoded.txt | wc -l ) - nb=$[$nd-$ng] - ndecodes=$[$ndecodes + $nd] - ngood=$[$ngood + $ng] - nbad=$[$nbad + $nb] - fi - nruns=$[$nruns + 1] - nmissed=$[$nruns-$ngood] - pe=$( echo "scale=5; $nmissed/$nruns" | bc -l ) - ps=$( echo "scale=5; $ngood/$nruns" | bc -l ) - echo -en snr: $snr nruns: $nruns ndecodes: $ndecodes ngood: $ngood nbad: $nbad nmissed: $nmissed wer: $pe success: $ps"\r" -done -echo snr: $snr nruns: $nruns ndecodes: $ndecodes ngood: $ngood nbad: $nbad nmissed: $nmissed wer: $pe success: $ps -done diff --git a/lib/fer65.f90 b/lib/fer65.f90 deleted file mode 100644 index 1284fb5..0000000 --- a/lib/fer65.f90 +++ /dev/null @@ -1,195 +0,0 @@ -program fer65 - -! End-to-end simulator for testing JT65. - -! Options -! jt65sim jt65 -!---------------------------------------------------------------- -! -a aggressive -! -d Doppler spread -d depth -! -f Number of files -f freq -! -m (sub)mode -m (sub)mode -! -n number of generated sigs -n ntrials -! -t Time offset (s) -r robust sync -! -p Do not seed random #s -c mycall -! -x hiscall -! -g hisgrid -! -X hinted-decode flags -! -s S/N in 2500 Hz -s single-decode mode - - implicit real*8 (a-h,o-z) - real*8 s(7),sq(7) - character arg*12,cmnd*100,decoded*22,submode*1,csync*1,f1*15,f2*15 - character*12 outfile - logical syncok - - nargs=iargc() - if(nargs.ne.7) then - print*,'Usage: fer65 submode fspread snr1 snr2 Navg DS iters' - print*,'Example: fer65 C 3.0 -28 -12 8 1 1000' - go to 999 - endif - - call getarg(1,submode) - call getarg(2,arg) - read(arg,*) d - call getarg(3,arg) - read(arg,*) snr1 - call getarg(4,arg) - read(arg,*) snr2 - call getarg(5,arg) - read(arg,*) navg - call getarg(6,arg) - read(arg,*) nds - call getarg(7,arg) - read(arg,*) iters - - write(outfile,1001) submode,d,navg,nds -1001 format(a1,f6.2,'_',i2.2,'_',i1) - if(outfile(2:2).eq.' ') outfile(2:2)='0' - if(outfile(3:3).eq.' ') outfile(3:3)='0' - - ndepth=3 - if(navg.gt.1) ndepth=ndepth+16 - if(nds.ne.0) ndepth=ndepth+32 - - dfmax=3 - if(submode.eq.'b' .or. submode.eq.'B') dfmax=6 - if(submode.eq.'c' .or. submode.eq.'C') dfmax=11 - - ntrials=1000 - naggressive=10 - - open(20,file=outfile,status='unknown') - open(21,file='fer65.21',status='unknown') - - write(20,1000) submode,iters,ntrials,naggressive,d,ndepth,navg,nds -1000 format(/'JT65',a1,' Iters:',i5,' T:',i6,' Aggr:',i3, & - ' Dop:',f6.2,' Depth:',i2,' Navg:',i3,' DS:',i2) - write(20,1002) -1002 format(/' dB nsync ngood nbad sync dsnr ', & - 'DT Freq Nsum Width'/85('-')) - flush(20) - - do isnr=0,20 - snr=snr1+isnr - if(snr.gt.snr2) exit - nsync=0 - ngood=0 - nbad=0 - s=0. - sq=0. - do iter=1,iters - write(cmnd,1010) submode,d,snr,navg -1010 format('./jt65sim -n 1 -m ',a1,' -d',f7.2,' -s \\',f5.1,' -f',i3,' >devnull') - call unlink('000000_????.wav') - call system(cmnd) - if(navg.gt.1) then - do i=navg,2,-1 - j=2*i-1 - write(f1,1011) i - write(f2,1011) j -1011 format('000000_',i4.4,'.wav') - call rename(f1,f2) - enddo - endif - call unlink('decoded.txt') - call unlink('fort.13') - isync=0 - nsnr=0 - dt=0. - nfreq=0 - ndrift=0 - nwidth=0 - cmnd='./jt65 -m A -a 10 -c K1ABC -f 1500 -n 1000 -d 5 -s 000000_????.wav > decoded.txt' - cmnd(11:11)=submode - write(cmnd(47:48),'(i2)') ndepth - call system(cmnd) - open(13,file='fort.13',status='old',err=20) - do i=1,navg - read(13,1012) nutc,isync,nsnr,dt,nfreq,ndrift,nwidth,decoded, & - nft,nsum,nsmo -1012 format(i4,i4,i5,f6.2,i5,i4,i3,1x,a22,5x,3i3) - if(nft.gt.0) exit - enddo - close(13) - syncok=abs(dt).lt.0.2 .and. float(abs(nfreq-1500)).lt.dfmax - csync=' ' - if(syncok) csync='*' - write(21,1014) nutc,isync,nsnr,dt,nfreq,ndrift,nwidth, & - nft,nsum,nsmo,csync,decoded(1:16),nft,nsum,nsmo -1014 format(i4,i4,i5,f6.2,i5,i4,3x,4i3,1x,a1,1x,a16,i2,2i3) - flush(21) - - if(syncok) then - nsync=nsync+1 - s(1)=s(1) + isync - sq(1)=sq(1) + isync*isync - s(6)=s(6) + nwidth - sq(6)=sq(6) + nwidth*nwidth - if(decoded.eq.'K1ABC W9XYZ EN37 ') then - ngood=ngood+1 - s(2)=s(2) + nsnr - s(3)=s(3) + dt - s(4)=s(4) + nfreq - s(5)=s(5) + ndrift - s(7)=s(7) + nsum - - sq(2)=sq(2) + nsnr*nsnr - sq(3)=sq(3) + dt*dt - sq(4)=sq(4) + nfreq*nfreq - sq(5)=sq(5) + ndrift*ndrift - sq(7)=sq(7) + nsum*nsum - else if(decoded.ne.' ') then - nbad=nbad+1 - print*,'Nbad:',nbad,decoded - endif - endif -20 continue - fsync=float(nsync)/iter - fgood=float(ngood)/iter - fbad=float(nbad)/iter - write(*,1020) nint(snr),iter,isync,nsnr,dt,nfreq,ndrift,nwidth,fsync, & - fgood,fbad,decoded(1:16),nft,nsum,nsmo -1020 format(i3,i5,i3,i4,f6.2,i5,i3,i3,2f6.3,f7.4,1x,a16,i2,2i3) - enddo - - if(nsync.ge.1) then - xsync=s(1)/nsync - xwidth=s(6)/nsync - endif - esync=0. - if(nsync.ge.2) then - esync=sqrt(sq(1)/nsync - xsync**2) - ewidth=sqrt(sq(6)/nsync - xwidth**2) - endif - - if(ngood.ge.1) then - xsnr=s(2)/ngood - xdt=s(3)/ngood - xfreq=s(4)/ngood - xdrift=s(5)/ngood - xsum=s(7)/ngood - endif - if(ngood.ge.2) then - esnr=sqrt(sq(2)/ngood - xsnr**2) - edt=sqrt(sq(3)/ngood - xdt**2) - efreq=sqrt(sq(4)/ngood - xfreq**2) - edrift=sqrt(sq(5)/ngood - xdrift**2) - esum=sqrt(sq(7)/ngood - xsum**2) - endif - - dsnr=xsnr-snr - dfreq=xfreq-1500.0 - if(ngood.eq.0) then - dsnr=0. - dfreq=0. - endif - write(20,1100) snr,nsync,ngood,nbad,xsync,esync,dsnr,esnr, & - xdt,edt,dfreq,efreq,xsum,esum,xwidth,ewidth -1100 format(f5.1,2i6,i4,2f6.1,f6.1,f5.1,f6.2,f5.2,6f5.1) - flush(20) - if(ngood.ge.int(0.99*iters)) exit - enddo - -999 end program fer65 diff --git a/lib/fersum.f90 b/lib/fersum.f90 deleted file mode 100644 index 4a99561..0000000 --- a/lib/fersum.f90 +++ /dev/null @@ -1,72 +0,0 @@ -program fersum - - character mode*5 - character infile*40 - real dop(0:9) - real thresh(0:9,12),threshsync(0:9,12) - data dop/0.25,0.5,1.0,2.0,4.0,8.0,16.0,32.0,64.0,128.0/ - - nargs=iargc() - if(nargs.ne.1) then - print*,'Usage: fersum ' - go to 999 - endif - call getarg(1,infile) - open(10,file=infile,status='old') - thresh=0. - threshsync=0. - - do iblk=1,999 -1 read(10,1002,end=100) mode,iters,ntot,naggr,d,navg,nds -1002 format(a5,8x,i5,4x,i6,7x,i3,6x,f6.2,17x,i3,5x,i2) - write(33,*) iblk,mode - if(mode.eq.' ') go to 1 - read(10,1002) - read(10,1002) - read(10,1002) - - nsync0=0 - ngood0=0 - xsum0=0. - do n=1,99 - read(10,1010,end=100) snr,nsync,ngood,nbad,xsync,esync,dsnr,esnr, & - xdt,edt,dfreq,efreq,xsum,esum,xwidth,ewidth -1010 format(f5.1,2i6i4,2f6.1,f6.1,f5.1,f6.2,f5.2,6f5.1) - if(snr.eq.0.0) exit - if(mode(5:5).eq.'A') nmode=1 - if(mode(5:5).eq.'B') nmode=2 - if(mode(5:5).eq.'C') nmode=3 - j=nint(log(d)/log(2.0) + 2.0) - if(navg.eq.1 .and. nds.eq.0) k=nmode - if(navg.eq.1 .and. nds.eq.1) k=nmode+3 - if(navg.gt.1 .and. nds.eq.0) k=nmode+6 - if(navg.gt.1 .and. nds.eq.1) k=nmode+9 - if(nsync0.le.iters/2 .and. nsync.ge.iters/2) then - threshsync(j,k)=snr-float(nsync-iters/2)/(nsync-nsync0) - endif - if(ngood0.le.iters/2 .and. ngood.ge.iters/2) then - threshold=snr-float(ngood-iters/2)/(ngood-ngood0) - xsumavg=max(1.0,0.5*(xsum0+xsum)) -! write(*,1020) mode,iters,ntot,naggr,d,navg,nds,threshold,xsumavg -!1020 format(a5,i7,i7,i3,f7.2,i3,i3,f7.1,f6.1) - thresh(j,k)=threshold - endif - nsync0=nsync - ngood0=ngood - xsum0=xsum - enddo - enddo - -100 write(12,1100) -1100 format(' ') - do i=0,9 - write(12,1110) dop(i),thresh(i,1:12) -1110 format(f6.2,13f6.1) - enddo - - write(12,1110) - do i=0,9 - write(12,1110) dop(i),threshsync(i,1:12) - enddo - -999 end program fersum diff --git a/lib/fix_contest_msg.f90 b/lib/fix_contest_msg.f90 deleted file mode 100644 index 8c0345e..0000000 --- a/lib/fix_contest_msg.f90 +++ /dev/null @@ -1,32 +0,0 @@ -subroutine fix_contest_msg(mygrid,msg) - -! If distance from mygrid to grid1 is more thsn 10000 km, change "grid1" -! to "R grid2" where grid2 is the antipodes of grid1. - - character*6 mygrid - character*22 msg - character*6 g1,g2 - logical isgrid - - isgrid(g1)=g1(1:1).ge.'A' .and. g1(1:1).le.'R' .and. g1(2:2).ge.'A' .and. & - g1(2:2).le.'R' .and. g1(3:3).ge.'0' .and. g1(3:3).le.'9' .and. & - g1(4:4).ge.'0' .and. g1(4:4).le.'9' .and. g1(1:4).ne.'RR73' - - n=len(trim(msg)) - if(n.lt.4) return - - g1=msg(n-3:n)//' ' - if(isgrid(g1)) then - call azdist(mygrid,g1,0.d0,nAz,nEl,nDmiles,nDkm,nHotAz,nHotABetter) - if(ndkm.gt.10000) then - call grid2deg(g1,dlong,dlat) - dlong=dlong+180.0 - if(dlong.gt.180.0) dlong=dlong-360.0 - dlat=-dlat - call deg2grid(dlong,dlat,g2) - msg=msg(1:n-4)//'R '//g2(1:4) - endif - endif - - return -end subroutine fix_contest_msg diff --git a/lib/ft8/ft8code.f90 b/lib/ft8/ft8code.f90 index 7a78f40..3100148 100644 --- a/lib/ft8/ft8code.f90 +++ b/lib/ft8/ft8code.f90 @@ -81,7 +81,6 @@ program ft8code call extractmessage174(decoded,message,ncrcflag) decoded=decoded0 - if(bcontest) call fix_contest_msg(mygrid6,message) bad=" " comment=' ' if(itype.ne.6 .and. message.ne.msgchk) bad="*" diff --git a/lib/ft8_decode.f90 b/lib/ft8_decode.f90 index a38565c..b3c9166 100644 --- a/lib/ft8_decode.f90 +++ b/lib/ft8_decode.f90 @@ -121,12 +121,6 @@ contains hd=nharderrors+dmin call timer('ft8b ',1) if(nbadcrc.eq.0) then -! call jtmsg(message,iflag) - if(bcontest) then - call fix_contest_msg(mygrid6,message) - msg37(1:22)=message - endif -! if(iand(iflag,31).ne.0) message(22:22)='?' ldupe=.false. do id=1,ndecodes if(message.eq.allmessages(id).and.nsnr.le.allsnrs(id)) ldupe=.true. @@ -136,11 +130,6 @@ contains allmessages(ndecodes)=message allsnrs(ndecodes)=nsnr endif -! write(81,1004) nutc,ncand,icand,ipass,iaptype,iappass, & -! nharderrors,dmin,hd,min(sync,999.0),nint(xsnr), & -! xdt,nint(f1),message -!1004 format(i6.6,2i4,3i2,i3,3f6.1,i4,f6.2,i5,2x,a22) -! flush(81) if(.not.ldupe .and. associated(this%callback)) then qual=1.0-(nharderrors+dmin)/60.0 ! scale qual to [0.0,1.0] call this%callback(sync,nsnr,xdt,f1,msg37,iaptype,qual) diff --git a/lib/ftrsd/Makefile b/lib/ftrsd/Makefile deleted file mode 100644 index 61b1357..0000000 --- a/lib/ftrsd/Makefile +++ /dev/null @@ -1,53 +0,0 @@ -# Makefile for Windows in JTSDK-PY environment - -# Re-direct stdout and stderr: cmd.exe bash -# make > junk 2>&1 make &> junk - -CC = gcc -FC = gfortran - -FFLAGS = -O2 -DWIN32 -fbounds-check -fno-second-underscore -Wall \ - -Wno-conversion -Wno-character-truncation -CFLAGS = -I. -DWIN32 -DWin32 -DBIGSYM -DHAVE_STRUCT_TIMESPEC - -# Default rules -%.o: %.c - ${CC} ${CFLAGS} -c $< -%.o: %.f - ${FC} ${FFLAGS} -c $< -%.o: %.F - ${FC} ${FFLAGS} -c $< -%.o: %.f90 - ${FC} ${FFLAGS} -c $< -%.o: %.F90 - ${FC} ${FFLAGS} -c $< - -all: libftrsd.a - -OBJS1 = extract2.o ftrsd2.o init_rs_int.o encode_rs_int.o decode_rs_int.o -libftrsd.a: $(OBJS1) - ar cr libftrsd.a $(OBJS1) - ranlib libftrsd.a - cp libftrsd.a .. - -# Build rsdtest -OBJS2 = rsdtest.o -rsdtest: $(OBJS2) ../libjt.a - $(FC) -o rsdtest $(OBJS2) libftrsd.a ../libjt.a ../libpthreadGC2.a - -ftrsd: ftrsd.o encode_rs_int.o decode_rs_int.o init_rs_int.o - gcc -g -o $@ $^ - -encode_rs_int.o: encode_rs.c - gcc -DBIGSYM=1 $(CFLAGS) -c -o $@ $^ - -decode_rs_int.o: decode_rs.c - gcc -DBIGSYM=1 $(CFLAGS) -c -o $@ $^ - -init_rs_int.o: init_rs.c - gcc -DBIGSYM=1 $(CFLAGS) -c -o $@ $^ - -.PHONY : clean - -clean: - rm -rf *.o libjt.a rsdtest ftrsd diff --git a/lib/ftrsd/Makefile.sfrsd b/lib/ftrsd/Makefile.sfrsd deleted file mode 100644 index 3f68f7e..0000000 --- a/lib/ftrsd/Makefile.sfrsd +++ /dev/null @@ -1,30 +0,0 @@ -srcdir = . -prefix = /usr/local -exec_prefix=${prefix} -CC=gcc - -CFLAGS=-I/usr/local/include -Wall -O2 - -all: encode_rs_int.o decode_rs_int.o init_rs_int.o sfrsd2.o sfrsd.o sfrsd - -encode_rs_int.o: encode_rs.c - gcc -DBIGSYM=1 $(CFLAGS) -c -o $@ $^ - -decode_rs_int.o: decode_rs.c - gcc -DBIGSYM=1 $(CFLAGS) -c -o $@ $^ - -init_rs_int.o: init_rs.c - gcc -DBIGSYM=1 $(CFLAGS) -c -o $@ $^ - -sfrsd2.o: sfrsd2.c - gcc -DBIGSYM=1 $(CFLAGS) -c -o $@ $^ - -sfrsd.o: sfrsd.c - gcc -DBIGSYM=1 $(CFLAGS) -c -o $@ $^ - -sfrsd: sfrsd.o encode_rs_int.o decode_rs_int.o init_rs_int.o sfrsd2.o - gcc -g -o $@ $^ - -clean: - rm -f *.o *.a sfrsd - diff --git a/lib/ftrsd/Makefile.sfrsd3 b/lib/ftrsd/Makefile.sfrsd3 deleted file mode 100644 index 93023f3..0000000 --- a/lib/ftrsd/Makefile.sfrsd3 +++ /dev/null @@ -1,38 +0,0 @@ -# Makefile for Windows in JTSDK-PY environment - -# Re-direct stdout and stderr: cmd.exe bash -# make > junk 2>&1 make &> junk - -CC = gcc -FC = gfortran - -FFLAGS = -O2 -DWIN32 -fbounds-check -fno-second-underscore -Wall \ - -Wno-conversion -Wno-character-truncation -CFLAGS = -I. -DWIN32 -DWin32 -DBIGSYM -DHAVE_STRUCT_TIMESPEC - -# Default rules -%.o: %.c - ${CC} ${CFLAGS} -c $< -%.o: %.f - ${FC} ${FFLAGS} -c $< -%.o: %.F - ${FC} ${FFLAGS} -c $< -%.o: %.f90 - ${FC} ${FFLAGS} -c $< -%.o: %.F90 - ${FC} ${FFLAGS} -c $< - -all: rsdtest - -# Build rsdtest -OBJS2 = rsdtest.o extract2.o demod64b.o sfrsd3.o -rsdtest: $(OBJS2) ../libjt.a - $(FC) -o rsdtest $(OBJS2) ../libjt.a ../libpthreadGC2.a - -sfrsd: sfrsd.o encode_rs_int.o decode_rs_int.o init_rs_int.o - gcc -g -o $@ $^ - -.PHONY : clean - -clean: - rm -rf *.o libjt.a rsdtest sfrsd diff --git a/lib/ftrsd/decode_rs.c b/lib/ftrsd/decode_rs.c deleted file mode 100644 index 990b687..0000000 --- a/lib/ftrsd/decode_rs.c +++ /dev/null @@ -1,268 +0,0 @@ -/* Reed-Solomon decoder - * Copyright 2002 Phil Karn, KA9Q - * May be used under the terms of the GNU General Public License (GPL) - * Modified by Steve Franke, K9AN, for use in a soft-symbol RS decoder - */ - -#ifdef DEBUG -#include -#endif - -#include -#include - -#define min(a,b) ((a) < (b) ? (a) : (b)) - -#ifdef FIXED -#include "fixed.h" -#elif defined(BIGSYM) -#include "int.h" -#else -#include "char.h" -#endif - -int DECODE_RS( -#ifndef FIXED - void *p, -#endif - DTYPE *data, int *eras_pos, int no_eras, int calc_syn){ - -#ifndef FIXED - struct rs *rs = (struct rs *)p; -#endif - int deg_lambda, el, deg_omega; - int i, j, r,k; - DTYPE u,q,tmp,num1,num2,den,discr_r; - DTYPE lambda[NROOTS+1]; // Err+Eras Locator poly - static DTYPE s[51]; // and syndrome poly - DTYPE b[NROOTS+1], t[NROOTS+1], omega[NROOTS+1]; - DTYPE root[NROOTS], reg[NROOTS+1], loc[NROOTS]; - int syn_error, count; - - if( calc_syn ) { - /* form the syndromes; i.e., evaluate data(x) at roots of g(x) */ - for(i=0;i 0) { - /* Init lambda to be the erasure locator polynomial */ - lambda[1] = ALPHA_TO[MODNN(PRIM*(NN-1-eras_pos[0]))]; - for (i = 1; i < no_eras; i++) { - u = MODNN(PRIM*(NN-1-eras_pos[i])); - for (j = i+1; j > 0; j--) { - tmp = INDEX_OF[lambda[j - 1]]; - if(tmp != A0) - lambda[j] ^= ALPHA_TO[MODNN(u + tmp)]; - } - } - -#if DEBUG >= 1 - /* Test code that verifies the erasure locator polynomial just constructed - Needed only for decoder debugging. */ - - /* find roots of the erasure location polynomial */ - for(i=1;i<=no_eras;i++) - reg[i] = INDEX_OF[lambda[i]]; - - count = 0; - for (i = 1,k=IPRIM-1; i <= NN; i++,k = MODNN(k+IPRIM)) { - q = 1; - for (j = 1; j <= no_eras; j++) - if (reg[j] != A0) { - reg[j] = MODNN(reg[j] + j); - q ^= ALPHA_TO[reg[j]]; - } - if (q != 0) - continue; - /* store root and error location number indices */ - root[count] = i; - loc[count] = k; - count++; - } - if (count != no_eras) { - printf("count = %d no_eras = %d\n lambda(x) is WRONG\n",count,no_eras); - count = -1; - goto finish; - } -#if DEBUG >= 2 - printf("\n Erasure positions as determined by roots of Eras Loc Poly:\n"); - for (i = 0; i < count; i++) - printf("%d ", loc[i]); - printf("\n"); -#endif -#endif - } - for(i=0;i 0; j--){ - if (reg[j] != A0) { - reg[j] = MODNN(reg[j] + j); - q ^= ALPHA_TO[reg[j]]; - } - } - if (q != 0) - continue; /* Not a root */ - /* store root (index-form) and error location number */ -#if DEBUG>=2 - printf("count %d root %d loc %d\n",count,i,k); -#endif - root[count] = i; - loc[count] = k; - /* If we've already found max possible roots, - * abort the search to save time - */ - if(++count == deg_lambda) - break; - } - if (deg_lambda != count) { - /* - * deg(lambda) unequal to number of roots => uncorrectable - * error detected - */ - count = -1; - goto finish; - } - /* - * Compute err+eras evaluator poly omega(x) = s(x)*lambda(x) (modulo - * x**NROOTS). in index form. Also find deg(omega). - */ - deg_omega = 0; - for (i = 0; i < NROOTS;i++){ - tmp = 0; - j = (deg_lambda < i) ? deg_lambda : i; - for(;j >= 0; j--){ - if ((s[i - j] != A0) && (lambda[j] != A0)) - tmp ^= ALPHA_TO[MODNN(s[i - j] + lambda[j])]; - } - if(tmp != 0) - deg_omega = i; - omega[i] = INDEX_OF[tmp]; - } - omega[NROOTS] = A0; - - /* - * Compute error values in poly-form. num1 = omega(inv(X(l))), num2 = - * inv(X(l))**(FCR-1) and den = lambda_pr(inv(X(l))) all in poly-form - */ - for (j = count-1; j >=0; j--) { - num1 = 0; - for (i = deg_omega; i >= 0; i--) { - if (omega[i] != A0) - num1 ^= ALPHA_TO[MODNN(omega[i] + i * root[j])]; - } - num2 = ALPHA_TO[MODNN(root[j] * (FCR - 1) + NN)]; - den = 0; - - /* lambda[i+1] for i even is the formal derivative lambda_pr of lambda[i] */ - for (i = min(deg_lambda,NROOTS-1) & ~1; i >= 0; i -=2) { - if(lambda[i+1] != A0) - den ^= ALPHA_TO[MODNN(lambda[i+1] + i * root[j])]; - } - if (den == 0) { -#if DEBUG >= 1 - printf("\n ERROR: denominator = 0\n"); -#endif - count = -1; - goto finish; - } - /* Apply error to data */ - if (num1 != 0) { - data[loc[j]] ^= ALPHA_TO[MODNN(INDEX_OF[num1] + INDEX_OF[num2] + NN - INDEX_OF[den])]; - } - } -finish: - if(eras_pos != NULL){ - for(i=0;i - -#ifdef FIXED -#include "fixed.h" -#elif defined(BIGSYM) -#include "int.h" -#else -#include "char.h" -#endif - -void ENCODE_RS( -#ifndef FIXED -void *p, -#endif -DTYPE *data, DTYPE *bb){ -#ifndef FIXED - struct rs *rs = (struct rs *)p; -#endif - int i, j; - DTYPE feedback; - - memset(bb,0,NROOTS*sizeof(DTYPE)); - - for(i=0;i -#include -#include -#include -#include -#include "rs2.h" - -static void *rs; -void getpp_(int workdat[], float *pp); - -void ftrsd2_(int mrsym[], int mrprob[], int mr2sym[], int mr2prob[], - int* ntrials0, int correct[], int param[], int ntry[]) -{ - int rxdat[63], rxprob[63], rxdat2[63], rxprob2[63]; - int workdat[63]; - int indexes[63]; - int era_pos[51]; - int i, j, numera, nerr, nn=63; - int ntrials = *ntrials0; - int nhard=0,nhard_min=32768,nsoft=0,nsoft_min=32768; - int ntotal=0,ntotal_min=32768,ncandidates; - int nera_best=0; - float pp,pp1,pp2; - static unsigned int nseed; - -// Power-percentage symbol metrics - composite gnnf/hf - int perr[8][8] = { - { 4, 9, 11, 13, 14, 14, 15, 15}, - { 2, 20, 20, 30, 40, 50, 50, 50}, - { 7, 24, 27, 40, 50, 50, 50, 50}, - {13, 25, 35, 46, 52, 70, 50, 50}, - {17, 30, 42, 54, 55, 64, 71, 70}, - {25, 39, 48, 57, 64, 66, 77, 77}, - {32, 45, 54, 63, 66, 75, 78, 83}, - {51, 58, 57, 66, 72, 77, 82, 86}}; - - -// Initialize the KA9Q Reed-Solomon encoder/decoder - unsigned int symsize=6, gfpoly=0x43, fcr=3, prim=1, nroots=51; - rs=init_rs_int(symsize, gfpoly, fcr, prim, nroots, 0); - -// Reverse the received symbol vectors for BM decoder - for (i=0; i<63; i++) { - rxdat[i]=mrsym[62-i]; - rxprob[i]=mrprob[62-i]; - rxdat2[i]=mr2sym[62-i]; - rxprob2[i]=mr2prob[62-i]; - } - -// Sort rxprob to find indexes of the least reliable symbols - int k, pass, tmp, nsym=63; - int probs[63]; - for (i=0; i<63; i++) { - indexes[i]=i; - probs[i]=rxprob[i]; - } - for (pass = 1; pass <= nsym-1; pass++) { - for (k = 0; k < nsym - pass; k++) { - if( probs[k] < probs[k+1] ) { - tmp = probs[k]; - probs[k] = probs[k+1]; - probs[k+1] = tmp; - tmp = indexes[k]; - indexes[k] = indexes[k+1]; - indexes[k+1] = tmp; - } - } - } - -// See if we can decode using BM HDD, and calculate the syndrome vector. - memset(era_pos,0,51*sizeof(int)); - numera=0; - memcpy(workdat,rxdat,sizeof(rxdat)); - nerr=decode_rs_int(rs,workdat,era_pos,numera,1); - if( nerr >= 0 ) { - // Hard-decision decoding succeeded. Save codeword and some parameters. - nhard=0; - for (i=0; i<63; i++) { - if( workdat[i] != rxdat[i] ) nhard=nhard+1; - } - memcpy(correct,workdat,63*sizeof(int)); - param[0]=0; - param[1]=nhard; - param[2]=0; - param[3]=0; - param[4]=0; - param[5]=0; - param[7]=1000*1000; - ntry[0]=0; - return; - } - -/* -Hard-decision decoding failed. Try the FT soft-decision method. -Generate random erasure-locator vectors and see if any of them -decode. This will generate a list of "candidate" codewords. The -soft distance between each candidate codeword and the received -word is estimated by finding the largest (pp1) and second-largest -(pp2) outputs from a synchronized filter-bank operating on the -symbol spectra, and using these to decide which candidate -codeword is "best". -*/ - - nseed=1; //Seed for random numbers - float ratio; - int thresh, nsum; - int thresh0[63]; - ncandidates=0; - nsum=0; - int ii,jj; - for (i=0; i= 0 ) { - // We have a candidate codeword. Find its hard and soft distance from - // the received word. Also find pp1 and pp2 from the full array - // s3(64,63) of synchronized symbol spectra. - ncandidates=ncandidates+1; - nhard=0; - nsoft=0; - for (i=0; i<63; i++) { - if(workdat[i] != rxdat[i]) { - nhard=nhard+1; - if(workdat[i] != rxdat2[i]) { - nsoft=nsoft+rxprob[i]; - } - } - } - nsoft=63*nsoft/nsum; - ntotal=nsoft+nhard; - - getpp_(workdat,&pp); - if(pp>pp1) { - pp2=pp1; - pp1=pp; - nsoft_min=nsoft; - nhard_min=nhard; - ntotal_min=ntotal; - memcpy(correct,workdat,63*sizeof(int)); - nera_best=numera; - ntry[0]=k; - } else { - if(pp>pp2 && pp!=pp1) pp2=pp; - } - if(nhard_min <= 41 && ntotal_min <= 71) break; - } - if(k == ntrials) ntry[0]=k; - } - - param[0]=ncandidates; - param[1]=nhard_min; - param[2]=nsoft_min; - param[3]=nera_best; - param[4]=1000.0*pp2/pp1; - param[5]=ntotal_min; - param[6]=ntry[0]; - param[7]=1000.0*pp2; - param[8]=1000.0*pp1; - if(param[0]==0) param[2]=-1; - return; -} diff --git a/lib/ftrsd/ftrsd_paper/JT65B_EME.png b/lib/ftrsd/ftrsd_paper/JT65B_EME.png deleted file mode 100644 index d5c86fb..0000000 Binary files a/lib/ftrsd/ftrsd_paper/JT65B_EME.png and /dev/null differ diff --git a/lib/ftrsd/ftrsd_paper/Makefile b/lib/ftrsd/ftrsd_paper/Makefile deleted file mode 100644 index a594397..0000000 --- a/lib/ftrsd/ftrsd_paper/Makefile +++ /dev/null @@ -1,40 +0,0 @@ -CC = gcc -FC = gfortran - -# Default rules -%.o: %.c - ${CC} ${CFLAGS} -c $< -%.o: %.f - ${FC} ${FFLAGS} -c $< -%.o: %.F - ${FC} ${FFLAGS} -c $< -%.o: %.f90 - ${FC} ${FFLAGS} -c $< -%.o: %.F90 - ${FC} ${FFLAGS} -c $< - -all: mfsk probs.out - -OBJS1 = prob.o binomial_subs.o -prob: $(OBJS1) - $(FC) -o prob $(OBJS1) - -OBJS2 = mfsk.o binomial_subs.o -mfsk: $(OBJS2) - $(FC) -o mfsk $(OBJS2) - -OBJS3 = bodide.o binomial_subs.o -bodide: $(OBJS3) - $(FC) -o bodide $(OBJS3) - - -probs.out: prob -# x N X s - prob 35 63 40 40 > probs.out - prob 37 63 40 45 >> probs.out - prob 37 53 40 45 >> probs.out - prob 38 53 40 47 >> probs.out - -clean: - rm -rf *.o prob probs.out - diff --git a/lib/ftrsd/ftrsd_paper/binomial.c b/lib/ftrsd/ftrsd_paper/binomial.c deleted file mode 100644 index fcbdafd..0000000 --- a/lib/ftrsd/ftrsd_paper/binomial.c +++ /dev/null @@ -1,69 +0,0 @@ -#include -#include - -/* Original code copied from - http://rosettacode.org/wiki/Evaluate_binomial_coefficients -*/ - -/* We go to some effort to handle overflow situations */ - -static unsigned long gcd_ui(unsigned long x, unsigned long y) { - unsigned long t; - if (y < x) { t = x; x = y; y = t; } - while (y > 0) { - t = y; y = x % y; x = t; /* y1 <- x0 % y0 ; x1 <- y0 */ - } - return x; -} - -unsigned long binomial(unsigned long n, unsigned long k) { - unsigned long d, g, r = 1; - if (k == 0) return 1; - if (k == 1) return n; - if (k >= n) return (k == n); - if (k > n/2) k = n-k; - for (d = 1; d <= k; d++) { - if (r >= ULONG_MAX/n) { /* Possible overflow */ - unsigned long nr, dr; /* reduced numerator / denominator */ - g = gcd_ui(n, d); nr = n/g; dr = d/g; - g = gcd_ui(r, dr); r = r/g; dr = dr/g; - if (r >= ULONG_MAX/nr) return 0; /* Unavoidable overflow */ - r *= nr; - r /= dr; - n--; - } else { - r *= n--; - r /= d; - } - } - return r; -} - -int main() { - - //Get test results - printf("%lu\n", binomial(5, 3)); // 10 - printf("%lu\n", binomial(40, 19)); // 131282408400 - printf("%lu\n", binomial(67, 31)); // 11923179284862717872 - - // Compute special cases for paper on TF soft-decision RS decoder: - double a,b,c,p; - a=(double)binomial(40, 35); - b=(double)binomial(23, 5); - c=(double)binomial(63, 40); - p=a*b/c; - printf("%e %e %e %e\n",a,b,c,p); - - a=(double)binomial(40, 36); - b=(double)binomial(23, 4); - c=(double)binomial(63, 40); - p=a*b/c; - printf("%e %e %e %e\n",a,b,c,p); - - a=(double)binomial(40, 37); - b=(double)binomial(23, 8); - c=(double)binomial(63, 45); - p=a*b/c; - printf("%e %e %e %e\n",a,b,c,p); - return 0; -} diff --git a/lib/ftrsd/ftrsd_paper/binomial_subs.c b/lib/ftrsd/ftrsd_paper/binomial_subs.c deleted file mode 100644 index be4a0ae..0000000 --- a/lib/ftrsd/ftrsd_paper/binomial_subs.c +++ /dev/null @@ -1,55 +0,0 @@ -#include -#include - -/* Original code copied from - http://rosettacode.org/wiki/Evaluate_binomial_coefficients -*/ - -/* We go to some effort to handle overflow situations */ - -static unsigned long long gcd_ui(unsigned long long x, unsigned long long y) { - unsigned long long t; - if (y < x) { t = x; x = y; y = t; } - while (y > 0) { - t = y; y = x % y; x = t; /* y1 <- x0 % y0 ; x1 <- y0 */ - } - return x; -} - -unsigned long long binomial(unsigned long long n, unsigned long long k) { - unsigned long long d, g, r = 1; - if (k == 0) return 1; - if (k == 1) return n; - if (k >= n) return (k == n); - if (k > n/2) k = n-k; - for (d = 1; d <= k; d++) { - if (r >= ULLONG_MAX/n) { /* Possible overflow */ - unsigned long long nr, dr; /* reduced numerator / denominator */ - g = gcd_ui(n, d); nr = n/g; dr = d/g; - g = gcd_ui(r, dr); r = r/g; dr = dr/g; - if (r >= ULLONG_MAX/nr) return 0; /* Unavoidable overflow */ - r *= nr; - r /= dr; - n--; - } else { - r *= n--; - r /= d; - } - } - return r; -} - -unsigned long long binomial_(int *n, int *k) -{ - // printf("n=%d k=%d %lu\n",*n,*k,binomial(*n,*k)); - return binomial(*n,*k); -} - -double hypergeo_(int *x, int *NN, int *XX, int *s) -{ - double a,b,c; - a=(double)binomial(*XX, *x); - b=(double)binomial(*NN-*XX, *s-*x); - c=(double)binomial(*NN, *s); - return a*b/c; -} diff --git a/lib/ftrsd/ftrsd_paper/bmdata-rf.dat b/lib/ftrsd/ftrsd_paper/bmdata-rf.dat deleted file mode 100644 index 17d5331..0000000 --- a/lib/ftrsd/ftrsd_paper/bmdata-rf.dat +++ /dev/null @@ -1,11 +0,0 @@ -fspread0 0.2, BM (ntrials=0) --22.0 0.09 --21.5 0.20 --21.0 0.36 --20.5 0.55 --20.0 0.69 --19.5 0.83 --19.0 0.91 --18.5 0.960 --18.0 0.978 --17.5 0.987 diff --git a/lib/ftrsd/ftrsd_paper/bmdata.dat b/lib/ftrsd/ftrsd_paper/bmdata.dat deleted file mode 100644 index 987bbbb..0000000 --- a/lib/ftrsd/ftrsd_paper/bmdata.dat +++ /dev/null @@ -1,8 +0,0 @@ --24.5 0.000 --24.0 0.006 --23.5 0.046 0.066 --23.0 0.250 0.305 --22.5 0.630 0.701 --22.0 0.900 0.945 --21.5 0.992 0.9974 --21.0 0.99987 diff --git a/lib/ftrsd/ftrsd_paper/bmtheory25.dat b/lib/ftrsd/ftrsd_paper/bmtheory25.dat deleted file mode 100644 index de85456..0000000 --- a/lib/ftrsd/ftrsd_paper/bmtheory25.dat +++ /dev/null @@ -1,43 +0,0 @@ -Es/No P(word error) ----------------------- - 0.0 0.9008E+00 0.1000E+01 - 0.5 0.8877E+00 0.1000E+01 - 1.0 0.8724E+00 0.1000E+01 - 1.5 0.8545E+00 0.1000E+01 - 2.0 0.8338E+00 0.1000E+01 - 2.5 0.8096E+00 0.1000E+01 - 3.0 0.7817E+00 0.1000E+01 - 3.5 0.7496E+00 0.1000E+01 - 4.0 0.7128E+00 0.1000E+01 - 4.5 0.6712E+00 0.1000E+01 - 5.0 0.6246E+00 0.9998E+00 - 5.5 0.5731E+00 0.9964E+00 - 6.0 0.5170E+00 0.9629E+00 - 6.5 0.4572E+00 0.7979E+00 - 7.0 0.3949E+00 0.4327E+00 - 7.5 0.3316E+00 0.1100E+00 - 8.0 0.2696E+00 0.9707E-02 - 8.5 0.2109E+00 0.2303E-03 - 9.0 0.1578E+00 0.1170E-05 - 9.5 0.1121E+00 0.1027E-08 -10.0 0.7499E-01 0.1263E-12 -10.5 0.4684E-01 0.1768E-17 -11.0 0.2703E-01 0.2282E-23 -11.5 0.1426E-01 0.2200E-30 -12.0 0.6789E-02 -.1348E-32 -12.5 0.2879E-02 -.1733E-32 -13.0 0.1072E-02 -.2119E-32 -13.5 0.3448E-03 0.3081E-32 -14.0 0.9421E-04 0.3852E-33 -14.5 0.2148E-04 -.1156E-32 -15.0 0.4006E-05 -.1733E-32 -15.5 0.5984E-06 0.2215E-32 -16.0 0.6994E-07 -.4430E-32 -16.5 0.6230E-08 -.3081E-32 -17.0 0.4105E-09 -.2889E-32 -17.5 0.1934E-10 -.1926E-33 -18.0 0.6266E-12 0.3852E-32 -18.5 0.1335E-13 -.1926E-33 -19.0 0.1777E-15 0.2119E-32 -19.5 0.1396E-17 0.1733E-32 -20.0 0.6076E-20 -.3852E-33 diff --git a/lib/ftrsd/ftrsd_paper/bmtheory40.dat b/lib/ftrsd/ftrsd_paper/bmtheory40.dat deleted file mode 100644 index 4903ef5..0000000 --- a/lib/ftrsd/ftrsd_paper/bmtheory40.dat +++ /dev/null @@ -1,43 +0,0 @@ -Es/No P(word error) ----------------------- - 0.0 0.9008E+00 0.1000E+01 - 0.5 0.8877E+00 0.1000E+01 - 1.0 0.8724E+00 0.1000E+01 - 1.5 0.8545E+00 0.1000E+01 - 2.0 0.8338E+00 0.9999E+00 - 2.5 0.8096E+00 0.9991E+00 - 3.0 0.7817E+00 0.9944E+00 - 3.5 0.7496E+00 0.9713E+00 - 4.0 0.7128E+00 0.8887E+00 - 4.5 0.6712E+00 0.6883E+00 - 5.0 0.6246E+00 0.3865E+00 - 5.5 0.5731E+00 0.1310E+00 - 6.0 0.5170E+00 0.2215E-01 - 6.5 0.4572E+00 0.1536E-02 - 7.0 0.3949E+00 0.3562E-04 - 7.5 0.3316E+00 0.2223E-06 - 8.0 0.2696E+00 0.2951E-09 - 8.5 0.2109E+00 0.6449E-13 - 9.0 0.1578E+00 0.1758E-17 - 9.5 0.1121E+00 0.4426E-23 -10.0 0.7499E-01 0.7428E-30 -10.5 0.4684E-01 -.1733E-32 -11.0 0.2703E-01 0.1348E-32 -11.5 0.1426E-01 0.2985E-32 -12.0 0.6789E-02 -.1348E-32 -12.5 0.2879E-02 -.1733E-32 -13.0 0.1072E-02 -.2119E-32 -13.5 0.3448E-03 0.3081E-32 -14.0 0.9421E-04 0.3852E-33 -14.5 0.2148E-04 -.1156E-32 -15.0 0.4006E-05 -.1733E-32 -15.5 0.5984E-06 0.2215E-32 -16.0 0.6994E-07 -.4430E-32 -16.5 0.6230E-08 -.3081E-32 -17.0 0.4105E-09 -.2889E-32 -17.5 0.1934E-10 -.1926E-33 -18.0 0.6266E-12 0.3852E-32 -18.5 0.1335E-13 -.1926E-33 -19.0 0.1777E-15 0.2119E-32 -19.5 0.1396E-17 0.1733E-32 -20.0 0.6076E-20 -.3852E-33 diff --git a/lib/ftrsd/ftrsd_paper/bmtheory43.dat b/lib/ftrsd/ftrsd_paper/bmtheory43.dat deleted file mode 100644 index b22ab8d..0000000 --- a/lib/ftrsd/ftrsd_paper/bmtheory43.dat +++ /dev/null @@ -1,43 +0,0 @@ -Es/No P(word error) ----------------------- - 0.0 0.9008E+00 0.1000E+01 - 0.5 0.8877E+00 0.1000E+01 - 1.0 0.8724E+00 0.9999E+00 - 1.5 0.8545E+00 0.9996E+00 - 2.0 0.8338E+00 0.9977E+00 - 2.5 0.8096E+00 0.9889E+00 - 3.0 0.7817E+00 0.9559E+00 - 3.5 0.7496E+00 0.8599E+00 - 4.0 0.7128E+00 0.6586E+00 - 4.5 0.6712E+00 0.3780E+00 - 5.0 0.6246E+00 0.1397E+00 - 5.5 0.5731E+00 0.2826E-01 - 6.0 0.5170E+00 0.2632E-02 - 6.5 0.4572E+00 0.9396E-04 - 7.0 0.3949E+00 0.1052E-05 - 7.5 0.3316E+00 0.2965E-08 - 8.0 0.2696E+00 0.1650E-11 - 8.5 0.2109E+00 0.1388E-15 - 9.0 0.1578E+00 0.1316E-20 - 9.5 0.1121E+00 0.1021E-26 -10.0 0.7499E-01 -.9630E-33 -10.5 0.4684E-01 -.1733E-32 -11.0 0.2703E-01 0.1348E-32 -11.5 0.1426E-01 0.2985E-32 -12.0 0.6789E-02 -.1348E-32 -12.5 0.2879E-02 -.1733E-32 -13.0 0.1072E-02 -.2119E-32 -13.5 0.3448E-03 0.3081E-32 -14.0 0.9421E-04 0.3852E-33 -14.5 0.2148E-04 -.1156E-32 -15.0 0.4006E-05 -.1733E-32 -15.5 0.5984E-06 0.2215E-32 -16.0 0.6994E-07 -.4430E-32 -16.5 0.6230E-08 -.3081E-32 -17.0 0.4105E-09 -.2889E-32 -17.5 0.1934E-10 -.1926E-33 -18.0 0.6266E-12 0.3852E-32 -18.5 0.1335E-13 -.1926E-33 -19.0 0.1777E-15 0.2119E-32 -19.5 0.1396E-17 0.1733E-32 -20.0 0.6076E-20 -.3852E-33 diff --git a/lib/ftrsd/ftrsd_paper/bodide.f90 b/lib/ftrsd/ftrsd_paper/bodide.f90 deleted file mode 100644 index 72e0f13..0000000 --- a/lib/ftrsd/ftrsd_paper/bodide.f90 +++ /dev/null @@ -1,54 +0,0 @@ -program bodide -! Compute probability of word error for a bounded distance decoder. -! Hardwired for non-coherent 64-FSK and the JT65 RS (63,12) code on GF(64). -! -! Let ps be symbol error probability. -! The probability of getting an error pattern with e symbol errors is: -! ps^e * (1-ps)*(n-e) -! The number of error patterns with e errors is binomial(63,e) -! Overall probability of getting a word with e errors is: -! P(e)= binomial(63,e)* ps^e * (1-ps)*(n-e) -! Probability that word is correct is P(0 to 25 errors) = sum{e=0}^{25} P(e) -! Probability that word is wrong is 1-P(0 to 25 errors) -! P_word_error=1-( sum_{e=0}^{t} P(e) ) -! - implicit real*16 (a-h,o-z) - - integer*8 binomial - integer x,s,XX,NN,M - character arg*8 - - nargs=iargc() - if(nargs.ne.1) then - print*,'Probability of word error for noncoherent 64-FSK with bounded distance decoding' - print*,'Usage: bounded_distance D' - print*,'Example: bounded_distance 25' - go to 999 - endif - call getarg(1,arg) - read(arg,*) nt - M=64 - write(*,1012) -1012 format('Es/No P(word error)'/ & - '----------------------') - do isnr=0,40 - esno=10**(isnr/2.0/10.0) - hsum=0.d0 - do k=1,M-1 - h=binomial(M-1,k) - h=h*((-1)**(k+1))/(k+1) - h=h*exp(-esno*k/(k+1)) - hsum=hsum + h - enddo - ps=hsum - hsum=0.d0 - do i=0,nt - h=binomial(63,i) - h=h*ps**i - h=h*(1-ps)**(63-i) - hsum=hsum+h - enddo - pw=1-hsum - write(*,'(f4.1,4x,e10.4,4x,e10.4)') isnr/2.0, ps, pw - enddo -999 end program bodide diff --git a/lib/ftrsd/ftrsd_paper/bodide.lab b/lib/ftrsd/ftrsd_paper/bodide.lab deleted file mode 100644 index 6fa108e..0000000 --- a/lib/ftrsd/ftrsd_paper/bodide.lab +++ /dev/null @@ -1,4 +0,0 @@ -7.5 0.05 BM -6.9 0.015 Theory -5.55 0.05 KV -5.3 0.005 FT diff --git a/lib/ftrsd/ftrsd_paper/fig_bodide.gnuplot b/lib/ftrsd/ftrsd_paper/fig_bodide.gnuplot deleted file mode 100644 index b8bb0ad..0000000 --- a/lib/ftrsd/ftrsd_paper/fig_bodide.gnuplot +++ /dev/null @@ -1,24 +0,0 @@ -# gnuplot script for comparison to theoretical word error rate for -# bounded distance decoding - -# run: gnuplot fig_bodide.gnuplot -# then: pdflatex fig_bodide.tex - -set term epslatex standalone size 6in,2*6/3in -set output "fig_bodide.tex" -set xlabel "$E_b/N_0$ (dB)" -set ylabel "Word Error Rate" -set style func linespoints -set key off -set tics in -set mxtics 2 -set mytics 10 -set grid -set logscale y -plot [3:9] [1e-4:1] \ - "bmdata.dat" using ($1+29.1):(1-$2) with linespoints lt 2 lw 2 pt 2, \ - "ftdata-100000.dat" using ($1+29.1):(1-$3) with linespoints lt 1 lw 2 pt 7, \ - "bmtheory25.dat" using ($1-0.6):3 with linespoints lt 1 pt 5, \ - "kvasd-15.dat" using ($1+29.1):(1-$3) with linespoints lt 4 pt 6, \ - "bodide.lab" with labels - diff --git a/lib/ftrsd/ftrsd_paper/fig_ntrials_vs_nhard.gnuplot b/lib/ftrsd/ftrsd_paper/fig_ntrials_vs_nhard.gnuplot deleted file mode 100644 index 9a6c9b0..0000000 --- a/lib/ftrsd/ftrsd_paper/fig_ntrials_vs_nhard.gnuplot +++ /dev/null @@ -1,14 +0,0 @@ -# gnuplot script for "ntrials_vs_nhard" figure -# run: gnuplot fig_ntrials_vs_nhard.gnuplot -# then: pdflatex fig_ntrials_vs_nhard.tex -# -set term epslatex standalone size 6in,2*6/3in -set output "fig_ntrials_vs_nhard.tex" -set xlabel "Errors in received word, $X$" -set ylabel "Number of trials" -set tics in -set mxtics 5 -set mytics 10 -#set grid -set logscale y -plot "stats-100000-24db-3.dat" using 1:4 pt 12 notitle diff --git a/lib/ftrsd/ftrsd_paper/fig_psuccess.gnuplot b/lib/ftrsd/ftrsd_paper/fig_psuccess.gnuplot deleted file mode 100644 index 3718e29..0000000 --- a/lib/ftrsd/ftrsd_paper/fig_psuccess.gnuplot +++ /dev/null @@ -1,25 +0,0 @@ -# gnuplot script for "Percent copy" figure -# run: gnuplot fig_psuccess.gnuplot -# then: pdflatex fig_psuccess.tex -# -set term epslatex standalone size 6in,4in -set output "fig_psuccess.tex" -set xlabel "SNR in 2500 Hz Bandwidth (dB)" -set ylabel "Percent copy" -set style func linespoints -set key off -set tics in -set mxtics 2 -set mytics 2 -set grid -plot [-30:-18] [0:105] \ - "stats_0.0" using 1:($4)/10.0 with linespoints lt 2 lw 2 pt 2, \ - "stats_0.0" using 1:($5)/10.0 with linespoints lt 1 lw 2 pt 3, \ - "stats_0.0" using 1:($6)/10.0 with linespoints lt 3 lw 2 pt 4, \ - "stats_0.2" using 1:($4)/10.0 with linespoints lt 2 pt 2, \ - "stats_0.2" using 1:($5)/10.0 with linespoints lt 1 pt 3, \ - "stats_0.2" using 1:($6)/10.0 with linespoints lt 3 pt 4, \ - "stats_1.0" using 1:($4)/10.0 with linespoints lt 2 pt 2, \ - "stats_1.0" using 1:($5)/10.0 with linespoints lt 1 pt 3, \ - "stats_1.0" using 1:($6)/10.0 with linespoints lt 3 pt 4, \ - "psuccess.lab" with labels diff --git a/lib/ftrsd/ftrsd_paper/fig_psuccess.pdf b/lib/ftrsd/ftrsd_paper/fig_psuccess.pdf deleted file mode 100644 index 7464629..0000000 Binary files a/lib/ftrsd/ftrsd_paper/fig_psuccess.pdf and /dev/null differ diff --git a/lib/ftrsd/ftrsd_paper/fig_subtracted.tiff b/lib/ftrsd/ftrsd_paper/fig_subtracted.tiff deleted file mode 100644 index b6f0f2f..0000000 Binary files a/lib/ftrsd/ftrsd_paper/fig_subtracted.tiff and /dev/null differ diff --git a/lib/ftrsd/ftrsd_paper/fig_waterfall.png b/lib/ftrsd/ftrsd_paper/fig_waterfall.png deleted file mode 100644 index b2a8dd9..0000000 Binary files a/lib/ftrsd/ftrsd_paper/fig_waterfall.png and /dev/null differ diff --git a/lib/ftrsd/ftrsd_paper/fig_waterfall.tiff b/lib/ftrsd/ftrsd_paper/fig_waterfall.tiff deleted file mode 100644 index ae2cbdd..0000000 Binary files a/lib/ftrsd/ftrsd_paper/fig_waterfall.tiff and /dev/null differ diff --git a/lib/ftrsd/ftrsd_paper/fig_wer.gnuplot b/lib/ftrsd/ftrsd_paper/fig_wer.gnuplot deleted file mode 100644 index bff0533..0000000 --- a/lib/ftrsd/ftrsd_paper/fig_wer.gnuplot +++ /dev/null @@ -1,23 +0,0 @@ -# gnuplot script for "Percent copy" figure -# run: gnuplot fig_wer.gnuplot -# then: pdflatex fig_wer.tex -# -set term epslatex standalone size 6in,4in -set output "fig_wer.tex" -set xlabel "$E_b/N_0$ (dB)" -set ylabel "Word Error Rate" -set style func linespoints -set key off -set tics in -set mxtics 2 -set mytics 10 -set grid -set logscale y -plot [3:7] "ftdata-100000.dat" using ($1+29.1):(1-$2) with linespoints lt 1 pt 7 title 'FT-100K', \ - "ftdata-10000.dat" using ($1+29.1):(1-$2) with linespoints lt 1 pt 7 title 'FT-10K', \ - "ftdata-1000.dat" using ($1+29.1):(1-$2) with linespoints lt 1 pt 7 title 'FT-1K', \ - "kvasd-8.dat" using ($1+29.1):(1-$2) with linespoints lt 2 pt 8 title 'KV-8', \ - "kvasd-12.dat" using ($1+29.1):(1-$2) with linespoints lt 2 pt 8 title 'KV-12', \ - "kvasd-15.dat" using ($1+29.1):(1-$2) with linespoints lt 2 pt 8 title 'KV-15', \ - "bmdata.dat" using ($1+29.1):(1-$2) with linespoints pt 7 title 'BM', \ - "wer.lab" with labels diff --git a/lib/ftrsd/ftrsd_paper/fig_wer.pdf b/lib/ftrsd/ftrsd_paper/fig_wer.pdf deleted file mode 100644 index 6533f00..0000000 Binary files a/lib/ftrsd/ftrsd_paper/fig_wer.pdf and /dev/null differ diff --git a/lib/ftrsd/ftrsd_paper/fig_wer2.gnuplot b/lib/ftrsd/ftrsd_paper/fig_wer2.gnuplot deleted file mode 100644 index dc8edc9..0000000 --- a/lib/ftrsd/ftrsd_paper/fig_wer2.gnuplot +++ /dev/null @@ -1,23 +0,0 @@ -# gnuplot script for "Percent copy" figure -# run: gnuplot fig_wer2.gnuplot -# then: pdflatex fig_wer2.tex -# -set term epslatex standalone size 6in,6*2/3in -set output "fig_wer2.tex" -set xlabel "SNR in 2500 Hz Bandwidth (dB)" -set ylabel "Percent Copy" -set style func linespoints -set key off -set tics in -set mxtics 2 -set mytics 5 -set grid -plot [-27:-22] [0:110] \ - "ftdata-100000.dat" using 1:(100*$3) with linespoints lt 1 lw 2 pt 7, \ - "ftdata-10000.dat" using 1:(100*$3) with linespoints lt 1 lw 2 pt 7, \ - "ftdata-1000.dat" using 1:(100*$3) with linespoints lt 1 lw 2 pt 7, \ - "ftdata-100.dat" using 1:(100*$3) with linespoints lt 1 lw 2 pt 7, \ - "ftdata-10.dat" using 1:(100*$2) with linespoints lt 1 lw 2 pt 7, \ - "kvasd-15.dat" using 1:(100*$2) with linespoints lt 4 pt 6, \ - "bmdata.dat" using 1:(100*$2) with linespoints lt 2 lw 2 pt 2, \ - "wer2.lab" with labels diff --git a/lib/ftrsd/ftrsd_paper/fig_wer3.gnuplot b/lib/ftrsd/ftrsd_paper/fig_wer3.gnuplot deleted file mode 100644 index f3c9d27..0000000 --- a/lib/ftrsd/ftrsd_paper/fig_wer3.gnuplot +++ /dev/null @@ -1,21 +0,0 @@ -# gnuplot script for "Percent copy" figure -# run: gnuplot fig_wer3.gnuplot -# then: pdflatex fig_wer3.tex -# -set term epslatex standalone size 6in,6*2/3in -set output "fig_wer3.tex" -set xlabel "SNR in 2500 Hz Bandwidth (dB)" -set ylabel "Percent Copy" -set style func linespoints -set key off -set tics in -set mxtics 2 -set mytics 10 -set grid -set label "r6315" at -25.25,30 -set label "r6330" at -26.0,30 -set label "$T=10^5$" at -22.8,15 -set label "$d=0.0$" at -22.8,10 -plot [-27:-22] [0:110] \ - "ftdata-100000.dat" using 1:(100*$3) with linespoints lt 1 pt 7 title 'FT-100K', \ - "ftdata-100000.dat" using 1:(100*$2) with linespoints lt 1 pt 7 title 'FT-100K' diff --git a/lib/ftrsd/ftrsd_paper/ftdata-10.dat b/lib/ftrsd/ftrsd_paper/ftdata-10.dat deleted file mode 100644 index 467be38..0000000 --- a/lib/ftrsd/ftrsd_paper/ftdata-10.dat +++ /dev/null @@ -1,10 +0,0 @@ - snr psuccess ntrials 10, r6321, r6333 --26.0 0.0 --25.5 0.007 --25.0 0.039 --24.5 0.157 0.14 --24.0 0.362 --23.5 0.701 0.681 --23.0 0.914 --22.5 0.985 0.988 --22.0 1.0 1.0 diff --git a/lib/ftrsd/ftrsd_paper/ftdata-100.dat b/lib/ftrsd/ftrsd_paper/ftdata-100.dat deleted file mode 100644 index a5d547c..0000000 --- a/lib/ftrsd/ftrsd_paper/ftdata-100.dat +++ /dev/null @@ -1,10 +0,0 @@ - snr psuccess ntrials 100, r6321, r6333 --26.0 0.003 0.003 --25.5 0.033 0.037 --25.0 0.113 0.113 --24.5 0.315 0.330 --24.0 0.635 0.670 --23.5 0.908 0.903 --23.0 0.977 0.984 --22.5 0.9986 0.999 --22.0 1.0 1.0 diff --git a/lib/ftrsd/ftrsd_paper/ftdata-1000.dat b/lib/ftrsd/ftrsd_paper/ftdata-1000.dat deleted file mode 100644 index 156a0b3..0000000 --- a/lib/ftrsd/ftrsd_paper/ftdata-1000.dat +++ /dev/null @@ -1,9 +0,0 @@ - snr psuccess ntrials 1000, r6315, r6333 --26.0 0.010 0.022 --25.5 0.052 0.097 --25.0 0.22 0.262 --24.5 0.51 0.535 --24.0 0.80 0.844 --23.5 0.956 0.968 --23.0 0.9958 0.9963 --22.5 1.0 1.0 diff --git a/lib/ftrsd/ftrsd_paper/ftdata-10000.dat b/lib/ftrsd/ftrsd_paper/ftdata-10000.dat deleted file mode 100644 index 99d4859..0000000 --- a/lib/ftrsd/ftrsd_paper/ftdata-10000.dat +++ /dev/null @@ -1,11 +0,0 @@ - snr psuccess ntrials 10000 r6315, r6330 --27.0 0.000 0.001 --26.5 0.004 0.014 --26.0 0.03 0.066 --25.5 0.107 0.208 0.19 --25.0 0.353 0.424 0.40 (2) --24.5 0.653 0.725 --24.0 0.913 0.913 --23.5 0.983 0.988 --23.0 0.998 0.999 --22.0 1.0 1.0 diff --git a/lib/ftrsd/ftrsd_paper/ftdata-100000.dat b/lib/ftrsd/ftrsd_paper/ftdata-100000.dat deleted file mode 100644 index e2db520..0000000 --- a/lib/ftrsd/ftrsd_paper/ftdata-100000.dat +++ /dev/null @@ -1,11 +0,0 @@ -snr psuccess 100000 trials r6315, r6330, --27.0 0.0 0.011 --26.5 0.007 0.035 --26.0 0.057 0.135 --25.5 0.207 0.326 --25.0 0.531 0.568 --24.5 0.822 0.836 --24.0 0.953 0.966 --23.5 0.99423 0.996 --23.0 0.99967 0.99974 302956/303056, 218991/219046 - diff --git a/lib/ftrsd/ftrsd_paper/ftrsd.lyx b/lib/ftrsd/ftrsd_paper/ftrsd.lyx deleted file mode 100644 index 4549c76..0000000 --- a/lib/ftrsd/ftrsd_paper/ftrsd.lyx +++ /dev/null @@ -1,3289 +0,0 @@ -#LyX 2.1 created this file. For more info see http://www.lyx.org/ -\lyxformat 474 -\begin_document -\begin_header -\textclass paper -\begin_preamble -\usepackage{ragged2e} -\exhyphenpenalty=10000\hyphenpenalty=10000 - -\fancyhf{} -\fancyhead[L]{Franke \& Taylor: {\it Open Source Soft-Decision Decoder \ldots}} -\fancyhead[R]{\thepage} -\makeatletter -\let\ps@plain\ps@fancy % Plain page style = fancy page style -\makeatother - -\usepackage{nomencl} -\usepackage{overcite} - -\renewcommand{\nomname}{Sidebar: Glossary of Specialized Terms} -\end_preamble -\use_default_options true -\begin_modules -boxedfloat -\end_modules -\maintain_unincluded_children false -\language english -\language_package default -\inputencoding auto -\fontencoding global -\font_roman lmodern -\font_sans lmss -\font_typewriter lmtt -\font_math auto -\font_default_family default -\use_non_tex_fonts false -\font_sc false -\font_osf false -\font_sf_scale 100 -\font_tt_scale 100 -\graphics default -\default_output_format default -\output_sync 0 -\bibtex_command default -\index_command default -\float_placement H -\paperfontsize 12 -\spacing onehalf -\use_hyperref false -\papersize default -\use_geometry true -\use_package amsmath 1 -\use_package amssymb 1 -\use_package cancel 1 -\use_package esint 1 -\use_package mathdots 1 -\use_package mathtools 1 -\use_package mhchem 1 -\use_package stackrel 1 -\use_package stmaryrd 1 -\use_package undertilde 1 -\cite_engine basic -\cite_engine_type default -\biblio_style plain -\use_bibtopic false -\use_indices false -\paperorientation portrait -\suppress_date false -\justification false -\use_refstyle 1 -\index Index -\shortcut idx -\color #008000 -\end_index -\leftmargin 1in -\topmargin 1in -\rightmargin 1in -\bottommargin 1in -\secnumdepth 3 -\tocdepth 3 -\paragraph_separation skip -\defskip bigskip -\quotes_language english -\papercolumns 1 -\papersides 1 -\paperpagestyle fancy -\tracking_changes false -\output_changes false -\html_math_output 0 -\html_css_as_file 0 -\html_be_strict false -\end_header - -\begin_body - -\begin_layout Title -Open Source Soft-Decision Decoder for the JT65 (63,12) Reed-Solomon Code -\end_layout - -\begin_layout SubTitle - -\emph on -Under-the-hood description of the JT65 decoding procedure, including a wholly - new algorithm for its powerful error-correcting code. -\end_layout - -\begin_layout Author -Steven J. - Franke, K9AN and Joseph H. - Taylor, K1JT -\end_layout - -\begin_layout Section -\begin_inset CommandInset label -LatexCommand label -name "sec:Introduction-and-Motivation" - -\end_inset - -Background and Motivation -\end_layout - -\begin_layout Standard -\begin_inset ERT -status open - -\begin_layout Plain Layout - - -\backslash -RaggedRight -\end_layout - -\end_inset - - The JT65 protocol has revolutionized amateur-radio weak-signal communication - by enabling operators with small or compromise antennas and relatively - low-power transmitters to communicate over propagation paths not usable - with traditional technologies. - The protocol was developed in 2003 for Earth-Moon-Earth (EME, or -\begin_inset Quotes eld -\end_inset - -moonbounce -\begin_inset Quotes erd -\end_inset - -) communication -\begin_inset CommandInset citation -LatexCommand cite -key "jt65_protocol" - -\end_inset - -, where the scattered return signals are always weak. - It was soon found that JT65 also enables worldwide communication on the - HF bands with low power, modest antennas, and efficient spectral usage. - Thousands of amateurs now use JT65 on a regular basis, making contacts - on all bands from 160 meters through microwaves. -\end_layout - -\begin_layout Standard -JT65 uses timed transmitting and receiving sequences one minute long. - Messages are short and structured so as to streamline minimal exchanges - between two amateur operators over potentially difficult radio paths. - Most messages contain two callsigns and a grid locator, signal report, - acknowledgment, or sign-off; one of the tokens CQ, QRZ, or DE may be substitute -d for the first callsign. - Alternatively, a message may contain up to 13 Latin characters of arbitrary - text. - All messages are efficiently compressed into exactly 72 bits of digital - information. - It should be obvious that the JT65 protocol is intended for the basic purpose - of completing legitimate, documented two-way contacts, but not for extended - conversations. - Full details of the message structure and encoding procedure were presented - in an earlier publication -\begin_inset CommandInset citation -LatexCommand cite -key "jt65_protocol" - -\end_inset - -. - For a concise description of the overall process of transmitting and receiving - a JT65 message, see the accompanying sidebar -\series bold -JT65 Message Processing -\series default -. -\end_layout - -\begin_layout Standard -A major reason for the success and popularity of JT65 is its use of a strong - error-correction code. - Before transmission, each 72-bit message is divided into 12 six-bit -\emph on -symbols -\begin_inset CommandInset nomenclature -LatexCommand nomenclature -symbol "{\\bf Symbol: }" -description "The information carried in one signalling interval, usually an integral number of bits. JT65 uses 6-bit symbols." - -\end_inset - - -\emph default - and augmented with 51 additional symbols of error-correcting information. - These 51 -\emph on -parity symbols -\emph default - are computed according to information-theory rules that maximize the probabilit -y of correctly decoding the message, even if many symbols are received incorrect -ly. - The JT65 code is properly described as a short block-length, low-rate Reed-Solo -mon code based on a 64-symbol -\emph on -alphabet. - -\emph default - -\begin_inset CommandInset nomenclature -LatexCommand nomenclature -symbol "{\\bf Alphabet: }" -description "A sequence of possible symbol values used for signaling. JT65 uses a 64-character alphabet, values in the range 0 to 63." - -\end_inset - - Characters in this alphabet are mapped onto 64 different frequencies for - transmission. - -\end_layout - -\begin_layout Standard -Reed Solomon codes are widely used to ensure reliability in data transmission - and storage. - In hardware implementations, decoding is generally accomplished with a - procedure such as the Berlekamp-Massey (BM) algorithm, based on -\emph on -hard decisions -\emph default - -\begin_inset CommandInset nomenclature -LatexCommand nomenclature -symbol "{\\bf Hard decision: }" -description "Received symbols are assigned definite values by the demodulator." - -\end_inset - - for each of the symbol values received. - -\emph on -Soft decisions -\begin_inset CommandInset nomenclature -LatexCommand nomenclature -symbol "{\\bf Soft decision: }" -description "Received symbols are assigned tentative values (most probable, second most probable, etc.) and quality indicators." - -\end_inset - - -\emph default - are potentially more powerful, however. - For each received JT65 symbol we can estimate not only the value most likely - to be correct, but also the second, third, etc., most likely. - Most importantly, we can also estimate the probability that each of those - possible values is the correct one. - Decoders that make use of such information are called -\emph on -soft-decision decoders. -\end_layout - -\begin_layout Standard -Until now, nearly all programs implementing JT65 have used the patented - Kötter-Vardy (KV) algebraic soft-decision decoder -\begin_inset CommandInset citation -LatexCommand cite -key "kv2001" - -\end_inset - -, licensed to and implemented by K1JT as a closed-source executable for - use only in amateur radio applications. - Since 2001 the KV decoder has been considered the best available soft-decision - decoder for Reed Solomon codes. -\end_layout - -\begin_layout Standard -We describe here a new open-source alternative called the Franke-Taylor - (FT, or K9AN-K1JT) soft-decision decoding algorithm. - It is conceptually simple, built on top of the BM hard-decision decoder, - and in this application it performs even better than the KV decoder. - The FT algorithm is implemented in the popular programs -\emph on -WSJT -\emph default -, -\emph on -MAP65 -\emph default -, and -\emph on -WSJT-X -\emph default -, widely used for amateur weak-signal communication using JT65 and other - specialized digital protocols. - These programs are open-source, freely available -\begin_inset CommandInset citation -LatexCommand cite -key "wsjt" - -\end_inset - -, and licensed under the GNU General Public License. -\end_layout - -\begin_layout Standard -The JT65 protocol specifies transmissions that start one second into a UTC - minute and last for 46.8 seconds. - Receiving software therefore has as much as ten seconds to decode a message - before the start of the next minute, when the operator will send a reply. - With today's personal computers, this relatively long time encourages experimen -tation with decoders of high computational complexity. - With time to spare, the FT algorithm lowers the decoding threshold on a - typical fading channel by many dB over the hard-decision BM decoder, and - by a meaningful amount over the KV decoder. - In addition to its excellent performance, the new algorithm has other desirable - properties, not least of which is its conceptual simplicity. - Decoding performance and computational complexity scale in a convenient - way, providing steadily increasing soft-decision decoding gain as a tunable - parameter is increased over more than five orders of magnitude. - Appreciable gain is available from our decoder even on very simple (and - relatively slow) computers. - On the other hand, because the algorithm benefits from a large number of - independent decoding trials, further performance gains should be achievable - through parallelization on high-performance computers. -\end_layout - -\begin_layout Standard -The remainder of this paper is organized as follows. - Section 2 presents a brief overview of the nature of Reed Solomon codes - and their error-correcting capabilities. - Section 3 provides statistical motivation for the FT algorithm, and Section - 4 describes the algorithm in full detail. - Material in these two sections is important because it documents our approach - and underlines its fundamental technical contributions. - These sections are heavier in formal mathematics than common in -\emph on -QEX -\emph default -; for this reason, some readers may choose to skip or skim them and proceed - more quickly to the results. - Most readers will benefit by reviewing the original paper on the JT65 protocol - -\begin_inset CommandInset citation -LatexCommand cite -key "jt65_protocol" - -\end_inset - -. - A procedure for -\emph on -hinted decoding -\emph default ---- determining which one, if any, of a list of likely messages matches - the one that was received --- is outlined in Section 5. - Finally, in Section 6 we present performance measurements of the FT and - hinted decoding algorithms and make explicit comparisons to the BM and - KV decoders familiar to users of older versions of -\emph on -WSJT -\emph default -, -\emph on -MAP65 -\emph default - and -\emph on -WSJT-X -\emph default -. - Section 7 summarizes some on-the-air experiences with the new decoder. - Refer to the sidebar -\series bold -Glossary of Specialized Terms -\series default - for brief definitions of some potentially unfamiliar language. -\end_layout - -\begin_layout Section -\begin_inset CommandInset label -LatexCommand label -name "sec:JT65-messages-and" - -\end_inset - -JT65 Messages and Reed Solomon Codes -\end_layout - -\begin_layout Standard -The JT65 message frame consists of a short, compressed 72-bit message encoded - for transmission with a Reed-Solomon code. - Reed-Solomon codes are -\emph on -block codes -\emph default - -\begin_inset CommandInset nomenclature -LatexCommand nomenclature -symbol "{\\bf Block code: }" -description "An error-correcting code that treats data in blocks of fixed size." - -\end_inset - - characterized by -\begin_inset Formula $n$ -\end_inset - -, the length of their -\emph on -codewords -\emph default -; -\begin_inset CommandInset nomenclature -LatexCommand nomenclature -symbol "{\\bf Codeword:}" -description "For the JT65 code, a vector of 63 symbol values each in the range 0 to 63." - -\end_inset - - -\begin_inset Formula $k$ -\end_inset - -, the number of message symbols conveyed by the codeword; and the transmission - alphabet, or number of possible values for each symbol in a codeword. - The codeword length and the number of message symbols are specified with - the notation -\begin_inset Formula $(n,k)$ -\end_inset - -. - JT65 uses a (63,12) Reed-Solomon code with an alphabet of 64 possible values - for each symbol. - Each of the 12 message symbols represents -\begin_inset Formula $\log_{2}64=6$ -\end_inset - - message bits. - The source-encoded -\begin_inset CommandInset nomenclature -LatexCommand nomenclature -symbol "{\\bf Source encoding: }" -description "Compression of a message to use a minimum number or bits. JT65 source-encodes all messages to 72 bits." - -\end_inset - - message conveyed by a 63-symbol JT65 frame thus consists of 72 information - bits. - The JT65 code is -\emph on -systematic -\emph default -, which means that the 12 message symbols are embedded in the codeword without - modification and another 51 parity symbols derived from the message symbols - are added to form a codeword of 63 symbols. - -\end_layout - -\begin_layout Standard -In coding theory the concept of -\emph on -Hamming distance -\emph default - -\begin_inset CommandInset nomenclature -LatexCommand nomenclature -symbol "{\\bf Hamming distance: }" -description "The Hamming distance between two codewords, or between a received word and a codeword, is equal to the number of symbol positions in which they differ." - -\end_inset - - is used as a measure of disagreement between different codewords, or between - a received word -\begin_inset CommandInset nomenclature -LatexCommand nomenclature -symbol "{\\bf Received word: }" -description "A vector of symbol values, possibly accompanied by soft information on individual reliabilities." - -\end_inset - - and a codeword. - Hamming distance is the number of code symbols that differ in two words - being compared. - Reed-Solomon codes have guaranteed minimum Hamming distance -\begin_inset Formula $d$ -\end_inset - -, where -\begin_inset Formula -\begin{equation} -d=n-k+1.\label{eq:minimum_distance} -\end{equation} - -\end_inset - -With -\begin_inset Formula $n=63$ -\end_inset - - and -\begin_inset Formula $k=12$ -\end_inset - - the minimum Hamming distance of the JT65 code is -\begin_inset Formula $d=52$ -\end_inset - -. - With 72 information bits in each message, JT65 can transmit any one of - -\begin_inset Formula $2^{72}\approx4.7\times10^{21}$ -\end_inset - - possible messages. - The codeword for any message differs from every other codeword in at least - 52 of the 63 symbol positions. -\end_layout - -\begin_layout Standard -A received word containing some -\emph on -errors -\emph default - (incorrect symbols) can be decoded into the correct codeword using a determinis -tic, -\begin_inset CommandInset nomenclature -LatexCommand nomenclature -symbol "{\\bf Deterministic algorithm: }" -description "A series of computational steps that for the same input always produces the same output." - -\end_inset - - algebraic algorithm provided that no more than -\begin_inset Formula $t$ -\end_inset - - symbols were received incorrectly, where -\begin_inset Formula -\begin{equation} -t=\left\lfloor \frac{n-k}{2}\right\rfloor .\label{eq:t} -\end{equation} - -\end_inset - -For the JT65 code -\begin_inset Formula $t=25$ -\end_inset - -, so it is always possible to decode a received word having 25 or fewer - symbol errors. - Any one of several well-known algebraic algorithms, such as the BM algorithm, - can carry out this hard-decision decoding. - Two steps are necessarily involved in this process. - We must (1) determine which symbols were received incorrectly, and (2) - find the correct value of the incorrect symbols. - If we somehow know that certain symbols are incorrect, that information - can be used to reduce the work involved in step 1 and allow step 2 to correct - more than -\begin_inset Formula $t$ -\end_inset - - errors. - In the unlikely event that the location of every error is known, and if - no correct symbols are accidentally labeled as errors, the BM algorithm - can correct up to -\begin_inset Formula $d-1=n-k$ -\end_inset - - errors. - -\end_layout - -\begin_layout Standard -The FT algorithm creates lists of symbols suspected of being incorrect and - sends them to the BM decoder. - Symbols flagged in this way are called -\emph on -erasures -\emph default - -\begin_inset CommandInset nomenclature -LatexCommand nomenclature -symbol "{\\bf Erasure: }" -description "A received symbol may be ``erased'' when confidence in its value is so low that it is unlikely to provide useful information. " - -\end_inset - -. - With perfect erasure information up to -\begin_inset Formula $n-k=51$ -\end_inset - - incorrect symbols can be corrected for the JT65 code. - Imperfect erasure information means that some erased symbols may be correct, - and some other symbols in error. - If -\begin_inset Formula $s$ -\end_inset - - symbols are erased and the remaining -\begin_inset Formula $n-s$ -\end_inset - - symbols contain -\begin_inset Formula $e$ -\end_inset - - errors, the BM algorithm can find the correct codeword as long as -\begin_inset Formula -\begin{equation} -s+2e\le d-1.\label{eq:erasures_and_errors} -\end{equation} - -\end_inset - -If -\begin_inset Formula $s=0$ -\end_inset - -, the decoder is said to be an -\emph on -errors-only -\emph default - decoder. - If -\begin_inset Formula $0=x|N,X,s) '/ & - '-------------------------------') - - hsum=0.d0 - do ix=x,XX - h=hypergeo(ix,NN,XX,s) - hsum=hsum + h - write(*,1020) ix,h,hsum -1020 format(i3,2d13.4) - enddo - -999 end program prob diff --git a/lib/ftrsd/ftrsd_paper/psuccess.lab b/lib/ftrsd/ftrsd_paper/psuccess.lab deleted file mode 100644 index 21ed973..0000000 --- a/lib/ftrsd/ftrsd_paper/psuccess.lab +++ /dev/null @@ -1,14 +0,0 @@ --21.5 55 BM --24.5 50 FT --27.0 68 DS --25.2 25 0 --25.7 37 0.2 --24.6 16 1.0 --22.6 35 0 --20.9 29 0.2 --19.5 35 1.0 --28.5 25 1.0 --28.2 56 0.2 --28.5 72 0 - - diff --git a/lib/ftrsd/ftrsd_paper/stats-100000-24db-3.dat b/lib/ftrsd/ftrsd_paper/stats-100000-24db-3.dat deleted file mode 100644 index bd2a10f..0000000 --- a/lib/ftrsd/ftrsd_paper/stats-100000-24db-3.dat +++ /dev/null @@ -1,930 +0,0 @@ - 35 19 45 12 - 34 20 46 6 - 35 27 43 4519 - 33 21 44 11 - 32 22 39 8 - 34 21 48 333 - 30 20 42 2 - 38 25 43 12 - 38 25 49 2958 - 28 20 43 10 - 41 29 44 4070 - 32 19 44 1 - 28 19 43 2 - 38 28 43 10421 - 25 0 0 0 - 36 24 42 8 - 38 25 42 243 - 39 25 45 81 - 33 17 39 2 - 38 25 39 157 - 37 27 45 1 - 31 18 39 8 - 35 22 41 2 - 31 20 45 32 - 40 30 45 11123 - 34 25 48 516 - 37 22 49 73 - 32 19 45 2 - 39 25 43 49 - 35 25 42 12 - 43 32 45 3645 - 35 21 45 124 - 39 26 48 31 - 40 26 48 23 - 36 25 43 169 - 33 21 41 8 - 31 21 49 3 - 37 23 46 2 - 32 27 41 8 - 36 23 43 2112 - 29 19 49 4 - 34 24 41 170 - 27 15 44 1 - 34 21 43 2 - 39 25 47 28 - 30 18 43 10 - 37 22 40 8 - 42 33 48 64709 - 36 25 43 10 - 35 20 51 17 - 37 28 45 301 - 34 18 40 9 - 34 25 47 23 - 39 28 43 4856 - 36 24 45 7057 - 35 25 47 769 - 38 28 47 208 - 39 27 47 52290 - 35 22 44 85 - 34 23 48 7 - 37 21 47 82 - 42 25 39 1677 - 29 17 41 8 - 41 24 46 656 - 35 24 43 2 - 38 22 45 10400 - 36 20 42 14 - 33 22 46 2 - 25 0 0 0 - 33 20 45 12 - 30 17 45 1 - 34 20 43 40 - 32 21 42 14 - 28 15 44 1 - 37 23 42 8 - 32 21 40 8 - 39 28 44 65 - 30 17 41 2 - 32 25 44 134 - 38 24 43 12 - 38 23 47 153 - 39 26 42 8 - 37 20 47 35 - 39 27 47 1003 - 36 23 45 215 - 38 28 49 46 - 34 24 47 200 - 35 23 40 8 - 30 19 44 1 - 38 25 43 32 - 32 22 39 103 - 33 23 42 2 - 34 24 47 6 - 33 22 43 13 - 42 28 43 2127 - 34 22 41 113 - 39 30 41 517 - 30 17 42 8 - 32 20 45 1 - 34 20 51 17 - 32 15 39 9 - 37 23 47 223 - 28 15 43 1 - 38 24 42 251 - 41 26 45 2 - 39 25 49 7 - 35 26 47 237 - 32 18 43 25 - 33 23 43 8 - 41 29 43 2667 - 28 17 45 1 - 34 23 47 53 - 32 19 39 9 - 34 24 42 59 - 36 22 44 8 - 34 20 45 59 - 37 24 45 12 - 28 17 44 1 - 41 29 43 24865 - 32 19 46 6 - 33 22 47 6 - 36 20 47 143 - 36 22 47 34 - 33 19 39 9 - 38 22 44 523 - 34 24 42 737 - 36 24 39 170 - 35 22 43 2 - 32 19 48 22 - 33 20 49 76 - 42 24 49 6910 - 37 22 47 94 - 40 24 43 6 - 35 25 45 33 - 29 22 41 2 - 40 24 46 2096 - 37 20 45 135 - 36 26 43 113 - 36 21 43 13 - 37 24 47 49 - 35 24 43 54 - 37 22 43 8 - 35 23 44 2 - 30 20 43 11 - 39 30 47 2870 - 42 33 44 585 - 26 17 45 2 - 41 29 47 79 - 40 24 46 836 - 33 19 45 201 - 34 21 39 13 - 33 21 49 60 - 35 24 44 248 - 33 24 43 24 - 39 29 44 151 - 31 23 46 1 - 36 23 46 1 - 41 27 47 5565 - 42 26 47 378 - 35 27 45 4571 - 40 30 47 6422 - 32 20 42 8 - 38 28 45 449 - 38 26 47 595 - 39 24 47 1555 - 41 25 49 645 - 32 19 40 8 - 35 25 45 97 - 25 0 0 0 - 30 19 44 25 - 31 18 45 1 - 41 24 51 6915 - 34 23 46 1917 - 30 19 43 2 - 35 22 47 20 - 38 23 43 882 - 30 20 48 5 - 37 25 44 919 - 34 20 45 74 - 38 25 46 394 - 39 21 49 738 - 35 20 47 22 - 40 30 47 190 - 41 27 45 1515 - 39 27 49 55 - 35 25 41 994 - 39 27 47 7117 - 37 22 46 19 - 33 21 41 2 - 34 18 47 19 - 30 20 46 6 - 31 21 46 1 - 36 24 47 98 - 40 24 43 39 - 38 25 45 138 - 41 27 47 33 - 40 29 49 2510 - 36 26 43 2 - 34 21 45 1 - 40 26 49 1924 - 36 17 43 2 - 38 27 45 68 - 34 22 45 61 - 32 22 40 8 - 37 19 43 4784 - 32 16 43 8 - 38 27 50 46 - 35 21 43 38 - 35 22 49 4 - 38 27 49 31 - 39 28 47 4677 - 30 18 45 2 - 43 28 47 8235 - 38 28 43 830 - 32 21 47 15 - 37 24 42 10 - 37 23 45 259 - 37 25 45 35 - 40 24 45 524 - 35 19 44 1 - 36 23 45 84 - 36 24 50 17 - 31 20 46 1 - 35 24 42 74 - 42 27 47 1445 - 40 28 48 31 - 36 23 45 151 - 34 22 46 6 - 33 24 49 16 - 30 20 45 2 - 38 22 43 125 - 40 25 49 64 - 35 23 49 86 - 38 24 46 613 - 42 25 47 4232 - 34 24 43 31 - 32 18 41 2 - 37 26 43 70 - 37 27 41 14 - 37 22 39 129 - 38 27 49 3 - 32 22 47 15 - 41 27 41 472 - 38 24 43 25 - 35 28 43 309 - 41 25 47 82 - 40 23 43 8 - 40 21 43 1716 - 38 22 48 5 - 37 20 47 22 - 42 28 43 315 - 32 23 43 79 - 25 0 0 0 - 42 23 47 2245 - 35 24 45 2 - 41 25 44 12 - 36 23 43 1 - 36 19 45 151 - 41 28 45 2207 - 40 27 45 76 - 34 20 47 6 - 41 28 46 370 - 38 20 45 12 - 32 20 43 8 - 39 24 45 8 - 41 27 47 26941 - 35 23 46 3 - 34 25 41 14 - 43 27 47 26905 - 35 25 45 2 - 32 20 50 3 - 31 17 41 2 - 38 26 47 4157 - 33 24 41 2 - 41 29 43 26513 - 35 22 45 297 - 37 26 44 99 - 33 19 43 10 - 39 23 45 138 - 39 26 47 1320 - 33 22 42 2 - 42 32 45 791 - 33 23 51 3 - 38 25 43 8 - 40 27 49 1210 - 43 27 45 32969 - 37 26 49 108 - 38 18 45 1268 - 40 28 49 7810 - 36 25 44 47 - 38 27 48 20 - 34 20 44 10 - 41 27 45 429 - 33 18 43 8 - 29 17 45 1 - 40 25 42 9 - 30 21 49 4 - 37 22 45 10 - 23 0 0 0 - 36 15 45 2509 - 29 21 45 18 - 33 23 45 53 - 43 27 49 7533 - 37 28 45 2652 - 36 24 49 31 - 32 20 43 25 - 42 27 49 1500 - 41 26 45 8 - 40 25 47 152 - 37 26 45 151 - 37 27 43 139 - 34 20 47 4 - 31 21 43 44 - 37 28 45 241 - 35 25 45 422 - 33 22 45 6 - 39 26 48 23 - 38 27 49 359 - 42 26 45 1430 - 36 28 47 116 - 33 23 41 232 - 38 25 47 73 - 35 24 43 16 - 42 29 47 398 - 38 27 49 2203 - 32 20 47 3 - 32 18 48 3 - 36 23 47 44 - 37 24 48 147 - 39 22 45 31 - 31 20 44 1 - 34 21 43 8 - 39 27 47 201 - 34 23 44 12 - 34 24 43 8 - 36 17 46 2 - 41 27 47 8709 - 41 26 45 112 - 37 23 47 216 - 38 24 45 93 - 32 19 45 44 - 34 22 45 8 - 33 24 41 14 - 34 22 41 9 - 35 23 42 136 - 36 26 43 3272 - 34 18 44 40 - 38 25 43 316 - 29 23 39 9 - 35 23 45 2 - 41 29 42 136 - 37 26 43 12 - 34 21 46 43 - 39 21 47 23 - 40 29 49 14666 - 36 19 45 400 - 37 24 43 8 - 35 19 44 2 - 36 26 45 14 - 36 22 43 103 - 33 19 45 6 - 35 24 43 1 - 31 22 43 80 - 35 23 46 22 - 28 18 41 2 - 35 24 45 31 - 34 24 47 46 - 37 24 42 2 - 37 27 43 525 - 31 16 41 9 - 30 18 45 2 - 39 25 47 1416 - 37 24 46 23 - 40 28 49 5 - 39 26 46 2071 - 28 13 42 8 - 31 17 47 3 - 34 22 49 3 - 42 23 47 61 - 30 21 41 2 - 40 23 47 208 - 38 22 48 6 - 35 17 40 8 - 36 20 45 32 - 37 22 47 1116 - 41 28 47 14145 - 43 28 49 96342 - 35 19 45 102 - 31 23 43 8 - 33 20 43 1 - 30 19 46 90 - 41 27 45 19090 - 35 26 45 2942 - 40 25 47 127 - 35 23 45 12 - 37 26 46 76 - 31 19 44 32 - 42 31 49 4951 - 43 30 44 38924 - 35 19 51 17 - 41 31 44 6637 - 33 22 42 2 - 33 25 46 12 - 31 24 44 10 - 27 16 49 4 - 39 24 45 16 - 33 20 40 8 - 39 31 48 5073 - 39 21 47 72 - 35 21 47 3 - 38 27 41 1168 - 35 22 43 8 - 28 18 45 1 - 38 28 40 776 - 33 22 51 3 - 34 22 41 370 - 37 25 43 3210 - 32 24 43 8 - 35 24 46 3 - 39 20 45 41 - 35 17 43 49 - 39 29 46 20 - 31 21 44 1 - 43 24 48 4400 - 36 23 48 350 - 38 29 47 520 - 36 24 45 49 - 39 27 43 493 - 34 15 45 6 - 41 31 43 59993 - 34 24 42 27 - 31 14 41 1 - 40 30 47 13295 - 35 23 47 202 - 36 22 47 35 - 38 26 45 18576 - 34 26 43 54 - 40 30 51 173 - 43 29 47 105 - 34 24 39 9 - 33 20 43 8 - 35 27 45 65 - 31 18 42 2 - 31 21 45 6 - 40 27 45 979 - 36 21 47 3 - 29 14 43 1 - 37 24 47 432 - 39 24 50 4778 - 33 20 44 2 - 40 27 44 7398 - 36 22 47 148 - 35 21 44 11 - 35 22 45 206 - 30 18 42 8 - 40 30 43 8 - 30 22 42 9 - 29 21 39 9 - 41 26 43 1248 - 39 24 43 14 - 38 24 49 605 - 35 20 42 155 - 33 22 47 53 - 34 20 43 10 - 35 26 49 21 - 31 18 45 1 - 32 19 39 9 - 31 20 43 19 - 41 23 41 157 - 36 23 42 9 - 28 19 45 1 - 33 19 43 10 - 38 22 44 25 - 29 19 41 2 - 34 19 42 8 - 35 21 39 9 - 34 23 45 2 - 41 30 47 71025 - 40 26 48 3059 - 36 24 45 1346 - 35 19 47 34 - 36 25 45 112 - 39 27 41 7065 - 38 24 47 4 - 29 18 42 1 - 30 20 41 2 - 32 22 49 3 - 40 29 45 4589 - 38 25 42 234 - 42 28 49 3171 - 35 22 45 34 - 39 24 41 5693 - 29 20 43 2 - 29 16 44 14 - 37 25 45 19 - 36 18 44 8 - 36 27 45 1224 - 38 28 47 8906 - 29 15 51 3 - 33 20 47 46 - 33 17 41 9 - 40 22 45 1775 - 32 22 45 8 - 35 21 43 8 - 38 24 41 9 - 41 22 47 10005 - 36 27 43 12 - 33 21 47 35 - 35 21 39 9 - 34 22 44 2 - 34 17 45 67 - 31 18 45 1 - 34 21 46 32 - 35 26 44 1 - 34 23 44 8 - 31 24 47 3 - 43 23 49 9210 - 40 20 48 114 - 36 25 42 8 - 37 24 46 336 - 37 23 43 138 - 38 26 47 89 - 38 24 47 6494 - 30 18 45 1 - 43 28 47 677 - 31 23 48 3 - 32 19 43 1 - 36 23 44 19 - 43 30 47 81276 - 37 22 48 106 - 37 24 45 12 - 37 22 45 68 - 28 17 43 24 - 43 28 45 1446 - 40 30 46 2753 - 35 23 44 1 - 28 16 43 2 - 29 19 42 2 - 31 21 42 2 - 39 26 48 98 - 41 30 47 21848 - 35 22 47 5 - 40 31 45 448 - 34 23 45 94 - 29 17 42 8 - 39 30 46 1231 - 41 22 47 49 - 30 15 51 7 - 35 26 41 9 - 29 17 49 7 - 33 22 43 12 - 33 19 46 5 - 35 24 45 12 - 33 22 42 9 - 34 18 43 13 - 36 21 43 63 - 37 27 45 32 - 37 23 49 474 - 31 17 46 19 - 38 24 41 2 - 40 28 47 1621 - 39 25 47 214 - 32 21 42 19 - 34 22 47 105 - 35 26 42 2 - 35 21 44 13 - 40 25 47 556 - 39 27 49 3 - 36 25 45 32 - 39 27 41 10 - 35 20 45 1 - 28 17 45 1 - 35 23 47 6 - 33 20 50 137 - 34 22 43 177 - 30 19 41 9 - 33 23 47 579 - 33 22 39 9 - 39 20 42 74 - 42 28 47 112 - 40 29 44 197 - 36 23 43 2 - 30 17 49 3 - 37 27 45 3815 - 35 24 43 74 - 35 22 47 24 - 40 27 46 82 - 36 25 41 366 - 33 23 44 1 - 37 21 40 131 - 34 22 45 16 - 36 24 45 306 - 39 26 47 82 - 29 17 45 1 - 36 23 48 3 - 35 20 44 63 - 35 23 46 5 - 39 25 43 792 - 32 22 49 5 - 35 23 41 9 - 37 24 41 12711 - 41 32 43 36575 - 34 23 42 8 - 31 21 43 2 - 35 24 41 2 - 35 24 39 8 - 37 23 48 75 - 35 19 43 12 - 40 25 49 914 - 38 22 49 60 - 34 19 42 10 - 42 33 44 9038 - 37 27 45 1849 - 29 20 42 138 - 37 27 43 332 - 36 26 45 36 - 32 18 45 6 - 37 25 46 4676 - 29 18 45 6 - 34 22 43 8 - 41 32 45 1966 - 30 18 42 12 - 33 20 45 1 - 31 23 45 6 - 30 21 46 1 - 36 21 43 14 - 34 18 45 37 - 42 32 47 3508 - 41 32 41 13 - 37 25 45 719 - 33 20 45 111 - 38 28 42 8 - 35 23 43 14 - 39 23 47 123 - 28 13 44 1 - 34 19 41 38 - 35 21 43 8 - 33 26 47 124 - 30 18 41 9 - 43 30 46 11935 - 40 28 48 2329 - 35 19 45 286 - 30 21 43 80 - 37 21 49 474 - 41 27 49 1560 - 42 24 46 1802 - 38 28 42 6807 - 38 24 43 63 - 33 24 49 35 - 41 27 41 9795 - 29 16 41 2 - 29 17 43 2 - 34 21 45 125 - 39 28 45 1008 - 34 21 42 8 - 36 23 45 2 - 34 22 41 8 - 34 21 41 74 - 37 21 43 262 - 30 18 41 8 - 33 22 49 3 - 33 21 42 1 - 35 28 49 21 - 31 19 43 1 - 36 24 44 10 - 40 23 49 583 - 33 19 37 9 - 32 21 45 6 - 38 24 47 15 - 42 27 47 2847 - 36 28 45 106 - 39 28 43 53 - 30 16 42 2 - 28 18 49 3 - 33 21 44 1 - 36 24 45 3050 - 37 27 40 8 - 35 19 43 12 - 41 29 43 19008 - 21 0 0 0 - 38 26 41 762 - 33 21 46 12 - 41 26 47 14517 - 33 24 49 3 - 41 31 47 287 - 35 24 51 17 - 37 27 42 38 - 34 22 43 24 - 39 26 46 135 - 38 26 41 493 - 35 22 42 8 - 38 24 41 1082 - 32 23 42 1 - 33 24 40 8 - 37 25 48 640 - 28 14 39 9 - 39 20 45 212 - 37 29 45 610 - 34 26 47 57 - 29 21 41 8 - 35 16 45 53 - 35 21 44 2 - 38 26 48 188 - 34 25 41 10 - 36 23 44 8 - 35 21 45 8 - 35 26 41 8 - 37 26 40 9 - 28 12 43 1 - 34 22 51 3 - 35 25 44 13 - 32 16 44 32 - 32 19 45 143 - 29 17 43 1 - 35 22 43 93 - 38 21 43 99 - 36 26 49 242 - 34 22 45 8 - 40 24 45 136 - 40 24 48 88 - 38 21 46 49 - 40 27 49 116 - 41 26 44 3696 - 35 23 42 8 - 28 15 45 104 - 33 21 43 106 - 35 25 45 31 - 33 24 40 113 - 36 24 46 23 - 37 25 45 334 - 32 21 46 12 - 35 21 41 2 - 36 22 45 8 - 37 18 43 13 - 37 26 47 48 - 39 25 46 400 - 37 27 43 174 - 37 23 47 41 - 40 21 47 1811 - 38 26 45 79 - 26 15 43 1 - 39 27 49 19 - 31 19 44 1 - 37 22 43 8 - 32 24 38 9 - 34 23 48 3 - 37 24 51 22 - 27 18 42 2 - 31 22 47 5 - 33 17 41 2 - 40 28 45 14534 - 37 21 47 5 - 27 15 43 2 - 43 26 47 46658 - 39 22 43 8 - 36 23 41 2 - 31 19 43 12 - 36 24 43 10 - 33 20 43 149 - 30 19 47 3 - 39 27 51 1236 - 41 26 45 4744 - 39 22 47 100 - 32 18 44 6 - 32 21 43 54 - 40 30 46 777 - 35 25 43 355 - 36 24 41 138 - 40 30 47 3056 - 39 28 46 19 - 34 21 46 6 - 34 18 46 52 - 36 27 41 232 - 35 25 51 3 - 36 28 44 110 - 33 23 45 1 - 37 22 46 64301 - 39 23 49 41 - 39 30 40 25 - 36 23 48 6 - 29 17 42 2 - 36 23 44 1 - 32 17 43 40 - 32 16 49 86 - 29 19 49 5 - 38 26 41 9 - 40 28 43 56710 - 41 29 45 1711 - 36 23 49 345 - 35 25 43 8 - 35 24 46 19 - 37 23 41 648 - 30 18 45 1 - 30 21 43 1 - 34 20 45 12 - 42 25 47 431 - 40 27 41 15878 - 34 22 43 8 - 41 29 48 49 - 32 21 43 2 - 37 22 43 2 - 39 28 49 86 - 43 28 45 8032 - 41 30 49 15674 - 34 22 48 17 - 36 24 48 107 - 28 20 44 1 - 43 28 48 1986 - 40 25 47 2585 - 38 21 43 59 - 38 28 41 167 - 34 22 39 9 - 43 27 48 4196 - 32 20 44 120 - 33 25 45 99 - 26 12 42 2 - 26 15 47 4 - 37 21 42 10 - 35 25 49 3 - 42 30 49 11151 - 33 20 44 2 - 39 26 45 65238 - 31 16 40 2 - 38 26 39 8 - 36 22 45 82 - 32 22 49 7 - 33 20 45 2 - 40 24 43 12 - 32 18 50 3 - 31 21 40 2 - 34 18 44 2 - 38 28 46 194 - 36 21 43 12 - 32 20 43 8 - 30 18 42 2 - 37 21 47 31 - 36 23 47 15 - 36 21 45 113 - 34 23 44 1 - 43 29 49 3889 - 37 24 47 32 - 41 22 43 243 - 38 25 47 707 - 35 22 43 18399 - 33 22 45 123 - 37 24 42 8 - 39 25 47 1087 - 34 23 47 107 - 32 21 42 2 - 42 25 47 106 - 39 24 42 13560 - 42 29 49 52387 - 38 27 43 59 - 31 18 39 9 - 40 28 48 41 - 37 25 45 11 - 30 23 45 242 - 38 23 47 1673 - 36 23 45 751 - 29 22 41 2 - 36 19 48 3 - 36 22 45 12 - 35 18 47 20 - 40 28 49 17369 - 29 19 46 2 - 36 26 42 25 - 42 30 49 4767 - 30 20 45 6 - 35 24 44 12 - 41 24 42 1537 - 38 25 47 629 - 31 21 44 2 - 34 22 43 1 - 33 20 47 3 - 34 20 43 8 - 40 26 49 4320 - 31 16 43 9 - 34 22 45 8 - 32 22 46 124 - 32 20 43 13 - 40 28 47 1185 - 41 24 45 30643 - 39 23 43 1658 - 33 23 44 8 - 36 22 46 23 - 41 25 47 114 - 36 21 42 12 - 33 19 48 31 - 42 28 48 76 - 29 22 39 9 - 36 21 47 3 - 37 27 45 282 - 42 29 46 24995 - 36 26 39 9 - 40 25 46 123 - 39 26 41 8 - 41 30 45 3143 - 34 20 41 27 - 38 31 42 17297 - 40 24 51 3052 - 36 28 45 190 - 31 23 42 8 - 42 26 42 68 - 39 31 45 37327 - 37 27 41 8 - 36 20 45 76 - 38 26 42 10 - 36 21 45 63 - 40 31 43 140 - 40 27 49 21 - 31 22 36 9 - 34 22 39 9 - 29 17 43 2 - 36 26 45 61 - 38 23 45 15 - 31 21 43 54 - 36 22 41 93 - 31 18 43 2 - 35 25 49 108 - 41 29 45 18292 - 37 25 45 104 - 28 20 41 2 - 35 26 46 35 - 34 20 46 19 - 38 22 51 183 - 34 14 43 8 - 32 23 43 16 - 27 17 44 1 - 29 15 42 2 - 37 26 41 129 diff --git a/lib/ftrsd/ftrsd_paper/stats_0.0 b/lib/ftrsd/ftrsd_paper/stats_0.0 deleted file mode 100644 index 75c9778..0000000 --- a/lib/ftrsd/ftrsd_paper/stats_0.0 +++ /dev/null @@ -1,27 +0,0 @@ - SNR Files Sync BM FT Hint Total False BadSync --------------------------------------------------------- --18.0 1000 1000 1000 1000 1000 1000 0 0 --18.5 1000 1000 1000 1000 1000 1000 0 0 --19.0 1000 1000 1000 1000 1000 1000 0 0 --19.5 1000 1000 1000 1000 1000 1000 0 0 --20.0 1000 1000 1000 1000 1000 1000 0 0 --20.5 1000 1000 1000 1000 1000 1000 0 0 --21.0 1000 1000 1000 1000 1000 1000 0 0 --21.5 1000 1000 991 1000 1000 1000 0 0 --22.0 1000 1000 918 1000 1000 1000 0 0 --22.5 1000 1000 631 1000 1000 1000 0 0 --23.0 1000 1000 261 1000 1000 1000 0 0 --23.5 1000 1000 57 990 1000 1000 0 0 --24.0 1000 1000 0 925 1000 1000 0 0 --24.5 1000 1000 0 737 1000 1000 0 0 --25.0 1000 999 0 445 999 999 1 ? --25.5 1000 996 0 191 996 996 2 ? --26.0 1000 980 0 68 985 985 3 ? --26.5 1000 953 0 18 975 975 3 ? --27.0 1000 904 0 3 926 926 4 ? --27.5 1000 816 0 2 874 874 3 ? --28.0 1000 722 0 0 786 786 7 ? --28.5 1000 590 0 0 616 616 12 ? --29.0 1000 451 0 0 479 479 15 ? --29.5 1000 355 0 0 303 303 27 ? --30.0 1000 277 0 0 173 173 28 ? diff --git a/lib/ftrsd/ftrsd_paper/stats_0.2 b/lib/ftrsd/ftrsd_paper/stats_0.2 deleted file mode 100644 index 1e0cb00..0000000 --- a/lib/ftrsd/ftrsd_paper/stats_0.2 +++ /dev/null @@ -1,27 +0,0 @@ - SNR Files Sync BM FT Hint Total False BadSync --------------------------------------------------------- --18.0 1000 998 973 998 998 998 0 2 --18.5 1000 1000 960 1000 1000 1000 0 0 --19.0 1000 1000 917 1000 1000 1000 0 0 --19.5 1000 1000 849 1000 1000 1000 0 0 --20.0 1000 1000 725 1000 1000 1000 0 0 --20.5 1000 1000 549 1000 1000 1000 0 0 --21.0 1000 1000 373 1000 1000 1000 0 0 --21.5 1000 1000 216 1000 1000 1000 0 0 --22.0 1000 1000 100 998 1000 1000 0 0 --22.5 1000 1000 32 998 1000 1000 0 0 --23.0 1000 1000 12 991 1000 1000 0 0 --23.5 1000 998 2 958 1000 1000 0 2 --24.0 1000 992 0 878 998 998 1 8 --24.5 1000 986 0 739 995 995 0 14 --25.0 1000 977 0 533 991 991 0 23 --25.5 1000 959 0 324 975 975 3 41 --26.0 1000 930 0 153 953 953 1 70 --26.5 1000 874 0 51 924 924 8 126 --27.0 1000 808 0 14 866 866 6 192 --27.5 1000 716 0 3 799 799 10 284 --28.0 1000 610 0 1 689 689 14 390 --28.5 1000 497 0 0 596 596 19 503 --29.0 1000 399 0 0 451 451 21 601 --29.5 1000 300 0 0 270 270 27 700 --30.0 1000 243 0 0 172 172 26 757 diff --git a/lib/ftrsd/ftrsd_paper/stats_1.0 b/lib/ftrsd/ftrsd_paper/stats_1.0 deleted file mode 100644 index 34f94c6..0000000 --- a/lib/ftrsd/ftrsd_paper/stats_1.0 +++ /dev/null @@ -1,27 +0,0 @@ - SNR Files Sync BM FT Hint Total False BadSync --------------------------------------------------------- --18.0 1000 998 917 998 998 998 1 2 --18.5 1000 998 824 998 998 998 0 2 --19.0 1000 999 695 999 999 999 0 1 --19.5 1000 999 504 999 999 999 0 1 --20.0 1000 1000 300 1000 1000 1000 0 0 --20.5 1000 1000 148 1000 1000 1000 0 0 --21.0 1000 1000 56 1000 1000 1000 0 0 --21.5 1000 1000 10 1000 1000 1000 0 0 --22.0 1000 999 3 995 1000 1000 0 1 --22.5 1000 998 0 972 1000 1000 0 2 --23.0 1000 997 0 899 999 999 0 3 --23.5 1000 996 0 758 999 999 0 4 --24.0 1000 990 0 545 999 999 0 10 --24.5 1000 981 0 305 988 988 2 19 --25.0 1000 964 0 128 987 987 0 36 --25.5 1000 930 0 43 956 956 4 70 --26.0 1000 870 0 15 932 932 4 130 --26.5 1000 810 0 4 889 889 8 190 --27.0 1000 737 0 0 798 798 9 263 --27.5 1000 632 0 0 650 650 10 368 --28.0 1000 522 0 0 526 526 15 478 --28.5 1000 426 0 0 383 383 19 574 --29.0 1000 332 0 0 226 226 34 668 --29.5 1000 260 0 0 136 136 32 740 --30.0 1000 209 0 0 64 64 47 791 diff --git a/lib/ftrsd/ftrsd_paper/wer.lab b/lib/ftrsd/ftrsd_paper/wer.lab deleted file mode 100644 index e69de29..0000000 diff --git a/lib/ftrsd/ftrsd_paper/wer2.lab b/lib/ftrsd/ftrsd_paper/wer2.lab deleted file mode 100644 index b3440f8..0000000 --- a/lib/ftrsd/ftrsd_paper/wer2.lab +++ /dev/null @@ -1,7 +0,0 @@ --25.7 30 $10^5$ --25.25 36 $10^4$ --24.5 44 $10^3$ --24.15 48 $10^2$ --23.7 44 10 --22.5 48 BM --25.2 24 KV \ No newline at end of file diff --git a/lib/ftrsd/ftrsdap.c b/lib/ftrsd/ftrsdap.c deleted file mode 100644 index b2b85dd..0000000 --- a/lib/ftrsd/ftrsdap.c +++ /dev/null @@ -1,227 +0,0 @@ -/* - ftrsdap.c - - A soft-decision decoder for the JT65 (63,12) Reed-Solomon code. - - This decoding scheme is built around Phil Karn's Berlekamp-Massey - errors and erasures decoder. The approach is inspired by a number of - publications, including the stochastic Chase decoder described - in "Stochastic Chase Decoding of Reed-Solomon Codes", by Leroux et al., - IEEE Communications Letters, Vol. 14, No. 9, September 2010 and - "Soft-Decision Decoding of Reed-Solomon Codes Using Successive Error- - and-Erasure Decoding," by Soo-Woong Lee and B. V. K. Vijaya Kumar. - - Steve Franke K9AN and Joe Taylor K1JT - */ - -#include -#include -#include -#include -#include -#include "../ftrsd/rs2.h" - -static void *rs; -void getpp_(int workdat[], float *pp); - -void ftrsdap_(int mrsym[], int mrprob[], int mr2sym[], int mr2prob[], - int ap[], int* ntrials0, int correct[], int param[], int ntry[]) -{ - int rxdat[63], rxprob[63], rxdat2[63], rxprob2[63]; - int workdat[63]; - int indexes[63]; - int era_pos[51]; - int i, j, numera, nerr, nn=63; - int ntrials = *ntrials0; - int nhard=0,nhard_min=32768,nsoft=0,nsoft_min=32768; - int ntotal=0,ntotal_min=32768,ncandidates; - int nera_best=0; - float pp,pp1,pp2; - static unsigned int nseed; - -// Power-percentage symbol metrics - composite gnnf/hf - int perr[8][8] = { - { 4, 9, 11, 13, 14, 14, 15, 15}, - { 2, 20, 20, 30, 40, 50, 50, 50}, - { 7, 24, 27, 40, 50, 50, 50, 50}, - {13, 25, 35, 46, 52, 70, 50, 50}, - {17, 30, 42, 54, 55, 64, 71, 70}, - {25, 39, 48, 57, 64, 66, 77, 77}, - {32, 45, 54, 63, 66, 75, 78, 83}, - {51, 58, 57, 66, 72, 77, 82, 86}}; - - -// Initialize the KA9Q Reed-Solomon encoder/decoder - unsigned int symsize=6, gfpoly=0x43, fcr=3, prim=1, nroots=51; - rs=init_rs_int(symsize, gfpoly, fcr, prim, nroots, 0); - -// Reverse the received symbol vectors for BM decoder - for (i=0; i<63; i++) { - rxdat[i]=mrsym[62-i]; - rxprob[i]=mrprob[62-i]; - rxdat2[i]=mr2sym[62-i]; - rxprob2[i]=mr2prob[62-i]; - } - -// Set ap symbols and ap mask - for (i=0; i<12; i++) { - if(ap[i]>=0) { - rxdat[11-i]=ap[i]; - rxprob2[11-i]=-1; - } - } - -// Sort rxprob to find indexes of the least reliable symbols - int k, pass, tmp, nsym=63; - int probs[63]; - for (i=0; i<63; i++) { - indexes[i]=i; - probs[i]=rxprob[i]; - } - for (pass = 1; pass <= nsym-1; pass++) { - for (k = 0; k < nsym - pass; k++) { - if( probs[k] < probs[k+1] ) { - tmp = probs[k]; - probs[k] = probs[k+1]; - probs[k+1] = tmp; - tmp = indexes[k]; - indexes[k] = indexes[k+1]; - indexes[k+1] = tmp; - } - } - } - -// See if we can decode using BM HDD, and calculate the syndrome vector. - memset(era_pos,0,51*sizeof(int)); - numera=0; - memcpy(workdat,rxdat,sizeof(rxdat)); - nerr=decode_rs_int(rs,workdat,era_pos,numera,1); - if( nerr >= 0 ) { - // Hard-decision decoding succeeded. Save codeword and some parameters. - nhard=0; - for (i=0; i<63; i++) { - if( workdat[i] != rxdat[i] ) nhard=nhard+1; - } - memcpy(correct,workdat,63*sizeof(int)); - param[0]=0; - param[1]=nhard; - param[2]=0; - param[3]=0; - param[4]=0; - param[5]=0; - param[7]=1000*1000; - ntry[0]=0; - return; - } - -/* -Hard-decision decoding failed. Try the FT soft-decision method. -Generate random erasure-locator vectors and see if any of them -decode. This will generate a list of "candidate" codewords. The -soft distance between each candidate codeword and the received -word is estimated by finding the largest (pp1) and second-largest -(pp2) outputs from a synchronized filter-bank operating on the -symbol spectra, and using these to decide which candidate -codeword is "best". -*/ - - nseed=1; //Seed for random numbers - float ratio; - int thresh, nsum; - int thresh0[63]; - ncandidates=0; - nsum=0; - int ii,jj; - for (i=0; i=0 ) { - ratio = (float)rxprob2[j]/((float)rxprob[j]+0.01); - ii = 7.999*ratio; - jj = (62-i)/8; - thresh0[i] = 1.3*perr[ii][jj]; - } else { - thresh0[i] = 0.0; - } -//printf("%d %d %d\n",i,j,rxdat[i]); - } - - if(nsum<=0) return; - - pp1=0.0; - pp2=0.0; - for (k=1; k<=ntrials; k++) { - memset(era_pos,0,51*sizeof(int)); - memcpy(workdat,rxdat,sizeof(rxdat)); - -/* -Mark a subset of the symbols as erasures. -Run through the ranked symbols, starting with the worst, i=0. -NB: j is the symbol-vector index of the symbol with rank i. -*/ - numera=0; - for (i=0; i= 0 ) { - // We have a candidate codeword. Find its hard and soft distance from - // the received word. Also find pp1 and pp2 from the full array - // s3(64,63) of synchronized symbol spectra. - ncandidates=ncandidates+1; - nhard=0; - nsoft=0; - for (i=0; i<63; i++) { - if(workdat[i] != rxdat[i]) { - nhard=nhard+1; - if(workdat[i] != rxdat2[i]) { - nsoft=nsoft+rxprob[i]; - } - } - } - nsoft=63*nsoft/nsum; - ntotal=nsoft+nhard; - - getpp_(workdat,&pp); - if(pp>pp1) { - pp2=pp1; - pp1=pp; - nsoft_min=nsoft; - nhard_min=nhard; - ntotal_min=ntotal; - memcpy(correct,workdat,63*sizeof(int)); - nera_best=numera; - ntry[0]=k; - } else { - if(pp>pp2 && pp!=pp1) pp2=pp; - } - if(nhard_min <= 41 && ntotal_min <= 71) break; - } - if(k == ntrials) ntry[0]=k; - } - - param[0]=ncandidates; - param[1]=nhard_min; - param[2]=nsoft_min; - param[3]=nera_best; - param[4]=1000.0*pp2/pp1; - param[5]=ntotal_min; - param[6]=ntry[0]; - param[7]=1000.0*pp2; - param[8]=1000.0*pp1; - if(param[0]==0) param[2]=-1; - return; -} diff --git a/lib/ftrsd/init_rs.c b/lib/ftrsd/init_rs.c deleted file mode 100644 index 4b1d1ed..0000000 --- a/lib/ftrsd/init_rs.c +++ /dev/null @@ -1,119 +0,0 @@ -/* Initialize a RS codec - * - * Copyright 2002 Phil Karn, KA9Q - * May be used under the terms of the GNU General Public License (GPL) - */ -#include - -#ifdef CCSDS -#include "ccsds.h" -#elif defined(BIGSYM) -#include "int.h" -#else -#include "char.h" -#endif - -void FREE_RS(void *p){ - struct rs *rs = (struct rs *)p; - - free(rs->alpha_to); - free(rs->index_of); - free(rs->genpoly); - free(rs); -} - -/* Initialize a Reed-Solomon codec - * symsize = symbol size, bits (1-8) - * gfpoly = Field generator polynomial coefficients - * fcr = first root of RS code generator polynomial, index form - * prim = primitive element to generate polynomial roots - * nroots = RS code generator polynomial degree (number of roots) - */ -void *INIT_RS(unsigned int symsize,unsigned int gfpoly,unsigned fcr,unsigned prim, - unsigned int nroots){ - struct rs *rs; - int i, j, sr,root,iprim; - - if(symsize > 8*sizeof(DTYPE)) - return NULL; /* Need version with ints rather than chars */ - - if(fcr >= (1<= (1<= (1<mm = symsize; - rs->nn = (1<alpha_to = (DTYPE *)malloc(sizeof(DTYPE)*(rs->nn+1)); - if(rs->alpha_to == NULL){ - free(rs); - return NULL; - } - rs->index_of = (DTYPE *)malloc(sizeof(DTYPE)*(rs->nn+1)); - if(rs->index_of == NULL){ - free(rs->alpha_to); - free(rs); - return NULL; - } - - /* Generate Galois field lookup tables */ - rs->index_of[0] = A0; /* log(zero) = -inf */ - rs->alpha_to[A0] = 0; /* alpha**-inf = 0 */ - sr = 1; - for(i=0;inn;i++){ - rs->index_of[sr] = i; - rs->alpha_to[i] = sr; - sr <<= 1; - if(sr & (1<nn; - } - if(sr != 1){ - /* field generator polynomial is not primitive! */ - free(rs->alpha_to); - free(rs->index_of); - free(rs); - return NULL; - } - - /* Form RS code generator polynomial from its roots */ - rs->genpoly = (DTYPE *)malloc(sizeof(DTYPE)*(nroots+1)); - if(rs->genpoly == NULL){ - free(rs->alpha_to); - free(rs->index_of); - free(rs); - return NULL; - } - rs->fcr = fcr; - rs->prim = prim; - rs->nroots = nroots; - - /* Find prim-th root of 1, used in decoding */ - for(iprim=1;(iprim % prim) != 0;iprim += rs->nn) - ; - rs->iprim = iprim / prim; - - rs->genpoly[0] = 1; - for (i = 0,root=fcr*prim; i < nroots; i++,root += prim) { - rs->genpoly[i+1] = 1; - - /* Multiply rs->genpoly[] by @**(root + x) */ - for (j = i; j > 0; j--){ - if (rs->genpoly[j] != 0) - rs->genpoly[j] = rs->genpoly[j-1] ^ rs->alpha_to[modnn(rs,rs->index_of[rs->genpoly[j]] + root)]; - else - rs->genpoly[j] = rs->genpoly[j-1]; - } - /* rs->genpoly[0] can never be zero */ - rs->genpoly[0] = rs->alpha_to[modnn(rs,rs->index_of[rs->genpoly[0]] + root)]; - } - /* convert rs->genpoly[] to index form for quicker encoding */ - for (i = 0; i <= nroots; i++) - rs->genpoly[i] = rs->index_of[rs->genpoly[i]]; - - return rs; -} diff --git a/lib/ftrsd/int.h b/lib/ftrsd/int.h deleted file mode 100644 index ada5bfd..0000000 --- a/lib/ftrsd/int.h +++ /dev/null @@ -1,54 +0,0 @@ -/* Include file to configure the RS codec for integer symbols - * - * Copyright 2002, Phil Karn, KA9Q - * May be used under the terms of the GNU General Public License (GPL) - */ -#define DTYPE int - -/* Reed-Solomon codec control block */ -struct rs { - unsigned int mm; /* Bits per symbol */ - unsigned int nn; /* Symbols per block (= (1<= rs->nn) { - x -= rs->nn; - x = (x >> rs->mm) + (x & rs->nn); - } - return x; -} -#define MODNN(x) modnn(rs,x) - -#define MM (rs->mm) -#define NN (rs->nn) -#define ALPHA_TO (rs->alpha_to) -#define INDEX_OF (rs->index_of) -#define GENPOLY (rs->genpoly) -#define NROOTS (rs->nroots) -#define FCR (rs->fcr) -#define PRIM (rs->prim) -#define IPRIM (rs->iprim) -#define A0 (NN) - -#define ENCODE_RS encode_rs_int -#define DECODE_RS decode_rs_int -#define INIT_RS init_rs_int -#define FREE_RS free_rs_int - -void ENCODE_RS(void *p,DTYPE *data,DTYPE *parity); -int DECODE_RS(void *p,DTYPE *data,int *eras_pos,int no_eras, int calc_syn); -void *INIT_RS(unsigned int symsize,unsigned int gfpoly,unsigned int fcr, - unsigned int prim,unsigned int nroots); -void FREE_RS(void *p); - - - - diff --git a/lib/ftrsd/rs2.h b/lib/ftrsd/rs2.h deleted file mode 100644 index c2b807d..0000000 --- a/lib/ftrsd/rs2.h +++ /dev/null @@ -1,16 +0,0 @@ -/* User include file for the Reed-Solomon codec - * Copyright 2002, Phil Karn KA9Q - * May be used under the terms of the GNU General Public License (GPL) - */ - -/* General purpose RS codec, integer symbols */ -void encode_rs_int(void *rs,int *data,int *parity); -int decode_rs_int(void *rs,int *data,int *eras_pos,int no_eras, int calc_syn); -void *init_rs_int(int symsize,int gfpoly,int fcr, - int prim,int nroots,int pad); -void free_rs_int(void *rs); - -/* Tables to map from conventional->dual (Taltab) and - * dual->conventional (Tal1tab) bases - */ -extern unsigned char Taltab[],Tal1tab[]; diff --git a/lib/ftrsd/rsdtest.f90 b/lib/ftrsd/rsdtest.f90 deleted file mode 100644 index 2c862e5..0000000 --- a/lib/ftrsd/rsdtest.f90 +++ /dev/null @@ -1,34 +0,0 @@ -program rsdtest - - real s3(64,63) - character msg*22,arg*12 - integer param(0:7) - - nargs=iargc() - if(nargs.ne.2) then - print*,'Usage: rsdtest ntrials nfiles' - go to 999 - endif - call getarg(1,arg) - read(arg,*) ntrials - call getarg(2,arg) - read(arg,*) nfiles - - open(10,file='s3_1000.bin',access='stream', status='old') - open(22,file='kvasd.dat',access='direct',recl=1024,status='unknown') - - nadd=1 - ifile0=0 - if(nfiles.lt.0) then - ifile0=-nfiles - nfiles=99999 - endif - - do ifile=1,nfiles - read(10,end=999) s3 - if(ifile.lt.ifile0) cycle - call extract2(s3,nadd,ntrials,param,msg) - if(ifile.eq.ifile0) exit - enddo - -999 end program rsdtest diff --git a/lib/ftrsd/sfrsd.c b/lib/ftrsd/sfrsd.c deleted file mode 100644 index e64dfc9..0000000 --- a/lib/ftrsd/sfrsd.c +++ /dev/null @@ -1,137 +0,0 @@ -/* - sfrsd.c - - A soft-decision decoder for the JT65 (63,12) Reed-Solomon code. - - This decoding scheme is built around Phil Karn's Berlekamp-Massey - errors and erasures decoder. The approach is inspired by a number of - publications, including the stochastic Chase decoder described - in "Stochastic Chase Decoding of Reed-Solomon Codes", by Leroux et al., - IEEE Communications Letters, Vol. 14, No. 9, September 2010 and - "Soft-Decision Decoding of Reed-Solomon Codes Using Successive Error- - and-Erasure Decoding," by Soo-Woong Lee and B. V. K. Vijaya Kumar. - - Steve Franke K9AN, Urbana IL, September 2015 - */ - -#include -#include -#include -#include -#include -#include "sfrsd2.h" - -//*************************************************************************** -void usage(void) -{ - printf("Usage: sfrsd [options...] \n"); - printf(" input file should be in kvasd format\n"); - printf("\n"); - printf("Options:\n"); - printf(" -n number of random erasure vectors to try\n"); - printf(" -v verbose\n"); -} - -int main(int argc, char *argv[]){ - - extern char *optarg; - extern int optind; - - int correct[63], indx[63], param[8]; - int c,i; - char *infile; - - FILE *datfile, *logfile; - int nsec, maxe, nads; - float xlambda; - int mrsym[63],mrprob[63],mr2sym[63],mr2prob[63]; - int nsec2,ncount,dat4[12]; - int ntrials, nverbose, ntry; - int nhard; - double tt; - - ntrials=10000; - nverbose=1; - - while ( (c = getopt(argc, argv, "n:qv")) !=-1 ) { - switch (c) { - case 'n': - ntrials=(int)strtof(optarg,NULL); - printf("ntrials set to %d\n",ntrials); - break; - case 'v': - nverbose=1; - break; - case 'q': //accept (and ignore) -q option for WSJT10 compatibility - break; - case '?': - usage(); - exit(1); - } - } - - if( optind+1 > argc) { - // usage(); - // exit(1); - infile="kvasd.dat"; - } else { - infile=argv[optind]; - } - - logfile=fopen("/tmp/sfrsd.log","a"); - if( !logfile ) { - printf("Unable to open sfrsd.log\n"); - exit(1); - } - - datfile=fopen(infile,"rb"); - if( !datfile ) { - printf("Unable to open kvasd.dat\n"); - exit(1); - } else { - fread(&nsec,sizeof(int),1,datfile); - fread(&xlambda,sizeof(float),1,datfile); - fread(&maxe,sizeof(int),1,datfile); - fread(&nads,sizeof(int),1,datfile); - fread(&mrsym,sizeof(int),63,datfile); - fread(&mrprob,sizeof(int),63,datfile); - fread(&mr2sym,sizeof(int),63,datfile); - fread(&mr2prob,sizeof(int),63,datfile); - fread(&nsec2,sizeof(int),1,datfile); - fread(&ncount,sizeof(int),1,datfile); - fread(&dat4,sizeof(int),12,datfile); - fclose(datfile); - } - - sfrsd2_(mrsym,mrprob,mr2sym,mr2prob,&ntrials,&nverbose,correct,param,indx,&tt,&ntry); - nhard=param[1]; - if( nhard>=0 ) { - for (i=0; i<12; i++) { - dat4[i]=correct[11-i]; - } - } else { - nhard=-1; - memset(dat4,0,12*sizeof(int)); - } - datfile=fopen(infile,"wb"); - if( !datfile ) { - printf("Unable to open kvasd.dat\n"); - return 1; - } else { - fwrite(&nsec,sizeof(int),1,datfile); - fwrite(&xlambda,sizeof(float),1,datfile); - fwrite(&maxe,sizeof(int),1,datfile); - fwrite(&nads,sizeof(int),1,datfile); - fwrite(&mrsym,sizeof(int),63,datfile); - fwrite(&mrprob,sizeof(int),63,datfile); - fwrite(&mr2sym,sizeof(int),63,datfile); - fwrite(&mr2prob,sizeof(int),63,datfile); - fwrite(&nsec2,sizeof(int),1,datfile); - fwrite(&nhard,sizeof(int),1,datfile); - fwrite(&dat4,sizeof(int),12,datfile); - fclose(datfile); - } - exit(0); -} - - diff --git a/lib/ftrsd/sfrsd2.h b/lib/ftrsd/sfrsd2.h deleted file mode 100644 index 4ef7ab4..0000000 --- a/lib/ftrsd/sfrsd2.h +++ /dev/null @@ -1,3 +0,0 @@ -void ftrsd2_(int mrsym[], int mrprob[], int mr2sym[], int mr2prob[], - int* ntrials0, int* verbose0, int correct[], int param[], - int indexes[], double tt[], int ntry[]); diff --git a/lib/ftrsd/sfrsd3.c b/lib/ftrsd/sfrsd3.c deleted file mode 100644 index f117dcc..0000000 --- a/lib/ftrsd/sfrsd3.c +++ /dev/null @@ -1,243 +0,0 @@ -/* - sfrsd2.c - - A soft-decision decoder for the JT65 (63,12) Reed-Solomon code. - - This decoding scheme is built around Phil Karn's Berlekamp-Massey - errors and erasures decoder. The approach is inspired by a number of - publications, including the stochastic Chase decoder described - in "Stochastic Chase Decoding of Reed-Solomon Codes", by Leroux et al., - IEEE Communications Letters, Vol. 14, No. 9, September 2010 and - "Soft-Decision Decoding of Reed-Solomon Codes Using Successive Error- - and-Erasure Decoding," by Soo-Woong Lee and B. V. K. Vijaya Kumar. - - Steve Franke K9AN and Joe Taylor K1JT - */ - -#include -#include -#include -#include -#include -#include "rs2.h" - -static void *rs; - -void sfrsd2_(int mrsym[], int mrprob[], int mr2sym[], int mr2prob[], - int* ntrials0, int* verbose0, int correct[], int param[], - int indexes[], double tt[], int ntry[]) -{ - int rxdat[63], rxprob[63], rxdat2[63], rxprob2[63]; - int workdat[63],workdat2[63]; - int era_pos[51]; - int c, i, j, numera, nmr2, nerr, nn=63, kk=12; - FILE *datfile, *logfile; - int ntrials = *ntrials0; - int verbose = *verbose0; - int nhard=0,nhard_min=32768,nsoft=0,nsoft_min=32768, ncandidates; - int ngmd,nera_best; - clock_t t0=0,t1=0; - int perr[8][8] = { - 12, 31, 44, 52, 60, 57, 50, 50, - 28, 38, 49, 58, 65, 69, 64, 80, - 40, 41, 53, 62, 66, 73, 76, 81, - 50, 53, 53, 64, 70, 76, 77, 81, - 50, 50, 52, 60, 71, 72, 77, 84, - 50, 50, 56, 62, 67, 73, 81, 85, - 50, 50, 71, 62, 70, 77, 80, 85, - 50, 50, 62, 64, 71, 75, 82, 87}; - - int pmr2[8][8] = { - 4, 8, 9, 7, 6, 0, 0, 0, - 13, 18, 15, 11, 9, 7, 5, 0, - 0, 23, 21, 15, 12, 10, 7, 4, - 0, 34, 28, 20, 16, 14, 11, 7, - 0, 20, 26, 25, 19, 14, 12, 9, - 0, 0, 28, 27, 22, 19, 14, 11, - 0, 0, 40, 29, 29, 23, 18, 12, - 0, 0, 40, 35, 31, 21, 20, 13}; - - if(verbose) { - logfile=fopen("sfrsd.log","a"); - if( !logfile ) { - printf("Unable to open sfrsd.log\n"); - exit(1); - } - } - -// Initialize the KA9Q Reed-Solomon encoder/decoder - unsigned int symsize=6, gfpoly=0x43, fcr=3, prim=1, nroots=51; - rs=init_rs_int(symsize, gfpoly, fcr, prim, nroots, 0); - -// Reverse the received symbol vector for BM decoder - for (i=0; i<63; i++) { - rxdat[i]=mrsym[62-i]; - rxprob[i]=mrprob[62-i]; - rxdat2[i]=mr2sym[62-i]; - rxprob2[i]=mr2prob[62-i]; - } - -// Sort the mrsym probabilities to find the least reliable symbols - int k, pass, tmp, nsym=63; - int probs[63]; - for (i=0; i<63; i++) { - indexes[i]=i; - probs[i]=rxprob[i]; - } - for (pass = 1; pass <= nsym-1; pass++) { - for (k = 0; k < nsym - pass; k++) { - if( probs[k] < probs[k+1] ) { - tmp = probs[k]; - probs[k] = probs[k+1]; - probs[k+1] = tmp; - tmp = indexes[k]; - indexes[k] = indexes[k+1]; - indexes[k+1] = tmp; - } - } - } - -// See if we can decode using BM HDD, and calculate the syndrome vector. - memset(era_pos,0,51*sizeof(int)); - numera=0; - memcpy(workdat,rxdat,sizeof(rxdat)); - nerr=decode_rs_int(rs,workdat,era_pos,numera,1); - if( nerr >= 0 ) { - if(verbose) fprintf(logfile," BM decode nerrors= %3d : ",nerr); - memcpy(correct,workdat,63*sizeof(int)); - ngmd=-1; - param[0]=0; - param[1]=0; - param[2]=0; - param[3]=0; - param[4]=0; - return; - } - -/* -Generate random erasure-locator vectors and see if any of them -decode. This will generate a list of potential codewords. The -"soft" distance between each codeword and the received word is -used to decide which codeword is "best". -*/ - -#ifdef WIN32 - srand(0xdeadbeef); -#else - srandom(0xdeadbeef); -#endif - - float ratio, ratio0[63]; - int threshe, thresh2, nsum; - int thresh0[63],thresh1[63], mr2flag; - ncandidates=0; - nsum=0; - int ii,jj; - for (i=0; i= 0 ) { - ncandidates=ncandidates+1; - nhard=0; - nsoft=0; - for (i=0; i<63; i++) { - if(workdat[i] != rxdat[i]) { - nhard=nhard+1; - if(workdat[i] != rxdat2[i]) { - nsoft=nsoft+rxprob[i]; - } - } - } - nsoft=63*nsoft/nsum; - if((nsoft < 33) && (nhard < 43) && (nhard+nsoft) < 74) { //??? - if( (nsoft < nsoft_min) ) { - nsoft_min=nsoft; - nhard_min=nhard; - memcpy(correct,workdat,63*sizeof(int)); - ngmd=0; - nera_best=numera; - ntry[0]=k; - } - } - if(nsoft_min < 27) break; - if((nsoft_min < 32) && (nhard_min < 43) && - (nhard_min+nsoft_min) < 74) break; - } - if(k == ntrials-1) ntry[0]=k+1; - } - - if(verbose) fprintf(logfile, - "%d trials and %d candidates after stochastic loop\n",k,ncandidates); - - if( (ncandidates >= 0) && (nsoft_min < 36) && (nhard_min < 44) ) { - if(verbose) { - for (i=0; i<63; i++) { - fprintf(logfile,"%3d %3d %3d %3d %3d %3d\n",i,correct[i], - rxdat[i],rxprob[i],rxdat2[i],rxprob2[i]); - } - fprintf(logfile,"**** ncandidates %d nhard %d nsoft %d nsum %d\n", - ncandidates,nhard_min,nsoft_min,nsum); - } - } else { - nhard_min=-1; - } - - if(verbose) { - fprintf(logfile,"exiting sfrsd\n"); - fclose(logfile); - } - param[0]=ncandidates; - param[1]=nhard_min; - param[2]=nsoft_min; - param[3]=nera_best; - param[4]=ngmd; - if(param[0]==0) param[2]=-1; - return; -} diff --git a/lib/g1 b/lib/g1 deleted file mode 100644 index 52f7616..0000000 --- a/lib/g1 +++ /dev/null @@ -1,4 +0,0 @@ -gcc -c gran.c -gfortran -c four2a.f90 -gfortran -c f77_wisdom.f90 -gfortran -o chkfft chkfft.f90 four2a.o f77_wisdom.o gran.o -lfftw3f diff --git a/lib/g1.bat b/lib/g1.bat deleted file mode 100644 index 6242f25..0000000 --- a/lib/g1.bat +++ /dev/null @@ -1,4 +0,0 @@ -gcc -c gran.c -gfortran -c four2a.f90 -gfortran -c f77_wisdom.f90 -gfortran -o chkfft chkfft.f90 four2a.o f77_wisdom.o gran.o /JTSDK-QT/appsupport/runtime/libfftw3f-3.dll diff --git a/lib/g2.bat b/lib/g2.bat deleted file mode 100644 index 4067107..0000000 --- a/lib/g2.bat +++ /dev/null @@ -1,4 +0,0 @@ -gcc -c gran.c -gfortran -c fftw3mod.f90 -gfortran -c f77_wisdom.f90 -gfortran -o chkfft2 chkfft2.f90 f77_wisdom.o gran.o /JTSDK-QT/appsupport/runtime/libfftw3f-3.dll diff --git a/lib/g3.bat b/lib/g3.bat deleted file mode 100644 index 904fce9..0000000 --- a/lib/g3.bat +++ /dev/null @@ -1,4 +0,0 @@ -gcc -c gran.c -gfortran -c fftw3mod.f90 -gfortran -c f77_wisdom.f90 -gfortran -o chkfft3 chkfft3.f90 f77_wisdom.o gran.o /JTSDK-QT/appsupport/runtime/libfftw3f-3.dll diff --git a/lib/g4.bat b/lib/g4.bat deleted file mode 100644 index 6475dad..0000000 --- a/lib/g4.bat +++ /dev/null @@ -1,3 +0,0 @@ -gcc -c gran.c -gfortran -c -Wall fftw3mod.f90 -gfortran -o timefft -Wall timefft.f90 timefft_opts.f90 gran.o libfftw3f-3.dll diff --git a/lib/gen4.f90 b/lib/gen4.f90 deleted file mode 100644 index 7b06be8..0000000 --- a/lib/gen4.f90 +++ /dev/null @@ -1,43 +0,0 @@ -subroutine gen4(msg0,ichk,msgsent,itone,itype) - -! Encode a JT4 message. Returns msgsent, the message as it will be -! decoded, an integer array itone(206) of 4-FSK tons values in the -! range 0-3; and itype, the JT message type. - - use jt4 - use packjt - character*22 msg0 - character*22 message !Message to be generated - character*22 msgsent !Message as it will be received - character*1 c - integer itone(206) - integer*4 i4Msg6BitWords(13) !72-bit message as 6-bit words - integer mettab(-128:127,0:1) - save - - if(msg0(1:1).eq.'@') then - read(msg0(2:5),*,end=1,err=1) nfreq - go to 2 -1 nfreq=1000 -2 itone(1)=nfreq - msgsent=msg0 - else - call getmet4(mettab,ndelta) - - message=msg0 - call fmtmsg(message,iz) - call packmsg(message,i4Msg6BitWords,itype,.false.) !Pack into 12 6-bit bytes - call unpackmsg(i4Msg6BitWords,msgsent,.false.,' ') !Unpack to get msgsent - if(ichk.ne.0) go to 999 - call encode4(message,itone) !Encode the information bits - i1=index(message,'-') - c=message(i1+1:i1+1) - if(i1.ge.9 .and. c.ge.'0' .and. c.le.'3') then - itone=2*itone + (1-npr(2:)) !Inverted '#' sync - else - itone=2*itone + npr(2:) !Data = MSB, sync = LSB - endif - endif - -999 return -end subroutine gen4 diff --git a/lib/gen65.f90 b/lib/gen65.f90 deleted file mode 100644 index ab61fd3..0000000 --- a/lib/gen65.f90 +++ /dev/null @@ -1,83 +0,0 @@ -subroutine gen65(msg0,ichk,msgsent,itone,itype) - -! Encodes a JT65 message to yieild itone(1:126) -! Temporarily, does not implement EME shorthands - - use packjt - character*22 msg0 - character*22 message !Message to be generated - character*22 msgsent !Message as it will be received - integer itone(126) - character*3 cok !' ' or 'OOO' - integer dgen(13) - integer sent(63) - integer nprc(126) - data nprc/1,0,0,1,1,0,0,0,1,1,1,1,1,1,0,1,0,1,0,0, & - 0,1,0,1,1,0,0,1,0,0,0,1,1,1,0,0,1,1,1,1, & - 0,1,1,0,1,1,1,1,0,0,0,1,1,0,1,0,1,0,1,1, & - 0,0,1,1,0,1,0,1,0,1,0,0,1,0,0,0,0,0,0,1, & - 1,0,0,0,0,0,0,0,1,1,0,1,0,0,1,0,1,1,0,1, & - 0,1,0,1,0,0,1,1,0,0,1,0,0,1,0,0,0,0,1,1, & - 1,1,1,1,1,1/ - save - - if(msg0(1:1).eq.'@') then - read(msg0(2:5),*,end=1,err=1) nfreq - go to 2 -1 nfreq=1000 -2 itone(1)=nfreq - else - message=msg0 - do i=1,22 - if(ichar(message(i:i)).eq.0) then - message(i:)=' ' - exit - endif - enddo - - do i=1,22 !Strip leading blanks - if(message(1:1).ne.' ') exit - message=message(i+1:) - enddo - - call chkmsg(message,cok,nspecial,flip) - ntest=0 - if(flip.lt.0.0) ntest=1 - if(nspecial.eq.0) then - call packmsg(message,dgen,itype,.false.) !Pack message into 72 bits - call unpackmsg(dgen,msgsent,.false.,' ') !Unpack to get message sent - msgsent(20:22)=cok - call fmtmsg(msgsent,iz) - if(ichk.ne.0) go to 999 !Return if checking only - - call rs_encode(dgen,sent) !Apply Reed-Solomon code - call interleave63(sent,1) !Apply interleaving - call graycode65(sent,63,1) !Apply Gray code - nsym=126 !Symbols per transmission - k=0 - do j=1,nsym - if(nprc(j).eq.ntest) then - k=k+1 - itone(j)=sent(k)+2 - else - itone(j)=0 - endif - enddo - else - nsym=32 - k=0 - do j=1,nsym - do n=1,4 - k=k+1 - if(iand(j,1).eq.1) itone(k)=0 - if(iand(j,1).eq.0) itone(k)=10*nspecial - if(k.eq.126) go to 10 - enddo - enddo -10 msgsent=message - itype=7 - endif - endif - -999 return -end subroutine gen65 diff --git a/lib/gen9.f90 b/lib/gen9.f90 deleted file mode 100644 index 503ef6d..0000000 --- a/lib/gen9.f90 +++ /dev/null @@ -1,65 +0,0 @@ -subroutine gen9(msg0,ichk,msgsent,i4tone,itype) - -! Encodes a JT9 message and returns msgsent, the message as it will -! be decoded, and an integer array i4tone(85) of 9-FSK tone values -! in the range 0-8. - - use packjt - character*22 msg0 - character*22 message !Message to be generated - character*22 msgsent !Message as it will be received - integer*4 i4Msg6BitWords(13) !72-bit message as 6-bit words - integer*1 i1Msg8BitBytes(13) !72 bits and zero tail as 8-bit bytes - integer*1 i1EncodedBits(207) !Encoded information-carrying bits - integer*1 i1ScrambledBits(207) !Encoded bits after interleaving - integer*4 i4DataSymbols(69) !Data symbols (values 0-7) - integer*4 i4GrayCodedSymbols(69) !Gray-coded symbols (values 0-7) - integer*4 i4tone(85) !Tone #s, data and sync (values 0-8) - include 'jt9sync.f90' - save - - if(msg0(1:1).eq.'@') then - read(msg0(2:5),*,end=1,err=1) nfreq - go to 2 -1 nfreq=1000 -2 i4tone(1)=nfreq - else - message=msg0 - do i=1,22 - if(ichar(message(i:i)).eq.0) then - message(i:)=' ' - exit - endif - enddo - - do i=1,22 !Strip leading blanks - if(message(1:1).ne.' ') exit - message=message(i+1:) - enddo - - call packmsg(message,i4Msg6BitWords,itype,.false.) !Pack into 12 6-bit bytes - call unpackmsg(i4Msg6BitWords,msgsent,.false.,' ') !Unpack to get msgsent - if(ichk.ne.0) go to 999 - call entail(i4Msg6BitWords,i1Msg8BitBytes) !Add tail, make 8-bit bytes - nsym2=206 - call encode232(i1Msg8BitBytes,nsym2,i1EncodedBits) !Encode K=32, r=1/2 - i1EncodedBits(207)=0 - call interleave9(i1EncodedBits,1,i1ScrambledBits) !Interleave bits - i1ScrambledBits(207)=0 - call packbits(i1ScrambledBits,69,3,i4DataSymbols) !Pk 3-bits into words - call graycode(i4DataSymbols,69,1,i4GrayCodedSymbols) !Apply Gray code - -! Insert sync symbols at ntone=0 and add 1 to the data-tone numbers. - j=0 - do i=1,85 - if(isync(i).eq.1) then - i4tone(i)=0 - else - j=j+1 - i4tone(i)=i4GrayCodedSymbols(j)+1 - endif - enddo - endif - -999 return -end subroutine gen9 diff --git a/lib/geniscat.f90 b/lib/geniscat.f90 deleted file mode 100644 index 6df6ed9..0000000 --- a/lib/geniscat.f90 +++ /dev/null @@ -1,55 +0,0 @@ -subroutine geniscat(msg,msgsent,itone) - -! Generate an ISCAT waveform. - - parameter (NSZ=1291) - character msg*28,msgsent*28 !Message to be transmitted - integer imsg(30) - integer itone(NSZ) - real*8 sps - character c*42 - integer icos(4) !Costas array - data icos/0,1,3,2/ - data nsync/4/,nlen/2/,ndat/18/ - data c/'0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZ /.?@-'/ - - sps=256.d0*12000.d0/11025.d0 - nsym=int(30*12000.d0/sps) - nblk=nsync+nlen+ndat - - do i=22,1,-1 - if(msg(i:i).ne.' ' .and. msg(i:i).ne.char(0)) exit - enddo - nmsg=i - msglen=nmsg+1 - k=0 - kk=1 - imsg(1)=40 !Always start with BOM char: '@' - do i=1,nmsg !Define the tone sequence - imsg(i+1)=36 !Illegal char set to blank - do j=1,42 - if(msg(i:i).eq.c(j:j)) imsg(i+1)=j-1 - enddo - enddo - - do i=1,nsym !Total symbols in 30 s - j=mod(i-1,nblk)+1 - if(j.le.nsync) then - itone(i)=icos(j) !Insert 4x4 Costas array - else if(j.gt.nsync .and. j.le.nsync+nlen) then - itone(i)=msglen !Insert message-length indicator - if(j.ge.nsync+2) then - n=msglen + 5*(j-nsync-1) - if(n.gt.41) n=n-42 - itone(i)=n - endif - else - k=k+1 - kk=mod(k-1,msglen)+1 - itone(i)=imsg(kk) - endif - enddo - msgsent=msg - - return -end subroutine geniscat diff --git a/lib/genmet.f90 b/lib/genmet.f90 deleted file mode 100644 index 81f2e56..0000000 --- a/lib/genmet.f90 +++ /dev/null @@ -1,90 +0,0 @@ -program genmet - -! Generate metric table for M-FSK modulation. - - character*12 arg - real*4 r(0:255) - integer hist(2,-128:128) - data hist/514*0/,idum/-1/ - - lim(x)=min(127,max(-128,nint(scale*x))) - - nargs=iargc() - if(nargs.ne.5) then - print*,'Usage: genmet ncoh nadd m0 snr iters' - go to 999 - endif - call getarg(1,arg) - read(arg,*) ncoh - call getarg(2,arg) - read(arg,*) nadd - call getarg(3,arg) - read(arg,*) m0 - call getarg(4,arg) - read(arg,*) snr - call getarg(5,arg) - read(arg,*) iters - - ntones=2**m0 - xm0=m0 - scale=5.0 - fac=sqrt(1.0/nadd) - s=sqrt(10.0**(0.1*snr)) - hist=0 - nerr=0 - - call sgran() - - do iter=1,iters - do i=0,ntones-1 - r(i)=0. - do n=1,nadd - x1=0.707*gran() - y1=0.707*gran() - if(i.eq.0) x1=x1+s - if(ncoh.eq.0) r(i)=r(i) + x1*x1 + y1*y1 - if(ncoh.ne.0) r(i)=r(i) + x1 - enddo - r(i)=fac*r(i) - enddo - do m=0,m0-1 - n=2**m - r1=0. - r2=0. - do i=0,ntones-1 - if(iand(i,n).ne.0) r1=max(r1,r(i)) - if(iand(i,n).eq.0) r2=max(r2,r(i)) - enddo - don=r2-r1 - doff=r1-r2 - if(don.lt.0.0) nerr=nerr+1 - j1=lim(doff) - hist(1,j1)=hist(1,j1)+1 - j2=lim(don) - hist(2,j2)=hist(2,j2)+1 - enddo - enddo - - do i=-128,127 - write(13,1010) i/scale,hist(1,i)/(xm0*iters),hist(2,i)/(xm0*iters) -1010 format(f8.3,2f12.9) - enddo - - ber=nerr/(xm0*iters) - write(*,1020) nadd,m0,snr,ber -1020 format('nadd:',i3,' m0:',i2,' snr: 'f5.1,' BER:',f8.3) - - xln2=log(2.0) - do i=-128,127 - p1=hist(2,i)/(xm0*iters) - p0=hist(1,i)/(xm0*iters) - if(p0+p1.eq.0.0 .and. i.lt.0) p0=1.e-6 - if(p0+p1.eq.0.0 .and. i.gt.0) p1=1.e-6 - xlhd0=log(max(0.001,2.0*p0/(p0+p1)))/xln2 - xlhd1=log(max(0.001,2.0*p1/(p0+p1)))/xln2 - write(14,1012) i/scale,xlhd0,xlhd1,p0/(p0+p1),p1/(p0+p1) -1012 format(f7.1,2f8.3,2f9.6) - enddo - -999 end program genmet - diff --git a/lib/genmsk144.f90 b/lib/genmsk144.f90 deleted file mode 100644 index 5f9ce93..0000000 --- a/lib/genmsk144.f90 +++ /dev/null @@ -1,147 +0,0 @@ -subroutine genmsk144(msg0,mygrid,ichk,bcontest,msgsent,i4tone,itype) -! s8 + 48bits + s8 + 80 bits = 144 bits (72ms message duration) -! -! Encode an MSK144 message -! Input: -! - msg0 requested message to be transmitted -! - ichk if ichk=1, return only msgsent -! if ichk.ge.10000, set imsg=ichk-10000 for short msg -! - msgsent message as it will be decoded -! - i4tone array of audio tone values, 0 or 1 -! - itype message type -! 1 = standard message "Call_1 Call_2 Grid/Rpt" -! 2 = type 1 prefix -! 3 = type 1 suffix -! 4 = type 2 prefix -! 5 = type 2 suffix -! 6 = free text (up to 13 characters) -! 7 = short message " Rpt" - - use iso_c_binding, only: c_loc,c_size_t - use packjt - use hashing - character*22 msg0 - character*22 message !Message to be generated - character*22 msgsent !Message as it will be received - character*6 mygrid - integer*4 i4Msg6BitWords(13) !72-bit message as 6-bit words - integer*4 i4tone(144) ! - integer*1, target:: i1Msg8BitBytes(10) !80 bits represented in 10 bytes - integer*1 codeword(128) !Encoded bits before re-ordering - integer*1 msgbits(80) !72-bit message + 8-bit hash - integer*1 bitseq(144) !Tone #s, data and sync (values 0-1) - integer*1 i1hash(4) - integer*1 s8(8) - logical bcontest - real*8 pp(12) - real*8 xi(864),xq(864),pi,twopi - data s8/0,1,1,1,0,0,1,0/ - equivalence (ihash,i1hash) - logical first - data first/.true./ - save - - if(first) then - first=.false. - nsym=128 - pi=4.0*atan(1.0) - twopi=8.*atan(1.0) - do i=1,12 - pp(i)=sin((i-1)*pi/12) - enddo - endif - - if(msg0(1:1).eq.'@') then !Generate a fixed tone - read(msg0(2:5),*,end=1,err=1) nfreq !at specified frequency - go to 2 -1 nfreq=1000 -2 i4tone(1)=nfreq - else - message=msg0 - do i=1,22 - if(ichar(message(i:i)).eq.0) then - message(i:)=' ' - exit - endif - enddo - - do i=1,22 !Strip leading blanks - if(message(1:1).ne.' ') exit - message=message(i+1:) - enddo - - if(message(1:1).eq.'<') then - call genmsk40(message,msgsent,ichk,i4tone,itype) - if(itype.lt.0) go to 999 - i4tone(41)=-40 - go to 999 - endif - - call packmsg(message,i4Msg6BitWords,itype,bcontest) !Pack into 12 6-bit bytes - call unpackmsg(i4Msg6BitWords,msgsent,bcontest,mygrid) !Unpack to get msgsent - - if(ichk.eq.1) go to 999 - i4=0 - ik=0 - im=0 - do i=1,12 - nn=i4Msg6BitWords(i) - do j=1, 6 - ik=ik+1 - i4=i4+i4+iand(1,ishft(nn,j-6)) - i4=iand(i4,255) - if(ik.eq.8) then - im=im+1 - i1Msg8BitBytes(im)=i4 - ik=0 - endif - enddo - enddo - - ihash=nhash(c_loc(i1Msg8BitBytes),int(9,c_size_t),146) - ihash=2*iand(ihash,32767) !Generate the 8-bit hash - i1Msg8BitBytes(10)=i1hash(1) !Hash code to byte 10 - - mbit=0 - do i=1, 10 - i1=i1Msg8BitBytes(i) - do ibit=1,8 - mbit=mbit+1 - msgbits(mbit)=iand(1,ishft(i1,ibit-8)) - enddo - enddo - - call encode_msk144(msgbits,codeword) - -!Create 144-bit channel vector: -!8-bit sync word + 48 bits + 8-bit sync word + 80 bits - bitseq=0 - bitseq(1:8)=s8 - bitseq(9:56)=codeword(1:48) - bitseq(57:64)=s8 - bitseq(65:144)=codeword(49:128) - bitseq=2*bitseq-1 - - xq(1:6)=bitseq(1)*pp(7:12) !first bit is mapped to 1st half-symbol on q - do i=1,71 - is=(i-1)*12+7 - xq(is:is+11)=bitseq(2*i+1)*pp - enddo - xq(864-5:864)=bitseq(1)*pp(1:6) !last half symbol - do i=1,72 - is=(i-1)*12+1 - xi(is:is+11)=bitseq(2*i)*pp - enddo -! Map I and Q to tones. - i4tone=0 - do i=1,72 - i4tone(2*i-1)=(bitseq(2*i)*bitseq(2*i-1)+1)/2; - i4tone(2*i)=-(bitseq(2*i)*bitseq(mod(2*i,144)+1)-1)/2; - enddo - endif - -! Flip polarity - i4tone=-i4tone+1 - -999 return -end subroutine genmsk144 diff --git a/lib/genmsk40.f90 b/lib/genmsk40.f90 deleted file mode 100644 index 3310b10..0000000 --- a/lib/genmsk40.f90 +++ /dev/null @@ -1,66 +0,0 @@ -subroutine genmsk40(msg,msgsent,ichk,itone,itype) - - use hashing - character*22 msg,msgsent,hashmsg - character*4 crpt,rpt(0:15) - logical first - integer*4 itone(144) - integer*1 message(16),codeword(32),bitseq(40) - integer*1 s8r(8) - data s8r/1,0,1,1,0,0,0,1/ ! Sync word is reversed wrt msk144 sync word. - data first/.true./ - data rpt/"-03 ","+00 ","+03 ","+06 ","+10 ","+13 ","+16 ", & - "R-03","R+00","R+03","R+06","R+10","R+13","R+16", & - "RRR ","73 "/ - save first,rpt - - itype=-1 - msgsent='*** bad message ***' - itone=0 - i1=index(msg,'>') - if(i1.lt.9) go to 900 - call fmtmsg(msg,iz) - crpt=msg(i1+2:i1+5) - do i=0,15 - if(crpt.eq.rpt(i)) go to 10 - enddo - go to 900 - -10 irpt=i !Report index, 0-15 - if(ichk.lt.10000) then - hashmsg=msg(2:i1-1) - call hash(hashmsg,22,ihash) - ihash=iand(ihash,4095) !12-bit hash - ig=16*ihash + irpt !4-bit report - else - ig=ichk-10000 - endif - - do i=1,16 - message(i)=iand(1,ishft(ig,1-i)) - enddo - - call encode_msk40(message,codeword) -! write(*,'(a6,i6,2x,a6,i6,2x,a6,i6)') ' msg: ',ig,'rprt: ',irpt,'hash: ',ihash -! write(*,'(a6,32i1)') ' cw: ',codeword - - bitseq(1:8)=s8r - bitseq(9:40)=codeword - bitseq=2*bitseq-1 - -! Map I and Q to tones. - itone=0 - do i=1, 20 - itone(2*i-1)=(bitseq(2*i)*bitseq(2*i-1)+1)/2; - itone(2*i)=-(bitseq(2*i)*bitseq(mod(2*i,40)+1)-1)/2; - enddo - -! Flip polarity - itone=-itone+1 - - msgsent=msg - itype=7 - -900 return -end subroutine genmsk40 - diff --git a/lib/genmsk_short.f90 b/lib/genmsk_short.f90 deleted file mode 100644 index f1b555f..0000000 --- a/lib/genmsk_short.f90 +++ /dev/null @@ -1,66 +0,0 @@ -subroutine genmsk_short(msg,msgsent,ichk,itone,itype) - - use hashing - character*22 msg,msgsent - character*3 crpt,rpt(0:7) - logical first - integer itone(35) - integer ig24(0:4096-1) !Codewords for Golay (24,12) code - integer b11(11) - data b11/1,1,1,0,0,0,1,0,0,1,0/ !Barker 11 code - data rpt /'26 ','27 ','28 ','R26','R27','R28','RRR','73 '/ - data first/.true./ - save first,ig24 - - if(first) then - call golay24_table(ig24) !Define the Golay(24,12) codewords - first=.false. - endif - - itype=-1 - msgsent='*** bad message ***' - itone=0 - i1=index(msg,'>') - if(i1.lt.9) go to 900 - call fmtmsg(msg,iz) - crpt=msg(i1+2:i1+5) - do i=0,7 - if(crpt.eq.rpt(i)) go to 10 - enddo - go to 900 - -10 irpt=i !Report index, 0-7 - if(ichk.lt.10000) then - call hash(msg(2:i1-1),i1-2,ihash) - ihash=iand(ihash,511) !9-bit hash for the two callsigns - ig=8*ihash + irpt !12-bit message information - else - ig=ichk-10000 - endif - ncodeword=ig24(ig) - itone(1:11)=b11 !Insert the Barker-11 code - n=2**24 - do i=12,35 !Insert codeword into itone array - n=n/2 - itone(i)=0 - if(iand(ncodeword,n).ne.0) itone(i)=1 - enddo - msgsent=msg - itype=7 - - n=count(itone(1:35).eq.0) - if(mod(n,2).ne.0) stop 'Parity error in genmsk_short.' - -900 return -end subroutine genmsk_short - -subroutine hash_calls(calls,ih9) - - use hashing - character*(*) calls - i1=index(calls,'>') - call hash(calls(2:i1-1),i1-2,ih9) - ih9=iand(ih9,511) !9-bit hash for the two callsigns - - return -end subroutine hash_calls diff --git a/lib/genqra64.f90 b/lib/genqra64.f90 deleted file mode 100644 index f1bc9bf..0000000 --- a/lib/genqra64.f90 +++ /dev/null @@ -1,57 +0,0 @@ -subroutine genqra64(msg0,ichk,msgsent,itone,itype) - -! Encodes a QRA64 message to yield itone(1:84) - - use packjt - character*22 msg0 - character*22 message !Message to be generated - character*22 msgsent !Message as it will be received - integer itone(84) - character*3 cok !' ' or 'OOO' - logical old_qra_sync - integer dgen(13) - integer sent(63) - integer icos7(0:6) - data icos7/4,2,5,6,1,3,0/ !Costas 7x7 tone pattern - save - - if(msg0(1:1).eq.'@') then - read(msg0(2:5),*,end=1,err=1) nfreq - go to 2 -1 nfreq=1000 -2 itone(1)=nfreq - write(msgsent,1000) nfreq -1000 format(i5,' Hz') - else - message=msg0 - do i=1,22 - if(ichar(message(i:i)).eq.0) then - message(i:)=' ' - exit - endif - enddo - - do i=1,22 !Strip leading blanks - if(message(1:1).ne.' ') exit - message=message(i+1:) - enddo - - call chkmsg(message,cok,nspecial,flip) - call packmsg(message,dgen,itype,.false.) !Pack message into 72 bits - call unpackmsg(dgen,msgsent,.false.,' ') !Unpack to get message sent - if(ichk.ne.0) go to 999 !Return if checking only - call qra64_enc(dgen,sent) !Encode using QRA64 - - nsync=10 - inquire(file='old_qra_sync',exist=old_qra_sync) - if(old_qra_sync) nsync=1 - - itone(1:7)=nsync*icos7 !Insert 7x7 Costas array in 3 places - itone(8:39)=sent(1:32) - itone(40:46)=nsync*icos7 - itone(47:77)=sent(33:63) - itone(78:84)=nsync*icos7 - endif - -999 return -end subroutine genqra64 diff --git a/lib/genwspr.f90 b/lib/genwspr.f90 deleted file mode 100644 index d1d5183..0000000 --- a/lib/genwspr.f90 +++ /dev/null @@ -1,30 +0,0 @@ -subroutine genwspr(message,msgsent,itone) -! Encode a WSPR message and generate the array of channel symbols. - - character*22 message,msgsent - parameter (MAXSYM=176) - integer*1 symbol(MAXSYM) - integer*1 data0(11) - integer*4 itone(162) - integer npr3(162) - data npr3/ & - 1,1,0,0,0,0,0,0,1,0,0,0,1,1,1,0,0,0,1,0, & - 0,1,0,1,1,1,1,0,0,0,0,0,0,0,1,0,0,1,0,1, & - 0,0,0,0,0,0,1,0,1,1,0,0,1,1,0,1,0,0,0,1, & - 1,0,1,0,0,0,0,1,1,0,1,0,1,0,1,0,1,0,0,1, & - 0,0,1,0,1,1,0,0,0,1,1,0,1,0,1,0,0,0,1,0, & - 0,0,0,0,1,0,0,1,0,0,1,1,1,0,1,1,0,0,1,1, & - 0,1,0,0,0,1,1,1,0,0,0,0,0,1,0,1,0,0,1,1, & - 0,0,0,0,0,0,0,1,1,0,1,0,1,1,0,0,0,1,1,0, & - 0,0/ - - call wqencode(message,ntype,data0) !Source encoding - call encode232(data0,162,symbol) !Convolutional encoding - call inter_wspr(symbol,1) !Interleaving - do i=1,162 - itone(i)=npr3(i) + 2*symbol(i) - enddo - msgsent=message !### To be fixed... ?? ### - - return -end subroutine genwspr diff --git a/lib/hspec.f90 b/lib/hspec.f90 deleted file mode 100644 index 4ede506..0000000 --- a/lib/hspec.f90 +++ /dev/null @@ -1,106 +0,0 @@ -subroutine hspec(id2,k,nutc0,ntrpdepth,nrxfreq,ntol,bmsk144,bcontest, & - btrain,pcoeffs,ingain,mycall,hiscall,bshmsg,bswl,datadir,green,s, & - jh,pxmax,dbNoGain,line1,mygrid) - -! Input: -! k pointer to the most recent new data -! nutc0 UTC for display of decode(s) -! ntrpdepth TR period and 1000*ndepth -! nrxfreq Rx audio center frequency -! ntol Decoding range is +/- ntol -! bmsk144 Boolean, true if in MSK144 mode -! btrain Boolean, turns on training in MSK144 mode -! ingain Relative gain for spectra - -! Output: -! green() power -! s() spectrum for horizontal spectrogram -! jh index of most recent data in green(), s() - - parameter (JZ=703) - character*80 line1 - character*512 datadir - character*12 mycall,hiscall - character*6 mygrid - integer*2 id2(0:120*12000-1) - logical*1 bmsk144,bcontest,bshmsg,btrain,bswl - real green(0:JZ-1) - real s(0:63,0:JZ-1) - real x(512) - real*8 pcoeffs(5) - complex cx(0:256) - data rms/999.0/,k0/99999999/ - equivalence (x,cx) - save ja,rms0 - - ndepth=ntrpdepth/1000 - ntrperiod=ntrpdepth - 1000*ndepth - gain=10.0**(0.1*ingain) - nfft=512 - nstep=nfft - nblks=7 - if(ntrperiod.lt.30) then - nstep=256 - nblks=14 - endif - - if(k.gt.30*12000) go to 900 - if(k.lt.nfft) then - jh=0 - go to 900 !Wait for enough samples to start - endif - - if(k.lt.k0) then !Start a new data block - ja=-nstep - jh=-1 - rms0=0.0 - endif - - pxmax = 0; - do iblk=1,nblks - if(jh.lt.JZ-1) jh=jh+1 - ja=ja+nstep - jb=ja+nfft-1 - x=id2(ja:jb) - sq=dot_product(x,x) - xmax = maxval(x); - xmin = abs(minval(x)); - if (xmin > xmax) xmax = xmin; - if (xmax.gt.0.0) pxmax=20.0*log10(xmax); - rms=sqrt(gain*sq/nfft) - rms2=sqrt(sq/nfft); - green(jh)=0. - if(rms.gt.0.0) then - green(jh)=20.0*log10(rms) - dbNoGain=20.0*log10(rms2); - endif - call four2a(x,nfft,1,-1,0) !Real-to-complex FFT - df=12000.0/nfft - fac=(1.0/nfft)**2 - do i=1,64 - j=2*i - sx=real(cx(j))**2 + aimag(cx(j))**2 + real(cx(j-1))**2 + & - aimag(cx(j-1))**2 - s(i-1,jh)=fac*gain*sx - enddo - if(ja+2*nfft.gt.k) exit - enddo - k0=k - - if(bmsk144) then - if(k.ge.7168) then - tsec=(k-7168)/12000.0 - k0=k-7168 - tt1=sum(float(abs(id2(k0:k0+3583)))) - k0=k-3584 - tt2=sum(float(abs(id2(k0:k0+3583)))) - if(tt1.ne.0.0 .and. tt2.ne.0) then - call mskrtd(id2(k-7168+1:k),nutc0,tsec,ntol,nrxfreq,ndepth, & - mycall,mygrid,hiscall,bshmsg,bcontest,btrain,pcoeffs,bswl,& - datadir,line1) - endif - endif - endif - -900 return -end subroutine hspec diff --git a/lib/js8/baselinejs8.f90 b/lib/js8/baselinejs8.f90 new file mode 100644 index 0000000..79f4003 --- /dev/null +++ b/lib/js8/baselinejs8.f90 @@ -0,0 +1,51 @@ +subroutine baselinejs8(s,nfa,nfb,sbase) + +! Fit baseline to spectrum (for FT8) +! Input: s(npts) Linear scale in power +! Output: sbase(npts) Baseline + + implicit real*8 (a-h,o-z) + + !include 'js8_params.f90' + + real*4 s(NSPS) + real*4 sbase(NSPS) + real*4 base + real*8 x(1000),y(1000),a(5) + data nseg/10/,npct/10/ + + df=12000.0/(NSPS*2.0d0) !3.125 Hz + ia=max(1,nint(nfa/df)) + ib=nint(nfb/df) + do i=ia,ib + s(i)=10.0*log10(s(i)) !Convert to dB scale + enddo + + nterms=5 + nlen=(ib-ia+1)/nseg !Length of test segment + i0=(ib-ia+1)/2 !Midpoint + k=0 + do n=1,nseg !Loop over all segments + ja=ia + (n-1)*nlen + jb=ja+nlen-1 + call pctile(s(ja),nlen,npct,base) !Find lowest npct of points + do i=ja,jb + if(s(i).le.base) then + if (k.lt.1000) k=k+1 !Save all "lower envelope" points + x(k)=i-i0 + y(k)=s(i) + endif + enddo + enddo + kz=k + a=0. + call polyfit(x,y,y,kz,nterms,0,a,chisqr) !Fit a low-order polynomial + do i=ia,ib + t=i-i0 + sbase(i)=a(1)+t*(a(2)+t*(a(3)+t*(a(4)+t*(a(5))))) + 0.65 +! write(51,3051) i*df,s(i),sbase(i) +!3051 format(3f12.3) + enddo + + return +end subroutine baselinejs8 diff --git a/lib/js8/costas/Costas_essense_N=7.txt b/lib/js8/costas/Costas_essense_N=7.txt new file mode 100644 index 0000000..b99cc8b --- /dev/null +++ b/lib/js8/costas/Costas_essense_N=7.txt @@ -0,0 +1,30 @@ + 0 1 5 3 6 2 4 + 0 1 6 3 5 4 2 + 0 1 6 4 3 5 2 + 0 2 5 1 6 3 4 + 0 2 5 1 6 4 3 + 0 2 6 5 3 4 1 + 0 3 4 2 6 5 1 + 0 3 4 6 1 5 2 + 0 3 5 4 2 6 1 + 0 4 2 5 6 1 3 + 0 4 6 5 2 3 1 + 0 5 4 6 2 3 1 + 0 6 2 3 5 4 1 + 1 0 4 6 2 5 3 + 1 0 5 3 6 2 4 + 1 2 4 0 6 5 3 + 1 3 2 5 6 0 4 + 1 3 4 0 6 5 2 + 1 3 6 2 0 5 4 + 1 4 0 5 6 3 2 + 1 4 0 6 5 2 3 + 1 4 5 0 2 6 3 + 1 4 5 3 0 6 2 + 1 4 6 0 5 2 3 + 1 4 6 0 5 3 2 + 1 5 0 2 3 6 4 + 1 5 6 0 3 2 4 + 2 1 4 6 0 5 3 + 2 3 0 6 5 1 4 + 2 5 0 6 4 1 3 diff --git a/lib/js8/costas/Costas_symmetrical_N=7.txt b/lib/js8/costas/Costas_symmetrical_N=7.txt new file mode 100644 index 0000000..7e38271 --- /dev/null +++ b/lib/js8/costas/Costas_symmetrical_N=7.txt @@ -0,0 +1,10 @@ + 0 1 5 3 6 2 4 + 0 1 6 3 5 4 2 + 0 1 6 4 3 5 2 + 0 6 2 3 5 4 1 + 1 0 4 6 2 5 3 + 1 0 5 3 6 2 4 + 1 4 5 0 2 6 3 + 1 4 5 3 0 6 2 + 1 5 0 2 3 6 4 + 2 5 0 6 4 1 3 diff --git a/lib/js8/costas/Sorted_Costas_arrays_N=7.txt b/lib/js8/costas/Sorted_Costas_arrays_N=7.txt new file mode 100644 index 0000000..b547377 --- /dev/null +++ b/lib/js8/costas/Sorted_Costas_arrays_N=7.txt @@ -0,0 +1,201 @@ + 7 200 + 0 1 5 3 6 2 4 + 0 1 6 3 5 4 2 + 0 1 6 4 3 5 2 + 0 2 5 1 6 3 4 + 0 2 5 1 6 4 3 + 0 2 6 5 3 4 1 + 0 3 1 5 6 2 4 + 0 3 1 6 5 2 4 + 0 3 4 2 6 5 1 + 0 3 4 6 1 5 2 + 0 3 5 4 2 6 1 + 0 4 2 5 6 1 3 + 0 4 6 1 2 5 3 + 0 4 6 5 2 3 1 + 0 5 2 6 1 3 4 + 0 5 4 6 2 3 1 + 0 6 1 4 5 3 2 + 0 6 2 3 5 4 1 + 0 6 3 1 2 5 4 + 0 6 4 1 3 2 5 + 0 6 4 5 1 3 2 + 0 6 4 5 2 1 3 + 1 0 4 6 2 5 3 + 1 0 5 3 6 2 4 + 1 2 4 0 6 5 3 + 1 3 2 5 6 0 4 + 1 3 2 5 6 4 0 + 1 3 2 6 4 5 0 + 1 3 4 0 6 5 2 + 1 3 6 2 0 5 4 + 1 4 0 5 6 3 2 + 1 4 0 6 5 2 3 + 1 4 3 5 2 0 6 + 1 4 3 5 6 2 0 + 1 4 5 0 2 6 3 + 1 4 5 3 0 6 2 + 1 4 5 3 2 6 0 + 1 4 6 0 5 2 3 + 1 4 6 0 5 3 2 + 1 5 0 2 3 6 4 + 1 5 6 0 3 2 4 + 1 5 6 2 4 3 0 + 1 6 2 4 5 3 0 + 1 6 4 5 0 3 2 + 2 0 3 4 6 1 5 + 2 0 5 6 1 4 3 + 2 0 6 5 1 3 4 + 2 1 4 0 5 6 3 + 2 1 4 5 0 6 3 + 2 1 4 5 3 0 6 + 2 1 4 6 0 5 3 + 2 1 6 4 0 3 5 + 2 1 6 4 5 0 3 + 2 3 0 5 1 4 6 + 2 3 0 5 4 6 1 + 2 3 0 6 5 1 4 + 2 3 1 5 4 6 0 + 2 3 5 0 4 1 6 + 2 3 5 0 6 4 1 + 2 3 5 1 0 6 4 + 2 3 5 4 1 6 0 + 2 3 6 5 0 4 1 + 2 4 0 1 5 3 6 + 2 4 0 3 1 5 6 + 2 4 0 3 1 6 5 + 2 4 1 0 5 3 6 + 2 4 1 5 6 0 3 + 2 4 1 6 5 0 3 + 2 4 3 6 0 1 5 + 2 4 5 3 6 1 0 + 2 5 0 1 6 4 3 + 2 5 0 6 4 1 3 + 2 5 1 0 6 3 4 + 2 5 1 6 4 3 0 + 2 5 3 4 6 1 0 + 2 5 6 0 4 1 3 + 2 5 6 0 4 3 1 + 2 5 6 1 3 0 4 + 2 6 0 1 4 3 5 + 2 6 0 3 5 4 1 + 2 6 3 5 0 1 4 + 3 0 1 6 2 5 4 + 3 0 4 6 1 2 5 + 3 0 5 4 6 1 2 + 3 0 5 6 1 4 2 + 3 0 6 1 2 5 4 + 3 0 6 5 1 4 2 + 3 1 0 6 2 4 5 + 3 1 2 5 4 6 0 + 3 1 4 0 2 6 5 + 3 1 4 0 6 5 2 + 3 1 4 5 0 2 6 + 3 1 4 6 0 5 2 + 3 1 6 0 2 5 4 + 3 1 6 5 2 4 0 + 3 2 0 5 1 4 6 + 3 2 0 5 6 1 4 + 3 2 5 0 1 6 4 + 3 2 5 0 6 4 1 + 3 2 5 6 0 4 1 + 3 4 1 0 6 2 5 + 3 4 1 6 0 2 5 + 3 4 1 6 5 0 2 + 3 4 6 1 0 5 2 + 3 4 6 1 5 2 0 + 3 5 0 1 4 2 6 + 3 5 0 6 4 1 2 + 3 5 2 0 6 1 4 + 3 5 2 1 6 4 0 + 3 5 2 6 0 1 4 + 3 5 2 6 4 0 1 + 3 5 4 1 2 0 6 + 3 5 6 0 4 2 1 + 3 6 0 1 5 2 4 + 3 6 0 5 4 1 2 + 3 6 1 0 5 2 4 + 3 6 1 2 0 5 4 + 3 6 2 0 5 4 1 + 3 6 5 0 4 1 2 + 4 0 3 1 6 5 2 + 4 0 6 3 1 2 5 + 4 0 6 5 2 3 1 + 4 1 0 5 3 6 2 + 4 1 0 6 2 3 5 + 4 1 0 6 2 5 3 + 4 1 3 2 0 5 6 + 4 1 5 0 2 3 6 + 4 1 5 6 0 3 2 + 4 1 6 0 2 5 3 + 4 1 6 5 0 2 3 + 4 2 1 3 0 5 6 + 4 2 3 0 6 5 1 + 4 2 5 0 1 6 3 + 4 2 5 1 0 6 3 + 4 2 5 6 1 3 0 + 4 2 6 3 5 0 1 + 4 2 6 3 5 1 0 + 4 2 6 5 1 3 0 + 4 3 0 1 6 2 5 + 4 3 1 2 5 0 6 + 4 3 1 5 6 0 2 + 4 3 1 6 0 2 5 + 4 3 1 6 2 5 0 + 4 3 5 1 2 0 6 + 4 3 6 0 1 5 2 + 4 3 6 1 2 0 5 + 4 3 6 1 5 2 0 + 4 5 0 2 1 6 3 + 4 5 0 2 6 3 1 + 4 5 2 0 6 1 3 + 4 5 2 1 3 6 0 + 4 5 2 1 6 0 3 + 4 5 2 6 1 0 3 + 4 6 0 1 5 3 2 + 4 6 1 0 5 2 3 + 4 6 3 2 0 5 1 + 5 0 2 1 6 3 4 + 5 0 4 2 1 3 6 + 5 1 0 4 2 3 6 + 5 1 0 6 3 4 2 + 5 1 6 4 3 0 2 + 5 2 0 6 1 3 4 + 5 2 0 6 1 4 3 + 5 2 1 3 4 0 6 + 5 2 1 3 6 0 4 + 5 2 1 6 4 0 3 + 5 2 3 1 0 4 6 + 5 2 3 1 4 6 0 + 5 2 6 0 1 4 3 + 5 2 6 1 0 3 4 + 5 3 0 4 6 1 2 + 5 3 2 6 0 1 4 + 5 3 4 0 2 1 6 + 5 3 4 1 0 2 6 + 5 3 4 1 0 6 2 + 5 4 2 6 0 1 3 + 5 6 1 3 0 4 2 + 5 6 2 0 4 1 3 + 6 0 2 1 4 5 3 + 6 0 2 1 5 3 4 + 6 0 2 5 3 4 1 + 6 0 3 5 4 1 2 + 6 0 4 3 1 2 5 + 6 0 5 2 1 3 4 + 6 1 2 0 4 3 5 + 6 1 4 0 5 3 2 + 6 2 0 1 4 3 5 + 6 2 0 5 4 1 3 + 6 2 4 1 0 5 3 + 6 3 1 2 4 0 5 + 6 3 2 0 5 1 4 + 6 3 2 4 0 1 5 + 6 3 5 0 1 4 2 + 6 3 5 1 0 4 2 + 6 4 0 1 3 2 5 + 6 4 1 5 0 2 3 + 6 4 1 5 0 3 2 + 6 5 0 2 3 1 4 + 6 5 0 3 1 2 4 + 6 5 1 3 0 4 2 diff --git a/lib/js8/genjs8.f90 b/lib/js8/genjs8.f90 new file mode 100644 index 0000000..37bba4b --- /dev/null +++ b/lib/js8/genjs8.f90 @@ -0,0 +1,93 @@ +subroutine genjs8(msg,mygrid,bcontest,i3bit,msgsent,msgbits,itone) + +! Encode an FT8 message, producing array itone(). + + use crc + use packjt + + include 'js8_params.f90' + + parameter (KK=87) !Information bits (75 + CRC12) + parameter (ND=58) !Data symbols + parameter (NS=21) !Sync symbols (3 @ Costas 7x7) + parameter (NN=NS+ND) !Total channel symbols (79) + + character*68 alphabet + character*22 msg,msgsent + character*6 mygrid + character*87 cbits + logical bcontest,checksumok + integer*4 i4Msg6BitWords(12) !72-bit message as 6-bit words + integer*1 msgbits(KK),codeword(3*ND) + integer*1, target:: i1Msg8BitBytes(11) + integer itone(NN) + + integer icos7a(0:6), icos7b(0:6), icos7c(0:6) + if(NCOSTAS.eq.1) then + icos7a = (/4,2,5,6,1,3,0/) !Beginning Costas 7x7 tone pattern + icos7b = (/4,2,5,6,1,3,0/) !Middle Costas 7x7 tone pattern + icos7c = (/4,2,5,6,1,3,0/) !End Costas 7x7 tone pattern + else + icos7a = (/0,6,2,3,5,4,1/) !Beginning Costas 7x7 tone pattern + icos7b = (/1,5,0,2,3,6,4/) !Middle Costas 7x7 tone pattern + icos7c = (/2,5,0,6,4,1,3/) !End Costas 7x7 tone pattern + endif + + alphabet='0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz-+/?.' + + itype=6 + do i=1,12 + v=index(alphabet, msg(i:i)) + if(v.eq.0) exit + i4Msg6BitWords(i)=v - 1 + enddo + msgsent=' ' + msgsent(1:12)=msg(1:12) + + ! call packmsg(msg,i4Msg6BitWords,itype,bcontest) !Pack into 12 6-bit bytes + ! call unpackmsg(i4Msg6BitWords,msgsent,bcontest,mygrid) !Unpack to get msgsent + + write(cbits,1000) i4Msg6BitWords,32*i3bit +1000 format(12b6.6,b8.8) + read(cbits,1001) i1Msg8BitBytes(1:10) +1001 format(10b8) + i1Msg8BitBytes(10)=iand(i1Msg8BitBytes(10),transfer(128+64+32,0_1)) + i1Msg8BitBytes(11)=0 + icrc12=crc12(c_loc(i1Msg8BitBytes),11) + icrc12=xor(icrc12, 42) ! TODO: jsherer - could change the crc here + +! For reference, here's how to check the CRC +! i1Msg8BitBytes(10)=icrc12/256 +! i1Msg8BitBytes(11)=iand (icrc12,255) +! checksumok = crc12_check(c_loc (i1Msg8BitBytes), 11) +! if( checksumok ) write(*,*) 'Good checksum' + + write(cbits,1003) i4Msg6BitWords,i3bit,icrc12 +1003 format(12b6.6,b3.3,b12.12) + read(cbits,1004) msgbits +1004 format(87i1) + + call encode174(msgbits,codeword) !Encode the test message + +! Message structure: S7 D29 S7 D29 S7 + itone(1:7)=icos7a + itone(36+1:36+7)=icos7b + itone(NN-6:NN)=icos7c + k=7 + do j=1,ND + i=3*j -2 + k=k+1 + if(j.eq.30) k=k+7 + indx=codeword(i)*4 + codeword(i+1)*2 + codeword(i+2) + itone(k)=indx + enddo + + if(NWRITELOG.eq.1) then + open(99, file="./js8.log", status="old", position="append", action="write") + write(99,*) 'tones', itone + write(99,*) '...', icos7a, '--->', NCOSTAS + close(99) + endif + + return +end subroutine genjs8 diff --git a/lib/js8/genjs8refsig.f90 b/lib/js8/genjs8refsig.f90 new file mode 100644 index 0000000..d3f4ea4 --- /dev/null +++ b/lib/js8/genjs8refsig.f90 @@ -0,0 +1,24 @@ +subroutine genjs8refsig(itone,cref,f0) + !include 'js8_params.f90' + + complex cref(NN*NSPS) + integer itone(NN) + real*8 twopi,phi,dphi,dt,xnsps + data twopi/0.d0/ + save twopi + if( twopi .lt. 0.1 ) twopi=8.d0*atan(1.d0) + + xnsps=NSPS*1.0d0 + dt=1.d0/12000.d0 + phi=0.d0 + k=1 + do i=1,NN + dphi=twopi*(f0*dt+itone(i)/xnsps) + do is=1,NSPS + cref(k)=cmplx(cos(phi),sin(phi)) + phi=mod(phi+dphi,twopi) + k=k+1 + enddo + enddo + return +end subroutine genjs8refsig diff --git a/lib/js8/js8_downsample.f90 b/lib/js8/js8_downsample.f90 new file mode 100644 index 0000000..f933be1 --- /dev/null +++ b/lib/js8/js8_downsample.f90 @@ -0,0 +1,54 @@ +subroutine js8_downsample(dd,newdat,f0,c1) + + ! Downconvert to complex data sampled at 200 Hz ==> 32 samples/symbol + + !include 'js8_params.f90' + + parameter (NDFFT1=NSPS*NDD, NDFFT2=NDFFT1/NDOWN) ! Downconverted FFT Size - 192000/60 = 3200 + + logical newdat,first + + complex c1(0:NDFFT2-1) + complex cx(0:NDFFT1/2) + real dd(NMAX),x(NDFFT1),taper(0:NDD) + equivalence (x,cx) + data first/.true./ + save cx,first,taper + + if(first) then + pi=4.0*atan(1.0) + do i=0,NDD + taper(i)=0.5*(1.0+cos(i*pi/NDD)) + enddo + first=.false. + endif + if(newdat) then + ! Data in dd have changed, recompute the long FFT + x(1:NMAX)=dd + x(NMAX+1:NDFFT1)=0. !Zero-pad the x array + call four2a(cx,NDFFT1,1,-1,0) !r2c FFT to freq domain + newdat=.false. + endif + + df=12000.0/NDFFT1 + baud=12000.0/NSPS + i0=nint(f0/df) + ft=f0+8.5*baud + it=min(nint(ft/df),NDFFT1/2) + fb=f0-1.5*baud + ib=max(1,nint(fb/df)) + k=0 + c1=0. + do i=ib,it + c1(k)=cx(i) + k=k+1 + enddo + c1(0:NDD)=c1(0:NDD)*taper(NDD:0:-1) + c1(k-1-NDD:k-1)=c1(k-1-NDD:k-1)*taper + c1=cshift(c1,i0-ib) + call four2a(c1,NDFFT2,1,1,1) !c2c FFT back to time domain + fac=1.0/sqrt(float(NDFFT1)*NDFFT2) + c1=fac*c1 + + return +end subroutine js8_downsample diff --git a/lib/js8/js8_params.f90 b/lib/js8/js8_params.f90 new file mode 100644 index 0000000..fc5512c --- /dev/null +++ b/lib/js8/js8_params.f90 @@ -0,0 +1,2 @@ +parameter (NCOSTAS=2) !Which JS8 Costas Arrays to use (1=original, 2=three symmetrical costas) +parameter (NWRITELOG=0) !Write log file? diff --git a/lib/js8/js8b_params.f90 b/lib/js8/js8b_params.f90 new file mode 100644 index 0000000..aece5a5 --- /dev/null +++ b/lib/js8/js8b_params.f90 @@ -0,0 +1,36 @@ +!parameter (NSPS=480) !Samples per symbol at 12000 S/s +!parameter (NTXDUR=5) !TX Duration in Seconds +!parameter (NDOWNSPS=16) !Downsampled samples per symbol +!parameter (AZ=6.0) !Near dupe sync spacing +!parameter (NDD=136) !Downconverted FFT Bins - 100 Bins +!parameter (JZ=62) !Sync Search Space over +/- 2.5s relative to 0.5s TX start time. 2.48 = 62/4/(12000/1920) ? + + +! parameter (NSPS=384, NTXDUR=4, NDOWNSPS=16, NDD=150, JZ=116) ! 250 Hz 31.25 baud 60 wpm -18.0dB (1.0Eb/N0) 2.52s +! parameter (NSPS=384, NTXDUR=5, NDOWNSPS=16, NDD=160, JZ=116) ! 250 Hz 31.25 baud 48 wpm -18.0dB (1.0Eb/N0) 2.52s +! parameter (NSPS=480, NTXDUR=5, NDOWNSPS=16, NDD=136, JZ=116) ! 200 Hz 25 baud 48 wpm -19.0dB (1.0Eb/N0) 3.16s +! parameter (NSPS=480, NTXDUR=6, NDOWNSPS=20, NDD=150, JZ=116) ! 200 Hz 25 baud 40 wpm -19.0dB (1.0Eb/N0) 3.16s +! parameter (NSPS=500, NTXDUR=6, NDOWNSPS=20, NDD=144, JZ=116) ! 192 Hz 24 baud 40 wpm -19.4dB (1.0Eb/N0) 3.29s +! parameter (NSPS=600, NTXDUR=6, NDOWNSPS=24, NDD=120, JZ=116) ! 160 Hz 20 baud 40 wpm -20.0dB (1.0Eb/N0) 3.95s +! parameter (NSPS=768, NTXDUR=8, NDOWNSPS=24, NDD=125, JZ=116) ! 125 Hz 15.625 baud 32 wpm -21.0dB (1.0Eb/N0) 5.05s +! parameter (NSPS=800, NTXDUR=8, NDOWNSPS=24, NDD=100, JZ=116) ! 120 Hz 15 baud 32 wpm -21.2dB (1.0Eb/N0) 5.26s +! parameter (NSPS=960, NTXDUR=8, NDOWNSPS=24, NDD=100, JZ=116) ! 100 Hz 12.50 baud 32 wpm -22.0dB (1.0Eb/N0) 5.92s + parameter (NSPS=1200, NTXDUR=10, NDOWNSPS=20, NDD=100, JZ=172) ! 80 Hz 10 baud 24 wpm -23.0dB (1.0Eb/N0) 7.90s +! parameter (NSPS=1920, NTXDUR=15, NDOWNSPS=32, NDD=100, JZ=116) ! 50 Hz 6.250 baud 16 wpm -25.0dB (1.0Eb/N0) 12.64s +! parameter (NSPS=4000, NTXDUR=30, NDOWNSPS=20, NDD=90, JZ=62) ! 24 Hz 3 baud 8 wpm -28.2dB (1.0Eb/N0) 26.33s + +parameter (AZ=12000.0/(1.0*NSPS)*0.64d0) !Dedupe overlap in Hz +parameter (ASTART=0.2) !Start delay in seconds +parameter (ASYNCMIN=1.5) !Minimum Sync + +parameter (KK=87) !Information bits (75 + CRC12) +parameter (ND=58) !Data symbols +parameter (NS=21) !Sync symbols (3 @ Costas 7x7) +parameter (NN=NS+ND) !Total channel symbols (79) +parameter (NZ=NSPS*NN) !Samples in full 15 s waveform (151,680) +parameter (NMAX=NTXDUR*12000) !Samples in iwave (180,000) +parameter (NFFT1=2*NSPS, NH1=NFFT1/2) !Length of FFTs for symbol spectra +parameter (NSTEP=NSPS/4) !Rough time-sync step size +parameter (NHSYM=NMAX/NSTEP-3) !Number of symbol spectra (1/4-sym steps) +parameter (NDOWN=NSPS/NDOWNSPS) !Downsample factor to 32 samples per symbol +parameter (NQSYMBOL=NDOWNSPS/4) !Downsample factor of a quarter symbol diff --git a/lib/js8/js8c_params.f90 b/lib/js8/js8c_params.f90 new file mode 100644 index 0000000..caba06e --- /dev/null +++ b/lib/js8/js8c_params.f90 @@ -0,0 +1,36 @@ +!parameter (NSPS=480) !Samples per symbol at 12000 S/s +!parameter (NTXDUR=5) !TX Duration in Seconds +!parameter (NDOWNSPS=16) !Downsampled samples per symbol +!parameter (AZ=6.0) !Near dupe sync spacing +!parameter (NDD=136) !Downconverted FFT Bins - 100 Bins +!parameter (JZ=62) !Sync Search Space over +/- 2.5s relative to 0.5s TX start time. 2.48 = 62/4/(12000/1920) ? + + +! parameter (NSPS=384, NTXDUR=4, NDOWNSPS=16, NDD=150, JZ=116) ! 250 Hz 31.25 baud 60 wpm -18.0dB (1.0Eb/N0) 2.52s +! parameter (NSPS=384, NTXDUR=5, NDOWNSPS=16, NDD=160, JZ=116) ! 250 Hz 31.25 baud 48 wpm -18.0dB (1.0Eb/N0) 2.52s +! parameter (NSPS=480, NTXDUR=5, NDOWNSPS=16, NDD=136, JZ=116) ! 200 Hz 25 baud 48 wpm -19.0dB (1.0Eb/N0) 3.16s +! parameter (NSPS=480, NTXDUR=6, NDOWNSPS=20, NDD=150, JZ=116) ! 200 Hz 25 baud 40 wpm -19.0dB (1.0Eb/N0) 3.16s +! parameter (NSPS=500, NTXDUR=6, NDOWNSPS=20, NDD=144, JZ=116) ! 192 Hz 24 baud 40 wpm -19.4dB (1.0Eb/N0) 3.29s + parameter (NSPS=600, NTXDUR=6, NDOWNSPS=12, NDD=120, JZ=172) ! 160 Hz 20 baud 40 wpm -20.0dB (1.0Eb/N0) 3.95s +! parameter (NSPS=768, NTXDUR=8, NDOWNSPS=24, NDD=125, JZ=116) ! 125 Hz 15.625 baud 32 wpm -21.0dB (1.0Eb/N0) 5.05s +! parameter (NSPS=800, NTXDUR=8, NDOWNSPS=24, NDD=100, JZ=116) ! 120 Hz 15 baud 32 wpm -21.2dB (1.0Eb/N0) 5.26s +! parameter (NSPS=960, NTXDUR=8, NDOWNSPS=24, NDD=100, JZ=116) ! 100 Hz 12.50 baud 32 wpm -22.0dB (1.0Eb/N0) 5.92s +! parameter (NSPS=1200, NTXDUR=10, NDOWNSPS=20, NDD=100, JZ=116) ! 80 Hz 10 baud 24 wpm -23.0dB (1.0Eb/N0) 7.90s +! parameter (NSPS=1920, NTXDUR=15, NDOWNSPS=32, NDD=100, JZ=116) ! 50 Hz 6.250 baud 16 wpm -25.0dB (1.0Eb/N0) 12.64s +! parameter (NSPS=4000, NTXDUR=30, NDOWNSPS=20, NDD=90, JZ=62) ! 24 Hz 3 baud 8 wpm -28.2dB (1.0Eb/N0) 26.33s + +parameter (AZ=12000.0/(1.0*NSPS)*0.64d0) !Dedupe overlap in Hz +parameter (ASTART=0.1) !Start delay in seconds +parameter (ASYNCMIN=1.5) !Minimum Sync + +parameter (KK=87) !Information bits (75 + CRC12) +parameter (ND=58) !Data symbols +parameter (NS=21) !Sync symbols (3 @ Costas 7x7) +parameter (NN=NS+ND) !Total channel symbols (79) +parameter (NZ=NSPS*NN) !Samples in full 15 s waveform (151,680) +parameter (NMAX=NTXDUR*12000) !Samples in iwave (180,000) +parameter (NFFT1=2*NSPS, NH1=NFFT1/2) !Length of FFTs for symbol spectra +parameter (NSTEP=NSPS/4) !Rough time-sync step size +parameter (NHSYM=NMAX/NSTEP-3) !Number of symbol spectra (1/4-sym steps) +parameter (NDOWN=NSPS/NDOWNSPS) !Downsample factor to 32 samples per symbol +parameter (NQSYMBOL=NDOWNSPS/4) !Downsample factor of a quarter symbol diff --git a/lib/js8/js8d_params.f90 b/lib/js8/js8d_params.f90 new file mode 100644 index 0000000..664e9c1 --- /dev/null +++ b/lib/js8/js8d_params.f90 @@ -0,0 +1,36 @@ +!parameter (NSPS=480) !Samples per symbol at 12000 S/s +!parameter (NTXDUR=5) !TX Duration in Seconds +!parameter (NDOWNSPS=16) !Downsampled samples per symbol +!parameter (AZ=6.0) !Near dupe sync spacing +!parameter (NDD=136) !Downconverted FFT Bins - 100 Bins +!parameter (JZ=62) !Sync Search Space over +/- 2.5s relative to 0.5s TX start time. 2.48 = 62/4/(12000/1920) ? + + + parameter (NSPS=384, NTXDUR=4, NDOWNSPS=12, NDD=125, JZ=250) ! 250 Hz 31.25 baud 60 wpm -18.0dB (1.0Eb/N0) 2.52s +! parameter (NSPS=384, NTXDUR=5, NDOWNSPS=12, NDD=125, JZ=116) ! 250 Hz 31.25 baud 48 wpm -18.0dB (1.0Eb/N0) 2.52s +! parameter (NSPS=480, NTXDUR=5, NDOWNSPS=12, NDD=125, JZ=116) ! 200 Hz 25 baud 48 wpm -19.0dB (1.0Eb/N0) 3.16s +! parameter (NSPS=480, NTXDUR=6, NDOWNSPS=20, NDD=150, JZ=116) ! 200 Hz 25 baud 40 wpm -19.0dB (1.0Eb/N0) 3.16s +! parameter (NSPS=500, NTXDUR=6, NDOWNSPS=20, NDD=144, JZ=116) ! 192 Hz 24 baud 40 wpm -19.4dB (1.0Eb/N0) 3.29s +! parameter (NSPS=600, NTXDUR=6, NDOWNSPS=24, NDD=120, JZ=172) ! 160 Hz 20 baud 40 wpm -20.0dB (1.0Eb/N0) 3.95s +! parameter (NSPS=768, NTXDUR=8, NDOWNSPS=24, NDD=125, JZ=116) ! 125 Hz 15.625 baud 32 wpm -21.0dB (1.0Eb/N0) 5.05s +! parameter (NSPS=800, NTXDUR=8, NDOWNSPS=24, NDD=100, JZ=116) ! 120 Hz 15 baud 32 wpm -21.2dB (1.0Eb/N0) 5.26s +! parameter (NSPS=960, NTXDUR=8, NDOWNSPS=24, NDD=100, JZ=116) ! 100 Hz 12.50 baud 32 wpm -22.0dB (1.0Eb/N0) 5.92s +! parameter (NSPS=1200, NTXDUR=10, NDOWNSPS=20, NDD=100, JZ=116) ! 80 Hz 10 baud 24 wpm -23.0dB (1.0Eb/N0) 7.90s +! parameter (NSPS=1920, NTXDUR=15, NDOWNSPS=32, NDD=100, JZ=116) ! 50 Hz 6.250 baud 16 wpm -25.0dB (1.0Eb/N0) 12.64s +! parameter (NSPS=4000, NTXDUR=30, NDOWNSPS=40, NDD=90, JZ=116) ! 24 Hz 3 baud 8 wpm -28.2dB (1.0Eb/N0) 26.33s + +parameter (AZ=12000.0/(1.0*NSPS)*0.64d0) !Dedupe overlap in Hz +parameter (ASTART=0.1) !Start delay in seconds +parameter (ASYNCMIN=1.5) !Minimum Sync + +parameter (KK=87) !Information bits (75 + CRC12) +parameter (ND=58) !Data symbols +parameter (NS=21) !Sync symbols (3 @ Costas 7x7) +parameter (NN=NS+ND) !Total channel symbols (79) +parameter (NZ=NSPS*NN) !Samples in full 15 s waveform (151,680) +parameter (NMAX=NTXDUR*12000) !Samples in iwave (180,000) +parameter (NFFT1=2*NSPS, NH1=NFFT1/2) !Length of FFTs for symbol spectra +parameter (NSTEP=NSPS/4) !Rough time-sync step size +parameter (NHSYM=NMAX/NSTEP-3) !Number of symbol spectra (1/4-sym steps) +parameter (NDOWN=NSPS/NDOWNSPS) !Downsample factor to 32 samples per symbol +parameter (NQSYMBOL=NDOWNSPS/4) !Downsample factor of a quarter symbol diff --git a/lib/js8/js8dec.f90 b/lib/js8/js8dec.f90 new file mode 100644 index 0000000..36b8f56 --- /dev/null +++ b/lib/js8/js8dec.f90 @@ -0,0 +1,486 @@ +subroutine js8dec(dd0,newdat,nQSOProgress,nfqso,nftx,ndepth,lapon,lapcqonly, & + napwid,lsubtract,nagain,iaptype,mycall12,mygrid6,hiscall12,bcontest, & + sync0,f1,xdt,xbase,apsym,nharderrors,dmin,nbadcrc,ipass,iera,msg37,xsnr) + + use crc + use timer_module, only: timer + + !include 'js8_params.f90' + + parameter(NP=3200) ! why 3200? not sure... + parameter(NP2=2812) + character*37 msg37 + character message*22,msgsent*22,origmsg*22 + character*12 mycall12,hiscall12 + character*6 mycall6,mygrid6,hiscall6,c1,c2 + character*87 cbits + logical bcontest + real a(5) + real s1(0:7,ND),s2(0:7,NN),s1sort(8*ND) + real ps(0:7),psl(0:7) + real bmeta(3*ND),bmetb(3*ND),bmetap(3*ND) + real llr(3*ND),llra(3*ND),llr0(3*ND),llr1(3*ND),llrap(3*ND) !Soft symbols + real dd0(NMAX) + integer*1 decoded(KK),decoded0(KK),apmask(3*ND),cw(3*ND) + integer*1 msgbits(KK) + integer apsym(KK) + integer mcq(28),mde(28),mrrr(16),m73(16),mrr73(16) + integer itone(NN) + integer indxs1(8*ND) + integer ip(1) + integer nappasses(0:5) !Number of decoding passes to use for each QSO state + integer naptypes(0:5,4) ! (nQSOProgress, decoding pass) maximum of 4 passes for now + integer*1, target:: i1hiscall(12) + complex cd0(0:NP-1) + complex ctwk(4*NSPS/NDOWN) + complex csymb(NDOWNSPS) + logical first,newdat,lsubtract,lapon,lapcqonly,nagain + equivalence (s1,s1sort) + data mcq/1,1,1,1,1,0,1,0,0,0,0,0,1,0,0,0,0,0,1,1,0,0,0,1,1,0,0,1/ + data mrrr/0,1,1,1,1,1,1,0,1,1,0,0,1,1,1,1/ + data m73/0,1,1,1,1,1,1,0,1,1,0,1,0,0,0,0/ + data mde/1,1,1,1,1,1,1,1,0,1,1,0,0,1,0,0,0,0,0,1,1,1,0,1,0,0,0,1/ + data mrr73/0,0,0,0,0,0,1,0,0,0,0,1,0,1,0,1/ + data first/.true./ + save nappasses,naptypes + + integer icos7a(0:6), icos7b(0:6), icos7c(0:6) + if(NCOSTAS.eq.1) then + icos7a = (/4,2,5,6,1,3,0/) !Beginning Costas 7x7 tone pattern + icos7b = (/4,2,5,6,1,3,0/) !Middle Costas 7x7 tone pattern + icos7c = (/4,2,5,6,1,3,0/) !End Costas 7x7 tone pattern + else + icos7a = (/0,6,2,3,5,4,1/) !Beginning Costas 7x7 tone pattern + icos7b = (/1,5,0,2,3,6,4/) !Middle Costas 7x7 tone pattern + icos7c = (/2,5,0,6,4,1,3/) !End Costas 7x7 tone pattern + endif + + if(first) then + mcq=2*mcq-1 + mde=2*mde-1 + mrrr=2*mrrr-1 + m73=2*m73-1 + mrr73=2*mrr73-1 + nappasses(0)=2 + nappasses(1)=2 + nappasses(2)=2 + nappasses(3)=4 + nappasses(4)=4 + nappasses(5)=3 + +! iaptype +!------------------------ +! 1 CQ ??? ??? +! 2 MyCall ??? ??? +! 3 MyCall DxCall ??? +! 4 MyCall DxCall RRR +! 5 MyCall DxCall 73 +! 6 MyCall DxCall RR73 +! 7 ??? DxCall ??? + + naptypes(0,1:4)=(/1,2,0,0/) + naptypes(1,1:4)=(/2,3,0,0/) + naptypes(2,1:4)=(/2,3,0,0/) + naptypes(3,1:4)=(/3,4,5,6/) + naptypes(4,1:4)=(/3,4,5,6/) + naptypes(5,1:4)=(/3,1,2,0/) + first=.false. + endif + + max_iterations=30 + nharderrors=-1 + fs2=12000.0/NDOWN + dt2=1.0/fs2 + twopi=8.0*atan(1.0) + delfbest=0. + ibest=0 + + call timer('js8_down',0) + call js8_downsample(dd0,newdat,f1,cd0) !Mix f1 to baseband and downsample + call timer('js8_down',1) + + xdt=xdt+ASTART + i0=nint(xdt*fs2) !Initial guess for start of signal + smax=0.0 + + if(NWRITELOG.eq.1) then + open(99, file="./js8.log", status="old", position="append", action="write") + write(99,*) 'initial dt guess', i0, xdt + close(99) + endif + + do idt=i0-NQSYMBOL,i0+NQSYMBOL !Search over +/- one quarter symbol + call syncjs8d(cd0,idt,ctwk,0,sync) + if(NWRITELOG.eq.1) then + open(99, file="./js8.log", status="old", position="append", action="write") + write(99,*) 'idt', idt, 'sync', sync + close(99) + endif + if(sync.gt.smax) then + smax=sync + ibest=idt + endif + enddo + xdt2=ibest*dt2 !Improved estimate for DT + + if(NWRITELOG.eq.1) then + open(99, file="./js8.log", status="old", position="append", action="write") + write(99,*) 'xdt2', xdt2, ibest + close(99) + endif + +! Now peak up in frequency + i0=nint(xdt2*fs2) + smax=0.0 + + do ifr=-5,5 !Search over +/- 2.5 Hz + delf=ifr*0.5 + dphi=twopi*delf*dt2 + phi=0.0 + do i=1,NDOWNSPS + ctwk(i)=cmplx(cos(phi),sin(phi)) + phi=mod(phi+dphi,twopi) + enddo + call syncjs8d(cd0,i0,ctwk,1,sync) + if(NWRITELOG.eq.1) then + open(99, file="./js8.log", status="old", position="append", action="write") + write(99,*) 'df', delf, 'sync', sync + close(99) + endif + if( sync .gt. smax ) then + smax=sync + delfbest=delf + endif + enddo + a=0.0 + a(1)=-delfbest + call twkfreq1(cd0,NP2,fs2,a,cd0) + xdt=xdt2 + f1=f1+delfbest !Improved estimate of DF + + if(NWRITELOG.eq.1) then + open(99, file="./js8.log", status="old", position="append", action="write") + write(99,*) 'twk', xdt, f1, smax + close(99) + endif + + call syncjs8d(cd0,i0,ctwk,2,sync) + + j=0 + do k=1,NN + i1=ibest+(k-1)*NDOWNSPS + csymb=cmplx(0.0,0.0) + !if( i1.ge.1 .and. i1+31 .le. NP2 ) csymb=cd0(i1:i1+31) + if( i1.ge.0 .and. i1+(NDOWNSPS-1) .le. NP2-1 ) csymb=cd0(i1:i1+(NDOWNSPS-1)) + call four2a(csymb,NDOWNSPS,1,-1,1) + s2(0:7,k)=abs(csymb(1:8))/1e3 + enddo + +! sync quality check + is1=0 + is2=0 + is3=0 + do k=1,7 + ip=maxloc(s2(:,k)) + if(icos7a(k-1).eq.(ip(1)-1)) is1=is1+1 + ip=maxloc(s2(:,k+36)) + if(icos7b(k-1).eq.(ip(1)-1)) is2=is2+1 + ip=maxloc(s2(:,k+72)) + if(icos7c(k-1).eq.(ip(1)-1)) is3=is3+1 + enddo +! hard sync sum - max is 21 + nsync=is1+is2+is3 + + if(NWRITELOG.eq.1) then + open(99, file="./js8.log", status="old", position="append", action="write") + write(99,*) 'sync', ibest, nsync + close(99) + endif + + if(nsync .le. 6) then ! bail out + call timer('badnsync', 0) + nbadcrc=1 + call timer('badnsync', 1) + return + endif + + j=0 + do k=1,NN + if(k.le.7) cycle + if(k.ge.37 .and. k.le.43) cycle + if(k.gt.72) cycle + j=j+1 + s1(0:7,j)=s2(0:7,k) + enddo + + call indexx(s1sort,8*ND,indxs1) + xmeds1=s1sort(indxs1(nint(0.5*8*ND))) + s1=s1/xmeds1 + + do j=1,ND + i4=3*j-2 + i2=3*j-1 + i1=3*j +! Max amplitude + ps=s1(0:7,j) + r1=max(ps(1),ps(3),ps(5),ps(7))-max(ps(0),ps(2),ps(4),ps(6)) + r2=max(ps(2),ps(3),ps(6),ps(7))-max(ps(0),ps(1),ps(4),ps(5)) + r4=max(ps(4),ps(5),ps(6),ps(7))-max(ps(0),ps(1),ps(2),ps(3)) + bmeta(i4)=r4 + bmeta(i2)=r2 + bmeta(i1)=r1 + bmetap(i4)=r4 + bmetap(i2)=r2 + bmetap(i1)=r1 +! Max log metric + psl=log(ps+1e-32) + r1=max(psl(1),psl(3),psl(5),psl(7))-max(psl(0),psl(2),psl(4),psl(6)) + r2=max(psl(2),psl(3),psl(6),psl(7))-max(psl(0),psl(1),psl(4),psl(5)) + r4=max(psl(4),psl(5),psl(6),psl(7))-max(psl(0),psl(1),psl(2),psl(3)) + bmetb(i4)=r4 + bmetb(i2)=r2 + bmetb(i1)=r1 + +! Metric for Cauchy noise +! r1=log(ps(1)**3+ps(3)**3+ps(5)**3+ps(7)**3)- & +! log(ps(0)**3+ps(2)**3+ps(4)**3+ps(6)**3) +! r2=log(ps(2)**3+ps(3)**3+ps(6)**3+ps(7)**3)- & +! log(ps(0)**3+ps(1)**3+ps(4)**3+ps(5)**3) +! r4=log(ps(4)**3+ps(5)**3+ps(6)**3+ps(7)**3)- & +! log(ps(0)**3+ps(1)**3+ps(2)**3+ps(3)**3) +! Metric for AWGN, no fading +! bscale=2.5 +! b0=bessi0(bscale*ps(0)) +! b1=bessi0(bscale*ps(1)) +! b2=bessi0(bscale*ps(2)) +! b3=bessi0(bscale*ps(3)) +! b4=bessi0(bscale*ps(4)) +! b5=bessi0(bscale*ps(5)) +! b6=bessi0(bscale*ps(6)) +! b7=bessi0(bscale*ps(7)) +! r1=log(b1+b3+b5+b7)-log(b0+b2+b4+b6) +! r2=log(b2+b3+b6+b7)-log(b0+b1+b4+b5) +! r4=log(b4+b5+b6+b7)-log(b0+b1+b2+b3) + + if(nQSOProgress .eq. 0 .or. nQSOProgress .eq. 5) then +! When bits 88:115 are set as ap bits, bit 115 lives in symbol 39 along +! with no-ap bits 116 and 117. Take care of metrics for bits 116 and 117. + if(j.eq.39) then ! take care of bits that live in symbol 39 + if(apsym(28).lt.0) then + bmetap(i2)=max(ps(2),ps(3))-max(ps(0),ps(1)) + bmetap(i1)=max(ps(1),ps(3))-max(ps(0),ps(2)) + else + bmetap(i2)=max(ps(6),ps(7))-max(ps(4),ps(5)) + bmetap(i1)=max(ps(5),ps(7))-max(ps(4),ps(6)) + endif + endif + endif + +! When bits 116:143 are set as ap bits, bit 115 lives in symbol 39 along +! with ap bits 116 and 117. Take care of metric for bit 115. + if(j.eq.39) then ! take care of bit 115 + iii=2*(apsym(29)+1)/2 + (apsym(30)+1)/2 ! known values of bits 116 & 117 + if(iii.eq.0) bmetap(i4)=ps(4)-ps(0) + if(iii.eq.1) bmetap(i4)=ps(5)-ps(1) + if(iii.eq.2) bmetap(i4)=ps(6)-ps(2) + if(iii.eq.3) bmetap(i4)=ps(7)-ps(3) + endif + +! bit 144 lives in symbol 48 and will be 1 if it is set as an ap bit. +! take care of metrics for bits 142 and 143 + if(j.eq.48) then ! bit 144 is always 1 + bmetap(i4)=max(ps(5),ps(7))-max(ps(1),ps(3)) + bmetap(i2)=max(ps(3),ps(7))-max(ps(1),ps(5)) + endif + +! bit 154 lives in symbol 52 and will be 0 if it is set as an ap bit +! take care of metrics for bits 155 and 156 + if(j.eq.52) then ! bit 154 will be 0 if it is set as an ap bit. + bmetap(i2)=max(ps(2),ps(3))-max(ps(0),ps(1)) + bmetap(i1)=max(ps(1),ps(3))-max(ps(0),ps(2)) + endif + + enddo + + call normalizebmet(bmeta,3*ND) + call normalizebmet(bmetb,3*ND) + call normalizebmet(bmetap,3*ND) + + scalefac=2.83 + llr0=scalefac*bmeta + llr1=scalefac*bmetb + llra=scalefac*bmetap ! llr's for use with ap + apmag=scalefac*(maxval(abs(bmetap))*1.01) + +! pass # +!------------------------------ +! 1 regular decoding +! 2 erase 24 +! 3 erase 48 +! 4 ap pass 1 +! 5 ap pass 2 +! 6 ap pass 3 +! 7 ap pass 4, etc. + + !if(lapon) then + ! if(.not.lapcqonly) then + ! npasses=4+nappasses(nQSOProgress) + ! else + ! npasses=5 + ! endif + !else + npasses=4 + !endif + + do ipass=1,npasses + + llr=llr0 + if(ipass.eq.2) llr=llr1 + if(ipass.eq.3) llr(1:24)=0. + if(ipass.eq.4) llr(1:48)=0. + if(ipass.le.4) then + apmask=0 + llrap=llr + iaptype=0 + endif + + !if(ipass .gt. 4) then + ! if(.not.lapcqonly) then + ! iaptype=naptypes(nQSOProgress,ipass-4) + ! else + ! iaptype=1 + ! endif + ! if(iaptype.ge.3 .and. (abs(f1-nfqso).gt.napwid .and. abs(f1-nftx).gt.napwid) ) cycle + ! if(iaptype.eq.1 .or. iaptype.eq.2 ) then ! AP,???,??? + ! apmask=0 + ! apmask(88:115)=1 ! first 28 bits are AP + ! apmask(144)=1 ! not free text + ! llrap=llr + ! if(iaptype.eq.1) llrap(88:115)=apmag*mcq + ! if(iaptype.eq.2) llrap(88:115)=apmag*apsym(1:28) + ! llrap(116:117)=llra(116:117) + ! llrap(142:143)=llra(142:143) + ! llrap(144)=-apmag + ! endif + ! if(iaptype.eq.3) then ! mycall, dxcall, ??? + ! apmask=0 + ! apmask(88:115)=1 ! mycall + ! apmask(116:143)=1 ! hiscall + ! apmask(144)=1 ! not free text + ! llrap=llr + ! llrap(88:143)=apmag*apsym(1:56) + ! llrap(144)=-apmag + ! endif + ! if(iaptype.eq.4 .or. iaptype.eq.5 .or. iaptype.eq.6) then + ! apmask=0 + ! apmask(88:115)=1 ! mycall + ! apmask(116:143)=1 ! hiscall + ! apmask(144:159)=1 ! RRR or 73 or RR73 + ! llrap=llr + ! llrap(88:143)=apmag*apsym(1:56) + ! if(iaptype.eq.4) llrap(144:159)=apmag*mrrr + ! if(iaptype.eq.5) llrap(144:159)=apmag*m73 + ! if(iaptype.eq.6) llrap(144:159)=apmag*mrr73 + ! endif + ! if(iaptype.eq.7) then ! ???, dxcall, ??? + ! apmask=0 + ! apmask(116:143)=1 ! hiscall + ! apmask(144)=1 ! not free text + ! llrap=llr + ! llrap(115)=llra(115) + ! llrap(116:143)=apmag*apsym(29:56) + ! llrap(144)=-apmag + ! endif + !endif + + cw=0 + call timer('bpd174 ',0) + call bpdecode174(llrap,apmask,max_iterations,decoded,cw,nharderrors, & + niterations) + call timer('bpd174 ',1) + + if(NWRITELOG.eq.1) then + open(99, file="./js8.log", status="old", position="append", action="write") + write(99,*) '> bpd174 ', ipass, nharderrors, dmin + close(99) + endif + + dmin=0.0 + if(ndepth.eq.3 .and. nharderrors.lt.0) then + ndeep=3 + if(abs(nfqso-f1).le.napwid .or. abs(nftx-f1).le.napwid) then + if((ipass.eq.3 .or. ipass.eq.4) .and. .not.nagain) then + ndeep=3 + else + ndeep=4 + endif + endif + if(nagain) ndeep=5 + call timer('osd174 ',0) + call osd174(llrap,apmask,ndeep,decoded,cw,nharderrors,dmin) + call timer('osd174 ',1) + endif + nbadcrc=1 + message=' ' + xsnr=-99.0 + + if(NWRITELOG.eq.1) then + open(99, file="./js8.log", status="old", position="append", action="write") + write(99,*) '> osd174', ipass, nharderrors, dmin, nharderrors + dmin, sync + close(99) + endif + + if(count(cw.eq.0).eq.174) cycle !Reject the all-zero codeword + if(nharderrors.ge.0 .and. nharderrors+dmin.lt.60.0 .and. & + .not.(sync.lt.2.0 .and. nharderrors.gt.35) .and. & + .not.(ipass.gt.2 .and. nharderrors.gt.39) .and. & + .not.(ipass.eq.4 .and. nharderrors.gt.30) & + ) then + call chkcrc12a(decoded,nbadcrc) + + if(NWRITELOG.eq.1) then + open(99, file="./js8.log", status="old", position="append", action="write") + write(99,*) '> crc', decoded + if(nbadcrc.eq.1) then + write(99,*) '> crc failed' + endif + close(99) + endif + else + nharderrors=-1 + cycle + endif + i3bit=4*decoded(73) + 2*decoded(74) + decoded(75) + + if(nbadcrc.eq.0) then + decoded0=decoded + call extractmessage174(decoded,origmsg,ncrcflag) + decoded=decoded0 + + message(1:12)=origmsg(1:12) + call genjs8(message,mygrid6,bcontest,i3bit,msgsent,msgbits,itone) + if(lsubtract) call subtractjs8(dd0,itone,f1,xdt2) + xsig=0.0 + xnoi=0.0 + do i=1,NN + xsig=xsig+s2(itone(i),i)**2 + ios=mod(itone(i)+4,7) + xnoi=xnoi+s2(ios,i)**2 + enddo + xsnr=0.001 + if(xnoi.gt.0 .and. xnoi.lt.xsig) xsnr=xsig/xnoi-1.0 + xsnr=10.0*log10(xsnr)-27.0 + xsnr2=db(xsig/xbase - 1.0) - 32.0 + if(.not.nagain) xsnr=xsnr2 + if(xsnr .lt. -24.0) xsnr=-24.0 + + msg37=origmsg//' ' + + msg37(22:22) = char(48 + i3bit) + + return + endif + enddo + + return +end subroutine js8dec diff --git a/lib/js8/ldpcsim174js8b.f90 b/lib/js8/ldpcsim174js8b.f90 new file mode 100644 index 0000000..de047d3 --- /dev/null +++ b/lib/js8/ldpcsim174js8b.f90 @@ -0,0 +1,238 @@ +program ldpcsim174js8 +! End to end test of the (174,75)/crc12 encoder and decoder. +use crc +use packjt + +include 'js8_params.f90' +include 'js8b_params.f90' + +character*22 msg,msgsent,msgreceived +character*8 arg +character*6 grid +integer*1, allocatable :: codeword(:), decoded(:), message(:) +integer*1, target:: i1Msg8BitBytes(11) +integer*1 msgbits(87) +integer*1 apmask(174), cw(174) +integer*2 checksum +integer*4 i4Msg6BitWords(13) +integer colorder(174) +integer nerrtot(174),nerrdec(174),nmpcbad(87) +logical checksumok,fsk,bpsk +real*8, allocatable :: rxdata(:) +real, allocatable :: llr(:) + +data colorder/ & + 0, 1, 2, 3, 30, 4, 5, 6, 7, 8, 9, 10, 11, 32, 12, 40, 13, 14, 15, 16,& + 17, 18, 37, 45, 29, 19, 20, 21, 41, 22, 42, 31, 33, 34, 44, 35, 47, 51, 50, 43,& + 36, 52, 63, 46, 25, 55, 27, 24, 23, 53, 39, 49, 59, 38, 48, 61, 60, 57, 28, 62,& + 56, 58, 65, 66, 26, 70, 64, 69, 68, 67, 74, 71, 54, 76, 72, 75, 78, 77, 80, 79,& + 73, 83, 84, 81, 82, 85, 86, 87, 88, 89, 90, 91, 92, 93, 94, 95, 96, 97, 98, 99,& + 100,101,102,103,104,105,106,107,108,109,110,111,112,113,114,115,116,117,118,119,& + 120,121,122,123,124,125,126,127,128,129,130,131,132,133,134,135,136,137,138,139,& + 140,141,142,143,144,145,146,147,148,149,150,151,152,153,154,155,156,157,158,159,& + 160,161,162,163,164,165,166,167,168,169,170,171,172,173/ + +nerrtot=0 +nerrdec=0 +nmpcbad=0 ! Used to collect the number of errors in the message+crc part of the codeword + +nargs=iargc() +if(nargs.ne.4) then + print*,'Usage: ldpcsim niter ndepth #trials s ' + print*,'eg: ldpcsim 10 2 1000 0.84' + print*,'belief propagation iterations: niter, ordered-statistics depth: ndepth' + print*,'If s is negative, then value is ignored and sigma is calculated from SNR.' + return +endif +call getarg(1,arg) +read(arg,*) max_iterations +call getarg(2,arg) +read(arg,*) ndepth +call getarg(3,arg) +read(arg,*) ntrials +call getarg(4,arg) +read(arg,*) s + +fsk=.false. +bpsk=.true. + +! don't count crc bits as data bits +N=174 +K=87 +! scale Eb/No for a (174,87) code +rate=real(K)/real(N) + +write(*,*) "rate: ",rate +write(*,*) "niter= ",max_iterations," s= ",s + +allocate ( codeword(N), decoded(K), message(K) ) +allocate ( rxdata(N), llr(N) ) + + msg="0123456789012" +! msg="G4WJS K9AN EN50" + call packmsg(msg,i4Msg6BitWords,itype,.false.) !Pack into 12 6-bit bytes + call unpackmsg(i4Msg6BitWords,msgsent,.false.,grid) !Unpack to get msgsent + write(*,*) "message sent ",msgsent + + i4=0 + ik=0 + im=0 + do i=1,12 + nna=i4Msg6BitWords(i) + do j=1, 6 + ik=ik+1 + i4=i4+i4+iand(1,ishft(nna,j-6)) + i4=iand(i4,255) + if(ik.eq.8) then + im=im+1 +! if(i4.gt.127) i4=i4-256 + i1Msg8BitBytes(im)=i4 + ik=0 + endif + enddo + enddo + + i1Msg8BitBytes(10:11)=0 + checksum = crc12 (c_loc (i1Msg8BitBytes), 11) + checksum = xor(checksum, 42) ! TODO: jsherer - could change the crc here +! For reference, the next 3 lines show how to check the CRC + i1Msg8BitBytes(10)=checksum/256 + i1Msg8BitBytes(11)=iand(checksum,transfer(255,0_2)) + checksumok = crc12_check(c_loc (i1Msg8BitBytes), 11) + if( checksumok ) write(*,*) 'Good checksum' + +! K=87, For now: +! msgbits(1:72) JT message bits +! msgbits(73:75) 3 free message bits (set to 0) +! msgbits(76:87) CRC12 + mbit=0 + do i=1, 9 + i1=i1Msg8BitBytes(i) + do ibit=1,8 + mbit=mbit+1 + msgbits(mbit)=iand(1,ishft(i1,ibit-8)) + enddo + enddo + msgbits(73:75)=0 ! the three extra message bits go here + i1=i1Msg8BitBytes(10) ! First 4 bits of crc12 are LSB of this byte + do ibit=1,4 + msgbits(75+ibit)=iand(1,ishft(i1,ibit-4)) + enddo + i1=i1Msg8BitBytes(11) ! Now shift in last 8 bits of the CRC + do ibit=1,8 + msgbits(79+ibit)=iand(1,ishft(i1,ibit-8)) + enddo + + write(*,*) 'message' + write(*,'(11(8i1,1x))') msgbits + + call encode174(msgbits,codeword) + call init_random_seed() +! call sgran() + + write(*,*) 'codeword' + write(*,'(22(8i1,1x))') codeword + +write(*,*) "Es/N0 SNR2500 ngood nundetected nbadcrc sigma" +do idb = 20,-10,-1 +!do idb = -3,-3,-1 + db=idb/2.0-1.0 + sigma=1/sqrt( 2*(10**(db/10.0)) ) + ngood=0 + nue=0 + nbadcrc=0 + nberr=0 + do itrial=1, ntrials +! Create a realization of a noisy received word + do i=1,N + if( bpsk ) then + rxdata(i) = 2.0*codeword(i)-1.0 + sigma*gran() + elseif( fsk ) then + if( codeword(i) .eq. 1 ) then + r1=(1.0 + sigma*gran())**2 + (sigma*gran())**2 + r2=(sigma*gran())**2 + (sigma*gran())**2 + elseif( codeword(i) .eq. 0 ) then + r2=(1.0 + sigma*gran())**2 + (sigma*gran())**2 + r1=(sigma*gran())**2 + (sigma*gran())**2 + endif +! rxdata(i)=0.35*(sqrt(r1)-sqrt(r2)) +! rxdata(i)=0.35*(exp(r1)-exp(r2)) + rxdata(i)=0.12*(log(r1)-log(r2)) + endif + enddo + nerr=0 + do i=1,N + if( rxdata(i)*(2*codeword(i)-1.0) .lt. 0 ) nerr=nerr+1 + enddo + if(nerr.ge.1) nerrtot(nerr)=nerrtot(nerr)+1 + nberr=nberr+nerr + +! Correct signal normalization is important for this decoder. + rxav=sum(rxdata)/N + rx2av=sum(rxdata*rxdata)/N + rxsig=sqrt(rx2av-rxav*rxav) + rxdata=rxdata/rxsig +! To match the metric to the channel, s should be set to the noise standard deviation. +! For now, set s to the value that optimizes decode probability near threshold. +! The s parameter can be tuned to trade a few tenth's dB of threshold for an order of +! magnitude in UER + if( s .lt. 0 ) then + ss=sigma + else + ss=s + endif + + llr=2.0*rxdata/(ss*ss) + nap=0 ! number of AP bits + llr(colorder(174-87+1:174-87+nap)+1)=5*(2.0*msgbits(1:nap)-1.0) + apmask=0 + apmask(colorder(174-87+1:174-87+nap)+1)=1 + +! max_iterations is max number of belief propagation iterations + call bpdecode174(llr, apmask, max_iterations, decoded, cw, nharderrors,niterations) + if( ndepth .ge. 0 .and. nharderrors .lt. 0 ) call osd174(llr, apmask, ndepth, decoded, cw, nharderrors, dmin) +! If the decoder finds a valid codeword, nharderrors will be .ge. 0. + if( nharderrors .ge. 0 ) then + call extractmessage174(decoded,msgreceived,ncrcflag) + if( ncrcflag .ne. 1 ) then + nbadcrc=nbadcrc+1 + endif + + nueflag=0 + nerrmpc=0 + do i=1,K ! find number of errors in message+crc part of codeword + if( msgbits(i) .ne. decoded(i) ) then + nueflag=1 + nerrmpc=nerrmpc+1 + endif + enddo + if(nerrmpc.ge.1) nmpcbad(nerrmpc)=nmpcbad(nerrmpc)+1 + if( ncrcflag .eq. 1 ) then + if( nueflag .eq. 0 ) then + ngood=ngood+1 + if(nerr.ge.1) nerrdec(nerr)=nerrdec(nerr)+1 + else if( nueflag .eq. 1 ) then + nue=nue+1; + endif + endif + endif + enddo + baud=12000.0/NSPS + snr2500=db+10.0*log10((baud/2500.0)) + pberr=real(nberr)/(real(ntrials*N)) + write(*,"(f4.1,4x,f5.1,1x,i8,1x,i8,1x,i8,8x,f5.2,8x,e10.3)") db,snr2500,ngood,nue,nbadcrc,ss,pberr + +enddo + +open(unit=23,file='nerrhisto.dat',status='unknown') +do i=1,174 + write(23,'(i4,2x,i10,i10,f10.2)') i,nerrdec(i),nerrtot(i),real(nerrdec(i))/real(nerrtot(i)+1e-10) +enddo +close(23) +open(unit=25,file='nmpcbad.dat',status='unknown') +do i=1,87 + write(25,'(i4,2x,i10)') i,nmpcbad(i) +enddo +close(25) + +end program ldpcsim174js8 diff --git a/lib/js8/ldpcsim174js8c.f90 b/lib/js8/ldpcsim174js8c.f90 new file mode 100644 index 0000000..d42070d --- /dev/null +++ b/lib/js8/ldpcsim174js8c.f90 @@ -0,0 +1,238 @@ +program ldpcsim174js8 +! End to end test of the (174,75)/crc12 encoder and decoder. +use crc +use packjt + +include 'js8_params.f90' +include 'js8c_params.f90' + +character*22 msg,msgsent,msgreceived +character*8 arg +character*6 grid +integer*1, allocatable :: codeword(:), decoded(:), message(:) +integer*1, target:: i1Msg8BitBytes(11) +integer*1 msgbits(87) +integer*1 apmask(174), cw(174) +integer*2 checksum +integer*4 i4Msg6BitWords(13) +integer colorder(174) +integer nerrtot(174),nerrdec(174),nmpcbad(87) +logical checksumok,fsk,bpsk +real*8, allocatable :: rxdata(:) +real, allocatable :: llr(:) + +data colorder/ & + 0, 1, 2, 3, 30, 4, 5, 6, 7, 8, 9, 10, 11, 32, 12, 40, 13, 14, 15, 16,& + 17, 18, 37, 45, 29, 19, 20, 21, 41, 22, 42, 31, 33, 34, 44, 35, 47, 51, 50, 43,& + 36, 52, 63, 46, 25, 55, 27, 24, 23, 53, 39, 49, 59, 38, 48, 61, 60, 57, 28, 62,& + 56, 58, 65, 66, 26, 70, 64, 69, 68, 67, 74, 71, 54, 76, 72, 75, 78, 77, 80, 79,& + 73, 83, 84, 81, 82, 85, 86, 87, 88, 89, 90, 91, 92, 93, 94, 95, 96, 97, 98, 99,& + 100,101,102,103,104,105,106,107,108,109,110,111,112,113,114,115,116,117,118,119,& + 120,121,122,123,124,125,126,127,128,129,130,131,132,133,134,135,136,137,138,139,& + 140,141,142,143,144,145,146,147,148,149,150,151,152,153,154,155,156,157,158,159,& + 160,161,162,163,164,165,166,167,168,169,170,171,172,173/ + +nerrtot=0 +nerrdec=0 +nmpcbad=0 ! Used to collect the number of errors in the message+crc part of the codeword + +nargs=iargc() +if(nargs.ne.4) then + print*,'Usage: ldpcsim niter ndepth #trials s ' + print*,'eg: ldpcsim 10 2 1000 0.84' + print*,'belief propagation iterations: niter, ordered-statistics depth: ndepth' + print*,'If s is negative, then value is ignored and sigma is calculated from SNR.' + return +endif +call getarg(1,arg) +read(arg,*) max_iterations +call getarg(2,arg) +read(arg,*) ndepth +call getarg(3,arg) +read(arg,*) ntrials +call getarg(4,arg) +read(arg,*) s + +fsk=.false. +bpsk=.true. + +! don't count crc bits as data bits +N=174 +K=87 +! scale Eb/No for a (174,87) code +rate=real(K)/real(N) + +write(*,*) "rate: ",rate +write(*,*) "niter= ",max_iterations," s= ",s + +allocate ( codeword(N), decoded(K), message(K) ) +allocate ( rxdata(N), llr(N) ) + + msg="0123456789012" +! msg="G4WJS K9AN EN50" + call packmsg(msg,i4Msg6BitWords,itype,.false.) !Pack into 12 6-bit bytes + call unpackmsg(i4Msg6BitWords,msgsent,.false.,grid) !Unpack to get msgsent + write(*,*) "message sent ",msgsent + + i4=0 + ik=0 + im=0 + do i=1,12 + nna=i4Msg6BitWords(i) + do j=1, 6 + ik=ik+1 + i4=i4+i4+iand(1,ishft(nna,j-6)) + i4=iand(i4,255) + if(ik.eq.8) then + im=im+1 +! if(i4.gt.127) i4=i4-256 + i1Msg8BitBytes(im)=i4 + ik=0 + endif + enddo + enddo + + i1Msg8BitBytes(10:11)=0 + checksum = crc12 (c_loc (i1Msg8BitBytes), 11) + checksum = xor(checksum, 42) ! TODO: jsherer - could change the crc here +! For reference, the next 3 lines show how to check the CRC + i1Msg8BitBytes(10)=checksum/256 + i1Msg8BitBytes(11)=iand(checksum,transfer(255,0_2)) + checksumok = crc12_check(c_loc (i1Msg8BitBytes), 11) + if( checksumok ) write(*,*) 'Good checksum' + +! K=87, For now: +! msgbits(1:72) JT message bits +! msgbits(73:75) 3 free message bits (set to 0) +! msgbits(76:87) CRC12 + mbit=0 + do i=1, 9 + i1=i1Msg8BitBytes(i) + do ibit=1,8 + mbit=mbit+1 + msgbits(mbit)=iand(1,ishft(i1,ibit-8)) + enddo + enddo + msgbits(73:75)=0 ! the three extra message bits go here + i1=i1Msg8BitBytes(10) ! First 4 bits of crc12 are LSB of this byte + do ibit=1,4 + msgbits(75+ibit)=iand(1,ishft(i1,ibit-4)) + enddo + i1=i1Msg8BitBytes(11) ! Now shift in last 8 bits of the CRC + do ibit=1,8 + msgbits(79+ibit)=iand(1,ishft(i1,ibit-8)) + enddo + + write(*,*) 'message' + write(*,'(11(8i1,1x))') msgbits + + call encode174(msgbits,codeword) + call init_random_seed() +! call sgran() + + write(*,*) 'codeword' + write(*,'(22(8i1,1x))') codeword + +write(*,*) "Es/N0 SNR2500 ngood nundetected nbadcrc sigma" +do idb = 20,-10,-1 +!do idb = -3,-3,-1 + db=idb/2.0-1.0 + sigma=1/sqrt( 2*(10**(db/10.0)) ) + ngood=0 + nue=0 + nbadcrc=0 + nberr=0 + do itrial=1, ntrials +! Create a realization of a noisy received word + do i=1,N + if( bpsk ) then + rxdata(i) = 2.0*codeword(i)-1.0 + sigma*gran() + elseif( fsk ) then + if( codeword(i) .eq. 1 ) then + r1=(1.0 + sigma*gran())**2 + (sigma*gran())**2 + r2=(sigma*gran())**2 + (sigma*gran())**2 + elseif( codeword(i) .eq. 0 ) then + r2=(1.0 + sigma*gran())**2 + (sigma*gran())**2 + r1=(sigma*gran())**2 + (sigma*gran())**2 + endif +! rxdata(i)=0.35*(sqrt(r1)-sqrt(r2)) +! rxdata(i)=0.35*(exp(r1)-exp(r2)) + rxdata(i)=0.12*(log(r1)-log(r2)) + endif + enddo + nerr=0 + do i=1,N + if( rxdata(i)*(2*codeword(i)-1.0) .lt. 0 ) nerr=nerr+1 + enddo + if(nerr.ge.1) nerrtot(nerr)=nerrtot(nerr)+1 + nberr=nberr+nerr + +! Correct signal normalization is important for this decoder. + rxav=sum(rxdata)/N + rx2av=sum(rxdata*rxdata)/N + rxsig=sqrt(rx2av-rxav*rxav) + rxdata=rxdata/rxsig +! To match the metric to the channel, s should be set to the noise standard deviation. +! For now, set s to the value that optimizes decode probability near threshold. +! The s parameter can be tuned to trade a few tenth's dB of threshold for an order of +! magnitude in UER + if( s .lt. 0 ) then + ss=sigma + else + ss=s + endif + + llr=2.0*rxdata/(ss*ss) + nap=0 ! number of AP bits + llr(colorder(174-87+1:174-87+nap)+1)=5*(2.0*msgbits(1:nap)-1.0) + apmask=0 + apmask(colorder(174-87+1:174-87+nap)+1)=1 + +! max_iterations is max number of belief propagation iterations + call bpdecode174(llr, apmask, max_iterations, decoded, cw, nharderrors,niterations) + if( ndepth .ge. 0 .and. nharderrors .lt. 0 ) call osd174(llr, apmask, ndepth, decoded, cw, nharderrors, dmin) +! If the decoder finds a valid codeword, nharderrors will be .ge. 0. + if( nharderrors .ge. 0 ) then + call extractmessage174(decoded,msgreceived,ncrcflag) + if( ncrcflag .ne. 1 ) then + nbadcrc=nbadcrc+1 + endif + + nueflag=0 + nerrmpc=0 + do i=1,K ! find number of errors in message+crc part of codeword + if( msgbits(i) .ne. decoded(i) ) then + nueflag=1 + nerrmpc=nerrmpc+1 + endif + enddo + if(nerrmpc.ge.1) nmpcbad(nerrmpc)=nmpcbad(nerrmpc)+1 + if( ncrcflag .eq. 1 ) then + if( nueflag .eq. 0 ) then + ngood=ngood+1 + if(nerr.ge.1) nerrdec(nerr)=nerrdec(nerr)+1 + else if( nueflag .eq. 1 ) then + nue=nue+1; + endif + endif + endif + enddo + baud=12000.0/NSPS + snr2500=db+10.0*log10((baud/2500.0)) + pberr=real(nberr)/(real(ntrials*N)) + write(*,"(f4.1,4x,f5.1,1x,i8,1x,i8,1x,i8,8x,f5.2,8x,e10.3)") db,snr2500,ngood,nue,nbadcrc,ss,pberr + +enddo + +open(unit=23,file='nerrhisto.dat',status='unknown') +do i=1,174 + write(23,'(i4,2x,i10,i10,f10.2)') i,nerrdec(i),nerrtot(i),real(nerrdec(i))/real(nerrtot(i)+1e-10) +enddo +close(23) +open(unit=25,file='nmpcbad.dat',status='unknown') +do i=1,87 + write(25,'(i4,2x,i10)') i,nmpcbad(i) +enddo +close(25) + +end program ldpcsim174js8 diff --git a/lib/js8/ldpcsim174js8d.f90 b/lib/js8/ldpcsim174js8d.f90 new file mode 100644 index 0000000..44f6a05 --- /dev/null +++ b/lib/js8/ldpcsim174js8d.f90 @@ -0,0 +1,238 @@ +program ldpcsim174js8 +! End to end test of the (174,75)/crc12 encoder and decoder. +use crc +use packjt + +include 'js8_params.f90' +include 'js8d_params.f90' + +character*22 msg,msgsent,msgreceived +character*8 arg +character*6 grid +integer*1, allocatable :: codeword(:), decoded(:), message(:) +integer*1, target:: i1Msg8BitBytes(11) +integer*1 msgbits(87) +integer*1 apmask(174), cw(174) +integer*2 checksum +integer*4 i4Msg6BitWords(13) +integer colorder(174) +integer nerrtot(174),nerrdec(174),nmpcbad(87) +logical checksumok,fsk,bpsk +real*8, allocatable :: rxdata(:) +real, allocatable :: llr(:) + +data colorder/ & + 0, 1, 2, 3, 30, 4, 5, 6, 7, 8, 9, 10, 11, 32, 12, 40, 13, 14, 15, 16,& + 17, 18, 37, 45, 29, 19, 20, 21, 41, 22, 42, 31, 33, 34, 44, 35, 47, 51, 50, 43,& + 36, 52, 63, 46, 25, 55, 27, 24, 23, 53, 39, 49, 59, 38, 48, 61, 60, 57, 28, 62,& + 56, 58, 65, 66, 26, 70, 64, 69, 68, 67, 74, 71, 54, 76, 72, 75, 78, 77, 80, 79,& + 73, 83, 84, 81, 82, 85, 86, 87, 88, 89, 90, 91, 92, 93, 94, 95, 96, 97, 98, 99,& + 100,101,102,103,104,105,106,107,108,109,110,111,112,113,114,115,116,117,118,119,& + 120,121,122,123,124,125,126,127,128,129,130,131,132,133,134,135,136,137,138,139,& + 140,141,142,143,144,145,146,147,148,149,150,151,152,153,154,155,156,157,158,159,& + 160,161,162,163,164,165,166,167,168,169,170,171,172,173/ + +nerrtot=0 +nerrdec=0 +nmpcbad=0 ! Used to collect the number of errors in the message+crc part of the codeword + +nargs=iargc() +if(nargs.ne.4) then + print*,'Usage: ldpcsim niter ndepth #trials s ' + print*,'eg: ldpcsim 10 2 1000 0.84' + print*,'belief propagation iterations: niter, ordered-statistics depth: ndepth' + print*,'If s is negative, then value is ignored and sigma is calculated from SNR.' + return +endif +call getarg(1,arg) +read(arg,*) max_iterations +call getarg(2,arg) +read(arg,*) ndepth +call getarg(3,arg) +read(arg,*) ntrials +call getarg(4,arg) +read(arg,*) s + +fsk=.false. +bpsk=.true. + +! don't count crc bits as data bits +N=174 +K=87 +! scale Eb/No for a (174,87) code +rate=real(K)/real(N) + +write(*,*) "rate: ",rate +write(*,*) "niter= ",max_iterations," s= ",s + +allocate ( codeword(N), decoded(K), message(K) ) +allocate ( rxdata(N), llr(N) ) + + msg="0123456789012" +! msg="G4WJS K9AN EN50" + call packmsg(msg,i4Msg6BitWords,itype,.false.) !Pack into 12 6-bit bytes + call unpackmsg(i4Msg6BitWords,msgsent,.false.,grid) !Unpack to get msgsent + write(*,*) "message sent ",msgsent + + i4=0 + ik=0 + im=0 + do i=1,12 + nna=i4Msg6BitWords(i) + do j=1, 6 + ik=ik+1 + i4=i4+i4+iand(1,ishft(nna,j-6)) + i4=iand(i4,255) + if(ik.eq.8) then + im=im+1 +! if(i4.gt.127) i4=i4-256 + i1Msg8BitBytes(im)=i4 + ik=0 + endif + enddo + enddo + + i1Msg8BitBytes(10:11)=0 + checksum = crc12 (c_loc (i1Msg8BitBytes), 11) + checksum = xor(checksum, 42) ! TODO: jsherer - could change the crc here +! For reference, the next 3 lines show how to check the CRC + i1Msg8BitBytes(10)=checksum/256 + i1Msg8BitBytes(11)=iand(checksum,transfer(255,0_2)) + checksumok = crc12_check(c_loc (i1Msg8BitBytes), 11) + if( checksumok ) write(*,*) 'Good checksum' + +! K=87, For now: +! msgbits(1:72) JT message bits +! msgbits(73:75) 3 free message bits (set to 0) +! msgbits(76:87) CRC12 + mbit=0 + do i=1, 9 + i1=i1Msg8BitBytes(i) + do ibit=1,8 + mbit=mbit+1 + msgbits(mbit)=iand(1,ishft(i1,ibit-8)) + enddo + enddo + msgbits(73:75)=0 ! the three extra message bits go here + i1=i1Msg8BitBytes(10) ! First 4 bits of crc12 are LSB of this byte + do ibit=1,4 + msgbits(75+ibit)=iand(1,ishft(i1,ibit-4)) + enddo + i1=i1Msg8BitBytes(11) ! Now shift in last 8 bits of the CRC + do ibit=1,8 + msgbits(79+ibit)=iand(1,ishft(i1,ibit-8)) + enddo + + write(*,*) 'message' + write(*,'(11(8i1,1x))') msgbits + + call encode174(msgbits,codeword) + call init_random_seed() +! call sgran() + + write(*,*) 'codeword' + write(*,'(22(8i1,1x))') codeword + +write(*,*) "Es/N0 SNR2500 ngood nundetected nbadcrc sigma" +do idb = 20,-10,-1 +!do idb = -3,-3,-1 + db=idb/2.0-1.0 + sigma=1/sqrt( 2*(10**(db/10.0)) ) + ngood=0 + nue=0 + nbadcrc=0 + nberr=0 + do itrial=1, ntrials +! Create a realization of a noisy received word + do i=1,N + if( bpsk ) then + rxdata(i) = 2.0*codeword(i)-1.0 + sigma*gran() + elseif( fsk ) then + if( codeword(i) .eq. 1 ) then + r1=(1.0 + sigma*gran())**2 + (sigma*gran())**2 + r2=(sigma*gran())**2 + (sigma*gran())**2 + elseif( codeword(i) .eq. 0 ) then + r2=(1.0 + sigma*gran())**2 + (sigma*gran())**2 + r1=(sigma*gran())**2 + (sigma*gran())**2 + endif +! rxdata(i)=0.35*(sqrt(r1)-sqrt(r2)) +! rxdata(i)=0.35*(exp(r1)-exp(r2)) + rxdata(i)=0.12*(log(r1)-log(r2)) + endif + enddo + nerr=0 + do i=1,N + if( rxdata(i)*(2*codeword(i)-1.0) .lt. 0 ) nerr=nerr+1 + enddo + if(nerr.ge.1) nerrtot(nerr)=nerrtot(nerr)+1 + nberr=nberr+nerr + +! Correct signal normalization is important for this decoder. + rxav=sum(rxdata)/N + rx2av=sum(rxdata*rxdata)/N + rxsig=sqrt(rx2av-rxav*rxav) + rxdata=rxdata/rxsig +! To match the metric to the channel, s should be set to the noise standard deviation. +! For now, set s to the value that optimizes decode probability near threshold. +! The s parameter can be tuned to trade a few tenth's dB of threshold for an order of +! magnitude in UER + if( s .lt. 0 ) then + ss=sigma + else + ss=s + endif + + llr=2.0*rxdata/(ss*ss) + nap=0 ! number of AP bits + llr(colorder(174-87+1:174-87+nap)+1)=5*(2.0*msgbits(1:nap)-1.0) + apmask=0 + apmask(colorder(174-87+1:174-87+nap)+1)=1 + +! max_iterations is max number of belief propagation iterations + call bpdecode174(llr, apmask, max_iterations, decoded, cw, nharderrors,niterations) + if( ndepth .ge. 0 .and. nharderrors .lt. 0 ) call osd174(llr, apmask, ndepth, decoded, cw, nharderrors, dmin) +! If the decoder finds a valid codeword, nharderrors will be .ge. 0. + if( nharderrors .ge. 0 ) then + call extractmessage174(decoded,msgreceived,ncrcflag) + if( ncrcflag .ne. 1 ) then + nbadcrc=nbadcrc+1 + endif + + nueflag=0 + nerrmpc=0 + do i=1,K ! find number of errors in message+crc part of codeword + if( msgbits(i) .ne. decoded(i) ) then + nueflag=1 + nerrmpc=nerrmpc+1 + endif + enddo + if(nerrmpc.ge.1) nmpcbad(nerrmpc)=nmpcbad(nerrmpc)+1 + if( ncrcflag .eq. 1 ) then + if( nueflag .eq. 0 ) then + ngood=ngood+1 + if(nerr.ge.1) nerrdec(nerr)=nerrdec(nerr)+1 + else if( nueflag .eq. 1 ) then + nue=nue+1; + endif + endif + endif + enddo + baud=12000.0/NSPS + snr2500=db+10.0*log10((baud/2500.0)) + pberr=real(nberr)/(real(ntrials*N)) + write(*,"(f4.1,4x,f5.1,1x,i8,1x,i8,1x,i8,8x,f5.2,8x,e10.3)") db,snr2500,ngood,nue,nbadcrc,ss,pberr + +enddo + +open(unit=23,file='nerrhisto.dat',status='unknown') +do i=1,174 + write(23,'(i4,2x,i10,i10,f10.2)') i,nerrdec(i),nerrtot(i),real(nerrdec(i))/real(nerrtot(i)+1e-10) +enddo +close(23) +open(unit=25,file='nmpcbad.dat',status='unknown') +do i=1,87 + write(25,'(i4,2x,i10)') i,nmpcbad(i) +enddo +close(25) + +end program ldpcsim174js8 diff --git a/lib/js8/subtractjs8.f90 b/lib/js8/subtractjs8.f90 new file mode 100644 index 0000000..c5689c5 --- /dev/null +++ b/lib/js8/subtractjs8.f90 @@ -0,0 +1,64 @@ +subroutine subtractjs8(dd,itone,f0,dt) + +! Subtract an ft8 signal +! +! Measured signal : dd(t) = a(t)cos(2*pi*f0*t+theta(t)) +! Reference signal : cref(t) = exp( j*(2*pi*f0*t+phi(t)) ) +! Complex amp : cfilt(t) = LPF[ dd(t)*CONJG(cref(t)) ] +! Subtract : dd(t) = dd(t) - 2*REAL{cref*cfilt} + + use timer_module, only: timer + + !include 'js8_params.f90' + + parameter (NFRAME=NSPS*NN) + parameter (NFFT=NMAX, NFILT=1400) + + real*4 dd(NMAX), window(-NFILT/2:NFILT/2) + complex cref,camp,cfilt,cw + integer itone(NN) + logical first + data first/.true./ + common/heap8/cref(NFRAME),camp(NMAX),cfilt(NMAX),cw(NMAX) + save first + + nstart=dt*12000+1 + call genjs8refsig(itone,cref,f0) + camp=0. + do i=1,nframe + id=nstart-1+i + if(id.ge.1.and.id.le.NMAX) camp(i)=dd(id)*conjg(cref(i)) + enddo + + if(first) then +! Create and normalize the filter + pi=4.0*atan(1.0) + fac=1.0/float(nfft) + sum=0.0 + do j=-NFILT/2,NFILT/2 + window(j)=cos(pi*j/NFILT)**2 + sum=sum+window(j) + enddo + cw=0. + cw(1:NFILT+1)=window/sum + cw=cshift(cw,NFILT/2+1) + call four2a(cw,nfft,1,-1,1) + cw=cw*fac + first=.false. + endif + + cfilt=0.0 + cfilt(1:nframe)=camp(1:nframe) + call four2a(cfilt,nfft,1,-1,1) + cfilt(1:nfft)=cfilt(1:nfft)*cw(1:nfft) + call four2a(cfilt,nfft,1,1,1) + +! Subtract the reconstructed signal + do i=1,nframe + j=nstart+i-1 + if(j.ge.1 .and. j.le.NMAX) dd(j)=dd(j)-2*REAL(cfilt(i)*cref(i)) + enddo + + return +end subroutine subtractjs8 + diff --git a/lib/js8/syncjs8.f90 b/lib/js8/syncjs8.f90 new file mode 100644 index 0000000..f4008bd --- /dev/null +++ b/lib/js8/syncjs8.f90 @@ -0,0 +1,183 @@ +subroutine syncjs8(dd,nfa,nfb,syncmin,nfqso,s,candidate,ncand,sbase) + + !include 'js8_params.f90' + + complex cx(0:NH1) + real s(NH1,NHSYM) + real savg(NH1) + real sbase(NH1) + real x(NFFT1) + real sync2d(NH1,-JZ:JZ) + real red(NH1) + real candidate0(3,200) + real candidate(3,200) + real dd(NMAX) + integer jpeak(NH1) + integer indx(NH1) + integer ii(1) + integer syoff !symbol offset + equivalence (x,cx) + + integer icos7a(0:6), icos7b(0:6), icos7c(0:6) + if(NCOSTAS.eq.1) then + icos7a = (/4,2,5,6,1,3,0/) !Beginning Costas 7x7 tone pattern + icos7b = (/4,2,5,6,1,3,0/) !Middle Costas 7x7 tone pattern + icos7c = (/4,2,5,6,1,3,0/) !End Costas 7x7 tone pattern + else + icos7a = (/0,6,2,3,5,4,1/) !Beginning Costas 7x7 tone pattern + icos7b = (/1,5,0,2,3,6,4/) !Middle Costas 7x7 tone pattern + icos7c = (/2,5,0,6,4,1,3/) !End Costas 7x7 tone pattern + endif + +! Compute symbol spectra, stepping by NSTEP steps. + savg=0. + tstep=NSTEP/12000.0 + df=12000.0/NFFT1 + fac=1.0/300.0 + do j=1,NHSYM + ia=(j-1)*NSTEP + 1 + ib=ia+NSPS-1 + x(1:NSPS)=fac*dd(ia:ib) + x(NSPS+1:)=0. + call four2a(x,NFFT1,1,-1,0) !r2c FFT + do i=1,NH1 + s(i,j)=real(cx(i))**2 + aimag(cx(i))**2 + enddo + savg=savg + s(1:NH1,j) !Average spectrum + enddo + call baselinejs8(savg,nfa,nfb,sbase) + + ia=max(1,nint(nfa/df)) ! min freq + ib=nint(nfb/df) ! max freq + nssy=NSPS/NSTEP ! steps per symbol + nfos=NFFT1/NSPS ! frequency bin oversampling factor + jstrt=ASTART/tstep ! the symbol step that we are starting at (NHSYM) + + candidate0=0. + k=0 + + do i=ia,ib + do j=-JZ,+JZ + ta=0. + tb=0. + tc=0. + t0a=0. + t0b=0. + t0c=0. + do n=0,6 + k=j+jstrt+nssy*n + + syoff=k + if(syoff.ge.1.and.syoff.le.NHSYM) then + ta=ta + s(i+nfos*icos7a(n),syoff) + t0a=t0a + sum(s(i:i+nfos*6:nfos,syoff)) + endif + + syoff=k+nssy*36 + if(syoff.ge.1.and.syoff.le.NHSYM) then + tb=tb + s(i+nfos*icos7b(n),syoff) + t0b=t0b + sum(s(i:i+nfos*6:nfos,syoff)) + endif + + syoff=k+nssy*72 + if(syoff.ge.1.and.syoff.le.NHSYM) then + tc=tc + s(i+nfos*icos7c(n),syoff) + t0c=t0c + sum(s(i:i+nfos*6:nfos,syoff)) + endif + enddo + + t=ta+tb+tc + t0=t0a+t0b+t0c + t0=(t0-t)/6.0 + sync_abc=t/t0 + + t=ta+tb + t0=t0a+t0b + t0=(t0-t)/6.0 + sync_ab=t/t0 + + t=ta+tc + t0=t0a+t0c + t0=(t0-t)/6.0 + sync_ac=t/t0 + + t=tb+tc + t0=t0b+t0c + t0=(t0-t)/6.0 + sync_bc=t/t0 + + !sync2d(i,j)=max(max(max(sync_abc, sync_ab), sync_ac), sync_bc) + sync2d(i,j)=max(sync_abc, sync_ab, sync_bc) + enddo + enddo + + red=0. + do i=ia,ib + ii=maxloc(sync2d(i,-JZ:JZ)) - 1 - JZ + j0=ii(1) + jpeak(i)=j0 + red(i)=sync2d(i,j0) + enddo + + iz=ib-ia+1 + call indexx(red(ia:ib),iz,indx) + + ibase=indx(nint(0.40*iz)) - 1 + ia + if(ibase.lt.1) ibase=1 + if(ibase.gt.nh1) ibase=nh1 + base=red(ibase) + red=red/base + + k=0 + do i=1,min(200,iz) + if(k.ge.200) exit + n=ia + indx(iz+1-i) - 1 + if(red(n).lt.syncmin.or.isnan(red(n))) exit + if(NWRITELOG.eq.1) then + open(99, file="./js8.log", status="old", position="append", action="write") + write(99,*) 'red candidate', red(n), n*df, (jpeak(n)-1)*tstep + close(99) + endif + k=k+1 + candidate0(1,k)=n*df + candidate0(2,k)=(jpeak(n)-1)*tstep + candidate0(3,k)=red(n) + enddo + ncand=k + +! Put nfqso at top of list, and save only the best of near-dupe freqs. + do i=1,ncand + if(abs(candidate0(1,i)-nfqso).lt.10.0) candidate0(1,i)=-candidate0(1,i) + if(i.ge.2) then + do j=1,i-1 + fdiff=abs(candidate0(1,i))-abs(candidate0(1,j)) + if(abs(fdiff).lt.AZ) then ! note: this dedupe difference is dependent on symbol spacing + if(candidate0(3,i).ge.candidate0(3,j)) candidate0(3,j)=0. + if(candidate0(3,i).lt.candidate0(3,j)) candidate0(3,i)=0. + endif + enddo + endif + enddo + + fac=20.0/maxval(s) + s=fac*s + +! Sort by sync +! call indexx(candidate0(3,1:ncand),ncand,indx) +! Sort by frequency + call indexx(candidate0(1,1:ncand),ncand,indx) + k=1 +! do i=ncand,1,-1 + do i=1,ncand + j=indx(i) +! if( candidate0(3,j) .ge. syncmin .and. candidate0(2,j).ge.-1.5 ) then + if( candidate0(3,j) .ge. syncmin ) then + candidate(1,k)=abs(candidate0(1,j)) + candidate(2,k)=candidate0(2,j) + candidate(3,k)=candidate0(3,j) + k=k+1 + endif + enddo + ncand=k-1 + return +end subroutine syncjs8 diff --git a/lib/js8/syncjs8d.f90 b/lib/js8/syncjs8d.f90 new file mode 100644 index 0000000..532e704 --- /dev/null +++ b/lib/js8/syncjs8d.f90 @@ -0,0 +1,89 @@ +subroutine syncjs8d(cd0,i0,ctwk,itwk,sync) +! Compute sync power for a complex, downsampled FT8 signal. + + !include 'js8_params.f90' + + parameter(NP=NMAX/NDOWN,NSS=NSPS/NDOWN) + complex cd0(0:NP-1) + complex csynca(4*NSS),csyncb(4*NSS),csyncc(4*NSS) + complex csync2(4*NSS) + complex ctwk(4*NSS) + complex z1,z2,z3 + logical first + data first/.true./ + save first,twopi,csynca,csyncb,csyncc + + p(z1)=(real(z1)**2 + aimag(z1)**2) !Statement function for power + + integer icos7a(0:6), icos7b(0:6), icos7c(0:6) + if(NCOSTAS.eq.1) then + icos7a = (/4,2,5,6,1,3,0/) !Beginning Costas 7x7 tone pattern + icos7b = (/4,2,5,6,1,3,0/) !Middle Costas 7x7 tone pattern + icos7c = (/4,2,5,6,1,3,0/) !End Costas 7x7 tone pattern + else + icos7a = (/0,6,2,3,5,4,1/) !Beginning Costas 7x7 tone pattern + icos7b = (/1,5,0,2,3,6,4/) !Middle Costas 7x7 tone pattern + icos7c = (/2,5,0,6,4,1,3/) !End Costas 7x7 tone pattern + endif + +! Set some constants and compute the csync array. + if( first ) then + twopi=8.0*atan(1.0) + + k=1 + phia=0.0 + phib=0.0 + phic=0.0 + + !fs2=12000.0/NDOWN !Sample rate after downsampling + !dt2=1/fs2 !Corresponding sample interval + !taus=NDOWNSPS*dt2 !Symbol duration + !baud=1.0/taus !Keying rate + + do i=0,6 + + dphia=2*twopi*icos7a(i)/real(NSS) + dphib=2*twopi*icos7b(i)/real(NSS) + dphic=2*twopi*icos7c(i)/real(NSS) + + do j=1,NSS/2 + + csynca(k)=cmplx(cos(phia),sin(phia)) !Waveform for Beginning 7x7 Costas array + csyncb(k)=cmplx(cos(phib),sin(phib)) !Waveform for Middle 7x7 Costas array + csyncc(k)=cmplx(cos(phic),sin(phic)) !Waveform for End 7x7 Costas array + phia=mod(phia+dphia,twopi) + phib=mod(phib+dphib,twopi) + phic=mod(phia+dphic,twopi) + + k=k+1 + + enddo + + enddo + first=.false. + endif + + i1=i0 !four Costas arrays + i2=i0+36*NSS + i3=i0+72*NSS + + z1=0. + z2=0. + z3=0. + + csync2=csynca + if(itwk.eq.1) csync2=ctwk*csynca !Tweak the frequency + if(i1.ge.0 .and. i1+8*NSS-1.le.NP-1) z1=sum(cd0(i1:i1+8*NSS-1:2)*conjg(csync2)) + + csync2=csyncb + if(itwk.eq.1) csync2=ctwk*csyncb !Tweak the frequency + if(i2.ge.0 .and. i2+8*NSS-1.le.NP-1) z2=sum(cd0(i2:i2+8*NSS-1:2)*conjg(csync2)) + + csync2=csyncc + if(itwk.eq.1) csync2=ctwk*csyncc !Tweak the frequency + if(i3.ge.0 .and. i3+8*NSS-1.le.NP-1) z3=sum(cd0(i3:i3+8*NSS-1:2)*conjg(csync2)) + + sync = p(z1) + p(z2) + p(z3) + + return +end subroutine syncjs8d diff --git a/lib/js8b_decode.f90 b/lib/js8b_decode.f90 new file mode 100644 index 0000000..22361b7 --- /dev/null +++ b/lib/js8b_decode.f90 @@ -0,0 +1,157 @@ +module js8b_decode + + type :: js8b_decoder + procedure(js8b_decode_callback), pointer :: callback + contains + procedure :: decode + end type js8b_decoder + + abstract interface + subroutine js8b_decode_callback (this,sync,snr,dt,freq,decoded,nap,qual) + import js8b_decoder + implicit none + class(js8b_decoder), intent(inout) :: this + real, intent(in) :: sync + integer, intent(in) :: snr + real, intent(in) :: dt + real, intent(in) :: freq + character(len=37), intent(in) :: decoded + integer, intent(in) :: nap + real, intent(in) :: qual + end subroutine js8b_decode_callback + end interface + +contains + + subroutine decode(this,callback,iwave,nQSOProgress,nfqso,nftx,newdat, & + nutc,nfa,nfb,nexp_decode,ndepth,nagain,lft8apon,lapcqonly,napwid, & + mycall12,mygrid6,hiscall12,hisgrid6) +! use wavhdr + use timer_module, only: timer +! type(hdr) h + use js8b_module + + class(js8b_decoder), intent(inout) :: this + procedure(js8b_decode_callback) :: callback + real s(NH1,NHSYM) + real sbase(NH1) + real candidate(3,200) + real dd(NMAX) + logical, intent(in) :: lft8apon,lapcqonly,nagain + logical newdat,lsubtract,ldupe,bcontest + character*12 mycall12, hiscall12 + character*6 mygrid6,hisgrid6 + integer*2 iwave(NMAX) + integer apsym(KK) + character datetime*13,message*22,msg37*37 + character*22 allmessages(100) + integer allsnrs(100) + save s,dd + + bcontest=iand(nexp_decode,128).ne.0 + this%callback => callback + write(datetime,1001) nutc !### TEMPORARY ### +1001 format("000000_",i6.6) + + call ft8apset(mycall12,mygrid6,hiscall12,hisgrid6,bcontest,apsym,iaptype) + + dd=iwave + ndecodes=0 + allmessages=' ' + allsnrs=0 + ifa=nfa + ifb=nfb + if(nagain) then + ifa=nfqso-10 + ifb=nfqso+10 + endif + +! For now: +! ndepth=1: no subtraction, 1 pass, belief propagation only +! ndepth=2: subtraction, 3 passes, belief propagation only +! ndepth=3: subtraction, 3 passes, bp+osd + if(ndepth.eq.1) npass=1 + if(ndepth.ge.2) npass=3 + do ipass=1,npass + newdat=.true. ! Is this a problem? I hijacked newdat. + syncmin=ASYNCMIN + if(ipass.eq.1) then + lsubtract=.true. + if(ndepth.eq.1) lsubtract=.false. + elseif(ipass.eq.2) then + n2=ndecodes + if(ndecodes.eq.0) cycle + lsubtract=.true. + elseif(ipass.eq.3) then + if((ndecodes-n2).eq.0) cycle + lsubtract=.false. + endif + + call timer('syncjs8 ',0) + call syncjs8(dd,ifa,ifb,syncmin,nfqso,s,candidate,ncand,sbase) + call timer('syncjs8 ',1) + + if(NWRITELOG.eq.1) then + open(99, file="./js8.log", status="old", position="append", action="write") + write(99,*) ncand, "candidates" + write(99,*) "---" + close(99) + endif + + do icand=1,ncand + sync=candidate(3,icand) + f1=candidate(1,icand) + xdt=candidate(2,icand) + xbase=10.0**(0.1*(sbase(nint(f1/(12000.0/NFFT1)))-40.0)) ! 3.125Hz + nsnr0=min(99,nint(10.0*log10(sync) - 25.5)) !### empirical ### + + if(NWRITELOG.eq.1) then + open(99, file="./js8.log", status="old", position="append", action="write") + write(99,*) 'icand', icand, f1, sync, xdt, xbase + close(99) + endif + + call timer('js8dec ',0) + call js8dec(dd,newdat,nQSOProgress,nfqso,nftx,ndepth,lft8apon, & + lapcqonly,napwid,lsubtract,nagain,iaptype,mycall12,mygrid6, & + hiscall12,bcontest,sync,f1,xdt,xbase,apsym,nharderrors,dmin, & + nbadcrc,iappass,iera,msg37,xsnr) + message=msg37(1:22) !### + nsnr=nint(xsnr) + xdt=xdt-ASTART + hd=nharderrors+dmin + + if(NWRITELOG.eq.1) then + open(99, file="./js8.log", status="old", position="append", action="write") + write(99,*) 'icand', icand, hd, nbadcrc + close(99) + endif + + call timer('js8dec ',1) + if(nbadcrc.eq.0) then + ldupe=.false. + do id=1,ndecodes + if(message.eq.allmessages(id).and.nsnr.le.allsnrs(id)) ldupe=.true. + enddo + if(.not.ldupe) then + ndecodes=ndecodes+1 + allmessages(ndecodes)=message + allsnrs(ndecodes)=nsnr + endif + if(.not.ldupe .and. associated(this%callback)) then + qual=1.0-(nharderrors+dmin)/60.0 ! scale qual to [0.0,1.0] + call this%callback(sync,nsnr,xdt,f1,msg37,iaptype,qual) + endif + endif + + if(NWRITELOG.eq.1) then + open(99, file="./js8.log", status="old", position="append", action="write") + write(99,*) '---' + close(99) + endif + enddo + enddo + return + end subroutine decode + +end module js8b_decode diff --git a/lib/js8b_module.f90 b/lib/js8b_module.f90 new file mode 100644 index 0000000..8e099c2 --- /dev/null +++ b/lib/js8b_module.f90 @@ -0,0 +1,13 @@ +module js8b_module + include 'js8/js8_params.f90' + include 'js8/js8b_params.f90' + +contains + include 'js8/baselinejs8.f90' + include 'js8/syncjs8.f90' + include 'js8/js8_downsample.f90' + include 'js8/syncjs8d.f90' + include 'js8/genjs8refsig.f90' + include 'js8/subtractjs8.f90' + include 'js8/js8dec.f90' +end module js8b_module diff --git a/lib/js8c_decode.f90 b/lib/js8c_decode.f90 new file mode 100644 index 0000000..cdb5da8 --- /dev/null +++ b/lib/js8c_decode.f90 @@ -0,0 +1,156 @@ +module js8c_decode + + type :: js8c_decoder + procedure(js8c_decode_callback), pointer :: callback + contains + procedure :: decode + end type js8c_decoder + + abstract interface + subroutine js8c_decode_callback (this,sync,snr,dt,freq,decoded,nap,qual) + import js8c_decoder + implicit none + class(js8c_decoder), intent(inout) :: this + real, intent(in) :: sync + integer, intent(in) :: snr + real, intent(in) :: dt + real, intent(in) :: freq + character(len=37), intent(in) :: decoded + integer, intent(in) :: nap + real, intent(in) :: qual + end subroutine js8c_decode_callback + end interface + +contains + + subroutine decode(this,callback,iwave,nQSOProgress,nfqso,nftx,newdat, & + nutc,nfa,nfb,nexp_decode,ndepth,nagain,lft8apon,lapcqonly,napwid, & + mycall12,mygrid6,hiscall12,hisgrid6) +! use wavhdr + use timer_module, only: timer +! type(hdr) h + use js8c_module + + class(js8c_decoder), intent(inout) :: this + procedure(js8c_decode_callback) :: callback + real s(NH1,NHSYM) + real sbase(NH1) + real candidate(3,200) + real dd(NMAX) + logical, intent(in) :: lft8apon,lapcqonly,nagain + logical newdat,lsubtract,ldupe,bcontest + character*12 mycall12, hiscall12 + character*6 mygrid6,hisgrid6 + integer*2 iwave(NMAX) + integer apsym(KK) + character datetime*13,message*22,msg37*37 + character*22 allmessages(100) + integer allsnrs(100) + save s,dd + + bcontest=iand(nexp_decode,128).ne.0 + this%callback => callback + write(datetime,1001) nutc !### TEMPORARY ### +1001 format("000000_",i6.6) + + call ft8apset(mycall12,mygrid6,hiscall12,hisgrid6,bcontest,apsym,iaptype) + + dd=iwave + ndecodes=0 + allmessages=' ' + allsnrs=0 + ifa=nfa + ifb=nfb + if(nagain) then + ifa=nfqso-10 + ifb=nfqso+10 + endif + +! For now: +! ndepth=1: no subtraction, 1 pass, belief propagation only +! ndepth=2: subtraction, 3 passes, belief propagation only +! ndepth=3: subtraction, 3 passes, bp+osd + if(ndepth.eq.1) npass=1 + if(ndepth.ge.2) npass=3 + do ipass=1,npass + newdat=.true. ! Is this a problem? I hijacked newdat. + syncmin=ASYNCMIN + if(ipass.eq.1) then + lsubtract=.true. + if(ndepth.eq.1) lsubtract=.false. + elseif(ipass.eq.2) then + n2=ndecodes + if(ndecodes.eq.0) cycle + lsubtract=.true. + elseif(ipass.eq.3) then + if((ndecodes-n2).eq.0) cycle + lsubtract=.false. + endif + + call timer('syncjs8 ',0) + call syncjs8(dd,ifa,ifb,syncmin,nfqso,s,candidate,ncand,sbase) + call timer('syncjs8 ',1) + + if(NWRITELOG.eq.1) then + open(99, file="./js8.log", status="old", position="append", action="write") + write(99,*) ncand, "candidates" + close(99) + endif + + do icand=1,ncand + sync=candidate(3,icand) + f1=candidate(1,icand) + xdt=candidate(2,icand) + xbase=10.0**(0.1*(sbase(nint(f1/(12000.0/NFFT1)))-40.0)) ! 3.125Hz + nsnr0=min(99,nint(10.0*log10(sync) - 25.5)) !### empirical ### + + if(NWRITELOG.eq.1) then + open(99, file="./js8.log", status="old", position="append", action="write") + write(99,*) 'icand', icand, f1, sync, xdt, xbase + close(99) + endif + + call timer('js8dec ',0) + call js8dec(dd,newdat,nQSOProgress,nfqso,nftx,ndepth,lft8apon, & + lapcqonly,napwid,lsubtract,nagain,iaptype,mycall12,mygrid6, & + hiscall12,bcontest,sync,f1,xdt,xbase,apsym,nharderrors,dmin, & + nbadcrc,iappass,iera,msg37,xsnr) + message=msg37(1:22) !### + nsnr=nint(xsnr) + xdt=xdt-ASTART + hd=nharderrors+dmin + + if(NWRITELOG.eq.1) then + open(99, file="./js8.log", status="old", position="append", action="write") + write(99,*) 'icand', icand, hd, nbadcrc + close(99) + endif + + call timer('js8dec ',1) + if(nbadcrc.eq.0) then + ldupe=.false. + do id=1,ndecodes + if(message.eq.allmessages(id).and.nsnr.le.allsnrs(id)) ldupe=.true. + enddo + if(.not.ldupe) then + ndecodes=ndecodes+1 + allmessages(ndecodes)=message + allsnrs(ndecodes)=nsnr + endif + if(.not.ldupe .and. associated(this%callback)) then + qual=1.0-(nharderrors+dmin)/60.0 ! scale qual to [0.0,1.0] + call this%callback(sync,nsnr,xdt,f1,msg37,iaptype,qual) + endif + endif + + if(NWRITELOG.eq.1) then + open(99, file="./js8.log", status="old", position="append", action="write") + write(99,*) '---' + close(99) + endif + enddo + enddo + return + end subroutine decode + +end module js8c_decode diff --git a/lib/js8c_module.f90 b/lib/js8c_module.f90 new file mode 100644 index 0000000..b5f28b9 --- /dev/null +++ b/lib/js8c_module.f90 @@ -0,0 +1,13 @@ +module js8c_module + include 'js8/js8_params.f90' + include 'js8/js8c_params.f90' + +contains + include 'js8/baselinejs8.f90' + include 'js8/syncjs8.f90' + include 'js8/js8_downsample.f90' + include 'js8/syncjs8d.f90' + include 'js8/genjs8refsig.f90' + include 'js8/subtractjs8.f90' + include 'js8/js8dec.f90' +end module js8c_module diff --git a/lib/js8d_decode.f90 b/lib/js8d_decode.f90 new file mode 100644 index 0000000..328fced --- /dev/null +++ b/lib/js8d_decode.f90 @@ -0,0 +1,156 @@ +module js8d_decode + + type :: js8d_decoder + procedure(js8d_decode_callback), pointer :: callback + contains + procedure :: decode + end type js8d_decoder + + abstract interface + subroutine js8d_decode_callback (this,sync,snr,dt,freq,decoded,nap,qual) + import js8d_decoder + implicit none + class(js8d_decoder), intent(inout) :: this + real, intent(in) :: sync + integer, intent(in) :: snr + real, intent(in) :: dt + real, intent(in) :: freq + character(len=37), intent(in) :: decoded + integer, intent(in) :: nap + real, intent(in) :: qual + end subroutine js8d_decode_callback + end interface + +contains + + subroutine decode(this,callback,iwave,nQSOProgress,nfqso,nftx,newdat, & + nutc,nfa,nfb,nexp_decode,ndepth,nagain,lft8apon,lapcqonly,napwid, & + mycall12,mygrid6,hiscall12,hisgrid6) +! use wavhdr + use timer_module, only: timer +! type(hdr) h + use js8d_module + + class(js8d_decoder), intent(inout) :: this + procedure(js8d_decode_callback) :: callback + real s(NH1,NHSYM) + real sbase(NH1) + real candidate(3,200) + real dd(NMAX) + logical, intent(in) :: lft8apon,lapcqonly,nagain + logical newdat,lsubtract,ldupe,bcontest + character*12 mycall12, hiscall12 + character*6 mygrid6,hisgrid6 + integer*2 iwave(NMAX) + integer apsym(KK) + character datetime*13,message*22,msg37*37 + character*22 allmessages(100) + integer allsnrs(100) + save s,dd + + bcontest=iand(nexp_decode,128).ne.0 + this%callback => callback + write(datetime,1001) nutc !### TEMPORARY ### +1001 format("000000_",i6.6) + + call ft8apset(mycall12,mygrid6,hiscall12,hisgrid6,bcontest,apsym,iaptype) + + dd=iwave + ndecodes=0 + allmessages=' ' + allsnrs=0 + ifa=nfa + ifb=nfb + if(nagain) then + ifa=nfqso-10 + ifb=nfqso+10 + endif + +! For now: +! ndepth=1: no subtraction, 1 pass, belief propagation only +! ndepth=2: subtraction, 3 passes, belief propagation only +! ndepth=3: subtraction, 3 passes, bp+osd + if(ndepth.eq.1) npass=1 + if(ndepth.ge.2) npass=3 + do ipass=1,npass + newdat=.true. ! Is this a problem? I hijacked newdat. + syncmin=ASYNCMIN + if(ipass.eq.1) then + lsubtract=.true. + if(ndepth.eq.1) lsubtract=.false. + elseif(ipass.eq.2) then + n2=ndecodes + if(ndecodes.eq.0) cycle + lsubtract=.true. + elseif(ipass.eq.3) then + if((ndecodes-n2).eq.0) cycle + lsubtract=.false. + endif + + call timer('syncjs8 ',0) + call syncjs8(dd,ifa,ifb,syncmin,nfqso,s,candidate,ncand,sbase) + call timer('syncjs8 ',1) + + if(NWRITELOG.eq.1) then + open(99, file="./js8.log", status="old", position="append", action="write") + write(99,*) ncand, "candidates" + close(99) + endif + + do icand=1,ncand + sync=candidate(3,icand) + f1=candidate(1,icand) + xdt=candidate(2,icand) + xbase=10.0**(0.1*(sbase(nint(f1/(12000.0/NFFT1)))-40.0)) ! 3.125Hz + nsnr0=min(99,nint(10.0*log10(sync) - 25.5)) !### empirical ### + + if(NWRITELOG.eq.1) then + open(99, file="./js8.log", status="old", position="append", action="write") + write(99,*) 'icand', icand, f1, sync, xdt, xbase + close(99) + endif + + call timer('js8dec ',0) + call js8dec(dd,newdat,nQSOProgress,nfqso,nftx,ndepth,lft8apon, & + lapcqonly,napwid,lsubtract,nagain,iaptype,mycall12,mygrid6, & + hiscall12,bcontest,sync,f1,xdt,xbase,apsym,nharderrors,dmin, & + nbadcrc,iappass,iera,msg37,xsnr) + message=msg37(1:22) !### + nsnr=nint(xsnr) + xdt=xdt-ASTART + hd=nharderrors+dmin + + if(NWRITELOG.eq.1) then + open(99, file="./js8.log", status="old", position="append", action="write") + write(99,*) 'icand', icand, hd, nbadcrc + close(99) + endif + + call timer('js8dec ',1) + if(nbadcrc.eq.0) then + ldupe=.false. + do id=1,ndecodes + if(message.eq.allmessages(id).and.nsnr.le.allsnrs(id)) ldupe=.true. + enddo + if(.not.ldupe) then + ndecodes=ndecodes+1 + allmessages(ndecodes)=message + allsnrs(ndecodes)=nsnr + endif + if(.not.ldupe .and. associated(this%callback)) then + qual=1.0-(nharderrors+dmin)/60.0 ! scale qual to [0.0,1.0] + call this%callback(sync,nsnr,xdt,f1,msg37,iaptype,qual) + endif + endif + + if(NWRITELOG.eq.1) then + open(99, file="./js8.log", status="old", position="append", action="write") + write(99,*) '---' + close(99) + endif + enddo + enddo + return + end subroutine decode + +end module js8d_decode diff --git a/lib/js8d_module.f90 b/lib/js8d_module.f90 new file mode 100644 index 0000000..315e2d7 --- /dev/null +++ b/lib/js8d_module.f90 @@ -0,0 +1,13 @@ +module js8d_module + include 'js8/js8_params.f90' + include 'js8/js8d_params.f90' + +contains + include 'js8/baselinejs8.f90' + include 'js8/syncjs8.f90' + include 'js8/js8_downsample.f90' + include 'js8/syncjs8d.f90' + include 'js8/genjs8refsig.f90' + include 'js8/subtractjs8.f90' + include 'js8/js8dec.f90' +end module js8d_module diff --git a/lib/jt4sim.f90 b/lib/jt4sim.f90 deleted file mode 100644 index 73edabf..0000000 --- a/lib/jt4sim.f90 +++ /dev/null @@ -1,181 +0,0 @@ -program jt4sim - -! Generate simulated jt4 data for testing the decoder using new fading models -! Based on qra64sim with appropriate changes for JT4 -! Includes option to generate 1000Hz single tone with "ST" as the message - - use wavhdr - use packjt - use jt4 - parameter (NMAX=60*12000) ! = 648,000 - parameter (NFFT=10*65536,NH=NFFT/2) - type(hdr) h !Header for .wav file - integer*2 iwave(NMAX) !Generated waveform - integer*4 itone(206) !Channel symbols (values 0-8) - real*4 xnoise(NMAX) !Generated random noise - real*4 dat(NMAX) !Generated real data - complex cdat(NMAX) !Generated complex waveform - complex cspread(0:NFFT-1) !Complex amplitude for Rayleigh fading - complex z - real*8 f0,dt,twopi,phi,dphi,baud,fsample,freq - character message*22,fname*11,csubmode*1,arg*12 - character msgsent*22 - - nargs=iargc() - if(nargs.ne. 7) then - print *, 'Usage: jt4sim "msg" A-E Nsigs fDop DT Nfiles SNR' - print *, 'Example jt4sim "K1ABC W9XYZ EN37" A 10 0.2 0.0 1 0' - print *, 'Example jt4sim "ST" A 10 0.2 0.0 1 0' - go to 999 - endif - call getarg(1,message) - call fmtmsg(message, iz) - call getarg(2,csubmode) - mode4=ichar(csubmode) - ichar('A') + 1 - call getarg(3,arg) - read(arg,*) nsigs - call getarg(4,arg) - read(arg,*) fspread - call getarg(5,arg) - read(arg,*) xdt - call getarg(6,arg) - read(arg,*) nfiles - call getarg(7,arg) - read(arg,*) snrdb - - if(mode4.ge.8) nsigs=1 ! temporary - will need sorting out - rms=100. - fsample=12000.d0 !Sample rate (Hz) - dt=1.d0/fsample !Sample interval (s) - twopi=8.d0*atan(1.d0) - npts=60*12000 !Total samples in .wav file - nsps=12000.d0/4.375d0 - baud=12000.d0/nsps !Keying rate = 1.7361111111 - nsym=206 !Number of channel symbols - h=default_header(12000,npts) - dfsig=2000.0/nsigs !Freq spacing between sigs in file (Hz) - ichk=0 - - write(*,1000) -1000 format('File Sig Freq A-E S/N DT Dop Message'/60('-')) - - do ifile=1,nfiles !Loop over requested number of files - write(fname,1002) ifile !Output filename -1002 format('000000_',i4.4) - open(10,file=fname//'.wav',access='stream',status='unknown') - xnoise=0. - cdat=0. - if(snrdb.lt.90) then - do i=1,npts - xnoise(i)=gran() !Generate gaussian noise - enddo - endif - - do isig=1,nsigs !Generate requested number of sigs - if(mod(nsigs,2).eq.0) f0=1500.0 + dfsig*(isig-0.5-nsigs/2) - if(mod(nsigs,2).eq.1) f0=1500.0 + dfsig*(isig-(nsigs+1)/2) - if(nsigs.eq.1) f0=1000.0 - xsnr=snrdb - if(snrdb.eq.0.0) xsnr=-20 - isig - - call gen4(message,ichk,msgsent,itone,itype) - - bandwidth_ratio=2500.0/6000.0 - sig=sqrt(2*bandwidth_ratio)*10.0**(0.05*xsnr) - if(xsnr.gt.90.0) sig=1.0 - write(*,1020) ifile,isig,f0,csubmode,xsnr,xdt,fspread,message -1020 format(i4,i4,f10.3,2x,a1,2x,f5.1,f6.2,f6.1,1x,a22) - - phi=0.d0 - dphi=0.d0 - k=(xdt+1.0)*12000 !Start audio at t = xdt + 1.0 s - isym0=-99 - - do i=1,npts !Add this signal into cdat() - isym=i/nsps + 1 - if(isym.gt.nsym) exit - if(isym.ne.isym0) then - if(message(1:2).eq.'ST') then !Finds ST in message string for single tone - freq=1000 !1000Hz for single tone - else - freq=f0 + itone(isym)*baud*nch(mode4) - endif - dphi=twopi*freq*dt - isym0=isym - - endif - phi=phi + dphi - if(phi.gt.twopi) phi=phi-twopi - xphi=phi - z=cmplx(cos(xphi),sin(xphi)) - k=k+1 - if(k.ge.1) cdat(k)=cdat(k) + sig*z - enddo - enddo - - if(fspread.ne.0) then !Apply specified Doppler spread - df=12000.0/nfft - twopi=8*atan(1.0) - cspread(0)=1.0 - cspread(NH)=0. - b=6.0 !Lorenzian 3/28 onward - do i=1,NH - f=i*df - x=b*f/fspread - z=0. - a=0. - if(x.lt.3.0) then !Cutoff beyond x=3 - a=sqrt(1.111/(1.0+x*x)-0.1) !Lorentzian - call random_number(r1) - phi1=twopi*r1 - z=a*cmplx(cos(phi1),sin(phi1)) - endif - cspread(i)=z - z=0. - if(x.lt.50.0) then - call random_number(r2) - phi2=twopi*r2 - z=a*cmplx(cos(phi2),sin(phi2)) - endif - cspread(NFFT-i)=z - enddo - - do i=0,NFFT-1 - f=i*df - if(i.gt.NH) f=(i-nfft)*df - s=real(cspread(i))**2 + aimag(cspread(i))**2 -! write(13,3000) i,f,s,cspread(i) -!3000 format(i5,f10.3,3f12.6) - enddo -! s=real(cspread(0))**2 + aimag(cspread(0))**2 -! write(13,3000) 1024,0.0,s,cspread(0) - - call four2a(cspread,NFFT,1,1,1) !Transform to time domain - - sum=0. - do i=0,NFFT-1 - p=real(cspread(i))**2 + aimag(cspread(i))**2 - sum=sum+p - enddo - avep=sum/NFFT - fac=sqrt(1.0/avep) - cspread=fac*cspread !Normalize to constant avg power - cdat(1:NFFT)=cspread*cdat(1:NFFT) !Apply Rayleigh fading - -! do i=0,NFFT-1 -! p=real(cspread(i))**2 + aimag(cspread(i))**2 -! write(14,3010) i,p,cspread(i) -!3010 format(i8,3f12.6) -! enddo - - endif - - dat=aimag(cdat) + xnoise !Add the generated noise - fac=32767.0/nsigs - if(snrdb.ge.90.0) iwave(1:npts)=nint(fac*dat(1:npts)) - if(snrdb.lt.90.0) iwave(1:npts)=nint(rms*dat(1:npts)) - write(10) h,iwave(1:npts) !Save the .wav file - close(10) - enddo - -999 end program jt4sim diff --git a/lib/msgs.txt b/lib/msgs.txt deleted file mode 100644 index c38aba9..0000000 --- a/lib/msgs.txt +++ /dev/null @@ -1,60 +0,0 @@ -W1AAA K2BBB EM00 -W2CCC K3DDD EM01 -W3EEE K4FFF EM02 -W5GGG K6HHH EM03 -W7III K8JJJ EM04 -W9KKK K0LLL EM05 -G0MMM F1NNN JN06 -G2OOO F3PPP JN07 -G4QQQ F5RRR JN08 -G6SSS F7TTT JN09 -W1XAA K2XBB EM10 -W2XCC K3XDD EM11 -W3XEE K4XFF EM12 -W5XGG K6XHH EM13 -W7XII K8XJJ EM14 -W9XKK K0XLL EM15 -G0XMM F1XNN JN16 -G2XOO F3XPP JN17 -G4XQQ F5XRR JN18 -G6XSS F7XTT JN19 -W1YAA K2YBB EM20 -W2YCC K3YDD EM21 -W3YEE K4YFF EM22 -W5YGG K6YHH EM23 -W7YII K8YJJ EM24 -W9YKK K0YLL EM25 -G0YMM F1YNN JN26 -G2YOO F3YPP JN27 -G4YQQ F5YRR JN28 -G6YSS F7YTT JN29 -W1ZAA K2ZBB EM30 -W2ZCC K3ZDD EM31 -W3ZEE K4ZFF EM32 -W5ZGG K6ZHH EM33 -W7ZII K8ZJJ EM34 -W9ZKK K0ZLL EM35 -G0ZMM F1ZNN JN36 -G2ZOO F3ZPP JN37 -G4ZQQ F5ZRR JN38 -G6ZSS F7ZTT JN39 -W1AXA K2BXB EM40 -W2CXC K3DXD EM41 -W3EXE K4FXF EM42 -W5GXG K6HXH EM43 -W7IXI K8JXJ EM44 -W9KXK K0LXL EM45 -G0MXM F1NXN JN46 -G2OXO F3PXP JN47 -G4QXQ F5RXR JN48 -G6SXS F7TXT JN49 -W1AYA K2BYB EM50 -W2CYC K3DYD EM51 -W3EYE K4FYF EM52 -W5GYG K6HYH EM53 -W7IYI K8JYJ EM54 -W9KYK K0LYL EM55 -G0MYM F1NYN JN56 -G2OYO F3PYP JN57 -G4QYQ F5RYR JN58 -G6SYS F7TYT JN59 diff --git a/lib/msk144_freq_search.f90 b/lib/msk144_freq_search.f90 deleted file mode 100644 index 5029816..0000000 --- a/lib/msk144_freq_search.f90 +++ /dev/null @@ -1,50 +0,0 @@ -subroutine msk144_freq_search(cdat,fc,if1,if2,delf,nframes,navmask,cb, & - cdat2,xmax,bestf,cs,xccs) - - parameter (NSPM=864,NZ=7*NSPM) - complex cdat(NZ) - complex cdat2(NZ) - complex c(NSPM) !Coherently averaged complex data - complex ct2(2*NSPM) - complex cs(NSPM) - complex cb(42) !Complex waveform for sync word - complex cc(0:NSPM-1) - real xcc(0:NSPM-1) - real xccs(0:NSPM-1) - integer navmask(nframes) !Tells which frames to average - - navg=sum(navmask) - n=nframes*NSPM - fac=1.0/(48.0*sqrt(float(navg))) - - do ifr=if1,if2 !Find freq that maximizes sync - ferr=ifr*delf - call tweak1(cdat,n,-(fc+ferr),cdat2) - c=0 - sumw=0. - do i=1,nframes - ib=(i-1)*NSPM+1 - ie=ib+NSPM-1 - if(navmask(i).eq.1) c=c + cdat2(ib:ie) - enddo - - cc=0 - ct2(1:NSPM)=c - ct2(NSPM+1:2*NSPM)=c - - do ish=0,NSPM-1 - cc(ish)=dot_product(ct2(1+ish:42+ish)+ct2(337+ish:378+ish),cb(1:42)) - enddo - - xcc=abs(cc) - xb=maxval(xcc)*fac - if(xb.gt.xmax) then - xmax=xb - bestf=ferr - cs=c - xccs=xcc - endif - enddo - - return -end subroutine msk144_freq_search diff --git a/lib/msk144code.f90 b/lib/msk144code.f90 deleted file mode 100644 index f49bebc..0000000 --- a/lib/msk144code.f90 +++ /dev/null @@ -1,70 +0,0 @@ -program msk144code - -! Provides examples of message packing, bit and symbol ordering, -! LDPC encoding, and other necessary details of the MSK144 protocol. - - use packjt - character msg*22,msgsent*22,decoded,bad*1,msgtype*13,mygrid*6 - integer*4 i4tone(144) - logical*1 bcontest - include 'testmsg.f90' - data mygrid/'FN20qi'/ - - nargs=iargc() - if(nargs.ne.1) then - print*,'Usage: msk144code "message"' - print*,' msk144code -t' - print*,' ' - print*,'Examples:' - print*,' msk144code "KA1ABC WB9XYZ EN37"' - print*,' msk144code " R-03"' - print*,' msk144code "KA1ABC WB9XYZ R EN37"' - go to 999 - endif - - call getarg(1,msg) - nmsg=1 - if(msg(1:2).eq."-t") then - testmsg(NTEST+1)=" -03" - testmsg(NTEST+2)=" R+03" - testmsg(NTEST+3)=" RRR" - testmsg(NTEST+4)=" 73" - testmsg(NTEST+5)="KA1ABC WB9XYZ R EN37" - nmsg=NTEST+5 - endif - - write(*,1010) -1010 format(" Message Decoded Err? Type"/ & - 74("-")) - do imsg=1,nmsg - if(nmsg.gt.1) msg=testmsg(imsg) - call fmtmsg(msg,iz) !To upper case, collapse multiple blanks - i1=len(trim(msg))-5 - bcontest=.false. - if(msg(i1:i1+1).eq.'R ') bcontest=.true. - ichk=0 - call genmsk144(msg,mygrid,ichk,bcontest,msgsent,i4tone,itype) - - msgtype="" - if(itype.eq.1) msgtype="Std Msg" - if(itype.eq.2) msgtype="Type 1 prefix" - if(itype.eq.3) msgtype="Type 1 suffix" - if(itype.eq.4) msgtype="Type 2 prefix" - if(itype.eq.5) msgtype="Type 2 suffix" - if(itype.eq.6) msgtype="Free text" - if(itype.eq.7) msgtype="Hashed calls" - - bad=" " - if(msgsent.ne.msg) bad="*" - write(*,1020) imsg,msg,msgsent,bad,itype,msgtype -1020 format(i2,'.',2x,a22,2x,a22,3x,a1,i3,": ",a13) - enddo - - if(nmsg.eq.1) then - n=144 - if(msg(1:1).eq."<") n=40 - write(*,1030) i4tone(1:n) -1030 format(/'Channel symbols'/(72i1)) - endif - -999 end program msk144code diff --git a/lib/msk144d2.f90 b/lib/msk144d2.f90 deleted file mode 100644 index 47eb43b..0000000 --- a/lib/msk144d2.f90 +++ /dev/null @@ -1,138 +0,0 @@ -program msk144d2 - - ! Test the msk144 decoder for WSJT-X - - use options - use timer_module, only: timer - use timer_impl, only: init_timer - use readwav - - character c - character*80 line - character*512 datadir - character*500 infile - character*12 mycall,hiscall - character*6 mygrid - character(len=500) optarg - - logical :: display_help=.false. - logical*1 bShMsgs - logical*1 bcontest - logical*1 btrain - logical*1 bswl - - type(wav_header) :: wav - - integer*2 id2(30*12000) - integer*2 ichunk(7*1024) - - real*8 pcoeffs(5) - - type (option) :: long_options(9) = [ & - option ('ndepth',.true.,'c','ndepth',''), & - option ('dxcall',.true.,'d','hiscall',''), & - option ('evemode',.true.,'e','Must be used with -s.',''), & - option ('frequency',.true.,'f','rxfreq',''), & - option ('help',.false.,'h','Display this help message',''), & - option ('mycall',.true.,'m','mycall',''), & - option ('nftol',.true.,'n','nftol',''), & - option ('rxequalize',.false.,'r','Rx Equalize',''), & - option ('short',.false.,'s','enable Sh','') & - ] - t0=0.0 - ndepth=3 - ntol=100 - nrxfreq=1500 - mycall='' - mygrid='EN50WC' - hiscall='' - bShMsgs=.false. - bcontest=.false. - btrain=.false. - bswl=.false. - datadir='.' - pcoeffs=0.d0 - - do - call getopt('c:d:ef:hm:n:rs',long_options,c,optarg,narglen,nstat,noffset,nremain,.true.) - if( nstat .ne. 0 ) then - exit - end if - select case (c) - case ('c') - read (optarg(:narglen), *) ndepth - case ('d') - read (optarg(:narglen), *) hiscall - case ('e') - bswl=.true. - case ('f') - read (optarg(:narglen), *) nrxfreq - case ('h') - display_help = .true. - case ('m') - read (optarg(:narglen), *) mycall - case ('n') - read (optarg(:narglen), *) ntol - case ('r') - btrain=.true. - case ('s') - bShMsgs=.true. - end select - end do - - if(display_help .or. nstat.lt.0 .or. nremain.lt.1) then - print *, '' - print *, 'Usage: msk144d [OPTIONS] file1 [file2 ...]' - print *, '' - print *, ' msk144 decode pre-recorded .WAV file(s)' - print *, '' - print *, 'OPTIONS:' - do i = 1, size (long_options) - call long_options(i) % print (6) - end do - go to 999 - endif - - call init_timer ('timer.out') - call timer('msk144 ',0) - ndecoded=0 - do ifile=noffset+1,noffset+nremain - call get_command_argument(ifile,optarg,narglen) - infile=optarg(:narglen) - call timer('read ',0) - call wav%read (infile) - i1=index(infile,'.wav') - if( i1 .eq. 0 ) i1=index(infile,'.WAV') - read(infile(i1-6:i1-1),*,err=998) nutc - inquire(FILE=infile,SIZE=isize) - npts=min((isize-216)/2,360000) - read(unit=wav%lun) id2(1:npts) - close(unit=wav%lun) - call timer('read ',1) - - do i=1,npts-7*1024+1,7*512 - ichunk=id2(i:i+7*1024-1) - tsec=(i-1)/12000.0 - tt=sum(float(abs(id2(i:i+7*512-1)))) - if( tt .ne. 0.0 ) then - call mskrtd(ichunk,nutc,tsec,ntol,nrxfreq,ndepth,mycall,mygrid,hiscall,bShMsgs, & - bcontest,btrain,pcoeffs,bswl,datadir,line) - if( index(line,"&") .ne. 0 .or. & - index(line,"^") .ne. 0 .or. & - index(line,"!") .ne. 0 .or. & - index(line,"@") .ne. 0 ) then - write(*,*) line - endif - endif - enddo - enddo - - call timer('msk144 ',1) - call timer('msk144 ',101) - go to 999 - -998 print*,'Cannot read from file:' - print*,infile - -999 continue -end program msk144d2 diff --git a/lib/msk144decodeframe.f90 b/lib/msk144decodeframe.f90 deleted file mode 100644 index 5d5e155..0000000 --- a/lib/msk144decodeframe.f90 +++ /dev/null @@ -1,107 +0,0 @@ -subroutine msk144decodeframe(c,softbits,msgreceived,nsuccess,recent_calls,nrecent) -! use timer_module, only: timer - - parameter (NSPM=864) - character*22 msgreceived - character*12 recent_calls(nrecent) - complex cb(42) - complex cfac,cca,ccb - complex c(NSPM) - integer*1 decoded(80) - integer s8(8),hardbits(144) - real*8 dt, fs, pi, twopi - real cbi(42),cbq(42) - real pp(12) - real softbits(144) - real llr(128) - logical first - data first/.true./ - data s8/0,1,1,1,0,0,1,0/ - save first,cb,fs,pi,twopi,dt,s8,pp - - if(first) then -! define half-sine pulse and raised-cosine edge window - pi=4d0*datan(1d0) - twopi=8d0*datan(1d0) - fs=12000.0 - dt=1.0/fs - - do i=1,12 - angle=(i-1)*pi/12.0 - pp(i)=sin(angle) - enddo - -! define the sync word waveforms - s8=2*s8-1 - cbq(1:6)=pp(7:12)*s8(1) - cbq(7:18)=pp*s8(3) - cbq(19:30)=pp*s8(5) - cbq(31:42)=pp*s8(7) - cbi(1:12)=pp*s8(2) - cbi(13:24)=pp*s8(4) - cbi(25:36)=pp*s8(6) - cbi(37:42)=pp(1:6)*s8(8) - cb=cmplx(cbi,cbq) - first=.false. - endif - - nsuccess=0 - msgreceived=' ' - -! Estimate carrier phase. - cca=sum(c(1:1+41)*conjg(cb)) - ccb=sum(c(1+56*6:1+56*6+41)*conjg(cb)) - cfac=ccb*conjg(cca) - phase0=atan2(imag(cca+ccb),real(cca+ccb)) - -! Remove phase error - want constellation rotated so that sample points lie on I/Q axes - cfac=cmplx(cos(phase0),sin(phase0)) - c=c*conjg(cfac) - -! matched filter - - softbits(1)=sum(imag(c(1:6))*pp(7:12))+sum(imag(c(864-5:864))*pp(1:6)) - softbits(2)=sum(real(c(1:12))*pp) - do i=2,72 - softbits(2*i-1)=sum(imag(c(1+(i-1)*12-6:1+(i-1)*12+5))*pp) - softbits(2*i)=sum(real(c(7+(i-1)*12-6:7+(i-1)*12+5))*pp) - enddo - -! sync word hard error weight is used as a discriminator for -! frames that have reasonable probability of decoding - hardbits=0 - do i=1,144 - if( softbits(i) .ge. 0.0 ) then - hardbits(i)=1 - endif - enddo - nbadsync1=(8-sum( (2*hardbits(1:8)-1)*s8 ) )/2 - nbadsync2=(8-sum( (2*hardbits(1+56:8+56)-1)*s8 ) )/2 - nbadsync=nbadsync1+nbadsync2 - if( nbadsync .gt. 4 ) then - return - endif - -! normalize the softsymbols before submitting to decoder - sav=sum(softbits)/144 - s2av=sum(softbits*softbits)/144 - ssig=sqrt(s2av-sav*sav) - softbits=softbits/ssig - - sigma=0.75 - llr(1:48)=softbits(9:9+47) - llr(49:128)=softbits(65:65+80-1) - llr=2.0*llr/(sigma*sigma) - - max_iterations=10 -! call timer('bpdec144 ',0) - call bpdecode144(llr,max_iterations,decoded,niterations) -! call timer('bpdec144 ',1) - if( niterations .ge. 0.0 ) then - call extractmessage144(decoded,msgreceived,nhashflag,recent_calls,nrecent) - if( nhashflag .gt. 0 ) then !Hash codes match, so print it - nsuccess=1 - endif - endif - - return -end subroutine msk144decodeframe diff --git a/lib/msk144sd.f90 b/lib/msk144sd.f90 deleted file mode 100644 index 267fff5..0000000 --- a/lib/msk144sd.f90 +++ /dev/null @@ -1,197 +0,0 @@ -program msk144sd -! -! A simple decoder for slow msk144. -! Can be used as a (slow) brute-force multi-decoder by looping -! over a set of carrier frequencies. -! - use options - use timer_module, only: timer - use timer_impl, only: init_timer - use readwav - - parameter (NRECENT=10) - parameter (NSPM=864) - parameter (NPATTERNS=4) - - character ch - character*80 line - character*500 infile - character*12 mycall,hiscall - character*6 mygrid - character(len=500) optarg - character*22 msgreceived - character*12 recent_calls(NRECENT) - - complex cdat(30*375) - complex c(NSPM) - complex ct(NSPM) - - real softbits(144) - real xmc(NPATTERNS) - - logical :: display_help=.false. - - type(wav_header) :: wav - - integer iavmask(8) - integer iavpatterns(8,NPATTERNS) - integer npkloc(10) - - integer*2 id2(30*12000) - integer*2 ichunk(7*1024) - - data iavpatterns/ & - 1,1,1,1,0,0,0,0, & - 0,1,1,1,1,0,0,0, & - 0,0,1,1,1,1,0,0, & - 1,1,1,1,1,1,0,0/ - data xmc/2.0,4.5,2.5,3.0/ - - type (option) :: long_options(2) = [ & - option ('frequency',.true.,'f','rxfreq',''), & - option ('help',.false.,'h','Display this help message','') & - ] - t0=0.0 - ntol=100 - nrxfreq=1500 - - do - call getopt('f:h',long_options,ch,optarg,narglen,nstat,noffset,nremain,.true.) - if( nstat .ne. 0 ) then - exit - end if - select case (ch) - case ('f') - read (optarg(:narglen), *) nrxfreq - case ('h') - display_help = .true. - end select - end do - - if(display_help .or. nstat.lt.0 .or. nremain.lt.1) then - print *, '' - print *, 'Usage: msk144sd [OPTIONS] file1 [file2 ...]' - print *, '' - print *, ' decode pre-recorded .WAV file(s)' - print *, '' - print *, 'OPTIONS:' - do i = 1, size (long_options) - call long_options(i) % print (6) - end do - go to 999 - endif - - call init_timer ('timer.out') - call timer('msk144 ',0) - ndecoded=0 - do ifile=noffset+1,noffset+nremain - call get_command_argument(ifile,optarg,narglen) - infile=optarg(:narglen) - call timer('read ',0) - call wav%read (infile) - i1=index(infile,'.wav') - if( i1 .eq. 0 ) i1=index(infile,'.WAV') - read(infile(i1-6:i1-1),*,err=998) nutc - inquire(FILE=infile,SIZE=isize) - npts=min((isize-216)/2,360000) - read(unit=wav%lun) id2(1:npts) - close(unit=wav%lun) - call timer('read ',1) - -! do if=1,89 ! brute force multi-decoder - fo=nrxfreq -! fo=(if-1)*25.0+300.0 - call msksddc(id2,npts,fo,cdat) - np=npts/32 - ntol=200 ! actual ntol is ntol/32=6.25 Hz. Detection window is 12.5 Hz wide - fc=1500.0 - call msk144spd(cdat,np,ntol,ndecodesuccess,msgreceived,fc,fest,tdec,navg,ct, & - softbits,recent_calls,nrecent) - nsnr=0 ! need an snr estimate - if( ndecodesuccess .eq. 1 ) then - fest=fo+fest-fc ! fudging because spd thinks input signal is at 1500 Hz - goto 900 - endif -! If short ping decoder doesn't find a decode - npat=NPATTERNS - do iavg=1,npat - iavmask=iavpatterns(1:8,iavg) - navg=sum(iavmask) - deltaf=4.0/real(navg) ! search increment for frequency sync - npeaks=4 - ntol=200 - fc=1500.0 - call msk144sync(cdat(1:6*NSPM),6,ntol,deltaf,iavmask,npeaks,fc, & - fest,npkloc,nsyncsuccess,xmax,c) - if( nsyncsuccess .eq. 0 ) cycle - - do ipk=1,npeaks - do is=1,3 - ic0=npkloc(ipk) - if(is.eq.2) ic0=max(1,ic0-1) - if(is.eq.3) ic0=min(NSPM,ic0+1) - ct=cshift(c,ic0-1) - call msk144decodeframe(ct,softbits,msgreceived,ndecodesuccess, & - recent_calls,nrecent) - if(ndecodesuccess .gt. 0) then - tdec=tsec+xmc(iavg)*tframe - fest=fo+(fest-fc)/32.0 - goto 900 - endif - enddo !Slicer dither - enddo !Peak loop - enddo - -! enddo -900 continue - if( ndecodesuccess .gt. 0 ) then - write(*,1020) nutc,nsnr,tdec,nint(fest),' % ',msgreceived,navg -1020 format(i6.6,i4,f5.1,i5,a3,a22,i4) - endif - enddo - - call timer('msk144 ',1) - call timer('msk144 ',101) - go to 999 - -998 print*,'Cannot read from file:' - print*,infile - -999 continue -end program msk144sd - -subroutine msksddc(id2,npts,fc,cdat) - -! The msk144 detector/demodulator/decoder will decode signals -! with carrier frequency, fc, in the range fN/4 +/- 0.03333*fN. -! -! For slow MSK144 with nslow=32: -! fs=12000/32=375 Hz, fN=187.5 Hz -! -! This routine accepts input samples with fs=12000 Hz. It -! downconverts and decimates by 32 to center a signal with input carrier -! frequency fc at new carrier frequency 1500/32=46.875 Hz. -! The analytic signal is returned. - - parameter (NFFT1=30*12000,NFFT2=30*375) - integer*2 id2(npts) - complex cx(0:NFFT1) - complex cdat(30*375) - - dt=1.0/12000.0 - df=1.0/(NFFT1*dt) - icenter=int(fc/df+0.5) - i46p875=int(46.875/df+0.5) - ishift=icenter-i46p875 - cx=cmplx(0.0,0.0) - cx(1:npts)=id2 - call four2a(cx,NFFT1,1,-1,1) - cx=cshift(cx,ishift) - cx(1)=0.5*cx(1) - cx(2*i46p875+1:)=cmplx(0.0,0.0) - call four2a(cx,NFFT2,1,1,1) - cdat(1:npts/32)=cx(0:npts/32-1)/NFFT1 - return - -end subroutine msksddc - diff --git a/lib/msk144signalquality.f90 b/lib/msk144signalquality.f90 deleted file mode 100644 index 24a146c..0000000 --- a/lib/msk144signalquality.f90 +++ /dev/null @@ -1,219 +0,0 @@ -subroutine msk144signalquality(cframe,snr,freq,t0,softbits,msg,dxcall, & - btrain,datadir,nbiterrors,eyeopening,pcoeffs) - - character*22 msg,msgsent - character*12 dxcall - character*12 training_dxcall - character*12 trained_dxcall - character*6 mygrid - character*512 pcoeff_filename - character*8 date - character*10 time - character*5 zone - character*512 datadir - - complex cframe(864) - complex cross(864) - complex cross_avg(864) - complex canalytic(1024) - complex cmodel(1024) - - integer i4tone(144) - integer hardbits(144) - integer msgbits(144) - integer values(8) - - logical*1 bcontest - logical*1 btrain - logical*1 first - logical*1 currently_training - logical*1 msg_has_dxcall - logical*1 is_training_frame - - real softbits(144) - real waveform(0:863) - real d(1024) - real phase(864) - real twopi,freq,phi,dphi0,dphi1,dphi - real*8 x(145),y(145),pp(145),sigmay(145),a(5),chisqr - real*8 pcoeffs(5) - - parameter (NFREQLOW=500,NFREQHIGH=2500) - data first/.true./ - save cross_avg,wt_avg,first,currently_training, & - navg,tlast,training_dxcall,trained_dxcall - - if (first) then - navg=0 - cross=cmplx(0.0,0.0) - cross_avg=cmplx(0.0,0.0) - wt_avg=0.0 - tlast=0.0 - trained_dxcall(1:12)=' ' - training_dxcall(1:12)=' ' - currently_training=.false. - first=.false. - endif - - if( (currently_training .and. (dxcall .ne. training_dxcall)) .or. & - (navg .gt. 10 )) then !reset and retrain - navg=0 - cross=cmplx(0.0,0.0) - cross_avg=cmplx(0.0,0.0) - wt_avg=0.0 - tlast=0.0 - trained_dxcall(1:12)=' ' - currently_training=.false. - training_dxcall(1:12)=' ' - trained_dxcall(1:12)=' ' -!write(*,*) 'reset to untrained state ' - endif - - indx_dxcall=index(msg,trim(dxcall)) - msg_has_dxcall = indx_dxcall .ge. 4 - - if( btrain .and. msg_has_dxcall .and. (.not. currently_training) ) then - currently_training=.true. - training_dxcall=trim(dxcall) - trained_dxcall(1:12)=' ' -!write(*,*) 'start training on call ',training_dxcall - endif - - if( msg_has_dxcall .and. currently_training ) then - trained_dxcall(1:12)=' ' - training_dxcall=dxcall - endif - -! use decoded message to figure out how many bit errors in the frame - do i=1, 144 - hardbits(i)=0 - if(softbits(i) .gt. 0 ) hardbits(i)=1 - enddo - -! generate tones from decoded message - mygrid="EN50" - ichk=0 - bcontest=.false. - call genmsk144(msg,mygrid,ichk,bcontest,msgsent,i4tone,itype) - -! reconstruct message bits from tones - msgbits(1)=0 - do i=1,143 - if( i4tone(i) .eq. 0 ) then - if( mod(i,2) .eq. 1 ) then - msgbits(i+1)=msgbits(i) - else - msgbits(i+1)=mod(msgbits(i)+1,2) - endif - else - if( mod(i,2) .eq. 1 ) then - msgbits(i+1)=mod(msgbits(i)+1,2) - else - msgbits(i+1)=msgbits(i) - endif - endif - enddo - - nbiterrors=0 - do i=1,144 - if( hardbits(i) .ne. msgbits(i) ) nbiterrors=nbiterrors+1 - enddo - - nplus=0 - nminus=0 - eyetop=1 - eyebot=-1 - do i=1,144 - if( msgbits(i) .eq. 1 ) then - if( softbits(i) .lt. eyetop ) eyetop=softbits(i) - else - if( softbits(i) .gt. eyebot ) eyebot=softbits(i) - endif - enddo - eyeopening=eyetop-eyebot - - is_training_frame = & - (snr.gt.5.0 .and.(nbiterrors.lt.7)) .and. & - (abs(t0-tlast) .gt. 0.072) .and. & - msg_has_dxcall - if( currently_training .and. is_training_frame ) then - twopi=8.0*atan(1.0) - nsym=144 - if( i4tone(41) .lt. 0 ) nsym=40 - dphi0=twopi*(freq-500)/12000.0 - dphi1=twopi*(freq+500)/12000.0 - phi=-twopi/8 - indx=0 - do i=1,nsym - if( i4tone(i) .eq. 0 ) then - dphi=dphi0 - else - dphi=dphi1 - endif - do j=1,6 - waveform(indx)=cos(phi); - indx=indx+1 - phi=mod(phi+dphi,twopi) - enddo - enddo -! convert the passband waveform to complex baseband - npts=864 - nfft=1024 - d=0 - d(1:864)=waveform(0:863) - call analytic(d,npts,nfft,canalytic,pcoeffs,.false.) ! don't equalize the model - call tweak1(canalytic,nfft,-freq,cmodel) - call four2a(cframe(1:864),864,1,-1,1) - call four2a(cmodel(1:864),864,1,-1,1) - -! Cross spectra from different messages can be averaged -! as long as all messages originate from dxcall. - cross=cmodel(1:864)*conjg(cframe)/1000.0 - cross=cshift(cross,864/2) - cross_avg=cross_avg+10**(snr/20.0)*cross - wt_avg=wt_avg+10**(snr/20.0) - navg=navg+1 - tlast=t0 - phase=atan2(imag(cross_avg),real(cross_avg)) - df=12000.0/864.0 - nm=145 - do i=1,145 - x(i)=(i-73)*df/1000.0 - enddo - y=phase((864/2-nm/2):(864/2+nm/2)) - sigmay=wt_avg/abs(cross_avg((864/2-nm/2):(864/2+nm/2))) - mode=1 - npts=145 - nterms=5 - call polyfit(x,y,sigmay,npts,nterms,mode,a,chisqr) - pp=a(1)+x*(a(2)+x*(a(3)+x*(a(4)+x*a(5)))) - rmsdiff=sum( (pp-phase((864/2-nm/2):(864/2+nm/2)))**2 )/145.0 -!write(*,*) 'training ',navg,sqrt(chisqr),rmsdiff - if( (sqrt(chisqr).lt.1.8) .and. (rmsdiff.lt.0.5) .and. (navg.ge.5) ) then - trained_dxcall=dxcall - call date_and_time(date,time,zone,values) - write(pcoeff_filename,'(i2.2,i2.2,i2.2,"_",i2.2,i2.2,i2.2)') & - values(1)-2000,values(2),values(3),values(5),values(6),values(7) - pcoeff_filename=trim(trained_dxcall)//"_"//trim(pcoeff_filename)//".pcoeff" - l1=index(datadir,char(0))-1 - datadir(l1+1:l1+1)="/" - pcoeff_filename=datadir(1:l1+1)//trim(pcoeff_filename) -!write(*,*) 'trained - writing coefficients to: ',pcoeff_filename - open(17,file=pcoeff_filename,status='new') - write(17,'(i4,2f10.2,3i5,5e25.16)') navg,sqrt(chisqr),rmsdiff,NFREQLOW,NFREQHIGH,nterms,a - do i=1, 145 - write(17,*) x(i),pp(i),y(i),sigmay(i) - enddo - do i=1,864 - write(17,*) i,real(cframe(i)),imag(cframe(i)),real(cross_avg(i)),imag(cross_avg(i)) - enddo - close(17) - training_dxcall(1:12)=' ' - currently_training=.false. - btrain=.false. - navg=0 - endif - endif - - return - end subroutine msk144signalquality diff --git a/lib/msk144sim.f90 b/lib/msk144sim.f90 deleted file mode 100644 index 28f17e6..0000000 --- a/lib/msk144sim.f90 +++ /dev/null @@ -1,99 +0,0 @@ -program msk144sim - - use wavhdr - parameter (NMAX=15*12000) - real pings(0:NMAX-1) - real waveform(0:NMAX-1) - character*6 mygrid - character arg*8,msg*22,msgsent*22,fname*40 - real wave(0:NMAX-1) !Simulated received waveform - real*8 twopi,freq,phi,dphi0,dphi1,dphi - type(hdr) h !Header for .wav file - integer*2 iwave(0:NMAX-1) - integer itone(144) !Message bits - logical*1 bcontest - data mygrid/"EN50wc"/ - - nargs=iargc() - if(nargs.ne.6) then - print*,'Usage: msk144sim message freq width nslow snr nfiles' - print*,'Example: msk144sim "K1ABC W9XYZ EN37" 1500 0.12 1 2 1' - print*,' msk144sim "K1ABC W9XYZ EN37" 1500 2.5 32 15 1' - go to 999 - endif - call getarg(1,msg) - call getarg(2,arg) - read(arg,*) freq - call getarg(3,arg) - read(arg,*) width - call getarg(4,arg) - read(arg,*) nslow - call getarg(5,arg) - read(arg,*) snrdb - call getarg(6,arg) - read(arg,*) nfiles - -!sig is the peak amplitude of the ping. - sig=sqrt(2.0)*10.0**(0.05*snrdb) - h=default_header(12000,NMAX) - i1=len(trim(msg))-5 - bcontest=.false. - if(msg(i1:i1+1).eq.'R ') bcontest=.true. - ichk=0 - call genmsk144(msg,mygrid,ichk,bcontest,msgsent,itone,itype) - twopi=8.d0*atan(1.d0) - - nsym=144 - nsps=6*nslow - if( itone(41) .lt. 0 ) nsym=40 - baud=2000.d0/nslow - dphi0=twopi*(freq-0.25d0*baud)/12000.d0 - dphi1=twopi*(freq+0.25d0*baud)/12000.d0 - phi=0.0 - k=0 - nreps=NMAX/(nsym*nsps) - print*,nsym,nslow,nsps,baud,freq - do jrep=1,nreps - do i=1,nsym - if( itone(i) .eq. 0 ) then - dphi=dphi0 - else - dphi=dphi1 - endif - do j=1,nsps - waveform(k)=cos(phi) - k=k+1 - phi=mod(phi+dphi,twopi) - enddo - enddo - enddo - - if(itype.lt.1 .or. itype.gt.7) then - print*,'Illegal message' - go to 999 - endif - - if(nslow.eq.1) call makepings(pings,NMAX,width,sig) - -! call sgran() - do ifile=1,nfiles !Loop over requested number of files - write(fname,1002) ifile !Output filename -1002 format('000000_',i6.6) - open(10,file=fname(1:13)//'.wav',access='stream',status='unknown') - - wave=0.0 - iwave=0 - fac=sqrt(6000.0/2500.0) - do i=0,NMAX-1 - xx=gran() - if(nslow.eq.1) wave(i)=pings(i)*waveform(i) + fac*xx - if(nslow.gt.1) wave(i)=sig*waveform(i) + fac*xx - iwave(i)=30.0*wave(i) - enddo - - write(10) h,iwave !Save the .wav file - close(10) - - enddo - -999 end program msk144sim diff --git a/lib/msk144spd.f90 b/lib/msk144spd.f90 deleted file mode 100644 index dcba359..0000000 --- a/lib/msk144spd.f90 +++ /dev/null @@ -1,197 +0,0 @@ -subroutine msk144spd(cbig,n,ntol,nsuccess,msgreceived,fc,fret,tret,navg,ct, & - softbits,recent_calls,nrecent) - -! MSK144 short-ping-decoder - - use timer_module, only: timer - - parameter (NSPM=864, MAXSTEPS=100, NFFT=NSPM, MAXCAND=5, NPATTERNS=6) - character*22 msgreceived - character*12 recent_calls(nrecent) - complex cbig(n) - complex cdat(3*NSPM) !Analytic signal - complex c(NSPM) - complex ct(NSPM) - complex ctmp(NFFT) - integer, dimension(1) :: iloc - integer indices(MAXSTEPS) - integer npkloc(10) - integer navpatterns(3,NPATTERNS) - integer navmask(3) - integer nstart(MAXCAND) - logical ismask(NFFT) - real detmet(-2:MAXSTEPS+3) - real detmet2(-2:MAXSTEPS+3) - real detfer(MAXSTEPS) - real rcw(12) - real ferrs(MAXCAND) - real snrs(MAXCAND) - real softbits(144) - real tonespec(NFFT) - real tpat(NPATTERNS) - real*8 dt, df, fs, pi, twopi - logical first - data first/.true./ - data navpatterns/ & - 0,1,0, & - 1,0,0, & - 0,0,1, & - 1,1,0, & - 0,1,1, & - 1,1,1/ - data tpat/1.5,0.5,2.5,1.0,2.0,1.5/ - - save df,first,fs,pi,twopi,dt,tframe,rcw - - if(first) then - nmatchedfilter=1 -! define half-sine pulse and raised-cosine edge window - pi=4d0*datan(1d0) - twopi=8d0*datan(1d0) - fs=12000.0 - dt=1.0/fs - df=fs/NFFT - tframe=NSPM/fs - - do i=1,12 - angle=(i-1)*pi/12.0 - rcw(i)=(1-cos(angle))/2 - enddo - - first=.false. - endif - - ! fill the detmet, detferr arrays - nstep=(n-NSPM)/216 ! 72ms/4=18ms steps - detmet=0 - detmet2=0 - detfer=-999.99 - nfhi=2*(fc+500) - nflo=2*(fc-500) - ihlo=nint((nfhi-2*ntol)/df) + 1 - ihhi=nint((nfhi+2*ntol)/df) + 1 - illo=nint((nflo-2*ntol)/df) + 1 - ilhi=nint((nflo+2*ntol)/df) + 1 - i2000=nint(nflo/df) + 1 - i4000=nint(nfhi/df) + 1 - do istp=1,nstep - ns=1+216*(istp-1) - ne=ns+NSPM-1 - if( ne .gt. n ) exit - ctmp=cmplx(0.0,0.0) - ctmp(1:NSPM)=cbig(ns:ne) - -! Coarse carrier frequency sync - seek tones at 2000 Hz and 4000 Hz in -! squared signal spectrum. - - ctmp=ctmp**2 - ctmp(1:12)=ctmp(1:12)*rcw - ctmp(NSPM-11:NSPM)=ctmp(NSPM-11:NSPM)*rcw(12:1:-1) - call four2a(ctmp,NFFT,1,-1,1) - tonespec=abs(ctmp)**2 - - ismask=.false. - ismask(ihlo:ihhi)=.true. ! high tone search window - iloc=maxloc(tonespec,ismask) - ihpk=iloc(1) - deltah=-real( (ctmp(ihpk-1)-ctmp(ihpk+1)) / (2*ctmp(ihpk)-ctmp(ihpk-1)-ctmp(ihpk+1)) ) - ah=tonespec(ihpk) - ahavp=(sum(tonespec,ismask)-ah)/count(ismask) - trath=ah/(ahavp+0.01) - ismask=.false. - ismask(illo:ilhi)=.true. ! window for low tone - iloc=maxloc(tonespec,ismask) - ilpk=iloc(1) - deltal=-real( (ctmp(ilpk-1)-ctmp(ilpk+1)) / (2*ctmp(ilpk)-ctmp(ilpk-1)-ctmp(ilpk+1)) ) - al=tonespec(ilpk) - alavp=(sum(tonespec,ismask)-al)/count(ismask) - tratl=al/(alavp+0.01) - fdiff=(ihpk+deltah-ilpk-deltal)*df - ferrh=(ihpk+deltah-i4000)*df/2.0 - ferrl=(ilpk+deltal-i2000)*df/2.0 - if( ah .ge. al ) then - ferr=ferrh - else - ferr=ferrl - endif - detmet(istp)=max(ah,al) - detmet2(istp)=max(trath,tratl) - detfer(istp)=ferr - enddo ! end of detection-metric and frequency error estimation loop - - call indexx(detmet(1:nstep),nstep,indices) !find median of detection metric vector - xmed=detmet(indices(nstep/4)) - detmet=detmet/xmed ! noise floor of detection metric is 1.0 - ndet=0 - - do ip=1,MAXCAND ! Find candidates - iloc=maxloc(detmet(1:nstep)) - il=iloc(1) - if( (detmet(il) .lt. 3.0) ) exit - if( abs(detfer(il)) .le. ntol ) then - ndet=ndet+1 - nstart(ndet)=1+(il-1)*216+1 - ferrs(ndet)=detfer(il) - snrs(ndet)=12.0*log10(detmet(il))/2-9.0 - endif - detmet(il)=0.0 - enddo - - if( ndet .lt. 3 ) then - do ip=1,MAXCAND-ndet ! Find candidates - iloc=maxloc(detmet2(1:nstep)) - il=iloc(1) - if( (detmet2(il) .lt. 12.0) ) exit - if( abs(detfer(il)) .le. ntol ) then - ndet=ndet+1 - nstart(ndet)=1+(il-1)*216+1 - ferrs(ndet)=detfer(il) - snrs(ndet)=12.0*log10(detmet2(il))/2-9.0 - endif - detmet2(il)=0.0 - enddo - endif - - nsuccess=0 - msgreceived=' ' - npeaks=2 - ntol0=8 - deltaf=2.0 - do icand=1,ndet ! Try to sync/demod/decode each candidate. - ib=max(1,nstart(icand)-NSPM) - ie=ib-1+3*NSPM - if( ie .gt. n ) then - ie=n - ib=ie-3*NSPM+1 - endif - cdat=cbig(ib:ie) - fo=fc+ferrs(icand) - do iav=1,NPATTERNS - navmask=navpatterns(1:3,iav) - call msk144sync(cdat,3,ntol0,deltaf,navmask,npeaks,fo,fest,npkloc, & - nsyncsuccess,xmax,c) - - if( nsyncsuccess .eq. 0 ) cycle - - do ipk=1,npeaks - do is=1,3 - ic0=npkloc(ipk) - if( is.eq.2) ic0=max(1,ic0-1) - if( is.eq.3) ic0=min(NSPM,ic0+1) - ct=cshift(c,ic0-1) - call msk144decodeframe(ct,softbits,msgreceived,ndecodesuccess, & - recent_calls,nrecent) - if( ndecodesuccess .gt. 0 ) then - tret=(nstart(icand)+NSPM/2)/fs - fret=fest - navg=sum(navmask) - nsuccess=1 - return - endif - enddo - enddo - enddo - enddo ! candidate loop - - return -end subroutine msk144spd diff --git a/lib/msk144sync.f90 b/lib/msk144sync.f90 deleted file mode 100644 index dfae9a2..0000000 --- a/lib/msk144sync.f90 +++ /dev/null @@ -1,101 +0,0 @@ -subroutine msk144sync(cdat,nframes,ntol,delf,navmask,npeaks,fc,fest, & - npklocs,nsuccess,xmax,c) - -!$ use omp_lib - - parameter (NSPM=864) - complex cdat(NSPM*nframes) - complex cdat2(NSPM*nframes,8) - complex c(NSPM) !Coherently averaged complex data - complex cs(NSPM,8) - complex cb(42) !Complex waveform for sync word - - integer s8(8) - integer iloc(1) - integer npklocs(npeaks) - integer navmask(nframes) ! defines which frames to average - - real cbi(42),cbq(42) - real pkamps(npeaks) - real xcc(0:NSPM-1) - real xccs(0:NSPM-1,8) - real xm(8) - real bf(8) - real pp(12) !Half-sine pulse shape - logical first - data first/.true./ - data s8/0,1,1,1,0,0,1,0/ - save first,cb,fs,pi,twopi,dt,s8,pp - - if(first) then - pi=4.0*atan(1.0) - twopi=8.0*atan(1.0) - fs=12000.0 - dt=1.0/fs - - do i=1,12 !Define half-sine pulse - angle=(i-1)*pi/12.0 - pp(i)=sin(angle) - enddo - -! Define the sync word waveforms - s8=2*s8-1 - cbq(1:6)=pp(7:12)*s8(1) - cbq(7:18)=pp*s8(3) - cbq(19:30)=pp*s8(5) - cbq(31:42)=pp*s8(7) - cbi(1:12)=pp*s8(2) - cbi(13:24)=pp*s8(4) - cbi(25:36)=pp*s8(6) - cbi(37:42)=pp(1:6)*s8(8) - cb=cmplx(cbi,cbq) - - first=.false. - endif - - nfreqs=2*nint(ntol/delf) + 1 - xm=0.0 - bf=0.0 - nthreads=1 -!$ nthreads=min(8,int(OMP_GET_MAX_THREADS(),4)) - nstep=nfreqs/nthreads - -!$OMP PARALLEL NUM_THREADS(nthreads) PRIVATE(id,if1,if2) - id=1 -!$ id=OMP_GET_THREAD_NUM() + 1 !Thread id = 1,2,... - if1=-nint(ntol/delf) + (id-1)*nstep - if2=if1+nstep-1 - if(id.eq.nthreads) if2=nint(ntol/delf) - call msk144_freq_search(cdat,fc,if1,if2,delf,nframes,navmask,cb, & - cdat2(1,id),xm(id),bf(id),cs(1,id),xccs(1,id)) -!$OMP END PARALLEL - - xmax=xm(1) - fest=fc+bf(1) - c=cs(1:NSPM,1) - xcc=xccs(0:NSPM-1,1) - if(nthreads.gt.1) then - do i=2,nthreads - if(xm(i).gt.xmax) then - xmax=xm(i) - fest=fc+bf(i) - c=cs(1:NSPM,i) - xcc=xccs(0:NSPM-1,i) - endif - enddo - endif - -! Find npeaks largest peaks - do ipk=1,npeaks - iloc=maxloc(xcc) - ic2=iloc(1) - npklocs(ipk)=ic2 - pkamps(ipk)=xcc(ic2-1) - xcc(max(0,ic2-7):min(NSPM-1,ic2+7))=0.0 - enddo - - nsuccess=0 - if(xmax.ge.1.3) nsuccess=1 - - return -end subroutine msk144sync diff --git a/lib/msk40_freq_search.f90 b/lib/msk40_freq_search.f90 deleted file mode 100644 index 97f74f5..0000000 --- a/lib/msk40_freq_search.f90 +++ /dev/null @@ -1,53 +0,0 @@ -subroutine msk40_freq_search(cdat,fc,if1,if2,delf,nframes,navmask,cb, & - cdat2,xmax,bestf,cs,xccs) - - parameter (NSPM=240,NZ=7*NSPM) - complex cdat(NZ) - complex cdat2(NZ) - complex c(NSPM) !Coherently averaged complex data - complex ct2(2*NSPM) - complex cs(NSPM) - complex cb(42) !Complex waveform for sync word - complex cc(0:NSPM-1) - real xcc(0:NSPM-1) - real xccs(0:NSPM-1) - integer navmask(nframes) !Tells which frames to average - - navg=sum(navmask) - n=nframes*NSPM -! fac=1.0/(48.0*sqrt(float(navg))) - fac=1.0/(24.0*sqrt(float(navg))) - - do ifr=if1,if2 !Find freq that maximizes sync - ferr=ifr*delf - call tweak1(cdat,n,-(fc+ferr),cdat2) - c=0 - do i=1,nframes - ib=(i-1)*NSPM+1 - ie=ib+NSPM-1 - if( navmask(i) .eq. 1 ) c=c+cdat2(ib:ie) - enddo - - cc=0 - ct2(1:NSPM)=c - ct2(NSPM+1:2*NSPM)=c - - do ish=0,NSPM-1 - cc(ish)=dot_product(ct2(1+ish:42+ish),cb(1:42)) - enddo - - xcc=abs(cc) - xb=maxval(xcc)*fac - if(xb.gt.xmax) then - xmax=xb - bestf=ferr - cs=c - xccs=xcc - endif - enddo - -! write(71,3001) fc,delf,if1,if2,nframes,bestf,xmax -!3001 format(2f8.3,3i5,2f8.3) - - return -end subroutine msk40_freq_search diff --git a/lib/msk40decodeframe.f90 b/lib/msk40decodeframe.f90 deleted file mode 100644 index 363d8dc..0000000 --- a/lib/msk40decodeframe.f90 +++ /dev/null @@ -1,169 +0,0 @@ -subroutine msk40decodeframe(c,mycall,hiscall,xsnr,bswl,nhasharray, & - recent_calls,nrecent,msgreceived,nsuccess) -! use timer_module, only: timer - - parameter (NSPM=240) - character*4 rpt(0:15) - character*6 mycall,hiscall,mycall0,hiscall0 - character*22 hashmsg,msgreceived - character*12 recent_calls(nrecent) - complex cb(42) - complex cfac,cca - complex c(NSPM) - integer*1 cw(32) - integer*1 decoded(16) - integer s8r(8),hardbits(40) - integer nhasharray(nrecent,nrecent) - real*8 dt, fs, pi, twopi - real cbi(42),cbq(42) - real pp(12) - real softbits(40) - real llr(32) - logical first - logical*1 bswl - data first/.true./ - data s8r/1,0,1,1,0,0,0,1/ - data mycall0/'dummy'/,hiscall0/'dummy'/ - data rpt/"-03 ","+00 ","+03 ","+06 ","+10 ","+13 ","+16 ", & - "R-03","R+00","R+03","R+06","R+10","R+13","R+16", & - "RRR ","73 "/ - save first,cb,fs,pi,twopi,dt,s8r,pp,rpt,mycall0,hiscall0,ihash - - if(first) then -! define half-sine pulse and raised-cosine edge window - pi=4d0*datan(1d0) - twopi=8d0*datan(1d0) - fs=12000.0 - dt=1.0/fs - - do i=1,12 - angle=(i-1)*pi/12.0 - pp(i)=sin(angle) - enddo - -! define the sync word waveforms - s8r=2*s8r-1 - cbq(1:6)=pp(7:12)*s8r(1) - cbq(7:18)=pp*s8r(3) - cbq(19:30)=pp*s8r(5) - cbq(31:42)=pp*s8r(7) - cbi(1:12)=pp*s8r(2) - cbi(13:24)=pp*s8r(4) - cbi(25:36)=pp*s8r(6) - cbi(37:42)=pp(1:6)*s8r(8) - cb=cmplx(cbi,cbq) - first=.false. - endif - - if(mycall.ne.mycall0 .or. hiscall.ne.hiscall0) then - hashmsg=trim(mycall)//' '//trim(hiscall) - if( hashmsg .ne. ' ' .and. hiscall .ne. '' ) then ! protect against blank mycall/hiscall - call fmtmsg(hashmsg,iz) - call hash(hashmsg,22,ihash) - ihash=iand(ihash,4095) - else - ihash=9999 ! so that it can never match a received hash - endif - mycall0=mycall - hiscall0=hiscall - endif - - nsuccess=0 - msgreceived=' ' - -! Estimate carrier phase. - cca=sum(c(1:1+41)*conjg(cb)) - phase0=atan2(imag(cca),real(cca)) - -! Remove phase error - want constellation rotated so that sample points lie on I/Q axes - cfac=cmplx(cos(phase0),sin(phase0)) - c=c*conjg(cfac) - -! Matched filter. - softbits(1)=sum(imag(c(1:6))*pp(7:12))+sum(imag(c(NSPM-5:NSPM))*pp(1:6)) - softbits(2)=sum(real(c(1:12))*pp) - do i=2,20 - softbits(2*i-1)=sum(imag(c(1+(i-1)*12-6:1+(i-1)*12+5))*pp) - softbits(2*i)=sum(real(c(7+(i-1)*12-6:7+(i-1)*12+5))*pp) - enddo - -! Sync word hard error weight is used to reject frames that -! are unlikely to decode. - hardbits=0 - do i=1,40 - if( softbits(i) .ge. 0.0 ) then - hardbits(i)=1 - endif - enddo - nbadsync1=(8-sum( (2*hardbits(1:8)-1)*s8r ) )/2 - nbadsync=nbadsync1 - if( nbadsync .gt. 3 ) then - return - endif - -! Normalize the softsymbols before submitting to decoder. - sav=sum(softbits)/40 - s2av=sum(softbits*softbits)/40 - ssig=sqrt(s2av-sav*sav) - softbits=softbits/ssig - - sigma=0.75 -! if(xsnr.lt.0.0) sigma=0.75-0.0875*xsnr - if(xsnr.lt.0.0) sigma=0.75-0.11*xsnr - llr(1:32)=softbits(9:40) - llr=2.0*llr/(sigma*sigma) - - max_iterations=5 - call bpdecode40(llr,max_iterations,decoded,niterations) - - if( niterations .ge. 0.0 ) then - call encode_msk40(decoded,cw) - nhammd=0 - cord=0.0 - do i=1,32 - if( cw(i) .ne. hardbits(i+8) ) then - nhammd=nhammd+1 - cord=cord+abs(softbits(i+8)) - endif - enddo - - imsg=0 - do i=1,16 - imsg=ishft(imsg,1)+iand(1_1,decoded(17-i)) - enddo - nrxrpt=iand(imsg,15) - nrxhash=(imsg-nrxrpt)/16 - - if(nhammd.le.4 .and. cord .lt. 0.65 .and. & - nrxhash.eq.ihash .and. nrxrpt.ge.7) then -!write(*,*) 'decodeframe 1',nbadsync,nhammd,cord,nrxhash,nrxrpt,ihash,xsnr,sigma - nsuccess=1 - write(msgreceived,'(a1,a,1x,a,a1,1x,a4)') "<",trim(mycall), & - trim(hiscall),">",rpt(nrxrpt) - return - elseif(bswl .and. nhammd.le.4 .and. cord.lt.0.65 .and. nrxrpt.ge.7 ) then - do i=1,nrecent - do j=i+1,nrecent - if( nrxhash .eq. nhasharray(i,j) ) then - nsuccess=2 - write(msgreceived,'(a1,a,1x,a,a1,1x,a4)') "<",trim(recent_calls(i)), & - trim(recent_calls(j)),">",rpt(nrxrpt) -!write(*,*) 'decodeframe 2',nbadsync,nhammd,cord,nrxhash,nrxrpt,ihash,xsnr,sigma - elseif( nrxhash .eq. nhasharray(j,i) ) then - nsuccess=2 - write(msgreceived,'(a1,a,1x,a,a1,1x,a4)') "<",trim(recent_calls(j)), & - trim(recent_calls(i)),">",rpt(nrxrpt) -!write(*,*) 'decodeframe 3',nbadsync,nhammd,cord,nrxhash,nrxrpt,ihash,xsnr,sigma - endif - enddo - enddo - if(nsuccess.eq.0) then - nsuccess=3 -!write(*,*) 'decodeframe 4',bswl,nbadsync,nhammd,cord,nrxhash,nrxrpt,ihash,xsnr,sigma,nsuccess - write(msgreceived,'(a1,i4.4,a1,1x,a4)') "<",nrxhash,">",rpt(nrxrpt) - endif - endif - endif - - return -end subroutine msk40decodeframe diff --git a/lib/msk40spd.f90 b/lib/msk40spd.f90 deleted file mode 100644 index c8af1a4..0000000 --- a/lib/msk40spd.f90 +++ /dev/null @@ -1,199 +0,0 @@ -subroutine msk40spd(cbig,n,ntol,mycall,hiscall,bswl,nhasharray,recent_calls, & - nrecent,nsuccess,msgreceived,fc,fret,tret,navg) -! msk40 short-ping-decoder - - use timer_module, only: timer - - parameter (NSPM=240, MAXSTEPS=150, NFFT=NSPM, MAXCAND=5, NPATTERNS=6) - character*6 mycall,hiscall - character*22 msgreceived - character*12 recent_calls(nrecent) - complex cbig(n) - complex cdat(3*NSPM) !Analytic signal - complex c(NSPM) - complex ct(NSPM) - complex ctmp(NFFT) - integer, dimension(1) :: iloc - integer indices(MAXSTEPS) - integer npkloc(10) - integer navpatterns(3,NPATTERNS) - integer navmask(3) - integer nstart(MAXCAND) - integer nhasharray(nrecent,nrecent) - logical ismask(NFFT) - logical*1 bswl - real detmet(-2:MAXSTEPS+3) - real detmet2(-2:MAXSTEPS+3) - real detfer(MAXSTEPS) - real rcw(12) - real ferrs(MAXCAND) - real snrs(MAXCAND) - real tonespec(NFFT) - real tpat(NPATTERNS) - real*8 dt, df, fs, pi, twopi - logical first - data first/.true./ - data navpatterns/ & - 0,1,0, & - 1,0,0, & - 0,0,1, & - 1,1,0, & - 0,1,1, & - 1,1,1/ - data tpat/1.5,0.5,2.5,1.0,2.0,1.5/ - save df,first,fs,pi,twopi,dt,tframe,rcw - - if(first) then - nmatchedfilter=1 -! define half-sine pulse and raised-cosine edge window - pi=4d0*datan(1d0) - twopi=8d0*datan(1d0) - fs=12000.0 - dt=1.0/fs - df=fs/NFFT - tframe=NSPM/fs - - do i=1,12 - angle=(i-1)*pi/12.0 - rcw(i)=(1-cos(angle))/2 - enddo - - first=.false. - endif - - - ! fill the detmet, detferr arrays - nstep=(n-NSPM)/60 ! 20ms/4=5ms steps - detmet=0 - detmet2=0 - detfer=-999.99 - nfhi=2*(fc+500) - nflo=2*(fc-500) - ihlo=nint((nfhi-2*ntol)/df)+1 - ihhi=nint((nfhi+2*ntol)/df)+1 - illo=nint((nflo-2*ntol)/df)+1 - ilhi=nint((nflo+2*ntol)/df)+1 - i2000=nint(nflo/df)+1 - i4000=nint(nfhi/df)+1 - do istp=1,nstep - ns=1+60*(istp-1) - ne=ns+NSPM-1 - if( ne .gt. n ) exit - ctmp=cmplx(0.0,0.0) - ctmp(1:NSPM)=cbig(ns:ne) - -! Coarse carrier frequency sync - seek tones at 2000 Hz and 4000 Hz in -! squared signal spectrum. - - ctmp=ctmp**2 - ctmp(1:12)=ctmp(1:12)*rcw - ctmp(NSPM-11:NSPM)=ctmp(NSPM-11:NSPM)*rcw(12:1:-1) - call four2a(ctmp,NFFT,1,-1,1) - tonespec=abs(ctmp)**2 - - ismask=.false. - ismask(ihlo:ihhi)=.true. ! high tone search window - iloc=maxloc(tonespec,ismask) - ihpk=iloc(1) - deltah=-real( (ctmp(ihpk-1)-ctmp(ihpk+1)) / (2*ctmp(ihpk)-ctmp(ihpk-1)-ctmp(ihpk+1)) ) - ah=tonespec(ihpk) - ahavp=(sum(tonespec,ismask)-ah)/count(ismask) - trath=ah/(ahavp+0.01) - ismask=.false. - ismask(illo:ilhi)=.true. ! window for low tone - iloc=maxloc(tonespec,ismask) - ilpk=iloc(1) - deltal=-real( (ctmp(ilpk-1)-ctmp(ilpk+1)) / (2*ctmp(ilpk)-ctmp(ilpk-1)-ctmp(ilpk+1)) ) - al=tonespec(ilpk) - alavp=(sum(tonespec,ismask)-al)/count(ismask) - tratl=al/(alavp+0.01) - fdiff=(ihpk+deltah-ilpk-deltal)*df - ferrh=(ihpk+deltah-i4000)*df/2.0 - ferrl=(ilpk+deltal-i2000)*df/2.0 - if( ah .ge. al ) then - ferr=ferrh - else - ferr=ferrl - endif - detmet(istp)=max(ah,al) - detmet2(istp)=max(trath,tratl) - detfer(istp)=ferr - enddo ! end of detection-metric and frequency error estimation loop - - call indexx(detmet(1:nstep),nstep,indices) !find median of detection metric vector - xmed=detmet(indices(nstep/4)) - detmet=detmet/xmed ! noise floor of detection metric is 1.0 - ndet=0 - - do ip=1,MAXCAND ! Find candidates - iloc=maxloc(detmet(1:nstep)) - il=iloc(1) - if( (detmet(il) .lt. 3.5) ) exit - if( abs(detfer(il)) .le. ntol ) then - ndet=ndet+1 - nstart(ndet)=1+(il-1)*60+1 - ferrs(ndet)=detfer(il) - snrs(ndet)=12.0*log10(detmet(il))/2-9.0 - endif - detmet(il)=0.0 - enddo - - if( ndet .lt. 3 ) then - do ip=1,MAXCAND-ndet ! Find candidates - iloc=maxloc(detmet2(1:nstep)) - il=iloc(1) - if( (detmet2(il) .lt. 12.0) ) exit - if( abs(detfer(il)) .le. ntol ) then - ndet=ndet+1 - nstart(ndet)=1+(il-1)*60+1 - ferrs(ndet)=detfer(il) - snrs(ndet)=12.0*log10(detmet2(il))/2-9.0 - endif - detmet2(il)=0.0 - enddo - endif - - nsuccess=0 - msgreceived=' ' - npeaks=2 - ntol0=29 - deltaf=7.2 - do icand=1,ndet ! Try to sync/demod/decode each candidate. - ib=max(1,nstart(icand)-NSPM) - ie=ib-1+3*NSPM - if( ie .gt. n ) then - ie=n - ib=ie-3*NSPM+1 - endif - cdat=cbig(ib:ie) - fo=fc+ferrs(icand) - xsnr=snrs(icand) - do iav=1,NPATTERNS - navmask=navpatterns(1:3,iav) - call msk40sync(cdat,3,ntol0,deltaf,navmask,npeaks,fo,fest,npkloc, & - nsyncsuccess,c) - if( nsyncsuccess .eq. 0 ) cycle - - do ipk=1,npeaks - do is=1,3 - ic0=npkloc(ipk) - if( is.eq.2) ic0=max(1,ic0-1) - if( is.eq.3) ic0=min(NSPM,ic0+1) - ct=cshift(c,ic0-1) - call msk40decodeframe(ct,mycall,hiscall,xsnr,bswl,nhasharray, & - recent_calls,nrecent,msgreceived,ndecodesuccess) - if( ndecodesuccess .gt. 0 ) then -!write(*,*) icand, iav, ipk, is, tret, fret, msgreceived - tret=(nstart(icand)+NSPM/2)/fs - fret=fest - navg=sum(navmask) - nsuccess=ndecodesuccess - return - endif - enddo - enddo - enddo - enddo ! candidate loop - - return -end subroutine msk40spd diff --git a/lib/msk40sync.f90 b/lib/msk40sync.f90 deleted file mode 100644 index 5a2ca1e..0000000 --- a/lib/msk40sync.f90 +++ /dev/null @@ -1,103 +0,0 @@ -subroutine msk40sync(cdat,nframes,ntol,delf,navmask,npeaks,fc,fest, & - npklocs,nsuccess,c) - - !$ use omp_lib - - parameter (NSPM=240) - complex cdat(NSPM*nframes) - complex cdat2(NSPM*nframes,8) - complex c(NSPM) !Coherently averaged complex data - complex cs(NSPM,8) - complex cb(42) !Complex waveform for sync word - - integer s8r(8) - integer iloc(1) - integer npklocs(npeaks) - integer navmask(nframes) ! defines which frames to average - - real cbi(42),cbq(42) - real pkamps(npeaks) - real xcc(0:NSPM-1) - real xccs(0:NSPM-1,8) - real xm(8) - real bf(8) - real pp(12) !Half-sine pulse shape - logical first - data first/.true./ - data s8r/1,0,1,1,0,0,0,1/ - save first,cb,fs,pi,twopi,dt,s8r,pp - - if(first) then - pi=4.0*atan(1.0) - twopi=8.0*atan(1.0) - fs=12000.0 - dt=1.0/fs - - do i=1,12 !Define half-sine pulse - angle=(i-1)*pi/12.0 - pp(i)=sin(angle) - enddo - -! Define the sync word waveforms - s8r=2*s8r-1 - cbq(1:6)=pp(7:12)*s8r(1) - cbq(7:18)=pp*s8r(3) - cbq(19:30)=pp*s8r(5) - cbq(31:42)=pp*s8r(7) - cbi(1:12)=pp*s8r(2) - cbi(13:24)=pp*s8r(4) - cbi(25:36)=pp*s8r(6) - cbi(37:42)=pp(1:6)*s8r(8) - cb=cmplx(cbi,cbq) - - first=.false. - endif - - nfreqs=2*nint(ntol/delf) + 1 - xm=0.0 - bf=0.0 - nthreads=1 - !$ nthreads=min(8,int(OMP_GET_MAX_THREADS(),4)) - nstep=nfreqs/nthreads - - !$OMP PARALLEL NUM_THREADS(nthreads) PRIVATE(id,if1,if2) - id=1 - !$ id=OMP_GET_THREAD_NUM() + 1 !Thread id = 1,2,... - if1=-nint(ntol/delf) + (id-1)*nstep - if2=if1+nstep-1 - if(id.eq.nthreads) if2=nint(ntol/delf) - call msk40_freq_search(cdat,fc,if1,if2,delf,nframes,navmask,cb, & - cdat2(1,id),xm(id),bf(id),cs(1,id),xccs(1,id)) -! write(73,3002) id,if1,if2,nfreqs,nthreads,bf(id),xm(id) -!3002 format(5i5,2f10.3) - !$OMP END PARALLEL - - xmax=xm(1) - fest=fc+bf(1) - c=cs(1:NSPM,1) - xcc=xccs(0:NSPM-1,1) - if(nthreads.gt.1) then - do i=2,nthreads - if(xm(i).gt.xmax) then - xmax=xm(i) - fest=fc+bf(i) - c=cs(1:NSPM,i) - xcc=xccs(0:NSPM-1,i) - endif - enddo - endif - -! Find npeaks largest peaks - do ipk=1,npeaks - iloc=maxloc(xcc) - ic2=iloc(1) - npklocs(ipk)=ic2 - pkamps(ipk)=xcc(ic2-1) - xcc(max(0,ic2-7):min(NSPM-1,ic2+7))=0.0 - enddo - - nsuccess=0 - if( xmax .ge. 1.3 ) nsuccess=1 - - return -end subroutine msk40sync diff --git a/lib/mskber.f90 b/lib/mskber.f90 deleted file mode 100644 index 4b31127..0000000 --- a/lib/mskber.f90 +++ /dev/null @@ -1,146 +0,0 @@ -program mskber - -! Generate an MSK waveform, pass it through an AWGN channel, apply coherent -! MSK receiver, and count number of errors at each Eb/No. - - parameter (MAXSYM=1000*1000) - parameter (NSPS=5) !Samples per symbol - real ct(-NSPS:NSPS*MAXSYM-1) !cos(pi*t/2T) - real st(-NSPS:NSPS*MAXSYM-1) !sin(pi*t/2T) - real r(0:MAXSYM-1) !Random numbers to set test bits - real xsym(0:MAXSYM-1) !Soft Rx symbols - - complex xt(-NSPS:NSPS*MAXSYM-1) !Complex baseband Tx waveform - complex nt(-NSPS:NSPS*MAXSYM-1) !Generated AWGN channel noise - complex yt(-NSPS:NSPS*MAXSYM-1) !Received signal, yt = xt + fac*nt - complex cwave(-NSPS:NSPS*MAXSYM-1) !Audio waveform, Tx real part - complex z - - integer sym0(0:MAXSYM-1) !Generated test bits - integer sym(0:MAXSYM-1) !Hard-copy received bits - integer sym1(0:7) - - character*12 arg - data sym1/1,1,0,0,0,1,1,1/ - - nargs=iargc() - if(nargs.ne.2) then - print*,'Usage: mskber nsym EbNo' - go to 999 - endif - call getarg(1,arg) - read(arg,*) nsym - call getarg(2,arg) - read(arg,*) EbNo - - pi=4.0*atan(1.0) - - do i=-NSPS,NSPS*nsym-1 !Define ct, st arrays - t=i*pi/(2.0*NSPS) - ct(i)=cos(t) - st(i)=sin(t) - enddo - fac=1.0/sqrt(float(NSPS)) - - do iEbNo=0,10 !Loop over a range of Eb/No - sym0=0 - call random_number(r) - where(r(0:nsym-1).gt.0.5) sym0(0:nsym-1)=1 !Generate random data bits - if(nsym.eq.8) sym0(0:nsym-1)=sym1 - call mskmod(sym0,nsym,NSPS,ct,st,xt,cwave) !Generate Tx waveform - - do i=-NSPS,NSPS*nsym-1 !Generate Gaussian noise - xx=0.707*gran() - yy=0.707*gran() - nt(i)=cmplx(xx,yy) - enddo - fac_noise=10.0**(-iEbNo/20.0) - if(EbNo.ne.0.0) fac_noise=10.0**(-EbNo/20.0) - yt=xt + fac_noise*nt !Rx signal, with noise - - call mskdemod(yt,nsym,NSPS,ct,st,xsym) !MSK demodulator - - sym=0 - where(xsym.gt.0.0) sym=1 - - if(nsym.le.160 .and. EbNo.ne.0.0) then - write(*,1012) sym0(0:nsym-1) - if(nsym.gt.50) write(*,1012) - write(*,1012) sym(0:nsym-1) -1012 format(50i1) - do i=-nsps,nsps*nsym-1 - phi=i*2.0*pi*1500/12000.0 - z=cwave(i)*cmplx(cos(phi),sin(phi)) !Mix back to baseband - write(51,1014) float(i)/nsps,xt(i),abs(xt(i)),cwave(i),z -1014 format(8f8.4) - enddo - endif - -! Count the hard errors - nerr=count(sym(0:nsym-1).ne.sym0(0:nsym-1)) - thber=0.5*erfc(10.0**(iEbNo/20.0)) - xEbNo=iEbNo - if(EbNo.ne.0.0) xEbNo=EbNo - write(*,1000) xEbNo,thber,float(nerr)/nsym -1000 format(f6.1,2f10.6) - if(EbNo.ne.0.0) exit - enddo - -999 end program mskber - -subroutine mskmod(sym,nsym,nsps,ct,st,xt,cwave) - -! Generate MSK Tx waveform at baseband. - - integer sym(0:nsym-1) !Hard-copy received bits - complex xt(-nsps:nsps*nsym-1) !Complex baseband Tx waveform - complex cwave(-nsps:nsps*nsym-1) !Audio waveform, fc=1500 Hz. - real ct(-nsps:nsps*nsym-1) !cos(pi*t/2T) - real st(-nsps:nsps*nsym-1) !sin(pi*t/2T) - real ai(-nsps:nsps*nsym-1) !Rectangular pulses for even symbols - real aq(-nsps:nsps*nsym-1) !Rectangular pulses for odd symbols - - ai=0. - aq=0. - fac=1.0/sqrt(float(nsps)) - do j=0,nsym-1,2 - ia=(j-1)*nsps - ib=ia+2*nsps-1 - ai(ia:ib)=2*sym(j)-1 !Even bits as rectangular pulses - aq(ia+nsps:ib+nsps)=2*sym(j+1)-1 !Odd bits as rectangular pulses - enddo - xt=fac*cmplx(ai*ct,aq*st) !Baseband Tx waveform - - twopi=8.0*atan(1.0) - do i=-nsps,nsps*nsym-1 - phi=i*twopi*1500/12000.0 - cwave(i)=xt(i)*cmplx(cos(phi),-sin(phi)) - enddo - - return -end subroutine mskmod - -subroutine mskdemod(yt,nsym,nsps,ct,st,xsym) - -! MSK demodulator -! Rx phase must be known and stable; symbol sync must be established. - - complex yt(-nsps:nsps*nsym-1) !Received signal - real ct(-nsps:nsps*nsym-1) !cos(pi*t/2T) - real st(-nsps:nsps*nsym-1) !sin(pi*t/2T) - real xe(-nsps:nsps*nsym-1) !Temp array for received even symbols - real xo(-nsps:nsps*nsym-1) !Temp array for received odd symbols - real xsym(0:nsym-1) !Soft Rx symbols - - iz=nsps*(nsym+1) - xe(-nsps:nsps*nsym-1)=real(yt)*ct !Apply matched filters - xo(-nsps:nsps*nsym-1)=aimag(yt)*st - do j=0,nsym-1,2 - ia=(j-1)*nsps - ib=ia+2*nsps-1 - xsym(j)=sum(xe(ia:ib)) !Integrate over 2 symbol lengths - xsym(j+1)=sum(xo(ia+nsps:ib+nsps)) - enddo - - return -end subroutine mskdemod diff --git a/lib/mskdt.f90 b/lib/mskdt.f90 deleted file mode 100644 index bca8359..0000000 --- a/lib/mskdt.f90 +++ /dev/null @@ -1,78 +0,0 @@ -subroutine mskdt(d,npts,ty,yellow,nyel) - - parameter (NFFT=1024,NH=NFFT/2) - real d(npts) - real x(0:NFFT-1) - real green(703) - real yellow(703) !703 = 30*12000/512 - real ty(703) - real y2(175) - real ty2(175) - integer indx(703) - logical ok - complex c(0:NH) - equivalence (x,c) - - df=12000.0/NFFT - i1=nint(300.0/df) - i2=nint(800.0/df) - i3=nint(2200.0/df) - i4=nint(2700.0/df) - nblks=npts/NH - 1 - - do j=1,nblks - ib=(j+1)*NH - ia=ib-NFFT+1 - x=d(ia:ib) - call four2a(x,NFFT,1,-1,0) !r2c FFT - sqlow=0. - do i=i1,i2 - sqlow=sqlow + real(c(i))**2 + aimag(c(i))**2 - enddo - sqmid=0. - do i=i2,i3 - sqmid=sqmid + real(c(i))**2 + aimag(c(i))**2 - enddo - sqhigh=0. - do i=i3,i4 - sqhigh=sqhigh + real(c(i))**2 + aimag(c(i))**2 - enddo - green(j)=db(sqlow+sqmid+sqhigh) - yellow(j)=db(sqmid/(sqlow+sqhigh)) - ty(j)=j*512.0/12000.0 - enddo - - npct=20 - call pctile(green,nblks,npct,base) - green(1:nblks)=green(1:nblks) - base - 0.3 - call pctile(yellow,nblks,npct,base) - yellow(1:nblks)=yellow(1:nblks) - base - 0.6 - call indexx(yellow,nblks,indx) - - do j=1,nblks/4 - k=indx(nblks+1-j) - ty(j)=ty(k) - yellow(j)=yellow(k) - if(yellow(j).lt.1.5) exit - enddo - nyel=j-1 - k=1 - y2(1)=yellow(1) - ty2(1)=ty(1) - do j=2,nyel - ok=.true. - do i=1,j-1 - if(abs(ty(i)-ty(j)).lt.0.117) ok=.false. - enddo - if(ok) then - k=k+1 - y2(k)=yellow(j) - ty2(k)=ty(j) - endif - enddo - nyel=k - yellow(1:nyel)=y2(1:nyel) - ty(1:nyel)=ty2(1:nyel) - - return -end subroutine mskdt diff --git a/lib/mskrtd.f90 b/lib/mskrtd.f90 deleted file mode 100644 index 5712c71..0000000 --- a/lib/mskrtd.f90 +++ /dev/null @@ -1,257 +0,0 @@ -subroutine mskrtd(id2,nutc0,tsec,ntol,nrxfreq,ndepth,mycall,mygrid,hiscall, & - bshmsg,bcontest,btrain,pcoeffs,bswl,datadir,line) - -! Real-time decoder for MSK144. -! Analysis block size = NZ = 7168 samples, t_block = 0.597333 s -! Called from hspec() at half-block increments, about 0.3 s - - parameter (NZ=7168) !Block size - parameter (NSPM=864) !Number of samples per message frame - parameter (NFFT1=8192) !FFT size for making analytic signal - parameter (NPATTERNS=4) !Number of frame averaging patterns to try - parameter (NRECENT=10) !Number of recent calls to remember - parameter (NSHMEM=50) !Number of recent SWL messages to remember - - character*4 decsym !"&" for mskspd or "^" for long averages - character*22 msgreceived !Decoded message - character*22 msglast,msglastswl !Used for dupechecking - character*80 line !Formatted line with UTC dB T Freq Msg - character*12 mycall,hiscall - character*6 mygrid - character*12 recent_calls(NRECENT) - character*22 recent_shmsgs(NSHMEM) - character*512 datadir - - complex cdat(NFFT1) !Analytic signal - complex c(NSPM) !Coherently averaged complex data - complex ct(NSPM) - - integer*2 id2(NZ) !Raw 16-bit data - integer iavmask(8) - integer iavpatterns(8,NPATTERNS) - integer npkloc(10) - integer nhasharray(NRECENT,NRECENT) - integer nsnrlast,nsnrlastswl - - real d(NFFT1) - real pow(8) - real softbits(144) - real xmc(NPATTERNS) - real*8 pcoeffs(5) - - logical*1 bshmsg,bcontest,btrain,bswl - logical*1 first - logical*1 bshdecode - logical*1 seenb4 - logical*1 bflag - logical*1 bvar - - data first/.true./ - data iavpatterns/ & - 1,1,1,1,0,0,0,0, & - 0,0,1,1,1,1,0,0, & - 1,1,1,1,1,0,0,0, & - 1,1,1,1,1,1,1,0/ - data xmc/2.0,4.5,2.5,3.5/ !Used to set time at center of averaging mask - save first,tsec0,nutc00,pnoise,cdat,msglast,msglastswl, & - nsnrlast,nsnrlastswl,recent_calls,nhasharray,recent_shmsgs - - if(first) then - tsec0=tsec - nutc00=nutc0 - pnoise=-1.0 - do i=1,nrecent - recent_calls(i)(1:12)=' ' - enddo - do i=1,nshmem - recent_shmsgs(i)(1:22)=' ' - enddo - msglast=' ' - msglastswl=' ' - nsnrlast=-99 - nsnrlastswl=-99 - first=.false. - endif - - fc=nrxfreq - -! Dupe checking setup - if(nutc00.ne.nutc0 .or. tsec.lt.tsec0) then ! reset dupe checker - msglast=' ' - msglastswl=' ' - nsnrlast=-99 - nsnrlastswl=-99 - nutc00=nutc0 - endif - - tframe=float(NSPM)/12000.0 - line=char(0) - msgreceived=' ' - max_iterations=10 - niterations=0 - d(1:NZ)=id2 - rms=sqrt(sum(d(1:NZ)*d(1:NZ))/NZ) - if(rms.lt.1.0) go to 999 - fac=1.0/rms - d(1:NZ)=fac*d(1:NZ) - d(NZ+1:NFFT1)=0. - bvar=.true. - if( btrain ) bvar=.false. ! if training, turn off rx eq - call analytic(d,NZ,NFFT1,cdat,pcoeffs,bvar) - -! Calculate average power for each frame and for the entire block. -! If decode is successful, largest power will be taken as signal+noise. -! If no decode, entire-block average will be used to update noise estimate. - pmax=-99 - do i=1,8 - ib=(i-1)*NSPM+1 - ie=ib+NSPM-1 - pow(i)=real(dot_product(cdat(ib:ie),cdat(ib:ie)))*rms**2 - pmax=max(pmax,pow(i)) - enddo - pavg=sum(pow)/8.0 - -! Short ping decoder uses squared-signal spectrum to determine where to -! center a 3-frame analysis window and attempts to decode each of the -! 3 frames along with 2- and 3-frame averages. - np=8*NSPM - call msk144spd(cdat,np,ntol,ndecodesuccess,msgreceived,fc,fest,tdec,navg,ct, & - softbits,recent_calls,nrecent) - if(ndecodesuccess.eq.0 .and. (bshmsg.or.bswl)) then - call msk40spd(cdat,np,ntol,mycall(1:6),hiscall(1:6),bswl,nhasharray, & - recent_calls,nrecent,ndecodesuccess,msgreceived,fc,fest,tdec,navg) - endif - if( ndecodesuccess .ge. 1 ) then - tdec=tsec+tdec - ipk=0 - is=0 - goto 900 - endif - -! If short ping decoder doesn't find a decode, -! Fast - short ping decoder only. -! Normal - try 4-frame averages -! Deep - try 4-, 5- and 7-frame averages. - npat=NPATTERNS - if( ndepth .eq. 1 ) npat=0 - if( ndepth .eq. 2 ) npat=2 - do iavg=1,npat - iavmask=iavpatterns(1:8,iavg) - navg=sum(iavmask) - deltaf=10.0/real(navg) ! search increment for frequency sync - npeaks=2 - call msk144sync(cdat(1:8*NSPM),8,ntol,deltaf,iavmask,npeaks,fc, & - fest,npkloc,nsyncsuccess,xmax,c) - if( nsyncsuccess .eq. 0 ) cycle - - do ipk=1,npeaks - do is=1,3 - ic0=npkloc(ipk) - if(is.eq.2) ic0=max(1,ic0-1) - if(is.eq.3) ic0=min(NSPM,ic0+1) - ct=cshift(c,ic0-1) - call msk144decodeframe(ct,softbits,msgreceived,ndecodesuccess, & - recent_calls,nrecent) - if(ndecodesuccess .gt. 0) then - tdec=tsec+xmc(iavg)*tframe - goto 900 - endif - enddo !Slicer dither - enddo !Peak loop - enddo - - - msgreceived=' ' - -! no decode - update noise level used for calculating displayed snr. - if( pnoise .lt. 0 ) then ! initialize noise level - pnoise=pavg - elseif( pavg .gt. pnoise ) then ! noise level is slow to rise - pnoise=0.9*pnoise+0.1*pavg - elseif( pavg .lt. pnoise ) then ! and quick to fall - pnoise=pavg - endif - go to 999 - -900 continue -! Successful decode - estimate snr - if( pnoise .gt. 0.0 ) then - snr0=10.0*log10(pmax/pnoise-1.0) - else - snr0=0.0 - endif - nsnr=nint(snr0) - - bshdecode=.false. - if( msgreceived(1:1) .eq. '<' ) bshdecode=.true. - - if(.not. bshdecode) then - call msk144signalquality(ct,snr0,fest,tdec,softbits,msgreceived,hiscall, & - btrain,datadir,ncorrected,eyeopening,pcoeffs) - endif - - decsym=' & ' - if( btrain ) decsym=' ^ ' - if( msgreceived(1:1).eq.'<') then - ncorrected=0 - eyeopening=0.0 - endif - - if( nsnr .lt. -8 ) nsnr=-8 - if( nsnr .gt. 24 ) nsnr=24 - -! Dupe check. - bflag=ndecodesuccess.eq.1 .and. & - (msgreceived.ne.msglast .or. nsnr.gt.nsnrlast .or. tsec.lt.tsec0) - if(bflag) then - msglast=msgreceived - nsnrlast=nsnr - if(.not. bshdecode) then - call update_hasharray(recent_calls,nrecent,nhasharray) - if(bcontest) call fix_contest_msg(mygrid,msgreceived) - endif - write(line,1020) nutc0,nsnr,tdec,nint(fest),decsym,msgreceived, & - navg,ncorrected,eyeopening,char(0) -1020 format(i6.6,i4,f5.1,i5,a4,a22,i2,i3,f5.1,a1) - elseif(bswl .and. ndecodesuccess.ge.2) then - seenb4=.false. - do i=1,nshmem - if( msgreceived .eq. recent_shmsgs(i) ) then - seenb4=.true. - endif - enddo - call update_recent_shmsgs(msgreceived,recent_shmsgs,nshmem) - bflag=seenb4 .and. & - (msgreceived.ne.msglastswl .or. nsnr.gt.nsnrlastswl .or. tsec.lt.tsec0) & - .and. nsnr.gt.-6 - if(bflag) then - msglastswl=msgreceived - nsnrlastswl=nsnr - write(line,1020) nutc0,nsnr,tdec,nint(fest),decsym,msgreceived, & - navg,ncorrected,eyeopening,char(0) - endif - endif -999 tsec0=tsec - - return -end subroutine mskrtd - -subroutine update_recent_shmsgs(message,msgs,nsize) - character*22 msgs(nsize) - character*22 message - logical*1 seen - - seen=.false. - do i=1,nsize - if( msgs(i) .eq. message ) seen=.true. - enddo - - if( .not. seen ) then - do i=nsize,2,-1 - msgs(i)=msgs(i-1) - enddo - msgs(1)=message - endif - - return -end subroutine update_recent_shmsgs diff --git a/lib/wsprd/nhash.c b/lib/nhash.c similarity index 100% rename from lib/wsprd/nhash.c rename to lib/nhash.c diff --git a/lib/wsprd/nhash.h b/lib/nhash.h similarity index 100% rename from lib/wsprd/nhash.h rename to lib/nhash.h diff --git a/lib/packjt.f90 b/lib/packjt.f90 index faefe7b..de76813 100644 --- a/lib/packjt.f90 +++ b/lib/packjt.f90 @@ -660,8 +660,6 @@ subroutine packbits(dbits,nsymd,m0,sym) msg(4:4).ge.'A' .and. msg(4:4).le.'Z' .and. & msg(5:5).eq.' ') msg='CQ '//msg(3:) - if(bcontest) call fix_contest_msg(mygrid,msg) - if(msg(1:5).eq.'CQ 00' .and. msg(6:6).ge.'0' .and. & msg(6:6).le.'9') msg='CQ '//msg(6:) diff --git a/lib/qra/qra64/Makefile.Win b/lib/qra/qra64/Makefile.Win deleted file mode 100644 index 7bd10c2..0000000 --- a/lib/qra/qra64/Makefile.Win +++ /dev/null @@ -1,30 +0,0 @@ -FC = gfortran -CC = gcc -CFLAGS = -O2 -Wall -I. -D_WIN32 - -# Default rules -%.o: %.c - ${CC} ${CFLAGS} -c $< -%.o: %.f - ${FC} ${FFLAGS} -c $< -%.o: %.F - ${FC} ${FFLAGS} -c $< -%.o: %.f90 - ${FC} ${FFLAGS} -c $< -%.o: %.F90 - ${FC} ${FFLAGS} -c $< - -all: qra64.exe - -OBJS1 = main.o qra64.o -qra64.exe: $(OBJS1) - ${CC} -o qra64.exe $(OBJS1) ../qracodes/libqra64.a -lm - -OBJS2 = qra64sim.o options.o wavhdr.o -qra64sim.exe: $(OBJS2) - ${FC} -o qra64sim.exe $(OBJS2) ../qracodes/libqra64.a -lm - -.PHONY : clean - -clean: - $(RM) *.o qra64.exe qra64sim.exe diff --git a/lib/qra/qra64/fadengauss.c b/lib/qra/qra64/fadengauss.c deleted file mode 100644 index c229626..0000000 --- a/lib/qra/qra64/fadengauss.c +++ /dev/null @@ -1,302 +0,0 @@ -// Gaussian energy fading tables for QRA64 -static const int glen_tab_gauss[64] = { - 2, 2, 2, 2, 2, 2, 2, 2, - 2, 2, 2, 2, 2, 2, 2, 2, - 3, 3, 3, 3, 3, 3, 3, 3, - 4, 4, 4, 4, 5, 5, 5, 6, - 6, 6, 7, 7, 8, 8, 9, 10, - 10, 11, 12, 13, 14, 15, 17, 18, - 19, 21, 23, 25, 27, 29, 32, 34, - 37, 41, 44, 48, 52, 57, 62, 65 -}; -static const float ggauss1[2] = { -0.0296f, 0.9101f -}; -static const float ggauss2[2] = { -0.0350f, 0.8954f -}; -static const float ggauss3[2] = { -0.0411f, 0.8787f -}; -static const float ggauss4[2] = { -0.0483f, 0.8598f -}; -static const float ggauss5[2] = { -0.0566f, 0.8387f -}; -static const float ggauss6[2] = { -0.0660f, 0.8154f -}; -static const float ggauss7[2] = { -0.0767f, 0.7898f -}; -static const float ggauss8[2] = { -0.0886f, 0.7621f -}; -static const float ggauss9[2] = { -0.1017f, 0.7325f -}; -static const float ggauss10[2] = { -0.1159f, 0.7012f -}; -static const float ggauss11[2] = { -0.1310f, 0.6687f -}; -static const float ggauss12[2] = { -0.1465f, 0.6352f -}; -static const float ggauss13[2] = { -0.1621f, 0.6013f -}; -static const float ggauss14[2] = { -0.1771f, 0.5674f -}; -static const float ggauss15[2] = { -0.1911f, 0.5339f -}; -static const float ggauss16[2] = { -0.2034f, 0.5010f -}; -static const float ggauss17[3] = { -0.0299f, 0.2135f, 0.4690f -}; -static const float ggauss18[3] = { -0.0369f, 0.2212f, 0.4383f -}; -static const float ggauss19[3] = { -0.0454f, 0.2263f, 0.4088f -}; -static const float ggauss20[3] = { -0.0552f, 0.2286f, 0.3806f -}; -static const float ggauss21[3] = { -0.0658f, 0.2284f, 0.3539f -}; -static const float ggauss22[3] = { -0.0766f, 0.2258f, 0.3287f -}; -static const float ggauss23[3] = { -0.0869f, 0.2212f, 0.3049f -}; -static const float ggauss24[3] = { -0.0962f, 0.2148f, 0.2826f -}; -static const float ggauss25[4] = { -0.0351f, 0.1041f, 0.2071f, 0.2616f -}; -static const float ggauss26[4] = { -0.0429f, 0.1102f, 0.1984f, 0.2420f -}; -static const float ggauss27[4] = { -0.0508f, 0.1145f, 0.1890f, 0.2237f -}; -static const float ggauss28[4] = { -0.0582f, 0.1169f, 0.1791f, 0.2067f -}; -static const float ggauss29[5] = { -0.0289f, 0.0648f, 0.1176f, 0.1689f, 0.1908f -}; -static const float ggauss30[5] = { -0.0351f, 0.0703f, 0.1168f, 0.1588f, 0.1760f -}; -static const float ggauss31[5] = { -0.0411f, 0.0745f, 0.1146f, 0.1488f, 0.1623f -}; -static const float ggauss32[6] = { -0.0246f, 0.0466f, 0.0773f, 0.1115f, 0.1390f, 0.1497f -}; -static const float ggauss33[6] = { -0.0297f, 0.0512f, 0.0788f, 0.1075f, 0.1295f, 0.1379f -}; -static const float ggauss34[6] = { -0.0345f, 0.0549f, 0.0791f, 0.1029f, 0.1205f, 0.1270f -}; -static const float ggauss35[7] = { -0.0240f, 0.0387f, 0.0575f, 0.0784f, 0.0979f, 0.1118f, 0.1169f -}; -static const float ggauss36[7] = { -0.0281f, 0.0422f, 0.0590f, 0.0767f, 0.0926f, 0.1037f, 0.1076f -}; -static const float ggauss37[8] = { -0.0212f, 0.0318f, 0.0449f, 0.0596f, 0.0744f, 0.0872f, 0.0960f, 0.0991f -}; -static const float ggauss38[8] = { -0.0247f, 0.0348f, 0.0467f, 0.0593f, 0.0716f, 0.0819f, 0.0887f, 0.0911f -}; -static const float ggauss39[9] = { -0.0199f, 0.0278f, 0.0372f, 0.0476f, 0.0584f, 0.0684f, 0.0766f, 0.0819f, -0.0838f -}; -static const float ggauss40[10] = { -0.0166f, 0.0228f, 0.0303f, 0.0388f, 0.0478f, 0.0568f, 0.0649f, 0.0714f, -0.0756f, 0.0771f -}; -static const float ggauss41[10] = { -0.0193f, 0.0254f, 0.0322f, 0.0397f, 0.0474f, 0.0548f, 0.0613f, 0.0664f, -0.0697f, 0.0709f -}; -static const float ggauss42[11] = { -0.0168f, 0.0217f, 0.0273f, 0.0335f, 0.0399f, 0.0464f, 0.0524f, 0.0576f, -0.0617f, 0.0643f, 0.0651f -}; -static const float ggauss43[12] = { -0.0151f, 0.0191f, 0.0237f, 0.0288f, 0.0342f, 0.0396f, 0.0449f, 0.0498f, -0.0540f, 0.0572f, 0.0592f, 0.0599f -}; -static const float ggauss44[13] = { -0.0138f, 0.0171f, 0.0210f, 0.0252f, 0.0297f, 0.0343f, 0.0388f, 0.0432f, -0.0471f, 0.0504f, 0.0529f, 0.0545f, 0.0550f -}; -static const float ggauss45[14] = { -0.0128f, 0.0157f, 0.0189f, 0.0224f, 0.0261f, 0.0300f, 0.0339f, 0.0377f, -0.0412f, 0.0444f, 0.0470f, 0.0489f, 0.0501f, 0.0505f -}; -static const float ggauss46[15] = { -0.0121f, 0.0146f, 0.0173f, 0.0202f, 0.0234f, 0.0266f, 0.0299f, 0.0332f, -0.0363f, 0.0391f, 0.0416f, 0.0437f, 0.0452f, 0.0461f, 0.0464f -}; -static const float ggauss47[17] = { -0.0097f, 0.0116f, 0.0138f, 0.0161f, 0.0186f, 0.0212f, 0.0239f, 0.0267f, -0.0294f, 0.0321f, 0.0346f, 0.0369f, 0.0389f, 0.0405f, 0.0417f, 0.0424f, -0.0427f -}; -static const float ggauss48[18] = { -0.0096f, 0.0113f, 0.0131f, 0.0151f, 0.0172f, 0.0194f, 0.0217f, 0.0241f, -0.0264f, 0.0287f, 0.0308f, 0.0329f, 0.0347f, 0.0362f, 0.0375f, 0.0384f, -0.0390f, 0.0392f -}; -static const float ggauss49[19] = { -0.0095f, 0.0110f, 0.0126f, 0.0143f, 0.0161f, 0.0180f, 0.0199f, 0.0219f, -0.0239f, 0.0258f, 0.0277f, 0.0294f, 0.0310f, 0.0325f, 0.0337f, 0.0347f, -0.0354f, 0.0358f, 0.0360f -}; -static const float ggauss50[21] = { -0.0083f, 0.0095f, 0.0108f, 0.0122f, 0.0136f, 0.0152f, 0.0168f, 0.0184f, -0.0201f, 0.0217f, 0.0234f, 0.0250f, 0.0265f, 0.0279f, 0.0292f, 0.0303f, -0.0313f, 0.0320f, 0.0326f, 0.0329f, 0.0330f -}; -static const float ggauss51[23] = { -0.0074f, 0.0084f, 0.0095f, 0.0106f, 0.0118f, 0.0131f, 0.0144f, 0.0157f, -0.0171f, 0.0185f, 0.0199f, 0.0213f, 0.0227f, 0.0240f, 0.0252f, 0.0263f, -0.0273f, 0.0282f, 0.0290f, 0.0296f, 0.0300f, 0.0303f, 0.0303f -}; -static const float ggauss52[25] = { -0.0068f, 0.0076f, 0.0085f, 0.0094f, 0.0104f, 0.0115f, 0.0126f, 0.0137f, -0.0149f, 0.0160f, 0.0172f, 0.0184f, 0.0196f, 0.0207f, 0.0218f, 0.0228f, -0.0238f, 0.0247f, 0.0255f, 0.0262f, 0.0268f, 0.0273f, 0.0276f, 0.0278f, -0.0279f -}; -static const float ggauss53[27] = { -0.0063f, 0.0070f, 0.0078f, 0.0086f, 0.0094f, 0.0103f, 0.0112f, 0.0121f, -0.0131f, 0.0141f, 0.0151f, 0.0161f, 0.0170f, 0.0180f, 0.0190f, 0.0199f, -0.0208f, 0.0216f, 0.0224f, 0.0231f, 0.0237f, 0.0243f, 0.0247f, 0.0251f, -0.0254f, 0.0255f, 0.0256f -}; -static const float ggauss54[29] = { -0.0060f, 0.0066f, 0.0072f, 0.0079f, 0.0086f, 0.0093f, 0.0101f, 0.0109f, -0.0117f, 0.0125f, 0.0133f, 0.0142f, 0.0150f, 0.0159f, 0.0167f, 0.0175f, -0.0183f, 0.0190f, 0.0197f, 0.0204f, 0.0210f, 0.0216f, 0.0221f, 0.0225f, -0.0228f, 0.0231f, 0.0233f, 0.0234f, 0.0235f -}; -static const float ggauss55[32] = { -0.0053f, 0.0058f, 0.0063f, 0.0068f, 0.0074f, 0.0080f, 0.0086f, 0.0093f, -0.0099f, 0.0106f, 0.0113f, 0.0120f, 0.0127f, 0.0134f, 0.0141f, 0.0148f, -0.0155f, 0.0162f, 0.0168f, 0.0174f, 0.0180f, 0.0186f, 0.0191f, 0.0196f, -0.0201f, 0.0204f, 0.0208f, 0.0211f, 0.0213f, 0.0214f, 0.0215f, 0.0216f -}; -static const float ggauss56[34] = { -0.0052f, 0.0056f, 0.0060f, 0.0065f, 0.0070f, 0.0075f, 0.0080f, 0.0086f, -0.0091f, 0.0097f, 0.0103f, 0.0109f, 0.0115f, 0.0121f, 0.0127f, 0.0133f, -0.0138f, 0.0144f, 0.0150f, 0.0155f, 0.0161f, 0.0166f, 0.0170f, 0.0175f, -0.0179f, 0.0183f, 0.0186f, 0.0189f, 0.0192f, 0.0194f, 0.0196f, 0.0197f, -0.0198f, 0.0198f -}; -static const float ggauss57[37] = { -0.0047f, 0.0051f, 0.0055f, 0.0058f, 0.0063f, 0.0067f, 0.0071f, 0.0076f, -0.0080f, 0.0085f, 0.0090f, 0.0095f, 0.0100f, 0.0105f, 0.0110f, 0.0115f, -0.0120f, 0.0125f, 0.0130f, 0.0134f, 0.0139f, 0.0144f, 0.0148f, 0.0152f, -0.0156f, 0.0160f, 0.0164f, 0.0167f, 0.0170f, 0.0173f, 0.0175f, 0.0177f, -0.0179f, 0.0180f, 0.0181f, 0.0181f, 0.0182f -}; -static const float ggauss58[41] = { -0.0041f, 0.0044f, 0.0047f, 0.0050f, 0.0054f, 0.0057f, 0.0060f, 0.0064f, -0.0068f, 0.0072f, 0.0076f, 0.0080f, 0.0084f, 0.0088f, 0.0092f, 0.0096f, -0.0101f, 0.0105f, 0.0109f, 0.0113f, 0.0117f, 0.0121f, 0.0125f, 0.0129f, -0.0133f, 0.0137f, 0.0140f, 0.0144f, 0.0147f, 0.0150f, 0.0153f, 0.0155f, -0.0158f, 0.0160f, 0.0162f, 0.0163f, 0.0164f, 0.0165f, 0.0166f, 0.0167f, -0.0167f -}; -static const float ggauss59[44] = { -0.0039f, 0.0042f, 0.0044f, 0.0047f, 0.0050f, 0.0053f, 0.0056f, 0.0059f, -0.0062f, 0.0065f, 0.0068f, 0.0072f, 0.0075f, 0.0079f, 0.0082f, 0.0086f, -0.0089f, 0.0093f, 0.0096f, 0.0100f, 0.0104f, 0.0107f, 0.0110f, 0.0114f, -0.0117f, 0.0120f, 0.0124f, 0.0127f, 0.0130f, 0.0132f, 0.0135f, 0.0138f, -0.0140f, 0.0142f, 0.0144f, 0.0146f, 0.0148f, 0.0149f, 0.0150f, 0.0151f, -0.0152f, 0.0153f, 0.0153f, 0.0153f -}; -static const float ggauss60[48] = { -0.0036f, 0.0038f, 0.0040f, 0.0042f, 0.0044f, 0.0047f, 0.0049f, 0.0052f, -0.0055f, 0.0057f, 0.0060f, 0.0063f, 0.0066f, 0.0068f, 0.0071f, 0.0074f, -0.0077f, 0.0080f, 0.0083f, 0.0086f, 0.0089f, 0.0092f, 0.0095f, 0.0098f, -0.0101f, 0.0104f, 0.0107f, 0.0109f, 0.0112f, 0.0115f, 0.0117f, 0.0120f, -0.0122f, 0.0124f, 0.0126f, 0.0128f, 0.0130f, 0.0132f, 0.0134f, 0.0135f, -0.0136f, 0.0137f, 0.0138f, 0.0139f, 0.0140f, 0.0140f, 0.0140f, 0.0140f -}; -static const float ggauss61[52] = { -0.0033f, 0.0035f, 0.0037f, 0.0039f, 0.0041f, 0.0043f, 0.0045f, 0.0047f, -0.0049f, 0.0051f, 0.0053f, 0.0056f, 0.0058f, 0.0060f, 0.0063f, 0.0065f, -0.0068f, 0.0070f, 0.0073f, 0.0075f, 0.0078f, 0.0080f, 0.0083f, 0.0085f, -0.0088f, 0.0090f, 0.0093f, 0.0095f, 0.0098f, 0.0100f, 0.0102f, 0.0105f, -0.0107f, 0.0109f, 0.0111f, 0.0113f, 0.0115f, 0.0116f, 0.0118f, 0.0120f, -0.0121f, 0.0122f, 0.0124f, 0.0125f, 0.0126f, 0.0126f, 0.0127f, 0.0128f, -0.0128f, 0.0129f, 0.0129f, 0.0129f -}; -static const float ggauss62[57] = { -0.0030f, 0.0031f, 0.0033f, 0.0034f, 0.0036f, 0.0038f, 0.0039f, 0.0041f, -0.0043f, 0.0045f, 0.0047f, 0.0048f, 0.0050f, 0.0052f, 0.0054f, 0.0056f, -0.0058f, 0.0060f, 0.0063f, 0.0065f, 0.0067f, 0.0069f, 0.0071f, 0.0073f, -0.0075f, 0.0077f, 0.0080f, 0.0082f, 0.0084f, 0.0086f, 0.0088f, 0.0090f, -0.0092f, 0.0094f, 0.0096f, 0.0097f, 0.0099f, 0.0101f, 0.0103f, 0.0104f, -0.0106f, 0.0107f, 0.0108f, 0.0110f, 0.0111f, 0.0112f, 0.0113f, 0.0114f, -0.0115f, 0.0116f, 0.0116f, 0.0117f, 0.0117f, 0.0118f, 0.0118f, 0.0118f, -0.0118f -}; -static const float ggauss63[62] = { -0.0027f, 0.0029f, 0.0030f, 0.0031f, 0.0032f, 0.0034f, 0.0035f, 0.0037f, -0.0038f, 0.0040f, 0.0041f, 0.0043f, 0.0045f, 0.0046f, 0.0048f, 0.0049f, -0.0051f, 0.0053f, 0.0055f, 0.0056f, 0.0058f, 0.0060f, 0.0062f, 0.0063f, -0.0065f, 0.0067f, 0.0069f, 0.0071f, 0.0072f, 0.0074f, 0.0076f, 0.0078f, -0.0079f, 0.0081f, 0.0083f, 0.0084f, 0.0086f, 0.0088f, 0.0089f, 0.0091f, -0.0092f, 0.0094f, 0.0095f, 0.0096f, 0.0098f, 0.0099f, 0.0100f, 0.0101f, -0.0102f, 0.0103f, 0.0104f, 0.0105f, 0.0105f, 0.0106f, 0.0107f, 0.0107f, -0.0108f, 0.0108f, 0.0108f, 0.0108f, 0.0109f, 0.0109f -}; -static const float ggauss64[65] = { -0.0028f, 0.0029f, 0.0030f, 0.0031f, 0.0032f, 0.0034f, 0.0035f, 0.0036f, -0.0037f, 0.0039f, 0.0040f, 0.0041f, 0.0043f, 0.0044f, 0.0046f, 0.0047f, -0.0048f, 0.0050f, 0.0051f, 0.0053f, 0.0054f, 0.0056f, 0.0057f, 0.0059f, -0.0060f, 0.0062f, 0.0063f, 0.0065f, 0.0066f, 0.0068f, 0.0069f, 0.0071f, -0.0072f, 0.0074f, 0.0075f, 0.0077f, 0.0078f, 0.0079f, 0.0081f, 0.0082f, -0.0083f, 0.0084f, 0.0086f, 0.0087f, 0.0088f, 0.0089f, 0.0090f, 0.0091f, -0.0092f, 0.0093f, 0.0094f, 0.0094f, 0.0095f, 0.0096f, 0.0097f, 0.0097f, -0.0098f, 0.0098f, 0.0099f, 0.0099f, 0.0099f, 0.0099f, 0.0100f, 0.0100f, -0.0100f -}; -static const float *gptr_tab_gauss[64] = { -ggauss1, ggauss2, ggauss3, ggauss4, -ggauss5, ggauss6, ggauss7, ggauss8, -ggauss9, ggauss10, ggauss11, ggauss12, -ggauss13, ggauss14, ggauss15, ggauss16, -ggauss17, ggauss18, ggauss19, ggauss20, -ggauss21, ggauss22, ggauss23, ggauss24, -ggauss25, ggauss26, ggauss27, ggauss28, -ggauss29, ggauss30, ggauss31, ggauss32, -ggauss33, ggauss34, ggauss35, ggauss36, -ggauss37, ggauss38, ggauss39, ggauss40, -ggauss41, ggauss42, ggauss43, ggauss44, -ggauss45, ggauss46, ggauss47, ggauss48, -ggauss49, ggauss50, ggauss51, ggauss52, -ggauss53, ggauss54, ggauss55, ggauss56, -ggauss57, ggauss58, ggauss59, ggauss60, -ggauss61, ggauss62, ggauss63, ggauss64 -}; diff --git a/lib/qra/qra64/fadenlorentz.c b/lib/qra/qra64/fadenlorentz.c deleted file mode 100644 index 673a890..0000000 --- a/lib/qra/qra64/fadenlorentz.c +++ /dev/null @@ -1,304 +0,0 @@ -// Lorentz energy fading tables for QRA64 -static const int glen_tab_lorentz[64] = { - 2, 2, 2, 2, 2, 2, 2, 2, - 2, 2, 2, 2, 2, 2, 3, 3, - 3, 3, 3, 3, 3, 4, 4, 4, - 4, 4, 5, 5, 5, 5, 6, 6, - 7, 7, 7, 8, 8, 9, 10, 10, - 11, 12, 13, 14, 15, 16, 17, 19, - 20, 22, 23, 25, 27, 30, 32, 35, - 38, 41, 45, 49, 53, 57, 62, 65 -}; -static const float glorentz1[2] = { -0.0214f, 0.9107f -}; -static const float glorentz2[2] = { -0.0244f, 0.9030f -}; -static const float glorentz3[2] = { -0.0280f, 0.8950f -}; -static const float glorentz4[2] = { -0.0314f, 0.8865f -}; -static const float glorentz5[2] = { -0.0349f, 0.8773f -}; -static const float glorentz6[2] = { -0.0388f, 0.8675f -}; -static const float glorentz7[2] = { -0.0426f, 0.8571f -}; -static const float glorentz8[2] = { -0.0463f, 0.8459f -}; -static const float glorentz9[2] = { -0.0500f, 0.8339f -}; -static const float glorentz10[2] = { -0.0538f, 0.8210f -}; -static const float glorentz11[2] = { -0.0579f, 0.8074f -}; -static const float glorentz12[2] = { -0.0622f, 0.7930f -}; -static const float glorentz13[2] = { -0.0668f, 0.7777f -}; -static const float glorentz14[2] = { -0.0715f, 0.7616f -}; -static const float glorentz15[3] = { -0.0196f, 0.0765f, 0.7445f -}; -static const float glorentz16[3] = { -0.0210f, 0.0816f, 0.7267f -}; -static const float glorentz17[3] = { -0.0226f, 0.0870f, 0.7080f -}; -static const float glorentz18[3] = { -0.0242f, 0.0925f, 0.6885f -}; -static const float glorentz19[3] = { -0.0259f, 0.0981f, 0.6682f -}; -static const float glorentz20[3] = { -0.0277f, 0.1039f, 0.6472f -}; -static const float glorentz21[3] = { -0.0296f, 0.1097f, 0.6255f -}; -static const float glorentz22[4] = { -0.0143f, 0.0316f, 0.1155f, 0.6031f -}; -static const float glorentz23[4] = { -0.0153f, 0.0337f, 0.1213f, 0.5803f -}; -static const float glorentz24[4] = { -0.0163f, 0.0358f, 0.1270f, 0.5570f -}; -static const float glorentz25[4] = { -0.0174f, 0.0381f, 0.1325f, 0.5333f -}; -static const float glorentz26[4] = { -0.0186f, 0.0405f, 0.1378f, 0.5095f -}; -static const float glorentz27[5] = { -0.0113f, 0.0198f, 0.0429f, 0.1428f, 0.4855f -}; -static const float glorentz28[5] = { -0.0120f, 0.0211f, 0.0455f, 0.1473f, 0.4615f -}; -static const float glorentz29[5] = { -0.0129f, 0.0225f, 0.0481f, 0.1514f, 0.4376f -}; -static const float glorentz30[5] = { -0.0137f, 0.0239f, 0.0508f, 0.1549f, 0.4140f -}; -static const float glorentz31[6] = { -0.0095f, 0.0147f, 0.0254f, 0.0536f, 0.1578f, 0.3907f -}; -static const float glorentz32[6] = { -0.0101f, 0.0156f, 0.0270f, 0.0564f, 0.1600f, 0.3680f -}; -static const float glorentz33[7] = { -0.0076f, 0.0109f, 0.0167f, 0.0287f, 0.0592f, 0.1614f, 0.3458f -}; -static const float glorentz34[7] = { -0.0081f, 0.0116f, 0.0178f, 0.0305f, 0.0621f, 0.1620f, 0.3243f -}; -static const float glorentz35[7] = { -0.0087f, 0.0124f, 0.0190f, 0.0324f, 0.0649f, 0.1618f, 0.3035f -}; -static const float glorentz36[8] = { -0.0069f, 0.0093f, 0.0133f, 0.0203f, 0.0343f, 0.0676f, 0.1607f, 0.2836f -}; -static const float glorentz37[8] = { -0.0074f, 0.0100f, 0.0142f, 0.0216f, 0.0362f, 0.0702f, 0.1588f, 0.2645f -}; -static const float glorentz38[9] = { -0.0061f, 0.0080f, 0.0107f, 0.0152f, 0.0230f, 0.0382f, 0.0726f, 0.1561f, -0.2464f -}; -static const float glorentz39[10] = { -0.0052f, 0.0066f, 0.0086f, 0.0115f, 0.0162f, 0.0244f, 0.0402f, 0.0747f, -0.1526f, 0.2291f -}; -static const float glorentz40[10] = { -0.0056f, 0.0071f, 0.0092f, 0.0123f, 0.0173f, 0.0259f, 0.0422f, 0.0766f, -0.1484f, 0.2128f -}; -static const float glorentz41[11] = { -0.0049f, 0.0061f, 0.0076f, 0.0098f, 0.0132f, 0.0184f, 0.0274f, 0.0441f, -0.0780f, 0.1437f, 0.1975f -}; -static const float glorentz42[12] = { -0.0044f, 0.0053f, 0.0065f, 0.0082f, 0.0106f, 0.0141f, 0.0196f, 0.0290f, -0.0460f, 0.0791f, 0.1384f, 0.1831f -}; -static const float glorentz43[13] = { -0.0040f, 0.0048f, 0.0057f, 0.0070f, 0.0088f, 0.0113f, 0.0150f, 0.0209f, -0.0305f, 0.0477f, 0.0797f, 0.1327f, 0.1695f -}; -static const float glorentz44[14] = { -0.0037f, 0.0043f, 0.0051f, 0.0062f, 0.0075f, 0.0094f, 0.0121f, 0.0160f, -0.0221f, 0.0321f, 0.0493f, 0.0799f, 0.1267f, 0.1568f -}; -static const float glorentz45[15] = { -0.0035f, 0.0040f, 0.0047f, 0.0055f, 0.0066f, 0.0081f, 0.0101f, 0.0129f, -0.0171f, 0.0234f, 0.0335f, 0.0506f, 0.0795f, 0.1204f, 0.1450f -}; -static const float glorentz46[16] = { -0.0033f, 0.0037f, 0.0043f, 0.0050f, 0.0059f, 0.0071f, 0.0087f, 0.0108f, -0.0138f, 0.0181f, 0.0246f, 0.0349f, 0.0517f, 0.0786f, 0.1141f, 0.1340f -}; -static const float glorentz47[17] = { -0.0031f, 0.0035f, 0.0040f, 0.0046f, 0.0054f, 0.0064f, 0.0077f, 0.0093f, -0.0116f, 0.0147f, 0.0192f, 0.0259f, 0.0362f, 0.0525f, 0.0773f, 0.1076f, -0.1237f -}; -static const float glorentz48[19] = { -0.0027f, 0.0030f, 0.0034f, 0.0038f, 0.0043f, 0.0050f, 0.0058f, 0.0069f, -0.0082f, 0.0100f, 0.0123f, 0.0156f, 0.0203f, 0.0271f, 0.0374f, 0.0530f, -0.0755f, 0.1013f, 0.1141f -}; -static const float glorentz49[20] = { -0.0026f, 0.0029f, 0.0032f, 0.0036f, 0.0041f, 0.0047f, 0.0054f, 0.0063f, -0.0074f, 0.0088f, 0.0107f, 0.0131f, 0.0165f, 0.0213f, 0.0282f, 0.0383f, -0.0531f, 0.0734f, 0.0950f, 0.1053f -}; -static const float glorentz50[22] = { -0.0023f, 0.0025f, 0.0028f, 0.0031f, 0.0035f, 0.0039f, 0.0044f, 0.0050f, -0.0058f, 0.0067f, 0.0079f, 0.0094f, 0.0114f, 0.0139f, 0.0175f, 0.0223f, -0.0292f, 0.0391f, 0.0529f, 0.0709f, 0.0889f, 0.0971f -}; -static const float glorentz51[23] = { -0.0023f, 0.0025f, 0.0027f, 0.0030f, 0.0034f, 0.0037f, 0.0042f, 0.0048f, -0.0054f, 0.0062f, 0.0072f, 0.0085f, 0.0100f, 0.0121f, 0.0148f, 0.0184f, -0.0233f, 0.0301f, 0.0396f, 0.0524f, 0.0681f, 0.0829f, 0.0894f -}; -static const float glorentz52[25] = { -0.0021f, 0.0023f, 0.0025f, 0.0027f, 0.0030f, 0.0033f, 0.0036f, 0.0040f, -0.0045f, 0.0051f, 0.0058f, 0.0067f, 0.0077f, 0.0090f, 0.0107f, 0.0128f, -0.0156f, 0.0192f, 0.0242f, 0.0308f, 0.0398f, 0.0515f, 0.0650f, 0.0772f, -0.0824f -}; -static const float glorentz53[27] = { -0.0019f, 0.0021f, 0.0022f, 0.0024f, 0.0027f, 0.0029f, 0.0032f, 0.0035f, -0.0039f, 0.0044f, 0.0049f, 0.0055f, 0.0062f, 0.0072f, 0.0083f, 0.0096f, -0.0113f, 0.0135f, 0.0164f, 0.0201f, 0.0249f, 0.0314f, 0.0398f, 0.0502f, -0.0619f, 0.0718f, 0.0759f -}; -static const float glorentz54[30] = { -0.0017f, 0.0018f, 0.0019f, 0.0021f, 0.0022f, 0.0024f, 0.0026f, 0.0029f, -0.0031f, 0.0034f, 0.0038f, 0.0042f, 0.0047f, 0.0052f, 0.0059f, 0.0067f, -0.0076f, 0.0088f, 0.0102f, 0.0120f, 0.0143f, 0.0171f, 0.0208f, 0.0256f, -0.0317f, 0.0395f, 0.0488f, 0.0586f, 0.0666f, 0.0698f -}; -static const float glorentz55[32] = { -0.0016f, 0.0017f, 0.0018f, 0.0019f, 0.0021f, 0.0022f, 0.0024f, 0.0026f, -0.0028f, 0.0031f, 0.0034f, 0.0037f, 0.0041f, 0.0045f, 0.0050f, 0.0056f, -0.0063f, 0.0071f, 0.0081f, 0.0094f, 0.0108f, 0.0127f, 0.0149f, 0.0178f, -0.0214f, 0.0261f, 0.0318f, 0.0389f, 0.0470f, 0.0553f, 0.0618f, 0.0643f -}; -static const float glorentz56[35] = { -0.0014f, 0.0015f, 0.0016f, 0.0017f, 0.0018f, 0.0020f, 0.0021f, 0.0023f, -0.0024f, 0.0026f, 0.0028f, 0.0031f, 0.0033f, 0.0036f, 0.0040f, 0.0044f, -0.0049f, 0.0054f, 0.0060f, 0.0067f, 0.0076f, 0.0087f, 0.0099f, 0.0114f, -0.0133f, 0.0156f, 0.0184f, 0.0220f, 0.0264f, 0.0318f, 0.0381f, 0.0451f, -0.0520f, 0.0572f, 0.0591f -}; -static const float glorentz57[38] = { -0.0013f, 0.0014f, 0.0015f, 0.0016f, 0.0017f, 0.0018f, 0.0019f, 0.0020f, -0.0021f, 0.0023f, 0.0024f, 0.0026f, 0.0028f, 0.0031f, 0.0033f, 0.0036f, -0.0039f, 0.0043f, 0.0047f, 0.0052f, 0.0058f, 0.0064f, 0.0072f, 0.0081f, -0.0092f, 0.0104f, 0.0120f, 0.0139f, 0.0162f, 0.0190f, 0.0224f, 0.0265f, -0.0315f, 0.0371f, 0.0431f, 0.0487f, 0.0529f, 0.0544f -}; -static const float glorentz58[41] = { -0.0012f, 0.0013f, 0.0014f, 0.0014f, 0.0015f, 0.0016f, 0.0017f, 0.0018f, -0.0019f, 0.0020f, 0.0022f, 0.0023f, 0.0025f, 0.0026f, 0.0028f, 0.0030f, -0.0033f, 0.0036f, 0.0039f, 0.0042f, 0.0046f, 0.0050f, 0.0056f, 0.0061f, -0.0068f, 0.0076f, 0.0086f, 0.0097f, 0.0110f, 0.0125f, 0.0144f, 0.0167f, -0.0194f, 0.0226f, 0.0265f, 0.0309f, 0.0359f, 0.0409f, 0.0455f, 0.0488f, -0.0500f -}; -static const float glorentz59[45] = { -0.0011f, 0.0012f, 0.0012f, 0.0013f, 0.0013f, 0.0014f, 0.0015f, 0.0016f, -0.0016f, 0.0017f, 0.0018f, 0.0019f, 0.0021f, 0.0022f, 0.0023f, 0.0025f, -0.0026f, 0.0028f, 0.0030f, 0.0033f, 0.0035f, 0.0038f, 0.0041f, 0.0045f, -0.0049f, 0.0054f, 0.0059f, 0.0065f, 0.0072f, 0.0081f, 0.0090f, 0.0102f, -0.0115f, 0.0130f, 0.0149f, 0.0171f, 0.0197f, 0.0227f, 0.0263f, 0.0302f, -0.0345f, 0.0387f, 0.0425f, 0.0451f, 0.0460f -}; -static const float glorentz60[49] = { -0.0010f, 0.0011f, 0.0011f, 0.0012f, 0.0012f, 0.0013f, 0.0013f, 0.0014f, -0.0014f, 0.0015f, 0.0016f, 0.0017f, 0.0018f, 0.0019f, 0.0020f, 0.0021f, -0.0022f, 0.0024f, 0.0025f, 0.0027f, 0.0028f, 0.0030f, 0.0033f, 0.0035f, -0.0038f, 0.0041f, 0.0044f, 0.0048f, 0.0052f, 0.0057f, 0.0063f, 0.0069f, -0.0077f, 0.0085f, 0.0095f, 0.0106f, 0.0119f, 0.0135f, 0.0153f, 0.0174f, -0.0199f, 0.0227f, 0.0259f, 0.0293f, 0.0330f, 0.0365f, 0.0395f, 0.0415f, -0.0423f -}; -static const float glorentz61[53] = { -0.0009f, 0.0010f, 0.0010f, 0.0011f, 0.0011f, 0.0011f, 0.0012f, 0.0012f, -0.0013f, 0.0014f, 0.0014f, 0.0015f, 0.0016f, 0.0016f, 0.0017f, 0.0018f, -0.0019f, 0.0020f, 0.0021f, 0.0023f, 0.0024f, 0.0025f, 0.0027f, 0.0029f, -0.0031f, 0.0033f, 0.0035f, 0.0038f, 0.0041f, 0.0044f, 0.0047f, 0.0051f, -0.0056f, 0.0061f, 0.0067f, 0.0073f, 0.0081f, 0.0089f, 0.0099f, 0.0110f, -0.0124f, 0.0139f, 0.0156f, 0.0176f, 0.0199f, 0.0225f, 0.0253f, 0.0283f, -0.0314f, 0.0343f, 0.0367f, 0.0383f, 0.0389f -}; -static const float glorentz62[57] = { -0.0009f, 0.0009f, 0.0009f, 0.0010f, 0.0010f, 0.0011f, 0.0011f, 0.0011f, -0.0012f, 0.0012f, 0.0013f, 0.0013f, 0.0014f, 0.0015f, 0.0015f, 0.0016f, -0.0017f, 0.0018f, 0.0019f, 0.0020f, 0.0021f, 0.0022f, 0.0023f, 0.0024f, -0.0026f, 0.0027f, 0.0029f, 0.0031f, 0.0033f, 0.0035f, 0.0038f, 0.0040f, -0.0043f, 0.0047f, 0.0050f, 0.0055f, 0.0059f, 0.0064f, 0.0070f, 0.0077f, -0.0085f, 0.0093f, 0.0103f, 0.0114f, 0.0127f, 0.0142f, 0.0158f, 0.0177f, -0.0198f, 0.0221f, 0.0246f, 0.0272f, 0.0297f, 0.0321f, 0.0340f, 0.0353f, -0.0357f -}; -static const float glorentz63[62] = { -0.0008f, 0.0008f, 0.0009f, 0.0009f, 0.0009f, 0.0010f, 0.0010f, 0.0010f, -0.0011f, 0.0011f, 0.0011f, 0.0012f, 0.0012f, 0.0013f, 0.0013f, 0.0014f, -0.0015f, 0.0015f, 0.0016f, 0.0017f, 0.0017f, 0.0018f, 0.0019f, 0.0020f, -0.0021f, 0.0022f, 0.0023f, 0.0025f, 0.0026f, 0.0028f, 0.0029f, 0.0031f, -0.0033f, 0.0035f, 0.0038f, 0.0040f, 0.0043f, 0.0046f, 0.0050f, 0.0053f, -0.0058f, 0.0062f, 0.0068f, 0.0074f, 0.0081f, 0.0088f, 0.0097f, 0.0106f, -0.0117f, 0.0130f, 0.0144f, 0.0159f, 0.0176f, 0.0195f, 0.0216f, 0.0237f, -0.0259f, 0.0280f, 0.0299f, 0.0315f, 0.0325f, 0.0328f -}; -static const float glorentz64[65] = { -0.0008f, 0.0008f, 0.0008f, 0.0009f, 0.0009f, 0.0009f, 0.0010f, 0.0010f, -0.0010f, 0.0011f, 0.0011f, 0.0012f, 0.0012f, 0.0012f, 0.0013f, 0.0013f, -0.0014f, 0.0014f, 0.0015f, 0.0016f, 0.0016f, 0.0017f, 0.0018f, 0.0019f, -0.0020f, 0.0021f, 0.0022f, 0.0023f, 0.0024f, 0.0025f, 0.0027f, 0.0028f, -0.0030f, 0.0031f, 0.0033f, 0.0035f, 0.0038f, 0.0040f, 0.0043f, 0.0046f, -0.0049f, 0.0052f, 0.0056f, 0.0061f, 0.0066f, 0.0071f, 0.0077f, 0.0084f, -0.0091f, 0.0100f, 0.0109f, 0.0120f, 0.0132f, 0.0145f, 0.0159f, 0.0175f, -0.0192f, 0.0209f, 0.0228f, 0.0246f, 0.0264f, 0.0279f, 0.0291f, 0.0299f, -0.0301f -}; -static const float *gptr_tab_lorentz[64] = { -glorentz1, glorentz2, glorentz3, glorentz4, -glorentz5, glorentz6, glorentz7, glorentz8, -glorentz9, glorentz10, glorentz11, glorentz12, -glorentz13, glorentz14, glorentz15, glorentz16, -glorentz17, glorentz18, glorentz19, glorentz20, -glorentz21, glorentz22, glorentz23, glorentz24, -glorentz25, glorentz26, glorentz27, glorentz28, -glorentz29, glorentz30, glorentz31, glorentz32, -glorentz33, glorentz34, glorentz35, glorentz36, -glorentz37, glorentz38, glorentz39, glorentz40, -glorentz41, glorentz42, glorentz43, glorentz44, -glorentz45, glorentz46, glorentz47, glorentz48, -glorentz49, glorentz50, glorentz51, glorentz52, -glorentz53, glorentz54, glorentz55, glorentz56, -glorentz57, glorentz58, glorentz59, glorentz60, -glorentz61, glorentz62, glorentz63, glorentz64 -}; diff --git a/lib/qra/qra64/main.c b/lib/qra/qra64/main.c deleted file mode 100644 index b685fd3..0000000 --- a/lib/qra/qra64/main.c +++ /dev/null @@ -1,746 +0,0 @@ -/* -main.c -QRA64 mode encode/decode tests - -(c) 2016 - Nico Palermo, IV3NWV - -Thanks to Andrea Montefusco IW0HDV for his help on adapting the sources -to OSs other than MS Windows - ------------------------------------------------------------------------------- -This file is part of the qracodes project, a Forward Error Control -encoding/decoding package based on Q-ary RA (Repeat and Accumulate) LDPC codes. - -Files in this package: - main.c - this file - qra64.c/.h - qra64 mode encode/decoding functions - - ../qracodes/normrnd.{c,h} - random gaussian number generator - ../qracodes/npfwht.{c,h} - Fast Walsh-Hadamard Transforms - ../qracodes/pdmath.{c,h} - Elementary math on probability distributions - ../qracodes/qra12_63_64_irr_b.{c,h} - Tables for a QRA(12,63) irregular RA - code over GF(64) - ../qracodes/qra13_64_64_irr_e.{c,h} - Tables for a QRA(13,64) irregular RA - code over GF(64) - ../qracodes/qracodes.{c,h} - QRA codes encoding/decoding functions - -------------------------------------------------------------------------------- - - qracodes is free software: you can redistribute it and/or modify - it under the terms of the GNU General Public License as published by - the Free Software Foundation, either version 3 of the License, or - (at your option) any later version. - qracodes is distributed in the hope that it will be useful, - but WITHOUT ANY WARRANTY; without even the implied warranty of - MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - GNU General Public License for more details. - - You should have received a copy of the GNU General Public License - along with qracodes source distribution. - If not, see . - ------------------------------------------------------------------------------ - -The code used by the QRA64 mode is the code: QRA13_64_64_IRR_E: K=13 -N=64 Q=64 irregular QRA code (defined in qra13_64_64_irr_e.{h,c}). - -This code has been designed to include a CRC as the 13th information -symbol and improve the code UER (Undetected Error Rate). The CRC -symbol is not sent along the channel (the codes are punctured) and the -resulting code is still a (12,63) code with an effective code rate of -R = 12/63. -*/ - -// OS dependent defines and includes ------------------------------------------ - -#if _WIN32 // note the underscore: without it, it's not msdn official! -// Windows (x64 and x86) -#include // required only for GetTickCount(...) -#include // _beginthread -#endif - -#if __linux__ -#include -#include - -unsigned GetTickCount(void) { - struct timespec ts; - unsigned theTick = 0U; - clock_gettime( CLOCK_REALTIME, &ts ); - theTick = ts.tv_nsec / 1000000; - theTick += ts.tv_sec * 1000; - return theTick; -} -#endif - -#if __APPLE__ -#endif - -#include -#include -#include - -#include "qra64.h" -#include "../qracodes/normrnd.h" // gaussian numbers generator - -// ---------------------------------------------------------------------------- - -// channel types -#define CHANNEL_AWGN 0 -#define CHANNEL_RAYLEIGH 1 -#define CHANNEL_FASTFADE 2 - -#define JT65_SNR_EBNO_OFFSET 29.1f // with the synch used in JT65 -#define QRA64_SNR_EBNO_OFFSET 31.0f // with the costas array synch - -void printwordd(char *msg, int *x, int size) -{ - int k; - printf("\n%s ",msg); - for (k=0;k-15) - if (channel_type == CHANNEL_AWGN) - for (k=0;k=0) { // decoded - printf("K1JT rx: received with apcode=%d %s\n",rc, decode_type[rc]); - -// Step 2a: K1JT replies to IV3NWV (with no grid) - printf("K1JT tx: IV3NWV K1JT\n"); - encodemsg_jt65(x,CALL_IV3NWV,CALL_K1JT, GRID_BLANK); - qra64_encode(codec_k1jt, y, x); - rx = mfskchannel(y,channel_type,EbNodB); - -// Step 2b: IV3NWV attempts to decode [? ? ?], [IV3NWV ? ?] or [IV3NWV ?] - rc = qra64_decode(codec_iv3nwv, 0, xdec,rx); - if (rc>=0) { // decoded - printf("IV3NWV rx: received with apcode=%d %s\n",rc, decode_type[rc]); - -// Step 3a: IV3NWV replies to K1JT with a 73 - printf("IV3NWV tx: K1JT IV3NWV 73\n"); - encodemsg_jt65(x,CALL_K1JT,CALL_IV3NWV, GRID_73); - qra64_encode(codec_iv3nwv, y, x); - rx = mfskchannel(y,channel_type,EbNodB); - -// Step 3b: K1JT attempts to decode [? ? ?] or [K1JT IV3NWV ?] - rc = qra64_decode(codec_k1jt, 0, xdec,rx); - if (rc>=0) { // decoded - printf("K1JT rx: received with apcode=%d %s\n",rc, decode_type[rc]); - -// Step 4a: K1JT replies to IV3NWV with a 73 - printf("K1JT tx: IV3NWV K1JT 73\n"); - encodemsg_jt65(x,CALL_IV3NWV,CALL_K1JT, GRID_73); - qra64_encode(codec_k1jt, y, x); - rx = mfskchannel(y,channel_type,EbNodB); - -// Step 4b: IV3NWV attempts to decode [? ? ?], [IV3NWV ? ?], or [IV3NWV ?] - rc = qra64_decode(codec_iv3nwv, 0, xdec,rx); - if (rc>=0) { // decoded - printf("IV3NWV rx: received with apcode=%d %s\n",rc, decode_type[rc]); - return 0; - } - } - } - } - printf("no decode\n"); - return -1; -} - -int test_proc_2(int channel_type, float EbNodB, int mode) -{ -/* -Here we simulate the decoder of K1JT after K1JT has sent a msg [IV3NWV K1JT] -and IV3NWV sends him the msg [K1JT IV3NWV JN66]. - -If mode=QRA_NOAP, K1JT decoder attempts to decode only msgs of type [? ? ?]. - -If mode=QRA_AUTOP, K1JT decoder will attempt to decode also the msgs -[K1JT IV3NWV] and [K1JT IV3NWV ?]. - -In the case a decode is successful the return code of the qra64_decode function -indicates the amount of a-priori information required to decode the received -message according to this table: - - rc=0 [? ? ?] AP0 - rc=1 [CQ ? ?] AP27 - rc=2 [CQ ? ] AP42 - rc=3 [CALL ? ?] AP29 - rc=4 [CALL ? ] AP44 - rc=5 [CALL CALL ?] AP57 - rc=6 [? CALL ?] AP29 - rc=7 [? CALL ] AP44 - rc=8 [CALL CALL GRID] AP72 - rc=9 [CQ CALL ?] AP55 - rc=10 [CQ CALL ] AP70 - rc=11 [CQ CALL GRID] AP70 - -The return code is <0 when decoding is unsuccessful - -This test simulates the situation ntx times and reports how many times -a particular type decode among the above 6 cases succeded. -*/ - - int x[QRA64_K], xdec[QRA64_K]; - int y[QRA64_N]; - float *rx; - float ebnodbest, ebnodbavg=0; - int rc,k; - - int ndecok[12] = { 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}; - int nundet = 0; - int ntx = 200,ndec=0; - - qra64codec *codec_iv3nwv = qra64_init(mode); // codec for IV3NWV - qra64codec *codec_k1jt = qra64_init(mode); // codec for K1JT - - printf("\nQRA64 Test #2 - Decoding with AP knowledge (SNR-Eb/No offset = %.1f dB)\n\n", - QRA64_SNR_EBNO_OFFSET); - -// This will enable K1JT's decoder to look for calls directed to him [K1JT ? ?/b] -// printf("K1JT decoder enabled for [K1JT ? ?/blank]\n"); -// qra64_apset(codec_k1jt, CALL_K1JT,0,0,APTYPE_MYCALL); - -// This will enable K1JT's decoder to look for IV3NWV calls directed to him [K1JT IV3NWV ?/b] -// printf("K1JT decoder enabled for [K1JT IV3NWV ?]\n"); -// qra64_apset(codec_k1jt, CALL_CQ,CALL_IV3NWV,0,APTYPE_BOTHCALLS); - -// This will enable K1JT's decoder to look for msges sent by IV3NWV [? IV3NWV ?] -// printf("K1JT decoder enabled for [? IV3NWV ?/blank]\n"); -// qra64_apset(codec_k1jt, 0,CALL_IV3NWV,GRID_BLANK,APTYPE_HISCALL); - -// This will enable K1JT's decoder to look for full-knowledge [K1JT IV3NWV JN66] msgs - printf("K1JT decoder enabled for [K1JT IV3NWV JN66]\n"); - qra64_apset(codec_k1jt, CALL_K1JT,CALL_IV3NWV,GRID_JN66,APTYPE_FULL); - -// This will enable K1JT's decoder to look for calls from IV3NWV [CQ IV3NWV ?/b] msgs - printf("K1JT decoder enabled for [CQ IV3NWV ?/b/JN66]\n"); - qra64_apset(codec_k1jt, 0,CALL_IV3NWV,GRID_JN66,APTYPE_CQHISCALL); - - - // Dx station IV3NWV calls - printf("\nIV3NWV encoder sends msg: [K1JT IV3NWV JN66]\n\n"); - encodemsg_jt65(x,CALL_CQ,CALL_IV3NWV,GRID_JN66); - -// printf("\nIV3NWV encoder sends msg: [CQ IV3NWV JN66]\n\n"); -// encodemsg_jt65(x,CALL_CQ,CALL_IV3NWV,GRID_JN66); - -// printf("\nIV3NWV encoder sends msg: [CQ IV3NWV]\n\n"); -// encodemsg_jt65(x,CALL_CQ,CALL_IV3NWV,GRID_BLANK); - qra64_encode(codec_iv3nwv, y, x); - - printf("Simulating K1JT decoder up to AP72\n"); - - for (k=0;k=0) { - ebnodbavg +=ebnodbest; - if (memcmp(xdec,x,12*sizeof(int))==0) - ndecok[rc]++; - else - nundet++; - } - } - printf("\n\n"); - - - printf("Transimtted msgs:%d\nDecoded msgs:\n\n",ntx); - for (k=0;k<12;k++) { - printf("%3d with %s\n",ndecok[k],decode_type[k]); - ndec += ndecok[k]; - } - printf("\nTotal: %d/%d (%d undetected errors)\n\n",ndec,ntx,nundet); - printf(""); - - ebnodbavg/=(ndec+nundet); - printf("Estimated SNR (average in dB) = %.2f dB\n\n",ebnodbavg-QRA64_SNR_EBNO_OFFSET); - - return 0; -} - -int test_fastfading(float EbNodB, float B90, int fadingModel, int submode, int apmode, int olddec, int channel_type, int ntx) -{ - int x[QRA64_K], xdec[QRA64_K]; - int y[QRA64_N]; - float *rx; - float ebnodbest, ebnodbavg=0; - int rc,k; - float rxolddec[QRA64_N*QRA64_M]; // holds the energies at nominal tone freqs - - int ndecok[12] = { 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}; - int nundet = 0; - int ndec=0; - - qra64codec *codec_iv3nwv; - qra64codec *codec_k1jt; - - codec_iv3nwv=qra64_init(QRA_NOAP); - codec_k1jt =qra64_init(apmode); - - if (channel_type==2) { // fast-fading case - printf("Simulating the fast-fading channel\n"); - printf("B90=%.2f Hz - Fading Model=%s - Submode=QRA64%c\n",B90,fadingModel?"Lorentz":"Gauss",submode+'A'); - printf("Decoder metric = %s\n",olddec?"AWGN":"Matched to fast-fading signal"); - } - else { - printf("Simulating the %s channel\n",channel_type?"Rayleigh block fading":"AWGN"); - printf("Decoder metric = AWGN\n"); - } - - - printf("\nEncoding msg [K1JT IV3NWV JN66]\n"); - encodemsg_jt65(x,CALL_K1JT,CALL_IV3NWV,GRID_JN66); -// printf("["); -// for (k=0;k<11;k++) printf("%02hX ",x[k]); printf("%02hX]\n",x[11]); - - qra64_encode(codec_iv3nwv, y, x); - printf("%d transmissions will be simulated\n\n",ntx); - - if (apmode==QRA_USERAP) { - // This will enable K1JT's decoder to look for cq/qrz calls [CQ/QRZ ? ?/b] - printf("K1JT decoder enabled for [CQ ? ?/blank]\n"); - qra64_apset(codec_k1jt, CALL_K1JT,0,0,APTYPE_CQQRZ); - - // This will enable K1JT's decoder to look for calls directed to him [K1JT ? ?/b] - printf("K1JT decoder enabled for [K1JT ? ?/blank]\n"); - qra64_apset(codec_k1jt, CALL_K1JT,0,0,APTYPE_MYCALL); - - // This will enable K1JT's decoder to look for msges sent by IV3NWV [? IV3NWV ?] - printf("K1JT decoder enabled for [? IV3NWV ?/blank]\n"); - qra64_apset(codec_k1jt, 0,CALL_IV3NWV,GRID_BLANK,APTYPE_HISCALL); - - // This will enable K1JT's decoder to look for IV3NWV calls directed to him [K1JT IV3NWV ?/b] - printf("K1JT decoder enabled for [K1JT IV3NWV ?]\n"); - qra64_apset(codec_k1jt, CALL_K1JT,CALL_IV3NWV,0,APTYPE_BOTHCALLS); - - // This will enable K1JT's decoder to look for full-knowledge [K1JT IV3NWV JN66] msgs - printf("K1JT decoder enabled for [K1JT IV3NWV JN66]\n"); - qra64_apset(codec_k1jt, CALL_K1JT,CALL_IV3NWV,GRID_JN66,APTYPE_FULL); - - // This will enable K1JT's decoder to look for calls from IV3NWV [CQ IV3NWV ?/b] msgs - printf("K1JT decoder enabled for [CQ IV3NWV ?/b/JN66]\n"); - qra64_apset(codec_k1jt, 0,CALL_IV3NWV,GRID_JN66,APTYPE_CQHISCALL); - - } - - printf("\nNow decoding with K1JT's decoder...\n"); -/* - if (channel_type==2) // simulate a fast-faded signal - printf("Simulating a fast-fading channel with given B90 and spread type\n"); - else - printf("Simulating a %s channel\n",channel_type?"Rayleigh block fading":"AWGN"); -*/ - for (k=0;k=0) { - ebnodbavg +=ebnodbest; - if (memcmp(xdec,x,12*sizeof(int))==0) - ndecok[rc]++; - else { - fprintf(stderr,"\nUndetected error with rc=%d\n",rc); - nundet++; - } - } - - } - printf(" %5.1f %%\r",100.0*k/ntx); - - printf("\n\n"); - - printf("Msgs transmitted:%d\nMsg decoded:\n\n",ntx); - for (k=0;k<12;k++) { - printf("rc=%2d %3d with %s\n",k,ndecok[k],decode_type[k]); - ndec += ndecok[k]; - } - printf("\nTotal: %d/%d (%d undetected errors)\n\n",ndec,ntx,nundet); - printf(""); - - if (ndec>0) { - ebnodbavg/=(ndec+nundet); - printf("Estimated SNR (average in dB) = %.2f dB\n\n",ebnodbavg-QRA64_SNR_EBNO_OFFSET); - } - - return 0; -} - - - -void syntax(void) -{ - - printf("\nQRA64 Mode Tests\n"); - printf("2016, Nico Palermo - IV3NWV\n\n"); - printf("---------------------------\n\n"); - printf("Syntax: qra64 [-s] [-c] [-a] [-t] [-h]\n"); - printf("Options: \n"); - printf(" -s : set simulation SNR in 2500 Hz BW (default:-27.5 dB)\n"); - printf(" -c : set channel type 0=AWGN (default) 1=Rayleigh 2=Fast-fading\n"); - printf(" -a : set decode type 0=NOAP 1=AUTOAP (default) 2=USERAP\n"); - printf(" -t: 0=simulate seq of msgs between IV3NWV and K1JT (default)\n"); - printf(" 1=simulate K1JT receiving K1JT IV3NWV JN66\n"); - printf(" 2=simulate fast-fading/awgn/rayliegh decoders performance\n"); - printf(" -n : simulate the transmission of ntx codewords (default=100)\n"); - - printf("Options used only for fast-fading simulations (-c2):\n"); - printf(" -b : 90%% fading bandwidth in Hz [1..230 Hz] (default = 2.5 Hz)\n"); - printf(" -m : fading model. 0=Gauss, 1=Lorentz (default = Lorentz)\n"); - printf(" -q : qra64 submode. 0=QRA64A,... 4=QRA64E (default = QRA64A)\n"); - printf(" -d : use the old awgn decoder\n"); - printf(" -h: this help\n"); - printf("Example:\n"); - printf(" qra64 -t2 -c2 -a2 -b50 -m1 -q2 -n10000 -s-26\n"); - printf(" runs the error performance test (-t2)\n"); - printf(" with USER_AP (-a2)\n"); - printf(" simulating a fast fading channel (-c2)\n"); - printf(" with B90 = 50 Hz (-b50), Lorentz Doppler (-m1), mode QRA64C (-q2)\n"); - printf(" ntx = 10000 codewords (-n10000) and SNR = -26 dB (-s-26)\n"); - -} - -int main(int argc, char* argv[]) -{ - int k, rc, nok=0; - float SNRdB = -27.5f; - unsigned int channel = CHANNEL_AWGN; - unsigned int mode = QRA_AUTOAP; - unsigned int testtype=0; - int nqso = 100; - float EbNodB; - float B90 = 2.5; - int fadingModel = 1; - int submode = 0; - int olddec = 0; - int ntx = 100; - -// Parse the command line - while(--argc) { - argv++; - - if (strncmp(*argv,"-h",2)==0) { - syntax(); - return 0; - } - else - if (strncmp(*argv,"-n",2)==0) { - ntx = ( int)atoi((*argv)+2); - if (ntx<100 || ntx>1000000) { - printf("Invalid -n option. ntx must be in the range [100..1000000]\n"); - syntax(); - return -1; - } - } - else - if (strncmp(*argv,"-a",2)==0) { - mode = ( int)atoi((*argv)+2); - if (mode>2) { - printf("Invalid decoding mode\n"); - syntax(); - return -1; - } - } - else - if (strncmp(*argv,"-s",2)==0) { - SNRdB = (float)atof((*argv)+2); - if (SNRdB>20 || SNRdB<-50) { - printf("SNR should be in the range [-50..20]\n"); - syntax(); - return -1; - } - } - else - if (strncmp(*argv,"-t",2)==0) { - testtype = ( int)atoi((*argv)+2); - if (testtype>2) { - printf("Invalid test type\n"); - syntax(); - return -1; - } - } - else - if (strncmp(*argv,"-c",2)==0) { - channel = ( int)atoi((*argv)+2); - if (channel>CHANNEL_FASTFADE) { - printf("Invalid channel type\n"); - syntax(); - return -1; - } - } - else - if (strncmp(*argv,"-b",2)==0) { - B90 = (float)atof((*argv)+2); - if (B90<1 || B90>230) { - printf("Invalid B90\n"); - syntax(); - return -1; - } - } - else - if (strncmp(*argv,"-m",2)==0) { - fadingModel = (int)atoi((*argv)+2); - if (fadingModel<0 || fadingModel>1) { - printf("Invalid fading model\n"); - syntax(); - return -1; - } - } - else - if (strncmp(*argv,"-q",2)==0) { - submode = (int)atoi((*argv)+2); - if (submode<0 || submode>4) { - printf("Invalid submode\n"); - syntax(); - return -1; - } - } - else - if (strncmp(*argv,"-d",2)==0) { - olddec = 1; - } - else { - printf("Invalid option\n"); - syntax(); - return -1; - } - } - - if (testtype<2) // old tests - if (channel==CHANNEL_FASTFADE) { - printf("Invalid Option. Test type 0 and 1 supports only AWGN or Rayleigh Channel model\n"); - return -1; - } - - EbNodB = SNRdB+QRA64_SNR_EBNO_OFFSET; - -#if defined(__linux__) || defined(__unix__) - srand48(GetTickCount()); -#endif - - if (testtype==0) { - for (k=0;k. - ------------------------------------------------------------------------------ - -QRA code used in this sowftware release: - -QRA13_64_64_IRR_E: K=13 N=64 Q=64 irregular QRA code (defined in -qra13_64_64_irr_e.h /.c) - -Codes with K=13 are designed to include a CRC as the 13th information symbol -and improve the code UER (Undetected Error Rate). -The CRC symbol is not sent along the channel (the codes are punctured) and the -resulting code is a (12,63) code -*/ -//---------------------------------------------------------------------------- - -#include -#include - -#include "qra64.h" -#include "../qracodes/qracodes.h" -#include "../qracodes/qra13_64_64_irr_e.h" -#include "../qracodes/pdmath.h" -#include "../qracodes/normrnd.h" - -// Code parameters of the QRA64 mode -#define QRA64_CODE qra_13_64_64_irr_e -#define QRA64_NMSG 218 // Must much value indicated in QRA64_CODE.NMSG - -#define QRA64_KC (QRA64_K+1) // Information symbols (crc included) -#define QRA64_NC (QRA64_N+1) // Codeword length (as defined in the code) -#define QRA64_NITER 100 // max number of iterations per decode - -// static functions declarations ---------------------------------------------- -static int calc_crc6(const int *x, int sz); -static void ix_mask(float *dst, const float *src, const int *mask, - const int *x); -static int qra64_decode_attempts(qra64codec *pcodec, int *xdec, const float *ix); -static int qra64_do_decode(int *x, const float *pix, const int *ap_mask, - const int *ap_x); -static float qra64_fastfading_estim_noise_std( - const float *rxen, - const float esnometric, - const int submode); - -static void qra64_fastfading_intrinsics( - float *pix, - const float *rxen, - const float *hptr, - const int hlen, - const float sigma, - const float EsNoMetric, - const int submode); - -static float qra64_fastfading_msg_esno( - const int *ydec, - const float *rxen, - const float sigma, - const float EsNoMetric, - const int hlen, - const int submode); - - -// a-priori information masks for fields in JT65-like msgs -------------------- - -// when defined limits the AP masks to reduce the false decode rate -#define LIMIT_AP_MASKS - -#ifdef LIMIT_AP_MASKS -#define MASK_CQQRZ 0xFFFFFFC -#define MASK_CALL1 0xFFFFFFC -#define MASK_CALL2 0xFFFFFFC -#define MASK_GRIDFULL 0x3FFC -#define MASK_GRIDFULL12 0x3FFC -#define MASK_GRIDBIT 0x8000 -#else -#define MASK_CQQRZ 0xFFFFFFC -#define MASK_CALL1 0xFFFFFFF -#define MASK_CALL2 0xFFFFFFF -#define MASK_GRIDFULL 0xFFFF -#define MASK_GRIDFULL12 0x3FFC -#define MASK_GRIDBIT 0x8000 // b[15] is 1 for free text, 0 otherwise -#endif - -// ---------------------------------------------------------------------------- - - - - -qra64codec *qra64_init(int flags) -{ - - // Eb/No value for which we optimize the decoder metric - const float EbNodBMetric = 2.8f; - const float EbNoMetric = (float)pow(10,EbNodBMetric/10); - const float R = 1.0f*(QRA64_KC)/(QRA64_NC); - - qra64codec *pcodec = (qra64codec*)malloc(sizeof(qra64codec)); - - if (!pcodec) - return 0; // can't allocate memory - - pcodec->decEsNoMetric = 1.0f*QRA64_m*R*EbNoMetric; - pcodec->apflags = flags; - - memset(pcodec->apmsg_set,0,APTYPE_SIZE*sizeof(int)); - - if (flags==QRA_NOAP) - return pcodec; - - // for QRA_USERAP and QRA_AUTOAP modes we always enable [CQ/QRZ ? ?] mgs look-up. - // encode CQ/QRZ AP messages - // NOTE: Here we handle only CQ and QRZ msgs. - // 'CQ nnn', 'CQ DX' and 'DE' msgs will be handled by the decoder - // as messages with no a-priori knowledge - qra64_apset(pcodec, CALL_CQ, 0, GRID_BLANK, APTYPE_CQQRZ); - - // initialize masks for decoding with a-priori information - encodemsg_jt65(pcodec->apmask_cqqrz, MASK_CQQRZ, 0, MASK_GRIDBIT); - encodemsg_jt65(pcodec->apmask_cqqrz_ooo, MASK_CQQRZ, 0, MASK_GRIDFULL); - encodemsg_jt65(pcodec->apmask_call1, MASK_CALL1, 0, MASK_GRIDBIT); - encodemsg_jt65(pcodec->apmask_call1_ooo, MASK_CALL1, 0, MASK_GRIDFULL); - encodemsg_jt65(pcodec->apmask_call2, 0, MASK_CALL2, MASK_GRIDBIT); - encodemsg_jt65(pcodec->apmask_call2_ooo, 0, MASK_CALL2, MASK_GRIDFULL); - encodemsg_jt65(pcodec->apmask_call1_call2, MASK_CALL1,MASK_CALL2, MASK_GRIDBIT); - encodemsg_jt65(pcodec->apmask_call1_call2_grid,MASK_CALL1,MASK_CALL2, MASK_GRIDFULL12); - encodemsg_jt65(pcodec->apmask_cq_call2, MASK_CQQRZ, MASK_CALL2, MASK_GRIDBIT); - encodemsg_jt65(pcodec->apmask_cq_call2_ooo, MASK_CQQRZ, MASK_CALL2, MASK_GRIDFULL12); - - return pcodec; -} - -void qra64_close(qra64codec *pcodec) -{ - free(pcodec); -} - -int qra64_apset(qra64codec *pcodec, const int mycall, const int hiscall, const int grid, const int aptype) -{ -// Set decoder a-priori knowledge accordingly to the type of the message to look up for -// arguments: -// pcodec = pointer to a qra64codec data structure as returned by qra64_init -// mycall = mycall to look for -// hiscall = hiscall to look for -// grid = grid to look for -// aptype = define and masks the type of AP to be set accordingly to the following: -// APTYPE_CQQRZ set [cq/qrz ? ?/blank] -// APTYPE_MYCALL set [mycall ? ?/blank] -// APTYPE_HISCALL set [? hiscall ?/blank] -// APTYPE_BOTHCALLS set [mycall hiscall ?] -// APTYPE_FULL set [mycall hiscall grid] -// APTYPE_CQHISCALL set [cq/qrz hiscall ?/blank] and [cq/qrz hiscall grid] -// returns: -// 0 on success -// -1 when qra64_init was called with the QRA_NOAP flag -// -2 invalid apytpe - - if (pcodec->apflags==QRA_NOAP) - return -1; - - switch (aptype) { - case APTYPE_CQQRZ: - encodemsg_jt65(pcodec->apmsg_cqqrz, CALL_CQ, 0, GRID_BLANK); - break; - case APTYPE_MYCALL: - encodemsg_jt65(pcodec->apmsg_call1, mycall, 0, GRID_BLANK); - break; - case APTYPE_HISCALL: - encodemsg_jt65(pcodec->apmsg_call2, 0, hiscall, GRID_BLANK); - break; - case APTYPE_BOTHCALLS: - encodemsg_jt65(pcodec->apmsg_call1_call2, mycall, hiscall, GRID_BLANK); - break; - case APTYPE_FULL: - encodemsg_jt65(pcodec->apmsg_call1_call2_grid, mycall, hiscall, grid); - break; - case APTYPE_CQHISCALL: - encodemsg_jt65(pcodec->apmsg_cq_call2, CALL_CQ, hiscall, GRID_BLANK); - encodemsg_jt65(pcodec->apmsg_cq_call2_grid, CALL_CQ, hiscall, grid); - break; - default: - return -2; // invalid ap type - } - - pcodec->apmsg_set[aptype]=1; // signal the decoder to look-up for the specified type - - - return 0; -} -void qra64_apdisable(qra64codec *pcodec, const int aptype) -{ - if (pcodec->apflags==QRA_NOAP) - return; - - if (aptype=APTYPE_SIZE) - return; - - pcodec->apmsg_set[aptype] = 0; // signal the decoder not to look-up to the specified type -} - -void qra64_encode(qra64codec *pcodec, int *y, const int *x) -{ - int encx[QRA64_KC]; // encoder input buffer - int ency[QRA64_NC]; // encoder output buffer - - int hiscall,mycall,grid; - - memcpy(encx,x,QRA64_K*sizeof(int)); // Copy input to encoder buffer - encx[QRA64_K]=calc_crc6(encx,QRA64_K); // Compute and add crc symbol - qra_encode(&QRA64_CODE, ency, encx); // encode msg+crc using given QRA code - - // copy codeword to output puncturing the crc symbol - memcpy(y,ency,QRA64_K*sizeof(int)); // copy information symbols - memcpy(y+QRA64_K,ency+QRA64_KC,QRA64_C*sizeof(int)); // copy parity symbols - - if (pcodec->apflags!=QRA_AUTOAP) - return; - - // Here we handle the QRA_AUTOAP mode -------------------------------------------- - - // When a [hiscall mycall ?] msg is detected we instruct the decoder - // to look for [mycall hiscall ?] msgs - // otherwise when a [cq mycall ?] msg is sent we reset the APTYPE_BOTHCALLS - - // look if the msg sent is a std type message (bit15 of grid field = 0) - if ((x[9]&0x80)==1) - return; // no, it's a text message, nothing to do - - // It's a [hiscall mycall grid] message - - // We assume that mycall is our call (but we don't check it) - // hiscall the station we are calling or a general call (CQ/QRZ/etc..) - decodemsg_jt65(&hiscall,&mycall,&grid,x); - - - if ((hiscall>=CALL_CQ && hiscall<=CALL_CQ999) || hiscall==CALL_CQDX || - hiscall==CALL_DE) { - // tell the decoder to look for msgs directed to us - qra64_apset(pcodec,mycall,0,0,APTYPE_MYCALL); - // We are making a general call and don't know who might reply - // Reset APTYPE_BOTHCALLS so decoder won't look for [mycall hiscall ?] msgs - qra64_apdisable(pcodec,APTYPE_BOTHCALLS); - } else { - // We are replying to someone named hiscall - // Set APTYPE_BOTHCALLS so decoder will try for [mycall hiscall ?] msgs - qra64_apset(pcodec,mycall, hiscall, GRID_BLANK, APTYPE_BOTHCALLS); - } - -} - -#define EBNO_MIN -10.0f // minimum Eb/No value returned by the decoder (in dB) -// AWGN metric decoder -int qra64_decode(qra64codec *pcodec, float *ebno, int *x, const float *rxen) -{ - int k; - float *srctmp, *dsttmp; - float ix[QRA64_NC*QRA64_M]; // (depunctured) intrisic information - int xdec[QRA64_KC]; // decoded message (with crc) - int ydec[QRA64_NC]; // re-encoded message (for snr calculations) - float noisestd; // estimated noise variance - float msge; // estimated message energy - float ebnoval; // estimated Eb/No - int rc; - - if (QRA64_NMSG!=QRA64_CODE.NMSG) // sanity check - return -16; // QRA64_NMSG define is wrong - - // compute symbols intrinsic probabilities from received energy observations - noisestd = qra_mfskbesselmetric(ix, rxen, QRA64_m, QRA64_N,pcodec->decEsNoMetric); - - // de-puncture observations adding a uniform distribution for the crc symbol - - // move check symbols distributions one symbol towards the end - dsttmp = PD_ROWADDR(ix,QRA64_M, QRA64_NC-1); //Point to last symbol prob dist - srctmp = dsttmp-QRA64_M; // source is the previous pd - for (k=0;k57.004f) - ebnoval=57.004f; - ebnoval = ebnoval*57.03f/(57.03f-ebnoval); - - // compute value in dB - if (ebnoval<=0) { - ebnoval = EBNO_MIN; // assume a minimum, positive value - } - else { - ebnoval = 10.0f*(float)log10(ebnoval); - if (ebnoval4) - return -17; // invalid submode - - if (B90<1.0f || B90>238.0f) - return -18; // B90 out of range - - // compute index to most appropriate amplitude weighting function coefficients - hidx = (int)(log((float)B90)/log(1.09f) - 0.499f); - - if (hidx<0 || hidx > 64) - return -19; // index of weighting function out of range - - if (fadingModel==0) { // gaussian fading model - // point to gaussian energy weighting taps - hlen = glen_tab_gauss[hidx]; // hlen = (L+1)/2 (where L=(odd) number of taps of w fun) - hptr = gptr_tab_gauss[hidx]; // pointer to the first (L+1)/2 coefficients of w fun - } - else if (fadingModel==1) { - // point to lorentzian energy weighting taps - hlen = glen_tab_lorentz[hidx]; // hlen = (L+1)/2 (where L=(odd) number of taps of w fun) - hptr = gptr_tab_lorentz[hidx]; // pointer to the first (L+1)/2 coefficients of w fun - } - else - return -20; // invalid fading model index - - - // compute (euristically) the optimal decoder metric accordingly the given spread amount - // We assume that the decoder threshold is: - // Es/No(dB) = Es/No(AWGN)(dB) + 8*log(B90)/log(240)(dB) - // that's to say, at the maximum Doppler spread bandwidth (240 Hz) there's a ~8 dB Es/No degradation - // over the AWGN case - tempf = 8.0f*(float)log((float)B90)/(float)log(240.0f); - EsNoMetric = pcodec->decEsNoMetric*(float)pow(10.0f,tempf/10.0f); - - - - // Step 1 ----------------------------------------------------------------------------------- - // Evaluate the noise stdev from the received energies at nominal tone frequencies - noisestd = qra64_fastfading_estim_noise_std(rxen, EsNoMetric, submode); - - // Step 2 ----------------------------------------------------------------------------------- - // Compute message symbols probability distributions - qra64_fastfading_intrinsics(ix, rxen, hptr, hlen, noisestd, EsNoMetric, submode); - - // Step 3 --------------------------------------------------------------------------- - // De-puncture observations adding a uniform distribution for the crc symbol - // Move check symbols distributions one symbol towards the end - dsttmp = PD_ROWADDR(ix,QRA64_M, QRA64_NC-1); //Point to last symbol prob dist - srctmp = dsttmp-QRA64_M; // source is the previous pd - for (k=0;k Eb/N0 conversion - ebnoval = 1.0f/(1.0f*QRA64_K/QRA64_N*QRA64_m)*esno; - - // compute value in dB - if (ebnoval<=0) { - ebnoval = EBNO_MIN; // assume a minimum, positive value - } - else { - ebnoval = 10.0f*(float)log10(ebnoval); - if (ebnoval238.0f) - return -18; // B90 out of range - - // compute index to most appropriate energy weighting function coefficients - hidx = (int)(log((float)B90)/log(1.09f) - 0.499f); - - if (hidx<0 || hidx > 64) - return -19; // index of weighting function out of range - - if (fadingModel==0) { // gaussian fading model - // point to gaussian weighting taps - hlen = glen_tab_gauss[hidx]; // hlen = (L+1)/2 (where L=(odd) number of taps of w fun) - hptr = gptr_tab_gauss[hidx]; // pointer to the first (L+1)/2 coefficients of w fun - } - else if (fadingModel==1) { - // point to lorentzian weighting taps - hlen = glen_tab_lorentz[hidx]; // hlen = (L+1)/2 (where L=(odd) number of taps of w fun) - hptr = gptr_tab_lorentz[hidx]; // pointer to the first (L+1)/2 coefficients of w fun - } - else - return -20; // invalid fading model index - - - // Compute the unfaded tone amplitudes from the Eb/No value passed to the call - N0 = 1.0f; // assume unitary noise PSD - sigmanoise = (float)sqrt(N0/2); - EsN0 = (float)pow(10.0f,EbN0dB/10.0f)*QRA64_m*QRA64_K/QRA64_N; // Es/No = m*R*Eb/No - Es = EsN0*N0; - - // compute signal bin sigmas - for (n=0;n=0;j--) { - normrnd_s(iq, 2, 0 , sigmasig[j]); - *curi++ += iq[0]; - *curq++ += iq[1]; - } - - } - - // compute total bin energies (S+N) and store in first half of buffer - curi = channel_out; - curq = channel_out+bpm; - for (n=0;nmaxloglh) // keep track of the max loglikelihood - maxloglh = loglh; - curix[k]=loglh; - } - - // scale to likelihoods - sumix = 0.f; - for (k=0;k1 - if (u<1) - return 0.f; - - // check u(bps/tothlen)) - return 10000.f; - - // solve for Es/No - esno = (u-1.0f)/(1.0f/tothlen-u/bps); - - return esno; - - -} - -#ifdef LIMIT_AP_MASKS - -static int call1_match(const int *papmsg, const int *pdec) -{ - // assumes MASK_CALL1 = 0xFFFFFFC - int u = papmsg[4]^pdec[4]; - return (u&0x3C)==0; -} -static int call2_match(const int *papmsg, const int *pdec) -{ - // assumes MASK_CALL2 = 0xFFFFFFC - int u = papmsg[9]^pdec[9]; - return (u&0x30)==0; -} -static int grid_match(const int *papmsg, const int *pdec) -{ - // assumes MASK_GRIDFULL = 0x3FFC - int u = papmsg[11]^pdec[11]; - int rc = (u&0x03)==0; - - u = papmsg[9]^pdec[9]; - - return (u&0x0C)==0 && rc; -} - -#else -#define call1_match(a,b) (1) -#define call2_match(a,b) (1) -#define grid_match(a,b) (1) -#endif - - - - -// Attempt to decode given intrisic information -static int qra64_decode_attempts(qra64codec *pcodec, int *xdec, const float *ix) -{ - int rc; - - // Attempt to decode without a-priori info -------------------------------- - rc = qra64_do_decode(xdec, ix, NULL, NULL); - if (rc>=0) - return 0; // successfull decode with AP0 - else - if (pcodec->apflags==QRA_NOAP) - // nothing more to do - return rc; // rc<0 = unsuccessful decode - - // Here we handle decoding with AP knowledge - - - // Attempt to decode CQ calls - rc = qra64_do_decode(xdec,ix,pcodec->apmask_cqqrz, pcodec->apmsg_cqqrz); - if (rc>=0) - return 1; // decoded [cq/qrz ? ?] - - rc = qra64_do_decode(xdec, ix, pcodec->apmask_cqqrz_ooo, - pcodec->apmsg_cqqrz); - if (rc>=0) - // check that ooo really matches - if (grid_match(pcodec->apmsg_cqqrz,xdec)) - return 2; // decoded [cq/qrz ? ooo] - - // attempt to decode calls directed to us - if (pcodec->apmsg_set[APTYPE_MYCALL]) { - rc = qra64_do_decode(xdec, ix, pcodec->apmask_call1, - pcodec->apmsg_call1); - if (rc>=0) - // check that mycall really matches - if (call1_match(pcodec->apmsg_call1,xdec)) - return 3; // decoded [mycall ? ?] - - rc = qra64_do_decode(xdec, ix, pcodec->apmask_call1_ooo, - pcodec->apmsg_call1); - if (rc>=0) - // check that mycall and ooo really match - if (call1_match(pcodec->apmsg_call1,xdec) && - grid_match(pcodec->apmsg_call1,xdec)) - return 4; // decoded [mycall ? ooo] - } - - // attempt to decode [mycall hiscall ?] msgs - if (pcodec->apmsg_set[APTYPE_BOTHCALLS]) { - rc = qra64_do_decode(xdec, ix, pcodec->apmask_call1_call2, - pcodec->apmsg_call1_call2); - if (rc>=0) - // check that mycall and hiscall really match - if (call1_match(pcodec->apmsg_call1_call2,xdec) && - call2_match(pcodec->apmsg_call1_call2,xdec)) - return 5; // decoded [mycall srccall ?] - } - - // attempt to decode [? hiscall ?/b] msgs - if (pcodec->apmsg_set[APTYPE_HISCALL]) { - rc = qra64_do_decode(xdec, ix, pcodec->apmask_call2, - pcodec->apmsg_call2); - if (rc>=0) - // check that hiscall really match - if (call2_match(pcodec->apmsg_call2,xdec)) - return 6; // decoded [? hiscall ?] - - rc = qra64_do_decode(xdec, ix, pcodec->apmask_call2_ooo, - pcodec->apmsg_call2); - if (rc>=0) - // check that hiscall and ooo match - if (call2_match(pcodec->apmsg_call2,xdec) && - grid_match(pcodec->apmsg_call2,xdec)) - return 7; // decoded [? hiscall ooo] - } - - // attempt to decode [cq/qrz hiscall ?/b/grid] msgs - if (pcodec->apmsg_set[APTYPE_CQHISCALL]) { - - rc = qra64_do_decode(xdec, ix, pcodec->apmask_cq_call2, - pcodec->apmsg_cq_call2); - if (rc>=0) - // check that hiscall matches - if (call2_match(pcodec->apmsg_call2,xdec)) - return 9; // decoded [cq/qrz hiscall ?] - - rc = qra64_do_decode(xdec, ix, pcodec->apmask_cq_call2_ooo, - pcodec->apmsg_cq_call2_grid); - if (rc>=0) { - // Full AP mask need special handling - // To minimize false decodes we check the decoded message - // with what passed in the ap_set call - if (memcmp(pcodec->apmsg_cq_call2_grid,xdec, QRA64_K*sizeof(int))==0) - return 11; // decoded [cq/qrz hiscall grid] - } - - rc = qra64_do_decode(xdec, ix, pcodec->apmask_cq_call2_ooo, - pcodec->apmsg_cq_call2); - if (rc>=0) { - // Full AP mask need special handling - // To minimize false decodes we check the decoded message - // with what passed in the ap_set call - if (memcmp(pcodec->apmsg_cq_call2,xdec, QRA64_K*sizeof(int))==0) - return 10; // decoded [cq/qrz hiscall ] - } - } - - // attempt to decode [mycall hiscall grid] - if (pcodec->apmsg_set[APTYPE_FULL]) { - rc = qra64_do_decode(xdec, ix, pcodec->apmask_call1_call2_grid, - pcodec->apmsg_call1_call2_grid); - if (rc>=0) { - // Full AP mask need special handling - // All the three msg fields were given. - // To minimize false decodes we check the decoded message - // with what passed in the ap_set call - if (memcmp(pcodec->apmsg_call1_call2_grid,xdec, QRA64_K*sizeof(int))==0) - return 8; // decoded [mycall hiscall grid] - } - } - - // all decoding attempts failed - return -1; -} - - - -// Decode with given a-priori information -static int qra64_do_decode(int *xdec, const float *pix, const int *ap_mask, - const int *ap_x) -{ - int rc; - const float *ixsrc; - float ix_masked[QRA64_NC*QRA64_M]; // Masked intrinsic information - float ex[QRA64_NC*QRA64_M]; // Extrinsic information from the decoder - - float v2cmsg[QRA64_NMSG*QRA64_M]; // buffers for the decoder messages - float c2vmsg[QRA64_NMSG*QRA64_M]; - - if (ap_mask==NULL) { // no a-priori information - ixsrc = pix; // intrinsic source is what passed as argument - } else { - // a-priori information provided - // mask channel observations with a-priori - ix_mask(ix_masked,pix,ap_mask,ap_x); - ixsrc = ix_masked; // intrinsic source is the masked version - } - - // run the decoding algorithm - rc = qra_extrinsic(&QRA64_CODE,ex,ixsrc,QRA64_NITER,v2cmsg,c2vmsg); - if (rc<0) - return -1; // no convergence in given iterations - - // decode - qra_mapdecode(&QRA64_CODE,xdec,ex,ixsrc); - - // verify crc - if (calc_crc6(xdec,QRA64_K)!=xdec[QRA64_K]) // crc doesn't match (detected error) - return -2; // decoding was succesfull but crc doesn't match - - return 0; -} - - -// crc functions -------------------------------------------------------------- -// crc-6 generator polynomial -// g(x) = x^6 + a5*x^5 + ... + a1*x + a0 - -// g(x) = x^6 + x + 1 -#define CRC6_GEN_POL 0x30 // MSB=a0 LSB=a5 - -// g(x) = x^6 + x^2 + x + 1 (See: https://users.ece.cmu.edu/~koopman/crc/) -// #define CRC6_GEN_POL 0x38 // MSB=a0 LSB=a5. Simulation results are similar - -static int calc_crc6(const int *x, int sz) -{ - // todo: compute it faster using a look up table - int k,j,t,sr = 0; - for (k=0;k>1) ^ CRC6_GEN_POL; - else - sr = (sr>>1); - t>>=1; - } - } - return sr; -} - -static void ix_mask(float *dst, const float *src, const int *mask, - const int *x) -{ - // mask intrinsic information (channel observations) with a priori knowledge - - int k,kk, smask; - float *row; - - memcpy(dst,src,(QRA64_NC*QRA64_M)*sizeof(float)); - - for (k=0;k>22)&0x3F; - y[1]= (call1>>16)&0x3F; - y[2]= (call1>>10)&0x3F; - y[3]= (call1>>4)&0x3F; - y[4]= (call1<<2)&0x3F; - - y[4] |= (call2>>26)&0x3F; - y[5]= (call2>>20)&0x3F; - y[6]= (call2>>14)&0x3F; - y[7]= (call2>>8)&0x3F; - y[8]= (call2>>2)&0x3F; - y[9]= (call2<<4)&0x3F; - - y[9] |= (grid>>12)&0x3F; - y[10]= (grid>>6)&0x3F; - y[11]= (grid)&0x3F; - -} -void decodemsg_jt65(int *call1, int *call2, int *grid, const int *x) -{ - int nc1, nc2, ng; - - nc1 = x[4]>>2; - nc1 |= x[3]<<4; - nc1 |= x[2]<<10; - nc1 |= x[1]<<16; - nc1 |= x[0]<<22; - - nc2 = x[9]>>4; - nc2 |= x[8]<<2; - nc2 |= x[7]<<8; - nc2 |= x[6]<<14; - nc2 |= x[5]<<20; - nc2 |= (x[4]&0x03)<<26; - - ng = x[11]; - ng |= x[10]<<6; - ng |= (x[9]&0x0F)<<12; - - *call1 = nc1; - *call2 = nc2; - *grid = ng; -} diff --git a/lib/qra/qra64/qra64.h b/lib/qra/qra64/qra64.h deleted file mode 100644 index 3b2b5bd..0000000 --- a/lib/qra/qra64/qra64.h +++ /dev/null @@ -1,269 +0,0 @@ -// qra64.h -// Encoding/decoding functions for the QRA64 mode -// -// (c) 2016 - Nico Palermo, IV3NWV -// ------------------------------------------------------------------------------ -// This file is part of the qracodes project, a Forward Error Control -// encoding/decoding package based on Q-ary RA (Repeat and Accumulate) LDPC codes. -// -// qracodes is free software: you can redistribute it and/or modify -// it under the terms of the GNU General Public License as published by -// the Free Software Foundation, either version 3 of the License, or -// (at your option) any later version. -// qracodes is distributed in the hope that it will be useful, -// but WITHOUT ANY WARRANTY; without even the implied warranty of -// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -// GNU General Public License for more details. - -// You should have received a copy of the GNU General Public License -// along with qracodes source distribution. -// If not, see . - -#ifndef _qra64_h_ -#define _qra64_h_ - -// qra64_init(...) initialization flags -#define QRA_NOAP 0 // don't use a-priori knowledge -#define QRA_AUTOAP 1 // use auto a-priori knowledge -#define QRA_USERAP 2 // a-priori knowledge messages provided by the user - -// QRA code parameters -#define QRA64_K 12 // information symbols -#define QRA64_N 63 // codeword length -#define QRA64_C 51 // (number of parity checks C=(N-K)) -#define QRA64_M 64 // code alphabet size -#define QRA64_m 6 // bits per symbol - -// packed predefined callsigns and fields as defined in JT65 -#define CALL_CQ 0xFA08319 -#define CALL_QRZ 0xFA0831A -#define CALL_CQ000 0xFA0831B -#define CALL_CQ999 0xFA08702 -#define CALL_CQDX 0x5624C39 -#define CALL_DE 0xFF641D1 -#define GRID_BLANK 0x7E91 - -// Types of a-priori knowledge messages -#define APTYPE_CQQRZ 0 // [cq/qrz ? ?/blank] -#define APTYPE_MYCALL 1 // [mycall ? ?/blank] -#define APTYPE_HISCALL 2 // [? hiscall ?/blank] -#define APTYPE_BOTHCALLS 3 // [mycall hiscall ?] -#define APTYPE_FULL 4 // [mycall hiscall grid] -#define APTYPE_CQHISCALL 5 // [cq/qrz hiscall ?/blank] -#define APTYPE_SIZE (APTYPE_CQHISCALL+1) - -typedef struct { - float decEsNoMetric; - int apflags; - int apmsg_set[APTYPE_SIZE]; // indicate which ap type knowledge has - // been set by the user -// ap messages buffers - int apmsg_cqqrz[12]; // [cq/qrz ? ?/blank] - int apmsg_call1[12]; // [mycall ? ?/blank] - int apmsg_call2[12]; // [? hiscall ?/blank] - int apmsg_call1_call2[12]; // [mycall hiscall ?] - int apmsg_call1_call2_grid[12]; // [mycall hiscall grid] - int apmsg_cq_call2[12]; // [cq hiscall ?/blank] - int apmsg_cq_call2_grid[12]; // [cq hiscall grid] - -// ap messages masks - int apmask_cqqrz[12]; - int apmask_cqqrz_ooo[12]; - int apmask_call1[12]; - int apmask_call1_ooo[12]; - int apmask_call2[12]; - int apmask_call2_ooo[12]; - int apmask_call1_call2[12]; - int apmask_call1_call2_grid[12]; - int apmask_cq_call2[12]; - int apmask_cq_call2_ooo[12]; -} qra64codec; - -#ifdef __cplusplus -extern "C" { -#endif - -qra64codec *qra64_init(int flags); -// QRA64 mode initialization function -// arguments: -// flags: set the decoder mode -// QRA_NOAP use no a-priori information -// QRA_AUTOAP use any relevant previous decodes -// QRA_USERAP use a-priori information provided via qra64_apset(...) -// returns: -// Pointer to initialized qra64codec data structure -// this pointer should be passed to the encoding/decoding functions -// -// 0 if unsuccessful (can't allocate memory) -// ---------------------------------------------------------------------------- - -void qra64_encode(qra64codec *pcodec, int *y, const int *x); -// QRA64 encoder -// arguments: -// pcodec = pointer to a qra64codec data structure as returned by qra64_init -// x = pointer to the message to be encoded, int x[12] -// x must point to an array of integers (i.e. defined as int x[12]) -// y = pointer to encoded message, int y[63]= -// ---------------------------------------------------------------------------- - -int qra64_decode(qra64codec *pcodec, float *ebno, int *x, const float *r); -// QRA64 mode decoder -// arguments: -// pcodec = pointer to a qra64codec data structure as returned by qra64_init -// ebno = pointer to a float where the avg Eb/No (in dB) will be stored -// in case of successfull decoding -// (pass a null pointer if not interested) -// x = pointer to decoded message, int x[12] -// r = pointer to received symbol energies (squared amplitudes) -// r must point to an array of length QRA64_M*QRA64_N (=64*63=4032) -// The first QRA_M entries should be the energies of the first -// symbol in the codeword; the last QRA_M entries should be the -// energies of the last symbol in the codeword -// -// return code: -// -// The return code is <0 when decoding is unsuccessful -// -16 indicates that the definition of QRA64_NMSG does not match what required by the code -// If the decoding process is successfull the return code is accordingly to the following table -// rc=0 [? ? ?] AP0 (decoding with no a-priori) -// rc=1 [CQ ? ?] AP27 -// rc=2 [CQ ? ] AP44 -// rc=3 [CALL ? ?] AP29 -// rc=4 [CALL ? ] AP45 -// rc=5 [CALL CALL ?] AP57 -// rc=6 [? CALL ?] AP29 -// rc=7 [? CALL ] AP45 -// rc=8 [CALL CALL GRID] AP72 (actually a AP68 mask to reduce false decodes) -// rc=9 [CQ CALL ?] AP55 -// rc=10 [CQ CALL ] AP70 (actaully a AP68 mask to reduce false decodes) - -// return codes in the range 1-10 indicate the amount and the type of a-priori -// information was required to decode the received message. - - -// Decode a QRA64 msg using a fast-fading metric -int qra64_decode_fastfading( - qra64codec *pcodec, // ptr to the codec structure - float *ebno, // ptr to where the estimated Eb/No value will be saved - int *x, // ptr to decoded message - const float *rxen, // ptr to received symbol energies array - const int submode, // submode idx (0=QRA64A ... 4=QRA64E) - const float B90, // spread bandwidth (90% fractional energy) - const int fadingModel); // 0=Gaussian 1=Lorentzian fade model -// -// rxen: The array of the received bin energies -// Bins must be spaced by integer multiples of the symbol rate (1/Ts Hz) -// The array must be an array of total length U = L x N where: -// L: is the number of frequency bins per message symbol (see after) -// N: is the number of symbols in a QRA64 msg (63) -// -// The number of bins/symbol L depends on the selected submode accordingly to -// the following rule: -// L = (64+64*2^submode+64) = 64*(2+2^submode) -// Tone 0 is always supposed to be at offset 64 in the array. -// The m-th tone nominal frequency is located at offset 64 + m*2^submode (m=0..63) -// -// Submode A: (2^submode = 1) -// L = 64*3 = 196 bins/symbol -// Total length of the energies array: U = 192*63 = 12096 floats -// -// Submode B: (2^submode = 2) -// L = 64*4 = 256 bins/symbol -// Total length of the energies array: U = 256*63 = 16128 floats -// -// Submode C: (2^submode = 4) -// L = 64*6 = 384 bins/symbol -// Total length of the energies array: U = 384*63 = 24192 floats -// -// Submode D: (2^submode = 8) -// L = 64*10 = 640 bins/symbol -// Total length of the energies array: U = 640*63 = 40320 floats -// -// Submode E: (2^submode = 16) -// L = 64*18 = 1152 bins/symbol -// Total length of the energies array: U = 1152*63 = 72576 floats -// -// Note: The rxen array is modified and reused for internal calculations. -// -// -// B90: spread fading bandwidth in Hz (90% fractional average energy) -// -// B90 should be in the range 1 Hz ... 238 Hz -// The value passed to the call is rounded to the closest value among the -// 64 available values: -// B = 1.09^k Hz, with k=0,1,...,63 -// -// I.e. B90=27 Hz will be approximated in this way: -// k = rnd(log(27)/log(1.09)) = 38 -// B90 = 1.09^k = 1.09^38 = 26.4 Hz -// -// For any input value the maximum rounding error is not larger than +/- 5% -// -// return codes: same return codes of qra64_decode (+some additional error codes) - - -// Simulate the fast-fading channel (to be used with qra64_decode_fastfading) -int qra64_fastfading_channel( - float **rxen, - const int *xmsg, - const int submode, - const float EbN0dB, - const float B90, - const int fadingModel); -// Simulate transmission over a fading channel with given B90, fading model and submode -// and non coherent detection. -// Sets rxen to point to an array of bin energies formatted as required -// by the (fast-fading) decoding routine. -// returns 0 on success or negative values on error conditions - - -int qra64_apset(qra64codec *pcodec, const int mycall, const int hiscall, const int grid, const int aptype); -// Set decoder a-priori knowledge accordingly to the type of the message to -// look up for -// arguments: -// pcodec = pointer to a qra64codec data structure as returned by qra64_init -// mycall = mycall to look for -// hiscall = hiscall to look for -// grid = grid to look for -// aptype = define the type of AP to be set: -// APTYPE_CQQRZ set [cq/qrz ? ?/blank] -// APTYPE_MYCALL set [mycall ? ?/blank] -// APTYPE_HISCALL set [? hiscall ?/blank] -// APTYPE_BOTHCALLS set [mycall hiscall ?] -// APTYPE_FULL set [mycall hiscall grid] -// APTYPE_CQHISCALL set [cq/qrz hiscall ?/blank] - -// returns: -// 0 on success -// -1 when qra64_init was called with the QRA_NOAP flag -// -2 invalid apytpe (valid range [APTYPE_CQQRZ..APTYPE_CQHISCALL] -// (APTYPE_CQQRZ [cq/qrz ? ?] is set by default ) - -void qra64_apdisable(qra64codec *pcodec, const int aptype); -// disable specific AP type -// arguments: -// pcodec = pointer to a qra64codec data structure as returned by qra64_init -// aptype = define the type of AP to be disabled -// APTYPE_CQQRZ disable [cq/qrz ? ?/blank] -// APTYPE_MYCALL disable [mycall ? ?/blank] -// APTYPE_HISCALL disable [ ? hiscall ?/blank] -// APTYPE_BOTHCALLS disable [mycall hiscall ? ] -// APTYPE_FULL disable [mycall hiscall grid] -// APTYPE_CQHISCALL set [cq/qrz hiscall ?/blank] - -void qra64_close(qra64codec *pcodec); -// Free memory allocated by qra64_init -// arguments: -// pcodec = pointer to a qra64codec data structure as returned by qra64_init - -// ---------------------------------------------------------------------------- - -// encode/decode std msgs in 12 symbols as done in jt65 -void encodemsg_jt65(int *y, const int call1, const int call2, const int grid); -void decodemsg_jt65(int *call1, int *call2, int *grid, const int *x); - -#ifdef __cplusplus -} -#endif - -#endif // _qra64_h_ diff --git a/lib/qra/qra64/qra64_all.c b/lib/qra/qra64/qra64_all.c deleted file mode 100644 index 28f8ab9..0000000 --- a/lib/qra/qra64/qra64_all.c +++ /dev/null @@ -1,1050 +0,0 @@ -/* -qra64.c -Encoding/decoding functions for the QRA64 mode - -(c) 2016 - Nico Palermo, IV3NWV - -------------------------------------------------------------------------------- - - qracodes is free software: you can redistribute it and/or modify - it under the terms of the GNU General Public License as published by - the Free Software Foundation, either version 3 of the License, or - (at your option) any later version. - qracodes is distributed in the hope that it will be useful, - but WITHOUT ANY WARRANTY; without even the implied warranty of - MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - GNU General Public License for more details. - - You should have received a copy of the GNU General Public License - along with qracodes source distribution. - If not, see . - ------------------------------------------------------------------------------ - -QRA code used in this sowftware release: - -QRA13_64_64_IRR_E: K=13 N=64 Q=64 irregular QRA code (defined in -qra13_64_64_irr_e.h /.c) - -Codes with K=13 are designed to include a CRC as the 13th information symbol -and improve the code UER (Undetected Error Rate). -The CRC symbol is not sent along the channel (the codes are punctured) and the -resulting code is a (12,63) code -*/ -//---------------------------------------------------------------------------- - -#include -#include - -#include "qra64.h" -#include "../qracodes/qracodes.h" -#include "../qracodes/qra13_64_64_irr_e.h" -#include "../qracodes/pdmath.h" -#include "../qracodes/normrnd.h" - -// Code parameters of the QRA64 mode -#define QRA64_CODE qra_13_64_64_irr_e -#define QRA64_NMSG 218 // Must much value indicated in QRA64_CODE.NMSG - -#define QRA64_KC (QRA64_K+1) // Information symbols (crc included) -#define QRA64_NC (QRA64_N+1) // Codeword length (as defined in the code) -#define QRA64_NITER 100 // max number of iterations per decode - -// static functions declarations ---------------------------------------------- -static int calc_crc6(const int *x, int sz); -static void ix_mask(float *dst, const float *src, const int *mask, - const int *x); -static int qra64_decode_attempts(qra64codec *pcodec, int *xdec, const float *ix); -static int qra64_do_decode(int *x, const float *pix, const int *ap_mask, - const int *ap_x); -static float qra64_fastfading_estim_noise_std( - float *rxen, - const float esnometric, - const int submode); -static void qra64_fastfading_intrinsics( - float *pix, - const float *rxamp, - const float *hptr, - const int hlen, - const float cmetric, - const int submode); -static float qra64_fastfading_msg_esno( - const int *ydec, - const float *rxamp, - const float sigma, - const float EsNoMetric, - const int hlen, - const int submode); - - -// a-priori information masks for fields in JT65-like msgs -------------------- -#define MASK_CQQRZ 0xFFFFFFC // CQ/QRZ calls common bits -#define MASK_CALL1 0xFFFFFFF -#define MASK_CALL2 0xFFFFFFF -#define MASK_GRIDFULL 0xFFFF -#define MASK_GRIDFULL12 0x3FFC // less aggressive mask (to be used with full AP decoding) -#define MASK_GRIDBIT 0x8000 // b[15] is 1 for free text, 0 otherwise -// ---------------------------------------------------------------------------- - -qra64codec *qra64_init(int flags) -{ - - // Eb/No value for which we optimize the decoder metric - const float EbNodBMetric = 2.8f; - const float EbNoMetric = (float)pow(10,EbNodBMetric/10); - const float R = 1.0f*(QRA64_KC)/(QRA64_NC); - - qra64codec *pcodec = (qra64codec*)malloc(sizeof(qra64codec)); - - if (!pcodec) - return 0; // can't allocate memory - - pcodec->decEsNoMetric = 1.0f*QRA64_m*R*EbNoMetric; - pcodec->apflags = flags; - - memset(pcodec->apmsg_set,0,APTYPE_SIZE*sizeof(int)); - - if (flags==QRA_NOAP) - return pcodec; - - // for QRA_USERAP and QRA_AUTOAP modes we always enable [CQ/QRZ ? ?] mgs look-up. - // encode CQ/QRZ AP messages - // NOTE: Here we handle only CQ and QRZ msgs. - // 'CQ nnn', 'CQ DX' and 'DE' msgs will be handled by the decoder - // as messages with no a-priori knowledge - qra64_apset(pcodec, CALL_CQ, 0, GRID_BLANK, APTYPE_CQQRZ); - - // initialize masks for decoding with a-priori information - encodemsg_jt65(pcodec->apmask_cqqrz, MASK_CQQRZ, 0, MASK_GRIDBIT); - encodemsg_jt65(pcodec->apmask_cqqrz_ooo, MASK_CQQRZ, 0, MASK_GRIDFULL); - encodemsg_jt65(pcodec->apmask_call1, MASK_CALL1, 0, MASK_GRIDBIT); - encodemsg_jt65(pcodec->apmask_call1_ooo, MASK_CALL1, 0, MASK_GRIDFULL); - encodemsg_jt65(pcodec->apmask_call2, 0, MASK_CALL2, MASK_GRIDBIT); - encodemsg_jt65(pcodec->apmask_call2_ooo, 0, MASK_CALL2, MASK_GRIDFULL); - encodemsg_jt65(pcodec->apmask_call1_call2, MASK_CALL1,MASK_CALL2, MASK_GRIDBIT); - encodemsg_jt65(pcodec->apmask_call1_call2_grid,MASK_CALL1,MASK_CALL2, MASK_GRIDFULL12); - encodemsg_jt65(pcodec->apmask_cq_call2, MASK_CQQRZ, MASK_CALL2, MASK_GRIDBIT); - encodemsg_jt65(pcodec->apmask_cq_call2_ooo, MASK_CQQRZ, MASK_CALL2, MASK_GRIDFULL12); - - return pcodec; -} - -void qra64_close(qra64codec *pcodec) -{ - free(pcodec); -} - -int qra64_apset(qra64codec *pcodec, const int mycall, const int hiscall, const int grid, const int aptype) -{ -// Set decoder a-priori knowledge accordingly to the type of the message to look up for -// arguments: -// pcodec = pointer to a qra64codec data structure as returned by qra64_init -// mycall = mycall to look for -// hiscall = hiscall to look for -// grid = grid to look for -// aptype = define and masks the type of AP to be set accordingly to the following: -// APTYPE_CQQRZ set [cq/qrz ? ?/blank] -// APTYPE_MYCALL set [mycall ? ?/blank] -// APTYPE_HISCALL set [? hiscall ?/blank] -// APTYPE_BOTHCALLS set [mycall hiscall ?] -// APTYPE_FULL set [mycall hiscall grid] -// APTYPE_CQHISCALL set [cq/qrz hiscall ?/blank] and [cq/qrz hiscall grid] -// returns: -// 0 on success -// -1 when qra64_init was called with the QRA_NOAP flag -// -2 invalid apytpe - - if (pcodec->apflags==QRA_NOAP) - return -1; - - switch (aptype) { - case APTYPE_CQQRZ: - encodemsg_jt65(pcodec->apmsg_cqqrz, CALL_CQ, 0, GRID_BLANK); - break; - case APTYPE_MYCALL: - encodemsg_jt65(pcodec->apmsg_call1, mycall, 0, GRID_BLANK); - break; - case APTYPE_HISCALL: - encodemsg_jt65(pcodec->apmsg_call2, 0, hiscall, GRID_BLANK); - break; - case APTYPE_BOTHCALLS: - encodemsg_jt65(pcodec->apmsg_call1_call2, mycall, hiscall, GRID_BLANK); - break; - case APTYPE_FULL: - encodemsg_jt65(pcodec->apmsg_call1_call2_grid, mycall, hiscall, grid); - break; - case APTYPE_CQHISCALL: - encodemsg_jt65(pcodec->apmsg_cq_call2, CALL_CQ, hiscall, GRID_BLANK); - encodemsg_jt65(pcodec->apmsg_cq_call2_grid, CALL_CQ, hiscall, grid); - break; - default: - return -2; // invalid ap type - } - - pcodec->apmsg_set[aptype]=1; // signal the decoder to look-up for the specified type - - - return 0; -} -void qra64_apdisable(qra64codec *pcodec, const int aptype) -{ - if (pcodec->apflags==QRA_NOAP) - return; - - if (aptype=APTYPE_SIZE) - return; - - pcodec->apmsg_set[aptype] = 0; // signal the decoder not to look-up to the specified type -} - -void qra64_encode(qra64codec *pcodec, int *y, const int *x) -{ - int encx[QRA64_KC]; // encoder input buffer - int ency[QRA64_NC]; // encoder output buffer - - int hiscall,mycall,grid; - - memcpy(encx,x,QRA64_K*sizeof(int)); // Copy input to encoder buffer - encx[QRA64_K]=calc_crc6(encx,QRA64_K); // Compute and add crc symbol - qra_encode(&QRA64_CODE, ency, encx); // encode msg+crc using given QRA code - - // copy codeword to output puncturing the crc symbol - memcpy(y,ency,QRA64_K*sizeof(int)); // copy information symbols - memcpy(y+QRA64_K,ency+QRA64_KC,QRA64_C*sizeof(int)); // copy parity symbols - - if (pcodec->apflags!=QRA_AUTOAP) - return; - - // Here we handle the QRA_AUTOAP mode -------------------------------------------- - - // When a [hiscall mycall ?] msg is detected we instruct the decoder - // to look for [mycall hiscall ?] msgs - // otherwise when a [cq mycall ?] msg is sent we reset the APTYPE_BOTHCALLS - - // look if the msg sent is a std type message (bit15 of grid field = 0) - if ((x[9]&0x80)==1) - return; // no, it's a text message, nothing to do - - // It's a [hiscall mycall grid] message - - // We assume that mycall is our call (but we don't check it) - // hiscall the station we are calling or a general call (CQ/QRZ/etc..) - decodemsg_jt65(&hiscall,&mycall,&grid,x); - - - if ((hiscall>=CALL_CQ && hiscall<=CALL_CQ999) || hiscall==CALL_CQDX || - hiscall==CALL_DE) { - // tell the decoder to look for msgs directed to us - qra64_apset(pcodec,mycall,0,0,APTYPE_MYCALL); - // We are making a general call and don't know who might reply - // Reset APTYPE_BOTHCALLS so decoder won't look for [mycall hiscall ?] msgs - qra64_apdisable(pcodec,APTYPE_BOTHCALLS); - } else { - // We are replying to someone named hiscall - // Set APTYPE_BOTHCALLS so decoder will try for [mycall hiscall ?] msgs - qra64_apset(pcodec,mycall, hiscall, GRID_BLANK, APTYPE_BOTHCALLS); - } - -} - -#define EBNO_MIN -10.0f // minimum Eb/No value returned by the decoder (in dB) -int qra64_decode(qra64codec *pcodec, float *ebno, int *x, const float *rxen) -{ - int k; - float *srctmp, *dsttmp; - float ix[QRA64_NC*QRA64_M]; // (depunctured) intrisic information - int xdec[QRA64_KC]; // decoded message (with crc) - int ydec[QRA64_NC]; // re-encoded message (for snr calculations) - float noisestd; // estimated noise variance - float msge; // estimated message energy - float ebnoval; // estimated Eb/No - int rc; - - if (QRA64_NMSG!=QRA64_CODE.NMSG) // sanity check - return -16; // QRA64_NMSG define is wrong - - // compute symbols intrinsic probabilities from received energy observations - noisestd = qra_mfskbesselmetric(ix, rxen, QRA64_m, QRA64_N,pcodec->decEsNoMetric); - - // de-puncture observations adding a uniform distribution for the crc symbol - - // move check symbols distributions one symbol towards the end - dsttmp = PD_ROWADDR(ix,QRA64_M, QRA64_NC-1); //Point to last symbol prob dist - srctmp = dsttmp-QRA64_M; // source is the previous pd - for (k=0;k57.004f) - ebnoval=57.004f; - ebnoval = ebnoval*57.03f/(57.03f-ebnoval); - - // compute value in dB - if (ebnoval<=0) - ebnoval = EBNO_MIN; // assume a minimum, positive value - else - ebnoval = 10.0f*(float)log10(ebnoval); - if (ebnoval4) - return -17; // invalid submode - - if (B90<1.0f || B90>238.0f) - return -18; // B90 out of range - - // compute index to most appropriate amplitude weighting function coefficients - hidx = (int)(log((float)B90)/log(1.09f) - 0.499f); - - if (hidx<0 || hidx > 64) - return -19; // index of weighting function out of range - - if (fadingModel==0) { // gaussian fading model - // point to gaussian weighting taps - hlen = hlen_tab_gauss[hidx]; // hlen = (L+1)/2 (where L=(odd) number of taps of w fun) - hptr = hptr_tab_gauss[hidx]; // pointer to the first (L+1)/2 coefficients of w fun - } - else if (fadingModel==1) { - // point to lorentzian weighting taps - hlen = hlen_tab_lorentz[hidx]; // hlen = (L+1)/2 (where L=(odd) number of taps of w fun) - hptr = hptr_tab_lorentz[hidx]; // pointer to the first (L+1)/2 coefficients of w fun - } - else - return -20; // invalid fading model index - - - // compute (euristically) the optimal decoder metric accordingly the given spread amount - // We assume that the decoder threshold is: - // Es/No(dB) = Es/No(AWGN)(dB) + 8*log(B90)/log(240)(dB) - // that's to say, at the maximum Doppler spread bandwidth (240 Hz) there's a ~8 dB Es/No degradation - // over the AWGN case - tempf = 8.0f*(float)log((float)B90)/(float)log(240.0f); - EsNoMetric = pcodec->decEsNoMetric*(float)pow(10.0f,tempf/10.0f); - - // Step 1 ----------------------------------------------------------------------------------- - // Evaluate the noise stdev from the received energies at nominal tone frequencies - // and transform energies to amplitudes - tempf = hptr[hlen-1]; // amplitude weigth at nominal freq; - tempf = tempf*tempf; // fractional energy at nominal freq. bin - - noisestd = qra64_fastfading_estim_noise_std(rxen, EsNoMetric, submode); - cmetric = (float)sqrt(M_PI_2*EsNoMetric)/noisestd; - - // Step 2 ----------------------------------------------------------------------------------- - // Compute message symbols probability distributions - qra64_fastfading_intrinsics(ix, rxen, hptr, hlen, cmetric, submode); - - // Step 3 --------------------------------------------------------------------------- - // De-puncture observations adding a uniform distribution for the crc symbol - // Move check symbols distributions one symbol towards the end - dsttmp = PD_ROWADDR(ix,QRA64_M, QRA64_NC-1); //Point to last symbol prob dist - srctmp = dsttmp-QRA64_M; // source is the previous pd - for (k=0;k238.0f) - return -18; // B90 out of range - - // compute index to most appropriate amplitude weighting function coefficients - hidx = (int)(log((float)B90)/log(1.09f) - 0.499f); - - if (hidx<0 || hidx > 64) - return -19; // index of weighting function out of range - - if (fadingModel==0) { // gaussian fading model - // point to gaussian weighting taps - hlen = hlen_tab_gauss[hidx]; // hlen = (L+1)/2 (where L=(odd) number of taps of w fun) - hptr = hptr_tab_gauss[hidx]; // pointer to the first (L+1)/2 coefficients of w fun - } - else if (fadingModel==1) { - // point to lorentzian weighting taps - hlen = hlen_tab_lorentz[hidx]; // hlen = (L+1)/2 (where L=(odd) number of taps of w fun) - hptr = hptr_tab_lorentz[hidx]; // pointer to the first (L+1)/2 coefficients of w fun - } - else - return -20; // invalid fading model index - - - // Compute the unfaded tone amplitudes from the Eb/No value passed to the call - N0 = 1.0f; // assume unitary noise PSD - sigmanoise = (float)sqrt(N0/2); - EsN0 = (float)pow(10.0f,EbN0dB/10.0f)*QRA64_m*QRA64_K/QRA64_N; // Es/No = m*R*Eb/No - Es = EsN0*N0; - A = (float)sqrt(Es/2.0f); // unfaded tone amplitude (i^2+q^2 = Es/2+Es/2 = Es) - - - // Generate gaussian noise iq components - normrnd_s(channel_out, bpm*2, 0 , sigmanoise); - - // Add message symbols energies - for (n=0;n=0;j--) { - sigmasig = A*hptr[j]; - normrnd_s(iq, 2, 0 , sigmasig); -// iq[0]=sigmasig*sqrt(2); iq[1]=0; debug: used to verify Eb/No - *curi++ += iq[0]; - *curq++ += iq[1]; -// tote +=iq[0]*iq[0]+iq[1]*iq[1]; // debug - } - - } - -// tote = tote/QRA64_N; // debug - - // compute total bin energies (S+N) and store in first half of buffer - curi = channel_out; - curq = channel_out+bpm; - for (n=0;n=0;j--) { - u = *curbin++ * hptr[j]*cmetric; - u = u*u/(u+(float)M_E); // log(I0(u)) approx. - loglh = loglh + u; - } - if (loglh>maxloglh) // keep track of the max loglikelihood - maxloglh = loglh; - curix[k]=loglh; - } - // scale to likelihoods - sumix = 0.f; - for (k=0;k=0;j--) { - u = *curbin++; - msgsn += u*u; - } - - } - - msgsn = msgsn/(QRA64_N*tothlen); // avg msg energy per bin (noise included) - - // as sigma is overestimated (sigmatrue = sigma*sqrt((1+EsNoMetric/bps)/(1+EsNo/bps)) - // we have: msgsn = (1+x/hlen)/(1+x/bps)*2*sigma^2*(1+EsnoMetric/bps), where x = Es/N0(true) - // - // we can then write: - // u = msgsn/2.0f/(sigma*sigma)/(1.0f+EsNoMetric/bps); - // (1+x/hlen)/(1+x/bps) = u - - u = msgsn/(2.0f*sigma*sigma)/(1.0f+EsNoMetric/bps); - - // check u>1 - if (u<1) - return 0.f; - - // check u(bps/tothlen)) - return 10000.f; - - // solve for Es/No - esno = (u-1.0f)/(1.0f/tothlen-u/bps); - - return esno; - - -} - - -// Attempt to decode given intrisic information -static int qra64_decode_attempts(qra64codec *pcodec, int *xdec, const float *ix) -{ - int rc; - - // Attempt to decode without a-priori info -------------------------------- - rc = qra64_do_decode(xdec, ix, NULL, NULL); - if (rc>=0) - return 0; // successfull decode with AP0 - else - if (pcodec->apflags==QRA_NOAP) - // nothing more to do - return rc; // rc<0 = unsuccessful decode - - // Here we handle decoding with AP knowledge - - // Attempt to decode CQ calls - rc = qra64_do_decode(xdec,ix,pcodec->apmask_cqqrz, pcodec->apmsg_cqqrz); - if (rc>=0) return 1; // decoded [cq/qrz ? ?] - - rc = qra64_do_decode(xdec, ix, pcodec->apmask_cqqrz_ooo, - pcodec->apmsg_cqqrz); - if (rc>=0) return 2; // decoded [cq ? ooo] - - // attempt to decode calls directed to us - if (pcodec->apmsg_set[APTYPE_MYCALL]) { - rc = qra64_do_decode(xdec, ix, pcodec->apmask_call1, - pcodec->apmsg_call1); - if (rc>=0) return 3; // decoded [mycall ? ?] - rc = qra64_do_decode(xdec, ix, pcodec->apmask_call1_ooo, - pcodec->apmsg_call1); - if (rc>=0) return 4; // decoded [mycall ? ooo] - } - - // attempt to decode [mycall srccall ?] msgs - if (pcodec->apmsg_set[APTYPE_BOTHCALLS]) { - rc = qra64_do_decode(xdec, ix, pcodec->apmask_call1_call2, - pcodec->apmsg_call1_call2); - if (rc>=0) return 5; // decoded [mycall srccall ?] - } - - // attempt to decode [? hiscall ?/b] msgs - if (pcodec->apmsg_set[APTYPE_HISCALL]) { - rc = qra64_do_decode(xdec, ix, pcodec->apmask_call2, - pcodec->apmsg_call2); - if (rc>=0) return 6; // decoded [? hiscall ?] - rc = qra64_do_decode(xdec, ix, pcodec->apmask_call2_ooo, - pcodec->apmsg_call2); - if (rc>=0) return 7; // decoded [? hiscall ooo] - } - - // attempt to decode [cq/qrz hiscall ?/b/grid] msgs - if (pcodec->apmsg_set[APTYPE_CQHISCALL]) { - - rc = qra64_do_decode(xdec, ix, pcodec->apmask_cq_call2, - pcodec->apmsg_cq_call2); - if (rc>=0) return 9; // decoded [cq/qrz hiscall ?] - - rc = qra64_do_decode(xdec, ix, pcodec->apmask_cq_call2_ooo, - pcodec->apmsg_cq_call2_grid); - if (rc>=0) { - // Full AP mask need special handling - // To minimize false decodes we check the decoded message - // with what passed in the ap_set call - if (memcmp(pcodec->apmsg_cq_call2_grid,xdec, QRA64_K*sizeof(int))!=0) - return -1; - else - return 11; // decoded [cq/qrz hiscall grid] - }; - - rc = qra64_do_decode(xdec, ix, pcodec->apmask_cq_call2_ooo, - pcodec->apmsg_cq_call2); - if (rc>=0) { - // Full AP mask need special handling - // To minimize false decodes we check the decoded message - // with what passed in the ap_set call - if (memcmp(pcodec->apmsg_cq_call2,xdec, QRA64_K*sizeof(int))!=0) - return -1; - else - return 10; // decoded [cq/qrz hiscall ] - } - } - - // attempt to decode [mycall hiscall grid] - if (pcodec->apmsg_set[APTYPE_FULL]) { - rc = qra64_do_decode(xdec, ix, pcodec->apmask_call1_call2_grid, - pcodec->apmsg_call1_call2_grid); - if (rc>=0) { - // Full AP mask need special handling - // All the three msg fields were given. - // To minimize false decodes we check the decoded message - // with what passed in the ap_set call - if (memcmp(pcodec->apmsg_call1_call2_grid,xdec, QRA64_K*sizeof(int))!=0) - return -1; - else - return 8; // decoded [mycall hiscall grid] - } - } - - // all decoding attempts failed - return rc; -} - - - -// Decode with given a-priori information -static int qra64_do_decode(int *xdec, const float *pix, const int *ap_mask, - const int *ap_x) -{ - int rc; - const float *ixsrc; - float ix_masked[QRA64_NC*QRA64_M]; // Masked intrinsic information - float ex[QRA64_NC*QRA64_M]; // Extrinsic information from the decoder - - float v2cmsg[QRA64_NMSG*QRA64_M]; // buffers for the decoder messages - float c2vmsg[QRA64_NMSG*QRA64_M]; - - if (ap_mask==NULL) { // no a-priori information - ixsrc = pix; // intrinsic source is what passed as argument - } else { - // a-priori information provided - // mask channel observations with a-priori - ix_mask(ix_masked,pix,ap_mask,ap_x); - ixsrc = ix_masked; // intrinsic source is the masked version - } - - // run the decoding algorithm - rc = qra_extrinsic(&QRA64_CODE,ex,ixsrc,QRA64_NITER,v2cmsg,c2vmsg); - if (rc<0) - return -1; // no convergence in given iterations - - // decode - qra_mapdecode(&QRA64_CODE,xdec,ex,ixsrc); - - // verify crc - if (calc_crc6(xdec,QRA64_K)!=xdec[QRA64_K]) // crc doesn't match (detected error) - return -2; // decoding was succesfull but crc doesn't match - - return 0; -} - - -// crc functions -------------------------------------------------------------- -// crc-6 generator polynomial -// g(x) = x^6 + a5*x^5 + ... + a1*x + a0 - -// g(x) = x^6 + x + 1 -#define CRC6_GEN_POL 0x30 // MSB=a0 LSB=a5 - -// g(x) = x^6 + x^2 + x + 1 (See: https://users.ece.cmu.edu/~koopman/crc/) -// #define CRC6_GEN_POL 0x38 // MSB=a0 LSB=a5. Simulation results are similar - -static int calc_crc6(const int *x, int sz) -{ - // todo: compute it faster using a look up table - int k,j,t,sr = 0; - for (k=0;k>1) ^ CRC6_GEN_POL; - else - sr = (sr>>1); - t>>=1; - } - } - return sr; -} - -static void ix_mask(float *dst, const float *src, const int *mask, - const int *x) -{ - // mask intrinsic information (channel observations) with a priori knowledge - - int k,kk, smask; - float *row; - - memcpy(dst,src,(QRA64_NC*QRA64_M)*sizeof(float)); - - for (k=0;k>22)&0x3F; - y[1]= (call1>>16)&0x3F; - y[2]= (call1>>10)&0x3F; - y[3]= (call1>>4)&0x3F; - y[4]= (call1<<2)&0x3F; - - y[4] |= (call2>>26)&0x3F; - y[5]= (call2>>20)&0x3F; - y[6]= (call2>>14)&0x3F; - y[7]= (call2>>8)&0x3F; - y[8]= (call2>>2)&0x3F; - y[9]= (call2<<4)&0x3F; - - y[9] |= (grid>>12)&0x3F; - y[10]= (grid>>6)&0x3F; - y[11]= (grid)&0x3F; - -} -void decodemsg_jt65(int *call1, int *call2, int *grid, const int *x) -{ - int nc1, nc2, ng; - - nc1 = x[4]>>2; - nc1 |= x[3]<<4; - nc1 |= x[2]<<10; - nc1 |= x[1]<<16; - nc1 |= x[0]<<22; - - nc2 = x[9]>>4; - nc2 |= x[8]<<2; - nc2 |= x[7]<<8; - nc2 |= x[6]<<14; - nc2 |= x[5]<<20; - nc2 |= (x[4]&0x03)<<26; - - ng = x[11]; - ng |= x[10]<<6; - ng |= (x[9]&0x0F)<<12; - - *call1 = nc1; - *call2 = nc2; - *grid = ng; -} diff --git a/lib/qra/qra64/qra64_subs.c b/lib/qra/qra64/qra64_subs.c deleted file mode 100644 index b60f9fa..0000000 --- a/lib/qra/qra64/qra64_subs.c +++ /dev/null @@ -1,65 +0,0 @@ -// qra64_subs.c -// Fortran interface routines for QRA64 - -#include "qra64.h" -#include - -static qra64codec *pqra64codec = NULL; - -void qra64_enc_(int x[], int y[]) -{ - if (pqra64codec==NULL) pqra64codec = qra64_init(QRA_USERAP); - qra64_encode(pqra64codec, y, x); -} - -void qra64_dec_(float r[], int* nc1, int* nc2, int* ng2, int* APtype, - int* iset, int* ns0, float* b0, int* nf0, - int xdec[], float* snr, int* rc) -{ -/* - APtype: AP ------------------------------------------------------------------------ - -1 0 (no AP information) - 0 [CQ/QRZ ? ? ] 25/37 - 1 [MyCall ? ? ] 25/37 - 2 [ ? HisCall ? ] 25/37 - 3 [MyCall HisCall ? ] 49/68 - 4 [MyCall HisCall grid] 68 - 5 [CQ/QRZ HisCall ? ] 49/68 - - rc Message format AP APTYPE Comments ------------------------------------------------------------------------- - -16 Failed sanity check - -2 Decoded but CRC failed - -1 No decode - 0 [ ? ? ? ] 0 -1 Decode with no AP info - 1 [CQ/QRZ ? ? ] 25 0 - 2 [CQ/QRZ ? _ ] 37 0 - 3 [MyCall ? ? ] 25 1 - 4 [MyCall ? _ ] 37 1 - 5 [MyCall HisCall ? ] 49 3 - 6 [ ? HisCall ? ] 25 2 Optional - 7 [ ? HisCall _ ] 37 2 Optional - 8 [MyCall HisCall Grid] 68 4 - 9 [CQ/QRZ HisCall ? ] 49 5 Optional (not needed?) - 10 [CQ/QRZ HisCall _ ] 68 5 Optional - 11 [CQ/QRZ HisCall Grid] 68 ? Optional -*/ - - float EbNodBEstimated; - int err=0; - int nSubmode=*ns0; - float b90=*b0; - int nFadingModel=*nf0; - - if(pqra64codec==NULL) pqra64codec = qra64_init(QRA_USERAP); - err=qra64_apset(pqra64codec,*nc1,*nc2,*ng2,*APtype); - if(err<0) printf("ERROR: qra64_apset returned %d\n",err); - - if(*iset==0) { - *rc = qra64_decode_fastfading(pqra64codec,&EbNodBEstimated,xdec,r, - nSubmode,b90,nFadingModel); - *snr = EbNodBEstimated - 31.0; - } -} - diff --git a/lib/qra/qra64/qra64example.txt b/lib/qra/qra64/qra64example.txt deleted file mode 100644 index 3add33d..0000000 --- a/lib/qra/qra64/qra64example.txt +++ /dev/null @@ -1,88 +0,0 @@ -$ qra64_nico -h - -QRA64 Mode Tests -2016, Nico Palermo - IV3NWV - ---------------------------- - -Syntax: qra64 [-s] [-c] [-a] [-t] [-h] -Options: - -s : set simulation SNR in 2500 Hz BW (default:-27.5 dB) - -c : set channel type 0=AWGN (default) 1=Rayleigh - -a : set decode type 0=NOAP 1=AUTOAP (default) 2=USERAP - -t: 0=simulate seq of msgs between IV3NWV and K1JT (default) - 1=simulate K1JT receiving K1JT IV3NWV JN66 - 2=simulate fast-fading routines (option -c ignored) -Options used only for fast-fading simulations: - -b : 90% fading bandwidth in Hz [1..230 Hz] (default = 2.5 Hz) - -m : fading model. 0=Gauss, 1=Lorentz (default = Lorentz) - -q : qra64 submode. 0=QRA64A,... 4=QRA64E (default = QRA64A) - -h: this help - - -############################################################################# -Usage example: - -qra64 -c2 -t2 -a2 -b50 -m1 -q2 -s-26.0 -n50000 - -Simulate a fast-fading channel (-c2) -Evaluate decoder performance (-t2) with -USER_AP (-a2) -B90 = 50 Hz (-b50) -Lorentz model (-m1) -submode QRA64C (-q2) -Input SNR = -26.0 dB (-s-26.0) -Simulate 50000 transmissions (-n50000) - -(type qra64 -h for command syntax) - -Command Output: - -Input SNR = -26.0dB ap-mode=USER AP - -Simulating the fast-fading channel -B90=50.00 Hz - Fading Model=Lorentz - Submode=QRA64C -Decoder metric = Matched to fast-fading signal - -Encoding msg [K1JT IV3NWV JN66] -50000 transmissions will be simulated - -K1JT decoder enabled for [CQ ? ?/blank] -K1JT decoder enabled for [K1JT ? ?/blank] -K1JT decoder enabled for [? IV3NWV ?/blank] -K1JT decoder enabled for [K1JT IV3NWV ?] -K1JT decoder enabled for [K1JT IV3NWV JN66] -K1JT decoder enabled for [CQ IV3NWV ?/b/JN66] - -Now decoding with K1JT's decoder... - 5.5 % -Undetected error with rc=6 - 13.1 % -Undetected error with rc=7 - 70.8 % -Undetected error with rc=1 - 75.8 % -Undetected error with rc=9 - 88.9 % -Undetected error with rc=6 - 100.0 % - -Msgs transmitted:50000 -Msg decoded: - -rc= 0 0 with [? ? ?] AP0 -rc= 1 0 with [CQ ? ?] AP27 -rc= 2 0 with [CQ ? ] AP42 -rc= 3 145 with [CALL ? ?] AP29 -rc= 4 0 with [CALL ? ] AP44 -rc= 5 12085 with [CALL CALL ?] AP57 -rc= 6 0 with [? CALL ?] AP29 -rc= 7 0 with [? CALL ] AP44 -rc= 8 24307 with [CALL CALL G] AP72 -rc= 9 0 with [CQ CALL ?] AP55 -rc=10 0 with [CQ CALL ] AP70 -rc=11 0 with [CQ CALL G] AP70 - -Total: 36537/50000 (5 undetected errors) - -Estimated SNR (average in dB) = -26.26 dB diff --git a/lib/qra/qra64/qra64sim.f90 b/lib/qra/qra64/qra64sim.f90 deleted file mode 100644 index b7ca2e1..0000000 --- a/lib/qra/qra64/qra64sim.f90 +++ /dev/null @@ -1,170 +0,0 @@ -program qra64sim - -! Generate simulated QRA64 data for testing the decoder. - - use wavhdr - use packjt - parameter (NMAX=54*12000) ! = 648,000 - parameter (NFFT=10*65536,NH=NFFT/2) - type(hdr) h !Header for .wav file - integer*2 iwave(NMAX) !Generated waveform - integer*4 itone(84) !Channel symbols (values 0-63) - real*4 xnoise(NMAX) !Generated random noise - real*4 dat(NMAX) !Generated real data - complex cdat(NMAX) !Generated complex waveform - complex cspread(0:NFFT-1) !Complex amplitude for Rayleigh fading - complex z - real*8 f0,dt,twopi,phi,dphi,baud,fsample,freq - character msg*22,fname*11,csubmode*1,arg*12 - character msgsent*22 - - nargs=iargc() - if(nargs.ne. 7) then - print *, 'Usage: qra64sim "msg" A-E Nsigs fDop DT Nfiles SNR' - print *, 'Example qra64sim "K1ABC W9XYZ EN37" A 10 0.2 0.0 1 0' - go to 999 - endif - call getarg(1,msg) - call getarg(2,csubmode) - mode64=2**(ichar(csubmode)-ichar('A')) - call getarg(3,arg) - read(arg,*) nsigs - call getarg(4,arg) - read(arg,*) fspread - call getarg(5,arg) - read(arg,*) xdt - call getarg(6,arg) - read(arg,*) nfiles - call getarg(7,arg) - read(arg,*) snrdb - - if(mode64.ge.8) nsigs=1 - rms=100. - fsample=12000.d0 !Sample rate (Hz) - dt=1.d0/fsample !Sample interval (s) - twopi=8.d0*atan(1.d0) - npts=54*12000 !Total samples in .wav file - nsps=6912 - baud=12000.d0/nsps !Keying rate = 1.7361111111 - nsym=84 !Number of channel symbols - h=default_header(12000,npts) - dfsig=2000.0/nsigs !Freq spacing between sigs in file (Hz) - ichk=0 - - write(*,1000) -1000 format('File Sig Freq A-E S/N DT Dop Message'/60('-')) - - do ifile=1,nfiles !Loop over requested number of files - write(fname,1002) ifile !Output filename -1002 format('000000_',i4.4) - open(10,file=fname//'.wav',access='stream',status='unknown') - xnoise=0. - cdat=0. - if(snrdb.lt.90) then - do i=1,npts - xnoise(i)=gran() !Generate gaussian noise - enddo - endif - - do isig=1,nsigs !Generate requested number of sigs - if(mod(nsigs,2).eq.0) f0=1500.0 + dfsig*(isig-0.5-nsigs/2) - if(mod(nsigs,2).eq.1) f0=1500.0 + dfsig*(isig-(nsigs+1)/2) - if(nsigs.eq.1) f0=1000.0 - xsnr=snrdb - if(snrdb.eq.0.0) xsnr=-20 - isig - - call genqra64(msg,ichk,msgsent,itone,itype) - - bandwidth_ratio=2500.0/6000.0 - sig=sqrt(2*bandwidth_ratio)*10.0**(0.05*xsnr) - if(xsnr.gt.90.0) sig=1.0 - write(*,1020) ifile,isig,f0,csubmode,xsnr,xdt,fspread,msg -1020 format(i4,i4,f10.3,2x,a1,2x,f5.1,f6.2,f6.1,1x,a22) - - phi=0.d0 - dphi=0.d0 - k=(xdt+1.0)*12000 !Start audio at t = xdt + 1.0 s - isym0=-99 - do i=1,npts !Add this signal into cdat() - isym=i/nsps + 1 - if(isym.gt.nsym) exit - if(isym.ne.isym0) then - freq=f0 + itone(isym)*baud*mode64 - dphi=twopi*freq*dt - isym0=isym - endif - phi=phi + dphi - if(phi.gt.twopi) phi=phi-twopi - xphi=phi - z=cmplx(cos(xphi),sin(xphi)) - k=k+1 - if(k.ge.1) cdat(k)=cdat(k) + sig*z - enddo - enddo - - if(fspread.ne.0) then !Apply specified Doppler spread - df=12000.0/nfft - twopi=8*atan(1.0) - cspread(0)=1.0 - cspread(NH)=0. - b=6.0 !Lorenzian 3/28 onward - do i=1,NH - f=i*df - x=b*f/fspread - z=0. - a=0. - if(x.lt.3.0) then !Cutoff beyond x=3 - a=sqrt(1.111/(1.0+x*x)-0.1) !Lorentzian - call random_number(r1) - phi1=twopi*r1 - z=a*cmplx(cos(phi1),sin(phi1)) - endif - cspread(i)=z - z=0. - if(x.lt.50.0) then - call random_number(r2) - phi2=twopi*r2 - z=a*cmplx(cos(phi2),sin(phi2)) - endif - cspread(NFFT-i)=z - enddo - - do i=0,NFFT-1 - f=i*df - if(i.gt.NH) f=(i-nfft)*df - s=real(cspread(i))**2 + aimag(cspread(i))**2 -! write(13,3000) i,f,s,cspread(i) -!3000 format(i5,f10.3,3f12.6) - enddo -! s=real(cspread(0))**2 + aimag(cspread(0))**2 -! write(13,3000) 1024,0.0,s,cspread(0) - - call four2a(cspread,NFFT,1,1,1) !Transform to time domain - - sum=0. - do i=0,NFFT-1 - p=real(cspread(i))**2 + aimag(cspread(i))**2 - sum=sum+p - enddo - avep=sum/NFFT - fac=sqrt(1.0/avep) - cspread=fac*cspread !Normalize to constant avg power - cdat=cspread(1:npts)*cdat !Apply Rayleigh fading - -! do i=0,NFFT-1 -! p=real(cspread(i))**2 + aimag(cspread(i))**2 -! write(14,3010) i,p,cspread(i) -!3010 format(i8,3f12.6) -! enddo - - endif - - dat=aimag(cdat) + xnoise !Add the generated noise - fac=32767.0/nsigs - if(snrdb.ge.90.0) iwave(1:npts)=nint(fac*dat(1:npts)) - if(snrdb.lt.90.0) iwave(1:npts)=nint(rms*dat(1:npts)) - write(10) h,iwave(1:npts) !Save the .wav file - close(10) - enddo - -999 end program qra64sim diff --git a/lib/qra/qracodes/Makefile.Win b/lib/qra/qracodes/Makefile.Win deleted file mode 100644 index fb30504..0000000 --- a/lib/qra/qracodes/Makefile.Win +++ /dev/null @@ -1,33 +0,0 @@ -CC = gcc -CFLAGS = -O2 -Wall -I. -D_WIN32 - -# Default rules -%.o: %.c - ${CC} ${CFLAGS} -c $< -%.o: %.f - ${FC} ${FFLAGS} -c $< -%.o: %.F - ${FC} ${FFLAGS} -c $< -%.o: %.f90 - ${FC} ${FFLAGS} -c $< -%.o: %.F90 - ${FC} ${FFLAGS} -c $< - -all: libqra64.a qracodes.exe - -OBJS1 = normrnd.o npfwht.o pdmath.o qra12_63_64_irr_b.o \ - qra13_64_64_irr_e.o qracodes.o - -libqra64.a: $(OBJS1) - ar cr libqra64.a $(OBJS1) - ranlib libqra64.a - -OBJS2 = main.o - -qracodes.exe: $(OBJS2) - ${CC} -o qracodes.exe $(OBJS2) libqra64.a -lm - -.PHONY : clean - -clean: - $(RM) *.o libqra64.a qracodes.exe diff --git a/lib/qra/qracodes/ebno10000.txt b/lib/qra/qracodes/ebno10000.txt deleted file mode 100644 index c41174b..0000000 --- a/lib/qra/qracodes/ebno10000.txt +++ /dev/null @@ -1,7 +0,0 @@ -# Eb/No Values to be used during the code simulation -# Each line of this file indicates the Eb/No value to be simulated (in dB) -# and the number of errors to be detected by the decoder -0.6 10000 -1.1 10000 -1.6 10000 -2.1 10000 diff --git a/lib/qra/qracodes/ebnovalues.txt b/lib/qra/qracodes/ebnovalues.txt deleted file mode 100644 index 7dba138..0000000 --- a/lib/qra/qracodes/ebnovalues.txt +++ /dev/null @@ -1,15 +0,0 @@ -# Eb/No Values to be used during the code simulation -# Each line of this file indicates the Eb/No value to be simulated (in dB) -# and the number of errors to be detected by the decoder -1.1 1000 -1.6 1000 -2.1 1000 -2.6 1000 -3.1 1000 -3.6 1000 -4.1 1000 -4.6 1000 -5.1 500 -5.6 200 -6.1 100 -6.6 50 \ No newline at end of file diff --git a/lib/qra/qracodes/ebnovaluesfast.txt b/lib/qra/qracodes/ebnovaluesfast.txt deleted file mode 100644 index b057b31..0000000 --- a/lib/qra/qracodes/ebnovaluesfast.txt +++ /dev/null @@ -1,11 +0,0 @@ -# Eb/No Values to be used during the code simulation -# Each line of this file indicates the Eb/No value to be simulated (in dB) -# and the number of errors to be detected by the decoder -1.1 500 -1.6 500 -2.1 500 -2.6 500 -3.1 500 -3.6 500 -4.1 200 -4.6 50 diff --git a/lib/qra/qracodes/main.c b/lib/qra/qracodes/main.c deleted file mode 100644 index 5f9f067..0000000 --- a/lib/qra/qracodes/main.c +++ /dev/null @@ -1,737 +0,0 @@ -// main.c -// Word Error Rate test example for Q-ary RA codes over GF(64) -// -// (c) 2016 - Nico Palermo, IV3NWV -// -// Thanks to Andrea Montefusco IW0HDV for his help on adapting the sources -// to OSs other than MS Windows -// -// ------------------------------------------------------------------------------ -// This file is part of the qracodes project, a Forward Error Control -// encoding/decoding package based on Q-ary RA (Repeat and Accumulate) LDPC codes. -// -// Files in this package: -// main.c - this file -// normrnd.c/.h - random gaussian number generator -// npfwht.c/.h - Fast Walsh-Hadamard Transforms -// pdmath.c/.h - Elementary math on probability distributions -// qra12_63_64_irr_b.c/.h - Tables for a QRA(12,63) irregular RA code over GF(64) -// qra13_64_64_irr_e.c/.h - Tables for a QRA(13,64) irregular RA code " " -// qracodes.c/.h - QRA codes encoding/decoding functions -// -// ------------------------------------------------------------------------------- -// -// qracodes is free software: you can redistribute it and/or modify -// it under the terms of the GNU General Public License as published by -// the Free Software Foundation, either version 3 of the License, or -// (at your option) any later version. -// qracodes is distributed in the hope that it will be useful, -// but WITHOUT ANY WARRANTY; without even the implied warranty of -// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -// GNU General Public License for more details. - -// You should have received a copy of the GNU General Public License -// along with qracodes source distribution. -// If not, see . - -// ----------------------------------------------------------------------------- - -// Two codes are available for simulations in this sowftware release: - -// QRA12_63_64_IRR_B: K=12 N=63 Q=64 irregular QRA code (defined in qra12_63_64_irr_b.h /.c) -// QRA13_64_64_IRR_E: K=13 N=64 Q=64 irregular QRA code (defined in qra13_64_64_irr_b.h /.c) - -// Codes with K=13 are designed to include a CRC as the 13th information symbol -// and improve the code UER (Undetected Error Rate). -// The CRC symbol is not sent along the channel (the codes are punctured) and the -// resulting code is still a (12,63) code with an effective code rate of R = 12/63. - -// ------------------------------------------------------------------------------ - -// OS dependent defines and includes -------------------------------------------- - -#if _WIN32 // note the underscore: without it, it's not msdn official! - // Windows (x64 and x86) - #include // required only for GetTickCount(...) - #include // _beginthread -#endif - -#if defined(__linux__) - -// remove unwanted macros -#define __cdecl - -// implements Windows API -#include - - unsigned int GetTickCount(void) { - struct timespec ts; - unsigned int theTick = 0U; - clock_gettime( CLOCK_REALTIME, &ts ); - theTick = ts.tv_nsec / 1000000; - theTick += ts.tv_sec * 1000; - return theTick; -} - -// Convert Windows millisecond sleep -// -// VOID WINAPI Sleep(_In_ DWORD dwMilliseconds); -// -// to Posix usleep (in microseconds) -// -// int usleep(useconds_t usec); -// -#include -#define Sleep(x) usleep(x*1000) - -#endif - -#if defined(__linux__) || ( defined(__MINGW32__) || defined (__MIGW64__) ) -#include -#endif - -#if __APPLE__ -#endif - -#include -#include - -#include "qracodes.h" -#include "normrnd.h" // gaussian numbers generator -#include "pdmath.h" // operations on probability distributions - -// defined codes -#include "qra12_63_64_irr_b.h" -#include "qra13_64_64_irr_e.h" - -// ----------------------------------------------------------------------------------- - -#define NTHREADS_MAX 160 - -// channel types -#define CHANNEL_AWGN 0 -#define CHANNEL_RAYLEIGH 1 - -// amount of a-priori information provided to the decoder -#define AP_NONE 0 -#define AP_28 1 -#define AP_44 2 -#define AP_56 3 - -const char ap_str[4][16] = { - "None", - "28 bit", - "44 bit", - "56 bit" -}; - -const char fnameout_pfx[2][64] = { - "wer-awgn-", - "wer-rayleigh-" -}; -const char fnameout_sfx[4][64] = { - "-ap00.txt", - "-ap28.txt", - "-ap44.txt", - "-ap56.txt" -}; - -const int ap_masks_jt65[4][13] = { -// Each row must be 13 entries long (to handle puntc. codes 13,64) -// The mask of 13th symbol (crc) is alway initializated to 0 - // AP0 - no a-priori knowledge - { 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, - // AP28 - 1st field known [cq ? ?] or [dst ? ?] - {0x3F,0x3F,0x3F,0x3F,0x3C, 0, 0, 0, 0, 0, 0, 0}, - // AP44 - 1st and 3rd fields known [cq ? 0] or [dst ? 0] - {0x3F,0x3F,0x3F,0x3F,0x3C, 0, 0, 0, 0,0x0F,0x3F,0x3F}, - // AP56 - 1st and 2nd fields known [dst src ?] - {0x3F,0x3F,0x3F,0x3F,0x3F,0x3F,0x3F,0x3F,0x3F,0x30, 0, 0} -}; - -void ix_mask(const qracode *pcode, float *r, const int *mask, const int *x); - -void printword(char *msg, int *x, int size) -{ - int k; - printf("\n%s ",msg); - for (k=0;kc msg buffer - float *qra_c2vmsg; //[qra_NMSG*qra_M]; MP decoder c->v msg buffer - float *rp; // [qra_N*qra_M]; received samples (real component) buffer - float *rq; // [qra_N*qra_M]; received samples (imag component) buffer - float *chp; //[qra_N]; channel gains (real component) buffer - float *chq; //[qra_N]; channel gains (imag component) buffer - float *r; //[qra_N*qra_M]; received samples (amplitude) buffer - float *ix; // [qra_N*qra_M]; // intrinsic information to the MP algorithm - float *ex; // [qra_N*qra_M]; // extrinsic information from the MP algorithm - -} wer_test_ds; - -typedef void( __cdecl *pwer_test_thread)(wer_test_ds*); - -// crc-6 generator polynomial -// g(x) = x^6 + a5*x^5 + ... + a1*x + a0 - -// g(x) = x^6 + x + 1 -#define CRC6_GEN_POL 0x30 // MSB=a0 LSB=a5 - -// g(x) = x^6 + x^2 + x + 1 (as suggested by Joe. See: https://users.ece.cmu.edu/~koopman/crc/) -// #define CRC6_GEN_POL 0x38 // MSB=a0 LSB=a5. Simulation results are similar - -int calc_crc6(int *x, int sz) -{ - int k,j,t,sr = 0; - for (k=0;k>1) ^ CRC6_GEN_POL; - else - sr = (sr>>1); - t>>=1; - } - } - return sr; -} - -void wer_test_thread(wer_test_ds *pdata) -{ - const qracode *pcode=pdata->pcode; - const int qra_K = pcode->K; - const int qra_N = pcode->N; - const int qra_M = pcode->M; - const int qra_m = pcode->m; - const int NSAMPLES = pcode->N*pcode->M; - - const float No = 1.0f; // noise spectral density - const float sigma = (float)sqrt(No/2.0f); // std dev of noise I/Q components - const float sigmach = (float)sqrt(1/2.0f); // std dev of channel I/Q gains - - // Eb/No value for which we optimize the bessel metric - const float EbNodBMetric = 2.8f; - const float EbNoMetric = (float)pow(10,EbNodBMetric/10); - - int k,t,j,diff; - float R; - float EsNoMetric; - float EbNo, EsNo, Es, A; - int channel_type, code_type; - int nt=0; // transmitted codewords - int nerrs = 0; // total number of errors - int nerrsu = 0; // number of undetected errors - int rc; - - - // inizialize pointer to required buffers - int *x=pdata->x; // message buffer - int *y=pdata->y, *ydec=pdata->ydec; // encoded/decoded codeword buffers - float *qra_v2cmsg=pdata->qra_v2cmsg; // table of the v->c messages - float *qra_c2vmsg=pdata->qra_c2vmsg; // table of the c->v messages - float *rp=pdata->rp; // received samples (real component) - float *rq=pdata->rq; // received samples (imag component) - float *chp=pdata->chp; // channel gains (real component) - float *chq=pdata->chq; // channel gains (imag component) - float *r=pdata->r; // received samples amplitudes - float *ix=pdata->ix; // intrinsic information to the MP algorithm - float *ex=pdata->ex; // extrinsic information from the MP algorithm - - channel_type = pdata->channel_type; - code_type = pcode->type; - - // define the (true) code rate accordingly to the code type - switch(code_type) { - case QRATYPE_CRC: - R = 1.0f*(qra_K-1)/qra_N; - break; - case QRATYPE_CRCPUNCTURED: - R = 1.0f*(qra_K-1)/(qra_N-1); - break; - case QRATYPE_NORMAL: - default: - R = 1.0f*(qra_K)/(qra_N); - } - - EsNoMetric = 1.0f*qra_m*R*EbNoMetric; - - EbNo = (float)pow(10,pdata->EbNodB/10); - EsNo = 1.0f*qra_m*R*EbNo; - Es = EsNo*No; - A = (float)sqrt(Es); - - - // encode the input - if (code_type==QRATYPE_CRC || code_type==QRATYPE_CRCPUNCTURED) { - // compute the information message symbol check as the (negated) xor of all the - // information message symbols - for (k=0;k<(qra_K-1);k++) - x[k]=k%qra_M; - x[k]=calc_crc6(x,qra_K-1); - } - else - for (k=0;kstop==0) { - - // simulate the channel - // NOTE: in the case that the code is punctured, for simplicity - // we compute the channel outputs and the metric also for the crc symbol - // then we ignore its observation. - normrnd_s(rp,NSAMPLES,0,sigma); - normrnd_s(rq,NSAMPLES,0,sigma); - - if (channel_type == CHANNEL_AWGN) { - for (k=0;kdone = 1; - return; // unknown channel type - } - - // compute the squares of the amplitudes of the received samples - for (k=0;km,pcode->N,EsNoMetric); - - if (code_type==QRATYPE_CRCPUNCTURED) { - // ignore observations of the CRC symbol as it is not actually sent - // over the channel - pd_init(PD_ROWADDR(ix,qra_M,qra_K),pd_uniform(qra_m),qra_M); - } - - - if (pdata->ap_index!=0) - // mask channel observations with a priori knowledge - ix_mask(pcode,ix,ap_masks_jt65[pdata->ap_index],x); - - - // compute the extrinsic symbols probabilities with the message-passing algorithm - // stop if extrinsic information does not converges to 1 within the given number of iterations - rc = qra_extrinsic(pcode,ex,ix,100,qra_v2cmsg,qra_c2vmsg); - - if (rc>=0) { // the MP algorithm converged to Iex~1 in rc iterations - - // decode the codeword - qra_mapdecode(pcode,ydec,ex,ix); - - // look for undetected errors - if (code_type==QRATYPE_CRC || code_type==QRATYPE_CRCPUNCTURED) { - - j = 0; diff = 0; - for (k=0;k<(qra_K-1);k++) - diff |= (ydec[k]!=x[k]); - t = calc_crc6(ydec,qra_K-1); - if (t!=ydec[k]) // error detected - crc doesn't matches - nerrs += 1; - else - if (diff) { // decoded message is not equal to the transmitted one but - // the crc test passed - // add as undetected error - nerrsu += 1; - nerrs += 1; - // uncomment to see what the undetected error pattern looks like - //printword("U", ydec); - } - } - else - for (k=0;knt=nt; - pdata->nerrs=nerrs; - pdata->nerrsu=nerrsu; - - } - - pdata->done=1; - - #if _WIN32 - _endthread(); - #endif -} - -#if defined(__linux__) || ( defined(__MINGW32__) || defined (__MIGW64__) ) - -void *wer_test_pthread(void *p) -{ - wer_test_thread ((wer_test_ds *)p); - return 0; -} - -#endif - -void ix_mask(const qracode *pcode, float *r, const int *mask, const int *x) -{ - // mask intrinsic information (channel observations) with a priori knowledge - - int k,kk, smask; - const int qra_K=pcode->K; - const int qra_M=pcode->M; - const int qra_m=pcode->m; - - for (k=0;kNTHREADS_MAX) { - printf("Error: nthreads should be <=%d\n",NTHREADS_MAX); - return -1; - } - - sprintf(fnameout,"%s%s%s", - fnameout_pfx[chtype], - pcode->name, - fnameout_sfx[ap_index]); - - fout = fopen(fnameout,"w"); - fprintf(fout,"# Channel (0=AWGN,1=Rayleigh), Eb/No (dB), Transmitted codewords, Errors, Undetected Errors, Avg dec. time (ms), WER\n"); - - printf("\nTesting the code %s over the %s channel\nSimulation data will be saved to %s\n", - pcode->name, - chtype==CHANNEL_AWGN?"AWGN":"Rayleigh", - fnameout); - fflush (stdout); - - // init fixed thread parameters and preallocate buffers - for (j=0;jK*sizeof(int)); - wt[j].y = (int*)malloc(pcode->N*sizeof(int)); - wt[j].ydec = (int*)malloc(pcode->N*sizeof(int)); - wt[j].qra_v2cmsg = (float*)malloc(pcode->NMSG*pcode->M*sizeof(float)); - wt[j].qra_c2vmsg = (float*)malloc(pcode->NMSG*pcode->M*sizeof(float)); - wt[j].rp = (float*)malloc(pcode->N*pcode->M*sizeof(float)); - wt[j].rq = (float*)malloc(pcode->N*pcode->M*sizeof(float)); - wt[j].chp = (float*)malloc(pcode->N*sizeof(float)); - wt[j].chq = (float*)malloc(pcode->N*sizeof(float)); - wt[j].r = (float*)malloc(pcode->N*pcode->M*sizeof(float)); - wt[j].ix = (float*)malloc(pcode->N*pcode->M*sizeof(float)); - wt[j].ex = (float*)malloc(pcode->N*pcode->M*sizeof(float)); - } - - - for (k=0;k=nerrstgt[k]) { - for (j=0;j] [-t] [-c] [-a] [-f[-h]\n"); - printf("Options: \n"); - printf(" -q: code to simulate. 0=qra_12_63_64_irr_b\n"); - printf(" 1=qra_13_64_64_irr_e (default)\n"); - printf(" -t : number of threads to be used for the simulation [1..24]\n"); - printf(" (default=8)\n"); - printf(" -c : channel_type. 0=AWGN 1=Rayleigh \n"); - printf(" (default=AWGN)\n"); - printf(" -a : amount of a-priori information provided to decoder. \n"); - printf(" 0= No a-priori (default)\n"); - printf(" 1= 28 bit \n"); - printf(" 2= 44 bit \n"); - printf(" 3= 56 bit \n"); - printf(" -f : name of the file containing the Eb/No values to be simulated\n"); - printf(" (default=ebnovalues.txt)\n"); - printf(" This file should contain lines in this format:\n"); - printf(" # Eb/No(dB) Target Errors\n"); - printf(" 0.1 5000\n"); - printf(" 0.6 5000\n"); - printf(" 1.1 1000\n"); - printf(" 1.6 1000\n"); - printf(" ...\n"); - printf(" (lines beginning with a # are treated as comments\n\n"); -} - -#define SIM_POINTS_MAX 20 - -int main(int argc, char* argv[]) -{ - - float EbNodB[SIM_POINTS_MAX]; - int nerrstgt[SIM_POINTS_MAX]; - FILE *fin; - - char fnamein[128]= "ebnovalues.txt"; - char buf[128]; - - int nitems = 0; - int code_idx = 1; - int nthreads = 8; - int ch_type = CHANNEL_AWGN; - int ap_index = AP_NONE; - - // parse command line - while(--argc) { - argv++; - if (strncmp(*argv,"-h",2)==0) { - syntax(); - return 0; - } - else - if (strncmp(*argv,"-q",2)==0) { - code_idx = (int)atoi((*argv)+2); - if (code_idx>1) { - printf("Invalid code index\n"); - syntax(); - return -1; - } - } - else - if (strncmp(*argv,"-t",2)==0) { - nthreads = (int)atoi((*argv)+2); - printf("nthreads = %d\n",nthreads); - if (nthreads>NTHREADS_MAX) { - printf("Invalid number of threads\n"); - syntax(); - return -1; - } - } - else - if (strncmp(*argv,"-c",2)==0) { - ch_type = (int)atoi((*argv)+2); - if (ch_type>CHANNEL_RAYLEIGH) { - printf("Invalid channel type\n"); - syntax(); - return -1; - } - } - else - if (strncmp(*argv,"-a",2)==0) { - ap_index = (int)atoi((*argv)+2); - if (ap_index>AP_56) { - printf("Invalid a-priori information index\n"); - syntax(); - return -1; - } - } - else - if (strncmp(*argv,"-f",2)==0) { - strncpy(fnamein,(*argv)+2,127); - } - else - if (strncmp(*argv,"-h",2)==0) { - syntax(); - return -1; - } - else { - printf("Invalid option\n"); - syntax(); - return -1; - } - } - - // parse points to be simulated from the input file - fin = fopen(fnamein,"r"); - if (!fin) { - printf("Can't open file: %s\n",fnamein); - syntax(); - } - - while (fgets(buf,128,fin)!=0) - if (*buf=='#' || *buf=='\n' ) - continue; - else - if (nitems==SIM_POINTS_MAX) - break; - else - if (sscanf(buf,"%f %u",&EbNodB[nitems],&nerrstgt[nitems])!=2) { - printf("Invalid input file format\n"); - syntax(); - return -1; - } - else - nitems++; - - fclose(fin); - - if (nitems==0) { - printf("No Eb/No point specified in file %s\n",fnamein); - syntax(); - return -1; - } - - printf("\nQ-ary Repeat-Accumulate Code Word Error Rate Simulator\n"); - printf("2016, Nico Palermo - IV3NWV\n\n"); - - printf("Nthreads = %d\n",nthreads); - printf("Channel = %s\n",ch_type==CHANNEL_AWGN?"AWGN":"Rayleigh"); - printf("Codename = %s\n",codetotest[code_idx]->name); - printf("A-priori = %s\n",ap_str[ap_index]); - printf("Eb/No input file = %s\n\n",fnamein); - - wer_test_proc(codetotest[code_idx], nthreads, ch_type, ap_index, EbNodB, nerrstgt, nitems); - - return 0; -} - diff --git a/lib/qra/qracodes/normrnd.c b/lib/qra/qracodes/normrnd.c deleted file mode 100644 index 90abfa4..0000000 --- a/lib/qra/qracodes/normrnd.c +++ /dev/null @@ -1,82 +0,0 @@ -// normrnd.c -// functions to generate gaussian distributed numbers -// -// (c) 2016 - Nico Palermo, IV3NWV - Microtelecom Srl, Italy -// -// Credits to Andrea Montefusco - IW0HDV for his help on adapting the sources -// to OSs other than MS Windows -// -// ------------------------------------------------------------------------------ -// This file is part of the qracodes project, a Forward Error Control -// encoding/decoding package based on Q-ary RA (Repeat and Accumulate) LDPC codes. -// -// qracodes is free software: you can redistribute it and/or modify -// it under the terms of the GNU General Public License as published by -// the Free Software Foundation, either version 3 of the License, or -// (at your option) any later version. -// qracodes is distributed in the hope that it will be useful, -// but WITHOUT ANY WARRANTY; without even the implied warranty of -// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -// GNU General Public License for more details. - -// You should have received a copy of the GNU General Public License -// along with qracodes source distribution. -// If not, see . - - -#include "normrnd.h" - -#if _WIN32 // note the underscore: without it, it's not msdn official! - // Windows (x64 and x86) - #include // required only for GetTickCount(...) - #define K_RAND_MAX UINT_MAX -#elif _SVID_SOURCE || _XOPEN_SOURCE || __unix__ || (defined (__APPLE__) && defined(__MACH__)) /* POSIX or Unix or Apple */ - #include - #define rand_s(x) (*x)=(unsigned int)lrand48() // returns unsigned integers in the range 0..0x7FFFFFFF - #define K_RAND_MAX 0x7FFFFFFF // that's the max number - // generated by lrand48 -#else - #error "No good quality PRNG found" -#endif - - -// use MS rand_s(...) function -void normrnd_s(float *dst, int nitems, float mean, float stdev) -{ - unsigned int r; - float phi=0, u=0; - int set = 0; - - while (nitems--) - if (set==1) { - *dst++ = (float)sin(phi)*u*stdev+mean; - set = 0; - } - else { - rand_s((unsigned int*)&r); phi = (M_2PI/(1.0f+K_RAND_MAX))*r; - rand_s((unsigned int*)&r); u = (float)sqrt(-2.0f* log( (1.0f/(1.0f+K_RAND_MAX))*(1.0f+r) ) ); - *dst++ = (float)cos(phi)*u*stdev+mean; - set=1; - } -} - -/* NOT USED -// use MS rand() function -void normrnd(float *dst, int nitems, float mean, float stdev) -{ - float phi=0, u=0; - int set = 0; - - while (nitems--) - if (set==1) { - *dst++ = (float)sin(phi)*u*stdev+mean; - set = 0; - } - else { - phi = (M_2PI/(1.0f+RAND_MAX))*rand(); - u = (float)sqrt(-2.0f* log( (1.0f/(1.0f+RAND_MAX))*(1.0f+rand()) ) ); - *dst++ = (float)cos(phi)*u*stdev+mean; - set=1; - } -} -*/ diff --git a/lib/qra/qracodes/normrnd.h b/lib/qra/qracodes/normrnd.h deleted file mode 100644 index dd4b65b..0000000 --- a/lib/qra/qracodes/normrnd.h +++ /dev/null @@ -1,51 +0,0 @@ -// normrnd.h -// Functions to generate gaussian distributed numbers -// -// (c) 2016 - Nico Palermo, IV3NWV - Microtelecom Srl, Italy -// ------------------------------------------------------------------------------ -// This file is part of the qracodes project, a Forward Error Control -// encoding/decoding package based on Q-ary RA (Repeat and Accumulate) LDPC codes. -// -// qracodes is free software: you can redistribute it and/or modify -// it under the terms of the GNU General Public License as published by -// the Free Software Foundation, either version 3 of the License, or -// (at your option) any later version. -// qracodes is distributed in the hope that it will be useful, -// but WITHOUT ANY WARRANTY; without even the implied warranty of -// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -// GNU General Public License for more details. - -// You should have received a copy of the GNU General Public License -// along with qracodes source distribution. -// If not, see . - -#ifndef _normrnd_h_ -#define _normrnd_h_ - -#define _CRT_RAND_S -#include - -#define _USE_MATH_DEFINES -#include -#define M_2PI (2.0f*(float)M_PI) - -#ifdef __cplusplus -extern "C" { -#endif - -void normrnd_s(float *dst, int nitems, float mean, float stdev); -// generate a random array of numbers with a gaussian distribution of given mean and stdev -// use MS rand_s(...) function - -/* not used -void normrnd(float *dst, int nitems, float mean, float stdev); -// generate a random array of numbers with a gaussian distribution of given mean and stdev -// use MS rand() function -*/ - -#ifdef __cplusplus -} -#endif - -#endif // _normrnd_h_ - diff --git a/lib/qra/qracodes/npfwht.c b/lib/qra/qracodes/npfwht.c deleted file mode 100644 index 5732ce9..0000000 --- a/lib/qra/qracodes/npfwht.c +++ /dev/null @@ -1,216 +0,0 @@ -// npfwht.c -// Basic implementation of the Fast Walsh-Hadamard Transforms -// -// (c) 2016 - Nico Palermo, IV3NWV - Microtelecom Srl, Italy -// ------------------------------------------------------------------------------ -// This file is part of the qracodes project, a Forward Error Control -// encoding/decoding package based on Q-ary RA (repeat and accumulate) LDPC codes. -// -// qracodes is free software: you can redistribute it and/or modify -// it under the terms of the GNU General Public License as published by -// the Free Software Foundation, either version 3 of the License, or -// (at your option) any later version. -// qracodes is distributed in the hope that it will be useful, -// but WITHOUT ANY WARRANTY; without even the implied warranty of -// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -// GNU General Public License for more details. - -// You should have received a copy of the GNU General Public License -// along with qracodes source distribution. -// If not, see . - -#include "npfwht.h" - -#define WHBFY(dst,src,base,offs,dist) { dst[base+offs]=src[base+offs]+src[base+offs+dist]; dst[base+offs+dist]=src[base+offs]-src[base+offs+dist]; } - -typedef void (*pnp_fwht)(float*,float*); - -static void np_fwht2(float *dst, float *src); - -static void np_fwht1(float *dst, float *src); -static void np_fwht2(float *dst, float *src); -static void np_fwht4(float *dst, float *src); -static void np_fwht8(float *dst, float *src); -static void np_fwht16(float *dst, float *src); -static void np_fwht32(float *dst, float *src); -static void np_fwht64(float *dst, float *src); - -static pnp_fwht np_fwht_tab[7] = { - np_fwht1, - np_fwht2, - np_fwht4, - np_fwht8, - np_fwht16, - np_fwht32, - np_fwht64 -}; - -void np_fwht(int nlogdim, float *dst, float *src) -{ - np_fwht_tab[nlogdim](dst,src); -} - -static void np_fwht1(float *dst, float *src) -{ - dst[0] = src[0]; -} - - -static void np_fwht2(float *dst, float *src) -{ - float t[2]; - - WHBFY(t,src,0,0,1); - dst[0]= t[0]; - dst[1]= t[1]; -} - -static void np_fwht4(float *dst, float *src) -{ - float t[4]; - - // group 1 - WHBFY(t,src,0,0,2); WHBFY(t,src,0,1,2); - // group 2 - WHBFY(dst,t,0,0,1); WHBFY(dst,t,2,0,1); -}; - - -static void np_fwht8(float *dst, float *src) -{ - float t[16]; - float *t1=t, *t2=t+8; - - // group 1 - WHBFY(t1,src,0,0,4); WHBFY(t1,src,0,1,4); WHBFY(t1,src,0,2,4); WHBFY(t1,src,0,3,4); - // group 2 - WHBFY(t2,t1,0,0,2); WHBFY(t2,t1,0,1,2); WHBFY(t2,t1,4,0,2); WHBFY(t2,t1,4,1,2); - // group 3 - WHBFY(dst,t2,0,0,1); WHBFY(dst,t2,2,0,1); WHBFY(dst,t2,4,0,1); WHBFY(dst,t2,6,0,1); -}; - - -static void np_fwht16(float *dst, float *src) -{ - float t[32]; - float *t1=t, *t2=t+16; - - // group 1 - WHBFY(t1,src,0,0,8); WHBFY(t1,src,0,1,8); WHBFY(t1,src,0,2,8); WHBFY(t1,src,0,3,8); - WHBFY(t1,src,0,4,8); WHBFY(t1,src,0,5,8); WHBFY(t1,src,0,6,8); WHBFY(t1,src,0,7,8); - // group 2 - WHBFY(t2,t1,0,0,4); WHBFY(t2,t1,0,1,4); WHBFY(t2,t1,0,2,4); WHBFY(t2,t1,0,3,4); - WHBFY(t2,t1,8,0,4); WHBFY(t2,t1,8,1,4); WHBFY(t2,t1,8,2,4); WHBFY(t2,t1,8,3,4); - // group 3 - WHBFY(t1,t2,0,0,2); WHBFY(t1,t2,0,1,2); WHBFY(t1,t2,4,0,2); WHBFY(t1,t2,4,1,2); - WHBFY(t1,t2,8,0,2); WHBFY(t1,t2,8,1,2); WHBFY(t1,t2,12,0,2); WHBFY(t1,t2,12,1,2); - // group 4 - WHBFY(dst,t1,0,0,1); WHBFY(dst,t1,2,0,1); WHBFY(dst,t1,4,0,1); WHBFY(dst,t1,6,0,1); - WHBFY(dst,t1,8,0,1); WHBFY(dst,t1,10,0,1); WHBFY(dst,t1,12,0,1); WHBFY(dst,t1,14,0,1); - -} - -static void np_fwht32(float *dst, float *src) -{ - float t[64]; - float *t1=t, *t2=t+32; - - // group 1 - WHBFY(t1,src,0,0,16); WHBFY(t1,src,0,1,16); WHBFY(t1,src,0,2,16); WHBFY(t1,src,0,3,16); - WHBFY(t1,src,0,4,16); WHBFY(t1,src,0,5,16); WHBFY(t1,src,0,6,16); WHBFY(t1,src,0,7,16); - WHBFY(t1,src,0,8,16); WHBFY(t1,src,0,9,16); WHBFY(t1,src,0,10,16); WHBFY(t1,src,0,11,16); - WHBFY(t1,src,0,12,16); WHBFY(t1,src,0,13,16); WHBFY(t1,src,0,14,16); WHBFY(t1,src,0,15,16); - - // group 2 - WHBFY(t2,t1,0,0,8); WHBFY(t2,t1,0,1,8); WHBFY(t2,t1,0,2,8); WHBFY(t2,t1,0,3,8); - WHBFY(t2,t1,0,4,8); WHBFY(t2,t1,0,5,8); WHBFY(t2,t1,0,6,8); WHBFY(t2,t1,0,7,8); - WHBFY(t2,t1,16,0,8); WHBFY(t2,t1,16,1,8); WHBFY(t2,t1,16,2,8); WHBFY(t2,t1,16,3,8); - WHBFY(t2,t1,16,4,8); WHBFY(t2,t1,16,5,8); WHBFY(t2,t1,16,6,8); WHBFY(t2,t1,16,7,8); - - // group 3 - WHBFY(t1,t2,0,0,4); WHBFY(t1,t2,0,1,4); WHBFY(t1,t2,0,2,4); WHBFY(t1,t2,0,3,4); - WHBFY(t1,t2,8,0,4); WHBFY(t1,t2,8,1,4); WHBFY(t1,t2,8,2,4); WHBFY(t1,t2,8,3,4); - WHBFY(t1,t2,16,0,4); WHBFY(t1,t2,16,1,4); WHBFY(t1,t2,16,2,4); WHBFY(t1,t2,16,3,4); - WHBFY(t1,t2,24,0,4); WHBFY(t1,t2,24,1,4); WHBFY(t1,t2,24,2,4); WHBFY(t1,t2,24,3,4); - - // group 4 - WHBFY(t2,t1,0,0,2); WHBFY(t2,t1,0,1,2); WHBFY(t2,t1,4,0,2); WHBFY(t2,t1,4,1,2); - WHBFY(t2,t1,8,0,2); WHBFY(t2,t1,8,1,2); WHBFY(t2,t1,12,0,2); WHBFY(t2,t1,12,1,2); - WHBFY(t2,t1,16,0,2); WHBFY(t2,t1,16,1,2); WHBFY(t2,t1,20,0,2); WHBFY(t2,t1,20,1,2); - WHBFY(t2,t1,24,0,2); WHBFY(t2,t1,24,1,2); WHBFY(t2,t1,28,0,2); WHBFY(t2,t1,28,1,2); - - // group 5 - WHBFY(dst,t2,0,0,1); WHBFY(dst,t2,2,0,1); WHBFY(dst,t2,4,0,1); WHBFY(dst,t2,6,0,1); - WHBFY(dst,t2,8,0,1); WHBFY(dst,t2,10,0,1); WHBFY(dst,t2,12,0,1); WHBFY(dst,t2,14,0,1); - WHBFY(dst,t2,16,0,1); WHBFY(dst,t2,18,0,1); WHBFY(dst,t2,20,0,1); WHBFY(dst,t2,22,0,1); - WHBFY(dst,t2,24,0,1); WHBFY(dst,t2,26,0,1); WHBFY(dst,t2,28,0,1); WHBFY(dst,t2,30,0,1); - -} - -static void np_fwht64(float *dst, float *src) -{ - float t[128]; - float *t1=t, *t2=t+64; - - - // group 1 - WHBFY(t1,src,0,0,32); WHBFY(t1,src,0,1,32); WHBFY(t1,src,0,2,32); WHBFY(t1,src,0,3,32); - WHBFY(t1,src,0,4,32); WHBFY(t1,src,0,5,32); WHBFY(t1,src,0,6,32); WHBFY(t1,src,0,7,32); - WHBFY(t1,src,0,8,32); WHBFY(t1,src,0,9,32); WHBFY(t1,src,0,10,32); WHBFY(t1,src,0,11,32); - WHBFY(t1,src,0,12,32); WHBFY(t1,src,0,13,32); WHBFY(t1,src,0,14,32); WHBFY(t1,src,0,15,32); - WHBFY(t1,src,0,16,32); WHBFY(t1,src,0,17,32); WHBFY(t1,src,0,18,32); WHBFY(t1,src,0,19,32); - WHBFY(t1,src,0,20,32); WHBFY(t1,src,0,21,32); WHBFY(t1,src,0,22,32); WHBFY(t1,src,0,23,32); - WHBFY(t1,src,0,24,32); WHBFY(t1,src,0,25,32); WHBFY(t1,src,0,26,32); WHBFY(t1,src,0,27,32); - WHBFY(t1,src,0,28,32); WHBFY(t1,src,0,29,32); WHBFY(t1,src,0,30,32); WHBFY(t1,src,0,31,32); - - // group 2 - WHBFY(t2,t1,0,0,16); WHBFY(t2,t1,0,1,16); WHBFY(t2,t1,0,2,16); WHBFY(t2,t1,0,3,16); - WHBFY(t2,t1,0,4,16); WHBFY(t2,t1,0,5,16); WHBFY(t2,t1,0,6,16); WHBFY(t2,t1,0,7,16); - WHBFY(t2,t1,0,8,16); WHBFY(t2,t1,0,9,16); WHBFY(t2,t1,0,10,16); WHBFY(t2,t1,0,11,16); - WHBFY(t2,t1,0,12,16); WHBFY(t2,t1,0,13,16); WHBFY(t2,t1,0,14,16); WHBFY(t2,t1,0,15,16); - - WHBFY(t2,t1,32,0,16); WHBFY(t2,t1,32,1,16); WHBFY(t2,t1,32,2,16); WHBFY(t2,t1,32,3,16); - WHBFY(t2,t1,32,4,16); WHBFY(t2,t1,32,5,16); WHBFY(t2,t1,32,6,16); WHBFY(t2,t1,32,7,16); - WHBFY(t2,t1,32,8,16); WHBFY(t2,t1,32,9,16); WHBFY(t2,t1,32,10,16); WHBFY(t2,t1,32,11,16); - WHBFY(t2,t1,32,12,16); WHBFY(t2,t1,32,13,16); WHBFY(t2,t1,32,14,16); WHBFY(t2,t1,32,15,16); - - // group 3 - WHBFY(t1,t2,0,0,8); WHBFY(t1,t2,0,1,8); WHBFY(t1,t2,0,2,8); WHBFY(t1,t2,0,3,8); - WHBFY(t1,t2,0,4,8); WHBFY(t1,t2,0,5,8); WHBFY(t1,t2,0,6,8); WHBFY(t1,t2,0,7,8); - WHBFY(t1,t2,16,0,8); WHBFY(t1,t2,16,1,8); WHBFY(t1,t2,16,2,8); WHBFY(t1,t2,16,3,8); - WHBFY(t1,t2,16,4,8); WHBFY(t1,t2,16,5,8); WHBFY(t1,t2,16,6,8); WHBFY(t1,t2,16,7,8); - WHBFY(t1,t2,32,0,8); WHBFY(t1,t2,32,1,8); WHBFY(t1,t2,32,2,8); WHBFY(t1,t2,32,3,8); - WHBFY(t1,t2,32,4,8); WHBFY(t1,t2,32,5,8); WHBFY(t1,t2,32,6,8); WHBFY(t1,t2,32,7,8); - WHBFY(t1,t2,48,0,8); WHBFY(t1,t2,48,1,8); WHBFY(t1,t2,48,2,8); WHBFY(t1,t2,48,3,8); - WHBFY(t1,t2,48,4,8); WHBFY(t1,t2,48,5,8); WHBFY(t1,t2,48,6,8); WHBFY(t1,t2,48,7,8); - - // group 4 - WHBFY(t2,t1,0,0,4); WHBFY(t2,t1,0,1,4); WHBFY(t2,t1,0,2,4); WHBFY(t2,t1,0,3,4); - WHBFY(t2,t1,8,0,4); WHBFY(t2,t1,8,1,4); WHBFY(t2,t1,8,2,4); WHBFY(t2,t1,8,3,4); - WHBFY(t2,t1,16,0,4); WHBFY(t2,t1,16,1,4); WHBFY(t2,t1,16,2,4); WHBFY(t2,t1,16,3,4); - WHBFY(t2,t1,24,0,4); WHBFY(t2,t1,24,1,4); WHBFY(t2,t1,24,2,4); WHBFY(t2,t1,24,3,4); - WHBFY(t2,t1,32,0,4); WHBFY(t2,t1,32,1,4); WHBFY(t2,t1,32,2,4); WHBFY(t2,t1,32,3,4); - WHBFY(t2,t1,40,0,4); WHBFY(t2,t1,40,1,4); WHBFY(t2,t1,40,2,4); WHBFY(t2,t1,40,3,4); - WHBFY(t2,t1,48,0,4); WHBFY(t2,t1,48,1,4); WHBFY(t2,t1,48,2,4); WHBFY(t2,t1,48,3,4); - WHBFY(t2,t1,56,0,4); WHBFY(t2,t1,56,1,4); WHBFY(t2,t1,56,2,4); WHBFY(t2,t1,56,3,4); - - // group 5 - WHBFY(t1,t2,0,0,2); WHBFY(t1,t2,0,1,2); WHBFY(t1,t2,4,0,2); WHBFY(t1,t2,4,1,2); - WHBFY(t1,t2,8,0,2); WHBFY(t1,t2,8,1,2); WHBFY(t1,t2,12,0,2); WHBFY(t1,t2,12,1,2); - WHBFY(t1,t2,16,0,2); WHBFY(t1,t2,16,1,2); WHBFY(t1,t2,20,0,2); WHBFY(t1,t2,20,1,2); - WHBFY(t1,t2,24,0,2); WHBFY(t1,t2,24,1,2); WHBFY(t1,t2,28,0,2); WHBFY(t1,t2,28,1,2); - WHBFY(t1,t2,32,0,2); WHBFY(t1,t2,32,1,2); WHBFY(t1,t2,36,0,2); WHBFY(t1,t2,36,1,2); - WHBFY(t1,t2,40,0,2); WHBFY(t1,t2,40,1,2); WHBFY(t1,t2,44,0,2); WHBFY(t1,t2,44,1,2); - WHBFY(t1,t2,48,0,2); WHBFY(t1,t2,48,1,2); WHBFY(t1,t2,52,0,2); WHBFY(t1,t2,52,1,2); - WHBFY(t1,t2,56,0,2); WHBFY(t1,t2,56,1,2); WHBFY(t1,t2,60,0,2); WHBFY(t1,t2,60,1,2); - - // group 6 - WHBFY(dst,t1,0,0,1); WHBFY(dst,t1,2,0,1); WHBFY(dst,t1,4,0,1); WHBFY(dst,t1,6,0,1); - WHBFY(dst,t1,8,0,1); WHBFY(dst,t1,10,0,1); WHBFY(dst,t1,12,0,1); WHBFY(dst,t1,14,0,1); - WHBFY(dst,t1,16,0,1); WHBFY(dst,t1,18,0,1); WHBFY(dst,t1,20,0,1); WHBFY(dst,t1,22,0,1); - WHBFY(dst,t1,24,0,1); WHBFY(dst,t1,26,0,1); WHBFY(dst,t1,28,0,1); WHBFY(dst,t1,30,0,1); - WHBFY(dst,t1,32,0,1); WHBFY(dst,t1,34,0,1); WHBFY(dst,t1,36,0,1); WHBFY(dst,t1,38,0,1); - WHBFY(dst,t1,40,0,1); WHBFY(dst,t1,42,0,1); WHBFY(dst,t1,44,0,1); WHBFY(dst,t1,46,0,1); - WHBFY(dst,t1,48,0,1); WHBFY(dst,t1,50,0,1); WHBFY(dst,t1,52,0,1); WHBFY(dst,t1,54,0,1); - WHBFY(dst,t1,56,0,1); WHBFY(dst,t1,58,0,1); WHBFY(dst,t1,60,0,1); WHBFY(dst,t1,62,0,1); -} \ No newline at end of file diff --git a/lib/qra/qracodes/npfwht.h b/lib/qra/qracodes/npfwht.h deleted file mode 100644 index 9452e20..0000000 --- a/lib/qra/qracodes/npfwht.h +++ /dev/null @@ -1,45 +0,0 @@ -// np_fwht.h -// Basic implementation of the Fast Walsh-Hadamard Transforms -// -// (c) 2016 - Nico Palermo, IV3NWV - Microtelecom Srl, Italy -// ------------------------------------------------------------------------------ -// This file is part of the qracodes project, a Forward Error Control -// encoding/decoding package based on Q-ary RA (repeat and accumulate) LDPC codes. -// -// qracodes is free software: you can redistribute it and/or modify -// it under the terms of the GNU General Public License as published by -// the Free Software Foundation, either version 3 of the License, or -// (at your option) any later version. -// qracodes is distributed in the hope that it will be useful, -// but WITHOUT ANY WARRANTY; without even the implied warranty of -// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -// GNU General Public License for more details. - -// You should have received a copy of the GNU General Public License -// along with qracodes source distribution. -// If not, see . - -#ifndef _npfwht_h_ -#define _npfwht_h_ - -#ifdef __cplusplus -extern "C" { -#endif - -void np_fwht(int nlogdim, float *dst, float *src); -// Compute the Walsh-Hadamard transform of the given data up to a -// 64-dimensional transform -// -// Input parameters: -// nlogdim: log2 of the transform size. Must be in the range [0..6] -// src : pointer to the input data buffer. -// dst : pointer to the output data buffer. -// -// src and dst must point to preallocated data buffers of size 2^nlogdim*sizeof(float) -// src and dst buffers can overlap - -#ifdef __cplusplus -} -#endif - -#endif // _npfwht_ diff --git a/lib/qra/qracodes/pdmath.c b/lib/qra/qracodes/pdmath.c deleted file mode 100644 index 47ecab9..0000000 --- a/lib/qra/qracodes/pdmath.c +++ /dev/null @@ -1,385 +0,0 @@ -// pdmath.c -// Elementary math on probability distributions -// -// (c) 2016 - Nico Palermo, IV3NWV - Microtelecom Srl, Italy -// ------------------------------------------------------------------------------ -// This file is part of the qracodes project, a Forward Error Control -// encoding/decoding package based on Q-ary RA (Repeat and Accumulate) LDPC codes. -// -// qracodes is free software: you can redistribute it and/or modify -// it under the terms of the GNU General Public License as published by -// the Free Software Foundation, either version 3 of the License, or -// (at your option) any later version. -// qracodes is distributed in the hope that it will be useful, -// but WITHOUT ANY WARRANTY; without even the implied warranty of -// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -// GNU General Public License for more details. - -// You should have received a copy of the GNU General Public License -// along with qracodes source distribution. -// If not, see . - -#include "pdmath.h" - -typedef const float *ppd_uniform; -typedef void (*ppd_imul)(float*,const float*); -typedef float (*ppd_norm)(float*); - -// define vector size in function of its logarithm in base 2 -static const int pd_log2dim[7] = { - 1,2,4,8,16,32,64 -}; - -// define uniform distributions of given size -static const float pd_uniform1[1] = { - 1. -}; -static const float pd_uniform2[2] = { - 1./2., 1./2. -}; -static const float pd_uniform4[4] = { - 1./4., 1./4.,1./4., 1./4. -}; -static const float pd_uniform8[8] = { - 1./8., 1./8.,1./8., 1./8.,1./8., 1./8.,1./8., 1./8. -}; -static const float pd_uniform16[16] = { - 1./16., 1./16., 1./16., 1./16.,1./16., 1./16.,1./16., 1./16., - 1./16., 1./16., 1./16., 1./16.,1./16., 1./16.,1./16., 1./16. -}; -static const float pd_uniform32[32] = { - 1./32., 1./32., 1./32., 1./32.,1./32., 1./32.,1./32., 1./32., - 1./32., 1./32., 1./32., 1./32.,1./32., 1./32.,1./32., 1./32., - 1./32., 1./32., 1./32., 1./32.,1./32., 1./32.,1./32., 1./32., - 1./32., 1./32., 1./32., 1./32.,1./32., 1./32.,1./32., 1./32. -}; -static const float pd_uniform64[64] = { - 1./64., 1./64., 1./64., 1./64.,1./64., 1./64.,1./64., 1./64., - 1./64., 1./64., 1./64., 1./64.,1./64., 1./64.,1./64., 1./64., - 1./64., 1./64., 1./64., 1./64.,1./64., 1./64.,1./64., 1./64., - 1./64., 1./64., 1./64., 1./64.,1./64., 1./64.,1./64., 1./64., - 1./64., 1./64., 1./64., 1./64.,1./64., 1./64.,1./64., 1./64., - 1./64., 1./64., 1./64., 1./64.,1./64., 1./64.,1./64., 1./64., - 1./64., 1./64., 1./64., 1./64.,1./64., 1./64.,1./64., 1./64., - 1./64., 1./64., 1./64., 1./64.,1./64., 1./64.,1./64., 1./64. - -}; - -static const ppd_uniform pd_uniform_tab[7] = { - pd_uniform1, - pd_uniform2, - pd_uniform4, - pd_uniform8, - pd_uniform16, - pd_uniform32, - pd_uniform64 -}; - -// returns a pointer to the uniform distribution of the given logsize -const float *pd_uniform(int nlogdim) -{ - return pd_uniform_tab[nlogdim]; -} - -// in-place multiplication functions -// compute dst = dst*src for any element of the distrib - -static void pd_imul1(float *dst, const float *src) -{ - dst[0] *= src[0]; -} - -static void pd_imul2(float *dst, const float *src) -{ - dst[0] *= src[0]; dst[1] *= src[1]; -} -static void pd_imul4(float *dst, const float *src) -{ - dst[0] *= src[0]; dst[1] *= src[1]; - dst[2] *= src[2]; dst[3] *= src[3]; -} -static void pd_imul8(float *dst, const float *src) -{ - dst[0] *= src[0]; dst[1] *= src[1]; dst[2] *= src[2]; dst[3] *= src[3]; - dst[4] *= src[4]; dst[5] *= src[5]; dst[6] *= src[6]; dst[7] *= src[7]; -} -static void pd_imul16(float *dst, const float *src) -{ - dst[0] *= src[0]; dst[1] *= src[1]; dst[2] *= src[2]; dst[3] *= src[3]; - dst[4] *= src[4]; dst[5] *= src[5]; dst[6] *= src[6]; dst[7] *= src[7]; - dst[8] *= src[8]; dst[9] *= src[9]; dst[10]*= src[10]; dst[11]*= src[11]; - dst[12]*= src[12]; dst[13]*= src[13]; dst[14]*= src[14]; dst[15]*= src[15]; -} -static void pd_imul32(float *dst, const float *src) -{ - pd_imul16(dst,src); - pd_imul16(dst+16,src+16); -} -static void pd_imul64(float *dst, const float *src) -{ - pd_imul16(dst, src); - pd_imul16(dst+16, src+16); - pd_imul16(dst+32, src+32); - pd_imul16(dst+48, src+48); -} - -static const ppd_imul pd_imul_tab[7] = { - pd_imul1, - pd_imul2, - pd_imul4, - pd_imul8, - pd_imul16, - pd_imul32, - pd_imul64 -}; - -// in place multiplication -// compute dst = dst*src for any element of the distrib give their log2 size -// arguments must be pointers to array of floats of the given size -void pd_imul(float *dst, const float *src, int nlogdim) -{ - pd_imul_tab[nlogdim](dst,src); -} - -static float pd_norm1(float *ppd) -{ - float t = ppd[0]; - ppd[0] = 1.f; - return t; -} - -static float pd_norm2(float *ppd) -{ - float t,to; - - t =ppd[0]; t +=ppd[1]; - - if (t<=0) { - pd_init(ppd,pd_uniform(1),pd_log2dim[1]); - return t; - } - - to = t; - t = 1.f/t; - ppd[0] *=t; ppd[1] *=t; - return to; - -} - -static float pd_norm4(float *ppd) -{ - float t,to; - - t =ppd[0]; t +=ppd[1]; t +=ppd[2]; t +=ppd[3]; - - if (t<=0) { - pd_init(ppd,pd_uniform(2),pd_log2dim[2]); - return t; - } - - to = t; - t = 1.f/t; - ppd[0] *=t; ppd[1] *=t; ppd[2] *=t; ppd[3] *=t; - return to; -} - -static float pd_norm8(float *ppd) -{ - float t,to; - - t =ppd[0]; t +=ppd[1]; t +=ppd[2]; t +=ppd[3]; - t +=ppd[4]; t +=ppd[5]; t +=ppd[6]; t +=ppd[7]; - - if (t<=0) { - pd_init(ppd,pd_uniform(3),pd_log2dim[3]); - return t; - } - - to = t; - t = 1.f/t; - ppd[0] *=t; ppd[1] *=t; ppd[2] *=t; ppd[3] *=t; - ppd[4] *=t; ppd[5] *=t; ppd[6] *=t; ppd[7] *=t; - return to; -} -static float pd_norm16(float *ppd) -{ - float t,to; - - t =ppd[0]; t +=ppd[1]; t +=ppd[2]; t +=ppd[3]; - t +=ppd[4]; t +=ppd[5]; t +=ppd[6]; t +=ppd[7]; - t +=ppd[8]; t +=ppd[9]; t +=ppd[10]; t +=ppd[11]; - t +=ppd[12]; t +=ppd[13]; t +=ppd[14]; t +=ppd[15]; - - if (t<=0) { - pd_init(ppd,pd_uniform(4),pd_log2dim[4]); - return t; - } - - to = t; - t = 1.f/t; - ppd[0] *=t; ppd[1] *=t; ppd[2] *=t; ppd[3] *=t; - ppd[4] *=t; ppd[5] *=t; ppd[6] *=t; ppd[7] *=t; - ppd[8] *=t; ppd[9] *=t; ppd[10] *=t; ppd[11] *=t; - ppd[12] *=t; ppd[13] *=t; ppd[14] *=t; ppd[15] *=t; - - return to; -} -static float pd_norm32(float *ppd) -{ - float t,to; - - t =ppd[0]; t +=ppd[1]; t +=ppd[2]; t +=ppd[3]; - t +=ppd[4]; t +=ppd[5]; t +=ppd[6]; t +=ppd[7]; - t +=ppd[8]; t +=ppd[9]; t +=ppd[10]; t +=ppd[11]; - t +=ppd[12]; t +=ppd[13]; t +=ppd[14]; t +=ppd[15]; - t +=ppd[16]; t +=ppd[17]; t +=ppd[18]; t +=ppd[19]; - t +=ppd[20]; t +=ppd[21]; t +=ppd[22]; t +=ppd[23]; - t +=ppd[24]; t +=ppd[25]; t +=ppd[26]; t +=ppd[27]; - t +=ppd[28]; t +=ppd[29]; t +=ppd[30]; t +=ppd[31]; - - if (t<=0) { - pd_init(ppd,pd_uniform(5),pd_log2dim[5]); - return t; - } - - to = t; - t = 1.f/t; - ppd[0] *=t; ppd[1] *=t; ppd[2] *=t; ppd[3] *=t; - ppd[4] *=t; ppd[5] *=t; ppd[6] *=t; ppd[7] *=t; - ppd[8] *=t; ppd[9] *=t; ppd[10] *=t; ppd[11] *=t; - ppd[12] *=t; ppd[13] *=t; ppd[14] *=t; ppd[15] *=t; - ppd[16] *=t; ppd[17] *=t; ppd[18] *=t; ppd[19] *=t; - ppd[20] *=t; ppd[21] *=t; ppd[22] *=t; ppd[23] *=t; - ppd[24] *=t; ppd[25] *=t; ppd[26] *=t; ppd[27] *=t; - ppd[28] *=t; ppd[29] *=t; ppd[30] *=t; ppd[31] *=t; - - return to; -} - -static float pd_norm64(float *ppd) -{ - float t,to; - - t =ppd[0]; t +=ppd[1]; t +=ppd[2]; t +=ppd[3]; - t +=ppd[4]; t +=ppd[5]; t +=ppd[6]; t +=ppd[7]; - t +=ppd[8]; t +=ppd[9]; t +=ppd[10]; t +=ppd[11]; - t +=ppd[12]; t +=ppd[13]; t +=ppd[14]; t +=ppd[15]; - t +=ppd[16]; t +=ppd[17]; t +=ppd[18]; t +=ppd[19]; - t +=ppd[20]; t +=ppd[21]; t +=ppd[22]; t +=ppd[23]; - t +=ppd[24]; t +=ppd[25]; t +=ppd[26]; t +=ppd[27]; - t +=ppd[28]; t +=ppd[29]; t +=ppd[30]; t +=ppd[31]; - - t +=ppd[32]; t +=ppd[33]; t +=ppd[34]; t +=ppd[35]; - t +=ppd[36]; t +=ppd[37]; t +=ppd[38]; t +=ppd[39]; - t +=ppd[40]; t +=ppd[41]; t +=ppd[42]; t +=ppd[43]; - t +=ppd[44]; t +=ppd[45]; t +=ppd[46]; t +=ppd[47]; - t +=ppd[48]; t +=ppd[49]; t +=ppd[50]; t +=ppd[51]; - t +=ppd[52]; t +=ppd[53]; t +=ppd[54]; t +=ppd[55]; - t +=ppd[56]; t +=ppd[57]; t +=ppd[58]; t +=ppd[59]; - t +=ppd[60]; t +=ppd[61]; t +=ppd[62]; t +=ppd[63]; - - if (t<=0) { - pd_init(ppd,pd_uniform(6),pd_log2dim[6]); - return t; - } - - to = t; - t = 1.0f/t; - ppd[0] *=t; ppd[1] *=t; ppd[2] *=t; ppd[3] *=t; - ppd[4] *=t; ppd[5] *=t; ppd[6] *=t; ppd[7] *=t; - ppd[8] *=t; ppd[9] *=t; ppd[10] *=t; ppd[11] *=t; - ppd[12] *=t; ppd[13] *=t; ppd[14] *=t; ppd[15] *=t; - ppd[16] *=t; ppd[17] *=t; ppd[18] *=t; ppd[19] *=t; - ppd[20] *=t; ppd[21] *=t; ppd[22] *=t; ppd[23] *=t; - ppd[24] *=t; ppd[25] *=t; ppd[26] *=t; ppd[27] *=t; - ppd[28] *=t; ppd[29] *=t; ppd[30] *=t; ppd[31] *=t; - - ppd[32] *=t; ppd[33] *=t; ppd[34] *=t; ppd[35] *=t; - ppd[36] *=t; ppd[37] *=t; ppd[38] *=t; ppd[39] *=t; - ppd[40] *=t; ppd[41] *=t; ppd[42] *=t; ppd[43] *=t; - ppd[44] *=t; ppd[45] *=t; ppd[46] *=t; ppd[47] *=t; - ppd[48] *=t; ppd[49] *=t; ppd[50] *=t; ppd[51] *=t; - ppd[52] *=t; ppd[53] *=t; ppd[54] *=t; ppd[55] *=t; - ppd[56] *=t; ppd[57] *=t; ppd[58] *=t; ppd[59] *=t; - ppd[60] *=t; ppd[61] *=t; ppd[62] *=t; ppd[63] *=t; - - return to; -} - - -static const ppd_norm pd_norm_tab[7] = { - pd_norm1, - pd_norm2, - pd_norm4, - pd_norm8, - pd_norm16, - pd_norm32, - pd_norm64 -}; - -float pd_norm(float *pd, int nlogdim) -{ - return pd_norm_tab[nlogdim](pd); -} - -void pd_memset(float *dst, const float *src, int ndim, int nitems) -{ - int size = PD_SIZE(ndim); - while(nitems--) { - memcpy(dst,src,size); - dst +=ndim; - } -} - -void pd_fwdperm(float *dst, float *src, const int *perm, int ndim) -{ - // TODO: non-loop implementation - while (ndim--) - dst[ndim] = src[perm[ndim]]; -} - -void pd_bwdperm(float *dst, float *src, const int *perm, int ndim) -{ - // TODO: non-loop implementation - while (ndim--) - dst[perm[ndim]] = src[ndim]; -} - -float pd_max(float *src, int ndim) -{ - // TODO: faster implementation - - float cmax=0; // we assume that prob distributions are always positive - float cval; - - while (ndim--) { - cval = src[ndim]; - if (cval>=cmax) { - cmax = cval; - } - } - - return cmax; -} - -int pd_argmax(float *pmax, float *src, int ndim) -{ - // TODO: faster implementation - - float cmax=0; // we assume that prob distributions are always positive - float cval; - int idxmax=-1; // indicates that all pd elements are <0 - - while (ndim--) { - cval = src[ndim]; - if (cval>=cmax) { - cmax = cval; - idxmax = ndim; - } - } - - if (pmax) - *pmax = cmax; - - return idxmax; -} diff --git a/lib/qra/qracodes/pdmath.h b/lib/qra/qracodes/pdmath.h deleted file mode 100644 index bbd1210..0000000 --- a/lib/qra/qracodes/pdmath.h +++ /dev/null @@ -1,85 +0,0 @@ -// pdmath.h -// Elementary math on probability distributions -// -// (c) 2016 - Nico Palermo, IV3NWV - Microtelecom Srl, Italy -// ------------------------------------------------------------------------------ -// This file is part of the qracodes project, a Forward Error Control -// encoding/decoding package based on Q-ary RA (repeat and accumulate) LDPC codes. -// -// qracodes is free software: you can redistribute it and/or modify -// it under the terms of the GNU General Public License as published by -// the Free Software Foundation, either version 3 of the License, or -// (at your option) any later version. -// qracodes is distributed in the hope that it will be useful, -// but WITHOUT ANY WARRANTY; without even the implied warranty of -// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -// GNU General Public License for more details. - -// You should have received a copy of the GNU General Public License -// along with qracodes source distribution. -// If not, see . - - -#ifndef _pdmath_h_ -#define _pdmath_h_ - -#include - -#ifdef __cplusplus -extern "C" { -#endif - -#define PD_NDIM(nlogdim) ((1<<(nlogdim)) -#define PD_SIZE(ndim) ((ndim)*sizeof(float)) -#define PD_ROWADDR(fp,ndim,idx) (fp+((ndim)*(idx))) - -const float *pd_uniform(int nlogdim); -// Returns a pointer to a (constant) uniform distribution of the given log2 size - -#define pd_init(dst,src,ndim) memcpy(dst,src,PD_SIZE(ndim)) -// Distribution copy - -void pd_memset(float *dst, const float *src, int ndim, int nitems); -// Copy the distribution pointed by src to the array of distributions dst -// src is a pointer to the input distribution (a vector of size ndim) -// dst is a pointer to a linear array of distributions (a vector of size ndim*nitems) - -void pd_imul(float *dst, const float *src, int nlogdim); -// In place multiplication -// Compute dst = dst*src for any element of the distrib give their log2 size -// src and dst arguments must be pointers to array of floats of the given size - -float pd_norm(float *pd, int nlogdim); -// In place normalizazion -// Normalizes the input vector so that the sum of its components are one -// pd must be a pointer to an array of floats of the given size. -// If the norm of the input vector is non-positive the vector components -// are replaced with a uniform distribution -// Returns the norm of the distribution prior to the normalization - -void pd_fwdperm(float *dst, float *src, const int *perm, int ndim); -// Forward permutation of a distribution -// Computes dst[k] = src[perm[k]] for every element in the distribution -// perm must be a pointer to an array of integers of length ndim - -void pd_bwdperm(float *dst, float *src, const int *perm, int ndim); -// Backward permutation of a distribution -// Computes dst[perm[k]] = src[k] for every element in the distribution -// perm must be a pointer to an array of integers of length ndim - -float pd_max(float *src, int ndim); -// Return the maximum of the elements of the given distribution -// Assumes that the input vector is a probability distribution and that each element in the -// distribution is non negative - -int pd_argmax(float *pmax, float *src, int ndim); -// Return the index of the maximum element of the given distribution -// The maximum is stored in the variable pointed by pmax if pmax is not null -// Same note of pd_max applies. -// Return -1 if all the elements in the distribution are negative - -#ifdef __cplusplus -} -#endif - -#endif // _pdmath_h_ diff --git a/lib/qra/qracodes/qra12_63_64_irr_b.c b/lib/qra/qracodes/qra12_63_64_irr_b.c deleted file mode 100644 index d69443b..0000000 --- a/lib/qra/qracodes/qra12_63_64_irr_b.c +++ /dev/null @@ -1,534 +0,0 @@ -// qra12_63_64_irr_b.c -// Encoding/Decoding tables for Q-ary RA code (12,63) over GF(64) -// Code Name: qra12_63_64_irr_b -// (12,63) RA Code over GF(64) - RF=333344455567 - -// (c) 2016 - Nico Palermo - IV3NWV - Microtelecom Srl, Italy - -// This file is part of the qracodes project, a Forward Error Control -// encoding/decoding package based on Q-ary RA (Repeat and Accumulate) LDPC codes. -// -// qracodes is free software: you can redistribute it and/or modify -// it under the terms of the GNU General Public License as published by -// the Free Software Foundation, either version 3 of the License, or -// (at your option) any later version. -// qracodes is distributed in the hope that it will be useful, -// but WITHOUT ANY WARRANTY; without even the implied warranty of -// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -// GNU General Public License for more details. -// -// You should have received a copy of the GNU General Public License -// along with qracodes source distribution. -// If not, see . - -#include "qra12_63_64_irr_b.h" - -#define qra_K 12 // number of information symbols -#define qra_N 63 // codeword length in symbols -#define qra_m 6 // bits/symbol -#define qra_M 64 // Symbol alphabet cardinality -#define qra_a 1 // grouping factor -#define qra_NC 51 // number of check symbols (N-K) - -// Defines used by the message passing decoder -------- - -#define qra_V 63 // number of variables in the code graph (N) -#define qra_C 115 // number of factors in the code graph (N +(N-K)+1) -#define qra_NMSG 217 // number of msgs in the code graph -#define qra_MAXVDEG 8 // maximum variable degree -#define qra_MAXCDEG 3 // maximum factor degree -#define qra_R 0.19048f // code rate (K/N) -#define CODE_NAME "qra_12_63_64_irr_b" - - -// table of the systematic symbols indexes in the accumulator chain -static const int qra_acc_input_idx[qra_NC+1] = { - 3, 11, 0, 1, 7, 8, 6, 5, 10, 4, - 11, 9, 0, 2, 6, 7, 8, 4, 11, 5, - 10, 2, 1, 9, 3, 8, 4, 11, 5, 7, - 10, 9, 6, 3, 11, 5, 8, 10, 0, 7, - 9, 11, 4, 2, 10, 6, 8, 1, 9, 7, - 11, 10 -}; - -// table of the systematic symbols weight logarithms over GF(M) -static const int qra_acc_input_wlog[qra_NC+1] = { - 39, 0, 34, 16, 25, 0, 34, 48, 19, 13, - 29, 56, 0, 5, 39, 42, 31, 0, 10, 0, - 57, 62, 33, 43, 0, 14, 22, 48, 28, 20, - 5, 45, 16, 43, 17, 4, 32, 0, 31, 0, - 0, 28, 57, 0, 18, 0, 60, 0, 10, 31, - 57, 27 -}; - -// table of the logarithms of the elements of GF(M) (log(0) never used) -static const int qra_log[qra_M] = { - -1, 0, 1, 6, 2, 12, 7, 26, 3, 32, - 13, 35, 8, 48, 27, 18, 4, 24, 33, 16, - 14, 52, 36, 54, 9, 45, 49, 38, 28, 41, - 19, 56, 5, 62, 25, 11, 34, 31, 17, 47, - 15, 23, 53, 51, 37, 44, 55, 40, 10, 61, - 46, 30, 50, 22, 39, 43, 29, 60, 42, 21, - 20, 59, 57, 58 -}; - -// table of GF(M) elements given their logarithm -static const int qra_exp[qra_M-1] = { - 1, 2, 4, 8, 16, 32, 3, 6, 12, 24, - 48, 35, 5, 10, 20, 40, 19, 38, 15, 30, - 60, 59, 53, 41, 17, 34, 7, 14, 28, 56, - 51, 37, 9, 18, 36, 11, 22, 44, 27, 54, - 47, 29, 58, 55, 45, 25, 50, 39, 13, 26, - 52, 43, 21, 42, 23, 46, 31, 62, 63, 61, - 57, 49, 33 -}; - -// table of the messages weight logarithms over GF(M) -static const int qra_msgw[qra_NMSG] = { - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 39, 0, 34, 16, 25, 0, 34, - 48, 19, 13, 29, 56, 0, 5, 39, 42, 31, - 0, 10, 0, 57, 62, 33, 43, 0, 14, 22, - 48, 28, 20, 5, 45, 16, 43, 17, 4, 32, - 0, 31, 0, 0, 28, 57, 0, 18, 0, 60, - 0, 10, 31, 57, 27, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0 -}; - -// table of the degrees of the variable nodes -static const int qra_vdeg[qra_V] = { - 4, 4, 4, 4, 5, 5, 5, 6, 6, 6, - 7, 8, 3, 3, 3, 3, 3, 3, 3, 3, - 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, - 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, - 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, - 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, - 3, 3, 3 -}; - -// table of the degrees of the factor nodes -static const int qra_cdeg[qra_C] = { - 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, - 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, - 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, - 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, - 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, - 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, - 1, 1, 1, 2, 3, 3, 3, 3, 3, 3, - 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, - 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, - 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, - 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, - 3, 3, 3, 3, 2 -}; - -// table (uncompressed) of the v->c message indexes (-1=unused entry) -static const int qra_v2cmidx[qra_V*qra_MAXVDEG] = { - 0, 65, 75, 101, -1, -1, -1, -1, - 1, 66, 85, 110, -1, -1, -1, -1, - 2, 76, 84, 106, -1, -1, -1, -1, - 3, 63, 87, 96, -1, -1, -1, -1, - 4, 72, 80, 89, 105, -1, -1, -1, - 5, 70, 82, 91, 98, -1, -1, -1, - 6, 69, 77, 95, 108, -1, -1, -1, - 7, 67, 78, 92, 102, 112, -1, -1, - 8, 68, 79, 88, 99, 109, -1, -1, - 9, 74, 86, 94, 103, 111, -1, -1, - 10, 71, 83, 93, 100, 107, 114, -1, - 11, 64, 73, 81, 90, 97, 104, 113, - 12, 115, 116, -1, -1, -1, -1, -1, - 13, 117, 118, -1, -1, -1, -1, -1, - 14, 119, 120, -1, -1, -1, -1, -1, - 15, 121, 122, -1, -1, -1, -1, -1, - 16, 123, 124, -1, -1, -1, -1, -1, - 17, 125, 126, -1, -1, -1, -1, -1, - 18, 127, 128, -1, -1, -1, -1, -1, - 19, 129, 130, -1, -1, -1, -1, -1, - 20, 131, 132, -1, -1, -1, -1, -1, - 21, 133, 134, -1, -1, -1, -1, -1, - 22, 135, 136, -1, -1, -1, -1, -1, - 23, 137, 138, -1, -1, -1, -1, -1, - 24, 139, 140, -1, -1, -1, -1, -1, - 25, 141, 142, -1, -1, -1, -1, -1, - 26, 143, 144, -1, -1, -1, -1, -1, - 27, 145, 146, -1, -1, -1, -1, -1, - 28, 147, 148, -1, -1, -1, -1, -1, - 29, 149, 150, -1, -1, -1, -1, -1, - 30, 151, 152, -1, -1, -1, -1, -1, - 31, 153, 154, -1, -1, -1, -1, -1, - 32, 155, 156, -1, -1, -1, -1, -1, - 33, 157, 158, -1, -1, -1, -1, -1, - 34, 159, 160, -1, -1, -1, -1, -1, - 35, 161, 162, -1, -1, -1, -1, -1, - 36, 163, 164, -1, -1, -1, -1, -1, - 37, 165, 166, -1, -1, -1, -1, -1, - 38, 167, 168, -1, -1, -1, -1, -1, - 39, 169, 170, -1, -1, -1, -1, -1, - 40, 171, 172, -1, -1, -1, -1, -1, - 41, 173, 174, -1, -1, -1, -1, -1, - 42, 175, 176, -1, -1, -1, -1, -1, - 43, 177, 178, -1, -1, -1, -1, -1, - 44, 179, 180, -1, -1, -1, -1, -1, - 45, 181, 182, -1, -1, -1, -1, -1, - 46, 183, 184, -1, -1, -1, -1, -1, - 47, 185, 186, -1, -1, -1, -1, -1, - 48, 187, 188, -1, -1, -1, -1, -1, - 49, 189, 190, -1, -1, -1, -1, -1, - 50, 191, 192, -1, -1, -1, -1, -1, - 51, 193, 194, -1, -1, -1, -1, -1, - 52, 195, 196, -1, -1, -1, -1, -1, - 53, 197, 198, -1, -1, -1, -1, -1, - 54, 199, 200, -1, -1, -1, -1, -1, - 55, 201, 202, -1, -1, -1, -1, -1, - 56, 203, 204, -1, -1, -1, -1, -1, - 57, 205, 206, -1, -1, -1, -1, -1, - 58, 207, 208, -1, -1, -1, -1, -1, - 59, 209, 210, -1, -1, -1, -1, -1, - 60, 211, 212, -1, -1, -1, -1, -1, - 61, 213, 214, -1, -1, -1, -1, -1, - 62, 215, 216, -1, -1, -1, -1, -1 -}; - -// table (uncompressed) of the c->v message indexes (-1=unused entry) -static const int qra_c2vmidx[qra_C*qra_MAXCDEG] = { - 0, -1, -1, 1, -1, -1, 2, -1, -1, 3, -1, -1, - 4, -1, -1, 5, -1, -1, 6, -1, -1, 7, -1, -1, - 8, -1, -1, 9, -1, -1, 10, -1, -1, 11, -1, -1, - 12, -1, -1, 13, -1, -1, 14, -1, -1, 15, -1, -1, - 16, -1, -1, 17, -1, -1, 18, -1, -1, 19, -1, -1, - 20, -1, -1, 21, -1, -1, 22, -1, -1, 23, -1, -1, - 24, -1, -1, 25, -1, -1, 26, -1, -1, 27, -1, -1, - 28, -1, -1, 29, -1, -1, 30, -1, -1, 31, -1, -1, - 32, -1, -1, 33, -1, -1, 34, -1, -1, 35, -1, -1, - 36, -1, -1, 37, -1, -1, 38, -1, -1, 39, -1, -1, - 40, -1, -1, 41, -1, -1, 42, -1, -1, 43, -1, -1, - 44, -1, -1, 45, -1, -1, 46, -1, -1, 47, -1, -1, - 48, -1, -1, 49, -1, -1, 50, -1, -1, 51, -1, -1, - 52, -1, -1, 53, -1, -1, 54, -1, -1, 55, -1, -1, - 56, -1, -1, 57, -1, -1, 58, -1, -1, 59, -1, -1, - 60, -1, -1, 61, -1, -1, 62, -1, -1, 63, 115, -1, - 64, 116, 117, 65, 118, 119, 66, 120, 121, 67, 122, 123, - 68, 124, 125, 69, 126, 127, 70, 128, 129, 71, 130, 131, - 72, 132, 133, 73, 134, 135, 74, 136, 137, 75, 138, 139, - 76, 140, 141, 77, 142, 143, 78, 144, 145, 79, 146, 147, - 80, 148, 149, 81, 150, 151, 82, 152, 153, 83, 154, 155, - 84, 156, 157, 85, 158, 159, 86, 160, 161, 87, 162, 163, - 88, 164, 165, 89, 166, 167, 90, 168, 169, 91, 170, 171, - 92, 172, 173, 93, 174, 175, 94, 176, 177, 95, 178, 179, - 96, 180, 181, 97, 182, 183, 98, 184, 185, 99, 186, 187, -100, 188, 189, 101, 190, 191, 102, 192, 193, 103, 194, 195, -104, 196, 197, 105, 198, 199, 106, 200, 201, 107, 202, 203, -108, 204, 205, 109, 206, 207, 110, 208, 209, 111, 210, 211, -112, 212, 213, 113, 214, 215, 114, 216, -1 -}; - -// permutation matrix to compute Prob(x*alfa^logw) -static const int qra_pmat[qra_M*qra_M] = { - 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, - 16, 17, 18, 19, 20, 21, 22, 23, 24, 25, 26, 27, 28, 29, 30, 31, - 32, 33, 34, 35, 36, 37, 38, 39, 40, 41, 42, 43, 44, 45, 46, 47, - 48, 49, 50, 51, 52, 53, 54, 55, 56, 57, 58, 59, 60, 61, 62, 63, - 0, 33, 1, 32, 2, 35, 3, 34, 4, 37, 5, 36, 6, 39, 7, 38, - 8, 41, 9, 40, 10, 43, 11, 42, 12, 45, 13, 44, 14, 47, 15, 46, - 16, 49, 17, 48, 18, 51, 19, 50, 20, 53, 21, 52, 22, 55, 23, 54, - 24, 57, 25, 56, 26, 59, 27, 58, 28, 61, 29, 60, 30, 63, 31, 62, - 0, 49, 33, 16, 1, 48, 32, 17, 2, 51, 35, 18, 3, 50, 34, 19, - 4, 53, 37, 20, 5, 52, 36, 21, 6, 55, 39, 22, 7, 54, 38, 23, - 8, 57, 41, 24, 9, 56, 40, 25, 10, 59, 43, 26, 11, 58, 42, 27, - 12, 61, 45, 28, 13, 60, 44, 29, 14, 63, 47, 30, 15, 62, 46, 31, - 0, 57, 49, 8, 33, 24, 16, 41, 1, 56, 48, 9, 32, 25, 17, 40, - 2, 59, 51, 10, 35, 26, 18, 43, 3, 58, 50, 11, 34, 27, 19, 42, - 4, 61, 53, 12, 37, 28, 20, 45, 5, 60, 52, 13, 36, 29, 21, 44, - 6, 63, 55, 14, 39, 30, 22, 47, 7, 62, 54, 15, 38, 31, 23, 46, - 0, 61, 57, 4, 49, 12, 8, 53, 33, 28, 24, 37, 16, 45, 41, 20, - 1, 60, 56, 5, 48, 13, 9, 52, 32, 29, 25, 36, 17, 44, 40, 21, - 2, 63, 59, 6, 51, 14, 10, 55, 35, 30, 26, 39, 18, 47, 43, 22, - 3, 62, 58, 7, 50, 15, 11, 54, 34, 31, 27, 38, 19, 46, 42, 23, - 0, 63, 61, 2, 57, 6, 4, 59, 49, 14, 12, 51, 8, 55, 53, 10, - 33, 30, 28, 35, 24, 39, 37, 26, 16, 47, 45, 18, 41, 22, 20, 43, - 1, 62, 60, 3, 56, 7, 5, 58, 48, 15, 13, 50, 9, 54, 52, 11, - 32, 31, 29, 34, 25, 38, 36, 27, 17, 46, 44, 19, 40, 23, 21, 42, - 0, 62, 63, 1, 61, 3, 2, 60, 57, 7, 6, 56, 4, 58, 59, 5, - 49, 15, 14, 48, 12, 50, 51, 13, 8, 54, 55, 9, 53, 11, 10, 52, - 33, 31, 30, 32, 28, 34, 35, 29, 24, 38, 39, 25, 37, 27, 26, 36, - 16, 46, 47, 17, 45, 19, 18, 44, 41, 23, 22, 40, 20, 42, 43, 21, - 0, 31, 62, 33, 63, 32, 1, 30, 61, 34, 3, 28, 2, 29, 60, 35, - 57, 38, 7, 24, 6, 25, 56, 39, 4, 27, 58, 37, 59, 36, 5, 26, - 49, 46, 15, 16, 14, 17, 48, 47, 12, 19, 50, 45, 51, 44, 13, 18, - 8, 23, 54, 41, 55, 40, 9, 22, 53, 42, 11, 20, 10, 21, 52, 43, - 0, 46, 31, 49, 62, 16, 33, 15, 63, 17, 32, 14, 1, 47, 30, 48, - 61, 19, 34, 12, 3, 45, 28, 50, 2, 44, 29, 51, 60, 18, 35, 13, - 57, 23, 38, 8, 7, 41, 24, 54, 6, 40, 25, 55, 56, 22, 39, 9, - 4, 42, 27, 53, 58, 20, 37, 11, 59, 21, 36, 10, 5, 43, 26, 52, - 0, 23, 46, 57, 31, 8, 49, 38, 62, 41, 16, 7, 33, 54, 15, 24, - 63, 40, 17, 6, 32, 55, 14, 25, 1, 22, 47, 56, 30, 9, 48, 39, - 61, 42, 19, 4, 34, 53, 12, 27, 3, 20, 45, 58, 28, 11, 50, 37, - 2, 21, 44, 59, 29, 10, 51, 36, 60, 43, 18, 5, 35, 52, 13, 26, - 0, 42, 23, 61, 46, 4, 57, 19, 31, 53, 8, 34, 49, 27, 38, 12, - 62, 20, 41, 3, 16, 58, 7, 45, 33, 11, 54, 28, 15, 37, 24, 50, - 63, 21, 40, 2, 17, 59, 6, 44, 32, 10, 55, 29, 14, 36, 25, 51, - 1, 43, 22, 60, 47, 5, 56, 18, 30, 52, 9, 35, 48, 26, 39, 13, - 0, 21, 42, 63, 23, 2, 61, 40, 46, 59, 4, 17, 57, 44, 19, 6, - 31, 10, 53, 32, 8, 29, 34, 55, 49, 36, 27, 14, 38, 51, 12, 25, - 62, 43, 20, 1, 41, 60, 3, 22, 16, 5, 58, 47, 7, 18, 45, 56, - 33, 52, 11, 30, 54, 35, 28, 9, 15, 26, 37, 48, 24, 13, 50, 39, - 0, 43, 21, 62, 42, 1, 63, 20, 23, 60, 2, 41, 61, 22, 40, 3, - 46, 5, 59, 16, 4, 47, 17, 58, 57, 18, 44, 7, 19, 56, 6, 45, - 31, 52, 10, 33, 53, 30, 32, 11, 8, 35, 29, 54, 34, 9, 55, 28, - 49, 26, 36, 15, 27, 48, 14, 37, 38, 13, 51, 24, 12, 39, 25, 50, - 0, 52, 43, 31, 21, 33, 62, 10, 42, 30, 1, 53, 63, 11, 20, 32, - 23, 35, 60, 8, 2, 54, 41, 29, 61, 9, 22, 34, 40, 28, 3, 55, - 46, 26, 5, 49, 59, 15, 16, 36, 4, 48, 47, 27, 17, 37, 58, 14, - 57, 13, 18, 38, 44, 24, 7, 51, 19, 39, 56, 12, 6, 50, 45, 25, - 0, 26, 52, 46, 43, 49, 31, 5, 21, 15, 33, 59, 62, 36, 10, 16, - 42, 48, 30, 4, 1, 27, 53, 47, 63, 37, 11, 17, 20, 14, 32, 58, - 23, 13, 35, 57, 60, 38, 8, 18, 2, 24, 54, 44, 41, 51, 29, 7, - 61, 39, 9, 19, 22, 12, 34, 56, 40, 50, 28, 6, 3, 25, 55, 45, - 0, 13, 26, 23, 52, 57, 46, 35, 43, 38, 49, 60, 31, 18, 5, 8, - 21, 24, 15, 2, 33, 44, 59, 54, 62, 51, 36, 41, 10, 7, 16, 29, - 42, 39, 48, 61, 30, 19, 4, 9, 1, 12, 27, 22, 53, 56, 47, 34, - 63, 50, 37, 40, 11, 6, 17, 28, 20, 25, 14, 3, 32, 45, 58, 55, - 0, 39, 13, 42, 26, 61, 23, 48, 52, 19, 57, 30, 46, 9, 35, 4, - 43, 12, 38, 1, 49, 22, 60, 27, 31, 56, 18, 53, 5, 34, 8, 47, - 21, 50, 24, 63, 15, 40, 2, 37, 33, 6, 44, 11, 59, 28, 54, 17, - 62, 25, 51, 20, 36, 3, 41, 14, 10, 45, 7, 32, 16, 55, 29, 58, - 0, 50, 39, 21, 13, 63, 42, 24, 26, 40, 61, 15, 23, 37, 48, 2, - 52, 6, 19, 33, 57, 11, 30, 44, 46, 28, 9, 59, 35, 17, 4, 54, - 43, 25, 12, 62, 38, 20, 1, 51, 49, 3, 22, 36, 60, 14, 27, 41, - 31, 45, 56, 10, 18, 32, 53, 7, 5, 55, 34, 16, 8, 58, 47, 29, - 0, 25, 50, 43, 39, 62, 21, 12, 13, 20, 63, 38, 42, 51, 24, 1, - 26, 3, 40, 49, 61, 36, 15, 22, 23, 14, 37, 60, 48, 41, 2, 27, - 52, 45, 6, 31, 19, 10, 33, 56, 57, 32, 11, 18, 30, 7, 44, 53, - 46, 55, 28, 5, 9, 16, 59, 34, 35, 58, 17, 8, 4, 29, 54, 47, - 0, 45, 25, 52, 50, 31, 43, 6, 39, 10, 62, 19, 21, 56, 12, 33, - 13, 32, 20, 57, 63, 18, 38, 11, 42, 7, 51, 30, 24, 53, 1, 44, - 26, 55, 3, 46, 40, 5, 49, 28, 61, 16, 36, 9, 15, 34, 22, 59, - 23, 58, 14, 35, 37, 8, 60, 17, 48, 29, 41, 4, 2, 47, 27, 54, - 0, 55, 45, 26, 25, 46, 52, 3, 50, 5, 31, 40, 43, 28, 6, 49, - 39, 16, 10, 61, 62, 9, 19, 36, 21, 34, 56, 15, 12, 59, 33, 22, - 13, 58, 32, 23, 20, 35, 57, 14, 63, 8, 18, 37, 38, 17, 11, 60, - 42, 29, 7, 48, 51, 4, 30, 41, 24, 47, 53, 2, 1, 54, 44, 27, - 0, 58, 55, 13, 45, 23, 26, 32, 25, 35, 46, 20, 52, 14, 3, 57, - 50, 8, 5, 63, 31, 37, 40, 18, 43, 17, 28, 38, 6, 60, 49, 11, - 39, 29, 16, 42, 10, 48, 61, 7, 62, 4, 9, 51, 19, 41, 36, 30, - 21, 47, 34, 24, 56, 2, 15, 53, 12, 54, 59, 1, 33, 27, 22, 44, - 0, 29, 58, 39, 55, 42, 13, 16, 45, 48, 23, 10, 26, 7, 32, 61, - 25, 4, 35, 62, 46, 51, 20, 9, 52, 41, 14, 19, 3, 30, 57, 36, - 50, 47, 8, 21, 5, 24, 63, 34, 31, 2, 37, 56, 40, 53, 18, 15, - 43, 54, 17, 12, 28, 1, 38, 59, 6, 27, 60, 33, 49, 44, 11, 22, - 0, 47, 29, 50, 58, 21, 39, 8, 55, 24, 42, 5, 13, 34, 16, 63, - 45, 2, 48, 31, 23, 56, 10, 37, 26, 53, 7, 40, 32, 15, 61, 18, - 25, 54, 4, 43, 35, 12, 62, 17, 46, 1, 51, 28, 20, 59, 9, 38, - 52, 27, 41, 6, 14, 33, 19, 60, 3, 44, 30, 49, 57, 22, 36, 11, - 0, 54, 47, 25, 29, 43, 50, 4, 58, 12, 21, 35, 39, 17, 8, 62, - 55, 1, 24, 46, 42, 28, 5, 51, 13, 59, 34, 20, 16, 38, 63, 9, - 45, 27, 2, 52, 48, 6, 31, 41, 23, 33, 56, 14, 10, 60, 37, 19, - 26, 44, 53, 3, 7, 49, 40, 30, 32, 22, 15, 57, 61, 11, 18, 36, - 0, 27, 54, 45, 47, 52, 25, 2, 29, 6, 43, 48, 50, 41, 4, 31, - 58, 33, 12, 23, 21, 14, 35, 56, 39, 60, 17, 10, 8, 19, 62, 37, - 55, 44, 1, 26, 24, 3, 46, 53, 42, 49, 28, 7, 5, 30, 51, 40, - 13, 22, 59, 32, 34, 57, 20, 15, 16, 11, 38, 61, 63, 36, 9, 18, - 0, 44, 27, 55, 54, 26, 45, 1, 47, 3, 52, 24, 25, 53, 2, 46, - 29, 49, 6, 42, 43, 7, 48, 28, 50, 30, 41, 5, 4, 40, 31, 51, - 58, 22, 33, 13, 12, 32, 23, 59, 21, 57, 14, 34, 35, 15, 56, 20, - 39, 11, 60, 16, 17, 61, 10, 38, 8, 36, 19, 63, 62, 18, 37, 9, - 0, 22, 44, 58, 27, 13, 55, 33, 54, 32, 26, 12, 45, 59, 1, 23, - 47, 57, 3, 21, 52, 34, 24, 14, 25, 15, 53, 35, 2, 20, 46, 56, - 29, 11, 49, 39, 6, 16, 42, 60, 43, 61, 7, 17, 48, 38, 28, 10, - 50, 36, 30, 8, 41, 63, 5, 19, 4, 18, 40, 62, 31, 9, 51, 37, - 0, 11, 22, 29, 44, 39, 58, 49, 27, 16, 13, 6, 55, 60, 33, 42, - 54, 61, 32, 43, 26, 17, 12, 7, 45, 38, 59, 48, 1, 10, 23, 28, - 47, 36, 57, 50, 3, 8, 21, 30, 52, 63, 34, 41, 24, 19, 14, 5, - 25, 18, 15, 4, 53, 62, 35, 40, 2, 9, 20, 31, 46, 37, 56, 51, - 0, 36, 11, 47, 22, 50, 29, 57, 44, 8, 39, 3, 58, 30, 49, 21, - 27, 63, 16, 52, 13, 41, 6, 34, 55, 19, 60, 24, 33, 5, 42, 14, - 54, 18, 61, 25, 32, 4, 43, 15, 26, 62, 17, 53, 12, 40, 7, 35, - 45, 9, 38, 2, 59, 31, 48, 20, 1, 37, 10, 46, 23, 51, 28, 56, - 0, 18, 36, 54, 11, 25, 47, 61, 22, 4, 50, 32, 29, 15, 57, 43, - 44, 62, 8, 26, 39, 53, 3, 17, 58, 40, 30, 12, 49, 35, 21, 7, - 27, 9, 63, 45, 16, 2, 52, 38, 13, 31, 41, 59, 6, 20, 34, 48, - 55, 37, 19, 1, 60, 46, 24, 10, 33, 51, 5, 23, 42, 56, 14, 28, - 0, 9, 18, 27, 36, 45, 54, 63, 11, 2, 25, 16, 47, 38, 61, 52, - 22, 31, 4, 13, 50, 59, 32, 41, 29, 20, 15, 6, 57, 48, 43, 34, - 44, 37, 62, 55, 8, 1, 26, 19, 39, 46, 53, 60, 3, 10, 17, 24, - 58, 51, 40, 33, 30, 23, 12, 5, 49, 56, 35, 42, 21, 28, 7, 14, - 0, 37, 9, 44, 18, 55, 27, 62, 36, 1, 45, 8, 54, 19, 63, 26, - 11, 46, 2, 39, 25, 60, 16, 53, 47, 10, 38, 3, 61, 24, 52, 17, - 22, 51, 31, 58, 4, 33, 13, 40, 50, 23, 59, 30, 32, 5, 41, 12, - 29, 56, 20, 49, 15, 42, 6, 35, 57, 28, 48, 21, 43, 14, 34, 7, - 0, 51, 37, 22, 9, 58, 44, 31, 18, 33, 55, 4, 27, 40, 62, 13, - 36, 23, 1, 50, 45, 30, 8, 59, 54, 5, 19, 32, 63, 12, 26, 41, - 11, 56, 46, 29, 2, 49, 39, 20, 25, 42, 60, 15, 16, 35, 53, 6, - 47, 28, 10, 57, 38, 21, 3, 48, 61, 14, 24, 43, 52, 7, 17, 34, - 0, 56, 51, 11, 37, 29, 22, 46, 9, 49, 58, 2, 44, 20, 31, 39, - 18, 42, 33, 25, 55, 15, 4, 60, 27, 35, 40, 16, 62, 6, 13, 53, - 36, 28, 23, 47, 1, 57, 50, 10, 45, 21, 30, 38, 8, 48, 59, 3, - 54, 14, 5, 61, 19, 43, 32, 24, 63, 7, 12, 52, 26, 34, 41, 17, - 0, 28, 56, 36, 51, 47, 11, 23, 37, 57, 29, 1, 22, 10, 46, 50, - 9, 21, 49, 45, 58, 38, 2, 30, 44, 48, 20, 8, 31, 3, 39, 59, - 18, 14, 42, 54, 33, 61, 25, 5, 55, 43, 15, 19, 4, 24, 60, 32, - 27, 7, 35, 63, 40, 52, 16, 12, 62, 34, 6, 26, 13, 17, 53, 41, - 0, 14, 28, 18, 56, 54, 36, 42, 51, 61, 47, 33, 11, 5, 23, 25, - 37, 43, 57, 55, 29, 19, 1, 15, 22, 24, 10, 4, 46, 32, 50, 60, - 9, 7, 21, 27, 49, 63, 45, 35, 58, 52, 38, 40, 2, 12, 30, 16, - 44, 34, 48, 62, 20, 26, 8, 6, 31, 17, 3, 13, 39, 41, 59, 53, - 0, 7, 14, 9, 28, 27, 18, 21, 56, 63, 54, 49, 36, 35, 42, 45, - 51, 52, 61, 58, 47, 40, 33, 38, 11, 12, 5, 2, 23, 16, 25, 30, - 37, 34, 43, 44, 57, 62, 55, 48, 29, 26, 19, 20, 1, 6, 15, 8, - 22, 17, 24, 31, 10, 13, 4, 3, 46, 41, 32, 39, 50, 53, 60, 59, - 0, 34, 7, 37, 14, 44, 9, 43, 28, 62, 27, 57, 18, 48, 21, 55, - 56, 26, 63, 29, 54, 20, 49, 19, 36, 6, 35, 1, 42, 8, 45, 15, - 51, 17, 52, 22, 61, 31, 58, 24, 47, 13, 40, 10, 33, 3, 38, 4, - 11, 41, 12, 46, 5, 39, 2, 32, 23, 53, 16, 50, 25, 59, 30, 60, - 0, 17, 34, 51, 7, 22, 37, 52, 14, 31, 44, 61, 9, 24, 43, 58, - 28, 13, 62, 47, 27, 10, 57, 40, 18, 3, 48, 33, 21, 4, 55, 38, - 56, 41, 26, 11, 63, 46, 29, 12, 54, 39, 20, 5, 49, 32, 19, 2, - 36, 53, 6, 23, 35, 50, 1, 16, 42, 59, 8, 25, 45, 60, 15, 30, - 0, 41, 17, 56, 34, 11, 51, 26, 7, 46, 22, 63, 37, 12, 52, 29, - 14, 39, 31, 54, 44, 5, 61, 20, 9, 32, 24, 49, 43, 2, 58, 19, - 28, 53, 13, 36, 62, 23, 47, 6, 27, 50, 10, 35, 57, 16, 40, 1, - 18, 59, 3, 42, 48, 25, 33, 8, 21, 60, 4, 45, 55, 30, 38, 15, - 0, 53, 41, 28, 17, 36, 56, 13, 34, 23, 11, 62, 51, 6, 26, 47, - 7, 50, 46, 27, 22, 35, 63, 10, 37, 16, 12, 57, 52, 1, 29, 40, - 14, 59, 39, 18, 31, 42, 54, 3, 44, 25, 5, 48, 61, 8, 20, 33, - 9, 60, 32, 21, 24, 45, 49, 4, 43, 30, 2, 55, 58, 15, 19, 38, - 0, 59, 53, 14, 41, 18, 28, 39, 17, 42, 36, 31, 56, 3, 13, 54, - 34, 25, 23, 44, 11, 48, 62, 5, 51, 8, 6, 61, 26, 33, 47, 20, - 7, 60, 50, 9, 46, 21, 27, 32, 22, 45, 35, 24, 63, 4, 10, 49, - 37, 30, 16, 43, 12, 55, 57, 2, 52, 15, 1, 58, 29, 38, 40, 19, - 0, 60, 59, 7, 53, 9, 14, 50, 41, 21, 18, 46, 28, 32, 39, 27, - 17, 45, 42, 22, 36, 24, 31, 35, 56, 4, 3, 63, 13, 49, 54, 10, - 34, 30, 25, 37, 23, 43, 44, 16, 11, 55, 48, 12, 62, 2, 5, 57, - 51, 15, 8, 52, 6, 58, 61, 1, 26, 38, 33, 29, 47, 19, 20, 40, - 0, 30, 60, 34, 59, 37, 7, 25, 53, 43, 9, 23, 14, 16, 50, 44, - 41, 55, 21, 11, 18, 12, 46, 48, 28, 2, 32, 62, 39, 57, 27, 5, - 17, 15, 45, 51, 42, 52, 22, 8, 36, 58, 24, 6, 31, 1, 35, 61, - 56, 38, 4, 26, 3, 29, 63, 33, 13, 19, 49, 47, 54, 40, 10, 20, - 0, 15, 30, 17, 60, 51, 34, 45, 59, 52, 37, 42, 7, 8, 25, 22, - 53, 58, 43, 36, 9, 6, 23, 24, 14, 1, 16, 31, 50, 61, 44, 35, - 41, 38, 55, 56, 21, 26, 11, 4, 18, 29, 12, 3, 46, 33, 48, 63, - 28, 19, 2, 13, 32, 47, 62, 49, 39, 40, 57, 54, 27, 20, 5, 10, - 0, 38, 15, 41, 30, 56, 17, 55, 60, 26, 51, 21, 34, 4, 45, 11, - 59, 29, 52, 18, 37, 3, 42, 12, 7, 33, 8, 46, 25, 63, 22, 48, - 53, 19, 58, 28, 43, 13, 36, 2, 9, 47, 6, 32, 23, 49, 24, 62, - 14, 40, 1, 39, 16, 54, 31, 57, 50, 20, 61, 27, 44, 10, 35, 5, - 0, 19, 38, 53, 15, 28, 41, 58, 30, 13, 56, 43, 17, 2, 55, 36, - 60, 47, 26, 9, 51, 32, 21, 6, 34, 49, 4, 23, 45, 62, 11, 24, - 59, 40, 29, 14, 52, 39, 18, 1, 37, 54, 3, 16, 42, 57, 12, 31, - 7, 20, 33, 50, 8, 27, 46, 61, 25, 10, 63, 44, 22, 5, 48, 35, - 0, 40, 19, 59, 38, 14, 53, 29, 15, 39, 28, 52, 41, 1, 58, 18, - 30, 54, 13, 37, 56, 16, 43, 3, 17, 57, 2, 42, 55, 31, 36, 12, - 60, 20, 47, 7, 26, 50, 9, 33, 51, 27, 32, 8, 21, 61, 6, 46, - 34, 10, 49, 25, 4, 44, 23, 63, 45, 5, 62, 22, 11, 35, 24, 48, - 0, 20, 40, 60, 19, 7, 59, 47, 38, 50, 14, 26, 53, 33, 29, 9, - 15, 27, 39, 51, 28, 8, 52, 32, 41, 61, 1, 21, 58, 46, 18, 6, - 30, 10, 54, 34, 13, 25, 37, 49, 56, 44, 16, 4, 43, 63, 3, 23, - 17, 5, 57, 45, 2, 22, 42, 62, 55, 35, 31, 11, 36, 48, 12, 24, - 0, 10, 20, 30, 40, 34, 60, 54, 19, 25, 7, 13, 59, 49, 47, 37, - 38, 44, 50, 56, 14, 4, 26, 16, 53, 63, 33, 43, 29, 23, 9, 3, - 15, 5, 27, 17, 39, 45, 51, 57, 28, 22, 8, 2, 52, 62, 32, 42, - 41, 35, 61, 55, 1, 11, 21, 31, 58, 48, 46, 36, 18, 24, 6, 12, - 0, 5, 10, 15, 20, 17, 30, 27, 40, 45, 34, 39, 60, 57, 54, 51, - 19, 22, 25, 28, 7, 2, 13, 8, 59, 62, 49, 52, 47, 42, 37, 32, - 38, 35, 44, 41, 50, 55, 56, 61, 14, 11, 4, 1, 26, 31, 16, 21, - 53, 48, 63, 58, 33, 36, 43, 46, 29, 24, 23, 18, 9, 12, 3, 6, - 0, 35, 5, 38, 10, 41, 15, 44, 20, 55, 17, 50, 30, 61, 27, 56, - 40, 11, 45, 14, 34, 1, 39, 4, 60, 31, 57, 26, 54, 21, 51, 16, - 19, 48, 22, 53, 25, 58, 28, 63, 7, 36, 2, 33, 13, 46, 8, 43, - 59, 24, 62, 29, 49, 18, 52, 23, 47, 12, 42, 9, 37, 6, 32, 3, - 0, 48, 35, 19, 5, 53, 38, 22, 10, 58, 41, 25, 15, 63, 44, 28, - 20, 36, 55, 7, 17, 33, 50, 2, 30, 46, 61, 13, 27, 43, 56, 8, - 40, 24, 11, 59, 45, 29, 14, 62, 34, 18, 1, 49, 39, 23, 4, 52, - 60, 12, 31, 47, 57, 9, 26, 42, 54, 6, 21, 37, 51, 3, 16, 32, - 0, 24, 48, 40, 35, 59, 19, 11, 5, 29, 53, 45, 38, 62, 22, 14, - 10, 18, 58, 34, 41, 49, 25, 1, 15, 23, 63, 39, 44, 52, 28, 4, - 20, 12, 36, 60, 55, 47, 7, 31, 17, 9, 33, 57, 50, 42, 2, 26, - 30, 6, 46, 54, 61, 37, 13, 21, 27, 3, 43, 51, 56, 32, 8, 16, - 0, 12, 24, 20, 48, 60, 40, 36, 35, 47, 59, 55, 19, 31, 11, 7, - 5, 9, 29, 17, 53, 57, 45, 33, 38, 42, 62, 50, 22, 26, 14, 2, - 10, 6, 18, 30, 58, 54, 34, 46, 41, 37, 49, 61, 25, 21, 1, 13, - 15, 3, 23, 27, 63, 51, 39, 43, 44, 32, 52, 56, 28, 16, 4, 8, - 0, 6, 12, 10, 24, 30, 20, 18, 48, 54, 60, 58, 40, 46, 36, 34, - 35, 37, 47, 41, 59, 61, 55, 49, 19, 21, 31, 25, 11, 13, 7, 1, - 5, 3, 9, 15, 29, 27, 17, 23, 53, 51, 57, 63, 45, 43, 33, 39, - 38, 32, 42, 44, 62, 56, 50, 52, 22, 16, 26, 28, 14, 8, 2, 4, - 0, 3, 6, 5, 12, 15, 10, 9, 24, 27, 30, 29, 20, 23, 18, 17, - 48, 51, 54, 53, 60, 63, 58, 57, 40, 43, 46, 45, 36, 39, 34, 33, - 35, 32, 37, 38, 47, 44, 41, 42, 59, 56, 61, 62, 55, 52, 49, 50, - 19, 16, 21, 22, 31, 28, 25, 26, 11, 8, 13, 14, 7, 4, 1, 2, - 0, 32, 3, 35, 6, 38, 5, 37, 12, 44, 15, 47, 10, 42, 9, 41, - 24, 56, 27, 59, 30, 62, 29, 61, 20, 52, 23, 55, 18, 50, 17, 49, - 48, 16, 51, 19, 54, 22, 53, 21, 60, 28, 63, 31, 58, 26, 57, 25, - 40, 8, 43, 11, 46, 14, 45, 13, 36, 4, 39, 7, 34, 2, 33, 1, - 0, 16, 32, 48, 3, 19, 35, 51, 6, 22, 38, 54, 5, 21, 37, 53, - 12, 28, 44, 60, 15, 31, 47, 63, 10, 26, 42, 58, 9, 25, 41, 57, - 24, 8, 56, 40, 27, 11, 59, 43, 30, 14, 62, 46, 29, 13, 61, 45, - 20, 4, 52, 36, 23, 7, 55, 39, 18, 2, 50, 34, 17, 1, 49, 33, - 0, 8, 16, 24, 32, 40, 48, 56, 3, 11, 19, 27, 35, 43, 51, 59, - 6, 14, 22, 30, 38, 46, 54, 62, 5, 13, 21, 29, 37, 45, 53, 61, - 12, 4, 28, 20, 44, 36, 60, 52, 15, 7, 31, 23, 47, 39, 63, 55, - 10, 2, 26, 18, 42, 34, 58, 50, 9, 1, 25, 17, 41, 33, 57, 49, - 0, 4, 8, 12, 16, 20, 24, 28, 32, 36, 40, 44, 48, 52, 56, 60, - 3, 7, 11, 15, 19, 23, 27, 31, 35, 39, 43, 47, 51, 55, 59, 63, - 6, 2, 14, 10, 22, 18, 30, 26, 38, 34, 46, 42, 54, 50, 62, 58, - 5, 1, 13, 9, 21, 17, 29, 25, 37, 33, 45, 41, 53, 49, 61, 57, - 0, 2, 4, 6, 8, 10, 12, 14, 16, 18, 20, 22, 24, 26, 28, 30, - 32, 34, 36, 38, 40, 42, 44, 46, 48, 50, 52, 54, 56, 58, 60, 62, - 3, 1, 7, 5, 11, 9, 15, 13, 19, 17, 23, 21, 27, 25, 31, 29, - 35, 33, 39, 37, 43, 41, 47, 45, 51, 49, 55, 53, 59, 57, 63, 61 -}; - -const qracode qra_12_63_64_irr_b = { - qra_K, - qra_N, - qra_m, - qra_M, - qra_a, - qra_NC, - qra_V, - qra_C, - qra_NMSG, - qra_MAXVDEG, - qra_MAXCDEG, - QRATYPE_NORMAL, - qra_R, - CODE_NAME, - qra_acc_input_idx, - qra_acc_input_wlog, - qra_log, - qra_exp, - qra_msgw, - qra_vdeg, - qra_cdeg, - qra_v2cmidx, - qra_c2vmidx, - qra_pmat -}; - -#undef qra_K -#undef qra_N -#undef qra_m -#undef qra_M -#undef qra_a -#undef qra_NC -#undef qra_V -#undef qra_C -#undef qra_NMSG -#undef qra_MAXVDEG -#undef qra_MAXCDEG -#undef qra_R -#undef CODE_NAME \ No newline at end of file diff --git a/lib/qra/qracodes/qra12_63_64_irr_b.h b/lib/qra/qracodes/qra12_63_64_irr_b.h deleted file mode 100644 index bf70b36..0000000 --- a/lib/qra/qracodes/qra12_63_64_irr_b.h +++ /dev/null @@ -1,39 +0,0 @@ -// qra12_63_64_irr_b.h -// Code tables and defines for Q-ary RA code (12,63) over GF(64) -// Code Name: qra12_63_64_irr_b -// (12,63) RA Code over GF(64) - RF=333344455567 - -// (c) 2016 - Nico Palermo - IV3NWV - Microtelecom Srl, Italy - -// This file is part of the qracodes project, a Forward Error Control -// encoding/decoding package based on Q-ary RA (Repeat and Accumulate) LDPC codes. -// -// qracodes is free software: you can redistribute it and/or modify -// it under the terms of the GNU General Public License as published by -// the Free Software Foundation, either version 3 of the License, or -// (at your option) any later version. -// qracodes is distributed in the hope that it will be useful, -// but WITHOUT ANY WARRANTY; without even the implied warranty of -// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -// GNU General Public License for more details. -// -// You should have received a copy of the GNU General Public License -// along with qracodes source distribution. -// If not, see . - -#ifndef _qra12_63_64_irr_b_h -#define _qra12_63_64_irr_b_h - -#include "qracodes.h" - -#ifdef __cplusplus -extern "C" { -#endif - -extern const qracode qra_12_63_64_irr_b; - -#ifdef __cplusplus -} -#endif - -#endif // _qra12_63_64_irr_b_h diff --git a/lib/qra/qracodes/qra13_64_64_irr_e.c b/lib/qra/qracodes/qra13_64_64_irr_e.c deleted file mode 100644 index 7adf22f..0000000 --- a/lib/qra/qracodes/qra13_64_64_irr_e.c +++ /dev/null @@ -1,534 +0,0 @@ -// qra13_64_64_irr_e.c -// Encoding/Decoding tables for Q-ary RA code (13,64) over GF(64) -// Code Name: qra13_64_64_irr_e -// (13,64) RA Code over GF(64) RF=[3x4 4x4 6x1 3x2 5x1 7x1]/18 - -// (c) 2016 - Nico Palermo - IV3NWV - Microtelecom Srl, Italy - -// This file is part of the qracodes project, a Forward Error Control -// encoding/decoding package based on Q-ary RA (Repeat and Accumulate) LDPC codes. -// -// qracodes is free software: you can redistribute it and/or modify -// it under the terms of the GNU General Public License as published by -// the Free Software Foundation, either version 3 of the License, or -// (at your option) any later version. -// qracodes is distributed in the hope that it will be useful, -// but WITHOUT ANY WARRANTY; without even the implied warranty of -// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -// GNU General Public License for more details. -// -// You should have received a copy of the GNU General Public License -// along with qracodes source distribution. -// If not, see . - -#include "qra13_64_64_irr_e.h" - -#define qra_K 13 // number of information symbols -#define qra_N 64 // codeword length in symbols -#define qra_m 6 // bits/symbol -#define qra_M 64 // Symbol alphabet cardinality -#define qra_a 1 // grouping factor -#define qra_NC 51 // number of check symbols (N-K) - -// Defines used by the message passing decoder -------- - -#define qra_V 64 // number of variables in the code graph (N) -#define qra_C 116 // number of factors in the code graph (N +(N-K)+1) -#define qra_NMSG 218 // number of msgs in the code graph -#define qra_MAXVDEG 8 // maximum variable degree -#define qra_MAXCDEG 3 // maximum factor degree -#define qra_R 0.20313f // code rate (K/N) -#define CODE_NAME "qra_13_64_64_irr_e" - -// table of the systematic symbols indexes in the accumulator chain -static const int qra_acc_input_idx[qra_NC+1] = { - 12, 4, 3, 9, 0, 11, 6, 8, 12, 1, - 2, 7, 4, 11, 3, 5, 9, 8, 12, 7, - 2, 4, 10, 3, 5, 11, 12, 8, 9, 6, - 7, 2, 5, 4, 12, 8, 11, 1, 6, 7, - 0, 10, 12, 8, 11, 5, 6, 1, 0, 10, - 12, 8 -}; - -// table of the systematic symbols weight logarithms over GF(M) -static const int qra_acc_input_wlog[qra_NC+1] = { - 0, 27, 0, 0, 0, 31, 28, 61, 31, 0, - 0, 52, 22, 7, 19, 47, 44, 62, 32, 50, - 52, 42, 48, 56, 40, 50, 51, 37, 37, 0, - 5, 14, 0, 0, 18, 2, 0, 45, 21, 0, - 62, 8, 11, 60, 36, 32, 17, 9, 5, 0, - 53, 0 -}; - -// table of the logarithms of the elements of GF(M) (log(0) never used) -static const int qra_log[qra_M] = { - -1, 0, 1, 6, 2, 12, 7, 26, 3, 32, - 13, 35, 8, 48, 27, 18, 4, 24, 33, 16, - 14, 52, 36, 54, 9, 45, 49, 38, 28, 41, - 19, 56, 5, 62, 25, 11, 34, 31, 17, 47, - 15, 23, 53, 51, 37, 44, 55, 40, 10, 61, - 46, 30, 50, 22, 39, 43, 29, 60, 42, 21, - 20, 59, 57, 58 -}; - -// table of GF(M) elements given their logarithm -static const int qra_exp[qra_M-1] = { - 1, 2, 4, 8, 16, 32, 3, 6, 12, 24, - 48, 35, 5, 10, 20, 40, 19, 38, 15, 30, - 60, 59, 53, 41, 17, 34, 7, 14, 28, 56, - 51, 37, 9, 18, 36, 11, 22, 44, 27, 54, - 47, 29, 58, 55, 45, 25, 50, 39, 13, 26, - 52, 43, 21, 42, 23, 46, 31, 62, 63, 61, - 57, 49, 33 -}; - -// table of the messages weight logarithms over GF(M) -static const int qra_msgw[qra_NMSG] = { - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 27, 0, 0, 0, 31, - 28, 61, 31, 0, 0, 52, 22, 7, 19, 47, - 44, 62, 32, 50, 52, 42, 48, 56, 40, 50, - 51, 37, 37, 0, 5, 14, 0, 0, 18, 2, - 0, 45, 21, 0, 62, 8, 11, 60, 36, 32, - 17, 9, 5, 0, 53, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0 -}; - -// table of the degrees of the variable nodes -static const int qra_vdeg[qra_V] = { - 4, 4, 4, 4, 5, 5, 5, 5, 7, 4, - 4, 6, 8, 3, 3, 3, 3, 3, 3, 3, - 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, - 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, - 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, - 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, - 3, 3, 3, 3 -}; - -// table of the degrees of the factor nodes -static const int qra_cdeg[qra_C] = { - 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, - 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, - 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, - 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, - 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, - 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, - 1, 1, 1, 1, 2, 3, 3, 3, 3, 3, - 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, - 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, - 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, - 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, - 3, 3, 3, 3, 3, 2 -}; - -// table (uncompressed) of the v->c message indexes (-1=unused entry) -static const int qra_v2cmidx[qra_V*qra_MAXVDEG] = { - 0, 68, 104, 112, -1, -1, -1, -1, - 1, 73, 101, 111, -1, -1, -1, -1, - 2, 74, 84, 95, -1, -1, -1, -1, - 3, 66, 78, 87, -1, -1, -1, -1, - 4, 65, 76, 85, 97, -1, -1, -1, - 5, 79, 88, 96, 109, -1, -1, -1, - 6, 70, 93, 102, 110, -1, -1, -1, - 7, 75, 83, 94, 103, -1, -1, -1, - 8, 71, 81, 91, 99, 107, 115, -1, - 9, 67, 80, 92, -1, -1, -1, -1, - 10, 86, 105, 113, -1, -1, -1, -1, - 11, 69, 77, 89, 100, 108, -1, -1, - 12, 64, 72, 82, 90, 98, 106, 114, - 13, 116, 117, -1, -1, -1, -1, -1, - 14, 118, 119, -1, -1, -1, -1, -1, - 15, 120, 121, -1, -1, -1, -1, -1, - 16, 122, 123, -1, -1, -1, -1, -1, - 17, 124, 125, -1, -1, -1, -1, -1, - 18, 126, 127, -1, -1, -1, -1, -1, - 19, 128, 129, -1, -1, -1, -1, -1, - 20, 130, 131, -1, -1, -1, -1, -1, - 21, 132, 133, -1, -1, -1, -1, -1, - 22, 134, 135, -1, -1, -1, -1, -1, - 23, 136, 137, -1, -1, -1, -1, -1, - 24, 138, 139, -1, -1, -1, -1, -1, - 25, 140, 141, -1, -1, -1, -1, -1, - 26, 142, 143, -1, -1, -1, -1, -1, - 27, 144, 145, -1, -1, -1, -1, -1, - 28, 146, 147, -1, -1, -1, -1, -1, - 29, 148, 149, -1, -1, -1, -1, -1, - 30, 150, 151, -1, -1, -1, -1, -1, - 31, 152, 153, -1, -1, -1, -1, -1, - 32, 154, 155, -1, -1, -1, -1, -1, - 33, 156, 157, -1, -1, -1, -1, -1, - 34, 158, 159, -1, -1, -1, -1, -1, - 35, 160, 161, -1, -1, -1, -1, -1, - 36, 162, 163, -1, -1, -1, -1, -1, - 37, 164, 165, -1, -1, -1, -1, -1, - 38, 166, 167, -1, -1, -1, -1, -1, - 39, 168, 169, -1, -1, -1, -1, -1, - 40, 170, 171, -1, -1, -1, -1, -1, - 41, 172, 173, -1, -1, -1, -1, -1, - 42, 174, 175, -1, -1, -1, -1, -1, - 43, 176, 177, -1, -1, -1, -1, -1, - 44, 178, 179, -1, -1, -1, -1, -1, - 45, 180, 181, -1, -1, -1, -1, -1, - 46, 182, 183, -1, -1, -1, -1, -1, - 47, 184, 185, -1, -1, -1, -1, -1, - 48, 186, 187, -1, -1, -1, -1, -1, - 49, 188, 189, -1, -1, -1, -1, -1, - 50, 190, 191, -1, -1, -1, -1, -1, - 51, 192, 193, -1, -1, -1, -1, -1, - 52, 194, 195, -1, -1, -1, -1, -1, - 53, 196, 197, -1, -1, -1, -1, -1, - 54, 198, 199, -1, -1, -1, -1, -1, - 55, 200, 201, -1, -1, -1, -1, -1, - 56, 202, 203, -1, -1, -1, -1, -1, - 57, 204, 205, -1, -1, -1, -1, -1, - 58, 206, 207, -1, -1, -1, -1, -1, - 59, 208, 209, -1, -1, -1, -1, -1, - 60, 210, 211, -1, -1, -1, -1, -1, - 61, 212, 213, -1, -1, -1, -1, -1, - 62, 214, 215, -1, -1, -1, -1, -1, - 63, 216, 217, -1, -1, -1, -1, -1 -}; - -// table (uncompressed) of the c->v message indexes (-1=unused entry) -static const int qra_c2vmidx[qra_C*qra_MAXCDEG] = { - 0, -1, -1, 1, -1, -1, 2, -1, -1, 3, -1, -1, - 4, -1, -1, 5, -1, -1, 6, -1, -1, 7, -1, -1, - 8, -1, -1, 9, -1, -1, 10, -1, -1, 11, -1, -1, - 12, -1, -1, 13, -1, -1, 14, -1, -1, 15, -1, -1, - 16, -1, -1, 17, -1, -1, 18, -1, -1, 19, -1, -1, - 20, -1, -1, 21, -1, -1, 22, -1, -1, 23, -1, -1, - 24, -1, -1, 25, -1, -1, 26, -1, -1, 27, -1, -1, - 28, -1, -1, 29, -1, -1, 30, -1, -1, 31, -1, -1, - 32, -1, -1, 33, -1, -1, 34, -1, -1, 35, -1, -1, - 36, -1, -1, 37, -1, -1, 38, -1, -1, 39, -1, -1, - 40, -1, -1, 41, -1, -1, 42, -1, -1, 43, -1, -1, - 44, -1, -1, 45, -1, -1, 46, -1, -1, 47, -1, -1, - 48, -1, -1, 49, -1, -1, 50, -1, -1, 51, -1, -1, - 52, -1, -1, 53, -1, -1, 54, -1, -1, 55, -1, -1, - 56, -1, -1, 57, -1, -1, 58, -1, -1, 59, -1, -1, - 60, -1, -1, 61, -1, -1, 62, -1, -1, 63, -1, -1, - 64, 116, -1, 65, 117, 118, 66, 119, 120, 67, 121, 122, - 68, 123, 124, 69, 125, 126, 70, 127, 128, 71, 129, 130, - 72, 131, 132, 73, 133, 134, 74, 135, 136, 75, 137, 138, - 76, 139, 140, 77, 141, 142, 78, 143, 144, 79, 145, 146, - 80, 147, 148, 81, 149, 150, 82, 151, 152, 83, 153, 154, - 84, 155, 156, 85, 157, 158, 86, 159, 160, 87, 161, 162, - 88, 163, 164, 89, 165, 166, 90, 167, 168, 91, 169, 170, - 92, 171, 172, 93, 173, 174, 94, 175, 176, 95, 177, 178, - 96, 179, 180, 97, 181, 182, 98, 183, 184, 99, 185, 186, -100, 187, 188, 101, 189, 190, 102, 191, 192, 103, 193, 194, -104, 195, 196, 105, 197, 198, 106, 199, 200, 107, 201, 202, -108, 203, 204, 109, 205, 206, 110, 207, 208, 111, 209, 210, -112, 211, 212, 113, 213, 214, 114, 215, 216, 115, 217, -1 -}; - -// permutation matrix to compute Prob(x*alfa^logw) -static const int qra_pmat[qra_M*qra_M] = { - 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, - 16, 17, 18, 19, 20, 21, 22, 23, 24, 25, 26, 27, 28, 29, 30, 31, - 32, 33, 34, 35, 36, 37, 38, 39, 40, 41, 42, 43, 44, 45, 46, 47, - 48, 49, 50, 51, 52, 53, 54, 55, 56, 57, 58, 59, 60, 61, 62, 63, - 0, 33, 1, 32, 2, 35, 3, 34, 4, 37, 5, 36, 6, 39, 7, 38, - 8, 41, 9, 40, 10, 43, 11, 42, 12, 45, 13, 44, 14, 47, 15, 46, - 16, 49, 17, 48, 18, 51, 19, 50, 20, 53, 21, 52, 22, 55, 23, 54, - 24, 57, 25, 56, 26, 59, 27, 58, 28, 61, 29, 60, 30, 63, 31, 62, - 0, 49, 33, 16, 1, 48, 32, 17, 2, 51, 35, 18, 3, 50, 34, 19, - 4, 53, 37, 20, 5, 52, 36, 21, 6, 55, 39, 22, 7, 54, 38, 23, - 8, 57, 41, 24, 9, 56, 40, 25, 10, 59, 43, 26, 11, 58, 42, 27, - 12, 61, 45, 28, 13, 60, 44, 29, 14, 63, 47, 30, 15, 62, 46, 31, - 0, 57, 49, 8, 33, 24, 16, 41, 1, 56, 48, 9, 32, 25, 17, 40, - 2, 59, 51, 10, 35, 26, 18, 43, 3, 58, 50, 11, 34, 27, 19, 42, - 4, 61, 53, 12, 37, 28, 20, 45, 5, 60, 52, 13, 36, 29, 21, 44, - 6, 63, 55, 14, 39, 30, 22, 47, 7, 62, 54, 15, 38, 31, 23, 46, - 0, 61, 57, 4, 49, 12, 8, 53, 33, 28, 24, 37, 16, 45, 41, 20, - 1, 60, 56, 5, 48, 13, 9, 52, 32, 29, 25, 36, 17, 44, 40, 21, - 2, 63, 59, 6, 51, 14, 10, 55, 35, 30, 26, 39, 18, 47, 43, 22, - 3, 62, 58, 7, 50, 15, 11, 54, 34, 31, 27, 38, 19, 46, 42, 23, - 0, 63, 61, 2, 57, 6, 4, 59, 49, 14, 12, 51, 8, 55, 53, 10, - 33, 30, 28, 35, 24, 39, 37, 26, 16, 47, 45, 18, 41, 22, 20, 43, - 1, 62, 60, 3, 56, 7, 5, 58, 48, 15, 13, 50, 9, 54, 52, 11, - 32, 31, 29, 34, 25, 38, 36, 27, 17, 46, 44, 19, 40, 23, 21, 42, - 0, 62, 63, 1, 61, 3, 2, 60, 57, 7, 6, 56, 4, 58, 59, 5, - 49, 15, 14, 48, 12, 50, 51, 13, 8, 54, 55, 9, 53, 11, 10, 52, - 33, 31, 30, 32, 28, 34, 35, 29, 24, 38, 39, 25, 37, 27, 26, 36, - 16, 46, 47, 17, 45, 19, 18, 44, 41, 23, 22, 40, 20, 42, 43, 21, - 0, 31, 62, 33, 63, 32, 1, 30, 61, 34, 3, 28, 2, 29, 60, 35, - 57, 38, 7, 24, 6, 25, 56, 39, 4, 27, 58, 37, 59, 36, 5, 26, - 49, 46, 15, 16, 14, 17, 48, 47, 12, 19, 50, 45, 51, 44, 13, 18, - 8, 23, 54, 41, 55, 40, 9, 22, 53, 42, 11, 20, 10, 21, 52, 43, - 0, 46, 31, 49, 62, 16, 33, 15, 63, 17, 32, 14, 1, 47, 30, 48, - 61, 19, 34, 12, 3, 45, 28, 50, 2, 44, 29, 51, 60, 18, 35, 13, - 57, 23, 38, 8, 7, 41, 24, 54, 6, 40, 25, 55, 56, 22, 39, 9, - 4, 42, 27, 53, 58, 20, 37, 11, 59, 21, 36, 10, 5, 43, 26, 52, - 0, 23, 46, 57, 31, 8, 49, 38, 62, 41, 16, 7, 33, 54, 15, 24, - 63, 40, 17, 6, 32, 55, 14, 25, 1, 22, 47, 56, 30, 9, 48, 39, - 61, 42, 19, 4, 34, 53, 12, 27, 3, 20, 45, 58, 28, 11, 50, 37, - 2, 21, 44, 59, 29, 10, 51, 36, 60, 43, 18, 5, 35, 52, 13, 26, - 0, 42, 23, 61, 46, 4, 57, 19, 31, 53, 8, 34, 49, 27, 38, 12, - 62, 20, 41, 3, 16, 58, 7, 45, 33, 11, 54, 28, 15, 37, 24, 50, - 63, 21, 40, 2, 17, 59, 6, 44, 32, 10, 55, 29, 14, 36, 25, 51, - 1, 43, 22, 60, 47, 5, 56, 18, 30, 52, 9, 35, 48, 26, 39, 13, - 0, 21, 42, 63, 23, 2, 61, 40, 46, 59, 4, 17, 57, 44, 19, 6, - 31, 10, 53, 32, 8, 29, 34, 55, 49, 36, 27, 14, 38, 51, 12, 25, - 62, 43, 20, 1, 41, 60, 3, 22, 16, 5, 58, 47, 7, 18, 45, 56, - 33, 52, 11, 30, 54, 35, 28, 9, 15, 26, 37, 48, 24, 13, 50, 39, - 0, 43, 21, 62, 42, 1, 63, 20, 23, 60, 2, 41, 61, 22, 40, 3, - 46, 5, 59, 16, 4, 47, 17, 58, 57, 18, 44, 7, 19, 56, 6, 45, - 31, 52, 10, 33, 53, 30, 32, 11, 8, 35, 29, 54, 34, 9, 55, 28, - 49, 26, 36, 15, 27, 48, 14, 37, 38, 13, 51, 24, 12, 39, 25, 50, - 0, 52, 43, 31, 21, 33, 62, 10, 42, 30, 1, 53, 63, 11, 20, 32, - 23, 35, 60, 8, 2, 54, 41, 29, 61, 9, 22, 34, 40, 28, 3, 55, - 46, 26, 5, 49, 59, 15, 16, 36, 4, 48, 47, 27, 17, 37, 58, 14, - 57, 13, 18, 38, 44, 24, 7, 51, 19, 39, 56, 12, 6, 50, 45, 25, - 0, 26, 52, 46, 43, 49, 31, 5, 21, 15, 33, 59, 62, 36, 10, 16, - 42, 48, 30, 4, 1, 27, 53, 47, 63, 37, 11, 17, 20, 14, 32, 58, - 23, 13, 35, 57, 60, 38, 8, 18, 2, 24, 54, 44, 41, 51, 29, 7, - 61, 39, 9, 19, 22, 12, 34, 56, 40, 50, 28, 6, 3, 25, 55, 45, - 0, 13, 26, 23, 52, 57, 46, 35, 43, 38, 49, 60, 31, 18, 5, 8, - 21, 24, 15, 2, 33, 44, 59, 54, 62, 51, 36, 41, 10, 7, 16, 29, - 42, 39, 48, 61, 30, 19, 4, 9, 1, 12, 27, 22, 53, 56, 47, 34, - 63, 50, 37, 40, 11, 6, 17, 28, 20, 25, 14, 3, 32, 45, 58, 55, - 0, 39, 13, 42, 26, 61, 23, 48, 52, 19, 57, 30, 46, 9, 35, 4, - 43, 12, 38, 1, 49, 22, 60, 27, 31, 56, 18, 53, 5, 34, 8, 47, - 21, 50, 24, 63, 15, 40, 2, 37, 33, 6, 44, 11, 59, 28, 54, 17, - 62, 25, 51, 20, 36, 3, 41, 14, 10, 45, 7, 32, 16, 55, 29, 58, - 0, 50, 39, 21, 13, 63, 42, 24, 26, 40, 61, 15, 23, 37, 48, 2, - 52, 6, 19, 33, 57, 11, 30, 44, 46, 28, 9, 59, 35, 17, 4, 54, - 43, 25, 12, 62, 38, 20, 1, 51, 49, 3, 22, 36, 60, 14, 27, 41, - 31, 45, 56, 10, 18, 32, 53, 7, 5, 55, 34, 16, 8, 58, 47, 29, - 0, 25, 50, 43, 39, 62, 21, 12, 13, 20, 63, 38, 42, 51, 24, 1, - 26, 3, 40, 49, 61, 36, 15, 22, 23, 14, 37, 60, 48, 41, 2, 27, - 52, 45, 6, 31, 19, 10, 33, 56, 57, 32, 11, 18, 30, 7, 44, 53, - 46, 55, 28, 5, 9, 16, 59, 34, 35, 58, 17, 8, 4, 29, 54, 47, - 0, 45, 25, 52, 50, 31, 43, 6, 39, 10, 62, 19, 21, 56, 12, 33, - 13, 32, 20, 57, 63, 18, 38, 11, 42, 7, 51, 30, 24, 53, 1, 44, - 26, 55, 3, 46, 40, 5, 49, 28, 61, 16, 36, 9, 15, 34, 22, 59, - 23, 58, 14, 35, 37, 8, 60, 17, 48, 29, 41, 4, 2, 47, 27, 54, - 0, 55, 45, 26, 25, 46, 52, 3, 50, 5, 31, 40, 43, 28, 6, 49, - 39, 16, 10, 61, 62, 9, 19, 36, 21, 34, 56, 15, 12, 59, 33, 22, - 13, 58, 32, 23, 20, 35, 57, 14, 63, 8, 18, 37, 38, 17, 11, 60, - 42, 29, 7, 48, 51, 4, 30, 41, 24, 47, 53, 2, 1, 54, 44, 27, - 0, 58, 55, 13, 45, 23, 26, 32, 25, 35, 46, 20, 52, 14, 3, 57, - 50, 8, 5, 63, 31, 37, 40, 18, 43, 17, 28, 38, 6, 60, 49, 11, - 39, 29, 16, 42, 10, 48, 61, 7, 62, 4, 9, 51, 19, 41, 36, 30, - 21, 47, 34, 24, 56, 2, 15, 53, 12, 54, 59, 1, 33, 27, 22, 44, - 0, 29, 58, 39, 55, 42, 13, 16, 45, 48, 23, 10, 26, 7, 32, 61, - 25, 4, 35, 62, 46, 51, 20, 9, 52, 41, 14, 19, 3, 30, 57, 36, - 50, 47, 8, 21, 5, 24, 63, 34, 31, 2, 37, 56, 40, 53, 18, 15, - 43, 54, 17, 12, 28, 1, 38, 59, 6, 27, 60, 33, 49, 44, 11, 22, - 0, 47, 29, 50, 58, 21, 39, 8, 55, 24, 42, 5, 13, 34, 16, 63, - 45, 2, 48, 31, 23, 56, 10, 37, 26, 53, 7, 40, 32, 15, 61, 18, - 25, 54, 4, 43, 35, 12, 62, 17, 46, 1, 51, 28, 20, 59, 9, 38, - 52, 27, 41, 6, 14, 33, 19, 60, 3, 44, 30, 49, 57, 22, 36, 11, - 0, 54, 47, 25, 29, 43, 50, 4, 58, 12, 21, 35, 39, 17, 8, 62, - 55, 1, 24, 46, 42, 28, 5, 51, 13, 59, 34, 20, 16, 38, 63, 9, - 45, 27, 2, 52, 48, 6, 31, 41, 23, 33, 56, 14, 10, 60, 37, 19, - 26, 44, 53, 3, 7, 49, 40, 30, 32, 22, 15, 57, 61, 11, 18, 36, - 0, 27, 54, 45, 47, 52, 25, 2, 29, 6, 43, 48, 50, 41, 4, 31, - 58, 33, 12, 23, 21, 14, 35, 56, 39, 60, 17, 10, 8, 19, 62, 37, - 55, 44, 1, 26, 24, 3, 46, 53, 42, 49, 28, 7, 5, 30, 51, 40, - 13, 22, 59, 32, 34, 57, 20, 15, 16, 11, 38, 61, 63, 36, 9, 18, - 0, 44, 27, 55, 54, 26, 45, 1, 47, 3, 52, 24, 25, 53, 2, 46, - 29, 49, 6, 42, 43, 7, 48, 28, 50, 30, 41, 5, 4, 40, 31, 51, - 58, 22, 33, 13, 12, 32, 23, 59, 21, 57, 14, 34, 35, 15, 56, 20, - 39, 11, 60, 16, 17, 61, 10, 38, 8, 36, 19, 63, 62, 18, 37, 9, - 0, 22, 44, 58, 27, 13, 55, 33, 54, 32, 26, 12, 45, 59, 1, 23, - 47, 57, 3, 21, 52, 34, 24, 14, 25, 15, 53, 35, 2, 20, 46, 56, - 29, 11, 49, 39, 6, 16, 42, 60, 43, 61, 7, 17, 48, 38, 28, 10, - 50, 36, 30, 8, 41, 63, 5, 19, 4, 18, 40, 62, 31, 9, 51, 37, - 0, 11, 22, 29, 44, 39, 58, 49, 27, 16, 13, 6, 55, 60, 33, 42, - 54, 61, 32, 43, 26, 17, 12, 7, 45, 38, 59, 48, 1, 10, 23, 28, - 47, 36, 57, 50, 3, 8, 21, 30, 52, 63, 34, 41, 24, 19, 14, 5, - 25, 18, 15, 4, 53, 62, 35, 40, 2, 9, 20, 31, 46, 37, 56, 51, - 0, 36, 11, 47, 22, 50, 29, 57, 44, 8, 39, 3, 58, 30, 49, 21, - 27, 63, 16, 52, 13, 41, 6, 34, 55, 19, 60, 24, 33, 5, 42, 14, - 54, 18, 61, 25, 32, 4, 43, 15, 26, 62, 17, 53, 12, 40, 7, 35, - 45, 9, 38, 2, 59, 31, 48, 20, 1, 37, 10, 46, 23, 51, 28, 56, - 0, 18, 36, 54, 11, 25, 47, 61, 22, 4, 50, 32, 29, 15, 57, 43, - 44, 62, 8, 26, 39, 53, 3, 17, 58, 40, 30, 12, 49, 35, 21, 7, - 27, 9, 63, 45, 16, 2, 52, 38, 13, 31, 41, 59, 6, 20, 34, 48, - 55, 37, 19, 1, 60, 46, 24, 10, 33, 51, 5, 23, 42, 56, 14, 28, - 0, 9, 18, 27, 36, 45, 54, 63, 11, 2, 25, 16, 47, 38, 61, 52, - 22, 31, 4, 13, 50, 59, 32, 41, 29, 20, 15, 6, 57, 48, 43, 34, - 44, 37, 62, 55, 8, 1, 26, 19, 39, 46, 53, 60, 3, 10, 17, 24, - 58, 51, 40, 33, 30, 23, 12, 5, 49, 56, 35, 42, 21, 28, 7, 14, - 0, 37, 9, 44, 18, 55, 27, 62, 36, 1, 45, 8, 54, 19, 63, 26, - 11, 46, 2, 39, 25, 60, 16, 53, 47, 10, 38, 3, 61, 24, 52, 17, - 22, 51, 31, 58, 4, 33, 13, 40, 50, 23, 59, 30, 32, 5, 41, 12, - 29, 56, 20, 49, 15, 42, 6, 35, 57, 28, 48, 21, 43, 14, 34, 7, - 0, 51, 37, 22, 9, 58, 44, 31, 18, 33, 55, 4, 27, 40, 62, 13, - 36, 23, 1, 50, 45, 30, 8, 59, 54, 5, 19, 32, 63, 12, 26, 41, - 11, 56, 46, 29, 2, 49, 39, 20, 25, 42, 60, 15, 16, 35, 53, 6, - 47, 28, 10, 57, 38, 21, 3, 48, 61, 14, 24, 43, 52, 7, 17, 34, - 0, 56, 51, 11, 37, 29, 22, 46, 9, 49, 58, 2, 44, 20, 31, 39, - 18, 42, 33, 25, 55, 15, 4, 60, 27, 35, 40, 16, 62, 6, 13, 53, - 36, 28, 23, 47, 1, 57, 50, 10, 45, 21, 30, 38, 8, 48, 59, 3, - 54, 14, 5, 61, 19, 43, 32, 24, 63, 7, 12, 52, 26, 34, 41, 17, - 0, 28, 56, 36, 51, 47, 11, 23, 37, 57, 29, 1, 22, 10, 46, 50, - 9, 21, 49, 45, 58, 38, 2, 30, 44, 48, 20, 8, 31, 3, 39, 59, - 18, 14, 42, 54, 33, 61, 25, 5, 55, 43, 15, 19, 4, 24, 60, 32, - 27, 7, 35, 63, 40, 52, 16, 12, 62, 34, 6, 26, 13, 17, 53, 41, - 0, 14, 28, 18, 56, 54, 36, 42, 51, 61, 47, 33, 11, 5, 23, 25, - 37, 43, 57, 55, 29, 19, 1, 15, 22, 24, 10, 4, 46, 32, 50, 60, - 9, 7, 21, 27, 49, 63, 45, 35, 58, 52, 38, 40, 2, 12, 30, 16, - 44, 34, 48, 62, 20, 26, 8, 6, 31, 17, 3, 13, 39, 41, 59, 53, - 0, 7, 14, 9, 28, 27, 18, 21, 56, 63, 54, 49, 36, 35, 42, 45, - 51, 52, 61, 58, 47, 40, 33, 38, 11, 12, 5, 2, 23, 16, 25, 30, - 37, 34, 43, 44, 57, 62, 55, 48, 29, 26, 19, 20, 1, 6, 15, 8, - 22, 17, 24, 31, 10, 13, 4, 3, 46, 41, 32, 39, 50, 53, 60, 59, - 0, 34, 7, 37, 14, 44, 9, 43, 28, 62, 27, 57, 18, 48, 21, 55, - 56, 26, 63, 29, 54, 20, 49, 19, 36, 6, 35, 1, 42, 8, 45, 15, - 51, 17, 52, 22, 61, 31, 58, 24, 47, 13, 40, 10, 33, 3, 38, 4, - 11, 41, 12, 46, 5, 39, 2, 32, 23, 53, 16, 50, 25, 59, 30, 60, - 0, 17, 34, 51, 7, 22, 37, 52, 14, 31, 44, 61, 9, 24, 43, 58, - 28, 13, 62, 47, 27, 10, 57, 40, 18, 3, 48, 33, 21, 4, 55, 38, - 56, 41, 26, 11, 63, 46, 29, 12, 54, 39, 20, 5, 49, 32, 19, 2, - 36, 53, 6, 23, 35, 50, 1, 16, 42, 59, 8, 25, 45, 60, 15, 30, - 0, 41, 17, 56, 34, 11, 51, 26, 7, 46, 22, 63, 37, 12, 52, 29, - 14, 39, 31, 54, 44, 5, 61, 20, 9, 32, 24, 49, 43, 2, 58, 19, - 28, 53, 13, 36, 62, 23, 47, 6, 27, 50, 10, 35, 57, 16, 40, 1, - 18, 59, 3, 42, 48, 25, 33, 8, 21, 60, 4, 45, 55, 30, 38, 15, - 0, 53, 41, 28, 17, 36, 56, 13, 34, 23, 11, 62, 51, 6, 26, 47, - 7, 50, 46, 27, 22, 35, 63, 10, 37, 16, 12, 57, 52, 1, 29, 40, - 14, 59, 39, 18, 31, 42, 54, 3, 44, 25, 5, 48, 61, 8, 20, 33, - 9, 60, 32, 21, 24, 45, 49, 4, 43, 30, 2, 55, 58, 15, 19, 38, - 0, 59, 53, 14, 41, 18, 28, 39, 17, 42, 36, 31, 56, 3, 13, 54, - 34, 25, 23, 44, 11, 48, 62, 5, 51, 8, 6, 61, 26, 33, 47, 20, - 7, 60, 50, 9, 46, 21, 27, 32, 22, 45, 35, 24, 63, 4, 10, 49, - 37, 30, 16, 43, 12, 55, 57, 2, 52, 15, 1, 58, 29, 38, 40, 19, - 0, 60, 59, 7, 53, 9, 14, 50, 41, 21, 18, 46, 28, 32, 39, 27, - 17, 45, 42, 22, 36, 24, 31, 35, 56, 4, 3, 63, 13, 49, 54, 10, - 34, 30, 25, 37, 23, 43, 44, 16, 11, 55, 48, 12, 62, 2, 5, 57, - 51, 15, 8, 52, 6, 58, 61, 1, 26, 38, 33, 29, 47, 19, 20, 40, - 0, 30, 60, 34, 59, 37, 7, 25, 53, 43, 9, 23, 14, 16, 50, 44, - 41, 55, 21, 11, 18, 12, 46, 48, 28, 2, 32, 62, 39, 57, 27, 5, - 17, 15, 45, 51, 42, 52, 22, 8, 36, 58, 24, 6, 31, 1, 35, 61, - 56, 38, 4, 26, 3, 29, 63, 33, 13, 19, 49, 47, 54, 40, 10, 20, - 0, 15, 30, 17, 60, 51, 34, 45, 59, 52, 37, 42, 7, 8, 25, 22, - 53, 58, 43, 36, 9, 6, 23, 24, 14, 1, 16, 31, 50, 61, 44, 35, - 41, 38, 55, 56, 21, 26, 11, 4, 18, 29, 12, 3, 46, 33, 48, 63, - 28, 19, 2, 13, 32, 47, 62, 49, 39, 40, 57, 54, 27, 20, 5, 10, - 0, 38, 15, 41, 30, 56, 17, 55, 60, 26, 51, 21, 34, 4, 45, 11, - 59, 29, 52, 18, 37, 3, 42, 12, 7, 33, 8, 46, 25, 63, 22, 48, - 53, 19, 58, 28, 43, 13, 36, 2, 9, 47, 6, 32, 23, 49, 24, 62, - 14, 40, 1, 39, 16, 54, 31, 57, 50, 20, 61, 27, 44, 10, 35, 5, - 0, 19, 38, 53, 15, 28, 41, 58, 30, 13, 56, 43, 17, 2, 55, 36, - 60, 47, 26, 9, 51, 32, 21, 6, 34, 49, 4, 23, 45, 62, 11, 24, - 59, 40, 29, 14, 52, 39, 18, 1, 37, 54, 3, 16, 42, 57, 12, 31, - 7, 20, 33, 50, 8, 27, 46, 61, 25, 10, 63, 44, 22, 5, 48, 35, - 0, 40, 19, 59, 38, 14, 53, 29, 15, 39, 28, 52, 41, 1, 58, 18, - 30, 54, 13, 37, 56, 16, 43, 3, 17, 57, 2, 42, 55, 31, 36, 12, - 60, 20, 47, 7, 26, 50, 9, 33, 51, 27, 32, 8, 21, 61, 6, 46, - 34, 10, 49, 25, 4, 44, 23, 63, 45, 5, 62, 22, 11, 35, 24, 48, - 0, 20, 40, 60, 19, 7, 59, 47, 38, 50, 14, 26, 53, 33, 29, 9, - 15, 27, 39, 51, 28, 8, 52, 32, 41, 61, 1, 21, 58, 46, 18, 6, - 30, 10, 54, 34, 13, 25, 37, 49, 56, 44, 16, 4, 43, 63, 3, 23, - 17, 5, 57, 45, 2, 22, 42, 62, 55, 35, 31, 11, 36, 48, 12, 24, - 0, 10, 20, 30, 40, 34, 60, 54, 19, 25, 7, 13, 59, 49, 47, 37, - 38, 44, 50, 56, 14, 4, 26, 16, 53, 63, 33, 43, 29, 23, 9, 3, - 15, 5, 27, 17, 39, 45, 51, 57, 28, 22, 8, 2, 52, 62, 32, 42, - 41, 35, 61, 55, 1, 11, 21, 31, 58, 48, 46, 36, 18, 24, 6, 12, - 0, 5, 10, 15, 20, 17, 30, 27, 40, 45, 34, 39, 60, 57, 54, 51, - 19, 22, 25, 28, 7, 2, 13, 8, 59, 62, 49, 52, 47, 42, 37, 32, - 38, 35, 44, 41, 50, 55, 56, 61, 14, 11, 4, 1, 26, 31, 16, 21, - 53, 48, 63, 58, 33, 36, 43, 46, 29, 24, 23, 18, 9, 12, 3, 6, - 0, 35, 5, 38, 10, 41, 15, 44, 20, 55, 17, 50, 30, 61, 27, 56, - 40, 11, 45, 14, 34, 1, 39, 4, 60, 31, 57, 26, 54, 21, 51, 16, - 19, 48, 22, 53, 25, 58, 28, 63, 7, 36, 2, 33, 13, 46, 8, 43, - 59, 24, 62, 29, 49, 18, 52, 23, 47, 12, 42, 9, 37, 6, 32, 3, - 0, 48, 35, 19, 5, 53, 38, 22, 10, 58, 41, 25, 15, 63, 44, 28, - 20, 36, 55, 7, 17, 33, 50, 2, 30, 46, 61, 13, 27, 43, 56, 8, - 40, 24, 11, 59, 45, 29, 14, 62, 34, 18, 1, 49, 39, 23, 4, 52, - 60, 12, 31, 47, 57, 9, 26, 42, 54, 6, 21, 37, 51, 3, 16, 32, - 0, 24, 48, 40, 35, 59, 19, 11, 5, 29, 53, 45, 38, 62, 22, 14, - 10, 18, 58, 34, 41, 49, 25, 1, 15, 23, 63, 39, 44, 52, 28, 4, - 20, 12, 36, 60, 55, 47, 7, 31, 17, 9, 33, 57, 50, 42, 2, 26, - 30, 6, 46, 54, 61, 37, 13, 21, 27, 3, 43, 51, 56, 32, 8, 16, - 0, 12, 24, 20, 48, 60, 40, 36, 35, 47, 59, 55, 19, 31, 11, 7, - 5, 9, 29, 17, 53, 57, 45, 33, 38, 42, 62, 50, 22, 26, 14, 2, - 10, 6, 18, 30, 58, 54, 34, 46, 41, 37, 49, 61, 25, 21, 1, 13, - 15, 3, 23, 27, 63, 51, 39, 43, 44, 32, 52, 56, 28, 16, 4, 8, - 0, 6, 12, 10, 24, 30, 20, 18, 48, 54, 60, 58, 40, 46, 36, 34, - 35, 37, 47, 41, 59, 61, 55, 49, 19, 21, 31, 25, 11, 13, 7, 1, - 5, 3, 9, 15, 29, 27, 17, 23, 53, 51, 57, 63, 45, 43, 33, 39, - 38, 32, 42, 44, 62, 56, 50, 52, 22, 16, 26, 28, 14, 8, 2, 4, - 0, 3, 6, 5, 12, 15, 10, 9, 24, 27, 30, 29, 20, 23, 18, 17, - 48, 51, 54, 53, 60, 63, 58, 57, 40, 43, 46, 45, 36, 39, 34, 33, - 35, 32, 37, 38, 47, 44, 41, 42, 59, 56, 61, 62, 55, 52, 49, 50, - 19, 16, 21, 22, 31, 28, 25, 26, 11, 8, 13, 14, 7, 4, 1, 2, - 0, 32, 3, 35, 6, 38, 5, 37, 12, 44, 15, 47, 10, 42, 9, 41, - 24, 56, 27, 59, 30, 62, 29, 61, 20, 52, 23, 55, 18, 50, 17, 49, - 48, 16, 51, 19, 54, 22, 53, 21, 60, 28, 63, 31, 58, 26, 57, 25, - 40, 8, 43, 11, 46, 14, 45, 13, 36, 4, 39, 7, 34, 2, 33, 1, - 0, 16, 32, 48, 3, 19, 35, 51, 6, 22, 38, 54, 5, 21, 37, 53, - 12, 28, 44, 60, 15, 31, 47, 63, 10, 26, 42, 58, 9, 25, 41, 57, - 24, 8, 56, 40, 27, 11, 59, 43, 30, 14, 62, 46, 29, 13, 61, 45, - 20, 4, 52, 36, 23, 7, 55, 39, 18, 2, 50, 34, 17, 1, 49, 33, - 0, 8, 16, 24, 32, 40, 48, 56, 3, 11, 19, 27, 35, 43, 51, 59, - 6, 14, 22, 30, 38, 46, 54, 62, 5, 13, 21, 29, 37, 45, 53, 61, - 12, 4, 28, 20, 44, 36, 60, 52, 15, 7, 31, 23, 47, 39, 63, 55, - 10, 2, 26, 18, 42, 34, 58, 50, 9, 1, 25, 17, 41, 33, 57, 49, - 0, 4, 8, 12, 16, 20, 24, 28, 32, 36, 40, 44, 48, 52, 56, 60, - 3, 7, 11, 15, 19, 23, 27, 31, 35, 39, 43, 47, 51, 55, 59, 63, - 6, 2, 14, 10, 22, 18, 30, 26, 38, 34, 46, 42, 54, 50, 62, 58, - 5, 1, 13, 9, 21, 17, 29, 25, 37, 33, 45, 41, 53, 49, 61, 57, - 0, 2, 4, 6, 8, 10, 12, 14, 16, 18, 20, 22, 24, 26, 28, 30, - 32, 34, 36, 38, 40, 42, 44, 46, 48, 50, 52, 54, 56, 58, 60, 62, - 3, 1, 7, 5, 11, 9, 15, 13, 19, 17, 23, 21, 27, 25, 31, 29, - 35, 33, 39, 37, 43, 41, 47, 45, 51, 49, 55, 53, 59, 57, 63, 61 -}; - -const qracode qra_13_64_64_irr_e = { - qra_K, - qra_N, - qra_m, - qra_M, - qra_a, - qra_NC, - qra_V, - qra_C, - qra_NMSG, - qra_MAXVDEG, - qra_MAXCDEG, - QRATYPE_CRCPUNCTURED, - qra_R, - CODE_NAME, - qra_acc_input_idx, - qra_acc_input_wlog, - qra_log, - qra_exp, - qra_msgw, - qra_vdeg, - qra_cdeg, - qra_v2cmidx, - qra_c2vmidx, - qra_pmat -}; - -#undef qra_K -#undef qra_N -#undef qra_m -#undef qra_M -#undef qra_a -#undef qra_NC -#undef qra_V -#undef qra_C -#undef qra_NMSG -#undef qra_MAXVDEG -#undef qra_MAXCDEG -#undef qra_R -#undef CODE_NAME \ No newline at end of file diff --git a/lib/qra/qracodes/qra13_64_64_irr_e.h b/lib/qra/qracodes/qra13_64_64_irr_e.h deleted file mode 100644 index d24421d..0000000 --- a/lib/qra/qracodes/qra13_64_64_irr_e.h +++ /dev/null @@ -1,39 +0,0 @@ -// qra13_64_64_irr_e.h -// Code tables and defines for Q-ary RA code (13,64) over GF(64) -// Code Name: qra13_64_64_irr_e -// (13,64) RA Code over GF(64) RF=[3x4 4x4 6x1 3x2 5x1 7x1]/18 - -// (c) 2016 - Nico Palermo - IV3NWV - Microtelecom Srl, Italy - -// This file is part of the qracodes project, a Forward Error Control -// encoding/decoding package based on Q-ary RA (Repeat and Accumulate) LDPC codes. -// -// qracodes is free software: you can redistribute it and/or modify -// it under the terms of the GNU General Public License as published by -// the Free Software Foundation, either version 3 of the License, or -// (at your option) any later version. -// qracodes is distributed in the hope that it will be useful, -// but WITHOUT ANY WARRANTY; without even the implied warranty of -// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -// GNU General Public License for more details. -// -// You should have received a copy of the GNU General Public License -// along with qracodes source distribution. -// If not, see . - -#ifndef _qra13_64_64_irr_e_h -#define _qra13_64_64_irr_e_h - -#include "qracodes.h" - -#ifdef __cplusplus -extern "C" { -#endif - -extern const qracode qra_13_64_64_irr_e; - -#ifdef __cplusplus -} -#endif - -#endif // _qra13_64_64_irr_e_h diff --git a/lib/qra/qracodes/qracodes.c b/lib/qra/qracodes/qracodes.c deleted file mode 100644 index 748a9c9..0000000 --- a/lib/qra/qracodes/qracodes.c +++ /dev/null @@ -1,474 +0,0 @@ -// qracodes.c -// Q-ary RA codes encoding/decoding functions -// -// (c) 2016 - Nico Palermo, IV3NWV - Microtelecom Srl, Italy -// ------------------------------------------------------------------------------ -// This file is part of the qracodes project, a Forward Error Control -// encoding/decoding package based on Q-ary RA (Repeat and Accumulate) LDPC codes. -// -// qracodes is free software: you can redistribute it and/or modify -// it under the terms of the GNU General Public License as published by -// the Free Software Foundation, either version 3 of the License, or -// (at your option) any later version. -// qracodes is distributed in the hope that it will be useful, -// but WITHOUT ANY WARRANTY; without even the implied warranty of -// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -// GNU General Public License for more details. - -// You should have received a copy of the GNU General Public License -// along with qracodes source distribution. -// If not, see . - -#include -#include - -#include "npfwht.h" -#include "pdmath.h" - -#include "qracodes.h" - -int qra_encode(const qracode *pcode, int *y, const int *x) -{ - int k,j,kk,jj; - int t, chk = 0; - - const int K = pcode->K; - const int M = pcode->M; - const int NC= pcode->NC; - const int a = pcode->a; - const int *acc_input_idx = pcode->acc_input_idx; - const int *acc_input_wlog = pcode->acc_input_wlog; - const int *gflog = pcode->gflog; - const int *gfexp = pcode->gfexp; - - // copy the systematic symbols to destination - memcpy(y,x,K*sizeof(int)); - - y = y+K; // point to check symbols - - // compute the code check symbols as a weighted accumulation of a permutated - // sequence of the (repeated) systematic input symbols: - // chk(k+1) = x(idx(k))*alfa^(logw(k)) + chk(k) - // (all operations performed over GF(M)) - - if (a==1) { // grouping factor = 1 - for (k=0;k 1 - for (k=0;k80.f) // avoid floating point exp() overflows - v=80.f; - - src[nitems] = (float)exp(v); - } -} - - -float qra_mfskbesselmetric(float *pix, const float *rsq, const int m, const int N, float EsNoMetric) -{ - // Computes the codeword symbols intrinsic probabilities - // given the square of the received input amplitudes. - - // The input vector rqs must be a linear array of size M*N, where M=2^m, - // containing the squared amplitudes (rp*rp+rq*rq) of the input samples - - // First symbol amplitudes should be stored in the first M positions, - // second symbol amplitudes stored at positions [M ... 2*M-1], and so on. - - // Output vector is the intrinsic symbol metric (the probability distribution) - // assuming that symbols are transmitted using a M-FSK modulation - // and incoherent demodulation. - - // As the input Es/No is generally unknown (as it cannot be exstimated accurately - // when the codeword length is few tens symbols) but an exact metric requires it - // we simply fix it to a predefined EsNoMetric value so that the metric is what - // expected at that specific value. - // The metric computed in this way is optimal only at this predefined Es/No value, - // nevertheless it is usually better than a generic parameter-free metric which - // makes no assumptions on the input Es/No. - - // returns the estimated noise standard deviation - - int k; - float rsum = 0.f; - float sigmaest, cmetric; - - const int M = 1<M; - const int qra_m = pcode->m; - const int qra_V = pcode->V; - const int qra_MAXVDEG = pcode->MAXVDEG; - const int *qra_vdeg = pcode->vdeg; - const int qra_C = pcode->C; - const int qra_MAXCDEG = pcode->MAXCDEG; - const int *qra_cdeg = pcode->cdeg; - const int *qra_v2cmidx = pcode->v2cmidx; - const int *qra_c2vmidx = pcode->c2vmidx; - const int *qra_pmat = pcode->gfpmat; - const int *qra_msgw = pcode->msgw; - -// float msgout[qra_M]; // buffer to store temporary results - float msgout[QRACODE_MAX_M]; // we use a fixed size in order to avoid mallocs - - float totex; // total extrinsic information - int nit; // current iteration - int nv; // current variable - int nc; // current check - int k,kk; // loop indexes - - int ndeg; // current node degree - int msgbase; // current offset in the table of msg indexes - int imsg; // current message index - int wmsg; // current message weight - - int rc = -1; // rc>=0 extrinsic converged to 1 at iteration rc (rc=0..maxiter-1) - // rc=-1 no convergence in the given number of iterations - // rc=-2 error in the code tables (code checks degrees must be >1) - // rc=-3 M is larger than QRACODE_MAX_M - - - - if (qra_M>QRACODE_MAX_M) - return -3; - - // message initialization ------------------------------------------------------- - - // init c->v variable intrinsic msgs - pd_init(C2VMSG(0),pix,qra_M*qra_V); - - // init the v->c messages directed to code factors (k=1..ndeg) with the intrinsic info - for (nv=0;nvc - for (k=1;kv step ----------------------------------------------------- - // Computes messages from code checks to code variables. - // As the first qra_V checks are associated with intrinsic information - // (the code tables have been constructed in this way) - // we need to do this step only for code checks in the range [qra_V..qra_C) - - // The convolutions of probability distributions over the alphabet of a finite field GF(qra_M) - // are performed with a fast convolution algorithm over the given field. - // - // I.e. given the code check x1+x2+x3 = 0 (with x1,x2,x3 in GF(2^m)) - // and given Prob(x2) and Prob(x3), we have that: - // Prob(x1=X1) = Prob((x2+x3)=X1) = sum((Prob(x2=X2)*Prob(x3=(X1+X2))) for all the X2s in the field - // This translates to Prob(x1) = IWHT(WHT(Prob(x2))*WHT(Prob(x3))) - // where WHT and IWHT are the direct and inverse Walsh-Hadamard transforms of the argument. - // Note that the WHT and the IWHF differs only by a multiplicative coefficent and since in this step - // we don't need that the output distribution is normalized we use the relationship - // Prob(x1) =(proportional to) WH(WH(Prob(x2))*WH(Prob(x3))) - - // In general given the check code x1+x2+x3+..+xm = 0 - // the output distribution of a variable given the distributions of the other m-1 variables - // is the inverse WHT of the product of the WHTs of the distribution of the other m-1 variables - // The complexity of this algorithm scales with M*log2(M) instead of the M^2 complexity of - // the brute force approach (M=size of the alphabet) - - for (nc=qra_V;nc1) - return -2; // bad code tables - - msgbase = nc*qra_MAXCDEG; // base to msg index row for the current node - - // transforms inputs in the Walsh-Hadamard "frequency" domain - // v->c -> fwht(v->c) - for (k=0;kv = prod(fwht(v->c)) - // TODO: we assume that checks degrees are not larger than three but - // if they are larger the products can be computed more efficiently - for (kk=0;kkc steps when multipling - // small fp numbers - msgout[0]+=1E-7f; // TODO: define the bias accordingly to the field size - - np_fwht(qra_m,msgout,msgout); - - // inverse weight and output - imsg = qra_c2vmidx[msgbase+k]; // current output msg index - wmsg = qra_msgw[imsg]; // current msg weight - - if (wmsg==0) - pd_init(C2VMSG(imsg),msgout,qra_M); - else - // output p(alfa^(-w)*x) - pd_bwdperm(C2VMSG(imsg),msgout, MSGPERM(wmsg), qra_M); - - } // for (k=0;kc step ----------------------------------------------------- - for (nv=0;nvc msg = prod(c->v) - // TODO: factor factors to reduce the number of computations for high degree nodes - for (kk=0;kkc are null - // normalize output to a probability distribution - if (pd_norm(msgout,qra_m)<=0) { - // dump msgin; - printf("warning: v->c pd with invalid norm. nit=%d nv=%d k=%d\n",nit,nv,k); - for (kk=0;kk(1.*(qra_V)-0.01)) { - // the total maximum extrinsic information of each symbol in the codeword - // is very close to one. This means that we have reached the (1,1) point in the - // code EXIT chart(s) and we have successfully decoded the input. - rc = nit; - break; // remove the break to evaluate the decoder speed performance as a function of the max iterations number) - } - - } // for (nit=0;nitM; - const int qra_m = pcode->m; - const int qra_K = pcode->K; - - int k; - - for (k=0;k. - -#ifndef _qracodes_h_ -#define _qracodes_h_ - -// type of codes -#define QRATYPE_NORMAL 0x00 // normal code -#define QRATYPE_CRC 0x01 // code with crc - last information symbol is a CRC -#define QRATYPE_CRCPUNCTURED 0x02 // the CRC symbol is punctured (not sent along the channel) - - -typedef struct { - // code parameters - const int K; // number of information symbols - const int N; // codeword length in symbols - const int m; // bits/symbol - const int M; // Symbol alphabet cardinality (2^m) - const int a; // code grouping factor - const int NC; // number of check symbols (N-K) - const int V; // number of variables in the code graph (N) - const int C; // number of factors in the code graph (N +(N-K)+1) - const int NMSG; // number of msgs in the code graph - const int MAXVDEG; // maximum variable degree - const int MAXCDEG; // maximum factor degree - const int type; // see QRATYPE_xx defines - const float R; // code rate (K/N) - const char name[64]; // code name - // tables used by the encoder - const int *acc_input_idx; - const int *acc_input_wlog; - const int *gflog; - const int *gfexp; - // tables used by the decoder ------------------------- - const int *msgw; - const int *vdeg; - const int *cdeg; - const int *v2cmidx; - const int *c2vmidx; - const int *gfpmat; -} qracode; -// Uncomment the header file of the code which needs to be tested - -//#include "qra12_63_64_irr_b.h" // irregular code (12,63) over GF(64) -//#include "qra13_64_64_irr_e.h" // irregular code with good performance and best UER protection at AP56 -//#include "qra13_64_64_reg_a.h" // regular code with good UER but perf. inferior to that of code qra12_63_64_irr_b - -#ifdef __cplusplus -extern "C" { -#endif - -int qra_encode(const qracode *pcode, int *y, const int *x); -float qra_mfskbesselmetric(float *pix, const float *rsq, const int m, const int N, float EsNoMetric); -int qra_extrinsic(const qracode *pcode, float *pex, const float *pix, int maxiter,float *qra_v2cmsg,float *qra_c2vmsg); -void qra_mapdecode(const qracode *pcode, int *xdec, float *pex, const float *pix); - -#ifdef __cplusplus -} -#endif - -#endif // _qracodes_h_ diff --git a/lib/qso50/g0 b/lib/qso50/g0 deleted file mode 100644 index 02e2aeb..0000000 --- a/lib/qso50/g0 +++ /dev/null @@ -1,8 +0,0 @@ -gfortran -o twq -Wall -Wno-conversion -fbounds-check twq.f90 \ - ../packjt.f90 wqenc.f90 wqdec.f90 packprop.f90 \ - packname.f90 packtext2.f90 unpackprop.f90 unpackname.f90 \ - unpacktext2.f90 unpackpfx.f90 pack50.f90 unpack50.f90 \ - ../hash.f90 ../deg2grid.f90 ../grid2deg.f90 \ - ../fix_contest_msg.f90 ../to_contest_msg.f90 \ - ../fmtmsg.f90 ../azdist.f90 ../geodist.f90 ../wsprd/nhash.c - \ No newline at end of file diff --git a/lib/qso50/pack50.f90 b/lib/qso50/pack50.f90 deleted file mode 100644 index 12c230c..0000000 --- a/lib/qso50/pack50.f90 +++ /dev/null @@ -1,26 +0,0 @@ -subroutine pack50(n1,n2,dat) - - integer*1 dat(11),i1 - - i1=iand(ishft(n1,-20),255) !8 bits - dat(1)=i1 - i1=iand(ishft(n1,-12),255) !8 bits - dat(2)=i1 - i1=iand(ishft(n1, -4),255) !8 bits - dat(3)=i1 - i1=16*iand(n1,15)+iand(ishft(n2,-18),15) !4+4 bits - dat(4)=i1 - i1=iand(ishft(n2,-10),255) !8 bits - dat(5)=i1 - i1=iand(ishft(n2, -2),255) !8 bits - dat(6)=i1 - i1=64*iand(n2,3) !2 bits - dat(7)=i1 - dat(8)=0 - dat(9)=0 - dat(10)=0 - dat(11)=0 - - return -end subroutine pack50 - diff --git a/lib/qso50/packname.f90 b/lib/qso50/packname.f90 deleted file mode 100644 index 5b3936e..0000000 --- a/lib/qso50/packname.f90 +++ /dev/null @@ -1,23 +0,0 @@ -subroutine packname(name,len,n1,n2) - - character*9 name - real*8 dn - - dn=0 - do i=1,len - n=ichar(name(i:i)) - if(n.ge.97 .and. n.le.122) n=n-32 - dn=27*dn + n-64 - enddo - if(len.lt.9) then - do i=len+1,9 - dn=27*dn - enddo - endif - - n2=mod(dn,32768.d0) - dn=dn/32768.d0 - n1=dn - - return -end subroutine packname diff --git a/lib/qso50/packprop.f90 b/lib/qso50/packprop.f90 deleted file mode 100644 index 5d22a37..0000000 --- a/lib/qso50/packprop.f90 +++ /dev/null @@ -1,36 +0,0 @@ -subroutine packprop(k,muf,ccur,cxp,n1) - -! Pack propagation indicators into a 21-bit number. - -! k k-index, 0-9; 10="N/A" -! muf muf, 2-60 MHz; 0=N/A, 1="none", 61=">60 MHz" -! ccur up to two current events, each indicated by single -! or double letter. -! cxp zero or one expected event, indicated by single or -! double letter - - character ccur*4,cxp*2 - - j=ichar(ccur(1:1))-64 - if(j.lt.0) j=0 - n1=j - do i=2,4 - if(ccur(i:i).eq.' ') go to 10 - if(ccur(i:i).eq.ccur(i-1:i-1)) then - n1=n1+26 - else - j=ichar(ccur(i:i))-64 - if(j.lt.0) j=0 - n1=53*n1 + j - endif - enddo - -10 j=ichar(cxp(1:1))-64 - if(j.lt.0) j=0 - if(cxp(2:2).eq.cxp(1:1)) j=j+26 - n1=53*n1 + j - n1=11*n1 + k - n1=62*n1 + muf - - return -end subroutine packprop diff --git a/lib/qso50/packtext2.f90 b/lib/qso50/packtext2.f90 deleted file mode 100644 index d54b52f..0000000 --- a/lib/qso50/packtext2.f90 +++ /dev/null @@ -1,22 +0,0 @@ -subroutine packtext2(msg,n1,ng) - - character*8 msg - real*8 dn - character*41 c - data c/'0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZ +./?'/ - - dn=0. - do i=1,8 - do j=1,41 - if(msg(i:i).eq.c(j:j)) go to 10 - enddo - j=37 -10 j=j-1 !Codes should start at zero - dn=41.d0*dn + j - enddo - - ng=mod(dn,32768.d0) - n1=(dn-ng)/32768.d0 - - return -end subroutine packtext2 diff --git a/lib/qso50/twq.f90 b/lib/qso50/twq.f90 deleted file mode 100644 index 9fdb263..0000000 --- a/lib/qso50/twq.f90 +++ /dev/null @@ -1,18 +0,0 @@ -program twq - - character*22 msg0,msg - integer*1 data0(11) - - open(10,file='wqmsg.txt',status='old') - write(*,1000) -1000 format(4x,'Encoded message',9x,'Decoded as',12x,'itype'/55('-')) - - do line=1,9999 - read(10,*,end=999) msg0 - call wqenc(msg0,itype,data0) - call wqdec(data0,msg,ntype) - write(*,1100) line,msg0,msg,ntype -1100 format(i2,'.',1x,a22,2x,a22,i3) - enddo - -999 end program twq diff --git a/lib/qso50/unpack50.f90 b/lib/qso50/unpack50.f90 deleted file mode 100644 index 101f1ab..0000000 --- a/lib/qso50/unpack50.f90 +++ /dev/null @@ -1,30 +0,0 @@ -subroutine unpack50(dat,n1,n2) - - integer*1 dat(11) - - i=dat(1) - i4=iand(i,255) - n1=ishft(i4,20) - i=dat(2) - i4=iand(i,255) - n1=n1 + ishft(i4,12) - i=dat(3) - i4=iand(i,255) - n1=n1 + ishft(i4,4) - i=dat(4) - i4=iand(i,255) - n1=n1 + iand(ishft(i4,-4),15) - n2=ishft(iand(i4,15),18) - i=dat(5) - i4=iand(i,255) - n2=n2 + ishft(i4,10) - i=dat(6) - i4=iand(i,255) - n2=n2 + ishft(i4,2) - i=dat(7) - i4=iand(i,255) - n2=n2 + iand(ishft(i4,-6),3) - - return -end subroutine unpack50 - diff --git a/lib/qso50/unpackname.f90 b/lib/qso50/unpackname.f90 deleted file mode 100644 index 3ae7c5c..0000000 --- a/lib/qso50/unpackname.f90 +++ /dev/null @@ -1,20 +0,0 @@ -subroutine unpackname(n1,n2,name,len) - - character*9 name - real*8 dn - - dn=32768.d0*n1 + n2 - len=0 - do i=9,1,-1 - j=mod(dn,27.d0) - if(j.ge.1) then - name(i:i)=char(64+j) - len=len+1 - else - name(i:i)=' ' - endif - dn=dn/27.d0 - enddo - - return -end subroutine unpackname diff --git a/lib/qso50/unpackpfx.f90 b/lib/qso50/unpackpfx.f90 deleted file mode 100644 index 4234e9e..0000000 --- a/lib/qso50/unpackpfx.f90 +++ /dev/null @@ -1,35 +0,0 @@ -subroutine unpackpfx(ng,call1) - - character*12 call1 - character*3 pfx - - if(ng.lt.60000) then -! Add-on prefix of 1 to 3 characters - n=ng - do i=3,1,-1 - nc=mod(n,37) - if(nc.ge.0 .and. nc.le.9) then - pfx(i:i)=char(nc+48) - else if(nc.ge.10 .and. nc.le.35) then - pfx(i:i)=char(nc+55) - else - pfx(i:i)=' ' - endif - n=n/37 - enddo - call1=pfx//'/'//call1 - if(call1(1:1).eq.' ') call1=call1(2:) - if(call1(1:1).eq.' ') call1=call1(2:) - else -! Add-on suffix, one character - i1=index(call1,' ') - nc=ng-60000 - if(nc.ge.0 .and. nc.le.9) then - call1=call1(:i1-1)//'/'//char(nc+48) - else if(nc.ge.10 .and. nc.le.35) then - call1=call1(:i1-1)//'/'//char(nc+55) - endif - endif - - return -end subroutine unpackpfx diff --git a/lib/qso50/unpackprop.f90 b/lib/qso50/unpackprop.f90 deleted file mode 100644 index 18cc1f5..0000000 --- a/lib/qso50/unpackprop.f90 +++ /dev/null @@ -1,28 +0,0 @@ -subroutine unpackprop(n1,k,muf,ccur,cxp) - - character ccur*4,cxp*2 - - muf=mod(n1,62) - n1=n1/62 - - k=mod(n1,11) - n1=n1/11 - - j=mod(n1,53) - n1=n1/53 - if(j.eq.0) cxp='*' - if(j.ge.1 .and. j.le.26) cxp=char(64+j) - if(j.gt.26) cxp=char(64+j-26)//char(64+j-26) - - j=mod(n1,53) - n1=n1/53 - if(j.eq.0) ccur(2:2)='*' - if(j.ge.1 .and. j.le.26) ccur(2:2)=char(64+j) - if(j.gt.26) ccur(2:3)=char(64+j-26)//char(64+j-26) - j=n1 - if(j.eq.0) ccur(1:1)='*' - if(j.ge.1 .and. j.le.26) ccur(1:1)=char(64+j) - if(j.gt.26) ccur=char(64+j-26)//char(64+j-26)//ccur(2:3) - - return -end subroutine unpackprop diff --git a/lib/qso50/unpacktext2.f90 b/lib/qso50/unpacktext2.f90 deleted file mode 100644 index 92dccce..0000000 --- a/lib/qso50/unpacktext2.f90 +++ /dev/null @@ -1,17 +0,0 @@ -subroutine unpacktext2(n1,ng,msg) - - character*22 msg - real*8 dn - character*41 c - data c/'0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZ +./?'/ - - msg=' ' - dn=32768.d0*n1 + ng - do i=8,1,-1 - j=mod(dn,41.d0) - msg(i:i)=c(j+1:j+1) - dn=dn/41.d0 - enddo - - return -end subroutine unpacktext2 diff --git a/lib/qso50/wqdec.f90 b/lib/qso50/wqdec.f90 deleted file mode 100644 index 791c78c..0000000 --- a/lib/qso50/wqdec.f90 +++ /dev/null @@ -1,316 +0,0 @@ -subroutine wqdec(data0,message,ntype) - - use packjt - parameter (N15=32758) - integer*1 data0(11) - character*22 message - character*12 callsign - character*3 cdbm,cf - character*2 crpt - character*4 grid,psfx - character*9 name - character*36 fmt - character*6 cwx(4) - character*7 cwind(5) - character ccur*4,cxp*2 - logical first - character*12 dcall(0:N15-1) - data first/.true./ - data cwx/'CLEAR','CLOUDY','RAIN','SNOW'/ - data cwind/'CALM','BREEZES','WINDY','DRY','HUMID'/ - save first,dcall - - if(first) then - dcall=' ' - first=.false. - endif - - message=' ' - call unpack50(data0,n1,n2) - call unpackcall(n1,callsign,iv2,psfx) - i1=index(callsign,' ') - call unpackgrid(n2/128,grid) - ntype=iand(n2,127) -64 - -! Standard WSPR message (types 0 3 7 10 13 17 ... 60) - nu=mod(ntype,10) - if(ntype.ge.0 .and. ntype.le.60 .and. (nu.eq.0 .or. nu.eq.3 .or. & - nu.eq.7)) then - write(cdbm,'(i3)'),ntype - if(cdbm(1:1).eq.' ') cdbm=cdbm(2:) - if(cdbm(1:1).eq.' ') cdbm=cdbm(2:) - message=callsign(1:i1)//grid//' '//cdbm - call hash(callsign,i1-1,ih) - dcall(ih)=callsign(:i1) - -! "Best DX" WSPR response (type 1) - else if(ntype.eq.1) then - message=grid//' DE '//callsign - -! CQ (msg 3; types 2,4,5) - else if(ntype.eq.2) then - message='CQ '//callsign(:i1)//grid - call hash(callsign,i1-1,ih) - dcall(ih)=callsign(:i1) - else if(ntype.eq.4 .or. ntype.eq.5) then - ng=n2/128 + 32768*(ntype-4) - call unpackpfx(ng,callsign) - message='CQ '//callsign - call hash(callsign,i1-1,ih) - dcall(ih)=callsign(:i1) - -! Reply to CQ (msg #2; type 6) - else if(ntype.eq.6) then - ih=(n2-64-ntype)/128 - if(dcall(ih)(1:1).ne.' ') then - i2=index(dcall(ih),' ') - message='<'//dcall(ih)(:i2-1)//'> '//callsign(:i1-1) - else - message='<...> '//callsign - endif - call hash(callsign,i1-1,ih) - dcall(ih)=callsign(:i1-1) - -! Reply to CQ (msg #2; type 8) - else if(ntype.eq.8) then - message='DE '//callsign(:i1)//grid - call hash(callsign,i1-1,ih) - dcall(ih)=callsign(:i1-1) - -! Reply to CQ, DE pfx/call (msg #2; types 9, 11) - else if(ntype.eq.9 .or. ntype.eq.11) then - ng=n2/128 + 32768*(ntype-9)/2 - call unpackpfx(ng,callsign) - message='DE '//callsign - call hash(callsign,i1-1,ih) - dcall(ih)=callsign(:i1-1) - -! Calls and report (msg #3; types -1 to -9) - else if(ntype.le.-1 .and. ntype.ge.-9) then - write(crpt,1010) -ntype -1010 format('S',i1) - ih=(n2-62-ntype)/128 - if(dcall(ih)(1:1).ne.' ') then - i2=index(dcall(ih),' ') - message=callsign(:i1)//'<'//dcall(ih)(:i2-1)//'> '//crpt - else - message=callsign(:i1)//'<...> '//crpt - endif - call hash(callsign,i1-1,ih) - dcall(ih)=callsign(:i1-1) - -! pfx/call and report (msg #3; types -10 to -27) - else if(ntype.le.-10 .and. ntype.ge.-27) then - ng=n2/128 - nrpt=-ntype-9 - if(ntype.le.-19) then - ng=ng + 32768 - nrpt=-ntype-18 - endif - write(crpt,1010) nrpt - call unpackpfx(ng,callsign) - message=callsign//' '//crpt - call hash(callsign,i1-1,ih) - dcall(ih)=callsign(:i1-1) - -! Calls and R and report (msg #4; types -28 to -36) - else if(ntype.le.-28 .and. ntype.ge.-36) then - write(crpt,1010) -(ntype+27) - ih=(n2-64+28-ntype)/128 - if(dcall(ih)(1:1).ne.' ') then - i2=index(dcall(ih),' ') - message=callsign(:i1)//'<'//dcall(ih)(:i2-1)//'> '//'R '//crpt - else - message=callsign(:i1)//'<...> '//'R '//crpt - endif - call hash(callsign,i1-1,ih) - dcall(ih)=callsign(:i1-1) - -! pfx/call R and report (msg #4; types -37 to -54) - else if(ntype.le.-37 .and. ntype.ge.-54) then - ng=n2/128 - nrpt=-ntype-36 - if(ntype.le.-46) then - ng=ng + 32768 - nrpt=-ntype-45 - endif - write(crpt,1010) nrpt - call unpackpfx(ng,callsign) - message=callsign//' R '//crpt - call hash(callsign,i1-1,ih) - dcall(ih)=callsign(:i1-1) - -! Calls and RRR (msg#5; type 12) - else if(ntype.eq.12) then - ih=(n2-64+28-ntype)/128 - if(dcall(ih)(1:1).ne.' ') then - i2=index(dcall(ih),' ') - message=callsign(:i1)//'<'//dcall(ih)(:i2-1)//'> RRR' - else - message=callsign(:i1)//'<...> RRR' - endif - call hash(callsign,i1-1,ih) - dcall(ih)=callsign(:i1-1) - -! Calls and RRR (msg#5; type 14) - else if(ntype.eq.14) then - ih=(n2-64+28-ntype)/128 - if(dcall(ih)(1:1).ne.' ') then - i2=index(dcall(ih),' ') - message='<'//dcall(ih)(:i2-1)//'> '//callsign(:i1)//'RRR' - else - message='<...> '//callsign(:i1)//' RRR' - endif - call hash(callsign,i1-1,ih) - dcall(ih)=callsign(:i1-1) - -! DE pfx/call and RRR (msg#5; types 15, 16) - else if(ntype.eq.15 .or. ntype.eq.16) then - ng=n2/128 + 32768*(ntype-15) - call unpackpfx(ng,callsign) - message='DE '//callsign//' RRR' - call hash(callsign,i1-1,ih) - dcall(ih)=callsign(:i1-1) - -! TNX [name] 73 GL (msg #6; type 18) - else if(ntype.eq.18) then - ng=(n2-18-64)/128 - call unpackname(n1,ng,name,len) - message='TNX '//name(:len)//' 73 GL' - -! OP [name] 73 GL (msg #6; type 18) - else if(ntype.eq.-56) then - ng=(n2+56-64)/128 - call unpackname(n1,ng,name,len) - message='OP '//name(:len)//' 73 GL' - -! 73 DE [call] [grid] (msg #6; type 19) - else if(ntype.eq.19) then - ng=(n2-19-64)/128 - message='73 DE '//callsign(:i1)//grid - call hash(callsign,i1-1,ih) - dcall(ih)=callsign(:i1-1) - -! 73 DE pfx/call (msg #6; type 21, 22) - else if(ntype.eq.21 .or. ntype.eq.22) then - ng=n2/128 + (ntype-21)*32768 - call unpackpfx(ng,callsign) - i1=index(callsign,' ') - message='73 DE '//callsign - call hash(callsign,i1-1,ih) - dcall(ih)=callsign(:i1-1) - -! [power] W [gain] DBD 73 GL (msg#6; type 24, 25) - else if(ntype.eq.24 .or. ntype.eq.25) then - ng=(n2-24-64)/128 - 32 - i1=1 - if(n1.gt.0) i1=log10(float(n1)) + 1 - i2=1 - if(ng.ge.10) i2=2 - if(ng.lt.0) i2=i2+1 - if(n1.le.3000) then - if(ntype.eq.24) fmt="(i4,' W ',i2,' DBD 73 GL')" - if(ntype.eq.25) fmt="(i4,' W ',i2,' DBD ')" - fmt(3:3)=char(48+i1) - fmt(12:12)=char(48+i2) - if(ng.le.100) then - write(message,fmt) n1,ng - else - if(ng.eq.30000) fmt=fmt(1:8)//"DIPOLE')" - if(ng.eq.30001) fmt=fmt(1:8)//"VERTICAL')" - write(message,fmt) n1 - endif - else - mw=n1-3000 - if(ntype.eq.24) fmt="('0.',i3.3,' W ',i2,' DBD 73 GL')" - if(ntype.eq.25) fmt="('0.',i3.3,' W ',i2,' DBD ')" - fmt(19:19)=char(48+i2) - if(ng.le.100) then - write(message,fmt) mw,ng - else - if(ng.eq.30000) fmt=fmt(1:15)//"DIPOLE')" - if(ng.eq.30001) fmt=fmt(1:15)//"VERTICAL')" - write(message,fmt) n1 - endif - if(index(message,'***').gt.0) go to 700 - endif - -! QRZ call (msg #3; type 26) - else if(ntype.eq.26) then - ng=(n2-24-64)/128 - 32 - message='QRZ '//callsign - -! PSE QSY [nnn] KHZ (msg #6; type 28) - else if(ntype.eq.28) then - if(n1.gt.0) i1=log10(float(n1)) + 1 - fmt="('PSE QSY ',i2,' KHZ')" - fmt(14:14)=char(48+i1) - write(message,fmt) n1 - -! WX wx temp C/F wind (msg #6; type 29) - else if(ntype.eq.29) then - nwx=n1/10000 - ntemp=mod(n1,10000) - 100 - cf=' F ' - if(ntemp.gt.800) then - ntemp=ntemp-1000 - cf=' C ' - endif - n2a=n2/128 - if(nwx.ge.1 .and. nwx.le.4 .and. n2a.ge.1 .and. n2a.le.5) then - write(message,1020) cwx(nwx),ntemp,cf,cwind(n2/128) -1020 format('WX ',a6,i3,a3,a7) - else - message='WX'//' (BadMsg)' - endif - -! Hexadecimal data (type 62) - else if(ntype.eq.62) then - ng=n2/128 - write(message,'(z4.4,z7.7)') ng,n1 - -! Solar/geomagnetic/ionospheric data (type 63) - else if(ntype.eq.63) then - ih=(n2-64-ntype)/128 - if(dcall(ih)(1:1).ne.' ') then - i2=index(dcall(ih),' ') - message='<'//dcall(ih)(:i2-1)//'> ' - else - message='<...> ' - endif - call unpackprop(n1,k,muf,ccur,cxp) - i2=index(message,'>') - write(message(i2+1:),'(i3,i3)') k,muf - message=message(:i2+7)//ccur//' '//cxp - -! [plain text] (msg #6; type -57) - else if(ntype.eq.-57) then - ng=n2/128 - call unpacktext2(n1,ng,message) - else - go to 700 - endif - go to 750 - -! message='' -700 i1=index(callsign,' ') - if(i1.lt.1) i1=12 - message=callsign(:i1)//' (BadMsg)' - -750 do i=1,22 - if(ichar(message(i:i)).eq.0) message(i:i)=' ' - enddo - - do i=22,1,-1 - if(message(i:i).ne.' ') go to 800 - enddo -800 i2=i - do n=1,20 - i1=index(message(:i2),' ') - if(i1.le.0) go to 900 - message=message(1:i1)//message(i1+2:) - i2=i2-1 - enddo - -900 return -end subroutine wqdec diff --git a/lib/qso50/wqenc.f90 b/lib/qso50/wqenc.f90 deleted file mode 100644 index 0f61292..0000000 --- a/lib/qso50/wqenc.f90 +++ /dev/null @@ -1,346 +0,0 @@ -subroutine wqenc(msg,ntype,data0) - -! Parse and encode a WSPR message. - - use packjt - parameter (MASK15=32767) - character*22 msg - character*12 call1,call2 - character*4 grid - character*9 name - character ccur*4,cxp*2 - logical lbad1,lbad2 - integer*1 data0(11) - integer nu(0:9) - data nu/0,-1,1,0,-1,2,1,0,-1,1/ - - read(msg,1001,end=1,err=1) ng,n1 -1001 format(z4,z7) - ntype=62 - n2=128*ng + (ntype+64) - call pack50(n1,n2,data0) !Pack 8 bits per byte, add tail - go to 900 - -1 if(msg(1:6).eq.'73 DE ') go to 80 - if(index(msg,' W ').gt.0 .and. index(msg,' DBD ').gt.0) go to 90 - if(msg(1:4).eq.'QRZ ') go to 100 - if(msg(1:8).eq.'PSE QSY ') go to 110 - if(msg(1:3).eq.'WX ') go to 120 - -! Standard WSPR message (types 0 3 7 10 13 17 ... 60) - i1=index(msg,' ') - if(i1.lt.4 .or. i1.gt.7) go to 10 - call1=msg(:i1-1) - grid=msg(i1+1:i1+4) - call packcall(call1,n1,lbad1) - call packgrid(grid,ng,lbad2) - if(lbad1 .or. lbad2) go to 10 - ndbm=0 - read(msg(i1+5:),*,err=10,end=800) ndbm - if(ndbm.lt.0 .or. ndbm.gt.60) go to 800 - ndbm=ndbm+nu(mod(ndbm,10)) - n2=128*ng + (ndbm+64) - call pack50(n1,n2,data0) - ntype=ndbm - go to 900 - -! "BestDX" automated WSPR reply (type 1) -10 if(i1.ne.5 .or. msg(5:8).ne.' DE ') go to 20 - grid=msg(1:4) - call packgrid(grid,ng,lbad2) - if(lbad2) go to 800 - call1=msg(9:) - call packcall(call1,n1,lbad1) - if(lbad1) go to 800 - ntype=1 - n2=128*ng + (ntype+64) - call pack50(n1,n2,data0) !Pack 8 bits per byte, add tail - go to 900 - -! CQ (msg #1; types 2, 4, 5) -20 if(msg(1:3).ne.'CQ ') go to 30 - if(index(msg,'/').le.0) then - i2=index(msg(4:),' ') - call1=msg(4:i2+3) - grid=msg(i2+4:) - call packcall(call1,n1,lbad1) - if(lbad1) go to 30 - call packgrid(grid,ng,lbad2) - if(lbad2) go to 30 - ntype=2 - n2=128*ng + (ntype+64) - call pack50(n1,n2,data0) - else - ntype=4 ! or 5 - call1=msg(4:) - call packpfx(call1,n1,ng,nadd) - ntype=ntype+nadd - n2=128*ng + ntype + 64 - call pack50(n1,n2,data0) - endif - go to 900 - -! Reply to CQ (msg #2; types 6,8,9,11) -30 if(msg(1:1).ne.'<' .and. msg(1:3).ne.'DE ') go to 40 - if(index(msg,' RRR ').gt.0) go to 50 - if(msg(1:1).eq.'<') then - ntype=6 - i1=index(msg,'>') - call1=msg(2:i1-1) - read(msg(i1+1:),*,err=31,end=31) k,muf,ccur,cxp - go to 130 -31 call2=msg(i1+2:) - call hash(call1,i1-2,ih) - call packcall(call2,n1,lbad1) - n2=128*ih + (ntype+64) - call pack50(n1,n2,data0) - else - i1=index(msg(4:),' ') - call1=msg(4:i1+2) - if(index(msg,'/').le.0) then - ntype=8 - ih=0 - call packcall(call1,n1,lbad1) - grid=msg(i1+4:i1+7) - call packgrid(grid,ng,lbad2) - n2=128*ng + (ntype+64) - call pack50(n1,n2,data0) - else - ntype=9 ! or 11 - call1=msg(4:) - call packpfx(call1,n1,ng,nadd) - ntype=ntype + 2*nadd - n2=128*ng + ntype + 64 - call pack50(n1,n2,data0) - endif - endif - go to 900 - -! Call(s) + report (msg #3; types -1 to -27) -! Call(s) + R + report (msg #4; types -28 to -54) -40 if(index(msg,' RRR').gt.0) go to 50 - i1=index(msg,'<') - if(i1.gt.0 .and. (i1.lt.5 .or. i1.gt.8)) go to 50 - i2=index(msg,'/') - if(i2.gt.0 .and.i2.le.4) then - ntype=-10 ! -10 to -27 - i0=index(msg,' ') - call1=msg(:i0-1) - call packpfx(call1,n1,ng,nadd) - ntype=ntype - 9*nadd - i2=index(msg,' ') - i3=index(msg,' R ') - if(i3.gt.0) i2=i2+2 !-28 to -36 - read(msg(i2+2:i2+2),*,end=800,err=800) nrpt - ntype=ntype - (nrpt-1) - if(i3.gt.0) ntype=ntype-27 - n2=128*ng + ntype + 64 - call pack50(n1,n2,data0) - go to 900 - else if(i1.eq.0) then - go to 50 - endif - call1=msg(:i1-2) !-1 to -9 - i2=index(msg,'>') - call2=msg(i1+1:i2-1) - call hash(call2,i2-i1-1,ih) - i3=index(msg,' R ') - if(i3.gt.0) i2=i2+2 !-28 to -36 - read(msg(i2+3:i2+3),*,end=42,err=42) nrpt - go to 43 -42 nrpt=1 -43 ntype=-nrpt - if(i3.gt.0) ntype=-(nrpt+27) - call packcall(call1,n1,lbad1) - n2=128*ih + (ntype+64) - call pack50(n1,n2,data0) - go to 900 - -50 i0=index(msg,'<') - if(i0.le.0 .and. msg(1:3).ne.'DE ') go to 60 - i3=index(msg,' RRR') - if(i3.le.0) go to 60 -! Call or calls and RRR (msg#5; type2 12,14,15,16) - i0=index(msg,'<') - if(i0.eq.1) then - if(index(msg,'/').le.0) then - ntype=14 - i1=index(msg,'>') - call1=msg(2:i1-1) - call2=msg(i1+2:) - i2=index(call2,' ') - call2=call2(:i2-1) - call packcall(call2,n1,lbad1) - call hash(call1,i1-2,ih) - n2=128*ih + (ntype+64) - call pack50(n1,n2,data0) - else - stop '0002' - endif - else if(i0.ge.5 .and. i0.le.8) then - if(index(msg,'/').le.0) then - ntype=12 - i1=index(msg,'>') - call1=msg(:i0-2) - call2=msg(i0+1:i1-1) - call packcall(call1,n1,lbad1) - call hash(call2,i1-i0-1,ih) - n2=128*ih + (ntype+64) - call pack50(n1,n2,data0) - else - stop '0002' - endif - else - i1=index(msg(4:),' ') - call1=msg(4:i1+2) - if(index(msg,'/').le.0) then - ntype=9 - grid=msg(i1+4:i1+7) - else - ntype=15 ! or 16 - call1=msg(4:) - i0=index(call1,' ') - call1=call1(:i0-1) - call packpfx(call1,n1,ng,nadd) - ntype=ntype+nadd - n2=128*ng + ntype + 64 - call pack50(n1,n2,data0) - endif - endif - go to 900 - -! TNX 73 GL (msg #6; type 18 ...) -60 if(msg(1:4).ne.'TNX ') go to 70 - ntype=18 - n1=0 - i2=index(msg(5:),' ') - name=msg(5:i2+4) - call packname(name,i2-1,n1,ng) - n2=128*ng + (ntype+64) - call pack50(n1,n2,data0) - go to 900 - -! TNX name 73 GL (msg #6; type -56 ...) -70 if(msg(1:3).ne.'OP ') go to 80 - ntype=-56 - n1=0 - i2=index(msg(4:),' ') - name=msg(4:i2+3) - call packname(name,i2-1,n1,ng) - n2=128*ng + (ntype+64) - call pack50(n1,n2,data0) - go to 900 - -! 73 DE call grid (msg #6; type 19) -80 if(msg(1:6).ne.'73 DE ') go to 90 - ntype=19 - i1=index(msg(7:),' ') - call1=msg(7:) - if(index(call1,'/').le.0) then - i1=index(call1,' ') - grid=call1(i1+1:) - call1=call1(:i1-1) - call packcall(call1,n1,lbad1) - call packgrid(grid,ng,lbad2) - if(lbad1 .or. lbad2) go to 800 - n2=128*ng + (ntype+64) - call pack50(n1,n2,data0) - go to 900 - else - ntype=21 ! or 22 - call packpfx(call1,n1,ng,nadd) - ntype=ntype + nadd - n2=128*ng + ntype + 64 - call pack50(n1,n2,data0) - go to 900 - endif - -! [pwr] W [gain] DBD [73 GL] (msg #6; types 24, 25) -90 if(index(msg,' W ').le.0) go to 140 - ntype=25 - if(index(msg,' DBD 73 GL').gt.0) ntype=24 - i1=index(msg,' ') - read(msg(:i1-1),*,end=800,err=800) watts - if(watts.ge.1.0) nwatts=watts - if(watts.lt.1.0) nwatts=3000 + nint(1000.*watts) - if(index(msg,'DIPOLE').gt.0) then - ndbd=30000 - else if(index(msg,'VERTICAL').gt.0) then - ndbd=30001 - else - i2=index(msg(i1+3:),' ') - read(msg(i1+3:i1+i2+1),*,end=800,err=800) ndbd - endif - n1=nwatts - ng=ndbd + 32 - n2=128*ng + (ntype+64) - call pack50(n1,n2,data0) - go to 900 - -! QRZ call (msg #3; type 26) -100 call1=msg(5:) - call packcall(call1,n1,lbad1) - if(lbad1) go to 800 - ntype=26 - n2=ntype+64 - call pack50(n1,n2,data0) - go to 900 - -! PSE QSY [nnn] KHZ (msg #6; type 28) -110 ntype=28 - read(msg(9:),*,end=800,err=800) n1 - n2=ntype+64 - call pack50(n1,n2,data0) - go to 900 - -! WX wx temp C|F wind (msg #6; type 29) -120 ntype=29 - if(index(msg,' CLEAR ').gt.0) then - i1=10 - n1=10000 - else if(index(msg,' CLOUDY ').gt.0) then - i1=11 - n1=20000 - else if(index(msg,' RAIN ').gt.0) then - i1=9 - n1=30000 - else if(index(msg,' SNOW ').gt.0) then - i1=9 - n1=40000 - endif - read(msg(i1:),*,err=800,end=800) ntemp - ntemp=ntemp+100 - i1=index(msg,' C ') - if(i1.gt.0) ntemp=ntemp+1000 - n1=n1+ntemp - if(index(msg,' CALM').gt.0) ng=1 - if(index(msg,' BREEZES').gt.0) ng=2 - if(index(msg,' WINDY').gt.0) ng=3 - if(index(msg,' DRY').gt.0) ng=4 - if(index(msg,' HUMID').gt.0) ng=5 - - n2=128*ng + (ntype+64) - call pack50(n1,n2,data0) - - go to 900 - -! Solar/geomagnetic/ionospheric data -130 ntype=63 - call packprop(k,muf,ccur,cxp,n1) - call hash(call1,i1-2,ih) - n2=128*ih + ntype + 64 - call pack50(n1,n2,data0) - go to 900 - -140 continue - -! Plain text -800 ntype=-57 - call packtext2(msg(:8),n1,ng) - n2=128*ng + ntype + 64 - call pack50(n1,n2,data0) - go to 900 - -900 continue - return -end subroutine wqenc diff --git a/lib/qso50/wqmsg.txt b/lib/qso50/wqmsg.txt deleted file mode 100644 index 9f509b3..0000000 --- a/lib/qso50/wqmsg.txt +++ /dev/null @@ -1,31 +0,0 @@ -"CQ K1JT FN20" -"CQ PJ4/K1JT" -" W6CQZ" -"DE W6CQZ CM87" -"DE PJ4/K1JT" -"W6CQZ S4" -"QRZ K1JT" -"PJ4/W6CQZ S4" -"K1JT R S3" -"PJ4/K1JT R S3" -" K1JT RRR" -"W6CQZ RRR" -"DE PJ4/K1JT RRR" -"73 DE W6CQZ CM87" -"73 DE PJ4/K1JT" -"TNX VICTORIA 73 GL" -"OP HARRY 73 GL" -"5 W DIPOLE" -"10 W VERTICAL" -"1 W 0 DBD" -"1500 W 21 DBD 73 GL" -"PSE QSY 1811 KHZ" -"WX SNOW -5 C CALM" -"CUL JACK" -"." -"CQ K1JT FN20" -" W6CQZ" -"W6CQZ S4" -"K1JT R S3" -" K1JT RRR" -"TNX JOE 73 GL" diff --git a/lib/wrapkarn.c b/lib/wrapkarn.c deleted file mode 100644 index 9e0a51c..0000000 --- a/lib/wrapkarn.c +++ /dev/null @@ -1,70 +0,0 @@ -#include -#include -#include -#include -#include -#include "rs.h" - -static void *rs; -static int first=1; - -void rs_encode_(int *dgen, int *sent) -// Encode JT65 data dgen[12], producing sent[63]. -{ - int dat1[12]; - int b[51]; - int i; - - if(first) { - // Initialize the JT65 codec - rs=init_rs_int(6,0x43,3,1,51,0); - first=0; - } - - // Reverse data order for the Karn codec. - for(i=0; i<12; i++) { - dat1[i]=dgen[11-i]; - } - // Compute the parity symbols - encode_rs_int(rs,dat1,b); - - // Move parity symbols and data into sent[] array, in reverse order. - for (i = 0; i < 51; i++) sent[50-i] = b[i]; - for (i = 0; i < 12; i++) sent[i+51] = dat1[11-i]; -} - -void rs_decode_(int *recd0, int *era0, int *numera0, int *decoded, int *nerr) -// Decode JT65 received data recd0[63], producing decoded[12]. -// Erasures are indicated in era0[numera]. The number of corrected -// errors is *nerr. If the data are uncorrectable, *nerr=-1 is returned. -{ - int numera; - int i; - int era_pos[50]; - int recd[63]; - - if(first) { - rs=init_rs_int(6,0x43,3,1,51,0); - first=0; - } - - numera=*numera0; - for(i=0; i<12; i++) recd[i]=recd0[62-i]; - for(i=0; i<51; i++) recd[12+i]=recd0[50-i]; - if(numera) - for(i=0; i::finished, this, &MainWindow::diskDat); - connect(&watcher3, SIGNAL(finished()),this,SLOT(fast_decode_done())); // Q_EMIT startAudioInputStream (m_config.audio_input_device (), m_framesAudioInputBuffered, &m_detector, m_downSampleFactor, m_config.audio_input_channel ()); Q_EMIT startAudioInputStream (m_config.audio_input_device (), m_framesAudioInputBuffered, m_detector, m_downSampleFactor, m_config.audio_input_channel ()); Q_EMIT initializeAudioOutputStream (m_config.audio_output_device (), AudioDevice::Mono == m_config.audio_output_channel () ? 1 : 2, m_msAudioOutputBuffered); @@ -1065,9 +1033,11 @@ MainWindow::MainWindow(QDir const& temp_directory, bool multiple, if(m_bFast9) m_bFastMode=true; ui->cbFast9->setChecked(m_bFast9 or m_bFastMode); - if(true || m_mode=="FT8") on_actionFT8_triggered(); + if(true || m_mode=="FT8") on_actionJS8_triggered(); + + // TODO: jsherer - is this needed? + //ui->sbSubmode->setValue (vhf ? m_nSubMode : 0); - ui->sbSubmode->setValue (vhf ? m_nSubMode : 0); if(m_mode=="MSK144") { Q_EMIT transmitFrequency (1000.0); } else { @@ -1133,7 +1103,7 @@ MainWindow::MainWindow(QDir const& temp_directory, bool multiple, ui->cbMenus->setChecked(false); } - //UI Customizations + //UI Customizations & Tweaks m_wideGraph.data()->installEventFilter(new EscapeKeyPressEater()); ui->mdiArea->addSubWindow(m_wideGraph.data(), Qt::Dialog | Qt::FramelessWindowHint | Qt::CustomizeWindowHint | Qt::Tool)->showMaximized(); //ui->menuDecode->setEnabled(true); @@ -1148,15 +1118,39 @@ MainWindow::MainWindow(QDir const& temp_directory, bool multiple, } ui->dxCallEntry->clear(); ui->dxGridEntry->clear(); - auto f = findFreeFreqOffset(1000, 2000, 50); - setFreqOffsetForRestore(f, false); + + //auto f = findFreeFreqOffset(1000, 2000, 50); + //setFreqOffsetForRestore(f, false); + ui->cbVHFcontest->setChecked(false); // this needs to always be false ui->actionModeAutoreply->setChecked(m_config.autoreply_on_at_startup()); ui->spotButton->setChecked(m_config.spot_to_reporting_networks()); + QActionGroup * modeActionGroup = new QActionGroup(this); + ui->actionModeJS8Normal->setActionGroup(modeActionGroup); + ui->actionModeJS8Fast->setActionGroup(modeActionGroup); + ui->actionModeJS8Turbo->setActionGroup(modeActionGroup); + ui->actionModeJS8Ultra->setActionGroup(modeActionGroup); + + auto mbmp = new MousePressEater(); + connect(mbmp, &MousePressEater::mousePressed, this, [this](QObject *, QMouseEvent * e, bool *pProcessed){ + ui->menuModeJS8->popup(e->globalPos()); + if(pProcessed) *pProcessed = true; + }); + ui->modeButton->installEventFilter(mbmp); + if(!JS8_ENABLE_JS8B){ + ui->actionModeJS8Fast->setVisible(false); + } + if(!JS8_ENABLE_JS8C){ + ui->actionModeJS8Turbo->setVisible(false); + } + if(!JS8_ENABLE_JS8D){ + ui->actionModeJS8Ultra->setVisible(false); + } + // prep - prepareAutoreplyMode(ui->actionModeAutoreply->isChecked()); + prepareHeartbeatMode(ui->actionModeJS8HB->isChecked()); prepareSpotting(); auto enterFilter = new EnterKeyPressEater(); @@ -1350,6 +1344,7 @@ MainWindow::MainWindow(QDir const& temp_directory, bool multiple, auto qsyAction = menu->addAction(QString("Jump to %1Hz").arg(selectedOffset)); connect(qsyAction, &QAction::triggered, this, [this, selectedOffset](){ setFreqOffsetForRestore(selectedOffset, false); + // TODO: prompt mode switch? }); menu->addSeparator(); } @@ -1378,6 +1373,10 @@ MainWindow::MainWindow(QDir const& temp_directory, bool multiple, ui->tableWidgetCalls->clearSelection(); }); + // savedMenu->setEnabled(savedMenu->isEnabled() && !ui->actionModeJS8HB->isChecked()); + // directedMenu->setEnabled(directedMenu->isEnabled() && !ui->actionModeJS8HB->isChecked()); + // relayAction->setEnabled(relayAction->isEnabled() && !ui->actionModeJS8HB->isChecked()); + menu->addSeparator(); removeActivity->setDisabled(selectedOffset == -1); @@ -1563,6 +1562,7 @@ MainWindow::MainWindow(QDir const& temp_directory, bool multiple, auto qsyAction = menu->addAction(QString("Jump to %1Hz").arg(selectedOffset)); connect(qsyAction, &QAction::triggered, this, [this, selectedOffset](){ setFreqOffsetForRestore(selectedOffset, false); + // TODO: prompt mode switch? }); menu->addSeparator(); } @@ -1598,6 +1598,10 @@ MainWindow::MainWindow(QDir const& temp_directory, bool multiple, ui->tableWidgetCalls->clearSelection(); }); + // savedMenu->setEnabled(savedMenu->isEnabled() && !ui->actionModeJS8HB->isChecked()); + // directedMenu->setEnabled(directedMenu->isEnabled() && !ui->actionModeJS8HB->isChecked()); + // relayAction->setEnabled(relayAction->isEnabled() && !ui->actionModeJS8HB->isChecked()); + menu->addSeparator(); menu->addAction(addStation); @@ -1661,6 +1665,18 @@ MainWindow::MainWindow(QDir const& temp_directory, bool multiple, btns.append(b); } */ + foreach(auto child, ui->buttonGrid->children()){ + if(!child->isWidgetType()){ + continue; + } + + if(!child->objectName().contains("Button")){ + continue; + } + + auto b = qobject_cast(child); + b->setCursor(QCursor(Qt::PointingHandCursor)); + } auto buttonLayout = ui->buttonGrid->layout(); auto gridButtonLayout = qobject_cast(buttonLayout); gridButtonLayout->setColumnMinimumWidth(0, width); @@ -1783,6 +1799,125 @@ void MainWindow::initializeDummyData(){ return; } +#if 0 + auto t = new QTimer(this); + t->setInterval(150); + connect(t, &QTimer::timeout, this, [this](){ + if(!ui->extFreeTextMsgEdit->hasFocus()){ + return; + } + + auto c = ui->extFreeTextMsgEdit->textCursor(); + int pos = qMin(c.selectionStart(), c.selectionEnd()); + + if(pos <= 5 && c.selectionStart() != c.selectionEnd()){ + c.clearSelection(); + ui->extFreeTextMsgEdit->setTextCursor(c); + } + }); + t->start(); + + auto kpe = new KeyPressEater(); + connect(kpe, &KeyPressEater::keyPressed, this, [this](QObject *obj, QKeyEvent * e, bool *pProcessed){ + auto t = e->text(); + auto c = ui->extFreeTextMsgEdit->textCursor(); + int pos = qMin(c.selectionStart(), c.selectionEnd()); + + if(e->key() == Qt::Key_Escape){ + *pProcessed = false; + return; + } + + QTextCursor cc(c); + cc.setPosition(5); + cc.movePosition(QTextCursor::NextWord); + int cpos = qMax(cc.selectionStart(), cc.selectionEnd()); + if(e->key() == Qt::Key_Backspace && e->modifiers().testFlag(Qt::ControlModifier) && pos < cpos){ + *pProcessed = true; + return; + } + + if((e->key() == Qt::Key_Backspace && pos <= 5) || + (e->key() == Qt::Key_Delete && pos < 5)){ + *pProcessed = true; + return; + } + + if(e->key() == Qt::Key_V && e->modifiers().testFlag(Qt::ControlModifier) && pos <= 5){ + *pProcessed = true; + return; + } + + if(!t.isEmpty() && pos < 5){ + *pProcessed = true; + return; + } + }); + ui->extFreeTextMsgEdit->installEventFilter(kpe); + + connect(ui->extFreeTextMsgEdit, &QTextEdit::copyAvailable, this, [this](bool available){ + if(!available){ + return; + } + auto c = ui->extFreeTextMsgEdit->textCursor(); + + qDebug() << "select" << c.selectionStart() << c.selectionEnd(); + + int pos = qMin(c.selectionStart(), c.selectionEnd()); + if(pos <= 5){ + auto text = c.selectedText(); + if(!text.isEmpty()){ + c.clearSelection(); + ui->extFreeTextMsgEdit->setTextCursor(c); + } + } + }); + + /* + connect(ui->extFreeTextMsgEdit->document(), &QTextDocument::cursorPositionChanged, this, [this](const QTextCursor &){ + auto c = ui->extFreeTextMsgEdit->textCursor(); + int pos = qMin(c.selectionStart(), c.selectionEnd()); + if(pos <= 5){ + auto text = c.selectedText(); + if(!text.isEmpty()){ + c.clearSelection(); + ui->extFreeTextMsgEdit->setTextCursor(c); + } + } + }); + + connect(ui->extFreeTextMsgEdit, &QTextEdit::cursorPositionChanged, this, [this](){ + auto c = ui->extFreeTextMsgEdit->textCursor(); + int pos = qMin(c.selectionStart(), c.selectionEnd()); + + if(pos <= 5){ + auto text = c.selectedText(); + if(!text.isEmpty()){ + c.clearSelection(); + ui->extFreeTextMsgEdit->setTextCursor(c); + } + } + }); + */ + + /*connect(ui->extFreeTextMsgEdit->document(), &QTextDocument::contentsChange, this, [this](int from, int removed, int added){ + if(from < 5 && removed == 1){ + ui->extFreeTextMsgEdit->document()->blockSignals(true); + ui->extFreeTextMsgEdit->document()->undo(); + ui->extFreeTextMsgEdit->document()->clearUndoRedoStacks(QTextDocument::RedoStack); + ui->extFreeTextMsgEdit->document()->blockSignals(false); + } + });*/ + + ui->extFreeTextMsgEdit->setText("HELLO BRAVE NEW WORLD"); + auto c = ui->extFreeTextMsgEdit->textCursor(); + c.setPosition(0); + c.setPosition(5, QTextCursor::KeepAnchor); + auto f = c.charFormat(); + f.setFontStrikeOut(true); + c.setCharFormat(f); +#endif + logHeardGraph("KN4CRD", "OH8STN"); logHeardGraph("KN4CRD", "K0OG"); logHeardGraph("K0OG", "KN4CRD"); @@ -1809,11 +1944,8 @@ void MainWindow::initializeDummyData(){ } } - auto d = DecodedText("h+vWp6mRPprH", 6); - qDebug() << d.message() << buildMessageFrames(d.message()); - - d = DecodedText("bYG4CKYT0cKG", 7); - qDebug() << d.message(); + auto d = DecodedText("SN5-lUuJkby0", Varicode::JS8CallFirst, 1); + qDebug () << "KN4CRD: K0OG ===>" << d.message(); // qDebug() << Varicode::isValidCallsign("@GROUP1", nullptr); // qDebug() << Varicode::packAlphaNumeric50("VE7/KN4CRD"); @@ -1854,6 +1986,7 @@ void MainWindow::initializeDummyData(){ cd.utcTimestamp = dt; cd.grid = i == 5 ? "J042" : i == 6 ? " FN42FN42FN" : ""; cd.tdrift = 0.1*i; + cd.mode = currentMode(); logCallActivity(cd, false); ActivityDetail ad = {}; @@ -1862,6 +1995,7 @@ void MainWindow::initializeDummyData(){ ad.freq = 500 + 100*i; ad.text = QString("%1: %2 TEST MESSAGE").arg(call).arg(m_config.my_callsign()); ad.utcTimestamp = dt; + ad.mode = cd.mode; m_bandActivity[500+100*i] = { ad }; markOffsetDirected(500+100*i, false); @@ -2089,7 +2223,9 @@ void MainWindow::writeSettings() m_settings->setValue("RxFreq",ui->RxFreqSpinBox->value()); m_settings->setValue("TxFreq",ui->TxFreqSpinBox->value()); m_settings->setValue("WSPRfreq",ui->WSPRfreqSpinBox->value()); - m_settings->setValue("SubMode",ui->sbSubmode->value()); + m_settings->setValue("SubMode",m_nSubMode); + m_settings->setValue("SubModeHB", ui->actionModeJS8HB->isChecked()); + m_settings->setValue("SubModeHBAck", ui->actionHeartbeatAcknowledgements->isChecked()); m_settings->setValue("DTtol",m_DTtol); m_settings->setValue("Ftol", ui->sbFtol->value ()); m_settings->setValue("MinSync",m_minSync); @@ -2119,8 +2255,6 @@ void MainWindow::writeSettings() m_settings->setValue ("JT65AP", ui->actionEnable_AP_JT65->isChecked ()); m_settings->setValue("SortBy", QVariant(m_sortCache)); m_settings->setValue("ShowColumns", QVariant(m_showColumnsCache)); - m_settings->setValue("HBAutoAck", m_hbAutoAck); - m_settings->setValue("HBHidden", m_hbHidden); m_settings->setValue("HBInterval", m_hbInterval); m_settings->setValue("CQInterval", m_cqInterval); @@ -2163,6 +2297,7 @@ void MainWindow::writeSettings() {"snr", QVariant(cd.snr)}, {"grid", QVariant(cd.grid)}, {"freq", QVariant(cd.freq)}, + {"tdrift", QVariant(cd.tdrift)}, #if CACHE_CALL_DATETIME_AS_STRINGS {"ackTimestamp", QVariant(cd.ackTimestamp.toString("yyyy-MM-dd hh:mm:ss"))}, {"utcTimestamp", QVariant(cd.utcTimestamp.toString("yyyy-MM-dd hh:mm:ss"))}, @@ -2170,6 +2305,7 @@ void MainWindow::writeSettings() {"ackTimestamp", QVariant(cd.ackTimestamp)}, {"utcTimestamp", QVariant(cd.utcTimestamp)}, #endif + {"mode", QVariant(cd.mode)}, }); } m_settings->endGroup(); @@ -2243,6 +2379,12 @@ void MainWindow::readSettings() ui->RxFreqSpinBox->setValue(0); // ensure a change is signaled ui->RxFreqSpinBox->setValue(m_settings->value("RxFreq",1500).toInt()); m_nSubMode=m_settings->value("SubMode",0).toInt(); + ui->actionModeJS8HB->setChecked(m_nSubMode == Varicode::JS8CallNormal && m_settings->value("SubModeHB", false).toBool()); + ui->actionHeartbeatAcknowledgements->setChecked(m_settings->value("SubModeHBAck", false).toBool()); + ui->actionModeJS8Normal->setChecked(m_nSubMode == Varicode::JS8CallNormal); + ui->actionModeJS8Fast->setChecked(m_nSubMode == Varicode::JS8CallFast); + ui->actionModeJS8Turbo->setChecked(m_nSubMode == Varicode::JS8CallTurbo); + ui->actionModeJS8Ultra->setChecked(m_nSubMode == Varicode::JS8CallUltra); ui->sbFtol->setValue (m_settings->value("Ftol", 20).toInt()); m_minSync=m_settings->value("MinSync",0).toInt(); ui->syncSpinBox->setValue(m_minSync); @@ -2284,8 +2426,6 @@ void MainWindow::readSettings() m_sortCache = m_settings->value("SortBy").toMap(); m_showColumnsCache = m_settings->value("ShowColumns").toMap(); - m_hbAutoAck = m_settings->value("HBAutoAck", true).toBool(); - m_hbHidden = m_settings->value("HBHidden", true).toBool(); m_hbInterval = m_settings->value("HBInterval", 0).toInt(); m_cqInterval = m_settings->value("CQInterval", 0).toInt(); @@ -2331,6 +2471,8 @@ void MainWindow::readSettings() auto snr = values.value("snr", -64).toInt(); auto grid = values.value("grid", "").toString(); auto freq = values.value("freq", 0).toInt(); + auto tdrift = values.value("tdrift", 0).toFloat(); + #if CACHE_CALL_DATETIME_AS_STRINGS auto ackTimestampStr = values.value("ackTimestamp", "").toString(); @@ -2344,14 +2486,17 @@ void MainWindow::readSettings() auto ackTimestamp = values.value("ackTimestamp").toDateTime(); auto utcTimestamp = values.value("utcTimestamp").toDateTime(); #endif + auto mode = values.value("mode", "JS8").toString(); CallDetail cd = {}; cd.call = call; cd.snr = snr; cd.grid = grid; cd.freq = freq; + cd.tdrift = tdrift; cd.ackTimestamp = ackTimestamp; cd.utcTimestamp = utcTimestamp; + cd.mode = mode; logCallActivity(cd, false); } @@ -2393,30 +2538,11 @@ void MainWindow::setDecodedTextFont (QFont const& font) void MainWindow::fixStop() { - m_hsymStop=179; - if(m_mode=="WSPR") { - m_hsymStop=396; - } else if(m_mode=="WSPR-LF") { - m_hsymStop=813; - } else if(m_mode=="Echo") { - m_hsymStop=9; - } else if (m_mode=="JT4"){ - m_hsymStop=176; - if(m_config.decode_at_52s()) m_hsymStop=179; - } else if (m_mode=="JT9"){ - m_hsymStop=173; - if(m_config.decode_at_52s()) m_hsymStop=179; - } else if (m_mode=="JT65" or m_mode=="JT9+JT65"){ - m_hsymStop=174; - if(m_config.decode_at_52s()) m_hsymStop=179; - } else if (m_mode=="QRA64"){ - m_hsymStop=179; - if(m_config.decode_at_52s()) m_hsymStop=186; - } else if (m_mode=="FreqCal"){ - m_hsymStop=((int(m_TRperiod/0.288))/8)*8; - } else if (m_mode=="FT8") { - m_hsymStop=JS8_SYMBOL_STOP; - } + m_hsymStop=((int(m_TRperiod/0.288))/8)*8 - 1; // 0.288 because 6912/12000/2 = 0.288 + + if(m_nSubMode == Varicode::JS8CallUltra){ + m_hsymStop++; + } } //-------------------------------------------------------------- dataSink() @@ -2442,11 +2568,6 @@ void MainWindow::dataSink(qint64 frames) &m_bUseRef,c_fname,len); m_bClearRefSpec=false; - if(m_mode=="ISCAT" or m_mode=="MSK144" or m_bFast9) { - fastSink(frames); - if(m_bFastMode) return; - } - // Get power, spectrum, and ihsym int trmin=m_TRperiod/60; // int k (frames - 1); @@ -2465,36 +2586,6 @@ void MainWindow::dataSink(qint64 frames) if(m_mode=="MSK144") return; fixStop(); - if (m_mode == "FreqCal" - // only calculate after 1st chunk, also skip chunk where rig - // changed frequency - && !(m_ihsym % 8) && m_ihsym > 8 && m_ihsym <= m_hsymStop) { - int RxFreq=ui->RxFreqSpinBox->value (); - int nkhz=(m_freqNominal+RxFreq)/1000; - int ftol = ui->sbFtol->value (); - freqcal_(&dec_data.d2[0],&k,&nkhz,&RxFreq,&ftol,&line[0],80); - QString t=QString::fromLatin1(line); - DecodedText decodedtext {t, false, m_config.my_grid ()}; - ui->decodedTextBrowser->displayDecodedText (decodedtext,m_baseCall,m_config.DXCC(), - m_logBook,m_config.color_primary_highlight(),m_config.color_MyCall(),m_config.color_DXCC(), - m_config.color_NewCall(),m_config.ppfx()); - if (ui->measure_check_box->isChecked ()) { - // Append results text to file "fmt.all". - QFile f {m_config.writeable_data_dir ().absoluteFilePath ("fmt.all")}; - if (f.open(QIODevice::WriteOnly | QIODevice::Text | QIODevice::Append)) { - QTextStream out(&f); - out << t << endl; - f.close(); - } else { - MessageBox::warning_message (this, tr ("File Open Error") - , tr ("Cannot open \"%1\" for append: %2") - .arg (f.fileName ()).arg (f.errorString ())); - } - } - if(m_ihsym==m_hsymStop && ui->actionFrequency_calibration->isChecked()) { - freqCalStep(); - } - } if(m_ihsym==3*m_hsymStop/4) { m_dialFreqRxWSPR=m_freqNominal; @@ -2621,120 +2712,6 @@ QString MainWindow::save_wave_file (QString const& name, short const * data, int //-------------------------------------------------------------- fastSink() void MainWindow::fastSink(qint64 frames) { - int k (frames); - bool decodeNow=false; - - if(k < m_k0) { //New sequence ? - memcpy(fast_green2,fast_green,4*703); //Copy fast_green[] to fast_green2[] - memcpy(fast_s2,fast_s,4*703*64); //Copy fast_s[] into fast_s2[] - fast_jh2=fast_jh; - if(!m_diskData) memset(dec_data.d2,0,2*30*12000); //Zero the d2[] array - m_bFastDecodeCalled=false; - m_bDecoded=false; - } - - QDateTime tnow=DriftingDateTime::currentDateTimeUtc(); - int ihr=tnow.toString("hh").toInt(); - int imin=tnow.toString("mm").toInt(); - int isec=tnow.toString("ss").toInt(); - isec=isec - isec%m_TRperiod; - int nutc0=10000*ihr + 100*imin + isec; - if(m_diskData) nutc0=m_UTCdisk; - char line[80]; - bool bmsk144=((m_mode=="MSK144") and (m_monitoring or m_diskData)); - line[0]=0; - - int RxFreq=ui->RxFreqSpinBox->value (); - int nTRpDepth=m_TRperiod + 1000*(m_ndepth & 3); - qint64 ms0 = DriftingDateTime::currentMSecsSinceEpoch(); - strncpy(dec_data.params.mycall, (m_baseCall+" ").toLatin1(),12); - QString hisCall {ui->dxCallEntry->text ()}; - bool bshmsg=ui->cbShMsgs->isChecked(); - bool bcontest=ui->cbVHFcontest->isChecked(); - bool bswl=ui->cbSWL->isChecked(); - strncpy(dec_data.params.hiscall,(Radio::base_callsign (hisCall) + " ").toLatin1 ().constData (), 12); - strncpy(dec_data.params.mygrid, (m_config.my_grid()+" ").toLatin1(),6); - QString dataDir; - dataDir = m_config.writeable_data_dir ().absolutePath (); - char ddir[512]; - strncpy(ddir,dataDir.toLatin1(), sizeof (ddir) - 1); - float pxmax = 0; - float rmsNoGain = 0; - int ftol = ui->sbFtol->value (); - hspec_(dec_data.d2,&k,&nutc0,&nTRpDepth,&RxFreq,&ftol,&bmsk144,&bcontest, - &m_bTrain,m_phaseEqCoefficients.constData(),&m_inGain,&dec_data.params.mycall[0], - &dec_data.params.hiscall[0],&bshmsg,&bswl, - &ddir[0],fast_green,fast_s,&fast_jh,&pxmax,&rmsNoGain,&line[0],&dec_data.params.mygrid[0], - 12,12,512,80,6); - float px = fast_green[fast_jh]; - QString t; - t.sprintf(" Rx noise: %5.1f ",px); - ui->signal_meter_widget->setValue(rmsNoGain,pxmax); // Update thermometer - m_fastGraph->plotSpec(m_diskData,m_UTCdisk); - - if(bmsk144 and (line[0]!=0)) { - QString message {QString::fromLatin1 (line)}; - DecodedText decodedtext {message.replace (QChar::LineFeed, ""), bcontest, m_config.my_grid ()}; - ui->decodedTextBrowser->displayDecodedText (decodedtext,m_baseCall,m_config.DXCC(), - m_logBook,m_config.color_primary_highlight(),m_config.color_MyCall(),m_config.color_DXCC(), - m_config.color_NewCall(),m_config.ppfx()); - m_bDecoded=true; - if (m_mode != "ISCAT") postDecode (true, decodedtext.string ()); - writeAllTxt(message, decodedtext.bits()); - bool stdMsg = decodedtext.report(m_baseCall, - Radio::base_callsign(ui->dxCallEntry->text()),m_rptRcvd); - //if (stdMsg) pskPost (decodedtext); - } - - float fracTR=float(k)/(12000.0*m_TRperiod); - decodeNow=false; - if(fracTR>0.92) { - m_dataAvailable=true; - fast_decode_done(); - m_bFastDone=true; - } - - m_k0=k; - if(m_diskData and m_k0 >= dec_data.params.kin - 7 * 512) decodeNow=true; - if(!m_diskData and m_tRemaining<0.35 and !m_bFastDecodeCalled) decodeNow=true; - if(m_mode=="MSK144") decodeNow=false; - - if(decodeNow) { - m_dataAvailable=true; - m_t0=0.0; - m_t1=k/12000.0; - m_kdone=k; - dec_data.params.newdat=1; - if(!m_decoderBusy) { - m_bFastDecodeCalled=true; - decode(); - } - } - - if(decodeNow or m_bFastDone) { - if(!m_diskData) { - QDateTime now {DriftingDateTime::currentDateTimeUtc()}; - int n=now.time().second() % m_TRperiod; - if(n<(m_TRperiod/2)) n=n+m_TRperiod; - auto const& period_start = now.addSecs (-n); - m_fnameWE = m_config.save_directory ().absoluteFilePath (period_start.toString ("yyMMdd_hhmmss")); - m_fileToSave.clear (); - if(m_saveAll or m_bAltV or (m_bDecoded and m_saveDecoded) or (m_mode!="MSK144" and m_mode!="FT8")) { - m_bAltV=false; - // the following is potential a threading hazard - not a good - // idea to pass pointer to be processed in another thread - m_saveWAVWatcher.setFuture (QtConcurrent::run (std::bind (&MainWindow::save_wave_file, - this, m_fnameWE, &dec_data.d2[0], m_TRperiod, m_config.my_callsign(), - m_config.my_grid(), m_mode, m_nSubMode, m_freqNominal, m_hisCall, m_hisGrid))); - } - if(m_mode!="MSK144") { - killFileTimer.start (3*1000*m_TRperiod/4); //Kill 3/4 period from now - } - } - m_bFastDone=false; - } - float tsec=0.001*(DriftingDateTime::currentMSecsSinceEpoch() - ms0); - m_fCPUmskrtd=0.9*m_fCPUmskrtd + 0.1*tsec; } void MainWindow::showSoundInError(const QString& errorMsg) @@ -2766,6 +2743,14 @@ void rebuildMacQAction(QMenu *menu, QAction *existingAction){ menu->removeAction(dummyAction); } +void MainWindow::on_menuModeJS8_aboutToShow(){ + bool canChangeMode = !m_transmitting && m_txFrameCount == 0 && m_txFrameQueue.isEmpty(); + ui->actionModeJS8Normal->setEnabled(canChangeMode); + ui->actionModeJS8Fast->setEnabled(canChangeMode); + ui->actionModeJS8Turbo->setEnabled(canChangeMode); + ui->actionModeJS8Ultra->setEnabled(canChangeMode); +} + void MainWindow::on_menuControl_aboutToShow(){ QMenu * freqMenu = new QMenu(this->menuBar()); buildFrequencyMenu(freqMenu); @@ -2848,7 +2833,7 @@ void MainWindow::on_menuWindow_aboutToShow(){ rebuildMacQAction(ui->menuWindow, ui->actionShow_Call_Activity_Columns); #endif - ui->actionShow_Band_Heartbeats_and_ACKs->setChecked(!m_hbHidden); + ui->actionShow_Band_Heartbeats_and_ACKs->setChecked(ui->actionModeJS8HB->isChecked()); ui->actionShow_Band_Heartbeats_and_ACKs->setEnabled(ui->actionShow_Band_Activity->isChecked()); } @@ -2937,7 +2922,6 @@ void MainWindow::on_actionShow_Band_Activity_triggered(bool checked){ } void MainWindow::on_actionShow_Band_Heartbeats_and_ACKs_triggered(bool checked){ - m_hbHidden = !checked; displayBandActivity(); } @@ -3071,7 +3055,7 @@ void MainWindow::openSettings(int tab){ bool b = vhf && (m_mode=="JT4" or m_mode=="JT65" or m_mode=="ISCAT" or m_mode=="JT9" or m_mode=="MSK144" or m_mode=="QRA64"); if(b) VHF_features_enabled(b); - if(m_mode=="FT8") on_actionFT8_triggered(); + if(m_mode=="FT8") on_actionJS8_triggered(); if(b) VHF_features_enabled(b); m_config.transceiver_online (); @@ -3255,6 +3239,27 @@ Radio::Frequency MainWindow::dialFrequency() { m_rigState.tx_frequency () : m_rigState.frequency ()}; } +QString MainWindow::currentMode(){ + if(m_nSubMode == Varicode::JS8CallNormal){ + return "NORMAL"; + } + else if(m_nSubMode == Varicode::JS8CallFast){ + return "FAST"; + } + else if(m_nSubMode == Varicode::JS8CallTurbo){ + return "TURBO"; + } + else if(m_nSubMode == Varicode::JS8CallUltra){ +#ifdef JS8D_IS_ULTRA + return "ULTRA"; +#else + return "SLOW"; +#endif + } + + return "?"; +} + void MainWindow::updateCurrentBand(){ QVariant state = ui->readFreq->property("state"); if(!state.isValid()){ @@ -4056,89 +4061,10 @@ void MainWindow::decode() //decode() from += noffset; size -= noffset; } - if(m_mode=="ISCAT" or m_mode=="MSK144" or m_bFast9) { - float t0=m_t0; - float t1=m_t1; - qApp->processEvents(); //Update the waterfall - if(m_nPick > 0) { - t0=m_t0Pick; - t1=m_t1Pick; - } - static short int d2b[360000]; - narg[0]=dec_data.params.nutc; - if(m_kdone>12000*m_TRperiod) { - m_kdone=12000*m_TRperiod; - } - narg[1]=m_kdone; - narg[2]=m_nSubMode; - narg[3]=dec_data.params.newdat; - narg[4]=dec_data.params.minSync; - narg[5]=m_nPick; - narg[6]=1000.0*t0; - narg[7]=1000.0*t1; - narg[8]=2; //Max decode lines per decode attempt - if(dec_data.params.minSync<0) narg[8]=50; - if(m_mode=="ISCAT") narg[9]=101; //ISCAT - if(m_mode=="JT9") narg[9]=102; //Fast JT9 - if(m_mode=="MSK144") narg[9]=104; //MSK144 - narg[10]=ui->RxFreqSpinBox->value(); - narg[11]=ui->sbFtol->value (); - narg[12]=0; - narg[13]=-1; - narg[14]=m_config.aggressive(); - memcpy(d2b,dec_data.d2,2*360000); - watcher3.setFuture (QtConcurrent::run (std::bind (fast_decode_,&d2b[0], - &narg[0],&m_TRperiod,&m_msg[0][0], - dec_data.params.mycall,dec_data.params.hiscall,8000,12,12))); - } else { - memcpy(to, from, qMin(mem_js8->size(), size)); - QFile {m_config.temp_dir ().absoluteFilePath (".lock")}.remove (); // Allow jt9 to start - decodeBusy(true); - } -} -void::MainWindow::fast_decode_done() -{ - float t,tmax=-99.0; - dec_data.params.nagain=false; - dec_data.params.ndiskdat=false; -// if(m_msg[0][0]==0) m_bDecoded=false; - for(int i=0; m_msg[i][0] && i<100; i++) { - QString message=QString::fromLatin1(m_msg[i]); - m_msg[i][0]=0; - if(message.length()>80) message=message.left (80); - if(narg[13]/8==narg[12]) message=message.trimmed().replace("<...>",m_calls); - -//Left (Band activity) window - DecodedText decodedtext {message.replace (QChar::LineFeed, ""), "FT8" == m_mode && - ui->cbVHFcontest->isChecked(), m_config.my_grid ()}; - if(!m_bFastDone) { - ui->decodedTextBrowser->displayDecodedText (decodedtext,m_baseCall,m_config.DXCC(), - m_logBook,m_config.color_primary_highlight(),m_config.color_MyCall(),m_config.color_DXCC(), - m_config.color_NewCall(),m_config.ppfx()); - } - - t=message.mid(10,5).toFloat(); - if(t>tmax) { - tmax=t; - m_bDecoded=true; - } - postDecode (true, decodedtext.string ()); - writeAllTxt(message, decodedtext.bits()); - - if(m_mode=="JT9" or m_mode=="MSK144") { - // find and extract any report for myCall - bool stdMsg = decodedtext.report(m_baseCall, - Radio::base_callsign(ui->dxCallEntry->text()), m_rptRcvd); - - // extract details and send to PSKreporter - //if (stdMsg) pskPost (decodedtext); - } - } - m_startAnother=m_loopall; - m_nPick=0; - ui->DecodeButton->setChecked (false); - m_bFastDone=false; + memcpy(to, from, qMin(mem_js8->size(), size)); + QFile {m_config.temp_dir ().absoluteFilePath (".lock")}.remove (); // Allow jt9 to start + decodeBusy(true); } void MainWindow::writeAllTxt(QString message, int bits) @@ -4153,7 +4079,7 @@ void MainWindow::writeAllTxt(QString message, int bits) << "JS8" << endl; m_RxLog=0; } - auto dt = DecodedText(message, bits); + auto dt = DecodedText(message, bits, m_nSubMode); out << dt.message() << endl; f.close(); } else { @@ -4285,7 +4211,7 @@ void MainWindow::readFromStdout() //readFromStdout } int n=t.length(); auto logText = t.mid(0, n-2); - auto dt = DecodedText(logText, false, m_config.my_grid()); + auto dt = DecodedText(logText, false, m_config.my_grid(), m_nSubMode); out << logText << " " << dt.message() << endl; f.close(); } else { @@ -4295,7 +4221,7 @@ void MainWindow::readFromStdout() //readFromStdout } DecodedText decodedtext {QString::fromUtf8 (t.constData ()).remove (QRegularExpression {"\r|\n"}), "FT8" == m_mode && - ui->cbVHFcontest->isChecked(), m_config.my_grid ()}; + ui->cbVHFcontest->isChecked(), m_config.my_grid (), m_nSubMode}; bool bValidFrame = decodedtext.snr() > -24; @@ -4342,6 +4268,7 @@ void MainWindow::readFromStdout() //readFromStdout d.snr = decodedtext.snr(); d.isBuffered = false; d.tdrift = decodedtext.dt(); + d.mode = currentMode(); // if we have any "first" frame, and a buffer is already established, clear it... int prevBufferOffset = -1; @@ -4378,6 +4305,7 @@ void MainWindow::readFromStdout() //readFromStdout cd.utcTimestamp = DriftingDateTime::currentDateTimeUtc(); cd.bits = decodedtext.bits(); cd.tdrift = decodedtext.dt(); + cd.mode = currentMode(); // Only respond to HEARTBEATS...remember that CQ messages are "Alt" pings if(decodedtext.isHeartbeat()){ @@ -4401,6 +4329,7 @@ void MainWindow::readFromStdout() //readFromStdout cmd.freq = cd.freq; cmd.utcTimestamp = cd.utcTimestamp; cmd.tdrift = cd.tdrift; + cmd.mode = cd.mode; m_rxCommandQueue.append(cmd); } @@ -4429,6 +4358,7 @@ void MainWindow::readFromStdout() //readFromStdout cmd.bits = decodedtext.bits(); cmd.extra = parts.length() > 2 ? parts.mid(3).join(" ") : ""; cmd.tdrift = decodedtext.dt(); + cmd.mode = currentMode(); // if the command is a buffered command and its not the last frame OR we have from or to in a separate message (compound call) if((Varicode::isCommandBuffered(cmd.cmd) && (cmd.bits & Varicode::JS8CallLast) != Varicode::JS8CallLast) || cmd.from == "<....>" || cmd.to == "<....>"){ @@ -4444,6 +4374,7 @@ void MainWindow::readFromStdout() //readFromStdout cmdcd.utcTimestamp = cmd.utcTimestamp; cmdcd.ackTimestamp = cmd.to == m_config.my_callsign() ? cmd.utcTimestamp : QDateTime{}; cmdcd.tdrift = cmd.tdrift; + cmdcd.mode = currentMode(); logCallActivity(cmdcd, false); logHeardGraph(cmd.from, cmd.to); } @@ -4477,6 +4408,7 @@ void MainWindow::readFromStdout() //readFromStdout td.freq = cmd.freq; td.utcTimestamp = cmd.utcTimestamp; td.tdrift = cmd.tdrift; + td.mode = currentMode(); logCallActivity(td, true); logHeardGraph(cmd.from, cmd.to); } @@ -4867,7 +4799,17 @@ void MainWindow::guiUpdate() if(m_TRperiod==0) m_TRperiod=60; txDuration=0.0; - if(m_modeTx=="FT8") txDuration=1.0 + JS8_NUM_SYMBOLS * (double)JS8_SYMBOL_SAMPLES/(double)RX_SAMPLE_RATE; // FT8 + if(m_modeTx=="FT8"){ + if(m_nSubMode == Varicode::JS8CallNormal){ + txDuration=JS8A_START_DELAY_MS/1000.0 + JS8_NUM_SYMBOLS * (double)JS8A_SYMBOL_SAMPLES/(double)RX_SAMPLE_RATE; + } else if(m_nSubMode == Varicode::JS8CallFast){ + txDuration=JS8B_START_DELAY_MS/1000.0 + JS8_NUM_SYMBOLS * (double)JS8B_SYMBOL_SAMPLES/(double)RX_SAMPLE_RATE; + } else if(m_nSubMode == Varicode::JS8CallTurbo){ + txDuration=JS8C_START_DELAY_MS/1000.0 + JS8_NUM_SYMBOLS * (double)JS8C_SYMBOL_SAMPLES/(double)RX_SAMPLE_RATE; + } else if(m_nSubMode == Varicode::JS8CallUltra){ + txDuration=JS8D_START_DELAY_MS/1000.0 + JS8_NUM_SYMBOLS * (double)JS8D_SYMBOL_SAMPLES/(double)RX_SAMPLE_RATE; + } + } double tx1=0.0; double tx2=txDuration; @@ -4941,7 +4883,21 @@ void MainWindow::guiUpdate() if(msgLength==0 and !m_tune) on_stopTxButton_clicked(); // 15.0 - 12.6 - if(fTR > 1.0-(2.4/15.0) && fTR < 1.0){ + double ratio = 1.0; + if(m_nSubMode == Varicode::JS8CallNormal){ + ratio = (((double)m_TRperiod - (JS8_NUM_SYMBOLS*(double)JS8A_SYMBOL_SAMPLES/(double)RX_SAMPLE_RATE))/(double)m_TRperiod); + } + else if(m_nSubMode == Varicode::JS8CallFast){ + ratio = (((double)m_TRperiod - (JS8_NUM_SYMBOLS*(double)JS8B_SYMBOL_SAMPLES/(double)RX_SAMPLE_RATE))/(double)m_TRperiod); + } + else if(m_nSubMode == Varicode::JS8CallTurbo){ + ratio = (((double)m_TRperiod - (JS8_NUM_SYMBOLS*(double)JS8C_SYMBOL_SAMPLES/(double)RX_SAMPLE_RATE))/(double)m_TRperiod); + } + else if(m_nSubMode == Varicode::JS8CallUltra){ + ratio = (((double)m_TRperiod - (JS8_NUM_SYMBOLS*(double)JS8D_SYMBOL_SAMPLES/(double)RX_SAMPLE_RATE))/(double)m_TRperiod); + } + + if(fTR > 1.0-ratio && fTR < 1.0){ if(!m_deadAirTone){ qDebug() << "should start dead air tone"; m_deadAirTone = true; @@ -4953,7 +4909,16 @@ void MainWindow::guiUpdate() } } - float lateThreshold=(2.5 - m_config.txDelay())/15.0; // 0.75; + // the late threshold is the dead air time minus the tx delay time + float lateThreshold = ratio - (m_config.txDelay() / m_TRperiod); + if(m_nSubMode == Varicode::JS8CallFast){ + // for the faster mode, only allow 3/4 late threshold + lateThreshold *= 0.75; + } + else if(m_nSubMode == Varicode::JS8CallTurbo){ + // for the turbo mode, only allow 1/2 late threshold + lateThreshold *= 0.5; + } if(g_iptt==0 and ((m_bTxTime and fTR0) or m_tune)) { //### Allow late starts icw[0]=m_ncw; @@ -4963,7 +4928,7 @@ void MainWindow::guiUpdate() emitPTT(true); m_tx_when_ready = true; - qDebug() << "start threshold" << fTR << lateThreshold; + qDebug() << "start threshold" << fTR << lateThreshold << ms; } // TODO: stop @@ -5010,10 +4975,18 @@ void MainWindow::guiUpdate() // 0: [000] <- this is standard set // 1: [001] <- this is fox/hound //m_i3bit=0; - qDebug() << "genft8" << message; + qDebug() << "gen tones" << message; char ft8msgbits[75 + 12]; //packed 75 bit ft8 message plus 12-bit CRC - genft8_(message, MyGrid, &bcontest, &m_i3bit, msgsent, const_cast (ft8msgbits), - const_cast (itone), 22, 6, 22); + + if(m_nSubMode == Varicode::JS8CallNormal){ + qDebug() << "gen ft8"; + genft8_(message, MyGrid, &bcontest, &m_i3bit, msgsent, const_cast (ft8msgbits), + const_cast (itone), 22, 6, 22); + } else if (m_nSubMode == Varicode::JS8CallFast || m_nSubMode == Varicode::JS8CallTurbo || m_nSubMode == Varicode::JS8CallUltra){ + qDebug() << "gen js8"; + genjs8_(message, MyGrid, &bcontest, &m_i3bit, msgsent, const_cast (ft8msgbits), + const_cast (itone), 22, 6, 22); + } msgibits = m_i3bit; msgsent[22]=0; @@ -5201,7 +5174,7 @@ void MainWindow::guiUpdate() if(m_transmitting) { char s[41]; - auto dt = DecodedText(msgsent, msgibits); + auto dt = DecodedText(msgsent, msgibits, m_nSubMode); sprintf(s,"Tx: %s", dt.message().toLocal8Bit().mid(0, 41).data()); m_nsendingsh=0; if(s[4]==64) m_nsendingsh=1; @@ -5387,7 +5360,7 @@ void MainWindow::startTx2() void MainWindow::stopTx() { Q_EMIT endTransmitMessage (); - auto dt = DecodedText(m_currentMessage.trimmed(), m_currentMessageBits); + auto dt = DecodedText(m_currentMessage.trimmed(), m_currentMessageBits, m_nSubMode); last_tx_label.setText("Last Tx: " + dt.message()); //m_currentMessage.trimmed()); m_btxok = false; @@ -5779,82 +5752,30 @@ void MainWindow::on_addButton_clicked() //Add button void MainWindow::msgtype(QString t, QLineEdit* tx) //msgtype() { - char message[29]; - char msgsent[29]; - int itone0[NUM_ISCAT_SYMBOLS]; //Dummy array, data not used - int len1=22; - QByteArray s=t.toUpper().toLocal8Bit(); - ba2msg(s,message); - int ichk=1,itype=0; - gen65_(message,&ichk,msgsent,itone0,&itype,len1,len1); - msgsent[22]=0; - bool text=false; - bool shortMsg=false; - if(itype==6) text=true; - if(itype==7 and m_config.enable_VHF_features() and - m_mode=="JT65") shortMsg=true; - if(m_mode=="MSK144" and t.mid(0,1)=="<") text=false; - if((m_mode=="MSK144" or m_mode=="FT8") and ui->cbVHFcontest->isChecked()) { - int i0=t.trimmed().length()-7; - if(t.mid(i0,3)==" R ") text=false; - } - QPalette p(tx->palette()); - if(text) { - p.setColor(QPalette::Base,"#ffccff"); - } else { - if(shortMsg) { - p.setColor(QPalette::Base,"#66ffff"); - } else { - p.setColor(QPalette::Base,Qt::transparent); - if(m_mode=="MSK144" and t.mid(0,1)=="<") { - p.setColor(QPalette::Base,"#00ffff"); - } - } - } - tx->setPalette(p); - auto pos = tx->cursorPosition (); - tx->setText(t.toUpper()); - tx->setCursorPosition (pos); } void MainWindow::on_tx1_editingFinished() //tx1 edited { - QString t=ui->tx1->text(); - msgtype(t, ui->tx1); } void MainWindow::on_tx2_editingFinished() //tx2 edited { - QString t=ui->tx2->text(); - msgtype(t, ui->tx2); } void MainWindow::on_tx3_editingFinished() //tx3 edited { - QString t=ui->tx3->text(); - msgtype(t, ui->tx3); } void MainWindow::on_tx4_editingFinished() //tx4 edited { - QString t=ui->tx4->text(); - msgtype(t, ui->tx4); } void MainWindow::on_tx5_currentTextChanged (QString const& text) //tx5 edited { - msgtype(text, ui->tx5->lineEdit ()); } void MainWindow::on_tx6_editingFinished() //tx6 edited { - QString t=ui->tx6->text().toUpper(); - if(t.indexOf(" ")>0) { - QString t1=t.split(" ").at(1); - m_CQtype="CQ"; - if(t1.size()==2) m_CQtype="CQ " + t1; - } - msgtype(t, ui->tx6); } void MainWindow::cacheActivity(QString key){ @@ -6274,7 +6195,7 @@ QString MainWindow::createMessageTransmitQueue(QString const& text, bool reset){ QStringList lines; foreach(auto frame, frames){ - auto dt = DecodedText(frame.first, frame.second); + auto dt = DecodedText(frame.first, frame.second, m_nSubMode); lines.append(dt.message()); } @@ -6284,7 +6205,11 @@ QString MainWindow::createMessageTransmitQueue(QString const& text, bool reset){ displayTextForFreq(QString("%1 %2 ").arg(joined).arg(m_config.eot()), freq, DriftingDateTime::currentDateTimeUtc(), true, true, true); // if we're transmitting a message to be displayed, we should bump the repeat buttons... +#if JS8HB_RESET_HB_TIMER_ON_TX resetAutomaticIntervalTransmissions(false, false); +#else + resetCQTimer(false); +#endif // keep track of the last message text sent m_lastTxMessage = text; @@ -6338,7 +6263,6 @@ void MainWindow::on_textEditRX_mouseDoubleClicked(){ void MainWindow::on_nextFreeTextMsg_currentTextChanged (QString const& text) { - msgtype(text, ui->nextFreeTextMsg); } void MainWindow::on_extFreeTextMsgEdit_currentTextChanged (QString const& text) @@ -6399,7 +6323,8 @@ QList> MainWindow::buildMessageFrames(const QString &text){ mygrid, selectedCall, text, - forceIdentify); + forceIdentify, + m_nSubMode); #if 0 qDebug() << "frames:"; @@ -6917,26 +6842,119 @@ void MainWindow::displayWidgets(qint64 n) m_lastCallsign.clear (); // ensures Tx5 is updated for new modes } -void MainWindow::on_actionModeJS8_triggered(){ - // TODO: uncheck all other modes +void MainWindow::on_actionModeJS8HB_toggled(bool checked){ + // prep hb mode + prepareHeartbeatMode(checked); + displayActivity(true); + + on_actionJS8_triggered(); +} + +void MainWindow::on_actionHeartbeatAcknowledgements_toggled(bool checked){ + // prep hb ack mode + prepareHeartbeatMode(ui->actionModeJS8HB->isChecked()); + displayActivity(true); + + on_actionJS8_triggered(); +} + +void MainWindow::on_actionModeJS8Normal_triggered(){ + on_actionJS8_triggered(); +} + +void MainWindow::on_actionModeJS8Fast_triggered(){ + on_actionJS8_triggered(); +} + +void MainWindow::on_actionModeJS8Turbo_triggered(){ + on_actionJS8_triggered(); +} + +void MainWindow::on_actionModeJS8Ultra_triggered(){ + on_actionJS8_triggered(); } void MainWindow::on_actionModeAutoreply_toggled(bool checked){ - prepareAutoreplyMode(checked); + // update the HB ack option (needs autoreply on) + prepareHeartbeatMode(ui->actionModeJS8HB->isChecked()); + + // then update the js8 mode + on_actionJS8_triggered(); } -void MainWindow::prepareAutoreplyMode(bool enabled){ - // heartbeat is now only available in autoreply mode +void MainWindow::prepareHeartbeatMode(bool enabled){ + // heartbeat is only available in HB mode ui->hbMacroButton->setVisible(enabled); - ui->actionHeartbeat->setVisible(enabled); + if(!enabled){ + ui->hbMacroButton->setChecked(false); + } + ui->actionHeartbeat->setEnabled(enabled); + ui->actionModeJS8HB->setEnabled(m_nSubMode == Varicode::JS8CallNormal); + ui->actionHeartbeatAcknowledgements->setEnabled(ui->actionModeAutoreply->isChecked() && enabled); + + //ui->actionCQ->setEnabled(!enabled); + //ui->actionFocus_Message_Reply_Area->setEnabled(!enabled); + + // default to not displaying the other buttons + // ui->cqMacroButton->setVisible(!enabled); + // ui->replyMacroButton->setVisible(!enabled); + // ui->snrMacroButton->setVisible(!enabled); + // ui->infoMacroButton->setVisible(!enabled); + // ui->macrosMacroButton->setVisible(!enabled); + // ui->queryButton->setVisible(!enabled); + // ui->extFreeTextMsgEdit->setVisible(!enabled); + // if(enabled){ + // ui->extFreeTextMsgEdit->clear(); + // } + + // show heartbeat and acks in hb mode only + // ui->actionShow_Band_Heartbeats_and_ACKs->setChecked(enabled); + // ui->actionShow_Band_Heartbeats_and_ACKs->setVisible(true); + // ui->actionShow_Band_Heartbeats_and_ACKs->setEnabled(false); // update the HB button immediately updateRepeatButtonDisplay(); + updateButtonDisplay(); } -void MainWindow::on_actionFT8_triggered() +void MainWindow::on_actionJS8_triggered() { m_mode="FT8"; + m_nSubMode=0; + if(ui->actionModeJS8Normal->isChecked()){ + m_nSubMode=Varicode::JS8CallNormal; + } + else if(ui->actionModeJS8Fast->isChecked()){ + m_nSubMode=Varicode::JS8CallFast; + } + else if(ui->actionModeJS8Turbo->isChecked()){ + m_nSubMode=Varicode::JS8CallTurbo; + } + else if(ui->actionModeJS8Ultra->isChecked()){ + m_nSubMode=Varicode::JS8CallUltra; + } + + // Only enable heartbeat for normal mode + ui->actionModeJS8HB->setEnabled(m_nSubMode == Varicode::JS8CallNormal); + if(m_nSubMode != Varicode::JS8CallNormal){ + ui->actionModeJS8HB->setChecked(false); + } + + auto modeText = currentMode(); + if(ui->actionModeAutoreply->isChecked()){ + modeText += QString("+AUTO"); + } + if(ui->actionModeJS8HB->isChecked()){ + if(ui->actionHeartbeatAcknowledgements->isChecked()){ + modeText += QString("+HB+ACK"); + } else { + modeText += QString("+HB"); + } + } + + ui->modeButton->setText(modeText); + + m_wideGraph->setSubMode(m_nSubMode); bool bVHF=m_config.enable_VHF_features(); m_bFast9=false; m_bFastMode=false; @@ -6946,7 +6964,7 @@ void MainWindow::on_actionFT8_triggered() m_nsps=6912; m_FFTSize = m_nsps / 2; Q_EMIT FFTSize (m_FFTSize); - m_hsymStop=JS8_SYMBOL_STOP; + fixStop(); setup_status_bar (bVHF); m_toneSpacing=0.0; //??? ui->actionFT8->setChecked(true); //??? @@ -6954,7 +6972,19 @@ void MainWindow::on_actionFT8_triggered() m_wideGraph->setModeTx(m_modeTx); VHF_features_enabled(bVHF); ui->cbAutoSeq->setChecked(true); - m_TRperiod=JS8_TX_SECONDS; + m_TRperiod = 0; + if(m_nSubMode == Varicode::JS8CallNormal){ + m_TRperiod = JS8A_TX_SECONDS; + } + else if(m_nSubMode == Varicode::JS8CallFast){ + m_TRperiod = JS8B_TX_SECONDS; + } + else if(m_nSubMode == Varicode::JS8CallTurbo){ + m_TRperiod = JS8C_TX_SECONDS; + } + else if(m_nSubMode == Varicode::JS8CallUltra){ + m_TRperiod = JS8D_TX_SECONDS; + } m_fastGraph->hide(); m_wideGraph->show(); ui->decodedTextLabel2->setText(" UTC dB DT Freq Message"); @@ -6987,6 +7017,8 @@ void MainWindow::on_actionFT8_triggered() ui->txFirstCheckBox->setEnabled(true); ui->cbAutoSeq->setEnabled(true); + updateTextDisplay(); + refreshTextDisplay(); statusChanged(); } @@ -7426,25 +7458,6 @@ void MainWindow::buildFrequencyMenu(QMenu *menu){ } void MainWindow::buildHeartbeatMenu(QMenu *menu){ - auto selectedCallsign = callsignSelected(); - bool enabled = ui->actionModeAutoreply->isChecked() && selectedCallsign.isEmpty(); - auto text = "Send Heartbeat Acknowledgments (ACK)"; - if(!ui->actionModeAutoreply->isChecked()){ - text = "Send Heartbeat Acknowledgments (ACK) (Disabled: Autoreply is off)"; - } - if(!selectedCallsign.isEmpty()){ - text = "Send Heartbeat Acknowledgments (ACK) (Disabled: Currently in QSO)"; - } - auto autoAckHB = menu->addAction(text); - autoAckHB->setEnabled(enabled); - autoAckHB->setCheckable(true); - autoAckHB->setChecked(m_hbAutoAck); - connect(autoAckHB, &QAction::triggered, this, [this, autoAckHB](){ - m_hbAutoAck = autoAckHB->isChecked(); - updateRepeatButtonDisplay(); - }); - menu->addSeparator(); - if(m_hbInterval > 0){ auto startStop = menu->addAction(ui->hbMacroButton->isChecked() ? "Stop Heartbeat Timer" : "Start Heartbeat Timer"); connect(startStop, &QAction::triggered, this, [this](){ ui->hbMacroButton->toggle(); }); @@ -7718,9 +7731,11 @@ void MainWindow::buildShowColumnsMenu(QMenu *menu, QString tableKey){ {"Last heard timestamp", "timestamp"}, {"SNR", "snr"}, {"Time Delta", "tdrift"}, + {"Mode Speed", "mode"}, }; QMap defaultOverride = { + {"mode", false}, {"tdrift", false}, {"grid", false}, {"distance", false} @@ -8015,7 +8030,6 @@ void MainWindow::buildQueryMenu(QMenu * menu, QString call){ addMessageText(QString("%1 MSG [MESSAGE]").arg(selectedCall), true, true); }); - auto msgToAction = menu->addAction(QString("%1 MSG TO:[CALLSIGN] [MESSAGE] - Please store this message at your station for later retreival by [CALLSIGN]").arg(call).trimmed()); msgToAction->setDisabled(isAllCall); connect(msgToAction, &QAction::triggered, this, [this](){ @@ -8061,7 +8075,9 @@ void MainWindow::buildQueryMenu(QMenu * menu, QString call){ addMessageText(QString("%1 QUERY MSG [ID]").arg(selectedCall), true, true); }); - auto agnAction = menu->addAction(QString("%1 AGN? - Please automatically repeat your last transmission").arg(call).trimmed()); + menu->addSeparator(); + + auto agnAction = menu->addAction(QString("%1 AGN? - Please repeat your last transmission").arg(call).trimmed()); connect(agnAction, &QAction::triggered, this, [this](){ QString selectedCall = callsignSelected(); @@ -8074,8 +8090,6 @@ void MainWindow::buildQueryMenu(QMenu * menu, QString call){ if(m_config.transmit_directed()) toggleTx(true); }); - menu->addSeparator(); - auto qslQueryAction = menu->addAction(QString("%1 QSL? - Did you receive my last transmission?").arg(call).trimmed()); connect(qslQueryAction, &QAction::triggered, this, [this](){ @@ -8423,6 +8437,8 @@ void MainWindow::on_tableWidgetRXAll_cellDoubleClicked(int row, int col){ // switch to the offset of this row setFreqOffsetForRestore(offset, false); + // TODO: prompt mode switch? + // print the history in the main window... int activityAging = m_config.activity_aging(); QDateTime now = DriftingDateTime::currentDateTimeUtc(); @@ -8547,7 +8563,6 @@ void MainWindow::on_tableWidgetCalls_selectionChanged(const QItemSelection &sele void MainWindow::on_freeTextMsg_currentTextChanged (QString const& text) { - msgtype(text, ui->freeTextMsg->lineEdit ()); } void MainWindow::on_driftSpinBox_valueChanged(int n){ @@ -9041,25 +9056,32 @@ void MainWindow::rigFailure (QString const& reason) void MainWindow::transmit (double snr) { double toneSpacing=0.0; - if (m_modeTx == "JT65") { - if(m_nSubMode==0) toneSpacing=11025.0/4096.0; - if(m_nSubMode==1) toneSpacing=2*11025.0/4096.0; - if(m_nSubMode==2) toneSpacing=4*11025.0/4096.0; - Q_EMIT sendMessage (NUM_JT65_SYMBOLS, - 4096.0*12000.0/11025.0, ui->TxFreqSpinBox->value () - m_XIT, - toneSpacing, m_soundOutput, m_config.audio_output_channel (), - true, false, snr, m_TRperiod); - } if (m_modeTx == "FT8") { - toneSpacing=(double)RX_SAMPLE_RATE/(double)JS8_SYMBOL_SAMPLES; - //if(m_config.x2ToneSpacing()) toneSpacing=2.0*(double)RX_SAMPLE_RATE/(double)JS8_SYMBOL_SAMPLES; - //if(m_config.x4ToneSpacing()) toneSpacing=4.0*(double)RX_SAMPLE_RATE/(double)JS8_SYMBOL_SAMPLES; + double symbolSamples = 0.0; + if(m_nSubMode == Varicode::JS8CallNormal){ + symbolSamples=(double)JS8A_SYMBOL_SAMPLES; + toneSpacing=(double)RX_SAMPLE_RATE/(double)JS8A_SYMBOL_SAMPLES; + } + else if(m_nSubMode == Varicode::JS8CallFast){ + symbolSamples=(double)JS8B_SYMBOL_SAMPLES; + toneSpacing=(double)RX_SAMPLE_RATE/(double)JS8B_SYMBOL_SAMPLES; + } + else if(m_nSubMode == Varicode::JS8CallTurbo){ + symbolSamples=(double)JS8C_SYMBOL_SAMPLES; + toneSpacing=(double)RX_SAMPLE_RATE/(double)JS8C_SYMBOL_SAMPLES; + } + else if(m_nSubMode == Varicode::JS8CallUltra){ + symbolSamples=(double)JS8D_SYMBOL_SAMPLES; + toneSpacing=(double)RX_SAMPLE_RATE/(double)JS8D_SYMBOL_SAMPLES; + } + if(m_config.x2ToneSpacing()) toneSpacing*=2.0; + if(m_config.x4ToneSpacing()) toneSpacing*=4.0; if(m_config.bFox() and !m_tune) toneSpacing=-1; if(TEST_FOX_WAVE_GEN && ui->turboButton->isChecked() && !m_tune) toneSpacing=-1; Q_EMIT sendMessage (JS8_NUM_SYMBOLS, - (double)JS8_SYMBOL_SAMPLES, ui->TxFreqSpinBox->value () - m_XIT, + symbolSamples, ui->TxFreqSpinBox->value () - m_XIT, toneSpacing, m_soundOutput, m_config.audio_output_channel (), true, false, snr, m_TRperiod); } @@ -9424,7 +9446,7 @@ void MainWindow::updateButtonDisplay(){ void MainWindow::updateRepeatButtonDisplay(){ auto selectedCallsign = callsignSelected(); - auto hbBase = m_hbAutoAck && ui->actionModeAutoreply->isChecked() && selectedCallsign.isEmpty() ? "HB + ACK" : "HB"; + auto hbBase = ui->actionModeAutoreply->isChecked() && ui->actionHeartbeatAcknowledgements->isChecked() && selectedCallsign.isEmpty() ? "HB + ACK" : "HB"; if(ui->hbMacroButton->isChecked() && m_hbInterval > 0 && m_nextHeartbeat.isValid()){ auto secs = DriftingDateTime::currentDateTimeUtc().secsTo(m_nextHeartbeat); if(secs > 0){ @@ -9514,7 +9536,8 @@ void MainWindow::refreshTextDisplay(){ mygrid, selectedCall, text, - forceIdentify + forceIdentify, + m_nSubMode ); connect(t, &BuildMessageFramesThread::finished, t, &QObject::deleteLater); @@ -9547,7 +9570,7 @@ void MainWindow::updateTextWordCheckerDisplay(){ } void MainWindow::updateTextStatsDisplay(QString text, int count){ - const double fpm = 60.0/JS8_TX_SECONDS; + const double fpm = 60.0/m_TRperiod; if(count > 0){ auto words = text.split(" ", QString::SkipEmptyParts).length(); auto wpm = QString::number(words/(count/fpm), 'f', 1); @@ -9801,8 +9824,8 @@ void MainWindow::processActivity(bool force) { } void MainWindow::observeTimeDeltaForAverage(float delta){ - // delta can only be +/- 15 seconds - delta = qMax(-15.0F, qMin(delta, 15.0F)); + // delta can only be +/- the TR period + delta = qMax(-(float)m_TRperiod, qMin(delta, (float)m_TRperiod)); // compute average drift if(m_timeDeltaMsMMA_N == 0){ @@ -9814,7 +9837,7 @@ void MainWindow::observeTimeDeltaForAverage(float delta){ } // display average - if(m_timeDeltaMsMMA < -15.0F || m_timeDeltaMsMMA > 15.0F){ + if(m_timeDeltaMsMMA < -(float)m_TRperiod || m_timeDeltaMsMMA > (float)m_TRperiod){ resetTimeDeltaAverage(); } ui->driftAvgLabel->setText(QString("Avg Time Delta: %1 ms").arg((int)m_timeDeltaMsMMA)); @@ -9929,6 +9952,7 @@ void MainWindow::processRxActivity() { cd.bits = d.bits; cd.tdrift = d.tdrift; cd.utcTimestamp = d.utcTimestamp; + cd.mode = currentMode(); logCallActivity(cd, true); } } @@ -10025,7 +10049,7 @@ void MainWindow::processCompoundActivity() { bits == Varicode::JS8Call || ((bits & Varicode::JS8CallFirst) == Varicode::JS8CallFirst) || ((bits & Varicode::JS8CallLast) == Varicode::JS8CallLast) || - ((bits & Varicode::JS8CallFlag) == Varicode::JS8CallFlag) + ((bits & Varicode::JS8CallData) == Varicode::JS8CallData) ); if (!validBits) { qDebug() << "-> buffer.cmd bits is invalid...skip"; @@ -10265,6 +10289,7 @@ void MainWindow::processCommandActivity() { cd.ackTimestamp = d.text.contains(": ACK") || toMe ? d.utcTimestamp : QDateTime{}; cd.utcTimestamp = d.utcTimestamp; cd.tdrift = d.tdrift; + cd.mode = currentMode(); logCallActivity(cd, true); logHeardGraph(d.from, d.to); @@ -10282,6 +10307,7 @@ void MainWindow::processCommandActivity() { cd.snr = d.snr; cd.utcTimestamp = d.utcTimestamp; cd.tdrift = d.tdrift; + cd.mode = currentMode(); m_aprsCallCache.remove(cd.call); m_aprsCallCache.remove(APRSISClient::replaceCallsignSuffixWithSSID(cd.call, Radio::base_callsign(cd.call))); @@ -10555,6 +10581,7 @@ void MainWindow::processCommandActivity() { cd.through = d.from; cd.utcTimestamp = DriftingDateTime::currentDateTimeUtc(); cd.tdrift = d.tdrift; + cd.mode = currentMode(); logCallActivity(cd, false); } @@ -10668,11 +10695,12 @@ void MainWindow::processCommandActivity() { } // PROCESS ACTIVE HEARTBEAT - // if we have auto reply enabled and auto ack enabled and no callsign is selected - else if (d.cmd == " HB" && ui->actionModeAutoreply->isChecked() && m_hbAutoAck && selectedCallsign.isEmpty()){ + // if we have hb mode enabled and auto reply enabled and auto ack enabled and no callsign is selected update: if we're in HB mode, doesn't matter if a callsign is selected. + else if (d.cmd == " HB" && ui->actionModeJS8HB->isChecked() && ui->actionModeAutoreply->isChecked() && ui->actionHeartbeatAcknowledgements->isChecked() && selectedCallsign.isEmpty()){ // check to make sure this callsign isn't blacklisted if(m_config.hb_blacklist().contains(d.from) || m_config.hb_blacklist().contains(Radio::base_callsign(d.from))){ + qDebug() << "hb blacklist blocking" << d.from; continue; } @@ -10910,11 +10938,13 @@ void MainWindow::processCommandActivity() { continue; } +#if 0 // TODO: jsherer - HB issue here // do not queue a reply if it's a HB and HB is not active - if((!ui->hbMacroButton->isChecked() || m_hbInterval <= 0) && d.cmd.contains("HB")){ - continue; - } + // if((!ui->hbMacroButton->isChecked() || m_hbInterval <= 0) && d.cmd.contains("HB")){ + // continue; + // } +#endif // do not queue for reply if there's text in the window if(!ui->extFreeTextMsgEdit->toPlainText().isEmpty()){ @@ -10982,6 +11012,7 @@ void MainWindow::refreshInboxCounts(){ cd.utcTimestamp = QDateTime::fromString(utc, "yyyy-MM-dd hh:mm:ss"); cd.utcTimestamp.setUtcOffset(0); cd.ackTimestamp = cd.utcTimestamp; + cd.mode = currentMode(); logCallActivity(cd, false); } } @@ -11363,6 +11394,8 @@ void MainWindow::displayBandActivity() { QString age; int snr = 0; float tdrift = 0; + QString mode; + int activityAging = m_config.activity_aging(); // hide items that shouldn't appear @@ -11377,9 +11410,10 @@ void MainWindow::displayBandActivity() { } // hide heartbeat items - if (m_hbHidden){ + if (!ui->actionShow_Band_Heartbeats_and_ACKs->isChecked()){ // hide heartbeats and acks if we have heartbeating hidden if(item.text.contains(" HB ") || item.text.contains(" ACK ")){ + // TODO: if text contains MSG ID and previous frame was hidden, hide this one too shouldDisplay = false; } } @@ -11412,6 +11446,7 @@ void MainWindow::displayBandActivity() { age = since(item.utcTimestamp); timestamp = item.utcTimestamp; tdrift = item.tdrift; + mode = item.mode; } auto joined = Varicode::rstrip(text.join("")); @@ -11441,6 +11476,12 @@ void MainWindow::displayBandActivity() { tdriftItem->setData(Qt::UserRole, QVariant(tdrift)); ui->tableWidgetRXAll->setItem(row, col++, tdriftItem); + auto modeItem = new QTableWidgetItem(mode.left(1).replace("H", "N")); + modeItem->setToolTip(mode); + modeItem->setData(Qt::UserRole, QVariant(mode)); + modeItem->setTextAlignment(Qt::AlignHCenter | Qt::AlignVCenter); + ui->tableWidgetRXAll->setItem(row, col++, modeItem); + // align right if eliding... int colWidth = ui->tableWidgetRXAll->columnWidth(3); auto textItem = new QTableWidgetItem(joined); @@ -11531,12 +11572,14 @@ void MainWindow::displayBandActivity() { ui->tableWidgetRXAll->setColumnHidden(1, !showColumn("band", "timestamp")); ui->tableWidgetRXAll->setColumnHidden(2, !showColumn("band", "snr")); ui->tableWidgetRXAll->setColumnHidden(3, !showColumn("band", "tdrift", false)); + ui->tableWidgetRXAll->setColumnHidden(4, !showColumn("band", "mode", false)); // Resize the table columns ui->tableWidgetRXAll->resizeColumnToContents(0); ui->tableWidgetRXAll->resizeColumnToContents(1); ui->tableWidgetRXAll->resizeColumnToContents(2); ui->tableWidgetRXAll->resizeColumnToContents(3); + ui->tableWidgetRXAll->resizeColumnToContents(4); // Reset the scroll position ui->tableWidgetRXAll->verticalScrollBar()->setValue(currentScrollPos); @@ -11725,6 +11768,12 @@ void MainWindow::displayCallActivity() { ui->tableWidgetCalls->setItem(row, col++, new QTableWidgetItem(QString("%1 ms").arg((int)(1000*d.tdrift)))); + auto modeItem = new QTableWidgetItem(d.mode.left(1).replace("H", "N")); + modeItem->setToolTip(d.mode); + modeItem->setData(Qt::UserRole, QVariant(d.mode)); + modeItem->setTextAlignment(Qt::AlignHCenter | Qt::AlignVCenter); + ui->tableWidgetCalls->setItem(row, col++, modeItem); + auto gridItem = new QTableWidgetItem(QString("%1").arg(d.grid.trimmed().left(4))); gridItem->setToolTip(d.grid.trimmed()); ui->tableWidgetCalls->setItem(row, col++, gridItem); @@ -11782,6 +11831,7 @@ void MainWindow::displayCallActivity() { ui->tableWidgetCalls->setItem(row, col++, new QTableWidgetItem("")); // snr ui->tableWidgetCalls->setItem(row, col++, new QTableWidgetItem("")); // freq ui->tableWidgetCalls->setItem(row, col++, new QTableWidgetItem("")); // tdrift + ui->tableWidgetCalls->setItem(row, col++, new QTableWidgetItem("")); // mode ui->tableWidgetCalls->setItem(row, col++, new QTableWidgetItem("")); // grid ui->tableWidgetCalls->setItem(row, col++, new QTableWidgetItem("")); // distance ui->tableWidgetCalls->setItem(row, col++, new QTableWidgetItem("")); // worked before @@ -11851,11 +11901,12 @@ void MainWindow::displayCallActivity() { ui->tableWidgetCalls->setColumnHidden(3, !showColumn("call", "snr")); ui->tableWidgetCalls->setColumnHidden(4, !showColumn("call", "offset")); ui->tableWidgetCalls->setColumnHidden(5, !showColumn("call", "tdrift", false)); - ui->tableWidgetCalls->setColumnHidden(6, !showColumn("call", "grid", false)); - ui->tableWidgetCalls->setColumnHidden(7, !showColumn("call", "distance", false)); - ui->tableWidgetCalls->setColumnHidden(8, !showColumn("call", "log")); - ui->tableWidgetCalls->setColumnHidden(9, !showColumn("call", "logName")); - ui->tableWidgetCalls->setColumnHidden(10, !showColumn("call", "logComment")); + ui->tableWidgetCalls->setColumnHidden(6, !showColumn("call", "mode", false)); + ui->tableWidgetCalls->setColumnHidden(7, !showColumn("call", "grid", false)); + ui->tableWidgetCalls->setColumnHidden(8, !showColumn("call", "distance", false)); + ui->tableWidgetCalls->setColumnHidden(9, !showColumn("call", "log")); + ui->tableWidgetCalls->setColumnHidden(10, !showColumn("call", "logName")); + ui->tableWidgetCalls->setColumnHidden(11, !showColumn("call", "logComment")); // Resize the table columns ui->tableWidgetCalls->resizeColumnToContents(0); @@ -11868,6 +11919,7 @@ void MainWindow::displayCallActivity() { ui->tableWidgetCalls->resizeColumnToContents(7); ui->tableWidgetCalls->resizeColumnToContents(8); ui->tableWidgetCalls->resizeColumnToContents(9); + ui->tableWidgetCalls->resizeColumnToContents(10); // Reset the scroll position ui->tableWidgetCalls->verticalScrollBar()->setValue(currentScrollPos); @@ -11910,6 +11962,7 @@ void MainWindow::emitTones(){ // emit tone numbers to network QVariantList t; for(int i = 0; i < JS8_NUM_SYMBOLS; i++){ + //qDebug() << "tone" << i << "=" << itone[i]; t.append(QVariant((int)itone[i])); } @@ -12768,7 +12821,7 @@ void MainWindow::write_transmit_entry (QString const& file_name) QTextStream out(&f); auto time = DriftingDateTime::currentDateTimeUtc (); time = time.addSecs (-(time.time ().second () % m_TRperiod)); - auto dt = DecodedText(m_currentMessage, m_currentMessageBits); + auto dt = DecodedText(m_currentMessage, m_currentMessageBits, m_nSubMode); out << time.toString("yyyy-MM-dd hh:mm:ss") << " Transmitting " << qSetRealNumberPrecision (12) << (m_freqNominal / 1.e6) << " MHz " << "JS8" diff --git a/mainwindow.h b/mainwindow.h index 1ae4045..f2f040b 100644 --- a/mainwindow.h +++ b/mainwindow.h @@ -177,6 +177,7 @@ private slots: void on_tx4_editingFinished(); void on_tx5_currentTextChanged (QString const&); void on_tx6_editingFinished(); + void on_menuModeJS8_aboutToShow(); void on_menuControl_aboutToShow(); void on_actionCheck_for_Updates_triggered(); void on_actionEnable_Spotting_toggled(bool checked); @@ -259,10 +260,15 @@ private slots: void on_dxCallEntry_returnPressed (); void on_genStdMsgsPushButton_clicked(); void on_logQSOButton_clicked(); - void on_actionModeJS8_triggered(); + void on_actionModeJS8HB_toggled(bool checked); + void on_actionModeJS8Normal_triggered(); + void on_actionModeJS8Fast_triggered(); + void on_actionModeJS8Turbo_triggered(); + void on_actionModeJS8Ultra_triggered(); + void on_actionHeartbeatAcknowledgements_toggled(bool checked); void on_actionModeAutoreply_toggled(bool checked); - void prepareAutoreplyMode(bool enabled); - void on_actionFT8_triggered(); + void prepareHeartbeatMode(bool enabled); + void on_actionJS8_triggered(); void on_TxFreqSpinBox_valueChanged(int arg1); void on_actionSave_decoded_triggered(); void on_actionQuickDecode_toggled (bool); @@ -409,7 +415,6 @@ private slots: void on_pbTxNext_clicked(bool b); void on_actionEcho_Graph_triggered(); void on_actionFast_Graph_triggered(); - void fast_decode_done(); void on_actionMeasure_reference_spectrum_triggered(); void on_actionErase_reference_spectrum_triggered(); void on_actionMeasure_phase_response_triggered(); @@ -729,6 +734,7 @@ private: int snr; int bits; float tdrift; + QString mode; }; struct CommandDetail @@ -746,6 +752,7 @@ private: QString text; QString extra; float tdrift; + QString mode; QString relayPath; }; @@ -763,6 +770,7 @@ private: int snr; bool shouldDisplay; float tdrift; + QString mode; }; struct MessageBuffer { @@ -872,8 +880,6 @@ private: QQueue m_foxQSOinProgress; //QSOs in progress: Fox has sent a report QQueue m_foxRateQueue; - bool m_hbAutoAck; - bool m_hbHidden; int m_hbInterval; int m_cqInterval; bool m_hbPaused; @@ -942,6 +948,7 @@ private: void pskLogReport(QString mode, int offset, int snr, QString callsign, QString grid); void aprsLogReport(int offset, int snr, QString callsign, QString grid); Radio::Frequency dialFrequency(); + QString currentMode(); void updateCurrentBand(); void displayDialFrequency (); void transmitDisplay (bool); diff --git a/mainwindow.ui b/mainwindow.ui index e0d60fb..fa25197 100644 --- a/mainwindow.ui +++ b/mainwindow.ui @@ -694,7 +694,7 @@ QPushButton:checked { - + true @@ -749,7 +749,7 @@ QPushButton:checked { - + true @@ -804,8 +804,8 @@ QPushButton:checked { - - + + true @@ -829,19 +829,20 @@ QPushButton:checked { - 9 + 75 + true - <html><head/><body><p><br/></p></body></html> + <html><head/><body><p>Set the JS8 mode settings</p></body></html> QPushButton { -background-color:lightgray; -padding:0.25em 0.25em; font-weight:normal; +padding:0.25em 0.25em; font-weight:bold; border-style:solid; border-width:0px; border-radius:2px; +background-color:#6699ff; } QPushButton:checked { @@ -849,7 +850,7 @@ background-color:#6699ff; } - ... + JS8 true @@ -888,7 +889,7 @@ background-color:#6699ff; - <html><head/><body><p>Transmit a tuning tone</p></body></html> + <html><head/><body><p>Spot to reporting networks</p></body></html> QPushButton { @@ -1079,6 +1080,11 @@ background-color:#6699ff; Time Delta + + + Speed + + Message(s) @@ -1268,6 +1274,11 @@ QTextEdit[transmitting="true"] { Time Delta + + + Speed + + Grid @@ -1331,24 +1342,8 @@ QTextEdit[transmitting="true"] { 0 - - - - - 75 - 30 - - - - <html><head/><body><p>Stop transmitting</p></body></html> - - - Halt - - - - - + + 0 @@ -1356,7 +1351,7 @@ QTextEdit[transmitting="true"] { - <html><head/><body><p>Send a CQ message</p></body></html> + <html><head/><body><p align="justify">Send a Heartbeat message</p></body></html> true @@ -1368,32 +1363,13 @@ QTextEdit[transmitting="true"] { } - CQ + HB true - - false - - - - - Qt::Horizontal - - - QSizePolicy::Preferred - - - - 20 - 10 - - - - @@ -1429,8 +1405,8 @@ color:#222; - - + + 0 @@ -1438,10 +1414,25 @@ color:#222; - <html><head/><body><p>Send a directed message to another station</p></body></html> + <html><head/><body><p>Send a CQ message</p></body></html> + + + true + + + QPushButton:checked { + font-weight:bold; + color:black; +} - Directed + CQ + + + true + + + false @@ -1461,68 +1452,40 @@ color:#222; - - - + + + + Qt::Horizontal + + + QSizePolicy::Preferred + + - 0 - 30 + 20 + 10 - - <html><head/><body><p>Send a saved message</p></body></html> - - - Saved - - - - - - - - 0 - 30 - - - - <html><head/><body><p>Reply to a CQ</p></body></html> - - - REPLY - - - - - - - - 0 - 30 - - - - <html><head/><body><p align="justify">Send a Heartbeat message</p></body></html> - - - true - - - QPushButton:checked { - font-weight:bold; - color:black; -} - - - HB - - - true - - + - + + + Qt::Horizontal + + + QSizePolicy::Preferred + + + + 20 + 10 + + + + + + Qt::Horizontal @@ -1553,6 +1516,70 @@ color:#222; + + + + + 0 + 30 + + + + <html><head/><body><p>Reply to a CQ</p></body></html> + + + REPLY + + + + + + + + 75 + 30 + + + + <html><head/><body><p>Stop transmitting</p></body></html> + + + Halt + + + + + + + + 0 + 30 + + + + <html><head/><body><p>Send a saved message</p></body></html> + + + Saved + + + + + + + + 0 + 30 + + + + <html><head/><body><p>Send a directed message to another station</p></body></html> + + + Directed + + + @@ -1575,22 +1602,6 @@ color:#222; - - - - Qt::Horizontal - - - QSizePolicy::Preferred - - - - 20 - 10 - - - - @@ -4798,9 +4809,14 @@ list. The list can be maintained in Settings (F2). Mode - + + + + + + @@ -5725,23 +5741,15 @@ list. The list can be maintained in Settings (F2). Ctrl+Alt+A - + true true - - false - - JS8 - - - - - AUTO + JS8 (Normal, 15s, 50Hz, ~16 WPM) @@ -5749,23 +5757,47 @@ list. The list can be maintained in Settings (F2). true - Enable Networking && Autoreply + Enable Autoreply (AUTO) - + true - Messaging + JS8 (Fast, 10s, 80Hz, ~24 WPM) - + true - Heartbeat + JS8 (Turbo, 6s, 160Hz, ~40 WPM) + + + + + true + + + JS8 (Ultra, 4s, 250Hz, ~60WPM) + + + + + true + + + Enable Heartbeat Networking (HB) + + + + + true + + + Enable Heartbeat Acknowledgments (ACK) diff --git a/plotter.cpp b/plotter.cpp index 8309a04..de45141 100644 --- a/plotter.cpp +++ b/plotter.cpp @@ -7,6 +7,7 @@ #include #include "DriftingDateTime.h" +#include "varicode.h" #define MAX_SCREENSIZE 2048 @@ -411,7 +412,19 @@ void CPlotter::DrawOverlay() //DrawOverlay() } } - float bw=7.0*(double)RX_SAMPLE_RATE/(double)JS8_SYMBOL_SAMPLES; //JS8 + float bw = 0; + if(m_nSubMode == Varicode::JS8CallNormal){ + bw = 8.0*(double)RX_SAMPLE_RATE/(double)JS8A_SYMBOL_SAMPLES; + } + else if(m_nSubMode == Varicode::JS8CallFast){ + bw = 8.0*(double)RX_SAMPLE_RATE/(double)JS8B_SYMBOL_SAMPLES; + } + else if(m_nSubMode == Varicode::JS8CallTurbo){ + bw = 8.0*(double)RX_SAMPLE_RATE/(double)JS8C_SYMBOL_SAMPLES; + } + else if(m_nSubMode == Varicode::JS8CallUltra){ + bw = 8.0*(double)RX_SAMPLE_RATE/(double)JS8D_SYMBOL_SAMPLES; + } painter0.setPen(penGreen); diff --git a/varicode.cpp b/varicode.cpp index 76202e1..2e76048 100644 --- a/varicode.cpp +++ b/varicode.cpp @@ -499,7 +499,7 @@ QList>> Varicode::huffEncode(const QMap const &huff, QVector const& bitvec){ QString text; - QString bits = Varicode::bitsToStr(bitvec); //.mid(0, bitvec.length()-pad); + QString bits = Varicode::bitsToStr(bitvec); // TODO: jsherer - this is naive... while(bits.length() > 0){ @@ -1570,7 +1570,7 @@ QStringList Varicode::unpackDirectedMessage(const QString &text, quint8 *pType){ return unpacked; } -QString packHuffMessage(const QString &input, int *n){ +QString packHuffMessage(const QString &input, const QVector prefix, int *n){ static const int frameSize = 72; QString frame; @@ -1580,7 +1580,10 @@ QString packHuffMessage(const QString &input, int *n){ // but, since none of the other frame types start with a 0, we can drop the two zeros and use // them for encoding the first two bits of the actuall data sent. boom! // The second bit is a flag that indicates this is not compressed frame (huffman coding) - QVector frameBits = {true, false}; + QVector frameBits; + if(!prefix.isEmpty()){ + frameBits << prefix; + } int i = 0; @@ -1628,7 +1631,7 @@ QString packHuffMessage(const QString &input, int *n){ return frame; } -QString packCompressedMessage(const QString &input, int *n){ +QString packCompressedMessage(const QString &input, QVector prefix, int *n){ static const int frameSize = 72; QString frame; @@ -1638,7 +1641,11 @@ QString packCompressedMessage(const QString &input, int *n){ // but, since none of the other frame types start with a 1, we can drop the two zeros and use // them for encoding the first two bits of the actuall data sent. boom! // The second bit is a flag that indicates this is a compressed frame (dense coding) - QVector frameBits = {true, true}; + // For fast modes, we don't use the prefix since it is indicated by the JS8CallData flag. + QVector frameBits; + if(!prefix.isEmpty()){ + frameBits << prefix; + } int i = 0; foreach(auto pair, JSC::compress(input)){ @@ -1675,14 +1682,15 @@ QString packCompressedMessage(const QString &input, int *n){ return frame; } +// pack data message using 70 bits available flagged as data by the first 2 bits QString Varicode::packDataMessage(const QString &input, int *n){ QString huffFrame; int huffChars = 0; - huffFrame = packHuffMessage(input, &huffChars); + huffFrame = packHuffMessage(input, {true, false}, &huffChars); QString compressedFrame; int compressedChars = 0; - compressedFrame = packCompressedMessage(input, &compressedChars); + compressedFrame = packCompressedMessage(input, {true, true}, &compressedChars); if(huffChars > compressedChars){ if(n) *n = huffChars; @@ -1693,7 +1701,7 @@ QString Varicode::packDataMessage(const QString &input, int *n){ } } - +// unpack data message using 70 bits available flagged as data by the first 2 bits QString Varicode::unpackDataMessage(const QString &text){ QString unpacked; @@ -1713,8 +1721,9 @@ QString Varicode::unpackDataMessage(const QString &text){ bits = bits.mid(1); bool compressed = bits.at(0); - int n = bits.lastIndexOf(0); + + // trim off the pad bits bits = bits.mid(1, n-1); if(compressed){ @@ -1728,14 +1737,82 @@ QString Varicode::unpackDataMessage(const QString &text){ return unpacked; } +#define JS8_FAST_DATA_CAN_USE_HUFF 0 + +// pack data message using the full 72 bits available (with the data flag in the i3bit header) +QString Varicode::packFastDataMessage(const QString &input, int *n){ +#if JS8_FAST_DATA_CAN_USE_HUFF + QString huffFrame; + int huffChars = 0; + huffFrame = packHuffMessage(input, {false}, &huffChars); + + QString compressedFrame; + int compressedChars = 0; + compressedFrame = packCompressedMessage(input, {true}, &compressedChars); + + if(huffChars > compressedChars){ + if(n) *n = huffChars; + return huffFrame; + } else { + if(n) *n = compressedChars; + return compressedFrame; + } +#else + QString compressedFrame; + int compressedChars = 0; + compressedFrame = packCompressedMessage(input, {}, &compressedChars); + + if(n) *n = compressedChars; + return compressedFrame; +#endif +} + +// unpack data message using the full 72 bits available (with the data flag in the i3bit header) +QString Varicode::unpackFastDataMessage(const QString &text){ + QString unpacked; + + if(text.length() < 12 || text.contains(" ")){ + return unpacked; + } + + quint8 rem = 0; + quint64 value = Varicode::unpack72bits(text, &rem); + auto bits = Varicode::intToBits(value, 64) + Varicode::intToBits(rem, 8); + +#if JS8_FAST_DATA_CAN_USE_HUFF + bool compressed = bits.at(0); + int n = bits.lastIndexOf(0); + + // trim off the pad bits + bits = bits.mid(1, n-1); + + if(compressed){ + // partial word (s,c)-dense coding with code tables + unpacked = JSC::decompress(bits); + } else { + // huff decode the bits (without escapes) + unpacked = Varicode::huffDecode(Varicode::defaultHuffTable(), bits); + } +#else + int n = bits.lastIndexOf(0); + + // trim off the pad bits + bits = bits.mid(0, n); + + // partial word (s,c)-dense coding with code tables + unpacked = JSC::decompress(bits); +#endif + + return unpacked; +} + // TODO: remove the dependence on providing all this data? -QList> Varicode::buildMessageFrames( - QString const& mycall, +QList> Varicode::buildMessageFrames(QString const& mycall, QString const& mygrid, QString const& selectedCall, QString const& text, - bool forceIdentify -){ + bool forceIdentify, + int submode){ #define ALLOW_SEND_COMPOUND 1 #define ALLOW_SEND_COMPOUND_DIRECTED 1 #define AUTO_PREPEND_DIRECTED 1 @@ -1836,7 +1913,15 @@ QList> Varicode::buildMessageFrames( } #endif int m = 0; - QString datFrame = Varicode::packDataMessage(line, &m); + bool fastDataFrame = false; + QString datFrame; + if(submode == Varicode::JS8CallNormal){ + datFrame = Varicode::packDataMessage(line, &m); + fastDataFrame = false; + } else { + datFrame = Varicode::packFastDataMessage(line, &m); + fastDataFrame = true; + } // if this parses to a standard FT8 free text message // but it can be parsed as a directed message, then we @@ -1951,7 +2036,8 @@ QList> Varicode::buildMessageFrames( } if(useDat){ - lineFrames.append({ frame, Varicode::JS8Call }); + // use the standard data frame + lineFrames.append({ frame, fastDataFrame ? Varicode::JS8CallData : Varicode::JS8Call }); line = line.mid(m); } } @@ -1972,13 +2058,15 @@ BuildMessageFramesThread::BuildMessageFramesThread(const QString &mycall, const QString &selectedCall, const QString &text, bool forceIdentify, + int submode, QObject *parent): QThread(parent), m_mycall{mycall}, m_mygrid{mygrid}, m_selectedCall{selectedCall}, m_text{text}, - m_forceIdentify{forceIdentify} + m_forceIdentify{forceIdentify}, + m_submode{submode} { } @@ -1988,15 +2076,16 @@ void BuildMessageFramesThread::run(){ m_mygrid, m_selectedCall, m_text, - m_forceIdentify + m_forceIdentify, + m_submode ); // TODO: jsherer - we wouldn't normally use decodedtext.h here... but it's useful for computing the actual frames transmitted. QStringList textList; qDebug() << "frames:"; foreach(auto frame, results){ - auto dt = DecodedText(frame.first, frame.second); - qDebug() << "->" << frame << dt.message() << Varicode::frameTypeString(dt.frameType()); + auto dt = DecodedText(frame.first, frame.second, m_submode); + qDebug() << "->" << frame << dt.message() << Varicode::frameTypeString(dt.frameType()) << m_submode; textList.append(dt.message()); } diff --git a/varicode.h b/varicode.h index 685db4a..238db99 100644 --- a/varicode.h +++ b/varicode.h @@ -16,12 +16,20 @@ class Varicode { public: + // submode types + enum SubmodeType { + JS8CallNormal = 0, + JS8CallFast = 1, + JS8CallTurbo = 2, + JS8CallUltra = 3 + }; + // frame type transmitted via itype and decoded by the ft8 decoded enum TransmissionType { JS8Call = 0, // [000] <- any other frame of the message JS8CallFirst = 1, // [001] <- the first frame of a message JS8CallLast = 2, // [010] <- the last frame of a message - JS8CallFlag = 4, // [100] <- flagged frame (no frame type header) + JS8CallData = 4, // [100] <- flagged frame (no frame type header) }; /* @@ -156,11 +164,15 @@ public: static QString packDataMessage(QString const& text, int *n); static QString unpackDataMessage(QString const& text); + static QString packFastDataMessage(QString const& text, int *n); + static QString unpackFastDataMessage(QString const& text); + static QList> buildMessageFrames(QString const& mycall, QString const& mygrid, QString const& selectedCall, QString const& text, - bool forceIdentify); + bool forceIdentify, + int submode); }; @@ -173,6 +185,7 @@ public: QString const& selectedCall, QString const& text, bool forceIdentify, + int submode, QObject *parent=nullptr); void run() override; signals: @@ -184,6 +197,7 @@ private: QString m_selectedCall; QString m_text; bool m_forceIdentify; + int m_submode; }; #endif // VARICODE_H