463 lines
12 KiB
C++
463 lines
12 KiB
C++
#include "device.h"
|
|
#include "dev_commands.h"
|
|
#include "helpers.h"
|
|
|
|
#include <QtGlobal>
|
|
|
|
|
|
|
|
//************** Constructor ********************
|
|
|
|
Device::Device(QObject *parent) : QObject(parent), controlSocket(this)
|
|
{
|
|
connect(&controlSocket, QTcpSocket::connected, this, Device::onConnected);
|
|
connect(&controlSocket,
|
|
static_cast<void(QAbstractSocket::*)(QAbstractSocket::SocketError)>(&QAbstractSocket::error),
|
|
this, Device::onSocketError);
|
|
connect(&controlSocket, QTcpSocket::disconnected, this, Device::onDisconnected);
|
|
|
|
/*dataReceiver.moveToThread(&receiverThread);
|
|
receiverThread.start();
|
|
dataReceiver.init();*/
|
|
}
|
|
|
|
Device::~Device()
|
|
{
|
|
if (connected)
|
|
{
|
|
stopAcq();
|
|
disconnectDevice();
|
|
}
|
|
|
|
/*receiverThread.quit();
|
|
receiverThread.wait();*/
|
|
}
|
|
|
|
|
|
//************** Device configuration ********************
|
|
|
|
void Device::configure(DeviceConfig &cfg)
|
|
{
|
|
int ip_changed = 0;
|
|
for (int i = 0; i < 4; i++)
|
|
if (cfg.device_ip[i] != deviceConfig.device_ip[i])
|
|
ip_changed = 1;
|
|
|
|
deviceConfig = cfg;
|
|
|
|
//update data receiver settings
|
|
quint32 ip32 = 0;
|
|
unsigned short ipshort[4];
|
|
for (int i = 0; i < 4; i++)
|
|
{
|
|
ip32 <<= 8;
|
|
ip32 |= (qint32)(unsigned char)deviceConfig.own_ip[i];
|
|
ipshort[i] = (unsigned short)(unsigned char)deviceConfig.own_ip[i];
|
|
}
|
|
dataReceiver.configureEthSettings(QHostAddress(ip32), DEV_BASE_DATA_PORT + deviceConfig.device_id);
|
|
dataReceiver.configureBunchSize(deviceConfig.dma_bunch, deviceConfig.eth_bunch);
|
|
dataReceiver.devNr = deviceConfig.device_id;
|
|
dataReceiver.sensorsPerBoard = deviceConfig.max_sensors();
|
|
|
|
if (connected)
|
|
{
|
|
//re-connect if needed
|
|
if (ip_changed)
|
|
{
|
|
disconnectDevice();
|
|
while(connected);
|
|
connectDevice();
|
|
|
|
int ctr = 0;
|
|
while (!connected)
|
|
{
|
|
QThread::msleep(10);
|
|
if (++ctr > 100)
|
|
{
|
|
qWarning(qPrintable(QString("Device %1: IP change: reconnection failed!").arg(deviceConfig.device_id)));
|
|
return;
|
|
}
|
|
}
|
|
}
|
|
|
|
//update device settings
|
|
qInfo(qPrintable(QString("Device %1: setting up.").arg(deviceConfig.device_id)));
|
|
|
|
ctrlMaster(deviceConfig.master);
|
|
ctrlSetPeriod(deviceConfig.period);
|
|
ctrlSetTint(deviceConfig.tint);
|
|
ctrlSetMasterDelay(deviceConfig.master_delay);
|
|
ctrlSetSlaveDelay(deviceConfig.slave_delay);
|
|
ctrlSetGain(deviceConfig.gain);
|
|
ctrlConfigBunch(deviceConfig.dma_bunch, deviceConfig.eth_bunch);
|
|
ctrlConfigPeer(ipshort, DEV_BASE_DATA_PORT+ deviceConfig.device_id);
|
|
}
|
|
}
|
|
|
|
//************** Device connection ********************
|
|
|
|
void Device::connectDevice()
|
|
{
|
|
QString addr_txt = QString("%1.%2.%3.%4")
|
|
.arg(deviceConfig.device_ip[0])
|
|
.arg(deviceConfig.device_ip[1])
|
|
.arg(deviceConfig.device_ip[2])
|
|
.arg(deviceConfig.device_ip[3]);
|
|
|
|
if (connected)
|
|
{
|
|
qWarning(qPrintable(QString("Device %1: connect: already connected, reconnecting!").arg(deviceConfig.device_id)));
|
|
disconnectDevice();
|
|
while (connected)
|
|
QThread::msleep(1);
|
|
}
|
|
|
|
qInfo(qPrintable(QString("Device %1: trying to connect to %2").arg(deviceConfig.device_id).arg(addr_txt)));
|
|
controlSocket.connectToHost(addr_txt, 4000);
|
|
|
|
}
|
|
|
|
void Device::disconnectDevice()
|
|
{
|
|
if (!connected)
|
|
qWarning(qPrintable(QString("Device %1: disconnect: device not connected!").arg(deviceConfig.device_id)));
|
|
|
|
controlSocket.disconnectFromHost();
|
|
}
|
|
|
|
void Device::onConnected()
|
|
{
|
|
qInfo(qPrintable(QString("Device %1: connected with %2.%3.%4.%5")
|
|
.arg(deviceConfig.device_id)
|
|
.arg(deviceConfig.device_ip[0])
|
|
.arg(deviceConfig.device_ip[1])
|
|
.arg(deviceConfig.device_ip[2])
|
|
.arg(deviceConfig.device_ip[3]) ));
|
|
connected = 1;
|
|
|
|
configure(deviceConfig);
|
|
}
|
|
|
|
void Device::onSocketError(QAbstractSocket::SocketError socketError)
|
|
{
|
|
qWarning(qPrintable(QString("Device %1: socket error %2!").arg(deviceConfig.device_id).arg((int)socketError)));
|
|
if (controlSocket.state() != QAbstractSocket::ConnectedState)
|
|
connected = 0;
|
|
else
|
|
connected = 1;
|
|
}
|
|
|
|
void Device::onDisconnected()
|
|
{
|
|
qInfo(qPrintable(QString("Device %1: disconnected.").arg(deviceConfig.device_id)));
|
|
connected = 0;
|
|
}
|
|
|
|
//************** Controlling device ********************
|
|
|
|
void Device::startAcq()
|
|
{
|
|
qInfo(qPrintable(QString("Device %1: starting data taking...").arg(deviceConfig.device_id)));
|
|
|
|
if (!connected)
|
|
{
|
|
qWarning(qPrintable(QString("Device %1: not connected!").arg(deviceConfig.device_id)));
|
|
return;
|
|
}
|
|
|
|
dataReceiver.dataBuffer.clear();
|
|
dataReceiver.outputEnable(1);
|
|
|
|
ctrlResetCounters();
|
|
ctrlDaq(1);
|
|
ctrlTrigger(1);
|
|
}
|
|
|
|
void Device::stopAcq()
|
|
{
|
|
qInfo(qPrintable(QString("Device %1: stopping data taking...").arg(deviceConfig.device_id)));
|
|
|
|
if (!connected)
|
|
{
|
|
qWarning(qPrintable(QString("Device %1: not connected!").arg(deviceConfig.device_id)));
|
|
return;
|
|
}
|
|
|
|
ctrlTrigger(0);
|
|
QThread::msleep(10);
|
|
ctrlFlushData();
|
|
ctrlDaq(0);
|
|
QThread::msleep(10);
|
|
//QThread::msleep(10);
|
|
|
|
dataReceiver.outputEnable(0);
|
|
}
|
|
|
|
void Device::leds(int leds_enable, int debug_led)
|
|
{
|
|
if (connected)
|
|
{
|
|
ctrlLeds(leds_enable);
|
|
ctrlDebugLed(debug_led);
|
|
}
|
|
else
|
|
qWarning(qPrintable(QString("Device %1: not connected!").arg(deviceConfig.device_id)));
|
|
}
|
|
|
|
int Device::getFrameRate()
|
|
{
|
|
return dataReceiver.frameRate;
|
|
}
|
|
|
|
//************** Data exchange ********************
|
|
|
|
int Device::sendCtrl(unsigned short command, QVector<unsigned short> &data)
|
|
{
|
|
if (!connected)
|
|
{
|
|
qWarning(qPrintable(QString("Device %1: not connected!").arg(deviceConfig.device_id)));
|
|
return DEV_CTRL_ERROR;
|
|
}
|
|
|
|
int dl = data.length();
|
|
char buffer[2*dl + 6];
|
|
|
|
buffer[0] = 0x55;
|
|
buffer[1] = 0x55;
|
|
buffer[2] = HI(command);
|
|
buffer[3] = LO(command);
|
|
buffer[4] = HI(dl);
|
|
buffer[5] = LO(dl);
|
|
|
|
for (int i = 0; i < dl; i++)
|
|
{
|
|
buffer[2*i+6] = HI(data[i]);
|
|
buffer[2*i+7] = LO(data[i]);
|
|
}
|
|
|
|
return (int)controlSocket.write(buffer, 2*dl + 6);
|
|
}
|
|
|
|
int Device::receiveCtrl(unsigned short &command, QVector<unsigned short> &data)
|
|
{
|
|
if (!connected)
|
|
{
|
|
qWarning(qPrintable(QString("Device %1: not connected!").arg(deviceConfig.device_id)));
|
|
return DEV_CTRL_ERROR;
|
|
}
|
|
//Wait for data
|
|
if (!controlSocket.waitForReadyRead(DEV_CTRL_READ_TIMEOUT))
|
|
{
|
|
qWarning(qPrintable(QString("Device %1: no data received!").arg(deviceConfig.device_id)));
|
|
return DEV_CTRL_ERROR;
|
|
}
|
|
|
|
//Find sync characters
|
|
int sync_found = 0;
|
|
char buffer;
|
|
while (sync_found < 2)
|
|
{
|
|
if (controlSocket.read(&buffer, 1) <= 0)
|
|
{
|
|
qWarning(qPrintable(QString("Device %1: no data received!").arg(deviceConfig.device_id)));
|
|
return DEV_CTRL_ERROR;
|
|
}
|
|
if (buffer == 0x55)
|
|
sync_found++;
|
|
else
|
|
qWarning( qPrintable(QString("Device %1: 0x%2 found instead of sync character(0x55)!")
|
|
.arg(deviceConfig.device_id).arg((int)(unsigned int)buffer,(int)2,(int)16,QLatin1Char('0'))) );
|
|
}
|
|
|
|
char header[4];
|
|
if (controlSocket.read(header,4) < 4)
|
|
{
|
|
qWarning(qPrintable(QString("Device %1: data receive error when getting header!").arg(deviceConfig.device_id)));
|
|
return DEV_CTRL_ERROR;
|
|
}
|
|
|
|
command = BYTES2SHORT(header);
|
|
unsigned short dl = BYTES2SHORT(header+2);
|
|
|
|
char data_buf[2*dl];
|
|
if (controlSocket.read(data_buf, 2*dl) < (2*dl))
|
|
{
|
|
qWarning(qPrintable(QString("Device %1: data receive error when getting data!").arg(deviceConfig.device_id)));
|
|
return DEV_CTRL_ERROR;
|
|
|
|
}
|
|
|
|
data.clear();
|
|
|
|
for (int i = 0; i < dl; i++)
|
|
data.append(BYTES2SHORT(data_buf + 2*i));
|
|
|
|
return dl;
|
|
}
|
|
|
|
int Device::queryCtrl(unsigned short command, QVector<unsigned short> &txdata, QVector<unsigned short> &rxdata)
|
|
{
|
|
if (sendCtrl(command, txdata) == DEV_CTRL_ERROR)
|
|
return DEV_CTRL_ERROR;
|
|
|
|
unsigned short command_rx;
|
|
if (receiveCtrl(command_rx, rxdata) == DEV_CTRL_ERROR)
|
|
return DEV_CTRL_ERROR;
|
|
|
|
if (command_rx != command)
|
|
return DEV_CTRL_ERROR;
|
|
|
|
return DEV_CTRL_OK;
|
|
}
|
|
|
|
//************** Simple commands ********************
|
|
|
|
int Device::ctrlPing()
|
|
{
|
|
QVector<unsigned short> rxdata;
|
|
QVector<unsigned short> txdata;
|
|
|
|
return queryCtrl(COMMAND_PING, txdata, rxdata);
|
|
}
|
|
|
|
int Device::ctrlDebugLed(int state)
|
|
{
|
|
QVector<unsigned short> rxdata;
|
|
QVector<unsigned short> txdata;
|
|
|
|
if (state)
|
|
return queryCtrl(COMMAND_DEBUG_LED_ON, txdata, rxdata);
|
|
else
|
|
return queryCtrl(COMMAND_DEBUG_LED_OFF, txdata, rxdata);
|
|
}
|
|
|
|
int Device::ctrlLeds(int en)
|
|
{
|
|
QVector<unsigned short> rxdata;
|
|
QVector<unsigned short> txdata;
|
|
|
|
if (en)
|
|
return queryCtrl(COMMAND_LEDS_ENABLE, txdata, rxdata);
|
|
else
|
|
return queryCtrl(COMMAND_LEDS_DISABLE, txdata, rxdata);
|
|
}
|
|
|
|
int Device::ctrlTrigger(int en)
|
|
{
|
|
QVector<unsigned short> rxdata;
|
|
QVector<unsigned short> txdata;
|
|
|
|
if (en)
|
|
return queryCtrl(COMMAND_TRIGGER_ENABLE, txdata, rxdata);
|
|
else
|
|
return queryCtrl(COMMAND_TRIGGER_DISABLE, txdata, rxdata);
|
|
}
|
|
|
|
int Device::ctrlMaster(int en)
|
|
{
|
|
QVector<unsigned short> rxdata;
|
|
QVector<unsigned short> txdata;
|
|
|
|
if (en)
|
|
return queryCtrl(COMMAND_TRIGGER_SET_MASTER, txdata, rxdata);
|
|
else
|
|
return queryCtrl(COMMAND_TRIGGER_SET_SLAVE, txdata, rxdata);
|
|
}
|
|
|
|
int Device::ctrlSetPeriod(int period)
|
|
{
|
|
QVector<unsigned short> rxdata;
|
|
QVector<unsigned short> txdata;
|
|
txdata.append((unsigned short)period);
|
|
|
|
return queryCtrl(COMMAND_TRIGGER_SET_PERIOD, txdata, rxdata);
|
|
}
|
|
|
|
int Device::ctrlSetTint(int tint)
|
|
{
|
|
QVector<unsigned short> rxdata;
|
|
QVector<unsigned short> txdata;
|
|
txdata.append((unsigned short)tint);
|
|
|
|
return queryCtrl(COMMAND_TRIGGER_SET_TINT, txdata, rxdata);
|
|
}
|
|
|
|
int Device::ctrlSetMasterDelay(int tint)
|
|
{
|
|
QVector<unsigned short> rxdata;
|
|
QVector<unsigned short> txdata;
|
|
txdata.append((unsigned short)tint);
|
|
|
|
return queryCtrl(COMMAND_TRIGGER_SET_MASTER_DELAY, txdata, rxdata);
|
|
}
|
|
|
|
int Device::ctrlSetSlaveDelay(int tint)
|
|
{
|
|
QVector<unsigned short> rxdata;
|
|
QVector<unsigned short> txdata;
|
|
txdata.append((unsigned short)tint);
|
|
|
|
return queryCtrl(COMMAND_TRIGGER_SET_SLAVE_DELAY, txdata, rxdata);
|
|
}
|
|
|
|
int Device::ctrlDaq(int en)
|
|
{
|
|
QVector<unsigned short> rxdata;
|
|
QVector<unsigned short> txdata;
|
|
|
|
if (en)
|
|
return queryCtrl(COMMAND_DAQ_ENABLE, txdata, rxdata);
|
|
else
|
|
return queryCtrl(COMMAND_DAQ_DISABLE, txdata, rxdata);
|
|
}
|
|
|
|
int Device::ctrlResetCounters()
|
|
{
|
|
QVector<unsigned short> rxdata;
|
|
QVector<unsigned short> txdata;
|
|
|
|
return queryCtrl(COMMAND_DAQ_RESET_COUNTERS, txdata, rxdata);
|
|
}
|
|
|
|
int Device::ctrlFlushData()
|
|
{
|
|
QVector<unsigned short> rxdata;
|
|
QVector<unsigned short> txdata;
|
|
|
|
return queryCtrl(COMMAND_DAQ_FLUSH_DATA, txdata, rxdata);
|
|
}
|
|
|
|
int Device::ctrlConfigPeer(unsigned short* ip, unsigned short port)
|
|
{
|
|
QVector<unsigned short> rxdata;
|
|
QVector<unsigned short> txdata;
|
|
for (int i = 0; i < 4; i++)
|
|
txdata.append(ip[i]);
|
|
txdata.append(port);
|
|
|
|
return queryCtrl(COMMAND_DAQ_CONFIG_PEER, txdata, rxdata);
|
|
}
|
|
|
|
int Device::ctrlSetGain(int val)
|
|
{
|
|
QVector<unsigned short> rxdata;
|
|
QVector<unsigned short> txdata;
|
|
txdata.append((unsigned short)(val?1:0));
|
|
|
|
return queryCtrl(COMMAND_SET_GAIN, txdata, rxdata);
|
|
}
|
|
|
|
int Device::ctrlConfigBunch(int dma, int eth)
|
|
{
|
|
qWarning("Bunch configuration not implemented!");
|
|
return DEV_CTRL_OK;
|
|
|
|
/*QVector<unsigned short> rxdata;
|
|
QVector<unsigned short> txdata;
|
|
|
|
if (en)
|
|
return queryCtrl(COMMAND_DAQ_ENABLE, txdata, rxdata);
|
|
else
|
|
return queryCtrl(COMMAND_DAQ_DISABLE, txdata, rxdata);*/
|
|
}
|