// Purpose: FreeDV main()
// Created: Apr. 9, 2012
// Authors: David Rowe, David Witten
-//
+//
// License:
//
// This program is free software; you can redistribute it and/or modify
m_zoom = 1.;
m_serialPort = NULL;
m_device = NULL;
-
+
tools->AppendSeparator();
wxMenuItem* m_menuItemToolsConfigDelete;
m_menuItemToolsConfigDelete = new wxMenuItem(tools, wxID_ANY, wxString(_("&Restore defaults")) , wxT("Delete config file/keys and restore defaults"), wxITEM_NORMAL);
tools->Append(m_menuItemToolsConfigDelete);
wxConfigBase *pConfig = wxConfigBase::Get();
- //MainApp theApp = wxGetApp();
// restore frame position and size
int x = pConfig->Read(wxT("/MainFrame/top"), 50);
if(wxGetApp().m_show_spect)
{
// Add Spectrum Plot window
- m_panelSpectrum = new PlotSpectrum((wxFrame*) m_auiNbookCtrl, g_avmag,
+ m_panelSpectrum = new PlotSpectrum((wxFrame*) m_auiNbookCtrl, g_avmag,
FDMDV_NSPEC*((float)MAX_F_HZ/FDMDV_MAX_F_HZ));
m_panelSpectrum->SetToolTip(_("Left click to tune"));
m_auiNbookCtrl->AddPage(m_panelSpectrum, _("Spectrum"), true, wxNullBitmap);
//m_togBtnALC->Disable();
SetupSerialPort();
-
+
// squelch settings
char sqsnr[15];
m_sliderSQ->SetValue((int)(g_SquelchLevel*2.0));
g_TxFreqOffsetFreqRect.imag = sin(g_TxFreqOffsetHz);
g_TxFreqOffsetPhaseRect.real = cos(0.0);
g_TxFreqOffsetPhaseRect.imag = sin(0.0);
-
+
g_tx = 0;
g_split = 0;
// data states
- g_txDataInFifo = fifo_create(MAX_CALLSIGN*VARICODE_MAX_BITS);
- g_rxDataOutFifo = fifo_create(MAX_CALLSIGN*VARICODE_MAX_BITS);
+ g_txDataInFifo = fifo_create(MAX_CALLSIGN*VARICODE_MAX_BITS);
+ g_rxDataOutFifo = fifo_create(MAX_CALLSIGN*VARICODE_MAX_BITS);
varicode_decode_init(&g_varicode_dec_states);
sox_biquad_start();
pConfig->Write(wxT("/Audio/snrSlow"), wxGetApp().m_snrSlow);
pConfig->Write(wxT("/Data/CallSign"), wxGetApp().m_callSign);
-
+
pConfig->Write(wxT("/Filter/MicInEQEnable"), wxGetApp().m_MicInEQEnable);
pConfig->Write(wxT("/Filter/SpkOutEQEnable"), wxGetApp().m_SpkOutEQEnable);
}
m_togBtnAnalog->Disconnect(wxEVT_UPDATE_UI, wxUpdateUIEventHandler(MainFrame::OnTogBtnAnalogClickUI), NULL, this);
//m_togBtnALC->Disconnect(wxEVT_UPDATE_UI, wxUpdateUIEventHandler(MainFrame::OnTogBtnALCClickUI), NULL, this);
//m_btnTogPTT->Disconnect(wxEVT_UPDATE_UI, wxUpdateUIEventHandler(MainFrame::OnTogBtnPTT_UI), NULL, this);
-
+
CloseSerialPort();
sox_biquad_finish();
-
+
if (m_RxRunning)
{
stopRxStream();
short demodInPlotSamples[WAVEFORM_PLOT_BUF];
if (fifo_read(g_plotDemodInFifo, demodInPlotSamples, WAVEFORM_PLOT_BUF))
- memset(demodInPlotSamples, 0, WAVEFORM_PLOT_BUF*sizeof(short));
+ memset(demodInPlotSamples, 0, WAVEFORM_PLOT_BUF*sizeof(short));
m_panelDemodIn->add_new_short_samples(0,demodInPlotSamples, WAVEFORM_PLOT_BUF, 32767);
m_panelDemodIn->Refresh();
// Level Gauge -----------------------------------------------------------------------
float tooHighThresh;
- if (!g_tx && m_RxRunning)
+ if (!g_tx && m_RxRunning)
{
// receive mode - display From Radio peaks
tooHighThresh = FROM_RADIO_MAX;
}
- else
+ else
{
// transmit mode - display From Mic peaks
// peak from last second
if (maxSpeechIn > m_maxLevel)
m_maxLevel = maxSpeechIn;
-
+
tooHighThresh = FROM_MIC_MAX;
}
-
+
// Peak Reading meter: updates peaks immediately, then slowly decays
int maxScaled = (int)(100.0 * ((float)m_maxLevel/32767.0));
m_gaugeLevel->SetValue(maxScaled);
// See if any Callsign info received --------------------------------
short ashort;
- while (fifo_read(g_rxDataOutFifo, &ashort, 1) == 0) {
+ while (fifo_read(g_rxDataOutFifo, &ashort, 1) == 0) {
if ((ashort == 13) || ((m_pcallsign - m_callsign) > MAX_CALLSIGN-1)) {
// CR completes line
*m_pcallsign = 0;
m_pcallsign = m_callsign;
}
- else
+ else
{
*m_pcallsign++ = (char)ashort;
wxString s;
if (m_newMicInFilter || m_newSpkOutFilter) {
g_mutexProtectingCallbackData.Lock();
deleteEQFilters(g_rxUserdata);
- designEQFilters(g_rxUserdata);
+ designEQFilters(g_rxUserdata);
g_mutexProtectingCallbackData.Unlock();
m_newMicInFilter = m_newSpkOutFilter = false;
}
// Toggle test frame mode at run time
if (!g_testFrames && m_ckboxTestFrame->GetValue()) {
-
+
// reset stats on check box off to on transition
-
+
g_test_frame_sync_state = 0;
g_total_bits = 0;
g_total_bit_errors = 0;
sprintf(errors, "Errors: %d", g_total_bit_errors); wxString errors_string(errors); m_textErrors->SetLabel(errors_string);
float b = (float)g_total_bit_errors/(1E-6+g_total_bits);
sprintf(ber, "BER...: %4.3f", b); wxString ber_string(ber); m_textBER->SetLabel(ber_string);
-
+
// update error plots
-
+
short *error_pattern = new short[g_sz_error_pattern];
if (fifo_read(g_errorFifo, error_pattern, g_sz_error_pattern) == 0) {
for(i=b; i<g_sz_error_pattern; i+= 2*g_Nc)
m_panelTestFrameErrors->add_new_sample(b, b + 0.8*error_pattern[i]);
}
-
+
m_panelTestFrameErrors->Refresh();
}
delete error_pattern;
}
-
+
}
#endif
{
int style = GetWindowStyle();
- if (style & wxSTAY_ON_TOP)
+ if (style & wxSTAY_ON_TOP)
{
style &= ~wxSTAY_ON_TOP;
}
- else
+ else
{
style |= wxSTAY_ON_TOP;
}
//-------------------------------------------------------------------------
void MainFrame::OnTogBtnPTT (wxCommandEvent& event)
{
- if (g_tx)
+ if (g_tx)
{
// tx-> rx transition, swap to the page we were on for last rx
- m_auiNbookCtrl->ChangeSelection(wxGetApp().m_rxNbookCtrl);
+ m_auiNbookCtrl->ChangeSelection(wxGetApp().m_rxNbookCtrl);
}
- else
+ else
{
// rx-> tx transition, swap to Mic In page to monitor speech
wxGetApp().m_rxNbookCtrl = m_auiNbookCtrl->GetSelection();
// Tortured and tortuous logic, it seems to me...
if(wxGetApp().m_boolUseSerialPTT && m_serialPort != NULL)
{
- if(event.IsChecked())
+ if(event.IsChecked())
{
if(wxGetApp().m_boolUseRTS) // Use RTS
{
m_serialPort->ClrLineState(ctb::LinestateDtr);
}
}
- }
+ }
else // !isChecked() - so Clear
{
if(wxGetApp().m_boolUseRTS) // Use RTS
m_serialPort->SetLineState(ctb::LinestateDtr);
}
}
- }
+ }
}
// reset level gauge
m_maxLevel = 0;
g_analog = 1;
else
g_analog = 0;
-
+
event.Skip();
}
{
wxUnusedVar(event);
- if(g_playFileToMicIn)
+ if(g_playFileToMicIn)
{
g_mutexProtectingCallbackData.Lock();
g_playFileToMicIn = false;
SetStatusText(wxT(""));
g_mutexProtectingCallbackData.Unlock();
}
- else
+ else
{
wxString soundFile;
SF_INFO sfInfo;
// add the loop check box
openFileDialog.SetExtraControlCreator(&createMyExtraPlayFilePanel);
-
+
if(openFileDialog.ShowModal() == wxID_CANCEL)
{
return; // the user changed their mind...
wxMessageBox(strErr, wxT("Couldn't open sound file"), wxOK);
return;
}
-
+
wxWindow * const ctrl = openFileDialog.GetExtraControl();
// Huh?! I just copied wxWidgets-2.9.4/samples/dialogs ....
wxUnusedVar(event);
printf("OnPlayFileFromRadio:: %d\n", (int)g_playFileFromRadio);
- if (g_playFileFromRadio)
+ if (g_playFileFromRadio)
{
printf("OnPlayFileFromRadio:: Stop\n");
g_mutexProtectingCallbackData.Lock();
SetStatusText(wxT(""));
g_mutexProtectingCallbackData.Unlock();
}
- else
+ else
{
wxString soundFile;
SF_INFO sfInfo;
// add the loop check box
openFileDialog.SetExtraControlCreator(&createMyExtraPlayFilePanel);
-
+
if(openFileDialog.ShowModal() == wxID_CANCEL)
{
return; // the user changed their mind...
wxMessageBox(strErr, wxT("Couldn't open sound file"), wxOK);
return;
}
-
+
wxWindow * const ctrl = openFileDialog.GetExtraControl();
// Huh?! I just copied wxWidgets-2.9.4/samples/dialogs ....
// add the loop check box
openFileDialog.SetExtraControlCreator(&createMyExtraRecFilePanel);
-
+
if(openFileDialog.ShowModal() == wxID_CANCEL)
{
return; // the user changed their mind...
sfInfo.samplerate = FS;
} else {
wxMessageBox(wxT("Invalid file format"), wxT("Record File From Radio"), wxOK);
- return;
+ return;
}
}
else {
wxMessageBox(wxT("Invalid file format"), wxT("Record File From Radio"), wxOK);
- return;
+ return;
}
// Bug: on Win32 I cant read m_recFileFromRadioSecs, so have hard coded it
wxMessageBox(strErr, wxT("Couldn't open sound file"), wxOK);
return;
}
-
+
SetStatusText(wxT("Recording File: ") + fileName + wxT(" From Radio") , 0);
- g_recFileFromRadio = true;
+ g_recFileFromRadio = true;
}
}
{
wxUnusedVar(event);
printf("MainFrame::OnToolSetCallSign\n");
- wxGetApp().m_callSign = wxGetTextFromUser(wxT("Enter Callsign"),
+ wxGetApp().m_callSign = wxGetTextFromUser(wxT("Enter Callsign"),
wxT("Enter Callsign"),
wxGetApp().m_callSign);
}
// Try to determine current SVN revision from the Internet
wxURL url(wxT("http://freetel.svn.sourceforge.net/svnroot/freetel/fdmdv2/"));
-
+
if(url.GetError() == wxURL_NOERR)
{
wxString htmldata;
wxInputStream *in = url.GetInputStream();
-
+
if(in && in->IsOk())
{
//printf("In OK\n");
wxStringOutputStream html_stream(&htmldata);
in->Read(html_stream);
//wxLogDebug(htmldata);
-
+
wxString s("<h2>freetel - Revision ");
int startIndex = htmldata.find(s) + s.Length();
int endIndex = htmldata.find(wxT(": /fdmdv2</h2>"));
// we are attempting to start
- if (startStop.IsSameAs("Start"))
+ if (startStop.IsSameAs("Start"))
{
- //
+ //
// Start Running -------------------------------------------------
//
//m_togRxID->Enable();
//m_togTxID->Enable();
m_togBtnAnalog->Enable();
-/*
+/*
if(m_serialPort != NULL)
{
m_btnTogPTT->Enable();
g_Nc = 14;
codec2_mode = CODEC2_MODE_1400;
}
-
+
if (m_rb1600->GetValue()) {
g_mode = MODE_1600;
g_Nc = 16;
// init Codec 2 LPC Post Filter
- codec2_set_lpc_post_filter(g_pCodec2,
- wxGetApp().m_codec2LPCPostFilterEnable,
- wxGetApp().m_codec2LPCPostFilterBassBoost,
- wxGetApp().m_codec2LPCPostFilterBeta,
+ codec2_set_lpc_post_filter(g_pCodec2,
+ wxGetApp().m_codec2LPCPostFilterEnable,
+ wxGetApp().m_codec2LPCPostFilterBassBoost,
+ wxGetApp().m_codec2LPCPostFilterBeta,
wxGetApp().m_codec2LPCPostFilterGamma);
g_State = 0;
startRxStream();
- if (m_RxRunning)
+ if (m_RxRunning)
{
#ifdef _USE_TIMER
m_plotTimer.Start(_REFRESH_TIMER_PERIOD, wxTIMER_CONTINUOUS);
#endif // _USE_TIMER
}
}
-
- // Stop was pressed or start up failed
+
+ // Stop was pressed or start up failed
if (startStop.IsSameAs("Stop") || !m_RxRunning ) {
- //
+ //
// Stop Running -------------------------------------------------
//
src_delete(g_rxUserdata->outsrc2);
}
-void MainFrame::initPortAudioDevice(PortAudioWrap *pa, int inDevice, int outDevice,
+void MainFrame::initPortAudioDevice(PortAudioWrap *pa, int inDevice, int outDevice,
int soundCard, int sampleRate, int inputChannels)
{
// Note all of the wrapper functions below just set values in a
}
m_rxPa = new PortAudioWrap();
-
+
if (g_nSoundCards == 0) {
wxMessageBox(wxT("No Sound Cards configured, use Tools - Audio Config to configure"), wxT("Error"), wxOK);
delete m_rxPa;
m_RxRunning = false;
return;
}
-
+
// Init Sound card 1 ----------------------------------------------
// sanity check on sound card device numbers
else
inputChannels1 = 2;
- initPortAudioDevice(m_rxPa, g_soundCard1InDeviceNum, g_soundCard1OutDeviceNum, 1,
+ initPortAudioDevice(m_rxPa, g_soundCard1InDeviceNum, g_soundCard1OutDeviceNum, 1,
g_soundCard1SampleRate, inputChannels1);
// Init Sound Card 2 ------------------------------------------------
inputChannels2 = 1;
else
inputChannels2 = 2;
-
- initPortAudioDevice(m_txPa, g_soundCard2InDeviceNum, g_soundCard2OutDeviceNum, 2,
+
+ initPortAudioDevice(m_txPa, g_soundCard2InDeviceNum, g_soundCard2OutDeviceNum, 2,
g_soundCard2SampleRate, inputChannels2);
}
g_rxUserdata->rxinfifo = fifo_create(3 * FDMDV_NOM_SAMPLES_PER_FRAME);
g_rxUserdata->rxoutfifo = fifo_create(2 * codec2_samples_per_frame(g_pCodec2));
-
+
// Init Equaliser Filters ------------------------------------------------------
m_newMicInFilter = m_newSpkOutFilter = true;
m_RxRunning = false;
return;
}
-
+
m_rxErr = m_rxPa->streamStart();
if(m_rxErr != paNoError) {
wxMessageBox(wxT("Sound Card 1 Stream Start Error."), wxT("Error"), wxOK);
// Start sound card 2 ----------------------------------------------------------
if (g_nSoundCards == 2) {
-
+
// question: can we use same callback data
// (g_rxUserdata)or both sound card callbacks? Is there a
// chance of them both being called at the same time? We
return;
}
}
-
+
// start tx/rx processing thread
m_txRxThread = new txRxThread;
void *sbq;
int i, argc;
- assert((strcmp(filterType, "bass") == 0) ||
+ assert((strcmp(filterType, "bass") == 0) ||
(strcmp(filterType, "treble") == 0) ||
(strcmp(filterType, "equalizer") == 0));
argc = 0;
if ((strcmp(filterType, "bass") == 0) || (strcmp(filterType, "treble") == 0)) {
- sprintf(arg[argc++], "%s", filterType);
+ sprintf(arg[argc++], "%s", filterType);
sprintf(arg[argc++], "%f", gaindB+1E-6);
- sprintf(arg[argc++], "%f", freqHz);
+ sprintf(arg[argc++], "%f", freqHz);
}
if (strcmp(filterType, "equalizer") == 0) {
- sprintf(arg[argc++], "%s", filterType);
- sprintf(arg[argc++], "%f", freqHz);
- sprintf(arg[argc++], "%f", Q);
+ sprintf(arg[argc++], "%s", filterType);
+ sprintf(arg[argc++], "%f", freqHz);
+ sprintf(arg[argc++], "%f", Q);
sprintf(arg[argc++], "%f", gaindB+1E-6);
}
nSamples = length/decimation;
- for(sample = 0; sample < nSamples; sample += 2)
+ for(sample = 0; sample < nSamples; sample += 2)
{
st = decimation*sample;
en = decimation*(sample+2);
max = min = 0;
- for(i=st; i<en; i++ )
+ for(i=st; i<en; i++ )
{
if (max < buf[i]) max = buf[i];
if (min > buf[i]) min = buf[i];
}
}
g_mutexProtectingCallbackData.Unlock();
-
+
fifo_write(cbData->rxinfifo, in8k_short, n8k);
resample_for_plot(g_plotDemodInFifo, in8k_short, n8k);
memcpy(out8k_short, in8k_short, sizeof(short)*n8k);
}
else {
- // we are in sync so use decoded audio
+ // we are in sync so use decoded audio
memset(out8k_short, 0, sizeof(short)*N8);
fifo_read(cbData->rxoutfifo, out8k_short, N8);
}
-
+
// Opional Spk Out EQ Filtering, need mutex as filter can change at run time
g_mutexProtectingCallbackData.Lock();
if (cbData->spkOutEQEnable) {
// between this sound card and sound card 2.
g_mutexProtectingCallbackData.Lock();
- while((unsigned)fifo_used(cbData->outfifo1) < 6*N48)
+ while((unsigned)fifo_used(cbData->outfifo1) < 6*N48)
{
g_mutexProtectingCallbackData.Unlock();
// zero speech input just in case infifo2 underflows
memset(in48k_short, 0, nsam*sizeof(short));
fifo_read(cbData->infifo2, in48k_short, nsam);
-
+
nout = resample(cbData->insrc2, in8k_short, in48k_short, FS, g_soundCard2SampleRate, 2*N8, nsam);
// optionally use file for mic input signal
}
else
per_frame_tx_processing(out8k_short, in8k_short, g_pCodec2);
-
+
// output 40ms of modem tone
nout = resample(cbData->outsrc1, out48k_short, out8k_short, g_soundCard1SampleRate, FS, 2*N48, 2*N8);
g_mutexProtectingCallbackData.Lock();
// compute rx spectrum & get demod stats, and update GUI plot data
fdmdv_get_rx_spectrum(g_pFDMDV, rx_spec, rx_fdm, nin_prev);
fdmdv_get_demod_stats(g_pFDMDV, &g_stats);
-
+
// Average rx spectrum data using a simple IIR low pass filter
for(i = 0; i < FDMDV_NSPEC; i++)
{
if(g_stats.sync == 1)
{
- next_state = 1;
+ next_state = 1;
}
//printf("sync state: %d\n", *state);
break;
codeword2 = golay23_decode(recd_codeword);
g_total_bit_errors += golay23_count_errors(recd_codeword, codeword2);
g_total_bits += 23;
-
+
// if (codeword2 != recd_codeword)
// printf("codeword2: 0x%x recd_codeword: 0x%x\n", codeword2,recd_codeword );
//fprintf(stderr, "received codeword2: 0x%x decoded codeword2: 0x%x\n", recd_codeword, codeword2);
data_flag_index = codec2_get_spare_bit_index(c2);
//printf("data_flag_index: %d\n", data_flag_index);
assert(data_flag_index != -1); // not supported for all rates
-
+
short abit = codec_bits[data_flag_index];
char ascii_out;
}
// reconstruct missing bit we steal for data bit and decode speech
-
+
valid = codec2_rebuild_spare_bit(c2, codec_bits);
assert(valid != -1);
assert(codec2_samples_per_frame(c2) == (2*N8));
codec2_decode(c2, output_buf, packed_bits);
}
-
+
fifo_write(output_fifo, output_buf, codec2_samples_per_frame(c2));
-
+
break;
}
//printf("state: %d next_state: %d reliable_sync_bit: %d\n", *state, next_state, reliable_sync_bit);
data <<= 1;
data |= bits[i];
}
- data =
+ data =
codeword1 = golay23_encode(data);
/* now pack output frame with parity bits at end to make them
//#define SC2_LOOPBACK
#ifdef SC2_LOOPBACK
-
+
for(i = 0; i < framesPerBuffer; i++, wptr += 2)
{
wptr[0] = indata[i];
wptr[1] = indata[i];
}
-
+
#else
fifo_write(cbData->infifo2, indata, framesPerBuffer);
void MainFrame::SetupSerialPort(void)
{
long baudrate;
-
+
wxGetApp().m_strRigCtrlBaud.ToLong(&baudrate, 10);
if(!wxGetApp().m_strRigCtrlPort.IsEmpty())
{
wxString protocol = wxGetApp().m_strRigCtrlDatabits + wxGetApp().m_strRigCtrlParity + wxGetApp().m_strRigCtrlStopbits;
m_serialPort = new ctb::SerialPort();
- if(m_serialPort->Open(wxGetApp().m_strRigCtrlPort.c_str(), baudrate, protocol.c_str(), ctb::SerialPort::NoFlowControl ) >= 0 )
+ if(m_serialPort->Open(wxGetApp().m_strRigCtrlPort.c_str(), baudrate, protocol.c_str(), ctb::SerialPort::NoFlowControl ) >= 0 )
{
m_device = m_serialPort;
// always start with PTT cleared
//m_btnTogPTT->Disable();
}
}
-/*
+/*
else
{
wxMessageBox(wxT("You must select a Serial port to Open!"), wxT("Error"), wxOK);
{
m_serialPort->Close();
m_serialPort = NULL;
- m_device = NULL;
+ m_device = NULL;
//m_btnTogPTT->SetLabel(wxT("PTT"));
//m_btnTogPTT->Enable(false);
}