SDRAngel  4.11.5
Developer docs for <a href="https://github.com/f4exb/sdrangel">SDRangel<\a>, an Open Source Qt5 / OpenGL 3.0+ SDR and signal analyzer frontend to various hardware.
cwkeyer.cpp
Go to the documentation of this file.
1 // Copyright (C) 2016 F4EXB //
3 // written by Edouard Griffiths //
4 // //
5 // This program is free software; you can redistribute it and/or modify //
6 // it under the terms of the GNU General Public License as published by //
7 // the Free Software Foundation as version 3 of the License, or //
8 // (at your option) any later version. //
9 // //
10 // This program is distributed in the hope that it will be useful, //
11 // but WITHOUT ANY WARRANTY; without even the implied warranty of //
12 // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the //
13 // GNU General Public License V3 for more details. //
14 // //
15 // You should have received a copy of the GNU General Public License //
16 // along with this program. If not, see <http://www.gnu.org/licenses/>. //
18 
19 #include <stdint.h>
20 #include <QChar>
21 #include <QDebug>
22 #include "cwkeyer.h"
23 #include "util/stepfunctions.h"
24 
26 
27 
32 const signed char CWKeyer::m_asciiToMorse[128][7] = {
33  {-1,0,0,0,0,0,0}, // 0
34  {-1,0,0,0,0,0,0}, // 1
35  {-1,0,0,0,0,0,0}, // 2
36  {-1,0,0,0,0,0,0}, // 3
37  {-1,0,0,0,0,0,0}, // 4
38  {-1,0,0,0,0,0,0}, // 5
39  {-1,0,0,0,0,0,0}, // 6
40  {-1,0,0,0,0,0,0}, // 7
41  {-1,0,0,0,0,0,0}, // 8
42  {-1,0,0,0,0,0,0}, // 9
43  {-1,0,0,0,0,0,0}, // 10
44  {-1,0,0,0,0,0,0}, // 11
45  {-1,0,0,0,0,0,0}, // 12
46  {-1,0,0,0,0,0,0}, // 13
47  {-1,0,0,0,0,0,0}, // 14
48  {-1,0,0,0,0,0,0}, // 15
49  {-1,0,0,0,0,0,0}, // 16
50  {-1,0,0,0,0,0,0}, // 17
51  {-1,0,0,0,0,0,0}, // 18
52  {-1,0,0,0,0,0,0}, // 19
53  {-1,0,0,0,0,0,0}, // 20
54  {-1,0,0,0,0,0,0}, // 21
55  {-1,0,0,0,0,0,0}, // 22
56  {-1,0,0,0,0,0,0}, // 23
57  {-1,0,0,0,0,0,0}, // 24
58  {-1,0,0,0,0,0,0}, // 25
59  {-1,0,0,0,0,0,0}, // 26
60  {-1,0,0,0,0,0,0}, // 27
61  {-1,0,0,0,0,0,0}, // 28
62  {-1,0,0,0,0,0,0}, // 29
63  {-1,0,0,0,0,0,0}, // 30
64  {-1,0,0,0,0,0,0}, // 31
65  {-1,0,0,0,0,0,0}, // 32 space is treated as word separator
66  {1,0,1,0,1,1,-1}, // 33 !
67  {0,1,0,0,1,0,-1}, // 34 "
68  {-1,0,0,0,0,0,0}, // 35
69  {-1,0,0,0,0,0,0}, // 36
70  {-1,0,0,0,0,0,0}, // 37
71  {-1,0,0,0,0,0,0}, // 38
72  {0,1,1,1,1,0,-1}, // 39 '
73  {1,0,1,1,0,1,-1}, // 40 (
74  {1,0,1,1,0,1,-1}, // 41 )
75  {-1,0,0,0,0,0,0}, // 42
76  {0,1,0,1,0,-1,0}, // 43 +
77  {1,1,0,0,1,1,-1}, // 44 ,
78  {1,0,0,0,0,1,-1}, // 45 -
79  {0,1,0,1,0,1,-1}, // 46 .
80  {1,0,0,1,0,-1,0}, // 47 /
81  {1,1,1,1,1,-1,0}, // 48 0
82  {0,1,1,1,1,-1,0}, // 49 1
83  {0,0,1,1,1,-1,0}, // 50 2
84  {0,0,0,1,1,-1,0}, // 51 3
85  {0,0,0,0,1,-1,0}, // 52 4
86  {0,0,0,0,0,-1,0}, // 53 5
87  {1,0,0,0,0,-1,0}, // 54 6
88  {1,1,0,0,0,-1,0}, // 55 7
89  {1,1,1,0,0,-1,0}, // 56 8
90  {1,1,1,1,0,-1,0}, // 57 9
91  {1,1,1,0,0,0,-1}, // 58 :
92  {1,0,1,0,1,0,-1}, // 59 ;
93  {-1,0,0,0,0,0,0}, // 60 <
94  {1,0,0,0,1,-1,0}, // 61 =
95  {-1,0,0,0,0,0,0}, // 62 >
96  {0,0,1,1,0,0,-1}, // 63 ?
97  {0,1,1,0,1,0,-1}, // 64 @
98  {0,1,-1,0,0,0,0}, // 65 A
99  {1,0,0,0,-1,0,0}, // 66 B
100  {1,0,1,0,-1,0,0}, // 67 C
101  {1,0,0,-1,0,0,0}, // 68 D
102  {0,-1,0,0,0,0,0}, // 69 E
103  {0,0,1,0,-1,0,0}, // 70 F
104  {1,1,0,-1,0,0,0}, // 71 G
105  {0,0,0,0,-1,0,0}, // 72 H
106  {0,0,-1,0,0,0,0}, // 73 I
107  {0,1,1,1,-1,0,0}, // 74 J
108  {1,0,1,-1,0,0,0}, // 75 K
109  {0,1,0,0,-1,0,0}, // 76 L
110  {1,1,-1,0,0,0,0}, // 77 M
111  {1,0,-1,0,0,0,0}, // 78 N
112  {1,1,1,-1,0,0,0}, // 79 O
113  {0,1,1,0,-1,0,0}, // 80 P
114  {1,1,0,1,-1,0,0}, // 81 Q
115  {0,1,0,-1,0,0,0}, // 82 R
116  {0,0,0,-1,0,0,0}, // 83 S
117  {1,-1,0,0,0,0,0}, // 84 T
118  {0,0,1,-1,0,0,0}, // 85 U
119  {0,0,0,1,-1,0,0}, // 86 V
120  {0,1,1,-1,0,0,0}, // 87 W
121  {1,0,0,1,-1,0,0}, // 88 X
122  {1,0,1,1,-1,0,0}, // 89 Y
123  {1,1,0,0,-1,0,0}, // 90 Z
124  {-1,0,0,0,0,0,0}, // 91 [
125  {-1,0,0,0,0,0,0}, // 92 back /
126  {-1,0,0,0,0,0,0}, // 93 ]
127  {-1,0,0,0,0,0,0}, // 94 ^
128  {-1,0,0,0,0,0,0}, // 95 _
129  {-1,0,0,0,0,0,0}, // 96 `
130  {0,1,-1,0,0,0,0}, // 97 A lowercase same as uppercase
131  {1,0,0,0,-1,0,0}, // 98 B
132  {1,0,1,0,-1,0,0}, // 99 C
133  {1,0,0,-1,0,0,0}, // 100 D
134  {0,-1,0,0,0,0,0}, // 101 E
135  {0,0,1,0,-1,0,0}, // 102 F
136  {1,1,0,-1,0,0,0}, // 103 G
137  {0,0,0,0,-1,0,0}, // 104 H
138  {0,0,-1,0,0,0,0}, // 105 I
139  {0,1,1,1,-1,0,0}, // 106 J
140  {1,0,1,-1,0,0,0}, // 107 K
141  {0,1,0,0,-1,0,0}, // 108 L
142  {1,1,-1,0,0,0,0}, // 109 M
143  {1,0,-1,0,0,0,0}, // 110 N
144  {1,1,1,-1,0,0,0}, // 111 O
145  {0,1,1,0,-1,0,0}, // 112 P
146  {1,1,0,1,-1,0,0}, // 113 Q
147  {0,1,0,-1,0,0,0}, // 114 R
148  {0,0,0,-1,0,0,0}, // 115 S
149  {1,-1,0,0,0,0,0}, // 116 T
150  {0,0,1,-1,0,0,0}, // 117 U
151  {0,0,0,1,-1,0,0}, // 118 V
152  {0,1,1,-1,0,0,0}, // 119 W
153  {1,0,0,1,-1,0,0}, // 120 X
154  {1,0,1,1,-1,0,0}, // 121 Y
155  {1,1,0,0,-1,0,0}, // 122 Z
156  {-1,0,0,0,0,0,0}, // 123 {
157  {-1,0,0,0,0,0,0}, // 124 |
158  {-1,0,0,0,0,0,0}, // 125 }
159  {-1,0,0,0,0,0,0}, // 126 ~
160  {-1,0,0,0,0,0,0}, // 127 DEL
161 };
162 
164  m_mutex(QMutex::Recursive),
165  m_textPointer(0),
166  m_elementPointer(0),
167  m_samplePointer(0),
168  m_elementSpace(false),
169  m_characterSpace(false),
170  m_key(false),
171  m_dot(false),
172  m_dash(false),
173  m_elementOn(false),
174  m_asciiChar('\0'),
175  m_keyIambicState(KeySilent),
176  m_textState(TextStart)
177 {
178  connect(&m_inputMessageQueue, SIGNAL(messageEnqueued()), this, SLOT(handleInputMessages()));
179  applySettings(m_settings, true);
180 }
181 
183 {
184 }
185 
186 void CWKeyer::setSampleRate(int sampleRate)
187 {
188  CWKeyerSettings settings = m_settings;
189  settings.m_sampleRate = sampleRate;
190  MsgConfigureCWKeyer *msg = MsgConfigureCWKeyer::create(settings, false);
192 }
193 
195 {
196  QMutexLocker mutexLocker(&m_mutex);
197 
199  {
200  nextStateText();
201  return m_key ? 1 : 0;
202  }
204  {
205  nextStateIambic();
206  return m_key ? 1 : 0;
207  }
209  {
211  {
212  nextStateIambic();
213  return m_key ? 1 : 0;
214  }
215  else
216  {
217  return (m_dot || m_dash) ? 1 : 0;
218  }
219  }
220  else
221  {
222  return 0;
223  }
224 }
225 
227 {
228  switch (m_keyIambicState)
229  {
230  case KeySilent:
231  if (m_dot)
232  {
234  m_samplePointer = 0;
235  }
236  else if (m_dash)
237  {
239  m_samplePointer = 0;
240  }
241 
242  m_key = false;
243  break;
244  case KeyDot:
245  if (m_samplePointer < m_dotLength) // dot key
246  {
247  m_key = true;
248  m_samplePointer++;
249  }
250  else if (m_samplePointer < 2*m_dotLength) // dot silence (+1 dot length)
251  {
252  m_key = false;
253  m_samplePointer++;
254  }
255  else // end
256  {
257  if (m_dash)
258  {
260  }
261  else if (!m_dot)
262  {
264  }
265 
266  m_samplePointer = 0;
267  m_key = false;
268  }
269  break;
270  case KeyDash:
271  if (m_samplePointer < 3*m_dotLength) // dash key
272  {
273  m_key = true;
274  m_samplePointer++;
275  }
276  else if (m_samplePointer < 4*m_dotLength) // dash silence (+1 dot length)
277  {
278  m_key = false;
279  m_samplePointer++;
280  }
281  else // end
282  {
283  if (m_dot)
284  {
286  }
287  else if (!m_dash)
288  {
290  }
291 
292  m_samplePointer = 0;
293  m_key = false;
294  }
295  break;
296  default:
297  m_samplePointer = 0;
298  m_key = false;
299  break;
300  }
301 }
302 
304 {
305  switch (m_textState)
306  {
307  case TextStart:
308  m_samplePointer = 0;
309  m_elementPointer = 0;
310  m_textPointer = 0;
312  m_key = false;
313  m_dot = false;
314  m_dash = false;
315  break;
316  case TextStartChar:
317  m_samplePointer = 0;
318  m_elementPointer = 0;
319  if (m_textPointer < m_settings.m_text.length())
320  {
321  m_asciiChar = (m_settings.m_text.at(m_textPointer)).toLatin1();
322 // qDebug() << "CWKeyer::nextStateText: TextStartChar: " << m_asciiChar;
323 
324  if (m_asciiChar < 0) { // non ASCII
325  m_asciiChar = 0;
326  }
327 
328  if (m_asciiChar == ' ')
329  {
331  }
332  else
333  {
335  }
336  m_textPointer++;
337  }
338  else // end of text
339  {
341  }
342  break;
343  case TextStartElement:
344  m_samplePointer = 0;
345 // qDebug() << "CWKeyer::nextStateText: TextStartElement: " << (int) m_asciiToMorse[m_asciiChar][m_elementPointer];
346  if (m_asciiToMorse[(uint8_t)(m_asciiChar&0x7F)][m_elementPointer] == -1) // end of morse character
347  {
348  m_elementPointer = 0;
350  }
351  else
352  {
353  if (m_asciiToMorse[(uint8_t)(m_asciiChar&0x7F)][m_elementPointer] == 0) // dot
354  {
355  m_dot = true;
356  m_dash = false;
357  }
358  else // dash
359  {
360  m_dot = false;
361  m_dash = true;
362  }
363  m_keyIambicState = KeySilent; // reset iambic state
364  nextStateIambic(); // init dash or dot
365  m_dot = false; // release keys
366  m_dash = false;
369  }
370  break;
371  case TextElement:
372  nextStateIambic(); // dash or dot
373  if (m_keyIambicState == KeySilent) // done
374  {
375  m_textState = TextStartElement; // next element
376  }
377  break;
378  case TextCharSpace:
379  if (m_samplePointer < 2*m_dotLength) // - 1 dot length space from element
380  {
381  m_samplePointer++;
382  m_key = false;
383  }
384  else
385  {
387  }
388  break;
389  case TextWordSpace:
390  if (m_samplePointer < 4*m_dotLength) // - 3 dot length space from character
391  {
392  m_samplePointer++;
393  m_key = false;
394  }
395  else
396  {
398  }
399  break;
400  case TextEnd:
401  if (m_settings.m_loop)
402  {
404  }
405  m_key = false;
406  m_dot = false;
407  m_dash = false;
408  break;
409  case TextStop:
410  default:
411  m_key = false;
412  m_dot = false;
413  m_dash = false;
414  break;
415  }
416 }
417 
419 {
420  return !(m_textPointer < m_settings.m_text.length());
421 }
422 
424 {
425  m_dot = true;
426  m_dash = false;
428 }
429 
431 {
432  m_dot = false;
433  m_dash = true;
435 }
436 
438 {
439  m_dot = false;
440  m_dash = false;
441 }
442 
444  m_fadeInCounter(0),
445  m_fadeOutCounter(0),
446  m_nbFadeSamples(0),
447  m_fadeInSamples(0),
448  m_fadeOutSamples(0)
449 {
450  setNbFadeSamples(192); // default is 4 ms at 48 kHz sample rate
451 }
452 
454 {
455  delete[] m_fadeInSamples;
456  delete[] m_fadeOutSamples;
457 }
458 
459 void CWSmoother::setNbFadeSamples(unsigned int nbFadeSamples)
460 {
461  if (nbFadeSamples != m_nbFadeSamples)
462  {
463  QMutexLocker mutexLocker(&m_mutex);
464 
465  m_nbFadeSamples = nbFadeSamples;
466 
467  if (m_fadeInSamples) delete[] m_fadeInSamples;
468  if (m_fadeOutSamples) delete[] m_fadeOutSamples;
469 
470  m_fadeInSamples = new float[m_nbFadeSamples];
471  m_fadeOutSamples = new float[m_nbFadeSamples];
472 
473  for (unsigned int i = 0; i < m_nbFadeSamples; i++)
474  {
475  float x = i/ (float) m_nbFadeSamples;
476  float y = 1.0f -x;
477 
480  }
481 
482  m_fadeInCounter = 0;
483  m_fadeOutCounter = 0;
484  }
485 }
486 
487 bool CWSmoother::getFadeSample(bool on, float& sample)
488 {
489  QMutexLocker mutexLocker(&m_mutex);
490 
491  if (on)
492  {
493  m_fadeOutCounter = 0;
494 
496  {
498  m_fadeInCounter++;
499  return true;
500  }
501  else
502  {
503  sample = 1.0f;
504  return false;
505  }
506  }
507  else
508  {
509  m_fadeInCounter = 0;
510 
512  {
515  return true;
516  }
517  else
518  {
519  sample = 0.0f;
520  return false;
521  }
522  }
523 }
524 
526 {
527  if (MsgConfigureCWKeyer::match(cmd))
528  {
530  qDebug() << "CWKeyer::handleMessage: MsgConfigureCWKeyer";
531 
532  applySettings(cfg.getSettings(), cfg.getForce());
533 
534  return true;
535  }
536 
537  return true;
538 }
539 
541 {
542  Message* message;
543 
544  while ((message = m_inputMessageQueue.pop()) != 0)
545  {
546  if (handleMessage(*message)) {
547  delete message;
548  }
549  }
550 }
551 
552 void CWKeyer::applySettings(const CWKeyerSettings& settings, bool force)
553 {
554  if ((m_settings.m_wpm != settings.m_wpm)
555  || (m_settings.m_sampleRate != settings.m_sampleRate) || force)
556  {
557  QMutexLocker mutexLocker(&m_mutex);
558  m_dotLength = (int) (0.24f * settings.m_sampleRate * (5.0f / settings.m_wpm));
559  m_cwSmoother.setNbFadeSamples(m_dotLength/5); // 20% the dot time
560  }
561 
562  if ((m_settings.m_mode != settings.m_mode) || force)
563  {
564  QMutexLocker mutexLocker(&m_mutex);
565 
566  if (settings.m_mode == CWKeyerSettings::CWText)
567  {
568  m_textState = TextStart;
569  }
570  else if (settings.m_mode == CWKeyerSettings::CWDots)
571  {
572  m_dot = true;
573  m_dash = false;
574  m_keyIambicState = KeySilent;
575  }
576  else if (settings.m_mode == CWKeyerSettings::CWDashes)
577  {
578  m_dot = false;
579  m_dash = true;
580  m_keyIambicState = KeySilent;
581  }
582  else if (settings.m_mode == CWKeyerSettings::CWKeyboard)
583  {
584  m_dot = false;
585  m_dash = false;
586  m_keyIambicState = KeySilent;
587  }
588  }
589 
590  if ((m_settings.m_text != settings.m_text) || force)
591  {
592  QMutexLocker mutexLocker(&m_mutex);
593  m_textState = TextStart;
594  }
595 
596  m_settings = settings;
597 }
598 
600  const QStringList& channelSettingsKeys,
601  CWKeyerSettings& cwKeyerSettings,
602  SWGSDRangel::SWGCWKeyerSettings *apiCwKeyerSettings
603 )
604 {
605  if (channelSettingsKeys.contains("cwKeyer.loop")) {
606  cwKeyerSettings.m_loop = apiCwKeyerSettings->getLoop() != 0;
607  }
608  if (channelSettingsKeys.contains("cwKeyer.mode")) {
609  cwKeyerSettings.m_mode = (CWKeyerSettings::CWMode) apiCwKeyerSettings->getMode();
610  }
611  if (channelSettingsKeys.contains("cwKeyer.text")) {
612  cwKeyerSettings.m_text = *apiCwKeyerSettings->getText();
613  }
614  if (channelSettingsKeys.contains("cwKeyer.sampleRate")) {
615  cwKeyerSettings.m_sampleRate = apiCwKeyerSettings->getSampleRate();
616  }
617  if (channelSettingsKeys.contains("cwKeyer.wpm")) {
618  cwKeyerSettings.m_wpm = apiCwKeyerSettings->getWpm();
619  }
620  if (channelSettingsKeys.contains("cwKeyer.keyboardIambic")) {
621  cwKeyerSettings.m_wpm = apiCwKeyerSettings->getKeyboardIambic() != 0;
622  }
623  if (channelSettingsKeys.contains("cwKeyer.dotKey")) {
624  cwKeyerSettings.m_dotKey = (Qt::Key) apiCwKeyerSettings->getDotKey();
625  }
626  if (channelSettingsKeys.contains("cwKeyer.dotKeyModifiers")) {
627  cwKeyerSettings.m_dotKeyModifiers = (Qt::KeyboardModifiers) apiCwKeyerSettings->getDotKeyModifiers();
628  }
629  if (channelSettingsKeys.contains("cwKeyer.dashKey")) {
630  cwKeyerSettings.m_dashKey = (Qt::Key) apiCwKeyerSettings->getDashKey();
631  }
632  if (channelSettingsKeys.contains("cwKeyer.dashKeyModifiers")) {
633  cwKeyerSettings.m_dashKeyModifiers = (Qt::KeyboardModifiers) apiCwKeyerSettings->getDashKeyModifiers();
634  }
635 }
636 
638  SWGSDRangel::SWGCWKeyerSettings *apiCwKeyerSettings,
639  const CWKeyerSettings& cwKeyerSettings
640 )
641 {
642  apiCwKeyerSettings->setLoop(cwKeyerSettings.m_loop ? 1 : 0);
643  apiCwKeyerSettings->setMode((int) cwKeyerSettings.m_mode);
644  apiCwKeyerSettings->setSampleRate(cwKeyerSettings.m_sampleRate);
645 
646  if (apiCwKeyerSettings->getText()) {
647  *apiCwKeyerSettings->getText() = cwKeyerSettings.m_text;
648  } else {
649  apiCwKeyerSettings->setText(new QString(cwKeyerSettings.m_text));
650  }
651 
652  apiCwKeyerSettings->setWpm(cwKeyerSettings.m_wpm);
653  apiCwKeyerSettings->setKeyboardIambic(cwKeyerSettings.m_keyboardIambic ? 1 : 0);
654  apiCwKeyerSettings->setDotKey((int) cwKeyerSettings.m_dotKey);
655  apiCwKeyerSettings->setDotKeyModifiers((unsigned int) cwKeyerSettings.m_dotKeyModifiers);
656  apiCwKeyerSettings->setDashKey((int) cwKeyerSettings.m_dashKey);
657  apiCwKeyerSettings->setDashKeyModifiers((unsigned int) cwKeyerSettings.m_dashKeyModifiers);
658 }
void push(Message *message, bool emitSignal=true)
Push message onto queue.
bool m_dash
Definition: cwkeyer.h:143
signed char m_asciiChar
Definition: cwkeyer.h:145
void setKeyboardDashes()
Definition: cwkeyer.cpp:430
static MsgConfigureCWKeyer * create(const CWKeyerSettings &settings, bool force)
Definition: cwkeyer.h:63
void handleInputMessages()
Definition: cwkeyer.cpp:540
void setKeyboardDots()
Definition: cwkeyer.cpp:423
bool m_key
Definition: cwkeyer.h:141
bool handleMessage(const Message &cmd)
Definition: cwkeyer.cpp:525
static float smootherstep(float x)
Definition: stepfunctions.h:24
int m_elementPointer
Definition: cwkeyer.h:137
static const signed char m_asciiToMorse[128][7]
Definition: cwkeyer.h:150
QMutex m_mutex
Definition: cwkeyer.h:44
int m_samplePointer
Definition: cwkeyer.h:138
void nextStateText()
Definition: cwkeyer.cpp:303
#define MESSAGE_CLASS_DEFINITION(Name, BaseClass)
Definition: message.h:52
bool getFadeSample(bool on, float &sample)
Definition: cwkeyer.cpp:487
unsigned char uint8_t
Definition: rtptypes_win.h:42
void setKeyboardSilence()
Definition: cwkeyer.cpp:437
void nextStateIambic()
Definition: cwkeyer.cpp:226
int m_dotLength
dot length in samples
Definition: cwkeyer.h:135
int32_t i
Definition: decimators.h:244
QMutex m_mutex
Definition: cwkeyer.h:132
void setNbFadeSamples(unsigned int nbFadeSamples)
Definition: cwkeyer.cpp:459
void setKeyboardIambic(qint32 keyboard_iambic)
float * m_fadeOutSamples
Definition: cwkeyer.h:49
bool eom()
Definition: cwkeyer.cpp:418
CWTextState m_textState
Definition: cwkeyer.h:147
Qt::KeyboardModifiers m_dotKeyModifiers
MessageQueue m_inputMessageQueue
Definition: cwkeyer.h:134
static void webapiFormatChannelSettings(SWGSDRangel::SWGCWKeyerSettings *apiCwKeyerSettings, const CWKeyerSettings &cwKeyerSettings)
Definition: cwkeyer.cpp:637
int getSample()
Definition: cwkeyer.cpp:194
unsigned int m_nbFadeSamples
Definition: cwkeyer.h:47
~CWKeyer()
Definition: cwkeyer.cpp:182
void applySettings(const CWKeyerSettings &settings, bool force=false)
Definition: cwkeyer.cpp:552
Qt::KeyboardModifiers m_dashKeyModifiers
CWKeyIambicState m_keyIambicState
Definition: cwkeyer.h:146
unsigned int m_fadeInCounter
Definition: cwkeyer.h:45
void setSampleRate(qint32 sample_rate)
static void webapiSettingsPutPatch(const QStringList &channelSettingsKeys, CWKeyerSettings &cwKeyerSettings, SWGSDRangel::SWGCWKeyerSettings *apiCwKeyerSettings)
Definition: cwkeyer.cpp:599
CWKeyer()
Definition: cwkeyer.cpp:163
bool m_dot
Definition: cwkeyer.h:142
void setDashKeyModifiers(qint32 dash_key_modifiers)
CWKeyerSettings m_settings
Definition: cwkeyer.h:133
void setDotKeyModifiers(qint32 dot_key_modifiers)
void setSampleRate(int sampleRate)
Definition: cwkeyer.cpp:186
unsigned int m_fadeOutCounter
Definition: cwkeyer.h:46
int m_textPointer
Definition: cwkeyer.h:136
const CWKeyerSettings & getSettings() const
Definition: cwkeyer.h:60
float * m_fadeInSamples
Definition: cwkeyer.h:48