From 1f73b26d06e0a437783c6e2eec5442884dbad947 Mon Sep 17 00:00:00 2001 From: drowe67 Date: Tue, 21 Feb 2017 02:44:40 +0000 Subject: [PATCH] starting to instrument to further develop 700C. Added SNR field to channel settings, bar graphs for bit error counting on test frames, option to view 700C scatter before diversity combination, immediate switching of several options rather than when apply pressed git-svn-id: https://svn.code.sf.net/p/freetel/code@3041 01035d8c-6547-0410-b346-abe4f91aad63 --- freedv-dev/src/dlg_options.cpp | 40 +++++++++++- freedv-dev/src/dlg_options.h | 5 ++ freedv-dev/src/fdmdv2_main.cpp | 85 +++++++++++++++++--------- freedv-dev/src/fdmdv2_main.h | 8 +++ freedv-dev/src/fdmdv2_plot_scalar.cpp | 29 +++++++-- freedv-dev/src/fdmdv2_plot_scalar.h | 14 +++-- freedv-dev/src/fdmdv2_plot_scatter.cpp | 2 +- 7 files changed, 137 insertions(+), 46 deletions(-) diff --git a/freedv-dev/src/dlg_options.cpp b/freedv-dev/src/dlg_options.cpp index 9189feba..817027ec 100644 --- a/freedv-dev/src/dlg_options.cpp +++ b/freedv-dev/src/dlg_options.cpp @@ -45,9 +45,11 @@ OptionsDlg::OptionsDlg(wxWindow* parent, wxWindowID id, const wxString& title, c m_ckboxTestFrame->SetToolTip(_("Send frames of known bits instead of compressed voice")); sbSizer_testFrames->Add(m_ckboxTestFrame, 0, wxALIGN_LEFT, 0); - m_ckboxChannelNoise = new wxCheckBox(this, wxID_ANY, _("Channel Noise"), wxDefaultPosition, wxDefaultSize, wxCHK_2STATE); + m_ckboxChannelNoise = new wxCheckBox(this, wxID_ANY, _("Channel Noise SNR (dB):"), wxDefaultPosition, wxDefaultSize, wxCHK_2STATE); m_ckboxChannelNoise->SetToolTip(_("Add simulated AWGN channel noise to received signal")); sbSizer_testFrames->Add(m_ckboxChannelNoise, 0, wxALIGN_LEFT, 0); + m_txtNoiseSNR = new wxTextCtrl(this, wxID_ANY, wxEmptyString, wxDefaultPosition, wxSize(50,-1), 0, wxTextValidator(wxFILTER_DIGITS)); + sbSizer_testFrames->Add(m_txtNoiseSNR, 0, wxALIGN_LEFT, 0); bSizer30->Add(sbSizer_testFrames,0, wxALIGN_CENTER_HORIZONTAL|wxALL|wxEXPAND, 3); @@ -56,12 +58,15 @@ OptionsDlg::OptionsDlg(wxWindow* parent, wxWindowID id, const wxString& title, c //------------------------------ wxStaticBoxSizer* sbSizer_freedv700; - wxStaticBox *sb_freedv700 = new wxStaticBox(this, wxID_ANY, _("FreeDV 700 Clipping")); + wxStaticBox *sb_freedv700 = new wxStaticBox(this, wxID_ANY, _("FreeDV 700 Options")); sbSizer_freedv700 = new wxStaticBoxSizer(sb_freedv700, wxHORIZONTAL); - m_ckboxFreeDV700txClip = new wxCheckBox(this, wxID_ANY, _("Enable"), wxDefaultPosition, wxDefaultSize, wxCHK_2STATE); + m_ckboxFreeDV700txClip = new wxCheckBox(this, wxID_ANY, _("Clipping"), wxDefaultPosition, wxDefaultSize, wxCHK_2STATE); m_ckboxFreeDV700txClip->SetToolTip(_("Clip FreeDv 700 tx waveform to reduce Peak to Average Power Ratio (PAPR)")); sbSizer_freedv700->Add(m_ckboxFreeDV700txClip, 0, wxALIGN_LEFT, 0); + m_ckboxFreeDV700scatterCombine = new wxCheckBox(this, wxID_ANY, _("Scatter Combine"), wxDefaultPosition, wxDefaultSize, wxCHK_2STATE); + m_ckboxFreeDV700scatterCombine->SetToolTip(_("Upper and Lower carriers combined for Scatter diagram")); + sbSizer_freedv700->Add(m_ckboxFreeDV700scatterCombine, 0, wxALIGN_LEFT, 0); bSizer30->Add(sbSizer_freedv700,0, wxALIGN_CENTER_HORIZONTAL|wxALL|wxEXPAND, 3); @@ -192,7 +197,10 @@ OptionsDlg::OptionsDlg(wxWindow* parent, wxWindowID id, const wxString& title, c m_sdbSizer5Cancel->Connect(wxEVT_COMMAND_BUTTON_CLICKED, wxCommandEventHandler(OptionsDlg::OnCancel), NULL, this); m_sdbSizer5Apply->Connect(wxEVT_COMMAND_BUTTON_CLICKED, wxCommandEventHandler(OptionsDlg::OnApply), NULL, this); + m_ckboxTestFrame->Connect(wxEVT_COMMAND_CHECKBOX_CLICKED, wxScrollEventHandler(OptionsDlg::OnTestFrame), NULL, this); + m_ckboxChannelNoise->Connect(wxEVT_COMMAND_CHECKBOX_CLICKED, wxScrollEventHandler(OptionsDlg::OnChannelNoise), NULL, this); m_ckboxFreeDV700txClip->Connect(wxEVT_COMMAND_CHECKBOX_CLICKED, wxScrollEventHandler(OptionsDlg::OnFreeDV700txClip), NULL, this); + m_ckboxFreeDV700scatterCombine->Connect(wxEVT_COMMAND_CHECKBOX_CLICKED, wxScrollEventHandler(OptionsDlg::OnFreeDV700scatterCombine), NULL, this); event_in_serial = 0; event_out_serial = 0; @@ -211,7 +219,11 @@ OptionsDlg::~OptionsDlg() m_sdbSizer5OK->Disconnect(wxEVT_COMMAND_BUTTON_CLICKED, wxCommandEventHandler(OptionsDlg::OnOK), NULL, this); m_sdbSizer5Cancel->Disconnect(wxEVT_COMMAND_BUTTON_CLICKED, wxCommandEventHandler(OptionsDlg::OnCancel), NULL, this); m_sdbSizer5Apply->Disconnect(wxEVT_COMMAND_BUTTON_CLICKED, wxCommandEventHandler(OptionsDlg::OnApply), NULL, this); + + m_ckboxTestFrame->Disconnect(wxEVT_COMMAND_CHECKBOX_CLICKED, wxScrollEventHandler(OptionsDlg::OnTestFrame), NULL, this); + m_ckboxChannelNoise->Disconnect(wxEVT_COMMAND_CHECKBOX_CLICKED, wxScrollEventHandler(OptionsDlg::OnChannelNoise), NULL, this); m_ckboxFreeDV700txClip->Disconnect(wxEVT_COMMAND_CHECKBOX_CLICKED, wxScrollEventHandler(OptionsDlg::OnFreeDV700txClip), NULL, this); + m_ckboxFreeDV700scatterCombine->Disconnect(wxEVT_COMMAND_CHECKBOX_CLICKED, wxScrollEventHandler(OptionsDlg::OnFreeDV700scatterCombine), NULL, this); } @@ -227,6 +239,7 @@ void OptionsDlg::ExchangeData(int inout, bool storePersistent) m_txtCtrlCallSign->SetValue(wxGetApp().m_callSign); m_ckboxTestFrame->SetValue(wxGetApp().m_testFrames); m_ckboxChannelNoise->SetValue(wxGetApp().m_channel_noise); + m_txtNoiseSNR->SetValue(wxString::Format(wxT("%i"),wxGetApp().m_noise_snr)); m_ckbox_events->SetValue(wxGetApp().m_events); m_txt_spam_timer->SetValue(wxString::Format(wxT("%i"),wxGetApp().m_events_spam_timer)); @@ -246,6 +259,7 @@ void OptionsDlg::ExchangeData(int inout, bool storePersistent) m_ckboxEnableChecksum->SetValue(wxGetApp().m_enable_checksum); m_ckboxFreeDV700txClip->SetValue(wxGetApp().m_FreeDV700txClip); + m_ckboxFreeDV700scatterCombine->SetValue(wxGetApp().m_FreeDV700scatterCombine); } if(inout == EXCHANGE_DATA_OUT) @@ -253,6 +267,9 @@ void OptionsDlg::ExchangeData(int inout, bool storePersistent) wxGetApp().m_callSign = m_txtCtrlCallSign->GetValue(); wxGetApp().m_testFrames = m_ckboxTestFrame->GetValue(); wxGetApp().m_channel_noise = m_ckboxChannelNoise->GetValue(); + long noise_snr; + m_txtNoiseSNR->GetValue().ToLong(&noise_snr); + wxGetApp().m_noise_snr = (int)noise_snr; wxGetApp().m_events = m_ckbox_events->GetValue(); long spam_timer; @@ -284,6 +301,7 @@ void OptionsDlg::ExchangeData(int inout, bool storePersistent) wxGetApp().m_enable_checksum = m_ckboxEnableChecksum->GetValue(); wxGetApp().m_FreeDV700txClip = m_ckboxFreeDV700txClip->GetValue(); + wxGetApp().m_FreeDV700scatterCombine = m_ckboxFreeDV700scatterCombine->GetValue(); if (storePersistent) { pConfig->Write(wxT("/Data/CallSign"), wxGetApp().m_callSign); @@ -300,7 +318,12 @@ void OptionsDlg::ExchangeData(int inout, bool storePersistent) pConfig->Write(wxT("/UDP/enable"), wxGetApp().m_udp_enable); pConfig->Write(wxT("/UDP/port"), wxGetApp().m_udp_port); + pConfig->Write(wxT("/Events/spam_timer"), wxGetApp().m_events_spam_timer); + pConfig->Write(wxT("/FreeDV700/txClip"), wxGetApp().m_FreeDV700txClip); + pConfig->Write(wxT("/FreeDV700/scatterCombine"), wxGetApp().m_FreeDV700scatterCombine); + + pConfig->Write(wxT("/Noise/noise_snr"), wxGetApp().m_noise_snr); pConfig->Flush(); } @@ -345,12 +368,23 @@ void OptionsDlg::OnInitDialog(wxInitDialogEvent& event) ExchangeData(EXCHANGE_DATA_IN, false); } +void OptionsDlg::OnTestFrame(wxScrollEvent& event) { + wxGetApp().m_testFrames = m_ckboxTestFrame->GetValue(); +} + // immediately change flags rather using ExchangeData() so we can switch on and off at run time +void OptionsDlg::OnChannelNoise(wxScrollEvent& event) { + wxGetApp().m_channel_noise = m_ckboxChannelNoise->GetValue(); +} + void OptionsDlg::OnFreeDV700txClip(wxScrollEvent& event) { wxGetApp().m_FreeDV700txClip = m_ckboxFreeDV700txClip->GetValue(); } +void OptionsDlg::OnFreeDV700scatterCombine(wxScrollEvent& event) { + wxGetApp().m_FreeDV700scatterCombine = m_ckboxFreeDV700scatterCombine->GetValue(); +} void OptionsDlg::updateEventLog(wxString event_in, wxString event_out) { wxString event_in_with_serial, event_out_with_serial; diff --git a/freedv-dev/src/dlg_options.h b/freedv-dev/src/dlg_options.h index fe355ac2..6c83fef6 100644 --- a/freedv-dev/src/dlg_options.h +++ b/freedv-dev/src/dlg_options.h @@ -65,12 +65,17 @@ class OptionsDlg : public wxDialog void OnClose(wxCloseEvent& event); void OnInitDialog(wxInitDialogEvent& event); + void OnTestFrame(wxScrollEvent& event); + void OnChannelNoise(wxScrollEvent& event); void OnFreeDV700txClip(wxScrollEvent& event); + void OnFreeDV700scatterCombine(wxScrollEvent& event); wxTextCtrl *m_txtCtrlCallSign; // TODO: this should be renamed to tx_txtmsg, and rename all related incl persis strge wxCheckBox *m_ckboxTestFrame; wxCheckBox *m_ckboxChannelNoise; + wxTextCtrl *m_txtNoiseSNR; wxCheckBox *m_ckboxFreeDV700txClip; + wxCheckBox *m_ckboxFreeDV700scatterCombine; wxRadioButton *m_rb_textEncoding1; wxRadioButton *m_rb_textEncoding2; diff --git a/freedv-dev/src/fdmdv2_main.cpp b/freedv-dev/src/fdmdv2_main.cpp index 12be3b8b..72a3787b 100644 --- a/freedv-dev/src/fdmdv2_main.cpp +++ b/freedv-dev/src/fdmdv2_main.cpp @@ -394,6 +394,7 @@ MainFrame::MainFrame(wxString plugInName, wxWindow *parent) : TopFrame(plugInNam // Add Test Frame Errors window m_panelTestFrameErrorsHist = new PlotScalar((wxFrame*) m_auiNbookCtrl, 1, 1.0, 1.0/(2*FDMDV_NC_MAX), 0.0, 1.0, 1.0/FDMDV_NC_MAX, 0.1, "%3.2f", 0); m_auiNbookCtrl->AddPage(m_panelTestFrameErrorsHist, L"Test Frame Histogram", true, wxNullBitmap); + m_panelTestFrameErrorsHist->setBarGraph(1); } wxGetApp().m_framesPerBuffer = pConfig->Read(wxT("/Audio/framesPerBuffer"), PA_FPB); @@ -497,6 +498,8 @@ MainFrame::MainFrame(wxString plugInName, wxWindow *parent) : TopFrame(plugInNam wxGetApp().m_udp_port = (int)pConfig->Read(wxT("/UDP/port"), 3000); wxGetApp().m_FreeDV700txClip = (float)pConfig->Read(wxT("/FreeDV700/txClip"), t); + wxGetApp().m_FreeDV700scatterCombine = (float)pConfig->Read(wxT("/FreeDV700/scatterCombine"), t); + wxGetApp().m_noise_snr = (float)pConfig->Read(wxT("/Noise/noise_snr"), 2); int mode = pConfig->Read(wxT("/Audio/mode"), (long)0); if (mode == 0) @@ -710,6 +713,8 @@ MainFrame::~MainFrame() pConfig->Write(wxT("/Filter/SpkOutEQEnable"), wxGetApp().m_SpkOutEQEnable); pConfig->Write(wxT("/FreeDV700/txClip"), wxGetApp().m_FreeDV700txClip); + pConfig->Write(wxT("/FreeDV700/scatterCombine"), wxGetApp().m_FreeDV700scatterCombine); + pConfig->Write(wxT("/Noise/noise_snr"), wxGetApp().m_noise_snr); int mode; if (m_rb1600->GetValue()) @@ -989,19 +994,31 @@ void MainFrame::OnTimer(wxTimerEvent &evt) if ((freedv_get_mode(g_pfreedv) == FREEDV_MODE_700B) || (freedv_get_mode(g_pfreedv) == FREEDV_MODE_700C)) { - /* - FreeDV 700 uses diversity, so combine symbols for - scatter plot, as combined symbols are used for - demodulation. Note we need to use a copy of the - symbols, as we are not sure when the stats will be - updated. - */ - - COMP rx_symbols_copy[g_Nc/2]; - - for(c=0; cadd_new_samples_scatter(rx_symbols_copy); + if (wxGetApp().m_FreeDV700scatterCombine) { + m_panelScatter->setNc(g_Nc/2); /* m_FreeDV700scatterCombine may have changed at run time */ + + /* + FreeDV 700 uses diversity, so optionaly combine + symbols for scatter plot, as combined symbols are + used for demodulation. Note we need to use a copy + of the symbols, as we are not sure when the stats + will be updated. + */ + + COMP rx_symbols_copy[g_Nc/2]; + + for(c=0; cadd_new_samples_scatter(rx_symbols_copy); + } + else { + m_panelScatter->setNc(g_Nc); /* m_FreeDV700scatterCombine may have changed at run time */ + /* + Sometimes useful to plot carriers separately, e.g. to determine if tx carrier power is constant + across carriers. + */ + m_panelScatter->add_new_samples_scatter(&g_stats.rx_symbols[r][0]); + } } } @@ -1280,7 +1297,7 @@ void MainFrame::OnTimer(wxTimerEvent &evt) /* both modes map IQ to alternate bits, but one same carrier */ if (freedv_get_mode(g_pfreedv) == FREEDV_MODE_1600) { - /* FreeDV 1600 mapping from error pattern to bit on each carrier */ + /* FreeDV 1600 mapping from error pattern to two bits on each carrier */ for(b=0; b max_hist) + for(b=0; b max_hist) { max_hist = g_error_hist[b]; + } + } m_panelTestFrameErrorsHist->add_new_short_samples(0, g_error_hist, 2*FDMDV_NC_MAX, max_hist); } @@ -1315,9 +1334,13 @@ void MainFrame::OnTimer(wxTimerEvent &evt) } int max_hist = 0; - for(b=0; b max_hist) + for(b=0; b max_hist) { max_hist = g_error_hist[b]; + } + //printf("%4d ", g_error_hist[b]); + } + printf("\n"); m_panelTestFrameErrorsHist->add_new_short_samples(0, g_error_hist, 2*FDMDV_NC_MAX, max_hist); } @@ -2379,17 +2402,27 @@ void MainFrame::OnTogBtnOnOff(wxCommandEvent& event) if (m_rb1600->GetValue()) { g_mode = FREEDV_MODE_1600; g_Nc = 16; - m_panelScatter->setNc(g_Nc); + m_panelScatter->setNc(g_Nc+1); /* +1 for BPSK pilot */ } if (m_rb700b->GetValue()) { g_mode = FREEDV_MODE_700B; g_Nc = 14; - m_panelScatter->setNc(g_Nc/2-1); /* due to diversity, -1 due to no pilot like FreeDV 1600 */ + if (wxGetApp().m_FreeDV700scatterCombine) { + m_panelScatter->setNc(g_Nc/2); /* diversity combnation */ + } + else { + m_panelScatter->setNc(g_Nc); + } } if (m_rb700c->GetValue()) { g_mode = FREEDV_MODE_700C; g_Nc = 14; - m_panelScatter->setNc(g_Nc/2-1); /* due to diversity, -1 due to no pilot like FreeDV 1600 */ + if (wxGetApp().m_FreeDV700scatterCombine) { + m_panelScatter->setNc(g_Nc/2); /* diversity combnation */ + } + else { + m_panelScatter->setNc(g_Nc); + } } if (m_rb800xa->GetValue()) { g_mode = FREEDV_MODE_800XA; @@ -3660,15 +3693,7 @@ void per_frame_rx_processing( } if (g_channel_noise) { - float snr; - - /* enough noise to get a couple of % errors */ - - if (freedv_get_mode(g_pfreedv) == FREEDV_MODE_1600) - snr = 2.0; - else - snr = -1.0; - fdmdv_simulate_channel(&g_sig_pwr_av, rx_fdm, nin, snr); + fdmdv_simulate_channel(&g_sig_pwr_av, rx_fdm, nin, wxGetApp().m_noise_snr); } freq_shift_coh(rx_fdm_offset, rx_fdm, g_RxFreqOffsetHz, freedv_get_modem_sample_rate(g_pfreedv), &g_RxFreqOffsetPhaseRect, nin); nout = freedv_comprx(g_pfreedv, output_buf, rx_fdm_offset); diff --git a/freedv-dev/src/fdmdv2_main.h b/freedv-dev/src/fdmdv2_main.h index 43f4d0ff..8df6aadc 100644 --- a/freedv-dev/src/fdmdv2_main.h +++ b/freedv-dev/src/fdmdv2_main.h @@ -295,7 +295,15 @@ class MainApp : public wxApp int FilterEvent(wxEvent& event); MainFrame *frame; + // 700 options + bool m_FreeDV700txClip; + bool m_FreeDV700scatterCombine; + + // Noise simulation + + int m_noise_snr; + protected: }; diff --git a/freedv-dev/src/fdmdv2_plot_scalar.cpp b/freedv-dev/src/fdmdv2_plot_scalar.cpp index 7a07f46f..2336f605 100644 --- a/freedv-dev/src/fdmdv2_plot_scalar.cpp +++ b/freedv-dev/src/fdmdv2_plot_scalar.cpp @@ -61,6 +61,7 @@ PlotScalar::PlotScalar(wxFrame* parent, assert(strlen(a_fmt) < 15); strcpy(m_a_fmt, a_fmt); m_mini = mini; + bar_graph = 0; // work out number of samples we will store and allocate storage @@ -122,7 +123,6 @@ void PlotScalar::draw(wxAutoBufferedPaintDC& dc) float index_to_px; float a_to_py; int i; - int x, y; int prev_x, prev_y; float a; @@ -161,11 +161,10 @@ void PlotScalar::draw(wxAutoBufferedPaintDC& dc) // plot each channel - int offset; + int offset, x, y; for(offset=0; offset m_a_max) a = m_a_max; @@ -174,6 +173,10 @@ void PlotScalar::draw(wxAutoBufferedPaintDC& dc) y = m_rGrid.GetHeight() - a_to_py * a + m_a_min*a_to_py; + // regular point-point line graph + + x = index_to_px * i; + // put inside plot window if (!m_mini) { @@ -181,9 +184,23 @@ void PlotScalar::draw(wxAutoBufferedPaintDC& dc) y += PLOT_BORDER; } - if (i) - dc.DrawLine(x, y, prev_x, prev_y); - prev_x = x; prev_y = y; + if (bar_graph) { + // use points to make a bar graph + + int x1, x2, y1; + + x1 = index_to_px * ((float)i - 0.5); + x2 = index_to_px * ((float)i + 0.5); + y1 = m_rGrid.GetHeight(); + x1 += PLOT_BORDER + XLEFT_OFFSET; x2 += PLOT_BORDER + XLEFT_OFFSET; + y1 += PLOT_BORDER; + dc.DrawLine(x1, y1, x1, y); dc.DrawLine(x1, y, x2, y); dc.DrawLine(x2, y, x2, y1); + } + else { + if (i) + dc.DrawLine(x, y, prev_x, prev_y); + prev_x = x; prev_y = y; + } } } diff --git a/freedv-dev/src/fdmdv2_plot_scalar.h b/freedv-dev/src/fdmdv2_plot_scalar.h index 70439872..11c9f8e2 100644 --- a/freedv-dev/src/fdmdv2_plot_scalar.h +++ b/freedv-dev/src/fdmdv2_plot_scalar.h @@ -45,6 +45,7 @@ class PlotScalar: public PlotPanel ~PlotScalar(); void add_new_sample(int channel, float sample); void add_new_short_samples(int channel, short samples[], int length, float scale_factor); + void setBarGraph(int abar_graph) { bar_graph = abar_graph; } protected: @@ -59,14 +60,15 @@ class PlotScalar: public PlotPanel int m_mini; int m_samples; float *m_mem; + int bar_graph; // non zero to plot bar graphs - void draw(wxAutoBufferedPaintDC& dc); - void drawGraticule(wxAutoBufferedPaintDC& dc); - void OnPaint(wxPaintEvent& event); - void OnSize(wxSizeEvent& event); - void OnShow(wxShowEvent& event); + void draw(wxAutoBufferedPaintDC& dc); + void drawGraticule(wxAutoBufferedPaintDC& dc); + void OnPaint(wxPaintEvent& event); + void OnSize(wxSizeEvent& event); + void OnShow(wxShowEvent& event); - DECLARE_EVENT_TABLE() + DECLARE_EVENT_TABLE() }; #endif // __FDMDV2_PLOT_SCALAR__ diff --git a/freedv-dev/src/fdmdv2_plot_scatter.cpp b/freedv-dev/src/fdmdv2_plot_scatter.cpp index 12957f44..d7e88c70 100644 --- a/freedv-dev/src/fdmdv2_plot_scatter.cpp +++ b/freedv-dev/src/fdmdv2_plot_scatter.cpp @@ -60,7 +60,7 @@ PlotScatter::PlotScatter(wxFrame* parent) : PlotPanel(parent) // changing number of carriers changes number of symbols to plot void PlotScatter::setNc(int Nc) { - Nsym = Nc+1; + Nsym = Nc; assert(Nsym <= (MODEM_STATS_NC_MAX+1)); scatterMemSyms = ((int)(SCATTER_MEM_SECS*(Nsym/DT))); assert(scatterMemSyms <= SCATTER_MEM_SYMS_MAX); -- 2.25.1