From: drowe67 Date: Mon, 14 Sep 2015 04:35:19 +0000 (+0000) Subject: voice keyer coded, builds OK, but not tested X-Git-Url: http://git.whiteaudio.com/gitweb/?a=commitdiff_plain;h=55cdae83ce2e7098862ca1e75dec580d5b2787b8;p=freetel-svn-tracking.git voice keyer coded, builds OK, but not tested git-svn-id: https://svn.code.sf.net/p/freetel/code@2324 01035d8c-6547-0410-b346-abe4f91aad63 --- diff --git a/freedv-dev/src/dlg_ptt.cpp b/freedv-dev/src/dlg_ptt.cpp index f3bdb4d8..8964587a 100644 --- a/freedv-dev/src/dlg_ptt.cpp +++ b/freedv-dev/src/dlg_ptt.cpp @@ -349,8 +349,8 @@ void ComPortsDlg::ExchangeData(int inout) /* Voice Keyer */ m_txtCtrlVoiceKeyerWaveFile->SetValue(wxGetApp().m_txtVoiceKeyerWaveFile); - m_txtCtrlVoiceKeyerRxPause->SetValue(wxGetApp().m_txtVoiceKeyerRxPause); - m_txtCtrlVoiceKeyerRepeats->SetValue(wxGetApp().m_txtVoiceKeyerRepeats); + m_txtCtrlVoiceKeyerRxPause->SetValue(wxString::Format(wxT("%i"), wxGetApp().m_intVoiceKeyerRxPause)); + m_txtCtrlVoiceKeyerRepeats->SetValue(wxString::Format(wxT("%i"), wxGetApp().m_intVoiceKeyerRepeats)); m_ckUseHamlibPTT->SetValue(wxGetApp().m_boolHamlibUseForPTT); m_cbRigName->SetSelection(wxGetApp().m_intHamlibRig); @@ -380,10 +380,13 @@ void ComPortsDlg::ExchangeData(int inout) wxGetApp().m_txtVoiceKeyerWaveFile = m_txtCtrlVoiceKeyerWaveFile->GetValue(); pConfig->Write(wxT("/VoiceKeyer/WaveFile"), wxGetApp().m_txtVoiceKeyerWaveFile); - wxGetApp().m_txtVoiceKeyerRxPause = m_txtCtrlVoiceKeyerRxPause->GetValue(); - pConfig->Write(wxT("/VoiceKeyer/RxPause"), wxGetApp().m_txtVoiceKeyerRxPause); - wxGetApp().m_txtVoiceKeyerRepeats = m_txtCtrlVoiceKeyerRepeats->GetValue(); - pConfig->Write(wxT("/VoiceKeyer/Repeats"), wxGetApp().m_txtVoiceKeyerRepeats); + long tmp; + m_txtCtrlVoiceKeyerRxPause->GetValue().ToLong(&tmp); if (tmp < 0) tmp = 0; wxGetApp().m_intVoiceKeyerRxPause = (int)tmp; + pConfig->Write(wxT("/VoiceKeyer/RxPause"), wxGetApp().m_intVoiceKeyerRxPause); + m_txtCtrlVoiceKeyerRepeats->GetValue().ToLong(&tmp); + if (tmp < 0) tmp = 0; if (tmp > 100) tmp = 100; + wxGetApp().m_intVoiceKeyerRepeats = (int)tmp; + pConfig->Write(wxT("/VoiceKeyer/Repeats"), wxGetApp().m_intVoiceKeyerRepeats); /* Hamlib settings. */ diff --git a/freedv-dev/src/fdmdv2_main.cpp b/freedv-dev/src/fdmdv2_main.cpp index f3a24042..3dc38c90 100644 --- a/freedv-dev/src/fdmdv2_main.cpp +++ b/freedv-dev/src/fdmdv2_main.cpp @@ -351,8 +351,8 @@ MainFrame::MainFrame(wxWindow *parent) : TopFrame(parent) wxGetApp().m_leftChannelVoxTone = pConfig->ReadBool("/Rig/leftChannelVoxTone", false); wxGetApp().m_txtVoiceKeyerWaveFile = pConfig->Read(wxT("/VoiceKeyer/WaveFile"), wxT("voicekeyer.wav")); - wxGetApp().m_txtVoiceKeyerRxPause = pConfig->Read(wxT("/VoiceKeyer/RxPause"), wxT("10")); - wxGetApp().m_txtVoiceKeyerRepeats = pConfig->Read(wxT("/VoiceKeyer/Repeats"), wxT("5")); + wxGetApp().m_intVoiceKeyerRxPause = pConfig->Read(wxT("/VoiceKeyer/RxPause"), 10); + wxGetApp().m_intVoiceKeyerRepeats = pConfig->Read(wxT("/VoiceKeyer/Repeats"), 5); wxGetApp().m_boolHamlibUseForPTT = pConfig->ReadBool("/Hamlib/UseForPTT", false); wxGetApp().m_intHamlibRig = pConfig->ReadLong("/Hamlib/RigName", 0); @@ -521,6 +521,7 @@ MainFrame::MainFrame(wxWindow *parent) : TopFrame(parent) optionsDlg = new OptionsDlg(NULL); m_schedule_restore = false; + vk_state = VK_IDLE; } //------------------------------------------------------------------------- @@ -594,8 +595,8 @@ MainFrame::~MainFrame() pConfig->Write(wxT("/Audio/soundCard2SampleRate"), g_soundCard2SampleRate ); pConfig->Write(wxT("/VoiceKeyer/WaveFile"), wxGetApp().m_txtVoiceKeyerWaveFile); - pConfig->Write(wxT("/VoiceKeyer/RxPause"), wxGetApp().m_txtVoiceKeyerRxPause); - pConfig->Write(wxT("/VoiceKeyer/Repeats"), wxGetApp().m_txtVoiceKeyerRepeats); + pConfig->Write(wxT("/VoiceKeyer/RxPause"), wxGetApp().m_intVoiceKeyerRxPause); + pConfig->Write(wxT("/VoiceKeyer/Repeats"), wxGetApp().m_intVoiceKeyerRepeats); pConfig->Write(wxT("/Rig/HalfDuplex"), wxGetApp().m_boolHalfDuplex); pConfig->Write(wxT("/Rig/leftChannelVoxTone"), wxGetApp().m_leftChannelVoxTone); @@ -1250,6 +1251,9 @@ void MainFrame::OnTimer(wxTimerEvent &evt) } } + // Voice Keyer state machine + + VoiceKeyerProcessEvent(VK_DT); } #endif @@ -1444,14 +1448,14 @@ void MainFrame::togglePTT(void) { if(wxGetApp().m_boolUseSerialPTT && (com_handle != COM_HANDLE_INVALID)) { if (wxGetApp().m_boolUseRTS) { - printf("g_tx: %d m_boolRTSPos: %d serialLine: %d\n", g_tx, wxGetApp().m_boolRTSPos, g_tx == wxGetApp().m_boolRTSPos); + //fprintf(stderr, "g_tx: %d m_boolRTSPos: %d serialLine: %d\n", g_tx, wxGetApp().m_boolRTSPos, g_tx == wxGetApp().m_boolRTSPos); if (g_tx == wxGetApp().m_boolRTSPos) raiseRTS(); else lowerRTS(); } if (wxGetApp().m_boolUseDTR) { - printf("g_tx: %d m_boolDTRPos: %d serialLine: %d\n", g_tx, wxGetApp().m_boolDTRPos, g_tx == wxGetApp().m_boolDTRPos); + //fprintf(stderr, "g_tx: %d m_boolDTRPos: %d serialLine: %d\n", g_tx, wxGetApp().m_boolDTRPos, g_tx == wxGetApp().m_boolDTRPos); if (g_tx == wxGetApp().m_boolDTRPos) raiseDTR(); else @@ -1467,6 +1471,160 @@ void MainFrame::togglePTT(void) { m_gaugeLevel->SetValue(0); } +/* + Voice Keyer: + + + space bar turns keyer off + + 5 secs of valid sync turns it off + + [ ] complete state machine and builds OK + [ ] file select dialog + [ ] test all states + [ ] restore size +*/ + +void MainFrame::OnTogBtnVoiceKeyerClick (wxCommandEvent& event) +{ + VoiceKeyerStartTx(); + event.Skip(); +} + + +int MainFrame::VoiceKeyerStartTx(void) +{ + int next_state; + + // start playing wave file or die trying + + SF_INFO sfInfo; + sfInfo.format = 0; + + g_sfPlayFile = sf_open(wxGetApp().m_txtVoiceKeyerWaveFile, SFM_READ, &sfInfo); + if(g_sfPlayFile == NULL) { + wxString strErr = sf_strerror(NULL); + wxMessageBox(strErr, wxT("Couldn't open voice keyer wave file"), wxOK); + m_togBtnVoiceKeyer->SetValue(false); + next_state = VK_IDLE; + } + else { + SetStatusText(wxT("Voice Keyer: Playing File") + wxGetApp().m_txtVoiceKeyerWaveFile + wxT(" to Mic Input") , 0); + g_loopPlayFileToMicIn = false; + g_playFileToMicIn = true; + + m_btnTogPTT->SetValue(true); togglePTT(); + next_state = VK_TX; + } + + return next_state; +} + + +void MainFrame::VoiceKeyerProcessEvent(int vk_event) { + int next_state = vk_state; + + switch(vk_state) { + + case VK_IDLE: + if (vk_event == VK_START) { + // sample these puppies at start just in case they are changed while VK running + vk_rx_pause = wxGetApp().m_intVoiceKeyerRxPause; + vk_repeats = wxGetApp().m_intVoiceKeyerRepeats; + + vk_repeat_counter = 0; + next_state = VoiceKeyerStartTx(); + } + break; + + case VK_TX: + + // In this state we are transmitting and playing a wave file + // to Mic In + + if (vk_event == VK_SPACE_BAR) { + m_btnTogPTT->SetValue(false); togglePTT(); + StopPlayFileToMicIn(); + m_togBtnVoiceKeyer->SetValue(false); + next_state = VK_IDLE; + } + + if (vk_event == VK_PLAY_FINISHED) { + m_btnTogPTT->SetValue(false); togglePTT(); + vk_repeat_counter++; + if (vk_repeat_counter > vk_repeats) { + m_togBtnVoiceKeyer->SetValue(false); + next_state = VK_IDLE; + } + vk_rx_time = 0.0; + next_state = VK_RX; + } + + break; + + case VK_RX: + + // in this state we are receiving and waiting for + // delay timer or valid sync + + if (vk_event == VK_DT) { + vk_rx_time += DT; + if (vk_rx_time >= vk_rx_pause) { + next_state = VoiceKeyerStartTx(); + } + } + + if (vk_event == VK_SPACE_BAR) { + m_togBtnVoiceKeyer->SetValue(false); + next_state = VK_IDLE; + } + + if (vk_event == VK_SYNC) { + vk_rx_time = 0; + next_state = VK_SYNC_WAIT; + } + break; + + case VK_SYNC_WAIT: + + // In this state we wait for valid sync to last + // VK_SYNC_WAIT_TIME seconds + + if (vk_event == VK_SPACE_BAR) { + m_togBtnVoiceKeyer->SetValue(false); + next_state = VK_IDLE; + } + + if (vk_event == VK_DT) { + vk_rx_time += DT; + + // if we lose sync restart RX state + + if (freedv_get_sync(g_pfreedv) == 0) { + vk_rx_time = 0.0; + next_state = VK_RX; + } + + // drop out of voice keyer if we get a few seconds of valid sync + + if (vk_rx_time >= VK_SYNC_WAIT_TIME) { + m_togBtnVoiceKeyer->SetValue(false); + next_state = VK_IDLE; + } + } + break; + + default: + // catch anything we missed + + m_btnTogPTT->SetValue(false); togglePTT(); + m_togBtnVoiceKeyer->SetValue(false); + next_state = VK_IDLE; + } + + fprintf(stderr, "VoiceKeyerProcessEvent: vk_state: %d vk_event: %d next_state: %d\n", vk_state, vk_event, next_state); + vk_state = next_state; +} + + //------------------------------------------------------------------------- // OnTogBtnRxID() //------------------------------------------------------------------------- @@ -1568,6 +1726,15 @@ static wxWindow* createMyExtraPlayFilePanel(wxWindow *parent) return new MyExtraPlayFilePanel(parent); } +void MainFrame::StopPlayFileToMicIn(void) +{ + g_mutexProtectingCallbackData.Lock(); + g_playFileToMicIn = false; + sf_close(g_sfPlayFile); + SetStatusText(wxT("")); + g_mutexProtectingCallbackData.Unlock(); +} + //------------------------------------------------------------------------- // OnPlayFileToMicIn() //------------------------------------------------------------------------- @@ -1575,13 +1742,9 @@ void MainFrame::OnPlayFileToMicIn(wxCommandEvent& event) { wxUnusedVar(event); - if(g_playFileToMicIn) - { - g_mutexProtectingCallbackData.Lock(); - g_playFileToMicIn = false; - sf_close(g_sfPlayFile); - SetStatusText(wxT("")); - g_mutexProtectingCallbackData.Unlock(); + if(g_playFileToMicIn) { + StopPlayFileToMicIn(); + VoiceKeyerProcessEvent(VK_PLAY_FINISHED); } else { diff --git a/freedv-dev/src/fdmdv2_main.h b/freedv-dev/src/fdmdv2_main.h index d963ccb3..34773f8a 100644 --- a/freedv-dev/src/fdmdv2_main.h +++ b/freedv-dev/src/fdmdv2_main.h @@ -120,6 +120,25 @@ extern int g_soundCard2InDeviceNum; extern int g_soundCard2OutDeviceNum; extern int g_soundCard2SampleRate; +// Voice Keyer Constants + +#define VK_SYNC_WAIT_TIME 5.0 + +// Voice Keyer States + +#define VK_IDLE 0 +#define VK_TX 1 +#define VK_RX 2 +#define VK_SYNC_WAIT 3 + +// Voice Keyer Events + +#define VK_START 0 +#define VK_SPACE_BAR 1 +#define VK_PLAY_FINISHED 2 +#define VK_DT 3 +#define VK_SYNC 4 + class MainFrame; //-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=--=-=-=-= @@ -156,8 +175,8 @@ class MainApp : public wxApp bool m_boolHalfDuplex; wxString m_txtVoiceKeyerWaveFile; - wxString m_txtVoiceKeyerRxPause; - wxString m_txtVoiceKeyerRepeats; + int m_intVoiceKeyerRxPause; + int m_intVoiceKeyerRepeats; bool m_boolHamlibUseForPTT; unsigned int m_intHamlibRig; @@ -473,6 +492,7 @@ class MainFrame : public TopFrame void OnToolsOptionsUI(wxUpdateUIEvent& event); void OnPlayFileToMicIn( wxCommandEvent& event ); + void StopPlayFileToMicIn(void); void OnRecFileFromRadio( wxCommandEvent& event ); void OnPlayFileFromRadio( wxCommandEvent& event ); @@ -492,6 +512,7 @@ class MainFrame : public TopFrame void OnTogBtnRxID( wxCommandEvent& event ); void OnTogBtnTxID( wxCommandEvent& event ); void OnTogBtnPTT( wxCommandEvent& event ); + void OnTogBtnVoiceKeyerClick (wxCommandEvent& event); void OnTogBtnOnOff( wxCommandEvent& event ); void OnCallSignReset( wxCommandEvent& event ); @@ -509,6 +530,9 @@ class MainFrame : public TopFrame void OnIdle(wxIdleEvent &evt); #endif + void VoiceKeyerProcessEvent(int vk_event); + int VoiceKeyerStartTx(void); + private: bool m_useMemory; wxTextCtrl* m_tc; @@ -537,6 +561,13 @@ class MainFrame : public TopFrame void* designAnEQFilter(const char filterType[], float freqHz, float gaindB, float Q = 0.0); void designEQFilters(paCallBackData *cb); void deleteEQFilters(paCallBackData *cb); + + // Voice Keyer States + + int vk_state; + int vk_rx_pause; + int vk_repeats, vk_repeat_counter; + float vk_rx_time; }; void txRxProcessing(); diff --git a/freedv-dev/src/topFrame.cpp b/freedv-dev/src/topFrame.cpp index 3a7bb95a..9a1298b7 100644 --- a/freedv-dev/src/topFrame.cpp +++ b/freedv-dev/src/topFrame.cpp @@ -308,7 +308,7 @@ TopFrame::TopFrame(wxWindow* parent, wxWindowID id, const wxString& title, const m_rb700 = new wxRadioButton( this, wxID_ANY, wxT("700"), wxDefaultPosition, wxDefaultSize, wxRB_GROUP); sbSizer_mode->Add(m_rb700, 0, wxALIGN_LEFT|wxALL, 1); #endif - m_rb700b = new wxRadioButton( this, wxID_ANY, wxT("700B"), wxDefaultPosition, wxDefaultSize, 0); + m_rb700b = new wxRadioButton( this, wxID_ANY, wxT("700B"), wxDefaultPosition, wxDefaultSize, wxRB_GROUP); sbSizer_mode->Add(m_rb700b, 0, wxALIGN_LEFT|wxALL, 1); m_rb1600 = new wxRadioButton( this, wxID_ANY, wxT("1600"), wxDefaultPosition, wxDefaultSize, 0); sbSizer_mode->Add(m_rb1600, 0, wxALIGN_LEFT|wxALL, 1);