forked from collin80/SavvyCAN
-
Notifications
You must be signed in to change notification settings - Fork 0
/
utility.h
271 lines (239 loc) · 9.01 KB
/
utility.h
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
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
#ifndef UTILITY_H
#define UTILITY_H
#include <Qt>
#include <stdint.h>
#include <QByteArray>
#include <QDateTime>
#include <QDebug>
#include <QApplication>
#include <QRect>
//#include <QDesktopWidget>
class Utility
{
public:
static bool decimalMode;
static bool secondsMode;
static bool sysTimeMode;
static QString timeFormat;
//determines whether the window position is within any available screens. If it is not we default
//back to 0,0 which is going to be on screen. This fixes a problem where some operating systems would
//otherwise let you put windows on a second monitor, disconnect that monitor, and still put windows on it.
static QPoint constrainedWindowPos(QPoint originalPos)
{
QScreen *screen = QGuiApplication::screenAt(originalPos);
if (!screen)
{
return QPoint(0,0);
}
return originalPos;
}
static QString unQuote(QString inStr)
{
QStringList temp;
temp = inStr.split('\"');
if (temp.length() >= 3)
return temp[1];
return inStr;
}
static uint64_t ParseStringToNum(QByteArray input)
{
uint64_t temp = 0;
input = input.toUpper();
if (input.startsWith("0X") || input.startsWith("X")) //hex number
{
if (input.length() < 3) temp = 0;
else temp = input.right(input.size() - 2).toLongLong(nullptr, 16);
}
else if (input.startsWith("0B") || input.startsWith("B")) //binary number
{
input = input.right(input.size() - 1); //remove the B
for (int i = 0; i < input.length(); i++)
{
if (input[i] == '1') temp += (uint64_t)1 << (input.length() - i - 1);
}
}
else //decimal number
{
temp = input.toLongLong();
}
return temp;
}
static uint64_t ParseStringToNum(QString input)
{
return ParseStringToNum(input.toUtf8());
}
static uint ParseStringToNum2(QString pInput, bool* pOk_p = nullptr)
{
if(pInput.startsWith("0b"))
{
pInput.remove(0, 2);
return pInput.toUInt(pOk_p, 2);
}
return pInput.toUInt(pOk_p, 0);
}
static uint64_t GetTimeMS()
{
QDateTime stamp = QDateTime::currentDateTime();
return (((static_cast<uint64_t>(stamp.time().hour()) * 3600ull) + (static_cast<uint64_t>(stamp.time().minute()) * 60ull)
+ (static_cast<uint64_t>(stamp.time().second())) * 1000ull) + static_cast<uint64_t>(stamp.time().msec()));
}
//prints hex numbers in uppercase with 0's filling out the number depending
//on the size needed. Promotes hex numbers to either 2, 4, or 8 digits
static QString formatHexNum(uint64_t input)
{
if (input < 256)
return "0x" + QString::number(input, 16).toUpper().rightJustified(2,'0');
if (input < 65536)
return "0x" + QString::number(input, 16).toUpper().rightJustified(4,'0');
if (input < 4294967296)
return "0x" + QString::number(input, 16).toUpper().rightJustified(8,'0');
return "0x" + QString::number(input, 16).toUpper().rightJustified(16,'0');
}
//uses decimalMode to see if it should show value as decimal or hex
static QString formatNumber(uint64_t value)
{
if (decimalMode)
{
return QString::number(value, 10);
}
else return formatHexNum(value);
}
static QString formatCANID(uint64_t id, bool extended)
{
if (decimalMode) return QString::number(id, 10);
if (extended)
{
return "0x" + QString::number(id, 16).toUpper().rightJustified(8,'0');
}
else
{
id = id & 0x7FF;
return "0x" + QString::number(id, 16).toUpper().rightJustified(3,'0');
}
}
static QString formatCANID(uint64_t id)
{
if (id < 0x800) return formatCANID(id, false);
return formatCANID(id, true);
}
static QString formatByteAsBinary(uint8_t value)
{
QString output;
for (int b = 7; b >= 0; b--)
{
if (value & (1 << b)) output += "1";
else output += "0";
}
return output;
}
static QVariant formatTimestamp(uint64_t timestamp)
{
if (!sysTimeMode) {
if (!secondsMode) return (unsigned long long)(timestamp);
else return (double)timestamp / 1000000.0;
}
else return QDateTime::fromMSecsSinceEpoch(timestamp / 1000);
}
//parses the input string to grab as much of it as possible while staying alpha numeric
static QString grabAlphaNumeric(QString &input)
{
QString builder;
QChar thisChar;
for (int i = 0; i < input.length(); i++)
{
thisChar = input[i];
if (thisChar.isLetterOrNumber() || thisChar == ':' || thisChar == '~') builder.append(input[i]);
else
{
//qDebug() << "i: "<< i << " len: " << input.length();
if (i < (input.length() - 1)) input = input.right(input.length() - i);
else input = "";
return builder;
}
}
//qDebug() << "Reached end of string in grabAlphaNumeric";
input = "";
return builder;
}
static QString grabOperation(QString &input)
{
QString builder;
QChar thisChar = input[0];
if (thisChar == '+' || thisChar == '-' || thisChar == '*' || thisChar == '/' || thisChar == '^' || thisChar == '&' || thisChar == '|' || thisChar == '=' || thisChar == '%')
{
input = input.right(input.length() - 1);
builder = thisChar;
}
return builder;
}
//simple linear interpolation between value1 and value2. sample point is 0.0 to 1.0
static double Lerp(double value1, double value2, double samplePoint)
{
return (value1 * (1.0 - samplePoint)) + (value2 * samplePoint);
}
static int64_t processIntegerSignal(const QByteArray data, int startBit, int sigSize, bool littleEndian, bool isSigned)
{
int64_t result = 0;
int bit;
int maxBytes = (startBit + sigSize) / 8;
if (data.size() < maxBytes) return 0;
if (littleEndian)
{
bit = startBit;
for (int bitpos = 0; bitpos < sigSize; bitpos++)
{
if (bit < 64) {
int bytePos = bit / 8;
if (bytePos >= data.count()) return 0; //error!
if (data[bit / 8] & (1 << (bit % 8)))
result += (1ULL << bitpos);
}
bit++;
}
}
else //motorola / big endian mode
{
bit = startBit;
for (int bitpos = 0; bitpos < sigSize; bitpos++)
{
if (bit < 64) {
int bytePos = bit / 8;
if (bytePos >= data.count()) return 0; //error!
if (data[bit / 8] & (1 << (bit % 8)))
result += (1ULL << (sigSize - bitpos - 1));
}
if ((bit % 8) == 0)
bit += 15;
else bit--;
}
}
if (isSigned)
{
int64_t mask = (1ULL << (sigSize - 1));
if ((result & mask) == mask) //is the highest bit possible for this signal size set?
{
/*
* if so we need to also set every bit higher in the result int too.
* This leads to the below two lines that are nasty. Here's the theory behind that...
* If the value is signed and the highest bit is set then it is negative. To create
* a negative value out of this even though the variable result is 64 bit we have to
* run 1's all of the way up to bit 63 in result. -1 is all ones for whatever size integer
* you have. So, it's 64 1's in this case.
* signedMask is done this way:
* first you take the signal size and shift 1 up that far. Then subtract one. Lets
* see that for a 16 bit signal:
* (1 << 16) - 1 = the first 16 bits set as 1's. So far so good. We then negate the whole
* thing which flips all bits. Thus signedMask ends up with 1's everwhere that the signal
* doesn't take up in the 64 bit signed integer result. Then, result has an OR operation on
* it with the old value and -1 masked so that the the 1 bits from -1 don't overwrite bits from the
* actual signal. This extends the sign bits out so that the integer result reads as the proper negative
* value. We dont need to do any of this if the sign bit wasn't set.
*/
uint64_t signedMask = ~((1ULL << sigSize) - 1);
result = (-1LL & signedMask) | result;
}
}
return result;
}
};
#endif // UTILITY_H