1
0
mirror of https://github.com/f4exb/sdrangel.git synced 2024-11-26 09:48:45 -05:00

CW Keyer: interim state (2)

This commit is contained in:
f4exb 2016-12-09 19:34:38 +01:00
parent 35baa46f3d
commit 808a8c85fd
2 changed files with 237 additions and 82 deletions

View File

@ -15,8 +15,14 @@
// along with this program. If not, see <http://www.gnu.org/licenses/>. //
///////////////////////////////////////////////////////////////////////////////////
#include <QChar>
#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
@ -152,14 +158,17 @@ CWKeyer::CWKeyer() :
m_sampleRate(48000),
m_textPointer(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)
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_keyState = KeyDot;
m_elementPointer = 0;
m_keyIambicState = KeyDot;
m_samplePointer = 0;
}
else if (m_dash)
{
m_keyState = KeyDash;
m_elementPointer = 0;
m_keyIambicState = KeyDash;
m_samplePointer = 0;
}
m_key = false;
break;
case KeyDot:
if (m_elementPointer < m_dotLength) // dot key
if (m_samplePointer < m_dotLength) // dot key
{
m_key = true;
m_elementPointer++;
m_samplePointer++;
}
else if (m_elementPointer < 2*m_dotLength) // dot silence
else if (m_samplePointer < 2*m_dotLength) // dot silence (+1 dot length)
{
m_key = false;
m_elementPointer++;
m_samplePointer++;
}
else // end
{
if (m_dash)
{
m_elementPointer = 0;
m_keyState = KeyDash;
m_samplePointer = 0;
m_keyIambicState = KeyDash;
}
else if (!m_dot)
{
m_keyState = KeySilent;
m_keyIambicState = KeySilent;
}
m_elementPointer = 0;
m_samplePointer = 0;
m_key = false;
}
break;
case KeyDash:
if (m_elementPointer < 3*m_dotLength) // dash key
if (m_samplePointer < 3*m_dotLength) // dash key
{
m_key = true;
m_elementPointer++;
m_samplePointer++;
}
else if (m_elementPointer < 4*m_dotLength) // dash silence
else if (m_samplePointer < 4*m_dotLength) // dash silence (+1 dot length)
{
m_key = false;
m_elementPointer++;
m_samplePointer++;
}
else // end
{
if (m_dot)
{
m_elementPointer = 0;
m_keyState = KeyDot;
m_samplePointer = 0;
m_keyIambicState = KeyDot;
}
else if (!m_dash)
{
m_keyState = KeySilent;
m_keyIambicState = KeySilent;
}
m_elementPointer = 0;
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;
}
return m_key ? 1 : 0;
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;
}
}
}
}

View File

@ -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();
};