dlg_comports.o \
dlg_options.o
-HDRS = fdmdv2_main.h fdmdv2_defines.h fdmdv2_plot.h fdmdv2_plot_scalar.h fdmdv2_plot_waterfall_linux.h fdmdv2_plot_scatter.h fdmdv2_plot_spectrum.h fdmdv2_pa_wrapper.h topFrame.h
+HDRS = fdmdv2_main.h fdmdv2_defines.h fdmdv2_plot.h fdmdv2_plot_scalar.h fdmdv2_plot_waterfall_linux.h fdmdv2_plot_scatter.h fdmdv2_plot_spectrum.h fdmdv2_pa_wrapper.h topFrame.h dlg_audiooptions.h
all: fdmdv2
dlg_comports.o \
dlg_options.o
-HDRS = fdmdv2_main.h fdmdv2_defines.h fdmdv2_plot.h fdmdv2_plot_scalar.h fdmdv2_plot_waterfall_linux.h fdmdv2_plot_scatter.h fdmdv2_plot_spectrum.h fdmdv2_pa_wrapper.h topFrame.h
+HDRS = fdmdv2_main.h fdmdv2_defines.h fdmdv2_plot.h fdmdv2_plot_scalar.h fdmdv2_plot_waterfall_linux.h fdmdv2_plot_scatter.h fdmdv2_plot_spectrum.h fdmdv2_pa_wrapper.h topFrame.h dlg_audiooptions.h
all: fdmdv2
#include "fdmdv2_main.h"
#include "dlg_audiooptions.h"
+// constants for test waveform plots
+
+#define TEST_WAVEFORM_X 100
+#define TEST_WAVEFORM_Y 100
+#define TEST_WAVEFORM_PLOT_TIME 2.0
+#define TEST_WAVEFORM_PLOT_FS 400
+#define TEST_BUF_SIZE 1024
+#define TEST_FS 48000.0
+#define TEST_DT 0.1 // time between plot updates in seconds
+#define TEST_WAVEFORM_PLOT_BUF ((int)(DT*400))
+
void AudioOptsDialog::Pa_Init(void)
{
m_isPaInitialized = false;
}
+void AudioOptsDialog::buildTestControls(PlotScalar **plotScalar, wxButton **btnTest, wxPanel *parentPanel, wxBoxSizer *bSizer)
+{
+ *btnTest = new wxButton(parentPanel, wxID_ANY, _("Test"), wxDefaultPosition, wxDefaultSize);
+ bSizer->Add(*btnTest, 0, wxALIGN_CENTER_VERTICAL|wxALL, 2);
+
+ wxPanel *panel = new wxPanel(parentPanel, wxID_ANY, wxDefaultPosition, wxSize(TEST_WAVEFORM_X, TEST_WAVEFORM_Y), 0);
+ *plotScalar = new PlotScalar((wxFrame*) panel, TEST_WAVEFORM_PLOT_TIME, 1.0/TEST_WAVEFORM_PLOT_FS, -1, 1, 1, 0.2, "", 1);
+ (*plotScalar)->SetClientSize(wxSize(TEST_WAVEFORM_X,TEST_WAVEFORM_Y));
+ bSizer->Add(panel, 0);
+}
+
//-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=--=-=-=-=
// AudioOptsDialog()
//-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=--=-=-=-=
m_staticText6->Wrap(-1);
bSizer811->Add(m_staticText6, 0, wxALIGN_CENTER_VERTICAL|wxALIGN_RIGHT|wxALL, 5);
m_cbSampleRateRxIn = new wxComboBox(m_panelRx, wxID_ANY, wxEmptyString, wxDefaultPosition, wxDefaultSize, 0, NULL, wxCB_DROPDOWN);
- bSizer811->Add(m_cbSampleRateRxIn, 0, wxALL, 2);
+ bSizer811->Add(m_cbSampleRateRxIn, 0, wxALIGN_CENTER_VERTICAL|wxALL, 2);
+
+ buildTestControls(&m_plotScalarRxIn, &m_btnRxInTest, m_panelRx, bSizer811);
+ /*
+ m_btnRxInTest = new wxButton(m_panelRx, wxID_ANY, _("Test"), wxDefaultPosition, wxDefaultSize);
+ bSizer811->Add(m_btnRxInTest, 0, wxALIGN_CENTER_VERTICAL|wxALL, 2);
+ m_panelRxInTest = new wxPanel(m_panelRx, wxID_ANY, wxDefaultPosition, wxSize(TEST_WAVEFORM_X, TEST_WAVEFORM_Y), 0);
+ m_plotScalarRxIn = new PlotScalar((wxFrame*) m_panelRxInTest, TEST_WAVEFORM_PLOT_TIME, 1.0/TEST_WAVEFORM_PLOT_FS, -1, 1, 1, 0.2, "", 1);
+ m_plotScalarRxIn->SetClientSize(wxSize(TEST_WAVEFORM_X,TEST_WAVEFORM_Y));
+ bSizer811->Add(m_panelRxInTest, 0);
+ */
+
sbSizer2->Add(bSizer811, 0, wxEXPAND, 5);
gSizer4->Add(sbSizer2, 1, wxEXPAND, 5);
m_listCtrlRxOutDevices->Connect( wxEVT_COMMAND_LIST_ITEM_SELECTED, wxListEventHandler( AudioOptsDialog::OnRxOutDeviceSelect ), NULL, this );
m_listCtrlTxInDevices->Connect( wxEVT_COMMAND_LIST_ITEM_SELECTED, wxListEventHandler( AudioOptsDialog::OnTxInDeviceSelect ), NULL, this );
m_listCtrlTxOutDevices->Connect( wxEVT_COMMAND_LIST_ITEM_SELECTED, wxListEventHandler( AudioOptsDialog::OnTxOutDeviceSelect ), NULL, this );
+
+ m_btnRxInTest->Connect( wxEVT_COMMAND_BUTTON_CLICKED, wxCommandEventHandler( AudioOptsDialog::OnRxInTest ), NULL, this );
+
m_btnRefresh->Connect( wxEVT_COMMAND_BUTTON_CLICKED, wxCommandEventHandler( AudioOptsDialog::OnRefreshClick ), NULL, this );
m_sdbSizer1Apply->Connect( wxEVT_COMMAND_BUTTON_CLICKED, wxCommandEventHandler( AudioOptsDialog::OnApplyAudioParameters ), NULL, this );
m_sdbSizer1Cancel->Connect( wxEVT_COMMAND_BUTTON_CLICKED, wxCommandEventHandler( AudioOptsDialog::OnCancelAudioParameters ), NULL, this );
m_listCtrlRxOutDevices->Disconnect(wxEVT_COMMAND_LIST_ITEM_SELECTED, wxListEventHandler(AudioOptsDialog::OnRxOutDeviceSelect), NULL, this);
m_listCtrlTxInDevices->Disconnect(wxEVT_COMMAND_LIST_ITEM_SELECTED, wxListEventHandler(AudioOptsDialog::OnTxInDeviceSelect), NULL, this);
m_listCtrlTxOutDevices->Disconnect(wxEVT_COMMAND_LIST_ITEM_SELECTED, wxListEventHandler(AudioOptsDialog::OnTxOutDeviceSelect), NULL, this);
+
+ m_btnRxInTest->Disconnect( wxEVT_COMMAND_BUTTON_CLICKED, wxCommandEventHandler( AudioOptsDialog::OnRxInTest ), NULL, this );
+
m_btnRefresh->Disconnect(wxEVT_COMMAND_BUTTON_CLICKED, wxCommandEventHandler(AudioOptsDialog::OnRefreshClick), NULL, this);
m_sdbSizer1Apply->Disconnect(wxEVT_COMMAND_BUTTON_CLICKED, wxCommandEventHandler(AudioOptsDialog::OnApplyAudioParameters), NULL, this);
m_sdbSizer1Cancel->Disconnect(wxEVT_COMMAND_BUTTON_CLICKED, wxCommandEventHandler(AudioOptsDialog::OnCancelAudioParameters), NULL, this);
int i, numSampleRates;
deviceInfo = Pa_GetDeviceInfo(devNum);
+ if (deviceInfo == NULL) {
+ printf("Pa_GetDeviceInfo(%d) failed!\n", devNum);
+ cbSampleRate->Clear();
+ return 0;
+ }
inputParameters.device = devNum;
inputParameters.channelCount = deviceInfo->maxInputChannels;
AUDIO_OUT);
}
+// opens a record device and plots the input speech for a few seconds. This is "modal" using
+// synchronous portaudio functions, so the GUI will not respond until after test sample has been
+// taken
+
+void AudioOptsDialog::plotDeviceInputForAFewSecs(int devNum, PlotScalar *plotScalar) {
+ PaStreamParameters inputParameters;
+ PaStream *stream = NULL;
+ PaError err;
+ short in48k_stereo_short[2*TEST_BUF_SIZE];
+ short in48k_short[TEST_BUF_SIZE];
+ short in8k_short[TEST_BUF_SIZE];
+ int numDevices, nBufs, i, j, src_error;
+ float t;
+ SRC_STATE *src;
+ FIFO *fifo;
+
+ // a basic sanity check
+ numDevices = Pa_GetDeviceCount();
+ if (devNum >= numDevices)
+ return;
+ if (devNum < 0)
+ return;
+ printf("devNum %d\n", devNum);
+
+ fifo = fifo_create((int)(DT*TEST_WAVEFORM_PLOT_FS*2)); assert(fifo != NULL);
+ src = src_new(SRC_SINC_FASTEST, 1, &src_error); assert(src != NULL);
+
+ inputParameters.device = devNum;
+ inputParameters.channelCount = 2;
+ inputParameters.sampleFormat = paInt16;
+ inputParameters.suggestedLatency = Pa_GetDeviceInfo( inputParameters.device )->defaultHighInputLatency;
+ inputParameters.hostApiSpecificStreamInfo = NULL;
+
+ nBufs = TEST_WAVEFORM_PLOT_TIME*TEST_FS/TEST_BUF_SIZE;
+ printf("nBufs %d\n", nBufs);
+
+ err = Pa_OpenStream(
+ &stream,
+ &inputParameters,
+ NULL,
+ TEST_FS,
+ TEST_BUF_SIZE,
+ paClipOff,
+ NULL, // no callback, use blocking API
+ NULL );
+ if (err != paNoError) {
+ wxMessageBox(wxT("Couldn't initialise sound device."), wxT("Error"), wxOK);
+ return;
+ }
+
+ err = Pa_StartStream(stream);
+ if (err != paNoError) {
+ wxMessageBox(wxT("Couldn't start sound device."), wxT("Error"), wxOK);
+ return;
+ }
+
+ for(i=0, t=0.0; i<nBufs; i++, t+=(float)TEST_BUF_SIZE/TEST_FS) {
+ Pa_ReadStream(stream, in48k_stereo_short, TEST_BUF_SIZE);
+ for(j=0; j<TEST_BUF_SIZE; j++)
+ in48k_short[j] = in48k_stereo_short[2*j]; // left channel only
+ int n8k = resample(src, in8k_short, in48k_short, 8000, TEST_FS, TEST_BUF_SIZE, TEST_BUF_SIZE);
+ resample_for_plot(fifo, in8k_short, n8k);
+
+ // every TEST_DT seconds update plot
+
+ if (t > TEST_DT) {
+ t -= TEST_DT;
+ short plotSamples[TEST_WAVEFORM_PLOT_BUF];
+ if (fifo_read(fifo, plotSamples, TEST_WAVEFORM_PLOT_BUF))
+ memset(plotSamples, 0, TEST_WAVEFORM_PLOT_BUF*sizeof(short));
+ plotScalar->add_new_short_samples(plotSamples, TEST_WAVEFORM_PLOT_BUF, 32767);
+ plotScalar->Refresh();
+ }
+ }
+
+ err = Pa_StopStream(stream);
+ if (err != paNoError) {
+ wxMessageBox(wxT("Couldn't stop sound device."), wxT("Error"), wxOK);
+ return;
+ }
+ Pa_CloseStream(stream);
+
+ fifo_destroy(fifo);
+ src_delete(src);
+}
+
+//-------------------------------------------------------------------------
+// OnRxInTest()
+//-------------------------------------------------------------------------
+void AudioOptsDialog::OnRxInTest(wxCommandEvent& event)
+{
+ plotDeviceInputForAFewSecs(rxInAudioDeviceNum, m_plotScalarRxIn);
+}
+
//-------------------------------------------------------------------------
// OnRefreshClick()
//-------------------------------------------------------------------------
#include "pa_asio.h"
#endif
#endif
+#include "fifo.h"
//-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=--=-=-=-=
// AudioInfoDisplay
int txInAudioDeviceNum;
int txOutAudioDeviceNum;
+ void buildTestControls(PlotScalar **plotScalar, wxButton **btnTest, wxPanel *parentPanel, wxBoxSizer *bSizer);
+ void plotDeviceInputForAFewSecs(int devNum, PlotScalar *plotScalar);
+
int buildListOfSupportedSampleRates(wxComboBox *cbSampleRate, int devNum, int in_out);
void populateParams(AudioInfoDisplay);
void showAPIInfo();
AudioInfoDisplay m_TxOutDevices;
wxPanel* m_panel1;
wxNotebook* m_notebook1;
+
wxPanel* m_panelRx;
wxListCtrl* m_listCtrlRxInDevices;
wxStaticText* m_staticText51;
wxTextCtrl* m_textCtrlRxIn;
wxStaticText* m_staticText6;
wxComboBox* m_cbSampleRateRxIn;
+
+ wxButton* m_btnRxInTest;
+ wxPanel* m_panelRxInTest;
+ PlotScalar* m_plotScalarRxIn;
+
wxListCtrl* m_listCtrlRxOutDevices;
wxStaticText* m_staticText9;
wxTextCtrl* m_textCtrlRxOut;
//virtual void OnActivateApp( wxActivateEvent& event ) { event.Skip(); }
// virtual void OnCloseFrame( wxCloseEvent& event ) { event.Skip(); }
void OnRxInDeviceSelect( wxListEvent& event );
+ void OnRxInTest( wxCommandEvent& event );
void OnRxOutDeviceSelect( wxListEvent& event );
void OnTxInDeviceSelect( wxListEvent& event );
void OnTxOutDeviceSelect( wxListEvent& event );
{
// Add Demod Input window
- m_panelDemodIn = new PlotScalar((wxFrame*) m_auiNbookCtrl, WAVEFORM_PLOT_TIME, 1.0/WAVEFORM_PLOT_FS, -1, 1, 1, 0.2, "%2.1f");
+ m_panelDemodIn = new PlotScalar((wxFrame*) m_auiNbookCtrl, WAVEFORM_PLOT_TIME, 1.0/WAVEFORM_PLOT_FS, -1, 1, 1, 0.2, "%2.1f", 0);
m_auiNbookCtrl->AddPage(m_panelDemodIn, _("Demod In"), true, wxNullBitmap);
g_plotDemodInFifo = fifo_create(2*WAVEFORM_PLOT_BUF);
}
{
// Add Speech Input window
- m_panelSpeechIn = new PlotScalar((wxFrame*) m_auiNbookCtrl, WAVEFORM_PLOT_TIME, 1.0/WAVEFORM_PLOT_FS, -1, 1, 1, 0.2, "%2.1f");
+ m_panelSpeechIn = new PlotScalar((wxFrame*) m_auiNbookCtrl, WAVEFORM_PLOT_TIME, 1.0/WAVEFORM_PLOT_FS, -1, 1, 1, 0.2, "%2.1f", 0);
m_auiNbookCtrl->AddPage(m_panelSpeechIn, _("Speech In"), true, wxNullBitmap);
g_plotSpeechInFifo = fifo_create(2*WAVEFORM_PLOT_BUF);
}
{
// Add Speech Output window
- m_panelSpeechOut = new PlotScalar((wxFrame*) m_auiNbookCtrl, WAVEFORM_PLOT_TIME, 1.0/WAVEFORM_PLOT_FS, -1, 1, 1, 0.2, "%2.1f");
+ m_panelSpeechOut = new PlotScalar((wxFrame*) m_auiNbookCtrl, WAVEFORM_PLOT_TIME, 1.0/WAVEFORM_PLOT_FS, -1, 1, 1, 0.2, "%2.1f", 0);
m_auiNbookCtrl->AddPage(m_panelSpeechOut, _("Speech Out"), true, wxNullBitmap);
g_plotSpeechOutFifo = fifo_create(2*WAVEFORM_PLOT_BUF);
}
if(wxGetApp().m_show_timing)
{
// Add Timing Offset window
- m_panelTimeOffset = new PlotScalar((wxFrame*) m_auiNbookCtrl, 5.0, DT, -0.5, 0.5, 1, 0.1, "%2.1f");
+ m_panelTimeOffset = new PlotScalar((wxFrame*) m_auiNbookCtrl, 5.0, DT, -0.5, 0.5, 1, 0.1, "%2.1f", 0);
m_auiNbookCtrl->AddPage(m_panelTimeOffset, L"Timing \u0394", true, wxNullBitmap);
}
if(wxGetApp().m_show_freq)
{
// Add Frequency Offset window
- m_panelFreqOffset = new PlotScalar((wxFrame*) m_auiNbookCtrl, 5.0, DT, -200, 200, 1, 50, "%3.0fHz");
+ m_panelFreqOffset = new PlotScalar((wxFrame*) m_auiNbookCtrl, 5.0, DT, -200, 200, 1, 50, "%3.0fHz", 0);
m_auiNbookCtrl->AddPage(m_panelFreqOffset, L"Frequency \u0394", true, wxNullBitmap);
}
// returns number of output samples generated by resampling
-static int resample(SRC_STATE *src,
+int resample(SRC_STATE *src,
short output_short[],
short input_short[],
int output_sample_rate,
// we don't hammer the graphics system too hard. Saves decimated data
// to a fifo for plotting on screen.
-static void resample_for_plot(struct FIFO *plotFifo, short buf[], int length)
+void resample_for_plot(struct FIFO *plotFifo, short buf[], int length)
{
int decimation = FS/WAVEFORM_PLOT_FS;
int nSamples, sample;
nSamples = length/decimation;
for(sample=0; sample<nSamples; sample+=2) {
- st = decimation*sample;
- en = decimation*(sample+2);
- max = min = 0;
- for(i=st; i<en; i++ ) {
- if (max < buf[i]) max = buf[i];
- if (min > buf[i]) min = buf[i];
- }
- dec_samples[sample] = max;
- dec_samples[sample+1] = min;
+ st = decimation*sample;
+ en = decimation*(sample+2);
+ max = min = 0;
+ for(i=st; i<en; i++ ) {
+ if (max < buf[i]) max = buf[i];
+ if (min > buf[i]) min = buf[i];
+ }
+ dec_samples[sample] = max;
+ dec_samples[sample+1] = min;
}
fifo_write(plotFifo, dec_samples, nSamples);
#include "topFrame.h"
#include "dlg_about.h"
-#include "dlg_audiooptions.h"
#include "dlg_options.h"
#include "dlg_comports.h"
#include "fdmdv2_plot.h"
#include "fdmdv2_pa_wrapper.h"
#include "sndfile.h"
#include "portaudio.h"
+#include "dlg_audiooptions.h"
#define _USE_TIMER 1
//#define _USE_ONIDLE 1
int m_zoom;
};
+void resample_for_plot(struct FIFO *plotFifo, short buf[], int length);
+int resample(SRC_STATE *src,
+ short output_short[],
+ short input_short[],
+ int output_sample_rate,
+ int input_sample_rate,
+ int length_output_short, // maximum output array length in samples
+ int length_input_short
+ );
+
#endif //__FDMDV2_MAIN__
//----------------------------------------------------------------
PlotScalar::PlotScalar(wxFrame* parent,
float t_secs, // time covered by entire x axis in seconds
- float sample_period_secs, // tiem between each sample in seconds
+ float sample_period_secs, // time between each sample in seconds
float a_min, // min ampltude of samples being plotted
float a_max, // max ampltude of samples being plotted
float graticule_t_step, // time step of x (time) axis graticule in seconds
float graticule_a_step, // step of amplitude axis graticule
- const char a_fmt[] // printf format string for amlitude axis labels
+ const char a_fmt[], // printf format string for amlitude axis labels
+ int mini // true for mini-plot - don't draw graticule
): PlotPanel(parent)
{
int i;
+ m_rCtrl = GetClientRect();
+
m_t_secs = t_secs;
m_sample_period_secs = sample_period_secs;
m_a_min = a_min;
m_graticule_a_step = graticule_a_step;
assert(strlen(a_fmt) < 15);
strcpy(m_a_fmt, a_fmt);
+ m_mini = mini;
// work out number of samples we will store and allocate storage
m_rCtrl = GetClientRect();
m_rGrid = m_rCtrl;
- m_rGrid = m_rGrid.Deflate(PLOT_BORDER + (XLEFT_OFFSET/2), (PLOT_BORDER + (YBOTTOM_OFFSET/2)));
+ if (!m_mini)
+ m_rGrid = m_rGrid.Deflate(PLOT_BORDER + (XLEFT_OFFSET/2), (PLOT_BORDER + (YBOTTOM_OFFSET/2)));
+
+ //printf("h %d w %d\n", m_rCtrl.GetWidth(), m_rCtrl.GetHeight());
+ //printf("h %d w %d\n", m_rGrid.GetWidth(), m_rGrid.GetHeight());
// black background
dc.Clear();
- m_rPlot = wxRect(PLOT_BORDER + XLEFT_OFFSET, PLOT_BORDER, m_rGrid.GetWidth(), m_rGrid.GetHeight());
+ if (m_mini)
+ m_rPlot = wxRect(0, 0, m_rGrid.GetWidth(), m_rGrid.GetHeight());
+ else
+ m_rPlot = wxRect(PLOT_BORDER + XLEFT_OFFSET, PLOT_BORDER, m_rGrid.GetWidth(), m_rGrid.GetHeight());
+
wxBrush ltGraphBkgBrush = wxBrush(BLACK_COLOR);
dc.SetBrush(ltGraphBkgBrush);
dc.SetPen(wxPen(BLACK_COLOR, 0));
// put inside plot window
- x += PLOT_BORDER + XLEFT_OFFSET;
- y += PLOT_BORDER;
+ if (!m_mini) {
+ x += PLOT_BORDER + XLEFT_OFFSET;
+ y += PLOT_BORDER;
+ }
if (i)
dc.DrawLine(x, y, prev_x, prev_y);
dc.SetPen(m_penShortDash);
for(t=0; t<=m_t_secs; t+=m_graticule_t_step) {
x = t*sec_to_px;
- x += PLOT_BORDER + XLEFT_OFFSET;
- dc.DrawLine(x, m_rGrid.GetHeight() + PLOT_BORDER, x, PLOT_BORDER);
- sprintf(buf, "%2.1fs", t);
- GetTextExtent(buf, &text_w, &text_h);
- dc.DrawText(buf, x - text_w/2, m_rGrid.GetHeight() + PLOT_BORDER + YBOTTOM_TEXT_OFFSET);
+ if (m_mini) {
+ dc.DrawLine(x, m_rGrid.GetHeight(), x, 0);
+ }
+ else {
+ x += PLOT_BORDER + XLEFT_OFFSET;
+ dc.DrawLine(x, m_rGrid.GetHeight() + PLOT_BORDER, x, PLOT_BORDER);
+ }
+ if (!m_mini) {
+ sprintf(buf, "%2.1fs", t);
+ GetTextExtent(buf, &text_w, &text_h);
+ dc.DrawText(buf, x - text_w/2, m_rGrid.GetHeight() + PLOT_BORDER + YBOTTOM_TEXT_OFFSET);
+ }
}
// Horizontal gridlines
dc.SetPen(m_penDotDash);
for(a=m_a_min; a<m_a_max; a+=m_graticule_a_step) {
y = m_rGrid.GetHeight() - a*a_to_py + m_a_min*a_to_py;
- y += PLOT_BORDER;
- dc.DrawLine(PLOT_BORDER + XLEFT_OFFSET, y,
- (m_rGrid.GetWidth() + PLOT_BORDER + XLEFT_OFFSET), y);
- sprintf(buf, m_a_fmt, a);
- GetTextExtent(buf, &text_w, &text_h);
- dc.DrawText(buf, PLOT_BORDER + XLEFT_OFFSET - text_w - XLEFT_TEXT_OFFSET, y-text_h/2);
+ if (m_mini) {
+ dc.DrawLine(0, y, m_rGrid.GetWidth(), y);
+ }
+ else {
+ y += PLOT_BORDER;
+ dc.DrawLine(PLOT_BORDER + XLEFT_OFFSET, y,
+ (m_rGrid.GetWidth() + PLOT_BORDER + XLEFT_OFFSET), y);
+ }
+ if (!m_mini) {
+ sprintf(buf, m_a_fmt, a);
+ GetTextExtent(buf, &text_w, &text_h);
+ dc.DrawText(buf, PLOT_BORDER + XLEFT_OFFSET - text_w - XLEFT_TEXT_OFFSET, y-text_h/2);
+ }
}
float a_max,
float graticule_t_step,
float graticule_a_step,
- const char a_fmt[]
+ const char a_fmt[],
+ int mini
);
~PlotScalar();
void add_new_sample(float sample);
float m_graticule_t_step;
float m_graticule_a_step;
char m_a_fmt[15];
+ int m_mini;
int m_samples;
float *m_mem;