-
Notifications
You must be signed in to change notification settings - Fork 0
/
logthread.cpp
139 lines (113 loc) · 3.96 KB
/
logthread.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
131
132
133
134
135
136
137
138
139
/*
Name : logthread.cpp
Author : Charles N. Burns (charlesnburns|gmail|com / burnchar|isu|edu)
Date : 11 February 2010
License : GPL3. See license.txt or www.gnu.org/licenses/gpl-3.0.txt
Requirements: Qt 4, Phidgets servo controller & C library (www.phidgets.com)
Notes : Written with Qt Creator. Best viewed with tab width 4.
Description : Thread for writing servo commands to a log on disk.
*/
#include <QReadWriteLock>
#include <QDebug>
#include "logthread.h"
const quint16 SIGNATURE = 0x4342; // Log file signature, ASCII initials "CB"
long logEntryCountByServo[8];
QQueue<LogEntry> actionLog; // Actions enqueued here are later written to disk
QReadWriteLock lock; // Smart mutex for actionlog
LogThread::LogThread()
{
for(int servoCount = 0; servoCount < 8; ++servoCount) {
logEntryCountByServo[servoCount] = 0;
}
logFile.setFileName("servolog.cnb");
if(!logFile.open(QIODevice::WriteOnly)) {
qDebug() << "Unable to write to log file.";
}
outStream.setDevice(&logFile);
writeHeader();
go = true;
}
//! Entrypoint for LogThread
//! Check to see if there are things to log and if so, write them to disk.
//! Otherwise, wait 100ms and check again.
//! Exit only when "go" is false AND all queued events are written
void LogThread::run()
{
while(! actionLog.isEmpty() || go) {
while(! actionLog.isEmpty()) { // Write all queued log entries
lock.lockForRead();
LogEntry entry = actionLog.dequeue();
lock.unlock();
outStream << entry.dat.asInt << entry.position;
++logEntryCountByServo[entry.dat.asBitfield.servoIndex];
yieldCurrentThread();
}
msleep(100);
}
exit(0);
}
LogThread::~LogThread()
{
logFile.close();
}
//! Writes the log file header to disk.
//! This consists of a signature, other pieces of information, and dummy entries
//! The dummy entries are to help in reconstruction of the log format in case
//! another program needs to read the data but doesn't know the proper byte
//! order of entries.
void LogThread::writeHeader()
{
LogHeader h;
h.signature = SIGNATURE; // "CB"
h.version = 1;
h.headerSize = sizeof(LogHeader);
h.logEntrySize = sizeof(LogEntry);
h.userID = 0; // TODO
h.sessionNumber = 0; // TODO
h.startTimeUTC = QDateTime::currentDateTime().toUTC().toTime_t();
h.dummyEntry1.position = 0xC0000003; // 11000000000000000000000000000011b
h.dummyEntry1.dat.asBitfield.isFromHmd = 1;
h.dummyEntry1.dat.asBitfield.isPaused = 1;
h.dummyEntry1.dat.asBitfield.msOffset = 0;
h.dummyEntry1.dat.asBitfield.servoIndex = 8; // 111b
h.dummyEntry2.position = 0xAAFF00CC; // 10101010111111110000000011001100b
h.dummyEntry2.dat.asBitfield.isFromHmd = 1;
h.dummyEntry2.dat.asBitfield.isPaused = 0;
h.dummyEntry2.dat.asBitfield.msOffset = 0x7FFFFFF; // 27 1's in binary
h.dummyEntry2.dat.asBitfield.servoIndex = 0;
outStream << h;
}
void LogThread::stop()
{
go = false;
}
//! Operator function for use with a QDataStream
QDataStream& operator << (QDataStream &stream, const LogHeader &lh)
{
return lh.writeMyself(stream);
}
//! Operator function for use with a QDataStream
QDataStream& operator >> (QDataStream &stream, LogHeader &lh)
{
return lh.readMyself(stream);
}
//! This function exists to be called by the operator<< friend function.
QDataStream& LogHeader::writeMyself(QDataStream &stream) const
{
return (stream
<< signature << headerSize << logEntrySize
<< userID << sessionNumber << startTimeUTC
<< dummyEntry1.dat.asInt << dummyEntry1.position
<< dummyEntry2.dat.asInt << dummyEntry2.position
);
}
//! This function exists to be called by the operator>> friend function.
QDataStream& LogHeader::readMyself(QDataStream &stream)
{
return( stream
>> signature >> headerSize >> logEntrySize
>> userID >> sessionNumber >> startTimeUTC
>> dummyEntry1.dat.asInt >> dummyEntry1.position
>> dummyEntry2.dat.asInt >> dummyEntry2.position
);
}