added RMS + CAL output version

This commit is contained in:
Blake Leverington 2025-02-20 15:39:04 +01:00
parent 5756204257
commit 4cd68ba3c6
89 changed files with 60350 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

View File

@ -0,0 +1,320 @@
915
917
947
971
981
964
977
980
965
969
965
975
961
967
979
959
978
978
982
976
964
962
971
976
948
957
977
970
950
981
978
962
983
960
980
958
980
978
973
949
963
969
970
982
982
978
971
974
979
976
976
980
982
968
972
961
973
976
982
983
948
981
952
969
992
990
1028
1032
1030
1033
1034
1023
1036
1024
1032
1030
1032
1026
1026
1026
1033
1033
1025
1039
1035
1041
1034
1055
1027
1036
1024
1021
1037
1028
1021
1033
1030
1047
1035
1037
1011
1049
1044
1028
1042
1032
1065
1035
1033
1033
1026
1037
1046
1039
1047
1035
1037
1023
1019
1046
1030
1031
1017
1038
1035
1036
1039
1008
990
992
1011
1050
1048
1043
1033
1051
1024
1040
1013
1015
1024
1054
1034
1046
1029
1041
1057
1053
1035
1045
1046
1047
1051
1064
1024
1037
1030
1040
1049
1049
1050
1023
1043
1053
1051
1045
1048
1056
1038
1020
1057
1033
1041
1029
1015
1043
1030
1033
1039
1047
1049
1075
1051
1040
1046
1051
1049
1038
1019
1044
1016
1040
947
960
958
1018
981
1005
984
982
998
983
993
981
981
985
986
1011
1002
982
986
988
992
988
1001
1002
998
996
993
1002
996
1001
992
996
993
979
978
974
1004
1013
1013
1005
988
982
1002
1010
988
1008
1011
1015
997
989
984
985
1020
1008
980
993
993
1012
1002
1001
1021
1001
1002
977
957
936
994
988
996
984
976
1005
1003
999
988
991
979
988
998
1002
1003
1001
1011
1011
989
998
1017
989
999
985
996
1013
996
999
993
991
1005
1004
1007
1001
1002
1013
987
983
997
1008
1011
1005
1011
983
978
999
1011
1013
999
1021
993
1007
1035
980
1012
1014
999
1007
1014
983
1014
972

View File

@ -0,0 +1,320 @@
889
855
854
864
880
904
876
867
877
888
885
903
873
899
905
889
864
905
886
867
889
903
888
867
892
902
889
886
891
906
917
874
902
914
915
923
887
888
879
902
906
901
876
881
886
899
888
926
904
901
894
897
898
900
892
882
888
895
893
886
864
887
897
868
863
880
883
898
867
878
888
879
882
903
899
893
886
879
873
889
900
891
877
883
895
892
897
889
885
887
880
881
898
884
901
881
914
900
900
886
894
902
891
889
883
884
899
902
873
885
878
886
882
898
895
900
897
898
902
898
895
901
881
891
889
887
903
890
836
827
847
854
865
853
866
860
870
874
860
876
845
856
853
847
846
858
852
855
853
858
867
869
855
848
850
862
867
873
864
862
865
844
851
867
841
874
890
868
867
855
895
888
868
870
871
867
885
862
881
882
860
869
865
863
889
870
854
863
883
892
868
837
922
931
949
950
957
957
953
935
942
950
950
961
962
956
956
954
951
982
955
974
962
962
957
954
963
964
973
962
963
969
950
955
958
957
947
964
968
953
948
959
958
963
969
969
966
971
961
972
970
972
966
968
971
956
957
949
944
929
935
973
964
942
959
947
929
921
922
953
921
948
943
947
968
957
950
941
929
937
940
936
941
960
956
952
932
928
921
944
951
946
935
941
943
962
952
946
940
931
935
952
942
931
946
928
943
944
949
958
941
956
925
937
942
957
950
946
944
964
939
933
969
945
953
951
956
942
948
948

View File

@ -0,0 +1,320 @@
292
2236
3354
3105
7221
9400
12401
13631
13691
13931
13820
14226
14262
14193
13841
12164
13073
14288
14708
14846
14607
14566
16327
16197
14976
13606
15111
15600
15104
15385
15585
15691
14442
15071
15404
14670
15226
15735
15885
15240
15421
15632
16418
16190
16396
16544
15611
16341
16292
15607
16837
16770
17584
17644
17259
16397
16245
16194
15645
15465
15829
16301
16352
15458
15709
16213
16426
14934
15597
15333
16580
15002
14353
13799
13907
14830
14998
14885
14920
14767
14467
13557
14248
14618
14087
14110
15946
16737
16667
16772
16794
16640
16436
16972
17241
16229
15695
14983
15890
16107
16291
16408
16613
14740
15041
17430
16539
15153
15607
15691
15877
16761
16481
15689
14962
15481
16829
17368
16976
16109
16325
17517
17986
17005
17225
17085
17721
17587
17660
17752
17974
18675
18316
17720
17612
17516
17415
17155
16846
14949
15134
16036
15515
14420
15595
15455
15903
15503
15831
15713
16079
15529
14932
15400
14932
14402
14036
13638
13295
11983
10865
12046
11275
10381
9449
8657
7414
8355
9042
7945
7151
7311
7157
7315
7118
7585
8448
10341
11301
10958
11201
10929
9803
8871
8421
8223
8315
7874
8251
7806
6670
6201
7470
7852
8363
8779
9532
11717
13115
11629
11103
10523
10391
10007
9355
7557
8805
8827
8506
8555
9192
9727
9243
8690
8686
8946
12062
15079
15874
15861
15842
16140
16235
16183
15863
16392
16435
15995
15766
16034
15759
15705
15344
15735
15857
15828
15255
14959
15338
15305
15537
15569
15663
15587
15485
14371
13474
13601
14865
15566
15473
14871
14575
14644
14473
14564
13554
13925
14119
13024
13263
13568
14021
13893
13724
13961
14120
14174
14798
14344
13661
13864
13873
13606
13835
13521
13510
13778
13621
13414
13537
13965
13682
13210
13867
14077
13843
13429
13986
13597
13745
14710
14062
13379
14384
13555
12435
12032
11849
12379
12928
13152
13373
13553
13792
13937
13379
13194
13383
13745
14034
14075
13900
13894
13561
13498
13373
12896
12759
13234

View File

@ -0,0 +1,320 @@
59
55
47
143
1221
4897
7637
11168
11616
11369
12995
14242
14300
15020
15670
15970
14825
15092
14423
14866
14131
14001
14161
14692
14121
14361
14495
14560
14560
14874
15295
15315
15335
15286
15077
13436
14987
14864
15092
15088
15300
15640
14271
15287
14538
14542
14180
14552
14665
13472
14836
14487
14001
14458
14442
14343
14528
14850
14372
15499
15323
15927
15899
16312
13760
13304
14078
13889
13917
13645
13786
14058
14011
13613
13661
13601
13703
13696
13843
13412
13311
13138
13396
13666
13831
13608
13748
13496
13764
13425
13614
13681
13285
13598
12987
13401
13088
12708
12927
13305
13256
13804
13891
13589
13084
12591
12189
12709
12716
12901
12823
13200
12987
13111
12949
12452
12073
12455
12980
13014
12724
12018
12189
12898
12054
12934
12521
12539
11278
11403
11340
11581
12107
11512
10728
11544
11225
11326
11323
11108
10458
10325
9554
10385
9803
7493
7532
10147
10140
10072
8807
8059
10109
10568
10439
11157
11312
11461
11417
11340
11348
11533
11505
11331
11152
11347
11915
11433
9679
10555
10725
11267
11366
11493
11161
11189
10803
10730
10840
10392
10619
10472
10304
10912
10703
10166
9948
8960
10034
9990
10197
10416
8959
8766
9190
9298
9236
8596
9092
9482
9790
9835
10088
9971
10062
10324
10341
9748
10072
10245
9441
9085
9683
9372
9169
9679
9806
8914
9044
8748
8290
8307
7325
7790
8837
9100
8261
8705
9385
9137
9316
9145
8356
8819
8496
8663
8133
7898
8784
9043
8561
8698
7944
7502
6689
7456
8129
8513
7800
8585
8504
8531
8308
8743
9198
9331
9113
8516
8569
8816
8617
9481
8963
8757
9096
9167
8956
8145
8567
8684
8800
9469
9210
9628
9948
9339
9643
9619
9925
9934
10249
10236
10815
10931
11116
10594
10234
10688
10141
10435
10545
10446
10467
10294
10355
10757
10567
10697
10606
10658
10497
10770
10869
11193
11234
11400
11468
11357
10930
10093
10511
10475
11062
10557
10463
10689
10545
10386
10344
10567

143
hit2023v2_RAWCAL/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,182 @@
#include "datareceiver.h"
#include "dev_commands.h"
#include "helpers.h"
#include <iostream>
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 + DATA_RMS_FRAME_SIZE);
if (size_received_bytes != expected_size_bytes)
{
std::cout << "packet error. Got" << size_received_bytes << " bytes expected" << expected_size_bytes << std::endl;
continue;
}
for (int ethb = 0; ethb < ethBunch; ethb++)
{
int baseaddr = ethb * (DATA_PACKET_HEADER_SIZE + DATA_SYNC_HEADER_SIZE + dmaBunch*DATA_BLOCK_SIZE + DATA_RMS_FRAME_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;
RMSFrame rms;
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);
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 - BYTES2INT(tmpBuffer + baseaddr3 + DATA_BYTES_PER_SAMPLE*s); //2 bytes RMS + 2 bytes CAL per channel
rms.mean = BYTES2SHORT(tmpBuffer+baseaddr+DATA_PACKET_HEADER_SIZE+DATA_SYNC_HEADER_SIZE+DATA_BLOCK_SIZE);
rms.sigma = BYTES2SHORT(tmpBuffer+baseaddr+DATA_PACKET_HEADER_SIZE+DATA_SYNC_HEADER_SIZE+DATA_BLOCK_SIZE + 2);
rms.max = BYTES2SHORT(tmpBuffer+baseaddr+DATA_PACKET_HEADER_SIZE+DATA_SYNC_HEADER_SIZE+DATA_BLOCK_SIZE + 4);
rms.status = BYTES2SHORT(tmpBuffer+baseaddr+DATA_PACKET_HEADER_SIZE+DATA_SYNC_HEADER_SIZE+DATA_BLOCK_SIZE + 6);
for (unsigned int ii = 0; ii < 4; ii++)
rms.registers[ii] = BYTES2SHORT(tmpBuffer+baseaddr+DATA_PACKET_HEADER_SIZE+DATA_SYNC_HEADER_SIZE+DATA_BLOCK_SIZE + 8+ii*2);
data_to_push.rms_frame = rms;
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, &DataReceiver::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,161 @@
#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_RMS_FRAME_SIZE 16 //8 unsigned short
#define DATA_BYTES_PER_SAMPLE 4 //RMS + CAL streamed in data RMSCALRMSCALRMSCAL etc
#define DATA_SAMPLES_PER_SENSOR 64
#define DATA_MAX_SENSORS_PER_BOARD 5
#define DATA_MAX_BUNCH 16 //max. product of dmaBunch * ethBunch
//#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)
#define DATA_PACKET_SIZE ( DATA_MAX_BUNCH * (DATA_PACKET_HEADER_SIZE + DATA_SYNC_HEADER_SIZE + DATA_BLOCK_SIZE + DATA_RMS_FRAME_SIZE ) )
#define DATA_MAX_BLOCK_SIZE (DATA_MAX_SENSORS_PER_BOARD * DATA_SAMPLES_PER_SENSOR * DATA_BYTES_PER_SAMPLE)
#define DATA_MAX_PACKET_SIZE ( DATA_MAX_BUNCH * (DATA_PACKET_HEADER_SIZE + DATA_SYNC_HEADER_SIZE + DATA_MAX_BLOCK_SIZE + DATA_RMS_FRAME_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;
typedef struct{
unsigned short mean;
unsigned short sigma;
unsigned short max;
unsigned short status;
unsigned short registers[4];
} RMSFrame;
class BufferData
{
public:
SyncFrame sync_frame;
RMSFrame rms_frame;
int buffer_size;
int* sensor_data; //4 byte int for RAW + CAL instead of 2byte unsigned short for one
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 int[size];
}
BufferData(const BufferData& master) : buffer_size(0), sensor_data(NULL)
{
sync_frame = master.sync_frame;
rms_frame = master.rms_frame;
resize(master.buffer_size);
memcpy(sensor_data, master.sensor_data, buffer_size*sizeof(int));
}
BufferData& operator=(const BufferData& master)
{
if (this == &master)
return *this; //self-assignment
sync_frame = master.sync_frame;
rms_frame = master.rms_frame;
resize(master.buffer_size);
memcpy(sensor_data, master.sensor_data, buffer_size*sizeof(int));
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

View File

@ -0,0 +1,135 @@
#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
#define COMMAND_SET_CLUSTER_THRESHOLD 0x4001
//L: 1
//D: []
//Send 8 bit beam cluster selection threshold
#define COMMAND_SET_CLUSTER_SIZE 0x4002
//L: 1
#define COMMAND_SET_CALIBRATION_FACTOR 0x4003
//L: 320*16bit
//D: []
// ***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

540
hit2023v2_RAWCAL/device.cpp Normal file
View File

@ -0,0 +1,540 @@
#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);
ctrlSetClusterThreshold(deviceConfig.threshold);
ctrlSetClusterSize(deviceConfig.clustersize);
ctrlSetCalibrationFactor(deviceConfig.calibrationFactor);
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);*/
}
int Device::ctrlSetClusterThreshold(int threshold)
{
QVector<unsigned short> rxdata;
QVector<unsigned short> txdata;
txdata.append((unsigned short)threshold);
if (threshold)
return queryCtrl(COMMAND_SET_CLUSTER_THRESHOLD, txdata, rxdata);
else
return queryCtrl(COMMAND_SET_CLUSTER_THRESHOLD, txdata, rxdata);
}
int Device::ctrlSetClusterSize(int size)
{
QVector<unsigned short> rxdata;
QVector<unsigned short> txdata;
txdata.append((unsigned short)size);
if (size)
return queryCtrl(COMMAND_SET_CLUSTER_SIZE, txdata, rxdata);
else
return queryCtrl(COMMAND_SET_CLUSTER_SIZE, txdata, rxdata);
}
int Device::ctrlSetCalibrationFactor(int calibrationFactor[320])
{
// Check for null pointer to ensure valid input
if (calibrationFactor == nullptr)
{
// Handle the error case: log it, return an error code, or throw an exception
return -1; // Or handle as appropriate
}
QVector<unsigned short> rxdata;
QVector<unsigned short> txdata;
int status = -1;
// Append each calibration factor to txdata
for (int i = 0; i < 320; ++i)
{
txdata.append(static_cast<unsigned short>(i));
txdata.append(static_cast<unsigned short>(calibrationFactor[i]));
// Perform the queryCtrl operation with the populated txdata
status = queryCtrl(COMMAND_SET_CALIBRATION_FACTOR, txdata, rxdata);
rxdata.clear();
txdata.clear();
//if (status == DEV_CTRL_ERROR) {return DEV_CTRL_ERROR;}
}
return DEV_CTRL_OK;
}

126
hit2023v2_RAWCAL/device.h Normal file
View File

@ -0,0 +1,126 @@
#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 threshold; //cluster amplitude threshold
int clustersize; //clustering channel size lower limit
int calibrationFactor[320];
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}, threshold{10}, clustersize{4}
{
// Initialize calibrationFactor array with default value 8192
for (int i = 0; i < 320; i++) {
calibrationFactor[i] = 8192;
}
}
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; }
};
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);
int ctrlSetClusterThreshold(int threshold);
int ctrlSetClusterSize(int clustersize);
int ctrlSetCalibrationFactor(int calibrationFactor[320]);
protected slots:
void onConnected();
void onSocketError(QAbstractSocket::SocketError socketError);
void onDisconnected();
};
#endif // DEVICE_H

View File

@ -0,0 +1,64 @@
[Global]
NrDevices=3
HostIp=10.0.7.1
[Device0]
IP=10.0.7.19
HardwareVer=2
Plane=0
Position=0
Sensors=5
Master=1
MasterDelay=61
SlaveDelay=34
Threshold=11
Size=4
CalibFile=C:/Users/leverington/Downloads/board0.txt
ClusterSize=4
Device0\CalibFile=C:/Users/leverington/Downloads/board0.txt
[Device1]
IP=10.0.7.18
HardwareVer=2
Plane=1
Position=0
Sensors=5
Master=0
MasterDelay=7
SlaveDelay=1
Threshold=12
Size=4
CalibFile=
ClusterSize=5
[Trigger]
Period=9000
Tint=8491
Gain=0
Period_v2=2499
Tint_v2=335
Gain_v2=0
[Device2]
IP=10.0.7.5
HardwareVer=1
Plane=2
Position=0
Sensors=2
Master=0
MasterDelay=7
SlaveDelay=1
Device0\CalibFile=C:/Users/leverington/Downloads/board0.txt
Threshold=13
ClusterSize=6
CalibFile=
[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,31 @@
[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=9000
Tint=1000
Gain=1
Period_v2=2500
Tint_v2=336
Gain_v2=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

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,456 @@
#include "dialogdevices.h"
#include "ui_dialogdevices.h"
#include "helpers.h"
#include <QFileDialog>
#include <QMessageBox>
#include <QFile>
#include <QTextStream>
#include <QVector>
#include <QPushButton> // Include QPushButton header for button creation
DialogDevices::DialogDevices(QWidget *parent) :
QDialog(parent),
ui(new Ui::DialogDevices)
{
ui->setupUi(this);
deviceSettings = new QSettings("./device_config.ini", QSettings::IniFormat);
}
DialogDevices::~DialogDevices()
{
delete ui;
}
//***************** Initialization ******************
//***************** Processing ******************
void DialogDevices::accept()
{
// qInfo("Accepted!");
if (validateAndSave())
QDialog::accept();
}
void DialogDevices::applyCalibrationDataToDevice(int dev_nr, const QVector<unsigned short>& data)
{
// Implementation for applying the calibration data to the specific device
// For example, updating device settings or performing calculations
// Example: Set the calibration data in your application logic
// deviceSettings->setValue("Device%1/CalibrationData", data); // if storing in settings
// Check if device number is valid
if (dev_nr < 0 || dev_nr >= deviceCalibrationData.size()) {
QMessageBox::warning(this, "Invalid Device", "The device number is out of range.");
return;
}
// Check if the provided data is valid
if (data.size() != 320) {
QMessageBox::warning(this, "Invalid Data", "The calibration data must contain exactly 320 values.");
return;
}
// Apply the calibration data to the specified device
deviceCalibrationData[dev_nr] = data;
}
// Load calibration factors from a file and store them
void DialogDevices::selectCalibrationFile(int dev_nr)
{
QString filename = QFileDialog::getOpenFileName(this, "Select Calibration File", "", "Text Files (*.txt);;All Files (*)");
if (filename.isEmpty()) {
return; // User canceled the dialog
}
QVector<unsigned short> calibrationFactors(320, 8192); // Initialize with default value 8192
QFile file(filename);
if (!file.open(QIODevice::ReadOnly | QIODevice::Text)) {
QMessageBox::critical(this, "Error", "Could not open calibration file: " + filename);
return;
}
QTextStream in(&file);
int index = 0;
while (!in.atEnd() && index < 320) {
QString line = in.readLine().trimmed();
bool ok;
int value = line.toInt(&ok);
// Validate value and ensure it is within the range of an unsigned short
if (ok && value >= 0 && value <= 65535) {
calibrationFactors[index] = value;
} else {
qWarning() << "Invalid calibration factor in file:" << line << "at index" << index;
calibrationFactors[index] = 8192; // Use default if invalid
}
index++;
}
// Ensure remaining indices are filled with default values
while (index < 320) {
calibrationFactors[index++] = 8192;
}
file.close();
// Store calibration factors for the device
if (dev_nr < deviceCalibrationData.size()) {
deviceCalibrationData[dev_nr] = calibrationFactors;
} else {
deviceCalibrationData.append(calibrationFactors);
}
// Save the calibration file path to QSettings
top(deviceSettings);
QString group_label = QString("Device%1").arg(dev_nr);
deviceSettings->beginGroup(group_label);
deviceSettings->setValue("CalibFile", filename); // Save the file path
deviceSettings->endGroup();
// Update the table display to show the file path (optional)
QTableWidgetItem* calibFileItem = new QTableWidgetItem(filename);
ui->tableDevices->setItem(dev_nr, 10, calibFileItem);
}
// Retrieve all calibration factors for each device
QVector<QVector<unsigned short>> DialogDevices::getAllCalibrationFactors() const
{
return deviceCalibrationData;
}
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(12);
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");
h_header.append("Threshold");
h_header.append("ClusterSize");
h_header.append("CalibFile"); // Column for showing file path
h_header.append("Select Calib File"); // New column for the button
ui->tableDevices->setHorizontalHeaderLabels(h_header);
importSettings();
}
initialized = 1;
}
QDialog::showEvent(event);
}
void DialogDevices::importSettings()
{
int nr_devices = ui->spinNrDevices->value();
ui->tableDevices->setRowCount(nr_devices);
// Ensure the device calibration data vector is initialized properly
deviceCalibrationData.resize(nr_devices, QVector<unsigned short>(320, 8192));
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);
newItem = new QTableWidgetItem(deviceSettings->value("Threshold", "10").toString());
ui->tableDevices->setItem(dev_nr, 8, newItem);
newItem = new QTableWidgetItem(deviceSettings->value("ClusterSize", "4").toString());
ui->tableDevices->setItem(dev_nr, 9, newItem);
// Load calibration file path and update table
QString calibFilePath = deviceSettings->value("CalibFile", "").toString();
newItem = new QTableWidgetItem(calibFilePath);
ui->tableDevices->setItem(dev_nr, 10, newItem);
// If the calibration file exists, load the factors
if (!calibFilePath.isEmpty()) {
QVector<unsigned short> calibrationFactors(320, 8192);
if (loadCalibrationFactorsFromFile(calibFilePath, calibrationFactors)) {
deviceCalibrationData[dev_nr] = calibrationFactors;
applyCalibrationDataToDevice(dev_nr, calibrationFactors);
}
}
// Add a button for selecting calibration files
QPushButton* calibButton = new QPushButton("Select File");
ui->tableDevices->setCellWidget(dev_nr, 11, calibButton);
// Connect the button to the slot
connect(calibButton, &QPushButton::clicked, this, [this, dev_nr]() { selectCalibrationFile(dev_nr); });
}
}
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 cluster threshold
user_data = ui->tableDevices->item(dev_nr,8)->text();
num_value = user_data.toInt();
if (num_value < 1)
num_value = 1;
if (num_value > 65535)
num_value = 65535;
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,8)->setText(generated);
//now cluster size
user_data = ui->tableDevices->item(dev_nr,9)->text();
num_value = user_data.toInt();
if (num_value < 1)
num_value = 1;
if (num_value > 320)
num_value = 320;
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,9)->setText(generated);
// Calibration file path
user_data = ui->tableDevices->item(dev_nr, 10)->text();
if (user_data.isEmpty()) {
// Set default calibration factors if the path is empty
QVector<unsigned short> defaultCalibration(320, 8192);
deviceCalibrationData[dev_nr] = defaultCalibration;
applyCalibrationDataToDevice(dev_nr, defaultCalibration);
} else {
deviceSettings->setValue("Device" + QString::number(dev_nr) + "/CalibFile", user_data); // Save the file path
}
// Save settings for each device
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());
deviceSettings->setValue("Threshold", ui->tableDevices->item(dev_nr, 8)->text());
deviceSettings->setValue("ClusterSize", ui->tableDevices->item(dev_nr, 9)->text());
deviceSettings->setValue("CalibFile", ui->tableDevices->item(dev_nr, 10)->text());
deviceSettings->endGroup();
}
// Store the global number of devices
top(deviceSettings);
deviceSettings->beginGroup("Global");
deviceSettings->setValue("NrDevices", nr_devices);
deviceSettings->endGroup();
if (!data_ok) {
QMessageBox::warning(this, "Invalid Data", "Some device settings were invalid and have been corrected. Please review the settings.");
}
return data_ok;
}
// Function to load calibration factors from a file
bool DialogDevices::loadCalibrationFactorsFromFile(const QString& filePath, QVector<unsigned short>& calibrationFactors)
{
QFile file(filePath);
if (!file.open(QIODevice::ReadOnly | QIODevice::Text)) {
qWarning() << "Could not open calibration file:" << filePath;
return false;
}
QTextStream in(&file);
int index = 0;
while (!in.atEnd() && index < 320) {
QString line = in.readLine().trimmed();
bool ok;
int value = line.toInt(&ok);
// Validate value and ensure it is within the range of an unsigned short
if (ok && value >= 0 && value <= 65535) {
calibrationFactors[index] = static_cast<unsigned short>(value);
} else {
qWarning() << "Invalid calibration factor in file:" << line << "at index" << index;
calibrationFactors[index] = 8192; // Use default if invalid
}
index++;
}
// Ensure remaining indices are filled with default values
while (index < 320) {
calibrationFactors[index++] = 8192;
}
file.close();
return true;
}
void DialogDevices::on_spinNrDevices_valueChanged(int arg1)
{
if (initialized)
importSettings();
}

View File

@ -0,0 +1,43 @@
#ifndef DIALOGDEVICES_H
#define DIALOGDEVICES_H
#include <QDialog>
#include <QSettings>
#include <QShowEvent>
#include <QVector> // Include QVector for calibration data storage
#include <QTableWidgetItem>
namespace Ui {
class DialogDevices;
}
class DialogDevices : public QDialog
{
Q_OBJECT
public:
explicit DialogDevices(QWidget *parent = 0);
~DialogDevices();
QSettings* deviceSettings = NULL;
QVector<QVector<unsigned short>> getAllCalibrationFactors() const; // Declaration of the method
public slots:
void showEvent(QShowEvent *event);
void accept();
protected:
int validateAndSave();
bool loadCalibrationFactorsFromFile(const QString &filePath, QVector<unsigned short> &calibrationFactors); // Function to load calibration factors from a file
void applyCalibrationDataToDevice(int dev_nr, const QVector<unsigned short>& data); // Function to apply calibration data to a device
void importSettings();
int last_nr_devices = -1;
int initialized = 0;
QVector<QVector<unsigned short>> deviceCalibrationData; // Storage for calibration data for each device
private slots:
void on_spinNrDevices_valueChanged(int arg1);
void selectCalibrationFile(int dev_nr); // Slot for handling calibration file selection
private:
Ui::DialogDevices *ui;
};
#endif // DIALOGDEVICES_H

View File

@ -0,0 +1,117 @@
<?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>1085</width>
<height>233</height>
</rect>
</property>
<property name="sizePolicy">
<sizepolicy hsizetype="Expanding" vsizetype="Expanding">
<horstretch>0</horstretch>
<verstretch>0</verstretch>
</sizepolicy>
</property>
<property name="windowTitle">
<string>Devices</string>
</property>
<property name="sizeGripEnabled">
<bool>true</bool>
</property>
<widget class="QDialogButtonBox" name="buttonBox">
<property name="geometry">
<rect>
<x>720</x>
<y>190</y>
<width>341</width>
<height>32</height>
</rect>
</property>
<property name="orientation">
<enum>Qt::Orientation::Horizontal</enum>
</property>
<property name="standardButtons">
<set>QDialogButtonBox::StandardButton::Cancel|QDialogButtonBox::StandardButton::Ok</set>
</property>
</widget>
<widget class="QWidget" name="verticalLayoutWidget">
<property name="geometry">
<rect>
<x>10</x>
<y>10</y>
<width>1061</width>
<height>171</height>
</rect>
</property>
<layout class="QVBoxLayout" name="verticalLayout">
<property name="sizeConstraint">
<enum>QLayout::SizeConstraint::SetNoConstraint</enum>
</property>
<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">
<attribute name="horizontalHeaderCascadingSectionResizes">
<bool>true</bool>
</attribute>
</widget>
</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>BPMDisplay</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,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>

View File

@ -0,0 +1,467 @@
#include "display.h"
#include "ui_display.h"
#include <QMessageBox>
#include <QFileDialog>
#include <QCheckBox>
#include <iostream>
BPMDisplay::BPMDisplay(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_savecalib, &QPushButton::clicked, this, &BPMDisplay::onSaveCalibrationClicked);
connect(ui->pushButton_loadcalib, &QPushButton::clicked, this, &BPMDisplay::onLoadCalibrationClicked);
connect(ui->checkBox_enablecalib, &QCheckBox::stateChanged, this, &BPMDisplay::onCalibrationCheckBoxChanged);
connect(ui->checkBox_expertmode, &QCheckBox::stateChanged, this, &BPMDisplay::onExpertModeStateChanged);
// Enable or disable the "Save Background" and "Save Calib" buttons accordingly
ui->pushButton_savecalib->setEnabled(expertModeEnabled);
// Gray out the buttons when they are disabled
ui->pushButton_savecalib->setStyleSheet(expertModeEnabled ? "" : "background-color: gray;");
}
BPMDisplay::~BPMDisplay()
{
delete ui;
}
void BPMDisplay::showEvent(QShowEvent * event)
{
if (!event->spontaneous())
{
ui->plot->addGraph();
}
QDialog::showEvent(event);
}
//***********************************************
void BPMDisplay::plot(const QVector<signed short> &data, const QVector<signed short> &rmsdata)
{
//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 (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<float> &calibrationData = calibrationDataMap[planeName];
// Apply calibration to the current data
for (int i = 0; i < nrPoints; ++i) {
dataY[i] = int(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);
updateMean((rmsdata[0]));
updateRms((rmsdata[1]));
updateMax((rmsdata[2]));
updateStatus((rmsdata[3]));
//plot
ui->plot->replot();
}
void BPMDisplay::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 (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<float> &calibrationData = calibrationDataMap[planeName];
// Apply calibration to the current data
for (int i = 0; i < nrPoints; ++i) {
dataY[i] = int(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 BPMDisplay::plot()
{
plot(buffer, rmsbuffer);
}
void BPMDisplay::setTitle(QString title)
{
ui->lineTitle->setText(title);
}
// Slot to handle button clicks
void BPMDisplay::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 BPMDisplay::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 BPMDisplay::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();
unsigned short value = line.toUShort();
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 BPMDisplay::onCheckBoxStateChanged(int state)
{
// The state argument will be Qt::Unchecked (0) or Qt::Checked (2)
subtractBackground = (state == Qt::Checked);
}
void BPMDisplay::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);
const QVector<signed short> &backgroundData = backgroundDataMap[planeName];
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] - backgroundData[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 BPMDisplay::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<float> calibrationData;
while (!stream.atEnd()) {
QString line = stream.readLine();
float value = line.toFloat();
calibrationData.append(value);
}
// Close the file
file.close();
// Normalize the calibration data to the median value of all values greater than zero
QVector<float> normalizedCalibrationData = calibrationData; // Copy the data
QVector<float> 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(), [](unsigned short value) {
return value < 50;
}), normalizedCalibrationData.end());
std::sort(normalizedCalibrationData.begin(), normalizedCalibrationData.end()); // Sort the data
int size = normalizedCalibrationData.size();
float 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];
}
if (medianValue>100){
//use the second copy to return the scaled calibration values.
for (auto &value : normalizedCalibrationData2) {
if (value > 50) {
value = medianValue / value;
}
else
{
value = 0;
}
// std::cerr << value << " ";
}
// std::cerr << std::endl;
// 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{
qWarning() << " Warning: MedianValue of calibration data too low. Not applied. ";
}
} else {
// Failed to open the file
qWarning() << "Warning: Failed to open" << filename << "for reading";
}
}
void BPMDisplay::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 BPMDisplay::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_savecalib->setEnabled(expertModeEnabled);
// Gray out the buttons when they are disabled
ui->pushButton_savecalib->setStyleSheet(expertModeEnabled ? "" : "background-color: gray;");
}
void BPMDisplay::updateMean(unsigned short value)
{
ui->lcdNumber_mean->display((value));
}
void BPMDisplay::updateRms(unsigned short value)
{
ui->lcdNumber_focus->display(value);
}
void BPMDisplay::updateMax(unsigned short value)
{
ui->lcdNumber_max->display((value));
}
void BPMDisplay::updateStatus(unsigned short value)
{
ui->lcdNumber_status->display((value));
}

View File

@ -0,0 +1,80 @@
#ifndef DISPLAY_H
#define DISPLAY_H
#include <QDialog>
#include <QVector>
#include <QRadioButton>
#include <QButtonGroup>
#include <QTextStream>
#include <QFile>
#include <QCheckBox>
#include <QLCDNumber>
namespace Ui {
class display;
}
class BPMDisplay : public QDialog
{
Q_OBJECT
public:
explicit BPMDisplay(QWidget *parent = 0);
~BPMDisplay();
void plot(const QVector<signed short> &data);
void plot();
void plot(const QVector<signed short> &data, const QVector<signed short> &rmsdata);
void setTitle(QString title);
QVector<signed short> buffer;
QVector<signed short> rmsbuffer;
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);
void updateMean(unsigned short value);
void updateRms(unsigned short value);
void updateMax(unsigned short value);
void updateStatus(unsigned short value);
protected:
int nrPoints = 0;
QVector<double> dataX;
QVector<double> dataY;
QVector<signed short> dataRMS;
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<float>> calibrationDataMap; // Map to store calibration data for each plane
bool applyCalibration = false; // Flag to track if calibration should be applied
QVector<float> calibrationData; // Stores the loaded calibration data
QCheckBox *checkBoxExpertMode; // Expert Mode checkbox
bool expertModeEnabled = false; // Flag to track if expert mode is enabled
QLCDNumber * lcdNumber_mean;
QLCDNumber * lcdNumber_focus;
QLCDNumber * lcdNumber_max;
QLCDNumber * lcdNumber_status;
};
#endif // DISPLAY_H

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<unsigned short> &data);
void plot();
void setTitle(QString title);
QVector<unsigned 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<unsigned short>> backgroundDataMap; // Map to store background data for each plane
bool subtractBackground = false; // Flag to track if background subtraction is enabled
QMap<QString, QVector<unsigned short>> calibrationDataMap; // Map to store calibration data for each plane
bool applyCalibration = false; // Flag to track if calibration should be applied
QVector<unsigned 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

439
hit2023v2_RAWCAL/display.ui Normal file
View File

@ -0,0 +1,439 @@
<?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>463</height>
</rect>
</property>
<property name="sizePolicy">
<sizepolicy hsizetype="Maximum" vsizetype="Preferred">
<horstretch>0</horstretch>
<verstretch>0</verstretch>
</sizepolicy>
</property>
<property name="windowTitle">
<string>Online BPMDisplay</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>410</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>
</layout>
</widget>
<widget class="QWidget" name="horizontalLayoutWidget_2">
<property name="geometry">
<rect>
<x>10</x>
<y>370</y>
<width>581</width>
<height>41</height>
</rect>
</property>
<layout class="QHBoxLayout" name="horizontalLayout_5">
<item>
<widget class="QFrame" name="frame">
<property name="frameShape">
<enum>QFrame::WinPanel</enum>
</property>
<property name="frameShadow">
<enum>QFrame::Sunken</enum>
</property>
<widget class="QLCDNumber" name="lcdNumber_mean">
<property name="geometry">
<rect>
<x>50</x>
<y>0</y>
<width>91</width>
<height>41</height>
</rect>
</property>
<property name="frameShape">
<enum>QFrame::NoFrame</enum>
</property>
<property name="frameShadow">
<enum>QFrame::Plain</enum>
</property>
<property name="smallDecimalPoint">
<bool>true</bool>
</property>
<property name="value" stdset="0">
<double>0.000000000000000</double>
</property>
<property name="intValue" stdset="0">
<number>0</number>
</property>
</widget>
<widget class="QLabel" name="label">
<property name="geometry">
<rect>
<x>10</x>
<y>10</y>
<width>61</width>
<height>21</height>
</rect>
</property>
<property name="font">
<font>
<pointsize>12</pointsize>
</font>
</property>
<property name="text">
<string>MEAN</string>
</property>
<property name="textFormat">
<enum>Qt::RichText</enum>
</property>
<property name="scaledContents">
<bool>true</bool>
</property>
</widget>
</widget>
</item>
<item>
<widget class="QFrame" name="frame_4">
<property name="frameShape">
<enum>QFrame::StyledPanel</enum>
</property>
<property name="frameShadow">
<enum>QFrame::Raised</enum>
</property>
<widget class="QLabel" name="label_4">
<property name="geometry">
<rect>
<x>0</x>
<y>10</y>
<width>61</width>
<height>21</height>
</rect>
</property>
<property name="font">
<font>
<pointsize>12</pointsize>
</font>
</property>
<property name="text">
<string>Status</string>
</property>
<property name="textFormat">
<enum>Qt::RichText</enum>
</property>
<property name="scaledContents">
<bool>true</bool>
</property>
</widget>
<widget class="QLCDNumber" name="lcdNumber_status">
<property name="geometry">
<rect>
<x>50</x>
<y>0</y>
<width>91</width>
<height>41</height>
</rect>
</property>
<property name="frameShape">
<enum>QFrame::NoFrame</enum>
</property>
<property name="frameShadow">
<enum>QFrame::Plain</enum>
</property>
<property name="smallDecimalPoint">
<bool>true</bool>
</property>
<property name="value" stdset="0">
<double>0.000000000000000</double>
</property>
<property name="intValue" stdset="0">
<number>0</number>
</property>
</widget>
</widget>
</item>
<item>
<widget class="QFrame" name="frame_3">
<property name="frameShape">
<enum>QFrame::WinPanel</enum>
</property>
<property name="frameShadow">
<enum>QFrame::Sunken</enum>
</property>
<widget class="QLCDNumber" name="lcdNumber_focus">
<property name="geometry">
<rect>
<x>60</x>
<y>0</y>
<width>71</width>
<height>41</height>
</rect>
</property>
<property name="frameShape">
<enum>QFrame::NoFrame</enum>
</property>
<property name="frameShadow">
<enum>QFrame::Plain</enum>
</property>
</widget>
<widget class="QLabel" name="label_2">
<property name="geometry">
<rect>
<x>8</x>
<y>10</y>
<width>61</width>
<height>21</height>
</rect>
</property>
<property name="font">
<font>
<pointsize>12</pointsize>
</font>
</property>
<property name="text">
<string>FOCUS</string>
</property>
</widget>
</widget>
</item>
<item>
<widget class="QFrame" name="frame_2">
<property name="frameShape">
<enum>QFrame::WinPanel</enum>
</property>
<property name="frameShadow">
<enum>QFrame::Sunken</enum>
</property>
<widget class="QLCDNumber" name="lcdNumber_max">
<property name="geometry">
<rect>
<x>50</x>
<y>0</y>
<width>71</width>
<height>41</height>
</rect>
</property>
<property name="font">
<font>
<family>Arial</family>
<pointsize>8</pointsize>
</font>
</property>
<property name="frameShape">
<enum>QFrame::NoFrame</enum>
</property>
</widget>
<widget class="QLabel" name="label_3">
<property name="geometry">
<rect>
<x>8</x>
<y>10</y>
<width>61</width>
<height>21</height>
</rect>
</property>
<property name="font">
<font>
<pointsize>12</pointsize>
</font>
</property>
<property name="text">
<string>MAX</string>
</property>
</widget>
</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,136 @@
#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++)
{
BPMDisplay* newDisplay = new BPMDisplay;
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);
displays[plane]->rmsbuffer.resize(4);
//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;
displays[plane]->rmsbuffer[0] = lastFrame[dev_id].rms_frame.mean;
displays[plane]->rmsbuffer[1] = lastFrame[dev_id].rms_frame.sigma;
displays[plane]->rmsbuffer[2] = lastFrame[dev_id].rms_frame.max;
displays[plane]->rmsbuffer[3] = lastFrame[dev_id].rms_frame.status;
}
//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<BPMDisplay*> displays;
PlaneConfig *findPlane(int plane_nr);
};
#endif // DISPLAYSERVER_H

View File

@ -0,0 +1,389 @@
#include "eventbuilder.h"
#include "hit_analyse_v2.h"
#include <QTime>
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();
//get the network thread
}
EventBuilder::~EventBuilder()
{
deinit();
thread.quit();
thread.wait();
// networkThread.stopThread();
// networkThread.wait(); // Wait for the network thread to finish gracefully
}
//************************* Data processing framework ********************
//main processing slot
void EventBuilder::onNewData(DataReceiver* receiver)
{
short * newcopy_sensor_data = new short int[320];
while (checkBufferOccupancies())
{
//find lowest global sync value
int lowest_id = findLowestId();
//get and validate data from buffers
for (int dev_nr = 0; dev_nr < nrReceivers; dev_nr++)
{
BufferData data = receivers[dev_nr]->dataBuffer.look();
if (data.sync_frame.global_ctr == lowest_id)
{
receivers[dev_nr]->dataBuffer.dump(); //right data, dump it from the buffer
}
else
{
data.sync_frame.data_ok = 0; //wrong data, mark as bad
}
//store data for complete frame
currentFrame[dev_nr] = data;
}
lastFrameMutex.lock();
//************ 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.
if (newDataSemaphore.available() == 1){
frame_counter++;
if (frame_counter<=32){
for (unsigned int dev_nr = 0; dev_nr < nrReceivers; dev_nr++){
if (frame_counter<=1) backgroundFrame[dev_nr].resize(channelCounts[dev_nr]);
// backgroundFrame[dev_nr].sensor_data = currentFrame[dev_nr].sensor_data;
// addArrays(backgroundFrame[dev_nr].sensor_data, currentFrame[dev_nr].sensor_data, channelCounts[dev_nr]);
// std::cerr << " set bkg" << std::endl;
}
}
else if (frame_counter==33){
for (unsigned int dev_nr = 0; dev_nr < nrReceivers; dev_nr++){
for (int i = 0; i < channelCounts[dev_nr]; ++i) {
// backgroundFrame[dev_nr].sensor_data[i] /= 32; // Right-shift by 5 positions (equivalent to dividing by 32)
}
}
}
else if (frame_counter>33){
HIT_ANALYSE_V2 hit_analyse_v2;//create the object
QString dataString;
for (unsigned int dev_nr = 0; dev_nr < nrReceivers; dev_nr++){
// subtractArrays(currentFrame[dev_nr].sensor_data, backgroundFrame[dev_nr].sensor_data, channelCounts[dev_nr], newcopy_sensor_data );
// std::cerr << currentFrame[dev_nr].sensor_data[0] << " " << backgroundFrame[dev_nr].sensor_data[0] << " " << channelCounts[dev_nr] << " " << newcopy_sensor_data[0] << std::endl;
// for (unsigned int dev_nrsim = 0; dev_nrsim < 3; dev_nrsim++){
//simulate 6 planes instead of just 2
// for (unsigned int dev_nr = 0; dev_nr < nrReceivers; dev_nr++){
// dataString += hit_analyse_v2.analyseBeamData(newcopy_sensor_data, dev_nr, channelCounts[dev_nr]);
// dataString += char(nrReceivers);
//}
// if (frame_counter%1000==0) std::cerr << dataString.toStdString() << std::endl;
}
}
}
/*
//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();
}
*/
// }
// QTime currentTime = QTime::currentTime();
//Calculate the time since midnight in milliseconds
// int millisecondsSinceMidnight = currentTime.msecsSinceStartOfDay();
// dataString += QString::number(millisecondsSinceMidnight);
// receiveData(dataString.toUtf8());
if (newDataSemaphore.available() == 0)
newDataSemaphore.release(1);
lastFrame = currentFrame;
lastFrameMutex.unlock();
//log data
if (loggingData) logDataToFile();
}
}
//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 4 unsigned shorts and 2 int)
* - Data D = Cn x unsigned short
* - RMSframe R = 1 x RMSframe(== 8 unsigned shorts == 16 bytes)
*/
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(unsigned short));
logFile.write((const char*)&(currentFrame[board].rms_frame), sizeof(RMSFrame));
}
//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();
}
void EventBuilder::receiveData(const QByteArray &data)
{
QMutexLocker locker(&mutex);
dataQueue.enqueue(data);
QString dataString = QString(data);
// std::cerr << dataString.toStdString() << std::endl;
dataAvailable.wakeOne();
}
QByteArray EventBuilder::getNextData()
{
QMutexLocker locker(&mutex);
if (dataQueue.isEmpty())
return QByteArray(); // Return an empty QByteArray if no data is available
return dataQueue.dequeue();
}

View File

@ -0,0 +1,115 @@
#ifndef EVENTBUILDER_H
#define EVENTBUILDER_H
#include <QObject>
#include <QVector>
#include <QList>
#include <QFile>
#include <QThread>
#include <QMutex>
#include <QMutexLocker>
#include <QQueue>
#include <QWaitCondition>
//#include "hw.h"
#include "datareceiver.h"
#include "histogram.h"
#include <immintrin.h> // Include for Intel Intrinsics
#include <emmintrin.h> // Include for SSE2
//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
// Define a signal to notify when postdata is updated
void dataReady(const QByteArray& data); // Define a signal for data readiness
public slots:
void onNewData(DataReceiver *receiver);
// Add a public slot to receive and store data
void receiveData(const QByteArray &data);
// Add a method to get data from the queue
QByteArray getNextData();
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;
signed short * copy_sensor_data;
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 long int frame_counter = 0;
double intensity = 0.0;
double position = 0.0;
double focus = 0.0;
QQueue<QByteArray> dataQueue;
QMutex mutex;
QWaitCondition dataAvailable;
};
#endif // EVENTBUILDER_H

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();
}

View File

@ -0,0 +1,50 @@
#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) ( ((unsigned short)(unsigned char)((by)[0]) << 8) | ((unsigned short)(unsigned char)((by)[1])) ) //safe way
#define BYTES2SIGNSHORT(by) ( *((signed short*)by) ) //faster
#define BYTES2SIGNEDSHORT(by) \
( \
(static_cast<short>(static_cast<unsigned char>((by)[0])) << 8) | \
(static_cast<short>(static_cast<unsigned char>((by)[1]))) \
)
//convert textual representation of IP to array of numbers and/or well-formatted string
#define BYTES2INT(by) \
( \
(static_cast<unsigned char>((by)[0]) << 24) | \
(static_cast<unsigned char>((by)[1]) << 16) | \
(static_cast<unsigned char>((by)[2]) << 8) | \
(static_cast<unsigned char>((by)[3]))\
)
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

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 );
}

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,87 @@
#-------------------------------------------------
#
# Project created by QtCreator 2017-08-21T15:59:19
#
#-------------------------------------------------
QT += core gui network serialport
#CONFIG += static
unix {
QMAKE_CXXFLAGS += -W -std=c++17
}
win32 {
QMAKE_CXXFLAGS += -Wa,-mbig-obj -std=c++17
}
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
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 \
networkthread.h \
qcustomplot.h \
display.h \
displayserver.h \
keithley.h \
keithley_thr.h \
dialoglinearity.h \
histogram.h \
dialogtiscan.h \
dialogprofiler.h \
stepper.h \
dialogbeta.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,236 @@
#include "hit_analyse_v2.h"
#include <random>
#include <immintrin.h> // Include for Intel Intrinsics
HIT_ANALYSE_V2::HIT_ANALYSE_V2(QObject *parent) : QObject(parent)
{
}
// Define your own functions for matrix operations
struct Matrix2x2 {
double data[2][2];
};
Matrix2x2 InvertMatrix2x2(const Matrix2x2& mat) {
Matrix2x2 result;
double det = mat.data[0][0] * mat.data[1][1] - mat.data[0][1] * mat.data[1][0];
if (det != 0.0) {
double invDet = 1.0 / det;
result.data[0][0] = mat.data[1][1] * invDet;
result.data[0][1] = -mat.data[0][1] * invDet;
result.data[1][0] = -mat.data[1][0] * invDet;
result.data[1][1] = mat.data[0][0] * invDet;
} else {
// Handle the case when the matrix is not invertible
// You might want to implement error handling here.
std::cerr << "Matrix not invertible! " << std::endl;
}
return result;
}
struct Vector2 {
double data[2];
};
QString HIT_ANALYSE_V2::analyseBeamData(short int * signal_list, const int dev_nr, const int vector_length)
{
double position=100;
double focus=8;
double intensity=1000.0;
QString dataString;
// Fill arr1 and arr2 with your data
std::vector<double> channel_list;
std::vector<double> short_signal_list;
std::vector<double> short_channel_list;
channel_list = fixed_channel;
// Create a vector to store the generated values
// std::vector<short int> result(vector_length);
// Fill the vector with random noise values
//add a gaussian profile, focus is FWHM, position is random between 50 and 250
bool fixeddata = false ;
if (fixeddata){
// signal_list = (short int)fixedsignalarray;
bool dummy = true;
}
else
{
// signal_list = dataframe[dev_nr].sensor_data;
bool dummy = false;
}
// std::cerr << signal_list[0] << " " << dev_nr << std::endl;
double SumArea = 0.0, SumY2 = 0.0, SumXY2 = 0.0, SumX2Y2 = 0.0, SumX3Y2 = 0.0;
double SumY2LnY = 0.0, SumXY2LnY = 0.0, Ymax = 0.0, Pomax = 0.0;
double fac_c = 0.0, Yn = 0.0, sigma = 0.0, amp = 0.0;
double SumYYP = 0.0, SumYYM = 0.0, MeanY = 0.0, window_start = 0.0, window_end = 0.0;
// ...
Matrix2x2 M1, M1inv;
Vector2 ABC, M2;
for (int i = 0; i < vector_length; i++) {
std::cerr<< signal_list[i] << " ";
if (signal_list[i] > Ymax) {
Ymax = signal_list[i];
Pomax = channel_list[i];
}
if (i > 0 && signal_list[i] > 34) {
SumArea += signal_list[i] * (channel_list[i] - channel_list[i - 1]);
}
}
std::cerr<< std::endl;
// Estimate sigma
sigma = SumArea / Ymax / 2.5066;
// Set a +-3 sigma window
window_start = Pomax - 3 * sigma;
window_end = Pomax + 3 * sigma;
std::cerr<< Pomax << " " << Ymax << " " << sigma << std::endl;
for (int i = 0; i < vector_length; i++) {
if (signal_list[i] > 34 && channel_list[i] > window_start && channel_list[i] < window_end) {
short_signal_list.push_back(signal_list[i]);
short_channel_list.push_back(channel_list[i]);
}
}
//signal_list.clear();
//channel_list.clear();
// Recalculate SumArea using the sieved data
SumArea = 0.0;
for (int i = 1; i < short_signal_list.size(); i++) {
SumArea += short_signal_list[i] * (short_channel_list[i] - short_channel_list[i - 1]);
}
const int shortlist_length = short_channel_list.size();
if (shortlist_length <= 3) {
intensity = -1;
focus = -1;
position = -128;
dataString += QString::number(intensity) + ',' + QString::number(position) + ',' + QString::number(focus)
+ ',' + QString::number(0);
return dataString;
}
// Re-Estimate sigma
sigma = SumArea / Ymax / 2.5066;
fac_c = -1.0 / (2.0 * sigma * sigma);
// std::cerr << sigma << std::endl;
for(int k=0; k<shortlist_length;k++){
SumY2 += short_signal_list[k]*short_signal_list[k];
SumXY2 += short_signal_list[k]*short_signal_list[k]*short_channel_list[k];
SumX2Y2 += short_signal_list[k]*short_signal_list[k]*short_channel_list[k]*short_channel_list[k];
SumX3Y2 += short_signal_list[k]*short_signal_list[k]*short_channel_list[k]*short_channel_list[k]*short_channel_list[k];
SumY2LnY += short_signal_list[k]*short_signal_list[k]*log(short_signal_list[k]);
SumXY2LnY += short_channel_list[k]*short_signal_list[k]*short_signal_list[k]*log(short_signal_list[k]);
// std::cerr<< shortlist_length << " " << short_channel_list[k] << " " << short_signal_list[k] << " " << short_signal_list[k] << " " << log(short_signal_list[k]) << std::endl;
MeanY+=short_signal_list[k];
}
MeanY/=shortlist_length;
// Use custom matrix and vector functions for calculations
M1.data[0][0] = SumY2;
M1.data[0][1] = SumXY2;
M1.data[1][0] = SumXY2;
M1.data[1][1] = SumX2Y2;
// std::cerr << M1.data[0][0] << " " << M1.data[0][1] << " " << M1.data[1][0] << " " << M1.data[1][1] << std::endl;
M2.data[0] = SumY2LnY - fac_c * SumX2Y2;
M2.data[1] = SumXY2LnY - fac_c * SumX3Y2;
// std::cerr << M2.data[0] << " " << M2.data[1] << std::endl;
M1inv = InvertMatrix2x2(M1);
ABC.data[0] = M1inv.data[0][0] * M2.data[0] + M1inv.data[0][1] * M2.data[1];
ABC.data[1] = M1inv.data[1][0] * M2.data[0] + M1inv.data[1][1] * M2.data[1];
// std::cerr << ABC.data[0] << " " << ABC.data[1] << std::endl;
//iterate to improve the fit.
int N_iter = 1;
for (int i = 0; i < N_iter; i++) {
SumY2 = 0.0;
SumXY2 = 0.0;
SumX2Y2 = 0.0;
SumX3Y2 = 0.0;
SumY2LnY = 0.0;
SumXY2LnY = 0.0;
for (int k = 0; k < shortlist_length; k++) {
Yn = exp(ABC.data[0] + ABC.data[1] * short_channel_list[k] + fac_c * short_channel_list[k] * short_channel_list[k]);
SumY2 += Yn * Yn;
SumXY2 += Yn * Yn * short_channel_list[k];
SumX2Y2 += Yn * Yn * short_channel_list[k] * short_channel_list[k];
SumX3Y2 += Yn * Yn * short_channel_list[k] * short_channel_list[k] * short_channel_list[k];
SumY2LnY += Yn * Yn * log(short_signal_list[k]);
SumXY2LnY += short_channel_list[k] * Yn * Yn * log(short_signal_list[k]);
}
M1.data[0][0] = SumY2;
M1.data[0][1] = SumXY2;
M1.data[1][0] = SumXY2;
M1.data[1][1] = SumX2Y2;
M2.data[0] = SumY2LnY - fac_c * SumX2Y2;
M2.data[1] = SumXY2LnY - fac_c * SumX3Y2;
M1inv = InvertMatrix2x2(M1);
ABC.data[0] = M1inv.data[0][0] * M2.data[0] + M1inv.data[0][1] * M2.data[1];
ABC.data[1] = M1inv.data[1][0] * M2.data[0] + M1inv.data[1][1] * M2.data[1];
}
position = -ABC.data[1]/fac_c/2;
amp = exp(ABC.data[0]-ABC.data[1]*ABC.data[1]/4/fac_c);
sigma=SumArea/amp/2.5066;
// cout << sigma << " " << mean << " " << amp << endl;
for(int k=0; k<shortlist_length;k++){
SumYYM+= (short_signal_list[k]-MeanY)*(short_signal_list[k]-MeanY);
SumYYP+= (amp*exp(-(short_channel_list[k]-position)*(short_channel_list[k]-position)/2/(sigma*sigma)) - MeanY )*(amp*exp(-(short_channel_list[k]-position)*(short_channel_list[k]-position)/2/(sigma*sigma)) - MeanY );
}
focus = 2.3548*sigma;
intensity = amp;
double R_squared = SumYYP/SumYYM;
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,337 @@
#include "hit_analyse_v2.h"
#include <random>
HIT_ANALYSE_V2::HIT_ANALYSE_V2(QObject *parent) : QObject(parent)
{
}
// Define your own functions for matrix operations
struct Matrix2x2 {
double data[2][2];
};
Matrix2x2 InvertMatrix2x2(const Matrix2x2& mat) {
Matrix2x2 result;
double det = mat.data[0][0] * mat.data[1][1] - mat.data[0][1] * mat.data[1][0];
if (det != 0.0) {
double invDet = 1.0 / det;
result.data[0][0] = mat.data[1][1] * invDet;
result.data[0][1] = -mat.data[0][1] * invDet;
result.data[1][0] = -mat.data[1][0] * invDet;
result.data[1][1] = mat.data[0][0] * invDet;
} else {
// Handle the case when the matrix is not invertible
// You might want to implement error handling here.
std::cerr << "Matrix not invertible! " << std::endl;
}
return result;
}
struct Vector2 {
double data[2];
};
QString HIT_ANALYSE_V2::analyseBeamData(QVector<BufferData> dataframe, const int dev_nr, const int vector_length){
double position=100;
double focus=8;
double intensity=1000.0;
QString dataString;
double * signal_list;
std::vector<double> channel_list;
std::vector<double> short_signal_list;
std::vector<double> short_channel_list;
// 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 noise values
//add a gaussian profile, focus is FWHM, position is random between 50 and 250
bool fixeddata = false;
if (!fixeddata){
position = 100;// + (rand() % (int)(250 - 50 + 1));
signal_list = (double*)(dataframe[dev_nr].sensor_data);
channel_list = fixed_channel;
for (int i = int(position) - (int)(focus); i < int(position) + (int)(focus) ; i++) {
// double randomValue = dist(gen);
// signal_list[i] = static_cast<short int>(std::round(randomValue));
// signal_list[i] = dataframe[dev_nr].sensor_data[i];
//channel_list[i] = i;
signal_list[i] += static_cast<short int>(std::round(intensity*exp(-4*log(2)*pow((channel_list[i]-position)/focus,2))));
// std::cerr << channel_list[i] << ", ";
}
// std::cerr <<std::endl;
}
else{
signal_list = fixedsignalarray;
channel_list = fixed_channel;
}
/*
// 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;
*/
double SumArea = 0.0, SumY2 = 0.0, SumXY2 = 0.0, SumX2Y2 = 0.0, SumX3Y2 = 0.0;
double SumY2LnY = 0.0, SumXY2LnY = 0.0, Ymax = 0.0, Pomax = 0.0;
double fac_c = 0.0, Yn = 0.0, sigma = 0.0, amp = 0.0;
double SumYYP = 0.0, SumYYM = 0.0, MeanY = 0.0, window_start = 0.0, window_end = 0.0;
// ...
Matrix2x2 M1, M1inv;
Vector2 ABC, M2;
for (int i = 0; i < vector_length; i++) {
if (signal_list[i] > Ymax) {
Ymax = signal_list[i];
Pomax = channel_list[i];
}
if (i > 0 && signal_list[i] > 34) {
SumArea += signal_list[i] * (channel_list[i] - channel_list[i - 1]);
}
}
// Estimate sigma
sigma = SumArea / Ymax / 2.5066;
// Set a +-3 sigma window
window_start = Pomax - 3 * sigma;
window_end = Pomax + 3 * sigma;
// std::cerr<< Pomax << " " << Ymax << " " << sigma << std::endl;
for (int i = 0; i < vector_length; i++) {
if (signal_list[i] > 34 && channel_list[i] > window_start && channel_list[i] < window_end) {
short_signal_list.push_back(signal_list[i]);
short_channel_list.push_back(channel_list[i]);
}
}
//signal_list.clear();
//channel_list.clear();
// Recalculate SumArea using the sieved data
SumArea = 0.0;
for (int i = 1; i < short_signal_list.size(); i++) {
SumArea += short_signal_list[i] * (short_channel_list[i] - short_channel_list[i - 1]);
}
const int shortlist_length = short_channel_list.size();
if (shortlist_length <= 3) {
intensity = -1;
focus = -1;
position = -128;
dataString += QString::number(intensity) + ',' + QString::number(position) + ',' + QString::number(focus)
+ ',' + QString::number(0);
return dataString;
}
// Re-Estimate sigma
sigma = SumArea / Ymax / 2.5066;
fac_c = -1.0 / (2.0 * sigma * sigma);
// std::cerr << sigma << std::endl;
for(int k=0; k<shortlist_length;k++){
SumY2 += short_signal_list[k]*short_signal_list[k];
SumXY2 += short_signal_list[k]*short_signal_list[k]*short_channel_list[k];
SumX2Y2 += short_signal_list[k]*short_signal_list[k]*short_channel_list[k]*short_channel_list[k];
SumX3Y2 += short_signal_list[k]*short_signal_list[k]*short_channel_list[k]*short_channel_list[k]*short_channel_list[k];
SumY2LnY += short_signal_list[k]*short_signal_list[k]*log(short_signal_list[k]);
SumXY2LnY += short_channel_list[k]*short_signal_list[k]*short_signal_list[k]*log(short_signal_list[k]);
// std::cerr<< shortlist_length << " " << short_channel_list[k] << " " << short_signal_list[k] << " " << short_signal_list[k] << " " << log(short_signal_list[k]) << std::endl;
MeanY+=short_signal_list[k];
}
MeanY/=shortlist_length;
// Use custom matrix and vector functions for calculations
M1.data[0][0] = SumY2;
M1.data[0][1] = SumXY2;
M1.data[1][0] = SumXY2;
M1.data[1][1] = SumX2Y2;
// std::cerr << M1.data[0][0] << " " << M1.data[0][1] << " " << M1.data[1][0] << " " << M1.data[1][1] << std::endl;
M2.data[0] = SumY2LnY - fac_c * SumX2Y2;
M2.data[1] = SumXY2LnY - fac_c * SumX3Y2;
// std::cerr << M2.data[0] << " " << M2.data[1] << std::endl;
M1inv = InvertMatrix2x2(M1);
ABC.data[0] = M1inv.data[0][0] * M2.data[0] + M1inv.data[0][1] * M2.data[1];
ABC.data[1] = M1inv.data[1][0] * M2.data[0] + M1inv.data[1][1] * M2.data[1];
// std::cerr << ABC.data[0] << " " << ABC.data[1] << std::endl;
//iterate to improve the fit.
int N_iter = 1;
for (int i = 0; i < N_iter; i++) {
SumY2 = 0.0;
SumXY2 = 0.0;
SumX2Y2 = 0.0;
SumX3Y2 = 0.0;
SumY2LnY = 0.0;
SumXY2LnY = 0.0;
for (int k = 0; k < shortlist_length; k++) {
Yn = exp(ABC.data[0] + ABC.data[1] * short_channel_list[k] + fac_c * short_channel_list[k] * short_channel_list[k]);
SumY2 += Yn * Yn;
SumXY2 += Yn * Yn * short_channel_list[k];
SumX2Y2 += Yn * Yn * short_channel_list[k] * short_channel_list[k];
SumX3Y2 += Yn * Yn * short_channel_list[k] * short_channel_list[k] * short_channel_list[k];
SumY2LnY += Yn * Yn * log(short_signal_list[k]);
SumXY2LnY += short_channel_list[k] * Yn * Yn * log(short_signal_list[k]);
}
M1.data[0][0] = SumY2;
M1.data[0][1] = SumXY2;
M1.data[1][0] = SumXY2;
M1.data[1][1] = SumX2Y2;
M2.data[0] = SumY2LnY - fac_c * SumX2Y2;
M2.data[1] = SumXY2LnY - fac_c * SumX3Y2;
M1inv = InvertMatrix2x2(M1);
ABC.data[0] = M1inv.data[0][0] * M2.data[0] + M1inv.data[0][1] * M2.data[1];
ABC.data[1] = M1inv.data[1][0] * M2.data[0] + M1inv.data[1][1] * M2.data[1];
}
position = -ABC.data[1]/fac_c/2;
amp = exp(ABC.data[0]-ABC.data[1]*ABC.data[1]/4/fac_c);
sigma=SumArea/amp/2.5066;
// cout << sigma << " " << mean << " " << amp << endl;
for(int k=0; k<shortlist_length;k++){
SumYYM+= (short_signal_list[k]-MeanY)*(short_signal_list[k]-MeanY);
SumYYP+= (amp*exp(-(short_channel_list[k]-position)*(short_channel_list[k]-position)/2/(sigma*sigma)) - MeanY )*(amp*exp(-(short_channel_list[k]-position)*(short_channel_list[k]-position)/2/(sigma*sigma)) - MeanY );
}
focus = 2.3548*sigma;
intensity = amp;
double R_squared = SumYYP/SumYYM;
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,81 @@
#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;
};
double fixedsignalarray[300] = {-13, -7, -12, 22, -6, 0, 22, 5, 8, 11, 25, -10, 11, 13, 32, -4, -2, -37, -21, 23, 13, 26, 11, -24, 1, -6, -6, 1, 22, 30, -21, -3, 11, -2, -11, 5, -2, 31, 24, 4, -17, 24, -24, 20, 31, -6, -1, -4, -10, -26, -12, -19, -7, -39, 1, 19, 3, -13, 37, 2, 11, -10, -14, 20, 14, -1, -13, 13, -18, -18, -15, -25, 14, 11, -32, 50, 18, -11, 26, 4, 4, -2, -10, 34, 6, 36, -9, 19, -3, 7, -10, -15, 4, 24, -3, 2, 13, -34, -28, -25, -4, -14, -11, 23, -19, -7, -6, 6, 23, 7, -21, 18, -8, 6, 21, -4, 3, -1, -11, 7, -38, -38, -12, -11, -11, 9, -11, -7, 2, -1, 19, 12, 0, -7, 15, 3, 28, -8, 1, 8, 2, -4, 4, 23, 31, -17, 8, 11, 34, 1, 7, 14, 14, 16, -1, -30, -2, 19, -20, -4, -9, 15, -6, -4, -4, 10, -27, -18, 24, 19, 20, 22, 68, 122, 234, 371, 496, 713, 840, 967, 1026, 957, 833, 674, 485, 317, 194, 98, 70, 45, 34, -15, 3, 10, 12, -19, 11, 27, -1, 2, -9, -1, -2, -15, -22, 7, 0, -20, -1, -7, 21, -4, -21, 21, -6, 23, -4, -2, -28, -17, -13, 1, 19, 20, 6, 10, -25, -4, 5, -14, -18, -4, 12, 7, -21, 7, -10, 10, 11, -21, 7, -6, -2, -3, 1, 16, 4, -23, 2, 14, 0, -5, -7, -12, -2, -8, -20, 11, 21, -5, -5, 20, -10, 3, -18, -5, 4, 6, 4, -21, -3, -26, -15, -7, -14, -10, -14, 7, -18, -2, -14, 36, -10, 11, 9, 3, -7, -51, -12, 2, 5, 9, 15, 20, -23, -6, -14, -4, 16, 4};
const std::vector<std::vector<double>> fixed_signal =
{
{-13, -7, -12, 22, -6, 0, 22, 5, 8, 11, 25, -10, 11, 13, 32, -4, -2, -37, -21, 23, 13, 26, 11, -24, 1, -6, -6, 1, 22, 30, -21, -3, 11, -2, -11, 5, -2, 31, 24, 4, -17, 24, -24, 20, 31, -6, -1, -4, -10, -26, -12, -19, -7, -39, 1, 19, 3, -13, 37, 2, 11, -10, -14, 20, 14, -1, -13, 13, -18, -18, -15, -25, 14, 11, -32, 50, 18, -11, 26, 4, 4, -2, -10, 34, 6, 36, -9, 19, -3, 7, -10, -15, 4, 24, -3, 2, 13, -34, -28, -25, -4, -14, -11, 23, -19, -7, -6, 6, 23, 7, -21, 18, -8, 6, 21, -4, 3, -1, -11, 7, -38, -38, -12, -11, -11, 9, -11, -7, 2, -1, 19, 12, 0, -7, 15, 3, 28, -8, 1, 8, 2, -4, 4, 23, 31, -17, 8, 11, 34, 1, 7, 14, 14, 16, -1, -30, -2, 19, -20, -4, -9, 15, -6, -4, -4, 10, -27, -18, 24, 19, 20, 22, 68, 122, 234, 371, 496, 713, 840, 967, 1026, 957, 833, 674, 485, 317, 194, 98, 70, 45, 34, -15, 3, 10, 12, -19, 11, 27, -1, 2, -9, -1, -2, -15, -22, 7, 0, -20, -1, -7, 21, -4, -21, 21, -6, 23, -4, -2, -28, -17, -13, 1, 19, 20, 6, 10, -25, -4, 5, -14, -18, -4, 12, 7, -21, 7, -10, 10, 11, -21, 7, -6, -2, -3, 1, 16, 4, -23, 2, 14, 0, -5, -7, -12, -2, -8, -20, 11, 21, -5, -5, 20, -10, 3, -18, -5, 4, 6, 4, -21, -3, -26, -15, -7, -14, -10, -14, 7, -18, -2, -14, 36, -10, 11, 9, 3, -7, -51, -12, 2, 5, 9, 15, 20, -23, -6, -14, -4, 16, 4}
,{-9, -1, -32, 19, 12, -13, 7, 7, -18, -5, 19, 15, 5, -5, -27, 4, -7, 7, -16, -9, -4, -6, -2, 27, 23, 15, -16, -23, 25, 4, 26, -17, -9, -1, 14, -9, -15, -29, -40, 5, 22, 14, 23, -25, 9, -16, -26, -4, -31, -6, -27, 1, 23, 24, 26, 61, 133, 222, 301, 501, 690, 822, 972, 980, 966, 852, 685, 486, 333, 239, 107, 54, 29, 19, 9, 1, 1, 6, 9, 14, -8, -5, 11, 21, -6, -17, -7, 11, 30, -3, 6, -4, 2, 18, -18, 4, -2, 18, 16, 17, 5, -15, -14, 24, -36, -19, 7, -22, -3, -15, -11, -4, -11, 13, -5, -6, 12, 8, 21, -24, -10, -10, -7, 5, 30, -16, -18, -3, -23, 3, -20, -3, 24, 8, -15, -1, -6, -1, -8, -25, 6, 1, -16, -11, 29, -21, 13, 11, -2, -10, 12, -13, 24, -31, 21, -7, 6, -13, 3, -6, -9, 20, -3, 2, -16, -14, 10, 6, 20, 6, 21, 9, 7, -27, 13, -17, 19, 20, -13, -11, -17, -4, 11, -24, 17, -7, -4, 26, 5, 13, 13, 4, -3, -17, -32, -14, 40, 1, -23, -28, 16, 1, 16, -4, -8, -9, 4, 2, -7, 7, -16, -23, -9, 10, 24, 0, -5, -24, -4, -22, -10, -29, 0, 2, 2, 4, -45, 4, -2, 12, 21, -22, -31, -15, 16, 2, 11, 35, 0, 3, 15, -15, -17, 20, -27, 24, 24, -6, 8, -15, 8, 26, -6, -14, 10, -20, 33, 6, -5, 1, 0, 9, 3, -33, -10, -3, 0, 11, -33, 0, 33, 25, -5, 1, 0, -32, -24, 17, 10, -2, 12, -26, 13, 7, -3, 36, 28, 10, 17, -26, 29, -15, 3, 14, -8, -9, -7, -15, -4, 0}
,{14, -3, 2, 20, 3, -9, 15, -3, 26, 3, 8, -1, -5, 13, -10, -18, -9, 35, 3, 29, -12, 37, 12, -12, -9, -34, 9, -3, -19, -3, -10, -9, 3, -1, 5, 22, 10, -10, -27, 30, -19, -26, -23, -25, 16, 4, 4, 9, -23, 5, 0, -35, -5, -21, 0, 22, 18, -42, -4, 16, 17, 41, -15, -12, 13, -5, 35, 5, -4, 19, -12, 4, 4, -2, 2, -12, -23, 5, -2, 4, 7, 5, -10, 41, -20, -2, 4, 5, -34, -19, -6, 6, -3, -12, 39, 38, 72, 104, 194, 347, 484, 666, 808, 946, 1018, 978, 838, 690, 511, 317, 211, 112, 51, 22, 0, -14, 21, -2, 12, -24, 1, -6, 18, 5, -12, 6, -3, -9, -6, -29, -31, -6, -15, -2, -22, 14, -33, 1, 3, -7, -13, 14, 21, -11, -17, -1, -9, -12, 7, 5, -2, -2, -4, -2, -12, -33, 2, 5, -2, -8, 10, 26, 2, -28, 3, -20, 10, -8, 22, 8, -25, 3, -18, -18, 19, 15, -8, 8, 24, -13, 0, -5, -15, 1, -24, -2, 3, -28, 8, 5, -5, 0, 12, 10, -5, 12, 0, -10, -5, -7, -23, -32, -3, 9, 17, -14, -12, -3, -35, -12, -5, 8, 15, -10, 13, 4, 9, 23, -21, -31, 32, 6, -3, -7, 10, -5, 25, -32, 16, -22, 18, 0, 1, -16, -13, -10, -13, 2, -20, -2, 15, 7, 17, -17, 0, 8, 43, -23, -34, -7, 45, 8, 16, 26, -7, -7, -5, 4, -20, -8, -21, 13, 4, -23, 9, 29, 1, 13, -3, -23, 3, 20, 23, 29, -7, -8, 37, -4, -23, 1, -14, -11, 9, -4, -13, -20, -20, 16, -12, 23, 31, 5, 0, 27, 2, 5, 30, -12, -10, 3}
,{-9, -15, -6, 24, -10, -12, 12, -9, -13, 1, -15, -2, -2, 0, 26, -19, -22, 7, 0, 26, 28, -13, -8, -24, 20, -1, -18, -1, -23, -21, -7, -10, 25, 29, 16, 23, -36, 9, 7, -28, -7, 1, 41, -1, -2, 14, -3, 26, -26, 20, -4, 22, 8, 50, 8, 0, -22, -8, 45, 1, -22, -24, -12, 6, 8, 26, 21, 22, -5, 1, -1, -10, -4, 22, 20, 40, -9, 11, -32, 9, -12, -3, -8, 13, 3, -4, -6, 2, 18, 6, 1, -16, 0, 33, 16, -18, -7, 27, 10, -3, 11, -10, -16, -3, 24, 1, -14, -4, 12, -11, -4, 22, 22, -21, -4, 24, 3, 12, 13, 28, -3, 27, 11, -6, 19, 8, -22, -1, 5, 0, 27, 2, -2, -12, -8, 6, 6, 9, 10, -8, 4, 40, 27, 38, 111, 200, 323, 492, 667, 834, 944, 990, 945, 861, 683, 466, 337, 205, 108, 53, 22, 0, 27, 9, -3, 37, 11, -8, -15, -16, 4, 23, 25, -14, -7, -7, -18, -7, 21, 6, 19, -12, 2, -13, -9, -8, -3, -7, -20, -27, 13, 4, -11, 16, 3, -24, 4, -23, 17, 17, -18, -25, 4, 5, -21, -10, -13, 43, 4, -1, -3, -1, -4, -4, 25, 47, 18, 21, 29, 4, -22, 16, -17, -37, -1, 12, -9, -7, 5, -4, 23, 21, -14, -17, 19, 11, 22, 39, -6, 3, 19, -25, 4, 1, -15, -8, 20, 13, -31, 5, 28, 10, 27, 9, -11, 2, 0, -20, -18, -9, 14, 9, 24, -16, -10, 29, 16, 13, 13, -22, 16, 18, 22, 20, 27, -20, 23, 6, 0, 14, -6, -6, -8, 15, -11, 23, -11, 23, -16, 16, -2, 10, 4, -22, -33, -17, -4, 4, 4, -8}
};
const std::vector<double> fixed_channel = {0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20, 21, 22, 23, 24, 25, 26, 27, 28, 29, 30, 31, 32, 33, 34, 35, 36, 37, 38, 39, 40, 41, 42, 43, 44, 45, 46, 47, 48, 49, 50, 51, 52, 53, 54, 55, 56, 57, 58, 59, 60, 61, 62, 63, 64, 65, 66, 67, 68, 69, 70, 71, 72, 73, 74, 75, 76, 77, 78, 79, 80, 81, 82, 83, 84, 85, 86, 87, 88, 89, 90, 91, 92, 93, 94, 95, 96, 97, 98, 99, 100, 101, 102, 103, 104, 105, 106, 107, 108, 109, 110, 111, 112, 113, 114, 115, 116, 117, 118, 119, 120, 121, 122, 123, 124, 125, 126, 127, 128, 129, 130, 131, 132, 133, 134, 135, 136, 137, 138, 139, 140, 141, 142, 143, 144, 145, 146, 147, 148, 149, 150, 151, 152, 153, 154, 155, 156, 157, 158, 159, 160, 161, 162, 163, 164, 165, 166, 167, 168, 169, 170, 171, 172, 173, 174, 175, 176, 177, 178, 179, 180, 181, 182, 183, 184, 185, 186, 187, 188, 189, 190, 191, 192, 193, 194, 195, 196, 197, 198, 199, 200, 201, 202, 203, 204, 205, 206, 207, 208, 209, 210, 211, 212, 213, 214, 215, 216, 217, 218, 219, 220, 221, 222, 223, 224, 225, 226, 227, 228, 229, 230, 231, 232, 233, 234, 235, 236, 237, 238, 239, 240, 241, 242, 243, 244, 245, 246, 247, 248, 249, 250, 251, 252, 253, 254, 255, 256, 257, 258, 259, 260, 261, 262, 263, 264, 265, 266, 267, 268, 269, 270, 271, 272, 273, 274, 275, 276, 277, 278, 279, 280, 281, 282, 283, 284, 285, 286, 287, 288, 289, 290, 291, 292, 293, 294, 295, 296, 297, 298, 299};
public slots:
QString analyseBeamData(short int * copysensor_data, const int dev_nr, const int vector_length);
// void processPendingDatagrams();
};
class Channel{
public:
double amplitude;;
double position;
int chnumber;
int last_neighbour;
int next_neighbour;
};
#endif // HIT_ANALYSE_V2_H

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;
};

117
hit2023v2_RAWCAL/hw.cpp Normal file
View File

@ -0,0 +1,117 @@
#include "hw.h"
HW::HW(QObject *parent) : QObject(parent), eventBuilder()// , networkThread(eventBuilder)
{
/*eventBuilder.moveToThread(&eventBuilderThread);
eventBuilderThread.start();
eventBuilder.init();*/
// Create and start the network thread
// networkThread.start();
}
HW::~HW()
{
// if (networkThread.isRunning()){
// networkThread.stopThread();
// networkThread.wait(); // Wait for the network thread to finish gracefully
// }
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.
// Start the UDP server when an instance of HW is created
//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()
{
// Application cleanup
//if (networkThread.isRunning()){
// networkThread.stopThread();
// networkThread.wait(); // Wait for the network thread to finish gracefully
// }
//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;
}

46
hit2023v2_RAWCAL/hw.h Normal file
View File

@ -0,0 +1,46 @@
#ifndef HW_H
#define HW_H
#include <QObject>
#include <QVector>
#include <QThread>
#include "device.h"
#include "eventbuilder.h"
#include "networkthread.h"
class HW : public QObject
{
Q_OBJECT
public:
public:
explicit HW(QObject *parent = 0);
~HW();
QVector<Device*> devices;
EventBuilder eventBuilder;
// NetworkThread networkThread;
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:
private:
};
#endif // HW_H

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;
}

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(&udpThread);
worker->timer.moveToThread(&udpThread);
worker->theKeithley.serialPort.moveToThread(&udpThread);
//controller -> worker
QObject::connect(&udpThread, &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);
udpThread.start();
}
keithley_thr::~keithley_thr()
{
udpThread.quit();
udpThread.wait();
}
//************************** slots for communication with worker thread ******************
//called on each current readout
void 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 udpThread;
double lastCurrentReadout;
QString portName;
int recognizeSpillState(double current);
public slots:
void 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

28
hit2023v2_RAWCAL/main.cpp Normal file
View File

@ -0,0 +1,28 @@
#include "mainwindow.h"
#include <QApplication>
int main(int argc, char *argv[])
{
QApplication a(argc, argv);
// 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,578 @@
#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(&timer, &QTimer::timeout, this, &MainWindow::on_timer);
// connect(theKeithley, keithley_thr::esig_newCurrentReadout, this, MainWindow::on_newCurrentReadout);
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();
// Retrieve device-specific settings from DialogDevices
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++) { // 4 bytes
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();
dc.threshold = deviceSettings->value("Threshold").toInt();
dc.clustersize = deviceSettings->value("ClusterSize").toInt();
// Get calibration factors for this device
// Get calibration factors from the settings
QString calibFilePath = deviceSettings->value("CalibFile").toString();
if (!calibFilePath.isEmpty()) {
// Load calibration factors from the file
loadCalibrationFactors(calibFilePath, dc.calibrationFactor);
} else {
// Default to 8192 if no calibration factors were set for this device
std::fill(std::begin(dc.calibrationFactor), std::end(dc.calibrationFactor), 8192);
}
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
}
}
// Provide a function to load calibration factors from a file
bool MainWindow::loadCalibrationFactors(const QString& filePath, int* calibrationFactors)
{
QFile file(filePath);
if (!file.open(QIODevice::ReadOnly | QIODevice::Text)) {
qWarning() << "Could not open calibration file:" << filePath;
return false;
}
QTextStream in(&file);
int index = 0;
bool allValid = true;
while (!in.atEnd() && index < 320) {
QString line = in.readLine().trimmed();
bool ok;
int value = line.toInt(&ok);
// Validate that value is within the range of an unsigned short
if (ok && value >= 0 && value <= 65535) {
calibrationFactors[index] = value;
} else {
qWarning() << "Invalid calibration factor:" << line << "at index" << index;
calibrationFactors[index] = 8192; // Default to 8192 if invalid
allValid = false;
}
index++;
}
// If file has fewer than 320 lines, fill the rest with default values
while (index < 320) {
calibrationFactors[index++] = 8192;
}
file.close();
return allValid;
}
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::startAnalysing(){
if (analysing)
stopAnalysing();
analysing = 1;
}
void MainWindow::stopAnalysing()
{
analysing = 0;
}
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_pushAnalysing_pressed()
{
if (!analysing)
startAnalysing();
else
stopAnalysing();
}
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.");
}
void MainWindow::on_pushButton_exit_clicked()
{
if(running) stop();
theHW->stop();
theHW->disconnectDevices();
QApplication::exit(); //close the application;
}

View File

@ -0,0 +1,91 @@
#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;
int analysing = 0;
void run();
void stop();
void startLogging();
void stopLogging();
void startAnalysing();
void stopAnalysing();
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;
bool loadCalibrationFactors(const QString& filePath, int* calibrationFactors); // Loads calibration factors from a file
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_pushAnalysing_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();
void on_pushButton_exit_clicked();
private:
Ui::MainWindow *ui;
};
#endif // MAINWINDOW_H

View File

@ -0,0 +1,225 @@
<?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 class="QPushButton" name="pushButton_exit">
<property name="geometry">
<rect>
<x>760</x>
<y>510</y>
<width>80</width>
<height>24</height>
</rect>
</property>
<property name="text">
<string>Quit</string>
</property>
</widget>
<widget class="QPushButton" name="pushAnalysing">
<property name="enabled">
<bool>true</bool>
</property>
<property name="geometry">
<rect>
<x>90</x>
<y>440</y>
<width>161</width>
<height>24</height>
</rect>
</property>
<property name="text">
<string>Start Analysing!</string>
</property>
</widget>
</widget>
<widget class="QMenuBar" name="menuBar">
<property name="geometry">
<rect>
<x>0</x>
<y>0</y>
<width>853</width>
<height>22</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,198 @@
#ifndef NETWORKTHREAD_H
#define NETWORKTHREAD_H
#include <QThread>
#include <QUdpSocket>
#include "iostream"
#include <QTime>
#include <QThread>
#include <QUdpSocket>
#include <QMutex>
#include <QWaitCondition>
#include "eventbuilder.h"
class NetworkThread : public QThread
{
Q_OBJECT
private:
quint16 serverPort = 1901; // Port number for the UDP server
double intensity = 0.0, position = 0.0, focus = 0.0;
QMutex mutex; // Mutex for data synchronization
QWaitCondition dataReady; // Condition variable to signal data readiness
EventBuilder &eventBuilder;
public:
NetworkThread(EventBuilder &builder, QObject *parent = nullptr) : QThread(parent), eventBuilder(builder), stopped(false) {}
void run() override
{
QUdpSocket udpSocket;
//udpSocket.bind(QHostAddress::Any, 12345); // Set your desired port
// Bind the socket to a specific IP address and port
if ( udpSocket.bind(QHostAddress("127.0.0.1"), serverPort) )
{
// connect(udpSocket, SIGNAL(readyRead()), this, SLOT(processPendingDatagrams()));
qInfo() << "UDP server started on port" << serverPort;
}
else
{
stopped = true;
qWarning() << "Failed to bind UDP socket on port" << serverPort;
}
while (!stopped)
{
// Your data serialization and broadcasting logic here
QByteArray data = eventBuilder.getNextData(); // Get data from the EventBuilder
if (!data.isEmpty())
{
QString dataString = QString(data);
udpSocket.writeDatagram(data.data(), data.size(), QHostAddress::Broadcast, serverPort);
// std::cerr << dataString.toStdString() << std::endl;
}
else
{
// std::cerr << "data is empty" << std::endl;
}
// QByteArray data = serializeYourData();
// QTime currentTime = QTime::currentTime();
// Calculate the time since midnight in milliseconds
// int millisecondsSinceMidnight = currentTime.msecsSinceStartOfDay();
// QByteArray data; // Create a QByteArray for your data
// Populate data with your custom data
// data.append(QByteArray::number(millisecondsSinceMidnight));
// udpSocket.writeDatagram(data.data(),data.size(), QHostAddress::Broadcast, serverPort); // Broadcast to all reachable devices
// emit dataReady(data); // Emit the signal when data is ready
// std::cerr << " running" << std::endl;
// QThread::msleep(1); // Sleep for microseconds usleep / millisecond msleep //!!!!! on windows the minimum is about 15ms from OS reasons. ~ 30 microseconds between loops without thread sleep.
}
}
void stopThread()
{
stopped = true;
emit terminationRequested();
}
// Add this public slot to receive data from the main thread
public slots:
signals:
void terminationRequested();
private:
bool stopped;
QByteArray serializeYourData()
{
// Implement your data serialization here
}
};
/*
#include <QThread>
#include <QUdpSocket>
#include <QMutex>
#include <QWaitCondition>
#include <QTime>
class NetworkThread : public QThread
{
Q_OBJECT
private:
quint16 serverPort = 1901; // Port number for the UDP server
double intensity = 0.0, position = 0.0, focus = 0.0;
QMutex mutex; // Mutex for data synchronization
QWaitCondition dataReady; // Condition variable to signal data readiness
public:
NetworkThread(QObject *parent = nullptr) : QThread(parent), stopped(false) {}
void run() override
{
QUdpSocket udpSocket;
if (udpSocket.bind(QHostAddress("10.0.7.1"), serverPort))
{
qInfo() << "UDP server started on port" << serverPort;
}
else
{
stopped = true;
qWarning() << "Failed to bind UDP socket on port" << serverPort;
}
while (!stopped)
{
// Wait for data to be ready
mutex.lock();
dataReady.wait(&mutex);
// Data is now ready, unlock the mutex
QTime currentTime = QTime::currentTime();
int millisecondsSinceMidnight = currentTime.msecsSinceStartOfDay();
QByteArray data;
data.append(QByteArray::number(millisecondsSinceMidnight));
// Append the updated parameters to the data
data.append(",");
data.append(QByteArray::number(intensity));
data.append(",");
data.append(QByteArray::number(position));
data.append(",");
data.append(QByteArray::number(focus));
udpSocket.writeDatagram(data.data(), data.size(), QHostAddress::Broadcast, serverPort);
mutex.unlock();
}
}
void stopThread()
{
stopped = true;
emit terminationRequested();
}
public slots:
// This slot is called from another thread to update the parameters
void updateParameters(double newIntensity, double newPosition, double newFocus)
{
// Lock the mutex before updating the parameters
mutex.lock();
// Update the parameters
intensity = newIntensity;
position = newPosition;
focus = newFocus;
// Signal that data is ready to be sent
dataReady.wakeAll();
// Unlock the mutex
mutex.unlock();
}
signals:
void terminationRequested();
private:
bool stopped;
};
*/
#endif // NETWORKTHREAD_H

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;
}

File diff suppressed because it is too large Load Diff

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

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;
}

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;
}

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_RAWCAL/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,56 @@
#ifndef UDPSERVER_H
#define UDPSERVER_H
#include <QObject>
#include <QVector>
#include <QThread>
#include <QUdpSocket>
class UDPServer : public QObject
{
Q_OBJECT
private:
QUdpSocket* udpSocket; // UDP socket for communication
quint16 serverPort = 12345; // Port number for the UDP server
public:
UDPServer(QObject* parent = nullptr) : QObject(parent)
{
// Initialize and configure your UDP server here
}
public slots:
void startServer()
{
// Start your UDP server here
udpSocket = new QUdpSocket(this);
// Bind the socket to a specific IP address and port
if ( udpSocket->bind(QHostAddress("10.0.7.1"), serverPort) )
{
connect(udpSocket, SIGNAL(readyRead()), this, SLOT(processPendingDatagrams()));
qDebug() << "UDP server started on port" << serverPort;
}
else
{
qWarning() << "Failed to bind UDP socket on port" << serverPort;
}
}
void stopServer()
{
// Stop your UDP server here
if (udpSocket)
{
udpSocket->close();
udpSocket->deleteLater();
}
qDebug() << "UDP server stopped";
}
// Add any other methods and signals relevant to your UDP server
};
#endif // UDPSERVER_H

Binary file not shown.