From f379ad5eab3f95264b30177f3b89f52ab2b73a72 Mon Sep 17 00:00:00 2001 From: Stelios Bounanos Date: Thu, 12 Jun 2008 23:15:17 +0100 Subject: [PATCH] Upstream version 3.0pre1 --- ChangeLog | 5 +- configure.ac | 6 +- src/Makefile.am | 2 + src/cw_rtty/rtty.cxx | 1 - src/dialogs/confdialog.cxx | 29 +- src/dialogs/confdialog.fl | 27 +- src/dialogs/fl_digi.cxx | 27 +- src/dialogs/htmlstrings.cxx | 568 ++++++++++++++++++++++++++++++++++++ src/feld/feld.cxx | 2 +- src/filters/fftfilt.cxx | 4 +- src/filters/filters.cxx | 2 +- src/include/FTextView.h | 3 + src/include/complex.h | 89 +++--- src/include/confdialog.h | 1 + src/include/configuration.h | 2 +- src/include/fftfilt.h | 2 +- src/include/filters.h | 2 +- src/include/htmlstrings.h | 31 ++ src/include/qrunner.h | 20 +- src/include/thor.h | 2 +- src/main.cxx | 2 +- src/misc/configuration.cxx | 4 +- src/mt63/mt63.cxx | 8 + src/olivia/olivia.cxx | 16 +- src/qrunner/fqueue.h | 96 ++---- src/qrunner/qrunner.cxx | 6 +- src/thor/thor.cxx | 4 +- src/throb/throb.cxx | 2 - src/waterfall/waterfall.cxx | 15 +- src/widgets/FTextView.cxx | 18 +- 30 files changed, 805 insertions(+), 191 deletions(-) create mode 100644 src/dialogs/htmlstrings.cxx create mode 100644 src/include/htmlstrings.h diff --git a/ChangeLog b/ChangeLog index 17e39946..23324fa3 100644 --- a/ChangeLog +++ b/ChangeLog @@ -1,6 +1,6 @@ Change Log: -2.11 1) Added EXEC macro +3.0 1) Added EXEC macro 2) Added mousewheel over Macro buttons to move between macro button sets. 3) Fixed bug in Olivia signal level display. 4) Ported to Windows (win32) and OS-X @@ -88,6 +88,9 @@ Change Log: 40) Fixed bug in waterfall update method that could cause a seg fault under certain conditions. 41) Change to PortAudio samplerate probing. + 42) Increased average power level in MT-63 mode. + 43) Significantly decreased cpu usage with changes to qrunner and complex + classes. 2.10.3) 1) Corrected memory leak bug. diff --git a/configure.ac b/configure.ac index b66a3448..87ab1ffe 100644 --- a/configure.ac +++ b/configure.ac @@ -7,9 +7,9 @@ AC_PREREQ(2.61) dnl major and minor must be integers; patch may dnl contain other characters or be empty -m4_define(FLDIGI_MAJOR, [2]) -m4_define(FLDIGI_MINOR, [11]) -m4_define(FLDIGI_PATCH, [AU]) +m4_define(FLDIGI_MAJOR, [3]) +m4_define(FLDIGI_MINOR, [0]) +m4_define(FLDIGI_PATCH, [pre]) AC_INIT([fldigi], FLDIGI_MAJOR.FLDIGI_MINOR[FLDIGI_PATCH], [w1hkj AT w1hkj DOT com]) diff --git a/src/Makefile.am b/src/Makefile.am index 5c2a96c4..177f4d57 100644 --- a/src/Makefile.am +++ b/src/Makefile.am @@ -120,6 +120,7 @@ fldigi_SOURCES += \ dialogs/fl_digi.cxx \ dialogs/font_browser.cxx \ dialogs/Viewer.cxx \ + dialogs/htmlstrings.cxx \ thor/thor.cxx \ thor/thorvaricode.cxx \ dominoex/dominoex.cxx \ @@ -134,6 +135,7 @@ fldigi_SOURCES += \ filters/filters.cxx \ filters/viterbi.cxx \ globals/globals.cxx \ + include/htmlstrings.h \ include/Combo_Box.h \ include/Combo_List.h \ include/confdialog.h \ diff --git a/src/cw_rtty/rtty.cxx b/src/cw_rtty/rtty.cxx index c87b4009..d94356ff 100644 --- a/src/cw_rtty/rtty.cxx +++ b/src/cw_rtty/rtty.cxx @@ -80,7 +80,6 @@ void rtty::init() rtty::~rtty() { if (hilbert) delete hilbert; -// if (wfid) delete wfid; if (bitfilt) delete bitfilt; if (bpfilt) delete bpfilt; } diff --git a/src/dialogs/confdialog.cxx b/src/dialogs/confdialog.cxx index ca5ada02..73920560 100644 --- a/src/dialogs/confdialog.cxx +++ b/src/dialogs/confdialog.cxx @@ -1056,6 +1056,13 @@ static void cb_btnFeldHellIdle(Fl_Check_Button* o, void*) { progdefaults.changed = true; } +Fl_Spinner *valHellXmtWidth=(Fl_Spinner *)0; + +static void cb_valHellXmtWidth(Fl_Spinner* o, void*) { + progdefaults.HellXmtWidth=(int)o->value(); +progdefaults.changed = true; +} + Fl_Group *tabOlivia=(Fl_Group *)0; Fl_Choice *mnuOlivia_Tones=(Fl_Choice *)0; @@ -1949,6 +1956,7 @@ l with your sound hardware."); { tabMisc = new Fl_Group(0, 25, 400, 195, "Misc"); tabMisc->color((Fl_Color)51); tabMisc->selection_color((Fl_Color)51); + tabMisc->hide(); { Fl_Group* o = new Fl_Group(5, 35, 390, 90, "Sweet Spot"); o->box(FL_ENGRAVED_FRAME); o->align(FL_ALIGN_TOP_LEFT|FL_ALIGN_INSIDE); @@ -2010,7 +2018,6 @@ l with your sound hardware."); { tabModems = new Fl_Group(0, 25, 401, 195, "Modem"); tabModems->color((Fl_Color)51); tabModems->selection_color((Fl_Color)51); - tabModems->hide(); { tabsModems = new Fl_Tabs(0, 25, 401, 195); tabsModems->color((Fl_Color)51); tabsModems->selection_color((Fl_Color)10); @@ -2209,6 +2216,7 @@ l with your sound hardware."); { tabDomEX = new Fl_Group(0, 50, 400, 170, "Dom"); tabDomEX->color((Fl_Color)51); tabDomEX->selection_color((Fl_Color)51); + tabDomEX->hide(); { txtSecondary = new Fl_Input(20, 75, 360, 44, "Secondary Text"); txtSecondary->type(4); txtSecondary->callback((Fl_Callback*)cb_txtSecondary); @@ -2250,8 +2258,7 @@ l with your sound hardware."); { tabFeld = new Fl_Group(0, 50, 400, 170, "Feld"); tabFeld->color((Fl_Color)51); tabFeld->selection_color((Fl_Color)51); - tabFeld->hide(); - { Fl_Choice* o = selHellFont = new Fl_Choice(175, 62, 122, 20, "Feld Hell Font:"); + { Fl_Choice* o = selHellFont = new Fl_Choice(260, 62, 122, 20, "Feld Hell Font:"); selHellFont->down_box(FL_BORDER_BOX); selHellFont->labelfont(4); selHellFont->textfont(4); @@ -2271,9 +2278,10 @@ l with your sound hardware."); sldrHellBW->align(FL_ALIGN_TOP_LEFT); o->value(progdefaults.HELL_BW); } // Fl_Value_Slider* sldrHellBW - { Fl_Check_Button* o = btnHellXmtWidth = new Fl_Check_Button(40, 93, 113, 15, "2x Xmt Width"); + { Fl_Check_Button* o = btnHellXmtWidth = new Fl_Check_Button(175, 175, 113, 15, "2x Xmt Width"); btnHellXmtWidth->down_box(FL_DOWN_BOX); btnHellXmtWidth->callback((Fl_Callback*)cb_btnHellXmtWidth); + btnHellXmtWidth->hide(); o->value(progdefaults.HellXmtWidth); } // Fl_Check_Button* btnHellXmtWidth { Fl_Check_Button* o = btnHellRcvWidth = new Fl_Check_Button(40, 113, 130, 15, "1/2 x Rcv Width"); @@ -2286,15 +2294,15 @@ l with your sound hardware."); btnBlackboard->callback((Fl_Callback*)cb_btnBlackboard); o->value(progdefaults.HellBlackboard); } // Fl_Check_Button* btnBlackboard - { Fl_Group* o = new Fl_Group(175, 90, 195, 85, "Pulse Shape"); + { Fl_Group* o = new Fl_Group(189, 90, 195, 85, "Pulse Shape"); o->box(FL_ENGRAVED_FRAME); o->align(FL_ALIGN_TOP_LEFT|FL_ALIGN_INSIDE); - { Fl_Check_Button* o = btnHellFastAttack = new Fl_Check_Button(185, 110, 169, 15, "Fast Attack (2 msec)"); + { Fl_Check_Button* o = btnHellFastAttack = new Fl_Check_Button(199, 110, 169, 15, "Fast Attack (2 msec)"); btnHellFastAttack->down_box(FL_DOWN_BOX); btnHellFastAttack->callback((Fl_Callback*)cb_btnHellFastAttack); o->value(progdefaults.HellPulseFast); } // Fl_Check_Button* btnHellFastAttack - { Fl_Check_Button* o = btnHellSlowAttack = new Fl_Check_Button(185, 131, 70, 15, "Slow Attack (4 msec)"); + { Fl_Check_Button* o = btnHellSlowAttack = new Fl_Check_Button(199, 131, 70, 15, "Slow Attack (4 msec)"); btnHellSlowAttack->down_box(FL_DOWN_BOX); btnHellSlowAttack->value(1); btnHellSlowAttack->callback((Fl_Callback*)cb_btnHellSlowAttack); @@ -2308,6 +2316,13 @@ l with your sound hardware."); btnFeldHellIdle->callback((Fl_Callback*)cb_btnFeldHellIdle); o->value(progdefaults.HellXmtIdle); } // Fl_Check_Button* btnFeldHellIdle + { Fl_Spinner* o = valHellXmtWidth = new Fl_Spinner(40, 80, 40, 25, "Xmt Width"); + valHellXmtWidth->maximum(3); + valHellXmtWidth->value(1); + valHellXmtWidth->callback((Fl_Callback*)cb_valHellXmtWidth); + valHellXmtWidth->align(FL_ALIGN_RIGHT); + o->value(progdefaults.HellXmtWidth); + } // Fl_Spinner* valHellXmtWidth tabFeld->end(); } // Fl_Group* tabFeld { tabOlivia = new Fl_Group(0, 50, 400, 170, "Olivia"); diff --git a/src/dialogs/confdialog.fl b/src/dialogs/confdialog.fl index 0ccd9d96..5ea84cba 100644 --- a/src/dialogs/confdialog.fl +++ b/src/dialogs/confdialog.fl @@ -898,7 +898,7 @@ progdefaults.changed = true;} } Fl_Group tabMisc { label Misc open - xywh {0 25 400 195} color 51 selection_color 51 + xywh {0 25 400 195} color 51 selection_color 51 hide } { Fl_Group {} { label {Sweet Spot} open @@ -952,7 +952,7 @@ progdefaults.changed = true;} Fl_Check_Button chkSlowCpu { label {Slow cpu} callback {progdefaults.slowcpu = o->value(); -progdefaults.changed = true;} selected +progdefaults.changed = true;} xywh {110 190 89 15} down_box DOWN_BOX code0 {o->value(progdefaults.slowcpu);} } @@ -960,7 +960,7 @@ progdefaults.changed = true;} selected } Fl_Group tabModems { label Modem open - xywh {0 25 401 195} color 51 selection_color 51 hide + xywh {0 25 401 195} color 51 selection_color 51 } { Fl_Tabs tabsModems {open xywh {0 25 401 195} color 51 selection_color 10 align 9 @@ -1133,7 +1133,7 @@ progdefaults.changed = true;} } Fl_Group tabDomEX { label Dom open - xywh {0 50 400 170} color 51 selection_color 51 + xywh {0 50 400 170} color 51 selection_color 51 hide } { Fl_Input txtSecondary { label {Secondary Text} @@ -1174,13 +1174,13 @@ progdefaults.changed = true;} } Fl_Group tabFeld { label Feld open - xywh {0 50 400 170} color 51 selection_color 51 hide + xywh {0 50 400 170} color 51 selection_color 51 } { Fl_Choice selHellFont { label {Feld Hell Font:} callback {progdefaults.feldfontnbr=o->value(); progdefaults.changed = true;} open - xywh {175 62 122 20} down_box BORDER_BOX labelfont 4 textfont 4 + xywh {260 62 122 20} down_box BORDER_BOX labelfont 4 textfont 4 code0 {\#include "fontdef.h"} code1 {o->add(szFeldFonts);} code2 {o->value(progdefaults.feldfontnbr);} @@ -1195,7 +1195,7 @@ progdefaults.changed = true;} open label {2x Xmt Width} callback {progdefaults.HellXmtWidth=o->value(); progdefaults.changed = true;} - xywh {40 93 113 15} down_box DOWN_BOX + xywh {175 175 113 15} down_box DOWN_BOX hide code0 {o->value(progdefaults.HellXmtWidth);} } Fl_Check_Button btnHellRcvWidth { @@ -1214,7 +1214,7 @@ progdefaults.changed = true;} } Fl_Group {} { label {Pulse Shape} open - xywh {175 90 195 85} box ENGRAVED_FRAME align 21 + xywh {189 90 195 85} box ENGRAVED_FRAME align 21 } { Fl_Check_Button btnHellFastAttack { label {Fast Attack (2 msec)} @@ -1226,7 +1226,7 @@ btnHellSlowAttack->value(1); progdefaults.HellPulseFast = false; } progdefaults.changed = true;} - xywh {185 110 169 15} down_box DOWN_BOX + xywh {199 110 169 15} down_box DOWN_BOX code0 {o->value(progdefaults.HellPulseFast);} } Fl_Check_Button btnHellSlowAttack { @@ -1239,7 +1239,7 @@ btnHellFastAttack->value(1); progdefaults.HellPulseFast = true; } progdefaults.changed = true;} - xywh {185 131 70 15} down_box DOWN_BOX value 1 + xywh {199 131 70 15} down_box DOWN_BOX value 1 code0 {o->value(!progdefaults.HellPulseFast);} } } @@ -1250,6 +1250,13 @@ progdefaults.changed = true;} xywh {40 155 70 15} down_box DOWN_BOX value 1 code0 {o->value(progdefaults.HellXmtIdle);} } + Fl_Spinner valHellXmtWidth { + label {Xmt Width} + callback {progdefaults.HellXmtWidth=(int)o->value(); +progdefaults.changed = true;} selected + xywh {40 80 40 25} align 8 maximum 3 value 1 + code0 {o->value(progdefaults.HellXmtWidth);} + } } Fl_Group tabOlivia { label Olivia open diff --git a/src/dialogs/fl_digi.cxx b/src/dialogs/fl_digi.cxx index 03a9929a..214665c1 100644 --- a/src/dialogs/fl_digi.cxx +++ b/src/dialogs/fl_digi.cxx @@ -100,6 +100,8 @@ #include "Viewer.h" #include "soundconf.h" +#include "htmlstrings.h" + Fl_Double_Window *fl_digi_main=(Fl_Double_Window *)0; Fl_Help_Dialog *help_dialog = (Fl_Help_Dialog *)0; Fl_Double_Window *scopeview = (Fl_Double_Window *)0; @@ -753,6 +755,25 @@ void html_help( const string &Html) help_dialog = new Fl_Help_Dialog; help_dialog->value(Html.c_str()); help_dialog->show(); + restoreFocus(); +} + +void cb_mnuBeginnersURL(Fl_Widget*, void*) +{ + if (!help_dialog) + help_dialog = new Fl_Help_Dialog; + help_dialog->value(szBeginner); + help_dialog->show(); + restoreFocus(); +} + +void cb_mnuAboutURL(Fl_Widget*, void*) +{ + if (!help_dialog) + help_dialog = new Fl_Help_Dialog; + help_dialog->value(szAbout); + help_dialog->show(); + restoreFocus(); } void fldigi_help(const string& theHelp) @@ -1189,12 +1210,13 @@ Fl_Menu_Item menu_[] = { // settle the gmfsk vs fldigi argument once and for all {"@-1circle Create sunspots", 0, cb_mnuFun, 0, FL_MENU_DIVIDER, FL_NORMAL_LABEL, 0, 14, 0}, #endif +{"Beginners Help", 0, cb_mnuBeginnersURL, 0, 0, FL_NORMAL_LABEL, 0, 14, 0}, {"Online documentation", 0, cb_mnuVisitURL, (void *)PACKAGE_DOCS, 0, FL_NORMAL_LABEL, 0, 14, 0}, {"Home page", 0, cb_mnuVisitURL, (void *)PACKAGE_HOME, FL_MENU_DIVIDER, FL_NORMAL_LABEL, 0, 14, 0}, {"Command line options", 0, cb_mnuCmdLineHelp, 0, 0, FL_NORMAL_LABEL, 0, 14, 0}, {"Audio device info", 0, cb_mnuAudioInfo, 0, 0, FL_NORMAL_LABEL, 0, 14, 0}, {"Build info", 0, cb_mnuBuildInfo, 0, FL_MENU_DIVIDER, FL_NORMAL_LABEL, 0, 14, 0}, -{"About", 0, cb_mnuAbout, 0, 0, FL_NORMAL_LABEL, 0, 14, 0}, +{"About", 0, cb_mnuAboutURL, 0, 0, FL_NORMAL_LABEL, 0, 14, 0}, {0,0,0,0,0,0,0,0,0}, {" ", 0, 0, 0, FL_MENU_INACTIVE, FL_NORMAL_LABEL, 0, 14, 0}, @@ -1346,7 +1368,7 @@ void create_fl_digi_main() { if (twoscopes) WNOM -= 2*DEFAULT_SW; - fl_digi_main = new Fl_Double_Window(WNOM, HNOM, "fldigi"); + fl_digi_main = new Fl_Double_Window(WNOM, HNOM, PACKAGE_NAME" "PACKAGE_VERSION);//"fldigi"); mnu = new Fl_Menu_Bar(0, 0, WNOM - 142, Hmenu); // FL_NORMAL_SIZE may have changed; update the menu items for (size_t i = 0; i < sizeof(menu_)/sizeof(menu_[0]); i++) @@ -2225,3 +2247,4 @@ void start_tx() fl_unlock(&trx_mutex); wf->set_XmtRcvBtn(true); } + diff --git a/src/dialogs/htmlstrings.cxx b/src/dialogs/htmlstrings.cxx new file mode 100644 index 00000000..9ff5e309 --- /dev/null +++ b/src/dialogs/htmlstrings.cxx @@ -0,0 +1,568 @@ +// ---------------------------------------------------------------------------- +// +// htmlstrings.cxx +// +// Copyright (C) 2008 +// Dave Freese, W1HKJ +// +// This file is part of fldigi. +// +// fldigi is free software; you can redistribute it and/or modify +// it under the terms of the GNU General Public License as published by +// the Free Software Foundation; either version 2 of the License, or +// (at your option) any later version. +// +// fldigi is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// GNU General Public License for more details. +// +// You should have received a copy of the GNU General Public License +// along with fldigi; if not, write to the Free Software +// Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA +// ---------------------------------------------------------------------------- + + +char szBeginner[] = "\ +\ +\ +Beginners' Guide to FLDIGI\ +\ +\ +\ +
\ +

Beginners' Guide to FLDIGI

\ +

\ +Requirements \ +Installation \ +Getting Started \ +Operating \ +Special Keys \ +\ +


\ +
\ +

Beginners' Questions Answered

\ +

What is FLDIGI?

\ +
\ +FLDIGI is a computer program intended for Amateur Radio Digital Modes operation using a PC (Personal Computer).\ +FLDIGI operates (as does most similar software) in conjunction with a conventional HF SSB radio transceiver,\ +and uses the\ +PC sound card as the main means of input from the radio, and output to the radio. These are audio-frequency\ +signals. The software also controls the radio by means of another connection, typically a serial port.\ +

\ +FLDIGI is multi-mode, which means that it is able to operate many popular digital modes without switching\ +programs, so you only have one program to learn. FLDIGI includes all the popular modes, such as DominoEX, MFSK16,\ +PSK31, and RTTY.\ +

\ +Unusually, FLDIGI is available for multiple computer operating systems; Linux, Free-BSD; OS-X and Windows(XP).\ +

\ +

What is a Digital Mode?

\ +
\ +Digital Modes are a means of operating Amateur radio from the computer keyboard. The computer acts as 'modem' (modulator - demodulator),\ +as well as allowing you to type, and see what the other person types. It also controls the transmitter, changes modes as required,\ +and provides various convenient features such as easy tuning of signals and prearranged messages.\ +

\ +In this context, we are talking\ +about modes used on the HF (high frequency) bands, specifically 'chat' modes, those used to have a regular\ +conversation in a similar way to voice or Morse, where one operator 'talks' for a minute or two, then another\ +does the same. These chat modes allow multiple operators to take part in a 'net'.\ +

\ +Because of sophisticated digital signal processing which takes place inside the computer, digital modes can\ +offer performance that cannot be achieved using voice (and in some cases even Morse), through reduced\ +bandwidth, improved signal-to-noise performance and reduced transmitter power requirement. Some modes also\ +offer built-in automatic error correction.\ +

\ +Digital Mode operating procedure is not unlike Morse operation, and many of the same abbreviations are used.\ +Software such as FLDIGI makes this very simple as most of the procedural business is set up for you using\ +the Function Keys at the top of the keyboard. These are easy to learn.\ +

\ +

Why all the different modes?

\ +
\ +HF propagation is very dependent on the ionosphere, which reflects the signals back to earth. There are strong\ +interactions between different signals arriving from different paths. Experience has shown that particular\ +modulation systems, speeds and bandwidths suit different operating conditions.\ +

\ +Other factors such as available band space, operating speed and convenience, noise level, signal level and\ +available power also affect the choice of mode. While in many cases several different modes might be suitable,\ +having a choice adds to the operating pleasure. It is diffcult to advise which mode is best for each particular\ +occasion, and experience plays an important role. \ +

\ +You might consider purchasing 'Digital Modes for All Occasions'\ +(ISBN 1-872309-82-8) by Murray Greenman ZL1BPU, published by the RSGB,\ +as this gives a good insight into each mode\ +and its capabilities. The book is also available from FUNKAMATEUR and CQ Communications.\ +

\ +

\ +

How do I recognise and tune in the signals?

\ +
\ +Recognising the different modes comes with experience. It is a matter of listening to the signal, and observing\ +the appearance of the signal on the tuning display. You can also practice transmitting with the transceiver\ +disconnected, listening to the sound of the signals coming from the computer. There is also (see later paragraph)\ +an automatic tuning option which can recognise and tune in most modes for you.\ +

\ +The software provides a tuning display which shows the radio signals that are receivable within the transceiver\ +passband. Using a 'point and click' technique with the mouse, you can click on the centre of a signal to select it,\ +and the software will tune it in for you. Some modes require more care than others, and of course you need to have\ +the software set for the correct mode first - not always so easy!\ +

\ +The 'RSID' (automatic mode detection and tuning) feature uses a special sequence of tones transmitted at the beginning of each transmission to identify\ +and tune in the signals received. For this feature to work, not only do you need to enable the feature in the receiver,\ +but in addition the stations you are wishing to tune in need to have this feature enabled on transmission. Other\ +programs also offer this RSID feature as an option.\ +

\ +

Where can I find detailed instructions for FLDIGI?

\ +
\ +Of necessity, this Beginner's Guide contains only as much as you need to know to get started. You can always read the\ +details and learn how to make best use of the program by reading the Online Documentation. You can also access it from within the FLDIGI program from the HELP Menu item. \ +
\ +\ +
\ +

Requirements

\ +
\ +
\ +
Computer
\ +
Pentium™ 3 or 4, Celeron™, or equivalent, 750MHz or better, 256MB RAM or more. Faster computers can give\ +better performance.
\ +
Operating System
\ +
Windows XP SP2 (Home or Pro), LINUX distributions such as Debian, Ubuntu, Kubuntu, Mandriva, Mandrake,\ +SuSE, Puppy Linux, or FreeBSD. FLDIGI can be home compiled for other distributions. FLDIGI does not support\ +Windows 98 or older, and may not work with Windows VISTA.
\ +
Other Requirements
\ +
  • Computer serial port (or USB serial port) for rig control\ +
  • Optional serial CAT (Computer Aided Tuning) computer control\ +
  • About 5MB of drive space is required for program files\ +
  • Internet connection will allow direct connection to the online help files and your online callsign server subscription.\ +
  • A radio interface to the sound card and serial port, such as the RigBlaster™ or similar. You can make one yourself.\ +
  • A modern HF SSB transceiver, with or without CAT control. For some modes, frequency stability is very important\ +(preferably less than 1Hz drift per over), and the difference between transmit and receive frequencies should also\ +be low (less than 1Hz). Tuning steps should be 100Hz or less. Most commercial synthesized transceivers made in the last\ +20 years will meet these requirements.\ +
  • \ +
    \ +
    \ +
    \ +

    Installation

    \ +

    Installing

    \ +
    \ +
    \ +

    Updating the Program

    \ +
    \ +
    • Delete the shortcut you made during installation\ +
    • Repeat the installation process described above, using the same folder. The new program will over-write the old.\ +
    • Make a new shortcut as described above.\ +
    \ +
    \ +

    Removing the Program

    \ +
    \ +
    • Delete the shortcut you made during installation\ +
    • Locate the program folder you made during installation, delete the contents, and then delete the folder.\ +
    \ +
    \ +

    Setting Up

    \ +
    \ +
    • Use the menu Configure/Defaults/Sound Card Audio Devices tab to select the sound card you wish to use.\ +You can ignore the other tabs for now.\ +
    • Use the menu Configure/Defaults/Operator item to set the user name, callsign, location and so on.\ +
    • Use the menu Configure/Defaults/Rig Ctrl item to set how you will control the rig. Set 'Ptt' to 'TTY'.\ +If you will control the rig via a serial port, select the COM port you will use, and select which line controls PTT.\ +If in doubt, check both RTS and DTR. You MUST then press the Initialize button.\ +
    • If you plan to use CAT control of the rig via the COM port, check 'userigCAT'. If in addition you wish to use\ +PTT control via CAT, also then check 'rigCAT PTT'. You MUST then press the Initialize button.\ +
    • Use the menu Configure/Defaults/Misc item to set whether you wish to transmit RSID data at the start of each\ +over (this is for the benefit of others, this setting does not affect RSID reception), and whether you have a slow computer (under 1000MHz)\ +or not. The receiver decoding strategy uses less processor power in 'Slow cpu' mode. If you plan to regularly\ +use the RSID feature on receive, you must leave the 'Start New Modem at Sweet Spot' item unchecked.\ +
    • Each of the modems can be individually set up from the Configure/Modems multi-tabbed dialog.\ +You need not change anything here to start with, although it might be a good idea to set the 'secondary text' for DominoEX\ +('Dom' tab) and THOR ('Thor' tab) to something useful, such as your call and locator. (Secondary text is transmitted when the text\ +you type does not keep up with the typing speed of the mode - this handy text appears in a small window at the very bottom of the screen).\ +Note that this set of tabs is also where you set the RTTY modem speed and shift, although the default values should be fine\ +for normal operation.\ +
    • Use the menu Configure/Save Config item to save the new configuration.\ +
    • Use your sound card 'Master Volume' applet to select the sound card, the Wave output and set the transmit audio level.\ +You can check the level using the TUNE button, top right, beyond the Menu.\ +
    • The 'Volume' applet can usually be opened by START/Run... and enter 'sndvol32', or from the Control Panel.\ +
    • Use your sound card 'Recording Control' applet to select the sound card, the line or mic input and set the receiver audio level.\ +Watch the waterfall display for receiver noise when setting the level. If you see any dark blue noise, you have the right input\ +and about the right level. The actual setting is not very important, provided you see blue noise. If the audio level is too high,\ +the little diamond shaped indicator (bottom right) will show red. The waterfall may also show red bands.\ +Performance will be degraded if the level is too high.\ +
    • The 'Record' applet can usually be opened by START/Run... and enter 'sndvol32 /r', or from the Control Panel.\ +If opened from the Control Panel, you'll end up with the Master Volume applet, and need to switch using Options/Properties, and selecting\ +the 'Recording' radio button.\ +
    \ +
    \ +\ +
    \ +

    Getting Started

    \ +

    Guided Tour

    \ +
    \ +Double-click on the FLDIGI shortcut to start the program. A window with three main panes will appear.\ +Study it carefully as you read these notes. From top to bottom, these are the RECEIVE pane\ +(orange), the TRANSMIT pane (light blue), and the WATERFALL pane (black). At the top is\ +the collection of entry items which form the LOG DATA, and at the very top, a\ +conventional drop-down MENU system, with entries for Files, Op Mode, Configure, View and Help.\ +

    \ +Between the RECEIVE and TRANSMIT panes is a line of boxes (buttons), which represent the Function Keys F1 - F12.\ +We call this the FUNCTIONS group.\ +Below the WATERFALL pane is another line of boxes (buttons), which provide various control features. We call this the\ +CONTROLS group. The program and various buttons can mostly be operated using the mouse or the keyboard, and users\ +generally find it convenient\ +to use the mouse while tuning around, and the keyboard and function keys during a QSO.\ +

    \ +

    RECEIVE Pane

    \ +
    \ +This is where the text from decoded incoming signals is displayed, in black text.\ +When you transmit, the transmitted text is also displayed here, but in red, so\ +the RECEIVE pane becomes a complete record of the QSO. The information in this pane can also be logged to a file.\ +

    \ +The line at the bottom of this pane can be dragged up and down with the mouse. You might prefer to drag it down a bit\ +to enlarge the RECEIVE pane and reduce the size of the TRANSMIT pane.\ +

    \ +

    TRANSMIT Pane

    \ +
    \ +This is where you type what you want to transmit. The mouse must click in here before you type (to obtain 'focus') otherwise\ +your text will go nowhere. You can type in here while you are receiving, and when you start transmitting, the text already typed\ +will be sent first. This trick is a cool way to impress others with your typing speed! As the text is transmitted, the text colour\ +changes from black to red. At the end of the over, all the transmitted\ +text (and any as yet not transmitted) will be deleted.\ +
    \ +

    WATERFALL Pane

    \ +
    \ +This is the main tuning facility. There are two modes, 'Waterfall' and 'FFT', selected by a button in the CONTROL group. For now,\ +leave it in 'Waterfall' mode, as this is the easiest to tune with, and gives the best identification of the signal.\ +
    • 'Waterfall' is a spectrogram display, of signal strength versus frequency, over passing time. The receiver passband\ +is analysed and displayed with lower frequencies to the left, higher to the right. Weak signals and background noise\ +are dark while stronger signals show as brighter colours. As time passes (over a few seconds), the historic signals move downwards like a waterfall.\ +
    • 'FFT' is a spectrum display, simply the mean signal strength versus frequency. Again frequency is displayed from left to right,\ +but now the vertical direction shows signal strength and there is no brightness or historic onformation.
    \ +

    \ +At the top of the pane is a scale of frequency in Hz, which corresponds to the frequency displayed immediately below it. This\ +scale can be moved around and zoomed using buttons in the CONTROL group.\ +

    \ +As you move the mouse around in this pane you will see a yellow group of tuning marks following the mouse pointer.\ +Tuning is achieved by left-clicking on a signal displayed by the waterfall in this pane. Use these yellow marks to\ +exactly straddle the signal and then left-click on the centre of the signal. The tuning marks change to\ +red. The red vertical lines will show the approximate\ +width of the active signal area (the expected signal bandwidth), while a red\ +horizontal bar above will indicate the receiver software's active decoding range. When you left-click, the red\ +marks move to where you clicked, and will attempt to auto-track the signal from there.\ +

    \ +You can temporarily 'monitor' a different signal by right-clicking on it. As long as you hold the mouse button down, the signal under\ +it will be decoded; as soon as you release the mouse, decoding will revert to the previously tuned spot (where the red marks are).\ +

    \ +

    LOG Data

    \ +
    \ +Using this group of entry boxes, you can keep a log of your QSOs. At the left are two 'Frequency' boxes.\ +If you use CAT control to operate your transceiver, the dial frequency is recorded automatically in the lower box;\ +otherwise you can type it manually or select (botton to the right) from a list of common frequencies. The audio frequency from the waterfall\ +is added to this value and displayed in the upper box - assuming your rig is calibrated correctly, this is the true\ +centre frequency of the station you are in QSO with. You can't type in the upper box.\ +

    \ +The program is able to switch sidebands (the 'U' or 'L' button under the 'Time' display),\ +so if your rig is in LSB mode, the signals are inverted for you, and when you\ +add the frequency to the log information, the audio frequency is subtracted rather than added, so again the true transmit\ +frequency is displayed and logged.\ +

    \ +The 'Time' box can be typed in, or you can push the adjacent button to insert the current time. All times are in UTC,\ +and the computer knows how to calculate this from the PC local civil time, time zone and summer-time setting. Clever stuff!\ +

    \ +You can type the other station's callsign and name in the 'Call' and 'Namel' boxes, or right-click\ +on the appropriate word in the RECEIVE pane to insert them automatically. The same applies to the 'QTH',\ +'LOC' (locator) and received signal report 'RST In'. The other entries must be added manually.\ +If you have access to an appropriate Callbook on-line subscription or CD, pressing the 'QRZ' button will fetch\ +this information for you automatically.\ +

    \ +The 'Clear' button clears all the log data; the 'Save' button sends the logged information to the log file.\ +

    \ +

    MENU

    \ +
    \ +At the very top of the program window is a conventional drop-down menu. If you click on any of the items, a list of optional\ +functions will appear. Keyboard menu selection is also provided.\ +Where underscored characters are shown in the menu, you can select these menu items from the keyboard\ +using the marked character and <Alt> at the same time, then moving around with the up/down/left/right keys.\ +Use <Esc> to quit from the menu with no change.\ +These menu functions are:\ +
    \ +
    Files
    \ +
    Allows you to open or save Macros (we won't get into that here), turn on/off logging to file, record/play audio samples, and exit the program. You can also exit the program by clicking on the 'X' in the tope right corner of the window, in the usual manner.
    \ +
    Op Mode
    \ +
    This is where you select the operating modem used for transmission and reception. Some modes only have one option. Where more are\ +offered, drag the mouse down the list and sideways following the arrow to a secondary list, before releasing it. When you start the\ +program next time, it will remember the last mode you used.\ +

    \ +Not all the modes are widely used, so choose a mode which (a) maximizes your chance of a QSO, and (b) is appropriate for\ +the band, conditions, bandwidth requirements and permissions relevant to your operating licence.\ +

    \ +At the bottom of the list are two 'modes' which aren't modes at all, and do not transmit (see\ +Online Documentation for details). WWV mode allows you to receive a standard time\ +signal so the beeps it transmits can be used for sound card calibration. Freq Analysis provides just a waterfall display with a very narrow cursor, and a frequency meter\ +which indicates the received frequency in Hz to two decimal places. This is useful for on-air frequency measurement.

    \ +
    Configure
    \ +
    This is where you set up the program to suit your computer, yourself and your operating preferences. Defaults\ +will allow you to change the operating settings of the program. This is where you enter your personal information,\ +or define your computer sound card, for example.\ +Modems can be individually changed, each having\ +different adjustments. The Modems dialog has multiple tabs, so you can edit any one of them. Don't fool with\ +the settings until you know what you are doing! The final item, Save Config allows you to save the altered configuration\ +for next time you start the program (otherwise changes are temporary).\ +
    View
    \ +
    This menu item allows you to open extra windows. Most will be greyed out, but two that are available are the Digiscope,\ +and the PSK Browser. The Digiscope provides a mode-specific graphical analysis of the received signal, and\ +can have more than one view (left click in the new window to change the view), or maybe none at all. The PSK Browser\ +is a rather cool tool that allows you to monitor several PSK31 signals all at the same time! These windows can be resized to suit.
    \ +
    Help
    \ +
    Brings up the Online Documentation, the FLDIGI\ +Home Page, and various information about the program.
    \ +
    \ +

    FUNCTIONS

    \ +
    \ +This line of buttons provides user-editable QSO features. For example, the first button on the left sends CQ for you. Both the\ +function of these buttons (we call them MACROS) and the label on each button, can be changed. Select each button\ +to use it by pressing the corresponding Function Key (F1 - F12, you'll notice the buttons are grouped in patterns four to a group,\ +just as the Function Keys are). You can also select them with a left-click of the mouse. If you right-click on the button, you\ +are able to edit the buttons label and its function. A handy dialog pops up to allow this to be done. There are many standard\ +shortcuts, such as <MYCALL> which you can use within the Macros. Notice that the buttons also turn the transmitter on\ +and off as necessary.\ +

    \ +You can just about hold a complete QSO using these buttons from left to right (but please don't!). Notice that at the right are\ +two spare buttons you can set as you wish, and then a button labelled '1'. Yes, this is the first set of FOUR sets of Macros,\ +and you can access the others using this button, which changes to read '2', '3', '4' then '1' again (right-click to go backwards),\ +or by pressing <Alt> and the corresponding number (1-4, not F1-F4) at the same time.\ +

    \ +If you REALLY mess up the Macros and can't see how to fix them, just close the program without saving them, and reopen it.\ +

    \ +

    CONTROLS

    \ +
    \ +The line of buttons under the waterfall is used to control the program (as opposed to the QSO). If you hover the mouse over\ +these buttons, you'll see a little yellow hint box appear which tells you what each button does.\ +

    \ +The Id? button turns on the receive\ +RSID (automatic mode detection and tuning) feature. When in use, the button turns yellow and no text reception is possible until\ +a signal is identified, or the feature is turned off again. If you plan to use the RSID feature on receive,\ +you must leave the 'Start New Modem at Sweet Spot' item in the Menu Configure/Defaults/Mics tab unchecked.\ +

    \ +The next three buttons control waterfall behaviour. The first switches between Waterfall and FFT modes; the next sets the scale\ +zoom factor (visible display width, x1, x2 or x4); the third selects the waterfall speed. NORM or SLOW setting is best unless\ +you have a very fast computer.\ +

    \ +The next three buttons move the waterfall left and right, followed by two (either side of a number, the audio frequency in Hz)\ +which control the receiving frequency (they move the red cursor lines).\ +

    \ +You can also adjust the signal level over which the waterfall works. The default range is from 0dB downwards 70dB (i.e. to -70dB).\ +Both of these values can be adjusted to suit your sound card and receiver audio level.\ +

    \ +The M button allows you to store or recall the current frequency (see the Online Documentation for details). The Lk button locks the transmit frequency (fixes the red cursors), and the Rv button turns\ +the signal decoding upside down (some modes are sideband sensitive, and if they are the wrong way up, can't be received\ +correctly). Remember to turn this one off when you're done, or you won't receive anything! If every signal you hear is upside\ +down, check your transceiver sideband setting.\ +

    \ +The T/R button forces the transmitter on or off - use this with care, as it will stop transmission immediately,\ +losing whatever is in the buffer (what you have typed in the Transmit pane), or start it immediately, even if nothing is ready to transmit.\ +

    \ +There are two further controls in the bottom right corner of the program, to the right of the Status line:\ +

    \ +
    Afc - The AFC control
    \ +
    When this button is pressed, an indicator on the button turns yellow, and the program will automatically retune to drifting signals.\ +When the button is again pressed, AFC is off, and the tuning will stay where you leave it.
    \ +
    Sql - The Squelch control
    \ +
    When off (no coloured indicator on the button, the receiver displays all 'text' received, even if there is no signal present,\ +and the receiver is simply attempting to decode noise. When activated by pressing the button, the indicator turns yellow.\ +If the incoming signal strength exceeds that set by the adjacent slider control (above the Sql button), the indicator\ +turns green and the incoming signal is decoded and printed. The signal strength is indicated on the green bar beside the\ +Squelch level slider. If nothing seems to be printing, the first thing to do is check the Squelch!
    \ +
    \ +\ +

    STATUS Line

    \ +
    \ +At the very bottom line of the FLDIGI window is a row of useful information. At the left is the current operating mode. Next (some modes)\ +is the measured signal-to-noise ratio at the receiver, and (in some modes) the measured signal intermodulation level (IMD).\ +

    \ +The larger central box shows (in DominoEX and THOR modes) the received 'Secondary Text'. This is information (such as\ +station identification) which is transmitted automatically whenever the transmitter has completed all user text that is\ +available to send. It is transmitted using special characters, and is automatically directed to this special window. Secondary text\ +you transmit is also shown here. This box changes size when you enlarge the program window.\ +

    \ +\ +
    \ +

    Operating

    \ +

    Procedure

    \ +
    \ +Operating procedure for digital modes is similar to that for Morse. Some of the same abbreviations are used. For example, at the beginning\ +of an over, you might send 'VK3XYZ de WB8ABC' or just 'RR Jack' and so on. At the end of an over, it is usual to send 'ZL1ABC de AA3AR K',\ +and at the end of a QSO '73 F3XYZ de 3D2ZZ SK'. When operating in a group or net it is usual to sign 'AA3AE es gp de ZK8WW K'.\ +

    \ +It is also considered a courtesy to send a blank line or two (press <Enter>)\ +before any text at the start of an over, and following the last text at the end of an over. You can also place these in the macros.\ +The purpose is to separate your text from the previous text, and especially from any rubbish that was printed between overs.\ +

    \ +FLDIGI does all of this for you. The Function Keys are set up to provide these start and end of over facilities, and can be edited\ +to suit your preferences. In\ +order that the other station's callsign can appear when these keys are used, you need to set the other station's callsign in the log\ +data - it does not matter if you use the log facility or not.\ +

    \ +
    Hint: Some Function Key Macro buttons have graphic symbols on them which imply the following:
    \ +
    >>  The transmitter comes on and stays on when you use this button/macro.\ +
    ||   The transmitter goes off when the text from this button/macro has been sent.\ +
    >|  The transmitter comes on, sends the text from this button/macro, and goes off when the text from this button/macro has been sent.\ +
    \ +\ +The Macros are set up to control the transmitter as necessary, but you can also switch the transmitter on at the start of an over with <Ctrl>\ +and T or the TX macro button, and off again with <Ctrl> and R or the RX macro button. If you\ +have Macros copied into or text already typed in the Transmit pane when you start the transmitter, this is sent first.\ +

    \ +Calling another station you have tuned in is as simple as pushing a button. Put his callsign into the log data (right click, select Call)\ +and press the ANS Macro button (or F2) when you are ready. If he replies, you are in business! Then press QSO (F3)\ +to start each over, and BTU (F4) to end it, and SK (F5) to sign off.\ +

    \ +
    Hint: When typing text, the correct use of upper and lower case is important:
    \ +
  • Modes such as RTTY and THROB have no lower case capability.\ +
  • In most other modes, excessive use of upper case is considered impolite, like SHOUTING!\ +
  • Modes such as PSK31, MFSK16, DominoEX and THOR use character sets which are optimized for lower case.\ +You should use lower case as much as possible in these modes to achieve maximum text speed. In these modes upper case\ +characters are noticeably slower to send and also slightly more prone to errors.\ +
  • \ +
    \ +

    Adjustment

    \ +
    \ +Most digital modes do not require much transmitter power, as the receiver software is very sensitive. Many modes (PSK31, THROB,\ +MT63) also require very high transmitter linearity, which is another reason to keep transmitter power below 30% of maximum.\ +Some modes (Hellschreiber, Morse) have high peak power output, which may not indicate well on the conventional power meter,\ +another reason to keep the average transmitted power low to prevent a very broad signal being transmitted.\ +

    \ +Adjust the transmitter output power using the TUNE button, top right, beyond the Menu. The output will be the same as the peak\ +power in other modes. Adjust the master Volume applet Wave Out and Master Volume controls to achieve the appropriate power.\ +Use of excessive drive will result in distortion (signal difficult to tune in, and often poorer reception) and a very broad signal.\ +

    Some multi-carrier modes (MT63 for example) may require individual adjustment as the average power may be rather low.\ +

    \ +
    Hint: Where possible, use the area above 1200Hz on the waterfall.\ +
  • Below 1200Hz the second harmonic of the transmitted audio will pass through the transmitter filters.\ +
  • When using lower frequency tones, adjust the transmitter and audio level with great\ +care, as the second (and even third) harmonic will appear in the transmitter passband, causing excessive signal width.\ +
  • A narrow (CW) filter in the rig is no help in this regard, as it is only used on receive. When you do use a narrow filter, this will restrict the area over which the receiver and transmitter will operate (without retuning of course). Try adjusting the passband tuning (if available).\ +
  • Keep the sound card audio level to a minimum and set the transmitter gain to a similar level used for SSB.\ +
  • \ +
    \ +

    Waterfall Tuning

    \ +
    \ +When using this program, as with most other digital modes programs, tuning is generally accomplished by leaving the\ +transceiver VFO at a popular spot (for example 14.070MHz, USB), and performing all the 'tuning' by moving around within\ +the software.\ +

    \ +The FLDIGI software has a second 'VFO' which is tuned by clicking on the waterfall. On a busy band, you\ +may see many signals at the same time (especially with PSK31 or Morse), and so you can click with the mouse on\ +any one of these signals to tune it in, receive it, and if the opportunity allows, reply to the station.\ +

    \ +The software 'VFO' operates in a transceive mode, so the transmitter signal is automatically and exactly tuned to the\ +received frequency. If you click correctly on the signal, your reply will always be in tune with the other station.\ +

    \ +
    Hint: You MUST NOT use RIT (Clarifier) when using digital modes.\ +
  • With RIT on, you will probably have to retune after every over.\ +
  • Use of the RIT will also cause the other station to change frequency, and you will chase each other\ +across the band.\ +
  • Older transceivers without digital synthesis may have an unwanted offset (frequency difference)\ +between transmit and receive frequencies. Such rigs should not be used for digital modes.\ +
  • \ +Wider digital modes (MT63, Olivia) can be tuned using the rig if necessary, as tuning is not at all critical.\ +The software tuning still operates, but because the signal is so wide, there is limited ability to move\ +around in the waterfall tuning.\ +
    \ +
    \ +

    Special Keys

    \ +
    \ +Several special keyboard controls are provided to make operating easier.\ +
    \ +
    Pause Transmission
    \ +
    \ +Press <Pause/Break> while in receive, and the program will switch to transmit mode. It will continue\ +with the text in the transmit buffer (the Transmit pane text) from the current point, i.e. where the red (previously sent) text ends and\ +the black (yet to be sent) text begins. If the buffer only contains unsent text, then it will begin at the first\ +character in the buffer. If the buffer is empty, the program will switch to transmit mode, and depending on the\ +mode of operation, will send idle characters or nothing at all until characters are entered into the buffer. \ +

    \ +If you press <Pause/Break> while in transmit mode, the program will return to receive mode. There\ +may be a slight delay for some modes like MFSK, PSK and others, that requires the transmitter to send a postamble\ +at the end of a transmission. The transmit text buffer stays intact, ready for the <Pause/Break>\ +key to return you to the transmit mode .\ +

    \ +Pressing <Alt/Meta> and R has the same effect as <Pause/Break>.\ +You could think of the <Pause/Break> key as a software break-in capability.

    \ +

    \ +

    ESCAPE
    \ +
    \ +Pressing <Esc> while transmitting will abort the transmission. Transmission stops as soon as possible,\ +(any necessary postamble is sent), and the program returns to receive. Any unsent text in the transmit\ +buffer will be lost.\ +

    \ +If you press <Esc> <Esc> (i.e. twice in quick succession),\ +transmission stops immediately, (without sending any postamble), and the program returns to receive. Any unsent\ +text in the transmit buffer will be lost. Use this feature as an EMERGENCY STOP.\ +

    \ +

    RETURN to Receive
    \ +
    Press <Ctrl> and R to insert the ^r command in the transmit buffer at the current typing\ +point. When transmission reaches this point, transmission will stop. The transmission does not stop immediately.\ +

    \ +

    START Transmission
    \ +
    Press <Ctrl> and T to start transmission if there is text ready in the transmit buffer.\ +

    \ +

    \ +

    MOVE Typing Cursor
    \ +
    Press <Tab> to move the cursor (typing insertion point) to the end of the transmit buffer.\ +This will also pause transmission. A <Tab> press at that position moves the cursor back to the\ +character following the last one transmitted. Morse operation is slightly different. See the on-line help for\ +CW. \ +

    \ +

    \ +

    SEND any ASCII character
    \ +
    Press <Ctl> and (at the same time) any three-digit number (on the numeric keypad) to\ +insert the ASCII character designated by that entry value into the transmit buffer. For example,\ +<Ctl>177 is '±' and <Ctl>176 is '°' (degree).\ +
    \ +
    \ +
    Copyright © M. Greenman 2008\ +
    \ +\ +\ +\ +\ +"; + +char szAbout[] = +"\ +\ +\ + about\ +\ +\ +\ +
    \ +

    Fldigi

    \ +
    \ +
    \ +

    Digital modem program for


    \ +

    \ +     Linux
    \ +     Free-BSD
    \ +     OS-X
    \ +     Windows (XP)
    \ +
    \ +

    Authors:


    \ +

    \ +     Dave Freese, W1HKJ
    \ +     Stelios Buonanos, M0GLD
    \ +     Leigh Klotz, WA5ZNU
    \ +
    \ +

    Beginners Help:


    \ +

    \ +     M. Greenman, ZL1BPU
    \ +\ +\ +\ +"; + diff --git a/src/feld/feld.cxx b/src/feld/feld.cxx index 8677f6ca..33b254a8 100644 --- a/src/feld/feld.cxx +++ b/src/feld/feld.cxx @@ -467,7 +467,7 @@ int feld::tx_process() int c; bool hdkey; - dxmode = 1 + progdefaults.HellXmtWidth; + dxmode = progdefaults.HellXmtWidth; hdkey = progdefaults.HellPulseFast; fntnbr = progdefaults.feldfontnbr; diff --git a/src/filters/fftfilt.cxx b/src/filters/fftfilt.cxx index e3d28192..b9ea3d83 100644 --- a/src/filters/fftfilt.cxx +++ b/src/filters/fftfilt.cxx @@ -85,7 +85,7 @@ void fftfilt::create_filter(double f1, double f2) /* * Filter with fast convolution (overlap-add algorithm). */ -int fftfilt::run(complex in, complex **out) +int fftfilt::run(const complex& in, complex **out) { // collect filterlen/2 input samples filtdata[inptr++] = in; @@ -103,7 +103,7 @@ int fftfilt::run(complex in, complex **out) // multiply with the filter shape for (int i = 0; i < filterlen; i++) - filtdata[i] = filtdata[i] * filter[i]; + filtdata[i] *= filter[i]; // IFFT transpose back to the time domain ift->icdft(filtdata); diff --git a/src/filters/filters.cxx b/src/filters/filters.cxx index bc16e54d..adb3b7d3 100644 --- a/src/filters/filters.cxx +++ b/src/filters/filters.cxx @@ -432,7 +432,7 @@ sfft::~sfft() // Values are not stable until more than "len" samples have been processed. // returns address of first component in array -complex *sfft::run(complex input) +complex *sfft::run(const complex& input) { complex z; complex y; diff --git a/src/include/FTextView.h b/src/include/FTextView.h index f9353787..8616d3b9 100644 --- a/src/include/FTextView.h +++ b/src/include/FTextView.h @@ -330,6 +330,9 @@ protected: int txpos; static int *ptxpos; int bkspaces; + char ascii_cnt; + unsigned ascii_chr; + }; diff --git a/src/include/complex.h b/src/include/complex.h index cb06ae7e..2f12cd70 100644 --- a/src/include/complex.h +++ b/src/include/complex.h @@ -11,56 +11,66 @@ class complex { public: double re; double im; - complex(double r = 0.0, double i = 0.0) { - re = r; - im = i; - } - ~complex() {}; + complex(double r = 0.0, double i = 0.0) + : re(r), im(i) { } + double real() { return re; }; void real(double R) {re = R;}; double imag() { return im; }; void imag(double I) {im = I;}; // Z = X * Y - complex operator* (complex y) { - complex z; - z.re = re * y.re - im * y.im; - z.im = re * y.im + im * y.re; - return z; + complex& operator*=(const complex& y) { + re = re * y.re - im * y.im; + im = re * y.im + im * y.re; + return *this; + } + complex operator*(const complex& y) const { + return complex(re * y.re - im * y.im, re * y.im + im * y.re); } // Z = X * y - complex operator* (double y) { - complex z; - z.re = y * z.re; - z.im = y * z.im; - return z; + complex& operator*=(double y) { + re *= y; + im *= y; + return *this; + } + complex operator*(double y) const { + return complex(re * y, im * y); } // Z = X + Y - complex operator+ (complex y) { - complex z; - z.re = re + y.re; - z.im = im + y.im; - return z; + complex& operator+=(const complex& y) { + re += y.re; + im += y.im; + return *this; + } + complex operator+(const complex& y) const { + return complex(re + y.re, im + y.im); } // Z = X - Y - complex operator- (complex y) { - complex z; - z.re = re - y.re; - z.im = im - y.im; - return z; + complex& operator-=(const complex& y) { + re -= y.re; + im -= y.im; + return *this; + } + complex operator-(const complex& y) const { + return complex(re - y.re, im - y.im); } // Z = X / Y - complex operator/ (complex y) { + complex& operator/=(const complex& y) { double denom = y.re*y.re + y.im*y.im; if (denom == 0.0) denom = 1e-10; - complex z; - z.re = (re * y.re + im * y.im) / denom; - z.im = (im * y.re - re * y.im) / denom; - return z; + re = (re * y.re + im * y.im) / denom; + im = (im * y.re - re * y.im) / denom; + return *this; + } + complex operator/(const complex& y) const { + double denom = y.re*y.re + y.im*y.im; + if (denom == 0.0) denom = 1e-10; + return complex((re * y.re + im * y.im) / denom, (im * y.re - re * y.im) / denom); } // Z = (complex conjugate of X) * Y @@ -68,7 +78,12 @@ public: // Z2 = x2 + jy2, or Z2 = |Z2|exp(jP2) // Z = (x1 - jy1) * (x2 + jy2) // or Z = |Z1|*|Z2| exp (j (P2 - P1)) - complex operator% (complex y) { + complex& operator%=(const complex& y) { + re = re * y.re + im * y.im; + im = re * y.im - im * y.re; + return *this; + } + complex operator%(const complex& y) const { complex z; z.re = re * y.re + im * y.im; z.im = re * y.im - im * y.re; @@ -76,29 +91,29 @@ public: } // n = |Z| * |Z| - double norm() { + double norm() const { return (re * re + im * im); } // n = |Z| - double mag() { + double mag() const { return sqrt(norm()); } // Z = x + jy // Z = |Z|exp(jP) // arg returns P - double arg() { + double arg() const { return atan2(im, re); } }; -inline complex cmac (complex *a, complex *b, int ptr, int len) { +inline complex cmac (const complex *a, const complex *b, int ptr, int len) { complex z; - ptr = ptr % len; + ptr %= len; for (int i = 0; i < len; i++) { - z = z + a[i] * b[ptr]; + z += a[i] * b[ptr]; ptr = (ptr + 1) % len; } return z; diff --git a/src/include/confdialog.h b/src/include/confdialog.h index d112b8c8..cc79d818 100644 --- a/src/include/confdialog.h +++ b/src/include/confdialog.h @@ -162,6 +162,7 @@ extern Fl_Check_Button *btnBlackboard; extern Fl_Check_Button *btnHellFastAttack; extern Fl_Check_Button *btnHellSlowAttack; extern Fl_Check_Button *btnFeldHellIdle; +extern Fl_Spinner *valHellXmtWidth; extern Fl_Group *tabOlivia; extern Fl_Choice *mnuOlivia_Tones; extern Fl_Choice *mnuOlivia_Bandwidth; diff --git a/src/include/configuration.h b/src/include/configuration.h index f066383e..91d84160 100644 --- a/src/include/configuration.h +++ b/src/include/configuration.h @@ -73,7 +73,7 @@ struct configuration { double HELL_BW; bool HellRcvWidth; bool HellBlackboard; - bool HellXmtWidth; + int HellXmtWidth; bool HellXmtIdle; bool HellPulseFast; // OLIVIA diff --git a/src/include/fftfilt.h b/src/include/fftfilt.h index cf17a909..c4216d7c 100644 --- a/src/include/fftfilt.h +++ b/src/include/fftfilt.h @@ -25,7 +25,7 @@ public: fftfilt(double f1, double f2, int len); ~fftfilt(); void create_filter(double f1, double f2); - int run(complex in, complex **out); + int run(const complex& in, complex **out); }; #endif diff --git a/src/include/filters.h b/src/include/filters.h index d7af2de2..98bac0ad 100644 --- a/src/include/filters.h +++ b/src/include/filters.h @@ -131,7 +131,7 @@ private: public: sfft(int len, int first, int last); ~sfft(); - complex *run(complex input); + complex *run(const complex& input); }; diff --git a/src/include/htmlstrings.h b/src/include/htmlstrings.h new file mode 100644 index 00000000..304c9142 --- /dev/null +++ b/src/include/htmlstrings.h @@ -0,0 +1,31 @@ +// ---------------------------------------------------------------------------- +// +// htmlstrings.h +// +// Copyright (C) 2008 +// Dave Freese, W1HKJ +// +// This file is part of fldigi. +// +// fldigi is free software; you can redistribute it and/or modify +// it under the terms of the GNU General Public License as published by +// the Free Software Foundation; either version 2 of the License, or +// (at your option) any later version. +// +// fldigi is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// GNU General Public License for more details. +// +// You should have received a copy of the GNU General Public License +// along with fldigi; if not, write to the Free Software +// Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA +// ---------------------------------------------------------------------------- + +#ifndef HTMLSTRINGS_H +#define HTMLSTRINGS_H + +extern char szBeginner[]; +extern char szAbout[]; + +#endif diff --git a/src/include/qrunner.h b/src/include/qrunner.h index 40256ef7..f8e62e3e 100644 --- a/src/include/qrunner.h +++ b/src/include/qrunner.h @@ -87,16 +87,16 @@ struct nop class qrunner { public: - qrunner(size_t npri_ = 1); + qrunner(); ~qrunner(); void attach(void); void detach(void); template - bool request(const F &f, size_t pri = 0) + bool request(const F& f) { - if (fifo->push(f, pri)) { + if (fifo->push(f)) { #ifdef NDEBUG if (unlikely(write(pfd[1], "", 1) != 1)) throw qexception(errno); @@ -113,13 +113,13 @@ public: } template - bool request_sync(const F &f, size_t pri = 0) + bool request_sync(const F& f) { if (!attached) - return request(f, pri); + return request(f); for (;;) { - if (request(f, pri)) + if (request(f)) break; sched_yield(); } @@ -128,7 +128,7 @@ public: fsignal s(&m, &c); fl_lock(&m); for (;;) { - if (request(s, pri)) + if (request(s)) break; sched_yield(); } @@ -141,14 +141,12 @@ public: static void execute(int fd, void *arg); void flush(void); - size_t nprio(void) { return fifo->queues(); } - void drop(size_t pri) { fifo->drop(pri); } - size_t size(size_t pri) { return fifo->size(pri); } + void drop(void) { fifo->drop(); } + size_t size(void) { return fifo->size(); } protected: fqueue *fifo; int pfd[2]; - size_t npri; bool attached; public: bool drop_flag; diff --git a/src/include/thor.h b/src/include/thor.h index 87bb9078..5ab863e7 100644 --- a/src/include/thor.h +++ b/src/include/thor.h @@ -137,7 +137,7 @@ protected: unsigned char symbolpair[2]; private: - complex mixer(int n, complex in); + complex mixer(int n, const complex& in); // Rx void recvchar(int c); diff --git a/src/main.cxx b/src/main.cxx index 043a565f..a3ba3919 100644 --- a/src/main.cxx +++ b/src/main.cxx @@ -135,7 +135,7 @@ int main(int argc, char ** argv) SET_THREAD_ID(FLMAIN_TID); for (int i = 0; i < NUM_QRUNNER_THREADS; i++) { - cbq[i] = new qrunner(1); + cbq[i] = new qrunner; cbq[i]->attach(); } diff --git a/src/misc/configuration.cxx b/src/misc/configuration.cxx index 66785171..9c0543a9 100644 --- a/src/misc/configuration.cxx +++ b/src/misc/configuration.cxx @@ -78,7 +78,7 @@ configuration progdefaults = { 150.0, // double HELL_BW; false, // bool HellRcvWidth; false, // bool HellBlackboard; - false, // bool HellXmtWidth; + 1, // bool HellXmtWidth; true, // bool HellXmtIdle; false, // bool HellPulseFast; // OLIVIA @@ -420,7 +420,7 @@ void configuration::writeDefaultsXML() writeXMLint(f, "FELDFONTNBR", feldfontnbr); writeXMLbool(f, "HELLRCVWIDTH", HellRcvWidth); - writeXMLbool(f, "HELLXMTWIDTH", HellXmtWidth); + writeXMLint(f, "HELLXMTWIDTH", HellXmtWidth); writeXMLbool(f, "HELLBLACKBOARD", HellBlackboard); writeXMLbool(f, "HELLPULSEFAST", HellPulseFast); writeXMLbool(f, "HELLXMTIDLE", HellXmtIdle); diff --git a/src/mt63/mt63.cxx b/src/mt63/mt63.cxx index ed62fc97..72874e18 100644 --- a/src/mt63/mt63.cxx +++ b/src/mt63/mt63.cxx @@ -53,6 +53,8 @@ void mt63::rx_init() escape = 0; } +double peak = 0.0; + int mt63::tx_process() { int c; @@ -69,6 +71,8 @@ int mt63::tx_process() if (stopflag && flush-- == 0) { stopflag = false; Tx->SendJam(); + for (int i = 0; i < Tx->Comb.Output.Len; i++) + Tx->Comb.Output.Data[i] /= 0.8; ModulateXmtr((Tx->Comb.Output.Data), Tx->Comb.Output.Len); cwid(); return -1; /* we're done */ @@ -82,10 +86,14 @@ int mt63::tx_process() if (c > 127) { c &= 127; Tx->SendChar(127); + for (int i = 0; i < Tx->Comb.Output.Len; i++) + Tx->Comb.Output.Data[i] /= 0.8; ModulateXmtr((Tx->Comb.Output.Data), Tx->Comb.Output.Len); } Tx->SendChar(c); + for (int i = 0; i < Tx->Comb.Output.Len; i++) + Tx->Comb.Output.Data[i] /= 0.8; ModulateXmtr((Tx->Comb.Output.Data), Tx->Comb.Output.Len); return 0; diff --git a/src/olivia/olivia.cxx b/src/olivia/olivia.cxx index 2c4462d7..daa46b74 100644 --- a/src/olivia/olivia.cxx +++ b/src/olivia/olivia.cxx @@ -255,7 +255,7 @@ int olivia::rx_process(const double *buf, int len) double s2n = 20.0 * log10(snr < 0.1 ? 0.1 : snr); - snprintf(msg1, sizeof(msg1), "s/n %4.1f", s2n);//Rx->SignalToNoiseRatio()); + snprintf(msg1, sizeof(msg1), "s/n %4.1f dB", s2n); put_Status1(msg1); snprintf(msg2, sizeof(msg2), "Freq: %+4.1f", Rx->FrequencyOffset()); put_Status2(msg2); @@ -272,11 +272,10 @@ void olivia::restart() tones = progdefaults.oliviatones; bw = progdefaults.oliviabw; samplerate = 8000; -// samplerate = 11025; Tx->Tones = 2 * (1 << tones); Tx->Bandwidth = 125 * (1 << bw); - Tx->SampleRate = samplerate; //8000.0; //samplerate; + Tx->SampleRate = samplerate; Tx->OutputSampleRate = samplerate; txbasefreq = get_txfreq_woffset(); @@ -300,8 +299,8 @@ void olivia::restart() if (txfbuffer) delete [] txfbuffer; txfbuffer = new double[txbufferlen]; - rxbufferlen = 0; //SCBLOCKSIZE; - rxbuffer = 0; //new short int[rxbufferlen]; + rxbufferlen = 0; + rxbuffer = 0; Rx->Tones = Tx->Tones; Rx->Bandwidth = Tx->Bandwidth; @@ -309,7 +308,7 @@ void olivia::restart() Rx->SyncIntegLen = sinteg; Rx->SyncThreshold = progStatus.sqlonoff ? progStatus.sldrSquelchValue : 0.0; - Rx->SampleRate = samplerate; // 8000.0;//samplerate; + Rx->SampleRate = samplerate; Rx->InputSampleRate = samplerate; if (reverse) { @@ -326,8 +325,6 @@ void olivia::restart() } fragmentsize = 1024; set_bandwidth(Tx->Bandwidth); - -// Rx->PrintParameters(); put_MODEstatus(mode); } @@ -344,7 +341,6 @@ olivia::olivia() txbuffer = 0; txfbuffer = 0; rxbuffer = 0; -// samplerate = 11025; samplerate = 8000; FL_LOCK(); @@ -353,7 +349,6 @@ olivia::olivia() FL_UNLOCK(); mode = MODE_OLIVIA; -// wfid = new id(this); smargin = progdefaults.oliviasmargin; sinteg = progdefaults.oliviasinteg; lastfreq = 0; @@ -367,6 +362,5 @@ olivia::~olivia() if (txbuffer) delete [] txbuffer; if (txfbuffer) delete [] txfbuffer; if (rxbuffer) delete [] rxbuffer; -// if (wfid) delete wfid; } diff --git a/src/qrunner/fqueue.h b/src/qrunner/fqueue.h index 8e89153b..5ffb6b01 100644 --- a/src/qrunner/fqueue.h +++ b/src/qrunner/fqueue.h @@ -58,113 +58,61 @@ class fqueue typedef ringbuffer fqueue_ringbuffer_t; public: - fqueue(size_t count = 2048, size_t nqueues_ = 1, size_t blocksize_ = 128) - : nqueues(nqueues_), blocksize(blocksize_) + fqueue(size_t count = 2048, size_t blocksize_ = 128) + : blocksize(blocksize_) { - rb = new fqueue_ringbuffer_t*[nqueues]; - for (size_t i = 0; i < nqueues; i++) - rb[i] = new fqueue_ringbuffer_t(blocksize * count); + rb = new fqueue_ringbuffer_t(blocksize * count); } ~fqueue() { - for (size_t i = 0; i < nqueues; i++) { - drop(i); - delete rb[i]; - } - delete [] rb; + drop(); + delete rb; } - bool empty(size_t q) - { - if (q != nqueues) - return rb[q]->read_space() == 0; - - for (size_t i = 0; i < nqueues; i++) - if (rb[i]->read_space() > 0) - return false; - return true; - } - bool empty(void) { return empty(nqueues); } - - bool full(size_t q) - { - if (q != nqueues) - return rb[q]->write_space() == 0; - - for (size_t i = 0; i < nqueues; i++) - if (rb[i]->write_space() > 0) - return false; - return true; - } - - size_t size(size_t q) - { - if (q != nqueues) - return rb[q]->read_space() / blocksize; - - size_t n = 0; - for (size_t i = 0; i < nqueues; i++) - n += rb[i]->read_space() / blocksize; - return n; - } - size_t size(void) { return size(nqueues); } - - size_t queues(void) { return nqueues; } + bool empty(void) { return rb->read_space() == 0; } + bool full(void) { return rb->write_space() == 0; } + size_t size(void) { return rb->read_space() / blocksize; } template - bool push(const T &t, size_t q) + bool push(const T& t) { // If we have any space left at all, it will be at least // a blocksize. It will not wrap around the end of the rb. - rb[q]->get_wv(wvec); - if (unlikely(wvec[0].len < blocksize)) + if (unlikely(rb->get_wv(wvec, blocksize) < blocksize)) return false; assert(blocksize >= sizeof(func_wrap)); // we assume a no-throw ctor! new (wvec[0].buf) func_wrap(t); - rb[q]->write_advance(blocksize); + rb->write_advance(blocksize); return true; } - bool pop(size_t q, bool exec = false) + bool pop(bool exec = false) { - size_t start, end; - if (q != nqueues) // pull from named queue - start = end = q; - else { // pull first available element - start = 0; - end = nqueues - 1; - } + if (rb->get_rv(rvec, blocksize) < blocksize) + return false; + reinterpret_cast(rvec[0].buf)->destroy(exec); + rb->read_advance(blocksize); - for (size_t i = start; i <= end; i++) { - rb[i]->get_rv(rvec); - if (rvec[0].len < blocksize) - continue; - reinterpret_cast(rvec[0].buf)->destroy(exec); - rb[i]->read_advance(blocksize); - - return true; - } - - return false; + return true; } - bool execute(void) { return pop(nqueues, true); } + bool execute(void) { return pop(true); } - size_t drop(size_t q) + size_t drop(void) { size_t n = 0; - while (pop(q, false)) + while (pop(false)) ++n; return n; } protected: - fqueue_ringbuffer_t **rb; + fqueue_ringbuffer_t* rb; fqueue_ringbuffer_t::vector_type rvec[2], wvec[2]; - size_t nqueues, blocksize; + size_t blocksize; }; #endif // FQUEUE_H_ diff --git a/src/qrunner/qrunner.cxx b/src/qrunner/qrunner.cxx index 3f02a1d1..0786ed65 100644 --- a/src/qrunner/qrunner.cxx +++ b/src/qrunner/qrunner.cxx @@ -34,10 +34,10 @@ #include "fqueue.h" #include "qrunner.h" -qrunner::qrunner(size_t npri_) - : npri(npri_), attached(false), drop_flag(false) +qrunner::qrunner() + : attached(false), drop_flag(false) { - fifo = new fqueue(2048, npri); + fifo = new fqueue(2048); #ifndef __CYGWIN__ if (pipe(pfd) == -1) #else diff --git a/src/thor/thor.cxx b/src/thor/thor.cxx index eb55a3ff..1033fb7d 100644 --- a/src/thor/thor.cxx +++ b/src/thor/thor.cxx @@ -245,7 +245,7 @@ thor::thor(trx_mode md) //===================================================================== // rx modules -complex thor::mixer(int n, complex in) +complex thor::mixer(int n, const complex& in) { complex z; double f; @@ -258,7 +258,7 @@ complex thor::mixer(int n, complex in) f = THORFIRSTIF - THORBASEFREQ - bandwidth/2 + (samplerate / symlen) * (1.0 * n / paths); z.re = cos(phase[n]); z.im = sin(phase[n]); - z = z * in; + z *= in; phase[n] -= twopi * f / samplerate; if (phase[n] > M_PI) phase[n] -= twopi; diff --git a/src/throb/throb.cxx b/src/throb/throb.cxx index d7003fe5..a00a3100 100644 --- a/src/throb/throb.cxx +++ b/src/throb/throb.cxx @@ -77,7 +77,6 @@ throb::~throb() if (outbuf) delete[] outbuf; for (int i = 0; i < num_tones; i++) if (rxtone[i]) delete [] rxtone[i]; -// if (wfid) delete wfid; } void throb::flip_syms() //call this whenever a space or idle is sent or received @@ -231,7 +230,6 @@ throb::throb(trx_mode throb_mode) : modem() syncpos = 0.5; scope_data = new double [SCOPE_DATA_LEN]; -// wfid = new id(this); phaseacc = 0.0; metric = 0.0; diff --git a/src/waterfall/waterfall.cxx b/src/waterfall/waterfall.cxx index 1d98675e..68fa29eb 100644 --- a/src/waterfall/waterfall.cxx +++ b/src/waterfall/waterfall.cxx @@ -626,7 +626,8 @@ void WFdisp::update_waterfall() { RGBI *p3, *p4; p1 = tmp_fft_db + offset; p3 = fft_img; - + short* limit = tmp_fft_db + image_area - step + 1; + for (int row = 0; row < image_height; row++) { p2 = p1; p4 = p3; @@ -635,38 +636,38 @@ void WFdisp::update_waterfall() { for (int col = 0; col < disp_width; col++) { *(p4++) = mag2RGBI[ (*p2+ *(p2+1)+ *(p2+2)+ *(p2+3))/4 ]; p2 += step; - if (p2 > tmp_fft_db + image_area - step + 1) break; + if (p2 > limit) break; } else if (step == 2) for (int col = 0; col < disp_width; col++) { *(p4++) = mag2RGBI[ (*p2 + *(p2+1))/2 ]; p2 += step; - if (p2 > tmp_fft_db + image_area - step + 1) break; + if (p2 > limit) break; } else for (int col = 0; col < disp_width; col++) { *(p4++) = mag2RGBI[ *p2 ]; p2 += step; - if (p2 > tmp_fft_db + image_area - step + 1) break; + if (p2 > limit) break; } } else { if (step == 4) for (int col = 0; col < disp_width; col++) { *(p4++) = mag2RGBI[ MAX( MAX ( MAX ( *p2, *(p2+1) ), *(p2+2) ), *(p2+3) ) ]; p2 += step; - if (p2 > tmp_fft_db + image_area - step + 1) break; + if (p2 > limit) break; } else if (step == 2) for (int col = 0; col < disp_width; col++) { *(p4++) = mag2RGBI[ MAX( *p2, *(p2+1) ) ]; p2 += step; - if (p2 > tmp_fft_db + image_area - step + 1) break; + if (p2 > limit) break; } else for (int col = 0; col < disp_width; col++) { *(p4++) = mag2RGBI[ *p2 ]; p2 += step; - if (p2 > tmp_fft_db + image_area - step + 1) break; + if (p2 > limit) break; } } p1 += IMAGE_WIDTH; diff --git a/src/widgets/FTextView.cxx b/src/widgets/FTextView.cxx index 98190b9d..75a1cba3 100644 --- a/src/widgets/FTextView.cxx +++ b/src/widgets/FTextView.cxx @@ -642,6 +642,8 @@ FTextEdit::FTextEdit(int x, int y, int w, int h, const char *l) context_menu = edit_menu; change_keybindings(); + ascii_cnt = 0; + ascii_chr = 0; } /// Handles fltk events for this widget. @@ -908,12 +910,13 @@ int FTextEdit::handle_key(int key) if (key >= FL_F && key <= FL_F_Last && insert_position() >= txpos) return handle_key_macro(key); - // read A/M-ddd, where d is a digit, as ascii characters (in base 10) - // and insert verbatim; e.g. M-001 inserts a - if (Fl::event_state() & FL_CTRL && isdigit(key) && + // read ctl-ddd, where d is a digit, as ascii characters (in base 10) + // and insert verbatim; e.g. ctl-001 inserts a + if (Fl::event_state() & FL_CTRL && (key >= FL_KP + '0') && (key <= FL_KP + '9') && insert_position() >= txpos) return handle_key_ascii(key); - + ascii_cnt = 0; // restart the numeric keypad entries. + ascii_chr = 0; // do not insert printable characters in the transmitted text if (insert_position() < txpos) { int d; @@ -953,16 +956,13 @@ int FTextEdit::handle_key_macro(int key) /// int FTextEdit::handle_key_ascii(int key) { - static char ascii_cnt = 0; - static unsigned ascii_chr = 0; - - key -= '0'; + key -= (FL_KP + '0'); ascii_cnt++; for (int i = 0; i < 3 - ascii_cnt; i++) key *= 10; ascii_chr += key; if (ascii_cnt == 3) { - if (ascii_chr <= 0x7F) + if (ascii_chr < 0x100) //0x7F) add(ascii_chr, (iscntrl(ascii_chr) ? CTRL : RECV)); ascii_cnt = ascii_chr = 0; }