diff --git a/ChangeLog b/ChangeLog index 6c3848b9..9e0bdb2d 100644 --- a/ChangeLog +++ b/ChangeLog @@ -1,3 +1,53 @@ +2013-01-10 David Freese + + d946848: High Speed / Multi-Carrier Modems + ce1d5c2: User configurable items + +2012-12-26 Makoto Fujiwara + + 2a22c31: NetBSD compile error + +2012-12-15 David Freese + + 6fe5fee: Dup Cty lookup + 2a3d1ae: Get RX buffer + 2004343: Util.h mod + 1884f2f: Capture Alt-F4 + 2719b0f: Macros LOG LNW EXEC + +2012-12-03 Remi Chateauneu + + 836c5c3: Progress widget + +2012-11-25 David Freese + + 2252cab: ARQ Socket + 5b9e09f: NBEMS modes + cb82ed8: Escape aborts + +2012-10-31 John Phelps + + 51db482: Allow xmit of EOT character + +2012-10-29 Andrej Lajovic + + 87afa66: UTF-8 overhaul + +2012-10-26 David Freese + + 600db9e: Thumbdrive + 0fa9396: TLF arq + 5ac5065: Logbook Dialogs + c17590e: ARQ rx/tx + 9006fde: View browser + 2a0f09d: FLAMP interface fix + +2012-10-04 Andrej Lajovic + + 7bdf035: UTF-8 wide characters + 6706da0: flarq bug fix + 1d7f8c2: Add_tx_char + 2012-10-03 David Freese d43f564: UI update diff --git a/src/Makefile.am b/src/Makefile.am index b921460b..c710c91c 100644 --- a/src/Makefile.am +++ b/src/Makefile.am @@ -597,6 +597,7 @@ EXTRA_fldigi_SOURCES += \ mt63/symbol.dat \ mt63/alias_k5.dat \ mt63/mt63intl.dat \ + rsid/rsid_defs.cxx \ trx/tune.cxx \ dialogs/guide.cxx \ widgets/Fl_Text_Buffer_mod_1_1.cxx \ diff --git a/src/dialogs/confdialog.cxx b/src/dialogs/confdialog.cxx index bda975d9..41b591fd 100644 --- a/src/dialogs/confdialog.cxx +++ b/src/dialogs/confdialog.cxx @@ -1941,20 +1941,6 @@ resetTHOR(); progdefaults.changed = true; } -Fl_Value_Slider2 *valThorCWI=(Fl_Value_Slider2 *)0; - -static void cb_valThorCWI(Fl_Value_Slider2* o, void*) { - progdefaults.ThorCWI = o->value(); -progdefaults.changed = true; -} - -Fl_Counter2 *valTHOR_PATHS=(Fl_Counter2 *)0; - -static void cb_valTHOR_PATHS(Fl_Counter2* o, void*) { - progdefaults.THOR_PATHS = (int)o->value(); -progdefaults.changed = true; -} - Fl_Check_Button *valTHOR_PREAMBLE=(Fl_Check_Button *)0; static void cb_valTHOR_PREAMBLE(Fl_Check_Button* o, void*) { @@ -1976,6 +1962,20 @@ static void cb_valTHOR_SOFTBITS(Fl_Check_Button* o, void*) { progdefaults.changed = true; } +Fl_Value_Slider2 *valThorCWI=(Fl_Value_Slider2 *)0; + +static void cb_valThorCWI(Fl_Value_Slider2* o, void*) { + progdefaults.ThorCWI = o->value(); +progdefaults.changed = true; +} + +Fl_Counter2 *valTHOR_PATHS=(Fl_Counter2 *)0; + +static void cb_valTHOR_PATHS(Fl_Counter2* o, void*) { + progdefaults.THOR_PATHS = (int)o->value(); +progdefaults.changed = true; +} + Fl_Group *tabPacket=(Fl_Group *)0; Fl_Choice *selPacket_Baud=(Fl_Choice *)0; @@ -3165,6 +3165,13 @@ static void cb_sldrRSIDsquelch(Fl_Value_Slider2* o, void*) { progdefaults.changed = true; } +Fl_Value_Slider2 *sldrRSIDresolution=(Fl_Value_Slider2 *)0; + +static void cb_sldrRSIDresolution(Fl_Value_Slider2* o, void*) { + progdefaults.rsid_resolution = (int)o->value(); +progdefaults.changed = true; +} + Fl_Button *bRSIDTxModes=(Fl_Button *)0; static void cb_bRSIDTxModes(Fl_Button* o, void*) { @@ -3720,13 +3727,14 @@ Fl_Double_Window* ConfigureDialog() { o->selection_color((Fl_Color)51); o->labelsize(18); o->align(Fl_Align(FL_ALIGN_CLIP|FL_ALIGN_INSIDE)); - { tabsConfigure = new Fl_Tabs(0, 0, 598, 370); + { tabsConfigure = new Fl_Tabs(0, 0, 599, 370); tabsConfigure->color(FL_LIGHT1); tabsConfigure->selection_color(FL_LIGHT1); - { tabOperator = new Fl_Group(0, 25, 598, 345, _("Operator")); + { tabOperator = new Fl_Group(1, 25, 598, 343, _("Operator")); tabOperator->tooltip(_("Operator information")); tabOperator->callback((Fl_Callback*)cb_tabOperator); tabOperator->when(FL_WHEN_CHANGED); + tabOperator->hide(); { Fl_Group* o = new Fl_Group(4, 35, 592, 165, _("Station")); o->box(FL_ENGRAVED_FRAME); o->align(Fl_Align(FL_ALIGN_TOP_LEFT|FL_ALIGN_INSIDE)); @@ -3833,11 +3841,12 @@ Fl_Double_Window* ConfigureDialog() { } // Fl_Group* grpNoise tabOperator->end(); } // Fl_Group* tabOperator - { tabUI = new Fl_Group(0, 25, 598, 345, _("UI")); + { tabUI = new Fl_Group(1, 25, 598, 345, _("UI")); tabUI->hide(); { tabsUI = new Fl_Tabs(2, 25, 596, 345); tabsUI->selection_color(FL_LIGHT1); - { tabBrowser = new Fl_Group(0, 50, 598, 320, _("Browser")); + { tabBrowser = new Fl_Group(2, 50, 596, 316, _("Browser")); + tabBrowser->hide(); { Fl_Group* o = new Fl_Group(6, 59, 588, 300); o->box(FL_ENGRAVED_FRAME); { Fl_Spinner2* o = cntChannels = new Fl_Spinner2(18, 69, 50, 24, _("Channels, first channel starts at waterfall lower limit")); @@ -3949,7 +3958,7 @@ Fl_Double_Window* ConfigureDialog() { } // Fl_Group* o tabBrowser->end(); } // Fl_Group* tabBrowser - { tabContest = new Fl_Group(0, 50, 598, 320, _("Contest")); + { tabContest = new Fl_Group(2, 50, 596, 316, _("Contest")); tabContest->hide(); { Fl_Group* o = new Fl_Group(8, 60, 584, 80, _("Exchanges")); o->box(FL_ENGRAVED_FRAME); @@ -4102,7 +4111,7 @@ Fl_Double_Window* ConfigureDialog() { } // Fl_Group* o tabContest->end(); } // Fl_Group* tabContest - { tabUserInterface = new Fl_Group(0, 50, 598, 320, _("General")); + { tabUserInterface = new Fl_Group(2, 50, 596, 316, _("General")); tabUserInterface->hide(); { Fl_Group* o = new Fl_Group(6, 55, 586, 76); o->box(FL_ENGRAVED_FRAME); @@ -4183,7 +4192,7 @@ ndow decoration close button pressed.")); } // Fl_Check_Button* btn2_confirm_exit o->end(); } // Fl_Group* o - { Fl_Group* o = new Fl_Group(6, 315, 586, 50, _("Check for updates")); + { Fl_Group* o = new Fl_Group(6, 315, 586, 48, _("Check for updates")); o->box(FL_ENGRAVED_FRAME); o->align(Fl_Align(FL_ALIGN_TOP_LEFT|FL_ALIGN_INSIDE)); { Fl_Check_Button* o = btn_check_for_updates = new Fl_Check_Button(47, 336, 383, 18, _("Check for updates when starting program")); @@ -4195,7 +4204,7 @@ ndow decoration close button pressed.")); } // Fl_Group* o tabUserInterface->end(); } // Fl_Group* tabUserInterface - { tabLogServer = new Fl_Group(0, 50, 598, 320, _("Logging")); + { tabLogServer = new Fl_Group(2, 50, 596, 316, _("Logging")); tabLogServer->hide(); { Fl_Group* o = new Fl_Group(6, 57, 586, 180, _("QSO logging")); o->box(FL_ENGRAVED_FRAME); @@ -4325,7 +4334,7 @@ ab and newline are automatically included.")); } // Fl_Input2* inpNonword o->end(); } // Fl_Group* o - { Fl_Group* o = new Fl_Group(6, 313, 586, 55, _("Client/Server Logbook")); + { Fl_Group* o = new Fl_Group(6, 313, 586, 51, _("Client/Server Logbook")); o->box(FL_ENGRAVED_FRAME); o->align(Fl_Align(FL_ALIGN_TOP_LEFT|FL_ALIGN_INSIDE)); { Fl_Input* o = xmllogServerAddress = new Fl_Input(157, 334, 100, 24, _("Address:")); @@ -4345,7 +4354,7 @@ ab and newline are automatically included.")); } // Fl_Group* o tabLogServer->end(); } // Fl_Group* tabLogServer - { tabMBars = new Fl_Group(0, 50, 598, 320, _("Macros")); + { tabMBars = new Fl_Group(2, 50, 596, 316, _("Macros")); tabMBars->hide(); { Fl_Group* o = new Fl_Group(6, 54, 586, 195, _("Number and position of macro bars")); o->box(FL_ENGRAVED_FRAME); @@ -4402,7 +4411,7 @@ ab and newline are automatically included.")); } // Fl_Check_Button* btnMacroMouseWheel o->end(); } // Fl_Group* o - { Fl_Group* o = new Fl_Group(6, 292, 586, 76); + { Fl_Group* o = new Fl_Group(6, 292, 586, 72); o->box(FL_ENGRAVED_FRAME); { Fl_Check_Button* o = btnUseLastMacro = new Fl_Check_Button(71, 298, 277, 20, _("Load last used macro file on startup")); btnUseLastMacro->tooltip(_("ON - use last set of macros\nOFF - use default set")); @@ -4426,8 +4435,7 @@ ab and newline are automatically included.")); } // Fl_Group* o tabMBars->end(); } // Fl_Group* tabMBars - { tabWF_UI = new Fl_Group(0, 50, 598, 320, _("WF Ctrls")); - tabWF_UI->hide(); + { tabWF_UI = new Fl_Group(2, 50, 596, 316, _("WF Ctrls")); { Fl_Group* o = new Fl_Group(6, 58, 586, 306); o->box(FL_ENGRAVED_BOX); { Fl_Box* o = new Fl_Box(31, 65, 446, 25, _("Enable check box to show each respective operator control")); @@ -4514,12 +4522,13 @@ ab and newline are automatically included.")); } // Fl_Tabs* tabsUI tabUI->end(); } // Fl_Group* tabUI - { tabWaterfall = new Fl_Group(0, 25, 598, 345, _("Waterfall")); + { tabWaterfall = new Fl_Group(1, 25, 598, 345, _("Waterfall")); tabWaterfall->hide(); { tabsWaterfall = new Fl_Tabs(2, 25, 596, 345); tabsWaterfall->color(FL_LIGHT1); tabsWaterfall->selection_color(FL_LIGHT1); - { Fl_Group* o = new Fl_Group(0, 50, 598, 320, _("Display")); + { Fl_Group* o = new Fl_Group(2, 50, 596, 316, _("Display")); + o->hide(); { Fl_Group* o = new Fl_Group(6, 60, 588, 194, _("Colors and cursors")); o->box(FL_ENGRAVED_FRAME); o->align(Fl_Align(FL_ALIGN_TOP_LEFT|FL_ALIGN_INSIDE)); @@ -4714,7 +4723,7 @@ ab and newline are automatically included.")); } // Fl_Group* o o->end(); } // Fl_Group* o - { Fl_Group* o = new Fl_Group(0, 50, 598, 320, _("FFT Processing")); + { Fl_Group* o = new Fl_Group(2, 50, 596, 316, _("FFT Processing")); o->hide(); { Fl_Group* o = new Fl_Group(6, 62, 588, 135); o->box(FL_ENGRAVED_FRAME); @@ -4825,8 +4834,7 @@ an merging")); } // Fl_Group* o o->end(); } // Fl_Group* o - { Fl_Group* o = new Fl_Group(0, 50, 598, 320, _("Mouse")); - o->hide(); + { Fl_Group* o = new Fl_Group(2, 50, 596, 316, _("Mouse")); { Fl_Group* o = new Fl_Group(6, 62, 588, 170); o->box(FL_ENGRAVED_FRAME); { Fl_Check_Button* o = btnWaterfallHistoryDefault = new Fl_Check_Button(69, 76, 340, 20, _("Left or right click always replays audio history")); @@ -4874,12 +4882,12 @@ an merging")); } // Fl_Tabs* tabsWaterfall tabWaterfall->end(); } // Fl_Group* tabWaterfall - { tabModems = new Fl_Group(0, 25, 598, 345, _("Modems")); - tabModems->hide(); - { tabsModems = new Fl_Tabs(0, 25, 598, 345, _("2")); + { tabModems = new Fl_Group(1, 25, 598, 343, _("Modems")); + { tabsModems = new Fl_Tabs(1, 25, 598, 343, _("2")); tabsModems->selection_color(FL_LIGHT1); tabsModems->align(Fl_Align(FL_ALIGN_TOP_RIGHT)); - { tabContestia = new Fl_Group(0, 50, 598, 320, _("Cntst\'")); + { tabContestia = new Fl_Group(2, 50, 596, 316, _("Cntst\'")); + tabContestia->hide(); { Fl_Group* o = new Fl_Group(6, 60, 588, 200, _("Contestia")); o->box(FL_ENGRAVED_FRAME); o->align(Fl_Align(FL_ALIGN_TOP_LEFT|FL_ALIGN_INSIDE)); @@ -4952,11 +4960,11 @@ an merging")); } // Fl_Group* o tabContestia->end(); } // Fl_Group* tabContestia - { tabCW = new Fl_Group(0, 50, 598, 320, _("CW")); + { tabCW = new Fl_Group(2, 50, 596, 316, _("CW")); tabCW->hide(); - { tabsCW = new Fl_Tabs(0, 50, 598, 320); + { tabsCW = new Fl_Tabs(2, 50, 596, 316); tabsCW->selection_color(FL_LIGHT1); - { Fl_Group* o = new Fl_Group(0, 75, 598, 295, _("General")); + { Fl_Group* o = new Fl_Group(4, 75, 592, 288, _("General")); o->align(Fl_Align(FL_ALIGN_TOP_LEFT)); { Fl_Group* o = new Fl_Group(6, 85, 588, 153, _("Receive")); o->box(FL_ENGRAVED_FRAME); @@ -5085,7 +5093,7 @@ an merging")); } // Fl_Box* o o->end(); } // Fl_Group* o - { Fl_Group* o = new Fl_Group(6, 239, 588, 126, _("Transmit")); + { Fl_Group* o = new Fl_Group(6, 239, 588, 123, _("Transmit")); o->box(FL_ENGRAVED_FRAME); o->align(Fl_Align(FL_ALIGN_TOP_LEFT|FL_ALIGN_INSIDE)); { Fl_Value_Slider2* o = sldrCWxmtWPM = new Fl_Value_Slider2(20, 267, 400, 20, _("TX WPM")); @@ -5183,7 +5191,7 @@ an merging")); } // Fl_Group* o o->end(); } // Fl_Group* o - { Fl_Group* o = new Fl_Group(0, 75, 598, 295, _("Timing and QSK")); + { Fl_Group* o = new Fl_Group(4, 75, 592, 288, _("Timing and QSK")); o->align(Fl_Align(FL_ALIGN_TOP_LEFT)); o->hide(); { Fl_Group* o = new Fl_Group(6, 85, 588, 120, _("Timing")); @@ -5329,7 +5337,7 @@ an merging")); } // Fl_Group* o o->end(); } // Fl_Group* o - { Fl_Group* o = new Fl_Group(0, 75, 598, 295, _("Prosigns")); + { Fl_Group* o = new Fl_Group(2, 75, 592, 289, _("Prosigns")); o->align(Fl_Align(FL_ALIGN_TOP_LEFT)); o->hide(); { Fl_Group* o = new Fl_Group(6, 84, 588, 280); @@ -5410,7 +5418,7 @@ an merging")); } // Fl_Tabs* tabsCW tabCW->end(); } // Fl_Group* tabCW - { tabDomEX = new Fl_Group(0, 50, 598, 320, _("Dom")); + { tabDomEX = new Fl_Group(2, 50, 596, 316, _("Dom")); tabDomEX->hide(); { Fl_Group* o = new Fl_Group(6, 60, 588, 180); o->box(FL_ENGRAVED_FRAME); @@ -5502,7 +5510,7 @@ an merging")); } // Fl_Group* o tabDomEX->end(); } // Fl_Group* tabDomEX - { tabFeld = new Fl_Group(0, 50, 598, 320, _("Feld")); + { tabFeld = new Fl_Group(2, 50, 596, 316, _("Feld")); tabFeld->hide(); { Fl_Group* o = new Fl_Group(6, 60, 588, 150); o->box(FL_ENGRAVED_FRAME); @@ -5589,7 +5597,7 @@ an merging")); } // Fl_Group* o tabFeld->end(); } // Fl_Group* tabFeld - { tabMT63 = new Fl_Group(0, 50, 598, 320, _("MT63")); + { tabMT63 = new Fl_Group(2, 50, 596, 316, _("MT63")); tabMT63->hide(); { Fl_Group* o = new Fl_Group(6, 60, 588, 115); o->box(FL_ENGRAVED_FRAME); @@ -5652,7 +5660,7 @@ an merging")); } // Fl_Group* o tabMT63->end(); } // Fl_Group* tabMT63 - { tabOlivia = new Fl_Group(0, 50, 598, 320, _("Olivia")); + { tabOlivia = new Fl_Group(2, 50, 596, 316, _("Olivia")); tabOlivia->hide(); { Fl_Group* o = new Fl_Group(6, 60, 588, 200); o->box(FL_ENGRAVED_FRAME); @@ -5724,7 +5732,7 @@ an merging")); } // Fl_Group* o tabOlivia->end(); } // Fl_Group* tabOlivia - { tabPSK = new Fl_Group(0, 50, 598, 320, _("PSK")); + { tabPSK = new Fl_Group(2, 50, 596, 316, _("PSK")); tabPSK->hide(); { Fl_Group* o = new Fl_Group(6, 60, 588, 98, _("AFC behavior")); o->box(FL_ENGRAVED_FRAME); @@ -5818,7 +5826,7 @@ an merging")); } // Fl_Group* o tabPSK->end(); } // Fl_Group* tabPSK - { tabRTTY = new Fl_Group(0, 50, 598, 320, _("RTTY")); + { tabRTTY = new Fl_Group(2, 50, 596, 316, _("RTTY")); tabRTTY->hide(); { Fl_Group* o = new Fl_Group(6, 60, 588, 300); o->box(FL_ENGRAVED_FRAME); @@ -6006,8 +6014,7 @@ an merging")); } // Fl_Group* o tabRTTY->end(); } // Fl_Group* tabRTTY - { tabTHOR = new Fl_Group(0, 50, 598, 320, _("Thor")); - tabTHOR->hide(); + { tabTHOR = new Fl_Group(2, 50, 596, 316, _("Thor")); { Fl_Group* o = new Fl_Group(5, 60, 588, 270); o->box(FL_ENGRAVED_FRAME); { txtTHORSecondary = new Fl_Input2(91, 87, 360, 40, _("Secondary Text")); @@ -6051,7 +6058,27 @@ an merging")); o->value(progdefaults.THOR_BW); o->labelsize(FL_NORMAL_SIZE); } // Fl_Counter2* valTHOR_BW - { Fl_Value_Slider2* o = valThorCWI = new Fl_Value_Slider2(89, 295, 260, 20, _("CWI threshold")); + { Fl_Check_Button* o = valTHOR_PREAMBLE = new Fl_Check_Button(90, 222, 200, 20, _("Preamble Detection")); + valTHOR_PREAMBLE->tooltip(_("Detect the THOR preamble (and clear the Rx pipeline in preparation for data)")); + valTHOR_PREAMBLE->down_box(FL_DOWN_BOX); + valTHOR_PREAMBLE->callback((Fl_Callback*)cb_valTHOR_PREAMBLE); + o->value(progdefaults.THOR_PREAMBLE); + } // Fl_Check_Button* valTHOR_PREAMBLE + { Fl_Check_Button* o = valTHOR_SOFTSYMBOLS = new Fl_Check_Button(90, 252, 190, 20, _("Soft-symbol decoding")); + valTHOR_SOFTSYMBOLS->tooltip(_("Use soft-decision decoding for symbol detection (also assists soft-bit decodi\ +ng)")); + valTHOR_SOFTSYMBOLS->down_box(FL_DOWN_BOX); + valTHOR_SOFTSYMBOLS->callback((Fl_Callback*)cb_valTHOR_SOFTSYMBOLS); + o->value(progdefaults.THOR_SOFTSYMBOLS); + } // Fl_Check_Button* valTHOR_SOFTSYMBOLS + { Fl_Check_Button* o = valTHOR_SOFTBITS = new Fl_Check_Button(90, 282, 170, 20, _("Soft-bit decoding")); + valTHOR_SOFTBITS->tooltip(_("Use soft-bit viterbi decoding for better Forward Error Correction (works best\ + with soft-symbol decoding enabled)")); + valTHOR_SOFTBITS->down_box(FL_DOWN_BOX); + valTHOR_SOFTBITS->callback((Fl_Callback*)cb_valTHOR_SOFTBITS); + o->value(progdefaults.THOR_SOFTBITS); + } // Fl_Check_Button* valTHOR_SOFTBITS + { Fl_Value_Slider2* o = valThorCWI = new Fl_Value_Slider2(90, 196, 260, 20, _("CWI threshold")); valThorCWI->tooltip(_("CWI detection and suppression")); valThorCWI->type(1); valThorCWI->box(FL_DOWN_BOX); @@ -6068,7 +6095,7 @@ an merging")); o->value(progdefaults.ThorCWI); o->labelsize(FL_NORMAL_SIZE); o->textsize(FL_NORMAL_SIZE); } // Fl_Value_Slider2* valThorCWI - { Fl_Counter2* o = valTHOR_PATHS = new Fl_Counter2(429, 193, 75, 21, _("Paths (hidden)")); + { Fl_Counter2* o = valTHOR_PATHS = new Fl_Counter2(468, 274, 75, 21, _("Paths (hidden)")); valTHOR_PATHS->type(1); valTHOR_PATHS->box(FL_UP_BOX); valTHOR_PATHS->color(FL_BACKGROUND_COLOR); @@ -6088,31 +6115,11 @@ an merging")); o->labelsize(FL_NORMAL_SIZE); o->hide(); } // Fl_Counter2* valTHOR_PATHS - { Fl_Check_Button* o = valTHOR_PREAMBLE = new Fl_Check_Button(90, 170, 200, 20, _("Preamble Detection")); - valTHOR_PREAMBLE->tooltip(_("Detect the THOR preamble (and clear the Rx pipeline in preparation for data)")); - valTHOR_PREAMBLE->down_box(FL_DOWN_BOX); - valTHOR_PREAMBLE->callback((Fl_Callback*)cb_valTHOR_PREAMBLE); - o->value(progdefaults.THOR_PREAMBLE); - } // Fl_Check_Button* valTHOR_PREAMBLE - { Fl_Check_Button* o = valTHOR_SOFTSYMBOLS = new Fl_Check_Button(90, 200, 190, 20, _("Soft-symbol decoding")); - valTHOR_SOFTSYMBOLS->tooltip(_("Use soft-decision decoding for symbol detection (also assists soft-bit decodi\ -ng)")); - valTHOR_SOFTSYMBOLS->down_box(FL_DOWN_BOX); - valTHOR_SOFTSYMBOLS->callback((Fl_Callback*)cb_valTHOR_SOFTSYMBOLS); - o->value(progdefaults.THOR_SOFTSYMBOLS); - } // Fl_Check_Button* valTHOR_SOFTSYMBOLS - { Fl_Check_Button* o = valTHOR_SOFTBITS = new Fl_Check_Button(90, 230, 170, 20, _("Soft-bit decoding")); - valTHOR_SOFTBITS->tooltip(_("Use soft-bit viterbi decoding for better Forward Error Correction (works best\ - with soft-symbol decoding enabled)")); - valTHOR_SOFTBITS->down_box(FL_DOWN_BOX); - valTHOR_SOFTBITS->callback((Fl_Callback*)cb_valTHOR_SOFTBITS); - o->value(progdefaults.THOR_SOFTBITS); - } // Fl_Check_Button* valTHOR_SOFTBITS o->end(); } // Fl_Group* o tabTHOR->end(); } // Fl_Group* tabTHOR - { tabPacket = new Fl_Group(0, 50, 598, 320, _("Packet")); + { tabPacket = new Fl_Group(2, 50, 596, 316, _("Packet")); tabPacket->hide(); { Fl_Group* o = new Fl_Group(6, 60, 588, 296); o->box(FL_ENGRAVED_FRAME); @@ -6253,7 +6260,7 @@ ng)")); } // Fl_Group* o tabPacket->end(); } // Fl_Group* tabPacket - { tabNavtex = new Fl_Group(0, 50, 598, 320, _("Navtex")); + { tabNavtex = new Fl_Group(2, 50, 596, 316, _("Navtex")); tabNavtex->hide(); { Fl_Group* o = new Fl_Group(6, 60, 588, 300); { Fl_Check_Button* o = btnNvtxAdifLog = new Fl_Check_Button(81, 87, 235, 30, _("Log Navtex messages to Adif file")); @@ -6275,7 +6282,7 @@ ng)")); } // Fl_Group* o tabNavtex->end(); } // Fl_Group* tabNavtex - { tabWefax = new Fl_Group(0, 50, 598, 320, _("Wefax")); + { tabWefax = new Fl_Group(2, 50, 596, 316, _("Wefax")); tabWefax->hide(); { Fl_Group* o = new Fl_Group(6, 60, 588, 300); { Fl_Check_Button* o = btnWefaxAdifLog = new Fl_Check_Button(97, 141, 235, 30, _("Log Wefax messages to Adif file")); @@ -6348,12 +6355,12 @@ ng)")); } // Fl_Tabs* tabsModems tabModems->end(); } // Fl_Group* tabModems - { tabRig = new Fl_Group(0, 25, 598, 345, _("Rig")); + { tabRig = new Fl_Group(1, 25, 598, 345, _("Rig")); tabRig->tooltip(_("Transceiver control")); tabRig->hide(); - { tabsRig = new Fl_Tabs(4, 25, 592, 345); + { tabsRig = new Fl_Tabs(2, 25, 596, 345); tabsRig->selection_color(FL_LIGHT1); - { Fl_Group* o = new Fl_Group(0, 50, 598, 320, _("Hardware PTT")); + { Fl_Group* o = new Fl_Group(2, 50, 596, 316, _("Hardware PTT")); { Fl_Group* o = new Fl_Group(6, 57, 588, 38); o->box(FL_ENGRAVED_FRAME); { Fl_Check_Button* o = btnPTTrightchannel = new Fl_Check_Button(175, 66, 250, 20, _("PTT tone on right audio channel ")); @@ -6439,7 +6446,7 @@ ng)")); } // Fl_Group* grpPTTdelays o->end(); } // Fl_Group* o - { Fl_Group* o = new Fl_Group(0, 50, 598, 320, _("RigCAT")); + { Fl_Group* o = new Fl_Group(2, 50, 596, 316, _("RigCAT")); o->tooltip(_("Rig Control using xml spec file")); o->hide(); { chkUSERIGCAT = new Fl_Check_Button(245, 58, 110, 20, _("Use RigCAT")); @@ -6602,7 +6609,7 @@ ng)")); } // Fl_Group* grpRigCAT o->end(); } // Fl_Group* o - { tabHamlib = new Fl_Group(0, 50, 598, 320, _("Hamlib")); + { tabHamlib = new Fl_Group(2, 50, 596, 316, _("Hamlib")); tabHamlib->hide(); { chkUSEHAMLIB = new Fl_Check_Button(250, 58, 100, 20, _("Use Hamlib")); chkUSEHAMLIB->tooltip(_("Hamlib used for rig control")); @@ -6811,7 +6818,7 @@ ng)")); } // Fl_Group* grpHamlib tabHamlib->end(); } // Fl_Group* tabHamlib - { Fl_Group* o = new Fl_Group(0, 50, 598, 320, _("MemMap")); + { Fl_Group* o = new Fl_Group(2, 50, 596, 316, _("MemMap")); o->hide(); { grpMemmap = new Fl_Group(6, 58, 588, 185); grpMemmap->box(FL_ENGRAVED_FRAME); @@ -6840,7 +6847,7 @@ ng)")); } // Fl_Group* grpMemmap o->end(); } // Fl_Group* o - { tabXMLRPC = new Fl_Group(0, 50, 598, 320, _("XML-RPC")); + { tabXMLRPC = new Fl_Group(2, 50, 596, 316, _("XML-RPC")); tabXMLRPC->hide(); { grpXMLRPC = new Fl_Group(6, 58, 588, 160); grpXMLRPC->box(FL_ENGRAVED_FRAME); @@ -6867,12 +6874,12 @@ ng)")); } // Fl_Tabs* tabsRig tabRig->end(); } // Fl_Group* tabRig - { tabSoundCard = new Fl_Group(0, 25, 598, 345, _("Audio")); + { tabSoundCard = new Fl_Group(1, 25, 598, 345, _("Audio")); tabSoundCard->tooltip(_("Audio devices")); tabSoundCard->hide(); { tabsSoundCard = new Fl_Tabs(2, 25, 596, 345); tabsSoundCard->selection_color(FL_LIGHT1); - { tabAudio = new Fl_Group(0, 50, 598, 320, _("Devices")); + { tabAudio = new Fl_Group(2, 50, 596, 316, _("Devices")); { AudioOSS = new Fl_Group(6, 60, 588, 45); AudioOSS->box(FL_ENGRAVED_FRAME); { btnAudioIO[0] = new Fl_Round_Button(15, 70, 53, 25, _("OSS")); @@ -6945,7 +6952,7 @@ ng)")); } // Fl_Group* AudioNull tabAudio->end(); } // Fl_Group* tabAudio - { tabAudioOpt = new Fl_Group(0, 50, 598, 320, _("Settings")); + { tabAudioOpt = new Fl_Group(2, 50, 596, 316, _("Settings")); tabAudioOpt->hide(); { grpAudioSampleRate = new Fl_Group(10, 60, 580, 90, _("Sample rate")); grpAudioSampleRate->box(FL_ENGRAVED_FRAME); @@ -7035,7 +7042,7 @@ ll with your audio device.")); } // Fl_Group* o tabAudioOpt->end(); } // Fl_Group* tabAudioOpt - { tabMixer = new Fl_Group(0, 50, 598, 320, _("Mixer")); + { tabMixer = new Fl_Group(2, 50, 596, 316, _("Mixer")); tabMixer->hide(); { Fl_Group* o = new Fl_Group(10, 57, 580, 145, _("OSS mixer")); o->box(FL_ENGRAVED_FRAME); @@ -7081,7 +7088,7 @@ ll with your audio device.")); } // Fl_Group* o tabMixer->end(); } // Fl_Group* tabMixer - { tabAudioRightChannel = new Fl_Group(0, 50, 598, 320, _("Right channel")); + { tabAudioRightChannel = new Fl_Group(2, 50, 596, 316, _("Right channel")); tabAudioRightChannel->hide(); { chkForceMono = new Fl_Check_Button(145, 66, 332, 20, _("Mono audio output")); chkForceMono->tooltip(_("Force output audio to single channel")); @@ -7132,7 +7139,7 @@ nce.\nYou may change the state from either location.\n...")); } // Fl_Tabs* tabsSoundCard tabSoundCard->end(); } // Fl_Group* tabSoundCard - { tabID = new Fl_Group(0, 25, 598, 345, _("ID")); + { tabID = new Fl_Group(1, 25, 598, 343, _("ID")); tabID->hide(); { Fl_Group* o = new Fl_Group(6, 35, 588, 103, _("Video Preamble ID")); o->box(FL_ENGRAVED_FRAME); @@ -7264,7 +7271,7 @@ nce.\nYou may change the state from either location.\n...")); chkRSidAutoDisable->value(progdefaults.rsid_auto_disable); if (progdefaults.rsid_notify_only) chkRSidAutoDisable->deactivate(); } // Fl_Check_Button* chkRSidAutoDisable - { chkRSidNotifyOnly = new Fl_Check_Button(44, 317, 155, 20, _("Notifications only")); + { chkRSidNotifyOnly = new Fl_Check_Button(44, 317, 155, 20, _("Notify only")); chkRSidNotifyOnly->tooltip(_("Check this to be notified when an RSID is received\nwithout changing modem an\ d frequency")); chkRSidNotifyOnly->down_box(FL_DOWN_BOX); @@ -7293,6 +7300,28 @@ d frequency")); o->value(progdefaults.rsid_squelch); o->labelsize(FL_NORMAL_SIZE); o->textsize(FL_NORMAL_SIZE); } // Fl_Value_Slider2* sldrRSIDsquelch + { Fl_Value_Slider2* o = sldrRSIDresolution = new Fl_Value_Slider2(133, 317, 90, 18, _("Sensitivity")); + sldrRSIDresolution->tooltip(_("2 = low sensitivity / decreased false detection\n5 = high sensitivity / incre\ +ased false detection")); + sldrRSIDresolution->type(1); + sldrRSIDresolution->box(FL_DOWN_BOX); + sldrRSIDresolution->color(FL_BACKGROUND_COLOR); + sldrRSIDresolution->selection_color(FL_BACKGROUND_COLOR); + sldrRSIDresolution->labeltype(FL_NORMAL_LABEL); + sldrRSIDresolution->labelfont(0); + sldrRSIDresolution->labelsize(14); + sldrRSIDresolution->labelcolor(FL_FOREGROUND_COLOR); + sldrRSIDresolution->minimum(2); + sldrRSIDresolution->maximum(5); + sldrRSIDresolution->step(1); + sldrRSIDresolution->value(5); + sldrRSIDresolution->textsize(14); + sldrRSIDresolution->callback((Fl_Callback*)cb_sldrRSIDresolution); + sldrRSIDresolution->align(Fl_Align(FL_ALIGN_RIGHT)); + sldrRSIDresolution->when(FL_WHEN_CHANGED); + o->value(progdefaults.rsid_resolution); + o->labelsize(FL_NORMAL_SIZE); o->textsize(FL_NORMAL_SIZE); + } // Fl_Value_Slider2* sldrRSIDresolution o->end(); } // Fl_Group* o { Fl_Group* o = new Fl_Group(340, 198, 253, 85, _("Reed-Solomon ID (Tx)")); @@ -7323,11 +7352,11 @@ d frequency")); } // Fl_Group* o tabID->end(); } // Fl_Group* tabID - { tabMisc = new Fl_Group(0, 25, 598, 345, _("Misc")); + { tabMisc = new Fl_Group(1, 25, 598, 345, _("Misc")); tabMisc->hide(); - { tabsMisc = new Fl_Tabs(4, 25, 592, 345); + { tabsMisc = new Fl_Tabs(2, 25, 596, 345); tabsMisc->selection_color(FL_LIGHT1); - { tabCPUspeed = new Fl_Group(0, 50, 598, 320, _("CPU")); + { tabCPUspeed = new Fl_Group(2, 50, 596, 316, _("CPU")); { Fl_Group* o = new Fl_Group(6, 60, 588, 51); o->box(FL_ENGRAVED_FRAME); o->align(Fl_Align(FL_ALIGN_TOP_LEFT|FL_ALIGN_INSIDE)); @@ -7341,7 +7370,7 @@ d frequency")); } // Fl_Group* o tabCPUspeed->end(); } // Fl_Group* tabCPUspeed - { tabNBEMS = new Fl_Group(0, 50, 598, 320, _("NBEMS")); + { tabNBEMS = new Fl_Group(2, 50, 596, 316, _("NBEMS")); tabNBEMS->hide(); { Fl_Group* o = new Fl_Group(6, 60, 588, 75, _("NBEMS data file interface")); o->box(FL_ENGRAVED_FRAME); @@ -7411,7 +7440,7 @@ d frequency")); } // Fl_Group* o tabNBEMS->end(); } // Fl_Group* tabNBEMS - { tabPskmail = new Fl_Group(0, 50, 598, 320, _("Pskmail")); + { tabPskmail = new Fl_Group(2, 50, 596, 316, _("Pskmail")); tabPskmail->align(Fl_Align(FL_ALIGN_TOP_LEFT)); tabPskmail->hide(); { Fl_Group* o = new Fl_Group(6, 58, 588, 174, _("Mail Server Attributes")); @@ -7518,7 +7547,7 @@ d frequency")); } // Fl_Group* o tabPskmail->end(); } // Fl_Group* tabPskmail - { tabSpot = new Fl_Group(0, 50, 598, 320, _("Spotting")); + { tabSpot = new Fl_Group(2, 50, 596, 316, _("Spotting")); tabSpot->hide(); { Fl_Group* o = new Fl_Group(6, 60, 588, 215, _("PSK Reporter")); o->box(FL_ENGRAVED_FRAME); @@ -7583,7 +7612,7 @@ d frequency")); } // Fl_Group* o tabSpot->end(); } // Fl_Group* tabSpot - { tabSweetSpot = new Fl_Group(0, 50, 598, 320, _("Sweet Spot")); + { tabSweetSpot = new Fl_Group(2, 50, 596, 316, _("Sweet Spot")); tabSweetSpot->hide(); { Fl_Group* o = new Fl_Group(6, 60, 588, 75); o->box(FL_ENGRAVED_FRAME); @@ -7674,7 +7703,7 @@ d frequency")); } // Fl_Group* o tabSweetSpot->end(); } // Fl_Group* tabSweetSpot - { tabText_IO = new Fl_Group(0, 50, 598, 320, _("Text i/o")); + { tabText_IO = new Fl_Group(2, 50, 596, 316, _("Text i/o")); tabText_IO->hide(); { grpTalker = new Fl_Group(6, 117, 588, 80, _("Talker Socket (MS only)")); grpTalker->box(FL_ENGRAVED_FRAME); @@ -7706,7 +7735,7 @@ d frequency")); } // Fl_Group* o tabText_IO->end(); } // Fl_Group* tabText_IO - { tabDTMFdecode = new Fl_Group(0, 50, 598, 320, _("DTMF")); + { tabDTMFdecode = new Fl_Group(2, 50, 596, 316, _("DTMF")); tabDTMFdecode->hide(); { Fl_Check_Button* o = chkDTMFdecode = new Fl_Check_Button(212, 85, 175, 20, _("Decode DTMF tones")); chkDTMFdecode->tooltip(_("Send rx text to file: textout.txt")); @@ -7716,7 +7745,7 @@ d frequency")); } // Fl_Check_Button* chkDTMFdecode tabDTMFdecode->end(); } // Fl_Group* tabDTMFdecode - { tabWX = new Fl_Group(0, 50, 598, 320, _("WX")); + { tabWX = new Fl_Group(2, 50, 596, 316, _("WX")); tabWX->hide(); { Fl_Group* o = new Fl_Group(6, 60, 588, 300, _("Weather query specification")); o->box(FL_ENGRAVED_FRAME); @@ -7801,12 +7830,12 @@ d frequency")); } // Fl_Tabs* tabsMisc tabMisc->end(); } // Fl_Group* tabMisc - { tabQRZ = new Fl_Group(0, 25, 598, 345, _("Web")); + { tabQRZ = new Fl_Group(1, 25, 598, 345, _("Web")); tabQRZ->tooltip(_("Callsign database")); tabQRZ->hide(); - { Fl_Tabs* o = new Fl_Tabs(4, 25, 592, 345); - { Fl_Group* o = new Fl_Group(0, 50, 598, 320, _("Call Lookup")); - { Fl_Group* o = new Fl_Group(6, 52, 588, 122, _("Web Browser lookup")); + { Fl_Tabs* o = new Fl_Tabs(2, 25, 596, 345); + { Fl_Group* o = new Fl_Group(2, 50, 596, 316, _("Call Lookup")); + { Fl_Group* o = new Fl_Group(6, 53, 588, 122, _("Web Browser lookup")); o->box(FL_ENGRAVED_FRAME); o->align(Fl_Align(FL_ALIGN_TOP_LEFT|FL_ALIGN_INSIDE)); { Fl_Round_Button* o = btnQRZWEBnotavailable = new Fl_Round_Button(168, 66, 337, 20, _("None")); @@ -7930,7 +7959,7 @@ d frequency")); } // Fl_Group* o o->end(); } // Fl_Group* o - { Fl_Group* o = new Fl_Group(0, 50, 598, 320, _("eQSL")); + { Fl_Group* o = new Fl_Group(2, 50, 596, 316, _("eQSL")); o->hide(); { Fl_Input2* o = inpEQSL_id = new Fl_Input2(225, 58, 150, 20, _("User ID")); inpEQSL_id->tooltip(_("Your login name")); diff --git a/src/dialogs/confdialog.fl b/src/dialogs/confdialog.fl index 5d9c613b..56d4910f 100644 --- a/src/dialogs/confdialog.fl +++ b/src/dialogs/confdialog.fl @@ -133,15 +133,15 @@ static const char szBaudRates[] = "300|600|1200|2400|4800|9600|19200|38400|57600 static const char szProsigns[] = "~|%|&|+|=|{|}|<|>|[|]| ";} {} Fl_Window {} { label {Fldigi configuration} open - xywh {604 62 600 400} type Double color 45 selection_color 51 labelsize 18 align 80 non_modal visible + xywh {598 533 600 400} type Double color 45 selection_color 51 labelsize 18 align 80 hide non_modal } { Fl_Tabs tabsConfigure {open - xywh {0 0 598 370} color 50 selection_color 50 + xywh {0 0 599 370} color 50 selection_color 50 } { Fl_Group tabOperator { label Operator - callback {progdefaults.changed = true;} selected - tooltip {Operator information} xywh {0 25 598 345} when 1 + callback {progdefaults.changed = true;} + tooltip {Operator information} xywh {1 25 598 343} when 1 hide } { Fl_Group {} { label Station open @@ -220,15 +220,15 @@ progdefaults.changed = true;} } } Fl_Group tabUI { - label UI - xywh {0 25 598 345} hide + label UI open + xywh {1 25 598 345} hide } { Fl_Tabs tabsUI {open xywh {2 25 596 345} selection_color 50 } { Fl_Group tabBrowser { label Browser - xywh {0 50 598 320} + xywh {2 50 596 316} hide } { Fl_Group {} {open xywh {6 59 588 300} box ENGRAVED_FRAME @@ -407,7 +407,7 @@ progdefaults.changed = true;} } Fl_Group tabContest { label Contest - xywh {0 50 598 320} hide + xywh {2 50 596 316} hide } { Fl_Group {} { label Exchanges open @@ -547,7 +547,7 @@ progdefaults.changed = true;} } Fl_Group tabUserInterface { label General open - xywh {0 50 598 320} hide + xywh {2 50 596 316} hide } { Fl_Group {} {open xywh {6 55 586 76} box ENGRAVED_FRAME @@ -649,7 +649,7 @@ progdefaults.changed = true;} } Fl_Group {} { label {Check for updates} open - xywh {6 315 586 50} box ENGRAVED_FRAME align 21 + xywh {6 315 586 48} box ENGRAVED_FRAME align 21 } { Fl_Check_Button btn_check_for_updates { label {Check for updates when starting program} @@ -662,7 +662,7 @@ progdefaults.changed = true;} } Fl_Group tabLogServer { label Logging - xywh {0 50 598 320} hide + xywh {2 50 596 316} hide } { Fl_Group {} { label {QSO logging} open @@ -791,7 +791,7 @@ defined here. Tab and newline are automatically included.} xywh {199 258 279 24} } Fl_Group {} { label {Client/Server Logbook} open - xywh {6 313 586 55} box ENGRAVED_FRAME align 21 + xywh {6 313 586 51} box ENGRAVED_FRAME align 21 } { Fl_Input xmllogServerAddress { label {Address:} @@ -815,7 +815,7 @@ connect_to_log_server();} } Fl_Group tabMBars { label Macros - xywh {0 50 598 320} hide + xywh {2 50 596 316} hide } { Fl_Group {} { label {Number and position of macro bars} open @@ -906,7 +906,7 @@ progdefaults.changed = true;} } } Fl_Group {} {open - xywh {6 292 586 76} box ENGRAVED_FRAME + xywh {6 292 586 72} box ENGRAVED_FRAME } { Fl_Check_Button btnUseLastMacro { label {Load last used macro file on startup} @@ -936,7 +936,7 @@ progdefaults.changed = true;} } Fl_Group tabWF_UI { label {WF Ctrls} - xywh {0 50 598 320} hide + xywh {2 50 596 316} } { Fl_Group {} {open xywh {6 58 586 306} box ENGRAVED_BOX @@ -1077,14 +1077,14 @@ WF_UI();} } Fl_Group tabWaterfall { label Waterfall - xywh {0 25 598 345} hide + xywh {1 25 598 345} hide } { Fl_Tabs tabsWaterfall {open xywh {2 25 596 345} color 50 selection_color 50 } { Fl_Group {} { label Display open - xywh {0 50 598 320} + xywh {2 50 596 316} hide } { Fl_Group {} { label {Colors and cursors} open @@ -1325,7 +1325,7 @@ progdefaults.changed = true;} } Fl_Group {} { label {FFT Processing} - xywh {0 50 598 320} hide + xywh {2 50 596 316} hide } { Fl_Group {} {open xywh {6 62 588 135} box ENGRAVED_FRAME @@ -1395,7 +1395,7 @@ progdefaults.changed = true;} } Fl_Group {} { label Mouse - xywh {0 50 598 320} hide + xywh {2 50 596 316} } { Fl_Group {} {open xywh {6 62 588 170} box ENGRAVED_FRAME @@ -1446,15 +1446,15 @@ behaves inside the waterfall} xywh {69 196 150 22} down_box BORDER_BOX align 8 } Fl_Group tabModems { label Modems open - xywh {0 25 598 345} hide + xywh {1 25 598 343} } { Fl_Tabs tabsModems { label 2 open - xywh {0 25 598 345} selection_color 50 align 9 + xywh {1 25 598 343} selection_color 50 align 9 } { Fl_Group tabContestia { label {Cntst'} - xywh {0 50 598 320} + xywh {2 50 596 316} hide } { Fl_Group {} { label Contestia @@ -1513,14 +1513,14 @@ progdefaults.changed = true;} } Fl_Group tabCW { label CW open - xywh {0 50 598 320} hide + xywh {2 50 596 316} hide } { Fl_Tabs tabsCW {open - xywh {0 50 598 320} selection_color 50 + xywh {2 50 596 316} selection_color 50 } { Fl_Group {} { label General - xywh {0 75 598 295} align 5 + xywh {4 75 592 288} align 5 } { Fl_Group {} { label Receive open @@ -1605,7 +1605,7 @@ progdefaults.changed = true;} } Fl_Group {} { label Transmit open - xywh {6 239 588 126} box ENGRAVED_FRAME align 21 + xywh {6 239 588 123} box ENGRAVED_FRAME align 21 } { Fl_Value_Slider sldrCWxmtWPM { label {TX WPM} @@ -1676,7 +1676,7 @@ progdefaults.changed = true;} } Fl_Group {} { label {Timing and QSK} - xywh {0 75 598 295} align 5 hide + xywh {4 75 592 288} align 5 hide } { Fl_Group {} { label Timing open @@ -1785,7 +1785,7 @@ progdefaults.changed = true;} } Fl_Group {} { label Prosigns - xywh {0 75 598 295} align 5 hide + xywh {2 75 592 289} align 5 hide } { Fl_Group {} {open xywh {6 84 588 280} box ENGRAVED_FRAME @@ -1956,7 +1956,7 @@ progdefaults.changed = true;} open } Fl_Group tabDomEX { label Dom - xywh {0 50 598 320} hide + xywh {2 50 596 316} hide } { Fl_Group {} {open xywh {6 60 588 180} box ENGRAVED_FRAME @@ -2017,7 +2017,7 @@ progdefaults.changed = true;} } Fl_Group tabFeld { label Feld - xywh {0 50 598 320} hide + xywh {2 50 596 316} hide } { Fl_Group {} {open xywh {6 60 588 150} box ENGRAVED_FRAME @@ -2090,7 +2090,7 @@ progdefaults.changed = true;} } Fl_Group tabMT63 { label MT63 - xywh {0 50 598 320} hide + xywh {2 50 596 316} hide } { Fl_Group {} {open xywh {6 60 588 115} box ENGRAVED_FRAME align 21 @@ -2165,7 +2165,7 @@ progdefaults.changed = true;} } Fl_Group tabOlivia { label Olivia - xywh {0 50 598 320} hide + xywh {2 50 596 316} hide } { Fl_Group {} {open xywh {6 60 588 200} box ENGRAVED_FRAME @@ -2223,7 +2223,7 @@ progdefaults.changed = true;} } Fl_Group tabPSK { label PSK - xywh {0 50 598 320} hide + xywh {2 50 596 316} hide } { Fl_Group {} { label {AFC behavior} open @@ -2290,7 +2290,7 @@ progdefaults.changed = true;} } Fl_Group tabRTTY { label RTTY - xywh {0 50 598 320} hide + xywh {2 50 596 316} hide } { Fl_Group {} {open xywh {6 60 588 300} box ENGRAVED_FRAME @@ -2481,8 +2481,8 @@ progdefaults.changed = true;} } } Fl_Group tabTHOR { - label Thor - xywh {0 50 598 320} hide + label Thor open + xywh {2 50 596 316} } { Fl_Group {} {open xywh {5 60 588 270} box ENGRAVED_FRAME @@ -2513,11 +2513,32 @@ progdefaults.changed = true;} code1 {o->labelsize(FL_NORMAL_SIZE);} class Fl_Counter2 } + Fl_Check_Button valTHOR_PREAMBLE { + label {Preamble Detection} + callback {progdefaults.THOR_PREAMBLE = o->value(); +progdefaults.changed = true;} + tooltip {Detect the THOR preamble (and clear the Rx pipeline in preparation for data)} xywh {90 222 200 20} down_box DOWN_BOX + code0 {o->value(progdefaults.THOR_PREAMBLE);} + } + Fl_Check_Button valTHOR_SOFTSYMBOLS { + label {Soft-symbol decoding} + callback {progdefaults.THOR_SOFTSYMBOLS = o->value(); +progdefaults.changed = true;} + tooltip {Use soft-decision decoding for symbol detection (also assists soft-bit decoding)} xywh {90 252 190 20} down_box DOWN_BOX + code0 {o->value(progdefaults.THOR_SOFTSYMBOLS);} + } + Fl_Check_Button valTHOR_SOFTBITS { + label {Soft-bit decoding} + callback {progdefaults.THOR_SOFTBITS = o->value(); +progdefaults.changed = true;} + tooltip {Use soft-bit viterbi decoding for better Forward Error Correction (works best with soft-symbol decoding enabled)} xywh {90 282 170 20} down_box DOWN_BOX + code0 {o->value(progdefaults.THOR_SOFTBITS);} + } Fl_Value_Slider valThorCWI { label {CWI threshold} callback {progdefaults.ThorCWI = o->value(); progdefaults.changed = true;} - tooltip {CWI detection and suppression} xywh {89 295 260 20} type Horizontal align 1 textsize 14 + tooltip {CWI detection and suppression} xywh {90 196 260 20} type Horizontal align 1 textsize 14 code0 {o->value(progdefaults.ThorCWI);} code1 {o->labelsize(FL_NORMAL_SIZE); o->textsize(FL_NORMAL_SIZE);} class Fl_Value_Slider2 @@ -2525,39 +2546,18 @@ progdefaults.changed = true;} Fl_Counter valTHOR_PATHS { label {Paths (hidden)} callback {progdefaults.THOR_PATHS = (int)o->value(); -progdefaults.changed = true;} - xywh {429 193 75 21} type Simple align 1 minimum 4 maximum 8 step 1 value 5 +progdefaults.changed = true;} selected + xywh {468 274 75 21} type Simple align 1 minimum 4 maximum 8 step 1 value 5 code0 {o->value(progdefaults.THOR_PATHS);} code1 {o->labelsize(FL_NORMAL_SIZE);} code2 {o->hide();} class Fl_Counter2 } - Fl_Check_Button valTHOR_PREAMBLE { - label {Preamble Detection} - callback {progdefaults.THOR_PREAMBLE = o->value(); -progdefaults.changed = true;} - tooltip {Detect the THOR preamble (and clear the Rx pipeline in preparation for data)} xywh {90 170 200 20} down_box DOWN_BOX - code0 {o->value(progdefaults.THOR_PREAMBLE);} - } - Fl_Check_Button valTHOR_SOFTSYMBOLS { - label {Soft-symbol decoding} - callback {progdefaults.THOR_SOFTSYMBOLS = o->value(); -progdefaults.changed = true;} - tooltip {Use soft-decision decoding for symbol detection (also assists soft-bit decoding)} xywh {90 200 190 20} down_box DOWN_BOX - code0 {o->value(progdefaults.THOR_SOFTSYMBOLS);} - } - Fl_Check_Button valTHOR_SOFTBITS { - label {Soft-bit decoding} - callback {progdefaults.THOR_SOFTBITS = o->value(); -progdefaults.changed = true;} - tooltip {Use soft-bit viterbi decoding for better Forward Error Correction (works best with soft-symbol decoding enabled)} xywh {90 230 170 20} down_box DOWN_BOX - code0 {o->value(progdefaults.THOR_SOFTBITS);} - } } } Fl_Group tabPacket { label Packet - xywh {0 50 598 320} hide + xywh {2 50 596 316} hide } { Fl_Group {} {open xywh {6 60 588 296} box ENGRAVED_FRAME @@ -2679,7 +2679,7 @@ progdefaults.changed = true;} } Fl_Group tabNavtex { label Navtex - xywh {0 50 598 320} hide + xywh {2 50 596 316} hide } { Fl_Group {} {open xywh {6 60 588 300} @@ -2709,7 +2709,7 @@ fc->show();} } Fl_Group tabWefax { label Wefax - xywh {0 50 598 320} hide + xywh {2 50 596 316} hide } { Fl_Group {} {open xywh {6 60 588 300} @@ -2782,14 +2782,14 @@ progdefaults.changed = true;} } Fl_Group tabRig { label Rig - tooltip {Transceiver control} xywh {0 25 598 345} hide + tooltip {Transceiver control} xywh {1 25 598 345} hide } { Fl_Tabs tabsRig {open - xywh {4 25 592 345} selection_color 50 + xywh {2 25 596 345} selection_color 50 } { Fl_Group {} { label {Hardware PTT} - xywh {0 50 598 320} + xywh {2 50 596 316} } { Fl_Group {} {open xywh {6 57 588 38} box ENGRAVED_FRAME @@ -2926,7 +2926,7 @@ progdefaults.changed = true;} } Fl_Group {} { label RigCAT - tooltip {Rig Control using xml spec file} xywh {0 50 598 320} hide + tooltip {Rig Control using xml spec file} xywh {2 50 596 316} hide } { Fl_Check_Button chkUSERIGCAT { label {Use RigCAT} @@ -3116,7 +3116,7 @@ btnRevertRIGCAT->activate();} } Fl_Group tabHamlib { label Hamlib - xywh {0 50 598 320} hide + xywh {2 50 596 316} hide } { Fl_Check_Button chkUSEHAMLIB { label {Use Hamlib} @@ -3317,7 +3317,7 @@ hamlib_restore_defaults(); } Fl_Group {} { label MemMap - xywh {0 50 598 320} hide + xywh {2 50 596 316} hide } { Fl_Group grpMemmap {open xywh {6 58 588 185} box ENGRAVED_FRAME @@ -3364,7 +3364,7 @@ progdefaults.changed = true;} } Fl_Group tabXMLRPC { label {XML-RPC} - xywh {0 50 598 320} hide + xywh {2 50 596 316} hide } { Fl_Group grpXMLRPC {open xywh {6 58 588 160} box ENGRAVED_FRAME @@ -3403,14 +3403,14 @@ progdefaults.changed = true;} } Fl_Group tabSoundCard { label Audio - tooltip {Audio devices} xywh {0 25 598 345} hide + tooltip {Audio devices} xywh {1 25 598 345} hide } { Fl_Tabs tabsSoundCard {open xywh {2 25 596 345} selection_color 50 } { Fl_Group tabAudio { label Devices - xywh {0 50 598 320} + xywh {2 50 596 316} } { Fl_Group AudioOSS { xywh {6 60 588 45} box ENGRAVED_FRAME @@ -3494,7 +3494,7 @@ resetSoundCard();} } Fl_Group tabAudioOpt { label Settings - xywh {0 50 598 320} hide + xywh {2 50 596 316} hide } { Fl_Group grpAudioSampleRate { label {Sample rate} open @@ -3575,7 +3575,7 @@ progdefaults.changed = true;} } Fl_Group tabMixer { label Mixer open - xywh {0 50 598 320} hide + xywh {2 50 596 316} hide } { Fl_Group {} { label {OSS mixer} open @@ -3640,7 +3640,7 @@ progdefaults.changed = true;} } Fl_Group tabAudioRightChannel { label {Right channel} open - xywh {0 50 598 320} hide + xywh {2 50 596 316} hide } { Fl_Check_Button chkForceMono { label {Mono audio output} @@ -3778,7 +3778,7 @@ if (o->value()) { } Fl_Group tabID { label ID open - xywh {0 25 598 345} hide + xywh {1 25 598 343} hide } { Fl_Group {} { label {Video Preamble ID} open @@ -3906,7 +3906,7 @@ progdefaults.changed = true;} code2 {if (progdefaults.rsid_notify_only) chkRSidAutoDisable->deactivate();} } Fl_Check_Button chkRSidNotifyOnly { - label {Notifications only} + label {Notify only} callback {progdefaults.rsid_notify_only = o->value(); notify_create_rsid_event(progdefaults.rsid_notify_only); if (progdefaults.rsid_notify_only) { @@ -3937,6 +3937,16 @@ progdefaults.changed = true;} code2 {o->labelsize(FL_NORMAL_SIZE); o->textsize(FL_NORMAL_SIZE);} class Fl_Value_Slider2 } + Fl_Value_Slider sldrRSIDresolution { + label Sensitivity + callback {progdefaults.rsid_resolution = (int)o->value(); +progdefaults.changed = true;} + tooltip {2 = low sensitivity / decreased false detection +5 = high sensitivity / increased false detection} xywh {133 317 90 18} type Horizontal align 8 minimum 2 maximum 5 step 1 value 5 textsize 14 + code0 {o->value(progdefaults.rsid_resolution);} + code2 {o->labelsize(FL_NORMAL_SIZE); o->textsize(FL_NORMAL_SIZE);} + class Fl_Value_Slider2 + } } Fl_Group {} { label {Reed-Solomon ID (Tx)} open @@ -3973,14 +3983,14 @@ progdefaults.changed = true;} } Fl_Group tabMisc { label Misc open - xywh {0 25 598 345} hide + xywh {1 25 598 345} hide } { Fl_Tabs tabsMisc {open - xywh {4 25 592 345} selection_color 50 + xywh {2 25 596 345} selection_color 50 } { Fl_Group tabCPUspeed { label CPU open - xywh {0 50 598 320} + xywh {2 50 596 316} } { Fl_Group {} {open xywh {6 60 588 51} box ENGRAVED_FRAME align 21 @@ -3996,7 +4006,7 @@ progdefaults.changed = true;} } Fl_Group tabNBEMS { label NBEMS open - xywh {0 50 598 320} hide + xywh {2 50 596 316} hide } { Fl_Group {} { label {NBEMS data file interface} open @@ -4059,7 +4069,7 @@ progdefaults.changed=true;} } Fl_Group tabPskmail { label Pskmail - xywh {0 50 598 320} align 5 hide + xywh {2 50 596 316} align 5 hide } { Fl_Group {} { label {Mail Server Attributes} open @@ -4126,7 +4136,7 @@ progdefaults.changed = true;} } Fl_Group tabSpot { label Spotting - xywh {0 50 598 320} hide + xywh {2 50 596 316} hide } { Fl_Group {} { label {PSK Reporter} open @@ -4202,7 +4212,7 @@ progdefaults.changed = true;} } Fl_Group tabSweetSpot { label {Sweet Spot} - xywh {0 50 598 320} hide + xywh {2 50 596 316} hide } { Fl_Group {} {open xywh {6 60 588 75} box ENGRAVED_FRAME align 21 @@ -4266,7 +4276,7 @@ progdefaults.changed=true;} } Fl_Group tabText_IO { label {Text i/o} - xywh {0 50 598 320} hide + xywh {2 50 596 316} hide } { Fl_Group grpTalker { label {Talker Socket (MS only)} open @@ -4306,7 +4316,7 @@ progdefaults.changed = true;} } Fl_Group tabDTMFdecode { label DTMF - xywh {0 50 598 320} hide + xywh {2 50 596 316} hide } { Fl_Check_Button chkDTMFdecode { label {Decode DTMF tones} @@ -4317,7 +4327,7 @@ progdefaults.changed = true;} } Fl_Group tabWX { label WX - xywh {0 50 598 320} hide + xywh {2 50 596 316} hide } { Fl_Group {} { label {Weather query specification} open @@ -4417,19 +4427,19 @@ progdefaults.changed = true;} } } Fl_Group tabQRZ { - label Web - tooltip {Callsign database} xywh {0 25 598 345} hide + label Web open + tooltip {Callsign database} xywh {1 25 598 345} hide } { Fl_Tabs {} {open - xywh {4 25 592 345} + xywh {2 25 596 345} } { Fl_Group {} { - label {Call Lookup} - xywh {0 50 598 320} + label {Call Lookup} open + xywh {2 50 596 316} } { Fl_Group {} { label {Web Browser lookup} open - xywh {6 52 588 122} box ENGRAVED_FRAME align 21 + xywh {6 53 588 122} box ENGRAVED_FRAME align 21 } { Fl_Round_Button btnQRZWEBnotavailable { label None @@ -4559,7 +4569,7 @@ o->label((inpQRZuserpassword->type() & FL_SECRET_INPUT) ? "Show" : "Hide");} } Fl_Group {} { label eQSL open - xywh {0 50 598 320} hide + xywh {2 50 596 316} hide } { Fl_Input inpEQSL_id { label {User ID} diff --git a/src/dialogs/fl_digi.cxx b/src/dialogs/fl_digi.cxx index 2e959167..406ecb30 100644 --- a/src/dialogs/fl_digi.cxx +++ b/src/dialogs/fl_digi.cxx @@ -436,13 +436,6 @@ bool clean_exit(bool ask); void cb_init_mode(Fl_Widget *, void *arg); -void cb_oliviaA(Fl_Widget *w, void *arg); -void cb_oliviaB(Fl_Widget *w, void *arg); -void cb_oliviaC(Fl_Widget *w, void *arg); -void cb_oliviaD(Fl_Widget *w, void *arg); -void cb_oliviaE(Fl_Widget *w, void *arg); -void cb_oliviaF(Fl_Widget *w, void *arg); -void cb_oliviaG(Fl_Widget *w, void *arg); void cb_oliviaCustom(Fl_Widget *w, void *arg); void cb_contestiaA(Fl_Widget *w, void *arg); @@ -477,6 +470,7 @@ Fl_Menu_Item quick_change_psk[] = { { mode_info[MODE_PSK125].name, 0, cb_init_mode, (void *)MODE_PSK125 }, { mode_info[MODE_PSK250].name, 0, cb_init_mode, (void *)MODE_PSK250 }, { mode_info[MODE_PSK500].name, 0, cb_init_mode, (void *)MODE_PSK500 }, + { mode_info[MODE_PSK1000].name, 0, cb_init_mode, (void *)MODE_PSK1000 }, { 0 } }; @@ -493,6 +487,46 @@ Fl_Menu_Item quick_change_pskr[] = { { mode_info[MODE_PSK125R].name, 0, cb_init_mode, (void *)MODE_PSK125R }, { mode_info[MODE_PSK250R].name, 0, cb_init_mode, (void *)MODE_PSK250R }, { mode_info[MODE_PSK500R].name, 0, cb_init_mode, (void *)MODE_PSK500R }, + { mode_info[MODE_PSK1000R].name, 0, cb_init_mode, (void *)MODE_PSK1000R }, + { 0 } +}; + +Fl_Menu_Item quick_change_psk_multiR[] = { + { mode_info[MODE_4X_PSK63R].name, 0, cb_init_mode, (void *)MODE_4X_PSK63R }, + { mode_info[MODE_5X_PSK63R].name, 0, cb_init_mode, (void *)MODE_5X_PSK63R }, + { mode_info[MODE_10X_PSK63R].name, 0, cb_init_mode, (void *)MODE_10X_PSK63R }, + { mode_info[MODE_20X_PSK63R].name, 0, cb_init_mode, (void *)MODE_20X_PSK63R }, + { mode_info[MODE_32X_PSK63R].name, 0, cb_init_mode, (void *)MODE_32X_PSK63R }, + + { mode_info[MODE_4X_PSK125R].name, 0, cb_init_mode, (void *)MODE_4X_PSK125R }, + { mode_info[MODE_5X_PSK125R].name, 0, cb_init_mode, (void *)MODE_5X_PSK125R }, + { mode_info[MODE_10X_PSK125R].name, 0, cb_init_mode, (void *)MODE_10X_PSK125R }, + { mode_info[MODE_12X_PSK125R].name, 0, cb_init_mode, (void *)MODE_12X_PSK125R }, + { mode_info[MODE_16X_PSK125R].name, 0, cb_init_mode, (void *)MODE_16X_PSK125R }, + + { mode_info[MODE_2X_PSK250R].name, 0, cb_init_mode, (void *)MODE_2X_PSK250R }, + { mode_info[MODE_3X_PSK250R].name, 0, cb_init_mode, (void *)MODE_3X_PSK250R }, + { mode_info[MODE_5X_PSK250R].name, 0, cb_init_mode, (void *)MODE_5X_PSK250R }, + { mode_info[MODE_6X_PSK250R].name, 0, cb_init_mode, (void *)MODE_6X_PSK250R }, + { mode_info[MODE_7X_PSK250R].name, 0, cb_init_mode, (void *)MODE_7X_PSK250R }, + + { mode_info[MODE_2X_PSK500R].name, 0, cb_init_mode, (void *)MODE_2X_PSK500R }, + { mode_info[MODE_3X_PSK500R].name, 0, cb_init_mode, (void *)MODE_3X_PSK500R }, + { mode_info[MODE_4X_PSK500R].name, 0, cb_init_mode, (void *)MODE_4X_PSK500R }, + + { mode_info[MODE_2X_PSK800R].name, 0, cb_init_mode, (void *)MODE_2X_PSK800R }, + + { mode_info[MODE_2X_PSK1000R].name, 0, cb_init_mode, (void *)MODE_2X_PSK1000R }, + { 0 } +}; + +Fl_Menu_Item quick_change_psk_multi[] = { + { mode_info[MODE_12X_PSK125].name, 0, cb_init_mode, (void *)MODE_12X_PSK125 }, + { mode_info[MODE_6X_PSK250].name, 0, cb_init_mode, (void *)MODE_6X_PSK250 }, + { mode_info[MODE_2X_PSK500].name, 0, cb_init_mode, (void *)MODE_2X_PSK500 }, + { mode_info[MODE_4X_PSK500].name, 0, cb_init_mode, (void *)MODE_4X_PSK500 }, + { mode_info[MODE_2X_PSK800].name, 0, cb_init_mode, (void *)MODE_2X_PSK800 }, + { mode_info[MODE_2X_PSK1000].name, 0, cb_init_mode, (void *)MODE_2X_PSK1000 }, { 0 } }; @@ -505,6 +539,7 @@ Fl_Menu_Item quick_change_mfsk[] = { { mode_info[MODE_MFSK31].name, 0, cb_init_mode, (void *)MODE_MFSK31 }, { mode_info[MODE_MFSK32].name, 0, cb_init_mode, (void *)MODE_MFSK32 }, { mode_info[MODE_MFSK64].name, 0, cb_init_mode, (void *)MODE_MFSK64 }, + { mode_info[MODE_MFSK128].name, 0, cb_init_mode, (void *)MODE_MFSK128 }, { 0 } }; @@ -534,8 +569,10 @@ Fl_Menu_Item quick_change_thor[] = { { mode_info[MODE_THOR11].name, 0, cb_init_mode, (void *)MODE_THOR11 }, { mode_info[MODE_THOR16].name, 0, cb_init_mode, (void *)MODE_THOR16 }, { mode_info[MODE_THOR22].name, 0, cb_init_mode, (void *)MODE_THOR22 }, - { mode_info[MODE_THOR44].name, 0, cb_init_mode, (void *)MODE_THOR44 }, - { mode_info[MODE_THOR88].name, 0, cb_init_mode, (void *)MODE_THOR88 }, + { mode_info[MODE_THOR25x4].name, 0, cb_init_mode, (void *)MODE_THOR25x4 }, + { mode_info[MODE_THOR50x1].name, 0, cb_init_mode, (void *)MODE_THOR50x1 }, + { mode_info[MODE_THOR50x2].name, 0, cb_init_mode, (void *)MODE_THOR50x2 }, + { mode_info[MODE_THOR100].name, 0, cb_init_mode, (void *)MODE_THOR100 }, { 0 } }; @@ -573,13 +610,15 @@ Fl_Menu_Item quick_change_throb[] = { }; Fl_Menu_Item quick_change_olivia[] = { - { "8/250", 0, cb_oliviaA, (void *)MODE_OLIVIA }, - { "4/500", 0, cb_oliviaF, (void *)MODE_OLIVIA }, - { "8/500", 0, cb_oliviaB, (void *)MODE_OLIVIA }, - { "16/500", 0, cb_oliviaC, (void *)MODE_OLIVIA }, - { "8/1000", 0, cb_oliviaD, (void *)MODE_OLIVIA }, - { "32/1000", 0, cb_oliviaE, (void *)MODE_OLIVIA }, - { "64/2000", 0, cb_oliviaG, (void *)MODE_OLIVIA }, + { mode_info[MODE_OLIVIA_4_250].name, 0, cb_init_mode, (void *)MODE_OLIVIA_4_250 }, + { mode_info[MODE_OLIVIA_8_250].name, 0, cb_init_mode, (void *)MODE_OLIVIA_8_250 }, + { mode_info[MODE_OLIVIA_4_500].name, 0, cb_init_mode, (void *)MODE_OLIVIA_4_500 }, + { mode_info[MODE_OLIVIA_8_500].name, 0, cb_init_mode, (void *)MODE_OLIVIA_8_500 }, + { mode_info[MODE_OLIVIA_16_500].name, 0, cb_init_mode, (void *)MODE_OLIVIA_16_500 }, + { mode_info[MODE_OLIVIA_8_1000].name, 0, cb_init_mode, (void *)MODE_OLIVIA_8_1000 }, + { mode_info[MODE_OLIVIA_16_1000].name, 0, cb_init_mode, (void *)MODE_OLIVIA_16_1000 }, + { mode_info[MODE_OLIVIA_32_1000].name, 0, cb_init_mode, (void *)MODE_OLIVIA_32_1000 }, + { mode_info[MODE_OLIVIA_64_2000].name, 0, cb_init_mode, (void *)MODE_OLIVIA_64_2000 }, { _("Custom..."), 0, cb_oliviaCustom, (void *)MODE_OLIVIA }, { 0 } }; @@ -641,62 +680,6 @@ void set_olivia_tab_widgets() set_olivia_default_integ(); } -void cb_oliviaA(Fl_Widget *w, void *arg) -{ - progdefaults.oliviatones = 2; - progdefaults.oliviabw = 1; - set_olivia_tab_widgets(); - cb_init_mode(w, arg); -} - -void cb_oliviaB(Fl_Widget *w, void *arg) -{ - progdefaults.oliviatones = 2; - progdefaults.oliviabw = 2; - set_olivia_tab_widgets(); - cb_init_mode(w, arg); -} - -void cb_oliviaC(Fl_Widget *w, void *arg) -{ - progdefaults.oliviatones = 3; - progdefaults.oliviabw = 2; - set_olivia_tab_widgets(); - cb_init_mode(w, arg); -} - -void cb_oliviaD(Fl_Widget *w, void *arg) -{ - progdefaults.oliviatones = 2; - progdefaults.oliviabw = 3; - set_olivia_tab_widgets(); - cb_init_mode(w, arg); -} - -void cb_oliviaE(Fl_Widget *w, void *arg) -{ - progdefaults.oliviatones = 4; - progdefaults.oliviabw = 3; - set_olivia_tab_widgets(); - cb_init_mode(w, arg); -} - -void cb_oliviaF(Fl_Widget *w, void *arg) -{ - progdefaults.oliviatones = 1; - progdefaults.oliviabw = 2; - set_olivia_tab_widgets(); - cb_init_mode(w, arg); -} - -void cb_oliviaG(Fl_Widget *w, void *arg) -{ - progdefaults.oliviatones = 5; - progdefaults.oliviabw = 4; - set_olivia_tab_widgets(); - cb_init_mode(w, arg); -} - void cb_oliviaCustom(Fl_Widget *w, void *arg) { modem_config_tab = tabOlivia; @@ -1162,7 +1145,7 @@ void init_modem(trx_mode mode, int freq) case MODE_THOR4: case MODE_THOR5: case MODE_THOR8: case MODE_THOR11:case MODE_THOR16: case MODE_THOR22: - case MODE_THOR44: case MODE_THOR88: + case MODE_THOR25x4: case MODE_THOR50x1: case MODE_THOR50x2: case MODE_THOR100: startup_modem(*mode_info[mode].modem ? *mode_info[mode].modem : *mode_info[mode].modem = new thor(mode), freq); quick_change = quick_change_thor; @@ -1199,6 +1182,7 @@ void init_modem(trx_mode mode, int freq) case MODE_MFSK8: case MODE_MFSK16: case MODE_MFSK32: + case MODE_MFSK128 : startup_modem(*mode_info[mode].modem ? *mode_info[mode].modem : *mode_info[mode].modem = new mfsk(mode), freq); quick_change = quick_change_mfsk; @@ -1229,6 +1213,7 @@ void init_modem(trx_mode mode, int freq) case MODE_PSK31: case MODE_PSK63: case MODE_PSK63F: case MODE_PSK125: case MODE_PSK250: case MODE_PSK500: + case MODE_PSK1000: startup_modem(*mode_info[mode].modem ? *mode_info[mode].modem : *mode_info[mode].modem = new psk(mode), freq); quick_change = quick_change_psk; @@ -1241,15 +1226,67 @@ void init_modem(trx_mode mode, int freq) modem_config_tab = tabPSK; break; case MODE_PSK125R: case MODE_PSK250R: case MODE_PSK500R: + case MODE_PSK1000R: startup_modem(*mode_info[mode].modem ? *mode_info[mode].modem : *mode_info[mode].modem = new psk(mode), freq); quick_change = quick_change_pskr; modem_config_tab = tabPSK; break; - case MODE_OLIVIA: + case MODE_12X_PSK125 : + case MODE_6X_PSK250 : + case MODE_2X_PSK500 : + case MODE_4X_PSK500 : + case MODE_2X_PSK800 : + case MODE_2X_PSK1000 : startup_modem(*mode_info[mode].modem ? *mode_info[mode].modem : - *mode_info[mode].modem = new olivia, freq); + *mode_info[mode].modem = new psk(mode), freq); + quick_change = quick_change_psk_multi; + modem_config_tab = tabPSK; + break; + + case MODE_4X_PSK63R : + case MODE_5X_PSK63R : + case MODE_10X_PSK63R : + case MODE_20X_PSK63R : + case MODE_32X_PSK63R : + + case MODE_4X_PSK125R : + case MODE_5X_PSK125R : + case MODE_10X_PSK125R : + case MODE_12X_PSK125R : + case MODE_16X_PSK125R : + + case MODE_2X_PSK250R : + case MODE_3X_PSK250R : + case MODE_5X_PSK250R : + case MODE_6X_PSK250R : + case MODE_7X_PSK250R : + + case MODE_2X_PSK500R : + case MODE_3X_PSK500R : + case MODE_4X_PSK500R : + + case MODE_2X_PSK800R : + case MODE_2X_PSK1000R : + startup_modem(*mode_info[mode].modem ? *mode_info[mode].modem : + *mode_info[mode].modem = new psk(mode), freq); + quick_change = quick_change_psk_multiR; + modem_config_tab = tabPSK; + break; + + case MODE_OLIVIA: + case MODE_OLIVIA_4_250: + case MODE_OLIVIA_8_250: + case MODE_OLIVIA_4_500: + case MODE_OLIVIA_8_500: + case MODE_OLIVIA_16_500: + case MODE_OLIVIA_8_1000: + case MODE_OLIVIA_16_1000: + case MODE_OLIVIA_32_1000: + case MODE_OLIVIA_64_2000: + startup_modem(*mode_info[mode].modem ? *mode_info[mode].modem : + *mode_info[mode].modem = new olivia(mode), freq); modem_config_tab = tabOlivia; quick_change = quick_change_olivia; break; @@ -2590,10 +2627,10 @@ int default_handler(int event) Fl_Widget* w = Fl::focus(); + int key = Fl::event_key(); if ((key == FL_F + 4) && Fl::event_alt()) clean_exit(true); if (w == fl_digi_main || w->window() == fl_digi_main) { - int key = Fl::event_key(); if (key == FL_Escape || (key >= FL_F && key <= FL_F_Last) || ((key == '1' || key == '2' || key == '3' || key == '4') && Fl::event_alt())) { TransmitText->take_focus(); @@ -3243,10 +3280,10 @@ Fl_Menu_Item menu_[] = { { mode_info[MODE_DOMINOEX5].name, 0, cb_init_mode, (void *)MODE_DOMINOEX5, 0, FL_NORMAL_LABEL, 0, 14, 0}, { mode_info[MODE_DOMINOEX8].name, 0, cb_init_mode, (void *)MODE_DOMINOEX8, 0, FL_NORMAL_LABEL, 0, 14, 0}, { mode_info[MODE_DOMINOEX11].name, 0, cb_init_mode, (void *)MODE_DOMINOEX11, 0, FL_NORMAL_LABEL, 0, 14, 0}, -{ mode_info[MODE_DOMINOEX16].name, 0, cb_init_mode, (void *)MODE_DOMINOEX16, 0, FL_NORMAL_LABEL, 0, 14, 0}, +{ mode_info[MODE_DOMINOEX16].name, 0, cb_init_mode, (void *)MODE_DOMINOEX16, FL_MENU_DIVIDER, FL_NORMAL_LABEL, 0, 14, 0}, { mode_info[MODE_DOMINOEX22].name, 0, cb_init_mode, (void *)MODE_DOMINOEX22, 0, FL_NORMAL_LABEL, 0, 14, 0}, -{ mode_info[MODE_DOMINOEX44].name, 0, cb_init_mode, (void *)MODE_DOMINOEX44, 0, FL_NORMAL_LABEL, 0, 14, 0}, -{ mode_info[MODE_DOMINOEX88].name, 0, cb_init_mode, (void *)MODE_DOMINOEX88, 0, FL_NORMAL_LABEL, 0, 14, 0}, +{ mode_info[MODE_DOMINOEX44].name, 0, cb_init_mode, (void *)MODE_DOMINOEX44, 0, FL_NORMAL_LABEL, 0, 14, 0}, +{ mode_info[MODE_DOMINOEX88].name, 0, cb_init_mode, (void *)MODE_DOMINOEX88, 0, FL_NORMAL_LABEL, 0, 14, 0}, {0,0,0,0,0,0,0,0,0}, {"Hell", 0, 0, 0, FL_SUBMENU, FL_NORMAL_LABEL, 0, 14, 0}, @@ -3264,10 +3301,11 @@ Fl_Menu_Item menu_[] = { { mode_info[MODE_MFSK8].name, 0, cb_init_mode, (void *)MODE_MFSK8, 0, FL_NORMAL_LABEL, 0, 14, 0}, { mode_info[MODE_MFSK11].name, 0, cb_init_mode, (void *)MODE_MFSK11, 0, FL_NORMAL_LABEL, 0, 14, 0}, { mode_info[MODE_MFSK16].name, 0, cb_init_mode, (void *)MODE_MFSK16, 0, FL_NORMAL_LABEL, 0, 14, 0}, -{ mode_info[MODE_MFSK22].name, 0, cb_init_mode, (void *)MODE_MFSK22, 0, FL_NORMAL_LABEL, 0, 14, 0}, +{ mode_info[MODE_MFSK22].name, 0, cb_init_mode, (void *)MODE_MFSK22, FL_MENU_DIVIDER, FL_NORMAL_LABEL, 0, 14, 0}, { mode_info[MODE_MFSK31].name, 0, cb_init_mode, (void *)MODE_MFSK31, 0, FL_NORMAL_LABEL, 0, 14, 0}, { mode_info[MODE_MFSK32].name, 0, cb_init_mode, (void *)MODE_MFSK32, 0, FL_NORMAL_LABEL, 0, 14, 0}, { mode_info[MODE_MFSK64].name, 0, cb_init_mode, (void *)MODE_MFSK64, 0, FL_NORMAL_LABEL, 0, 14, 0}, +{ mode_info[MODE_MFSK128].name, 0, cb_init_mode, (void *)MODE_MFSK128, 0, FL_NORMAL_LABEL, 0, 14, 0}, {0,0,0,0,0,0,0,0,0}, {"MT63", 0, 0, 0, FL_SUBMENU, FL_NORMAL_LABEL, 0, 14, 0}, @@ -3277,13 +3315,15 @@ Fl_Menu_Item menu_[] = { {0,0,0,0,0,0,0,0,0}, { OLIVIA_MLABEL, 0, 0, 0, FL_SUBMENU, FL_NORMAL_LABEL, 0, 14, 0}, -{ "8/250", 0, cb_oliviaA, (void *)MODE_OLIVIA, FL_MENU_DIVIDER, FL_NORMAL_LABEL, 0, 14, 0}, -{ "4/500", 0, cb_oliviaF, (void *)MODE_OLIVIA, 0, FL_NORMAL_LABEL, 0, 14, 0}, -{ "8/500", 0, cb_oliviaB, (void *)MODE_OLIVIA, 0, FL_NORMAL_LABEL, 0, 14, 0}, -{ "16/500", 0, cb_oliviaC, (void *)MODE_OLIVIA, FL_MENU_DIVIDER, FL_NORMAL_LABEL, 0, 14, 0}, -{ "8/1000", 0, cb_oliviaD, (void *)MODE_OLIVIA, 0, FL_NORMAL_LABEL, 0, 14, 0}, -{ "32/1000", 0, cb_oliviaE, (void *)MODE_OLIVIA, FL_MENU_DIVIDER, FL_NORMAL_LABEL, 0, 14, 0}, -{ "64/2000", 0, cb_oliviaG, (void *)MODE_OLIVIA, FL_MENU_DIVIDER, FL_NORMAL_LABEL, 0, 14, 0}, +{ mode_info[MODE_OLIVIA_4_250].name, 0, cb_init_mode, (void *)MODE_OLIVIA_4_250, 0, FL_NORMAL_LABEL, 0, 14, 0}, +{ mode_info[MODE_OLIVIA_8_250].name, 0, cb_init_mode, (void *)MODE_OLIVIA_8_250, 0, FL_NORMAL_LABEL, 0, 14, 0}, +{ mode_info[MODE_OLIVIA_4_500].name, 0, cb_init_mode, (void *)MODE_OLIVIA_4_500, 0, FL_NORMAL_LABEL, 0, 14, 0}, +{ mode_info[MODE_OLIVIA_8_500].name, 0, cb_init_mode, (void *)MODE_OLIVIA_8_500, 0, FL_NORMAL_LABEL, 0, 14, 0}, +{ mode_info[MODE_OLIVIA_16_500].name, 0, cb_init_mode, (void *)MODE_OLIVIA_16_500, 0, FL_NORMAL_LABEL, 0, 14, 0}, +{ mode_info[MODE_OLIVIA_8_1000].name, 0, cb_init_mode, (void *)MODE_OLIVIA_8_1000, 0, FL_NORMAL_LABEL, 0, 14, 0}, +{ mode_info[MODE_OLIVIA_16_1000].name, 0, cb_init_mode, (void *)MODE_OLIVIA_16_1000, 0, FL_NORMAL_LABEL, 0, 14, 0}, +{ mode_info[MODE_OLIVIA_32_1000].name, 0, cb_init_mode, (void *)MODE_OLIVIA_32_1000, 0, FL_NORMAL_LABEL, 0, 14, 0}, +{ mode_info[MODE_OLIVIA_64_2000].name, 0, cb_init_mode, (void *)MODE_OLIVIA_64_2000, 0, FL_NORMAL_LABEL, 0, 14, 0}, { _("Custom..."), 0, cb_oliviaCustom, (void *)MODE_OLIVIA, 0, FL_NORMAL_LABEL, 0, 14, 0}, {0,0,0,0,0,0,0,0,0}, @@ -3294,6 +3334,15 @@ Fl_Menu_Item menu_[] = { { mode_info[MODE_PSK125].name, 0, cb_init_mode, (void *)MODE_PSK125, 0, FL_NORMAL_LABEL, 0, 14, 0}, { mode_info[MODE_PSK250].name, 0, cb_init_mode, (void *)MODE_PSK250, 0, FL_NORMAL_LABEL, 0, 14, 0}, { mode_info[MODE_PSK500].name, 0, cb_init_mode, (void *)MODE_PSK500, 0, FL_NORMAL_LABEL, 0, 14, 0}, +{ mode_info[MODE_PSK1000].name, 0, cb_init_mode, (void *)MODE_PSK1000, 0, FL_NORMAL_LABEL, 0, 14, 0}, +{"MultiCarrier", 0, 0, 0, FL_SUBMENU, FL_NORMAL_LABEL, 0, 14, 0}, +{ mode_info[MODE_12X_PSK125].name, 0, cb_init_mode, (void *)MODE_12X_PSK125, FL_MENU_DIVIDER, FL_NORMAL_LABEL, 0, 14, 0}, +{ mode_info[MODE_6X_PSK250].name, 0, cb_init_mode, (void *)MODE_6X_PSK250, FL_MENU_DIVIDER, FL_NORMAL_LABEL, 0, 14, 0}, +{ mode_info[MODE_2X_PSK500].name, 0, cb_init_mode, (void *)MODE_2X_PSK500, 0, FL_NORMAL_LABEL, 0, 14, 0}, +{ mode_info[MODE_4X_PSK500].name, 0, cb_init_mode, (void *)MODE_4X_PSK500, FL_MENU_DIVIDER, FL_NORMAL_LABEL, 0, 14, 0}, +{ mode_info[MODE_2X_PSK800].name, 0, cb_init_mode, (void *)MODE_2X_PSK800, FL_MENU_DIVIDER, FL_NORMAL_LABEL, 0, 14, 0}, +{ mode_info[MODE_2X_PSK1000].name, 0, cb_init_mode, (void *)MODE_2X_PSK1000, 0, FL_NORMAL_LABEL, 0, 14, 0}, +{0,0,0,0,0,0,0,0,0}, {0,0,0,0,0,0,0,0,0}, {"QPSK", 0, 0, 0, FL_SUBMENU, FL_NORMAL_LABEL, 0, 14, 0}, @@ -3308,6 +3357,29 @@ Fl_Menu_Item menu_[] = { { mode_info[MODE_PSK125R].name, 0, cb_init_mode, (void *)MODE_PSK125R, 0, FL_NORMAL_LABEL, 0, 14, 0}, { mode_info[MODE_PSK250R].name, 0, cb_init_mode, (void *)MODE_PSK250R, 0, FL_NORMAL_LABEL, 0, 14, 0}, { mode_info[MODE_PSK500R].name, 0, cb_init_mode, (void *)MODE_PSK500R, 0, FL_NORMAL_LABEL, 0, 14, 0}, +{ mode_info[MODE_PSK1000R].name, 0, cb_init_mode, (void *)MODE_PSK1000R, 0, FL_NORMAL_LABEL, 0, 14, 0}, +{"MultiCarrier", 0, 0, 0, FL_SUBMENU, FL_NORMAL_LABEL, 0, 14, 0}, +{ mode_info[MODE_4X_PSK63R].name, 0, cb_init_mode, (void *)MODE_4X_PSK63R, 0, FL_NORMAL_LABEL, 0, 14, 0}, +{ mode_info[MODE_5X_PSK63R].name, 0, cb_init_mode, (void *)MODE_5X_PSK63R, 0, FL_NORMAL_LABEL, 0, 14, 0}, +{ mode_info[MODE_10X_PSK63R].name, 0, cb_init_mode, (void *)MODE_10X_PSK63R, 0, FL_NORMAL_LABEL, 0, 14, 0}, +{ mode_info[MODE_20X_PSK63R].name, 0, cb_init_mode, (void *)MODE_20X_PSK63R, 0, FL_NORMAL_LABEL, 0, 14, 0}, +{ mode_info[MODE_32X_PSK63R].name, 0, cb_init_mode, (void *)MODE_32X_PSK63R, FL_MENU_DIVIDER, FL_NORMAL_LABEL, 0, 14, 0}, +{ mode_info[MODE_4X_PSK125R].name, 0, cb_init_mode, (void *)MODE_4X_PSK125R, 0, FL_NORMAL_LABEL, 0, 14, 0}, +{ mode_info[MODE_5X_PSK125R].name, 0, cb_init_mode, (void *)MODE_5X_PSK125R, 0, FL_NORMAL_LABEL, 0, 14, 0}, +{ mode_info[MODE_10X_PSK125R].name, 0, cb_init_mode, (void *)MODE_10X_PSK125R, 0, FL_NORMAL_LABEL, 0, 14, 0}, +{ mode_info[MODE_12X_PSK125R].name, 0, cb_init_mode, (void *)MODE_12X_PSK125R, 0, FL_NORMAL_LABEL, 0, 14, 0}, +{ mode_info[MODE_16X_PSK125R].name, 0, cb_init_mode, (void *)MODE_16X_PSK125R, FL_MENU_DIVIDER, FL_NORMAL_LABEL, 0, 14, 0}, +{ mode_info[MODE_2X_PSK250R].name, 0, cb_init_mode, (void *)MODE_2X_PSK250R, 0, FL_NORMAL_LABEL, 0, 14, 0}, +{ mode_info[MODE_3X_PSK250R].name, 0, cb_init_mode, (void *)MODE_3X_PSK250R, 0, FL_NORMAL_LABEL, 0, 14, 0}, +{ mode_info[MODE_5X_PSK250R].name, 0, cb_init_mode, (void *)MODE_5X_PSK250R, 0, FL_NORMAL_LABEL, 0, 14, 0}, +{ mode_info[MODE_6X_PSK250R].name, 0, cb_init_mode, (void *)MODE_6X_PSK250R, 0, FL_NORMAL_LABEL, 0, 14, 0}, +{ mode_info[MODE_7X_PSK250R].name, 0, cb_init_mode, (void *)MODE_7X_PSK250R, FL_MENU_DIVIDER, FL_NORMAL_LABEL, 0, 14, 0}, +{ mode_info[MODE_2X_PSK500R].name, 0, cb_init_mode, (void *)MODE_2X_PSK500R, 0, FL_NORMAL_LABEL, 0, 14, 0}, +{ mode_info[MODE_3X_PSK500R].name, 0, cb_init_mode, (void *)MODE_3X_PSK500R, 0, FL_NORMAL_LABEL, 0, 14, 0}, +{ mode_info[MODE_4X_PSK500R].name, 0, cb_init_mode, (void *)MODE_4X_PSK500R, FL_MENU_DIVIDER, FL_NORMAL_LABEL, 0, 14, 0}, +{ mode_info[MODE_2X_PSK800R].name, 0, cb_init_mode, (void *)MODE_2X_PSK800R, FL_MENU_DIVIDER, FL_NORMAL_LABEL, 0, 14, 0}, +{ mode_info[MODE_2X_PSK1000R].name, 0, cb_init_mode, (void *)MODE_2X_PSK1000R, 0, FL_NORMAL_LABEL, 0, 14, 0}, +{0,0,0,0,0,0,0,0,0}, {0,0,0,0,0,0,0,0,0}, { RTTY_MLABEL, 0, 0, 0, FL_SUBMENU, FL_NORMAL_LABEL, 0, 14, 0}, @@ -3323,10 +3395,12 @@ Fl_Menu_Item menu_[] = { { mode_info[MODE_THOR5].name, 0, cb_init_mode, (void *)MODE_THOR5, 0, FL_NORMAL_LABEL, 0, 14, 0}, { mode_info[MODE_THOR8].name, 0, cb_init_mode, (void *)MODE_THOR8, 0, FL_NORMAL_LABEL, 0, 14, 0}, { mode_info[MODE_THOR11].name, 0, cb_init_mode, (void *)MODE_THOR11, 0, FL_NORMAL_LABEL, 0, 14, 0}, -{ mode_info[MODE_THOR16].name, 0, cb_init_mode, (void *)MODE_THOR16, 0, FL_NORMAL_LABEL, 0, 14, 0}, +{ mode_info[MODE_THOR16].name, 0, cb_init_mode, (void *)MODE_THOR16, FL_MENU_DIVIDER, FL_NORMAL_LABEL, 0, 14, 0}, { mode_info[MODE_THOR22].name, 0, cb_init_mode, (void *)MODE_THOR22, 0, FL_NORMAL_LABEL, 0, 14, 0}, -{ mode_info[MODE_THOR44].name, 0, cb_init_mode, (void *)MODE_THOR44, 0, FL_NORMAL_LABEL, 0, 14, 0}, -{ mode_info[MODE_THOR88].name, 0, cb_init_mode, (void *)MODE_THOR88, 0, FL_NORMAL_LABEL, 0, 14, 0}, +{ mode_info[MODE_THOR25x4].name, 0, cb_init_mode, (void *)MODE_THOR25x4, 0, FL_NORMAL_LABEL, 0, 14, 0}, +{ mode_info[MODE_THOR50x1].name, 0, cb_init_mode, (void *)MODE_THOR50x1, 0, FL_NORMAL_LABEL, 0, 14, 0}, +{ mode_info[MODE_THOR50x2].name, 0, cb_init_mode, (void *)MODE_THOR50x2, 0, FL_NORMAL_LABEL, 0, 14, 0}, +{ mode_info[MODE_THOR100].name, 0, cb_init_mode, (void *)MODE_THOR100, 0, FL_NORMAL_LABEL, 0, 14, 0}, {0,0,0,0,0,0,0,0,0}, {"Throb", 0, 0, 0, FL_SUBMENU, FL_NORMAL_LABEL, 0, 14, 0}, @@ -3347,17 +3421,17 @@ Fl_Menu_Item menu_[] = { { mode_info[MODE_WEFAX_288].name, 0, cb_init_mode, (void *)MODE_WEFAX_288, 0, FL_NORMAL_LABEL, 0, 14, 0}, {0,0,0,0,0,0,0,0,0}, -{"Navtex/SitorB", 0, 0, 0, FL_SUBMENU, FL_NORMAL_LABEL, 0, 14, 0}, +{"Navtex/SitorB", 0, 0, 0, FL_SUBMENU | FL_MENU_DIVIDER, FL_NORMAL_LABEL, 0, 14, 0}, { mode_info[MODE_NAVTEX].name, 0, cb_init_mode, (void *)MODE_NAVTEX, 0, FL_NORMAL_LABEL, 0, 14, 0}, { mode_info[MODE_SITORB].name, 0, cb_init_mode, (void *)MODE_SITORB, 0, FL_NORMAL_LABEL, 0, 14, 0}, {0,0,0,0,0,0,0,0,0}, +{ mode_info[MODE_WWV].name, 0, cb_init_mode, (void *)MODE_WWV, 0, FL_NORMAL_LABEL, 0, 14, 0}, +{ mode_info[MODE_ANALYSIS].name, 0, cb_init_mode, (void *)MODE_ANALYSIS, FL_MENU_DIVIDER, FL_NORMAL_LABEL, 0, 14, 0}, + { mode_info[MODE_NULL].name, 0, cb_init_mode, (void *)MODE_NULL, 0, FL_NORMAL_LABEL, 0, 14, 0}, { mode_info[MODE_SSB].name, 0, cb_init_mode, (void *)MODE_SSB, 0, FL_NORMAL_LABEL, 0, 14, 0}, -{ mode_info[MODE_WWV].name, 0, cb_init_mode, (void *)MODE_WWV, 0, FL_NORMAL_LABEL, 0, 14, 0}, - -{ mode_info[MODE_ANALYSIS].name, 0, cb_init_mode, (void *)MODE_ANALYSIS, 0, FL_NORMAL_LABEL, 0, 14, 0}, { OPMODES_FEWER, 0, cb_opmode_show, 0, FL_MENU_INVISIBLE, FL_NORMAL_LABEL, FL_HELVETICA_ITALIC, 14, 0 }, {0,0,0,0,0,0,0,0,0}, @@ -3366,7 +3440,8 @@ Fl_Menu_Item menu_[] = { { make_icon_label(_("Colors && Fonts"), preferences_desktop_font_icon), 0, (Fl_Callback*)cb_mnuConfigFonts, 0, 0, _FL_MULTI_LABEL, 0, 14, 0}, { make_icon_label(_("User Interface")), 0, (Fl_Callback*)cb_mnuUI, 0, 0, _FL_MULTI_LABEL, 0, 14, 0}, { make_icon_label(_("Waterfall"), waterfall_icon), 0, (Fl_Callback*)cb_mnuConfigWaterfall, 0, 0, _FL_MULTI_LABEL, 0, 14, 0}, -{ make_icon_label(_("Waterfall controls")), 0, (Fl_Callback*)cb_mnuConfigWFcontrols, 0, FL_MENU_DIVIDER, _FL_MULTI_LABEL, 0, 14, 0}, +{ make_icon_label(_("Waterfall controls")), 0, (Fl_Callback*)cb_mnuConfigWFcontrols, 0, FL_MENU_DIVIDER, +_FL_MULTI_LABEL, 0, 14, 0}, { make_icon_label(_("Modems"), emblems_system_icon), 0, (Fl_Callback*)cb_mnuConfigModems, 0, 0, _FL_MULTI_LABEL, 0, 14, 0}, { make_icon_label(RIGCONTROL_MLABEL, multimedia_player_icon), 0, (Fl_Callback*)cb_mnuConfigRigCtrl, 0, 0, _FL_MULTI_LABEL, 0, 14, 0}, { make_icon_label(_("Sound Card"), audio_card_icon), 0, (Fl_Callback*)cb_mnuConfigSoundCard, 0, FL_MENU_DIVIDER, _FL_MULTI_LABEL, 0, 14, 0}, @@ -5348,13 +5423,15 @@ Fl_Menu_Item alt_menu_[] = { {0,0,0,0,0,0,0,0,0}, {"Olivia", 0, 0, 0, FL_SUBMENU, FL_NORMAL_LABEL, 0, 14, 0}, -{ "8/250", 0, cb_oliviaA, (void *)MODE_OLIVIA, 0, FL_NORMAL_LABEL, 0, 14, 0}, -{ "4/500", 0, cb_oliviaF, (void *)MODE_OLIVIA, 0, FL_NORMAL_LABEL, 0, 14, 0}, -{ "8/500", 0, cb_oliviaB, (void *)MODE_OLIVIA, 0, FL_NORMAL_LABEL, 0, 14, 0}, -{ "16/500", 0, cb_oliviaC, (void *)MODE_OLIVIA, FL_MENU_DIVIDER, FL_NORMAL_LABEL, 0, 14, 0}, -{ "8/1000", 0, cb_oliviaD, (void *)MODE_OLIVIA, 0, FL_NORMAL_LABEL, 0, 14, 0}, -{ "32/1000", 0, cb_oliviaE, (void *)MODE_OLIVIA, FL_MENU_DIVIDER, FL_NORMAL_LABEL, 0, 14, 0}, -{ "64/2000", 0, cb_oliviaG, (void *)MODE_OLIVIA, FL_MENU_DIVIDER, FL_NORMAL_LABEL, 0, 14, 0}, +{ mode_info[MODE_OLIVIA_4_250].name, 0, cb_init_mode, (void *)MODE_OLIVIA_4_250, 0, FL_NORMAL_LABEL, 0, 14, 0}, +{ mode_info[MODE_OLIVIA_8_250].name, 0, cb_init_mode, (void *)MODE_OLIVIA_8_250, 0, FL_NORMAL_LABEL, 0, 14, 0}, +{ mode_info[MODE_OLIVIA_4_500].name, 0, cb_init_mode, (void *)MODE_OLIVIA_4_500, 0, FL_NORMAL_LABEL, 0, 14, 0}, +{ mode_info[MODE_OLIVIA_8_500].name, 0, cb_init_mode, (void *)MODE_OLIVIA_8_500, 0, FL_NORMAL_LABEL, 0, 14, 0}, +{ mode_info[MODE_OLIVIA_16_500].name, 0, cb_init_mode, (void *)MODE_OLIVIA_16_500, 0, FL_NORMAL_LABEL, 0, 14, 0}, +{ mode_info[MODE_OLIVIA_8_1000].name, 0, cb_init_mode, (void *)MODE_OLIVIA_8_1000, 0, FL_NORMAL_LABEL, 0, 14, 0}, +{ mode_info[MODE_OLIVIA_16_1000].name, 0, cb_init_mode, (void *)MODE_OLIVIA_16_1000, 0, FL_NORMAL_LABEL, 0, 14, 0}, +{ mode_info[MODE_OLIVIA_32_1000].name, 0, cb_init_mode, (void *)MODE_OLIVIA_32_1000, 0, FL_NORMAL_LABEL, 0, 14, 0}, +{ mode_info[MODE_OLIVIA_64_2000].name, 0, cb_init_mode, (void *)MODE_OLIVIA_64_2000, 0, FL_NORMAL_LABEL, 0, 14, 0}, { _("Custom..."), 0, cb_oliviaCustom, (void *)MODE_OLIVIA, 0, FL_NORMAL_LABEL, 0, 14, 0}, {0,0,0,0,0,0,0,0,0}, @@ -5412,17 +5489,17 @@ Fl_Menu_Item alt_menu_[] = { { mode_info[MODE_WEFAX_288].name, 0, cb_init_mode, (void *)MODE_WEFAX_288, 0, FL_NORMAL_LABEL, 0, 14, 0}, {0,0,0,0,0,0,0,0,0}, -{"Navtex/SitorB", 0, 0, 0, FL_SUBMENU, FL_NORMAL_LABEL, 0, 14, 0}, +{"Navtex/SitorB", 0, 0, 0, FL_SUBMENU | FL_MENU_DIVIDER, FL_NORMAL_LABEL, 0, 14, 0}, { mode_info[MODE_NAVTEX].name, 0, cb_init_mode, (void *)MODE_NAVTEX, 0, FL_NORMAL_LABEL, 0, 14, 0}, { mode_info[MODE_SITORB].name, 0, cb_init_mode, (void *)MODE_SITORB, 0, FL_NORMAL_LABEL, 0, 14, 0}, {0,0,0,0,0,0,0,0,0}, +{ mode_info[MODE_WWV].name, 0, cb_init_mode, (void *)MODE_WWV, 0, FL_NORMAL_LABEL, 0, 14, 0}, +{ mode_info[MODE_ANALYSIS].name, 0, cb_init_mode, (void *)MODE_ANALYSIS, FL_MENU_DIVIDER, FL_NORMAL_LABEL, 0, 14, 0}, + { mode_info[MODE_NULL].name, 0, cb_init_mode, (void *)MODE_NULL, 0, FL_NORMAL_LABEL, 0, 14, 0}, { mode_info[MODE_SSB].name, 0, cb_init_mode, (void *)MODE_SSB, 0, FL_NORMAL_LABEL, 0, 14, 0}, -{ mode_info[MODE_WWV].name, 0, cb_init_mode, (void *)MODE_WWV, 0, FL_NORMAL_LABEL, 0, 14, 0}, - -{ mode_info[MODE_ANALYSIS].name, 0, cb_init_mode, (void *)MODE_ANALYSIS, 0, FL_NORMAL_LABEL, 0, 14, 0}, {0,0,0,0,0,0,0,0,0}, {_("&Configure"), 0, 0, 0, FL_SUBMENU, FL_NORMAL_LABEL, 0, 14, 0}, @@ -6547,7 +6624,8 @@ void resetTHOR() { if (md == MODE_THOR4 || md == MODE_THOR5 || md == MODE_THOR8 || md == MODE_THOR11 || md == MODE_THOR16 || md == MODE_THOR22 || - md == MODE_THOR44 || md == MODE_THOR88 ) + md == MODE_THOR25x4 || md == MODE_THOR50x1 || + md == MODE_THOR50x2 || md == MODE_THOR100 ) trx_start_modem(active_modem); } diff --git a/src/dominoex/dominoex.cxx b/src/dominoex/dominoex.cxx index 7f95d056..3e172136 100644 --- a/src/dominoex/dominoex.cxx +++ b/src/dominoex/dominoex.cxx @@ -2,10 +2,10 @@ // // dominoex.cxx -- DominoEX modem // -// Copyright (C) 2008-2009 -// David Freese (w1hkj@w1hkj.com) -// Copyright (C) 2006 -// Hamish Moffatt (hamish@debian.org) +// Copyright (C) 2008-20012 +// David Freese +// Hamish Moffatt +// John Phelps // // based on code in gmfsk // @@ -94,16 +94,15 @@ void dominoex::rx_init() void dominoex::reset_filters() { // fft filter at first IF frequency - fft->create_filter( - (FIRSTIF - 0.5 * progdefaults.DOMINOEX_BW * bandwidth) / samplerate, - (FIRSTIF + 0.5 * progdefaults.DOMINOEX_BW * bandwidth)/ samplerate ); + fft->create_filter( (FIRSTIF - 0.5 * progdefaults.DOMINOEX_BW * bandwidth) / samplerate, + (FIRSTIF + 0.5 * progdefaults.DOMINOEX_BW * bandwidth)/ samplerate ); for (int i = 0; i < MAXFFTS; i++) { if (binsfft[i]) delete binsfft[i]; binsfft[i] = 0; } - if (slowcpu || samplerate == 22050) { + if (slowcpu) { extones = 4; paths = 3; } else { @@ -116,13 +115,8 @@ void dominoex::reset_filters() numbins = hitone - lotone; - for (int i = 0; i < paths; i++) { //MAXFFTS; i++) + for (int i = 0; i < paths; i++)//MAXFFTS; i++) binsfft[i] = new sfft (symlen, lotone, hitone); - if (!binsfft[i]) { - printf("Domino Arrgh %d\n", i); - exit(0); - } - } filter_reset = false; } @@ -138,6 +132,7 @@ void dominoex::init() MuPsk_sec2pri_init(); modem::init(); +// reset_filters(); rx_init(); set_scope_mode(Digiscope::DOMDATA); @@ -190,11 +185,9 @@ dominoex::~dominoex() { if (hilbert) delete hilbert; - for (int i = 0; i < MAXFFTS; i++) { //paths; i++) {//MAXFFTS; i++) { - if (binsfft[i]) { - delete binsfft[i]; - binsfft[i] = 0; - } + for (int i = 0; i < MAXFFTS; i++) { + if (binsfft[i]) delete binsfft[i]; + binsfft[i] = 0; } for (int i = 0; i < SCOPESIZE; i++) { @@ -225,29 +218,16 @@ dominoex::dominoex(trx_mode md) doublespaced = 2; samplerate = 11025; break; - case MODE_DOMINOEX11: symlen = 1024; doublespaced = 1; samplerate = 11025; break; - case MODE_DOMINOEX22: symlen = 512; doublespaced = 1; samplerate = 11025; break; - - case MODE_DOMINOEX44: - symlen = 250; - doublespaced = 2; - samplerate = 11025; - break; - case MODE_DOMINOEX88: - symlen = 125; - doublespaced = 1; - samplerate = 11025; - break; // 8kHz modes case MODE_DOMINOEX4: symlen = 2048; @@ -264,6 +244,19 @@ dominoex::dominoex(trx_mode md) doublespaced = 1; samplerate = 8000; break; +// experimental + case MODE_DOMINOEX44: + symlen = 256; + doublespaced = 2; + samplerate = 11025; + break; + case MODE_DOMINOEX88: + symlen = 128; + doublespaced = 1; + samplerate = 11025; + break; + + default: // EX8 symlen = 1024; doublespaced = 2; @@ -278,10 +271,10 @@ dominoex::dominoex(trx_mode md) hilbert->init_hilbert(37, 1); // fft filter at first if frequency - fft = new fftfilt( - (FIRSTIF - 0.5 * progdefaults.DOMINOEX_BW * bandwidth) / samplerate, - (FIRSTIF + 0.5 * progdefaults.DOMINOEX_BW * bandwidth)/ samplerate, - 1024 ); + fft = new fftfilt( (FIRSTIF - 0.5 * progdefaults.DOMINOEX_BW * bandwidth) / samplerate, + (FIRSTIF + 0.5 * progdefaults.DOMINOEX_BW * bandwidth)/ samplerate, + 1024 ); + basetone = (int)floor(BASEFREQ * symlen / samplerate + 0.5); slowcpu = progdefaults.slowcpu; @@ -315,9 +308,11 @@ dominoex::dominoex(trx_mode md) prev1symbol = prev2symbol = 0; MuPskEnc = new encoder (K, POLY1, POLY2); - MuPskDec = new viterbi::impl (POLY1, POLY2); - MuPskTxinlv = new interleave (-1, INTERLEAVE_FWD); - MuPskRxinlv = new interleave (-1, INTERLEAVE_REV); + MuPskDec = new viterbi (K, POLY1, POLY2); + MuPskDec->settraceback (45); + MuPskDec->setchunksize (1); + MuPskTxinlv = new interleave (4, 4, INTERLEAVE_FWD); + MuPskRxinlv = new interleave (4, 4, INTERLEAVE_REV); Mu_bitstate = 0; Mu_symbolpair[0] = Mu_symbolpair[1] = 0; Mu_datashreg = 1; diff --git a/src/filters/viterbi.cxx b/src/filters/viterbi.cxx index 676a7bbe..309b30aa 100644 --- a/src/filters/viterbi.cxx +++ b/src/filters/viterbi.cxx @@ -33,21 +33,172 @@ #include "misc.h" /* ---------------------------------------------------------------------- */ -viterbi::viterbi( int poly1, int poly2, unsigned int * output, int outsize ) +viterbi::viterbi(int k, int poly1, int poly2) { + int outsize = 1 << k; + _traceback = PATHMEM - 1; + _chunksize = 8; + nstates = 1 << (k - 1); + + output = new int[outsize]; + for (int i = 0; i < outsize; i++) { output[i] = parity(poly1 & i) | (parity(poly2 & i) << 1); } + for (int i = 0; i < PATHMEM; i++) { + metrics[i] = new int[nstates]; + history[i] = new int[nstates]; + sequence[i] = 0; + for (int j = 0; j < nstates; j++) + metrics[i][j] = history[i][j] = 0; + } for (int i = 0; i < 256; i++) { mettab[0][i] = 128 - i; mettab[1][i] = i - 128; } + reset(); } -viterbi::~viterbi() {} +viterbi::~viterbi() +{ + if (output) delete [] output; + for (int i = 0; i < PATHMEM; i++) { + if (metrics[i]) delete [] metrics[i]; + if (history[i]) delete [] history[i]; + } +} + +void viterbi::reset() +{ + for (int i = 0; i < PATHMEM; i++) { + memset(metrics[i], 0, nstates * sizeof(int)); + memset(history[i], 0, nstates * sizeof(int)); + } + ptr = 0; +} + +int viterbi::settraceback(int trace) { + if (trace < 0 || trace > PATHMEM - 1) + return -1; + _traceback = trace; + return 0; +} + +int viterbi::setchunksize(int chunk) { + if (chunk < 1 || chunk > _traceback) + return -1; + _chunksize = chunk; + return 0; +} + +int viterbi::traceback(int *metric) +{ + int bestmetric, beststate; + unsigned int p, c = 0; + + p = (ptr - 1) % PATHMEM; + +// Find the state with the best metric + bestmetric = INT_MIN; + beststate = 0; + + for (int i = 0; i < nstates; i++) { + if (metrics[p][i] > bestmetric) { + bestmetric = metrics[p][i]; + beststate = i; + } + } + +// Trace back 'traceback' steps, starting from the best state + sequence[p] = beststate; + + for (int i = 0; i < _traceback; i++) { + unsigned int prev = (p - 1) % PATHMEM; + + sequence[prev] = history[p][sequence[p]]; + p = prev; + } + + if (metric) + *metric = metrics[p][sequence[p]]; + +// Decode 'chunksize' bits + for (int i = 0; i < _chunksize; i++) { +// low bit of state is the previous input bit + c = (c << 1) | (sequence[p] & 1); + p = (p + 1) % PATHMEM; + } + + if (metric) + *metric = metrics[p][sequence[p]] - *metric; + + return c; +} + +int viterbi::decode(unsigned char *sym, int *metric) +{ + unsigned int currptr, prevptr; + int met[4]; + + currptr = ptr; + prevptr = (currptr - 1) % PATHMEM; +// if (prevptr < 0) prevptr = PATHMEM - 1; + + met[0] = mettab[0][sym[1]] + mettab[0][sym[0]]; + met[1] = mettab[0][sym[1]] + mettab[1][sym[0]]; + met[2] = mettab[1][sym[1]] + mettab[0][sym[0]]; + met[3] = mettab[1][sym[1]] + mettab[1][sym[0]]; + +// met[0] = 256 - sym[1] - sym[0]; +// met[1] = sym[0] - sym[1]; +// met[2] = sym[1] - sym[0]; +// met[3] = sym[0] + sym[1] - 256; + + for (int n = 0; n < nstates; n++) { + int p0, p1, s0, s1, m0, m1; + + m0 = 0; + m1 = 0; + s0 = n; + s1 = n + nstates; + + p0 = s0 >> 1; + p1 = s1 >> 1; + + m0 = metrics[prevptr][p0] + met[output[s0]]; + m1 = metrics[prevptr][p1] + met[output[s1]]; + + if (m0 > m1) { + metrics[currptr][n] = m0; + history[currptr][n] = p0; + } else { + metrics[currptr][n] = m1; + history[currptr][n] = p1; + } + } + + ptr = (ptr + 1) % PATHMEM; + + if ((ptr % _chunksize) == 0) + return traceback(metric); + + if (metrics[currptr][0] > INT_MAX / 2) { + for (int i = 0; i < PATHMEM; i++) + for (int j = 0; j < nstates; j++) + metrics[i][j] -= INT_MAX / 2; + } + if (metrics[currptr][0] < INT_MIN / 2) { + for (int i = 0; i < PATHMEM; i++) + for (int j = 0; j < nstates; j++) + metrics[i][j] += INT_MIN / 2; + } + + return -1; +} /* ---------------------------------------------------------------------- */ +#include encoder::encoder(int k, int poly1, int poly2) { int size = 1 << k; /* size of the output table */ diff --git a/src/globals/globals.cxx b/src/globals/globals.cxx index 0046064d..b9bb4620 100644 --- a/src/globals/globals.cxx +++ b/src/globals/globals.cxx @@ -55,8 +55,8 @@ const struct mode_info_t mode_info[NUM_MODES] = { { MODE_DOMINOEX11, &dominoex11_modem, "DOMX11", "DominoEX 11", "DOMINOEX11", "DOMINO", "DM11" }, { MODE_DOMINOEX16, &dominoex16_modem, "DOMX16", "DominoEX 16", "DOMINOEX16", "DOMINO", "DM16" }, { MODE_DOMINOEX22, &dominoex22_modem, "DOMX22", "DominoEX 22", "DOMINOEX22", "DOMINO", "DM22" }, - { MODE_DOMINOEX44, &dominoex44_modem, "DOMX44", "DominoEX 44", "DOMINOEX44", "DOMINO", "DOM44" }, - { MODE_DOMINOEX88, &dominoex88_modem, "DOMX88", "DominoEX 88", "DOMINOEX88", "DOMINO", "DOM88" }, + { MODE_DOMINOEX44, &dominoex44_modem, "DOMX44", "DominoEX 44", "DOMINOEX44", "DOMINO", "DM44" }, + { MODE_DOMINOEX88, &dominoex88_modem, "DOMX88", "DominoEX 88", "DOMINOEX88", "DOMINO", "DM88" }, { MODE_FELDHELL, &feld_modem, "FELDHELL", "Feld Hell", "", "HELL", "HELL" }, { MODE_SLOWHELL, &feld_slowmodem, "SLOWHELL", "Slow Hell", "", "HELL", "SHLL" }, @@ -75,6 +75,7 @@ const struct mode_info_t mode_info[NUM_MODES] = { { MODE_MFSK22, &mfsk22_modem, "MFSK22", "MFSK-22", "MFSK22", "MFSK22", "MK22" }, { MODE_MFSK31, &mfsk31_modem, "MFSK31", "MFSK-31", "MFSK31", "MFSK31", "MK31" }, { MODE_MFSK64, &mfsk64_modem, "MFSK64", "MFSK-64", "MFSK64", "MFSK64", "MK64" }, + { MODE_MFSK128, &mfsk128_modem, "MFSK128", "MFSK-128", "MFSK128", "MFSK128", "MK128" }, { MODE_WEFAX_576, &wefax576_modem, "WEFAX576", "WEFAX-IOC576", "WEFAXIOC576", "FAX", "FX576" }, { MODE_WEFAX_288, &wefax288_modem, "WEFAX288", "WEFAX-IOC288", "WEFAXIOC288", "FAX", "FX288" }, @@ -92,16 +93,30 @@ const struct mode_info_t mode_info[NUM_MODES] = { { MODE_PSK125, &psk125_modem, "BPSK125", "BPSK-125", "PSK125", "PSK125", "P125" }, { MODE_PSK250, &psk250_modem, "BPSK250", "BPSK-250", "PSK250", "PSK250", "P250" }, { MODE_PSK500, &psk500_modem, "BPSK500", "BPSK-500", "PSK500", "PSK500", "P500" }, + { MODE_QPSK31, &qpsk31_modem, "QPSK31", "QPSK-31", "QPSK31", "QPSK31", "Q31" }, { MODE_QPSK63, &qpsk63_modem, "QPSK63", "QPSK-63", "QPSK63", "QPSK63", "Q63" }, { MODE_QPSK125, &qpsk125_modem, "QPSK125", "QPSK-125", "QPSK125", "QPSK125", "Q125" }, { MODE_QPSK250, &qpsk250_modem, "QPSK250", "QPSK-250", "QPSK250", "QPSK250", "Q250" }, { MODE_QPSK500, &qpsk500_modem, "QPSK500", "QPSK-500", "QPSK500", "QPSK500", "Q500" }, + { MODE_PSK125R, &psk125r_modem, "PSK125R", "PSK-125R", "PSK125R", "PSK125R", "P125R" }, { MODE_PSK250R, &psk250r_modem, "PSK250R", "PSK-250R", "PSK250R", "PSK250R", "P250R" }, { MODE_PSK500R, &psk500r_modem, "PSK500R", "PSK-500R", "PSK500R", "PSK500R", "P500R" }, - { MODE_OLIVIA, &olivia_modem, "OLIVIA", "Olivia", "", "OLIVIA", "OL" }, + { MODE_PSK1000, &psk1000_modem, "BPSK1000", "BPSK-1000", "PSK1000", "PSK1000", "P1000" }, + { MODE_PSK1000R, &psk1000r_modem, "PSK1000R", "PSK-1000R", "PSK1000R", "PSK1000R", "PSK1000R" }, + + { MODE_OLIVIA, &olivia_modem, "OLIVIA", "OLIVIA", "OLIVIA", "OLIVIA", "OL" }, + { MODE_OLIVIA_4_250, &olivia_4_250_modem, "Olivia-4-250", "OL 4-250", "OLIV 4/250", "OLIVIA", "OL4/250" }, + { MODE_OLIVIA_8_250, &olivia_8_250_modem, "Olivia-8-250", "OL 8-250", "OLIV 8/250", "OLIVIA", "OL8/250" }, + { MODE_OLIVIA_4_500, &olivia_4_500_modem, "Olivia-4-500", "OL 4-500", "OLIV 4/500", "OLIVIA", "OL4/500" }, + { MODE_OLIVIA_8_500, &olivia_8_500_modem, "Olivia-8-500", "OL 8-500", "OLIV 8/500", "OLIVIA", "OL8/500" }, + { MODE_OLIVIA_16_500, &olivia_16_500_modem, "Olivia-16-500", "OL 16-500", "OLIV 16/500", "OLIVIA", "OL16/500" }, + { MODE_OLIVIA_8_1000, &olivia_8_1000_modem, "Olivia-8-1K", "OL 8-1K", "OLIV 8/1K", "OLIVIA", "OL8/1K" }, + { MODE_OLIVIA_16_1000, &olivia_16_1000_modem, "Olivia-16-1K", "OL 16-1K", "OLIV 16/1K", "OLIVIA", "OL16/1K" }, + { MODE_OLIVIA_32_1000, &olivia_32_1000_modem, "Olivia-32-1K", "OL 32-1K", "OLIV 32/1K", "OLIVIA", "OL32/1K" }, + { MODE_OLIVIA_64_2000, &olivia_64_2000_modem, "Olivia-64-2K", "OL 64-2K", "OLIV 64/2K", "OLIVIA", "OL64/2K" }, { MODE_RTTY, &rtty_modem, "RTTY", "RTTY", "RTTY", "RTTY", "RY" }, @@ -111,8 +126,11 @@ const struct mode_info_t mode_info[NUM_MODES] = { { MODE_THOR11, &thor11_modem, "THOR11", "THOR 11", "THOR11", "THOR", "TH11" }, { MODE_THOR16, &thor16_modem, "THOR16", "THOR 16", "THOR16", "THOR", "TH16" }, { MODE_THOR22, &thor22_modem, "THOR22", "THOR 22", "THOR22", "THOR", "TH22" }, - { MODE_THOR44, &thor44_modem, "THOR44", "THOR 44", "THOR44", "THOR", "TH44" }, - { MODE_THOR88, &thor88_modem, "THOR88", "THOR 88", "THOR88", "THOR", "TH88" }, + { MODE_THOR25x4, &thor25x4_modem, "THOR25x4", "THOR 25 x4", "THOR25x4", "THOR", "TH25" }, + { MODE_THOR50x1, &thor50x1_modem, "THOR50x1", "THOR 50 x1", "THOR50x1", "THOR", "TH51" }, + { MODE_THOR50x2, &thor50x2_modem, "THOR50x2", "THOR 50 x2", "THOR50x2", "THOR", "TH52" }, + { MODE_THOR100, &thor100_modem, "THOR100", "THOR 100", "THOR100", "THOR", "TH10" }, + { MODE_THROB1, &throb1_modem, "THROB1", "Throb 1", "", "THRB", "TB1" }, { MODE_THROB2, &throb2_modem, "THROB2", "Throb 2", "", "THRB", "TB2" }, @@ -123,9 +141,45 @@ const struct mode_info_t mode_info[NUM_MODES] = { { MODE_PACKET, &pkt_modem, "PACKET", "Packet", "", "PKT", "PKT" }, + { MODE_4X_PSK63R, &psk63r_c4_modem, "PSK63RC4", "4xPSK63R", "PSK63RC4", "PSK63RC4", "P63R4" }, + { MODE_5X_PSK63R, &psk63r_c5_modem, "PSK63RC5", "5xPSK63R", "PSK63RC5", "PSK63RC5", "P63R5" }, + { MODE_10X_PSK63R, &psk63r_c10_modem, "PSK63RC10", "10xPSK63R", "PSK63RC10", "PSK63RC10", "P63R10" }, + { MODE_20X_PSK63R, &psk63r_c20_modem, "PSK63RC20", "20xPSK63R", "PSK63RC20", "PSK63RC20", "P63R20" }, + { MODE_32X_PSK63R, &psk63r_c32_modem, "PSK63RC32", "32xPSK63R", "PSK63RC32", "PSK63RC32", "P63R32" }, + + { MODE_4X_PSK125R, &psk125r_c4_modem, "PSK125RC4", "4xPSK125R", "PSK125RC4", "PSK125RC4", "P125R4" }, + { MODE_5X_PSK125R, &psk125r_c5_modem, "PSK125RC5", "5xPSK125R", "PSK125RC5", "PSK125RC5", "P125R5" }, + { MODE_10X_PSK125R, &psk125r_c10_modem, "PSK125RC10", "10xPSK125R", "PSK125RC10", "PSK125RC10", "P125R10" }, + { MODE_12X_PSK125, &psk125_c12_modem, "PSK125C12", "12xPSK125", "PSK125C12", "PSK125C12", "P125C12" }, + { MODE_12X_PSK125R, &psk125r_c12_modem, "PSK125RC12", "12xPSK125R", "PSK125RC12", "PSK125RC12", "P125R12" }, + { MODE_16X_PSK125R, &psk125r_c16_modem, "PSK125RC16", "16xPSK125R", "PSK125RC16", "PSK125RC16", "P125R16" }, + + { MODE_6X_PSK250, &psk250_c6_modem, "PSK250C6", "6xPSK250", "PSK250C6", "PSK250C6", "P2506"}, + + { MODE_2X_PSK250R, &psk250r_c2_modem, "PSK250RC2", "2xPSK250R", "PSK250RC2", "PSK250RC2", "P250R2" }, + { MODE_3X_PSK250R, &psk250r_c3_modem, "PSK250RC3", "3xPSK250R", "PSK250RC3", "PSK250RC3", "P250R3" }, + { MODE_5X_PSK250R, &psk250r_c5_modem, "PSK250RC5", "5xPSK250R", "PSK250RC5", "PSK250RC5", "P250R5"}, + { MODE_6X_PSK250R, &psk250r_c6_modem, "PSK250RC6", "6xPSK250R", "PSK250RC6", "PSK250RC6", "P250R6"}, + { MODE_7X_PSK250R, &psk250r_c7_modem, "PSK250RC7", "7xPSK250R", "PSK250RC7", "PSK250RC7", "P250R7"}, + + { MODE_2X_PSK500, &psk500_c2_modem, "PSK500C2", "2xPSK500", "PSK500C2", "PSK500C2", "2xP500" }, + { MODE_4X_PSK500, &psk500_c4_modem, "PSK500C4", "4xPSK500", "PSK500C4", "PSK500C4", "4xP500" }, + + { MODE_2X_PSK500R, &psk500r_c2_modem, "PSK500RC2", "2xPSK500R", "PSK500RC2", "PSK500RC2", "P500R2" }, + { MODE_3X_PSK500R, &psk500r_c3_modem, "PSK500RC3", "3xPSK500R", "PSK500RC3", "PSK500RC3", "P500R3" }, + { MODE_4X_PSK500R, &psk500r_c4_modem, "PSK500RC4", "4xPSK500R", "PSK500RC4", "PSK500RC4", "P500R4"}, + + { MODE_2X_PSK800, &psk800_c2_modem, "PSK800C2", "2xPSK800", "PSK800C2", "PSK800C2", "P800RC2" }, + + { MODE_2X_PSK800R, &psk800r_c2_modem, "PSK800RC2", "2xPSK800R", "PSK800RC2", "PSK800RC2", "P800RC2" }, + + { MODE_2X_PSK1000, &psk1000_c2_modem, "PSK1000C2", "2xPSK1000", "PSK1000C2", "PSK1000C2", "P1KC2" }, + { MODE_2X_PSK1000R, &psk1000r_c2_modem, "PSK1000RC2", "2xPSK1000R", "PSK1000RC2", "PSK1000RC2", "P1KRC2" }, + { MODE_SSB, &ssb_modem, "SSB", "SSB", "", "SSB", "" }, { MODE_WWV, &wwv_modem, "WWV", "WWV", "", "", "" }, { MODE_ANALYSIS, &anal_modem, "ANALYSIS", "Freq Analysis", "", "", "" } + }; std::ostream& operator<<(std::ostream& s, const qrg_mode_t& m) diff --git a/src/include/confdialog.h b/src/include/confdialog.h index 4ff65ff3..c8d4abbd 100644 --- a/src/include/confdialog.h +++ b/src/include/confdialog.h @@ -261,11 +261,11 @@ extern Fl_Group *tabTHOR; extern Fl_Input2 *txtTHORSecondary; extern Fl_Check_Button *valTHOR_FILTER; extern Fl_Counter2 *valTHOR_BW; -extern Fl_Value_Slider2 *valThorCWI; -extern Fl_Counter2 *valTHOR_PATHS; extern Fl_Check_Button *valTHOR_PREAMBLE; extern Fl_Check_Button *valTHOR_SOFTSYMBOLS; extern Fl_Check_Button *valTHOR_SOFTBITS; +extern Fl_Value_Slider2 *valThorCWI; +extern Fl_Counter2 *valTHOR_PATHS; extern Fl_Group *tabPacket; extern Fl_Choice *selPacket_Baud; extern Fl_Counter2 *valPacket_LoSig_RXGain; @@ -417,6 +417,7 @@ extern Fl_Check_Button *chkRSidAutoDisable; extern Fl_Check_Button *chkRSidNotifyOnly; extern Fl_Button *bRSIDRxModes; extern Fl_Value_Slider2 *sldrRSIDsquelch; +extern Fl_Value_Slider2 *sldrRSIDresolution; extern Fl_Button *bRSIDTxModes; extern Fl_Check_Button *btn_post_rsid; extern Fl_Counter *val_pretone; diff --git a/src/include/dominoex.h b/src/include/dominoex.h index 42644f90..caa0efeb 100644 --- a/src/include/dominoex.h +++ b/src/include/dominoex.h @@ -45,12 +45,9 @@ #include "viterbi.h" #define NUMTONES 18 -//#define MAXFFTS 4 #define MAXFFTS 8 #define BASEFREQ 1000.0 #define FIRSTIF 1500.0 -//#define BASEFREQ 500.0 -//#define FIRSTIF 1000.0 #define SCOPESIZE 64 diff --git a/src/include/globals.h b/src/include/globals.h index c8c3c6a1..5ee4ff80 100644 --- a/src/include/globals.h +++ b/src/include/globals.h @@ -79,14 +79,14 @@ enum { MODE_MFSK8, MODE_MFSK16, MODE_MFSK32, -// experimental modes MODE_MFSK4, MODE_MFSK11, MODE_MFSK22, MODE_MFSK31, MODE_MFSK64, + MODE_MFSK128, MODE_MFSK_FIRST = MODE_MFSK8, - MODE_MFSK_LAST = MODE_MFSK64, + MODE_MFSK_LAST = MODE_MFSK128, MODE_WEFAX_576, MODE_WEFAX_288, @@ -115,13 +115,25 @@ enum { MODE_QPSK125, MODE_QPSK250, MODE_QPSK500, + MODE_PSK125R, MODE_PSK250R, MODE_PSK500R, + MODE_PSK1000, + MODE_PSK1000R, MODE_PSK_FIRST = MODE_PSK31, - MODE_PSK_LAST = MODE_PSK500R, + MODE_PSK_LAST = MODE_PSK1000R, MODE_OLIVIA, + MODE_OLIVIA_4_250, + MODE_OLIVIA_8_250, + MODE_OLIVIA_4_500, + MODE_OLIVIA_8_500, + MODE_OLIVIA_16_500, + MODE_OLIVIA_8_1000, + MODE_OLIVIA_16_1000, + MODE_OLIVIA_32_1000, + MODE_OLIVIA_64_2000, MODE_RTTY, @@ -131,10 +143,12 @@ enum { MODE_THOR11, MODE_THOR16, MODE_THOR22, - MODE_THOR44, - MODE_THOR88, + MODE_THOR25x4, + MODE_THOR50x1, + MODE_THOR50x2, + MODE_THOR100, MODE_THOR_FIRST = MODE_THOR4, - MODE_THOR_LAST = MODE_THOR88, + MODE_THOR_LAST = MODE_THOR100, MODE_THROB1, MODE_THROB2, @@ -146,6 +160,41 @@ enum { MODE_THROB_LAST = MODE_THROBX4, MODE_PACKET, +// high speed && multiple carrier modes + + MODE_4X_PSK63R, + MODE_5X_PSK63R, + MODE_10X_PSK63R, + MODE_20X_PSK63R, + MODE_32X_PSK63R, + + MODE_4X_PSK125R, + MODE_5X_PSK125R, + MODE_10X_PSK125R, + MODE_12X_PSK125, + MODE_12X_PSK125R, + MODE_16X_PSK125R, + + MODE_6X_PSK250, + + MODE_2X_PSK250R, + MODE_3X_PSK250R, + MODE_5X_PSK250R, + MODE_6X_PSK250R, + MODE_7X_PSK250R, + + MODE_2X_PSK500, + MODE_4X_PSK500, + + MODE_2X_PSK500R, + MODE_3X_PSK500R, + MODE_4X_PSK500R, + + MODE_2X_PSK800, + MODE_2X_PSK800R, + + MODE_2X_PSK1000, + MODE_2X_PSK1000R, MODE_SSB, MODE_WWV, diff --git a/src/include/interleave.h b/src/include/interleave.h index 49d5a238..bbe1fd02 100644 --- a/src/include/interleave.h +++ b/src/include/interleave.h @@ -41,7 +41,7 @@ protected: } public: - interleave(int _size, int dir); + interleave(int _size, int depth, int dir); ~interleave(); void symbols (unsigned char *psyms); void bits (unsigned int *pbits); diff --git a/src/include/mfsk.h b/src/include/mfsk.h index 06bc7b59..bc3474d0 100644 --- a/src/include/mfsk.h +++ b/src/include/mfsk.h @@ -167,6 +167,9 @@ protected: unsigned int datashreg; + //VK2ETA high speed modes + int preamble; + complex currvector; complex prev1vector; complex prev2vector; @@ -242,7 +245,7 @@ protected: void eval_s2n(); void sendsymbol(int sym); void sendbit(int bit); - void sendchar(unsigned int c); + void sendchar(unsigned char c); void sendidle(); void flushtx(); void clearbits(); diff --git a/src/include/modem.h b/src/include/modem.h index d7f7e5da..51874907 100644 --- a/src/include/modem.h +++ b/src/include/modem.h @@ -197,6 +197,7 @@ extern modem *mfsk11_modem; extern modem *mfsk22_modem; extern modem *mfsk31_modem; extern modem *mfsk64_modem; +extern modem *mfsk128_modem; extern modem *wefax576_modem; extern modem *wefax288_modem; @@ -223,6 +224,7 @@ extern modem *psk63f_modem; extern modem *psk125_modem; extern modem *psk250_modem; extern modem *psk500_modem; +extern modem *psk1000_modem; extern modem *qpsk31_modem; extern modem *qpsk63_modem; @@ -233,11 +235,55 @@ extern modem *qpsk500_modem; extern modem *psk125r_modem; extern modem *psk250r_modem; extern modem *psk500r_modem; +extern modem *psk1000r_modem; + +extern modem *psk800_c2_modem; +extern modem *psk800r_c2_modem; + +extern modem *psk1000_c2_modem; +extern modem *psk1000r_c2_modem; + +extern modem *psk63r_c4_modem; +extern modem *psk63r_c5_modem; +extern modem *psk63r_c10_modem; +extern modem *psk63r_c20_modem; +extern modem *psk63r_c32_modem; + +extern modem *psk125r_c4_modem; +extern modem *psk125r_c5_modem; +extern modem *psk125r_c10_modem; +extern modem *psk125_c12_modem; +extern modem *psk125r_c12_modem; +extern modem *psk125r_c16_modem; + +extern modem *psk250r_c2_modem; +extern modem *psk250r_c3_modem; +extern modem *psk250r_c5_modem; +extern modem *psk250_c6_modem; +extern modem *psk250r_c6_modem; +extern modem *psk250r_c7_modem; + +extern modem *psk500_c2_modem; +extern modem *psk500_c4_modem; + +extern modem *psk500r_c2_modem; +extern modem *psk500r_c3_modem; +extern modem *psk500r_c4_modem; extern modem *rtty_modem; extern modem *pkt_modem; extern modem *olivia_modem; +extern modem *olivia_4_250_modem; +extern modem *olivia_8_250_modem; +extern modem *olivia_4_500_modem; +extern modem *olivia_8_500_modem; +extern modem *olivia_16_500_modem; +extern modem *olivia_8_1000_modem; +extern modem *olivia_16_1000_modem; +extern modem *olivia_32_1000_modem; +extern modem *olivia_64_2000_modem; + extern modem *contestia_modem; extern modem *thor4_modem; @@ -246,11 +292,10 @@ extern modem *thor8_modem; extern modem *thor11_modem; extern modem *thor16_modem; extern modem *thor22_modem; - -extern modem *dominoex44_modem; -extern modem *thor44_modem; -extern modem *dominoex88_modem; -extern modem *thor88_modem; +extern modem *thor25x4_modem; +extern modem *thor50x1_modem; +extern modem *thor50x2_modem; +extern modem *thor100_modem; extern modem *dominoex4_modem; extern modem *dominoex5_modem; @@ -258,6 +303,8 @@ extern modem *dominoex8_modem; extern modem *dominoex11_modem; extern modem *dominoex16_modem; extern modem *dominoex22_modem; +extern modem *dominoex44_modem; +extern modem *dominoex88_modem; extern modem *throb1_modem; extern modem *throb2_modem; diff --git a/src/include/olivia.h b/src/include/olivia.h index 8605c2d6..d35e6543 100644 --- a/src/include/olivia.h +++ b/src/include/olivia.h @@ -76,7 +76,7 @@ private: void send_tones(); public: - olivia(); + olivia(trx_mode omode = MODE_OLIVIA); ~olivia(); void init(); void rx_init(); diff --git a/src/include/psk.h b/src/include/psk.h index ed664a6f..5809558a 100644 --- a/src/include/psk.h +++ b/src/include/psk.h @@ -48,6 +48,8 @@ #define NUM_FILTERS 3 #define GOERTZEL 288 //96 x 2 must be an integer value +#define MAX_CARRIERS 32 + //===================================================================== class psk : public modem { @@ -56,17 +58,18 @@ private: int symbollen; bool _qpsk; bool _pskr; - double phaseacc; - complex prevsymbol; + double phaseacc[MAX_CARRIERS]; + complex prevsymbol[MAX_CARRIERS]; unsigned int shreg; //FEC: 2nd stream unsigned int shreg2; int numinterleavers; //interleaver size (speed dependant) + double numcarriers; //Number of parallel carriers for M CAR PSK and PSKR and QPSKR + double inter_carrier; // Frequency gap betweeb carriers // rx variables & functions - - C_FIR_filter *fir1; - C_FIR_filter *fir2; + C_FIR_filter *fir1[MAX_CARRIERS]; + C_FIR_filter *fir2[MAX_CARRIERS]; // C_FIR_filter *fir3; double *fir1c; double *fir2c; @@ -89,7 +92,7 @@ private: interleave *Rxinlv; interleave *Rxinlv2; interleave *Txinlv; - unsigned int bitshreg; + unsigned int bitshreg; int rxbitstate; //PSKR modes - Soft decoding unsigned char symbolpair[2]; @@ -115,7 +118,7 @@ private: viewpsk* pskviewer; pskeval* evalpsk; - void rx_symbol(complex symbol); + void rx_symbol(complex symbol, int car); void rx_bit(int bit); void rx_bit2(int bit); void rx_qpsk(int bits); @@ -127,15 +130,20 @@ private: double snratio, s2n, imdratio, imd; double E1, E2, E3; double afcmetric; - - //PSKR modes + +//PSKR modes bool firstbit; bool startpreamble; +//MULTI-CARRIER + double sc_bw; // single carrier bandwidth // complex thirdorder; // tx variables & functions + int accumulated_bits; //JD for multiple carriers + int txsymbols[MAX_CARRIERS]; + double *tx_shape; int preamble; void tx_symbol(int sym); diff --git a/src/include/pskeval.h b/src/include/pskeval.h index 5b4cbf23..73014f20 100644 --- a/src/include/pskeval.h +++ b/src/include/pskeval.h @@ -42,7 +42,7 @@ public: void clear(); void setbw(double w) { bw = w;} void sigdensity(); - double sigpeak(int &f, int f1, int f2, int bw); + double sigpeak(int &f, int f1, int f2); double peak(int &f, int f1, int f2, double level); double power(int f1, int f2); }; diff --git a/src/include/qrunner.h b/src/include/qrunner.h index eea86a1a..c027abee 100644 --- a/src/include/qrunner.h +++ b/src/include/qrunner.h @@ -113,7 +113,9 @@ public: } #ifndef NDEBUG - LOG_ERROR("qrunner: thread %" PRIdPTR " fifo full!", GET_THREAD_ID()); +//Remi's extra debugging info LOG_ERROR("qrunner: thread %" PRIdPTR " fifo full!", GET_THREAD_ID()); + LOG_ERROR("qrunner: thread %" PRIdPTR " fifo full at %s!", GET_THREAD_ID(),typeid(F).name() ); + #endif return false; } diff --git a/src/include/rsid.h b/src/include/rsid.h index 6aa924c6..41324732 100644 --- a/src/include/rsid.h +++ b/src/include/rsid.h @@ -72,16 +72,29 @@ enum { struct RSIDs { unsigned short rs; trx_mode mode; const char* name; }; class cRsId { + +protected: +// note: hamming distance > 5 causes false detection on second burst +enum { HAMMING_HIGH = 2, HAMMING_MED = 4, HAMMING_LOW = 5 };// 6 }; +enum { INITIAL, EXTENDED, WAIT }; + private: // Table of precalculated Reed Solomon symbols unsigned char *pCodes; + unsigned char *pCodes2; static const RSIDs rsid_ids[]; static const int rsid_ids_size; - static const int Squares[]; static const int indices[]; + static const RSIDs rsid_ids2[]; + static const int rsid_ids_size2; + + int state; + + int hamming_resolution; + // Span of FFT bins, in which the RSID will be searched for int nBinLow; int nBinHigh; @@ -95,13 +108,22 @@ private: unsigned char aHashTable1[RSID_HASH_LEN]; unsigned char aHashTable2[RSID_HASH_LEN]; - bool bPrevTimeSliceValid; + unsigned char aHashTable1_2[RSID_HASH_LEN]; + unsigned char aHashTable2_2[RSID_HASH_LEN]; + + bool bPrevTimeSliceValid; int iPrevDistance; int iPrevBin; int iPrevSymbol; int iTime; // modulo RSID_NTIMES int aBuckets[RSID_NTIMES][RSID_FFT_SIZE]; + bool bPrevTimeSliceValid2; + int iPrevDistance2; + int iPrevBin2; + int iPrevSymbol2; + int iTime2; // modulo RSID_NTIMES + int DistanceOut; int MetricsOut; @@ -120,14 +142,18 @@ private: int HammingDistance(int iBucket, unsigned char *p2); void CalculateBuckets(const double *pSpectrum, int iBegin, int iEnd); bool search_amp( int &pSymbolOut, int &pBinOut); + bool search_amp2( int &pSymbolOut, int &pBinOut); void search(void); void apply (int iSymbol, int iBin); + void apply2 (int iSymbol, int iBin); public: cRsId(); ~cRsId(); void reset(); void receive(const float* buf, size_t len); void send(bool postidle); + +friend void reset_rsid(void *who); }; #endif diff --git a/src/include/thor.h b/src/include/thor.h index c5830090..e6776ba3 100644 --- a/src/include/thor.h +++ b/src/include/thor.h @@ -1,8 +1,10 @@ // ---------------------------------------------------------------------------- // thor.h -- thor modem // -// Copyright (C) 2008-2009 -// David Freese (w1hkj@w1hkj.com) +// Copyright (C) 2008-2012 +// David Freese +// John Douyere +// John Phelps // // This file is part of fldigi. // @@ -39,6 +41,7 @@ #define THOR_POLY1 0x6d #define THOR_POLY2 0x4f +//VK2ETA high speed modes // NASA Galileo coefficients for viterbi encode/decode algorithms #define GALILEO_K 15 #define GALILEO_POLY1 046321 @@ -51,10 +54,8 @@ #define THORNUMTONES 18 #define THORMAXFFTS 8 -//#define THORBASEFREQ 500.0 -//#define THORFIRSTIF 1000.0 -#define THORBASEFREQ 1000.0 -#define THORFIRSTIF 1500.0 +#define THORBASEFREQ 1500.0 +#define THORFIRSTIF 2000.0 #define THORSCOPESIZE 64 @@ -129,6 +130,8 @@ protected: bool filter_reset; bool staticburst; + + int fec_confidence; // tx variables int txstate; @@ -144,6 +147,9 @@ protected: int bitstate; unsigned char symbolpair[2]; + int flushlength; + + private: complex mixer(int n, const complex& in); @@ -152,6 +158,7 @@ private: void decodesymbol(); void softdecodesymbol(); int harddecode(); + int softdecode(); void update_syncscope(); void synchronize(); void reset_afc(); @@ -159,7 +166,6 @@ private: int get_secondary_char(); void reset_filters(); void decodePairs(unsigned char symbol); -// void decodeEX(int c); bool preambledetect(int c); void softflushrx(); diff --git a/src/include/viterbi.h b/src/include/viterbi.h index cbd30b5e..19bba528 100644 --- a/src/include/viterbi.h +++ b/src/include/viterbi.h @@ -25,181 +25,31 @@ #ifndef VITERBI_H #define VITERBI_H -#define PATHMEM 128 // Must be a power of base 2 (32,64,128,256...) +#define PATHMEM 128 class viterbi { -protected: - int mettab[2][256]; - viterbi( int poly1, int poly2, unsigned int * output, int outsize ); -public: - virtual ~viterbi() ; - - /// CPU cost of this virtual is negligible compared to the rest. - virtual int decode(const unsigned char * sym, int * __restrict__ metric = NULL) = 0; - - template< int k, - int _chunksize = 8, - int _traceback = PATHMEM - 1 > - class impl ; - -}; - -/// Real implementation of viterbi interface. -template< int k, - int _chunksize, - int _traceback > -class viterbi::impl : public viterbi { - // Find the state with the best metric - // We are sure that nstates is even and greater or equal than 2 - int best_metric(int p) const { - const int * __restrict__ metrics_p = metrics[p]; - int bestmetric0 = metrics_p[0]; - int beststate0 = 0; - int bestmetric1 = metrics_p[1]; - int beststate1 = 1; - - /// Loop is unrolled with two tests at a time. - for (int i = 2; i < nstates; i+=2) { - int metrics_p_i_0 = metrics_p[i]; - if (metrics_p_i_0 > bestmetric0) { - bestmetric0 = metrics_p_i_0; - beststate0 = i; - } - int metrics_p_i_1 = metrics_p[i+1]; - if (metrics_p_i_1 > bestmetric1) { - bestmetric1 = metrics_p_i_1; - beststate1 = i+1; - } - } - return bestmetric0 > bestmetric1 ? beststate0 : beststate1 ; - } - - // n is always even because k is always bigger than 1, - // because the number of states must be at least equal to 2. - static const int nstates = 1 << ( k - 1 ); - static const int outsize = 1 << k ; - /// Stores values between zero and three. - unsigned int output[outsize]; - int metrics[PATHMEM][nstates]; - int history[PATHMEM][nstates]; +private: + int _traceback; + int _chunksize; + int nstates; + int *output; + int *metrics[PATHMEM]; + int *history[PATHMEM]; int sequence[PATHMEM]; + int mettab[2][256]; unsigned int ptr; - - int traceback(int * __restrict__ metric) - { - unsigned int p = ptr ? ptr - 1 : PATHMEM - 1 ; - - // Trace back 'traceback' steps, starting from the best state - sequence[p] = best_metric(p); - - int delta = p - _traceback ; - unsigned int limit = delta > 0 ? delta : 0 ; - for( ; p > limit ; --p ) - sequence[p-1] = history[p][sequence[p]]; - - if( delta < 0 ) { - sequence[PATHMEM-1] = history[0][sequence[0]]; - limit = PATHMEM + delta ; - for( p = PATHMEM-1 ; p > limit ; --p ) - sequence[p-1] = history[p][sequence[p]]; - } - - if (metric) - *metric = metrics[p][sequence[p]]; - - // Decode 'chunksize' bits - unsigned int c = 0; - for (int i = 0; i < _chunksize; i++) { - // low bit of state is the previous input bit - c = (c << 1) | (sequence[p] & 1); - p = ( p == PATHMEM - 1 ) ? 0 : p + 1 ; - } - - if (metric) - *metric = metrics[p][sequence[p]] - *metric; - - return c; - } - + int traceback(int *metric); public: - impl(int poly1, int poly2 ) : viterbi( poly1, poly2, output, outsize ) - { - /// Will be eliminated at compile-time if OK. - if (_traceback > PATHMEM - 1) abort(); - if (_chunksize > _traceback) abort(); - - memset( sequence, 0, sizeof(int) * PATHMEM ); - memset( metrics, 0, nstates * sizeof(int) * PATHMEM ); - memset( history, 0, nstates * sizeof(int) * PATHMEM ); - ptr = 0; - } - - ~impl() {} - - int decode(const unsigned char *sym, int * __restrict__ metric = NULL) - { - unsigned int currptr = ptr; - unsigned int prevptr = currptr ? currptr - 1 : PATHMEM - 1 ; - - const int sym0 = sym[0], sym1 = sym[1]; - const int * __restrict__ mettab0 = viterbi::mettab[0]; - const int * __restrict__ mettab1 = viterbi::mettab[1] ; - const int met[4] = { - mettab0[sym1] + mettab0[sym0], - mettab0[sym1] + mettab1[sym0], - mettab1[sym1] + mettab0[sym0], - mettab1[sym1] + mettab1[sym0] } ; - - const int * __restrict__ metrics_prevptr = metrics[prevptr]; - int * __restrict__ metrics_currptr = metrics[currptr]; - int * __restrict__ history_currptr = history[currptr]; - // n and nstates are always even. - for (int n = 0; n < nstates; n+=2) { - /// p0 and p1 do not change if n = n+1, because n is even. - int p0 = n >> 1; - /// Equal to (n + nstates)>> 1 because n and nstates are even. - int p1 = p0 + ( nstates >> 1 ); - - int metrics_p0 = metrics_prevptr[p0]; - int metrics_p1 = metrics_prevptr[p1]; - - int m0 = metrics_p0 + met[output[n]]; - int m1 = metrics_p1 + met[output[n + nstates]]; - - bool m0_gt_1 = m0 > m1 ; - metrics_currptr[n] = m0_gt_1 ? m0 : m1 ; - history_currptr[n] = m0_gt_1 ? p0 : p1 ; - - m0 = metrics_p0 + met[output[n + 1]]; - m1 = metrics_p1 + met[output[n + 1 + nstates]]; - - m0_gt_1 = m0 > m1 ; - metrics_currptr[n + 1] = m0_gt_1 ? m0 : m1 ; - history_currptr[n + 1] = m0_gt_1 ? p0 : p1 ; - } - - ptr = ( ptr == PATHMEM - 1 ) ? 0 : ptr + 1 ; - - if ((ptr % _chunksize) == 0) - return traceback(metric); - - if (metrics[currptr][0] > INT_MAX / 2) { - for (int i = 0; i < PATHMEM; i++) - for (int j = 0; j < nstates; j++) - metrics[i][j] -= INT_MAX / 2; - } - /// This test or the previous, but not both. - else if (metrics[currptr][0] < INT_MIN / 2) { - for (int i = 0; i < PATHMEM; i++) - for (int j = 0; j < nstates; j++) - metrics[i][j] += INT_MIN / 2; - } - - return -1; - } + viterbi(int k, int poly1, int poly2); + ~viterbi(); + void reset(); + int settraceback(int trace); + int setchunksize(int chunk); + int decode(unsigned char *sym, int *metric); }; + class encoder { private: int *output; diff --git a/src/mfsk/interleave.cxx b/src/mfsk/interleave.cxx index 23d0342d..fafdc8b3 100644 --- a/src/mfsk/interleave.cxx +++ b/src/mfsk/interleave.cxx @@ -31,32 +31,10 @@ // ---------------------------------------------------------------------- -interleave::interleave (int _size, int dir) +interleave::interleave (int _size, int _depth, int dir) { size = _size; - if (size == -1) { // dominoEX interleaver - size = 4; - depth = 4; -//BPSK+FEC+interleaver. First digit is size, then number of concatenated square interleavers - } else if (size == -220) { // BPSK FEC + Interleaver 2x2x20 - size = 2; - depth = 20; - } else if (size == -240) { // BPSK FEC + Interleaver 2x2x40 - size = 2; - depth = 40; - } else if (size == -280) { // BPSK FEC + Interleaver 2x2x80 - size = 2; - depth = 80; - } else if (size == -2160) { // BPSK FEC + Interleaver 2x2x160 - size = 2; - depth = 160; - } else if (size == -488) { // THOR 44/88 Interleaver 4x4x88 - size = 4; - depth = 88; - } else if (size == 5) - depth = 5; - else - depth = 10; + depth = _depth; direction = dir; table = new unsigned char [depth * size * size]; memset(table, 0, depth * size * size); diff --git a/src/mfsk/mfsk.cxx b/src/mfsk/mfsk.cxx index ce75b058..ec26b763 100644 --- a/src/mfsk/mfsk.cxx +++ b/src/mfsk/mfsk.cxx @@ -133,13 +133,26 @@ mfsk::mfsk(trx_mode mfsk_mode) : modem() double bw, cf, flo, fhi; mode = mfsk_mode; + int depth = 10; + + //VK2ETA high speed modes + preamble = 107; switch (mode) { + case MODE_MFSK4: + samplerate = 8000; + symlen = 2048; + symbits = 5; + depth = 5; + basetone = 256; + numtones = 32; + break; case MODE_MFSK8: samplerate = 8000; symlen = 1024; symbits = 5; + depth = 5; basetone = 128; numtones = 32; break; @@ -147,46 +160,55 @@ mfsk::mfsk(trx_mode mfsk_mode) : modem() samplerate = 8000; symlen = 512; symbits = 4; + depth = 10; basetone = 64; numtones = 16; cap |= CAP_IMG; break; + case MODE_MFSK31: + samplerate = 8000; + symlen = 256; + symbits = 3; + depth = 10; + basetone = 32; + numtones = 8; + cap |= CAP_IMG; + break; case MODE_MFSK32: samplerate = 8000; symlen = 256; symbits = 4; + depth = 10; basetone = 32; numtones = 16; cap |= CAP_IMG; break; - - case MODE_MFSK4: - samplerate = 8000; - symlen = 2048; - symbits = 5; - basetone = 256; - numtones = 32; - break; - case MODE_MFSK31: - samplerate = 8000; - symlen = 256; - symbits = 3; - basetone = 32; - numtones = 8; - cap |= CAP_IMG; - break; case MODE_MFSK64: samplerate = 8000; symlen = 128; symbits = 4; + depth = 10; basetone = 16; numtones = 16; + preamble = 180; cap |= CAP_IMG; break; + case MODE_MFSK128: + samplerate = 8000; + symlen = 64; + symbits = 4; + depth = 20; + basetone = 8; + numtones = 16; + cap |= CAP_IMG; + preamble = 214; + break; + case MODE_MFSK11: samplerate = 11025; symlen = 1024; symbits = 4; + depth = 10; basetone = 93; numtones = 16; cap |= CAP_IMG; @@ -195,15 +217,17 @@ mfsk::mfsk(trx_mode mfsk_mode) : modem() samplerate = 11025; symlen = 512; symbits = 4; + depth = 10; basetone = 46; numtones = 16; cap |= CAP_IMG; break; -// + default: samplerate = 8000; symlen = 512; symbits = 4; + depth = 10; basetone = 64; numtones = 16; break; @@ -224,11 +248,16 @@ mfsk::mfsk(trx_mode mfsk_mode) : modem() pipe = new rxpipe[ 2 * symlen ]; enc = new encoder (K, POLY1, POLY2); - dec1 = new viterbi::impl ( POLY1, POLY2 ); - dec2 = new viterbi::impl ( POLY1, POLY2 ); + dec1 = new viterbi (K, POLY1, POLY2); + dec2 = new viterbi (K, POLY1, POLY2); - txinlv = new interleave (symbits, INTERLEAVE_FWD); - rxinlv = new interleave (symbits, INTERLEAVE_REV); + dec1->settraceback (45); + dec2->settraceback (45); + dec1->setchunksize (1); + dec2->setchunksize (1); + + txinlv = new interleave (symbits, depth, INTERLEAVE_FWD); + rxinlv = new interleave (symbits, depth, INTERLEAVE_REV); bw = (numtones - 1) * tonespacing; cf = basefreq + bw / 2.0; @@ -512,7 +541,7 @@ void mfsk::softdecode(complex *bins) // shift to range 0...255 for (i = 0; i < symbits; i++) if (staticburst) - symbols[i] = 128; // puncturing 128 is neither 0 nor a 1 + symbols[i] = 0; // puncturing else symbols[i] = (unsigned char)clamp(128.0 + (b[i] / sum * 128.0), 0, 255); @@ -803,12 +832,11 @@ void mfsk::sendbit(int bit) } } -void mfsk::sendchar(unsigned int c) +void mfsk::sendchar(unsigned char c) { const char *code = varienc(c); while (*code) sendbit(*code++ - '0'); - put_echo_char(c); } @@ -828,7 +856,8 @@ void mfsk::flushtx() sendbit(1); // flush the convolutional encoder and interleaver - for (int i = 0; i < 107; i++) +//VK2ETA high speed modes for (int i = 0; i < 107; i++) + for (int i = 0; i < preamble; i++) sendbit(0); bitstate = 0; @@ -868,7 +897,8 @@ void mfsk::sendpic(unsigned char *data, int len) void mfsk::clearbits() { int data = enc->encode(0); - for (int k = 0; k < 100; k++) { +//VK2ETA high speed modes for (int k = 0; k < 100; k++) { + for (int k = 0; k < preamble; k++) { for (int i = 0; i < 2; i++) { bitshreg = (bitshreg << 1) | ((data >> i) & 1); bitstate++; @@ -890,7 +920,8 @@ int mfsk::tx_process() switch (txstate) { case TX_STATE_PREAMBLE: clearbits(); - for (int i = 0; i < 32; i++) +//VK2ETA high speed modes for (int i = 0; i < 32; i++) + for (int i = 0; i < preamble / 3; i++) sendbit(0); txstate = TX_STATE_START; break; @@ -918,9 +949,12 @@ int mfsk::tx_process() txstate = TX_STATE_FLUSH; else if (xmtbyte == GET_TX_CHAR_NODATA) sendidle(); - else + else { + if (xmtbyte & 0x8000) // UTF-8 character send two bytes + sendchar((xmtbyte >> 8) & 0xFF); sendchar(xmtbyte); - break; + } + break; case TX_STATE_FLUSH: sendchar('\r'); diff --git a/src/misc/macros.cxx b/src/misc/macros.cxx index 93a627d3..2e8645e1 100644 --- a/src/misc/macros.cxx +++ b/src/misc/macros.cxx @@ -984,10 +984,23 @@ static void doMODEM(std::string s) set_contestia_tones((int)args[1]); break; case MODE_OLIVIA: // bandwidth, tones - if (args.at(0) != DBL_MIN) - set_olivia_bw((int)args[0]); - if (args.at(1) != DBL_MIN) - set_olivia_tones((int)args[1]); + if (args.at(0) != DBL_MIN && args.at(1) != DBL_MIN) { + int bw = (int)args[0]; + int tones = (int)args[1]; + if (bw == 250 && tones == 4) m = MODE_OLIVIA_4_250; + else if (bw == 250 && tones == 8) m = MODE_OLIVIA_8_250; + else if (bw == 500 && tones == 4) m = MODE_OLIVIA_4_500; + else if (bw == 500 && tones == 8) m = MODE_OLIVIA_8_500; + else if (bw == 500 && tones == 16) m = MODE_OLIVIA_16_500; + else if (bw == 1000 && tones == 8) m = MODE_OLIVIA_8_1000; + else if (bw == 1000 && tones == 16) m = MODE_OLIVIA_16_1000; + else if (bw == 1000 && tones == 32) m = MODE_OLIVIA_32_1000; + else if (bw == 2000 && tones == 64) m = MODE_OLIVIA_64_2000; + else { + set_olivia_bw(bw); + set_olivia_tones(tones); + } + } break; default: break; @@ -1075,10 +1088,23 @@ static void pMODEM(std::string &s, size_t &i, size_t endbracket) set_contestia_tones((int)args[1]); break; case MODE_OLIVIA: // bandwidth, tones - if (args.at(0) != DBL_MIN) - set_olivia_bw((int)args[0]); - if (args.at(1) != DBL_MIN) - set_olivia_tones((int)args[1]); + if (args.at(0) != DBL_MIN && args.at(1) != DBL_MIN) { + int bw = (int)args[0]; + int tones = (int)args[1]; + if (bw == 250 && tones == 4) m = MODE_OLIVIA_4_250; + else if (bw == 250 && tones == 8) m = MODE_OLIVIA_8_250; + else if (bw == 500 && tones == 4) m = MODE_OLIVIA_4_500; + else if (bw == 500 && tones == 8) m = MODE_OLIVIA_8_500; + else if (bw == 500 && tones == 16) m = MODE_OLIVIA_16_500; + else if (bw == 1000 && tones == 8) m = MODE_OLIVIA_8_1000; + else if (bw == 1000 && tones == 16) m = MODE_OLIVIA_16_1000; + else if (bw == 1000 && tones == 32) m = MODE_OLIVIA_32_1000; + else if (bw == 2000 && tones == 64) m = MODE_OLIVIA_64_2000; + else { + set_olivia_bw(bw); + set_olivia_tones(tones); + } + } break; default: break; diff --git a/src/olivia/olivia.cxx b/src/olivia/olivia.cxx index b228025b..6ff37973 100755 --- a/src/olivia/olivia.cxx +++ b/src/olivia/olivia.cxx @@ -37,6 +37,7 @@ #include "confdialog.h" #include "status.h" #include "debug.h" +#include "qrunner.h" LOG_FILE_SOURCE(debug::LOG_MODEM); @@ -142,8 +143,9 @@ int olivia::tx_process() { int c = 0, len = 0; - if (tones != progdefaults.oliviatones || - bw != progdefaults.oliviabw || + if ((mode == MODE_OLIVIA && + (tones != progdefaults.oliviatones || + bw != progdefaults.oliviabw)) || smargin != progdefaults.oliviasmargin || sinteg != progdefaults.oliviasinteg ) restart(); @@ -212,8 +214,9 @@ int olivia::rx_process(const double *buf, int len) static char msg1[20]; static char msg2[20]; - if (tones != progdefaults.oliviatones || - bw != progdefaults.oliviabw || + if ((mode == MODE_OLIVIA && + (tones != progdefaults.oliviatones || + bw != progdefaults.oliviabw)) || smargin != progdefaults.oliviasmargin || sinteg != progdefaults.oliviasinteg ) restart(); @@ -270,8 +273,10 @@ int olivia::rx_process(const double *buf, int len) void olivia::restart() { - tones = progdefaults.oliviatones; - bw = progdefaults.oliviabw; + if (mode == MODE_OLIVIA) { + tones = progdefaults.oliviatones; + bw = progdefaults.oliviabw; + } smargin = progdefaults.oliviasmargin; sinteg = progdefaults.oliviasinteg; @@ -329,7 +334,11 @@ void olivia::restart() fragmentsize = 1024; set_bandwidth(Tx->Bandwidth - Tx->Bandwidth / Tx->Tones); - put_MODEstatus("%s %" PRIuSZ "/%" PRIuSZ "", get_mode_name(), Tx->Tones, Tx->Bandwidth); + if (mode == MODE_OLIVIA) + put_MODEstatus("%s %" PRIuSZ "/%" PRIuSZ "", get_mode_name(), Tx->Tones, Tx->Bandwidth); + else + put_MODEstatus("%s", mode_info[mode].sname);//get_mode_name()); + metric = 0; sigpwr = 1e-10; noisepwr = 1e-8; @@ -343,17 +352,71 @@ void olivia::init() set_scope_mode(Digiscope::BLANK); } -olivia::olivia() +olivia::olivia(trx_mode omode) { + mode = omode; cap |= CAP_REV; txfbuffer = 0; samplerate = 8000; + switch (mode) { + case MODE_OLIVIA_4_250: + progdefaults.oliviatones = tones = 1; + progdefaults.oliviabw = bw = 1; + REQ(set_olivia_tab_widgets); + break; + case MODE_OLIVIA_8_250: + progdefaults.oliviatones = tones = 2; + progdefaults.oliviabw = bw = 1; + REQ(set_olivia_tab_widgets); + break; + case MODE_OLIVIA_4_500: + progdefaults.oliviatones = tones = 1; + progdefaults.oliviabw = bw = 2; + REQ(set_olivia_tab_widgets); + break; + case MODE_OLIVIA_8_500: + progdefaults.oliviatones = tones = 2; + progdefaults.oliviabw = bw = 2; + REQ(set_olivia_tab_widgets); + break; + case MODE_OLIVIA_16_500: + progdefaults.oliviatones = tones = 3; + progdefaults.oliviabw = bw = 2; + REQ(set_olivia_tab_widgets); + break; + case MODE_OLIVIA_8_1000: + progdefaults.oliviatones = tones = 2; + progdefaults.oliviabw = bw = 3; + REQ(set_olivia_tab_widgets); + break; + case MODE_OLIVIA_16_1000: + progdefaults.oliviatones = tones = 3; + progdefaults.oliviabw = bw = 3; + REQ(set_olivia_tab_widgets); + break; + case MODE_OLIVIA_32_1000: + progdefaults.oliviatones = tones = 4; + progdefaults.oliviabw = bw = 3; + REQ(set_olivia_tab_widgets); + break; + case MODE_OLIVIA_64_2000: + progdefaults.oliviatones = tones = 5; + progdefaults.oliviabw = bw = 4; + REQ(set_olivia_tab_widgets); + break; + case MODE_OLIVIA: + default: + tones = progdefaults.oliviatones; + bw = progdefaults.oliviabw; + REQ(set_olivia_tab_widgets); + break; + } + Tx = new MFSK_Transmitter< double >; Rx = new MFSK_Receiver< double >; - mode = MODE_OLIVIA; lastfreq = 0; for (int i = 0; i < SR4; i++) ampshape[i] = 1.0; diff --git a/src/psk/psk.cxx b/src/psk/psk.cxx index 08f0abbc..d3a85e02 100644 --- a/src/psk/psk.cxx +++ b/src/psk/psk.cxx @@ -46,8 +46,6 @@ #include "pskeval.h" #include "ascii.h" -#include "debug.h" - extern waterfall *wf; // Change the following for DCD low pass filter adjustment @@ -65,15 +63,22 @@ extern waterfall *wf; #define PSKR_POLY1 0x6d #define PSKR_POLY2 0x4f +#define SEPARATION 1.4 //separation between carriers expressed as a ratio to sc_bw + +#define GALILEO_K 15 +#define GALILEO_POLY1 046321 +#define GALILEO_POLY2 051271 + char pskmsg[80]; viewpsk *pskviewer = (viewpsk *)0; -pskeval *evalpsk = (pskeval *)0; void psk::tx_init(SoundBase *sc) { scard = sc; - phaseacc = 0; - prevsymbol = complex (1.0, 0.0); + for (int car = 0; car < numcarriers; car++) { + phaseacc[car] = 0; + prevsymbol[car] = complex (1.0, 0.0); + } preamble = dcdbits; if (_pskr) { // MFSK based varicode instead of psk @@ -89,12 +94,17 @@ void psk::tx_init(SoundBase *sc) bitshreg = 0; startpreamble = true; +//Multiple carriers handling + accumulated_bits = 0; + } void psk::rx_init() { - phaseacc = 0; - prevsymbol = complex (1.0, 0.0); + for (int car = 0; car < numcarriers; car++) { + phaseacc[car] = 0; + prevsymbol[car] = complex (1.0, 0.0); + } quality = complex (0.0, 0.0); if (_pskr) { // MFSK varicode instead of psk @@ -124,8 +134,9 @@ void psk::rx_init() void psk::restart() { - pskviewer->restart(mode); - evalpsk->setbw(bandwidth); + if (numcarriers == 1) + pskviewer->restart(mode); + evalpsk->setbw(sc_bw); } void psk::init() @@ -147,13 +158,17 @@ psk::~psk() // FEC 2nd Viterbi decoder if (dec2) delete dec2; - if (fir1) delete fir1; - if (fir2) delete fir2; + for (int i = 0; i < MAX_CARRIERS; i++) { + if (fir1[i]) delete fir1[i]; + if (fir2[i]) delete fir2[i]; + } if (snfilt) delete snfilt; if (imdfilt) delete imdfilt; -// delete local reference to global pointer - pskviewer = 0; - evalpsk = 0; + if (::pskviewer == pskviewer) + ::pskviewer = 0; + delete pskviewer; + delete evalpsk; + // Interleaver if (Rxinlv) delete Rxinlv; if (Rxinlv2) delete Rxinlv2; @@ -166,6 +181,10 @@ psk::psk(trx_mode pskmode) : modem() cap |= CAP_AFC | CAP_AFC_SR; mode = pskmode; + int isize = 5; + int idepth = 5; // 5x5x5 interleaver + + numcarriers = 1; switch (mode) { case MODE_PSK31: @@ -173,30 +192,42 @@ psk::psk(trx_mode pskmode) : modem() _qpsk = false; _pskr = false; dcdbits = 32; + numcarriers = 1; break; case MODE_PSK63: symbollen = 128; _qpsk = false; _pskr = false; dcdbits = 64; + numcarriers = 1; break; case MODE_PSK125: symbollen = 64; _qpsk = false; _pskr = false; dcdbits = 128; + numcarriers = 1; break; case MODE_PSK250: symbollen = 32; _qpsk = false; _pskr = false; dcdbits = 256; + numcarriers = 1; break; case MODE_PSK500: symbollen = 16; _qpsk = false; _pskr = false; dcdbits = 512; + numcarriers = 1; + break; + case MODE_PSK1000: + symbollen = 8; + _qpsk = false; + _pskr = false; + dcdbits = 128; + numcarriers = 1; break; case MODE_QPSK31: @@ -205,6 +236,7 @@ psk::psk(trx_mode pskmode) : modem() _pskr = false; dcdbits = 32; cap |= CAP_REV; + numcarriers = 1; break; case MODE_QPSK63: symbollen = 128; @@ -212,6 +244,7 @@ psk::psk(trx_mode pskmode) : modem() _pskr = false; dcdbits = 64; cap |= CAP_REV; + numcarriers = 1; break; case MODE_QPSK125: symbollen = 64; @@ -219,6 +252,7 @@ psk::psk(trx_mode pskmode) : modem() _pskr = false; dcdbits = 128; cap |= CAP_REV; + numcarriers = 1; break; case MODE_QPSK250: symbollen = 32; @@ -226,6 +260,7 @@ psk::psk(trx_mode pskmode) : modem() _pskr = false; dcdbits = 256; cap |= CAP_REV; + numcarriers = 1; break; case MODE_QPSK500: symbollen = 16; @@ -233,13 +268,14 @@ psk::psk(trx_mode pskmode) : modem() _pskr = false; dcdbits = 512; cap |= CAP_REV; + numcarriers = 1; break; - case MODE_PSK63F: // As per Multipsk (BPSK63 + FEC + MFSK Varicode) symbollen = 128; _qpsk = false; _pskr = true; dcdbits = 64; + numcarriers = 1; break; case MODE_PSK125R: @@ -247,21 +283,270 @@ psk::psk(trx_mode pskmode) : modem() _qpsk = false; _pskr = true; dcdbits = 128; - numinterleavers = -240; // 2x2x40 interleaver + isize = 2; + idepth = 40; // 2x2x40 interleaver + numcarriers = 1; break; case MODE_PSK250R: symbollen = 32; _qpsk = false; _pskr = true; dcdbits = 256; - numinterleavers = -280; // 2x2x80 interleaver + isize = 2; + idepth = 80; // 2x2x80 interleaver + numcarriers = 1; break; case MODE_PSK500R: symbollen = 16; _qpsk = false; _pskr = true; dcdbits = 512; - numinterleavers = -2160; // 2x2x160 interleaver + isize = 2; + idepth = 160; // 2x2x160 interleaver + numcarriers = 1; + break; + case MODE_PSK1000R: + symbollen = 8; + _qpsk = false; + _pskr = true; + dcdbits = 512; + isize = 2; + idepth = 160; // 2x2x160 interleaver + numcarriers = 1; + break; + +// multi-carrier modems + case MODE_4X_PSK63R: + symbollen = 128;//PSK63 + dcdbits = 128; + _qpsk = false; + _pskr = true;//PSKR + numcarriers = 4; + isize = 2; + idepth = 80; // 2x2x80 interleaver + break; + case MODE_5X_PSK63R: + symbollen = 128; //PSK63 + dcdbits = 512; + _qpsk = false; + _pskr = true; //PSKR + numcarriers = 5; + isize = 2; + idepth = 260; // 2x2x160 interleaver + break; + case MODE_10X_PSK63R: + symbollen = 128; //PSK63 + dcdbits = 512; + _qpsk = false; + _pskr = true; //PSKR + numcarriers = 10; + isize = 2; + idepth = 160; // 2x2x160 interleaver + break; + case MODE_20X_PSK63R: + symbollen = 128; //PSK63 + dcdbits = 512; + _qpsk = false; + _pskr = true; //PSKR + numcarriers = 20; + isize = 2; + idepth = 160; // 2x2x160 interleaver + break; + case MODE_32X_PSK63R: + symbollen = 128; //PSK63 + dcdbits = 512; + _qpsk = false; + _pskr = true; //PSKR + numcarriers = 32; + isize = 2; + idepth = 160; // 2x2x160 interleaver + break; + + case MODE_4X_PSK125R: + symbollen = 64;//PSK125 + dcdbits = 512; + _qpsk = false; + _pskr = true;//PSKR + numcarriers = 4; + isize = 2; + idepth = 80; // 2x2x80 interleaver + break; + case MODE_5X_PSK125R: + symbollen = 64;//PSK125 + dcdbits = 512; + _qpsk = false; + _pskr = true;//PSKR + numcarriers = 5; + isize = 2; + idepth = 160; // 2x2x160 interleaver + break; + case MODE_10X_PSK125R: + symbollen = 64;//PSK125 + dcdbits = 512; + _qpsk = false; + _pskr = true;//PSKR + numcarriers = 10; + isize = 2; + idepth = 160; // 2x2x160 interleaver + break; + + case MODE_12X_PSK125: + symbollen = 64;//PSK125 + dcdbits = 128;//512; + _qpsk = false; + _pskr = false; + numcarriers = 12; + break; + case MODE_12X_PSK125R: + symbollen = 64;//PSK125 + dcdbits = 512; + _qpsk = false; + _pskr = true;//PSKR + numcarriers = 12; + isize = 2; + idepth = 160; // 2x2x160 interleaver + break; + + case MODE_16X_PSK125R: + symbollen = 64;//PSK125 + dcdbits = 512; + _qpsk = false; + _pskr = true;//PSKR + numcarriers = 16; + isize = 2; + idepth = 160; // 2x2x160 interleaver + break; + + case MODE_2X_PSK250R: + symbollen = 32;//PSK250 + dcdbits = 512; + _qpsk = false; + _pskr = true;//PSKR + numcarriers = 2; + isize = 2; + idepth = 160; // 2x2x160 interleaver + break; + case MODE_3X_PSK250R: + symbollen = 32;//PSK250 + dcdbits = 512; + _qpsk = false; + _pskr = true;//PSKR + numcarriers = 3; + isize = 2; + idepth = 160; // 2x2x160 interleaver + break; + case MODE_5X_PSK250R: + symbollen = 32;//PSK250 + _qpsk = false; + _pskr = true;//PSKR + dcdbits = 1024; + numcarriers = 5; + isize = 2; + idepth = 160; // 2x2x160 interleaver + break; + case MODE_6X_PSK250: + symbollen = 32;//PSK250 + _qpsk = false; + _pskr = false; + dcdbits = 512; + numcarriers = 6; + break; + case MODE_6X_PSK250R: + symbollen = 32;//PSK250 + _qpsk = false; + _pskr = true;//PSKR + dcdbits = 1024; + numcarriers = 6; + isize = 2; + idepth = 160; // 2x2x160 interleaver + break; + case MODE_7X_PSK250R: + symbollen = 32;//PSK250 + _qpsk = false; + _pskr = true;//PSKR + dcdbits = 1024; + numcarriers = 7; + isize = 2; + idepth = 160; // 2x2x160 interleaver + break; + + case MODE_2X_PSK500: + symbollen = 16; + _qpsk = false; + _pskr = false; + dcdbits = 512; + numcarriers = 2; + break; + case MODE_4X_PSK500: + symbollen = 16; + _qpsk = false; + _pskr = false; + dcdbits = 512; + numcarriers = 4; + break; + + case MODE_2X_PSK500R: + symbollen = 16; + _qpsk = false; + _pskr = true; + dcdbits = 1024; + isize = 2; + idepth = 160; // 2x2x160 interleaver + numcarriers = 2; + break; + case MODE_3X_PSK500R: + symbollen = 16; + _qpsk = false; + _pskr = true; + dcdbits = 1024; + isize = 2; + idepth = 160; // 2x2x160 interleaver + numcarriers = 3; + break; + case MODE_4X_PSK500R: + symbollen = 16; + _qpsk = false; + _pskr = true; + dcdbits = 1024; + isize = 2; + idepth = 160; // 2x2x160 interleaver + numcarriers = 4; + break; + + case MODE_2X_PSK800: + symbollen = 10; + _qpsk = false; + _pskr = false; + dcdbits = 512; + numcarriers = 2; + break; + case MODE_2X_PSK800R: + symbollen = 10; + _qpsk = false; + _pskr = true; + dcdbits = 1024; + isize = 2; + idepth = 160; // 2x2x160 interleaver + numcarriers = 2; + break; + + case MODE_2X_PSK1000: + symbollen = 8;//PSK1000 + _qpsk = false; + _pskr = false; + dcdbits = 1024; + numcarriers = 2; + isize = 2; + idepth = 160; // 2x2x160 interleaver + break; + case MODE_2X_PSK1000R: + symbollen = 8;//PSK1000 + _qpsk = false; + _pskr = true;//PSKR + dcdbits = 1024; + numcarriers = 2; + isize = 2; + idepth = 160; // 2x2x160 interleaver break; default: @@ -270,8 +555,13 @@ psk::psk(trx_mode pskmode) : modem() _qpsk = false; _pskr = false; dcdbits = 32; + numcarriers = 1; } +//printf("%s: symlen %d, dcdbits %d, _qpsk %d, _pskr %d, numc %f\n", +//mode_info[mode].sname, +//symbollen, dcdbits, _qpsk, _pskr, numcarriers); + enc = (encoder *)0; dec = (viterbi *)0; // BPSK+FEC - 2nd Viterbi decoder and de-interleaver @@ -285,9 +575,15 @@ psk::psk(trx_mode pskmode) : modem() double fir1c[64]; double fir2c[64]; - fir1 = new C_FIR_filter(); - fir2 = new C_FIR_filter(); - + for (int i = 0; i < MAX_CARRIERS; i++) { + if (i < numcarriers) { + fir1[i] = new C_FIR_filter(); + fir2[i] = new C_FIR_filter(); + } else { + fir1[i] = (C_FIR_filter *)0; + fir2[i] = (C_FIR_filter *)0; + } + } switch (progdefaults.PSK_filter) { case 1: // use the original gmfsk matched filters @@ -295,37 +591,47 @@ psk::psk(trx_mode pskmode) : modem() fir1c[i] = gmfir1c[i]; fir2c[i] = gmfir2c[i]; } - fir1->init(FIRLEN, symbollen / 16, fir1c, fir1c); - fir2->init(FIRLEN, 1, fir2c, fir2c); + for (int i = 0; i < numcarriers; i++) { + fir1[i]->init(FIRLEN, symbollen > 15 ? symbollen / 16 : 1, fir1c, fir1c); + fir2[i]->init(FIRLEN, 1, fir2c, fir2c); + } break; case 2: // creates fir1c matched sin(x)/x filter w hamming wsincfilt(fir1c, 1.0 / symbollen, false); - fir1->init(FIRLEN, symbollen / 16, fir1c, fir1c); // creates fir2c matched sin(x)/x filter w hamming wsincfilt(fir2c, 1.0 / 16.0, false); - fir2->init(FIRLEN, 1, fir2c, fir2c); + for (int i = 0; i < numcarriers; i++) { + fir1[i]->init(FIRLEN, symbollen > 15 ? symbollen / 16 : 1, fir1c, fir1c); + fir2[i]->init(FIRLEN, 1, fir2c, fir2c); + } break; case 3: // creates fir1c matched sin(x)/x filter w hamming wsincfilt(fir1c, 1.0 / symbollen, false); - fir1->init(FIRLEN, symbollen / 16, fir1c, fir1c); // 1/22 with Hamming window nearly identical to gmfir2c wsincfilt(fir2c, 1.0 / 22.0, false); - fir2->init(FIRLEN, 1, fir2c, fir2c); + for (int i = 0; i < numcarriers; i++) { + fir1[i]->init(FIRLEN, symbollen > 15 ? symbollen / 16 : 1, fir1c, fir1c); + fir2[i]->init(FIRLEN, 1, fir2c, fir2c); + } break; case 4: - fir1->init_lowpass (FIRLEN, 16, 1.5 / symbollen); wsincfilt(fir2c, 1.5 / 16.0, true); - fir2->init(FIRLEN, 1, fir2c, fir2c); + for (int i = 0; i < numcarriers; i++) { + fir1[i]->init_lowpass (FIRLEN, 16, 1.5 / symbollen); + fir2[i]->init(FIRLEN, 1, fir2c, fir2c); + } case 0: default : // creates fir1c matched sin(x)/x filter w blackman wsincfilt(fir1c, 1.0 / symbollen, true); - fir1->init(FIRLEN, symbollen / 16, fir1c, fir1c); // creates fir2c matched sin(x)/x filter w blackman wsincfilt(fir2c, 1.0 / 16.0, true); - fir2->init(FIRLEN, 1, fir2c, fir2c); + for (int i = 0; i < numcarriers; i++) { + fir1[i]->init(FIRLEN, symbollen > 15 ? symbollen / 16 : 1, fir1c, fir1c); + fir2[i]->init(FIRLEN, 1, fir2c, fir2c); + } } snfilt = new Cmovavg(16); @@ -333,29 +639,31 @@ psk::psk(trx_mode pskmode) : modem() if (_qpsk) { enc = new encoder(K, POLY1, POLY2); - dec = new viterbi::impl(POLY1, POLY2); + dec = new viterbi(K, POLY1, POLY2); } if (_pskr) { - // FEC for BPSK. Use a 2nd Viterbi decoder for comparison. - // Set decode size to 4 since some characters can be as small - // as 3 bits long. This minimises intercharacters decoding - // interactions. +// FEC for BPSK. Use a 2nd Viterbi decoder for comparison. +// Set decode size to 4 since some characters can be as small +// as 3 bits long. This minimises intercharacters decoding +// interactions. enc = new encoder(PSKR_K, PSKR_POLY1, PSKR_POLY2); - dec = new viterbi::impl( PSKR_POLY1, PSKR_POLY2); - dec2 = new viterbi::impl(PSKR_POLY1, PSKR_POLY2); + dec = new viterbi(PSKR_K, PSKR_POLY1, PSKR_POLY2); + dec->setchunksize(4); + dec2 = new viterbi(PSKR_K, PSKR_POLY1, PSKR_POLY2); + dec2->setchunksize(4); - // Interleaver. To maintain constant time delay between bits, - // we double the number of concatenated square iterleavers for - // each doubling of speed: 2x2x20 for BSK63+FEC, 2x2x40 for - // BPSK125+FEC, etc.. +// Interleaver. To maintain constant time delay between bits, +// we double the number of concatenated square iterleavers for +// each doubling of speed: 2x2x20 for BSK63+FEC, 2x2x40 for +// BPSK125+FEC, etc.. if (_pskr && (mode != MODE_PSK63F)) { - // 2x2x(20,40,80,160) - Txinlv = new interleave (numinterleavers, INTERLEAVE_FWD); - // 2x2x(20,40,80,160) - Rxinlv = new interleave (numinterleavers, INTERLEAVE_REV); - // 2x2x(20,40,80,160) - Rxinlv2 = new interleave (numinterleavers, INTERLEAVE_REV); +// 2x2x(20,40,80,160) + Txinlv = new interleave (isize, idepth, INTERLEAVE_FWD);//numinterleavers, INTERLEAVE_FWD); +// 2x2x(20,40,80,160) + Rxinlv = new interleave (isize, idepth, INTERLEAVE_REV);//numinterleavers, INTERLEAVE_REV); +// 2x2x(20,40,80,160) + Rxinlv2 = new interleave (isize, idepth, INTERLEAVE_REV);//numinterleavers, INTERLEAVE_REV); } bitshreg = 0; rxbitstate = 0; @@ -370,7 +678,11 @@ psk::psk(trx_mode pskmode) : modem() samplerate = PskSampleRate; fragmentsize = symbollen; - bandwidth = samplerate / symbollen; + sc_bw = samplerate / symbollen; + //JD added for multiple carriers + inter_carrier = SEPARATION * sc_bw; + bandwidth = sc_bw * ( 1 + SEPARATION * (numcarriers - 1)); + snratio = s2n = imdratio = imd = 0; if (mailserver && progdefaults.PSKmailSweetSpot) @@ -382,13 +694,12 @@ psk::psk(trx_mode pskmode) : modem() E1 = E2 = E3 = 0.0; acquire = 0; -//create global instances of evalpsk and pskviewer if they do not exist - if (!::evalpsk) ::evalpsk = new pskeval; - if (!::pskviewer) ::pskviewer = new viewpsk(::evalpsk, mode); - evalpsk = ::evalpsk; - pskviewer = ::pskviewer; + evalpsk = new pskeval; + if (numcarriers == 1) { + ::pskviewer = pskviewer = new viewpsk(evalpsk, mode); + } else + ::pskviewer = pskviewer = 0; -// init(); } //============================================================================= @@ -399,7 +710,7 @@ psk::psk(trx_mode pskmode) : modem() void psk::s2nreport(void) { modem::s2nreport(); - s2n_sum = s2n_sum2 = s2n_ncount = 0.0; + s2n_sum = s2n_sum2 = s2n_ncount = 0.0; } void psk::rx_bit(int bit) @@ -419,6 +730,12 @@ void psk::rx_bit(int bit) s2n_sum += s2n_metric; s2n_sum2 += (s2n_metric * s2n_metric); s2n_ncount ++; +/* if (c == SOH && noSOHyet) { + s2n_sum = s2n_sum2 = 0.0; + s2n_ncount = 1.0; + noSOHyet = false; + } +*/ if (c == EOT) s2nreport(); } @@ -435,6 +752,12 @@ void psk::rx_bit(int bit) s2n_sum += s2n_metric; s2n_sum2 += (s2n_metric * s2n_metric); s2n_ncount++; +/* if (c == SOH && noSOHyet) { + s2n_sum = s2n_sum2 = 0.0; + s2n_ncount = 1.0; + noSOHyet = false; + } +*/ if (c == EOT) s2nreport(); } @@ -463,6 +786,12 @@ void psk::rx_bit2(int bit) s2n_sum += s2n_metric; s2n_sum2 += (s2n_metric * s2n_metric); s2n_ncount++; +/* if (c == SOH && noSOHyet) { + s2n_sum = s2n_sum2 = 0.0; + s2n_ncount = 1.0; + noSOHyet = false; + } +*/ if (c == EOT) s2nreport(); } @@ -483,6 +812,9 @@ void psk::rx_qpsk(int bits) sym[0] = (bits & 1) ? 255 : 0; sym[1] = (bits & 2) ? 0 : 255; // top bit is flipped + //JD added de-interleaver +// Rxinlv->symbols(sym); + c = dec->decode(sym, NULL); if (c != -1) { @@ -504,7 +836,9 @@ void psk::rx_pskr(unsigned char symbol) unsigned char tempc; int c; - // Accumulate the soft bits for the interleaver THEN submit to Viterbi + //In the case of multiple carriers, if even number of carriers then we + // know the bit-order and don't need voting otherwise + // we accumulate the soft bits for the interleaver THEN submit to Viterbi // decoder in alternance so that each one is processed one bit later. // Only two possibilities for sync: current bit or previous one since // we encode with R = 1/2 and send encoded bits one after the other @@ -513,8 +847,14 @@ void psk::rx_pskr(unsigned char symbol) symbolpair[1] = symbolpair[0]; symbolpair[0] = symbol; + if (rxbitstate == 0) { rxbitstate++; + //Only use one decoder is using even carriers (we know the bits order) +// if (((int)numcarriers) % 2 == 0) { +// fecmet2 = -9999.0; +// return; +// } // copy to avoid scrambling symbolpair for the next bit twosym[0] = symbolpair[0]; twosym[1] = symbolpair[1]; @@ -559,37 +899,37 @@ void psk::rx_pskr(unsigned char symbol) void psk::searchDown() { - double srchfreq = frequency - bandwidth * 2; - double minfreq = bandwidth * 2; + double srchfreq = frequency - sc_bw * 2; + double minfreq = sc_bw * 2; double spwr, npwr; while (srchfreq > minfreq) { - spwr = wf->powerDensity(srchfreq, bandwidth); - npwr = wf->powerDensity(srchfreq + bandwidth, bandwidth/2) + 1e-10; + spwr = wf->powerDensity(srchfreq, sc_bw); + npwr = wf->powerDensity(srchfreq + sc_bw, sc_bw/2) + 1e-10; if (spwr / npwr > pow(10, progdefaults.ServerACQsn / 10)) { frequency = srchfreq; set_freq(frequency); sigsearch = SIGSEARCH; break; } - srchfreq -= bandwidth; + srchfreq -= sc_bw; } } void psk::searchUp() { - double srchfreq = frequency + bandwidth * 2; - double maxfreq = IMAGE_WIDTH - bandwidth * 2; + double srchfreq = frequency + sc_bw * 2; + double maxfreq = IMAGE_WIDTH - sc_bw * 2; double spwr, npwr; while (srchfreq < maxfreq) { - spwr = wf->powerDensity(srchfreq, bandwidth/2); - npwr = wf->powerDensity(srchfreq - bandwidth, bandwidth/2) + 1e-10; + spwr = wf->powerDensity(srchfreq, sc_bw/2); + npwr = wf->powerDensity(srchfreq - sc_bw, sc_bw/2) + 1e-10; if (spwr / npwr > pow(10, progdefaults.ServerACQsn / 10)) { frequency = srchfreq; set_freq(frequency); sigsearch = SIGSEARCH; break; } - srchfreq += bandwidth; + srchfreq += sc_bw; } } @@ -609,7 +949,7 @@ void psk::findsignal() f1 = (int)(frequency - progdefaults.ServerOffset); f2 = (int)(frequency + progdefaults.ServerOffset); } - if (evalpsk->sigpeak(ftest, f1, f2, bandwidth) > pow(10, progdefaults.ServerACQsn / 10) ) { + if (evalpsk->sigpeak(ftest, f1, f2) > pow(10, progdefaults.ServerACQsn / 10) ) { if (progdefaults.PSKmailSweetSpot) { if (fabs(ftest - progdefaults.ServerCarrier) < progdefaults.ServerOffset) { frequency = ftest; @@ -633,10 +973,9 @@ void psk::findsignal() } } } else { // normal signal search algorithm - ftest = frequency; - f1 = ftest - progdefaults.SearchRange/2; - f2 = ftest + progdefaults.SearchRange/2; - if (evalpsk->peak(ftest, f1, f2, progdefaults.ACQsn) ) { + f1 = (int)(frequency - progdefaults.SearchRange/2); + f2 = (int)(frequency + progdefaults.SearchRange/2); + if (evalpsk->sigpeak(ftest, f1, f2) > pow(10, progdefaults.ACQsn / 10.0) ) { frequency = ftest; set_freq(frequency); freqerr = 0.0; @@ -647,26 +986,30 @@ void psk::findsignal() } } +//JD: disable for multiple carriers as we are running as modem and +// therefore use other strategies for frequency alignment like RSID void psk::phaseafc() { double error; - if (afcmetric < 0.05) return; + if (afcmetric < 0.05 || + mode == MODE_PSK500 || + mode == MODE_QPSK500 || + numcarriers > 1 ) return; error = (phase - bits * M_PI / 2.0); - if (error < M_PI / 2.0) error += 2 * M_PI; - if (error > M_PI / 2.0) error -= 2 * M_PI; - - error *= (samplerate / (TWOPI * symbollen))/16.0; // the count between symbols - frequency -= error; - - if (mailserver) { - if (frequency < progdefaults.ServerCarrier - progdefaults.ServerAFCrange) - frequency = progdefaults.ServerCarrier - progdefaults.ServerAFCrange; - if (frequency > progdefaults.ServerCarrier + progdefaults.ServerAFCrange) - frequency = progdefaults.ServerCarrier + progdefaults.ServerAFCrange; + if (error < -M_PI / 2.0 || error > M_PI / 2.0) return; + error *= samplerate / (TWOPI * symbollen); + if (fabs(error) < sc_bw ) { + freqerr = error / dcdbits; + frequency -= freqerr; + if (mailserver) { + if (frequency < progdefaults.ServerCarrier - progdefaults.ServerAFCrange) + frequency = progdefaults.ServerCarrier - progdefaults.ServerAFCrange; + if (frequency > progdefaults.ServerCarrier + progdefaults.ServerAFCrange) + frequency = progdefaults.ServerCarrier + progdefaults.ServerAFCrange; + } + set_freq (frequency); } - set_freq (frequency); - if (acquire) acquire--; } @@ -679,7 +1022,7 @@ void psk::afc() } -void psk::rx_symbol(complex symbol) +void psk::rx_symbol(complex symbol, int car) { int n; unsigned char softbit = 0; @@ -689,8 +1032,8 @@ void psk::rx_symbol(complex symbol) static double averageamp; - phase = (prevsymbol % symbol).arg(); - prevsymbol = symbol; + phase = (prevsymbol[car] % symbol).arg(); + prevsymbol[car] = symbol; if (phase < 0) phase += TWOPI; @@ -723,8 +1066,10 @@ static double averageamp; } // simple low pass filter for quality of signal - quality.re = decayavg(quality.re, cos(n*phase), _pskr ? SQLDECAY * 5 : SQLDECAY); - quality.im = decayavg(quality.im, sin(n*phase), _pskr ? SQLDECAY * 5 : SQLDECAY); +// quality.re = decayavg(quality.re, cos(n*phase), _pskr ? SQLDECAY * 5 : SQLDECAY); +// quality.im = decayavg(quality.im, sin(n*phase), _pskr ? SQLDECAY * 5 : SQLDECAY); + quality.re = decayavg(quality.re, cos(n*phase), _pskr ? SQLDECAY * 10 : SQLDECAY); + quality.im = decayavg(quality.im, sin(n*phase), _pskr ? SQLDECAY * 10 : SQLDECAY); metric = 100.0 * quality.norm(); @@ -770,6 +1115,8 @@ static double averageamp; acquire = 0; quality = complex (1.0, 0.0); imdValid = true; +//VK2ETA added logic to prevent resetting +// noSOHyet = true; if (progdefaults.Pskmails2nreport && (mailserver || mailclient)) s2n_sum = s2n_sum2 = s2n_ncount = 0.0; } @@ -845,58 +1192,171 @@ char bitstatus[100]; int psk::rx_process(const double *buf, int len) { - double delta; - complex z, z2; + double delta[MAX_CARRIERS], frequencies[MAX_CARRIERS]; + complex z, z2[MAX_CARRIERS]; + bool can_rx_symbol = false; - if (pskviewer && !bHistory && progdefaults.pskbrowser_on) - pskviewer->rx_process(buf, len); - if (evalpsk) evalpsk->sigdensity(); + if (numcarriers == 1) { + if (pskviewer && !bHistory) pskviewer->rx_process(buf, len); + if (evalpsk) evalpsk->sigdensity(); + } - delta = TWOPI * frequency / samplerate; + frequencies[0] = frequency + ((-1 * numcarriers) + 1) * inter_carrier / 2; + delta[0] = TWOPI * frequencies[0] / samplerate; + for (int car = 1; car < numcarriers; car++) { + frequencies[car] = frequencies[car - 1] + inter_carrier; + delta[car] = TWOPI * frequencies[car] / samplerate; + } while (len-- > 0) { - // Mix with the internal NCO - z = complex ( *buf * cos(phaseacc), *buf * sin(phaseacc) ); - buf++; - phaseacc += delta; - if (phaseacc > M_PI) - phaseacc -= TWOPI; + for (int car = 0; car < numcarriers; car++) { + + // Mix with the internal NCO + z = complex ( *buf * cos(phaseacc[car]), *buf * sin(phaseacc[car]) ); + + phaseacc[car] += delta[car]; + if (phaseacc[car] > M_PI) + phaseacc[car] -= TWOPI; // Filter and downsample // by 16 (psk31, qpsk31) // by 8 (psk63, qpsk63) // by 4 (psk125, qpsk125) // by 2 (psk250, qpsk250) + // by 1 (psk500, qpsk500) = no down sampling // first filter - if (fir1->run( z, z )) { // fir1 returns true every Nth sample - // final filter - fir2->run( z, z2 ); // fir2 returns value on every sample - calcSN_IMD(z); + if (fir1[car]->run( z, z )) { // fir1 returns true every Nth sample + // final filter + fir2[car]->run( z, z2[car] ); // fir2 returns value on every sample + + //On last carrier processing + if (car == numcarriers - 1) { + + calcSN_IMD(z); //JD OR all carriers together check logic??? + +/** +* This is the symbol timing recovery mechanism. After the demodulated +* signal is processed by the matched filters, the signal lobes are +* expected to have been modified to a fairly symmetric shape. The +* magnitude of the samples are taken, thus rectifying the signal to +* positive values. "bitclk" is a counter that is very close in rate to +* (samples / symbol). Its purpose is to repeatedly "draw" one symbol +* waveform in the syncbuf array, according to its amplitude (not phase). +*/ int idx = (int) bitclk; double sum = 0.0; double ampsum = 0.0; - syncbuf[idx] = 0.8 * syncbuf[idx] + 0.2 * z2.mag(); + for (int ii = 0; ii < numcarriers; ii++) { + sum += z2[ii].mag()/numcarriers; + } +// syncbuf[idx] = 0.8 * syncbuf[idx] + 0.2 * z2[car].mag(); + syncbuf[idx] = 0.8 * syncbuf[idx] + 0.2 * sum; + sum = 0.0; - for (int i = 0; i < 8; i++) { + //Handling of modes faster than PSK500/PSK500R + +/* for (int i = 0; i < 8; i++) { sum += (syncbuf[i] - syncbuf[i+8]); ampsum += (syncbuf[i] + syncbuf[i+8]); } +*/ +// double bitsteps = (symbollen >= 16 ? 16 : 8); + double bitsteps = (symbollen >= 16 ? 16 : symbollen); + int symsteps = (int) (bitsteps / 2); + +/** +* Here we sum up the difference between each sample's magnitude in the +* lower half of the array with its counterpart on the upper half of the +* array, or the other side of the waveform. Each pair's difference is +* divided by their sum, scaling it so that the signal amplitude does not +* affect the result. When the differences are summed, it gives an +* indication of which side is larger than the other. +*/ + + for (int i = 0; i < symsteps; i++) { + sum += (syncbuf[i] - syncbuf[i+symsteps]); + ampsum += (syncbuf[i] + syncbuf[i+symsteps]); + } // added correction as per PocketDigi sum = (ampsum == 0 ? 0 : sum / ampsum); - bitclk -= sum / 5.0; +/** +* If the lower side is larger (meaning that the waveform is shifted in that +* direction), then the sum is negative, and bitclk needs to be adjusted to +* be a little faster, so that the next drawing of the waveform in syncbuf +* will be shifted right. Conversely, if the sum is positive, then it needs +* to slow down bitclk so that the waveform is shifted left. Thus the +* error is subtracted from bitclk, rather than added. The goal is to +* get the error as close to zero as possible, so that the receiver is +* exactly synced with the transmitter and the waveform is exactly in +* the middle of syncbuf. +*/ + +// bitclk -= sum / 5.0; + bitclk -= sum / (5.0 * 16 / bitsteps); bitclk += 1; - if (bitclk < 0) bitclk += 16.0; - if (bitclk >= 16.0) { - bitclk -= 16.0; - rx_symbol(z2); +/** +* When bitclock reaches the end of the buffer, then a complete waveform +* has been received. It is time to output the current sample and wrap +* around to the next cycle. +* +* There is a complete symbol waveform in syncbuf, so that each +* sample[0..N/2-1] is very close in amplitude with the corresponding +* sample in [N/2..N-1]. +* +* | ******** ******** | +* | **** **** **** **** | +* | *** *** *** *** | +* | ** ** ** ** | +* | * * * * | +* | * * * * | +* |* * *| +* |_______________________________________________________________| +* 0 N/2 N-1 +* +* === or some variation of it .... === +* +* |**** ******** *****| +* | **** **** **** **** | +* | *** *** *** *** | +* | ** ** ** ** | +* | * * * * | +* | * * * * | +* | * * | +* |_______________________________________________________________| +* 0 N/2 N-1 +* +* At the end of this cycle, bitclk is pointing at a sample which will +* have the maximum phase difference, if any, from the previous symbol's +* phase. +* +*/ + +// if (bitclk < 0) bitclk += 16.0; +// if (bitclk >= 16.0) { +// bitclk -= 16.0; + + if (bitclk < 0) bitclk += bitsteps; + if (bitclk >= bitsteps) { + bitclk -= bitsteps; + can_rx_symbol = true; update_syncscope(); afc(); } + } + } + } + if (can_rx_symbol) { + for (int car = 0; car < numcarriers; car++) { + rx_symbol(z2[car], car); + } + can_rx_symbol = false; + } + buf++; } if (sigsearch) @@ -926,50 +1386,78 @@ int psk::rx_process(const double *buf, int len) void psk::tx_symbol(int sym) { - double delta; + double delta[MAX_CARRIERS]; double ival, qval, shapeA, shapeB; complex symbol; + double frequencies[MAX_CARRIERS]; - if (_qpsk && !reverse) - sym = (4 - sym) & 3; + txsymbols[accumulated_bits] = sym; - // differential QPSK modulation - top bit flipped - switch (sym) { - case 0: - symbol = complex (-1.0, 0.0); // 180 degrees - break; - case 1: - symbol = complex (0.0, -1.0); // 270 degrees - break; - case 2: - symbol = complex (1.0, 0.0); // 0 degrees - break; - case 3: - symbol = complex (0.0, 1.0); // 90 degrees - break; + if (++accumulated_bits < numcarriers) { + return; + } + + //Process all carrier's symbols, then submit to sound card + accumulated_bits = 0; //reset + frequencies[0] = get_txfreq_woffset() + ((-1 * numcarriers) + 1) * inter_carrier / 2; + delta[0] = TWOPI * frequencies[0] / samplerate; + for (int car = 1; car < numcarriers; car++) { + frequencies[car] = frequencies[car - 1] + inter_carrier; + delta[car] = TWOPI * frequencies[car] / samplerate; } - symbol = prevsymbol * symbol; // complex multiplication - delta = 2.0 * M_PI * get_txfreq_woffset() / samplerate; +double maxamp = 0; + for (int car = 0; car < numcarriers; car++) { + sym = txsymbols[car]; - for (int i = 0; i < symbollen; i++) { + if (_qpsk && !reverse) + sym = (4 - sym) & 3; - shapeA = tx_shape[i]; - shapeB = (1.0 - shapeA); + // differential QPSK modulation - top bit flipped + switch (sym) { + case 0: + symbol = complex (-1.0, 0.0); // 180 degrees + break; + case 1: + symbol = complex (0.0, -1.0); // 270 degrees + break; + case 2: + symbol = complex (1.0, 0.0); // 0 degrees + break; + case 3: + symbol = complex (0.0, 1.0); // 90 degrees + break; + } + symbol = prevsymbol[car] * symbol; // complex multiplication - ival = shapeA * prevsymbol.real() + shapeB * symbol.real(); - qval = shapeA * prevsymbol.imag() + shapeB * symbol.imag(); + for (int i = 0; i < symbollen; i++) { - outbuf[i] = ival * cos(phaseacc) + qval * sin(phaseacc); + shapeA = tx_shape[i]; + shapeB = (1.0 - shapeA); - phaseacc += delta; - if (phaseacc > M_PI) - phaseacc -= 2.0 * M_PI; + ival = shapeA * prevsymbol[car].real() + shapeB * symbol.real(); + qval = shapeA * prevsymbol[car].imag() + shapeB * symbol.imag(); + + if (car != 0) { + outbuf[i] += (ival * cos(phaseacc[car]) + qval * sin(phaseacc[car]));// / numcarriers; + } else { + outbuf[i] = (ival * cos(phaseacc[car]) + qval * sin(phaseacc[car]));// / numcarriers; + } + if (maxamp < fabs(outbuf[i])) { + maxamp = fabs(outbuf[i]); + } + + phaseacc[car] += delta[car]; + if (phaseacc[car] > M_PI) + phaseacc[car] -= 2.0 * M_PI; + } + + prevsymbol[car] = symbol; } + if (maxamp) + for (int i = 0; i < symbollen; i++) outbuf[i] /= maxamp; ModulateXmtr(outbuf, symbollen); - - prevsymbol = symbol; } void psk::tx_bit(int bit) @@ -979,6 +1467,9 @@ void psk::tx_bit(int bit) // qpsk transmission if (_qpsk) { sym = enc->encode(bit); + //JD add interleaver +// Txinlv->bits(&sym); + sym = sym & 3;//JD just to make sure tx_symbol(sym); // else pskr (fec + interleaver) transmission } else if (_pskr) { @@ -1026,8 +1517,15 @@ void psk::tx_char(unsigned char c) void psk::tx_flush() { if (_pskr) { - for (int i = 0; i < dcdbits; i++) - tx_bit(0); + //VK2ETA replace with a more effective flushing sequence (avoids cutting the last characters in low s/n) +/* for (int i = 0; i < dcdbits; i++) + tx_bit(0); + } +*/ + for (int i = 0; i < dcdbits / 2; i++) { + tx_bit(1); + tx_bit(1); + } } // QPSK - flush the encoder if (_qpsk) { @@ -1037,8 +1535,11 @@ void psk::tx_flush() } // Standard BPSK postamble // DCD off sequence (unmodulated carrier) - for (int i = 0; i < dcdbits; i++) - tx_symbol(2); + //VK2ETA remove for pskr since it is not used for DCD and only adds delay and creates TX overlaps + if (!_pskr) { + for (int i = 0; i < dcdbits; i++) + tx_symbol(2); + } } // Necessary to clear the interleaver before we start sending @@ -1072,6 +1573,8 @@ int psk::tx_process() if (preamble == 0) tx_bit(0); return 0; } else { + //JD for QPSK500R +// if (mode == MODE_QPSK500) clearbits(); // Standard BPSK/QPSK preamble preamble--; tx_symbol(0); // send phase reversals diff --git a/src/psk/pskeval.cxx b/src/psk/pskeval.cxx index 744a6522..6d9cf9e8 100644 --- a/src/psk/pskeval.cxx +++ b/src/psk/pskeval.cxx @@ -77,7 +77,7 @@ void pskeval::sigdensity() { delete [] vals; } -double pskeval::sigpeak(int &f, int f1, int f2, int w) +double pskeval::sigpeak(int &f, int f1, int f2) { double peak = 0; f1 -= bw; diff --git a/src/qrunner/qrunner.cxx b/src/qrunner/qrunner.cxx index 1ccd52fe..b4d69004 100644 --- a/src/qrunner/qrunner.cxx +++ b/src/qrunner/qrunner.cxx @@ -37,7 +37,8 @@ #include "fqueue.h" #include "qrunner.h" -#define FIFO_SIZE 2048 +//Remi's advice for FIFO full issue #define FIFO_SIZE 2048 +#define FIFO_SIZE 8192 #ifndef __MINGW32__ # define QRUNNER_EAGAIN() (errno == EAGAIN) diff --git a/src/rsid/rsid.cxx b/src/rsid/rsid.cxx index 4f3b3e63..be08bb4d 100644 --- a/src/rsid/rsid.cxx +++ b/src/rsid/rsid.cxx @@ -2,10 +2,12 @@ // // rsid.cxx // -// Copyright (C) 2008-2010 +// Copyright (C) 2008-2012 // Dave Freese, W1HKJ -// Copyright (C) 2009 +// Copyright (C) 2009-2012 // Stelios Bounanos, M0GLD +// Copyright (C) 2012 +// John Douyere, VK2ETA // // This file is part of fldigi. // @@ -47,203 +49,19 @@ LOG_FILE_SOURCE(debug::LOG_MODEM); -// Syntax: ELEM_(rsid_code, rsid_tag, fldigi_mode) -// fldigi_mode is NUM_MODES if mode is not available in fldigi, -// otherwise one of the tags defined in globals.h. -// rsid_tag is stringified and may be shown to the user. -#undef ELEM_ -#define RSID_LIST \ - ELEM_(1, BPSK31, MODE_PSK31) \ - ELEM_(110, QPSK31, MODE_QPSK31) \ - ELEM_(2, BPSK63, MODE_PSK63) \ - ELEM_(3, QPSK63, MODE_QPSK63) \ - ELEM_(4, BPSK125, MODE_PSK125) \ - ELEM_(5, QPSK125, MODE_QPSK125) \ - ELEM_(126, BPSK250, MODE_PSK250) \ - ELEM_(127, QPSK250, MODE_QPSK250) \ - ELEM_(173, BPSK500, MODE_PSK500) \ - \ - ELEM_(183, PSK125R, MODE_PSK125R) \ - ELEM_(186, PSK250R, MODE_PSK250R) \ - ELEM_(187, PSK500R, MODE_PSK500R) \ - \ - ELEM_(7, PSKFEC31, NUM_MODES) \ - ELEM_(8, PSK10, NUM_MODES) \ - \ - ELEM_(9, MT63_500_LG, MODE_MT63_500) \ - ELEM_(10, MT63_500_ST, MODE_MT63_500) \ - ELEM_(11, MT63_500_VST, MODE_MT63_500) \ - ELEM_(12, MT63_1000_LG, MODE_MT63_1000) \ - ELEM_(13, MT63_1000_ST, MODE_MT63_1000) \ - ELEM_(14, MT63_1000_VST, MODE_MT63_1000) \ - ELEM_(15, MT63_2000_LG, MODE_MT63_2000) \ - ELEM_(17, MT63_2000_ST, MODE_MT63_2000) \ - ELEM_(18, MT63_2000_VST, MODE_MT63_2000) \ - \ - ELEM_(19, PSKAM10, NUM_MODES) \ - ELEM_(20, PSKAM31, NUM_MODES) \ - ELEM_(21, PSKAM50, NUM_MODES) \ - \ - ELEM_(22, PSK63F, MODE_PSK63F) \ - ELEM_(23, PSK220F, NUM_MODES) \ - \ - ELEM_(24, CHIP64, NUM_MODES) \ - ELEM_(25, CHIP128, NUM_MODES) \ - \ - ELEM_(26, CW, MODE_CW) \ - \ - ELEM_(27, CCW_OOK_12, NUM_MODES) \ - ELEM_(28, CCW_OOK_24, NUM_MODES) \ - ELEM_(29, CCW_OOK_48, NUM_MODES) \ - ELEM_(30, CCW_FSK_12, NUM_MODES) \ - ELEM_(31, CCW_FSK_24, NUM_MODES) \ - ELEM_(33, CCW_FSK_48, NUM_MODES) \ - \ - ELEM_(34, PACTOR1_FEC, NUM_MODES) \ - \ - ELEM_(113, PACKET_110, NUM_MODES) \ - ELEM_(35, PACKET_300, NUM_MODES) \ - ELEM_(36, PACKET_1200, NUM_MODES) \ - \ - ELEM_(37, RTTY_ASCII_7, MODE_RTTY) \ - ELEM_(38, RTTY_ASCII_8, MODE_RTTY) \ - ELEM_(39, RTTY_45, MODE_RTTY) \ - ELEM_(40, RTTY_50, MODE_RTTY) \ - ELEM_(41, RTTY_75, MODE_RTTY) \ - \ - ELEM_(42, AMTOR_FEC, NUM_MODES) \ - \ - ELEM_(43, THROB_1, MODE_THROB1) \ - ELEM_(44, THROB_2, MODE_THROB2) \ - ELEM_(45, THROB_4, MODE_THROB4) \ - ELEM_(46, THROBX_1, MODE_THROBX1) \ - ELEM_(47, THROBX_2, MODE_THROBX2) \ - ELEM_(146, THROBX_4, MODE_THROBX4) \ - \ - ELEM_(204, CONTESTIA_4_125, MODE_CONTESTIA) \ - ELEM_(55, CONTESTIA_4_250, MODE_CONTESTIA) \ - ELEM_(54, CONTESTIA_4_500, MODE_CONTESTIA) \ - ELEM_(255, CONTESTIA_4_1000, MODE_CONTESTIA) \ - ELEM_(254, CONTESTIA_4_2000, MODE_CONTESTIA) \ - \ - ELEM_(169, CONTESTIA_8_125, MODE_CONTESTIA) \ - ELEM_(49, CONTESTIA_8_250, MODE_CONTESTIA) \ - ELEM_(52, CONTESTIA_8_500, MODE_CONTESTIA) \ - ELEM_(117, CONTESTIA_8_1000, MODE_CONTESTIA) \ - ELEM_(247, CONTESTIA_8_2000, MODE_CONTESTIA) \ - \ - ELEM_(50, CONTESTIA_16_500, MODE_CONTESTIA) \ - ELEM_(53, CONTESTIA_16_1000, MODE_CONTESTIA) \ - ELEM_(259, CONTESTIA_16_2000, MODE_CONTESTIA) \ - \ - ELEM_(51, CONTESTIA_32_1000, MODE_CONTESTIA) \ - ELEM_(201, CONTESTIA_32_2000, MODE_CONTESTIA) \ - \ - ELEM_(194, CONTESTIA_64_500, MODE_CONTESTIA) \ - ELEM_(193, CONTESTIA_64_1000, MODE_CONTESTIA) \ - ELEM_(191, CONTESTIA_64_2000, MODE_CONTESTIA) \ - \ - ELEM_(261, CONTESTIA_128_2000, MODE_CONTESTIA) \ - \ - ELEM_(56, VOICE, NUM_MODES) \ - \ - ELEM_(60, MFSK8, MODE_MFSK8) \ - ELEM_(57, MFSK16, MODE_MFSK16) \ - ELEM_(147, MFSK32, MODE_MFSK32) \ - ELEM_(148, MFSK11, MODE_MFSK11) \ - ELEM_(152, MFSK22, MODE_MFSK22) \ - \ - ELEM_(61, RTTYM_8_250, NUM_MODES) \ - ELEM_(62, RTTYM_16_500, NUM_MODES) \ - ELEM_(63, RTTYM_32_1000, NUM_MODES) \ - ELEM_(65, RTTYM_8_500, NUM_MODES) \ - ELEM_(66, RTTYM_16_1000, NUM_MODES) \ - ELEM_(67, RTTYM_4_500, NUM_MODES) \ - ELEM_(68, RTTYM_4_250, NUM_MODES) \ - ELEM_(119, RTTYM_8_1000, NUM_MODES) \ - ELEM_(170, RTTYM_8_125, NUM_MODES) \ - \ - ELEM_(203, OLIVIA_4_125, MODE_OLIVIA) \ - ELEM_(75, OLIVIA_4_250, MODE_OLIVIA) \ - ELEM_(74, OLIVIA_4_500, MODE_OLIVIA) \ - ELEM_(229, OLIVIA_4_1000, MODE_OLIVIA) \ - ELEM_(238, OLIVIA_4_2000, MODE_OLIVIA) \ - \ - ELEM_(163, OLIVIA_8_125, MODE_OLIVIA) \ - ELEM_(69, OLIVIA_8_250, MODE_OLIVIA) \ - ELEM_(72, OLIVIA_8_500, MODE_OLIVIA) \ - ELEM_(116, OLIVIA_8_1000, MODE_OLIVIA) \ - ELEM_(214, OLIVIA_8_2000, MODE_OLIVIA) \ - \ - ELEM_(70, OLIVIA_16_500, MODE_OLIVIA) \ - ELEM_(73, OLIVIA_16_1000, MODE_OLIVIA) \ - ELEM_(234, OLIVIA_16_2000, MODE_OLIVIA) \ - \ - ELEM_(71, OLIVIA_32_1000, MODE_OLIVIA) \ - ELEM_(221, OLIVIA_32_2000, MODE_OLIVIA) \ - \ - ELEM_(211, OLIVIA_64_2000, MODE_OLIVIA) \ - \ - ELEM_(76, PAX, NUM_MODES) \ - ELEM_(77, PAX2, NUM_MODES) \ - ELEM_(78, DOMINOF, NUM_MODES) \ - ELEM_(79, FAX, NUM_MODES) \ - ELEM_(81, SSTV, NUM_MODES) \ - \ - ELEM_(84, DOMINOEX_4, MODE_DOMINOEX4) \ - ELEM_(85, DOMINOEX_5, MODE_DOMINOEX5) \ - ELEM_(86, DOMINOEX_8, MODE_DOMINOEX8) \ - ELEM_(87, DOMINOEX_11, MODE_DOMINOEX11) \ - ELEM_(88, DOMINOEX_16, MODE_DOMINOEX16) \ - ELEM_(90, DOMINOEX_22, MODE_DOMINOEX22) \ - ELEM_(92, DOMINOEX_4_FEC, MODE_DOMINOEX4) \ - ELEM_(93, DOMINOEX_5_FEC, MODE_DOMINOEX5) \ - ELEM_(97, DOMINOEX_8_FEC, MODE_DOMINOEX8) \ - ELEM_(98, DOMINOEX_11_FEC, MODE_DOMINOEX11) \ - ELEM_(99, DOMINOEX_16_FEC, MODE_DOMINOEX16) \ - ELEM_(101, DOMINOEX_22_FEC, MODE_DOMINOEX22) \ - \ - ELEM_(104, FELD_HELL, MODE_FELDHELL) \ - ELEM_(105, PSK_HELL, NUM_MODES) \ - ELEM_(106, HELL_80, MODE_HELL80) \ - ELEM_(107, FM_HELL_105, MODE_FSKH105) \ - ELEM_(108, FM_HELL_245, NUM_MODES) \ - \ - ELEM_(114, MODE_141A, NUM_MODES) \ - ELEM_(123, DTMF, NUM_MODES) \ - ELEM_(125, ALE400, NUM_MODES) \ - ELEM_(131, FDMDV, NUM_MODES) \ - \ - ELEM_(132, JT65_A, NUM_MODES) \ - ELEM_(134, JT65_B, NUM_MODES) \ - ELEM_(135, JT65_C, NUM_MODES) \ - \ - ELEM_(136, THOR_4, MODE_THOR4) \ - ELEM_(137, THOR_8, MODE_THOR8) \ - ELEM_(138, THOR_16, MODE_THOR16) \ - ELEM_(139, THOR_5, MODE_THOR5) \ - ELEM_(143, THOR_11, MODE_THOR11) \ - ELEM_(145, THOR_22, MODE_THOR22) \ - \ - ELEM_(153, CALL_ID, NUM_MODES) \ - \ - ELEM_(155, PACKET_PSK1200, NUM_MODES) \ - ELEM_(156, PACKET_PSK250, NUM_MODES) \ - ELEM_(159, PACKET_PSK63, NUM_MODES) \ - \ - ELEM_(172, MODE_188_110A_8N1, NUM_MODES) \ - \ - /* NONE must be the last element */ \ - ELEM_(0, NONE, NUM_MODES) +#include "rsid_defs.cxx" -#define ELEM_(code_, tag_, mode_) RSID_ ## tag_ = code_, -enum { RSID_LIST }; -#undef ELEM_ +void reset_rsid(void *who) { + cRsId *me = (cRsId *)who; + LOG_INFO("%s", "RxID detector reset"); + me->state = cRsId::INITIAL; + me->reset(); +} -#define ELEM_(code_, tag_, mode_) { RSID_ ## tag_, mode_, #tag_ }, -const RSIDs cRsId::rsid_ids[] = { RSID_LIST }; -#undef ELEM_ -const int cRsId::rsid_ids_size = sizeof(rsid_ids)/sizeof(*rsid_ids) - 1; +void reset_rsid_detector(void *me) { + Fl::remove_timeout(reset_rsid); + Fl::add_timeout(3*15*RSID_SYMLEN, reset_rsid, me); +} const int cRsId::Squares[] = { 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, @@ -285,14 +103,14 @@ cRsId::cRsId() memset(aHashTable1, 255, sizeof(aHashTable1)); memset(aHashTable2, 255, sizeof(aHashTable2)); memset(fftwindow, 0, RSID_ARRAY_SIZE * sizeof(double)); -// BlackmanWindow(fftwindow, RSID_FFT_SIZE); -// HammingWindow(fftwindow, RSID_FFT_SIZE); -// HanningWindow(fftwindow, RSID_FFT_SIZE); RectWindow(fftwindow, RSID_FFT_SIZE); - + pCodes = new unsigned char[rsid_ids_size * RSID_NSYMBOLS]; memset(pCodes, 0, rsid_ids_size * RSID_NSYMBOLS); + pCodes2 = new unsigned char[rsid_ids_size2 * RSID_NSYMBOLS]; + memset(pCodes, 0, rsid_ids_size2 * RSID_NSYMBOLS); + // Initialization of assigned mode/submode IDs. // HashTable is used for finding a code with lowest Hamming distance. unsigned char* c; @@ -306,17 +124,33 @@ cRsId::cRsId() aHashTable2[hash2] = i; } + for (int i = 0; i < rsid_ids_size2; i++) { + c = pCodes2 + i * RSID_NSYMBOLS; + Encode(rsid_ids2[i].rs, c); + hash1 = c[11] | (c[12] << 4); + hash2 = c[13] | (c[14] << 4); + aHashTable1_2[hash1] = i; + aHashTable2_2[hash2] = i; + } + nBinLow = RSID_RESOL + 1; nBinHigh = RSID_FFT_SIZE - 32; outbuf = 0; symlen = 0; + + hamming_resolution = progdefaults.rsid_resolution; + + state = INITIAL; } cRsId::~cRsId() { delete [] pCodes; + delete [] pCodes2; + delete [] outbuf; + delete rsfft; src_delete(src_state); } @@ -324,7 +158,9 @@ void cRsId::reset() { iPrevDistance = 99; bPrevTimeSliceValid = false; + bPrevTimeSliceValid2 = false; iTime = 0; + iTime2 = 0; memset(aInputSamples, 0, sizeof(aInputSamples)); memset(aFFTReal, 0, sizeof(aFFTReal)); memset(aFFTAmpl, 0, sizeof(aFFTAmpl)); @@ -351,7 +187,6 @@ void cRsId::Encode(int code, unsigned char *rsid) } } - void cRsId::CalculateBuckets(const double *pSpectrum, int iBegin, int iEnd) { double Amp = 0.0, AmpMax = 0.0; @@ -435,9 +270,7 @@ void cRsId::search(void) else { double centerfreq = active_modem->get_freq(); nBinLow = (int)((centerfreq - 100.0 * RSID_RESOL) * 2048.0 / RSID_SAMPLE_RATE); - if (nBinLow < RSID_RESOL + 1) nBinLow = RSID_RESOL + 1; nBinHigh = (int)((centerfreq + 100.0 * RSID_RESOL) * 2048.0 / RSID_SAMPLE_RATE); - if (nBinHigh > RSID_FFT_SIZE -32) nBinHigh = RSID_FFT_SIZE; } bool bReverse = !(wf->Reverse() ^ wf->USB()); @@ -475,10 +308,29 @@ void cRsId::search(void) } int SymbolOut = -1, BinOut = -1; - if (search_amp(SymbolOut, BinOut)) { + if (state == INITIAL && search_amp(SymbolOut, BinOut)) { + LOG_INFO("Rsid_code detected: %d", SymbolOut); + if (SymbolOut == RSID_ESCAPE) { + state = EXTENDED; + reset(); + REQ(reset_rsid_detector, this); // reset after fixed time interval + return; + } if (bReverse) BinOut = 1024 - BinOut - 31; apply(SymbolOut, BinOut); + Fl::remove_timeout(reset_rsid); + state = INITIAL; + reset(); + } else if (state == EXTENDED && search_amp(SymbolOut, BinOut)) { + LOG_INFO("Ext' rsid_code detected: %d", SymbolOut); + if (bReverse) + BinOut = 1024 - BinOut - 31; + if (SymbolOut != RSID_ESCAPE2) + apply2(SymbolOut, BinOut); + Fl::remove_timeout(reset_rsid); + state = INITIAL; + reset(); } } @@ -729,11 +581,6 @@ void cRsId::apply(int iSymbol, int iBin) progdefaults.contestiabw = 4; REQ(&set_contestia_tab_widgets); break; - case RSID_CONTESTIA_128_2000: - progdefaults.contestiatones = 6; - progdefaults.contestiabw = 4; - REQ(&set_contestia_tab_widgets); - break; // mt63 case RSID_MT63_500_LG: case RSID_MT63_1000_LG: case RSID_MT63_2000_LG: progdefaults.mt63_interleave = 64; @@ -764,6 +611,54 @@ void cRsId::apply(int iSymbol, int iBin) } } +void cRsId::apply2(int iSymbol, int iBin) +{ + ENSURE_THREAD(TRX_TID); + + double freq = (iBin + (RSID_NSYMBOLS - 1) * RSID_RESOL / 2) * RSID_SAMPLE_RATE / 2048.0; + + int n, mbin = NUM_MODES; + for (n = 0; n < rsid_ids_size2; n++) { + if (rsid_ids2[n].rs == iSymbol) { + mbin = rsid_ids2[n].mode; + break; + } + } + if (mbin == NUM_MODES) { + char msg[50]; + if (n < rsid_ids_size2) // RSID known but unimplemented + snprintf(msg, sizeof(msg), "RSID-2: %s unimplemented", rsid_ids2[n].name); + else // RSID unknown; shouldn't happen + snprintf(msg, sizeof(msg), "RSID-2: code %d unknown", iSymbol); + put_status(msg, 4.0); + LOG_VERBOSE("%s", msg); + return; + } + else if (!progdefaults.rsid_rx_modes.test(mbin)) { + LOG_DEBUG("Ignoring RSID: %s @ %0.0f Hz", rsid_ids2[n].name, freq); + return; + } + else + LOG_INFO("RSID: %s @ %0.0f Hz", rsid_ids2[n].name, freq); + + if (!progdefaults.rsid_notify_only && progdefaults.rsid_auto_disable) + REQ(toggleRSID); + + if (mailclient || mailserver) + REQ(pskmail_notify_rsid, mbin); + + if (progdefaults.rsid_mark && !progdefaults.rsid_notify_only) // mark current modem & freq + REQ(note_qrg, false, "\nBefore RSID: ", "\n", + active_modem->get_mode(), 0LL, active_modem->get_freq()); + REQ(notify_rsid, mbin, freq); + if (!progdefaults.rsid_notify_only) { + if (progdefaults.rsid_squelch) + REQ(init_modem_squelch, mbin, freq); + else + REQ(init_modem, mbin, freq); + } +} + //============================================================================= // search_amp routine #1 //============================================================================= @@ -776,7 +671,8 @@ int cRsId::HammingDistance(int iBucket, unsigned char *p2) j += RSID_NTIMES; for (int i = 0; i < RSID_NSYMBOLS; i++) { if (aBuckets[j][iBucket] != p2[i])//*p2++) - if (++dist == 2) +//VK2ETA For ARQ modes, allow more bit corrections (4 in 6) + if (++dist == hamming_resolution) return dist; j += RSID_RESOL;//2; if (j >= RSID_NTIMES) @@ -816,9 +712,10 @@ bool cRsId::search_amp( int &SymbolOut, int &BinOut) for (i = nBinLow; i < iEnd; ++ i) { j = aHashTable1[aBuckets[i1][i] | (aBuckets[i2][i] << 4)]; - if (j < rsid_ids_size) { //!= 255) { + if (j < rsid_ids_size) { iDistance = HammingDistance(i, pCodes + j * RSID_NSYMBOLS); - if (iDistance < 2 && iDistance < iDistanceMin) { +//VK2ETA For ARQ modes, allow more bit corrections (4 in 6) + if (iDistance < hamming_resolution && iDistance < iDistanceMin) { iDistanceMin = iDistance; iSymbol = rsid_ids[j].rs; iBin = i; @@ -827,7 +724,8 @@ bool cRsId::search_amp( int &SymbolOut, int &BinOut) j = aHashTable2[aBuckets[i3][i] | (aBuckets[iTime][i] << 4)]; if (j < rsid_ids_size) { //!= 255) { iDistance = HammingDistance (i, pCodes + j * RSID_NSYMBOLS); - if (iDistance < 2 && iDistance < iDistanceMin) { +//VK2ETA For ARQ modes, allow more bit corrections (4 in 6) + if (iDistance < hamming_resolution && iDistance < iDistanceMin) { iDistanceMin = iDistance; iSymbol = rsid_ids[j].rs; iBin = i; @@ -859,6 +757,82 @@ bool cRsId::search_amp( int &SymbolOut, int &BinOut) return false; } +bool cRsId::search_amp2( int &SymbolOut, int &BinOut) +{ + int i, j; + int iDistanceMin = 99; // infinity + int iDistance; + int iBin = -1; + int iSymbol = -1; + int iEnd = nBinHigh - RSID_NTIMES;//30; + int i1, i2, i3; + + if (++iTime2 == RSID_NTIMES) + iTime2 = 0; + + i1 = iTime2 - 3 * RSID_RESOL;//6; + i2 = i1 + RSID_RESOL;//2; + i3 = i2 + RSID_RESOL;//2; + + if (i1 < 0) { + i1 += RSID_NTIMES; + if (i2 < 0) { + i2 += RSID_NTIMES; + if (i3 < 0) + i3 += RSID_NTIMES; + } + } + + CalculateBuckets ( aFFTAmpl, nBinLow, iEnd);//nBinHigh - 30); + CalculateBuckets ( aFFTAmpl, nBinLow + 1, iEnd);//nBinHigh - 30); + + for (i = nBinLow; i < iEnd; ++ i) { + j = aHashTable1_2[aBuckets[i1][i] | (aBuckets[i2][i] << 4)]; + if (j < rsid_ids_size2) { + iDistance = HammingDistance(i, pCodes2 + j * RSID_NSYMBOLS); +//VK2ETA For ARQ modes, allow more bit corrections (4 in 6) + if (iDistance < hamming_resolution && iDistance < iDistanceMin) { + iDistanceMin = iDistance; + iSymbol = rsid_ids2[j].rs; + iBin = i; + } + } + j = aHashTable2_2[aBuckets[i3][i] | (aBuckets[iTime2][i] << 4)]; + if (j < rsid_ids_size2) { + iDistance = HammingDistance (i, pCodes2 + j * RSID_NSYMBOLS); +//VK2ETA For ARQ modes, allow more bit corrections (4 in 6) + if (iDistance < hamming_resolution && iDistance < iDistanceMin) { + iDistanceMin = iDistance; + iSymbol = rsid_ids2[j].rs; + iBin = i; + } + } + } + + if (iSymbol == -1) { + // No RSID found in this time slice. + // If there is a code stored from the previous time slice, return it. + if (bPrevTimeSliceValid2) { + SymbolOut = iPrevSymbol2; + BinOut = iPrevBin2; + DistanceOut = iPrevDistance2; + MetricsOut = 0; + bPrevTimeSliceValid = false; + return true; + } + return false; + } + + if (! bPrevTimeSliceValid2 || + iDistanceMin <= iPrevDistance2) { + iPrevSymbol2 = iSymbol; + iPrevBin2 = iBin; + iPrevDistance2 = iDistanceMin; + } + bPrevTimeSliceValid2 = true; + return false; +} + //============================================================================= // transmit rsid code for current mode //============================================================================= @@ -876,6 +850,7 @@ void cRsId::send(bool preRSID) return; unsigned short rmode = RSID_NONE; + unsigned short rmode2 = RSID_NONE; switch (mode) { case MODE_RTTY : @@ -894,7 +869,15 @@ void cRsId::send(bool preRSID) break; case MODE_OLIVIA: - + case MODE_OLIVIA_4_250: + case MODE_OLIVIA_8_250: + case MODE_OLIVIA_4_500: + case MODE_OLIVIA_8_500: + case MODE_OLIVIA_16_500: + case MODE_OLIVIA_8_1000: + case MODE_OLIVIA_16_1000: + case MODE_OLIVIA_32_1000: + case MODE_OLIVIA_64_2000: if (progdefaults.oliviatones == 1 && progdefaults.oliviabw == 0) rmode = RSID_OLIVIA_4_125; else if (progdefaults.oliviatones == 1 && progdefaults.oliviabw == 1) @@ -979,9 +962,6 @@ void cRsId::send(bool preRSID) else if (progdefaults.contestiatones == 5 && progdefaults.contestiabw == 4) rmode = RSID_CONTESTIA_64_2000; - else if (progdefaults.contestiatones == 6 && progdefaults.contestiabw == 4) - rmode = RSID_CONTESTIA_128_2000; - else return; break; @@ -1025,49 +1005,60 @@ void cRsId::send(bool preRSID) break; } - // if rmode is still unset, look it up +// if rmode is still unset, look it up +// Try secondary table first if (rmode == RSID_NONE) { - for (size_t i = 0; i < sizeof(rsid_ids)/sizeof(*rsid_ids); i++) { - if (mode == rsid_ids[i].mode) { - rmode = rsid_ids[i].rs; + for (size_t i = 0; i < sizeof(rsid_ids2)/sizeof(*rsid_ids2); i++) { + if (mode == rsid_ids2[i].mode) { + rmode2 = rsid_ids2[i].rs; break; } } + if (rmode2 == RSID_NONE2) { + for (size_t i = 0; i < sizeof(rsid_ids)/sizeof(*rsid_ids); i++) { + if (mode == rsid_ids[i].mode) { + rmode = rsid_ids[i].rs; + break; + } + } + } else + rmode = RSID_ESCAPE; } if (rmode == RSID_NONE) return; unsigned char rsid[RSID_NSYMBOLS]; + double sr; + size_t len; + int iTone; + double freq, phaseincr; + double fr; + double phase; Encode(rmode, rsid); - - double sr = active_modem->get_samplerate(); - size_t len = (size_t)floor(RSID_SYMLEN * sr); + sr = active_modem->get_samplerate(); + len = (size_t)floor(RSID_SYMLEN * sr); if (unlikely(len != symlen)) { symlen = len; delete [] outbuf; outbuf = new double[symlen]; } - - // transmit 3 symbol periods of silence at end of transmission +// transmit 3 symbol periods of silence at end of transmission if (!preRSID) { memset(outbuf, 0, symlen * sizeof(*outbuf)); for (int i = 0; i < 3; i++) active_modem->ModulateXmtr(outbuf, symlen); } - // transmit sequence of 15 symbols (tones) - int iTone; - double freq, phaseincr; - double fr = 1.0 * active_modem->get_txfreq() - (RSID_SAMPLE_RATE * 7 / 1024); - double phase = 0.0; - +// transmit sequence of 15 symbols (tones) + fr = 1.0 * active_modem->get_txfreq() - (RSID_SAMPLE_RATE * 7 / 1024); + phase = 0.0; for (int i = 0; i < 15; i++) { iTone = rsid[i]; if (active_modem->get_reverse()) - iTone = 15 - iTone; + iTone = 15 - iTone; freq = fr + iTone * RSID_SAMPLE_RATE / 1024; phaseincr = 2.0 * M_PI * freq / sr; @@ -1077,8 +1068,42 @@ void cRsId::send(bool preRSID) outbuf[j] = sin(phase); } active_modem->ModulateXmtr(outbuf, symlen); - } + + if (rmode == RSID_ESCAPE && rmode2 != RSID_NONE2) { +// transmit 3 symbol periods between rsid bursts + memset(outbuf, 0, symlen * sizeof(*outbuf)); + for (int i = 0; i < 3; i++) + active_modem->ModulateXmtr(outbuf, symlen); + + Encode(rmode2, rsid); + sr = active_modem->get_samplerate(); + len = (size_t)floor(RSID_SYMLEN * sr); + if (unlikely(len != symlen)) { + symlen = len; + delete [] outbuf; + outbuf = new double[symlen]; + } +// transmit sequence of 15 symbols (tones) + fr = 1.0 * active_modem->get_txfreq() - (RSID_SAMPLE_RATE * 7 / 1024); + phase = 0.0; + + for (int i = 0; i < 15; i++) { + iTone = rsid[i]; + if (active_modem->get_reverse()) + iTone = 15 - iTone; + freq = fr + iTone * RSID_SAMPLE_RATE / 1024; + phaseincr = 2.0 * M_PI * freq / sr; + + for (size_t j = 0; j < symlen; j++) { + phase += phaseincr; + if (phase > 2.0 * M_PI) phase -= 2.0 * M_PI; + outbuf[j] = sin(phase); + } + active_modem->ModulateXmtr(outbuf, symlen); + } + } + // one symbol period of silence memset(outbuf, 0, symlen * sizeof(*outbuf)); active_modem->ModulateXmtr(outbuf, symlen); @@ -1090,5 +1115,6 @@ void cRsId::send(bool preRSID) active_modem->ModulateXmtr(outbuf, symlen); } + } diff --git a/src/rsid/rsid_defs.cxx b/src/rsid/rsid_defs.cxx new file mode 100644 index 00000000..82b394de --- /dev/null +++ b/src/rsid/rsid_defs.cxx @@ -0,0 +1,262 @@ +// Syntax: ELEM_(rsid_code, rsid_tag, fldigi_mode) +// fldigi_mode is NUM_MODES if mode is not available in fldigi, +// otherwise one of the tags defined in globals.h. +// rsid_tag is stringified and may be shown to the user. +#undef ELEM_ +#define RSID_LIST \ + ELEM_(1, BPSK31, MODE_PSK31) \ + ELEM_(110, QPSK31, MODE_QPSK31) \ + ELEM_(2, BPSK63, MODE_PSK63) \ + ELEM_(3, QPSK63, MODE_QPSK63) \ + ELEM_(4, BPSK125, MODE_PSK125) \ + ELEM_(5, QPSK125, MODE_QPSK125) \ + ELEM_(126, BPSK250, MODE_PSK250) \ + ELEM_(127, QPSK250, MODE_QPSK250) \ + ELEM_(173, BPSK500, MODE_PSK500) \ + \ + ELEM_(183, PSK125R, MODE_PSK125R) \ + ELEM_(186, PSK250R, MODE_PSK250R) \ + ELEM_(187, PSK500R, MODE_PSK500R) \ + \ + ELEM_(7, PSKFEC31, NUM_MODES) \ + ELEM_(8, PSK10, NUM_MODES) \ + \ + ELEM_(9, MT63_500_LG, MODE_MT63_500) \ + ELEM_(10, MT63_500_ST, MODE_MT63_500) \ + ELEM_(11, MT63_500_VST, MODE_MT63_500) \ + ELEM_(12, MT63_1000_LG, MODE_MT63_1000) \ + ELEM_(13, MT63_1000_ST, MODE_MT63_1000) \ + ELEM_(14, MT63_1000_VST, MODE_MT63_1000) \ + ELEM_(15, MT63_2000_LG, MODE_MT63_2000) \ + ELEM_(17, MT63_2000_ST, MODE_MT63_2000) \ + ELEM_(18, MT63_2000_VST, MODE_MT63_2000) \ + \ + ELEM_(19, PSKAM10, NUM_MODES) \ + ELEM_(20, PSKAM31, NUM_MODES) \ + ELEM_(21, PSKAM50, NUM_MODES) \ + \ + ELEM_(22, PSK63F, MODE_PSK63F) \ + ELEM_(23, PSK220F, NUM_MODES) \ + \ + ELEM_(24, CHIP64, NUM_MODES) \ + ELEM_(25, CHIP128, NUM_MODES) \ + \ + ELEM_(26, CW, MODE_CW) \ + \ + ELEM_(27, CCW_OOK_12, NUM_MODES) \ + ELEM_(28, CCW_OOK_24, NUM_MODES) \ + ELEM_(29, CCW_OOK_48, NUM_MODES) \ + ELEM_(30, CCW_FSK_12, NUM_MODES) \ + ELEM_(31, CCW_FSK_24, NUM_MODES) \ + ELEM_(33, CCW_FSK_48, NUM_MODES) \ + \ + ELEM_(34, PACTOR1_FEC, NUM_MODES) \ + \ + ELEM_(113, PACKET_110, NUM_MODES) \ + ELEM_(35, PACKET_300, NUM_MODES) \ + ELEM_(36, PACKET_1200, NUM_MODES) \ + \ + ELEM_(37, RTTY_ASCII_7, MODE_RTTY) \ + ELEM_(38, RTTY_ASCII_8, MODE_RTTY) \ + ELEM_(39, RTTY_45, MODE_RTTY) \ + ELEM_(40, RTTY_50, MODE_RTTY) \ + ELEM_(41, RTTY_75, MODE_RTTY) \ + \ + ELEM_(42, AMTOR_FEC, NUM_MODES) \ + \ + ELEM_(43, THROB_1, MODE_THROB1) \ + ELEM_(44, THROB_2, MODE_THROB2) \ + ELEM_(45, THROB_4, MODE_THROB4) \ + ELEM_(46, THROBX_1, MODE_THROBX1) \ + ELEM_(47, THROBX_2, MODE_THROBX2) \ + ELEM_(146, THROBX_4, MODE_THROBX4) \ + \ + ELEM_(204, CONTESTIA_4_125, MODE_CONTESTIA) \ + ELEM_(55, CONTESTIA_4_250, MODE_CONTESTIA) \ + ELEM_(54, CONTESTIA_4_500, MODE_CONTESTIA) \ + ELEM_(255, CONTESTIA_4_1000, MODE_CONTESTIA) \ + ELEM_(254, CONTESTIA_4_2000, MODE_CONTESTIA) \ + \ + ELEM_(169, CONTESTIA_8_125, MODE_CONTESTIA) \ + ELEM_(49, CONTESTIA_8_250, MODE_CONTESTIA) \ + ELEM_(52, CONTESTIA_8_500, MODE_CONTESTIA) \ + ELEM_(117, CONTESTIA_8_1000, MODE_CONTESTIA) \ + ELEM_(247, CONTESTIA_8_2000, MODE_CONTESTIA) \ + \ + ELEM_(50, CONTESTIA_16_500, MODE_CONTESTIA) \ + ELEM_(53, CONTESTIA_16_1000, MODE_CONTESTIA) \ + ELEM_(259, CONTESTIA_16_2000, MODE_CONTESTIA) \ + \ + ELEM_(51, CONTESTIA_32_1000, MODE_CONTESTIA) \ + ELEM_(201, CONTESTIA_32_2000, MODE_CONTESTIA) \ + \ + ELEM_(194, CONTESTIA_64_500, MODE_CONTESTIA) \ + ELEM_(193, CONTESTIA_64_1000, MODE_CONTESTIA) \ + ELEM_(191, CONTESTIA_64_2000, MODE_CONTESTIA) \ + \ + ELEM_(56, VOICE, NUM_MODES) \ + \ + ELEM_(60, MFSK8, MODE_MFSK8) \ + ELEM_(57, MFSK16, MODE_MFSK16) \ + ELEM_(147, MFSK32, MODE_MFSK32) \ + \ + ELEM_(148, MFSK11, MODE_MFSK11) \ + ELEM_(152, MFSK22, MODE_MFSK22) \ + \ + ELEM_(61, RTTYM_8_250, NUM_MODES) \ + ELEM_(62, RTTYM_16_500, NUM_MODES) \ + ELEM_(63, RTTYM_32_1000, NUM_MODES) \ + ELEM_(65, RTTYM_8_500, NUM_MODES) \ + ELEM_(66, RTTYM_16_1000, NUM_MODES) \ + ELEM_(67, RTTYM_4_500, NUM_MODES) \ + ELEM_(68, RTTYM_4_250, NUM_MODES) \ + ELEM_(119, RTTYM_8_1000, NUM_MODES) \ + ELEM_(170, RTTYM_8_125, NUM_MODES) \ + \ + ELEM_(203, OLIVIA_4_125, MODE_OLIVIA) \ + ELEM_(75, OLIVIA_4_250, MODE_OLIVIA_4_250) \ + ELEM_(74, OLIVIA_4_500, MODE_OLIVIA_4_500) \ + ELEM_(229, OLIVIA_4_1000, MODE_OLIVIA) \ + ELEM_(238, OLIVIA_4_2000, MODE_OLIVIA) \ + \ + ELEM_(163, OLIVIA_8_125, MODE_OLIVIA) \ + ELEM_(69, OLIVIA_8_250, MODE_OLIVIA_8_250) \ + ELEM_(72, OLIVIA_8_500, MODE_OLIVIA_8_500) \ + ELEM_(116, OLIVIA_8_1000, MODE_OLIVIA_8_1000) \ + ELEM_(214, OLIVIA_8_2000, MODE_OLIVIA) \ + \ + ELEM_(70, OLIVIA_16_500, MODE_OLIVIA_16_500) \ + ELEM_(73, OLIVIA_16_1000, MODE_OLIVIA) \ + ELEM_(234, OLIVIA_16_2000, MODE_OLIVIA) \ + \ + ELEM_(71, OLIVIA_32_1000, MODE_OLIVIA_32_1000) \ + ELEM_(221, OLIVIA_32_2000, MODE_OLIVIA) \ + \ + ELEM_(211, OLIVIA_64_2000, MODE_OLIVIA_64_2000) \ + \ + ELEM_(76, PAX, NUM_MODES) \ + ELEM_(77, PAX2, NUM_MODES) \ + ELEM_(78, DOMINOF, NUM_MODES) \ + ELEM_(79, FAX, NUM_MODES) \ + ELEM_(81, SSTV, NUM_MODES) \ + \ + ELEM_(84, DOMINOEX_4, MODE_DOMINOEX4) \ + ELEM_(85, DOMINOEX_5, MODE_DOMINOEX5) \ + ELEM_(86, DOMINOEX_8, MODE_DOMINOEX8) \ + ELEM_(87, DOMINOEX_11, MODE_DOMINOEX11) \ + ELEM_(88, DOMINOEX_16, MODE_DOMINOEX16) \ + ELEM_(90, DOMINOEX_22, MODE_DOMINOEX22) \ + ELEM_(92, DOMINOEX_4_FEC, MODE_DOMINOEX4) \ + ELEM_(93, DOMINOEX_5_FEC, MODE_DOMINOEX5) \ + ELEM_(97, DOMINOEX_8_FEC, MODE_DOMINOEX8) \ + ELEM_(98, DOMINOEX_11_FEC, MODE_DOMINOEX11) \ + ELEM_(99, DOMINOEX_16_FEC, MODE_DOMINOEX16) \ + ELEM_(101, DOMINOEX_22_FEC, MODE_DOMINOEX22) \ + \ + ELEM_(104, FELD_HELL, MODE_FELDHELL) \ + ELEM_(105, PSK_HELL, NUM_MODES) \ + ELEM_(106, HELL_80, MODE_HELL80) \ + ELEM_(107, FM_HELL_105, MODE_FSKH105) \ + ELEM_(108, FM_HELL_245, NUM_MODES) \ + \ + ELEM_(114, MODE_141A, NUM_MODES) \ + ELEM_(123, DTMF, NUM_MODES) \ + ELEM_(125, ALE400, NUM_MODES) \ + ELEM_(131, FDMDV, NUM_MODES) \ + \ + ELEM_(132, JT65_A, NUM_MODES) \ + ELEM_(134, JT65_B, NUM_MODES) \ + ELEM_(135, JT65_C, NUM_MODES) \ + \ + ELEM_(136, THOR_4, MODE_THOR4) \ + ELEM_(137, THOR_8, MODE_THOR8) \ + ELEM_(138, THOR_16, MODE_THOR16) \ + ELEM_(139, THOR_5, MODE_THOR5) \ + ELEM_(143, THOR_11, MODE_THOR11) \ + ELEM_(145, THOR_22, MODE_THOR22) \ + \ + ELEM_(153, CALL_ID, NUM_MODES) \ + \ + ELEM_(155, PACKET_PSK1200, NUM_MODES) \ + ELEM_(156, PACKET_PSK250, NUM_MODES) \ + ELEM_(159, PACKET_PSK63, NUM_MODES) \ + \ + ELEM_(172, MODE_188_110A_8N1, NUM_MODES) \ + \ +/* ESCAPE used to transition to 2nd RSID set */ \ + ELEM_(263, ESCAPE, NUM_MODES) \ + /* NONE must be the last element */ \ + ELEM_(0, NONE, NUM_MODES) + +#define ELEM_(code_, tag_, mode_) RSID_ ## tag_ = code_, +enum { RSID_LIST }; +#undef ELEM_ + +#define ELEM_(code_, tag_, mode_) { RSID_ ## tag_, mode_, #tag_ }, +const RSIDs cRsId::rsid_ids[] = { RSID_LIST }; +#undef ELEM_ + +const int cRsId::rsid_ids_size = sizeof(rsid_ids)/sizeof(*rsid_ids) - 1; + +//====================================================================== + +#define RSID_LIST2 \ + ELEM_(263, ESCAPE2, NUM_MODES) \ + \ + ELEM_(1, PSK63RX4, MODE_4X_PSK63R) \ + ELEM_(2, PSK63RX5, MODE_5X_PSK63R) \ + ELEM_(3, PSK63RX10, MODE_10X_PSK63R) \ + ELEM_(4, PSK63RX20, MODE_20X_PSK63R) \ + ELEM_(5, PSK63RX32, MODE_32X_PSK63R) \ + \ + ELEM_(10, PSK125RX4, MODE_4X_PSK125R) \ + ELEM_(11, PSK125RX5, MODE_5X_PSK125R) \ + ELEM_(12, PSK125RX10, MODE_10X_PSK125R) \ + ELEM_(61, PSK125X12, MODE_12X_PSK125) \ + ELEM_(62, PSK125RX12, MODE_12X_PSK125R) \ + ELEM_(13, PSK125RX16, MODE_16X_PSK125R) \ + \ + ELEM_(20, PSK250RX2, MODE_2X_PSK250R) \ + ELEM_(21, PSK250RX3, MODE_3X_PSK250R) \ + ELEM_(22, PSK250RX5, MODE_5X_PSK250R) \ + ELEM_(63, PSK250X6, MODE_6X_PSK250) \ + ELEM_(65, PSK250RX6, MODE_6X_PSK250R) \ + ELEM_(23, PSK250RX7, MODE_7X_PSK250R) \ + \ + ELEM_(24, PSK500RX2, MODE_2X_PSK500R) \ + ELEM_(25, PSK500RX3, MODE_3X_PSK500R) \ + ELEM_(26, PSK500RX4, MODE_4X_PSK500R) \ + ELEM_(27, PSK500X2, MODE_2X_PSK500) \ + ELEM_(28, PSK500X4, MODE_4X_PSK500) \ + \ + ELEM_(30, MFSK64, MODE_MFSK64) \ + ELEM_(31, MFSK128, MODE_MFSK128) \ + \ + ELEM_(40, THOR25x4, MODE_THOR25x4) \ + ELEM_(41, THOR50x1, MODE_THOR50x1) \ + ELEM_(42, THOR50x2, MODE_THOR50x2) \ + ELEM_(43, THOR100, MODE_THOR100) \ + \ + ELEM_(45, DOMINOEX_44, MODE_DOMINOEX44) \ + ELEM_(46, DOMINOEX_88, MODE_DOMINOEX88) \ + \ + ELEM_(50, PSK1000, MODE_PSK1000) \ + ELEM_(51, PSK1000R, MODE_PSK1000R) \ + ELEM_(52, PSK1000X2, MODE_2X_PSK1000) \ + ELEM_(53, PSK1000RX2, MODE_2X_PSK1000R) \ + ELEM_(54, PSK800RX2, MODE_2X_PSK800R) \ + ELEM_(57, PSK800X2, MODE_2X_PSK800) \ + \ + /* NONE2 must be the last element */ \ + ELEM_(0, NONE2, NUM_MODES) + +#define ELEM_(code_, tag_, mode_) RSID_ ## tag_ = code_, +enum { RSID_LIST2 }; +#undef ELEM_ + +#define ELEM_(code_, tag_, mode_) { RSID_ ## tag_, mode_, #tag_ }, +const RSIDs cRsId::rsid_ids2[] = { RSID_LIST2 }; +#undef ELEM_ + +const int cRsId::rsid_ids_size2 = sizeof(rsid_ids2)/sizeof(*rsid_ids2) - 1; + diff --git a/src/thor/thor.cxx b/src/thor/thor.cxx index ddab8be7..bd746404 100644 --- a/src/thor/thor.cxx +++ b/src/thor/thor.cxx @@ -1,8 +1,10 @@ // ---------------------------------------------------------------------------- // thor.cxx -- thor modem // -// Copyright (C) 2008, 2009 -// David Freese +// Copyright (C) 2008-2012 +// David Freese +// John Douyere +// John Phelps // // This file is part of fldigi. // @@ -40,13 +42,15 @@ #include "ascii.h" #include "main.h" +#include "debug.h" // Enable to enable profiling output for the soft-decision decoder -#define SOFTPROFILE false +#define SOFTPROFILE true using namespace std; char thormsg[80]; +char confidence[80]; void thor::tx_init(SoundBase *sc) { @@ -87,38 +91,33 @@ void thor::rx_init() void thor::reset_filters() { // fft filter at first IF frequency - fft->create_filter( - (THORFIRSTIF - 0.5 * progdefaults.THOR_BW * bandwidth) / samplerate, - (THORFIRSTIF + 0.5 * progdefaults.THOR_BW * bandwidth)/ samplerate ); + fft->create_filter( (THORFIRSTIF - 0.5 * progdefaults.THOR_BW * bandwidth) / samplerate, + (THORFIRSTIF + 0.5 * progdefaults.THOR_BW * bandwidth)/ samplerate ); for (int i = 0; i < THORMAXFFTS; i++) if (binsfft[i]) { delete binsfft[i]; binsfft[i] = 0; } - - if (slowcpu || samplerate == 22050) { + + if (slowcpu) { extones = 4; paths = THORSLOWPATHS; } else { extones = THORNUMTONES / 2; paths = THORFASTPATHS; } - + lotone = basetone - extones * doublespaced; - if (lotone < 1) lotone = 1; hitone = basetone + THORNUMTONES * doublespaced + extones * doublespaced; + numbins = hitone - lotone; - for (int i = 0; i < paths; i++) { + for (int i = 0; i < paths; i++) binsfft[i] = new sfft (symlen, lotone, hitone); - if (!binsfft[i]) { - printf("Thor Arrgh %d\n", i); - exit(0); - } - } - filter_reset = false; + + filter_reset = false; } void thor::restart() @@ -138,7 +137,7 @@ void thor::init() thor::~thor() { if (hilbert) delete hilbert; - + for (int i = 0; i < THORMAXFFTS; i++) { if (binsfft[i]) delete binsfft[i]; } @@ -147,15 +146,15 @@ thor::~thor() if (vidfilter[i]) delete vidfilter[i]; } if (syncfilter) delete syncfilter; - + if (pipe) delete [] pipe; if (fft) delete fft; - + if (Rxinlv) delete Rxinlv; if (Txinlv) delete Txinlv; if (Dec) delete Dec; if (Enc) delete Enc; - + } thor::thor(trx_mode md) @@ -164,6 +163,10 @@ thor::thor(trx_mode md) mode = md; + int isize = 4; + int idepth = 10; + flushlength = 4; + switch (mode) { // 11.025 kHz modes case MODE_THOR5: @@ -177,27 +180,13 @@ thor::thor(trx_mode md) doublespaced = 1; samplerate = 11025; break; -// case MODE_TSOR11: -// symlen = 1024; -// doublespaced = 2; -// samplerate = 11025; -// break; + case MODE_THOR22: symlen = 512; doublespaced = 1; samplerate = 11025; break; - case MODE_THOR44: - symlen = 250; - doublespaced = 2; - samplerate = 11025; - break; - case MODE_THOR88: - symlen = 125; - doublespaced = 1; - samplerate = 11025; - break; // 8kHz modes case MODE_THOR4: symlen = 2048; @@ -210,6 +199,39 @@ thor::thor(trx_mode md) doublespaced = 2; samplerate = 8000; break; + + case MODE_THOR25x4: + symlen = 320; + doublespaced = 4; + samplerate = 8000; + idepth = 50; // 2 sec interleave + flushlength = 40; + break; + + case MODE_THOR50x1: + symlen = 160; + doublespaced = 1; + samplerate = 8000; + idepth = 50; // 1 sec interleave + flushlength = 40; + break; + + case MODE_THOR50x2: + symlen = 160; + doublespaced = 2; + samplerate = 8000; + idepth = 50; // 1 sec interleave + flushlength = 40; + break; + + case MODE_THOR100: + symlen = 80; + doublespaced = 1; + samplerate = 8000; + idepth = 50; // 0.5 sec interleave + flushlength = 40; + break; + case MODE_THOR16: default: symlen = 512; @@ -225,32 +247,32 @@ thor::thor(trx_mode md) hilbert->init_hilbert(37, 1); // fft filter at first if frequency - fft = new fftfilt( - (THORFIRSTIF - 0.5 * progdefaults.THOR_BW * bandwidth) / samplerate, - (THORFIRSTIF + 0.5 * progdefaults.THOR_BW * bandwidth)/ samplerate, - 1024 ); + fft = new fftfilt( (THORFIRSTIF - 0.5 * progdefaults.THOR_BW * bandwidth) / samplerate, + (THORFIRSTIF + 0.5 * progdefaults.THOR_BW * bandwidth)/ samplerate, + 1024 ); + basetone = (int)floor(THORBASEFREQ * symlen / samplerate + 0.5); slowcpu = progdefaults.slowcpu; - + for (int i = 0; i < THORMAXFFTS; i++) binsfft[i] = 0; - + reset_filters(); for (int i = 0; i < THORSCOPESIZE; i++) vidfilter[i] = new Cmovavg(16); - + syncfilter = new Cmovavg(8); twosym = 2 * symlen; pipe = new THORrxpipe[twosym]; - + scopedata.alloc(THORSCOPESIZE); videodata.alloc(THORMAXFFTS * numbins ); pipeptr = 0; - + symcounter = 0; metric = 0.0; @@ -260,26 +282,25 @@ thor::thor(trx_mode md) prev1symbol = prev2symbol = 0; - static const int longtraceback = 127 ; - static const int traceback = 45 ; - static const int chunksize = 1 ; + prev1symbol = prev2symbol = 0; - if ( mode == MODE_THOR88 || mode == MODE_THOR44) { + if ( mode == MODE_THOR100 || mode == MODE_THOR50x1 || mode == MODE_THOR50x2 || mode == MODE_THOR25x4 ) { Enc = new encoder (GALILEO_K, GALILEO_POLY1, GALILEO_POLY2); - Dec = new viterbi::impl ( GALILEO_POLY1, GALILEO_POLY2 ); - Txinlv = new interleave (-488, INTERLEAVE_FWD); // 4x4x88 - Rxinlv = new interleave (-488, INTERLEAVE_REV); // 4x4x88 + Dec = new viterbi (GALILEO_K, GALILEO_POLY1, GALILEO_POLY2); + Dec->settraceback (PATHMEM-1); // Long constraint length codes require longer traceback } else { Enc = new encoder (THOR_K, THOR_POLY1, THOR_POLY2); - Dec = new viterbi::impl ( THOR_POLY1, THOR_POLY2 ); - Txinlv = new interleave (4, INTERLEAVE_FWD); // 4x4x10 - Rxinlv = new interleave (4, INTERLEAVE_REV); // 4x4x10 + Dec = new viterbi (THOR_K, THOR_POLY1, THOR_POLY2); + Dec->settraceback (45); } + Txinlv = new interleave (isize, idepth, INTERLEAVE_FWD); + Rxinlv = new interleave (isize, idepth, INTERLEAVE_REV); + Dec->setchunksize (1); + bitstate = 0; symbolpair[0] = symbolpair[1] = 0; datashreg = 1; -// init(); } //===================================================================== @@ -345,68 +366,79 @@ void thor::recvchar(int c) void thor::decodePairs(unsigned char symbol) { + int c, ch, met; + symbolpair[0] = symbolpair[1]; symbolpair[1] = symbol; symcounter = symcounter ? 0 : 1; - + if (symcounter) return; - int c = Dec->decode (symbolpair); + c = Dec->decode (symbolpair, &met); if (c == -1) return; + + if(met < 255 / 2) fec_confidence -= 2 + fec_confidence / 2; + else fec_confidence += 2; + if (fec_confidence < 0) fec_confidence = 0; + if (fec_confidence > 100) fec_confidence = 100; if (progStatus.sqlonoff && metric < progStatus.sldrSquelchValue) return; datashreg = (datashreg << 1) | !!c; if ((datashreg & 7) == 1) { - int ch = thorvaridec(datashreg >> 1); + ch = thorvaridec(datashreg >> 1); recvchar(ch); datashreg = 1; } + + } void thor::decodesymbol() { + int c; + double fdiff;//, softmag; unsigned char symbols[4]; bool outofrange = false; // Decode the IFK+ sequence, which results in a single nibble - double fdiff = currsymbol - prev1symbol; - + fdiff = currsymbol - prev1symbol; + if (reverse) fdiff = -fdiff; fdiff /= paths; fdiff /= doublespaced; if (fabs(fdiff) > 17) outofrange = true; - int c = (int)floor(fdiff + .5); { + c = (int)floor(fdiff + .5); { if (progdefaults.THOR_PREAMBLE) { if ( preambledetect(c) ) { softflushrx(); // Flush the soft rx pipeline with punctures (interleaver & viterbi decoder) return; } - } + } } c -= 2; if (c < 0) c += THORNUMTONES; if (staticburst == true || outofrange == true) // puncture the code - symbols[3] = symbols[2] = symbols[1] = symbols[0] = 128; + symbols[3] = symbols[2] = symbols[1] = symbols[0] = 128; else { symbols[3] = (c & 1) == 1 ? 255 : 0; c /= 2; symbols[2] = (c & 1) == 1 ? 255 : 0; c /= 2; symbols[1] = (c & 1) == 1 ? 255 : 0; c /= 2; symbols[0] = (c & 1) == 1 ? 255 : 0; c /= 2; - } + } Rxinlv->symbols(symbols); for (int i = 0; i < 4; i++) decodePairs(symbols[i]); - + } void thor::softdecodesymbol() @@ -421,7 +453,7 @@ void thor::softdecodesymbol() if (reverse) fdiff = -fdiff; fdiff /= paths; fdiff /= doublespaced; - + c = (int)floor(fdiff + .5); { if (c < -16 || 0 == c || 1 == c || c > 17) outofrange = true; // Out of the range of the function thor::sendsymbol() if (progdefaults.THOR_PREAMBLE) { @@ -432,30 +464,40 @@ void thor::softdecodesymbol() } } #if SOFTPROFILE - printf("\nSymbol: %3d",currsymbol); - if (c >= 0) printf(" \tDELTAf: +%2d",c); - else printf(" \tDELTAf: %3d",c); + LOG_DEBUG("\nSymbol: %3d; DELTAf: +%3d",currsymbol, c); #endif } c -= 2; - if (c < 0) c += THORNUMTONES; - - // Since the THOR modem is differential, when an outofrange error occurs there are 2 possibilities: - // either previous (reference) symbol or current. 50% probability of each being the culprit. - // either way, the current symbol is lost, puncture it. Also 50% probability next symbol will have an error + if (c < 0) c += THORNUMTONES; + +// Since the THOR modem is differential, when an outofrange error occurs +// there are 2 possibilities: +// . either previous (reference) symbol or current with a 50% +// probability of each being the culprit. +// Either way, the current symbol is lost, puncture it. There is also a +// 50% probability the next symbol will have an error if (outofrange){ lastmag /= 2; nowmag = 0; nextmag /= 2; } + // O is puncture/null-symbol from softdecode + if (0 == currsymbol) { + nowmag = 0; + nextmag = 0; + } + + // puncture while squelched + if (progStatus.sqlonoff && metric < progStatus.sldrSquelchValue) nowmag = 0; + // One in 16 chance the correct reference tone chosen in staticburst if (staticburst){ nowmag /= 16; nextmag /= 16; } - - if (lastmag <= 0) { // puncture + + if (lastmag <= 0) { // puncture one = 128; zero = 128; } @@ -468,28 +510,27 @@ void thor::softdecodesymbol() zero = static_cast( 127-lastmag ); // never < 0 } -#if SOFTPROFILE - printf(" \t-->%.3d|%.3d|%.3d = ",nextmag, nowmag, lastmag); - printf("%.3d|%.3d",zero,one); - if (outofrange) printf(" (outofrange)"); - if (staticburst) printf(" (staticburst)"); +#if SOFTPROFILE + LOG_DEBUG("next mag %.3d | now mag %.3d | last mag %.3d",nextmag, nowmag, lastmag); + if (outofrange) LOG_DEBUG("%s","outofrange"); + if (staticburst) LOG_DEBUG("%s","staticburst"); #endif lastsymbols[3] = (lastc & 1) == 1 ? one : zero ; lastc /= 2; lastsymbols[2] = (lastc & 1) == 1 ? one : zero ; lastc /= 2; lastsymbols[1] = (lastc & 1) == 1 ? one : zero ; lastc /= 2; lastsymbols[0] = (lastc & 1) == 1 ? one : zero ; lastc /= 2; - + Rxinlv->symbols(lastsymbols); for (int i = 0; i < 4; i++) decodePairs(lastsymbols[i]); - // Since modem is differential, wait until next symbol (to detect errors) then decode. +// Since modem is differential, wait until next symbol (to detect errors) +// then decode. lastc = c; lastmag = nowmag; nowmag = nextmag; } - int thor::harddecode() { double x, max = 0.0; @@ -501,9 +542,9 @@ int thor::harddecode() for (int i = 0; i < paths * numbins; i++) avg += pipe[pipeptr].vector[i].mag(); avg /= (paths * numbins); - + if (avg < 1e-10) avg = 1e-10; - + int numtests = 10; int count = 0; for (int i = 0; i < paths * numbins; i++) { @@ -515,9 +556,9 @@ int thor::harddecode() cwmag = (pipe[j].vector[i].mag())/numtests; if (cwmag >= 50.0 * (1.0 - progdefaults.ThorCWI) * avg) count++; } - cwi[i] = (count == numtests); + cwi[i] = (count == numtests); } - + for (int i = 0; i < paths * numbins ; i++) { if (cwi[i] == false) { x = pipe[pipeptr].vector[i].mag(); @@ -533,6 +574,77 @@ int thor::harddecode() return symbol; } +int thor::softdecode() +{ + static const int SoftBailout=6; // Max number of attempts to get a valid symbol + + double x, max = 0.0, avg = 0.0; + int symbol = 0; + int avgcount = 0; + int soft_symbol_trycount=0; + + static bool lastCWI[1024] = {false}; + bool nextCWI[paths * numbins]; + + int lowest_tone = 0; + int highest_tone = paths * numbins; + + // Clear nextCWI bool array for this run + for (int i = lowest_tone; i < highest_tone; i++) nextCWI[i] = false; + + // Allow for case where symbol == prev2symbol (before calculating signal average...) + lastCWI[prev2symbol-1] = lastCWI[prev2symbol] = lastCWI[prev2symbol+1] = false; + + // Constrict the tone set further so CWI detect & set does not go out of intended range + lowest_tone += 1; + highest_tone -= 1; + + // Calculate signal average, ignoring CWI signals + for (int i = lowest_tone; i < highest_tone; i++) + { + if ( !lastCWI[i] ) { + avg += pipe[pipeptr].vector[i].mag(); + avgcount++; + } + } + avg /= avgcount; + if (avg < 1e-10) avg = 1e-10; + + + // Run symbol-decoder until a non-CWI && non-Repeated symbol is selected + do { + soft_symbol_trycount++; + max = 0.0; + + for (int i = lowest_tone; i < highest_tone; i++) { + x = pipe[pipeptr].vector[i].mag(); + if ( x > max && !nextCWI[i-1] && !nextCWI[i] && !nextCWI[i+1] ) { + max = x; + symbol = i; + } + } + + // detect repeated symbols (an invalid pattern for IFK+ modems) + if ( abs(prev1symbol - symbol) < paths ) { + nextCWI[symbol-1] = nextCWI[symbol] = nextCWI[symbol+1] = true; + } + // Update the next CWI mask if the tone from last-run persists + else if ( lastCWI[symbol-1] || lastCWI[symbol] || lastCWI[symbol+1] ) { + nextCWI[symbol-1] = nextCWI[symbol] = nextCWI[symbol+1] = true; + } + + } while ( nextCWI[symbol] && soft_symbol_trycount < SoftBailout ); // Run while the detected symbol has been identified as CWI (alt: bailout after 6 trys) + + // Copy the newly-detected CWI mask to the static lastCWI array for use on next function call + for (int i = lowest_tone-1; i < highest_tone+1; i++) lastCWI[i] = nextCWI[i]; + + staticburst = (max / avg < 1.2); + + // Return a NULL / Puncture symbol if a bailout occured + if (soft_symbol_trycount >= SoftBailout) return 0; + else return symbol; +} + bool thor::preambledetect(int c) { static int preamblecheck=0, twocount=0; @@ -541,19 +653,21 @@ bool thor::preambledetect(int c) if (twocount > 14 ) twocount = 0; if (-16 == c && twocount > 2 ) neg16seen = true; - else if (2 != c) neg16seen = false; // 2 does not reset the neg16seen bool +// 2 does not reset the neg16seen bool + else if (2 != c) neg16seen = false; else if (2 == c) twocount ++; - - if (-16 != c && 2 != c) // -16 does not reset the twos counter - if (twocount > 1) twocount -= 2; -#if SOFTPROFILE - printf(" [%d:%d]",twocount, preamblecheck); -#endif + +// -16 does not reset the twos counter + if (-16 != c && 2 != c) + if (twocount > 1) twocount -= 2; +//#if SOFTPROFILE +// LOG_DEBUG("[2count:pcheck] [%d:%d]",twocount, preamblecheck); +//#endif if ( twocount > 4 && neg16seen ){ if ( ++preamblecheck > 4 ) return true; } - else preamblecheck = 0; - + else preamblecheck = 0; + return false; } @@ -563,11 +677,13 @@ void thor::softflushrx() unsigned char puncture[2], flushsymbols[4]; puncture[0]=128; puncture[1]=128; - + for (int i = 0; i < 4; i++) flushsymbols[i] = 128; - - for(int i=0; i<90; i++) Rxinlv->symbols(flushsymbols); // flush interleaver with punctured symbols - for (int j = 0; j < 128; j++) Dec->decode (puncture, NULL); // flush viterbi with puncture soft-bits + +// flush interleaver with punctured symbols + for(int i = 0; i < 90; i++) Rxinlv->symbols(flushsymbols); +// flush viterbi with puncture soft-bits + for (int j = 0; j < 128; j++) Dec->decode (puncture, NULL); } void thor::update_syncscope() @@ -614,7 +730,7 @@ void thor::synchronize() double val, max = 0.0; if (staticburst == true) return; - + if (currsymbol == prev1symbol) return; if (prev1symbol == prev2symbol) @@ -628,7 +744,7 @@ void thor::synchronize() } j = (j + 1) % twosym; } - + syn = syncfilter->run(syn); synccounter += (int) floor(1.0 * (syn - symlen) / THORNUMTONES + 0.5); @@ -651,7 +767,7 @@ void thor::eval_s2n() else s2n = 0; // To partially offset the increase of noise by (THORNUMTONES -1) - // in the noise calculation above, + // in the noise calculation above, // add 15*log10(THORNUMTONES -1) = 18.4, and multiply by 6 metric = 6 * (s2n + 18.4); @@ -667,6 +783,18 @@ void thor::eval_s2n() snprintf(thormsg, sizeof(thormsg), "s/n %3.0f dB", s2n ); put_Status1(thormsg); + + // Scale FEC indicatior to reduce erratic / jumpy / unreadable display in GUI + int scalefec; + if (fec_confidence++ > 90) scalefec = 100; + else if (fec_confidence++ > 60) scalefec = 75; + else if (fec_confidence++ > 40) scalefec = 50; + else if (fec_confidence++ >= 20) scalefec = 25; + else if ( fec_confidence > 9) scalefec = 10; + else scalefec = 0; // Else just round to 0. + + snprintf(confidence, sizeof(confidence), "FEC: %3.1d%%", scalefec); + put_Status2(confidence); } int thor::rx_process(const double *buf, int len) @@ -681,7 +809,7 @@ int thor::rx_process(const double *buf, int len) slowcpu = progdefaults.slowcpu; reset_filters(); } - + while (len) { // create analytic signal at first IF zref.re = zref.im = *buf++; @@ -696,7 +824,7 @@ int thor::rx_process(const double *buf, int len) zp = zarray; n = 1; } - + if (n) { for (int i = 0; i < n; i++) { complex * pipe_pipeptr_vector = pipe[pipeptr].vector ; @@ -711,14 +839,20 @@ int thor::rx_process(const double *buf, int len) } if (--synccounter <= 0) { synccounter = symlen; - //if (progdefaults.THOR_SOFTSYMBOLS) - currsymbol = harddecode(); + + if (progdefaults.THOR_SOFTSYMBOLS) + currsymbol = softdecode(); + else + currsymbol = harddecode(); + currmag = pipe_pipeptr_vector[currsymbol].mag(); eval_s2n(); - - if (progdefaults.THOR_SOFTBITS) softdecodesymbol(); - else decodesymbol(); - + + if (progdefaults.THOR_SOFTBITS) + softdecodesymbol(); + else + decodesymbol(); + synchronize(); prev2symbol = prev1symbol; prev1symbol = currsymbol; @@ -732,7 +866,7 @@ int thor::rx_process(const double *buf, int len) } --len; } - + return 0; } @@ -771,7 +905,7 @@ void thor::sendsymbol(int sym) { complex z; int tone; - + tone = (txprevtone + 2 + sym) % THORNUMTONES; txprevtone = tone; if (reverse) @@ -786,7 +920,7 @@ void thor::sendchar(unsigned char c, int secondary) const char *code; code = thorvarienc(c, secondary); - + while (*code) { int data = Enc->encode(*code++ - '0'); for (int i = 0; i < 2; i++) { @@ -835,30 +969,22 @@ void thor::flushtx() { // flush the varicode decoder at the other end // flush the convolutional encoder and interleaver - if ( mode == MODE_THOR88 || mode == MODE_THOR44) for (int i=0; i<57; i++) sendidle(); - else { - for (int i = 0; i < 4; i++) - sendidle(); - bitstate = 0; - } + for (int i = 0; i < flushlength; i++) sendidle(); + + bitstate = 0; } int thor::tx_process() { - int i; + int i = 0; switch (txstate) { case TX_STATE_PREAMBLE: Clearbits(); - for (int j = 0; j < 16; j++) sendsymbol(0); -// sendtone(THORNUMTONES/2, 4); -// for (int k = 0; k < 3; k++) { -// sendtone(THORNUMTONES, 3); -// sendtone(0, 3); -// } -// sendtone(THORNUMTONES/2, 4); - sendidle(); + for (int j = 0; j < 16; j++) sendsymbol(0); + + sendidle(); txstate = TX_STATE_START; break; case TX_STATE_START: diff --git a/src/trx/modem.cxx b/src/trx/modem.cxx index 81440aac..611551f0 100644 --- a/src/trx/modem.cxx +++ b/src/trx/modem.cxx @@ -54,6 +54,7 @@ modem *mfsk11_modem = 0; modem *mfsk22_modem = 0; modem *mfsk31_modem = 0; modem *mfsk64_modem = 0; +modem *mfsk128_modem = 0; modem *wefax576_modem = 0; modem *wefax288_modem = 0; @@ -80,6 +81,7 @@ modem *psk63f_modem = 0; modem *psk125_modem = 0; modem *psk250_modem = 0; modem *psk500_modem = 0; +modem *psk1000_modem = 0; modem *qpsk31_modem = 0; modem *qpsk63_modem = 0; @@ -90,8 +92,51 @@ modem *qpsk500_modem = 0; modem *psk125r_modem = 0; modem *psk250r_modem = 0; modem *psk500r_modem = 0; +modem *psk1000r_modem = 0; + +modem *psk800_c2_modem = 0; +modem *psk800r_c2_modem = 0; +modem *psk1000_c2_modem = 0; +modem *psk1000r_c2_modem = 0; + +modem *psk63r_c4_modem = 0; +modem *psk63r_c5_modem = 0; +modem *psk63r_c10_modem = 0; +modem *psk63r_c20_modem = 0; +modem *psk63r_c32_modem = 0; + +modem *psk125r_c4_modem = 0; +modem *psk125r_c5_modem = 0; +modem *psk125r_c10_modem = 0; +modem *psk125_c12_modem = 0; +modem *psk125r_c12_modem = 0; +modem *psk125r_c16_modem = 0; + +modem *psk250r_c2_modem = 0; +modem *psk250r_c3_modem = 0; +modem *psk250r_c5_modem = 0; +modem *psk250_c6_modem = 0; +modem *psk250r_c6_modem = 0; +modem *psk250r_c7_modem = 0; + +modem *psk500_c2_modem = 0; +modem *psk500_c4_modem = 0; + +modem *psk500r_c2_modem = 0; +modem *psk500r_c3_modem = 0; +modem *psk500r_c4_modem = 0; modem *olivia_modem = 0; +modem *olivia_4_250_modem = 0; +modem *olivia_8_250_modem = 0; +modem *olivia_4_500_modem = 0; +modem *olivia_8_500_modem = 0; +modem *olivia_16_500_modem = 0; +modem *olivia_8_1000_modem = 0; +modem *olivia_16_1000_modem = 0; +modem *olivia_32_1000_modem = 0; +modem *olivia_64_2000_modem = 0; + modem *contestia_modem = 0; modem *rtty_modem = 0; @@ -103,8 +148,10 @@ modem *thor8_modem = 0; modem *thor11_modem = 0; modem *thor16_modem = 0; modem *thor22_modem = 0; -modem *thor44_modem = 0; -modem *thor88_modem = 0; +modem *thor25x4_modem = 0; +modem *thor50x1_modem = 0; +modem *thor50x2_modem = 0; +modem *thor100_modem = 0; modem *dominoex4_modem = 0; modem *dominoex5_modem = 0; @@ -665,7 +712,6 @@ void modem::wfid_send(int numchars) void modem::wfid_sendchars(string s) { - long long int symbol; int len = s.length(); int n[len]; int c; @@ -682,7 +728,6 @@ void modem::wfid_sendchars(string s) } // send rows from bottom to top so they appear to scroll down the waterfall correctly for (int row = 0; row < NUMROWS; row++) { - symbol = 0; for (int i = 0; i < len; i++) { if (useIDSMALL) symbols[i] = idch1[n[i]].byte[NUMROWS - 1 - row];