260 lines
6.2 KiB
C++
260 lines
6.2 KiB
C++
#include "eventbuilder.h"
|
|
|
|
EventBuilder::EventBuilder(QObject *parent) : QObject(parent)
|
|
{
|
|
connect(this, EventBuilder::sigInit, this, EventBuilder::onInit);
|
|
connect(this, EventBuilder::sigDeinit, this, EventBuilder::onDeinit);
|
|
connect(this, EventBuilder::sigStartLogging, this, EventBuilder::onStartLogging);
|
|
connect(this, EventBuilder::sigStopLogging, this, EventBuilder::onStopLogging);
|
|
connect(this, EventBuilder::sigStartTakingHistos, this, EventBuilder::onStartTakingHistos);
|
|
connect(this, EventBuilder::sigStopTakingHistos, this, EventBuilder::onStopTakingHistos);
|
|
|
|
moveToThread(&thread);
|
|
thread.start();
|
|
init();
|
|
}
|
|
|
|
EventBuilder::~EventBuilder()
|
|
{
|
|
deinit();
|
|
|
|
thread.quit();
|
|
thread.wait();
|
|
}
|
|
|
|
//************************* Data processing framework ********************
|
|
|
|
//main processing slot
|
|
void EventBuilder::onNewData(DataReceiver* receiver)
|
|
{
|
|
|
|
while (checkBufferOccupancies())
|
|
{
|
|
//find lowest global sync value
|
|
int lowest_id = findLowestId();
|
|
|
|
//get and validate data from buffers
|
|
for (int dev_nr = 0; dev_nr < nrReceivers; dev_nr++)
|
|
{
|
|
BufferData data = receivers[dev_nr]->dataBuffer.look();
|
|
if (data.sync_frame.global_ctr == lowest_id)
|
|
{
|
|
receivers[dev_nr]->dataBuffer.dump(); //right data, dump it from the buffer
|
|
}
|
|
else
|
|
{
|
|
data.sync_frame.data_ok = 0; //wrong data, mark as bad
|
|
}
|
|
//store data for complete frame
|
|
currentFrame[dev_nr] = data;
|
|
|
|
}
|
|
|
|
lastFrameMutex.lock();
|
|
if (newDataSemaphore.available() == 0)
|
|
newDataSemaphore.release(1);
|
|
lastFrame = currentFrame;
|
|
lastFrameMutex.unlock();
|
|
|
|
//histogram stuff
|
|
if (histogramSamplesToTake)
|
|
{
|
|
for (int dev_nr = 0; dev_nr < nrReceivers; dev_nr++)
|
|
for (int ch = 0; ch < 128; ch++)
|
|
histograms[128*dev_nr + ch].shoot(currentFrame[dev_nr].sensor_data[ch]);
|
|
|
|
if (histogramSamplesToTake != -1)
|
|
histogramSamplesToTake--;
|
|
if (histogramSamplesToTake == 0)
|
|
emit sigHistoCompleted();
|
|
}
|
|
|
|
//log data
|
|
if (loggingData)
|
|
logDataToFile();
|
|
|
|
|
|
//************ TODO ************
|
|
//Here we can do something more with the complete frame
|
|
|
|
}
|
|
|
|
}
|
|
|
|
//return 1 if buffer levels allow/force data processing
|
|
int EventBuilder::checkBufferOccupancies()
|
|
{
|
|
int result = 1;
|
|
for (int dev_nr = 0; dev_nr < nrReceivers; dev_nr++)
|
|
{
|
|
int nr_items = receivers[dev_nr]->dataBuffer.nrItems();
|
|
if (nr_items > EVB_MAX_BUFFER_OCCUPANCY)
|
|
return 1; //if at least one buffer is above high threshold - return immediately
|
|
if (nr_items < EVB_MIN_BUFFER_OCCUPANCY)
|
|
result = 0;
|
|
}
|
|
return result;
|
|
}
|
|
|
|
int EventBuilder::findLowestId()
|
|
{
|
|
int min1 = INT_MAX, min2 = INT_MAX;
|
|
int max1 = INT_MIN, max2 = INT_MIN;
|
|
|
|
for (int dev_nr = 0; dev_nr < nrReceivers; dev_nr++)
|
|
{
|
|
int value = receivers[dev_nr]->dataBuffer.look().sync_frame.global_ctr;
|
|
//for non-zero-crossing case
|
|
if (value < min1) min1 = value;
|
|
if (value > max1) max1 = value;
|
|
//for zero-crossing case
|
|
if (value > 256) value -= 512;
|
|
if (value < min2) min2 = value;
|
|
if (value > max2) max2 = value;
|
|
}
|
|
if ((max1-min1) < (max2-min2))
|
|
{
|
|
//non-zero-crossing
|
|
return min1;
|
|
}
|
|
else
|
|
{
|
|
//zero-crossing
|
|
if (min2 < 0) min2 += 512;
|
|
return min2;
|
|
}
|
|
}
|
|
|
|
void EventBuilder::logDataToFile()
|
|
{
|
|
//write data in native binary format
|
|
logFile.write((const char*)currentFrame.constData(), nrReceivers*sizeof(BufferData));
|
|
}
|
|
|
|
//************************* Protected slots ********************
|
|
|
|
void EventBuilder::onInit()
|
|
{
|
|
//Still nothing? Strange...
|
|
|
|
initSemaphore.release();
|
|
}
|
|
|
|
void EventBuilder::onDeinit()
|
|
{
|
|
//Still nothing? Strange...
|
|
|
|
initSemaphore.release();
|
|
}
|
|
|
|
void EventBuilder::onStartLogging()
|
|
{
|
|
if (loggingData)
|
|
onStopLogging();
|
|
|
|
logFile.setFileName(logFileName);
|
|
logFile.open(QIODevice::WriteOnly);
|
|
|
|
loggingData = 1;
|
|
}
|
|
|
|
void EventBuilder::onStopLogging()
|
|
{
|
|
loggingData = 0;
|
|
|
|
logFile.close();
|
|
}
|
|
|
|
void EventBuilder::onStartTakingHistos(int sample_count)
|
|
{
|
|
histograms.resize(128*nrReceivers);
|
|
for (int ch = 0; ch < histograms.length(); ch++)
|
|
histograms[ch].resize(65536);
|
|
|
|
histogramSamplesToTake = sample_count;
|
|
}
|
|
|
|
void EventBuilder::onStopTakingHistos()
|
|
{
|
|
histogramSamplesToTake = 0;
|
|
emit sigHistoCompleted();
|
|
}
|
|
|
|
|
|
//******************** Thread-safe interface *******************
|
|
|
|
void EventBuilder::init()
|
|
{
|
|
emit sigInit();
|
|
initSemaphore.acquire(); //wait for initialization
|
|
}
|
|
|
|
void EventBuilder::deinit()
|
|
{
|
|
emit sigDeinit();
|
|
initSemaphore.acquire(); //wait for deinitialization
|
|
}
|
|
|
|
void EventBuilder::addSource(DataReceiver* source)
|
|
{
|
|
receivers.append(source);
|
|
nrReceivers = receivers.length();
|
|
currentFrame.resize(nrReceivers);
|
|
connect(source, DataReceiver::sigDataReady, this, EventBuilder::onNewData);
|
|
}
|
|
|
|
void EventBuilder::deleteSources()
|
|
{
|
|
for (int i = 0; i < receivers.length(); i++)
|
|
disconnect(receivers[i], DataReceiver::sigDataReady, this, EventBuilder::onNewData);
|
|
|
|
receivers.clear();
|
|
nrReceivers = receivers.length();
|
|
}
|
|
|
|
void EventBuilder::startLogging(QString filename)
|
|
{
|
|
logFileName = filename;
|
|
emit sigStartLogging();
|
|
}
|
|
|
|
void EventBuilder::stopLogging()
|
|
{
|
|
emit sigStopLogging();
|
|
|
|
}
|
|
|
|
int EventBuilder::isLogging()
|
|
{
|
|
return loggingData;
|
|
}
|
|
|
|
void EventBuilder::startTakingHistos(int sample_count)
|
|
{
|
|
emit sigStartTakingHistos(sample_count);
|
|
}
|
|
|
|
void EventBuilder::stopTakingHistos()
|
|
{
|
|
emit sigStopTakingHistos();
|
|
}
|
|
|
|
QVector<Histogram>& EventBuilder::getHistos()
|
|
{
|
|
return histograms;
|
|
}
|
|
|
|
QVector<BufferData> EventBuilder::getLastFrame()
|
|
{
|
|
QMutexLocker locker(&lastFrameMutex);
|
|
return lastFrame;
|
|
}
|
|
|
|
QVector<BufferData> EventBuilder::getNewFrame()
|
|
{
|
|
//wait for new data
|
|
newDataSemaphore.acquire(1);
|
|
//and return it
|
|
return getLastFrame();
|
|
}
|