diff --git a/CMakeLists.txt b/CMakeLists.txt index 8adf24af2..c2dac7fa8 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -102,6 +102,7 @@ set(sdrbase_SOURCES sdrbase/dsp/upchannelizer.cpp sdrbase/dsp/channelmarker.cpp sdrbase/dsp/ctcssdetector.cpp + sdrbase/dsp/cwkeyer.cpp sdrbase/dsp/dspcommands.cpp sdrbase/dsp/dspengine.cpp sdrbase/dsp/dspdevicesourceengine.cpp @@ -194,6 +195,7 @@ set(sdrbase_HEADERS sdrbase/dsp/upchannelizer.h sdrbase/dsp/channelmarker.h sdrbase/dsp/complex.h + sdrbase/dsp/cwkeyer.h sdrbase/dsp/decimators.h sdrbase/dsp/dspcommands.h sdrbase/dsp/dspengine.h diff --git a/sdrbase/dsp/cwkeyer.cpp b/sdrbase/dsp/cwkeyer.cpp new file mode 100644 index 000000000..796ecde33 --- /dev/null +++ b/sdrbase/dsp/cwkeyer.cpp @@ -0,0 +1,293 @@ +/////////////////////////////////////////////////////////////////////////////////// +// Copyright (C) 2016 F4EXB // +// written by Edouard Griffiths // +// // +// This program is free software; you can redistribute it and/or modify // +// it under the terms of the GNU General Public License as published by // +// the Free Software Foundation as version 3 of the License, or // +// // +// This program is distributed in the hope that it will be useful, // +// but WITHOUT ANY WARRANTY; without even the implied warranty of // +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the // +// GNU General Public License V3 for more details. // +// // +// You should have received a copy of the GNU General Public License // +// along with this program. If not, see . // +/////////////////////////////////////////////////////////////////////////////////// + +#include "cwkeyer.h" + +const char m_asciiToMorse[][128] = { + {-1}, // 0 + {-1}, // 1 + {-1}, // 2 + {-1}, // 3 + {-1}, // 4 + {-1}, // 5 + {-1}, // 6 + {-1}, // 7 + {-1}, // 8 + {-1}, // 9 + {-1}, // 10 + {-1}, // 11 + {-1}, // 12 + {-1}, // 13 + {-1}, // 14 + {-1}, // 15 + {-1}, // 16 + {-1}, // 17 + {-1}, // 18 + {-1}, // 19 + {-1}, // 20 + {-1}, // 21 + {-1}, // 22 + {-1}, // 23 + {-1}, // 24 + {-1}, // 25 + {-1}, // 26 + {-1}, // 27 + {-1}, // 28 + {-1}, // 29 + {-1}, // 30 + {-1}, // 31 + {-1}, // 32 + {1,0,1,0,1,1,-1}, // 33 ! + {0,1,0,0,1,0,-1}, // 34 " + {-1}, // 35 + {-1}, // 36 + {-1}, // 37 + {-1}, // 38 + {0,1,1,1,1,0,-1}, // 39 ' + {1,0,1,1,0,1,-1}, // 40 ( + {1,0,1,1,0,1,-1}, // 41 ) + {-1}, // 42 + {0,1,0,1,0,-1}, // 43 + + {1,1,0,0,1,1,-1}, // 44 , + {1,0,0,0,0,1,-1}, // 45 - + {0,1,0,1,0,1,-1}, // 46 . + {1,0,0,1,0,-1}, // 47 / + {1,1,1,1,1,-1}, // 48 0 + {0,1,1,1,1,-1}, // 49 1 + {0,0,1,1,1,-1}, // 50 2 + {0,0,0,1,1,-1}, // 51 3 + {0,0,0,0,1,-1}, // 52 4 + {0,0,0,0,0,-1}, // 53 5 + {1,0,0,0,0,-1}, // 54 6 + {1,1,0,0,0,-1}, // 55 7 + {1,1,1,0,0,-1}, // 56 8 + {1,1,1,1,0,-1}, // 57 9 + {1,1,1,0,0,0,-1}, // 58 : + {1,0,1,0,1,0,-1}, // 59 ; + {-1}, // 60 < + {1,0,0,0,1,-1}, // 61 = + {-1}, // 62 > + {0,0,1,1,0,0,-1}, // 63 ? + {0,1,1,0,1,0,-1}, // 64 @ + {0,1,-1}, // 65 A + {1,0,0,0,-1}, // 66 B + {1,0,1,0,-1}, // 67 C + {1,0,0,-1}, // 68 D + {0,-1}, // 69 E + {0,0,1,0,-1}, // 70 F + {1,1,0,-1}, // 71 G + {0,0,0,0,-1}, // 72 H + {0,0,-1}, // 73 I + {0,1,1,1,-1}, // 74 J + {1,0,1,-1}, // 75 K + {0,1,0,0,-1}, // 76 L + {1,1,-1}, // 77 M + {1,0,-1}, // 78 N + {1,1,1,-1}, // 79 O + {0,1,1,0,-1}, // 80 P + {1,1,0,1,-1}, // 81 Q + {0,1,0,-1}, // 82 R + {0,0,0,-1}, // 83 S + {1,-1}, // 84 T + {0,0,1,-1}, // 85 U + {0,0,0,1,-1}, // 86 V + {0,1,1,-1}, // 87 W + {1,0,0,1,-1}, // 88 X + {1,0,1,1,-1}, // 89 Y + {1,1,0,0,-1}, // 90 Z + {-1}, // 91 [ + {-1}, // 92 \ + {-1}, // 93 ] + {-1}, // 94 ^ + {-1}, // 95 _ + {-1}, // 96 ` + {0,1,-1}, // 97 A + {1,0,0,0,-1}, // 98 B + {1,0,1,0,-1}, // 99 C + {1,0,0,-1}, // 100 D + {0,-1}, // 101 E + {0,0,1,0,-1}, // 102 F + {1,1,0,-1}, // 103 G + {0,0,0,0,-1}, // 104 H + {0,0,-1}, // 105 I + {0,1,1,1,-1}, // 106 J + {1,0,1,-1}, // 107 K + {0,1,0,0,-1}, // 108 L + {1,1,-1}, // 109 M + {1,0,-1}, // 110 N + {1,1,1,-1}, // 111 O + {0,1,1,0,-1}, // 112 P + {1,1,0,1,-1}, // 113 Q + {0,1,0,-1}, // 114 R + {0,0,0,-1}, // 115 S + {1,-1}, // 116 T + {0,0,1,-1}, // 117 U + {0,0,0,1,-1}, // 118 V + {0,1,1,-1}, // 119 W + {1,0,0,1,-1}, // 120 X + {1,0,1,1,-1}, // 121 Y + {1,1,0,0,-1}, // 122 Z + {-1}, // 123 { + {-1}, // 124 | + {-1}, // 125 } + {-1}, // 126 ~ + {-1}, // 127 DEL +}; + +CWKeyer::CWKeyer() : + m_sampleRate(48000), + m_textPointer(0), + m_elementPointer(0), + m_elementSpace(false), + m_characterSpace(false), + m_key(false), + m_dot(false), + m_dash(false), + m_elementOn(false), + m_mode(CWKey), + m_keyState(KeySilent) +{ + setWPM(13); +} + +CWKeyer::~CWKeyer() +{ +} + +void CWKeyer::setWPM(int wpm) +{ + if ((wpm > 0) && (wpm < 21)) + { + m_wpm = wpm; + m_dotLength = (int) (m_sampleRate / (2.4f * wpm)); + } +} + +void CWKeyer::setDot(bool dotOn) +{ + if (dotOn) + { + m_dash = false; + m_dot = true; + } + else + { + m_dot = false; + } +} + +void CWKeyer::setDash(bool dashOn) +{ + if (dashOn) + { + m_dot = false; + m_dash = true; + } + else + { + m_dash = false; + } +} + +int CWKeyer::getSample() +{ + if (m_mode == CWKey) + { + return m_key ? 1 : 0; + } + 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; + } + + return m_key ? 1 : 0; + } +} + diff --git a/sdrbase/dsp/cwkeyer.h b/sdrbase/dsp/cwkeyer.h new file mode 100644 index 000000000..b05890375 --- /dev/null +++ b/sdrbase/dsp/cwkeyer.h @@ -0,0 +1,78 @@ +/////////////////////////////////////////////////////////////////////////////////// +// Copyright (C) 2016 F4EXB // +// written by Edouard Griffiths // +// // +// This program is free software; you can redistribute it and/or modify // +// it under the terms of the GNU General Public License as published by // +// the Free Software Foundation as version 3 of the License, or // +// // +// This program is distributed in the hope that it will be useful, // +// but WITHOUT ANY WARRANTY; without even the implied warranty of // +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the // +// GNU General Public License V3 for more details. // +// // +// You should have received a copy of the GNU General Public License // +// along with this program. If not, see . // +/////////////////////////////////////////////////////////////////////////////////// + +#ifndef SDRBASE_DSP_CWKEYER_H_ +#define SDRBASE_DSP_CWKEYER_H_ + +#include +#include "util/export.h" + +class SDRANGEL_API CWKeyer : public QObject { + Q_OBJECT + +public: + typedef enum + { + CWText, + CWKey, + CWIambic + } CWMode; + + typedef enum + { + KeySilent, + KeyDot, + KeyDash + } CWKeyState; + + CWKeyer(); + ~CWKeyer(); + + void setSampleRate(int sampleRate) { m_sampleRate = sampleRate; } + void setWPM(int wpm); + void setText(QString& text) { m_text = text; } + void setMode(CWMode mode) { m_mode = mode; } + + void setKey(bool key) { m_key = key; }; + void setDot(bool dotOn); + void setDash(bool dashOn); + + int getSample(); + bool eom(); + +private: + int m_sampleRate; + int m_wpm; + int m_dotLength; //!< dot length in samples + QString m_text; + int m_textPointer; + int m_elementPointer; + bool m_elementSpace; + bool m_characterSpace; + bool m_key; + bool m_dot; + bool m_dash; + bool m_elementOn; + CWMode m_mode; + CWKeyState m_keyState; + + static const char m_asciiToMorse[][128]; +}; + + + +#endif /* SDRBASE_DSP_CWKEYER_H_ */ diff --git a/sdrbase/gui/cwkeyergui.ui b/sdrbase/gui/cwkeyergui.ui index 68559172d..10ac04079 100644 --- a/sdrbase/gui/cwkeyergui.ui +++ b/sdrbase/gui/cwkeyergui.ui @@ -1,582 +1,598 @@ - - - GLSpectrumGUI - - - - 0 - 0 - 375 - 60 - - - - - Sans Serif - 8 - - - - Oscilloscope - - - - 2 - - - 2 - - - 2 - - - 2 - - - 3 - - - - - 3 - - - - - - 0 - 0 - - - - - 24 - 24 - - - - Audio tone - - - Histogram - - - - :/mono.png:/mono.png - - - - 16 - 16 - - - - true - - - - - - - - 24 - 24 - - - - Audio tone volume - - - 240 - - - 1 - - - - - - - 1.0 - - - - - - - Qt::Vertical - - - - - - - - 24 - 24 - - - - CW speed (WPM) - - - 0 - - - 20 - - - 1 - - - - - - - CW speed display (WPM) - - - 13 - - - - - - - - 0 - 0 - - - - - 24 - 24 - - - - Morse key - - - Max Hold - - - - :/morsekey.png:/morsekey.png - - - - 16 - 16 - - - - true - - - - - - - - 0 - 0 - - - - - 0 - 0 - - - - - 30 - 16777215 - - - - Morse key assignment - - - - 0 - - - - - 1 - - - - - 2 - - - - - 3 - - - - - 4 - - - - - 5 - - - - - 6 - - - - - 7 - - - - - 8 - - - - - 9 - - - - - - - - - 0 - 0 - - - - - 24 - 24 - - - - Iambic key - - - Max Hold - - - - :/iambickey.png:/iambickey.png - - - - 16 - 16 - - - - true - - - - - - - - 0 - 0 - - - - - 30 - 16777215 - - - - Iambic key dot assignment - - - - 0 - - - - - 1 - - - - - 2 - - - - - 3 - - - - - 4 - - - - - 5 - - - - - 6 - - - - - 7 - - - - - 8 - - - - - 9 - - - - - - - - - 0 - 0 - - - - - 30 - 16777215 - - - - Iambic key dash assignment - - - - 0 - - - - - 1 - - - - - 2 - - - - - 3 - - - - - 4 - - - - - 5 - - - - - 6 - - - - - 7 - - - - - 8 - - - - - 9 - - - - - - - - Qt::Vertical - - - - - - - - 0 - 0 - - - - - 24 - 24 - - - - Play text in a loop - - - Inv - - - - :/playloop.png:/playloop.png - - - - 16 - 16 - - - - true - - - - - - - - 0 - 0 - - - - - 24 - 24 - - - - Play / pause text - - - Waterfall - - - - :/play.png - :/pause.png:/play.png - - - - 16 - 16 - - - - true - - - false - - - - - - - Qt::Horizontal - - - - 40 - 20 - - - - - - - - - - - - CW text - - - - - - - - 24 - 24 - - - - - 24 - 24 - - - - Clear CW text - - - - - - - :/clear.png:/clear.png - - - - 16 - 16 - - - - - - - - - - - ButtonSwitch - QToolButton -
gui/buttonswitch.h
-
-
- - morseKey - playLoop - - - - - -
+ + + CWKeyerGUI + + + + 0 + 0 + 375 + 60 + + + + + Sans Serif + 8 + + + + CW Keyer + + + + 2 + + + 3 + + + + + 3 + + + + + + 0 + 0 + + + + + 24 + 24 + + + + Audio tone + + + Histogram + + + + :/mono.png:/mono.png + + + + 16 + 16 + + + + true + + + + + + + + 24 + 24 + + + + Audio tone volume + + + 240 + + + 1 + + + + + + + + 9 + + + + 1.0 + + + + + + + Qt::Vertical + + + + + + + + 24 + 24 + + + + CW speed (WPM) + + + 0 + + + 20 + + + 1 + + + + + + + + 9 + + + + CW speed display (WPM) + + + 13 + + + + + + + + 0 + 0 + + + + + 24 + 24 + + + + Morse key + + + Max Hold + + + + :/morsekey.png:/morsekey.png + + + + 16 + 16 + + + + true + + + + + + + + 0 + 0 + + + + + 0 + 0 + + + + + 35 + 16777215 + + + + + 9 + + + + Morse key assignment + + + + 0 + + + + + 1 + + + + + 2 + + + + + 3 + + + + + 4 + + + + + 5 + + + + + 6 + + + + + 7 + + + + + 8 + + + + + 9 + + + + + + + + + 0 + 0 + + + + + 24 + 24 + + + + Iambic key + + + Max Hold + + + + :/iambickey.png:/iambickey.png + + + + 16 + 16 + + + + true + + + + + + + + 0 + 0 + + + + + 35 + 16777215 + + + + + 9 + + + + Iambic key dot assignment + + + + 0 + + + + + 1 + + + + + 2 + + + + + 3 + + + + + 4 + + + + + 5 + + + + + 6 + + + + + 7 + + + + + 8 + + + + + 9 + + + + + + + + + 0 + 0 + + + + + 35 + 16777215 + + + + + 9 + + + + Iambic key dash assignment + + + + 0 + + + + + 1 + + + + + 2 + + + + + 3 + + + + + 4 + + + + + 5 + + + + + 6 + + + + + 7 + + + + + 8 + + + + + 9 + + + + + + + + Qt::Vertical + + + + + + + + 0 + 0 + + + + + 24 + 24 + + + + Play text in a loop + + + Inv + + + + :/playloop.png:/playloop.png + + + + 16 + 16 + + + + true + + + + + + + + 0 + 0 + + + + + 24 + 24 + + + + Play / pause text + + + Waterfall + + + + :/play.png + :/pause.png:/play.png + + + + 16 + 16 + + + + true + + + false + + + + + + + Qt::Horizontal + + + + 40 + 20 + + + + + + + + + + + + CW text + + + + + + + + 24 + 24 + + + + + 24 + 24 + + + + Clear CW text + + + + + + + :/clear.png:/clear.png + + + + 16 + 16 + + + + + + + + + + + ButtonSwitch + QToolButton +
gui/buttonswitch.h
+
+
+ + morseKey + playLoop + + + + + +