diff --git a/sdrbase/dsp/cwkeyer.cpp b/sdrbase/dsp/cwkeyer.cpp
index 796ecde33..e3de686b8 100644
--- a/sdrbase/dsp/cwkeyer.cpp
+++ b/sdrbase/dsp/cwkeyer.cpp
@@ -15,8 +15,14 @@
// along with this program. If not, see . //
///////////////////////////////////////////////////////////////////////////////////
+#include
#include "cwkeyer.h"
+/**
+ * 0: dot
+ * 1: dash
+ * -1: end of sequence
+ */
const char m_asciiToMorse[][128] = {
{-1}, // 0
{-1}, // 1
@@ -50,7 +56,7 @@ const char m_asciiToMorse[][128] = {
{-1}, // 29
{-1}, // 30
{-1}, // 31
- {-1}, // 32
+ {-1}, // 32 space is treated as word separator
{1,0,1,0,1,1,-1}, // 33 !
{0,1,0,0,1,0,-1}, // 34 "
{-1}, // 35
@@ -115,7 +121,7 @@ const char m_asciiToMorse[][128] = {
{-1}, // 94 ^
{-1}, // 95 _
{-1}, // 96 `
- {0,1,-1}, // 97 A
+ {0,1,-1}, // 97 A lowercase same as uppercase
{1,0,0,0,-1}, // 98 B
{1,0,1,0,-1}, // 99 C
{1,0,0,-1}, // 100 D
@@ -151,15 +157,18 @@ const char m_asciiToMorse[][128] = {
CWKeyer::CWKeyer() :
m_sampleRate(48000),
m_textPointer(0),
- m_elementPointer(0),
+ m_elementPointer(0),
+ m_samplePointer(0),
m_elementSpace(false),
m_characterSpace(false),
m_key(false),
m_dot(false),
m_dash(false),
m_elementOn(false),
+ m_asciiChar('\0'),
m_mode(CWKey),
- m_keyState(KeySilent)
+ m_keyIambicState(KeySilent),
+ m_textState(TextStart)
{
setWPM(13);
}
@@ -211,83 +220,212 @@ int CWKeyer::getSample()
}
else if (m_mode == CWIambic)
{
- switch (m_keyState)
- {
- case KeySilent:
- if (m_dot)
- {
- m_keyState = KeyDot;
- m_elementPointer = 0;
- }
- else if (m_dash)
- {
- m_keyState = KeyDash;
- m_elementPointer = 0;
- }
-
- m_key = false;
- break;
- case KeyDot:
- if (m_elementPointer < m_dotLength) // dot key
- {
- m_key = true;
- m_elementPointer++;
- }
- else if (m_elementPointer < 2*m_dotLength) // dot silence
- {
- m_key = false;
- m_elementPointer++;
- }
- else // end
- {
- if (m_dash)
- {
- m_elementPointer = 0;
- m_keyState = KeyDash;
- }
- else if (!m_dot)
- {
- m_keyState = KeySilent;
- }
-
- m_elementPointer = 0;
- m_key = false;
- }
- break;
- case KeyDash:
- if (m_elementPointer < 3*m_dotLength) // dash key
- {
- m_key = true;
- m_elementPointer++;
- }
- else if (m_elementPointer < 4*m_dotLength) // dash silence
- {
- m_key = false;
- m_elementPointer++;
- }
- else // end
- {
- if (m_dot)
- {
- m_elementPointer = 0;
- m_keyState = KeyDot;
- }
- else if (!m_dash)
- {
- m_keyState = KeySilent;
- }
-
- m_elementPointer = 0;
- m_key = false;
- }
- break;
- default:
- m_elementPointer = 0;
- m_key = false;
- break;
- }
-
+ nextStateIambic();
return m_key ? 1 : 0;
}
+ else if (m_mode == CWText)
+ {
+ nextStateText();
+ return m_key ? 1 : 0;
+ }
+ else
+ {
+ return 0;
+ }
}
+void CWKeyer::nextStateIambic()
+{
+ switch (m_keyIambicState)
+ {
+ case KeySilent:
+ if (m_dot)
+ {
+ m_keyIambicState = KeyDot;
+ m_samplePointer = 0;
+ }
+ else if (m_dash)
+ {
+ m_keyIambicState = KeyDash;
+ m_samplePointer = 0;
+ }
+
+ m_key = false;
+ break;
+ case KeyDot:
+ if (m_samplePointer < m_dotLength) // dot key
+ {
+ m_key = true;
+ m_samplePointer++;
+ }
+ else if (m_samplePointer < 2*m_dotLength) // dot silence (+1 dot length)
+ {
+ m_key = false;
+ m_samplePointer++;
+ }
+ else // end
+ {
+ if (m_dash)
+ {
+ m_samplePointer = 0;
+ m_keyIambicState = KeyDash;
+ }
+ else if (!m_dot)
+ {
+ m_keyIambicState = KeySilent;
+ }
+
+ m_samplePointer = 0;
+ m_key = false;
+ }
+ break;
+ case KeyDash:
+ if (m_samplePointer < 3*m_dotLength) // dash key
+ {
+ m_key = true;
+ m_samplePointer++;
+ }
+ else if (m_samplePointer < 4*m_dotLength) // dash silence (+1 dot length)
+ {
+ m_key = false;
+ m_samplePointer++;
+ }
+ else // end
+ {
+ if (m_dot)
+ {
+ m_samplePointer = 0;
+ m_keyIambicState = KeyDot;
+ }
+ else if (!m_dash)
+ {
+ m_keyIambicState = KeySilent;
+ }
+
+ m_samplePointer = 0;
+ m_key = false;
+ }
+ break;
+ default:
+ m_samplePointer = 0;
+ m_key = false;
+ break;
+ }
+}
+
+
+void CWKeyer::nextStateText()
+{
+ // TODO...
+ switch (m_textState)
+ {
+ case TextStart:
+ m_samplePointer = 0;
+ m_elementPointer = 0;
+ m_textPointer = 0;
+ m_textState = TextStartChar;
+ nextStateText();
+ break;
+ case TextStartChar:
+ m_samplePointer = 0;
+ m_elementPointer = 0;
+ m_textState = TextStartElement;
+ break;
+ case TextStartElement:
+ m_samplePointer = 0;
+ m_textState = TextElement;
+ break;
+ case TextElement:
+ nextStateIambic(); // dash or dot
+ if (m_samplePointer == 0) // done
+ {
+ m_textState = TextStartElement; // next element
+ }
+ break;
+ case TextCharSpace:
+ if (m_samplePointer < 3*m_dotLength)
+ {
+ m_samplePointer++;
+ m_key = false;
+ }
+ else
+ {
+ m_samplePointer = 0;
+ m_textState = TextStartChar;
+ }
+ break;
+ case TextWordSpace:
+ if (m_samplePointer < 7*m_dotLength)
+ {
+ m_samplePointer++;
+ m_key = false;
+ }
+ else
+ {
+ m_samplePointer = 0;
+ m_textState = TextStartChar;
+ }
+ break;
+ case TextEnd:
+ default:
+ m_key = false;
+ break;
+ }
+
+
+ if (m_samplePointer == 0) // element not started or finished
+ {
+ if (m_asciiToMorse[m_elementPointer][m_asciiChar] == -1) // end of morse symbol
+ {
+ m_keyIambicState = KeyCharSpace;
+ m_samplePointer++;
+ m_key = false;
+ }
+ else
+ {
+ if (m_asciiToMorse[m_elementPointer][m_asciiChar] == 0) // dot
+ {
+ m_dot = true;
+ m_dash = false;
+ }
+ else // dash
+ {
+ m_dot = false;
+ m_dash = true;
+ }
+
+ nextStateIambic();
+ }
+
+ if (m_textPointer < m_text.length())
+ {
+ m_asciiChar = (m_text[m_textPointer]).toAscii();
+
+ if (m_asciiChar < 0) {
+ m_asciiChar = 0;
+ }
+
+ m_elementPointer = 0;
+ m_textPointer++;
+ }
+ else
+ {
+ // TODO: end of text
+ }
+ }
+ else
+ {
+ if ((m_keyIambicState == KeyDot) || (m_keyIambicState == KeyDash))
+ {
+ nextStateIambic();
+ }
+ else if (m_keyIambicState == KeyCharSpace)
+ {
+ if (m_samplePointer < 2*m_dotLength) // rest of a dash period (+2 dot periods)
+ {
+ m_samplePointer++;
+ m_key = false;
+ }
+ }
+ }
+}
diff --git a/sdrbase/dsp/cwkeyer.h b/sdrbase/dsp/cwkeyer.h
index b05890375..b1f844795 100644
--- a/sdrbase/dsp/cwkeyer.h
+++ b/sdrbase/dsp/cwkeyer.h
@@ -37,7 +37,18 @@ public:
KeySilent,
KeyDot,
KeyDash
- } CWKeyState;
+ } CWKeyIambicState;
+
+ typedef enum
+ {
+ TextStart,
+ TextStartChar,
+ TextStartElement,
+ TextElement,
+ TextCharSpace,
+ TextWordSpace,
+ TextEnd
+ } CWTextState;
CWKeyer();
~CWKeyer();
@@ -61,16 +72,22 @@ private:
QString m_text;
int m_textPointer;
int m_elementPointer;
+ int m_samplePointer;
bool m_elementSpace;
bool m_characterSpace;
bool m_key;
bool m_dot;
bool m_dash;
bool m_elementOn;
+ char m_asciiChar;
CWMode m_mode;
- CWKeyState m_keyState;
+ CWKeyIambicState m_keyIambicState;
+ CWTextState m_textState;
static const char m_asciiToMorse[][128];
+
+ void nextStateIambic();
+ void nextStateText();
};