-
Notifications
You must be signed in to change notification settings - Fork 8
/
Copy pathKeyingReader.cpp
130 lines (110 loc) · 4.32 KB
/
KeyingReader.cpp
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
#include "KeyingReader.h"
#include "Morse.h"
#include "qdebug.h"
KeyingReader::KeyingReader()
: pastDitLength(-1)
{
int intCode;
#include "inverse_code.h"
}
QString KeyingReader::analyzeKeying(const QList<int> &m_keyedTimes, int *timingUsed, bool useAll)
{
QString results = "";
const int letterSpaceWeight = 4; // number of dits
int spaceExpected = -1;
int ditLength = 0xffff;
int usedCount = 0;
*timingUsed = 0;
QList<int>::const_iterator end = m_keyedTimes.end();
QList<int>::const_iterator spot = m_keyedTimes.begin();
QList<int>::const_iterator startAt;
//qDebug() << "keyed times: " << m_keyedTimes;
while ((useAll && spot != end) || spot == m_keyedTimes.begin()) {
QList<int> keyedTimes;
startAt = spot;
for(; spot != end;) {
usedCount++;
// starting point is a key-down
int downKey = *spot;
spot++;
if (spot == end)
return results; // key pressed down, not up yet
// next is the release
int upKey = *spot;
// calculate the time in between
int delta = upKey - downKey;
keyedTimes.push_back(delta);
// Always use the smallest value for the dit
if (ditLength > delta) {
ditLength = delta;
spaceExpected = delta * letterSpaceWeight;
}
// now calculate the length of the space after this
if (spot != end) {
// XXX: we should really just require an ending space and force a timer usage
spot++;
int nextSpace = *spot - upKey;
if (nextSpace > spaceExpected) {
// we've gotten to a point where everything from startAt till now is a letter.
if (m_keyedTimes.count() > 3) // at least two keys
results = results + analyzeKey(keyedTimes, (*(m_keyedTimes.begin() + 2) - (*(m_keyedTimes.begin() + 1))));
else
results = results + analyzeKey(keyedTimes, -1); // single character; we don't know how long it should be
keyedTimes.clear();
*timingUsed = usedCount;
}
}
}
}
return results;
}
QString KeyingReader::analyzeKey(const QList<int> &m_keyedLengths, int pauseLength) {
// we have a complete sequence from first keyDown to last keyUp for a letter
QList<int>::const_iterator pt1, pt2;
int sequence = 0;
qDebug() << "keyed lengths:" << m_keyedLengths;
int maxv = -1, minv = 0xffff;
int aveLength;
QList<int>::const_iterator end = m_keyedLengths.end();
QList<int>::const_iterator length;
for(length = m_keyedLengths.begin() ; length != end; length++) {
maxv = qMax(maxv, *length);
minv = qMin(minv, *length);
}
qDebug() << "min=" << minv << ", max=" << maxv << ", pause=" << pauseLength * 3;
// Ok, if the maxv is at least 2x the minv then they're different lengths in general (yay)
if (maxv > minv*2.0) {
pastDitLength = minv;
aveLength = minv + (maxv - minv)/2;
} else {
// the lengths are the same, so either they're all dits or they're all dahs
if (pastDitLength != -1) {
if (maxv < 2 * pastDitLength)
aveLength = maxv + 1; // all dahs
else
aveLength = minv - 1; // all dits
} else {
// the guessing gets worse if we've never recevied a true dit/dah letter yet
if (maxv < pauseLength/2)
aveLength = maxv+1; // they're all dits
else
aveLength = minv-1; // they're all dahs
}
}
// Ok, now loop through them all and determine what each is.
for(length = m_keyedLengths.begin() ; length != end; length++) {
if (*length > aveLength) {
// it's a DAH
sequence = (sequence << 4) | 2;
} else {
sequence = (sequence << 4) | 1;
}
}
qDebug() << "keyed: " << sequence;
if (!inverseCode.contains(sequence)) {
qWarning() << "ERROR: they keyed something invalid: " << QString::number(sequence, 16);
return "";
}
return inverseCode[sequence];
// Now we have the list, we can get the char from the sequence
}