diff --git a/ChangeLog b/ChangeLog index fee1a037..b99ff6e0 100644 --- a/ChangeLog +++ b/ChangeLog @@ -9,6 +9,18 @@ Change Log: 7) Added PSKmail tab and control to allow disabling the automatic return to the PSK sweet spot if running a mail server 8) Added "Save To" menu item on received text popup menu. + 9) Added relative sizing of Rx / Tx text widgets to state memory + 10) Added hidden Menus "Test / Capture / Generate / Playback" + Capture - captures current audio input stream to file "capture.snd" + Generate - sends current audio output stream to file "generate.snd" + Playback - reads audio stream from file "playback.snd" in lieu of + the audio sound card + These provide the ability to make repetitive tests of various modems + by playing back a known audio stream. + If you capture an audio stream and then copy the file to playback.snd + you can then play that audio stream back. The stream will loop repitively + until the playback is turned off. + The three menu items, Capture, Generate and Playback are all toggle menu items. 1.34 1) Cleaned up unused code segments 2) Modified CW decoder to allow setting upper and lower limits on Tx WPM diff --git a/INSTALL b/INSTALL deleted file mode 100644 index eff40b3b..00000000 --- a/INSTALL +++ /dev/null @@ -1,46 +0,0 @@ -A single makefile is used to create various compile strategies for fldigi - - make - builds fldigi with hamlib support - - make clean - removes all vestiges of prior builds - - make CFG=hamlib-debug - builds fldigi with hamlib support and gdb debug information - - make CFG=hamlib-local - builds fldigi with hamlib support and fltk_jpeg, fltk_png and - fltk_z compiled into the fltk library - - make CFG=nhl - builds fldigi without hamlib support - - make CFG=nhl-debug - builds fldigi without hamlib supoort but with gdb debug - information - - make CFG=nhl-local - builds fldigi without hamlib support but with fltk_jpeg, fltk_png - and fltk_z compiled into the fltk library - -All make's place the object files in ./Objects and the target executable -in ./Install - -The ./Install directory also contains icons suitable for both desktop and -menu use. - -Copy the executable file fldigi to a directory that your shell can routinely -access for executable files. I have a ~/bin directory that holds all of my -local executables. - -If you plan on using fldigi with pskmail then you should create a separate -directory with a single file in it to start: - o PSKmailclient, or PSKmailserver, depending on your desired pskmail - service. - o then you should execute Fldigi from this directory, preferably from - a terminal window - -After first use you will find a $HOME/.fldigi directory created with -all of the files needed for fldigi to run and be configured. - diff --git a/src/config.h b/src/config.h index 5b2bbe0c..8f3cd018 100644 --- a/src/config.h +++ b/src/config.h @@ -25,7 +25,7 @@ #ifndef _CONFIG_H #define _CONFIG_H -// You can change the width of the waterfall / spectrum display by modifying this +// You can change the x1 width of the waterfall / spectrum display by modifying this // constant. // Suggest that you make the value a multiple of 100. // DO NOT EXCEED 4000 @@ -34,5 +34,58 @@ #define IMAGE_WIDTH 3000 +// widget sizes internal to the waterfall widget +#define BEZEL 2 +#define WFTEXT 10 +#define WFSCALE 10 +#define WFMARKER 6 +#define BTN_HEIGHT 20 + +// use the following for EmComm minimal footprint +//#define Hwfall 120 +//#define WMINIMUM (Hwfall + 580) +//#define HNOM 450 // do not make smaller than 400 +//#define WNOM WMINIMUM + +// use the following for the original fldigi waterfall sizing +#define Hwfall 140 +#define WMINIMUM (IMAGE_WIDTH / 4 + Hwfall - BTN_HEIGHT) +#define HNOM 570 +#define WNOM WMINIMUM + + +#define bwColor 30 +#define bwFFT 30 +#define bwX1 30 +#define bwMov 20 +#define cwCnt 100 +#define cwRef 50 +#define cwMode 85 +#define bwQsy 45 +#define bwRate 45 +#define bwXmtLock 45 +#define bwRev 45 +#define bwXmtRcv 45 +#define wSpace 2 + +#define Hmenu 22 +#define Hqsoframe 48 +#define Hnotes 22 +#define Hstatus 22 +#define Hmacros 22 + +#define Htext (HNOM - 4 - Hwfall - Hmenu - Hstatus - Hmacros - Hqsoframe - Hnotes) +#define Hxmttxt (Htext) / 4 +#define Hrcvtxt (Htext - (Hxmttxt)) + +#define Wwfall (WNOM - Hwfall + BTN_HEIGHT + 2 * BEZEL) +#define Wmode 80 +#define Ws2n 100 +#define Wimd 100 +#define Wwarn 16 +#define bwAfcOnOff (Hwfall -22)/2 +#define bwSqlOnOff (Hwfall -22)/2 + +#define Wstatus (WNOM - Wmode - Ws2n - Wimd - Wwarn - bwAfcOnOff - bwSqlOnOff) #endif diff --git a/src/dialogs/fl_digi.cxx b/src/dialogs/fl_digi.cxx index 4d9e07bb..e2c168b8 100644 --- a/src/dialogs/fl_digi.cxx +++ b/src/dialogs/fl_digi.cxx @@ -30,12 +30,10 @@ #include #include #include -#include #include "version.h" #include "waterfall.h" -#include "raster.h" #include "main.h" #include "threads.h" #include "trx.h" @@ -80,7 +78,6 @@ cMixer mixer; Fl_Button *btnTune = (Fl_Button *)0; Fl_Tile *TiledGroup = (Fl_Tile *)0; -//Fl_Group *TiledGroup = (Fl_Group *)0; TextView *ReceiveText=(TextView *)0; TextEdit *TransmitText=(TextEdit *)0; Fl_Text_Buffer *rcvBuffer = (Fl_Text_Buffer *)0; @@ -118,7 +115,6 @@ bool altMacros = false; bool bSaveFreqList = false; string strMacroName[10]; - waterfall *wf = (waterfall *)0; Digiscope *digiscope = (Digiscope *)0; Fl_Slider *sldrSquelch = (Fl_Slider *)0; @@ -662,6 +658,31 @@ void cb_mnuConfigModems(Fl_Menu_*, void*) { dlgConfig->show(); } +bool capval = false; +void cb_mnuCapture(Fl_Menu_ *m, void *d) +{ + if (!scard) return; + capval = !capval; + scard->Capture(capval); +} + +bool genval = false; +void cb_mnuGenerate(Fl_Menu_ *m, void *d) +{ + if (!scard) return; + genval = !genval; + scard->Generate(genval); +} + +bool playval = false; +void cb_mnuPlayback(Fl_Menu_ *m, void *d) +{ + if (!scard) return; + playval = !playval; + scard->Playback(playval); +} + + void cb_FontBrowser(Font_Browser*, void* v) { Font_Browser *ft= (Font_Browser*)v; @@ -987,10 +1008,15 @@ Fl_Menu_Item menu_[] = { {" ", 0, 0, 0, FL_MENU_INACTIVE, FL_NORMAL_LABEL, 0, 14, 0}, // 57 {"Rig", 0, (Fl_Callback*)cb_mnuRig, 0, 0, FL_NORMAL_LABEL, 0, 14, 0}, // 58 {" ", 0, 0, 0, FL_MENU_INACTIVE, FL_NORMAL_LABEL, 0, 14, 0}, // 59 -{"Help", 0, 0, 0, FL_SUBMENU, FL_NORMAL_LABEL, 0, 14, 0}, // 60 -{"About", 0, (Fl_Callback*)cb_mnuAbout, 0, 0, FL_NORMAL_LABEL, 0, 14, 0}, // 61 -{0,0,0,0,0,0,0,0,0}, // 62 -{0,0,0,0,0,0,0,0,0}, // 63 +{"Test", 0, 0, 0, FL_SUBMENU, FL_NORMAL_LABEL, 0, 14, 0}, // 60 +{"Capture", 0, (Fl_Callback*)cb_mnuCapture, 0, FL_MENU_TOGGLE, FL_NORMAL_LABEL, 0, 14, 0}, // 61 +{"Generate", 0, (Fl_Callback*)cb_mnuGenerate, 0, FL_MENU_TOGGLE, FL_NORMAL_LABEL, 0, 14, 0}, // 62 +{"Playback", 0, (Fl_Callback*)cb_mnuPlayback, 0, FL_MENU_TOGGLE, FL_NORMAL_LABEL, 0, 14, 0}, // 63 +{0,0,0,0,0,0,0,0,0}, // 64 +{"Help", 0, 0, 0, FL_SUBMENU, FL_NORMAL_LABEL, 0, 14, 0}, // 65 +{"About", 0, (Fl_Callback*)cb_mnuAbout, 0, 0, FL_NORMAL_LABEL, 0, 14, 0}, // 66 +{0,0,0,0,0,0,0,0,0}, // 67 +{0,0,0,0,0,0,0,0,0}, // 68 }; Fl_Menu_Bar *mnu; @@ -1009,6 +1035,16 @@ void activate_rig_menu_item(bool b) mnu->redraw(); } +void activate_test_menu_item(bool b) +{ + if (b) + menu_[60].show(); + else + menu_[60].hide(); + mnu->redraw(); +} + + void create_fl_digi_main() { int Y = 0; fl_digi_main = new Fl_Double_Window(WNOM, HNOM, "fldigi"); @@ -1076,14 +1112,16 @@ void create_fl_digi_main() { int sw = 15; Fl_Group *MixerFrame = new Fl_Group(0,Y,sw, Hrcvtxt + Hxmttxt); - valRcvMixer = new Fl_Slider(0, Y, sw, (Hrcvtxt + Hxmttxt)/2 - 15, "R"); +// valRcvMixer = new Fl_Slider(0, Y, sw, (Htext)/2 - 15, "R"); + valRcvMixer = new Fl_Slider(0, Y, sw, (Htext)/2, ""); valRcvMixer->type(FL_VERT_NICE_SLIDER); valRcvMixer->color(fl_rgb_color(0,110,30)); valRcvMixer->labeltype(FL_ENGRAVED_LABEL); valRcvMixer->selection_color(fl_rgb_color(255,255,0)); valRcvMixer->range(1.0,0.0); valRcvMixer->callback( (Fl_Callback *)cb_RcvMixer); - valXmtMixer = new Fl_Slider(0, Y + (Hrcvtxt + Hxmttxt)/2, sw, (Hrcvtxt + Hxmttxt)/2 - 15, "T"); +// valXmtMixer = new Fl_Slider(0, Y + (Htext)/2, sw, (Htext)/2 - 15, "T"); + valXmtMixer = new Fl_Slider(0, Y + (Htext)/2, sw, (Htext)/2, ""); valXmtMixer->type(FL_VERT_NICE_SLIDER); valXmtMixer->color(fl_rgb_color(110,0,30)); valXmtMixer->labeltype(FL_ENGRAVED_LABEL); @@ -1094,9 +1132,8 @@ void create_fl_digi_main() { valXmtMixer->deactivate(); MixerFrame->end(); - Fl_Tile *TiledGroup = new Fl_Tile(sw, Y, WNOM-sw, Hrcvtxt + Hxmttxt); -// Fl_Group *TiledGroup = new Fl_Group(sw, Y, WNOM-sw, Hrcvtxt + Hxmttxt); - Fl_Box *minbox = new Fl_Box(sw,Y + 66, WNOM-sw, Hxmttxt + Hrcvtxt - 66 - 32); + Fl_Tile *TiledGroup = new Fl_Tile(sw, Y, WNOM-sw, Htext); + Fl_Box *minbox = new Fl_Box(sw,Y + 66, WNOM-sw, Htext - 66 - 32); minbox->hide(); ReceiveText = new TextView(sw, Y, WNOM-sw, Hrcvtxt, ""); @@ -1141,19 +1178,23 @@ void create_fl_digi_main() { wfpack->type(1); wf = new waterfall(0, Y, Wwfall, Hwfall); wf->end(); - Fl_Pack *ypack = new Fl_Pack(WNOM-(Hwfall-22), Y, Hwfall-22, Hwfall); + int Wscope = Hwfall - BTN_HEIGHT - 2 * BEZEL; + Fl_Pack *ypack = new Fl_Pack( WNOM - Wscope, Y, + Wscope, Hwfall); ypack->type(0); - digiscope = new Digiscope (WNOM-(Hwfall-22), Y, Hwfall-22, Hwfall-22); - + digiscope = new Digiscope ( WNOM - Wscope, Y, + Wscope, + Wscope); pgrsSquelch = new Fl_Progress( - WNOM-(Hwfall-22), Y + Hwfall - 22, - Hwfall - 22, 10, ""); + WNOM - Wscope, Y + Wscope, + Wscope, (BTN_HEIGHT + 2*BEZEL) / 2, ""); pgrsSquelch->color(FL_BACKGROUND2_COLOR, FL_DARK_GREEN); + sldrSquelch = new Fl_Slider( FL_HOR_NICE_SLIDER, - WNOM-(Hwfall-22), Y + Hwfall - 12, - Hwfall - 22, 12, ""); + WNOM - Wscope, Y + Wscope + BEZEL + (BTN_HEIGHT + 2*BEZEL) / 2, + Wscope, (BTN_HEIGHT + 2*BEZEL) / 2, ""); sldrSquelch->minimum(0); sldrSquelch->maximum(100); @@ -1167,7 +1208,7 @@ void create_fl_digi_main() { Fl_Group::current()->resizable(wf); wfpack->end(); Y += (Hwfall + 2); - + Fl_Pack *hpack = new Fl_Pack(0, Y, WNOM, Hstatus); hpack->type(1); MODEstatus = new Fl_Button(0,Hmenu+Hrcvtxt+Hxmttxt+Hwfall, Wmode, Hstatus, ""); @@ -1237,7 +1278,6 @@ void display_metric(double metric) void put_cwRcvWPM(double wpm) { -// if (!prgsCWrcvWPM) return; int U = progdefaults.CWupperlimit; int L = progdefaults.CWlowerlimit; double dWPM = 100.0*(wpm - L)/(U - L); diff --git a/src/include/fl_digi.h b/src/include/fl_digi.h index 937986dc..176484ef 100644 --- a/src/include/fl_digi.h +++ b/src/include/fl_digi.h @@ -37,9 +37,12 @@ #include #include #include +#include + #include "combo.h" #include "TextView.h" +#include "raster.h" #include "waterfall.h" #include "digiscope.h" #include "globals.h" @@ -50,6 +53,8 @@ extern cMixer mixer; extern TextView *ReceiveText; extern TextEdit *TransmitText; +extern Raster *FHdisp; +extern Fl_Tile *TiledGroup; extern Fl_Text_Buffer *rcvBuffer; extern Fl_Text_Buffer *xmtBuffer; extern Fl_Box *StatusBar; @@ -78,9 +83,6 @@ extern Fl_Slider *valXmtMixer; extern bool altMacros; -//extern Fl_Browser *ReceiveText; -//extern Fl_Browser *TransmitText; - extern waterfall *wf; extern Digiscope *digiscope; @@ -88,6 +90,7 @@ extern Digiscope *digiscope; extern void create_fl_digi_main(); extern Fl_Menu_Item menu_[]; extern void activate_rig_menu_item(bool b); +extern void activate_test_menu_item(bool b); extern void put_freq(double frequency); extern void put_Bandwidth(int bandwidth); diff --git a/src/include/main.h b/src/include/main.h index d495cc93..e3a92040 100644 --- a/src/include/main.h +++ b/src/include/main.h @@ -21,30 +21,6 @@ #include "rigclass.h" #endif -#define Hmenu 24 -#define Hqsoframe 48 -#define Hnotes 24 -#define Hrcvtxt 200 -#define Hxmttxt 100 -//#define Hrcvtxt 160 -//#define Hxmttxt 100 -#define Hwfall 140 -//#define Hwfall 118 -#define Hstatus 22 -#define Hmacros 24 -#define Wmode 80 -#define Ws2n 100 -#define Wimd 100 -#define Wwarn 16 -#define bwAfcOnOff (Hwfall -22)/2 -#define bwSqlOnOff (Hwfall -22)/2 - -#define Wwfall 754 -//#define Wwfall 654 -#define HNOM (Hwfall + Hxmttxt + Hrcvtxt + Hmenu + (Hstatus + 4) + Hmacros + Hqsoframe + Hnotes) -#define WNOM (Wwfall + Hwfall - 22) -#define Wstatus (WNOM - Wmode - Ws2n - Wimd - Wwarn - bwAfcOnOff - bwSqlOnOff) - extern Fl_Mutex trx_mutex; extern Fl_Cond trx_cond; @@ -55,6 +31,7 @@ extern string HomeDir; extern string PskMailDir; extern string xmlfname; extern bool gmfskmail; +extern bool testmenu; extern std::string scDevice; extern PTT *push2talk; diff --git a/src/include/sound.h b/src/include/sound.h index baf25cbf..333d68d6 100644 --- a/src/include/sound.h +++ b/src/include/sound.h @@ -16,6 +16,7 @@ #include #include +#include #include #include "samplerate/samplerate.h" @@ -28,6 +29,8 @@ #define SND_BUF_LEN 65536 //#define SRC_BUF_LEN (8*SND_BUF_LEN) +using namespace std; + class SndException { public: char szError[80]; @@ -58,6 +61,10 @@ private: int rxppm; int mode; bool formatok; + + bool capture; + bool playback; + bool generate; void getVersion(); void getCapabilities(); @@ -77,10 +84,19 @@ private: float *snd_buffer; float *src_buffer; unsigned char *cbuff; + + ofstream ofGenerate; + ofstream ofCapture; + fstream ifPlayback; + + void writeGenerate(double *buff, int count); + void writeCapture(double *buff, int count); + int readPlayback(double *buff, int count); + public: cSound(const char *dev = "/dev/dsp"); ~cSound(); - int Open(int mode, int freq = 8000); + int Open(int mode, int freq = 8000, int nchan = 2); void Close(); int Write(unsigned char *, int); int write_samples(double *, int); @@ -95,6 +111,10 @@ public: int Channels() { return channels;}; int Format() { return play_format;}; bool FormatOK() { return formatok;}; + + void Capture(bool on); + void Playback(bool on); + void Generate(bool on); }; #endif diff --git a/src/include/status.h b/src/include/status.h index 51a30671..ba2cedd5 100644 --- a/src/include/status.h +++ b/src/include/status.h @@ -17,6 +17,7 @@ struct status { int mainY; int mainW; int mainH; + int RxTextHeight; bool rigShown; int rigX; int rigY; diff --git a/src/include/version.h b/src/include/version.h index b0483d91..fd892c30 100644 --- a/src/include/version.h +++ b/src/include/version.h @@ -1,6 +1,6 @@ #ifndef _VERSION_H #define _VERSION_H -#define FLDIGI_VERSION "1.35J" +#define FLDIGI_VERSION "1.35L" #endif diff --git a/src/include/waterfall.h b/src/include/waterfall.h index 170cdf34..6fc2482e 100644 --- a/src/include/waterfall.h +++ b/src/include/waterfall.h @@ -15,7 +15,7 @@ * You should have received a copy of the GNU Library General Public * License along with this library; if not, write to the * Free Software Foundation, Inc., 59 Temple Place - Suite 330, - * Boston, MA 02111-1307, USA. + * Boston, MA 02111-1307, USA. * Please report all bugs and problems to "w1hkj@w1hkj.com". */ @@ -24,10 +24,10 @@ #include #include -#include +#include #include "config.h" - + #include "complex.h" #include "fft.h" #include "sound.h" @@ -36,15 +36,15 @@ #include #include #include -#include +#include #include #include -#include -#include -#include +#include +#include +#include #include -/* +/* #ifdef HAVE_DFFTW_H # include #endif @@ -53,37 +53,15 @@ #endif */ -// recommended minimum size for the control is width = 504, height = 104; -// the actual waterfall will be width -4 (bezel size) and -// height - 4 - 24 (bezel, text, scale & marker) - +// recommended minimum size for the control is width = 504, height = 104; +// the actual waterfall will be width -4 (bezel size) and +// height - 4 - 24 (bezel, text, scale & marker) + //#define FFT_LEN 2048 #define FFT_LEN 4096 #define SC_SMPLRATE 8000 - -#define BEZEL 2 -#define WFTEXT 10 -#define WFSCALE 10 -#define WFMARKER 6 -#define BTN_HEIGHT 20 - -#define bwColor 35 -#define bwFFT 35 -#define bwX1 25 -#define bgX14 75 -#define bwMov 20 -#define bgMov 60 -#define cwCnt 120 -#define cwRef 60 -#define cwMode 85 -#define bwQsy 45 -#define bwRate 45 -#define bwXmtLock 45 -#define bwRev 45 -#define bwXmtRcv 60 -#define wSpace 4 - -#define fftabs(a,b) sqrt((a)*(a) + (b)*(b)) + +#define fftabs(a,b) sqrt((a)*(a) + (b)*(b)) struct RGB { uchar R; @@ -96,19 +74,19 @@ struct RGBint { int G; int B; }; - -struct RGBI { - uchar R; - uchar G; + +struct RGBI { + uchar R; + uchar G; uchar B; - uchar I; -}; + uchar I; +}; extern RGBI mag2RGBI[256]; -extern RGB palette[9]; - -class WFdisp : public Fl_Widget { -public: +extern RGB palette[9]; + +class WFdisp : public Fl_Widget { +public: enum WFmode { WATERFALL, SPECTRUM, @@ -121,48 +99,48 @@ enum WFmode { enum WFspeed {FAST = 1, NORMAL = 2, SLOW = 4}; - WFdisp (int x, int y, int w, int h, char *lbl = 0); - ~WFdisp (); + WFdisp (int x, int y, int w, int h, char *lbl = 0); + ~WFdisp (); int wfmag(); - void Mode(WFmode M) { - mode = M; - } - WFmode Mode() { - return mode; + void Mode(WFmode M) { + mode = M; + } + WFmode Mode() { + return mode; } int cursorFreq(int xpos) { return (offset + step * xpos); - } - void DispColor(bool Y) { - dispcolor = Y; - } - bool DispColor() { - return dispcolor; - } - void Ampspan(double AmpSpn) { + } + void DispColor(bool Y) { + dispcolor = Y; + } + bool DispColor() { + return dispcolor; + } + void Ampspan(double AmpSpn) { ampspan = (int)AmpSpn; - update_fft_db(); - } - double Ampspan() { - return ampspan; - } - void Reflevel(double RefLev) { + update_fft_db(); + } + double Ampspan() { + return ampspan; + } + void Reflevel(double RefLev) { reflevel = (int)RefLev; - update_fft_db(); - } - double Reflevel() { - return reflevel; - } - void Bandwidth (int bw) { - bandwidth = bw; + update_fft_db(); + } + double Reflevel() { + return reflevel; + } + void Bandwidth (int bw) { + bandwidth = bw; makeMarker(); - } - int Bandwidth () { - return bandwidth; - } - void Overload(int ovr) { - if (overload == ovr) return; - overload = ovr; + } + int Bandwidth () { + return bandwidth; + } + void Overload(int ovr) { + if (overload == ovr) return; + overload = ovr; } WFspeed Speed() { return wfspeed;} void Speed(WFspeed rate) { wfspeed = rate;} @@ -170,17 +148,17 @@ enum WFspeed {FAST = 1, NORMAL = 2, SLOW = 4}; void initmaps(); void draw(); // void resize (int, int, int, int); - void update_sigmap(); - void update_waterfall(); - void checkoffset(); - void slew(int); - void movetocenter(); - void carrier(int cf); - int carrier(); + void update_sigmap(); + void update_waterfall(); + void checkoffset(); + void slew(int); + void movetocenter(); + void carrier(int cf); + int carrier(); void makeMarker(); void process_analog(double *sig, int len); void processFFT(); - void sig_data( double *sig, int len ); + void sig_data( double *sig, int len ); void rfcarrier(long long f) { rfc = f; } @@ -211,92 +189,92 @@ enum WFspeed {FAST = 1, NORMAL = 2, SLOW = 4}; void defaultColors(); private: - int disp_width; + int disp_width; int image_width; int scale_width; int RGBwidth; - int RGBsize; - int image_height; - int image_area; + int RGBsize; + int image_height; + int image_area; int sig_image_area; int mag; int magset; WFmode mode; bool overload; - bool usb; + bool usb; long long rfc; - bool usebands; - int offset; + bool usebands; + int offset; int sigoffset; - int step; - int carrierfreq; + int step; + int carrierfreq; int bandwidth; int wfspdcnt; int dispcnt; int ampspan; int reflevel; double dfreq; - bool centercarrier; + bool centercarrier; bool dispcolor; bool cursormoved; WFspeed wfspeed; int srate; RGBI *fft_img; -// RGBI mag2RGBI[256]; +// RGBI mag2RGBI[256]; RGB *markerimage; RGB RGBmarker; RGB RGBcursor; double *fftout; - uchar *scaleimage; - uchar *fft_sig_img; - uchar *sig_img; + uchar *scaleimage; + uchar *fft_sig_img; + uchar *sig_img; uchar *scline; short int *fft_hist; short int *fft_db; double *circbuff; - double *pwr; + double *pwr; Cfft *wfft; int checkMag(); - void checkWidth(); - void initMarkers(); - void makeScale(); - void drawScale(); - void drawMarker(); + void checkWidth(); + void initMarkers(); + void makeScale(); + void drawScale(); + void drawMarker(); int log2disp(int v); void update_fft_db(); - void drawcolorWF(); - void drawgrayWF(); - void drawspectrum(); + void drawcolorWF(); + void drawgrayWF(); + void drawspectrum(); void drawsignal(); protected: public: bool wantcursor; int cursorpos; }; - -class waterfall: public Fl_Group { - friend void x1_cb(Fl_Widget *w, void* v); - friend void bwclr_cb(Fl_Widget *w, void * v); + +class waterfall: public Fl_Group { + friend void x1_cb(Fl_Widget *w, void* v); + friend void bwclr_cb(Fl_Widget *w, void * v); // friend void slew_cb(Fl_Widget *w, void * v); - friend void slew_left(Fl_Widget *w, void * v); - friend void slew_right(Fl_Widget *w, void * v); - friend void center_cb(Fl_Widget *w, void *v); - friend void carrier_cb(Fl_Widget *w, void *v); - friend void mode_cb(Fl_Widget *w, void *v); - friend void reflevel_cb(Fl_Widget *w, void *v); + friend void slew_left(Fl_Widget *w, void * v); + friend void slew_right(Fl_Widget *w, void * v); + friend void center_cb(Fl_Widget *w, void *v); + friend void carrier_cb(Fl_Widget *w, void *v); + friend void mode_cb(Fl_Widget *w, void *v); + friend void reflevel_cb(Fl_Widget *w, void *v); friend void ampspan_cb(Fl_Widget *w, void *v); friend void qsy_cb(Fl_Widget *w, void *v); - friend void rate_cb(Fl_Widget *w, void *v); -public: - waterfall(int x, int y, int w, int h, char *lbl= 0); + friend void rate_cb(Fl_Widget *w, void *v); +public: + waterfall(int x, int y, int w, int h, char *lbl= 0); ~waterfall(){}; void opmode(); void sig_data(double *sig, int len){ wfdisp->sig_data(sig, len); - } + } void Overload(bool ovr) { wfdisp->Overload(ovr); } @@ -341,20 +319,20 @@ public: wfdisp->useBands(!on); } - + int handle(int event); /* */ Fl_Button *btnRev; -private: - Fl_Box *bezel; - WFdisp *wfdisp; +private: + Fl_Box *bezel; + WFdisp *wfdisp; Fl_Button *bwclr; - Fl_Button *mode; + Fl_Button *mode; Fl_Button *x1; Fl_Button *left; Fl_Button *center; - Fl_Button *right; + Fl_Button *right; Fl_Counter *wfcarrier; Fl_Counter *wfRefLevel; Fl_Counter *wfAmpSpan; @@ -364,7 +342,7 @@ private: Fl_Light_Button *xmtlock; int buttonrow; bool reverse; -protected: -}; - +protected: +}; + #endif diff --git a/src/main.cxx b/src/main.cxx index 3060ca39..a2f2bbba 100644 --- a/src/main.cxx +++ b/src/main.cxx @@ -54,7 +54,7 @@ string PskMailFile; string HomeDir; string xmlfname; -bool gmfskmail = false; +bool testmenu = false; PTT *push2talk = (PTT *)0; #ifndef NOHAMLIB @@ -63,6 +63,7 @@ Rig *xcvr = (Rig *)0; cLogfile *logfile = 0;; +bool gmfskmail = false; cLogfile *Maillogfile = (cLogfile *)0; FILE *server; FILE *client; @@ -127,9 +128,16 @@ int main(int argc, char ** argv) { Fl::visual(FL_RGB); // insure 24 bit color operation fl_register_images(); Fl::set_fonts(0); - + + if (argc == 2) + if (strcasecmp(argv[1], "TEST") == 0) + testmenu = true; + rigcontrol = createRigDialog(); create_fl_digi_main(); + + activate_test_menu_item(testmenu); + createConfig(); macros.loadDefault(); @@ -144,11 +152,7 @@ int main(int argc, char ** argv) { progdefaults.btnRTSDTRis, progdefaults.btnPTTREVis ); - if (argc == 2) - scDevice = argv[1]; - else - scDevice = progdefaults.SCdevice; - + scDevice = progdefaults.SCdevice; trx_start(scDevice.c_str()); progdefaults.initInterface(); diff --git a/src/misc/status.cxx b/src/misc/status.cxx index 8c0a8737..9e7f9d7f 100644 --- a/src/misc/status.cxx +++ b/src/misc/status.cxx @@ -26,6 +26,7 @@ status progStatus = { 0, // int mainY; WNOM, // int mainW; HNOM, // int mainH; + Hrcvtxt, // int RxTextHeight; false, // bool rigShown; 0, // int rigX; 0, // int rigY; @@ -43,6 +44,7 @@ void status::saveLastState() mainY = fl_digi_main->y(); mainW = fl_digi_main->w(); mainH = fl_digi_main->h(); + RxTextHeight = ReceiveText->h(); if (rigcontrol) if (rigcontrol->visible()) { rigShown = rigcontrol->visible(); @@ -60,6 +62,7 @@ void status::saveLastState() deffile << rigShown << endl; deffile << rigX << endl; deffile << rigY << endl; + deffile << RxTextHeight << endl; deffile.close(); } @@ -77,6 +80,7 @@ void status::initLastState() deffile >> rigShown; deffile >> rigX; deffile >> rigY; + deffile >> RxTextHeight; deffile.close(); } trx_mode m = (trx_mode) lastmode; @@ -118,7 +122,23 @@ void status::initLastState() active_modem->set_freq(progdefaults.RTTYsweetspot); else active_modem->set_freq(progdefaults.PSKsweetspot); + +//std::cout << ReceiveText->h() << std::endl; +//std::cout << RxTextHeight << std::endl; + + int X, Y, W, H, Yx, Hx; + X = ReceiveText->x(); + Y = ReceiveText->y(); + W = ReceiveText->w(); + H = ReceiveText->h(); + Yx = TransmitText->y(); + Hx = TransmitText->h(); + + ReceiveText->resize(X,Y,W,RxTextHeight); + FHdisp->resize(X,Y,W,RxTextHeight); + TransmitText->resize(X, Y + RxTextHeight, W, H + Hx - RxTextHeight); +// TiledGroup->position( 0, ReceiveText->h(), 0, RxTextHeight); fl_digi_main->resize(mainX, mainY, mainW, mainH); if (rigShown == true) { if (!rigcontrol) diff --git a/src/psk/psk.cxx b/src/psk/psk.cxx index 6e2d22a4..7906284f 100644 --- a/src/psk/psk.cxx +++ b/src/psk/psk.cxx @@ -283,6 +283,7 @@ void psk::searchUp() void psk::afc() { double error, ftest, sigpwr, noise; + static int cntdown = 0; if (mailserver && progdefaults.PSKmailSweetSpot) ftest = wf->peakFreq((int)progdefaults.PSKsweetspot, (int) bandwidth); else @@ -292,6 +293,7 @@ void psk::afc() // fast search for peak signal frequency if (sigsearch) { freqerr = 0.0; + cntdown = 16; if (sigpwr/noise > 2.0) {//afcthreshold) { if (!mailserver || (mailserver && !progdefaults.PSKmailSweetSpot) || (mailserver && (fabs(progdefaults.PSKsweetspot - ftest) < 15))) { @@ -311,11 +313,14 @@ void psk::afc() error += 2 * M_PI; if (error > M_PI / 2) error -= 2 * M_PI; - error *= ((samplerate / (symbollen * 2 * M_PI)/16)); - freqerr = decayavg( freqerr, error, 8);//32); + if (cntdown > 0) cntdown--; + if (cntdown) + freqerr = decayavg( freqerr, error * ((samplerate / (symbollen * 2 * M_PI)/16)), 2); + else + freqerr = decayavg( freqerr, error * ((samplerate / (symbollen * 2 * M_PI)/16)), 16); frequency -= freqerr; set_freq (frequency); -//sprintf(phasemsg,"%5.4f %8.2f", freqerr, frequency); +//sprintf(phasemsg,"%5.4f %5.4f %8.2f", error, freqerr, frequency); //put_status(phasemsg); } else if (mailserver && progdefaults.PSKmailSweetSpot) sigsearch = 3; @@ -323,8 +328,6 @@ void psk::afc() void psk::rx_symbol(complex symbol) { -// double phase, error; -// int bits, n; int n; phase = (prevsymbol % symbol).arg(); prevsymbol = symbol; diff --git a/src/soundcard/sound.cxx b/src/soundcard/sound.cxx index 17ae8f18..cb9456b1 100644 --- a/src/soundcard/sound.cxx +++ b/src/soundcard/sound.cxx @@ -3,10 +3,13 @@ cSound::cSound(const char *dev ) { device = dev; + capture = playback = generate = false; + tx_src_state = 0; tx_src_data = 0; rx_src_state = 0; rx_src_data = 0; + cbuff = 0; snd_buffer = 0; src_buffer = 0; txppm = progdefaults.TX_corr; @@ -24,46 +27,6 @@ cSound::cSound(const char *dev ) { << " <" << device.c_str() << ">" << std::endl; } - - try { - int err; - snd_buffer = new float [2*SND_BUF_LEN]; //new float[SND_BUF_LEN]; - src_buffer = new float [2*SND_BUF_LEN]; //new float[SND_BUF_LEN]; - cbuff = new unsigned char [4 * SND_BUF_LEN]; //new unsigned char [2 * SND_BUF_LEN]; - if (!snd_buffer || !src_buffer || !cbuff) - throw("Cannot create src buffers"); -// for (int i = 0; i < SND_BUF_LEN; i++) - for (int i = 0; i < 2*SND_BUF_LEN; i++) - snd_buffer[i] = src_buffer[i] = 0.0; -// for (int i = 0; i < 2 * SND_BUF_LEN; i++) - for (int i = 0; i < 4 * SND_BUF_LEN; i++) - cbuff[i] = 0; - - tx_src_data = new SRC_DATA; - rx_src_data = new SRC_DATA; - if (!tx_src_data || !rx_src_data) - throw("Cannot create source data structures"); - -// rx_src_state = src_new(SRC_SINC_FASTEST, 1, &err); - rx_src_state = src_new(SRC_SINC_FASTEST, 2, &err); - if (rx_src_state == 0) - throw(src_strerror(err)); - -// tx_src_state = src_new(SRC_SINC_FASTEST, 1, &err); - tx_src_state = src_new(SRC_SINC_FASTEST, 2, &err); - if (tx_src_state == 0) - throw(src_strerror(err)); - - rx_src_data->src_ratio = 1.0/(1.0 + rxppm/1e6); - src_set_ratio ( rx_src_state, 1.0/(1.0 + rxppm/1e6)); - - tx_src_data->src_ratio = 1.0 + txppm/1e6; - src_set_ratio ( tx_src_state, 1.0 + txppm/1e6); - } - catch (SndException){ - exit(1); - }; - } cSound::~cSound() @@ -76,6 +39,13 @@ cSound::~cSound() if (rx_src_data) delete rx_src_data; if (rx_src_state) src_delete (rx_src_state); if (tx_src_state) src_delete (tx_src_state); + tx_src_state = 0; + tx_src_data = 0; + rx_src_state = 0; + rx_src_data = 0; + cbuff = 0; + snd_buffer = 0; + src_buffer = 0; } void cSound::setfragsize() @@ -95,7 +65,7 @@ void cSound::setfragsize() throw errno; } -int cSound::Open(int md, int freq) +int cSound::Open(int md, int freq, int nchan) { mode = md; try { @@ -103,14 +73,57 @@ int cSound::Open(int md, int freq) if (device_fd == -1) throw SndException(errno); Format(AFMT_S16_LE); // default: 16 bit little endian -// Channels(1); // 1 channel - Channels(2); // 2 channels - Frequency(freq); + Channels(nchan); // 2 channels is default + Frequency(freq); // 8000 Hz is default setfragsize(); } catch (...) { throw; } + + if (cbuff) delete [] cbuff; + if (snd_buffer) delete [] snd_buffer; + if (src_buffer) delete [] src_buffer; + if (tx_src_data) delete tx_src_data; + if (rx_src_data) delete rx_src_data; + if (rx_src_state) src_delete (rx_src_state); + if (tx_src_state) src_delete (tx_src_state); + + try { + int err; + snd_buffer = new float [channels * SND_BUF_LEN]; + src_buffer = new float [channels * SND_BUF_LEN]; + cbuff = new unsigned char [channels * 2 * SND_BUF_LEN]; + if (!snd_buffer || !src_buffer || !cbuff) + throw("Cannot create src buffers"); + for (int i = 0; i < channels * SND_BUF_LEN; i++) + snd_buffer[i] = src_buffer[i] = 0.0; + for (int i = 0; i < channels * 2 * SND_BUF_LEN; i++) + cbuff[i] = 0; + + tx_src_data = new SRC_DATA; + rx_src_data = new SRC_DATA; + if (!tx_src_data || !rx_src_data) + throw("Cannot create source data structures"); + + rx_src_state = src_new(SRC_SINC_FASTEST, channels, &err); + if (rx_src_state == 0) + throw(src_strerror(err)); + + tx_src_state = src_new(SRC_SINC_FASTEST, channels, &err); + if (tx_src_state == 0) + throw(src_strerror(err)); + + rx_src_data->src_ratio = 1.0/(1.0 + rxppm/1e6); + src_set_ratio ( rx_src_state, 1.0/(1.0 + rxppm/1e6)); + + tx_src_data->src_ratio = 1.0 + txppm/1e6; + src_set_ratio ( tx_src_state, 1.0 + txppm/1e6); + } + catch (SndException){ + exit(1); + }; + return device_fd; } @@ -256,7 +269,11 @@ int cSound::Read(double *buffer, int buffersize) rx_src_data->src_ratio = 1.0/(1.0 + rxppm/1e6); src_set_ratio ( rx_src_state, 1.0/(1.0 + rxppm/1e6)); } - if (rxppm == 0) + + if (capture) writeCapture( buffer, buffersize); + else if (playback) readPlayback( buffer, buffersize); + + if (rxppm == 0 || playback) return buffersize; // process using samplerate library @@ -285,6 +302,8 @@ int cSound::write_samples(double *buf, int count) short int *wbuff; unsigned char *p; + if (generate) writeGenerate( buf, count); + if (device_fd == -1 || count <= 0) return -1; @@ -345,6 +364,8 @@ int cSound::write_stereo(double *bufleft, double *bufright, int count) short int *wbuff; unsigned char *p; + if (generate) writeGenerate( bufleft, count ); + if (device_fd == -1 || count <= 0) return -1; @@ -355,7 +376,6 @@ int cSound::write_stereo(double *bufleft, double *bufright, int count) } if (txppm == 0) { - wbuff = new short int[count]; wbuff = new short int[2*count]; p = (unsigned char *)wbuff; for (int i = 0; i < count; i++) { @@ -403,3 +423,60 @@ int cSound::write_stereo(double *bufleft, double *bufright, int count) return retval; } + +void cSound::Capture(bool on) +{ + if (on) + ofCapture.open("capture.snd"); + else + ofCapture.close(); + capture = on; +} + +void cSound::Playback(bool on) +{ +// std::cout << "Playback " << on << endl; + if (on) { + ifPlayback.open("playback.snd", ios::in | ios::binary); + if (ifPlayback.is_open() == true) + playback = true; + return; + } else + ifPlayback.close(); + playback = false; +} + +void cSound::Generate(bool on) +{ + if (on) + ofGenerate.open("generate.snd"); + else + ofGenerate.close(); + generate = on; +} + +void cSound::writeGenerate(double *buff, int count) +{ + char *cbuff = (char *)buff; + ofGenerate.write(cbuff, count * sizeof(double) ); +} + +void cSound::writeCapture(double *buff, int count) +{ + char *cbuff = (char *)buff; + ofCapture.write(cbuff, count * sizeof(double) ); +} + +int cSound::readPlayback(double *buff, int count) +{ + char *cbuff = (char *)buff; + if (ifPlayback.eof() == true) { + ifPlayback.close(); + ifPlayback.open("playback.snd", ios::in | ios::binary); + } + ifPlayback.read(cbuff, count * sizeof(double) ); +// std::cout << count << " " << ifPlayback.tellg() << endl; + + return count; +} + diff --git a/src/waterfall/waterfall.cxx b/src/waterfall/waterfall.cxx index a0b3985d..7d25f4ca 100644 --- a/src/waterfall/waterfall.cxx +++ b/src/waterfall/waterfall.cxx @@ -973,54 +973,57 @@ bool waterfall::USB() { waterfall::waterfall(int x0, int y0, int w0, int h0, char *lbl) : Fl_Group(x0,y0,w0,h0,lbl) { - int xpos = x() + 4; + int xpos; - buttonrow = h() - BTN_HEIGHT + y(); + buttonrow = h() + y() - BTN_HEIGHT - BEZEL; bezel = new Fl_Box( FL_DOWN_BOX, x(), y(), w(), - h() - BTN_HEIGHT - 2, 0); + h() - BTN_HEIGHT - 2 * BEZEL, 0); wfdisp = new WFdisp(x() + BEZEL, y() + BEZEL, - w() - BEZEL - BEZEL, - h() - BEZEL - BEZEL - BTN_HEIGHT - 2); + w() - 2 * BEZEL, + h() - BTN_HEIGHT - 4 * BEZEL); wfdisp->tooltip("Click to set tracking point"); + xpos = x() + wSpace; bwclr = new Fl_Button(xpos, buttonrow, bwColor, BTN_HEIGHT, "clr"); bwclr->callback(bwclr_cb, 0); bwclr->tooltip("Color / BW waterfall"); - xpos = xpos + bwColor + wSpace; + xpos = xpos + bwColor + wSpace; mode = new Fl_Button(xpos, buttonrow, bwFFT, BTN_HEIGHT,"Wtr"); mode->callback(mode_cb, 0); mode->tooltip("Waterfall/FFT - Shift click for signal scope"); + xpos = xpos + bwFFT + wSpace; - x1 = new Fl_Button(xpos, buttonrow, bwX1, BTN_HEIGHT, "x1"); x1->callback(x1_cb, 0); x1->tooltip("Change scale"); - xpos = xpos + bwX1 + wSpace; + xpos = xpos + bwX1 + wSpace; wfrate = new Fl_Button(xpos, buttonrow, bwRate, BTN_HEIGHT, "Norm"); wfrate->callback(rate_cb, 0); wfrate->tooltip("Waterfall drop speed"); - xpos = xpos + bwRate + 2*wSpace; - + + xpos = xpos + bwRate + wSpace; left = new Fl_Repeat_Button(xpos, buttonrow, bwMov, BTN_HEIGHT, "@<"); left->callback(slew_left, 0); left->tooltip("Slew display lower in freq"); + xpos += bwMov; center = new Fl_Button(xpos, buttonrow, bwMov, BTN_HEIGHT, "@||"); center->callback(center_cb, 0); center->tooltip("Center display on signal"); + xpos += bwMov; right = new Fl_Repeat_Button(xpos, buttonrow, bwMov, BTN_HEIGHT, "@>"); right->callback(slew_right, 0); right->tooltip("Slew display higher in freq"); - xpos = xpos + bwMov + 2*wSpace; + xpos = xpos + bwMov + wSpace; wfcarrier = new Fl_Counter(xpos, buttonrow, cwCnt, BTN_HEIGHT ); wfcarrier->callback(carrier_cb, 0); wfcarrier->step(1.0); @@ -1029,8 +1032,8 @@ waterfall::waterfall(int x0, int y0, int w0, int h0, char *lbl) : wfcarrier->range(16.0, IMAGE_WIDTH - 16.0); wfcarrier->value(wfdisp->carrier()); wfcarrier->tooltip("Adjust selected tracking freq"); - xpos = xpos + cwCnt + 2*wSpace; - + + xpos = xpos + cwCnt + wSpace; wfRefLevel = new Fl_Counter(xpos, buttonrow, cwRef, BTN_HEIGHT ); wfRefLevel->callback(reflevel_cb, 0); wfRefLevel->step(1.0); @@ -1040,8 +1043,8 @@ waterfall::waterfall(int x0, int y0, int w0, int h0, char *lbl) : wfdisp->Reflevel(0.0); wfRefLevel->tooltip("Upper signal limit in dB"); wfRefLevel->type(FL_SIMPLE_COUNTER); - xpos = xpos + cwRef + 2*wSpace; - + + xpos = xpos + cwRef + wSpace; wfAmpSpan = new Fl_Counter(xpos, buttonrow, cwRef, BTN_HEIGHT ); wfAmpSpan->callback(ampspan_cb, 0); wfAmpSpan->step(1.0); @@ -1052,26 +1055,25 @@ waterfall::waterfall(int x0, int y0, int w0, int h0, char *lbl) : wfAmpSpan->tooltip("Signal range in dB"); wfAmpSpan->type(FL_SIMPLE_COUNTER); - xpos = xpos + cwRef + 2*wSpace; + xpos = xpos + cwRef + wSpace; qsy = new Fl_Button(xpos, buttonrow, bwQsy, BTN_HEIGHT, "QSY"); qsy->callback(qsy_cb, 0); qsy->tooltip("Cntr in Xcvr PB"); qsy->deactivate(); xpos = xpos + bwQsy + wSpace; - xmtlock = new Fl_Light_Button(xpos, buttonrow, bwXmtLock, BTN_HEIGHT, "Lck"); + xmtlock = new Fl_Light_Button(xpos, buttonrow, bwXmtLock, BTN_HEIGHT, "Lk"); xmtlock->callback(xmtlock_cb, 0); xmtlock->value(0); xmtlock->tooltip("Xmt freq locked"); + xpos = xpos + bwXmtLock + wSpace; - - btnRev = new Fl_Light_Button(xpos, buttonrow, bwRev, BTN_HEIGHT, "Rev"); + btnRev = new Fl_Light_Button(xpos, buttonrow, bwRev, BTN_HEIGHT, "Rv"); btnRev->callback(btnRev_cb, 0); btnRev->value(0); btnRev->tooltip("Reverse"); reverse = false; - xpos = w() - bwXmtRcv - wSpace; xmtrcv = new Fl_Light_Button(xpos, buttonrow, bwXmtRcv, BTN_HEIGHT, "T/R"); xmtrcv->callback(xmtrcv_cb, 0);