Skip to content
Projects
Groups
Snippets
Help
Loading...
Sign in
Toggle navigation
DIOT WIC Gateware
Project
Project
Details
Activity
Cycle Analytics
Repository
Repository
Files
Commits
Branches
Tags
Contributors
Graph
Compare
Charts
Issues
0
Issues
0
List
Board
Labels
Milestones
Merge Requests
0
Merge Requests
0
Wiki
Wiki
image/svg+xml
Discourse
Discourse
Members
Members
Collapse sidebar
Close sidebar
Activity
Graph
Charts
Create a new issue
Commits
Issue Boards
Open sidebar
Projects
DIOT WIC Gateware
Commits
f3b96b13
Commit
f3b96b13
authored
Nov 27, 2018
by
Grzegorz Daniluk
Browse files
Options
Browse Files
Download
Plain Diff
Merge branch 'orson-wic-sw'
parents
3af98e16
c41ce8b0
Hide whitespace changes
Inline
Side-by-side
Showing
17 changed files
with
455 additions
and
436 deletions
+455
-436
controller.cpp
sw/diot-sw/gui_demo/controller.cpp
+89
-10
controller.h
sw/diot-sw/gui_demo/controller.h
+17
-4
demo.pro
sw/diot-sw/gui_demo/demo.pro
+2
-2
diot_crate.h
sw/diot-sw/gui_demo/diot_crate.h
+1
-1
diot_dialog.cpp
sw/diot-sw/gui_demo/diot_dialog.cpp
+35
-0
diot_dialog.h
sw/diot-sw/gui_demo/diot_dialog.h
+34
-0
main.cpp
sw/diot-sw/gui_demo/main.cpp
+2
-16
libmfipp.cpp
sw/diot-sw/libmfipp/libmfipp.cpp
+56
-6
libmfipp.h
sw/diot-sw/libmfipp/libmfipp.h
+67
-8
libmfipp_test.cpp
sw/diot-sw/libmfipp/libmfipp_test.cpp
+61
-3
nanofip.cpp
sw/diot-sw/libmfipp/nanofip.cpp
+60
-12
nanofip.h
sw/diot-sw/libmfipp/nanofip.h
+31
-1
dialog.ui
sw/python_gui/dialog.ui
+0
-121
main_win.ui
sw/python_gui/main_win.ui
+0
-58
test1.py
sw/python_gui/test1.py
+0
-99
ui_dialog.py
sw/python_gui/ui_dialog.py
+0
-55
ui_main_win.py
sw/python_gui/ui_main_win.py
+0
-40
No files found.
sw/diot-sw/gui_demo/controller.cpp
View file @
f3b96b13
...
...
@@ -17,12 +17,22 @@
*/
#include <QtWidgets/QPushButton>
#include <QtWidgets/QDialog>
#include <QtWidgets/QGroupBox>
#include <QBoxLayout>
#include <QLabel>
#include <QStatusBar>
#include "controller.h"
// Register custom type for Qt signals
static
struct
registerMetatypes
{
registerMetatypes
()
{
qRegisterMetaType
<
nanoFIP
::
DataStatusMap
>
(
"nanoFIP::DataStatusMap"
);
qRegisterMetaType
<
mstrfip_data_status
>
(
"mstrfip_data_status"
);
}
}
_registerMetatypes
;
DiotHardware
::
DiotHardware
(
int
address
,
int
slots_nr
)
{
// Configure MasterFIP
...
...
@@ -45,7 +55,13 @@ DiotHardware::DiotHardware(int address, int slots_nr)
crate
.
reset
(
new
DIOT_Crate
(
address
,
slots_nr
));
crate
->
AddVariables
(
cycle
->
GetPeriodicVarWindow
());
crate
->
SetConsVarCb
([
&
](
nanoFIP
&
nf
)
{
crate
->
SetConsVarCb
([
&
](
nanoFIP
&
nf
,
mstrfip_data
*
data
)
{
emit
StatusChanged
(
data
->
status
,
nf
.
GetDataStats
());
// No more updates if the data is invalid
if
(
data
->
status
!=
MSTRFIP_DATA_OK
)
return
;
// Report the crate state
DIOT_Crate
*
crate
=
static_cast
<
DIOT_Crate
*>
(
&
nf
);
...
...
@@ -86,7 +102,7 @@ void DiotHardware::SetOutput(int slot, unsigned int state)
}
DiotIOCard
::
DiotIOCard
(
Q
Dialog
*
parent
,
DiotHardware
&
hw
,
int
num
,
int
idx
)
DiotIOCard
::
DiotIOCard
(
Q
Widget
*
parent
,
const
DiotHardware
&
hw
,
int
num
,
int
idx
)
:
QFrame
(
parent
),
inputs
(
num
,
true
),
outputs
(
num
,
false
),
slot_nr
(
idx
),
io_count
(
num
)
{
...
...
@@ -167,7 +183,7 @@ void DiotIOCard::testBtn_click(int slot, int io) {
void
DiotIOCard
::
update_inputs
()
{
for
(
int
i
=
0
;
i
<
io_count
;
++
i
)
{
if
(
inputs
[
i
])
{
if
(
!
inputs
[
i
])
{
lbl_state
[
i
]
->
setStyleSheet
(
"background-color: green; color: white"
);
}
else
{
lbl_state
[
i
]
->
setStyleSheet
(
"background-color: maroon; color: white"
);
...
...
@@ -210,7 +226,7 @@ bool DiotIOCard::int_to_vec(unsigned int integer, std::vector<bool>& vec)
}
DiotIOController
::
DiotIOController
(
Q
Dialog
*
dialog
,
DiotHardware
&
hw
,
int
slots_count
)
DiotIOController
::
DiotIOController
(
Q
Widget
*
dialog
,
DiotHardware
&
hw
,
int
slots_count
)
:
QFrame
(
dialog
)
{
QHBoxLayout
*
boxLayout
=
new
QHBoxLayout
();
...
...
@@ -244,11 +260,12 @@ void DiotIOController::UpdateInputErr(int slot, unsigned int state)
}
DiotDiag
::
DiotDiag
(
Q
Dialog
*
parent
,
DiotHardware
&
hw
)
DiotDiag
::
DiotDiag
(
Q
Widget
*
parent
,
const
DiotHardware
&
hw
)
:
QFrame
(
parent
)
{
DIOT_Crate
*
crate
=
hw
.
GetCrate
();
QHBoxLayout
*
mainLayout
=
new
QHBoxLayout
();
QVBoxLayout
*
mainLayout
=
new
QVBoxLayout
();
QHBoxLayout
*
statsLayout
=
new
QHBoxLayout
();
// Fans
QGroupBox
*
fanBox
=
new
QGroupBox
(
this
);
...
...
@@ -260,7 +277,7 @@ DiotDiag::DiotDiag(QDialog* parent, DiotHardware& hw)
}
fanBox
->
setTitle
(
"Fans"
);
fanBox
->
setLayout
(
fanLayout
);
main
Layout
->
addWidget
(
fanBox
);
stats
Layout
->
addWidget
(
fanBox
);
// Temperature sensors
QGroupBox
*
tempBox
=
new
QGroupBox
(
this
);
...
...
@@ -272,7 +289,7 @@ DiotDiag::DiotDiag(QDialog* parent, DiotHardware& hw)
}
tempBox
->
setTitle
(
"Temperature"
);
tempBox
->
setLayout
(
tempLayout
);
main
Layout
->
addWidget
(
tempBox
);
stats
Layout
->
addWidget
(
tempBox
);
// Voltages
QGroupBox
*
voltBox
=
new
QGroupBox
(
this
);
...
...
@@ -285,7 +302,25 @@ DiotDiag::DiotDiag(QDialog* parent, DiotHardware& hw)
}
voltBox
->
setTitle
(
"Voltages"
);
voltBox
->
setLayout
(
voltLayout
);
mainLayout
->
addWidget
(
voltBox
);
statsLayout
->
addWidget
(
voltBox
);
// Data statistics
QGroupBox
*
statBox
=
new
QGroupBox
(
this
);
QVBoxLayout
*
statLayout
=
new
QVBoxLayout
();
for
(
const
auto
&
statType
:
hw
.
GetCrate
()
->
GetDataStats
())
{
auto
statWidget
=
new
QLabel
(
QString
(
"%1: 0"
)
.
arg
(
QString
::
fromStdString
(
nanoFIP
::
GetDataStatDesc
(
statType
.
first
))));
statLayout
->
addWidget
(
statWidget
);
stat_lbl
.
push_back
(
statWidget
);
}
statBox
->
setTitle
(
"Data statistics"
);
statBox
->
setLayout
(
statLayout
);
statsLayout
->
addWidget
(
statBox
);
mainLayout
->
addLayout
(
statsLayout
,
1
);
statusBar
=
new
QStatusBar
(
this
);
mainLayout
->
addWidget
(
statusBar
);
setLayout
(
mainLayout
);
...
...
@@ -295,6 +330,8 @@ DiotDiag::DiotDiag(QDialog* parent, DiotHardware& hw)
this
,
&
DiotDiag
::
UpdateTemperature
);
QObject
::
connect
(
&
hw
,
&
DiotHardware
::
VoltageChanged
,
this
,
&
DiotDiag
::
UpdateVoltage
);
QObject
::
connect
(
&
hw
,
&
DiotHardware
::
StatusChanged
,
this
,
&
DiotDiag
::
UpdateStatus
);
}
...
...
@@ -316,6 +353,48 @@ void DiotDiag::UpdateVoltage(unsigned int volt, bool state)
}
void
DiotDiag
::
UpdateStatus
(
mstrfip_data_status
status
,
const
nanoFIP
::
DataStatusMap
&
stats
)
{
qDebug
()
<<
"status: "
<<
status
;
switch
(
status
)
{
case
MSTRFIP_DATA_OK
:
statusBar
->
showMessage
(
"Status: data OK"
);
break
;
case
MSTRFIP_DATA_FRAME_ERROR
:
statusBar
->
showMessage
(
"Status: frame error"
);
break
;
case
MSTRFIP_DATA_PAYLOAD_ERROR
:
statusBar
->
showMessage
(
"Status: payload error"
);
break
;
case
MSTRFIP_DATA_NOT_RECEIVED
:
statusBar
->
showMessage
(
"Status: data not received"
);
break
;
}
if
(
status
==
MSTRFIP_DATA_OK
)
{
statusBar
->
setStyleSheet
(
"color: green"
);
parentWidget
()
->
setEnabled
(
true
);
}
else
{
statusBar
->
setStyleSheet
(
"color: red"
);
parentWidget
()
->
setEnabled
(
false
);
}
for
(
const
auto
&
stat
:
stats
)
{
stat_lbl
[
static_cast
<
int
>
(
stat
.
first
)]
->
setText
(
QString
(
"%1: %2"
)
.
arg
(
QString
::
fromStdString
(
nanoFIP
::
GetDataStatDesc
(
stat
.
first
)))
.
arg
(
stat
.
second
));
}
}
void
DiotDiag
::
updateLabel
(
std
::
vector
<
QLabel
*>
labels
,
unsigned
int
idx
,
bool
state
,
const
QString
&
desc
,
int
val
)
{
...
...
sw/diot-sw/gui_demo/controller.h
View file @
f3b96b13
...
...
@@ -28,9 +28,9 @@
#include <diot_crate.h>
class
DiotIOController
;
class
QDialog
;
class
QLabel
;
class
QPushButton
;
class
QStatusBar
;
/**
* Class representing the DIOT crate hardware in the Qt world.
...
...
@@ -104,6 +104,15 @@ signals:
*/
void
VoltageChanged
(
unsigned
int
volt
,
bool
state
);
/**
* Signal emitted to update the data status.
* @param status is the new data status.
* @param stats contains statistics.
* @see enum mstrfip_data_status
*/
void
StatusChanged
(
mstrfip_data_status
status
,
const
nanoFIP
::
DataStatusMap
&
stats
);
private
:
std
::
unique_ptr
<
MasterFIP
>
mfip
;
std
::
unique_ptr
<
CycleSimple
>
cycle
;
...
...
@@ -120,7 +129,7 @@ class DiotIOCard : public QFrame {
Q_OBJECT
public
:
DiotIOCard
(
Q
Dialog
*
parent
,
DiotHardware
&
hw
,
int
num
,
int
idx
);
DiotIOCard
(
Q
Widget
*
parent
,
const
DiotHardware
&
hw
,
int
num
,
int
idx
);
virtual
~
DiotIOCard
()
{}
unsigned
int
GetInput
()
const
{
...
...
@@ -164,7 +173,7 @@ class DiotIOController : public QFrame {
Q_OBJECT
public
:
DiotIOController
(
Q
Dialog
*
dialog
,
DiotHardware
&
hw
,
int
slots_count
);
DiotIOController
(
Q
Widget
*
dialog
,
DiotHardware
&
hw
,
int
slots_count
);
public
slots
:
void
UpdateInput
(
int
slot
,
unsigned
int
state
);
...
...
@@ -183,7 +192,7 @@ class DiotDiag : public QFrame {
Q_OBJECT
public
:
DiotDiag
(
Q
Dialog
*
parent
,
DiotHardware
&
hw
);
DiotDiag
(
Q
Widget
*
parent
,
const
DiotHardware
&
hw
);
virtual
~
DiotDiag
()
{}
public
slots
:
...
...
@@ -201,6 +210,8 @@ public slots:
void
UpdateVoltage
(
unsigned
int
volt
,
bool
state
);
void
UpdateStatus
(
mstrfip_data_status
status
,
const
nanoFIP
::
DataStatusMap
&
stats
);
private
:
// Helper function to update labels
void
updateLabel
(
std
::
vector
<
QLabel
*>
labels
,
...
...
@@ -209,6 +220,8 @@ private:
std
::
vector
<
QLabel
*>
fan_lbl
;
std
::
vector
<
QLabel
*>
temp_lbl
;
std
::
vector
<
QLabel
*>
volt_lbl
;
std
::
vector
<
QLabel
*>
stat_lbl
;
QStatusBar
*
statusBar
;
};
#endif
/* CONTROLLER_H */
sw/diot-sw/gui_demo/demo.pro
View file @
f3b96b13
...
...
@@ -18,9 +18,9 @@ DEFINES += QT_DEPRECATED_WARNINGS
#DEFINES += QT_DISABLE_DEPRECATED_BEFORE=0x060000 # disables all the APIs deprecated before Qt 6.0.0
# Input
HEADERS
+=
controller
.
h
diot_crate
.
h
HEADERS
+=
controller
.
h
diot_crate
.
h
diot_dialog
.
h
#FORMS += dialog.ui main_win.ui
SOURCES
+=
main
.
cpp
controller
.
cpp
diot_crate
.
cpp
SOURCES
+=
main
.
cpp
controller
.
cpp
diot_crate
.
cpp
diot_dialog
.
cpp
# enable C++11
CONFIG
+=
c
++
11
...
...
sw/diot-sw/gui_demo/diot_crate.h
View file @
f3b96b13
...
...
@@ -265,7 +265,7 @@ private:
static
constexpr
unsigned
int
FAN_COUNT
=
3
;
///> Number of temperature sensors
static
constexpr
unsigned
int
TEMP_COUNT
=
6
;
static
constexpr
unsigned
int
TEMP_COUNT
=
2
;
///> Vector storing all voltages
static
const
std
::
vector
<
std
::
pair
<
VOLTAGE
,
std
::
string
>>
VOLTAGES
;
...
...
sw/diot-sw/gui_demo/diot_dialog.cpp
0 → 100644
View file @
f3b96b13
/*
* Copyright (C) 2018 CERN
* Author: Maciej Suminski <maciej.suminski@cern.ch>
*
* This program is free software: you can redistribute it and/or modify it
* under the terms of the GNU General Public License as published by the
* Free Software Foundation, either version 3 of the License, or (at your
* option) any later version.
*
* This program is distributed in the hope that it will be useful, but
* WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
* General Public License for more details.
*
* You should have received a copy of the GNU General Public License along
* with this program. If not, see <http://www.gnu.org/licenses/>.
*/
#include <QBoxLayout>
#include "diot_dialog.h"
DIOT_Dialog
::
DIOT_Dialog
(
int
address
,
int
slots_nr
)
:
hw
(
address
,
slots_nr
)
{
QVBoxLayout
*
mainLayout
=
new
QVBoxLayout
();
DiotIOController
*
controller
=
new
DiotIOController
(
this
,
hw
,
slots_nr
);
mainLayout
->
addWidget
(
controller
);
DiotDiag
*
diag
=
new
DiotDiag
(
this
,
hw
);
mainLayout
->
addWidget
(
diag
);
setLayout
(
mainLayout
);
hw
.
Start
();
}
sw/diot-sw/gui_demo/diot_dialog.h
0 → 100644
View file @
f3b96b13
/*
* Copyright (C) 2018 CERN
* Author: Maciej Suminski <maciej.suminski@cern.ch>
*
* This program is free software: you can redistribute it and/or modify it
* under the terms of the GNU General Public License as published by the
* Free Software Foundation, either version 3 of the License, or (at your
* option) any later version.
*
* This program is distributed in the hope that it will be useful, but
* WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
* General Public License for more details.
*
* You should have received a copy of the GNU General Public License along
* with this program. If not, see <http://www.gnu.org/licenses/>.
*/
#ifndef DIOT_DIALOG_H
#define DIOT_DIALOG_H
#include <QDialog>
#include "controller.h"
class
DIOT_Dialog
:
public
QDialog
{
public
:
DIOT_Dialog
(
int
address
,
int
slots_nr
);
protected
:
DiotHardware
hw
;
};
#endif
/* DIOT_DIALOG_H */
sw/diot-sw/gui_demo/main.cpp
View file @
f3b96b13
...
...
@@ -18,9 +18,7 @@
#include <iostream>
#include <QtWidgets/QApplication>
#include <QtWidgets/QDialog>
#include <QBoxLayout>
#include "controller.h"
#include "diot_dialog.h"
// Argument values
constexpr
int
ADDRESS_DEFAULT
=
1
;
...
...
@@ -40,7 +38,6 @@ static void usage() {
int
main
(
int
argc
,
char
**
argv
)
{
QApplication
a
(
argc
,
argv
);
QDialog
w
;
// Process arguments
int
address
=
ADDRESS_DEFAULT
;
...
...
@@ -69,18 +66,7 @@ int main( int argc, char **argv ) {
return
0
;
}
DiotHardware
hw
(
address
,
slots_nr
);
QVBoxLayout
*
mainLayout
=
new
QVBoxLayout
();
DiotIOController
*
controller
=
new
DiotIOController
(
&
w
,
hw
,
slots_nr
);
mainLayout
->
addWidget
(
controller
);
DiotDiag
*
diag
=
new
DiotDiag
(
&
w
,
hw
);
mainLayout
->
addWidget
(
diag
);
w
.
setLayout
(
mainLayout
);
DIOT_Dialog
w
(
address
,
slots_nr
);
w
.
show
();
hw
.
Start
();
return
a
.
exec
();
}
sw/diot-sw/libmfipp/libmfipp.cpp
View file @
f3b96b13
...
...
@@ -48,6 +48,7 @@ MasterFIP::MasterFIP(struct mstrfip_dev *device)
throw
std
::
runtime_error
(
"Duplicate mstrfip_dev"
);
}
ClearErrors
();
instances
[
dev
]
=
this
;
}
...
...
@@ -136,7 +137,7 @@ void MasterFIP::StartCycle(CycleBase &cycle)
void
MasterFIP
::
StopCycle
()
{
if
(
state
==
STOPPED
)
{
DBG
(
"No cycle to stop"
);
DBG
(
"No cycle to stop
\n
"
);
return
;
}
...
...
@@ -148,12 +149,45 @@ void MasterFIP::StopCycle()
}
void
MasterFIP
::
ClearErrors
()
{
errors
[
MSTRFIP_INVALID_ANSWER_ACK
]
=
0
;
errors
[
MSTRFIP_INVALID_BITRATE
]
=
0
;
errors
[
MSTRFIP_INVALID_BA_INSTR_COUNT
]
=
0
;
errors
[
MSTRFIP_BA_IS_NULL
]
=
0
;
errors
[
MSTRFIP_BA_MAX_VAR
]
=
0
;
errors
[
MSTRFIP_BA_INVALID_VAR_COUNT
]
=
0
;
errors
[
MSTRFIP_BA_PER_WIND_CFG_BAD
]
=
0
;
errors
[
MSTRFIP_BA_INVALID_INSTR_PARAM
]
=
0
;
errors
[
MSTRFIP_BA_NOT_STOP_STATE
]
=
0
;
errors
[
MSTRFIP_BA_INCONSISTENCY
]
=
0
;
errors
[
MSTRFIP_BA_WRONG_CYCLE_LENGTH
]
=
0
;
errors
[
MSTRFIP_BA_INCONSISTENT_INSTR_SET
]
=
0
;
errors
[
MSTRFIP_BA_WAIT_WIND_INSTR_MISSING
]
=
0
;
errors
[
MSTRFIP_BA_INVALID_MACROCYCLE
]
=
0
;
errors
[
MSTRFIP_INVALID_HW_VERS
]
=
0
;
errors
[
MSTRFIP_TRTL_MSG_COUNT_INCONSISTENCY
]
=
0
;
errors
[
MSTRFIP_TRTL_MSG_COUNT_OVERFLOW
]
=
0
;
errors
[
MSTRFIP_TRTL_MSG_OVERFLOW
]
=
0
;
errors
[
MSTRFIP_TRTL_MSG_READ_ERR
]
=
0
;
errors
[
MSTRFIP_TRTL_MSG_READ_NULL
]
=
0
;
errors
[
MSTRFIP_POLL_TIMEOUT
]
=
0
;
errors
[
MSTRFIP_POLL_ERROR
]
=
0
;
errors
[
MSTRFIP_BA_APER_VAR_NO_CB
]
=
0
;
errors
[
MSTRFIP_BA_APER_MSG_NO_CB
]
=
0
;
errors
[
MSTRFIP_BA_PER_VAR_NO_CB
]
=
0
;
errors
[
MSTRFIP_RESET_MOCKTRTL_ERR
]
=
0
;
// initialize the sentinel, so there are no exceptions when it is accessed
errors
[
__MSTRFIP_MAX_ERROR_CODE
]
=
0
;
}
void
MasterFIP
::
error_handler
(
mstrfip_dev
*
dev
,
mstrfip_error_list
error
)
{
auto
it
=
MasterFIP
::
instances
.
find
(
dev
);
if
(
it
==
MasterFIP
::
instances
.
end
())
{
DBG
(
"error_handler could not find 0x%p device"
,
dev
);
DBG
(
"error_handler could not find 0x%p device
\n
"
,
dev
);
return
;
}
...
...
@@ -315,7 +349,7 @@ CycleBase::CycleBase(const MasterFIP &mfip, int length_us)
CycleBase
::~
CycleBase
()
{
if
(
mstrfip_macrocycle_delete
(
dev
,
mcycle
))
DBG
(
"Could not delete cycle"
);
DBG
(
"Could not delete cycle
\n
"
);
}
...
...
@@ -332,8 +366,7 @@ int CycleBase::ReadRespTime()
if
(
mstrfip_hw_response_time_get
(
dev
,
agents
.
size
(),
addresses
.
data
(),
resp_time
.
data
()))
{
//DBG(MasterFIP::errStr("Read turn around time failed: "));
DBG
(
"Read turn around time failed: "
);
DBG
(
MasterFIP
::
errStr
(
"Read turn around time failed: "
));
return
-
1
;
}
...
...
@@ -366,7 +399,7 @@ int CycleSimple::Update()
}
if
(
empty
)
{
DBG
(
"Empty macrocyle"
);
DBG
(
"Empty macrocyle
\n
"
);
return
-
1
;
}
...
...
@@ -387,6 +420,8 @@ AgentBase::AgentBase(unsigned int addr)
{
if
(
addr
>=
255
)
throw
std
::
runtime_error
(
"Agent address must lower than 255"
);
ClearErrors
();
}
...
...
@@ -395,6 +430,21 @@ AgentBase::~AgentBase()
}
void
AgentBase
::
ClearErrors
()
{
errors
[
WRITE_FAILED
]
=
0
;
errors
[
MISSED
]
=
0
;
errors
[
NOT_FRESHED
]
=
0
;
errors
[
NOT_SIGNIFICANT
]
=
0
;
errors
[
TIMEOUT
]
=
0
;
errors
[
HW_ERR
]
=
0
;
errors
[
HW_BSZ
]
=
0
;
errors
[
HW_CTRL
]
=
0
;
errors
[
HW_PDU
]
=
0
;
errors
[
UNKNOWN
]
=
0
;
}
int
WaitForSignal
()
{
int
signo
;
...
...
sw/diot-sw/libmfipp/libmfipp.h
View file @
f3b96b13
...
...
@@ -117,12 +117,12 @@ public:
return
dev
;
}
typedef
std
::
unordered_map
<
mstrfip_error_list
,
int
>
ErrorMap
;
typedef
std
::
unordered_map
<
mstrfip_error_list
,
int
>
Master
ErrorMap
;
/**
* Returns error counters.
*/
const
ErrorMap
&
GetErrorCount
()
const
const
MasterErrorMap
&
GetErrors
()
const
{
return
errors
;
}
...
...
@@ -130,10 +130,7 @@ public:
/**
* Resets error counters.
*/
void
ClearErrors
()
{
errors
.
clear
();
}
void
ClearErrors
();
protected
:
///> Error handler wrapper
...
...
@@ -158,7 +155,7 @@ protected:
void
(
*
orig_err_handler
)(
mstrfip_dev
*
dev
,
mstrfip_error_list
error
);
///> Error counter
ErrorMap
errors
;
Master
ErrorMap
errors
;
///> MasterFIP instances to resolve handlers
static
std
::
unordered_map
<
mstrfip_dev
*
,
MasterFIP
*>
instances
;
...
...
@@ -366,6 +363,34 @@ protected:
};
///> Communication error types
enum
AgentError
{
WRITE_FAILED
,
///< writing new value failed
MISSED
,
///< missed data (not updated)
NOT_FRESHED
,
///< other than 0x5 promptness & significance
NOT_SIGNIFICANT
,
///< other than 0x4 promptness & significance
TIMEOUT
,
///< time out, no reply from agent
HW_ERR
,
///< hw bit error in the frame
HW_BSZ
,
///< hw wrong number of bytes in the frame
HW_CTRL
,
///< hw bad control byte in the frame
HW_PDU
,
///< hw bad pdu byte in the frame
UNKNOWN
};
namespace
std
{
template
<>
struct
hash
<
AgentError
>
{
size_t
operator
()(
const
AgentError
&
a
)
const
noexcept
{
// no need for any fancy algorithm, enum values are already unique
return
a
;
}
};
}
// namespace std
class
AgentBase
{
public
:
...
...
@@ -377,12 +402,46 @@ public:
return
address
;
}
typedef
std
::
unordered_map
<
AgentError
,
unsigned
int
>
AgentErrorMap
;
/**
* Returns error counters.
*/
const
AgentErrorMap
&
GetErrors
()
const
{
return
errors
;
}
/**
* Resets error counters.
*/
void
ClearErrors
();
protected
:
/**
* Reports an error occurence.
* @param AgentError is the error type.
*/
void
reportError
(
AgentError
error
)
{
// TODO error handler callback?
++
errors
[
error
];
}
///> Agent address on the FIP bus.
const
unsigned
int
address
;
private
:
AgentErrorMap
errors
;
};
///> Sleeps until a signal arrives
/**
* Sleeps until a signal arrives
*
* Helper function for user applications. It will suspend the current thread
* execution until a signal is received.
*/
int
WaitForSignal
();
...
...
sw/diot-sw/libmfipp/libmfipp_test.cpp
View file @
f3b96b13
...
...
@@ -54,17 +54,21 @@ int main(int argc, char *argv[])
}
// Produced variable handler
agent1
.
SetProdVarCb
([
&
](
nanoFIP
&
nf
)
{
++
prod
;
agent1
.
SetProdVarCb
([
&
](
nanoFIP
&
nf
,
mstrfip_data
*
data
)
{
++
prod
;
// Produce next value in sequence
for
(
int
i
=
0
;
i
<
VAR_SIZE
;
++
i
)
{
agent1
.
SetProdVarData
(
i
,
prod
);
}
std
::
cout
<<
"variable produced = "
<<
(
int
)
prod
<<
std
::
endl
;
if
(
data
->
status
!=
MSTRFIP_DATA_OK
)
{
std
::
cout
<<
"produced variable cb error "
<<
data
->
status
<<
std
::
endl
;
}
}
);
agent1
.
SetConsVarCb
([
&
](
nanoFIP
&
nf
)
{
agent1
.
SetConsVarCb
([
&
](
nanoFIP
&
nf
,
mstrfip_data
*
data
)
{
uint8_t
cons
=
nf
.
GetConsVarData
(
0
);
for
(
int
i
=
1
;
i
<
VAR_SIZE
;
++
i
)
{
...
...
@@ -77,6 +81,10 @@ int main(int argc, char *argv[])
}
std
::
cout
<<
"variable consumed = "
<<
(
int
)
cons
<<
std
::
endl
;
if
(
data
->
status
!=
MSTRFIP_DATA_OK
)
{
std
::
cout
<<
"produced variable cb error "
<<
data
->
status
<<
std
::
endl
;
}
}
);
mfip
->
Configure
(
hw_cfg
,
sw_cfg
);
...
...
@@ -85,6 +93,56 @@ int main(int argc, char *argv[])
// Keep running until a signal arrives
WaitForSignal
();
std
::
cout
<<
"--------------------------------------"
<<
std
::
endl
;
// Display statistics
const
auto
&
mfipErrors
=
mfip
->
GetErrors
();
std
::
cout
<<
"MasterFIP interface errors:"
<<
std
::
endl
;
std
::
cout
<<
"
\t
INVALID_ANSWER_ACK: "
<<
mfipErrors
.
at
(
MSTRFIP_INVALID_ANSWER_ACK
)
<<
std
::
endl
;
std
::
cout
<<
"
\t
INVALID_BITRATE: "
<<
mfipErrors
.
at
(
MSTRFIP_INVALID_BITRATE
)
<<
std
::
endl
;
std
::
cout
<<
"
\t
INVALID_BA_INSTR_COUNT: "
<<
mfipErrors
.
at
(
MSTRFIP_INVALID_BA_INSTR_COUNT
)
<<
std
::
endl
;
std
::
cout
<<
"
\t
BA_IS_NULL: "
<<
mfipErrors
.
at
(
MSTRFIP_BA_IS_NULL
)
<<
std
::
endl
;
std
::
cout
<<
"
\t
BA_MAX_VAR: "
<<
mfipErrors
.
at
(
MSTRFIP_BA_MAX_VAR
)
<<
std
::
endl
;
std
::
cout
<<
"
\t
BA_INVALID_VAR_COUNT: "
<<
mfipErrors
.
at
(
MSTRFIP_BA_INVALID_VAR_COUNT
)
<<
std
::
endl
;
std
::
cout
<<
"
\t
BA_PER_WIND_CFG_BAD: "
<<
mfipErrors
.
at
(
MSTRFIP_BA_PER_WIND_CFG_BAD
)
<<
std
::
endl
;
std
::
cout
<<
"
\t
BA_INVALID_INSTR_PARAM: "
<<
mfipErrors
.
at
(
MSTRFIP_BA_INVALID_INSTR_PARAM
)
<<
std
::
endl
;
std
::
cout
<<
"
\t
BA_NOT_STOP_STATE: "
<<
mfipErrors
.
at
(
MSTRFIP_BA_NOT_STOP_STATE
)
<<
std
::
endl
;
std
::
cout
<<
"
\t
BA_INCONSISTENCY: "
<<
mfipErrors
.
at
(
MSTRFIP_BA_INCONSISTENCY
)
<<
std
::
endl
;
std
::
cout
<<
"
\t
BA_WRONG_CYCLE_LENGTH: "
<<
mfipErrors
.
at
(
MSTRFIP_BA_WRONG_CYCLE_LENGTH
)
<<
std
::
endl
;
std
::
cout
<<
"
\t
BA_INCONSISTENT_INSTR_SET: "
<<
mfipErrors
.
at
(
MSTRFIP_BA_INCONSISTENT_INSTR_SET
)
<<
std
::
endl
;
std
::
cout
<<
"
\t
BA_WAIT_WIND_INSTR_MISSING: "
<<
mfipErrors
.
at
(
MSTRFIP_BA_WAIT_WIND_INSTR_MISSING
)
<<
std
::
endl
;
std
::
cout
<<
"
\t
BA_INVALID_MACROCYCLE: "
<<
mfipErrors
.
at
(
MSTRFIP_BA_INVALID_MACROCYCLE
)
<<
std
::
endl
;
std
::
cout
<<
"
\t
INVALID_HW_VERS: "
<<
mfipErrors
.
at
(
MSTRFIP_INVALID_HW_VERS
)
<<
std
::
endl
;
std
::
cout
<<
"
\t
TRTL_MSG_COUNT_INCONSISTENCY: "
<<
mfipErrors
.
at
(
MSTRFIP_TRTL_MSG_COUNT_INCONSISTENCY
)
<<
std
::
endl
;
std
::
cout
<<
"
\t
TRTL_MSG_COUNT_OVERFLOW: "
<<
mfipErrors
.
at
(
MSTRFIP_TRTL_MSG_COUNT_OVERFLOW
)
<<
std
::
endl
;
std
::
cout
<<
"
\t
TRTL_MSG_OVERFLOW: "
<<
mfipErrors
.
at
(
MSTRFIP_TRTL_MSG_OVERFLOW
)
<<
std
::
endl
;
std
::
cout
<<
"
\t
TRTL_MSG_READ_ERR: "
<<
mfipErrors
.
at
(
MSTRFIP_TRTL_MSG_READ_ERR
)
<<
std
::
endl
;
std
::
cout
<<
"
\t
TRTL_MSG_READ_NULL: "
<<
mfipErrors
.
at
(
MSTRFIP_TRTL_MSG_READ_NULL
)
<<
std
::
endl
;
std
::
cout
<<
"
\t
POLL_TIMEOUT: "
<<
mfipErrors
.
at
(
MSTRFIP_POLL_TIMEOUT
)
<<
std
::
endl
;
std
::
cout
<<
"
\t
POLL_ERROR: "
<<
mfipErrors
.
at
(
MSTRFIP_POLL_ERROR
)
<<
std
::
endl
;
std
::
cout
<<
"
\t
BA_APER_VAR_NO_CB: "
<<
mfipErrors
.
at
(
MSTRFIP_BA_APER_VAR_NO_CB
)
<<
std
::
endl
;
std
::
cout
<<
"
\t
BA_APER_MSG_NO_CB: "
<<
mfipErrors
.
at
(
MSTRFIP_BA_APER_MSG_NO_CB
)
<<
std
::
endl
;
std
::
cout
<<
"
\t
BA_PER_VAR_NO_CB: "
<<
mfipErrors
.
at
(
MSTRFIP_BA_PER_VAR_NO_CB
)
<<
std
::
endl
;
std
::
cout
<<
"
\t
RESET_MOCKTRTL_ERR: "
<<
mfipErrors
.
at
(
MSTRFIP_RESET_MOCKTRTL_ERR
)
<<
std
::
endl
;
const
auto
&
agentErrors
=
agent1
.
GetErrors
();
std
::
cout
<<
"Agent errors:"
<<
std
::
endl
;
std
::
cout
<<
"
\t
Write failed: "
<<
agentErrors
.
at
(
WRITE_FAILED
)
<<
std
::
endl
;
std
::
cout
<<
"
\t
Missed data: "
<<
agentErrors
.
at
(
MISSED
)
<<
std
::
endl
;
std
::
cout
<<
"
\t
Not refreshed: "
<<
agentErrors
.
at
(
NOT_FRESHED
)
<<
std
::
endl
;
std
::
cout
<<
"
\t
Not significant: "
<<
agentErrors
.
at
(
NOT_SIGNIFICANT
)
<<
std
::
endl
;
std
::
cout
<<
"
\t
Timeout: "
<<
agentErrors
.
at
(
TIMEOUT
)
<<
std
::
endl
;
std
::
cout
<<
"
\t
HW bit errors: "
<<
agentErrors
.
at
(
HW_ERR
)
<<
std
::
endl
;
std
::
cout
<<
"
\t
HW wrong number of bytes: "
<<
agentErrors
.
at
(
HW_BSZ
)
<<
std
::
endl
;
std
::
cout
<<
"
\t
HW bad control byte: "
<<
agentErrors
.
at
(
HW_CTRL
)
<<
std
::
endl
;
std
::
cout
<<
"
\t
HW bad PDU byte: "
<<
agentErrors
.
at
(
HW_PDU
)
<<
std
::
endl
;
std
::
cout
<<
"
\t
Unknown error: "
<<
agentErrors
.
at
(
UNKNOWN
)
<<
std
::
endl
;
std
::
cout
<<
"Agent frame statistics: "
<<
std
::
endl
;
for
(
const
auto
&
stat
:
agent1
.
GetDataStats
())
{
std
::
cout
<<
"
\t
"
<<
nanoFIP
::
GetDataStatDesc
(
stat
.
first
)
<<
": "
<<
stat
.
second
<<
std
::
endl
;
}
//mfip->StopCycle();
return
0
;
...
...
sw/diot-sw/libmfipp/nanofip.cpp
View file @
f3b96b13
...
...
@@ -27,6 +27,7 @@ nanoFIP::nanoFIP(unsigned int addr, unsigned int variable_size)
{
cons_data
.
resize
(
variable_size
);
prod_data
.
resize
(
variable_size
);
ClearDataStats
();
}
...
...
@@ -51,6 +52,32 @@ int nanoFIP::AddVariables(WindowPeriodicVar& window)
}
void
nanoFIP
::
ClearDataStats
()
{
const
mstrfip_data_status
types
[]
=
{
MSTRFIP_DATA_OK
,
MSTRFIP_DATA_FRAME_ERROR
,
MSTRFIP_DATA_PAYLOAD_ERROR
,
MSTRFIP_DATA_NOT_RECEIVED
};
for
(
auto
type
:
types
)
{
data_stats
[
type
]
=
0
;
}
}
const
std
::
string
&
nanoFIP
::
GetDataStatDesc
(
mstrfip_data_status
stat
)
{
static
const
std
::
unordered_map
<
mstrfip_data_status
,
std
::
string
>
statusMap
=
{
{
MSTRFIP_DATA_OK
,
"Data OK"
},
{
MSTRFIP_DATA_FRAME_ERROR
,
"Frame error"
},
{
MSTRFIP_DATA_PAYLOAD_ERROR
,
"Payload error"
},
{
MSTRFIP_DATA_NOT_RECEIVED
,
"Data not received"
}
};
return
statusMap
.
at
(
stat
);
}
void
nanoFIP
::
consVarHandler
(
mstrfip_dev
*
dev
,
mstrfip_data
*
cvar
,
mstrfip_irq
*
irq
)
{
...
...
@@ -64,24 +91,43 @@ void nanoFIP::consVarHandler(mstrfip_dev *dev, mstrfip_data *cvar,
break
;
case
MSTRFIP_DATA_PAYLOAD_ERROR
:
// TODO check cvar->payload_error
DBG
(
"Data payload error"
);
if
(
cvar
->
payload_error
&
MSTRFIP_FRAME_PAYLOAD_NOT_REFRESH
)
reportError
(
NOT_FRESHED
);
if
(
cvar
->
payload_error
&
MSTRFIP_FRAME_PAYLOAD_NOT_SIGNIFICANT
)
reportError
(
NOT_SIGNIFICANT
);
DBG
(
"Data payload error
\n
"
);
break
;
case
MSTRFIP_DATA_NOT_RECEIVED
:
// TODO
DBG
(
"Data not received"
);
reportError
(
MISSED
);
DBG
(
"Data not received
\n
"
);
break
;
case
MSTRFIP_DATA_FRAME_ERROR
:
// TODO check cvar->frame_error
DBG
(
"Data frame error"
);
if
(
cvar
->
frame_error
&
MSTRFIP_FRAME_TMO
)
reportError
(
TIMEOUT
);
if
(
cvar
->
frame_error
&
MSTRFIP_FRAME_ERR
)
reportError
(
HW_ERR
);
if
(
cvar
->
frame_error
&
MSTRFIP_FRAME_BAD_CTRL
)
reportError
(
HW_CTRL
);
if
(
cvar
->
frame_error
&
MSTRFIP_FRAME_BAD_PDU
)
reportError
(
HW_PDU
);
if
(
cvar
->
frame_error
&
MSTRFIP_FRAME_BAD_BSZ
)
reportError
(
HW_BSZ
);
DBG
(
"Data frame error
\n
"
);
break
;
default
:
reportError
(
UNKNOWN
);
DBG
(
"Unknown error
\n
"
);
break
;
}
++
data_stats
[
cvar
->
status
];
}
if
(
cons_cb
)
// User callback
cons_cb
(
*
this
);
cons_cb
(
*
this
,
cvar
);
}
...
...
@@ -96,14 +142,16 @@ void nanoFIP::prodVarHandler(mstrfip_dev *dev, mstrfip_data *pvar,
int
res
=
mstrfip_var_write
(
dev
,
pvar
);
if
(
res
)
{
DBG
(
"Variable write failed"
);
return
;
reportError
(
WRITE_FAILED
);
DBG
(
"Variable write failed
\n
"
);
}
else
{
prod_dirty
=
false
;
}
prod_dirty
=
false
;
}
}
if
(
prod_cb
)
// User callback
prod_cb
(
*
this
);
prod_cb
(
*
this
,
pvar
);
}
sw/diot-sw/libmfipp/nanofip.h
View file @
f3b96b13
...
...
@@ -24,6 +24,18 @@
#include <functional>
#include <mutex>
namespace
std
{
template
<>
struct
hash
<
mstrfip_data_status
>
{
size_t
operator
()(
const
mstrfip_data_status
&
a
)
const
noexcept
{
// no need for any fancy algorithm, enum values are already unique
return
a
;
}
};
}
// namespace std
/**
* NanoFIP is a base class for all devices taking advantage of nanoFIP agent.
* It might be also used as a generic interface to nanoFIP.
...
...
@@ -35,7 +47,10 @@ protected:
public
:
///> Produced/consumed variable event handler signature
typedef
std
::
function
<
void
(
nanoFIP
&
)
>
VarCallback
;
typedef
std
::
function
<
void
(
nanoFIP
&
,
mstrfip_data
*
)
>
VarCallback
;
///> Map to store data frame stats
typedef
std
::
unordered_map
<
mstrfip_data_status
,
unsigned
int
>
DataStatusMap
;
/**
* nanoFIP constructor.
...
...
@@ -104,6 +119,18 @@ public:
prod_cb
=
cb
;
}
///> Returns frame statistics
const
DataStatusMap
&
GetDataStats
()
const
{
return
data_stats
;
}
///> Resets frame statistics
void
ClearDataStats
();
///> Returns human-readable description for data status enum
static
const
std
::
string
&
GetDataStatDesc
(
mstrfip_data_status
stat
);
protected
:
///> Consumed variable event handler
virtual
void
consVarHandler
(
mstrfip_dev
*
dev
,
mstrfip_data
*
cvar
,
...
...
@@ -157,6 +184,9 @@ protected:
}
private
:
///> Data frame stats
DataStatusMap
data_stats
;
///> Raw consumed variable data (updated by consVarHandler), guarded with cons_mtx
std
::
vector
<
uint8_t
>
cons_data
;
...
...
sw/python_gui/dialog.ui
deleted
100644 → 0
View file @
3af98e16
<?xml version="1.0" encoding="UTF-8"?>
<ui
version=
"4.0"
>
<class>
Dialog
</class>
<widget
class=
"QDialog"
name=
"Dialog"
>
<property
name=
"geometry"
>
<rect>
<x>
0
</x>
<y>
0
</y>
<width>
510
</width>
<height>
597
</height>
</rect>
</property>
<property
name=
"windowTitle"
>
<string>
Dialog
</string>
</property>
<widget
class=
"QGroupBox"
name=
"groupBox"
>
<property
name=
"geometry"
>
<rect>
<x>
70
</x>
<y>
90
</y>
<width>
101
</width>
<height>
351
</height>
</rect>
</property>
<property
name=
"title"
>
<string>
Slot 1
</string>
</property>
<widget
class=
"QPushButton"
name=
"pushButton"
>
<property
name=
"geometry"
>
<rect>
<x>
0
</x>
<y>
90
</y>
<width>
31
</width>
<height>
27
</height>
</rect>
</property>
<property
name=
"text"
>
<string>
1
</string>
</property>
<property
name=
"checkable"
>
<bool>
false
</bool>
</property>
<property
name=
"checked"
>
<bool>
false
</bool>
</property>
</widget>
<widget
class=
"QPushButton"
name=
"pushButton_2"
>
<property
name=
"geometry"
>
<rect>
<x>
0
</x>
<y>
120
</y>
<width>
31
</width>
<height>
27
</height>
</rect>
</property>
<property
name=
"text"
>
<string>
2
</string>
</property>
<property
name=
"checkable"
>
<bool>
false
</bool>
</property>
<property
name=
"checked"
>
<bool>
false
</bool>
</property>
</widget>
</widget>
<widget
class=
"QGroupBox"
name=
"groupBox_2"
>
<property
name=
"geometry"
>
<rect>
<x>
220
</x>
<y>
90
</y>
<width>
101
</width>
<height>
351
</height>
</rect>
</property>
<property
name=
"title"
>
<string>
Slot 2
</string>
</property>
<widget
class=
"QPushButton"
name=
"pushButton_3"
>
<property
name=
"geometry"
>
<rect>
<x>
0
</x>
<y>
90
</y>
<width>
31
</width>
<height>
27
</height>
</rect>
</property>
<property
name=
"text"
>
<string>
3
</string>
</property>
<property
name=
"checkable"
>
<bool>
false
</bool>
</property>
<property
name=
"checked"
>
<bool>
false
</bool>
</property>
</widget>
<widget
class=
"QPushButton"
name=
"pushButton_4"
>
<property
name=
"geometry"
>
<rect>
<x>
0
</x>
<y>
120
</y>
<width>
31
</width>
<height>
27
</height>
</rect>
</property>
<property
name=
"text"
>
<string>
4
</string>
</property>
<property
name=
"checkable"
>
<bool>
false
</bool>
</property>
<property
name=
"checked"
>
<bool>
false
</bool>
</property>
</widget>
</widget>
</widget>
<resources/>
<connections/>
</ui>
sw/python_gui/main_win.ui
deleted
100644 → 0
View file @
3af98e16
<?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>
800
</width>
<height>
600
</height>
</rect>
</property>
<property
name=
"windowTitle"
>
<string>
MainWindow
</string>
</property>
<widget
class=
"QWidget"
name=
"centralwidget"
>
<widget
class=
"QPushButton"
name=
"but1"
>
<property
name=
"geometry"
>
<rect>
<x>
410
</x>
<y>
330
</y>
<width>
99
</width>
<height>
27
</height>
</rect>
</property>
<property
name=
"text"
>
<string>
PushButton
</string>
</property>
</widget>
<widget
class=
"QRadioButton"
name=
"radioButton"
>
<property
name=
"geometry"
>
<rect>
<x>
80
</x>
<y>
150
</y>
<width>
117
</width>
<height>
22
</height>
</rect>
</property>
<property
name=
"text"
>
<string>
RadioButton
</string>
</property>
</widget>
</widget>
<widget
class=
"QMenuBar"
name=
"menubar"
>
<property
name=
"geometry"
>
<rect>
<x>
0
</x>
<y>
0
</y>
<width>
800
</width>
<height>
25
</height>
</rect>
</property>
</widget>
<widget
class=
"QStatusBar"
name=
"statusbar"
/>
</widget>
<resources/>
<connections/>
</ui>
sw/python_gui/test1.py
deleted
100755 → 0
View file @
3af98e16
#!/usr/bin/python3
###############################################################################
# This work is part of the Distributed I/O Tier project
# Copyright (c) 2018 CERN (www.cern.ch)
# Author: Greg Daniluk <grzegorz.daniluk@cern.ch>
# Released according to the GNU GPL, version 2 or any later version.
###############################################################################
import
sys
import
copy
from
PyQt5.QtWidgets
import
*
from
PyQt5
import
QtCore
from
ui_dialog
import
Ui_Dialog
import
threading
import
time
class
TestDialog
(
QDialog
,
Ui_Dialog
):
def
__init__
(
self
):
super
(
TestDialog
,
self
)
.
__init__
()
# setup GUI from Qt Designer
self
.
setupUi
(
self
)
self
.
show
()
##########################################################
## DiotSlot class definition ##
##########################################################
class
DiotSlot
():
def
__init__
(
self
,
Dialog
,
num
,
idx
):
self
.
btn_state
=
[]
self
.
io_state
=
[]
self
.
btn_test
=
[]
#######################
self
.
groupBox
=
QGroupBox
(
Dialog
)
self
.
groupBox
.
setGeometry
(
QtCore
.
QRect
(
20
+
idx
*
170
,
20
,
150
,
40
+
num
*
30
))
self
.
groupBox
.
setTitle
(
"Slot "
+
str
(
idx
+
1
))
for
i
in
range
(
0
,
num
):
self
.
io_state
.
append
(
True
)
self
.
btn_state
.
append
(
QPushButton
(
self
.
groupBox
))
self
.
btn_state
[
i
]
.
setGeometry
(
QtCore
.
QRect
(
20
,
30
+
i
*
30
,
30
,
30
))
self
.
btn_state
[
i
]
.
setText
(
str
((
i
+
1
)
+
idx
*
num
))
self
.
btn_state
[
i
]
.
setStyleSheet
(
"background-color: green"
)
self
.
btn_test
.
append
(
QPushButton
(
self
.
groupBox
))
self
.
btn_test
[
i
]
.
setGeometry
(
QtCore
.
QRect
(
50
,
30
+
i
*
30
,
80
,
30
))
self
.
btn_test
[
i
]
.
setText
(
"Test"
)
self
.
btn_test
[
i
]
.
clicked
.
connect
(
lambda
state
,
slot
=
idx
,
io
=
i
:
self
.
action_click
(
slot
,
io
))
def
action_click
(
self
,
slot
,
io
):
print
(
"Button test clicked - slot("
+
str
(
slot
)
+
") io("
+
str
(
io
)
+
")"
)
## TODO: add here sending new output state over fieldbus
self
.
update_state
(
io
,
not
self
.
io_state
[
io
])
def
update_state
(
self
,
io
,
new_state
):
self
.
io_state
[
io
]
=
new_state
# and refresh color
if
self
.
io_state
[
io
]
==
True
:
self
.
btn_state
[
io
]
.
setStyleSheet
(
"background-color: green"
)
else
:
self
.
btn_state
[
io
]
.
setStyleSheet
(
"background-color: red"
)
##########################################################
## Thread class definition ##
##########################################################
class
ReadThread
(
threading
.
Thread
):
def
__init__
(
self
,
threadID
,
name
,
slots
):
threading
.
Thread
.
__init__
(
self
)
self
.
threadID
=
threadID
self
.
name
=
name
self
.
slots
=
slots
self
.
end_thread
=
0
def
run
(
self
):
## TODO: put here cyclic reading of all IO state
while
self
.
end_thread
==
0
:
time
.
sleep
(
1
)
self
.
slots
[
3
]
.
update_state
(
5
,
not
self
.
slots
[
3
]
.
io_state
[
5
])
print
(
"thread updated io"
)
def
stop
(
self
):
self
.
end_thread
=
1
if
__name__
==
'__main__'
:
app
=
QApplication
(
sys
.
argv
)
#w = TestDialog()
w
=
QDialog
()
slots
=
[]
for
i
in
range
(
0
,
8
):
slots
.
append
(
DiotSlot
(
w
,
16
,
i
))
#ui = Ui_Dialog()
#ui.setupUi(w)
w
.
show
()
thread1
=
ReadThread
(
1
,
"ReadThread-1"
,
slots
)
thread1
.
start
()
sys
.
exit
(
app
.
exec_
())
print
(
"Exiting"
)
thread1
.
stop
()
print
(
"thread stopped?"
)
sw/python_gui/ui_dialog.py
deleted
100644 → 0
View file @
3af98e16
# -*- coding: utf-8 -*-
# Form implementation generated from reading ui file 'dialog.ui'
#
# Created by: PyQt5 UI code generator 5.10.1
#
# WARNING! All changes made in this file will be lost!
from
PyQt5
import
QtCore
,
QtGui
,
QtWidgets
class
Ui_Dialog
(
object
):
def
setupUi
(
self
,
Dialog
):
Dialog
.
setObjectName
(
"Dialog"
)
Dialog
.
resize
(
510
,
597
)
self
.
groupBox
=
QtWidgets
.
QGroupBox
(
Dialog
)
self
.
groupBox
.
setGeometry
(
QtCore
.
QRect
(
70
,
90
,
101
,
351
))
self
.
groupBox
.
setObjectName
(
"groupBox"
)
self
.
pushButton
=
QtWidgets
.
QPushButton
(
self
.
groupBox
)
self
.
pushButton
.
setGeometry
(
QtCore
.
QRect
(
0
,
90
,
31
,
27
))
self
.
pushButton
.
setCheckable
(
False
)
self
.
pushButton
.
setChecked
(
False
)
self
.
pushButton
.
setObjectName
(
"pushButton"
)
self
.
pushButton_2
=
QtWidgets
.
QPushButton
(
self
.
groupBox
)
self
.
pushButton_2
.
setGeometry
(
QtCore
.
QRect
(
0
,
120
,
31
,
27
))
self
.
pushButton_2
.
setCheckable
(
False
)
self
.
pushButton_2
.
setChecked
(
False
)
self
.
pushButton_2
.
setObjectName
(
"pushButton_2"
)
self
.
groupBox_2
=
QtWidgets
.
QGroupBox
(
Dialog
)
self
.
groupBox_2
.
setGeometry
(
QtCore
.
QRect
(
220
,
90
,
101
,
351
))
self
.
groupBox_2
.
setObjectName
(
"groupBox_2"
)
self
.
pushButton_3
=
QtWidgets
.
QPushButton
(
self
.
groupBox_2
)
self
.
pushButton_3
.
setGeometry
(
QtCore
.
QRect
(
0
,
90
,
31
,
27
))
self
.
pushButton_3
.
setCheckable
(
False
)
self
.
pushButton_3
.
setChecked
(
False
)
self
.
pushButton_3
.
setObjectName
(
"pushButton_3"
)
self
.
pushButton_4
=
QtWidgets
.
QPushButton
(
self
.
groupBox_2
)
self
.
pushButton_4
.
setGeometry
(
QtCore
.
QRect
(
0
,
120
,
31
,
27
))
self
.
pushButton_4
.
setCheckable
(
False
)
self
.
pushButton_4
.
setChecked
(
False
)
self
.
pushButton_4
.
setObjectName
(
"pushButton_4"
)
self
.
retranslateUi
(
Dialog
)
QtCore
.
QMetaObject
.
connectSlotsByName
(
Dialog
)
def
retranslateUi
(
self
,
Dialog
):
_translate
=
QtCore
.
QCoreApplication
.
translate
Dialog
.
setWindowTitle
(
_translate
(
"Dialog"
,
"Dialog"
))
self
.
groupBox
.
setTitle
(
_translate
(
"Dialog"
,
"Slot 1"
))
self
.
pushButton
.
setText
(
_translate
(
"Dialog"
,
"1"
))
self
.
pushButton_2
.
setText
(
_translate
(
"Dialog"
,
"2"
))
self
.
groupBox_2
.
setTitle
(
_translate
(
"Dialog"
,
"Slot 2"
))
self
.
pushButton_3
.
setText
(
_translate
(
"Dialog"
,
"3"
))
self
.
pushButton_4
.
setText
(
_translate
(
"Dialog"
,
"4"
))
sw/python_gui/ui_main_win.py
deleted
100644 → 0
View file @
3af98e16
# -*- coding: utf-8 -*-
# Form implementation generated from reading ui file 'main_win.ui'
#
# Created by: PyQt5 UI code generator 5.10.1
#
# WARNING! All changes made in this file will be lost!
from
PyQt5
import
QtCore
,
QtGui
,
QtWidgets
class
Ui_MainWindow
(
object
):
def
setupUi
(
self
,
MainWindow
):
MainWindow
.
setObjectName
(
"MainWindow"
)
MainWindow
.
resize
(
800
,
600
)
self
.
centralwidget
=
QtWidgets
.
QWidget
(
MainWindow
)
self
.
centralwidget
.
setObjectName
(
"centralwidget"
)
self
.
but1
=
QtWidgets
.
QPushButton
(
self
.
centralwidget
)
self
.
but1
.
setGeometry
(
QtCore
.
QRect
(
410
,
330
,
99
,
27
))
self
.
but1
.
setObjectName
(
"but1"
)
self
.
radioButton
=
QtWidgets
.
QRadioButton
(
self
.
centralwidget
)
self
.
radioButton
.
setGeometry
(
QtCore
.
QRect
(
140
,
180
,
117
,
22
))
self
.
radioButton
.
setObjectName
(
"radioButton"
)
MainWindow
.
setCentralWidget
(
self
.
centralwidget
)
self
.
menubar
=
QtWidgets
.
QMenuBar
(
MainWindow
)
self
.
menubar
.
setGeometry
(
QtCore
.
QRect
(
0
,
0
,
800
,
25
))
self
.
menubar
.
setObjectName
(
"menubar"
)
MainWindow
.
setMenuBar
(
self
.
menubar
)
self
.
statusbar
=
QtWidgets
.
QStatusBar
(
MainWindow
)
self
.
statusbar
.
setObjectName
(
"statusbar"
)
MainWindow
.
setStatusBar
(
self
.
statusbar
)
self
.
retranslateUi
(
MainWindow
)
QtCore
.
QMetaObject
.
connectSlotsByName
(
MainWindow
)
def
retranslateUi
(
self
,
MainWindow
):
_translate
=
QtCore
.
QCoreApplication
.
translate
MainWindow
.
setWindowTitle
(
_translate
(
"MainWindow"
,
"MainWindow"
))
self
.
but1
.
setText
(
_translate
(
"MainWindow"
,
"PushButton"
))
self
.
radioButton
.
setText
(
_translate
(
"MainWindow"
,
"RadioButton"
))
Write
Preview
Markdown
is supported
0%
Try again
or
attach a new file
Attach a file
Cancel
You are about to add
0
people
to the discussion. Proceed with caution.
Finish editing this message first!
Cancel
Please
register
or
sign in
to comment