added 4*4 bytes to the data packet for RMS reconstruction and changed the channel data to signed short

This commit is contained in:
Blake Leverington 2024-01-19 17:07:41 +01:00
parent 89258a816f
commit bce899fc20
85 changed files with 57277 additions and 0 deletions

View File

@ -0,0 +1,43 @@
QMAKE_DEFAULT_INCDIRS = \
C:/Qt/Tools/mingw530_32/lib/gcc/i686-w64-mingw32/5.3.0/include \
C:/Qt/Tools/mingw530_32/lib/gcc/i686-w64-mingw32/5.3.0/include-fixed \
C:/Qt/Tools/mingw530_32/i686-w64-mingw32/include \
C:/Qt/Tools/mingw530_32/i686-w64-mingw32/include/c++ \
C:/Qt/Tools/mingw530_32/i686-w64-mingw32/include/c++/i686-w64-mingw32 \
C:/Qt/Tools/mingw530_32/i686-w64-mingw32/include/c++/backward
QMAKE_DEFAULT_LIBDIRS = \
C:/Qt/Tools/mingw530_32/lib/gcc/i686-w64-mingw32/5.3.0 \
C:/Qt/Tools/mingw530_32/lib/gcc \
C:/Qt/Tools/mingw530_32/i686-w64-mingw32/lib \
C:/Qt/Tools/mingw530_32/lib
QMAKE_CXX.QT_COMPILER_STDCXX = 201703L
QMAKE_CXX.QMAKE_GCC_MAJOR_VERSION = 11
QMAKE_CXX.QMAKE_GCC_MINOR_VERSION = 2
QMAKE_CXX.QMAKE_GCC_PATCH_VERSION = 0
QMAKE_CXX.COMPILER_MACROS = \
QT_COMPILER_STDCXX \
QMAKE_GCC_MAJOR_VERSION \
QMAKE_GCC_MINOR_VERSION \
QMAKE_GCC_PATCH_VERSION
QMAKE_CXX.INCDIRS = \
C:/Qt/Tools/mingw530_32/lib/gcc/i686-w64-mingw32/5.3.0/include \
C:/Qt/Tools/mingw530_32/lib/gcc/i686-w64-mingw32/5.3.0/include-fixed \
C:/Qt/Tools/mingw530_32/i686-w64-mingw32/include \
C:/Qt/Tools/mingw530_32/i686-w64-mingw32/include/c++ \
C:/Qt/Tools/mingw530_32/i686-w64-mingw32/include/c++/i686-w64-mingw32 \
C:/Qt/Tools/mingw530_32/i686-w64-mingw32/include/c++/backward \
C:/Qt/Tools/mingw1120_64/lib/gcc/x86_64-w64-mingw32/11.2.0/include/c++ \
C:/Qt/Tools/mingw1120_64/lib/gcc/x86_64-w64-mingw32/11.2.0/include/c++/x86_64-w64-mingw32 \
C:/Qt/Tools/mingw1120_64/lib/gcc/x86_64-w64-mingw32/11.2.0/include/c++/backward \
C:/Qt/Tools/mingw1120_64/lib/gcc/x86_64-w64-mingw32/11.2.0/include \
C:/Qt/Tools/mingw1120_64/lib/gcc/x86_64-w64-mingw32/11.2.0/include-fixed \
C:/Qt/Tools/mingw1120_64/x86_64-w64-mingw32/include
QMAKE_CXX.LIBDIRS = \
C:/Qt/Tools/mingw530_32/lib/gcc/i686-w64-mingw32/5.3.0 \
C:/Qt/Tools/mingw530_32/lib/gcc \
C:/Qt/Tools/mingw530_32/i686-w64-mingw32/lib \
C:/Qt/Tools/mingw530_32/lib \
C:/Qt/Tools/mingw1120_64/lib/gcc/x86_64-w64-mingw32/11.2.0 \
C:/Qt/Tools/mingw1120_64/lib/gcc \
C:/Qt/Tools/mingw1120_64/x86_64-w64-mingw32/lib \
C:/Qt/Tools/mingw1120_64/lib

View File

@ -0,0 +1,46 @@
#ifndef Q_DEBUGSTREAM_H
#define Q_DEBUGSTREAM_H
#include <iostream>
#include <streambuf>
#include <string>
#include <QTextBrowser>
#include <QtGlobal>
#define DS_DEBUG 0x01
#define DS_INFO 0x02
#define DS_WARNING 0x04
#define DS_CRITICAL 0x08
#define DS_FATAL 0x10
class Q_DebugStream : public std::basic_streambuf<char>
{
public:
Q_DebugStream(std::ostream &stream, QTextBrowser* text_edit);
~Q_DebugStream();
static void registerQDebugMessageHandler();
int displayMask;
int detailsMask;
private:
static void myQDebugMessageHandler(QtMsgType type, const QMessageLogContext &context, const QString &msg);
protected:
//This is called when a std::endl has been inserted into the stream
virtual int_type overflow(int_type v);
virtual std::streamsize xsputn(const char *p, std::streamsize n);
private:
std::ostream &m_stream;
std::streambuf *m_old_buf;
QTextBrowser* log_window;
};
#endif // Q_DEBUGSTREAM_H

143
hit2023v2_RMS/cbuffer.h Normal file
View File

@ -0,0 +1,143 @@
#ifndef CBUFFER_H
#define CBUFFER_H
#include <QMutex>
template <class T> class CBuffer
{
public:
CBuffer(int queueSize)
{
data = new T[queueSize];
size = queueSize;
push_ptr = 0;
pop_ptr = 0;
};
~CBuffer()
{
delete[] data;
};
int nrItems()
{
int result;
mutex.lock();
result = prvNrItems();
mutex.unlock();
return result;
};
int push(const T &to_push)
{
mutex.lock();
if (prvNrItems() >= (size - 1))
{
mutex.unlock();
return 0; //queue full!
}
data[push_ptr++] = to_push;
if (push_ptr >= size)
push_ptr = 0;
mutex.unlock();
return 1;
};
int pop(T &popped)
{
mutex.lock();
if (prvNrItems() == 0)
{
mutex.unlock();
return 0;
}
popped = data[pop_ptr++];
if (pop_ptr >= size)
pop_ptr = 0;
mutex.unlock();
return 1;
};
T pop()
{
mutex.lock();
T popped;
if (prvNrItems() >0)
{
popped = data[pop_ptr++];
if (pop_ptr >= size)
pop_ptr = 0;
}
mutex.unlock();
return popped;
};
//just look at the next element to be popped
int look(T &looked)
{
mutex.lock();
if (prvNrItems() == 0)
{
mutex.unlock();
return 0;
}
looked = data[pop_ptr];
mutex.unlock();
return 1;
};
T look()
{
mutex.lock();
T looked;
if (prvNrItems() >0)
looked = data[pop_ptr];
mutex.unlock();
return looked;
};
//just remove what would be popped
void dump()
{
mutex.lock();
if (prvNrItems() >0)
{
if (++pop_ptr >= size)
pop_ptr = 0;
}
mutex.unlock();
}
void clear()
{
mutex.lock();
push_ptr = 0;
pop_ptr = 0;
mutex.unlock();
};
protected:
T* data;
int push_ptr;
int pop_ptr;
int size;
QMutex mutex;
int prvNrItems()
{
int result = push_ptr - pop_ptr;
if (result < 0)
result += size;
return result;
};
};
#endif // CBUFFER_H

View File

@ -0,0 +1,171 @@
#include "datareceiver.h"
#include "dev_commands.h"
#include "helpers.h"
DataReceiver::DataReceiver(QObject *parent) : QObject(parent), dataBuffer(RECEIVER_BUFFER_SIZE)
{
connect(this, DataReceiver::sigInit, this, DataReceiver::onInit);
connect(this, DataReceiver::sigDeinit, this, DataReceiver::onDeinit);
connect(this, DataReceiver::sigConfigureEthSettings, this, DataReceiver::onConfigureEthSettings);
moveToThread(&thread);
thread.start();
init();
}
DataReceiver::~DataReceiver()
{
deinit();
thread.quit();
thread.wait();
}
//********************** Receiving data **************************
void DataReceiver::readData()
{
int size_received_bytes;
while ((size_received_bytes = dataSocket->readDatagram(tmpBuffer, DATA_PACKET_SIZE)) > 0)
{
//look if the packet isn't too short
int expected_size_bytes = ethBunch * (DATA_PACKET_HEADER_SIZE + DATA_SYNC_HEADER_SIZE + dmaBunch*DATA_BLOCK_SIZE);
if (size_received_bytes < expected_size_bytes)
continue;
for (int ethb = 0; ethb < ethBunch; ethb++)
{
int baseaddr = ethb * (DATA_PACKET_HEADER_SIZE + DATA_SYNC_HEADER_SIZE + dmaBunch*DATA_BLOCK_SIZE);
//check the header
if (BYTES2SHORT(tmpBuffer+baseaddr+0) != 0x5555)
continue;
if (BYTES2SHORT(tmpBuffer+baseaddr+2) != COMMAND_DATA_TRANSFER)
continue;
if ((BYTES2SHORT(tmpBuffer+baseaddr+4)*2) != (DATA_SYNC_HEADER_SIZE + dmaBunch*DATA_BLOCK_SIZE))
continue;
//read sync data;
SyncFrame sync;
sync.local_ctr = BYTES2SHORT(tmpBuffer+baseaddr+DATA_PACKET_HEADER_SIZE);
sync.global_ctr = BYTES2SHORT(tmpBuffer+baseaddr+DATA_PACKET_HEADER_SIZE+2);
sync.sma_state = BYTES2SHORT(tmpBuffer+baseaddr+DATA_PACKET_HEADER_SIZE+4);
sync.device_nr = devNr;
sync.data_ok = 1;
for (int dmab=0; dmab<dmaBunch; dmab++)
{
framesReceived++;
int baseaddr2 = baseaddr + dmab*DATA_BLOCK_SIZE;
if (outputEnabled)
{
BufferData data_to_push(sensorsPerBoard * DATA_SAMPLES_PER_SENSOR); //todo is this big enough
data_to_push.sync_frame = sync;
int baseaddr3 = baseaddr2 + DATA_PACKET_HEADER_SIZE + DATA_SYNC_HEADER_SIZE;
for (int s = 0; s < (sensorsPerBoard * DATA_SAMPLES_PER_SENSOR); s++)
data_to_push.sensor_data[s] = 65535 - BYTES2SHORT(tmpBuffer + baseaddr3 + 2*s);
for (int i = 0; i < DATA_RMS_SIZE/4; i++)
data_to_push.rms_data[i] = BYTES2INT(tmpBuffer + baseaddr3 + 2 * sensorsPerBoard * DATA_SAMPLES_PER_SENSOR + 4 * i); //what is baseaddr3?
dataBuffer.push(data_to_push);
framesFromLastSig++;
}
}
}
}
if (framesFromLastSig >= RECEIVER_FRAMES_PER_SIG)
{
framesFromLastSig = 0;
emit sigDataReady(this);
}
}
//********************** Internal slots ************************
void DataReceiver::onTimer()
{
frameRate = framesReceived * 1000 / RECEIVER_TIMER_PERIOD_MS;
framesReceived = 0;
}
void DataReceiver::onInit()
{
if (dataSocket == NULL)
{
dataSocket = new QUdpSocket(this);
connect(dataSocket, QUdpSocket::readyRead, this, DataReceiver::readData);
}
if (timer == NULL)
{
timer = new QTimer(this);
connect(timer, QTimer::timeout, this, onTimer);
timer->start(RECEIVER_TIMER_PERIOD_MS);
}
initSemaphore.release();
}
void DataReceiver::onDeinit()
{
if (dataSocket != NULL)
{
delete dataSocket;
dataSocket = NULL;
}
if (timer != NULL)
{
delete timer;
timer = NULL;
}
initSemaphore.release();
}
void DataReceiver::onConfigureEthSettings()
{
dataSocket->close();
dataSocket->bind(address, port);
}
//********************** Controlling DataReceiver************************
void DataReceiver::init()
{
emit sigInit();
initSemaphore.acquire(); //wait for initialization
}
void DataReceiver::deinit()
{
emit sigDeinit();
initSemaphore.acquire(); //wait for deinitialization
}
void DataReceiver::configureEthSettings(QHostAddress address_to_set, quint16 port_to_set)
{
address = address_to_set;
port = port_to_set;
emit sigConfigureEthSettings();
}
void DataReceiver::configureBunchSize(int dma, int eth)
{
dmaBunch = dma;
ethBunch = eth;
}
void DataReceiver::outputEnable (int en)
{
outputEnabled = en;
if (!en)
dataBuffer.clear();
}

View File

@ -0,0 +1,159 @@
#ifndef DATARECEIVER_H
#define DATARECEIVER_H
#include <QObject>
#include <QUdpSocket>
#include <QTimer>
#include <QThread>
#include <QSemaphore>
#include "cbuffer.h"
#define DATA_PACKET_HEADER_SIZE 6
#define DATA_SYNC_HEADER_SIZE 6
#define DATA_BYTES_PER_SAMPLE 2
#define DATA_SAMPLES_PER_SENSOR 64
#define DATA_MAX_SENSORS_PER_BOARD 5
#define DATA_MAX_BUNCH 16 //max. product of dmaBunch * ethBunch
//new for RMS
#define DATA_RMS_MEAN 4 //bytes, 32 bits
#define DATA_RMS_STD 4
#define DATA_RMS_MAX 4
#define DATA_RMS_STATUS 4
#define DATA_RMS_SIZE (DATA_RMS_MEAN + DATA_RMS_STD + DATA_RMS_MAX + DATA_RMS_STATUS)
//end new for RMS
//#define DATA_BLOCK_SIZE (DATA_SENSORS_PER_BOARD * DATA_SAMPLES_PER_SENSOR * DATA_BYTES_PER_SAMPLE)
#define DATA_BLOCK_SIZE (sensorsPerBoard * DATA_SAMPLES_PER_SENSOR * DATA_BYTES_PER_SAMPLE + DATA_RMS_SIZE)
#define DATA_PACKET_SIZE ( DATA_MAX_BUNCH * (DATA_PACKET_HEADER_SIZE + DATA_SYNC_HEADER_SIZE + DATA_BLOCK_SIZE) )
#define DATA_MAX_BLOCK_SIZE (DATA_MAX_SENSORS_PER_BOARD * DATA_SAMPLES_PER_SENSOR * DATA_BYTES_PER_SAMPLE + DATA_RMS_SIZE)
#define DATA_MAX_PACKET_SIZE ( DATA_MAX_BUNCH * (DATA_PACKET_HEADER_SIZE + DATA_SYNC_HEADER_SIZE + DATA_MAX_BLOCK_SIZE) )
#define RECEIVER_BUFFER_SIZE 10000
#define RECEIVER_TIMER_PERIOD_MS 200 //The period of the timer to measure data rate. The measurement is always properly scaled.
#define RECEIVER_FRAMES_PER_SIG 100 //The DataReady signal is transmitted only every N frames, not to overload queued signals framework.
typedef struct
{
//unsigned short channel_id;
unsigned short local_ctr;
unsigned short global_ctr;
unsigned short sma_state;
//these files are additional compared to STM side
unsigned short dummy = 0xFFFF; //for nice structure packing
int device_nr;
int data_ok;
} SyncFrame;
class BufferData
{
public:
SyncFrame sync_frame;
int buffer_size;
signed short* sensor_data;
int rms_data[DATA_RMS_SIZE/4];
BufferData() : buffer_size(0), sensor_data(NULL) {}
BufferData(int size) : buffer_size(0), sensor_data(NULL)
{
resize(size);
}
void resize(int size)
{
if (size == buffer_size)
return; //no need to change
if (sensor_data)
{
delete[] sensor_data;
sensor_data = NULL;
}
buffer_size = size;
if (size) //do not allocate memory for an empty buffer
sensor_data = new signed short[size];
}
BufferData(const BufferData& master) : buffer_size(0), sensor_data(NULL)
{
sync_frame = master.sync_frame;
resize(master.buffer_size);
memcpy(sensor_data, master.sensor_data, buffer_size*sizeof(signed short));
memcpy(rms_data, master.rms_data, DATA_RMS_SIZE);
}
BufferData& operator=(const BufferData& master)
{
if (this == &master)
return *this; //self-assignment
sync_frame = master.sync_frame;
resize(master.buffer_size);
memcpy(sensor_data, master.sensor_data, buffer_size*sizeof(signed short));
memcpy(rms_data, master.rms_data, DATA_RMS_SIZE);
return *this;
}
~BufferData()
{
resize(0); // :)
}
//unsigned short sensor_data[DATA_SENSORS_PER_BOARD * DATA_SAMPLES_PER_SENSOR];
};
typedef CBuffer<BufferData> DataBuffer;
class DataReceiver : public QObject
{
Q_OBJECT
public:
explicit DataReceiver(QObject *parent = 0);
~DataReceiver();
void configureEthSettings(QHostAddress address_to_set, quint16 port_to_set);
void configureBunchSize(int dma, int eth);
void outputEnable(int en);
int frameRate = 0;
int devNr = 0;
int sensorsPerBoard = 2;
DataBuffer dataBuffer;
signals:
void sigInit();
void sigDeinit();
void sigConfigureEthSettings();
void sigDataReady(DataReceiver* ptr);
public slots:
void onTimer();
protected:
void init();
void deinit();
QThread thread;
QSemaphore initSemaphore;
QTimer* timer = NULL;
QUdpSocket* dataSocket = NULL;
QHostAddress address;
quint16 port;
int outputEnabled = 0;
int dmaBunch = 1;
int ethBunch = 1;
char tmpBuffer[DATA_MAX_PACKET_SIZE];
int framesReceived = 0; //to calculate frame rate
int framesFromLastSig = 0;
protected slots:
void readData();
void onInit();
void onDeinit();
void onConfigureEthSettings();
};
#endif // DATARECEIVER_H

Binary file not shown.

View File

@ -0,0 +1,51 @@
[Global]
NrDevices=3
HostIp=10.0.7.1
[Device0]
IP=10.0.7.17
HardwareVer=2
Plane=0
Position=0
Sensors=5
Master=1
MasterDelay=62
SlaveDelay=34
[Device1]
IP=10.0.7.3
HardwareVer=1
Plane=1
Position=0
Sensors=2
Master=0
MasterDelay=7
SlaveDelay=1
[Trigger]
Period=8999
Tint=8549
Gain=1
Period_v2=2499
Tint_v2=336
Gain_v2=1
[Device2]
IP=10.0.7.5
HardwareVer=1
Plane=2
Position=0
Sensors=2
Master=0
MasterDelay=7
SlaveDelay=1
[Device3]
IP=10.0.7.6
HardwareVer=1
Plane=3
Position=0
Sensors=2
Master=0
MasterDelay=7
SlaveDelay=1

Binary file not shown.

Binary file not shown.

View File

@ -0,0 +1,123 @@
#ifndef DEV_COMMANDS_H
#define DEV_COMMANDS_H
#define COMMAND_PING 0x0001
//L: 0
//D: []
//Return the same
#define COMMAND_DEBUG_LED_OFF 0x0010
//L: 0
//D: [];
//Turn off green LED
#define COMMAND_DEBUG_LED_ON 0x0011
//L: 0
//D: [];
//Turn on green LED
// ***DEVICE CONTROL***
#define COMMAND_LEDS_DISABLE 0x0110
//L: 0
//D: [];
//Disable and turn off all LEDs
#define COMMAND_LEDS_ENABLE 0x0111
//L: 0
//D: [];
//Enable all LEDs
// ***TRIGGER SETTING***
#define COMMAND_TRIGGER_DISABLE 0x0210
//L: 0
//D: [];
//Disable trigger generation in master mode
#define COMMAND_TRIGGER_ENABLE 0x0211
//L: 0
//D: [];
//Enable trigger generation in master mode
#define COMMAND_TRIGGER_SET_SLAVE 0x0220
//L: 0
//D: [];
//Set trigger to slave mode
#define COMMAND_TRIGGER_SET_MASTER 0x0221
//L: 0
//D: [];
//Set trigger to master mode
#define COMMAND_TRIGGER_SET_PERIOD 0x0230
//L: 1 L: 0
//D: [Period_ticks] D: []
//Set trigger period for master mode in timer ticks
#define COMMAND_TRIGGER_SET_TINT 0x0240
//L: 1 L: 0
//D: [Tint_ticks] D: []
//Set integration time in timer ticks
#define COMMAND_SET_GAIN 0x0250
//L: 1 L:0
//D: [gain] D: []
#define COMMAND_TRIGGER_SET_MASTER_DELAY 0x0260
//L: 1 L: 0
//D: [Tdelay_ticks] D: []
//Set trigger delay time in timer ticks for master mode.
#define COMMAND_TRIGGER_SET_SLAVE_DELAY 0x0270
//L: 1 L: 0
//D: [Tdelay_ticks] D: []
//Set trigger delay time in timer ticks for slave mode.
// ***DAQ CONTROL***
#define COMMAND_DAQ_DISABLE 0x0310
//L: 0
//D: [];
//Disable sending data
#define COMMAND_DAQ_ENABLE 0x0311
//L: 0
//D: [];
//Enable sending data
#define COMMAND_DAQ_RESET_COUNTERS 0x0321
//L: 0
//D: []
//Reset synchronization counters
#define COMMAND_DAQ_FLUSH_DATA 0x0322
//L: 0
//D: []
//Send all remaining data over data socket
#define COMMAND_DAQ_CONFIG_PEER 0x0331
//L: 5 L: 0
//D: [ip ip ip ip port] D: []
//Set connection settings (peer IP and port) for data transfer
//Warning: IP is sent as 4 shorts with MSB=0!
// ***SLOW CONTROL***
#define COMMAND_SLOWCTRL_SNAPSHOT 0x0410
//L: 0 L: 10
//D:[] D: [(Readout of 5 ADC channels as 32-bit integers)]
//Slow control snapshot - read all channels of ADC
// ***DATA TRANSFER - SOCKET 1!!!!***
#define COMMAND_DATA_TRANSFER 0x8000
//(no incoming packet) L: 64*daq_dma_frame_bunch*daq_eth_frame_bunch
//(no incoming packet) D: [(Readout of 5 ADC channels as 32-bit integers)]
//Slow control snapshot - read all channels of ADC
#endif // DEV_COMMANDS_H

482
hit2023v2_RMS/device.cpp Normal file
View File

@ -0,0 +1,482 @@
#include "device.h"
#include "dev_commands.h"
#include "helpers.h"
#include <QtGlobal>
//************** Constructor ********************
// Qt5
/*
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();*/
//}
//Qt6
Device::Device(QObject *parent) : QObject(parent), controlSocket(this)
{
connect(&controlSocket, &QTcpSocket::connected, this, &Device::onConnected);
connect(&controlSocket, &QAbstractSocket::errorOccurred,
[this](QAbstractSocket::SocketError socketError) {
this->onSocketError(socketError);
});
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);*/
}

110
hit2023v2_RMS/device.h Normal file
View File

@ -0,0 +1,110 @@
#ifndef DEVICE_H
#define DEVICE_H
#include <QObject>
#include <QTcpSocket>
#include <QUdpSocket>
#include <QVector>
#include <QThread>
#include <QMutex>
#include "datareceiver.h"
#define DEV_CTRL_READ_TIMEOUT 500
#define DEV_CTRL_ERROR -1
#define DEV_CTRL_OK 0
#define DEV_BASE_DATA_PORT 4000
class DeviceConfig
{
public:
unsigned char own_ip[4];
unsigned char device_ip[4];
int device_id;
int hardware_ver;
int master;
int plane; //for ex. X may be 0 and Y may be 1
int position; //physical position within plane
int nr_sensors; //a device may be equipped with only one sensor
int period;
int tint;
int master_delay; //trigger delay values to synchronize boards
int slave_delay;
int gain; //0 (low) or 1 (high); TO BE DONE
int dma_bunch;
int eth_bunch;
int max_sensors()
{
switch(hardware_ver)
{
case 1: return 2; break;
case 2: return 5; break;
default: qCritical("Unsupported hardware version!"); return 0; break;
}
}
int max_channels() {return 64*max_sensors();}
int nr_channels() {return 64*nr_sensors;}
DeviceConfig() : own_ip{10,0,7,1}, device_ip{10,0,7,2},
device_id{0}, hardware_ver{0}, master{1}, plane{0}, position{0}, nr_sensors{0},
period{65535}, tint{1}, master_delay{1}, slave_delay{1}, gain{0}, dma_bunch{1}, eth_bunch{1} {}
};
class Device : public QObject
{
Q_OBJECT
public:
explicit Device(QObject *parent = 0);
~Device();
void connectDevice();
void disconnectDevice();
void configure(DeviceConfig &cfg);
void startAcq();
void stopAcq();
void leds(int leds_enable, int debug_led);
int getFrameRate();
DeviceConfig deviceConfig;
DataReceiver dataReceiver;
signals:
protected:
int connected = 0;
QTcpSocket controlSocket;
//QThread receiverThread;
int sendCtrl(unsigned short command, QVector<unsigned short> &data);
int receiveCtrl(unsigned short &command, QVector<unsigned short> &data);
int queryCtrl(unsigned short command, QVector<unsigned short> &txdata, QVector<unsigned short> &rxdata);
int ctrlPing();
int ctrlDebugLed(int state);
int ctrlLeds(int en);
int ctrlTrigger(int en);
int ctrlMaster(int en);
int ctrlSetPeriod(int period);
int ctrlSetTint(int tint);
int ctrlDaq(int en);
int ctrlResetCounters();
int ctrlFlushData();
int ctrlConfigPeer(unsigned short *ip, unsigned short port);
int ctrlSetGain(int val);
int ctrlConfigBunch(int dma, int eth);
int ctrlSetMasterDelay(int tint);
int ctrlSetSlaveDelay(int tint);
protected slots:
void onConnected();
void onSocketError(QAbstractSocket::SocketError socketError);
void onDisconnected();
};
#endif // DEVICE_H

View File

@ -0,0 +1,51 @@
[Global]
NrDevices=2
HostIp=10.0.7.1
[Device0]
IP=10.0.7.17
HardwareVer=2
Plane=0
Position=0
Sensors=5
Master=1
MasterDelay=62
SlaveDelay=34
[Device1]
IP=10.0.7.18
HardwareVer=2
Plane=1
Position=0
Sensors=5
Master=0
MasterDelay=7
SlaveDelay=1
[Trigger]
Period=8999
Tint=8491
Gain=1
Period_v2=2500
Tint_v2=336
Gain_v2=1
[Device2]
IP=10.0.7.5
HardwareVer=1
Plane=2
Position=0
Sensors=2
Master=0
MasterDelay=7
SlaveDelay=1
[Device3]
IP=10.0.7.6
HardwareVer=1
Plane=3
Position=0
Sensors=2
Master=0
MasterDelay=7
SlaveDelay=1

View File

@ -0,0 +1,288 @@
#include "dialogbeta.h"
#include "ui_dialogbeta.h"
#include <QFileDialog>
#define RUNNING 1
#define STOPPED 0
#define STOP_ISSUED -1
DialogBeta::DialogBeta(QWidget *parent) :
QDialog(parent),
ui(new Ui::DialogBeta)
{
ui->setupUi(this);
runState = STOPPED;
nrRunsDone = 0;
maxSpeed = 1500;
}
DialogBeta::~DialogBeta()
{
timer.stop();
disconnect(&timer, QTimer::timeout, this, &DialogBeta::onTimer);
delete ui;
}
void DialogBeta::showEvent(QShowEvent * event)
{
if (!event->spontaneous())
{
ui->spinScanSpeed->setMaximum(maxSpeed);
ui->lineRunsDone->setText(QString("%1").arg(nrRunsDone));
//data logging possible only if global data logging is switched off
if (theHW->eventBuilder.isLogging())
ui->checkSaveRawData->setEnabled(FALSE);
connect(&timer, QTimer::timeout, this, &DialogBeta::onTimer);
timer.start(250);
}
}
//************** Timer event ***************
void DialogBeta::onTimer()
{
theStepper->command_GAP(STEPPER_SAP_ACTUAL_POSITION, &currentPosition);
QString to_print = QString("%1").arg(currentPosition);
ui->lineStepperPosition->setText(to_print);
}
//************** Processing ***************
void DialogBeta::run(QString raw_data_filename)
{
runState = RUNNING;
//Prepare measurement
ui->plotResultsMean->clearGraphs();
ui->plotResultsStd->clearGraphs();
int nr_devices = theHW->devices.length();
int start_pos = ui->spinStartPos->value();
int end_pos = ui->spinEndPos->value();
int scan_speed = ui->spinScanSpeed->value();
//Data structures for plot
QVector<double> xdata;
QVector<double> ymeandata;
QVector<double> ystddata;
ui->plotResultsMean->addGraph();
ui->plotResultsStd->addGraph();
for (int ch = 0; ch < nr_devices*128; ch++)
xdata.append(ch);
double ymeanmin = 1e+10;
double ymeanmax = -1e+10;
double ystdmin = 1e+10;
double ystdmax = -1e+10;
//Set up stepper drive
qInfo("Setting up stepper drive...");
theStepper->command_SAP(4,maxSpeed);
theStepper->command_MVP(STEPPER_MVP_ABSOLUTE, start_pos);
while (currentPosition != start_pos)
{
QCoreApplication::processEvents();
QThread::msleep(10);
if (runState == STOP_ISSUED)
{
theStepper->command_MST();
runState = STOPPED;
return;
}
}
//Measure!
qInfo("Scanning...");
theStepper->command_SAP(4,scan_speed);
theStepper->command_MVP(STEPPER_MVP_ABSOLUTE, end_pos);
if (raw_data_filename.length())
theHW->eventBuilder.startLogging(raw_data_filename);
theHW->eventBuilder.startTakingHistos(-1);
while ((runState != STOP_ISSUED) && (currentPosition != end_pos))
{
QCoreApplication::processEvents();
QThread::msleep(10);
if (runState == STOP_ISSUED)
{
theStepper->command_MST();
runState = STOPPED;
return;
}
}
theHW->eventBuilder.stopTakingHistos();
if (raw_data_filename.length())
theHW->eventBuilder.stopLogging();
//Process results
qInfo("Processing data...");
BetaTestResult result;
//Collect sensor data
QVector<Histogram> histos = theHW->eventBuilder.getHistos();
result.mean.fill(0, nr_devices*128);
result.std.fill(0, nr_devices*128);
for (int i = 0; i < result.mean.length(); i++)
{
histos[i].MS(&(result.mean[i]), &(result.std[i]));
}
//Add other information
result.nracqs = histos[0].getNrSamples();
result.startpos = start_pos;
result.endpos = end_pos;
result.motorspeed = scan_speed;
//Store result
results.append(result);
//Plot data...
ymeandata.clear();
ymeandata.fill(0, nr_devices*128);
ystddata.clear();
ystddata.fill(0,nr_devices*128);
for (int ch = 0; ch < (nr_devices*128); ch++)
{
ymeandata[ch] = result.mean[ch];
if (result.mean[ch] > ymeanmax)
ymeanmax = result.mean[ch];
if (result.mean[ch] < ymeanmin)
ymeanmin = result.mean[ch];
ystddata[ch] = result.std[ch];
if (result.std[ch] > ystdmax)
ystdmax = result.std[ch];
if (result.std[ch] < ystdmin)
ystdmin = result.std[ch];
}
ui->plotResultsMean->xAxis->setRange(0, nr_devices*128-1);
ui->plotResultsMean->yAxis->setRange(ymeanmin, ymeanmax);
ui->plotResultsStd->xAxis->setRange(0, nr_devices*128-1);
ui->plotResultsStd->yAxis->setRange(ystdmin, ystdmax);
ui->plotResultsMean->graph(0)->setData(xdata, ymeandata);
ui->plotResultsStd->graph(0)->setData(xdata, ystddata);
ui->plotResultsMean->replot();
ui->plotResultsStd->replot();
nrRunsDone++;
ui->lineRunsDone->setText(QString("%1").arg(nrRunsDone));
qInfo("Scan finished!");
runState = STOPPED;
}
//************** Slots ****************
void DialogBeta::onHistogramCompleted()
{
histoReady = 1;
}
void DialogBeta::on_pushRun_pressed()
{
if (runState)
{
runState = STOP_ISSUED;
}
else
{
ui->pushRun->setText("Stop");
ui->pushClear->setEnabled(false);
ui->pushSave->setEnabled(false);
QString raw_data_filename = QString("");
if (ui->checkSaveRawData->isChecked())
raw_data_filename = QFileDialog::getSaveFileName(this, "Select file for saving data", "", tr("Binary log files (*.dat)"));
if (raw_data_filename.length())
{
//Make copy of current settings
QString ini_filename = raw_data_filename/*.left(filename.lastIndexOf(QString("."))) */ + QString(".ini");
QSettings* settings_copy = new QSettings(ini_filename,QSettings::IniFormat);
copyQSettings (deviceSettings, settings_copy);
settings_copy->sync();
delete settings_copy;
}
run(raw_data_filename);
ui->pushRun->setText("Run");
ui->pushClear->setEnabled(true);
ui->pushSave->setEnabled(true);
}
}
void DialogBeta::on_pushSave_pressed()
{
QString filename = QFileDialog::getSaveFileName(this, "Select file for saving data", "", tr("Comma separated files (*.csv)"));
QString delimiter = QString(",");
if (filename.length() == 0)
return;
QFile file(filename);
if (!file.open(QIODevice::WriteOnly | QIODevice::Text))
return;
QTextStream out(&file);
out << qSetFieldWidth(14) << qSetRealNumberPrecision(8);
for (int row = 0; row < results.length(); row++)
{
out << results[row].nracqs << delimiter
<< results[row].startpos << delimiter
<< results[row].endpos << delimiter
<< results[row].motorspeed;
for (int col = 0; (col < results[row].mean.length()) && (col < results[row].std.length()); col++)
out << delimiter << results[row].mean[col] << delimiter << results[row].std[col];
out << QString("\n");
}
file.close();
}
void DialogBeta::on_pushClear_pressed()
{
nrRunsDone = 0;
results.clear();
ui->lineRunsDone->setText(QString("%1").arg(nrRunsDone));
}
void DialogBeta::on_pushLeft_pressed()
{
theStepper->command_ROL(maxSpeed);
}
void DialogBeta::on_pushLeft_released()
{
theStepper->command_MST();
}
void DialogBeta::on_pushRight_pressed()
{
theStepper->command_ROR(maxSpeed);
}
void DialogBeta::on_pushRight_released()
{
theStepper->command_MST();
}
void DialogBeta::on_pushResetCtr_pressed()
{
theStepper->command_SAP(STEPPER_SAP_ACTUAL_POSITION, 0);
}

View File

@ -0,0 +1,69 @@
#ifndef DIALOGBETA_H
#define DIALOGBETA_H
#include <QDialog>
#include <QVector>
#include <QList>
#include <QTimer>
#include <QSettings>
#include "hw.h"
#include "stepper.h"
#include "histogram.h"
#include "helpers.h"
typedef struct
{
int nracqs;
int startpos;
int endpos;
int motorspeed;
QVector<double> mean;
QVector<double> std;
} BetaTestResult;
namespace Ui {
class DialogBeta;
}
class DialogBeta : public QDialog
{
Q_OBJECT
public:
explicit DialogBeta(QWidget *parent = 0);
~DialogBeta();
HW* theHW;
Stepper* theStepper;
QSettings* deviceSettings;
int maxSpeed;
int currentPosition;
public slots:
void showEvent(QShowEvent *event);
void onHistogramCompleted();
void onTimer();
protected:
int runState;
int histoReady;
int nrRunsDone;
QList<BetaTestResult> results;
QTimer timer;
void run(QString raw_data_filename);
private slots:
void on_pushRun_pressed();
void on_pushSave_pressed();
void on_pushClear_pressed();
void on_pushLeft_pressed();
void on_pushLeft_released();
void on_pushRight_pressed();
void on_pushRight_released();
void on_pushResetCtr_pressed();
private:
Ui::DialogBeta *ui;
};
#endif // DIALOGLINEARITY_H

425
hit2023v2_RMS/dialogbeta.ui Normal file
View File

@ -0,0 +1,425 @@
<?xml version="1.0" encoding="UTF-8"?>
<ui version="4.0">
<class>DialogBeta</class>
<widget class="QDialog" name="DialogBeta">
<property name="geometry">
<rect>
<x>0</x>
<y>0</y>
<width>844</width>
<height>632</height>
</rect>
</property>
<property name="windowTitle">
<string>Beta Scanner</string>
</property>
<widget class="QDialogButtonBox" name="buttonBox">
<property name="geometry">
<rect>
<x>490</x>
<y>590</y>
<width>341</width>
<height>32</height>
</rect>
</property>
<property name="orientation">
<enum>Qt::Horizontal</enum>
</property>
<property name="standardButtons">
<set>QDialogButtonBox::Close</set>
</property>
</widget>
<widget class="QWidget" name="horizontalLayoutWidget">
<property name="geometry">
<rect>
<x>10</x>
<y>10</y>
<width>821</width>
<height>571</height>
</rect>
</property>
<layout class="QHBoxLayout" name="horizontalLayout">
<item>
<layout class="QVBoxLayout" name="verticalLayout">
<item>
<widget class="QLabel" name="label">
<property name="sizePolicy">
<sizepolicy hsizetype="Fixed" vsizetype="Fixed">
<horstretch>0</horstretch>
<verstretch>0</verstretch>
</sizepolicy>
</property>
<property name="text">
<string>Motor control</string>
</property>
<property name="alignment">
<set>Qt::AlignCenter</set>
</property>
</widget>
</item>
<item>
<layout class="QGridLayout" name="gridLayout_2">
<property name="leftMargin">
<number>0</number>
</property>
<property name="topMargin">
<number>0</number>
</property>
<property name="rightMargin">
<number>0</number>
</property>
<property name="bottomMargin">
<number>0</number>
</property>
<item row="0" column="0">
<widget class="QPushButton" name="pushLeft">
<property name="text">
<string>Left!</string>
</property>
</widget>
</item>
<item row="0" column="1">
<widget class="QPushButton" name="pushRight">
<property name="text">
<string>Right!</string>
</property>
</widget>
</item>
</layout>
</item>
<item>
<layout class="QHBoxLayout" name="horizontalLayout_3">
<property name="leftMargin">
<number>0</number>
</property>
<property name="topMargin">
<number>0</number>
</property>
<property name="rightMargin">
<number>0</number>
</property>
<property name="bottomMargin">
<number>0</number>
</property>
<item>
<widget class="QLineEdit" name="lineStepperPosition">
<property name="sizePolicy">
<sizepolicy hsizetype="Minimum" vsizetype="Fixed">
<horstretch>0</horstretch>
<verstretch>0</verstretch>
</sizepolicy>
</property>
</widget>
</item>
<item>
<widget class="QPushButton" name="pushResetCtr">
<property name="sizePolicy">
<sizepolicy hsizetype="Minimum" vsizetype="Fixed">
<horstretch>0</horstretch>
<verstretch>0</verstretch>
</sizepolicy>
</property>
<property name="text">
<string>Reset</string>
</property>
</widget>
</item>
</layout>
</item>
<item>
<spacer name="verticalSpacer_4">
<property name="orientation">
<enum>Qt::Vertical</enum>
</property>
<property name="sizeType">
<enum>QSizePolicy::Fixed</enum>
</property>
<property name="sizeHint" stdset="0">
<size>
<width>20</width>
<height>40</height>
</size>
</property>
</spacer>
</item>
<item>
<widget class="QLabel" name="label_3">
<property name="text">
<string>Scan settings</string>
</property>
</widget>
</item>
<item>
<layout class="QGridLayout" name="gridLayout">
<item row="1" column="0">
<widget class="QLabel" name="label_11">
<property name="text">
<string>Start pos:</string>
</property>
</widget>
</item>
<item row="0" column="0">
<widget class="QLabel" name="label_10">
<property name="text">
<string>Scanning speed</string>
</property>
</widget>
</item>
<item row="0" column="1">
<widget class="QSpinBox" name="spinScanSpeed">
<property name="minimum">
<number>1</number>
</property>
<property name="maximum">
<number>2048</number>
</property>
<property name="singleStep">
<number>100</number>
</property>
<property name="value">
<number>1000</number>
</property>
</widget>
</item>
<item row="1" column="1">
<widget class="QSpinBox" name="spinStartPos">
<property name="minimum">
<number>0</number>
</property>
<property name="maximum">
<number>1800000</number>
</property>
<property name="singleStep">
<number>10000</number>
</property>
<property name="value">
<number>0</number>
</property>
</widget>
</item>
<item row="2" column="0">
<widget class="QLabel" name="label_4">
<property name="text">
<string>End pos:</string>
</property>
</widget>
</item>
<item row="2" column="1">
<widget class="QSpinBox" name="spinEndPos">
<property name="maximum">
<number>1800000</number>
</property>
<property name="singleStep">
<number>10000</number>
</property>
<property name="value">
<number>1800000</number>
</property>
</widget>
</item>
</layout>
</item>
<item>
<spacer name="verticalSpacer_3">
<property name="orientation">
<enum>Qt::Vertical</enum>
</property>
<property name="sizeType">
<enum>QSizePolicy::Fixed</enum>
</property>
<property name="sizeHint" stdset="0">
<size>
<width>20</width>
<height>40</height>
</size>
</property>
</spacer>
</item>
<item>
<widget class="QPushButton" name="pushRun">
<property name="text">
<string>Run!</string>
</property>
</widget>
</item>
<item>
<widget class="QCheckBox" name="checkSaveRawData">
<property name="text">
<string>Save raw data</string>
</property>
</widget>
</item>
<item>
<spacer name="verticalSpacer_2">
<property name="orientation">
<enum>Qt::Vertical</enum>
</property>
<property name="sizeType">
<enum>QSizePolicy::Fixed</enum>
</property>
<property name="sizeHint" stdset="0">
<size>
<width>20</width>
<height>40</height>
</size>
</property>
</spacer>
</item>
<item>
<layout class="QHBoxLayout" name="horizontalLayout_2">
<property name="bottomMargin">
<number>0</number>
</property>
<item>
<widget class="QLabel" name="label_2">
<property name="text">
<string>Runs:</string>
</property>
</widget>
</item>
<item>
<widget class="QLineEdit" name="lineRunsDone">
<property name="sizePolicy">
<sizepolicy hsizetype="Fixed" vsizetype="Fixed">
<horstretch>0</horstretch>
<verstretch>0</verstretch>
</sizepolicy>
</property>
<property name="autoFillBackground">
<bool>false</bool>
</property>
<property name="readOnly">
<bool>true</bool>
</property>
</widget>
</item>
</layout>
</item>
<item>
<widget class="QPushButton" name="pushClear">
<property name="text">
<string>Clear</string>
</property>
</widget>
</item>
<item>
<widget class="QPushButton" name="pushSave">
<property name="text">
<string>Save results...</string>
</property>
</widget>
</item>
<item>
<spacer name="verticalSpacer">
<property name="orientation">
<enum>Qt::Vertical</enum>
</property>
<property name="sizeHint" stdset="0">
<size>
<width>20</width>
<height>40</height>
</size>
</property>
</spacer>
</item>
</layout>
</item>
<item>
<layout class="QVBoxLayout" name="verticalLayout_3">
<item>
<widget class="QLabel" name="label_12">
<property name="sizePolicy">
<sizepolicy hsizetype="Preferred" vsizetype="Fixed">
<horstretch>0</horstretch>
<verstretch>0</verstretch>
</sizepolicy>
</property>
<property name="text">
<string>Signal mean</string>
</property>
<property name="alignment">
<set>Qt::AlignCenter</set>
</property>
</widget>
</item>
<item>
<widget class="QCustomPlot" name="plotResultsMean" native="true">
<property name="sizePolicy">
<sizepolicy hsizetype="Expanding" vsizetype="Minimum">
<horstretch>0</horstretch>
<verstretch>0</verstretch>
</sizepolicy>
</property>
</widget>
</item>
<item>
<widget class="QLabel" name="label_13">
<property name="sizePolicy">
<sizepolicy hsizetype="Preferred" vsizetype="Fixed">
<horstretch>0</horstretch>
<verstretch>0</verstretch>
</sizepolicy>
</property>
<property name="text">
<string>Signal standard deviation</string>
</property>
<property name="alignment">
<set>Qt::AlignCenter</set>
</property>
</widget>
</item>
<item>
<widget class="QCustomPlot" name="plotResultsStd" native="true"/>
</item>
</layout>
</item>
</layout>
</widget>
<zorder>buttonBox</zorder>
<zorder>horizontalLayoutWidget</zorder>
<zorder>verticalSpacer_4</zorder>
</widget>
<customwidgets>
<customwidget>
<class>QCustomPlot</class>
<extends>QWidget</extends>
<header>qcustomplot.h</header>
<container>1</container>
</customwidget>
</customwidgets>
<resources/>
<connections>
<connection>
<sender>buttonBox</sender>
<signal>accepted()</signal>
<receiver>DialogBeta</receiver>
<slot>accept()</slot>
<hints>
<hint type="sourcelabel">
<x>248</x>
<y>254</y>
</hint>
<hint type="destinationlabel">
<x>157</x>
<y>274</y>
</hint>
</hints>
</connection>
<connection>
<sender>buttonBox</sender>
<signal>rejected()</signal>
<receiver>DialogBeta</receiver>
<slot>reject()</slot>
<hints>
<hint type="sourcelabel">
<x>316</x>
<y>260</y>
</hint>
<hint type="destinationlabel">
<x>286</x>
<y>274</y>
</hint>
</hints>
</connection>
</connections>
</ui>

View File

@ -0,0 +1,238 @@
#include "dialogdevices.h"
#include "ui_dialogdevices.h"
#include "helpers.h"
DialogDevices::DialogDevices(QWidget *parent) :
QDialog(parent),
ui(new Ui::DialogDevices)
{
ui->setupUi(this);
}
DialogDevices::~DialogDevices()
{
delete ui;
}
//***************** Initialization ******************
void DialogDevices::showEvent(QShowEvent * event)
{
if (!event->spontaneous())
{
if (deviceSettings != NULL)
{
top(deviceSettings);
deviceSettings->beginGroup("Global");
ui->spinNrDevices->setValue(deviceSettings->value("NrDevices", int(1)).toInt());
ui->tableDevices->setColumnCount(8);
QStringList h_header;
h_header.append("IP Address");
h_header.append("Hardware ver.");
h_header.append("Layer");
h_header.append("Position");
h_header.append("Sensors");
h_header.append("Master");
h_header.append("Master dly");
h_header.append("Slave dly");
ui->tableDevices->setHorizontalHeaderLabels(h_header);
importSettings();
}
initialized = 1;
}
QDialog::showEvent(event);
}
//***************** Processing ******************
void DialogDevices::accept()
{
// qInfo("Accepted!");
if (validateAndSave())
QDialog::accept();
}
void DialogDevices::importSettings()
{
int nr_devices = ui->spinNrDevices->value();
ui->tableDevices->setRowCount(nr_devices);
for (int dev_nr = 0; dev_nr < nr_devices; dev_nr++)
{
if (dev_nr >= last_nr_devices) //update only new rows!
{
top(deviceSettings);
QString group_label = QString("Device%1").arg(dev_nr);
deviceSettings->beginGroup(group_label);
QTableWidgetItem* newItem;
newItem = new QTableWidgetItem(deviceSettings->value("IP","0.0.0.0").toString());
ui->tableDevices->setItem(dev_nr, 0, newItem );
newItem = new QTableWidgetItem(deviceSettings->value("HardwareVer","1").toString());
ui->tableDevices->setItem(dev_nr, 1, newItem );
newItem = new QTableWidgetItem(deviceSettings->value("Plane","0").toString());
ui->tableDevices->setItem(dev_nr, 2, newItem );
newItem = new QTableWidgetItem(deviceSettings->value("Position","0").toString());
ui->tableDevices->setItem(dev_nr, 3, newItem );
newItem = new QTableWidgetItem(deviceSettings->value("Sensors","2").toString());
ui->tableDevices->setItem(dev_nr, 4, newItem );
newItem = new QTableWidgetItem(deviceSettings->value("Master","0").toString());
ui->tableDevices->setItem(dev_nr, 5, newItem );
newItem = new QTableWidgetItem(deviceSettings->value("MasterDelay","22").toString());
ui->tableDevices->setItem(dev_nr, 6, newItem );
newItem = new QTableWidgetItem(deviceSettings->value("SlaveDelay","1").toString());
ui->tableDevices->setItem(dev_nr, 7, newItem );
}
}
last_nr_devices = nr_devices;
}
int DialogDevices::validateAndSave()
{
if (deviceSettings == NULL)
return 0;
int nr_devices = ui->spinNrDevices->value();
int data_ok = 1;
//check each table row
for (int dev_nr = 0; dev_nr < nr_devices; dev_nr++)
{
//first the IP
QString user_data = ui->tableDevices->item(dev_nr,0)->text();
QString generated = ip2num(user_data);
//if the strings are identical, save the value and return 1
if (generated.compare(user_data) != 0)
data_ok = 0;
ui->tableDevices->item(dev_nr,0)->setText(generated);
//hardware version
user_data = ui->tableDevices->item(dev_nr,1)->text();
int num_hw = user_data.toInt();
if (num_hw < 1)
num_hw = 1;
if (num_hw > 2)
num_hw = 2;
generated = QString("%1").arg(num_hw);
//if the strings are identical, save the value and return 1
if (generated.compare(user_data) != 0)
data_ok = 0;
ui->tableDevices->item(dev_nr,1)->setText(generated);
//now the plane
user_data = ui->tableDevices->item(dev_nr,2)->text();
int num_value = user_data.toInt();
if (num_value < 0)
num_value = 0;
generated = QString("%1").arg(num_value);
//if the strings are identical, save the value and return 1
if (generated.compare(user_data) != 0)
data_ok = 0;
ui->tableDevices->item(dev_nr,2)->setText(generated);
//now physical position
user_data = ui->tableDevices->item(dev_nr,3)->text();
num_value = user_data.toInt();
if (num_value < 0)
num_value = 0;
generated = QString("%1").arg(num_value);
//if the strings are identical, save the value and return 1
if (generated.compare(user_data) != 0)
data_ok = 0;
ui->tableDevices->item(dev_nr,3)->setText(generated);
//now number of sensors
user_data = ui->tableDevices->item(dev_nr,4)->text();
num_value = user_data.toInt();
int max_sensors = (num_hw == 1) ? 2 : 5;
if (num_value < 1)
num_value = 1;
if (num_value > max_sensors)
num_value = max_sensors;
generated = QString("%1").arg(num_value);
//if the strings are identical, save the value and return 1
if (generated.compare(user_data) != 0)
data_ok = 0;
ui->tableDevices->item(dev_nr,4)->setText(generated);
//now master selector
user_data = ui->tableDevices->item(dev_nr,5)->text();
num_value = user_data.toInt();
if (num_value < 0)
num_value = 0;
if (num_value > 1)
num_value = 1;
generated = QString("%1").arg(num_value);
//if the strings are identical, save the value and return 1
if (generated.compare(user_data) != 0)
data_ok = 0;
ui->tableDevices->item(dev_nr,5)->setText(generated);
//now master delay
user_data = ui->tableDevices->item(dev_nr,6)->text();
num_value = user_data.toInt();
if (num_value < 1)
num_value = 1;
if (num_value > 255)
num_value = 255;
generated = QString("%1").arg(num_value);
//if the strings are identical, save the value and return 1
if (generated.compare(user_data) != 0)
data_ok = 0;
ui->tableDevices->item(dev_nr,6)->setText(generated);
//now slave delay
user_data = ui->tableDevices->item(dev_nr,7)->text();
num_value = user_data.toInt();
if (num_value < 1)
num_value = 1;
if (num_value > 255)
num_value = 255;
generated = QString("%1").arg(num_value);
//if the strings are identical, save the value and return 1
if (generated.compare(user_data) != 0)
data_ok = 0;
ui->tableDevices->item(dev_nr,7)->setText(generated);
}
//now store the data
if (!data_ok)
return 0;
top(deviceSettings);
deviceSettings->beginGroup("Global");
deviceSettings->setValue("NrDevices", nr_devices);
for (int dev_nr = 0; dev_nr < nr_devices; dev_nr++)
{
top(deviceSettings);
QString group_label = QString("Device%1").arg(dev_nr);
deviceSettings->beginGroup(group_label);
deviceSettings->setValue("IP", ui->tableDevices->item(dev_nr,0)->text());
deviceSettings->setValue("HardwareVer", ui->tableDevices->item(dev_nr,1)->text());
deviceSettings->setValue("Plane", ui->tableDevices->item(dev_nr,2)->text());
deviceSettings->setValue("Position", ui->tableDevices->item(dev_nr,3)->text());
deviceSettings->setValue("Sensors", ui->tableDevices->item(dev_nr,4)->text());
deviceSettings->setValue("Master", ui->tableDevices->item(dev_nr,5)->text());
deviceSettings->setValue("MasterDelay", ui->tableDevices->item(dev_nr,6)->text());
deviceSettings->setValue("SlaveDelay", ui->tableDevices->item(dev_nr,7)->text());
}
return 1;
}
void DialogDevices::on_spinNrDevices_valueChanged(int arg1)
{
if (initialized)
importSettings();
}

View File

@ -0,0 +1,36 @@
#ifndef DIALOGDEVICES_H
#define DIALOGDEVICES_H
#include <QDialog>
#include <QSettings>
#include <QShowEvent>
namespace Ui {
class DialogDevices;
}
class DialogDevices : public QDialog
{
Q_OBJECT
public:
explicit DialogDevices(QWidget *parent = 0);
~DialogDevices();
QSettings* deviceSettings = NULL;
public slots:
void showEvent(QShowEvent *event);
void accept();
protected:
int validateAndSave();
void importSettings();
int last_nr_devices = -1;
int initialized = 0;
private slots:
void on_spinNrDevices_valueChanged(int arg1);
private:
Ui::DialogDevices *ui;
};
#endif // DIALOGDEVICES_H

View File

@ -0,0 +1,101 @@
<?xml version="1.0" encoding="UTF-8"?>
<ui version="4.0">
<class>DialogDevices</class>
<widget class="QDialog" name="DialogDevices">
<property name="geometry">
<rect>
<x>0</x>
<y>0</y>
<width>573</width>
<height>233</height>
</rect>
</property>
<property name="windowTitle">
<string>Devices</string>
</property>
<widget class="QDialogButtonBox" name="buttonBox">
<property name="geometry">
<rect>
<x>210</x>
<y>190</y>
<width>341</width>
<height>32</height>
</rect>
</property>
<property name="orientation">
<enum>Qt::Horizontal</enum>
</property>
<property name="standardButtons">
<set>QDialogButtonBox::Cancel|QDialogButtonBox::Ok</set>
</property>
</widget>
<widget class="QWidget" name="verticalLayoutWidget">
<property name="geometry">
<rect>
<x>20</x>
<y>10</y>
<width>531</width>
<height>171</height>
</rect>
</property>
<layout class="QVBoxLayout" name="verticalLayout">
<item>
<layout class="QHBoxLayout" name="horizontalLayout_2">
<item>
<widget class="QLabel" name="label">
<property name="text">
<string>Number of devices</string>
</property>
</widget>
</item>
<item>
<widget class="QSpinBox" name="spinNrDevices">
<property name="minimum">
<number>1</number>
</property>
</widget>
</item>
</layout>
</item>
<item>
<widget class="QTableWidget" name="tableDevices"/>
</item>
</layout>
</widget>
</widget>
<resources/>
<connections>
<connection>
<sender>buttonBox</sender>
<signal>accepted()</signal>
<receiver>DialogDevices</receiver>
<slot>accept()</slot>
<hints>
<hint type="sourcelabel">
<x>248</x>
<y>254</y>
</hint>
<hint type="destinationlabel">
<x>157</x>
<y>274</y>
</hint>
</hints>
</connection>
<connection>
<sender>buttonBox</sender>
<signal>rejected()</signal>
<receiver>DialogDevices</receiver>
<slot>reject()</slot>
<hints>
<hint type="sourcelabel">
<x>316</x>
<y>260</y>
</hint>
<hint type="destinationlabel">
<x>286</x>
<y>274</y>
</hint>
</hints>
</connection>
</connections>
</ui>

View File

@ -0,0 +1,74 @@
#include "dialoghostip.h"
#include "ui_dialoghostip.h"
#include "helpers.h"
#include <QStringList>
DialogHostIp::DialogHostIp(QWidget *parent) :
QDialog(parent),
ui(new Ui::DialogHostIp)
{
ui->setupUi(this);
}
DialogHostIp::~DialogHostIp()
{
delete ui;
}
//***************** Initialization ******************
void DialogHostIp::showEvent(QShowEvent * event)
{
if (!event->spontaneous())
if (deviceSettings != NULL)
{
top(deviceSettings);
deviceSettings->beginGroup("Global");
QString ip = deviceSettings->value("HostIp", QString("0.0.0.0")).toString();
ui->lineIp->setText(ip);
}
QDialog::showEvent(event);
}
//***************** Processing ******************
void DialogHostIp::accept()
{
// qInfo("Accepted!");
if (validateAndSave())
QDialog::accept();
}
int DialogHostIp::validateAndSave()
{
if (deviceSettings == NULL)
return 0;
QString user_data = ui->lineIp->text();
QString generated = ip2num(user_data);
//if the strings are identical, save the value and return 1
if (generated.compare(user_data) == 0)
{
top(deviceSettings);
deviceSettings->beginGroup("Global");
deviceSettings->setValue("HostIp", generated);
return 1;
}
else
//if not, display the parsed value and return 0
{
ui->lineIp->setText(generated);
return 0;
}
}

View File

@ -0,0 +1,33 @@
#ifndef DIALOGHOSTIP_H
#define DIALOGHOSTIP_H
#include <QDialog>
#include <QSettings>
#include <QShowEvent>
namespace Ui {
class DialogHostIp;
}
class DialogHostIp : public QDialog
{
Q_OBJECT
public:
explicit DialogHostIp(QWidget *parent = 0);
~DialogHostIp();
QSettings* deviceSettings = NULL;
public slots:
void showEvent(QShowEvent *event);
void accept();
protected:
int validateAndSave();
private slots:
private:
Ui::DialogHostIp *ui;
};
#endif // DIALOGHOSTIP_H

View File

@ -0,0 +1,90 @@
<?xml version="1.0" encoding="UTF-8"?>
<ui version="4.0">
<class>DialogHostIp</class>
<widget class="QDialog" name="DialogHostIp">
<property name="geometry">
<rect>
<x>0</x>
<y>0</y>
<width>185</width>
<height>99</height>
</rect>
</property>
<property name="windowTitle">
<string>Host IP</string>
</property>
<widget class="QDialogButtonBox" name="buttonBox">
<property name="geometry">
<rect>
<x>10</x>
<y>60</y>
<width>161</width>
<height>32</height>
</rect>
</property>
<property name="orientation">
<enum>Qt::Horizontal</enum>
</property>
<property name="standardButtons">
<set>QDialogButtonBox::Cancel|QDialogButtonBox::Ok</set>
</property>
</widget>
<widget class="QWidget" name="horizontalLayoutWidget">
<property name="geometry">
<rect>
<x>10</x>
<y>10</y>
<width>160</width>
<height>41</height>
</rect>
</property>
<layout class="QHBoxLayout" name="horizontalLayout">
<item>
<widget class="QLabel" name="label">
<property name="text">
<string>Host IP:</string>
</property>
</widget>
</item>
<item>
<widget class="QLineEdit" name="lineIp"/>
</item>
</layout>
</widget>
</widget>
<resources/>
<connections>
<connection>
<sender>buttonBox</sender>
<signal>accepted()</signal>
<receiver>DialogHostIp</receiver>
<slot>accept()</slot>
<hints>
<hint type="sourcelabel">
<x>248</x>
<y>254</y>
</hint>
<hint type="destinationlabel">
<x>157</x>
<y>274</y>
</hint>
</hints>
</connection>
<connection>
<sender>buttonBox</sender>
<signal>rejected()</signal>
<receiver>DialogHostIp</receiver>
<slot>reject()</slot>
<hints>
<hint type="sourcelabel">
<x>316</x>
<y>260</y>
</hint>
<hint type="destinationlabel">
<x>286</x>
<y>274</y>
</hint>
</hints>
</connection>
</connections>
</ui>

View File

@ -0,0 +1,204 @@
#include "dialoglinearity.h"
#include "ui_dialoglinearity.h"
#define RUNNING 1
#define STOPPED 0
#define STOP_ISSUED -1
DialogLinearity::DialogLinearity(QWidget *parent) :
QDialog(parent),
ui(new Ui::DialogLinearity)
{
ui->setupUi(this);
runState = STOPPED;
}
DialogLinearity::~DialogLinearity()
{
delete ui;
}
//************** Processing ***************
void DialogLinearity::run()
{
runState = RUNNING;
qInfo("Starting linearity test...");
//Prepare measurement
ui->plotResultsMean->clearGraphs();
ui->plotResultsStd->clearGraphs();
results.clear();
int nr_devices = theHW->devices.length();
int decimation = ui->spinPLotDecimation->value();
int tdelay = ui->spinDelay->value();
int nacqs = ui->spinAcquisitions->value();
double vstart = ui->doubleSpinVstart->value();
double vend = ui->doubleSpinVend->value();
double vinc = ui->doubleSpinVinc->value();
double vcurrent = vstart;
//Plot data
QVector<double> xdata;
QList<QVector<double>> ymeandata;
QList<QVector<double>> ystddata;
for (int ch = 0; ch < (nr_devices*128); ch+= decimation)
{
ymeandata.append(xdata); //just add empty vectors to the list
ystddata.append(xdata); //just add empty vectors to the list
}
//The number of plotted lines is smaller than number of channels - see decimation
for (int plotnr = 0; plotnr < nr_devices*128; plotnr++)
{
ui->plotResultsMean->addGraph();
ui->plotResultsStd->addGraph();
}
double xmin = 1e+10;
double xmax = -1e+10;
double ymeanmin = 1e+10;
double ymeanmax = -1e+10;
double ystdmin = 1e+10;
double ystdmax = -1e+10;
theKeithley->setVoltage(vcurrent);
theKeithley->on(1);
//Measure!
while ((runState != STOP_ISSUED) && (vcurrent <= vend))
{
//Set LED voltage
qInfo(qPrintable(QString("LED voltage: %1 V").arg(vcurrent)));
theKeithley->setVoltage(vcurrent);
//Wait
msleep2(tdelay);
TestResult result;
//Collect sensor data
histoReady = 0;
connect(&(theHW->eventBuilder), EventBuilder::sigHistoCompleted, this, DialogLinearity::onHistogramCompleted);
theHW->eventBuilder.startTakingHistos(nacqs);
while (!histoReady)
{
QCoreApplication::processEvents();
QThread::msleep(10);
}
disconnect(&(theHW->eventBuilder), EventBuilder::sigHistoCompleted, this, DialogLinearity::onHistogramCompleted);
QVector<Histogram> histos = theHW->eventBuilder.getHistos();
result.mean.fill(0, nr_devices*128);
result.std.fill(0, nr_devices*128);
for (int i = 0; i < result.mean.length(); i++)
{
histos[i].MS(&(result.mean[i]), &(result.std[i]));
//result.mean[i] = histos[i].mean();
//result.std[i] = histos[i].stdev();
}
//Add LED/PD information
result.vled = vcurrent;
result.ipd = theKeithley->getCurrent();
results.append(result);
//Plot data...
xdata.append(result.ipd);
if (result.ipd > xmax)
xmax = result.ipd;
if (result.ipd < xmin)
xmin = result.ipd;
for (int ch = 0, i = 0; ch < (nr_devices*128); ch+= decimation, i++)
{
ymeandata[i].append(result.mean[ch]);
if (result.mean[ch] > ymeanmax)
ymeanmax = result.mean[ch];
if (result.mean[ch] < ymeanmin)
ymeanmin = result.mean[ch];
ystddata[i].append(result.std[ch]);
if (result.std[ch] > ystdmax)
ystdmax = result.std[ch];
if (result.std[ch] < ystdmin)
ystdmin = result.std[ch];
}
ui->plotResultsMean->xAxis->setRange(xmin, xmax);
ui->plotResultsMean->yAxis->setRange(ymeanmin, ymeanmax);
ui->plotResultsStd->xAxis->setRange(xmin, xmax);
ui->plotResultsStd->yAxis->setRange(ystdmin, ystdmax);
for (int ch = 0, i = 0; ch < (nr_devices*128); ch+= decimation, i++)
{
ui->plotResultsMean->graph(i)->setData(xdata, ymeandata[i]);
ui->plotResultsStd->graph(i)->setData(xdata, ystddata[i]);
}
ui->plotResultsMean->replot();
ui->plotResultsStd->replot();
//Roll over
vcurrent += vinc;
QCoreApplication::processEvents();
}
theKeithley->on(0);
qInfo("Linearity test finished!");
runState = STOPPED;
}
//************** Slots ****************
void DialogLinearity::onHistogramCompleted()
{
histoReady = 1;
}
void DialogLinearity::on_pushRun_pressed()
{
if (runState)
{
runState = STOP_ISSUED;
}
else
{
ui->pushRun->setText("Stop");
ui->pushSave->setEnabled(false);
run();
ui->pushRun->setText("Run");
ui->pushSave->setEnabled(true);
}
}
void DialogLinearity::on_pushSave_pressed()
{
QString filename = QFileDialog::getSaveFileName(this, "Select file for saving data", "", tr("Comma separated files (*.csv)"));
QString delimiter = QString(",");
if (filename.length() == 0)
return;
QFile file(filename);
if (!file.open(QIODevice::WriteOnly | QIODevice::Text))
return;
QTextStream out(&file);
out << qSetFieldWidth(14) << qSetRealNumberPrecision(8);
for (int row = 0; row < results.length(); row++)
{
out << results[row].vled << delimiter << results[row].ipd;
for (int col = 0; (col < results[row].mean.length()) && (col < results[row].std.length()); col++)
out << delimiter << results[row].mean[col] << delimiter << results[row].std[col];
out << QString("\n");
}
file.close();
}

View File

@ -0,0 +1,52 @@
#ifndef DIALOGLINEARITY_H
#define DIALOGLINEARITY_H
#include <QDialog>
#include <QVector>
#include <QList>
#include "hw.h"
#include "keithley_thr.h"
#include "histogram.h"
#include "helpers.h"
typedef struct
{
double vled;
double ipd;
QVector<double> mean;
QVector<double> std;
} TestResult;
namespace Ui {
class DialogLinearity;
}
class DialogLinearity : public QDialog
{
Q_OBJECT
public:
explicit DialogLinearity(QWidget *parent = 0);
~DialogLinearity();
HW* theHW;
keithley_thr* theKeithley;
public slots:
void onHistogramCompleted();
protected:
int runState;
int histoReady;
QList<TestResult> results;
void run();
private slots:
void on_pushRun_pressed();
void on_pushSave_pressed();
private:
Ui::DialogLinearity *ui;
};
#endif // DIALOGLINEARITY_H

View File

@ -0,0 +1,386 @@
<?xml version="1.0" encoding="UTF-8"?>
<ui version="4.0">
<class>DialogLinearity</class>
<widget class="QDialog" name="DialogLinearity">
<property name="geometry">
<rect>
<x>0</x>
<y>0</y>
<width>844</width>
<height>632</height>
</rect>
</property>
<property name="windowTitle">
<string>Linearity Test</string>
</property>
<widget class="QDialogButtonBox" name="buttonBox">
<property name="geometry">
<rect>
<x>490</x>
<y>590</y>
<width>341</width>
<height>32</height>
</rect>
</property>
<property name="orientation">
<enum>Qt::Horizontal</enum>
</property>
<property name="standardButtons">
<set>QDialogButtonBox::Close</set>
</property>
</widget>
<widget class="QWidget" name="horizontalLayoutWidget">
<property name="geometry">
<rect>
<x>10</x>
<y>10</y>
<width>821</width>
<height>571</height>
</rect>
</property>
<layout class="QHBoxLayout" name="horizontalLayout">
<item>
<layout class="QVBoxLayout" name="verticalLayout">
<item>
<widget class="QLabel" name="label">
<property name="sizePolicy">
<sizepolicy hsizetype="Fixed" vsizetype="Fixed">
<horstretch>0</horstretch>
<verstretch>0</verstretch>
</sizepolicy>
</property>
<property name="text">
<string>Scan settings</string>
</property>
<property name="alignment">
<set>Qt::AlignCenter</set>
</property>
</widget>
</item>
<item>
<layout class="QGridLayout" name="gridLayout">
<item row="3" column="0">
<spacer name="verticalSpacer_2">
<property name="orientation">
<enum>Qt::Vertical</enum>
</property>
<property name="sizeType">
<enum>QSizePolicy::Fixed</enum>
</property>
<property name="sizeHint" stdset="0">
<size>
<width>20</width>
<height>40</height>
</size>
</property>
</spacer>
</item>
<item row="0" column="2">
<widget class="QLabel" name="label_5">
<property name="text">
<string>V</string>
</property>
</widget>
</item>
<item row="4" column="0">
<widget class="QLabel" name="label_8">
<property name="text">
<string>Measurement delay:</string>
</property>
</widget>
</item>
<item row="4" column="1">
<widget class="QSpinBox" name="spinDelay">
<property name="minimum">
<number>100</number>
</property>
<property name="maximum">
<number>10000</number>
</property>
<property name="singleStep">
<number>100</number>
</property>
<property name="value">
<number>1500</number>
</property>
</widget>
</item>
<item row="4" column="2">
<widget class="QLabel" name="label_9">
<property name="text">
<string>ms</string>
</property>
</widget>
</item>
<item row="2" column="2">
<widget class="QLabel" name="label_7">
<property name="text">
<string>V</string>
</property>
</widget>
</item>
<item row="1" column="2">
<widget class="QLabel" name="label_6">
<property name="text">
<string>V</string>
</property>
</widget>
</item>
<item row="5" column="0">
<widget class="QLabel" name="label_10">
<property name="text">
<string>Acqs/point:</string>
</property>
</widget>
</item>
<item row="5" column="1">
<widget class="QSpinBox" name="spinAcquisitions">
<property name="minimum">
<number>1</number>
</property>
<property name="maximum">
<number>1000000</number>
</property>
<property name="singleStep">
<number>1000</number>
</property>
<property name="value">
<number>10000</number>
</property>
</widget>
</item>
<item row="1" column="0">
<widget class="QLabel" name="label_3">
<property name="text">
<string>End LED voltage:</string>
</property>
</widget>
</item>
<item row="1" column="1">
<widget class="QDoubleSpinBox" name="doubleSpinVend">
<property name="maximum">
<double>10.000000000000000</double>
</property>
<property name="singleStep">
<double>0.100000000000000</double>
</property>
<property name="value">
<double>6.000000000000000</double>
</property>
</widget>
</item>
<item row="0" column="1">
<widget class="QDoubleSpinBox" name="doubleSpinVstart">
<property name="sizePolicy">
<sizepolicy hsizetype="Minimum" vsizetype="Fixed">
<horstretch>0</horstretch>
<verstretch>0</verstretch>
</sizepolicy>
</property>
<property name="maximum">
<double>10.000000000000000</double>
</property>
<property name="singleStep">
<double>0.100000000000000</double>
</property>
<property name="value">
<double>2.000000000000000</double>
</property>
</widget>
</item>
<item row="0" column="0">
<widget class="QLabel" name="label_2">
<property name="sizePolicy">
<sizepolicy hsizetype="Fixed" vsizetype="Preferred">
<horstretch>0</horstretch>
<verstretch>0</verstretch>
</sizepolicy>
</property>
<property name="text">
<string>Start LED voltage:</string>
</property>
</widget>
</item>
<item row="2" column="0">
<widget class="QLabel" name="label_4">
<property name="text">
<string>Voltage increment:</string>
</property>
</widget>
</item>
<item row="2" column="1">
<widget class="QDoubleSpinBox" name="doubleSpinVinc">
<property name="maximum">
<double>10.000000000000000</double>
</property>
<property name="singleStep">
<double>0.010000000000000</double>
</property>
<property name="value">
<double>0.100000000000000</double>
</property>
</widget>
</item>
<item row="6" column="0">
<widget class="QLabel" name="label_11">
<property name="text">
<string>Plot decimation:</string>
</property>
</widget>
</item>
<item row="6" column="1">
<widget class="QSpinBox" name="spinPLotDecimation">
<property name="minimum">
<number>1</number>
</property>
<property name="maximum">
<number>128</number>
</property>
<property name="value">
<number>16</number>
</property>
</widget>
</item>
</layout>
</item>
<item>
<spacer name="verticalSpacer_3">
<property name="orientation">
<enum>Qt::Vertical</enum>
</property>
<property name="sizeType">
<enum>QSizePolicy::Fixed</enum>
</property>
<property name="sizeHint" stdset="0">
<size>
<width>20</width>
<height>40</height>
</size>
</property>
</spacer>
</item>
<item>
<widget class="QPushButton" name="pushRun">
<property name="text">
<string>Run!</string>
</property>
</widget>
</item>
<item>
<widget class="QPushButton" name="pushSave">
<property name="text">
<string>Save results...</string>
</property>
</widget>
</item>
<item>
<spacer name="verticalSpacer">
<property name="orientation">
<enum>Qt::Vertical</enum>
</property>
<property name="sizeHint" stdset="0">
<size>
<width>20</width>
<height>40</height>
</size>
</property>
</spacer>
</item>
</layout>
</item>
<item>
<layout class="QVBoxLayout" name="verticalLayout_3">
<item>
<widget class="QLabel" name="label_12">
<property name="sizePolicy">
<sizepolicy hsizetype="Preferred" vsizetype="Fixed">
<horstretch>0</horstretch>
<verstretch>0</verstretch>
</sizepolicy>
</property>
<property name="text">
<string>Signal mean</string>
</property>
<property name="alignment">
<set>Qt::AlignCenter</set>
</property>
</widget>
</item>
<item>
<widget class="QCustomPlot" name="plotResultsMean" native="true">
<property name="sizePolicy">
<sizepolicy hsizetype="Expanding" vsizetype="Minimum">
<horstretch>0</horstretch>
<verstretch>0</verstretch>
</sizepolicy>
</property>
</widget>
</item>
<item>
<widget class="QLabel" name="label_13">
<property name="sizePolicy">
<sizepolicy hsizetype="Preferred" vsizetype="Fixed">
<horstretch>0</horstretch>
<verstretch>0</verstretch>
</sizepolicy>
</property>
<property name="text">
<string>Signal standard deviation</string>
</property>
<property name="alignment">
<set>Qt::AlignCenter</set>
</property>
</widget>
</item>
<item>
<widget class="QCustomPlot" name="plotResultsStd" native="true"/>
</item>
</layout>
</item>
</layout>
</widget>
</widget>
<customwidgets>
<customwidget>
<class>QCustomPlot</class>
<extends>QWidget</extends>
<header>qcustomplot.h</header>
<container>1</container>
</customwidget>
</customwidgets>
<resources/>
<connections>
<connection>
<sender>buttonBox</sender>
<signal>accepted()</signal>
<receiver>DialogLinearity</receiver>
<slot>accept()</slot>
<hints>
<hint type="sourcelabel">
<x>248</x>
<y>254</y>
</hint>
<hint type="destinationlabel">
<x>157</x>
<y>274</y>
</hint>
</hints>
</connection>
<connection>
<sender>buttonBox</sender>
<signal>rejected()</signal>
<receiver>DialogLinearity</receiver>
<slot>reject()</slot>
<hints>
<hint type="sourcelabel">
<x>316</x>
<y>260</y>
</hint>
<hint type="destinationlabel">
<x>286</x>
<y>274</y>
</hint>
</hints>
</connection>
</connections>
</ui>

View File

@ -0,0 +1,56 @@
#include "dialoglogsettings.h"
#include "ui_dialoglogsettings.h"
#include "Q_DebugStream.h"
#include <QShowEvent>
DialogLogSettings::DialogLogSettings(QWidget *parent) :
QDialog(parent),
ui(new Ui::DialogLogSettings)
{
ui->setupUi(this);
}
DialogLogSettings::~DialogLogSettings()
{
delete ui;
}
//$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$
void DialogLogSettings::showEvent(QShowEvent * event)
{
if (!event->spontaneous())
{
ui->checkDisplayDebug->setChecked((bool)(displayMask & DS_DEBUG));
ui->checkDisplayInfo->setChecked((bool)(displayMask & DS_INFO));
ui->checkDisplayWarning->setChecked((bool)(displayMask & DS_WARNING));
ui->checkDisplayCritical->setChecked((bool)(displayMask & DS_CRITICAL));
ui->checkDisplayFatal->setChecked((bool)(displayMask & DS_FATAL));
ui->checkDetailsDebug->setChecked((bool)(detailsMask & DS_DEBUG));
ui->checkDetailsInfo->setChecked((bool)(detailsMask & DS_INFO));
ui->checkDetailsWarning->setChecked((bool)(detailsMask & DS_WARNING));
ui->checkDetailsCritical->setChecked((bool)(detailsMask & DS_CRITICAL));
ui->checkDetailsFatal->setChecked((bool)(detailsMask & DS_FATAL));
}
QDialog::showEvent(event);
}
void DialogLogSettings::on_buttonGroup_buttonReleased(int arg1)
{
displayMask = 0;
if (ui->checkDisplayDebug->isChecked()) displayMask |= DS_DEBUG;
if (ui->checkDisplayInfo->isChecked()) displayMask |= DS_INFO;
if (ui->checkDisplayWarning->isChecked()) displayMask |= DS_WARNING;
if (ui->checkDisplayCritical->isChecked()) displayMask |= DS_CRITICAL;
if (ui->checkDisplayFatal->isChecked()) displayMask |= DS_FATAL;
detailsMask = 0;
if (ui->checkDetailsDebug->isChecked()) detailsMask |= DS_DEBUG;
if (ui->checkDetailsInfo->isChecked()) detailsMask |= DS_INFO;
if (ui->checkDetailsWarning->isChecked()) detailsMask |= DS_WARNING;
if (ui->checkDetailsCritical->isChecked()) detailsMask |= DS_CRITICAL;
if (ui->checkDetailsFatal->isChecked()) detailsMask |= DS_FATAL;
}

View File

@ -0,0 +1,28 @@
#ifndef DIALOGLOGSETTINGS_H
#define DIALOGLOGSETTINGS_H
#include <QDialog>
namespace Ui {
class DialogLogSettings;
}
class DialogLogSettings : public QDialog
{
Q_OBJECT
public:
explicit DialogLogSettings(QWidget *parent = 0);
~DialogLogSettings();
int displayMask;
int detailsMask;
private slots:
void on_buttonGroup_buttonReleased(int arg1);
void showEvent(QShowEvent *event);
private:
Ui::DialogLogSettings *ui;
};
#endif // DIALOGLOGSETTINGS_H

View File

@ -0,0 +1,321 @@
<?xml version="1.0" encoding="UTF-8"?>
<ui version="4.0">
<class>DialogLogSettings</class>
<widget class="QDialog" name="DialogLogSettings">
<property name="geometry">
<rect>
<x>0</x>
<y>0</y>
<width>284</width>
<height>239</height>
</rect>
</property>
<property name="windowTitle">
<string>Log window settings</string>
</property>
<widget class="QDialogButtonBox" name="buttonBox">
<property name="geometry">
<rect>
<x>80</x>
<y>190</y>
<width>181</width>
<height>32</height>
</rect>
</property>
<property name="orientation">
<enum>Qt::Horizontal</enum>
</property>
<property name="standardButtons">
<set>QDialogButtonBox::Cancel|QDialogButtonBox::Ok</set>
</property>
</widget>
<widget class="QWidget" name="gridLayoutWidget">
<property name="geometry">
<rect>
<x>20</x>
<y>20</y>
<width>241</width>
<height>161</height>
</rect>
</property>
<layout class="QGridLayout" name="gridLayout">
<item row="0" column="2">
<widget class="QLabel" name="label_3">
<property name="text">
<string>Details</string>
</property>
</widget>
</item>
<item row="1" column="0">
<widget class="QLabel" name="label_4">
<property name="text">
<string>Debug</string>
</property>
<property name="alignment">
<set>Qt::AlignCenter</set>
</property>
</widget>
</item>
<item row="3" column="0">
<widget class="QLabel" name="label_6">
<property name="text">
<string>Warning</string>
</property>
<property name="alignment">
<set>Qt::AlignCenter</set>
</property>
</widget>
</item>
<item row="0" column="0">
<widget class="QLabel" name="label">
<property name="text">
<string>Message type</string>
</property>
<property name="alignment">
<set>Qt::AlignCenter</set>
</property>
</widget>
</item>
<item row="4" column="0">
<widget class="QLabel" name="label_7">
<property name="text">
<string>Critical</string>
</property>
<property name="alignment">
<set>Qt::AlignCenter</set>
</property>
</widget>
</item>
<item row="2" column="0">
<widget class="QLabel" name="label_5">
<property name="text">
<string>Info</string>
</property>
<property name="alignment">
<set>Qt::AlignCenter</set>
</property>
</widget>
</item>
<item row="0" column="1">
<widget class="QLabel" name="label_2">
<property name="text">
<string>Display</string>
</property>
</widget>
</item>
<item row="5" column="0">
<widget class="QLabel" name="label_8">
<property name="text">
<string>Fatal</string>
</property>
<property name="alignment">
<set>Qt::AlignCenter</set>
</property>
</widget>
</item>
<item row="1" column="1">
<widget class="QCheckBox" name="checkDisplayDebug">
<property name="sizePolicy">
<sizepolicy hsizetype="Maximum" vsizetype="Fixed">
<horstretch>0</horstretch>
<verstretch>0</verstretch>
</sizepolicy>
</property>
<property name="text">
<string/>
</property>
<attribute name="buttonGroup">
<string notr="true">buttonGroup</string>
</attribute>
</widget>
</item>
<item row="1" column="2">
<widget class="QCheckBox" name="checkDetailsDebug">
<property name="sizePolicy">
<sizepolicy hsizetype="Maximum" vsizetype="Fixed">
<horstretch>0</horstretch>
<verstretch>0</verstretch>
</sizepolicy>
</property>
<property name="text">
<string/>
</property>
<attribute name="buttonGroup">
<string notr="true">buttonGroup</string>
</attribute>
</widget>
</item>
<item row="2" column="1">
<widget class="QCheckBox" name="checkDisplayInfo">
<property name="sizePolicy">
<sizepolicy hsizetype="Maximum" vsizetype="Fixed">
<horstretch>0</horstretch>
<verstretch>0</verstretch>
</sizepolicy>
</property>
<property name="text">
<string/>
</property>
<attribute name="buttonGroup">
<string notr="true">buttonGroup</string>
</attribute>
</widget>
</item>
<item row="2" column="2">
<widget class="QCheckBox" name="checkDetailsInfo">
<property name="sizePolicy">
<sizepolicy hsizetype="Maximum" vsizetype="Fixed">
<horstretch>0</horstretch>
<verstretch>0</verstretch>
</sizepolicy>
</property>
<property name="text">
<string/>
</property>
<attribute name="buttonGroup">
<string notr="true">buttonGroup</string>
</attribute>
</widget>
</item>
<item row="3" column="1">
<widget class="QCheckBox" name="checkDisplayWarning">
<property name="sizePolicy">
<sizepolicy hsizetype="Maximum" vsizetype="Fixed">
<horstretch>0</horstretch>
<verstretch>0</verstretch>
</sizepolicy>
</property>
<property name="text">
<string/>
</property>
<attribute name="buttonGroup">
<string notr="true">buttonGroup</string>
</attribute>
</widget>
</item>
<item row="3" column="2">
<widget class="QCheckBox" name="checkDetailsWarning">
<property name="sizePolicy">
<sizepolicy hsizetype="Maximum" vsizetype="Fixed">
<horstretch>0</horstretch>
<verstretch>0</verstretch>
</sizepolicy>
</property>
<property name="text">
<string/>
</property>
<attribute name="buttonGroup">
<string notr="true">buttonGroup</string>
</attribute>
</widget>
</item>
<item row="4" column="1">
<widget class="QCheckBox" name="checkDisplayCritical">
<property name="sizePolicy">
<sizepolicy hsizetype="Maximum" vsizetype="Fixed">
<horstretch>0</horstretch>
<verstretch>0</verstretch>
</sizepolicy>
</property>
<property name="text">
<string/>
</property>
<attribute name="buttonGroup">
<string notr="true">buttonGroup</string>
</attribute>
</widget>
</item>
<item row="4" column="2">
<widget class="QCheckBox" name="checkDetailsCritical">
<property name="sizePolicy">
<sizepolicy hsizetype="Maximum" vsizetype="Fixed">
<horstretch>0</horstretch>
<verstretch>0</verstretch>
</sizepolicy>
</property>
<property name="text">
<string/>
</property>
<attribute name="buttonGroup">
<string notr="true">buttonGroup</string>
</attribute>
</widget>
</item>
<item row="5" column="1">
<widget class="QCheckBox" name="checkDisplayFatal">
<property name="sizePolicy">
<sizepolicy hsizetype="Maximum" vsizetype="Fixed">
<horstretch>0</horstretch>
<verstretch>0</verstretch>
</sizepolicy>
</property>
<property name="text">
<string/>
</property>
<attribute name="buttonGroup">
<string notr="true">buttonGroup</string>
</attribute>
</widget>
</item>
<item row="5" column="2">
<widget class="QCheckBox" name="checkDetailsFatal">
<property name="sizePolicy">
<sizepolicy hsizetype="Maximum" vsizetype="Fixed">
<horstretch>0</horstretch>
<verstretch>0</verstretch>
</sizepolicy>
</property>
<property name="text">
<string/>
</property>
<attribute name="buttonGroup">
<string notr="true">buttonGroup</string>
</attribute>
</widget>
</item>
</layout>
</widget>
</widget>
<resources/>
<connections>
<connection>
<sender>buttonBox</sender>
<signal>accepted()</signal>
<receiver>DialogLogSettings</receiver>
<slot>accept()</slot>
<hints>
<hint type="sourcelabel">
<x>248</x>
<y>254</y>
</hint>
<hint type="destinationlabel">
<x>157</x>
<y>274</y>
</hint>
</hints>
</connection>
<connection>
<sender>buttonBox</sender>
<signal>rejected()</signal>
<receiver>DialogLogSettings</receiver>
<slot>reject()</slot>
<hints>
<hint type="sourcelabel">
<x>316</x>
<y>260</y>
</hint>
<hint type="destinationlabel">
<x>286</x>
<y>274</y>
</hint>
</hints>
</connection>
</connections>
<buttongroups>
<buttongroup name="buttonGroup">
<property name="exclusive">
<bool>false</bool>
</property>
</buttongroup>
</buttongroups>
</ui>

View File

@ -0,0 +1,199 @@
#include "dialogprofiler.h"
#include "ui_dialogprofiler.h"
#define RUNNING 1
#define STOPPED 0
#define STOP_ISSUED -1
DialogProfiler::DialogProfiler(QWidget *parent) :
QDialog(parent),
ui(new Ui::DialogProfiler)
{
ui->setupUi(this);
runState = STOPPED;
nrRunsDone = 0;
}
DialogProfiler::~DialogProfiler()
{
delete ui;
}
//************** Processing ***************
void DialogProfiler::run(int nr_loops)
{
runState = RUNNING;
qInfo("Starting profile acquisition");
//Prepare measurement
ui->plotResultsMean->clearGraphs();
ui->plotResultsStd->clearGraphs();
int nr_devices = theHW->devices.length();
int nacqs = ui->spinAcquisitions->value();
//Data structures for plot
QVector<double> xdata;
QVector<double> ymeandata;
QVector<double> ystddata;
ui->plotResultsMean->addGraph();
ui->plotResultsStd->addGraph();
for (int ch = 0; ch < nr_devices*128; ch++)
xdata.append(ch);
double ymeanmin = 1e+10;
double ymeanmax = -1e+10;
double ystdmin = 1e+10;
double ystdmax = -1e+10;
//Measure!
int loop_nr = 0;
while ((runState != STOP_ISSUED) && ((loop_nr < nr_loops) || (nr_loops == -1)))
{
ProfilerTestResult result;
//Collect sensor data
histoReady = 0;
connect(&(theHW->eventBuilder), EventBuilder::sigHistoCompleted, this, DialogProfiler::onHistogramCompleted);
theHW->eventBuilder.startTakingHistos(nacqs);
while (!histoReady)
{
QCoreApplication::processEvents();
QThread::msleep(10);
}
disconnect(&(theHW->eventBuilder), EventBuilder::sigHistoCompleted, this, DialogProfiler::onHistogramCompleted);
QVector<Histogram> histos = theHW->eventBuilder.getHistos();
result.mean.fill(0, nr_devices*128);
result.std.fill(0, nr_devices*128);
for (int i = 0; i < result.mean.length(); i++)
{
histos[i].MS(&(result.mean[i]), &(result.std[i]));
}
//Add LED/PD information
result.nracqs = nacqs;
results.append(result);
//Plot data...
ymeandata.clear();
ymeandata.fill(0, nr_devices*128);
ystddata.clear();
ystddata.fill(0,nr_devices*128);
for (int ch = 0; ch < (nr_devices*128); ch++)
{
ymeandata[ch] = result.mean[ch];
if (result.mean[ch] > ymeanmax)
ymeanmax = result.mean[ch];
if (result.mean[ch] < ymeanmin)
ymeanmin = result.mean[ch];
ystddata[ch] = result.std[ch];
if (result.std[ch] > ystdmax)
ystdmax = result.std[ch];
if (result.std[ch] < ystdmin)
ystdmin = result.std[ch];
}
ui->plotResultsMean->xAxis->setRange(0, nr_devices*128-1);
ui->plotResultsMean->yAxis->setRange(ymeanmin, ymeanmax);
ui->plotResultsStd->xAxis->setRange(0, nr_devices*128-1);
ui->plotResultsStd->yAxis->setRange(ystdmin, ystdmax);
ui->plotResultsMean->graph(0)->setData(xdata, ymeandata);
ui->plotResultsStd->graph(0)->setData(xdata, ystddata);
ui->plotResultsMean->replot();
ui->plotResultsStd->replot();
//Roll over
loop_nr++;
nrRunsDone++;
ui->lineRunsDone->setText(QString("%1").arg(nrRunsDone));
QCoreApplication::processEvents();
}
qInfo("Profile acquisition finished!");
runState = STOPPED;
}
void DialogProfiler::runHelper(int nr_loops)
{
if (runState)
{
runState = STOP_ISSUED;
}
else
{
ui->pushRun->setText("Stop");
ui->pushRunOnce->setEnabled(false);
ui->pushRunInfinite->setEnabled(false);
ui->pushClear->setEnabled(false);
ui->pushSave->setEnabled(false);
run(nr_loops);
ui->pushRun->setText("Run");
ui->pushRunOnce->setEnabled(true);
ui->pushRunInfinite->setEnabled(true);
ui->pushClear->setEnabled(true);
ui->pushSave->setEnabled(true);
}
}
//************** Slots ****************
void DialogProfiler::onHistogramCompleted()
{
histoReady = 1;
}
void DialogProfiler::on_pushRun_pressed()
{
runHelper(ui->spinRuns->value());
}
void DialogProfiler::on_pushRunOnce_pressed()
{
runHelper(1);
}
void DialogProfiler::on_pushRunInfinite_pressed()
{
runHelper(-1);
}
void DialogProfiler::on_pushSave_pressed()
{
QString filename = QFileDialog::getSaveFileName(this, "Select file for saving data", "", tr("Comma separated files (*.csv)"));
QString delimiter = QString(",");
if (filename.length() == 0)
return;
QFile file(filename);
if (!file.open(QIODevice::WriteOnly | QIODevice::Text))
return;
QTextStream out(&file);
out << qSetFieldWidth(14) << qSetRealNumberPrecision(8);
for (int row = 0; row < results.length(); row++)
{
out << results[row].nracqs;
for (int col = 0; (col < results[row].mean.length()) && (col < results[row].std.length()); col++)
out << delimiter << results[row].mean[col] << delimiter << results[row].std[col];
out << QString("\n");
}
file.close();
}
void DialogProfiler::on_pushClear_pressed()
{
nrRunsDone = 0;
results.clear();
ui->lineRunsDone->setText(QString("%1").arg(nrRunsDone));
}

View File

@ -0,0 +1,59 @@
#ifndef DIALOGPROFILER_H
#define DIALOGPROFILER_H
#include <QDialog>
#include <QVector>
#include <QList>
#include "hw.h"
#include "keithley_thr.h"
#include "histogram.h"
#include "helpers.h"
typedef struct
{
int nracqs;
QVector<double> mean;
QVector<double> std;
} ProfilerTestResult;
namespace Ui {
class DialogProfiler;
}
class DialogProfiler : public QDialog
{
Q_OBJECT
public:
explicit DialogProfiler(QWidget *parent = 0);
~DialogProfiler();
HW* theHW;
keithley_thr* theKeithley;
public slots:
void onHistogramCompleted();
protected:
int runState;
int histoReady;
int nrRunsDone;
QList<ProfilerTestResult> results;
void run(int nr_loops);
void runHelper(int nr_loops);
private slots:
void on_pushRun_pressed();
void on_pushSave_pressed();
void on_pushRunOnce_pressed();
void on_pushRunInfinite_pressed();
void on_pushClear_pressed();
private:
Ui::DialogProfiler *ui;
};
#endif // DIALOGLINEARITY_H

View File

@ -0,0 +1,314 @@
<?xml version="1.0" encoding="UTF-8"?>
<ui version="4.0">
<class>DialogProfiler</class>
<widget class="QDialog" name="DialogProfiler">
<property name="geometry">
<rect>
<x>0</x>
<y>0</y>
<width>844</width>
<height>632</height>
</rect>
</property>
<property name="windowTitle">
<string>Profile Viewer</string>
</property>
<widget class="QDialogButtonBox" name="buttonBox">
<property name="geometry">
<rect>
<x>490</x>
<y>590</y>
<width>341</width>
<height>32</height>
</rect>
</property>
<property name="orientation">
<enum>Qt::Horizontal</enum>
</property>
<property name="standardButtons">
<set>QDialogButtonBox::Close</set>
</property>
</widget>
<widget class="QWidget" name="horizontalLayoutWidget">
<property name="geometry">
<rect>
<x>10</x>
<y>10</y>
<width>821</width>
<height>571</height>
</rect>
</property>
<layout class="QHBoxLayout" name="horizontalLayout">
<item>
<layout class="QVBoxLayout" name="verticalLayout">
<item>
<widget class="QLabel" name="label">
<property name="sizePolicy">
<sizepolicy hsizetype="Fixed" vsizetype="Fixed">
<horstretch>0</horstretch>
<verstretch>0</verstretch>
</sizepolicy>
</property>
<property name="text">
<string>Scan settings</string>
</property>
<property name="alignment">
<set>Qt::AlignCenter</set>
</property>
</widget>
</item>
<item>
<layout class="QGridLayout" name="gridLayout">
<item row="0" column="0">
<widget class="QLabel" name="label_10">
<property name="text">
<string>Acqs/run:</string>
</property>
</widget>
</item>
<item row="0" column="1">
<widget class="QSpinBox" name="spinAcquisitions">
<property name="minimum">
<number>1</number>
</property>
<property name="maximum">
<number>1000000</number>
</property>
<property name="singleStep">
<number>1000</number>
</property>
<property name="value">
<number>1000</number>
</property>
</widget>
</item>
<item row="1" column="0">
<widget class="QLabel" name="label_11">
<property name="text">
<string>Nr runs:</string>
</property>
</widget>
</item>
<item row="1" column="1">
<widget class="QSpinBox" name="spinRuns">
<property name="minimum">
<number>1</number>
</property>
<property name="maximum">
<number>128</number>
</property>
<property name="value">
<number>16</number>
</property>
</widget>
</item>
</layout>
</item>
<item>
<spacer name="verticalSpacer_3">
<property name="orientation">
<enum>Qt::Vertical</enum>
</property>
<property name="sizeType">
<enum>QSizePolicy::Fixed</enum>
</property>
<property name="sizeHint" stdset="0">
<size>
<width>20</width>
<height>40</height>
</size>
</property>
</spacer>
</item>
<item>
<widget class="QPushButton" name="pushRun">
<property name="text">
<string>Run!</string>
</property>
</widget>
</item>
<item>
<widget class="QPushButton" name="pushRunOnce">
<property name="text">
<string>Run once!</string>
</property>
</widget>
</item>
<item>
<widget class="QPushButton" name="pushRunInfinite">
<property name="text">
<string>Run infinite!</string>
</property>
</widget>
</item>
<item>
<spacer name="verticalSpacer_2">
<property name="orientation">
<enum>Qt::Vertical</enum>
</property>
<property name="sizeType">
<enum>QSizePolicy::Fixed</enum>
</property>
<property name="sizeHint" stdset="0">
<size>
<width>20</width>
<height>40</height>
</size>
</property>
</spacer>
</item>
<item>
<layout class="QHBoxLayout" name="horizontalLayout_2">
<property name="bottomMargin">
<number>0</number>
</property>
<item>
<widget class="QLabel" name="label_2">
<property name="text">
<string>Runs:</string>
</property>
</widget>
</item>
<item>
<widget class="QLineEdit" name="lineRunsDone">
<property name="sizePolicy">
<sizepolicy hsizetype="Fixed" vsizetype="Fixed">
<horstretch>0</horstretch>
<verstretch>0</verstretch>
</sizepolicy>
</property>
<property name="autoFillBackground">
<bool>false</bool>
</property>
<property name="readOnly">
<bool>true</bool>
</property>
</widget>
</item>
</layout>
</item>
<item>
<widget class="QPushButton" name="pushClear">
<property name="text">
<string>Clear</string>
</property>
</widget>
</item>
<item>
<widget class="QPushButton" name="pushSave">
<property name="text">
<string>Save results...</string>
</property>
</widget>
</item>
<item>
<spacer name="verticalSpacer">
<property name="orientation">
<enum>Qt::Vertical</enum>
</property>
<property name="sizeHint" stdset="0">
<size>
<width>20</width>
<height>40</height>
</size>
</property>
</spacer>
</item>
</layout>
</item>
<item>
<layout class="QVBoxLayout" name="verticalLayout_3">
<item>
<widget class="QLabel" name="label_12">
<property name="sizePolicy">
<sizepolicy hsizetype="Preferred" vsizetype="Fixed">
<horstretch>0</horstretch>
<verstretch>0</verstretch>
</sizepolicy>
</property>
<property name="text">
<string>Signal mean</string>
</property>
<property name="alignment">
<set>Qt::AlignCenter</set>
</property>
</widget>
</item>
<item>
<widget class="QCustomPlot" name="plotResultsMean" native="true">
<property name="sizePolicy">
<sizepolicy hsizetype="Expanding" vsizetype="Minimum">
<horstretch>0</horstretch>
<verstretch>0</verstretch>
</sizepolicy>
</property>
</widget>
</item>
<item>
<widget class="QLabel" name="label_13">
<property name="sizePolicy">
<sizepolicy hsizetype="Preferred" vsizetype="Fixed">
<horstretch>0</horstretch>
<verstretch>0</verstretch>
</sizepolicy>
</property>
<property name="text">
<string>Signal standard deviation</string>
</property>
<property name="alignment">
<set>Qt::AlignCenter</set>
</property>
</widget>
</item>
<item>
<widget class="QCustomPlot" name="plotResultsStd" native="true"/>
</item>
</layout>
</item>
</layout>
</widget>
</widget>
<customwidgets>
<customwidget>
<class>QCustomPlot</class>
<extends>QWidget</extends>
<header>qcustomplot.h</header>
<container>1</container>
</customwidget>
</customwidgets>
<resources/>
<connections>
<connection>
<sender>buttonBox</sender>
<signal>accepted()</signal>
<receiver>DialogProfiler</receiver>
<slot>accept()</slot>
<hints>
<hint type="sourcelabel">
<x>248</x>
<y>254</y>
</hint>
<hint type="destinationlabel">
<x>157</x>
<y>274</y>
</hint>
</hints>
</connection>
<connection>
<sender>buttonBox</sender>
<signal>rejected()</signal>
<receiver>DialogProfiler</receiver>
<slot>reject()</slot>
<hints>
<hint type="sourcelabel">
<x>316</x>
<y>260</y>
</hint>
<hint type="destinationlabel">
<x>286</x>
<y>274</y>
</hint>
</hints>
</connection>
</connections>
</ui>

View File

@ -0,0 +1,230 @@
#include "dialogtiscan.h"
#include "ui_dialogtiscan.h"
#define RUNNING 1
#define STOPPED 0
#define STOP_ISSUED -1
DialogTiScan::DialogTiScan(QWidget *parent) :
QDialog(parent),
ui(new Ui::DialogTiScan)
{
ui->setupUi(this);
runState = STOPPED;
}
DialogTiScan::~DialogTiScan()
{
delete ui;
}
void DialogTiScan::showEvent(QShowEvent * event)
{
if (!event->spontaneous())
{
if (!theKeithley->isOpen)
ui->checkUseLED->setEnabled(false);
}
QDialog::showEvent(event);
}
//************** Processing ***************
void DialogTiScan::run()
{
runState = RUNNING;
qInfo("Starting integration time scan...");
//Prepare measurement
ui->plotResultsMean->clearGraphs();
ui->plotResultsStd->clearGraphs();
results.clear();
int nr_devices = theHW->devices.length();
int use_led = ui->checkUseLED->isChecked();
double ledv = ui->doubleSpinLEDV->value();
int decimation = ui->spinPLotDecimation->value();
int nacqs = ui->spinAcquisitions->value();
int tstart = ui->spintStart->value();
int tend = ui->spinTEnd->value();
int tinc = ui->spinTIncrement->value();
int tcurrent = tstart;
//Plot data
QVector<double> xdata;
QList<QVector<double>> ymeandata;
QList<QVector<double>> ystddata;
for (int ch = 0; ch < (nr_devices*128); ch+= decimation)
{
ymeandata.append(xdata); //just add empty vectors to the list
ystddata.append(xdata); //just add empty vectors to the list
}
//The number of plotted lines is smaller than number of channels - see decimation
for (int plotnr = 0; plotnr < nr_devices*128; plotnr++)
{
ui->plotResultsMean->addGraph();
ui->plotResultsStd->addGraph();
}
double xmin = 1e+10;
double xmax = -1e+10;
double ymeanmin = 1e+10;
double ymeanmax = -1e+10;
double ystdmin = 1e+10;
double ystdmax = -1e+10;
if (use_led)
{
theKeithley->setVoltage(ledv);
theKeithley->on(1);
}
theHW->run();
//Measure!
while ((runState != STOP_ISSUED) && (tcurrent <= tend))
{
//Set LED voltage
qInfo(qPrintable(QString("Integration time: %1 ").arg(tcurrent)));
//set up integration time for all devices
theHW->stop();
for (int dev_nr = 0; dev_nr < theHW->devices.length(); dev_nr++)
{
DeviceConfig dc = theHW->devices[dev_nr]->deviceConfig;
dc.tint = tcurrent;
theHW->devices[dev_nr]->configure(dc);
}
theHW->run();
TiScanResult result;
//Collect sensor data
histoReady = 0;
connect(&(theHW->eventBuilder), EventBuilder::sigHistoCompleted, this, DialogTiScan::onHistogramCompleted);
theHW->eventBuilder.startTakingHistos(nacqs);
while (!histoReady)
{
QCoreApplication::processEvents();
QThread::msleep(10);
}
disconnect(&(theHW->eventBuilder), EventBuilder::sigHistoCompleted, this, DialogTiScan::onHistogramCompleted);
QVector<Histogram> histos = theHW->eventBuilder.getHistos();
result.mean.fill(0, nr_devices*128);
result.std.fill(0, nr_devices*128);
for (int i = 0; i < result.mean.length(); i++)
{
histos[i].MS(&(result.mean[i]), &(result.std[i]));
//result.mean[i] = histos[i].mean();
//result.std[i] = histos[i].stdev();
}
//Add information on integration time
result.tint = tcurrent;
results.append(result);
//Plot data...
xdata.append(result.tint);
if (result.tint > xmax)
xmax = result.tint;
if (result.tint < xmin)
xmin = result.tint;
for (int ch = 0, i = 0; ch < (nr_devices*128); ch+= decimation, i++)
{
ymeandata[i].append(result.mean[ch]);
if (result.mean[ch] > ymeanmax)
ymeanmax = result.mean[ch];
if (result.mean[ch] < ymeanmin)
ymeanmin = result.mean[ch];
ystddata[i].append(result.std[ch]);
if (result.std[ch] > ystdmax)
ystdmax = result.std[ch];
if (result.std[ch] < ystdmin)
ystdmin = result.std[ch];
}
ui->plotResultsMean->xAxis->setRange(xmin, xmax);
ui->plotResultsMean->yAxis->setRange(ymeanmin, ymeanmax);
ui->plotResultsStd->xAxis->setRange(xmin, xmax);
ui->plotResultsStd->yAxis->setRange(ystdmin, ystdmax);
for (int ch = 0, i = 0; ch < (nr_devices*128); ch+= decimation, i++)
{
ui->plotResultsMean->graph(i)->setData(xdata, ymeandata[i]);
ui->plotResultsStd->graph(i)->setData(xdata, ystddata[i]);
}
ui->plotResultsMean->replot();
ui->plotResultsStd->replot();
//Roll over
tcurrent += tinc;
QCoreApplication::processEvents();
}
if (use_led)
theKeithley->on(0);
theHW->stop();
qInfo("Integration time scan finished!");
runState = STOPPED;
}
//************** Slots ****************
void DialogTiScan::onHistogramCompleted()
{
histoReady = 1;
}
void DialogTiScan::on_pushRun_pressed()
{
if (runState)
{
runState = STOP_ISSUED;
}
else
{
ui->pushRun->setText("Stop");
ui->pushSave->setEnabled(false);
run();
ui->pushRun->setText("Run");
ui->pushSave->setEnabled(true);
}
}
void DialogTiScan::on_pushSave_pressed()
{
QString filename = QFileDialog::getSaveFileName(this, "Select file for saving data", "", tr("Comma separated files (*.csv)"));
QString delimiter = QString(",");
if (filename.length() == 0)
return;
QFile file(filename);
if (!file.open(QIODevice::WriteOnly | QIODevice::Text))
return;
QTextStream out(&file);
out << qSetFieldWidth(14) << qSetRealNumberPrecision(8);
for (int row = 0; row < results.length(); row++)
{
out << results[row].tint;
for (int col = 0; (col < results[row].mean.length()) && (col < results[row].std.length()); col++)
out << delimiter << results[row].mean[col] << delimiter << results[row].std[col];
out << QString("\n");
}
file.close();
}

View File

@ -0,0 +1,52 @@
#ifndef DIALOGTISCAN_H
#define DIALOGTISCAN_H
#include <QDialog>
#include <QVector>
#include <QList>
#include "hw.h"
#include "keithley_thr.h"
#include "histogram.h"
#include "helpers.h"
typedef struct
{
int tint;
QVector<double> mean;
QVector<double> std;
} TiScanResult;
namespace Ui {
class DialogTiScan;
}
class DialogTiScan : public QDialog
{
Q_OBJECT
public:
explicit DialogTiScan(QWidget *parent = 0);
~DialogTiScan();
HW* theHW;
keithley_thr* theKeithley;
public slots:
void onHistogramCompleted();
void showEvent(QShowEvent *event);
protected:
int runState;
int histoReady;
QList<TiScanResult> results;
void run();
private slots:
void on_pushRun_pressed();
void on_pushSave_pressed();
private:
Ui::DialogTiScan *ui;
};
#endif // DIALOGTISCAN_H

View File

@ -0,0 +1,383 @@
<?xml version="1.0" encoding="UTF-8"?>
<ui version="4.0">
<class>DialogTiScan</class>
<widget class="QDialog" name="DialogTiScan">
<property name="geometry">
<rect>
<x>0</x>
<y>0</y>
<width>844</width>
<height>632</height>
</rect>
</property>
<property name="windowTitle">
<string>Integration Time Scan</string>
</property>
<widget class="QDialogButtonBox" name="buttonBox">
<property name="geometry">
<rect>
<x>490</x>
<y>590</y>
<width>341</width>
<height>32</height>
</rect>
</property>
<property name="orientation">
<enum>Qt::Horizontal</enum>
</property>
<property name="standardButtons">
<set>QDialogButtonBox::Close</set>
</property>
</widget>
<widget class="QWidget" name="horizontalLayoutWidget">
<property name="geometry">
<rect>
<x>10</x>
<y>10</y>
<width>821</width>
<height>571</height>
</rect>
</property>
<layout class="QHBoxLayout" name="horizontalLayout">
<item>
<layout class="QVBoxLayout" name="verticalLayout">
<item>
<widget class="QLabel" name="label">
<property name="sizePolicy">
<sizepolicy hsizetype="Fixed" vsizetype="Fixed">
<horstretch>0</horstretch>
<verstretch>0</verstretch>
</sizepolicy>
</property>
<property name="text">
<string>Scan settings</string>
</property>
<property name="alignment">
<set>Qt::AlignCenter</set>
</property>
</widget>
</item>
<item>
<layout class="QGridLayout" name="gridLayout">
<item row="5" column="0">
<widget class="QLabel" name="label_4">
<property name="text">
<string>Time increment:</string>
</property>
</widget>
</item>
<item row="0" column="0">
<widget class="QLabel" name="label_2">
<property name="sizePolicy">
<sizepolicy hsizetype="Fixed" vsizetype="Preferred">
<horstretch>0</horstretch>
<verstretch>0</verstretch>
</sizepolicy>
</property>
<property name="text">
<string>Use LED:</string>
</property>
</widget>
</item>
<item row="8" column="0">
<widget class="QLabel" name="label_11">
<property name="text">
<string>Plot decimation:</string>
</property>
</widget>
</item>
<item row="8" column="1">
<widget class="QSpinBox" name="spinPLotDecimation">
<property name="minimum">
<number>1</number>
</property>
<property name="maximum">
<number>128</number>
</property>
<property name="value">
<number>16</number>
</property>
</widget>
</item>
<item row="6" column="0">
<spacer name="verticalSpacer_2">
<property name="orientation">
<enum>Qt::Vertical</enum>
</property>
<property name="sizeType">
<enum>QSizePolicy::Fixed</enum>
</property>
<property name="sizeHint" stdset="0">
<size>
<width>20</width>
<height>40</height>
</size>
</property>
</spacer>
</item>
<item row="1" column="0">
<widget class="QLabel" name="label_3">
<property name="text">
<string>LED voltage:</string>
</property>
</widget>
</item>
<item row="1" column="2">
<widget class="QLabel" name="label_6">
<property name="text">
<string>V</string>
</property>
</widget>
</item>
<item row="7" column="1">
<widget class="QSpinBox" name="spinAcquisitions">
<property name="minimum">
<number>1</number>
</property>
<property name="maximum">
<number>1000000</number>
</property>
<property name="singleStep">
<number>1000</number>
</property>
<property name="value">
<number>10000</number>
</property>
</widget>
</item>
<item row="7" column="0">
<widget class="QLabel" name="label_10">
<property name="text">
<string>Acqs/point:</string>
</property>
</widget>
</item>
<item row="1" column="1">
<widget class="QDoubleSpinBox" name="doubleSpinLEDV">
<property name="maximum">
<double>10.000000000000000</double>
</property>
<property name="singleStep">
<double>0.100000000000000</double>
</property>
<property name="value">
<double>6.000000000000000</double>
</property>
</widget>
</item>
<item row="3" column="0">
<widget class="QLabel" name="label_13">
<property name="text">
<string>Start integration time:</string>
</property>
</widget>
</item>
<item row="4" column="0">
<widget class="QLabel" name="label_12">
<property name="text">
<string>End integration time:</string>
</property>
</widget>
</item>
<item row="4" column="1">
<widget class="QSpinBox" name="spinTEnd">
<property name="minimum">
<number>10</number>
</property>
<property name="maximum">
<number>100000</number>
</property>
<property name="value">
<number>8549</number>
</property>
</widget>
</item>
<item row="5" column="1">
<widget class="QSpinBox" name="spinTIncrement">
<property name="minimum">
<number>1</number>
</property>
<property name="maximum">
<number>100000</number>
</property>
<property name="value">
<number>100</number>
</property>
</widget>
</item>
<item row="2" column="0">
<spacer name="verticalSpacer_4">
<property name="orientation">
<enum>Qt::Vertical</enum>
</property>
<property name="sizeHint" stdset="0">
<size>
<width>20</width>
<height>40</height>
</size>
</property>
</spacer>
</item>
<item row="0" column="1">
<widget class="QCheckBox" name="checkUseLED">
<property name="text">
<string>CheckBox</string>
</property>
</widget>
</item>
<item row="3" column="1">
<widget class="QSpinBox" name="spintStart">
<property name="minimum">
<number>10</number>
</property>
<property name="maximum">
<number>100000</number>
</property>
<property name="value">
<number>100</number>
</property>
</widget>
</item>
</layout>
</item>
<item>
<spacer name="verticalSpacer_3">
<property name="orientation">
<enum>Qt::Vertical</enum>
</property>
<property name="sizeType">
<enum>QSizePolicy::Fixed</enum>
</property>
<property name="sizeHint" stdset="0">
<size>
<width>20</width>
<height>40</height>
</size>
</property>
</spacer>
</item>
<item>
<widget class="QPushButton" name="pushRun">
<property name="text">
<string>Run!</string>
</property>
</widget>
</item>
<item>
<widget class="QPushButton" name="pushSave">
<property name="text">
<string>Save results...</string>
</property>
</widget>
</item>
<item>
<spacer name="verticalSpacer">
<property name="orientation">
<enum>Qt::Vertical</enum>
</property>
<property name="sizeHint" stdset="0">
<size>
<width>20</width>
<height>40</height>
</size>
</property>
</spacer>
</item>
</layout>
</item>
<item>
<layout class="QVBoxLayout" name="verticalLayout_2">
<item>
<widget class="QLabel" name="label_5">
<property name="sizePolicy">
<sizepolicy hsizetype="Preferred" vsizetype="Fixed">
<horstretch>0</horstretch>
<verstretch>0</verstretch>
</sizepolicy>
</property>
<property name="text">
<string>Signal mean</string>
</property>
<property name="alignment">
<set>Qt::AlignCenter</set>
</property>
</widget>
</item>
<item>
<widget class="QCustomPlot" name="plotResultsMean" native="true">
<property name="sizePolicy">
<sizepolicy hsizetype="Expanding" vsizetype="Minimum">
<horstretch>0</horstretch>
<verstretch>0</verstretch>
</sizepolicy>
</property>
</widget>
</item>
<item>
<widget class="QLabel" name="label_7">
<property name="sizePolicy">
<sizepolicy hsizetype="Preferred" vsizetype="Fixed">
<horstretch>0</horstretch>
<verstretch>0</verstretch>
</sizepolicy>
</property>
<property name="text">
<string>Signal standard deviation</string>
</property>
<property name="alignment">
<set>Qt::AlignCenter</set>
</property>
</widget>
</item>
<item>
<widget class="QCustomPlot" name="plotResultsStd" native="true"/>
</item>
</layout>
</item>
</layout>
</widget>
</widget>
<customwidgets>
<customwidget>
<class>QCustomPlot</class>
<extends>QWidget</extends>
<header>qcustomplot.h</header>
<container>1</container>
</customwidget>
</customwidgets>
<resources/>
<connections>
<connection>
<sender>buttonBox</sender>
<signal>accepted()</signal>
<receiver>DialogTiScan</receiver>
<slot>accept()</slot>
<hints>
<hint type="sourcelabel">
<x>248</x>
<y>254</y>
</hint>
<hint type="destinationlabel">
<x>157</x>
<y>274</y>
</hint>
</hints>
</connection>
<connection>
<sender>buttonBox</sender>
<signal>rejected()</signal>
<receiver>DialogTiScan</receiver>
<slot>reject()</slot>
<hints>
<hint type="sourcelabel">
<x>316</x>
<y>260</y>
</hint>
<hint type="destinationlabel">
<x>286</x>
<y>274</y>
</hint>
</hints>
</connection>
</connections>
</ui>

View File

@ -0,0 +1,156 @@
#include "dialogtriggersettings.h"
#include "ui_dialogtriggersettings.h"
#include "helpers.h"
DialogTriggerSettings::DialogTriggerSettings(QWidget *parent) :
QDialog(parent),
ui(new Ui::DialogTriggerSettings)
{
ui->setupUi(this);
}
DialogTriggerSettings::~DialogTriggerSettings()
{
delete ui;
}
//***************** Initialization ******************
void DialogTriggerSettings::showEvent(QShowEvent * event)
{
if (!event->spontaneous())
{
if (deviceSettings != NULL)
{
top(deviceSettings);
deviceSettings->beginGroup("Trigger");
ui->spinPeriodTicks->setValue( deviceSettings->value("Period", (int)9000).toInt() );
ui->spinTintTicks->setValue( deviceSettings->value("Tint", (int)1000).toInt() );
if (deviceSettings->value("Gain", (int)0).toInt() == 0)
ui->radioLow->setChecked(true);
else
ui->radioHigh->setChecked(true);
ui->spinPeriodTicks_v2->setValue( deviceSettings->value("Period_v2", (int)2500).toInt() );
ui->spinTintTicks_v2->setValue( deviceSettings->value("Tint_v2", (int)1000).toInt() );
if (deviceSettings->value("Gain_v2", (int)0).toInt() == 0)
ui->radioLow_v2->setChecked(true);
else
ui->radioHigh_v2->setChecked(true);
}
updateCalculations();
}
QDialog::showEvent(event);
}
//***************** Processing ******************
void DialogTriggerSettings::accept()
{
// qInfo("Accepted!");
if (validateAndSave())
QDialog::accept();
}
int DialogTriggerSettings::validateAndSave()
{
if (deviceSettings == NULL)
return 0;
if (!data_ok)
return 0;
top(deviceSettings);
deviceSettings->beginGroup("Trigger");
deviceSettings->setValue("Period", ui->spinPeriodTicks->value());
deviceSettings->setValue("Tint", ui->spinTintTicks->value());
if (ui->radioHigh->isChecked())
deviceSettings->setValue("Gain", 1);
else
deviceSettings->setValue("Gain", 0);
deviceSettings->setValue("Period_v2", ui->spinPeriodTicks_v2->value());
deviceSettings->setValue("Tint_v2", ui->spinTintTicks_v2->value());
if (ui->radioHigh_v2->isChecked())
deviceSettings->setValue("Gain_v2", 1);
else
deviceSettings->setValue("Gain_v2", 0);
return 1;
}
void DialogTriggerSettings::updateCalculations()
{
data_ok = 1;
// ***** V1 *****
double period_us = (double)(ui->spinPeriodTicks->value()+1) / 90.0;
ui->linePeriodUs->setText(QString("%1").arg(period_us, 0, 'f', 2));
double freq_kHz = 1e+3/period_us;
ui->lineFreqKhz->setText((QString("%1").arg(freq_kHz, 0, 'f', 3)));
ui->linePeriodOK->setText("OK");
double tint_us = (double)(ui->spinTintTicks->value()+1) / 90.0; //45.0;
ui->lineTintUs->setText(QString("%1").arg(tint_us, 0, 'f', 2));
if (tint_us > (period_us - (20.0/4)))
{
ui->lineTintOK->setText("Too long!");
data_ok = 0;
}
else
ui->lineTintOK->setText("OK");
// ***** V2 *****
double period_us_v2 = (double)(ui->spinPeriodTicks_v2->value()+1) / 25.0;
ui->linePeriodUs_v2->setText(QString("%1").arg(period_us_v2, 0, 'f', 2));
double freq_kHz_v2 = 1e+3/period_us_v2;
ui->lineFreqKhz_v2->setText((QString("%1").arg(freq_kHz_v2, 0, 'f', 3)));
ui->linePeriodOK_v2->setText("OK");
double tint_us_v2 = (double)(ui->spinTintTicks_v2->value()+1) / (50.0/14.0); //makes these 3.5714... MHz
ui->lineTintUs_v2->setText(QString("%1").arg(tint_us_v2, 0, 'f', 2));
if (tint_us_v2 > (period_us_v2 - (20.0/(50.0/14.0))))
{
ui->lineTintOK_v2->setText("Too long!");
data_ok = 0;
}
else
ui->lineTintOK_v2->setText("OK");
}
void DialogTriggerSettings::on_spinPeriodTicks_valueChanged(int arg1)
{
updateCalculations();
}
void DialogTriggerSettings::on_spinTintTicks_valueChanged(int arg1)
{
updateCalculations();
}
void DialogTriggerSettings::on_spinPeriodTicks_v2_valueChanged(int arg1)
{
updateCalculations();
}
void DialogTriggerSettings::on_spinTintTicks_v2_valueChanged(int arg1)
{
updateCalculations();
}

View File

@ -0,0 +1,41 @@
#ifndef DIALOGTRIGGERSETTINGS_H
#define DIALOGTRIGGERSETTINGS_H
#include <QDialog>
#include <QSettings>
#include <QShowEvent>
namespace Ui {
class DialogTriggerSettings;
}
class DialogTriggerSettings : public QDialog
{
Q_OBJECT
public:
explicit DialogTriggerSettings(QWidget *parent = 0);
~DialogTriggerSettings();
QSettings* deviceSettings = NULL;
public slots:
void showEvent(QShowEvent *event);
void accept();
protected:
int validateAndSave();
void updateCalculations();
int data_ok = 0;
private slots:
void on_spinPeriodTicks_valueChanged(int arg1);
void on_spinTintTicks_valueChanged(int arg1);
void on_spinPeriodTicks_v2_valueChanged(int arg1);
void on_spinTintTicks_v2_valueChanged(int arg1);
private:
Ui::DialogTriggerSettings *ui;
};
#endif // DIALOGTRIGGERSETTINGS_H

View File

@ -0,0 +1,412 @@
<?xml version="1.0" encoding="UTF-8"?>
<ui version="4.0">
<class>DialogTriggerSettings</class>
<widget class="QDialog" name="DialogTriggerSettings">
<property name="geometry">
<rect>
<x>0</x>
<y>0</y>
<width>443</width>
<height>281</height>
</rect>
</property>
<property name="windowTitle">
<string>Trigger configuration</string>
</property>
<widget class="QDialogButtonBox" name="buttonBox">
<property name="geometry">
<rect>
<x>90</x>
<y>240</y>
<width>341</width>
<height>32</height>
</rect>
</property>
<property name="orientation">
<enum>Qt::Horizontal</enum>
</property>
<property name="standardButtons">
<set>QDialogButtonBox::Cancel|QDialogButtonBox::Ok</set>
</property>
</widget>
<widget class="QWidget" name="verticalLayoutWidget">
<property name="geometry">
<rect>
<x>10</x>
<y>10</y>
<width>421</width>
<height>221</height>
</rect>
</property>
<layout class="QVBoxLayout" name="verticalLayout">
<item>
<widget class="QLabel" name="label_9">
<property name="text">
<string>Hardware v.1</string>
</property>
<property name="alignment">
<set>Qt::AlignCenter</set>
</property>
</widget>
</item>
<item>
<layout class="QGridLayout" name="gridLayout">
<item row="1" column="2">
<widget class="QLabel" name="label_6">
<property name="text">
<string>=</string>
</property>
</widget>
</item>
<item row="0" column="0">
<widget class="QLabel" name="label">
<property name="text">
<string>Period:</string>
</property>
</widget>
</item>
<item row="1" column="7">
<widget class="QLineEdit" name="lineTintOK">
<property name="alignment">
<set>Qt::AlignCenter</set>
</property>
<property name="readOnly">
<bool>true</bool>
</property>
</widget>
</item>
<item row="0" column="7">
<widget class="QLineEdit" name="linePeriodOK">
<property name="alignment">
<set>Qt::AlignCenter</set>
</property>
<property name="readOnly">
<bool>true</bool>
</property>
</widget>
</item>
<item row="0" column="5">
<widget class="QLineEdit" name="lineFreqKhz">
<property name="alignment">
<set>Qt::AlignRight|Qt::AlignTrailing|Qt::AlignVCenter</set>
</property>
<property name="readOnly">
<bool>true</bool>
</property>
</widget>
</item>
<item row="0" column="6">
<widget class="QLabel" name="label_4">
<property name="text">
<string>kHz</string>
</property>
</widget>
</item>
<item row="0" column="3">
<widget class="QLineEdit" name="linePeriodUs">
<property name="alignment">
<set>Qt::AlignRight|Qt::AlignTrailing|Qt::AlignVCenter</set>
</property>
<property name="readOnly">
<bool>true</bool>
</property>
</widget>
</item>
<item row="1" column="0">
<widget class="QLabel" name="label_2">
<property name="text">
<string>Tint:</string>
</property>
</widget>
</item>
<item row="1" column="3">
<widget class="QLineEdit" name="lineTintUs">
<property name="alignment">
<set>Qt::AlignRight|Qt::AlignTrailing|Qt::AlignVCenter</set>
</property>
<property name="readOnly">
<bool>true</bool>
</property>
</widget>
</item>
<item row="1" column="4">
<widget class="QLabel" name="label_7">
<property name="text">
<string>us</string>
</property>
</widget>
</item>
<item row="0" column="4">
<widget class="QLabel" name="label_3">
<property name="text">
<string>us =&gt;</string>
</property>
</widget>
</item>
<item row="0" column="2">
<widget class="QLabel" name="label_5">
<property name="text">
<string>=</string>
</property>
</widget>
</item>
<item row="0" column="1">
<widget class="QSpinBox" name="spinPeriodTicks">
<property name="minimum">
<number>8000</number>
</property>
<property name="maximum">
<number>65535</number>
</property>
</widget>
</item>
<item row="2" column="0">
<widget class="QLabel" name="label_8">
<property name="text">
<string>Gain:</string>
</property>
</widget>
</item>
<item row="1" column="1">
<widget class="QSpinBox" name="spinTintTicks">
<property name="minimum">
<number>10</number>
</property>
<property name="maximum">
<number>65535</number>
</property>
</widget>
</item>
<item row="2" column="1">
<layout class="QHBoxLayout" name="horizontalLayout">
<item>
<widget class="QRadioButton" name="radioLow">
<property name="text">
<string>Lo</string>
</property>
<attribute name="buttonGroup">
<string notr="true">buttonGroup_2</string>
</attribute>
</widget>
</item>
<item>
<widget class="QRadioButton" name="radioHigh">
<property name="text">
<string>Hi</string>
</property>
<attribute name="buttonGroup">
<string notr="true">buttonGroup_2</string>
</attribute>
</widget>
</item>
</layout>
</item>
</layout>
</item>
<item>
<widget class="QLabel" name="label_10">
<property name="text">
<string>Harware v.2</string>
</property>
<property name="alignment">
<set>Qt::AlignCenter</set>
</property>
</widget>
</item>
<item>
<layout class="QGridLayout" name="gridLayout_3">
<item row="1" column="2">
<widget class="QLabel" name="label_12">
<property name="text">
<string>=</string>
</property>
</widget>
</item>
<item row="0" column="0">
<widget class="QLabel" name="label_13">
<property name="text">
<string>Period:</string>
</property>
</widget>
</item>
<item row="1" column="7">
<widget class="QLineEdit" name="lineTintOK_v2">
<property name="alignment">
<set>Qt::AlignCenter</set>
</property>
<property name="readOnly">
<bool>true</bool>
</property>
</widget>
</item>
<item row="0" column="7">
<widget class="QLineEdit" name="linePeriodOK_v2">
<property name="alignment">
<set>Qt::AlignCenter</set>
</property>
<property name="readOnly">
<bool>true</bool>
</property>
</widget>
</item>
<item row="0" column="5">
<widget class="QLineEdit" name="lineFreqKhz_v2">
<property name="alignment">
<set>Qt::AlignRight|Qt::AlignTrailing|Qt::AlignVCenter</set>
</property>
<property name="readOnly">
<bool>true</bool>
</property>
</widget>
</item>
<item row="0" column="6">
<widget class="QLabel" name="label_14">
<property name="text">
<string>kHz</string>
</property>
</widget>
</item>
<item row="0" column="3">
<widget class="QLineEdit" name="linePeriodUs_v2">
<property name="alignment">
<set>Qt::AlignRight|Qt::AlignTrailing|Qt::AlignVCenter</set>
</property>
<property name="readOnly">
<bool>true</bool>
</property>
</widget>
</item>
<item row="1" column="0">
<widget class="QLabel" name="label_15">
<property name="text">
<string>Tint:</string>
</property>
</widget>
</item>
<item row="1" column="3">
<widget class="QLineEdit" name="lineTintUs_v2">
<property name="alignment">
<set>Qt::AlignRight|Qt::AlignTrailing|Qt::AlignVCenter</set>
</property>
<property name="readOnly">
<bool>true</bool>
</property>
</widget>
</item>
<item row="1" column="4">
<widget class="QLabel" name="label_16">
<property name="text">
<string>us</string>
</property>
</widget>
</item>
<item row="0" column="4">
<widget class="QLabel" name="label_17">
<property name="text">
<string>us =&gt;</string>
</property>
</widget>
</item>
<item row="0" column="2">
<widget class="QLabel" name="label_18">
<property name="text">
<string>=</string>
</property>
</widget>
</item>
<item row="0" column="1">
<widget class="QSpinBox" name="spinPeriodTicks_v2">
<property name="minimum">
<number>2000</number>
</property>
<property name="maximum">
<number>65535</number>
</property>
</widget>
</item>
<item row="2" column="0">
<widget class="QLabel" name="label_19">
<property name="text">
<string>Gain:</string>
</property>
</widget>
</item>
<item row="1" column="1">
<widget class="QSpinBox" name="spinTintTicks_v2">
<property name="minimum">
<number>10</number>
</property>
<property name="maximum">
<number>65535</number>
</property>
</widget>
</item>
<item row="2" column="1">
<layout class="QHBoxLayout" name="horizontalLayout_2">
<item>
<widget class="QRadioButton" name="radioLow_v2">
<property name="text">
<string>Lo</string>
</property>
<attribute name="buttonGroup">
<string notr="true">buttonGroup</string>
</attribute>
</widget>
</item>
<item>
<widget class="QRadioButton" name="radioHigh_v2">
<property name="text">
<string>Hi</string>
</property>
<attribute name="buttonGroup">
<string notr="true">buttonGroup</string>
</attribute>
</widget>
</item>
</layout>
</item>
</layout>
</item>
</layout>
</widget>
</widget>
<resources/>
<connections>
<connection>
<sender>buttonBox</sender>
<signal>accepted()</signal>
<receiver>DialogTriggerSettings</receiver>
<slot>accept()</slot>
<hints>
<hint type="sourcelabel">
<x>248</x>
<y>254</y>
</hint>
<hint type="destinationlabel">
<x>157</x>
<y>274</y>
</hint>
</hints>
</connection>
<connection>
<sender>buttonBox</sender>
<signal>rejected()</signal>
<receiver>DialogTriggerSettings</receiver>
<slot>reject()</slot>
<hints>
<hint type="sourcelabel">
<x>316</x>
<y>260</y>
</hint>
<hint type="destinationlabel">
<x>286</x>
<y>274</y>
</hint>
</hints>
</connection>
</connections>
<buttongroups>
<buttongroup name="buttonGroup_2"/>
<buttongroup name="buttonGroup"/>
</buttongroups>
</ui>

383
hit2023v2_RMS/display.cpp Normal file
View File

@ -0,0 +1,383 @@
#include "display.h"
#include "ui_display.h"
#include <QMessageBox>
#include <QFileDialog>
#include <QCheckBox>
Display::Display(QWidget *parent) :
QDialog(parent),
ui(new Ui::display)
{
ui->setupUi(this);
// Copy/Create and initialize radio buttons
radioButtonFixedScale = ui->radioButtonFixedScale;//new QRadioButton("Fixed Scale", this);
radioButtonAutoscale = ui->radioButtonAutoscale;//new QRadioButton("Autoscale", this);
// Copy/Create and initialize the button group
buttonGroup = ui->buttonGroup;//new QButtonGroup(this);
buttonGroup->setExclusive(true); // Ensure exclusivity
// Add radio buttons to the button group
buttonGroup->addButton(ui->radioButtonFixedScale);
buttonGroup->addButton(ui->radioButtonAutoscale);
buttonGroup->addButton(ui->radioButtonMaxScale);
// Connect the buttonClicked signal of the button group
connect(buttonGroup, SIGNAL(buttonClicked(QAbstractButton*)), this, SLOT(onButtonClicked(QAbstractButton*)));
connect(ui->pushButton_savebkg, &QPushButton::clicked, this, &Display::onSaveBackgroundClicked);
connect(ui->pushButton_loadbkg, &QPushButton::clicked, this, &Display::onLoadBackgroundClicked);
connect(ui->checkBox_subbkg, &QCheckBox::stateChanged, this, &Display::onCheckBoxStateChanged);
connect(ui->pushButton_savecalib, &QPushButton::clicked, this, &Display::onSaveCalibrationClicked);
connect(ui->pushButton_loadcalib, &QPushButton::clicked, this, &Display::onLoadCalibrationClicked);
connect(ui->checkBox_expertmode, &QCheckBox::stateChanged, this, &Display::onExpertModeStateChanged);
// Enable or disable the "Save Background" and "Save Calib" buttons accordingly
ui->pushButton_savebkg->setEnabled(expertModeEnabled);
ui->pushButton_savecalib->setEnabled(expertModeEnabled);
// Gray out the buttons when they are disabled
ui->pushButton_savebkg->setStyleSheet(expertModeEnabled ? "" : "background-color: gray;");
ui->pushButton_savecalib->setStyleSheet(expertModeEnabled ? "" : "background-color: gray;");
}
Display::~Display()
{
delete ui;
}
void Display::showEvent(QShowEvent * event)
{
if (!event->spontaneous())
{
ui->plot->addGraph();
}
QDialog::showEvent(event);
}
//***********************************************
void Display::plot(const QVector<signed short> &data)
{
//resize data vectors and fill X values - only if needed
if (data.length() != nrPoints)
{
nrPoints = data.length();
dataX.clear();
dataY.clear();
dataX.resize(nrPoints);
dataY.resize(nrPoints);
ui->plot->xAxis->setRange(0,nrPoints-1);
//ui->plot->yAxis->setRange(-1000,66000);
for (int i = 0; i < nrPoints; i++)
dataX[i] = i;
}
//fill Y values
double min = 65535;
double max = 0;
for (int i = 0; i < nrPoints; i++)
{
dataY[i] = /*65535 -*/ data[i];
if (dataY[i] < min)
min = dataY[i];
if (dataY[i] > max)
max = dataY[i];
}
QString planeName = ui->lineTitle->text();
planeName.remove(QChar(' '));
if (subtractBackground && ui->checkBox_subbkg->isChecked()) {
// Check if background subtraction is enabled and the checkbox is checked
// Check if background data exists for this plane
if (backgroundDataMap.contains(planeName)) {
const QVector<signed short> &backgroundData = backgroundDataMap[planeName];
// Subtract background data from the current data
for (int i = 0; i < nrPoints; ++i) {
dataY[i] -= backgroundData[i];
}
}
}
if (applyCalibration && ui->checkBox_enablecalib->isChecked()) {
// Check if calibration is enabled and the checkbox is checked
// Check if calibration data exists
if (calibrationDataMap.contains(planeName) ){
const QVector<signed short> &calibrationData = calibrationDataMap[planeName];
// Apply calibration to the current data
for (int i = 0; i < nrPoints; ++i) {
dataY[i] = dataY[i] / calibrationData[i];
}
}
}
//set Y range
if (ui->radioButtonAutoscale->isChecked())
ui->plot->yAxis->setRange(min-0.05*(max-min),max+0.05*(max-min));
else if (ui->radioButtonFixedScale ->isChecked())
ui->plot->yAxis->setRange(ui->spinBox_fixedmin->value(), ui->spinBox_fixedmax->value());
else
ui->plot->yAxis->setRange(-1000,66000);
//feed plotter
ui->plot->graph(0)->setData(dataX, dataY);
//plot
ui->plot->replot();
}
void Display::plot()
{
plot(buffer);
}
void Display::setTitle(QString title)
{
ui->lineTitle->setText(title);
}
// Slot to handle button clicks
void Display::onButtonClicked(QAbstractButton *button)
{
// Handle button clicks here
if (button == radioButtonFixedScale)
{
// Fixed Scale radio button clicked
// Handle the Fixed Scale selection
// Perform actions when Fixed Scale is selected
radioButtonFixedScale->setChecked(true); // Enable relevant controls
radioButtonAutoscale->setChecked(false); // Disable other controls
}//
else if (button == radioButtonAutoscale)
{
// Autoscale radio button clicked
// Handle the Autoscale selection
// Perform actions when Autoscale is selected
ui->radioButtonFixedScale->setChecked(false); // Disable relevant controls
ui->radioButtonAutoscale->setChecked(true); // setEnabled(true); // Enable other controls
}
}
void Display::onSaveBackgroundClicked()
{
// Check if there is data to save
if (buffer.isEmpty()) {
// No data to save
return;
}
// Get the plane's name (you might need to adjust how you retrieve it)
QString planeName = ui->lineTitle->text();
// Remove invalid characters from the plane name (e.g., spaces)
planeName.remove(QChar(' '));
// Generate the filename with the plane name appended
QString filename = QString("bkg/background_%1.txt").arg(planeName);
// Open the file for writing
QFile file(filename);
if (file.open(QIODevice::WriteOnly | QIODevice::Text)) {
QTextStream stream(&file);
// Write the data to the file
for (int i = 0; i < buffer.size(); ++i) {
stream << QString::number(buffer[i]) << "\n";
}
// Close the file
file.close();
// Notify the user that the data has been saved
qInfo() << "Data saved to" << filename;
} else {
// Failed to open the file
qWarning() << "Error: Failed to open" << filename << "for writing";
}
}
void Display::onLoadBackgroundClicked()
{
// Get the plane's name (you might need to adjust how you retrieve it)
QString planeName = ui->lineTitle->text();
// Remove invalid characters from the plane name (e.g., spaces)
planeName.remove(QChar(' '));
// Generate the filename with the plane name appended
QString filename = QString("bkg/background_%1.txt").arg(planeName);
// Open the file for reading
QFile file(filename);
if (file.open(QIODevice::ReadOnly | QIODevice::Text)) {
QTextStream stream(&file);
// Read the data from the file and store it in the map
QVector<signed short> backgroundData;
while (!stream.atEnd()) {
QString line = stream.readLine();
signed short value = line.toShort();
backgroundData.append(value);
}
// Close the file
file.close();
// Store the background data in the map
backgroundDataMap[planeName] = backgroundData;
// Notify the user that the data has been loaded
qInfo() << "Background data loaded for" << planeName;
} else {
// Failed to open the file
qWarning() << "Error: Failed to open" << filename << "for reading";
}
}
void Display::onCheckBoxStateChanged(int state)
{
// The state argument will be Qt::Unchecked (0) or Qt::Checked (2)
subtractBackground = (state == Qt::Checked);
}
void Display::onSaveCalibrationClicked()
{
// Check if there is data to save
if (buffer.isEmpty()) {
// No data to save
return;
}
// Get the plane's name (you might need to adjust how you retrieve it)
QString planeName = ui->lineTitle->text();
// Remove invalid characters from the plane name (e.g., spaces)
planeName.remove(QChar(' '));
// Generate the filename with the plane name appended
QString filename = QString("calib/calibration_%1.txt").arg(planeName);
// Open the file for writing
QFile file(filename);
if (file.open(QIODevice::WriteOnly | QIODevice::Text)) {
QTextStream stream(&file);
// Write the data to the file
for (int i = 0; i < buffer.size(); ++i) {
stream << QString::number(buffer[i]) << "\n";
}
// Close the file
file.close();
// Notify the user that the data has been saved
qInfo() << "Calibration data saved for" << planeName;
} else {
// Failed to open the file
qWarning() << "Error: Failed to open" << filename << "for writing";
}
}
void Display::onLoadCalibrationClicked()
{
// Get the plane's name (you might need to adjust how you retrieve it)
QString planeName = ui->lineTitle->text();
// Remove invalid characters from the plane name (e.g., spaces)
planeName.remove(QChar(' '));
// Generate the filename with the plane name appended
QString filename = QString("calib/calibration_%1.txt").arg(planeName);
// Open the file for reading
QFile file(filename);
if (file.open(QIODevice::ReadOnly | QIODevice::Text)) {
QTextStream stream(&file);
// Read the data from the file and store it in a vector
QVector<signed short> calibrationData;
while (!stream.atEnd()) {
QString line = stream.readLine();
signed short value = line.toShort();
calibrationData.append(value);
}
// Close the file
file.close();
// Normalize the calibration data to the median value of all values greater than zero
QVector<signed short> normalizedCalibrationData = calibrationData; // Copy the data
QVector<signed short> normalizedCalibrationData2 = calibrationData; // Copy the data again
// Remove values less than 50 (noise or dead channels) before determining the median for live channels
normalizedCalibrationData.erase(std::remove_if(normalizedCalibrationData.begin(), normalizedCalibrationData.end(), [](signed short value) {
return value < 50;
}), normalizedCalibrationData.end());
std::sort(normalizedCalibrationData.begin(), normalizedCalibrationData.end()); // Sort the data
int size = normalizedCalibrationData.size();
signed short medianValue = 0;
if (size % 2 == 0) {
// If the size is even, take the average of the two middle values
medianValue = (normalizedCalibrationData[size / 2 - 1] + normalizedCalibrationData[size / 2]) / 2;
} else {
// If the size is odd, take the middle value
medianValue = normalizedCalibrationData[size / 2];
}
//use the second copy to return the scaled calibration values.
for (signed short &value : normalizedCalibrationData2) {
if (value > 50) {
value /= medianValue;
}
else
{
value = 0;
}
}
// Store the normalized calibration data in the map
calibrationDataMap[planeName] = normalizedCalibrationData2;
// Notify the user that the data has been loaded and normalized
qInfo() << "Calibration data loaded and normalized for" << planeName;
} else {
// Failed to open the file
qWarning() << "Error: Failed to open" << filename << "for reading";
}
}
void Display::onCalibrationCheckBoxChanged(int state) {
// Check the state and update the subtractCalibration flag accordingly
applyCalibration = (state == Qt::Checked);
}
// Slot to handle the state change of the "Expert Mode" checkbox
void Display::onExpertModeStateChanged(int state)
{
// Check if the checkbox is checked (Expert Mode enabled)
expertModeEnabled = (state == Qt::Checked);
// Enable or disable the "Save Background" and "Save Calib" buttons accordingly
ui->pushButton_savebkg->setEnabled(expertModeEnabled);
ui->pushButton_savecalib->setEnabled(expertModeEnabled);
// Gray out the buttons when they are disabled
ui->pushButton_savebkg->setStyleSheet(expertModeEnabled ? "" : "background-color: gray;");
ui->pushButton_savecalib->setStyleSheet(expertModeEnabled ? "" : "background-color: gray;");
}

61
hit2023v2_RMS/display.h Normal file
View File

@ -0,0 +1,61 @@
#ifndef DISPLAY_H
#define DISPLAY_H
#include <QDialog>
#include <QVector>
#include <QRadioButton>
#include <QButtonGroup>
#include <QTextStream>
#include <QFile>
#include <QCheckBox>
namespace Ui {
class display;
}
class Display : public QDialog
{
Q_OBJECT
public:
explicit Display(QWidget *parent = 0);
~Display();
void plot(const QVector<signed short> &data);
void plot();
void setTitle(QString title);
QVector<signed short> buffer;
public slots:
void showEvent(QShowEvent *event);
void onButtonClicked(QAbstractButton *button);
void onSaveBackgroundClicked();
void onLoadBackgroundClicked();
void onCheckBoxStateChanged(int state);
void onSaveCalibrationClicked();
void onLoadCalibrationClicked();
void onCalibrationCheckBoxChanged(int state);
void onExpertModeStateChanged(int state);
protected:
int nrPoints = 0;
QVector<double> dataX;
QVector<double> dataY;
private:
Ui::display *ui;
QRadioButton *radioButtonFixedScale; // Pointer to the Fixed Scale radio button
QRadioButton *radioButtonAutoscale; // Pointer to the Autoscale radio button
QButtonGroup *buttonGroup;
QMap<QString, QVector<signed short>> backgroundDataMap; // Map to store background data for each plane
bool subtractBackground = false; // Flag to track if background subtraction is enabled
QMap<QString, QVector<signed short>> calibrationDataMap; // Map to store calibration data for each plane
bool applyCalibration = false; // Flag to track if calibration should be applied
QVector<signed short> calibrationData; // Stores the loaded calibration data
QCheckBox *checkBoxExpertMode; // Expert Mode checkbox
bool expertModeEnabled = false; // Flag to track if expert mode is enabled
};
#endif // DISPLAY_H

242
hit2023v2_RMS/display.ui Normal file
View File

@ -0,0 +1,242 @@
<?xml version="1.0" encoding="UTF-8"?>
<ui version="4.0">
<class>display</class>
<widget class="QDialog" name="display">
<property name="geometry">
<rect>
<x>0</x>
<y>0</y>
<width>609</width>
<height>418</height>
</rect>
</property>
<property name="sizePolicy">
<sizepolicy hsizetype="Maximum" vsizetype="Preferred">
<horstretch>0</horstretch>
<verstretch>0</verstretch>
</sizepolicy>
</property>
<property name="windowTitle">
<string>Online Display</string>
</property>
<widget class="QWidget" name="verticalLayoutWidget">
<property name="geometry">
<rect>
<x>9</x>
<y>10</y>
<width>581</width>
<height>341</height>
</rect>
</property>
<layout class="QVBoxLayout" name="verticalLayout">
<item>
<widget class="QLineEdit" name="lineTitle">
<property name="frame">
<bool>false</bool>
</property>
<property name="alignment">
<set>Qt::AlignCenter</set>
</property>
<property name="readOnly">
<bool>true</bool>
</property>
</widget>
</item>
<item>
<widget class="QCustomPlot" name="plot" native="true">
<property name="sizePolicy">
<sizepolicy hsizetype="Preferred" vsizetype="Expanding">
<horstretch>0</horstretch>
<verstretch>0</verstretch>
</sizepolicy>
</property>
</widget>
</item>
<item>
<layout class="QHBoxLayout" name="horizontalLayout">
<item>
<widget class="QRadioButton" name="radioButtonAutoscale">
<property name="text">
<string>Auto Y-Scale</string>
</property>
<attribute name="buttonGroup">
<string notr="true">buttonGroup</string>
</attribute>
</widget>
</item>
<item>
<widget class="Line" name="line">
<property name="orientation">
<enum>Qt::Vertical</enum>
</property>
</widget>
</item>
<item>
<widget class="QRadioButton" name="radioButtonMaxScale">
<property name="text">
<string>Max Y-Scale</string>
</property>
<attribute name="buttonGroup">
<string notr="true">buttonGroup</string>
</attribute>
</widget>
</item>
<item>
<widget class="Line" name="line_2">
<property name="orientation">
<enum>Qt::Vertical</enum>
</property>
</widget>
</item>
<item>
<widget class="QRadioButton" name="radioButtonFixedScale">
<property name="text">
<string>Fixed Y-Scale</string>
</property>
<attribute name="buttonGroup">
<string notr="true">buttonGroup</string>
</attribute>
</widget>
</item>
<item>
<widget class="QSpinBox" name="spinBox_fixedmin">
<property name="minimum">
<number>-1000</number>
</property>
<property name="maximum">
<number>66000</number>
</property>
<property name="singleStep">
<number>100</number>
</property>
<property name="value">
<number>-1000</number>
</property>
<property name="displayIntegerBase">
<number>10</number>
</property>
</widget>
</item>
<item>
<widget class="QSpinBox" name="spinBox_fixedmax">
<property name="minimum">
<number>1000</number>
</property>
<property name="maximum">
<number>65000</number>
</property>
<property name="singleStep">
<number>100</number>
</property>
<property name="value">
<number>65000</number>
</property>
</widget>
</item>
</layout>
</item>
</layout>
</widget>
<widget class="Line" name="line_3">
<property name="geometry">
<rect>
<x>10</x>
<y>350</y>
<width>581</width>
<height>20</height>
</rect>
</property>
<property name="sizePolicy">
<sizepolicy hsizetype="Expanding" vsizetype="Fixed">
<horstretch>0</horstretch>
<verstretch>0</verstretch>
</sizepolicy>
</property>
<property name="orientation">
<enum>Qt::Horizontal</enum>
</property>
</widget>
<widget class="QWidget" name="horizontalLayoutWidget">
<property name="geometry">
<rect>
<x>10</x>
<y>370</y>
<width>581</width>
<height>41</height>
</rect>
</property>
<layout class="QHBoxLayout" name="horizontalLayout_2">
<item>
<widget class="QCheckBox" name="checkBox_expertmode">
<property name="text">
<string>expert
mode</string>
</property>
</widget>
</item>
<item>
<widget class="QCheckBox" name="checkBox_enablecalib">
<property name="text">
<string>enable
calibration</string>
</property>
</widget>
</item>
<item>
<widget class="QPushButton" name="pushButton_loadcalib">
<property name="text">
<string>Load calib</string>
</property>
</widget>
</item>
<item>
<widget class="QPushButton" name="pushButton_savecalib">
<property name="enabled">
<bool>false</bool>
</property>
<property name="text">
<string>save calib</string>
</property>
</widget>
</item>
<item>
<widget class="QCheckBox" name="checkBox_subbkg">
<property name="text">
<string>sub bkg</string>
</property>
</widget>
</item>
<item>
<widget class="QPushButton" name="pushButton_loadbkg">
<property name="text">
<string>load bkg</string>
</property>
</widget>
</item>
<item>
<widget class="QPushButton" name="pushButton_savebkg">
<property name="enabled">
<bool>false</bool>
</property>
<property name="text">
<string>save bkg</string>
</property>
</widget>
</item>
</layout>
</widget>
</widget>
<customwidgets>
<customwidget>
<class>QCustomPlot</class>
<extends>QWidget</extends>
<header>qcustomplot.h</header>
<container>1</container>
</customwidget>
</customwidgets>
<resources/>
<connections/>
<buttongroups>
<buttongroup name="buttonGroup"/>
</buttongroups>
</ui>

View File

@ -0,0 +1,129 @@
#include "displayserver.h"
DisplayServer::DisplayServer(QObject *parent) : QObject(parent)
{
}
DisplayServer::~DisplayServer()
{
unsetup();
}
//********************************************
PlaneConfig* DisplayServer::findPlane(int plane_nr)
{
for (int plane = 0; plane < planeConfig.length(); plane++)
{
if (planeConfig[plane]->nr == plane_nr)
return planeConfig[plane];
}
//create new plane if not found
PlaneConfig* new_plane = new PlaneConfig;
new_plane->nr = plane_nr;
new_plane->name = QString("Plane %1").arg(plane_nr);
new_plane->nr_devices = 0;
new_plane->nr_sensors = 0;
planeConfig.append(new_plane);
return new_plane;
}
void DisplayServer::setup(HW* hw)
{
unsetup(); //hide is inside;)
theHW = hw;
for (int dev_nr = 0; dev_nr < theHW->devices.length(); dev_nr++)
{
PlaneConfig* current_plane = findPlane(theHW->devices[dev_nr]->deviceConfig.plane);
current_plane->devices.append(theHW->devices[dev_nr]);
current_plane->nr_devices++;
current_plane->nr_sensors += theHW->devices[dev_nr]->deviceConfig.nr_sensors;
}
}
void DisplayServer::unsetup()
{
hide();
for (int plane_nr = 0; plane_nr < planeConfig.length(); plane_nr++)
{
delete planeConfig[plane_nr];
planeConfig[plane_nr] = NULL;
}
planeConfig.clear();
}
//********************************************
void DisplayServer::show()
{
hide();
displays.clear();
for (int plane = 0; plane < planeConfig.length(); plane++)
{
Display* newDisplay = new Display;
newDisplay->setTitle(planeConfig[plane]->name);
newDisplay->show();
displays.append(newDisplay);
}
active = 1;
}
void DisplayServer::hide()
{
if (active)
{
for (int plane = 0; plane < displays.length(); plane++)
{
displays[plane]->close();
delete displays[plane];
}
displays.clear();
active = 0;
}
}
void DisplayServer::plot()
{
if (!active)
return;
QVector<BufferData> lastFrame = theHW->eventBuilder.getLastFrame();
if (lastFrame.length() == 0)
return;
for (int plane = 0; plane < planeConfig.length(); plane++)
{
//initialize buffer
displays[plane]->buffer.resize(planeConfig[plane]->nr_sensors*64);
//fill with data
int current_base = 0;
for (int dev_nr = 0; dev_nr < planeConfig[plane]->nr_devices; dev_nr++)
{
int dev_id = planeConfig[plane]->devices[dev_nr]->deviceConfig.device_id;
int nr_channels = planeConfig[plane]->devices[dev_nr]->deviceConfig.nr_channels();
if (nr_channels > lastFrame[dev_id].buffer_size)
nr_channels = lastFrame[dev_id].buffer_size; //check if there's really some data in the buffer
//WARNING!!! Device order is not yet implemented!!! (probably)
for (int i = 0; i < nr_channels; i++)
displays[plane]->buffer[current_base+i] = lastFrame[dev_id].sensor_data[i];
current_base += nr_channels;
}
//plot
displays[plane]->plot();
}
}
int DisplayServer::isActive()
{
return active;
}

View File

@ -0,0 +1,46 @@
#ifndef DISPLAYSERVER_H
#define DISPLAYSERVER_H
#include <QObject>
#include <QVector>
#include "hw.h"
#include "display.h"
typedef struct
{
int nr;
QString name;
int nr_sensors; //this is commonly 2*nr_devices or 2*nr_devices-1
int nr_devices;
QVector<Device*> devices;
} PlaneConfig;
class DisplayServer : public QObject
{
Q_OBJECT
public:
explicit DisplayServer(QObject *parent = 0);
void setup(HW *hw);
void show();
void hide();
void plot();
int isActive();
~DisplayServer();
void unsetup();
signals:
public slots:
protected:
int active = 0;
HW* theHW;
QVector<PlaneConfig*> planeConfig;
QVector<Display*> displays;
PlaneConfig *findPlane(int plane_nr);
};
#endif // DISPLAYSERVER_H

View File

@ -0,0 +1,344 @@
#include "eventbuilder.h"
#include "udpserver.h"
#include "hit_analyse_v2.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;
}
//************ TODO ************
//Here we can do something more with the complete frame
// I probably want to find the position and focus with the linear regression algorithm, but first, just send data to the udpserver to test.
//ToDo:
//1. Background subtraction.
frame_counter++;
while (frame_counter<10000){
for (unsigned int dev_nr = 0; dev_nr < nrReceivers; dev_nr++){
for (unsigned int ch = 0; ch < channelCounts[dev_nr]; ch++)
backgroundFrame[dev_nr].sensor_data[ch]+= currentFrame[dev_nr].sensor_data[ch];
}
}
if (frame_counter==10000){
for (unsigned int dev_nr = 0; dev_nr < nrReceivers; dev_nr++){
for (unsigned int ch = 0; ch < channelCounts[dev_nr]; ch++)
backgroundFrame[dev_nr].sensor_data[ch]/= 10000 ;
}
}
if (frame_counter>10000){
for (unsigned int dev_nr = 0; dev_nr < nrReceivers; dev_nr++){
for (unsigned int ch = 0; ch < channelCounts[dev_nr]; ch++)
currentFrame[dev_nr].sensor_data[ch]-=backgroundFrame[dev_nr].sensor_data[ch] ;
}
}
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 < channelCounts[dev_nr]; ch++)
histograms[baseAddresses[dev_nr] + ch].shoot(currentFrame[dev_nr].sensor_data[ch]);
if (histogramSamplesToTake != -1)
histogramSamplesToTake--;
if (histogramSamplesToTake == 0)
emit sigHistoCompleted();
}
//log data
if (loggingData) logDataToFile();
//HIT_ANALYSE_V2 hit_analyse_v2;//create the object
// QString dataString = hit_analyse_v2.analyseBeamData(currentFrame);
// Call sendData method of the UDP server
QString dataString = QString::number(intensity) + ',' + QString::number(position) + ',' + QString::number(focus);
QByteArray data = dataString.toUtf8();
udpServer.sendData(data);
}
}
//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 binary format:
* - number of boards: N = 1 x unsigned short
* - number of channels per each board Cn: N x unsigned short
* - N times the following sequence:
* - SyncFrame S = 1 x SyncFrame (== 16 bytes)
* - Data D = Cn x signed short
*/
logFile.write((const char*)&totalBoards, sizeof(unsigned short));
logFile.write((const char*)channelCounts.constData(), totalBoards * sizeof(unsigned short));
for (int board = 0; board < totalBoards; board++)
{
logFile.write((const char*)&(currentFrame[board].sync_frame), sizeof(SyncFrame));
logFile.write((const char*)currentFrame[board].sensor_data, currentFrame[board].buffer_size*sizeof(signed short));
}
//write data in native binary format. All devices written as 5-sensor-wide!
//logFile.write((const char*)currentFrame.constData(), nrReceivers*sizeof(BufferData));
}
void EventBuilder::recalculateChannels()
{
totalBoards = baseAddresses.count();
if (totalBoards == 0)
return;
for (int i = 1; i < totalBoards; i++)
baseAddresses[i] = baseAddresses[i-1] + channelCounts[i-1];
totalChannels = 0;
for (int i = 0; i < channelCounts.count(); i++)
totalChannels += channelCounts[i];
}
void EventBuilder::setChannelCount(int sensor_nr, int nr_channels)
{
channelCounts[sensor_nr] = nr_channels;
recalculateChannels();
}
//************************* 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(totalChannels);
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)
{
baseAddresses.push_back(0);
channelCounts.push_back(0);
receivers.append(source);
nrReceivers = receivers.length();
currentFrame.resize(nrReceivers);
backgroundFrame.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();
baseAddresses.clear();
channelCounts.clear();
}
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();
}

View File

@ -0,0 +1,100 @@
#ifndef EVENTBUILDER_H
#define EVENTBUILDER_H
#include <QObject>
#include <QVector>
#include <QList>
#include <QFile>
#include <QThread>
#include <QMutex>
#include <QMutexLocker>
#include "udpserver.h" // Include the UDP server header
//#include "hw.h"
#include "datareceiver.h"
#include "histogram.h"
//The event builder will constantly keep some data in the buffers to enable synchronization of the devices. So:
#define EVB_MIN_BUFFER_OCCUPANCY (RECEIVER_BUFFER_SIZE / 8) //the EVB will wait until so much data is in each device buffer
#define EVB_MAX_BUFFER_OCCUPANCY (RECEIVER_BUFFER_SIZE / 2) //or so much in at least one
class EventBuilder : public QObject
{
Q_OBJECT
public:
explicit EventBuilder(QObject *parent = 0);
~EventBuilder();
void addSource(DataReceiver *source);
void deleteSources();
void startLogging(QString filename);
void stopLogging();
int isLogging();
void startTakingHistos(int sample_count);
void stopTakingHistos();
QVector<Histogram> &getHistos();
QVector<BufferData> getLastFrame();
QVector<BufferData> getNewFrame(); //as getLastFrame(), but ensures that the frame is new, i.e. no frame will be read twice
void recalculateChannels(); //recalculate baseAddresses
void setChannelCount(int sensor_nr, int nr_channels);
signals:
void sigInit();
void sigDeinit();
void sigStartLogging();
void sigStopLogging();
void sigStartTakingHistos(int);
void sigStopTakingHistos();
void sigHistoCompleted(); //this is a public signal which can be used to notify user that the histo is ready
public slots:
void onNewData(DataReceiver *receiver);
protected:
int checkBufferOccupancies();
int findLowestId();
void logDataToFile();
void init(); //run after moving to thread
void deinit();
QThread thread;
QSemaphore initSemaphore;
QVector<DataReceiver*> receivers;
QVector<BufferData> currentFrame;
QVector<BufferData> backgroundFrame;
QVector<BufferData> lastFrame;
QVector<Histogram> histograms;
int histogramSamplesToTake = 0;
QVector<unsigned short> baseAddresses; //base channel numbers for receivers
QVector<unsigned short> channelCounts; //and numbers of channels
unsigned short totalChannels; //we like unsigned shorts to put them directly into the data file
unsigned short totalBoards;
QMutex lastFrameMutex;
QSemaphore newDataSemaphore;
int nrReceivers;
QString logFileName;
QFile logFile;
int loggingData = 0;
protected slots:
void onInit();
void onDeinit();
void onStartLogging();
void onStopLogging();
void onStartTakingHistos(int sample_count);
void onStopTakingHistos();
private:
long unsigned int frame_counter = 0;
double intensity = 0.0;
double position = 0.0;
double focus = 0.0;
};
#endif // EVENTBUILDER_H

97
hit2023v2_RMS/helpers.cpp Normal file
View File

@ -0,0 +1,97 @@
#include "helpers.h"
QString ip2num(QString input, unsigned char* numbers)
{
QStringList ip_sl = input.split(".");
unsigned char ip_arr[4];
for (int i = 0; i < 4; i++)
if (i < ip_sl.length())
ip_arr[i] = (unsigned char) ip_sl.at(i).toInt();
else
ip_arr[i] = 0;
QString generated = QString("%1.%2.%3.%4")
.arg(ip_arr[0])
.arg(ip_arr[1])
.arg(ip_arr[2])
.arg(ip_arr[3]);
if (numbers)
{
for (int i = 0; i < 4; i++)
numbers[i] = ip_arr[i];
}
return generated;
}
void top (QSettings* settings)
{
while(settings->group().length() != 0)
settings->endGroup();
}
void copyQSettingsHelper(QSettings* from, QSettings* to)
{
//copy own keys
QStringList keys = from->childKeys();
for(int i = 0; i < keys.length(); i++)
{
to->setValue(keys[i], from->value(keys[i]));
}
//recursively copy child groups
QStringList groups = from->childGroups();
for(int i = 0; i < groups.length(); i++)
{
from->beginGroup(groups[i]);
to->beginGroup(groups[i]);
copyQSettingsHelper(from, to);
from->endGroup();\
to->endGroup();
}
}
void copyQSettings(QSettings* from, QSettings* to)
{
to->clear();
top(from);
copyQSettingsHelper(from, to);
}
void msleep2(unsigned int ms, unsigned int resolution)
{
QTimer timer;
timer.setSingleShot(1);
timer.start(ms);
while(timer.isActive())
{
QCoreApplication::processEvents();
QThread::msleep(resolution);
}
}
void saveCsvFile(QString filename, QList<QVector<double>> params, QList<QVector<double>> sensormean, QList<QVector<double>> sensorstd, QString delimiter)
{
QFile file(filename);
if (!file.open(QIODevice::WriteOnly | QIODevice::Text))
return;
QTextStream out(&file);
out << qSetFieldWidth(14) << qSetRealNumberPrecision(8);
for (int row = 0; (row < params.length()) && (row < sensormean.length()) && (row < sensorstd.length()); row++)
{
int col;
for (col = 0; col < params[row].length(); col++)
out << params[row][col] << delimiter;\
for (col = 0; (col < (sensormean[row].length() - 1)) && (col < (sensorstd[row].length() - 1)); col++)
out << sensormean[row][col] << delimiter << sensorstd[row][col] << delimiter;
out << sensormean[row][col+1] << delimiter << sensorstd[row][col+1] << QString("\n");
}
file.close();
}

48
hit2023v2_RMS/helpers.h Normal file
View File

@ -0,0 +1,48 @@
#ifndef HELPERS_H
#define HELPERS_H
#include <QString>
#include <QStringList>
#include <QSettings>
#include <QTimer>
#include <QCoreApplication>
#include <QThread>
#include <QList>
#include <QVector>
#include <QFile>
#include <QTextStream>
//byte array <-> unsiged short conversion
#define SHORT2BYTES(sh,by) {by[0] = (sh>>8) & 0xFF; by[1] = sh & 0xFF;}
#define LO(x) (x & 0xFF)
#define HI(x) ((x>>8) & 0xFF)
#define BYTES2SHORT(by) \
( \
(static_cast<short>(static_cast<unsigned char>((by)[0])) << 8) | \
(static_cast<short>(static_cast<unsigned char>((by)[1]))) \
)
#define BYTES2INT(by) \
( \
(static_cast<int>(static_cast<unsigned char>((by)[0])) << 24) | \
(static_cast<int>(static_cast<unsigned char>((by)[1])) << 16) | \
(static_cast<int>(static_cast<unsigned char>((by)[2])) << 8) | \
(static_cast<int>(static_cast<unsigned char>((by)[3]))) \
)
//convert textual representation of IP to array of numbers and/or well-formatted string
QString ip2num(QString input, unsigned char* numbers = NULL);
//go to the main branch of settings
void top (QSettings* settings);
//copy settings table
void copyQSettings(QSettings* from, QSettings* to);
//sleep with processing queues
void msleep2(unsigned int ms, unsigned int resolution = 10);
//Save data in form of CSV file. The three tables should have the same number of rows. They will be concatenated. Sensormean and sensorstd will be interlaced.
void saveCsvFile(QString filename, QList<QVector<double>> params, QList<QVector<double>> sensormean, QList<QVector<double>> sensorstd, QString delimiter = QString(","));
#endif // HELPERS_H

144
hit2023v2_RMS/histogram.cpp Normal file
View File

@ -0,0 +1,144 @@
#include "histogram.h"
Histogram::Histogram()
{
resize(1);
}
Histogram::Histogram(const Histogram& other)
{
length = other.getLength();
data = other.data;
}
Histogram::Histogram(int newlength)
{
resize(newlength);
}
Histogram::~Histogram()
{
data.clear();
}
void Histogram::resize(int newlength)
{
length = newlength;
data.clear();
data.resize(length);
clear();
}
void Histogram::clear()
{
data.fill(0);
}
int Histogram::getLength() const
{
return length;
}
int& Histogram::operator[](int pos)
{
if (pos < 0)
pos = 0;
if (pos >= length)
pos = length-1;
return data[pos];
}
Histogram& Histogram::operator=(const Histogram& other)
{
if (this != &other)
{
length = other.getLength();
data = other.data;
}
return *this;
}
void Histogram::shoot(int channel)
{
if ((channel >= 0) && (channel < length))
data[channel]++;
}
int Histogram::getNrSamples()
{
int result = 0;
for (int ch = 0; ch < length; ch++)
result += data[ch];\
return result;
}
double Histogram::moment(int n)
{
double result;
for (int ch = 0; ch < length; ch++)
result += (pow(ch,n) * data[ch]);
result /= getNrSamples();
return result;
}
double Histogram::cmoment(int n)
{
double result;
double EX = moment(1);
for (int ch = 0; ch < length; ch++)
result += (pow((ch-EX),n) * data[ch]);
result /= getNrSamples();
return result;
}
double Histogram::mean()
{
//return moment(1);
//faster:
double result;
for (int ch = 0; ch < length; ch++)
result += ((long int)ch * (long int)data[ch]);
return (double) result / getNrSamples();
}
double Histogram::var()
{
//return moment(2) - pow(mean(),2);
//faster:
double result;
for (int ch = 0; ch < length; ch++)
result += ((double)ch * (double)ch * (double)data[ch]);
return (double) result / getNrSamples();
}
double Histogram::stdev()
{
return sqrt(var());
}
void Histogram::MS(double* mean, double* stdev)
{
double nr_samples = 0;
double EX = 0;
double EX2 = 0;
double tmp;
for (int ch = 0; ch < length; ch++)
{
tmp = (double)ch * (double)data[ch];
nr_samples += data[ch];
EX += tmp;
EX2 += (double)ch * tmp;
}
EX /= nr_samples;
EX2 /= nr_samples;
*mean = EX;
*stdev = sqrt( EX2 - EX*EX );
}

36
hit2023v2_RMS/histogram.h Normal file
View File

@ -0,0 +1,36 @@
#ifndef HISTOGRAM_H
#define HISTOGRAM_H
#include <QVector>
class Histogram
{
public:
Histogram();
Histogram(const Histogram &other);
Histogram(int newlength);
~Histogram();
void resize(int newlength);
void clear();
int getLength() const;
int &operator [](int pos);
int length;
QVector<int> data;
Histogram &operator =(const Histogram &other);
void shoot(int channel); //add one event to the histogram
int getNrSamples();
double moment(int n);
double cmoment(int n);
double mean();
double var();
double stdev();
void MS(double *mean, double *stdev); //calculate mean and stdev
protected:
};
#endif // HISTOGRAM_H

View File

@ -0,0 +1,82 @@
#-------------------------------------------------
#
# Project created by QtCreator 2017-08-21T15:59:19
#
#-------------------------------------------------
QT += core gui network serialport
QMAKE_CXXFLAGS += -Wa,-mbig-obj
greaterThan(QT_MAJOR_VERSION, 5): QT += widgets printsupport
TARGET = hit2023v2
TEMPLATE = app
SOURCES += main.cpp\
hit_analyse_v2.cpp \
mainwindow.cpp \
q_debugstream.cpp \
dialoglogsettings.cpp \
device.cpp \
datareceiver.cpp \
hw.cpp \
dialoghostip.cpp \
dialogtriggersettings.cpp \
dialogdevices.cpp \
helpers.cpp \
eventbuilder.cpp \
qcustomplot.cpp \
display.cpp \
displayserver.cpp \
keithley.cpp \
keithley_thr.cpp \
dialoglinearity.cpp \
histogram.cpp \
dialogtiscan.cpp \
dialogprofiler.cpp \
stepper.cpp \
dialogbeta.cpp \
udpserver.cpp
HEADERS += mainwindow.h \
Q_DebugStream.h \
dialoglogsettings.h \
device.h \
dev_commands.h \
datareceiver.h \
hit_analyse_v2.h \
hw.h \
dialoghostip.h \
dialogtriggersettings.h \
dialogdevices.h \
helpers.h \
cbuffer.h \
eventbuilder.h \
qcustomplot.h \
display.h \
displayserver.h \
keithley.h \
keithley_thr.h \
dialoglinearity.h \
histogram.h \
dialogtiscan.h \
dialogprofiler.h \
stepper.h \
dialogbeta.h \
udpserver.h \
hitreader.h
FORMS += mainwindow.ui \
dialoglogsettings.ui \
dialoghostip.ui \
dialogtriggersettings.ui \
dialogdevices.ui \
display.ui \
dialoglinearity.ui \
dialogtiscan.ui \
dialogprofiler.ui \
dialogbeta.ui

View File

@ -0,0 +1,154 @@
#include "hit_analyse_v2.h"
#include <random>
HIT_ANALYSE_V2::HIT_ANALYSE_V2(QObject *parent) : QObject(parent)
{
}
QString HIT_ANALYSE_V2::analyseBeamData(QVector<BufferData> dataframe){
double position=0.1;
double focus=8;
double intensity=10000.0;
QString dataString;
const int vector_length = 300; // Replace with the actual length of your vectors
std::vector<double> signal_list(vector_length);
std::vector<double> channel_list(vector_length);
// Create a random number generator with a Gaussian distribution
std::random_device rd;
std::mt19937 gen(rd());
std::normal_distribution<double> dist(0.0, 17.0); // Mean of 0 and Sigma of 17
// Create a vector to store the generated values
std::vector<short int> result(vector_length);
// Fill the vector with random values
for (int i = 0; i < vector_length; ++i) {
result[i] = static_cast<short int>(dist(gen));
signal_list.push_back(result[i]);
channel_list.push_back(i);
}
//add a gaussian profile, focus is FWHM, position is random between 50 and 250
position = 50 + (rand() % (int)(250 - 50 + 1));
for (int i = 0; i < vector_length; ++i) {
signal_list[i] += intensity*exp(-4*log(2)*pow((channel_list[i]-position)/focus,2));
}
// Fill signal_list and channel_list with your data
double SumT = 0.0, SumS = 0.0, SumS2 = 0.0, SumST = 0.0, SumT2 = 0.0, SumY = 0.0, SumYS = 0.0, SumYT = 0.0;
double b_den = 0.0, b_num = 0.0, b = 0.0, p = 0.0, c = 0.0, SumYYP = 0.0, SumYYM = 0.0, MeanY = 0.0;
double S[vector_length];
double T[vector_length];
for (int k = 0; k < vector_length; k++) {
if (k == 0) {
S[k] = 0.0;
T[k] = 0.0;
} else {
S[k] = S[k - 1] + 0.5 * (signal_list[k] + signal_list[k - 1]) * (channel_list[k] - channel_list[k - 1]);
T[k] = T[k - 1] + 0.5 * (channel_list[k] * signal_list[k] + channel_list[k - 1] * signal_list[k - 1]) *
(channel_list[k] - channel_list[k - 1]);
}
SumS += S[k];
SumT += T[k];
SumY += signal_list[k];
SumS2 += S[k] * S[k];
SumST += S[k] * T[k];
SumT2 += T[k] * T[k];
SumYS += signal_list[k] * S[k];
SumYT += signal_list[k] * T[k];
MeanY += signal_list[k];
}
MeanY /= vector_length;
// Calculate M1 matrix elements
double M1_00 = SumT2;
double M1_01 = SumST;
double M1_02 = SumT;
double M1_10 = SumST;
double M1_11 = SumS2;
double M1_12 = SumS;
double M1_20 = SumT;
double M1_21 = SumS;
double M1_22 = vector_length;
// Calculate M2 vector elements
double M2_0 = SumYT;
double M2_1 = SumYS;
double M2_2 = SumY;
// Calculate the inverse of M1
double detM1 = M1_00 * (M1_11 * M1_22 - M1_12 * M1_21) -
M1_01 * (M1_10 * M1_22 - M1_12 * M1_20) +
M1_02 * (M1_10 * M1_21 - M1_11 * M1_20);
if (detM1 == 0.0) {
std::cerr << "M1 is not invertible." << std::endl;
//return 1;
}
double invM1_00 = (M1_11 * M1_22 - M1_12 * M1_21) / detM1;
double invM1_01 = (M1_02 * M1_21 - M1_01 * M1_22) / detM1;
double invM1_02 = (M1_01 * M1_12 - M1_02 * M1_11) / detM1;
double invM1_10 = (M1_12 * M1_20 - M1_10 * M1_22) / detM1;
double invM1_11 = (M1_00 * M1_22 - M1_02 * M1_20) / detM1;
double invM1_12 = (M1_02 * M1_10 - M1_00 * M1_12) / detM1;
double invM1_20 = (M1_10 * M1_21 - M1_11 * M1_20) / detM1;
double invM1_21 = (M1_01 * M1_20 - M1_00 * M1_21) / detM1;
double invM1_22 = (M1_00 * M1_11 - M1_01 * M1_10) / detM1;
// Calculate ABC vector
double ABC_0 = invM1_00 * M2_0 + invM1_01 * M2_1 + invM1_02 * M2_2;
double ABC_1 = invM1_10 * M2_0 + invM1_11 * M2_1 + invM1_12 * M2_2;
double ABC_2 = invM1_20 * M2_0 + invM1_21 * M2_1 + invM1_22 * M2_2;
// Calculate b, p, and c
p = -ABC_0 / 2.0;
c = -ABC_1 / ABC_0;
for (int k = 0; k < vector_length; k++) {
double exp_term = exp(-p * (channel_list[k] - c) * (channel_list[k] - c));
b_num += exp_term * signal_list[k];
b_den += exp_term;
}
b = b_num / b_den;
for (int k = 0; k < vector_length; k++) {
double y_pred = b * exp(-p * (channel_list[k] - c) * (channel_list[k] - c));
SumYYM += (signal_list[k] - MeanY) * (signal_list[k] - MeanY);
SumYYP += (y_pred - MeanY) * (y_pred - MeanY);
}
double R_squared = SumYYP / SumYYM;
//std::cout << "R-squared = " << R_squared << endl;
position = -ABC_1/ ABC_0;
//sigma = sqrt(1.0 / (2.0 * ABC_0));
focus = 2.3548/sqrt(2*p);
intensity = b;
dataString += QString::number(intensity) + ',' + QString::number(position) + ',' + QString::number(focus)
+ ',' + QString::number(R_squared);
return dataString;
}
HIT_ANALYSE_V2::~HIT_ANALYSE_V2()
{
}

View File

@ -0,0 +1,72 @@
#ifndef HIT_ANALYSE_V2_H
#define HIT_ANALYSE_V2_H
#include <string>
#include <stdio.h>
#include <iostream>
#include <numeric>
#include <vector>
#include <algorithm> // std::count
#include <utility>
#include <math.h>
#include <fstream>
#include <iomanip> // std::setprecision
#include <QObject>
#include <QUdpSocket>
#include <complex.h>
#include <stdlib.h>
#include "datareceiver.h"
//#include <gsl/gsl_errno.h>
//#include <gsl/gsl_fft_complex.h>
//#include <gsl/gsl_sort.h>
//#include <gsl/gsl_statistics.h>
class HIT_ANALYSE_V2 : public QObject
{
Q_OBJECT
public:
explicit HIT_ANALYSE_V2(QObject *parent = nullptr);
~HIT_ANALYSE_V2();
private:
struct beamRecon {
double Position;
double Focus;
double Peak;
double Rsqr;
double Skew;
double Kurtosis;
double Sum;
int n_channels;
};
struct bpm_frame_v2 {
double channel_amp[320];
double channel_position[320];
double avg_position;
double avg_width;
double integratedsignalamp;
double maxchannel_amp;
int maxchannel;
int nrChannels;
int board_number;
int sma_state;
};
public slots:
QString analyseBeamData(QVector<BufferData> dataframe);
// void processPendingDatagrams();
};
class Channel{
public:
double amplitude;;
double position;
int chnumber;
int last_neighbour;
int next_neighbour;
};
#endif // HIT_ANALYSE_V2_H

441
hit2023v2_RMS/hitreader.h Normal file
View File

@ -0,0 +1,441 @@
//This is an object interface for reading HIT data files
//See HIT documentation for details and examples.
/*
THIS DOESN'T WORK!
.L hitreader.c
Hitdata data;
data.read(my_file.da2); //to load whole file at once forget it! See below.
data.read(my_file.da2,1000,100,10) //to read 100 frames starting from frame 1000 and incrementing by 10 (i.e. frame 1000, 1010, 1020, ... 1990 will be read)
//Reading 10 000 frames is reasonable. Reading 100 000 frames made my VM beg for memory.
data.nrFrames //to see how many frames you have
data.frames[0].nrBoards //to see how many boards you had in the system
data.frames[0].boards[0].nrChannels //to see how many channels you have in board 0
data.frames[10].boards[0].data[100] //get signal value for frame 10, board 0, channel 100
data.frames[10].boards[0].syncframe.local_ctr //get the local synchro counter for frame 10, board 0
//same for .global_ctr, .sma_state, .dummy, .device_nr, .data_ok
*/
//*********************** Helper *************************
#include <fstream>
#include <iostream>
using namespace std;
//#define debug(str) std::cout << "HIT DEBUG: " << str << endl;
#define debug(str)
//*********************** Syncframe *************************
class Syncframe
{
public:
Syncframe()
{
debug("Syncframe()");
local_ctr = global_ctr = 0;
sma_state = dummy = 0;
device_nr = -1;
data_ok = 0;
};
~Syncframe()
{
debug("~Syncframe()");
};
int sizeInFile()
{
return 16;
};
int read(std::ifstream* file)
{
char buffer[16];
file->read(buffer,16);
if (file->fail())
return 0;
local_ctr = *(unsigned short*)(buffer+0);
global_ctr = *(unsigned short*)(buffer+2);
sma_state = *(unsigned short*)(buffer+4);
dummy = *(unsigned short*)(buffer+6);
device_nr = *(int*)(buffer+8);
data_ok = *(int*)(buffer+12);
// std::cout << "Syncframe:" << local_ctr << " " << global_ctr << " " << sma_state << " " << dummy << " " << device_nr << " " << data_ok << std::endl;
return 1;
};
unsigned short local_ctr;
unsigned short global_ctr;
unsigned short sma_state;
unsigned short dummy;
int device_nr;
unsigned int data_ok;
};
//*********************** Sensorframe *************************
class Boardframe
{
public:
Boardframe(int nr_channels = 0)
{
debug("Boardframe()");
data = NULL;
resize (nr_channels);
};
Boardframe(const Boardframe& in)
{
debug("Boardframe(Boardframe&)");
data = NULL;
resize(in.nrChannels);
for (int i = 0; i < nrChannels; i++)
data[i] = in.data[i];
syncframe = in.syncframe;
};
Boardframe& operator=(const Boardframe& in)
{
debug("Boardframe::operator==");
resize(in.nrChannels);//creates an array called data of length nrChannels
for (int i = 0; i < nrChannels; i++)
data[i] = in.data[i];
syncframe = in.syncframe;
return *this;
};
~Boardframe()
{
debug("~Boardframe()");
if (data)
delete[] data;
};
void resize(int nr_channels)
{
if (data)
delete[] data;
nrChannels = nr_channels;
if (nrChannels)
data = new unsigned short[nrChannels];
else
data = NULL;
};
int sizeInFile()
{
// std::cout << "boardframe.sizeInFile() = " << syncframe.sizeInFile() + nrChannels*2 << std::endl;
return syncframe.sizeInFile() + nrChannels*2;
};
int read(std::ifstream* file)
{
if (syncframe.read(file) == 0)//get the syncframe before the board data
return 0;
//I must be already resized at this point!
file->read((char*)data,2*nrChannels);
if (file->fail())
return 0;
// std::cout<< "data[" << nrChannels << "]: ";
// for (int i = 0;i<nrChannels;i++) std::cout << data[i] << " ";
// std::cout << std::endl;
return 1;
};
unsigned short& operator[] (int index)
{
return data[index];
};
Syncframe syncframe;
int nrChannels;
unsigned short* data;
};
//*********************** Fullframe *************************
class Fullframe
{
public:
Fullframe(int nr_boards = 0)
{
debug("Fullframe()");
boards = NULL;
resize(nr_boards);
};
Fullframe(const Fullframe& in)
{
debug("Fullframe(Fullframe&)");
boards = NULL;
resize(in.nrBoards);
for (int i = 0; i < nrBoards; i++)
boards[i] = in.boards[i];
};
Fullframe& operator=(const Fullframe& in)
{
debug("Fullframe::operator==");
resize(in.nrBoards);
for (int i = 0; i < nrBoards; i++)
boards[i] = in.boards[i];
return *this;
};
~Fullframe()
{
debug("~Fullframe()");
if (boards)
delete[] boards;
};
void resize (int nr_boards)
{
if (boards)
delete[] boards;
nrBoards = nr_boards;
if (nrBoards)
boards = new Boardframe[nrBoards];
else
boards = NULL;
}
int sizeInFile()
{
if (boards){
// std::cout << "Fullframe.sizeInFile() = " << 2 + nrBoards*2 + nrBoards * boards[0].sizeInFile() << std::endl;
// return 2 + nrBoards*2 + nrBoards * boards[0].sizeInFile();
//// boards[0].sizeInFile() returns 656 for every board...
return 2 + 4*2 + (16 + 320 * 2) + (16 + 128*2)*3; //1482
}
else
return 0; //no boards, makes no sense...
};
int read(std::ifstream* file)
{
//Read number of boards
unsigned short nr_boards;
file->read((char*)&nr_boards,2);
if(file->fail()){
std::cerr << "File read failed." << std::endl;
return 0;
}
if (nr_boards!=4){
std::cerr << "Unrealistic number(!=) of boards to be read:"<< nr_boards << std::endl;
std::cerr << "Will try to resync frame." << std::endl;
for (int j = 0;j<741;j++){
file->read((char*)&nr_boards,2);
if (nr_boards==4) break;
}
if ( nr_boards!=4){
std::cerr << "Resync failed." << std::endl;
return 0;
}
}
//std::cout << " nr_boards: " << nr_boards << std::endl;
//Read channel counts
unsigned short* channel_counts = new unsigned short[nr_boards];
file->read((char*)channel_counts,nr_boards*2);
if (file->fail())
{
delete[] channel_counts;
return 0;
}
//Read board frames
resize(nr_boards);
for (int board_nr = 0; board_nr < nr_boards; board_nr++)
{
// std::cout << " channel_counts[" << board_nr << "]: "<< channel_counts[board_nr] << std::endl;
boards[board_nr].resize(channel_counts[board_nr]);
if (boards[board_nr].read(file) == 0)//read the board
{
delete[] channel_counts;
return 0;
}
}
delete[] channel_counts;
return 1;
};
int nrChannels()
{
int result = 0;
for (int board_nr = 0; board_nr < nrBoards; board_nr++)
result += boards[board_nr].nrChannels;
return result;
};
unsigned short& operator[] (int index)
{
for (int board_nr = 0; board_nr < nrBoards; board_nr++)
{
if (index >= boards[board_nr].nrChannels)
index -= boards[board_nr].nrChannels;
else
return boards[board_nr][index];
}
std::cerr << " ### Fullframe::operator[]: index out of range!" << std::endl;
// return (*NULL); //this will cause crash (intended).
return boards[nrBoards][index];
};
int nrBoards;
Boardframe* boards;
};
//*********************** Hitdata *************************
class Hitdata
{
public:
Hitdata(int nr_frames = 0)
{
frames = NULL;
resize(nr_frames);
};
Hitdata(const Hitdata& in)
{
frames = NULL;
resize(in.nrFrames);
for (int i = 0; i < nrFrames; i++)
frames[i] = in.frames[i];
};
Hitdata& operator=(const Hitdata& in)
{
resize(in.nrFrames);
for (int i = 0; i < nrFrames; i++)
frames[i] = in.frames[i];
return *this;
};
~Hitdata()
{
if (nrFrames)
delete[] frames;
};
void resize (int nr_frames)
{
if (nrFrames)
delete[] frames;
nrFrames = nr_frames;
if (nrFrames)
frames = new Fullframe[nrFrames];
else
frames = NULL;
};
//Read data from a given file.
//first_frame is the number of first frame to be read
//nr_frames is the maximum number of frames to be read
//-1 to read all of them
//increment allows you reading once every nth sample
//Return number of frames read or 0 in case of failure
int readFile(char* filename, int first_frame = 1, int nr_frames = -1, int increment = 1)
{
std::ifstream file;
//Open the file
file.open(filename, ios_base::in | ios_base::binary);
if (!file.is_open())
{
std::cerr << " ### Hitdata: File could not be open!" << std::endl;
return 0; //file could not be opened
}
//Read first record to find board configuration
Fullframe sampleframe;
if (sampleframe.read(&file) == 0)
{
std::cerr << " ### Hitdata: First frame could not be read!" << std::endl;
file.close();
return 0;
}
else {
std::cout << "Sample frame size (bytes): " << sampleframe.sizeInFile() << std::endl;
}
//Check file size
file.seekg(0, std::ios::beg);
std::streamsize fsize = file.tellg();
file.seekg(0, std::ios::end);
fsize = file.tellg() - fsize;
//Determine real frames to read
unsigned int max_frames = fsize / sampleframe.sizeInFile();
if ((max_frames == -1) || (max_frames < nr_frames))
nr_frames = max_frames;
std::cout << " Hitdata: Nr frames to be read: " << nr_frames << std::endl;
//Read!
// resize(nr_frames); //make an array of Fullframes called frames of size nr_frames
file.seekg(first_frame * sampleframe.sizeInFile(), std::ios::beg);
for (int frame_nr = first_frame; frame_nr < nr_frames; frame_nr++)
{
if ((frame_nr%10000) == 0)
std::cout << " Frame " << frame_nr << std::endl;
file.seekg((frame_nr*increment) * sampleframe.sizeInFile() , std::ios::beg);
if (file.eof()) {
std::cerr<< "end of file reached." << std::endl;
return frame_nr;
}
if ( sampleframe.read(&file) == 0) //read the next frame
{
std::cerr << " ### Hitdata: Frame " << frame_nr << " could not be read!" << std::endl;
file.close(); //read error, finish!
// frames = frame_nr; //Kinky! We decrease nr_frames, but the actual array size remains unchanged!
///???? I don't know what the above line does.
return frame_nr;
}
// std::cout << frames[frame_nr].nrBoards << std::endl;
}
//Finished
file.close();
return nr_frames;
};
Fullframe& operator[] (int index)
{
if (index < nrFrames)
return frames[index];
else
{
std::cerr << " ### Hitdata::operator[]: index out of range!" << std::endl;
// return (*NULL); //this will cause crash (intended).
return frames[index];
}
};
int nrFrames;
Fullframe* frames;
};

107
hit2023v2_RMS/hw.cpp Normal file
View File

@ -0,0 +1,107 @@
#include "hw.h"
HW::HW(QObject *parent) : QObject(parent)
{
/*eventBuilder.moveToThread(&eventBuilderThread);
eventBuilderThread.start();
eventBuilder.init();*/
}
HW::~HW()
{
eventBuilder.stopLogging();
removeDevices();
}
Device& HW::operator[](int nr)
{
return *(devices[nr]);
}
void HW::addDevices(int nr_devices)
{
for (int i = 0; i < nr_devices; i++)
{
Device* new_dev = new Device;
devices.push_back(new_dev);
eventBuilder.addSource(&(new_dev->dataReceiver));
}
}
void HW::removeDevices()
{
eventBuilder.deleteSources();
for (int i = 0; i < devices.length(); i++)
delete devices[i];
devices.clear();
}
void HW::configureDevice(int dev_nr, DeviceConfig dc)
{
(*this)[dev_nr].configure(dc);
eventBuilder.setChannelCount(dev_nr, dc.max_channels());
}
void HW::connectDevices()
{
qInfo("Connecting devices...");
for (int i = 0; i < devices.length(); i++)
devices[i]->connectDevice();
}
void HW::disconnectDevices()
{
qInfo("Disconnecting devices...");
for (int i = 0; i < devices.length(); i++)
devices[i]->disconnectDevice();
}
void HW::run()
{
//No need to start EVB. It's running all the time.
//run slave(s)
for (int i = 0; i < devices.length(); i++)
if (devices[i]->deviceConfig.master == 0)
devices[i]->startAcq();
//run master(s)
for (int i = 0; i < devices.length(); i++)
if (devices[i]->deviceConfig.master != 0)
devices[i]->startAcq();
}
void HW::stop()
{
//stop master(s)
for (int i = 0; i < devices.length(); i++)
if (devices[i]->deviceConfig.master != 0)
devices[i]->stopAcq();
//stop slave(s)
for (int i = 0; i < devices.length(); i++)
if (devices[i]->deviceConfig.master == 0)
devices[i]->stopAcq();
//EVB is running all the time.
}
QString HW::report()
{
int nr_devices = devices.length();
QString result;
for (int dev_nr = 0; dev_nr < nr_devices; dev_nr++)
{
double buffer_ocupancy = 100.0 * (double)(devices[dev_nr]->dataReceiver.dataBuffer.nrItems()) / (double)RECEIVER_BUFFER_SIZE;
double ksps = (double)(devices[dev_nr]->getFrameRate())/1000.0;
result += QString("%1: %2kfps, %3% ").arg(dev_nr).arg(ksps,5,'f',2,'0').arg(buffer_ocupancy,4,'f',1,'0');
}
return result;
}

41
hit2023v2_RMS/hw.h Normal file
View File

@ -0,0 +1,41 @@
#ifndef HW_H
#define HW_H
#include <QObject>
#include <QVector>
#include <QThread>
#include "device.h"
#include "eventbuilder.h"
class HW : public QObject
{
Q_OBJECT
public:
explicit HW(QObject *parent = 0);
~HW();
QVector<Device*> devices;
EventBuilder eventBuilder;
Device &operator [](int nr);
void addDevices(int nr_devices);
void removeDevices();
void connectDevices();
void disconnectDevices();
void run();
void stop();
QString report();
void configureDevice(int dev_nr, DeviceConfig dc);
signals:
public slots:
protected:
};
#endif // HW_H

241
hit2023v2_RMS/keithley.cpp Normal file
View File

@ -0,0 +1,241 @@
#include "keithley.h"
//THIS IS KEITHLEY 6487 (PICOAMMETER) RS-232 LIBRARY!
keithley::keithley()
{
isOpen = 0;
}
/*void keithley::ps_printf(const char* fmt, ...)
{
QString result;
va_list args;
va_start(args, fmt);
result.vsprintf(fmt, args);
va_end(args);
//char toWrite[result.length()+1];
//strcpy(toWrite, qPrintable(result));
//serialPort.write(toWrite, strlen(toWrite));
socket.write(qPrintable(result), result.length());
socket.waitForBytesWritten(500);
}
//read a CR-LF terminated string from PS
int keithley::ps_read(char* dest, int maxSize)
{
int ptr = 0;
while (1)
{
if (socket.read(dest+ptr,1) <= 0)
{
if (!socket.waitForReadyRead(10))
break; //no new data - break
}
else
ptr++;
if (dest[ptr-1] == '\n')
{
ptr--;
break; //newline found - delete and break
}
if (dest[ptr-1] == '\r')
ptr--; //CR found - delete it
if (ptr >= (maxSize-1))
break; //buffer full = break
}
dest[ptr] = 0;
//return number of read characters
return ptr;
}*/
//Qt5
/*
void keithley::ps_printf(const char* fmt, ...)
{
QString result;
va_list args;
va_start(args, fmt);
result.vsprintf(fmt, args);
va_end(args);
//char toWrite[result.length()+1];
//strcpy(toWrite, qPrintable(result));
//serialPort.write(toWrite, strlen(toWrite));
serialPort.write(qPrintable(result), result.length());
serialPort.waitForBytesWritten(500);
}
*/
//Qt6
void keithley::ps_printf(const char* fmt, ...)
{
va_list args;
va_start(args, fmt);
QString result = QString::vasprintf(fmt, args);
va_end(args);
serialPort.write(result.toUtf8());
serialPort.waitForBytesWritten(500);
}
//read a CR-LF terminated string from PS
int keithley::ps_read(char* dest, int maxSize)
{
int ptr = 0;
while (1)
{
if (serialPort.read(dest+ptr,1) <= 0)
{
if (!serialPort.waitForReadyRead(500))
break; //no new data - break
}
else
{
ptr++;
if (dest[ptr-1] == '\n')
{
ptr--;
break; //newline found - delete and break
}
if (dest[ptr-1] == '\r')
{
ptr--; //CR found - delete and break
break;
}
if (ptr >= (maxSize-1))
break; //buffer full = break
}
}
dest[ptr] = 0;
return ptr;
}
void keithley::ps_flush()
{
char buffer[32];
while (ps_read(buffer, 32));
}
//**************************************************************************
int keithley::connect()
{
/*disconnect(); //just if we were connected
socket.connectToHost(hostName, port);
if (socket.waitForConnected(5000))
{
isOpen = 1;
return 1;
}
return 0;*/
QList<QSerialPortInfo> list = QSerialPortInfo::availablePorts();
disconnect(); //close port if it's open
if (list.size() == 0)
return -1; //no serial ports found
for (int port = 0; port < list.size(); port++)
{
serialPort.setPort(list[port]);
serialPort.setBaudRate(57600);
if (serialPort.open(QIODevice::ReadWrite))
{
serialPort.setBaudRate(57600);
ps_printf("*IDN?\n");
QThread::msleep(100);
char buffer[128];
ps_read(buffer,128);
if (strstr(buffer, "KEITHLEY INSTRUMENTS INC.,MODEL 6487"))
{ //gotta our PS!
isOpen = 1;
portName = list[port].portName();
//configure for measurement
QThread::msleep(100);
ps_printf("CONF\n");
//setup medium readout reate (Tint = 20 ms)
QThread::msleep(100);
ps_printf("NPLC 1\n");
QThread::msleep(100);
ps_printf("RANG:AUTO 0\n");
QThread::msleep(100);
ps_printf("RANG 2e-5\n");
QThread::msleep(100);
//setup source
ps_printf("SOUR:VOLT:RANG 10\n");
QThread::msleep(100);
ps_printf("SOUR:VOLT:ILIM 2.5e-2\n");
QThread::msleep(100);
break;
}
serialPort.close();
}
}
return isOpen;
}
void keithley::disconnect()
{
if (!isOpen)
return;
//socket.close();
serialPort.close();
isOpen = 0;
}
void keithley::setVoltage(double voltage)
{
if (!isOpen)
return;
//ps_printf("smua.source.func=smua.OUTPUT_DCVOLTS\n");
//ps_printf("smua.source.levelv=%1.2f\n", voltage);
ps_printf("SOUR:VOLT %1.2f\n", voltage);
}
void keithley::on(int state)
{
if (!isOpen)
return;
if (state)
{
//ps_printf("smua.source.output=smua.OUTPUT_ON\n");
ps_printf("SOUR:VOLT:STAT ON\n");
}
else
{
//ps_printf("smua.source.output=smua.OUTPUT_OFF\n");
ps_printf("SOUR:VOLT:STAT OFF\n");
}
}
void keithley::reset()
{
if (!isOpen)
return;
//ps_printf("smua.reset()\n");
ps_printf("*RST\n");
}
double keithley::getCurrent()
{
char reply[128];
ps_flush();
//ps_printf("print(smua.measure.i())\n");
//ps_printf("MEAS?\n");
ps_printf("READ?\n");
//QThread::msleep(250);
while (!ps_read(reply, 128));
double result = atof(reply);
return result;
}

30
hit2023v2_RMS/keithley.h Normal file
View File

@ -0,0 +1,30 @@
#ifndef KEITHLEY_H
#define KEITHLEY_H
//THIS IS KEITHLEY 6487 (PICOAMMETER) RS-232 LIBRARY!
#include <QtSerialPort/QtSerialPort>
#include <QSerialPortInfo>
#include <QSerialPort>
class keithley
{
public:
keithley();
//QTcpSocket socket;
int isOpen;
QString portName;
QSerialPort serialPort;
int connect();
void disconnect();
void ps_printf(const char *fmt...);
int ps_read(char* dest, int maxSize);
void setVoltage(double voltage);
void on(int state);
void reset();
double getCurrent();
void ps_flush();
};
#endif // KEITHLEY_H

View File

@ -0,0 +1,150 @@
#include "keithley_thr.h"
//THIS IS KEITHLEY 6487 (PICOAMMETER) RS-232 LIBRARY!
//************************** worker class ******************
keithleyWorker::keithleyWorker()
{
QObject::connect(&timer, &QTimer::timeout, this, &keithleyWorker::timerEvent);
timer.setSingleShot(true);
}
void keithleyWorker::connect()
{
int isOpen = theKeithley.connect();
emit sig_isOpen(isOpen, theKeithley.portName);
}
void keithleyWorker::disconnect()
{
theKeithley.disconnect();
}
void keithleyWorker::runTimer(const int state)
{
if (state)
timer.start(readoutDelay);
else
timer.stop();
}
void keithleyWorker::timerEvent()
{
//do the readout
lastCurrentReadout = theKeithley.getCurrent();
emit sig_currentReadout(lastCurrentReadout);
//run the timer again
timer.start(readoutDelay);
}
void keithleyWorker::on(const int state)
{
theKeithley.on(state);
}
void keithleyWorker::setVoltage(const double voltage)
{
theKeithley.setVoltage(voltage);
}
void keithleyWorker::reset()
{
theKeithley.reset();
}
//************************** constructor and destructor ******************
keithley_thr::keithley_thr()
{
lastCurrentReadout = -1;
isOpen = 0;
keithleyWorker *worker = new keithleyWorker;
//worker->theKeithley = &theKeithley;
worker->moveToThread(&workerThread);
worker->timer.moveToThread(&workerThread);
worker->theKeithley.serialPort.moveToThread(&workerThread);
//controller -> worker
QObject::connect(&workerThread, &QThread::finished, worker, &QObject::deleteLater);
QObject::connect(this, &keithley_thr::sig_connect, worker, &keithleyWorker::connect);
QObject::connect(this, &keithley_thr::sig_disconnect, worker, &keithleyWorker::disconnect);
QObject::connect(this, &keithley_thr::sig_on, worker, &keithleyWorker::on);
QObject::connect(this, &keithley_thr::sig_setVoltage, worker, &keithleyWorker::setVoltage);
QObject::connect(this, &keithley_thr::sig_reset, worker, &keithleyWorker::reset);
QObject::connect(this, &keithley_thr::sig_runTimer, worker, &keithleyWorker::runTimer);
//worker -> controller
QObject::connect(worker, &keithleyWorker::sig_currentReadout, this, &keithley_thr::on_currentReadout);
QObject::connect(worker, &keithleyWorker::sig_isOpen, this, &keithley_thr::on_isOpen);
workerThread.start();
}
keithley_thr::~keithley_thr()
{
workerThread.quit();
workerThread.wait();
}
//************************** slots for communication with worker thread ******************
//called on each current readout
keithley_thr::on_currentReadout(const double value)
{
lastCurrentReadout = value;
emit esig_newCurrentReadout(lastCurrentReadout);
}
//called after opening the socket
int keithley_thr::on_isOpen(const int state, const QString givenPortName)
{
isOpen = state;
portName = givenPortName;
}
//************************** class keithley mirror ******************
int keithley_thr::connect()
{
isOpen = -1;
emit sig_connect();
//wait until the socket opens or fails
while (isOpen == -1)
qApp->processEvents();
//run readout if opened succesfully
emit sig_runTimer(isOpen);
return isOpen;
}
void keithley_thr::disconnect()
{
emit sig_runTimer(0);
emit sig_disconnect();
}
void keithley_thr::setVoltage(double voltage)
{
emit sig_setVoltage(voltage);
}
void keithley_thr::on(int state)
{
emit sig_on(state);
}
void keithley_thr::reset()
{
emit sig_reset();
}
double keithley_thr::getCurrent()
{
return lastCurrentReadout;
}

View File

@ -0,0 +1,81 @@
#ifndef KEITHLEY_THR_H
#define KEITHLEY_THR_H
//THIS IS KEITHLEY 6487 (PICOAMMETER) RS-232 LIBRARY!
#include <QtCore>
#include <QObject>
#include <QThread>
#include <QTimer>
#include "keithley.h"
class keithleyWorker : public QObject
{
Q_OBJECT
public:
keithleyWorker();
keithley theKeithley;
QTimer timer;
double lastCurrentReadout;
int readoutDelay = 100;
public slots:
void on(const int state);
void setVoltage(const double voltage);
void reset();
void timerEvent();
void runTimer(const int state);
void connect();
void disconnect();
signals:
//void resultReady(const QString &result);
void sig_currentReadout(const double value);
void sig_isOpen(const int state, const QString portName);
};
class keithley_thr : public QObject
{
Q_OBJECT
public:
keithley_thr();
~keithley_thr();
//keithley theKeithley;
int isOpen;
int connect();
void disconnect();
void ps_printf(const char *fmt...);
int ps_read(char *dest, int maxSize);
void setVoltage(double voltage);
void on(int state);
void reset();
double getCurrent();
void ps_flush();
QThread workerThread;
double lastCurrentReadout;
QString portName;
int recognizeSpillState(double current);
public slots:
on_currentReadout(const double value);
int on_isOpen(const int state, const QString givenPortName);
signals:
void sig_connect();
void sig_disconnect(void);
void sig_on(const int);
void sig_setVoltage(const double);
void sig_reset(void);
void sig_runTimer(const int);
void esig_newCurrentReadout(const double);
};
#endif // KEITHLEY_THR_H

34
hit2023v2_RMS/main.cpp Normal file
View File

@ -0,0 +1,34 @@
#include "mainwindow.h"
#include <QApplication>
#include "udpserver.h" // Include udpserver header
// Define the global UdpServer object
UdpServer udpServer; // This allocates memory for udpServer
int main(int argc, char *argv[])
{
QApplication a(argc, argv);
// Create the UdpServer object on the heap and store a pointer to it
udpServer.startServer();
// Apply the stylesheet to each display
qDebug() << "App path : " << qApp->applicationDirPath();
qApp->setStyleSheet("");
QString stylesheetPath = qApp->applicationDirPath()+"/styles/Medize.qss";
// Load and apply the new stylesheet
QFile styleFile(stylesheetPath);
if (styleFile.open(QFile::ReadOnly | QFile::Text)) {
QString style = QTextStream(&styleFile).readAll();
qApp->setStyleSheet(style);
styleFile.close();
} else {
qWarning("Failed to open stylesheet file: %s", qPrintable(stylesheetPath));
}
MainWindow w;
w.show();
return a.exec();
}

View File

@ -0,0 +1,481 @@
#include "mainwindow.h"
#include "ui_mainwindow.h"
#include "dialoglogsettings.h"
#include "dialoghostip.h"
#include "dialogtriggersettings.h"
#include "dialogdevices.h"
#include "dialoglinearity.h"
#include "dialogtiscan.h"
#include "dialogprofiler.h"
#include "dialogbeta.h"
#include "helpers.h"
#include <QShowEvent>
#include <QMessageBox>
#include <QFileDialog>
MainWindow::MainWindow(QWidget *parent) :
QMainWindow(parent),
ui(new Ui::MainWindow)
{
ui->setupUi(this);
debugStream = new Q_DebugStream(std::cout, ui->logWindow); //Redirect Console output to QTextEdit
Q_DebugStream::registerQDebugMessageHandler(); //Redirect qDebug() output to QTextEdit
deviceSettings = new QSettings("./device_config.ini", QSettings::IniFormat);
theHW = new HW;
theDisplay = new DisplayServer;
theKeithley = new keithley_thr;
theStepper = new Stepper;
connect(&timer, QTimer::timeout, this, on_timer);
connect(theKeithley, keithley_thr::esig_newCurrentReadout, this, MainWindow::on_newCurrentReadout);
}
MainWindow::~MainWindow()
{
delete ui;
delete deviceSettings;
delete theHW;
delete theDisplay;
delete theKeithley;
}
//***************** Initialization ******************
void MainWindow::showEvent(QShowEvent * event)
{
if (!event->spontaneous())
{
status1.setReadOnly(true);
statusBar()->addWidget(&status1,2);
statusKeithley.setReadOnly(true);
statusBar()->addWidget(&statusKeithley,1);
statusKeithley.setText("Keithley disconnected");
std::cout << "Hello, World!" << std::endl;
std::cout << "Everyone likes log windows!" << std::endl;
log_separator();
timer.start(100);
setupDeviceList();
setupHardware();
}
QMainWindow::showEvent(event);
}
void MainWindow::closeEvent(QCloseEvent * event)
{
stopDisplay();
theKeithley->disconnect();
QMainWindow::closeEvent(event);
}
//******************** Debug window *************************
//put horizontal line
void MainWindow::log_separator()
{
std::cout << "~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~" << std::endl;
}
//******************** Helpers *************************
void MainWindow::setupHardware()
{
qInfo("Setting up hardware...");
DeviceConfig dc;
unsigned char ip[4];
top(deviceSettings);
deviceSettings->beginGroup("Global");
int nr_devices = deviceSettings->value("NrDevices").toInt();
ip2num(deviceSettings->value("HostIp").toString(), ip);
for (int i = 0; i < 4; i++)
dc.own_ip[i] = ip[i];
dc.eth_bunch = 1; //must be left as is for v2
dc.dma_bunch = 1; //must be left as is for v2
top(deviceSettings);
deviceSettings->beginGroup("Trigger");
int period_v1 = deviceSettings->value("Period").toInt();
int tint_v1 = deviceSettings->value("Tint").toInt();
int gain_v1 = deviceSettings->value("Gain").toInt();
int period_v2 = deviceSettings->value("Period_v2").toInt();
int tint_v2 = deviceSettings->value("Tint_v2").toInt();
int gain_v2 = deviceSettings->value("Gain_v2").toInt();
for (int dev_nr = 0; dev_nr < nr_devices; dev_nr++)
{
top(deviceSettings);
QString group_label = QString("Device%1").arg(dev_nr);
deviceSettings->beginGroup(group_label);
dc.device_id = dev_nr;
dc.hardware_ver = deviceSettings->value("HardwareVer").toInt();
ip2num(deviceSettings->value("IP").toString(), ip);
for (int i = 0; i < 4; i++)
dc.device_ip[i] = ip[i];
dc.master = deviceSettings->value("Master").toInt();
dc.plane = deviceSettings->value("Plane").toInt();
dc.position = deviceSettings->value("Position").toInt();
dc.nr_sensors = deviceSettings->value("Sensors").toInt();
dc.master_delay = deviceSettings->value("MasterDelay").toInt();
dc.slave_delay = deviceSettings->value("SlaveDelay").toInt();
switch (dc.hardware_ver)
{
case 1:
dc.period = period_v1;
dc.tint = tint_v1;
dc.gain = gain_v1;
break;
case 2:
dc.period = period_v2;
dc.tint = tint_v2;
dc.gain = gain_v2;
break;
default:
qCritical("Unsupported hardware version!");
break;
}
theHW->configureDevice(dev_nr, dc); //configure the device and an entry in base address table in the event builder
}
//theDisplay.setup(&theHW);
}
void MainWindow::setupDeviceList()
{
qInfo("Setting up device list...");
ui->pushRun->setEnabled(false);
theHW->removeDevices();
top(deviceSettings);
deviceSettings->beginGroup("Global");
theHW->addDevices(deviceSettings->value("NrDevices", (int)1).toInt());
}
void MainWindow::run()
{
if (running)
stop();
theHW->run();
ui->pushRun->setText("Stop!");
running = 1;
}
void MainWindow::stop()
{
if (!running)
return;
theHW->stop();
ui->pushRun->setText("Run!");
running = 0;
}
void MainWindow::startLogging()
{
if (logging)
stopLogging();
QString filename = QFileDialog::getSaveFileName(this, "Select file for saving data", "", tr("Binary log files (*.da2)"));
if (filename.length())
{
//Make copy of current settings
QString ini_filename = filename/*.left(filename.lastIndexOf(QString(".")))*/ + QString(".ini");
QSettings* settings_copy = new QSettings(ini_filename,QSettings::IniFormat);
copyQSettings (deviceSettings, settings_copy);
settings_copy->sync();
delete settings_copy;
//Start logging
theHW->eventBuilder.startLogging(filename);
logging = 1;
ui->pushLogging->setText("Stop logging!");
}
}
void MainWindow::stopLogging()
{
theHW->eventBuilder.stopLogging();
logging = 0;
ui->pushLogging->setText("Start logging!");
}
void MainWindow::startDisplay()
{
ui->pushDisplay->setText("Hide display!");
theDisplay->setup(theHW);
theDisplay->show();
}
void MainWindow::stopDisplay()
{
ui->pushDisplay->setText("Show display!");
theDisplay->hide();
}
//******************** Slots *************************
void MainWindow::on_timer()
{
status1.setText(theHW->report());
if (theDisplay->isActive())
theDisplay->plot();
}
void MainWindow::on_pushLogSettings_pressed()
{
DialogLogSettings dlg;
dlg.displayMask = debugStream->displayMask;
dlg.detailsMask = debugStream->detailsMask;
if (dlg.exec() == QDialog::Accepted)
{
debugStream->displayMask = dlg.displayMask;
debugStream->detailsMask = dlg.detailsMask;
std::cout << "(logger settings changed)" << std::endl;
}
}
void MainWindow::on_actionConnect_triggered()
{
stop();
theHW->connectDevices();
ui->pushRun->setEnabled(true);
}
void MainWindow::on_actionDisconnect_triggered()
{
stop();
theHW->disconnectDevices();
ui->pushRun->setEnabled(false);
}
void MainWindow::on_actionHost_IP_triggered()
{
DialogHostIp dlg;
dlg.deviceSettings = deviceSettings;
if (dlg.exec() == QDialog::Accepted)
{
stop();
setupHardware();
}
}
void MainWindow::on_actionTrigger_config_triggered()
{
DialogTriggerSettings dlg;
dlg.deviceSettings = deviceSettings;
if (dlg.exec() == QDialog::Accepted)
{
stop();
setupHardware();
}
}
void MainWindow::on_actionDevices_triggered()
{
DialogDevices dlg;
dlg.deviceSettings = deviceSettings;
if (dlg.exec() == QDialog::Accepted)
{
stop();
if (theDisplay->isActive())
stopDisplay();
setupDeviceList();
setupHardware();
}
}
void MainWindow::on_pushRun_pressed()
{
if (!running)
run();
else
stop();
}
void MainWindow::on_pushLogging_pressed()
{
if (!logging)
startLogging();
else
stopLogging();
}
void MainWindow::on_pushDisplay_pressed()
{
if (theDisplay->isActive())
stopDisplay();
else
startDisplay();
}
void MainWindow::on_actionLinearity_test_triggered()
{
if (!theKeithley->isOpen)
{
qWarning("Keithley not connected! Aborting linearity test!");
return;
}
if (!running)
{
qWarning("Run is stopped! Aborting linearity test!");
return;
}
DialogLinearity dlg;
dlg.theHW = theHW;
dlg.theKeithley = theKeithley;
dlg.exec();
}
void MainWindow::on_actionIntegration_time_scan_triggered()
{
/*if (!theKeithley->isOpen)
{
qWarning("Keithley not connected! Aborting integration time scan!");
return;
}*/
if (!ui->pushRun->isEnabled())
{
qWarning("Run cannot be started! Aborting integration time scan!");
return;
}
int was_running = running;
stop();
DialogTiScan dlg;
dlg.theHW = theHW;
dlg.theKeithley = theKeithley;
dlg.exec();
//recover previous state
setupHardware();
if (was_running)
run();
}
void MainWindow::on_actionProfile_viewer_triggered()
{
if (!running)
{
qWarning("Run is stopped! Aborting profile viewer run!");
return;
}
DialogProfiler dlg;
dlg.theHW = theHW;
dlg.theKeithley = theKeithley;
dlg.exec();
}
void MainWindow::on_actionBeta_Scanner_triggered()
{
if (!running)
{
qWarning("Run is stopped! Aborting beta scanner run!");
return;
}
if (!theStepper->isOpen)
{
qWarning("Stepper controller not connected! Aborting beta scanner run!");
return;
}
if (theHW->eventBuilder.isLogging())
{
qWarning("Data logging active! No raw data logging for the scan will be possible!");
}
DialogBeta dlg;
dlg.theHW = theHW;
dlg.theStepper = theStepper;
dlg.deviceSettings = deviceSettings;
dlg.exec();
}
//************** Keithley support *******************
//Qt5
/*void MainWindow::on_newCurrentReadout(const double currentReadout)
{
QString text;
text.sprintf("I=%1.8f nA", 1e+9*currentReadout);
statusKeithley.setText(text);
}*/
//Qt6
void MainWindow::on_newCurrentReadout(const double currentReadout)
{
QString text = QString("I=%1 nA").arg(1e+9 * currentReadout, 0, 'f', 8);
statusKeithley.setText(text);
}
void MainWindow::on_actionConnect_Keithley_triggered()
{
if (theKeithley->connect())
{
qInfo(qPrintable(QString("Keithley connected at port %1").arg(theKeithley->portName)));
}
else
{
qInfo("Keithley connection failed!");
}
}
void MainWindow::on_actionDisconnect_Keithley_triggered()
{
theKeithley->disconnect();
qInfo("Keithley disconnected.");
statusKeithley.setText("Keithley disconnected");
}
//***************** Stepper support *********************
void MainWindow::on_actionConnect_Stepper_triggered()
{
theStepper->connect(1);
if (theStepper->isOpen)
{
qInfo(qPrintable(QString("Stepper controller connected at port %1").arg(theStepper->portName)));
}
else
{
qInfo("Stepper connection failed!");
}
}
void MainWindow::on_actionDisconnect_Stepper_triggered()
{
theStepper->disconnect();
qInfo("Stepper controller disconnected.");
}

View File

@ -0,0 +1,96 @@
#ifndef MAINWINDOW_H
#define MAINWINDOW_H
#include <QMainWindow>
#include <QSettings>
#include <QList>
#include <QVector>
#include <QTimer>
#include <QLineEdit>
#include "Q_DebugStream.h"
#include "device.h"
#include "hw.h"
#include "displayserver.h"
#include "keithley_thr.h"
#include "stepper.h"
namespace Ui {
class MainWindow;
}
class MainWindow : public QMainWindow
{
Q_OBJECT
public:
explicit MainWindow(QWidget *parent = 0);
~MainWindow();
Q_DebugStream* debugStream;
HW* theHW;
DisplayServer* theDisplay;
keithley_thr* theKeithley;
Stepper* theStepper;
QSettings* deviceSettings;
int running = 0;
int logging = 0;
void run();
void stop();
void startLogging();
void stopLogging();
void startDisplay();
void stopDisplay();
public slots:
void showEvent(QShowEvent *event);
void closeEvent(QCloseEvent *event);
void on_timer();
void on_newCurrentReadout(const double currentReadout);
protected:
void log_separator();
void setupHardware();
void setupDeviceList();
QTimer timer;
QLineEdit status1;
QLineEdit statusKeithley;
private slots:
void on_pushLogSettings_pressed();
void on_actionConnect_triggered();
void on_actionDisconnect_triggered();
void on_actionHost_IP_triggered();
void on_actionTrigger_config_triggered();
void on_actionDevices_triggered();
void on_pushRun_pressed();
void on_pushLogging_pressed();
void on_pushDisplay_pressed();
void on_actionConnect_Keithley_triggered();
void on_actionDisconnect_Keithley_triggered();
void on_actionLinearity_test_triggered();
void on_actionIntegration_time_scan_triggered();
void on_actionProfile_viewer_triggered();
void on_actionConnect_Stepper_triggered();
void on_actionDisconnect_Stepper_triggered();
void on_actionBeta_Scanner_triggered();
private:
Ui::MainWindow *ui;
};
#endif // MAINWINDOW_H

196
hit2023v2_RMS/mainwindow.ui Normal file
View File

@ -0,0 +1,196 @@
<?xml version="1.0" encoding="UTF-8"?>
<ui version="4.0">
<class>MainWindow</class>
<widget class="QMainWindow" name="MainWindow">
<property name="geometry">
<rect>
<x>0</x>
<y>0</y>
<width>853</width>
<height>601</height>
</rect>
</property>
<property name="windowTitle">
<string>HIT DAQ</string>
</property>
<widget class="QWidget" name="centralWidget">
<widget class="QWidget" name="verticalLayoutWidget">
<property name="geometry">
<rect>
<x>10</x>
<y>10</y>
<width>831</width>
<height>421</height>
</rect>
</property>
<layout class="QVBoxLayout" name="verticalLayout">
<item>
<widget class="QTextBrowser" name="logWindow"/>
</item>
<item>
<layout class="QHBoxLayout" name="horizontalLayout">
<item>
<widget class="QPushButton" name="pushRun">
<property name="enabled">
<bool>false</bool>
</property>
<property name="text">
<string>Run!</string>
</property>
</widget>
</item>
<item>
<widget class="QPushButton" name="pushLogging">
<property name="enabled">
<bool>true</bool>
</property>
<property name="text">
<string>Start logging!</string>
</property>
</widget>
</item>
<item>
<widget class="QPushButton" name="pushDisplay">
<property name="text">
<string>Show display!</string>
</property>
</widget>
</item>
<item>
<spacer name="horizontalSpacer">
<property name="orientation">
<enum>Qt::Horizontal</enum>
</property>
<property name="sizeHint" stdset="0">
<size>
<width>40</width>
<height>20</height>
</size>
</property>
</spacer>
</item>
<item>
<widget class="QPushButton" name="pushLogSettings">
<property name="text">
<string>Log settings...</string>
</property>
</widget>
</item>
</layout>
</item>
</layout>
</widget>
</widget>
<widget class="QMenuBar" name="menuBar">
<property name="geometry">
<rect>
<x>0</x>
<y>0</y>
<width>853</width>
<height>21</height>
</rect>
</property>
<widget class="QMenu" name="menuDevice">
<property name="title">
<string>Device</string>
</property>
<addaction name="actionConnect"/>
<addaction name="actionDisconnect"/>
<addaction name="separator"/>
<addaction name="separator"/>
</widget>
<widget class="QMenu" name="menuSettings">
<property name="title">
<string>Settings</string>
</property>
<addaction name="actionHost_IP"/>
<addaction name="actionDevices"/>
<addaction name="actionTrigger_config"/>
</widget>
<addaction name="menuDevice"/>
<addaction name="menuSettings"/>
</widget>
<widget class="QToolBar" name="mainToolBar">
<attribute name="toolBarArea">
<enum>TopToolBarArea</enum>
</attribute>
<attribute name="toolBarBreak">
<bool>false</bool>
</attribute>
</widget>
<widget class="QStatusBar" name="statusBar"/>
<action name="actionConnect">
<property name="text">
<string>Connect</string>
</property>
</action>
<action name="actionDisconnect">
<property name="text">
<string>Disconnect</string>
</property>
</action>
<action name="actionHost_IP">
<property name="text">
<string>Host IP...</string>
</property>
</action>
<action name="actionDevices">
<property name="text">
<string>Devices...</string>
</property>
</action>
<action name="actionTrigger_config">
<property name="text">
<string>Trigger config...</string>
</property>
</action>
<action name="actionRun">
<property name="text">
<string>Run</string>
</property>
</action>
<action name="actionConnect_Keithley">
<property name="text">
<string>Connect Keithley</string>
</property>
</action>
<action name="actionDisconnect_Keithley">
<property name="text">
<string>Disconnect Keithley</string>
</property>
</action>
<action name="actionLinearity_test">
<property name="text">
<string>Linearity test</string>
</property>
</action>
<action name="actionIntegration_time_scan">
<property name="text">
<string>Integration time scan</string>
</property>
</action>
<action name="actionProfile_viewer">
<property name="text">
<string>Profile viewer</string>
</property>
</action>
<action name="actionConnect_Stepper">
<property name="text">
<string>Connect Stepper</string>
</property>
</action>
<action name="actionDisconnect_Stepper">
<property name="text">
<string>Disconnect Stepper</string>
</property>
</action>
<action name="actionBeta_Scanner">
<property name="text">
<string>Beta Scanner</string>
</property>
</action>
</widget>
<layoutdefault spacing="6" margin="11"/>
<resources/>
<connections/>
</ui>

View File

@ -0,0 +1,121 @@
#include "Q_DebugStream.h"
Q_DebugStream* debugStreamHandle;
Q_DebugStream::Q_DebugStream(std::ostream &stream, QTextBrowser* text_edit) : m_stream(stream)
{
debugStreamHandle = this; //we can use a global variable as only one instance of QDebugStream can be active
displayMask = DS_INFO | DS_WARNING | DS_CRITICAL | DS_FATAL;
// detailsMask = DS_WARNING | DS_CRITICAL | DS_FATAL; //why not info too?
detailsMask = DS_CRITICAL | DS_FATAL;
log_window = text_edit;
m_old_buf = stream.rdbuf();
stream.rdbuf(this);
}
Q_DebugStream::~Q_DebugStream()
{
m_stream.rdbuf(m_old_buf);
}
void Q_DebugStream::registerQDebugMessageHandler()
{
qInstallMessageHandler(myQDebugMessageHandler);
}
void Q_DebugStream::myQDebugMessageHandler(QtMsgType type, const QMessageLogContext &context, const QString &msg)
{
//std::cout << msg.toStdString().c_str();
QByteArray localMsg = msg.toLocal8Bit();
switch (type)
{
case QtDebugMsg:
if (debugStreamHandle->displayMask & DS_DEBUG)
{
std::cout << "[DEBUG] " << localMsg.constData();
if (debugStreamHandle->detailsMask & DS_DEBUG)
std::cout << " (" << context.file << ":" << context.line << ", " << context.function << ")";
std::cout << std::endl;
}
break;
case QtInfoMsg:
if (debugStreamHandle->displayMask & DS_INFO)
{
std::cout << "[INFO] " << localMsg.constData();
if (debugStreamHandle->detailsMask & DS_INFO)
std::cout << " (" << context.file << ":" << context.line << ", " << context.function << ")";
std::cout << std::endl;
}
break;
case QtWarningMsg:
if (debugStreamHandle->displayMask & DS_WARNING)
{
std::cout << "[WARNING] " << localMsg.constData();
if (debugStreamHandle->detailsMask & DS_WARNING)
std::cout << " (" << context.file << ":" << context.line << ", " << context.function << ")";
std::cout << std::endl;
}
break;
case QtCriticalMsg:
if (debugStreamHandle->displayMask & DS_CRITICAL)
{
std::cout << "[CRITICAL] " << localMsg.constData();
if (debugStreamHandle->detailsMask & DS_CRITICAL)
std::cout << " (" << context.file << ":" << context.line << ", " << context.function << ")";
std::cout << std::endl;
}
break;
case QtFatalMsg:
if (debugStreamHandle->displayMask & DS_FATAL)
{
std::cout << "[FATAL] " << localMsg.constData();
if (debugStreamHandle->detailsMask & DS_FATAL)
std::cout << " (" << context.file << ":" << context.line << ", " << context.function << ")";
std::cout << std::endl;
}
//abort();
}
}
//This is called when a std::endl has been inserted into the stream
int Q_DebugStream::overflow(int_type v)
{
if (v == '\n')
{
log_window->append("");
}
return v;
}
std::streamsize Q_DebugStream::xsputn(const char *p, std::streamsize n)
{
QString str(p);
str = str.left(n);
if (str.size() == 0)
return 0; //don't print empty strings (i.e. don't put newline)
if(str.contains("\n"))
{
QStringList strSplitted = str.split("\n");
//log_window->moveCursor (QTextCursor::End);
//log_window->insertPlainText (strSplitted.at(0)); //Index 0 is still on the same old line
for(int i = 0; i < strSplitted.size(); i++)
{
log_window->moveCursor(QTextCursor::End);
log_window->insertPlainText(strSplitted.at(i));
log_window->moveCursor(QTextCursor::End);
}
}
else
{
//log_window->moveCursor (QTextCursor::End);
//log_window->insertPlainText (str);
log_window->moveCursor(QTextCursor::End);
log_window->insertPlainText(str);
log_window->moveCursor(QTextCursor::End);
}
return n;
}

35529
hit2023v2_RMS/qcustomplot.cpp Normal file

File diff suppressed because it is too large Load Diff

7774
hit2023v2_RMS/qcustomplot.h Normal file

File diff suppressed because it is too large Load Diff

View File

@ -0,0 +1,51 @@
[Global]
NrDevices=2
HostIp=10.0.7.1
[Device0]
IP=10.0.7.17
HardwareVer=2
Plane=0
Position=0
Sensors=5
Master=1
MasterDelay=61
SlaveDelay=34
[Device1]
IP=10.0.7.18
HardwareVer=2
Plane=1
Position=0
Sensors=5
Master=0
MasterDelay=7
SlaveDelay=1
[Trigger]
Period=8999
Tint=8466
Gain=1
Period_v2=2501
Tint_v2=335
Gain_v2=1
[Device2]
IP=10.0.7.3
HardwareVer=1
Plane=2
Position=0
Sensors=2
Master=0
MasterDelay=7
SlaveDelay=1
[Device3]
IP=10.0.7.6
HardwareVer=1
Plane=3
Position=0
Sensors=2
Master=0
MasterDelay=7
SlaveDelay=1

Binary file not shown.

Binary file not shown.

Binary file not shown.

View File

@ -0,0 +1,762 @@
/*Copyright (c) DevSec Studio. All rights reserved.
MIT License
Permission is hereby granted, free of charge, to any person obtaining a copy
of this software and associated documentation files (the "Software"), to deal
in the Software without restriction, including without limitation the rights
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
copies of the Software, and to permit persons to whom the Software is
furnished to do so, subject to the following conditions:
The above copyright notice and this permission notice shall be included in all
copies or substantial portions of the Software.
THE SOFTWARE IS PROVIDED *AS IS*, WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
*/
/*-----QWidget-----*/
QWidget
{
background-color: #aaaaaa;
color: #000;
}
/*-----QLabel-----*/
QLabel
{
background-color: transparent;
color: #000;
}
/*-----QMenuBar-----*/
QMenuBar
{
background-color: #aaaaaa;
border : none;
}
QMenuBar::item
{
background-color: transparent;
}
QMenuBar::item:selected
{
background-color: #303030;
color: #fff;
}
QMenuBar::item:pressed
{
background-color: #1c1c1c;
color: #fff;
}
/*-----QMenu-----*/
QMenu
{
background-color: #1c1c1c;
border: 1px solid transparent;
border-radius: 10px;
color: #fff;
opacity: 20;
margin: 4px;
}
QMenu::item
{
padding: 2px 25px 2px 20px;
background-color: #1c1c1c;
border-radius: 10px;
}
QMenu::item:selected
{
color: #000;
padding: 2px 25px 2px 20px;
background-color: qlineargradient(spread:pad, x1:0.494, y1:0, x2:0.492, y2:1, stop:0 rgba(111, 159, 215, 255), stop:1 rgba(72, 100, 138, 255));
border-radius: 2px;
border: 1px solid rgb(28, 28, 28);
}
QMenu::separator
{
height: 1px;
background: darkgray;
margin : 3px;
}
QMenu::indicator
{
width: 13px;
height: 13px;
}
/*-----QToolBar-----*/
QToolBar
{
background-color: #aaaaaa;
border: none;
padding: 2px;
}
QToolBar::handle
{
width: 10px;
margin: 4px 2px;
}
QToolBar::separator
{
width: 1px;
margin: 0px 4px;
background-color: rgba(0,0,0);
}
/*-----QDialog-----*/
QDialog
{
background-color: #1c1c1c;
border: 1px solid #000;
border-radius: 1px;
color: #fff;
opacity: 20;
}
/*-----QPlainTextEdit-----*/
QPlainTextEdit
{
color: black;
background-color: #fff;
border: 1px solid darkgray;
border-top: none;
border-radius : 2px;
}
/*-----QTabBar-----*/
QTabBar
{
background-color: qlineargradient(spread:repeat, x1:1, y1:0, x2:1, y2:1, stop:0 rgba(102, 102, 102, 255),stop:1 rgba(85, 85, 85, 255));
margin-top:0px;
border: 1px solid gray;
}
QTabBar::tear
{
width: 10px;
border: none;
}
QTabWidget::tab-bar
{
border:none;
left: 0px;
}
QTabBar::tab
{
font: 7pt "Verdana";
font: bold;
color: #fff;
padding-left: 15px;
padding-right: 15px;
height: 25px;
}
QTabWidget::pane
{
border: 1px solid rgb(71, 71, 71);
margin-top: 0px;
}
QTabBar::tab:!selected
{
color: #b1b1b1;
border: 1px solid gray;
background-color: qlineargradient(spread:pad, x1:1, y1:0, x2:1, y2:1, stop:0 rgba(101, 101, 101, 255),stop:1 rgba(66, 66, 66, 255));
}
QTabBar::tab:selected
{
background-color: qlineargradient(spread:pad, x1:1, y1:0, x2:1, y2:1, stop:0 rgba(197, 197, 197, 255),stop:1 rgba(154, 154, 154, 255));
border: 1px solid #414141;
color: #000;
}
QTabBar::tab:!selected:hover
{
color: #fff;
}
/*-----QPushButton-----*/
QPushButton
{
color: #000;
border: 1px solid #000;
border-radius: 4px;
background-color: qlineargradient(spread:pad, x1:0.494, y1:0, x2:0.492, y2:1, stop:0 rgba(97, 147, 237, 255), stop:1 rgba(78, 119, 191, 255));
}
QPushButton:hover
{
color: #000;
border: 1px solid #000;
border-radius: 4px;
background-color: qlineargradient(spread:pad, x1:0.494, y1:0, x2:0.492, y2:1, stop:0 rgba(86, 131, 212, 255), stop:1 rgba(70, 107, 173, 255));
font: bold;
}
QPushButton:pressed
{
color: #000;
border: 1px solid #000;
border-radius: 4px;
background-color: qlineargradient(spread:pad, x1:0.494, y1:0, x2:0.492, y2:1, stop:0 rgba(74, 113, 182, 255), stop:1 rgba(65, 99, 159, 255));
font: bold;
}
/*-----QToolButton-----*/
QToolButton
{
background-color: qlineargradient(spread:pad, x1:1, y1:0, x2:1, y2:1, stop:0 rgba(197, 197, 197, 255),stop:1 rgba(154, 154, 154, 255));
color: #000;
border: 1px solid #414141;
border-radius: 2px;
padding: 2px;
}
QToolButton:hover
{
background-color: qlineargradient(spread:pad, x1:1, y1:0, x2:1, y2:1, stop:0 rgba(214, 214, 214, 255),stop:1 rgba(198, 198, 198, 255));
}
QToolButton:pressed
{
background-color: qlineargradient(spread:pad, x1:1, y1:0, x2:1, y2:1, stop:0 rgba(101, 101, 101, 255),stop:1 rgba(66, 66, 66, 255));
}
QToolButton:checked
{
background-color: qlineargradient(spread:pad, x1:1, y1:0, x2:1, y2:1, stop:0 rgba(101, 101, 101, 255),stop:1 rgba(66, 66, 66, 255));
}
/*-----QComboBox-----*/
QComboBox
{
color : #fff;
background-color: #262626;
border : 1px solid rgb(28, 28, 28);
border-radius: 0px;
padding: 5px;
margin-right: 5px;
margin-left: 5px;
max-height : 10px;
min-width : 72px;
selection-background-color: rgb(85, 85, 255);
}
QComboBox::drop-down
{
background-color: rgb(98, 98, 98);
subcontrol-origin: padding;
subcontrol-position: top right;
width: 15px;
border-left-width: 1px;
border-left-color: darkgray;
border-left-style: solid;
border-top-right-radius: 3px;
border-bottom-right-radius: 3px;
}
QComboBox::down-arrow
{
image: url(:/Icons/resources/icons/downarrow.png);
}
QComboBox QWidget
{
color : #fff;
background-color: #262626;
border : 1px solid rgb(28, 28, 28);
}
/*-----QDockWidget-----*/
QDockWidget
{
color : lightgray;
border-top: 0px solid #262626;;
border-left: 1px solid #262626;;
border-right: 1px solid #262626;;
border-bottom: 1px solid #262626;;
background-color: rgb(49, 49, 49);
}
QDockWidget::title
{
background-color: rgb(58, 58, 58);
border: 1px solid rgb(58, 58, 58);
border-top-right-radius: 3px;
border-top-left-radius: 3px;
border-bottom-right-radius: 0px;
border-bottom-left-radius: 0px;
text-align: left;
margin-top:1px;
}
QDockWidget::close-button
{
max-width: 14px;
max-height: 14px;
margin-top:1px;
}
QDockWidget::float-button
{
max-width: 14px;
max-height: 14px;
margin-top:1px;
}
QDockWidget::close-button:hover
{
border: none;
background-color: none;
}
QDockWidget::float-button:hover
{
border: none;
background-color: none;
}
QDockWidget::separator
{
width: 1px;
margin: 6px 4px;
background-color: rgba(0,0,0);
}
/*-----QTreeWidget-----*/
QTreeWidget
{
show-decoration-selected: 0;
selection-background-color: transparent; /* Used on Mac */
selection-color: #fff; /* Used on Mac */
background-color: #262626;
padding-top : 5px;
border: none;
color: #fff;
font: 8pt;
}
QTreeView::item:selected
{
color:#000;
background-color: qlineargradient(spread:pad, x1:0.494, y1:0, x2:0.492, y2:1, stop:0 rgba(111, 159, 215, 255), stop:1 rgba(72, 100, 138, 255));
border-radius: 0px;
}
QTreeView::item:!selected:hover
{
color:#fff;
background-color: rgb(86, 100, 123);
border: none;
border-radius: 0px;
}
QTreeView::branch:has-children:!has-siblings:closed,
QTreeView::branch:closed:has-children:has-siblings
{
image: url(://tree-closed.png);
}
QTreeView::branch:open:has-children:!has-siblings,
QTreeView::branch:open:has-children:has-siblings
{
image: url(://tree-open.png);
}
/*-----QListView-----*/
QListView
{
border : none;
background-color: #262626;
color: white;
show-decoration-selected: 1; /* make the selection span the entire width of the view */
outline: 0;
border: 1px solid gray;
}
QListView::disabled
{
background-color: #656565;
color: #1b1b1b;
border: 1px solid #656565;
}
QListView::item
{
padding: 1px;
}
QListView::item:alternate
{
background-color: #4a4b4d;
}
QListView::item:selected
{
border: 1px solid #6a6ea9;
border: none;
color: #000;
}
QListView::item:selected:!active
{
background-color: qlineargradient(spread:pad, x1:0.494, y1:0, x2:0.492, y2:1, stop:0 rgba(111, 159, 215, 255), stop:1 rgba(72, 100, 138, 255));
border: none;
color: #000;
}
QListView::item:selected:active
{
background-color: qlineargradient(spread:pad, x1:0.494, y1:0, x2:0.492, y2:1, stop:0 rgba(111, 159, 215, 255), stop:1 rgba(72, 100, 138, 255));
border: none;
color: #000;
}
QListView::item:hover {
background-color: rgb(86, 100, 123);
border: none;
color: white;
}
/*-----QScrollBar-----*/
QScrollBar:horizontal
{
background-color: transparent;
height: 17px;
margin-bottom: 1px;
}
QScrollBar::handle:horizontal
{
border-radius : 5px;
background-color: qlineargradient(spread:pad, x1:0.494, y1:0, x2:0.492, y2:1, stop:0 rgba(97, 147, 237, 255), stop:1 rgba(78, 119, 191, 255));
min-width: 50px;
height : 10px;
}
QScrollBar::handle:horizontal:pressed
{
background-color: qlineargradient(spread:pad, x1:0.494, y1:0, x2:0.492, y2:1, stop:0 rgba(77, 127, 217, 255), stop:1 rgba(58, 99, 171, 255));
border-radius : 5px;
}
QScrollBar::add-line:horizontal
{
border: none;
background-color: transparent;
width: 0px;
}
QScrollBar::add-line:horizontal:hover
{
background-color: transparent;
}
QScrollBar::add-line:horizontal:pressed
{
background-color: transparent;
}
QScrollBar::sub-line:horizontal
{
border: none;
background-color: transparent;
border-radius :0px;
width: 0px;
}
QScrollBar::sub-line:horizontal:hover
{
background-color: transprarent;
}
QScrollBar::sub-line:horizontal:pressed
{
background-color: transparent;
}
QScrollBar:left-arrow:horizontal
{
width: 0px;
height: 0px;
background: transparent;
}
QScrollBar::right-arrow:horizontal
{
width: 0px;
height: 0px;
background: transparent;
}
QScrollBar::add-page:horizontal, QScrollBar::sub-page:horizontal
{
background-color: transparent;
}
QScrollBar:vertical
{
background-color: transparent;
border : none;
width: 10px;
}
QScrollBar::handle:vertical
{
background-color: qlineargradient(spread:pad, x1:0.494, y1:0, x2:0.492, y2:1, stop:0 rgba(97, 147, 237, 255), stop:1 rgba(78, 119, 191, 255));
border-radius : 5px;
min-height: 80px;
width : 10px;
margin: 0px;
}
QScrollBar::handle:vertical:pressed
{
border-radius : 5px;
background-color: qlineargradient(spread:pad, x1:0.494, y1:0, x2:0.492, y2:1, stop:0 rgba(77, 127, 217, 255), stop:1 rgba(58, 99, 171, 255));
}
QScrollBar::add-line:vertical
{
border: none;
background: transparent;
height: 0px;
subcontrol-position: none;
subcontrol-origin: none;
}
QScrollBar::add-line:vertical:hover
{
background-color: transparent;
}
QScrollBar::add-line:vertical:pressed
{
background-color: transparent;
}
QScrollBar::sub-line:vertical
{
border: none;
background: transparent;
height: 0px;
}
QScrollBar::sub-line:vertical:hover
{
background-color: transparent;
}
QScrollBar::sub-line:vertical:pressed
{
background-color: transparent;
}
QScrollBar::up-arrow:vertical
{
width: 0px;
height: 0px;
background: transparent;
}
QScrollBar::down-arrow:vertical
{
width: 0px;
height: 0px;
background: transparent;
}
QScrollBar::add-page:vertical, QScrollBar::sub-page:vertical
{
background-color: transparent;
}
/*-----QStatusBar-----*/
QStatusBar
{
color: #000;
margin : 0px;
padding : -5px;
background-color: rgb(170, 170, 170);
}
QStatusBar::item
{
background-color: transparent;
color: #000;
}

View File

@ -0,0 +1,244 @@
/*Copyright (c) DevSec Studio. All rights reserved.
MIT License
Permission is hereby granted, free of charge, to any person obtaining a copy
of this software and associated documentation files (the "Software"), to deal
in the Software without restriction, including without limitation the rights
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
copies of the Software, and to permit persons to whom the Software is
furnished to do so, subject to the following conditions:
The above copyright notice and this permission notice shall be included in all
copies or substantial portions of the Software.
THE SOFTWARE IS PROVIDED *AS IS*, WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
*/
/*-----QWidget-----*/
QWidget
{
color: #aaa;
background-color: #323232;
}
/*-----QLabel-----*/
QLabel
{
background-color: transparent;
color: #fff;
}
/*-----QMenuBar-----*/
QMenuBar
{
background-color: #323232;
}
QMenuBar::item
{
background: transparent;
}
QMenuBar::item:selected
{
background: #444;
}
QMenuBar::item:pressed
{
border: 1px solid #000;
background-color: #444;
margin-bottom:-1px;
padding-bottom:1px;
}
/*-----QMenu-----*/
QMenu
{
background-color: #444;
border: 1px solid #222;
padding: 4px;
padding-right: 0px;
}
QMenu::item
{
background-color: transparent;
padding: 2px 20px 2px 20px;
}
QMenu::item:disabled
{
color: #555;
background-color: transparent;
padding: 2px 20px 2px 20px;
}
QMenu::item:selected
{
background-color: #55aaff;
color: #fff;
}
/*-----QToolTip-----*/
QToolTip
{
border: 1px solid #222;
background-color: #333;
color: #aaa;
}
/*-----QToolButton-----*/
QToolButton
{
color: #b1b1b1;
background-color: QLinearGradient( x1: 0, y1: 0, x2: 0, y2: 1, stop: 0 #565656, stop: 0.1 #525252, stop: 0.5 #4e4e4e, stop: 0.9 #4a4a4a, stop: 1 #464646);
border-width: 1px;
border-color: #1e1e1e;
border-style: solid;
margin-right: 2px;
padding: 3px;
}
QToolButton:pressed
{
background-color: QLinearGradient( x1: 0, y1: 0, x2: 0, y2: 1, stop: 0 #2d2d2d, stop: 0.1 #2b2b2b, stop: 0.5 #292929, stop: 0.9 #282828, stop: 1 #252525);
}
QToolButton:checked
{
background-color: gray;
}
/*-----QLineEdit-----*/
QLineEdit{
background-color: #fff;
color: #000;
selection-color: #fff;
selection-background-color: #507098;
}
/*-----QTreeView-----*/
QTreeView
{
background-color: #434343;
border: 0.5px solid rgba(108,108,108,75);
}
QTreeView::item,
QTreeView::branch
{
background: transparent;
color: #DDD;
}
QTreeView::item:hover,
QTreeView::branch:hover
{
background-color: #55aaff;
color: #DDD;
}
QTreeView::item:selected,
QTreeView::branch:selected
{
background-color: #55aaff;
color: #fff;
}
/*-----QScrollBar-----*/
QScrollBar:horizontal
{
background-color: #333;
height: 8px;
margin: 0px;
padding: 0px;
}
QScrollBar::handle:horizontal
{
border: 1px solid #111;
background-color: #535353;
}
QScrollBar::add-line:horizontal, QScrollBar::sub-line:horizontal,
QScrollBar::add-page:horizontal, QScrollBar::sub-page:horizontal
{
width: 0px;
background-color: transparent;
}
QScrollBar:vertical
{
background-color: #333;
width: 8px;
margin: 0;
}
QScrollBar::handle:vertical
{
border: 1px solid #111;
background-color: #535353;
}
QScrollBar::add-line:vertical, QScrollBar::sub-line:vertical,
QScrollBar::add-page:vertical, QScrollBar::sub-page:vertical
{
height: 0px;
background-color: transparent;
}

View File

@ -0,0 +1,119 @@
/*Copyright (c) DevSec Studio. All rights reserved.
MIT License
Permission is hereby granted, free of charge, to any person obtaining a copy
of this software and associated documentation files (the "Software"), to deal
in the Software without restriction, including without limitation the rights
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
copies of the Software, and to permit persons to whom the Software is
furnished to do so, subject to the following conditions:
The above copyright notice and this permission notice shall be included in all
copies or substantial portions of the Software.
THE SOFTWARE IS PROVIDED *AS IS*, WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
*/
/*-----QWidget-----*/
QWidget
{
background-color: QLinearGradient(x1:0, y1:0, x2:0, y2:1, stop:1 #212121, stop:.4 #343434);
color: #000000;
border-color: #000000;
}
/*-----QLabel-----*/
QLabel
{
background-color: transparent;
color: #fff;
font-size: 14pt;
border-color: #000000;
}
/*-----QToolButton-----*/
QToolButton
{
background-color: qlineargradient(spread:repeat, x1:1, y1:0, x2:1, y2:1, stop:0 rgba(254, 171, 66, 255),stop:1 rgba(255, 153, 0, 255));
color: #000;
font-size: 14pt;
border-radius: 4px;
padding: 10px;
}
QToolButton::pressed
{
background-color: #6b960f;
}
/*-----QTabWidget-----*/
QTabBar::tab
{
font-size: 8pt;
font-weight: bold;
width: 80px;
border: 1px solid #444;
border-bottom-style: none;
border-top-style: none;
background-color: #323232;
padding-top: 3px;
padding-bottom: 2px;
margin-right: -1px;
}
QTabWidget::pane
{
border: 1px solid qlineargradient(spread:repeat, x1:1, y1:0, x2:1, y2:1, stop:0 rgba(254, 171, 66, 255),stop:1 rgba(255, 153, 0, 255));
top: 1px;
}
QTabBar::tab:last
{
margin-right: 0;
}
QTabBar::tab:first:!selected
{
margin-left: 0px;
}
QTabBar::tab:!selected
{
color: #fff;
border-bottom-style: solid;
margin-top: 3px;
background-color: QLinearGradient(x1:0, y1:0, x2:0, y2:1, stop:1 #212121, stop:.4 #343434);
}
QTabBar::tab:selected
{
background-color: qlineargradient(spread:repeat, x1:1, y1:0, x2:1, y2:1, stop:0 rgba(254, 171, 66, 255),stop:1 rgba(255, 153, 0, 255));
color: #000;
margin-bottom: 0px;
}
QTabBar::tab:!selected:hover
{
background-color: QLinearGradient(x1:0, y1:0, x2:0, y2:1, stop:1 #212121, stop:0.4 #343434, stop:0.2 #343434, stop:0.1 #ffaa00);
}

View File

@ -0,0 +1,434 @@
/*Copyright (c) DevSec Studio. All rights reserved.
MIT License
Permission is hereby granted, free of charge, to any person obtaining a copy
of this software and associated documentation files (the "Software"), to deal
in the Software without restriction, including without limitation the rights
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
copies of the Software, and to permit persons to whom the Software is
furnished to do so, subject to the following conditions:
The above copyright notice and this permission notice shall be included in all
copies or substantial portions of the Software.
THE SOFTWARE IS PROVIDED *AS IS*, WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
*/
QWidget{
background-color: #e6e7eb;
}
/*-----QLabel-----*/
QLabel
{
background-color: transparent;
color: #000000;
border-color: #000000;
}
/*-----QMenuBar-----*/
QMenuBar
{
background-color: #d6e1f0;
color: #000;
}
QMenuBar::disabled
{
background-color: #404040;
color: #656565;
border-color: #051a39;
}
QMenuBar::item
{
background-color: transparent;
}
QMenuBar::item:selected
{
background-color: #a7dfff;
color: #000;
}
QMenuBar::item:pressed
{
background-color: #98daff;
border: 1px solid #000;
margin-bottom: -1px;
padding-bottom: 1px;
}
/*-----QMenu-----*/
QMenu
{
background-color: #beccde;
border: 1px solid;
color: #000;
}
QMenu QWidget{
background-color: transparent;
}
QMenu::separator
{
height: 1px;
background-color: #6d8eff;
color: #ffffff;
padding-left: 4px;
margin-left: 10px;
margin-right: 5px;
}
QMenu::item
{
min-width : 150px;
padding: 3px 20px 3px 20px;
}
QMenu::item:selected
{
background-color: #d6e1f0;
color: #000;
}
QMenu::item:disabled
{
color: #262626;
}
/*-----QToolBar-----*/
QToolBar
{
background-color: #d6e1f0;
color: #ffffff;
border-color: #000000;
}
/*-----QToolButton-----*/
QToolButton
{
background-color: #d6e1f0;
color: #ffffff;
border-color: #000000;
}
QToolButton::hover
{
background-color: #f0f5f3;
color: #ffffff;
border: none;
}
QToolButton::checked:hover
{
background-color: #5cc4ff;
color: #ffffff;
border: none;
}
QToolButton::pressed
{
background-color: #5cc4ff;
color: #ffffff;
border: none;
}
QToolButton::checked
{
background-color: #5cc4ff;
color: #ffffff;
border: none;
show-decoration-selected: 0;
outline: 0;
}
/*-----QToolTip-----*/
QToolTip
{
border: 1px solid black;
background-color: #b2c1d5;
border-radius: 0px;
color: #000;
}
/*-----QLineEdit-----*/
QLineEdit{
background-color: #fefffc;
color: #000;
}
/*-----QTextEdit-----*/
QTableWidget{
background-color: #fff;
padding: 10px;
}
/*-----QComboBox-----*/
QComboBox
{
background-color: #fefefe;
border: 1px solid #1e1e1e;
border-radius: 0px;
padding-left: 6px;
color: #000;
height: 20px;
}
QComboBox:on
{
background-color: #fefefe;
}
QComboBox QAbstractItemView
{
background-color: #dcdcdf;
color: #000;
border: 1px solid black;
selection-background-color: #217346;
selection-color: #dcdcdf;
outline: 0;
}
QComboBox::drop-down
{
subcontrol-origin: padding;
subcontrol-position: top right;
width: 15px;
border-left-width: 0px;
border-left-color: darkgray;
border-left-style: solid;
border-top-right-radius: 3px;
border-bottom-right-radius: 3px;
}
QComboBox::down-arrow
{
image: url("./ressources/down_arrow.png");
width:8px;
height:8px;
}
/*-----QSpinBox-----*/
QSpinBox
{
background-color: #fefefe;
border-width: 1px;
border-color: #1e1e1e;
border-style: solid;
color: #000;
padding: 2px;
selection-background-color: #4e4e8f;
}
QSpinBox::up-button,
QSpinBox::down-button
{
background-color: #fefefe;
}
QSpinBox::up-button:hover,
QSpinBox::down-button:hover
{
background-color: #fefefe;
}
QSpinBox::up-button:pressed,
QSpinBox::down-button:pressed
{
background-color: #ebebeb;
border: 1px solid #ebebeb;
}
QSpinBox::down-arrow
{
image: url("./ressources/down_arrow.png");
width: 7px;
}
QSpinBox::up-arrow
{
image: url("./ressources/up_arrow.png");
width: 7px;
}
/*-----QSlider-----*/
QSlider
{
background-color: transparent;
padding: 2px;
}
QSlider::groove:horizontal
{
subcontrol-origin: content;
background-color: transparent;
height: 15px;
}
QSlider::handle:horizontal
{
background-color: #4ebfff;
width: 15px;
border-radius: 7px;
}
QSlider::sub-page:horizontal
{
background-color: #999;
margin: 5px;
border-radius: 5px;
}
QSlider::add-page:horizontal
{
background-color: #666;
margin: 5px;
border-radius: 5px;
}
/*-----QScrollBar-----*/
QScrollBar:horizontal
{
background-color: #beccde;
border: 1px solid darkgray;
height: 15px;
}
QScrollBar::handle:horizontal
{
border: 1px solid gray;
min-width: 100px;
background-color: #e6edf6;
}
QScrollBar::add-line:horizontal,
QScrollBar::sub-line:horizontal,
QScrollBar::add-page:horizontal,
QScrollBar::sub-page:horizontal
{
width: 0px;
background-color: transparent;
}
QScrollBar:vertical
{
background-color: #beccde;
border: 1px solid darkgray;
width: 14px;
}
QScrollBar::handle:vertical
{
border: 1px solid gray;
min-height: 100px;
background-color: #e6edf6;
}
QScrollBar::add-line:vertical,
QScrollBar::sub-line:vertical,
QScrollBar::add-page:vertical,
QScrollBar::sub-page:vertical
{
height: 0px;
background-color: transparent;
}
/*-----QStatusBar-----*/
QStatusBar
{
background-color: #d6e1f0;
color: #000000;
border-color: #000000;
}

View File

@ -0,0 +1,461 @@
/*Copyright (c) DevSec Studio. All rights reserved.
MIT License
Permission is hereby granted, free of charge, to any person obtaining a copy
of this software and associated documentation files (the "Software"), to deal
in the Software without restriction, including without limitation the rights
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
copies of the Software, and to permit persons to whom the Software is
furnished to do so, subject to the following conditions:
The above copyright notice and this permission notice shall be included in all
copies or substantial portions of the Software.
THE SOFTWARE IS PROVIDED *AS IS*, WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
*/
/*-----QWidget-----*/
QWidget
{
background-color: #fff;
color: red;
}
/*-----QLabel-----*/
QLabel
{
background-color: transparent;
color: #454544;
font-weight: bold;
font-size: 13px;
}
/*-----QPushButton-----*/
QPushButton
{
background-color: #5c55e9;
color: #fff;
font-size: 13px;
font-weight: bold;
border-top-right-radius: 15px;
border-top-left-radius: 0px;
border-bottom-right-radius: 0px;
border-bottom-left-radius: 15px;
padding: 10px;
}
QPushButton::disabled
{
background-color: #5c5c5c;
}
QPushButton::hover
{
background-color: #5564f2;
}
QPushButton::pressed
{
background-color: #3d4ef2;
}
/*-----QCheckBox-----*/
QCheckBox
{
background-color: transparent;
color: #5c55e9;
font-size: 10px;
font-weight: bold;
border: none;
border-radius: 5px;
}
/*-----QCheckBox-----*/
QCheckBox::indicator
{
background-color: #323232;
border: 1px solid darkgray;
width: 12px;
height: 12px;
}
QCheckBox::indicator:checked
{
image:url("./ressources/check.png");
background-color: #5c55e9;
border: 1px solid #5c55e9;
}
QCheckBox::indicator:unchecked:hover
{
border: 1px solid #5c55e9;
}
QCheckBox::disabled
{
color: #656565;
}
QCheckBox::indicator:disabled
{
background-color: #656565;
color: #656565;
border: 1px solid #656565;
}
/*-----QLineEdit-----*/
QLineEdit
{
background-color: #c2c7d5;
color: #2a547f;
border: none;
padding: 5px;
}
/*-----QListView-----*/
QListView
{
background-color: #5c55e9;
color: #fff;
font-size: 14px;
font-weight: bold;
show-decoration-selected: 0;
border-radius: 4px;
padding-left: -15px;
padding-right: -15px;
padding-top: 5px;
}
QListView:disabled
{
background-color: #5c5c5c;
}
QListView::item
{
background-color: #454e5e;
border: none;
padding: 10px;
border-radius: 0px;
padding-left : 10px;
height: 32px;
}
QListView::item:selected
{
color: #000;
background-color: #fff;
}
QListView::item:!selected
{
color:white;
background-color: transparent;
border: none;
padding-left : 10px;
}
QListView::item:!selected:hover
{
color: #fff;
background-color: #5564f2;
border: none;
padding-left : 10px;
}
/*-----QTreeView-----*/
QTreeView
{
background-color: #fff;
show-decoration-selected: 0;
color: #454544;
}
QTreeView:disabled
{
background-color: #242526;
show-decoration-selected: 0;
}
QTreeView::item
{
border-top-color: transparent;
border-bottom-color: transparent;
}
QTreeView::item:hover
{
background-color: #bcbdbb;
color: #000;
}
QTreeView::item:selected
{
background-color: #5c55e9;
color: #fff;
}
QTreeView::item:selected:active
{
background-color: #5c55e9;
color: #fff;
}
QTreeView::item:selected:disabled
{
background-color: #525251;
color: #656565;
}
QTreeView::branch:has-children:!has-siblings:closed,
QTreeView::branch:closed:has-children:has-siblings
{
image: url(://tree-closed.png);
}
QTreeView::branch:open:has-children:!has-siblings,
QTreeView::branch:open:has-children:has-siblings
{
image: url(://tree-open.png);
}
/*-----QTableView & QTableWidget-----*/
QTableView
{
background-color: #fff;
border: 1px solid gray;
color: #454544;
gridline-color: gray;
outline : 0;
}
QTableView::disabled
{
background-color: #242526;
border: 1px solid #32414B;
color: #656565;
gridline-color: #656565;
outline : 0;
}
QTableView::item:hover
{
background-color: #bcbdbb;
color: #000;
}
QTableView::item:selected
{
background-color: #5c55e9;
color: #fff;
}
QTableView::item:selected:disabled
{
background-color: #1a1b1c;
border: 2px solid #525251;
color: #656565;
}
QTableCornerButton::section
{
background-color: #ced5e3;
border: none;
color: #fff;
}
QHeaderView::section
{
color: #2a547f;
border: 0px;
background-color: #ced5e3;
padding: 5px;
}
QHeaderView::section:disabled
{
background-color: #525251;
color: #656565;
}
QHeaderView::section:checked
{
color: #fff;
background-color: #5c55e9;
}
QHeaderView::section:checked:disabled
{
color: #656565;
background-color: #525251;
}
QHeaderView::section::vertical::first,
QHeaderView::section::vertical::only-one
{
border-top: 1px solid #353635;
}
QHeaderView::section::vertical
{
border-top: 1px solid #353635;
}
QHeaderView::section::horizontal::first,
QHeaderView::section::horizontal::only-one
{
border-left: 1px solid #353635;
}
QHeaderView::section::horizontal
{
border-left: 1px solid #353635;
}
/*-----QScrollBar-----*/
QScrollBar:horizontal
{
background-color: transparent;
height: 8px;
margin: 0px;
padding: 0px;
}
QScrollBar::handle:horizontal
{
border: none;
min-width: 100px;
background-color: #7e92b7;
}
QScrollBar::add-line:horizontal,
QScrollBar::sub-line:horizontal,
QScrollBar::add-page:horizontal,
QScrollBar::sub-page:horizontal
{
width: 0px;
background-color: #d8dce6;
}
QScrollBar:vertical
{
background-color: transparent;
width: 8px;
margin: 0;
}
QScrollBar::handle:vertical
{
border: none;
min-height: 100px;
background-color: #7e92b7;
}
QScrollBar::add-line:vertical,
QScrollBar::sub-line:vertical,
QScrollBar::add-page:vertical,
QScrollBar::sub-page:vertical
{
height: 0px;
background-color: #d8dce6;
}

142
hit2023v2_RMS/stepper.cpp Normal file
View File

@ -0,0 +1,142 @@
#include "stepper.h"
Stepper::Stepper(QObject *parent) : QObject(parent)
{
isOpen = 0;
}
Stepper::~Stepper()
{
disconnect();
}
//******** Basic IO *******
int Stepper::command(int command, int type, unsigned int parameter, unsigned int* param_out)
{
//1. Prepare data
unsigned char buffer[9];
buffer[0] = (unsigned char)moduleAddress;
buffer[1] = (unsigned char)command;
buffer[2] = (unsigned char)type;
buffer[3] = 0; //Motor/bank number
for (int i = 0; i < 4; i++)
buffer[4+i] = (unsigned char)(parameter >> (8*(3-i)));
buffer[8] = 0; //checksum
for (int i = 0; i < 8; i++)
buffer[8] += buffer[i]; //calculate checksum
//2. Send data
serialPort.write((const char*)buffer, 9);
serialPort.waitForBytesWritten(500);
//3. Read data
int ptr = 0;
while (1)
{
if (serialPort.read((char*)buffer+ptr,1) <= 0)
{
if (!serialPort.waitForReadyRead(500))
break; //no new data - break
}
else
{
ptr++;
if (ptr >= 9)
break; //buffer full = break
}
}
//4. Parse data
if (ptr < 9)
return STEPPER_ERROR_NOREPLY; //no new data
if (buffer[2] != 100)
return STEPPER_ERROR_CHECKSUM;
if (param_out != NULL)
{
*param_out = ( (unsigned int)buffer[4]<<24 ) |
( (unsigned int)buffer[5]<<16 ) |
( (unsigned int)buffer[6]<<8 ) |
( (unsigned int)buffer[7]);
}
return STEPPER_OK;
}
//******** Commands *********
int Stepper::command_ROL(int speed)
{
return command(2,0,speed);
}
int Stepper::command_ROR(int speed)
{
return command(1,0,speed);
}
int Stepper::command_MST()
{
return command(3,0,0);
}
int Stepper::command_MVP(int ref_type, int position)
{
return command(4, ref_type, position);
}
int Stepper::command_SAP(int parameter_number, int value)
{
return command(5, parameter_number, value);
}
int Stepper::command_GAP(int parameter_number, int* value)
{
return command(6, parameter_number, 0, (unsigned int*)value);
}
//******** Connecting ***********
int Stepper::connect(int address)
{
disconnect(); //just if we were connected
moduleAddress = address;
QList<QSerialPortInfo> list = QSerialPortInfo::availablePorts();
if (list.size() == 0)
return -1; //no serial ports found
for (int port = 0; port < list.size(); port++)
{
serialPort.setPort(list[port]);
serialPort.setBaudRate(9600);
if (serialPort.open(QIODevice::ReadWrite))
{
serialPort.setBaudRate(9600);
if (command_MST() == STEPPER_OK)
{ //gotta our PS!
isOpen = 1;
portName = list[port].portName();
//maybe configure something
command_SAP(STEPPER_SAP_MAXIMUM_SPEED,1000);
break;
}
serialPort.close();
}
}
return isOpen;
}
void Stepper::disconnect()
{
if (!isOpen)
return;
serialPort.close();
isOpen = 0;
}

59
hit2023v2_RMS/stepper.h Normal file
View File

@ -0,0 +1,59 @@
#ifndef STEPPER_H
#define STEPPER_H
#include <QObject>
#include <QtSerialPort/QtSerialPort>
#include <QSerialPortInfo>
#include <QSerialPort>
#define STEPPER_OK 0
#define STEPPER_ERROR_NOREPLY -1
#define STEPPER_ERROR_CHECKSUM -2
#define STEPPER_MVP_ABSOLUTE 0
#define STEPPER_MVP_RELATIVE 1
#define STEPPER_SAP_TARGET_POSITION 0
#define STEPPER_SAP_ACTUAL_POSITION 1
#define STEPPER_SAP_TARGET_SPEED 2
#define STEPPER_SAP_ACTUAL_SPEED 3
#define STEPPER_SAP_MAXIMUM_SPEED 4
#define STEPPER_SAP_MAXIMUM_ACCELERATION 5
#define STEPPER_SAP_MAXIMUM_CURRENT 6
#define STEPPER_SAP_STANDBY_CURRENT 7
#define STEPPER_SAP_RIGHT_SWITCH_DISABLE 12
#define STEPPER_SAP_LEFT_SWITCH_DISABLE 13
#define STEPPER_SAP_MINIMUM_SPEED 130
#define STEPPER_SAP_RAMP_MODE 138
#define STEPPER_SAP_MICROSTEP_RESOLUTION 140 //0(full step) to 6 (/64 microstep)
//there are many others...
class Stepper : public QObject
{
Q_OBJECT
public:
explicit Stepper(QObject *parent = 0);
~Stepper();
int command(int command, int type, unsigned int parameter, unsigned int *param_out = NULL);
int connect(int address);
void disconnect();
int command_ROL(int speed); //rotate left
int command_ROR(int speed); //rotate right
int command_MST(); //motor stop
int command_MVP(int ref_type, int position); //move to position; ref_type: STEPPER_MVP_ABSOLUTE or STEPPER_MVP_RELATIVE
int command_SAP(int parameter_number, int value); //Set axis parameter. See defines.
int command_GAP(int parameter_number, int *value); //Get axis parameter. See defines for SAP.
int moduleAddress;
int isOpen;
QString portName;
QSerialPort serialPort;
signals:
public slots:
protected:
};
#endif // STEPPER_H

View File

@ -0,0 +1,762 @@
/*Copyright (c) DevSec Studio. All rights reserved.
MIT License
Permission is hereby granted, free of charge, to any person obtaining a copy
of this software and associated documentation files (the "Software"), to deal
in the Software without restriction, including without limitation the rights
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
copies of the Software, and to permit persons to whom the Software is
furnished to do so, subject to the following conditions:
The above copyright notice and this permission notice shall be included in all
copies or substantial portions of the Software.
THE SOFTWARE IS PROVIDED *AS IS*, WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
*/
/*-----QWidget-----*/
QWidget
{
background-color: #aaaaaa;
color: #000;
}
/*-----QLabel-----*/
QLabel
{
background-color: transparent;
color: #000;
}
/*-----QMenuBar-----*/
QMenuBar
{
background-color: #aaaaaa;
border : none;
}
QMenuBar::item
{
background-color: transparent;
}
QMenuBar::item:selected
{
background-color: #303030;
color: #fff;
}
QMenuBar::item:pressed
{
background-color: #1c1c1c;
color: #fff;
}
/*-----QMenu-----*/
QMenu
{
background-color: #1c1c1c;
border: 1px solid transparent;
border-radius: 10px;
color: #fff;
opacity: 20;
margin: 4px;
}
QMenu::item
{
padding: 2px 25px 2px 20px;
background-color: #1c1c1c;
border-radius: 10px;
}
QMenu::item:selected
{
color: #000;
padding: 2px 25px 2px 20px;
background-color: qlineargradient(spread:pad, x1:0.494, y1:0, x2:0.492, y2:1, stop:0 rgba(111, 159, 215, 255), stop:1 rgba(72, 100, 138, 255));
border-radius: 2px;
border: 1px solid rgb(28, 28, 28);
}
QMenu::separator
{
height: 1px;
background: darkgray;
margin : 3px;
}
QMenu::indicator
{
width: 13px;
height: 13px;
}
/*-----QToolBar-----*/
QToolBar
{
background-color: #aaaaaa;
border: none;
padding: 2px;
}
QToolBar::handle
{
width: 10px;
margin: 4px 2px;
}
QToolBar::separator
{
width: 1px;
margin: 0px 4px;
background-color: rgba(0,0,0);
}
/*-----QDialog-----*/
QDialog
{
background-color: #1c1c1c;
border: 1px solid #000;
border-radius: 1px;
color: #fff;
opacity: 20;
}
/*-----QPlainTextEdit-----*/
QPlainTextEdit
{
color: black;
background-color: #fff;
border: 1px solid darkgray;
border-top: none;
border-radius : 2px;
}
/*-----QTabBar-----*/
QTabBar
{
background-color: qlineargradient(spread:repeat, x1:1, y1:0, x2:1, y2:1, stop:0 rgba(102, 102, 102, 255),stop:1 rgba(85, 85, 85, 255));
margin-top:0px;
border: 1px solid gray;
}
QTabBar::tear
{
width: 10px;
border: none;
}
QTabWidget::tab-bar
{
border:none;
left: 0px;
}
QTabBar::tab
{
font: 7pt "Verdana";
font: bold;
color: #fff;
padding-left: 15px;
padding-right: 15px;
height: 25px;
}
QTabWidget::pane
{
border: 1px solid rgb(71, 71, 71);
margin-top: 0px;
}
QTabBar::tab:!selected
{
color: #b1b1b1;
border: 1px solid gray;
background-color: qlineargradient(spread:pad, x1:1, y1:0, x2:1, y2:1, stop:0 rgba(101, 101, 101, 255),stop:1 rgba(66, 66, 66, 255));
}
QTabBar::tab:selected
{
background-color: qlineargradient(spread:pad, x1:1, y1:0, x2:1, y2:1, stop:0 rgba(197, 197, 197, 255),stop:1 rgba(154, 154, 154, 255));
border: 1px solid #414141;
color: #000;
}
QTabBar::tab:!selected:hover
{
color: #fff;
}
/*-----QPushButton-----*/
QPushButton
{
color: #000;
border: 1px solid #000;
border-radius: 4px;
background-color: qlineargradient(spread:pad, x1:0.494, y1:0, x2:0.492, y2:1, stop:0 rgba(97, 147, 237, 255), stop:1 rgba(78, 119, 191, 255));
}
QPushButton:hover
{
color: #000;
border: 1px solid #000;
border-radius: 4px;
background-color: qlineargradient(spread:pad, x1:0.494, y1:0, x2:0.492, y2:1, stop:0 rgba(86, 131, 212, 255), stop:1 rgba(70, 107, 173, 255));
font: bold;
}
QPushButton:pressed
{
color: #000;
border: 1px solid #000;
border-radius: 4px;
background-color: qlineargradient(spread:pad, x1:0.494, y1:0, x2:0.492, y2:1, stop:0 rgba(74, 113, 182, 255), stop:1 rgba(65, 99, 159, 255));
font: bold;
}
/*-----QToolButton-----*/
QToolButton
{
background-color: qlineargradient(spread:pad, x1:1, y1:0, x2:1, y2:1, stop:0 rgba(197, 197, 197, 255),stop:1 rgba(154, 154, 154, 255));
color: #000;
border: 1px solid #414141;
border-radius: 2px;
padding: 2px;
}
QToolButton:hover
{
background-color: qlineargradient(spread:pad, x1:1, y1:0, x2:1, y2:1, stop:0 rgba(214, 214, 214, 255),stop:1 rgba(198, 198, 198, 255));
}
QToolButton:pressed
{
background-color: qlineargradient(spread:pad, x1:1, y1:0, x2:1, y2:1, stop:0 rgba(101, 101, 101, 255),stop:1 rgba(66, 66, 66, 255));
}
QToolButton:checked
{
background-color: qlineargradient(spread:pad, x1:1, y1:0, x2:1, y2:1, stop:0 rgba(101, 101, 101, 255),stop:1 rgba(66, 66, 66, 255));
}
/*-----QComboBox-----*/
QComboBox
{
color : #fff;
background-color: #262626;
border : 1px solid rgb(28, 28, 28);
border-radius: 0px;
padding: 5px;
margin-right: 5px;
margin-left: 5px;
max-height : 10px;
min-width : 72px;
selection-background-color: rgb(85, 85, 255);
}
QComboBox::drop-down
{
background-color: rgb(98, 98, 98);
subcontrol-origin: padding;
subcontrol-position: top right;
width: 15px;
border-left-width: 1px;
border-left-color: darkgray;
border-left-style: solid;
border-top-right-radius: 3px;
border-bottom-right-radius: 3px;
}
QComboBox::down-arrow
{
image: url(:/Icons/resources/icons/downarrow.png);
}
QComboBox QWidget
{
color : #fff;
background-color: #262626;
border : 1px solid rgb(28, 28, 28);
}
/*-----QDockWidget-----*/
QDockWidget
{
color : lightgray;
border-top: 0px solid #262626;;
border-left: 1px solid #262626;;
border-right: 1px solid #262626;;
border-bottom: 1px solid #262626;;
background-color: rgb(49, 49, 49);
}
QDockWidget::title
{
background-color: rgb(58, 58, 58);
border: 1px solid rgb(58, 58, 58);
border-top-right-radius: 3px;
border-top-left-radius: 3px;
border-bottom-right-radius: 0px;
border-bottom-left-radius: 0px;
text-align: left;
margin-top:1px;
}
QDockWidget::close-button
{
max-width: 14px;
max-height: 14px;
margin-top:1px;
}
QDockWidget::float-button
{
max-width: 14px;
max-height: 14px;
margin-top:1px;
}
QDockWidget::close-button:hover
{
border: none;
background-color: none;
}
QDockWidget::float-button:hover
{
border: none;
background-color: none;
}
QDockWidget::separator
{
width: 1px;
margin: 6px 4px;
background-color: rgba(0,0,0);
}
/*-----QTreeWidget-----*/
QTreeWidget
{
show-decoration-selected: 0;
selection-background-color: transparent; /* Used on Mac */
selection-color: #fff; /* Used on Mac */
background-color: #262626;
padding-top : 5px;
border: none;
color: #fff;
font: 8pt;
}
QTreeView::item:selected
{
color:#000;
background-color: qlineargradient(spread:pad, x1:0.494, y1:0, x2:0.492, y2:1, stop:0 rgba(111, 159, 215, 255), stop:1 rgba(72, 100, 138, 255));
border-radius: 0px;
}
QTreeView::item:!selected:hover
{
color:#fff;
background-color: rgb(86, 100, 123);
border: none;
border-radius: 0px;
}
QTreeView::branch:has-children:!has-siblings:closed,
QTreeView::branch:closed:has-children:has-siblings
{
image: url(://tree-closed.png);
}
QTreeView::branch:open:has-children:!has-siblings,
QTreeView::branch:open:has-children:has-siblings
{
image: url(://tree-open.png);
}
/*-----QListView-----*/
QListView
{
border : none;
background-color: #262626;
color: white;
show-decoration-selected: 1; /* make the selection span the entire width of the view */
outline: 0;
border: 1px solid gray;
}
QListView::disabled
{
background-color: #656565;
color: #1b1b1b;
border: 1px solid #656565;
}
QListView::item
{
padding: 1px;
}
QListView::item:alternate
{
background-color: #4a4b4d;
}
QListView::item:selected
{
border: 1px solid #6a6ea9;
border: none;
color: #000;
}
QListView::item:selected:!active
{
background-color: qlineargradient(spread:pad, x1:0.494, y1:0, x2:0.492, y2:1, stop:0 rgba(111, 159, 215, 255), stop:1 rgba(72, 100, 138, 255));
border: none;
color: #000;
}
QListView::item:selected:active
{
background-color: qlineargradient(spread:pad, x1:0.494, y1:0, x2:0.492, y2:1, stop:0 rgba(111, 159, 215, 255), stop:1 rgba(72, 100, 138, 255));
border: none;
color: #000;
}
QListView::item:hover {
background-color: rgb(86, 100, 123);
border: none;
color: white;
}
/*-----QScrollBar-----*/
QScrollBar:horizontal
{
background-color: transparent;
height: 17px;
margin-bottom: 1px;
}
QScrollBar::handle:horizontal
{
border-radius : 5px;
background-color: qlineargradient(spread:pad, x1:0.494, y1:0, x2:0.492, y2:1, stop:0 rgba(97, 147, 237, 255), stop:1 rgba(78, 119, 191, 255));
min-width: 50px;
height : 10px;
}
QScrollBar::handle:horizontal:pressed
{
background-color: qlineargradient(spread:pad, x1:0.494, y1:0, x2:0.492, y2:1, stop:0 rgba(77, 127, 217, 255), stop:1 rgba(58, 99, 171, 255));
border-radius : 5px;
}
QScrollBar::add-line:horizontal
{
border: none;
background-color: transparent;
width: 0px;
}
QScrollBar::add-line:horizontal:hover
{
background-color: transparent;
}
QScrollBar::add-line:horizontal:pressed
{
background-color: transparent;
}
QScrollBar::sub-line:horizontal
{
border: none;
background-color: transparent;
border-radius :0px;
width: 0px;
}
QScrollBar::sub-line:horizontal:hover
{
background-color: transprarent;
}
QScrollBar::sub-line:horizontal:pressed
{
background-color: transparent;
}
QScrollBar:left-arrow:horizontal
{
width: 0px;
height: 0px;
background: transparent;
}
QScrollBar::right-arrow:horizontal
{
width: 0px;
height: 0px;
background: transparent;
}
QScrollBar::add-page:horizontal, QScrollBar::sub-page:horizontal
{
background-color: transparent;
}
QScrollBar:vertical
{
background-color: transparent;
border : none;
width: 10px;
}
QScrollBar::handle:vertical
{
background-color: qlineargradient(spread:pad, x1:0.494, y1:0, x2:0.492, y2:1, stop:0 rgba(97, 147, 237, 255), stop:1 rgba(78, 119, 191, 255));
border-radius : 5px;
min-height: 80px;
width : 10px;
margin: 0px;
}
QScrollBar::handle:vertical:pressed
{
border-radius : 5px;
background-color: qlineargradient(spread:pad, x1:0.494, y1:0, x2:0.492, y2:1, stop:0 rgba(77, 127, 217, 255), stop:1 rgba(58, 99, 171, 255));
}
QScrollBar::add-line:vertical
{
border: none;
background: transparent;
height: 0px;
subcontrol-position: none;
subcontrol-origin: none;
}
QScrollBar::add-line:vertical:hover
{
background-color: transparent;
}
QScrollBar::add-line:vertical:pressed
{
background-color: transparent;
}
QScrollBar::sub-line:vertical
{
border: none;
background: transparent;
height: 0px;
}
QScrollBar::sub-line:vertical:hover
{
background-color: transparent;
}
QScrollBar::sub-line:vertical:pressed
{
background-color: transparent;
}
QScrollBar::up-arrow:vertical
{
width: 0px;
height: 0px;
background: transparent;
}
QScrollBar::down-arrow:vertical
{
width: 0px;
height: 0px;
background: transparent;
}
QScrollBar::add-page:vertical, QScrollBar::sub-page:vertical
{
background-color: transparent;
}
/*-----QStatusBar-----*/
QStatusBar
{
color: #000;
margin : 0px;
padding : -5px;
background-color: rgb(170, 170, 170);
}
QStatusBar::item
{
background-color: transparent;
color: #000;
}

View File

@ -0,0 +1,244 @@
/*Copyright (c) DevSec Studio. All rights reserved.
MIT License
Permission is hereby granted, free of charge, to any person obtaining a copy
of this software and associated documentation files (the "Software"), to deal
in the Software without restriction, including without limitation the rights
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
copies of the Software, and to permit persons to whom the Software is
furnished to do so, subject to the following conditions:
The above copyright notice and this permission notice shall be included in all
copies or substantial portions of the Software.
THE SOFTWARE IS PROVIDED *AS IS*, WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
*/
/*-----QWidget-----*/
QWidget
{
color: #aaa;
background-color: #323232;
}
/*-----QLabel-----*/
QLabel
{
background-color: transparent;
color: #fff;
}
/*-----QMenuBar-----*/
QMenuBar
{
background-color: #323232;
}
QMenuBar::item
{
background: transparent;
}
QMenuBar::item:selected
{
background: #444;
}
QMenuBar::item:pressed
{
border: 1px solid #000;
background-color: #444;
margin-bottom:-1px;
padding-bottom:1px;
}
/*-----QMenu-----*/
QMenu
{
background-color: #444;
border: 1px solid #222;
padding: 4px;
padding-right: 0px;
}
QMenu::item
{
background-color: transparent;
padding: 2px 20px 2px 20px;
}
QMenu::item:disabled
{
color: #555;
background-color: transparent;
padding: 2px 20px 2px 20px;
}
QMenu::item:selected
{
background-color: #55aaff;
color: #fff;
}
/*-----QToolTip-----*/
QToolTip
{
border: 1px solid #222;
background-color: #333;
color: #aaa;
}
/*-----QToolButton-----*/
QToolButton
{
color: #b1b1b1;
background-color: QLinearGradient( x1: 0, y1: 0, x2: 0, y2: 1, stop: 0 #565656, stop: 0.1 #525252, stop: 0.5 #4e4e4e, stop: 0.9 #4a4a4a, stop: 1 #464646);
border-width: 1px;
border-color: #1e1e1e;
border-style: solid;
margin-right: 2px;
padding: 3px;
}
QToolButton:pressed
{
background-color: QLinearGradient( x1: 0, y1: 0, x2: 0, y2: 1, stop: 0 #2d2d2d, stop: 0.1 #2b2b2b, stop: 0.5 #292929, stop: 0.9 #282828, stop: 1 #252525);
}
QToolButton:checked
{
background-color: gray;
}
/*-----QLineEdit-----*/
QLineEdit{
background-color: #fff;
color: #000;
selection-color: #fff;
selection-background-color: #507098;
}
/*-----QTreeView-----*/
QTreeView
{
background-color: #434343;
border: 0.5px solid rgba(108,108,108,75);
}
QTreeView::item,
QTreeView::branch
{
background: transparent;
color: #DDD;
}
QTreeView::item:hover,
QTreeView::branch:hover
{
background-color: #55aaff;
color: #DDD;
}
QTreeView::item:selected,
QTreeView::branch:selected
{
background-color: #55aaff;
color: #fff;
}
/*-----QScrollBar-----*/
QScrollBar:horizontal
{
background-color: #333;
height: 8px;
margin: 0px;
padding: 0px;
}
QScrollBar::handle:horizontal
{
border: 1px solid #111;
background-color: #535353;
}
QScrollBar::add-line:horizontal, QScrollBar::sub-line:horizontal,
QScrollBar::add-page:horizontal, QScrollBar::sub-page:horizontal
{
width: 0px;
background-color: transparent;
}
QScrollBar:vertical
{
background-color: #333;
width: 8px;
margin: 0;
}
QScrollBar::handle:vertical
{
border: 1px solid #111;
background-color: #535353;
}
QScrollBar::add-line:vertical, QScrollBar::sub-line:vertical,
QScrollBar::add-page:vertical, QScrollBar::sub-page:vertical
{
height: 0px;
background-color: transparent;
}

View File

@ -0,0 +1,119 @@
/*Copyright (c) DevSec Studio. All rights reserved.
MIT License
Permission is hereby granted, free of charge, to any person obtaining a copy
of this software and associated documentation files (the "Software"), to deal
in the Software without restriction, including without limitation the rights
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
copies of the Software, and to permit persons to whom the Software is
furnished to do so, subject to the following conditions:
The above copyright notice and this permission notice shall be included in all
copies or substantial portions of the Software.
THE SOFTWARE IS PROVIDED *AS IS*, WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
*/
/*-----QWidget-----*/
QWidget
{
background-color: QLinearGradient(x1:0, y1:0, x2:0, y2:1, stop:1 #212121, stop:.4 #343434);
color: #000000;
border-color: #000000;
}
/*-----QLabel-----*/
QLabel
{
background-color: transparent;
color: #fff;
font-size: 14pt;
border-color: #000000;
}
/*-----QToolButton-----*/
QToolButton
{
background-color: qlineargradient(spread:repeat, x1:1, y1:0, x2:1, y2:1, stop:0 rgba(254, 171, 66, 255),stop:1 rgba(255, 153, 0, 255));
color: #000;
font-size: 14pt;
border-radius: 4px;
padding: 10px;
}
QToolButton::pressed
{
background-color: #6b960f;
}
/*-----QTabWidget-----*/
QTabBar::tab
{
font-size: 8pt;
font-weight: bold;
width: 80px;
border: 1px solid #444;
border-bottom-style: none;
border-top-style: none;
background-color: #323232;
padding-top: 3px;
padding-bottom: 2px;
margin-right: -1px;
}
QTabWidget::pane
{
border: 1px solid qlineargradient(spread:repeat, x1:1, y1:0, x2:1, y2:1, stop:0 rgba(254, 171, 66, 255),stop:1 rgba(255, 153, 0, 255));
top: 1px;
}
QTabBar::tab:last
{
margin-right: 0;
}
QTabBar::tab:first:!selected
{
margin-left: 0px;
}
QTabBar::tab:!selected
{
color: #fff;
border-bottom-style: solid;
margin-top: 3px;
background-color: QLinearGradient(x1:0, y1:0, x2:0, y2:1, stop:1 #212121, stop:.4 #343434);
}
QTabBar::tab:selected
{
background-color: qlineargradient(spread:repeat, x1:1, y1:0, x2:1, y2:1, stop:0 rgba(254, 171, 66, 255),stop:1 rgba(255, 153, 0, 255));
color: #000;
margin-bottom: 0px;
}
QTabBar::tab:!selected:hover
{
background-color: QLinearGradient(x1:0, y1:0, x2:0, y2:1, stop:1 #212121, stop:0.4 #343434, stop:0.2 #343434, stop:0.1 #ffaa00);
}

View File

@ -0,0 +1,434 @@
/*Copyright (c) DevSec Studio. All rights reserved.
MIT License
Permission is hereby granted, free of charge, to any person obtaining a copy
of this software and associated documentation files (the "Software"), to deal
in the Software without restriction, including without limitation the rights
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
copies of the Software, and to permit persons to whom the Software is
furnished to do so, subject to the following conditions:
The above copyright notice and this permission notice shall be included in all
copies or substantial portions of the Software.
THE SOFTWARE IS PROVIDED *AS IS*, WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
*/
QWidget{
background-color: #e6e7eb;
}
/*-----QLabel-----*/
QLabel
{
background-color: transparent;
color: #000000;
border-color: #000000;
}
/*-----QMenuBar-----*/
QMenuBar
{
background-color: #d6e1f0;
color: #000;
}
QMenuBar::disabled
{
background-color: #404040;
color: #656565;
border-color: #051a39;
}
QMenuBar::item
{
background-color: transparent;
}
QMenuBar::item:selected
{
background-color: #a7dfff;
color: #000;
}
QMenuBar::item:pressed
{
background-color: #98daff;
border: 1px solid #000;
margin-bottom: -1px;
padding-bottom: 1px;
}
/*-----QMenu-----*/
QMenu
{
background-color: #beccde;
border: 1px solid;
color: #000;
}
QMenu QWidget{
background-color: transparent;
}
QMenu::separator
{
height: 1px;
background-color: #6d8eff;
color: #ffffff;
padding-left: 4px;
margin-left: 10px;
margin-right: 5px;
}
QMenu::item
{
min-width : 150px;
padding: 3px 20px 3px 20px;
}
QMenu::item:selected
{
background-color: #d6e1f0;
color: #000;
}
QMenu::item:disabled
{
color: #262626;
}
/*-----QToolBar-----*/
QToolBar
{
background-color: #d6e1f0;
color: #ffffff;
border-color: #000000;
}
/*-----QToolButton-----*/
QToolButton
{
background-color: #d6e1f0;
color: #ffffff;
border-color: #000000;
}
QToolButton::hover
{
background-color: #f0f5f3;
color: #ffffff;
border: none;
}
QToolButton::checked:hover
{
background-color: #5cc4ff;
color: #ffffff;
border: none;
}
QToolButton::pressed
{
background-color: #5cc4ff;
color: #ffffff;
border: none;
}
QToolButton::checked
{
background-color: #5cc4ff;
color: #ffffff;
border: none;
show-decoration-selected: 0;
outline: 0;
}
/*-----QToolTip-----*/
QToolTip
{
border: 1px solid black;
background-color: #b2c1d5;
border-radius: 0px;
color: #000;
}
/*-----QLineEdit-----*/
QLineEdit{
background-color: #fefffc;
color: #000;
}
/*-----QTextEdit-----*/
QTableWidget{
background-color: #fff;
padding: 10px;
}
/*-----QComboBox-----*/
QComboBox
{
background-color: #fefefe;
border: 1px solid #1e1e1e;
border-radius: 0px;
padding-left: 6px;
color: #000;
height: 20px;
}
QComboBox:on
{
background-color: #fefefe;
}
QComboBox QAbstractItemView
{
background-color: #dcdcdf;
color: #000;
border: 1px solid black;
selection-background-color: #217346;
selection-color: #dcdcdf;
outline: 0;
}
QComboBox::drop-down
{
subcontrol-origin: padding;
subcontrol-position: top right;
width: 15px;
border-left-width: 0px;
border-left-color: darkgray;
border-left-style: solid;
border-top-right-radius: 3px;
border-bottom-right-radius: 3px;
}
QComboBox::down-arrow
{
image: url("./ressources/down_arrow.png");
width:8px;
height:8px;
}
/*-----QSpinBox-----*/
QSpinBox
{
background-color: #fefefe;
border-width: 1px;
border-color: #1e1e1e;
border-style: solid;
color: #000;
padding: 2px;
selection-background-color: #4e4e8f;
}
QSpinBox::up-button,
QSpinBox::down-button
{
background-color: #fefefe;
}
QSpinBox::up-button:hover,
QSpinBox::down-button:hover
{
background-color: #fefefe;
}
QSpinBox::up-button:pressed,
QSpinBox::down-button:pressed
{
background-color: #ebebeb;
border: 1px solid #ebebeb;
}
QSpinBox::down-arrow
{
image: url("./ressources/down_arrow.png");
width: 7px;
}
QSpinBox::up-arrow
{
image: url("./ressources/up_arrow.png");
width: 7px;
}
/*-----QSlider-----*/
QSlider
{
background-color: transparent;
padding: 2px;
}
QSlider::groove:horizontal
{
subcontrol-origin: content;
background-color: transparent;
height: 15px;
}
QSlider::handle:horizontal
{
background-color: #4ebfff;
width: 15px;
border-radius: 7px;
}
QSlider::sub-page:horizontal
{
background-color: #999;
margin: 5px;
border-radius: 5px;
}
QSlider::add-page:horizontal
{
background-color: #666;
margin: 5px;
border-radius: 5px;
}
/*-----QScrollBar-----*/
QScrollBar:horizontal
{
background-color: #beccde;
border: 1px solid darkgray;
height: 15px;
}
QScrollBar::handle:horizontal
{
border: 1px solid gray;
min-width: 100px;
background-color: #e6edf6;
}
QScrollBar::add-line:horizontal,
QScrollBar::sub-line:horizontal,
QScrollBar::add-page:horizontal,
QScrollBar::sub-page:horizontal
{
width: 0px;
background-color: transparent;
}
QScrollBar:vertical
{
background-color: #beccde;
border: 1px solid darkgray;
width: 14px;
}
QScrollBar::handle:vertical
{
border: 1px solid gray;
min-height: 100px;
background-color: #e6edf6;
}
QScrollBar::add-line:vertical,
QScrollBar::sub-line:vertical,
QScrollBar::add-page:vertical,
QScrollBar::sub-page:vertical
{
height: 0px;
background-color: transparent;
}
/*-----QStatusBar-----*/
QStatusBar
{
background-color: #d6e1f0;
color: #000000;
border-color: #000000;
}

View File

@ -0,0 +1,461 @@
/*Copyright (c) DevSec Studio. All rights reserved.
MIT License
Permission is hereby granted, free of charge, to any person obtaining a copy
of this software and associated documentation files (the "Software"), to deal
in the Software without restriction, including without limitation the rights
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
copies of the Software, and to permit persons to whom the Software is
furnished to do so, subject to the following conditions:
The above copyright notice and this permission notice shall be included in all
copies or substantial portions of the Software.
THE SOFTWARE IS PROVIDED *AS IS*, WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
*/
/*-----QWidget-----*/
QWidget
{
background-color: #fff;
color: red;
}
/*-----QLabel-----*/
QLabel
{
background-color: transparent;
color: #454544;
font-weight: bold;
font-size: 13px;
}
/*-----QPushButton-----*/
QPushButton
{
background-color: #5c55e9;
color: #fff;
font-size: 13px;
font-weight: bold;
border-top-right-radius: 15px;
border-top-left-radius: 0px;
border-bottom-right-radius: 0px;
border-bottom-left-radius: 15px;
padding: 10px;
}
QPushButton::disabled
{
background-color: #5c5c5c;
}
QPushButton::hover
{
background-color: #5564f2;
}
QPushButton::pressed
{
background-color: #3d4ef2;
}
/*-----QCheckBox-----*/
QCheckBox
{
background-color: transparent;
color: #5c55e9;
font-size: 10px;
font-weight: bold;
border: none;
border-radius: 5px;
}
/*-----QCheckBox-----*/
QCheckBox::indicator
{
background-color: #323232;
border: 1px solid darkgray;
width: 12px;
height: 12px;
}
QCheckBox::indicator:checked
{
image:url("./ressources/check.png");
background-color: #5c55e9;
border: 1px solid #5c55e9;
}
QCheckBox::indicator:unchecked:hover
{
border: 1px solid #5c55e9;
}
QCheckBox::disabled
{
color: #656565;
}
QCheckBox::indicator:disabled
{
background-color: #656565;
color: #656565;
border: 1px solid #656565;
}
/*-----QLineEdit-----*/
QLineEdit
{
background-color: #c2c7d5;
color: #2a547f;
border: none;
padding: 5px;
}
/*-----QListView-----*/
QListView
{
background-color: #5c55e9;
color: #fff;
font-size: 14px;
font-weight: bold;
show-decoration-selected: 0;
border-radius: 4px;
padding-left: -15px;
padding-right: -15px;
padding-top: 5px;
}
QListView:disabled
{
background-color: #5c5c5c;
}
QListView::item
{
background-color: #454e5e;
border: none;
padding: 10px;
border-radius: 0px;
padding-left : 10px;
height: 32px;
}
QListView::item:selected
{
color: #000;
background-color: #fff;
}
QListView::item:!selected
{
color:white;
background-color: transparent;
border: none;
padding-left : 10px;
}
QListView::item:!selected:hover
{
color: #fff;
background-color: #5564f2;
border: none;
padding-left : 10px;
}
/*-----QTreeView-----*/
QTreeView
{
background-color: #fff;
show-decoration-selected: 0;
color: #454544;
}
QTreeView:disabled
{
background-color: #242526;
show-decoration-selected: 0;
}
QTreeView::item
{
border-top-color: transparent;
border-bottom-color: transparent;
}
QTreeView::item:hover
{
background-color: #bcbdbb;
color: #000;
}
QTreeView::item:selected
{
background-color: #5c55e9;
color: #fff;
}
QTreeView::item:selected:active
{
background-color: #5c55e9;
color: #fff;
}
QTreeView::item:selected:disabled
{
background-color: #525251;
color: #656565;
}
QTreeView::branch:has-children:!has-siblings:closed,
QTreeView::branch:closed:has-children:has-siblings
{
image: url(://tree-closed.png);
}
QTreeView::branch:open:has-children:!has-siblings,
QTreeView::branch:open:has-children:has-siblings
{
image: url(://tree-open.png);
}
/*-----QTableView & QTableWidget-----*/
QTableView
{
background-color: #fff;
border: 1px solid gray;
color: #454544;
gridline-color: gray;
outline : 0;
}
QTableView::disabled
{
background-color: #242526;
border: 1px solid #32414B;
color: #656565;
gridline-color: #656565;
outline : 0;
}
QTableView::item:hover
{
background-color: #bcbdbb;
color: #000;
}
QTableView::item:selected
{
background-color: #5c55e9;
color: #fff;
}
QTableView::item:selected:disabled
{
background-color: #1a1b1c;
border: 2px solid #525251;
color: #656565;
}
QTableCornerButton::section
{
background-color: #ced5e3;
border: none;
color: #fff;
}
QHeaderView::section
{
color: #2a547f;
border: 0px;
background-color: #ced5e3;
padding: 5px;
}
QHeaderView::section:disabled
{
background-color: #525251;
color: #656565;
}
QHeaderView::section:checked
{
color: #fff;
background-color: #5c55e9;
}
QHeaderView::section:checked:disabled
{
color: #656565;
background-color: #525251;
}
QHeaderView::section::vertical::first,
QHeaderView::section::vertical::only-one
{
border-top: 1px solid #353635;
}
QHeaderView::section::vertical
{
border-top: 1px solid #353635;
}
QHeaderView::section::horizontal::first,
QHeaderView::section::horizontal::only-one
{
border-left: 1px solid #353635;
}
QHeaderView::section::horizontal
{
border-left: 1px solid #353635;
}
/*-----QScrollBar-----*/
QScrollBar:horizontal
{
background-color: transparent;
height: 8px;
margin: 0px;
padding: 0px;
}
QScrollBar::handle:horizontal
{
border: none;
min-width: 100px;
background-color: #7e92b7;
}
QScrollBar::add-line:horizontal,
QScrollBar::sub-line:horizontal,
QScrollBar::add-page:horizontal,
QScrollBar::sub-page:horizontal
{
width: 0px;
background-color: #d8dce6;
}
QScrollBar:vertical
{
background-color: transparent;
width: 8px;
margin: 0;
}
QScrollBar::handle:vertical
{
border: none;
min-height: 100px;
background-color: #7e92b7;
}
QScrollBar::add-line:vertical,
QScrollBar::sub-line:vertical,
QScrollBar::add-page:vertical,
QScrollBar::sub-page:vertical
{
height: 0px;
background-color: #d8dce6;
}

BIN
hit2023v2_RMS/test.dat Normal file

Binary file not shown.

View File

@ -0,0 +1,31 @@
[Device0]
HardwareVer=1
IP=10.0.7.6
Master=1
MasterDelay=22
Plane=0
Position=0
Sensors=2
SlaveDelay=1
[Device1]
HardwareVer=2
IP=10.0.7.17
Master=0
MasterDelay=22
Plane=1
Position=0
Sensors=5
SlaveDelay=1
[Global]
HostIp=10.0.7.1
NrDevices=1
[Trigger]
Gain=0
Gain_v2=0
Period=8999
Period_v2=9999
Tint=8549
Tint_v2=336

View File

@ -0,0 +1,37 @@
#include "udpserver.h"
UdpServer::UdpServer(QObject *parent) : QObject(parent)
{
// Configure the timer for data updates
// connect(&timer, &QTimer::timeout, this, &UdpServer::sendData);
// timer.setInterval(1); // 1 milliseconds (1 kHz)
startServer();
}
void UdpServer::startServer()
{
// Bind the UDP socket to a specific port (replace with your desired port)
// udpSocket.bind(QHostAddress::Any, 12345); // Replace 12345 with your desired port
udpSocket.bind(QHostAddress("10.0.7.1"), 12345); // Use the desired host address and port
// udpSocket.bind(QHostAddress::LocalHost, 12345); // Use "localhost" (127.0.0.1) and port 12345
// Start the timer for data updates
// timer.start();
}
void UdpServer::stopServer()
{
// Stop the timer and close the UDP socket
// timer.stop();
udpSocket.close();
}
void UdpServer::sendData(QByteArray data)
{
// Prepare the data to be sent
// QString dataString = QString::number(intensity) + ',' + QString::number(position) + ',' + QString::number(focus);
// QByteArray data = dataString.toUtf8();
// Send the data to all connected clients (broadcast to all on the same network)
udpSocket.writeDatagram(data, QHostAddress::Broadcast, 12345); // Replace 12345 with your desired port
}

31
hit2023v2_RMS/udpserver.h Normal file
View File

@ -0,0 +1,31 @@
#ifndef UDPSERVER_H
#define UDPSERVER_H
#include <QObject>
#include <QUdpSocket>
#include <QTimer> // Add this line to include QTimer
class UdpServer : public QObject
{
Q_OBJECT
public:
explicit UdpServer(QObject *parent = nullptr);
public slots:
void startServer();
void stopServer();
void sendData(QByteArray data); // New slot to send data with custom values
private:
QUdpSocket udpSocket;
QTimer timer;
};
// Declare the global UdpServer object as an external variable
extern UdpServer udpServer;
#endif // UDPSERVER_H