voice keyer coded, builds OK, but not tested
authordrowe67 <drowe67@01035d8c-6547-0410-b346-abe4f91aad63>
Mon, 14 Sep 2015 04:35:19 +0000 (04:35 +0000)
committerdrowe67 <drowe67@01035d8c-6547-0410-b346-abe4f91aad63>
Mon, 14 Sep 2015 04:35:19 +0000 (04:35 +0000)
git-svn-id: https://svn.code.sf.net/p/freetel/code@2324 01035d8c-6547-0410-b346-abe4f91aad63

freedv-dev/src/dlg_ptt.cpp
freedv-dev/src/fdmdv2_main.cpp
freedv-dev/src/fdmdv2_main.h
freedv-dev/src/topFrame.cpp

index f3bdb4d8bf7e2f21eaaf02c5b14157692d95581c..8964587ae8fd0d1fbe93b9fca0e04f87e1f968b6 100644 (file)
@@ -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. */
 
index f3a24042eacb31ebf9b86b90e902676d6e9701da..3dc38c907b97690965688c0a9f34831e71c839db 100644 (file)
@@ -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
     {
index d963ccb362eb4e6c3ecd6d6ea513247b1c41de60..34773f8a1c177e6bd8ae3d949687a5a3034d7905 100644 (file)
@@ -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();
index 3a7bb95a20e4fbb4e410a8d013b3dcd8939ed9f7..9a1298b78851f9b669e1db36075fac2dc50b629d 100644 (file)
@@ -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);