pyxcp 0.25.2__cp313-cp313-manylinux_2_27_x86_64.manylinux_2_28_x86_64.whl
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- pyxcp/__init__.py +20 -0
- pyxcp/aml/EtasCANMonitoring.a2l +82 -0
- pyxcp/aml/EtasCANMonitoring.aml +67 -0
- pyxcp/aml/XCP_Common.aml +408 -0
- pyxcp/aml/XCPonCAN.aml +78 -0
- pyxcp/aml/XCPonEth.aml +33 -0
- pyxcp/aml/XCPonFlx.aml +113 -0
- pyxcp/aml/XCPonSxI.aml +66 -0
- pyxcp/aml/XCPonUSB.aml +106 -0
- pyxcp/aml/ifdata_CAN.a2l +20 -0
- pyxcp/aml/ifdata_Eth.a2l +11 -0
- pyxcp/aml/ifdata_Flx.a2l +94 -0
- pyxcp/aml/ifdata_SxI.a2l +13 -0
- pyxcp/aml/ifdata_USB.a2l +81 -0
- pyxcp/asam/__init__.py +0 -0
- pyxcp/asam/types.py +131 -0
- pyxcp/asamkeydll +0 -0
- pyxcp/asamkeydll.c +116 -0
- pyxcp/asamkeydll.sh +2 -0
- pyxcp/checksum.py +732 -0
- pyxcp/cmdline.py +83 -0
- pyxcp/config/__init__.py +1257 -0
- pyxcp/config/legacy.py +120 -0
- pyxcp/constants.py +47 -0
- pyxcp/cpp_ext/__init__.py +0 -0
- pyxcp/cpp_ext/aligned_buffer.hpp +168 -0
- pyxcp/cpp_ext/bin.hpp +105 -0
- pyxcp/cpp_ext/blockmem.hpp +58 -0
- pyxcp/cpp_ext/cpp_ext.cpython-310-x86_64-linux-gnu.so +0 -0
- pyxcp/cpp_ext/cpp_ext.cpython-311-x86_64-linux-gnu.so +0 -0
- pyxcp/cpp_ext/cpp_ext.cpython-312-x86_64-linux-gnu.so +0 -0
- pyxcp/cpp_ext/cpp_ext.cpython-313-x86_64-linux-gnu.so +0 -0
- pyxcp/cpp_ext/daqlist.hpp +374 -0
- pyxcp/cpp_ext/event.hpp +67 -0
- pyxcp/cpp_ext/extension_wrapper.cpp +131 -0
- pyxcp/cpp_ext/framing.hpp +360 -0
- pyxcp/cpp_ext/helper.hpp +280 -0
- pyxcp/cpp_ext/mcobject.hpp +248 -0
- pyxcp/cpp_ext/sxi_framing.hpp +332 -0
- pyxcp/cpp_ext/tsqueue.hpp +46 -0
- pyxcp/daq_stim/__init__.py +306 -0
- pyxcp/daq_stim/optimize/__init__.py +67 -0
- pyxcp/daq_stim/optimize/binpacking.py +41 -0
- pyxcp/daq_stim/scheduler.cpp +62 -0
- pyxcp/daq_stim/scheduler.hpp +75 -0
- pyxcp/daq_stim/stim.cpp +13 -0
- pyxcp/daq_stim/stim.cpython-310-x86_64-linux-gnu.so +0 -0
- pyxcp/daq_stim/stim.cpython-311-x86_64-linux-gnu.so +0 -0
- pyxcp/daq_stim/stim.cpython-312-x86_64-linux-gnu.so +0 -0
- pyxcp/daq_stim/stim.cpython-313-x86_64-linux-gnu.so +0 -0
- pyxcp/daq_stim/stim.hpp +604 -0
- pyxcp/daq_stim/stim_wrapper.cpp +50 -0
- pyxcp/dllif.py +100 -0
- pyxcp/errormatrix.py +878 -0
- pyxcp/examples/conf_can.toml +19 -0
- pyxcp/examples/conf_can_user.toml +16 -0
- pyxcp/examples/conf_can_vector.json +11 -0
- pyxcp/examples/conf_can_vector.toml +11 -0
- pyxcp/examples/conf_eth.toml +9 -0
- pyxcp/examples/conf_nixnet.json +20 -0
- pyxcp/examples/conf_socket_can.toml +12 -0
- pyxcp/examples/run_daq.py +165 -0
- pyxcp/examples/xcp_policy.py +60 -0
- pyxcp/examples/xcp_read_benchmark.py +38 -0
- pyxcp/examples/xcp_skel.py +48 -0
- pyxcp/examples/xcp_unlock.py +38 -0
- pyxcp/examples/xcp_user_supplied_driver.py +43 -0
- pyxcp/examples/xcphello.py +79 -0
- pyxcp/examples/xcphello_recorder.py +107 -0
- pyxcp/master/__init__.py +10 -0
- pyxcp/master/errorhandler.py +677 -0
- pyxcp/master/master.py +2645 -0
- pyxcp/py.typed +0 -0
- pyxcp/recorder/.idea/.gitignore +8 -0
- pyxcp/recorder/.idea/misc.xml +4 -0
- pyxcp/recorder/.idea/modules.xml +8 -0
- pyxcp/recorder/.idea/recorder.iml +6 -0
- pyxcp/recorder/.idea/sonarlint/issuestore/3/8/3808afc69ac1edb9d760000a2f137335b1b99728 +7 -0
- pyxcp/recorder/.idea/sonarlint/issuestore/9/a/9a2aa4db38d3115ed60da621e012c0efc0172aae +0 -0
- pyxcp/recorder/.idea/sonarlint/issuestore/b/4/b49006702b459496a8e8c94ebe60947108361b91 +0 -0
- pyxcp/recorder/.idea/sonarlint/issuestore/index.pb +7 -0
- pyxcp/recorder/.idea/sonarlint/securityhotspotstore/3/8/3808afc69ac1edb9d760000a2f137335b1b99728 +0 -0
- pyxcp/recorder/.idea/sonarlint/securityhotspotstore/9/a/9a2aa4db38d3115ed60da621e012c0efc0172aae +0 -0
- pyxcp/recorder/.idea/sonarlint/securityhotspotstore/b/4/b49006702b459496a8e8c94ebe60947108361b91 +0 -0
- pyxcp/recorder/.idea/sonarlint/securityhotspotstore/index.pb +7 -0
- pyxcp/recorder/.idea/vcs.xml +10 -0
- pyxcp/recorder/__init__.py +96 -0
- pyxcp/recorder/build_clang.cmd +1 -0
- pyxcp/recorder/build_clang.sh +2 -0
- pyxcp/recorder/build_gcc.cmd +1 -0
- pyxcp/recorder/build_gcc.sh +2 -0
- pyxcp/recorder/build_gcc_arm.sh +2 -0
- pyxcp/recorder/converter/__init__.py +445 -0
- pyxcp/recorder/lz4.c +2829 -0
- pyxcp/recorder/lz4.h +879 -0
- pyxcp/recorder/lz4hc.c +2041 -0
- pyxcp/recorder/lz4hc.h +413 -0
- pyxcp/recorder/mio.hpp +1714 -0
- pyxcp/recorder/reader.hpp +138 -0
- pyxcp/recorder/reco.py +278 -0
- pyxcp/recorder/recorder.rst +0 -0
- pyxcp/recorder/rekorder.cpp +59 -0
- pyxcp/recorder/rekorder.cpython-310-x86_64-linux-gnu.so +0 -0
- pyxcp/recorder/rekorder.cpython-311-x86_64-linux-gnu.so +0 -0
- pyxcp/recorder/rekorder.cpython-312-x86_64-linux-gnu.so +0 -0
- pyxcp/recorder/rekorder.cpython-313-x86_64-linux-gnu.so +0 -0
- pyxcp/recorder/rekorder.hpp +274 -0
- pyxcp/recorder/setup.py +41 -0
- pyxcp/recorder/test_reko.py +34 -0
- pyxcp/recorder/unfolder.hpp +1354 -0
- pyxcp/recorder/wrap.cpp +184 -0
- pyxcp/recorder/writer.hpp +302 -0
- pyxcp/scripts/__init__.py +0 -0
- pyxcp/scripts/pyxcp_probe_can_drivers.py +20 -0
- pyxcp/scripts/xcp_examples.py +64 -0
- pyxcp/scripts/xcp_fetch_a2l.py +40 -0
- pyxcp/scripts/xcp_id_scanner.py +18 -0
- pyxcp/scripts/xcp_info.py +144 -0
- pyxcp/scripts/xcp_profile.py +26 -0
- pyxcp/scripts/xmraw_converter.py +31 -0
- pyxcp/stim/__init__.py +0 -0
- pyxcp/tests/test_asam_types.py +24 -0
- pyxcp/tests/test_binpacking.py +186 -0
- pyxcp/tests/test_can.py +1324 -0
- pyxcp/tests/test_checksum.py +95 -0
- pyxcp/tests/test_daq.py +193 -0
- pyxcp/tests/test_daq_opt.py +426 -0
- pyxcp/tests/test_frame_padding.py +156 -0
- pyxcp/tests/test_framing.py +262 -0
- pyxcp/tests/test_master.py +2116 -0
- pyxcp/tests/test_transport.py +177 -0
- pyxcp/tests/test_utils.py +30 -0
- pyxcp/timing.py +60 -0
- pyxcp/transport/__init__.py +13 -0
- pyxcp/transport/base.py +484 -0
- pyxcp/transport/base_transport.hpp +0 -0
- pyxcp/transport/can.py +660 -0
- pyxcp/transport/eth.py +254 -0
- pyxcp/transport/sxi.py +209 -0
- pyxcp/transport/transport_ext.hpp +214 -0
- pyxcp/transport/transport_wrapper.cpp +249 -0
- pyxcp/transport/usb_transport.py +229 -0
- pyxcp/types.py +987 -0
- pyxcp/utils.py +127 -0
- pyxcp/vector/__init__.py +0 -0
- pyxcp/vector/map.py +82 -0
- pyxcp-0.25.2.dist-info/METADATA +341 -0
- pyxcp-0.25.2.dist-info/RECORD +151 -0
- pyxcp-0.25.2.dist-info/WHEEL +6 -0
- pyxcp-0.25.2.dist-info/entry_points.txt +9 -0
- pyxcp-0.25.2.dist-info/licenses/LICENSE +165 -0
pyxcp/daq_stim/stim.hpp
ADDED
|
@@ -0,0 +1,604 @@
|
|
|
1
|
+
|
|
2
|
+
#if !defined(__STIM_HPP)
|
|
3
|
+
#define __STIM_HPP
|
|
4
|
+
|
|
5
|
+
#include <pybind11/pybind11.h>
|
|
6
|
+
|
|
7
|
+
#include <algorithm>
|
|
8
|
+
#include <cstdint>
|
|
9
|
+
#include <functional>
|
|
10
|
+
#include <iostream>
|
|
11
|
+
#include <map>
|
|
12
|
+
#include <mutex>
|
|
13
|
+
#include <numeric>
|
|
14
|
+
#include <optional>
|
|
15
|
+
#include <queue>
|
|
16
|
+
#include <set>
|
|
17
|
+
#include <sstream>
|
|
18
|
+
#include <tuple>
|
|
19
|
+
#include <vector>
|
|
20
|
+
|
|
21
|
+
#include "helper.hpp"
|
|
22
|
+
#include "scheduler.hpp"
|
|
23
|
+
|
|
24
|
+
#if defined(_MSC_VER) && (defined(_WIN32) || defined(_WIN64))
|
|
25
|
+
#include <Avrt.h>
|
|
26
|
+
#include <Windows.h>
|
|
27
|
+
#endif
|
|
28
|
+
|
|
29
|
+
namespace py = pybind11;
|
|
30
|
+
|
|
31
|
+
constexpr double TMR_RESOLUTION = 1.0 / 1000.0; // Timer resolution is one millisecond.
|
|
32
|
+
|
|
33
|
+
constexpr std::uint8_t MIN_STIM_PID = 0x00;
|
|
34
|
+
constexpr std::uint8_t MAX_STIM_PID = 0xBF;
|
|
35
|
+
|
|
36
|
+
struct DAQListType {};
|
|
37
|
+
|
|
38
|
+
///// From BlueParrot XCP.
|
|
39
|
+
|
|
40
|
+
using XcpDaq_ODTEntryIntegerType = std::uint16_t;
|
|
41
|
+
using XcpDaq_ODTIntegerType = std::uint16_t;
|
|
42
|
+
|
|
43
|
+
typedef enum tagXcpDaq_DirectionType {
|
|
44
|
+
XCP_DIRECTION_NONE,
|
|
45
|
+
XCP_DIRECTION_DAQ,
|
|
46
|
+
XCP_DIRECTION_STIM,
|
|
47
|
+
XCP_DIRECTION_DAQ_STIM
|
|
48
|
+
} XcpDaq_DirectionType;
|
|
49
|
+
|
|
50
|
+
//////////////// C++ style ////////////////
|
|
51
|
+
|
|
52
|
+
struct OdtEntryType {
|
|
53
|
+
void clear() {
|
|
54
|
+
address = 0;
|
|
55
|
+
address_extension = 0;
|
|
56
|
+
bitOffset = 0;
|
|
57
|
+
entry_size = 0;
|
|
58
|
+
}
|
|
59
|
+
|
|
60
|
+
std::uint32_t address;
|
|
61
|
+
std::uint16_t address_extension;
|
|
62
|
+
std::uint16_t bitOffset;
|
|
63
|
+
std::uint32_t entry_size;
|
|
64
|
+
};
|
|
65
|
+
|
|
66
|
+
struct OdtType {
|
|
67
|
+
XcpDaq_ODTEntryIntegerType numOdtEntries;
|
|
68
|
+
std::uint16_t firstOdtEntry;
|
|
69
|
+
|
|
70
|
+
void clear() {
|
|
71
|
+
m_entries.resize(0);
|
|
72
|
+
}
|
|
73
|
+
|
|
74
|
+
void resize(std::uint16_t n) {
|
|
75
|
+
m_entries.resize(n);
|
|
76
|
+
}
|
|
77
|
+
|
|
78
|
+
std::vector<OdtEntryType> m_entries;
|
|
79
|
+
};
|
|
80
|
+
|
|
81
|
+
struct DynamicListType {
|
|
82
|
+
void clear() {
|
|
83
|
+
numOdts = 0;
|
|
84
|
+
firstOdt = 0;
|
|
85
|
+
mode = 0;
|
|
86
|
+
prescaler = 0;
|
|
87
|
+
counter = 0;
|
|
88
|
+
event_channel_number = 0;
|
|
89
|
+
priority = 0;
|
|
90
|
+
m_odts.resize(0);
|
|
91
|
+
}
|
|
92
|
+
|
|
93
|
+
void resize(std::size_t n) {
|
|
94
|
+
m_odts.resize(n);
|
|
95
|
+
}
|
|
96
|
+
|
|
97
|
+
XcpDaq_ODTIntegerType numOdts;
|
|
98
|
+
std::uint16_t firstOdt;
|
|
99
|
+
std::uint16_t mode;
|
|
100
|
+
|
|
101
|
+
std::uint16_t prescaler;
|
|
102
|
+
std::uint16_t event_channel_number;
|
|
103
|
+
std::uint16_t counter;
|
|
104
|
+
std::uint16_t priority;
|
|
105
|
+
|
|
106
|
+
std::vector<OdtType> m_odts{};
|
|
107
|
+
};
|
|
108
|
+
|
|
109
|
+
//////////////// C++ style ////////////////
|
|
110
|
+
|
|
111
|
+
typedef struct tagXcpDaq_ListConfigurationType {
|
|
112
|
+
XcpDaq_ODTIntegerType numOdts;
|
|
113
|
+
std::uint16_t firstOdt;
|
|
114
|
+
} XcpDaq_ListConfigurationType;
|
|
115
|
+
|
|
116
|
+
typedef struct tagXcpDaq_ListStateType {
|
|
117
|
+
std::uint16_t mode;
|
|
118
|
+
#if XCP_DAQ_ENABLE_PRESCALER == XCP_ON
|
|
119
|
+
std::uint16_t prescaler;
|
|
120
|
+
std::uint16_t counter;
|
|
121
|
+
#endif /* XCP_DAQ_ENABLE_PRESCALER */
|
|
122
|
+
} XcpDaq_ListStateType;
|
|
123
|
+
|
|
124
|
+
typedef enum tagXcpDaq_EntityKindType {
|
|
125
|
+
XCP_ENTITY_UNUSED,
|
|
126
|
+
XCP_ENTITY_DAQ_LIST,
|
|
127
|
+
XCP_ENTITY_ODT,
|
|
128
|
+
XCP_ENTITY_ODT_ENTRY
|
|
129
|
+
} XcpDaq_EntityKindType;
|
|
130
|
+
|
|
131
|
+
typedef struct tagXcpDaq_EventType {
|
|
132
|
+
std::uint8_t const * const name;
|
|
133
|
+
std::uint8_t nameLen;
|
|
134
|
+
std::uint8_t properties;
|
|
135
|
+
std::uint8_t timeunit;
|
|
136
|
+
std::uint8_t cycle;
|
|
137
|
+
/* unit8_t priority; */
|
|
138
|
+
} XcpDaq_EventType;
|
|
139
|
+
|
|
140
|
+
typedef struct tagXcpDaq_MessageType {
|
|
141
|
+
std::uint8_t dlc;
|
|
142
|
+
std::uint8_t const * data;
|
|
143
|
+
} XcpDaq_MessageType;
|
|
144
|
+
|
|
145
|
+
/////
|
|
146
|
+
|
|
147
|
+
class FakeEnum {
|
|
148
|
+
public:
|
|
149
|
+
|
|
150
|
+
FakeEnum(std::uint8_t value) : m_value(value) {
|
|
151
|
+
}
|
|
152
|
+
|
|
153
|
+
const std::string get_name() const {
|
|
154
|
+
return std::string("STIM");
|
|
155
|
+
}
|
|
156
|
+
|
|
157
|
+
const std::uint8_t get_value() const {
|
|
158
|
+
return m_value;
|
|
159
|
+
}
|
|
160
|
+
|
|
161
|
+
operator int() const {
|
|
162
|
+
return m_value;
|
|
163
|
+
}
|
|
164
|
+
|
|
165
|
+
int bit_length() const {
|
|
166
|
+
return 8;
|
|
167
|
+
}
|
|
168
|
+
|
|
169
|
+
py::bytes to_bytes(std::uint8_t length, std::string_view encoding) const {
|
|
170
|
+
std::stringstream ss;
|
|
171
|
+
|
|
172
|
+
ss << m_value;
|
|
173
|
+
return py::bytes(ss.str());
|
|
174
|
+
}
|
|
175
|
+
|
|
176
|
+
private:
|
|
177
|
+
|
|
178
|
+
std::uint8_t m_value;
|
|
179
|
+
};
|
|
180
|
+
|
|
181
|
+
struct StimParameters {
|
|
182
|
+
std::byte max_dto;
|
|
183
|
+
};
|
|
184
|
+
|
|
185
|
+
struct DaqEventInfo {
|
|
186
|
+
explicit DaqEventInfo(
|
|
187
|
+
/*std::string_view*/ const std::string& name, std::int8_t unit_exp, std::size_t cycle, std::size_t maxDaqList,
|
|
188
|
+
std::size_t priority, std::string_view consistency, bool daq, bool stim, bool packed
|
|
189
|
+
) :
|
|
190
|
+
m_name(name),
|
|
191
|
+
m_unit_exp(unit_exp),
|
|
192
|
+
m_cycle(cycle),
|
|
193
|
+
m_maxDaqList(maxDaqList),
|
|
194
|
+
m_priority(priority),
|
|
195
|
+
m_consistency(consistency),
|
|
196
|
+
m_daq(daq),
|
|
197
|
+
m_stim(stim),
|
|
198
|
+
m_packed(packed) {
|
|
199
|
+
if (cycle == 0) {
|
|
200
|
+
m_periodic = false;
|
|
201
|
+
m_cycle_time = 0;
|
|
202
|
+
} else {
|
|
203
|
+
m_periodic = true;
|
|
204
|
+
auto cycle_time = cycle * std::pow(10, unit_exp);
|
|
205
|
+
if (cycle_time < TMR_RESOLUTION) {
|
|
206
|
+
cycle_time = TMR_RESOLUTION;
|
|
207
|
+
}
|
|
208
|
+
m_cycle_time = static_cast<std::size_t>(cycle_time * 1000.0);
|
|
209
|
+
}
|
|
210
|
+
}
|
|
211
|
+
|
|
212
|
+
public:
|
|
213
|
+
|
|
214
|
+
std::string m_name;
|
|
215
|
+
std::int8_t m_unit_exp;
|
|
216
|
+
std::size_t m_cycle;
|
|
217
|
+
std::size_t m_maxDaqList;
|
|
218
|
+
std::size_t m_priority;
|
|
219
|
+
std::string m_consistency{};
|
|
220
|
+
bool m_daq;
|
|
221
|
+
bool m_stim;
|
|
222
|
+
bool m_packed;
|
|
223
|
+
bool m_periodic;
|
|
224
|
+
std::size_t m_cycle_time;
|
|
225
|
+
std::set<std::uint16_t> m_daq_lists{};
|
|
226
|
+
};
|
|
227
|
+
|
|
228
|
+
enum class EventChannelTimeUnit : std::uint8_t {
|
|
229
|
+
EVENT_CHANNEL_TIME_UNIT_1NS = 0,
|
|
230
|
+
EVENT_CHANNEL_TIME_UNIT_10NS = 1,
|
|
231
|
+
EVENT_CHANNEL_TIME_UNIT_100NS = 2,
|
|
232
|
+
EVENT_CHANNEL_TIME_UNIT_1US = 3,
|
|
233
|
+
EVENT_CHANNEL_TIME_UNIT_10US = 4,
|
|
234
|
+
EVENT_CHANNEL_TIME_UNIT_100US = 5,
|
|
235
|
+
EVENT_CHANNEL_TIME_UNIT_1MS = 6,
|
|
236
|
+
EVENT_CHANNEL_TIME_UNIT_10MS = 7,
|
|
237
|
+
EVENT_CHANNEL_TIME_UNIT_100MS = 8,
|
|
238
|
+
EVENT_CHANNEL_TIME_UNIT_1S = 9,
|
|
239
|
+
EVENT_CHANNEL_TIME_UNIT_1PS = 10,
|
|
240
|
+
EVENT_CHANNEL_TIME_UNIT_10PS = 11,
|
|
241
|
+
EVENT_CHANNEL_TIME_UNIT_100PS = 12,
|
|
242
|
+
};
|
|
243
|
+
|
|
244
|
+
enum class DAQ_TIMESTAMP_UNIT_TO_EXP : std::int8_t {
|
|
245
|
+
DAQ_TIMESTAMP_UNIT_1PS = -12,
|
|
246
|
+
DAQ_TIMESTAMP_UNIT_10PS = -11,
|
|
247
|
+
DAQ_TIMESTAMP_UNIT_100PS = -10,
|
|
248
|
+
DAQ_TIMESTAMP_UNIT_1NS = -9,
|
|
249
|
+
DAQ_TIMESTAMP_UNIT_10NS = -8,
|
|
250
|
+
DAQ_TIMESTAMP_UNIT_100NS = -7,
|
|
251
|
+
DAQ_TIMESTAMP_UNIT_1US = -6,
|
|
252
|
+
DAQ_TIMESTAMP_UNIT_10US = -5,
|
|
253
|
+
DAQ_TIMESTAMP_UNIT_100US = -4,
|
|
254
|
+
DAQ_TIMESTAMP_UNIT_1MS = -3,
|
|
255
|
+
DAQ_TIMESTAMP_UNIT_10MS = -2,
|
|
256
|
+
DAQ_TIMESTAMP_UNIT_100MS = -1,
|
|
257
|
+
DAQ_TIMESTAMP_UNIT_1S = 0,
|
|
258
|
+
};
|
|
259
|
+
|
|
260
|
+
void sched_init(); // TODO: Incl.
|
|
261
|
+
|
|
262
|
+
class Stim {
|
|
263
|
+
public:
|
|
264
|
+
|
|
265
|
+
const std::uint8_t RESUME = 0x80;
|
|
266
|
+
const std::uint8_t RUNNING = 0x40;
|
|
267
|
+
const std::uint8_t PID_OFF = 0x20;
|
|
268
|
+
const std::uint8_t TIMESTAMP = 0x10;
|
|
269
|
+
const std::uint8_t DIRECTION = 0x02;
|
|
270
|
+
const std::uint8_t SELECTED = 0x01;
|
|
271
|
+
|
|
272
|
+
const std::uint8_t DIRECTION_STIM = 0x02;
|
|
273
|
+
|
|
274
|
+
using feed_function_t = std::function<void(std::size_t, std::size_t, float, std::vector<std::uint8_t>)>;
|
|
275
|
+
using send_function_t = std::function<void(FakeEnum, std::vector<std::uint8_t>)>;
|
|
276
|
+
|
|
277
|
+
explicit Stim(bool activate = true) : m_activate(activate) {
|
|
278
|
+
#if defined(_MSC_VER) && (defined(_WIN32) || defined(_WIN64))
|
|
279
|
+
if (timeBeginPeriod(100) == TIMERR_NOERROR) {
|
|
280
|
+
// std::cout << "timeBeginPeriod() OK!!!" << std::endl;
|
|
281
|
+
} else {
|
|
282
|
+
// std::cout << "timeBeginPeriod() failed!!!" << std::endl;
|
|
283
|
+
}
|
|
284
|
+
|
|
285
|
+
DWORD task_index = 0UL;
|
|
286
|
+
|
|
287
|
+
auto xxx = AvSetMmThreadCharacteristics("Pro Audio", &task_index);
|
|
288
|
+
|
|
289
|
+
auto start = timeGetTime();
|
|
290
|
+
#endif
|
|
291
|
+
// m_scheduler.start_thread();
|
|
292
|
+
}
|
|
293
|
+
|
|
294
|
+
void setParameters(const StimParameters& params) {
|
|
295
|
+
m_params = params;
|
|
296
|
+
}
|
|
297
|
+
|
|
298
|
+
void setDaqEventInfo(const std::vector<DaqEventInfo>& daq_event_info) {
|
|
299
|
+
std::uint16_t idx = 0;
|
|
300
|
+
|
|
301
|
+
// DBG_PRINTN("SET_DAQ_EVENT_INFO\n");
|
|
302
|
+
if (!m_activate) {
|
|
303
|
+
return;
|
|
304
|
+
}
|
|
305
|
+
|
|
306
|
+
for (const auto& event : daq_event_info) {
|
|
307
|
+
m_daq_event_info.try_emplace(idx, event);
|
|
308
|
+
if (event.m_stim) {
|
|
309
|
+
// std::cout << "\tSTIM: " << event.m_name << ":" << idx << std::endl;
|
|
310
|
+
}
|
|
311
|
+
idx++;
|
|
312
|
+
}
|
|
313
|
+
}
|
|
314
|
+
|
|
315
|
+
void setDaqPtr(std::uint16_t daqListNumber, std::uint16_t odtNumber, std::uint16_t odtEntryNumber) {
|
|
316
|
+
if (!m_activate) {
|
|
317
|
+
return;
|
|
318
|
+
}
|
|
319
|
+
|
|
320
|
+
if (!validateEntryNumber(daqListNumber, odtNumber, odtEntryNumber)) {
|
|
321
|
+
return;
|
|
322
|
+
}
|
|
323
|
+
m_daq_ptr = { daqListNumber, odtNumber, odtEntryNumber };
|
|
324
|
+
// DBG_PRINTN("SET_DAQ_PTR -- daq:", daqListNumber, " odt:", odtNumber, " entry:", odtEntryNumber, std::endl);
|
|
325
|
+
}
|
|
326
|
+
|
|
327
|
+
void clearDaqList(std::uint16_t daqListNumber) {
|
|
328
|
+
if (!m_activate) {
|
|
329
|
+
return;
|
|
330
|
+
}
|
|
331
|
+
|
|
332
|
+
if (!validateEntryNumber(daqListNumber)) {
|
|
333
|
+
return;
|
|
334
|
+
}
|
|
335
|
+
auto entry = m_daq_lists[daqListNumber];
|
|
336
|
+
// DBG_PRINTN("CLEAR_DAQ_LIST -- daq:", daqListNumber, std::endl);
|
|
337
|
+
entry.clear();
|
|
338
|
+
}
|
|
339
|
+
|
|
340
|
+
void writeDaq(std::uint16_t bitOffset, std::uint16_t entrySize, std::uint16_t addressExt, std::uint32_t address) {
|
|
341
|
+
if (!m_activate) {
|
|
342
|
+
return;
|
|
343
|
+
}
|
|
344
|
+
|
|
345
|
+
auto [d, o, e] = m_daq_ptr;
|
|
346
|
+
auto& entry = m_daq_lists[d].m_odts[o].m_entries[e];
|
|
347
|
+
|
|
348
|
+
// DBG_PRINTN("WRITE_DAQ -- bit-offset:", bitOffset, " size:", entrySize, " addr-ext:", addressExt," addr:", address,
|
|
349
|
+
// std::endl);
|
|
350
|
+
|
|
351
|
+
entry.bitOffset = bitOffset;
|
|
352
|
+
entry.address = address;
|
|
353
|
+
entry.address_extension = addressExt;
|
|
354
|
+
entry.entry_size = entrySize;
|
|
355
|
+
#if 0
|
|
356
|
+
std::cout << "\tBO: " << entry.bitOffset << std::endl;
|
|
357
|
+
std::cout << "\tES: " << entry.entry_size << std::endl;
|
|
358
|
+
std::cout << "\tAD: " << entry.address << std::endl;
|
|
359
|
+
std::cout << "\tAE: " << entry.address_extension << std::endl;
|
|
360
|
+
#endif
|
|
361
|
+
}
|
|
362
|
+
|
|
363
|
+
void setDaqListMode(
|
|
364
|
+
std::uint16_t mode, std::uint16_t daqListNumber, std::uint16_t eventChannelNumber, std::uint16_t prescaler,
|
|
365
|
+
std::uint16_t priority
|
|
366
|
+
) {
|
|
367
|
+
if (!m_activate) {
|
|
368
|
+
return;
|
|
369
|
+
}
|
|
370
|
+
if (!validateEntryNumber(daqListNumber)) {
|
|
371
|
+
throw std::runtime_error("Invalid DAQ list number: " + std::to_string(eventChannelNumber) + "\n");
|
|
372
|
+
}
|
|
373
|
+
// std::cout << "SET_DAQ_LIST_MODE: " << mode << ":" << daqListNumber << ":" << eventChannelNumber << ":" << prescaler <<
|
|
374
|
+
// ":"
|
|
375
|
+
// << priority << std::endl;
|
|
376
|
+
|
|
377
|
+
auto& entry = m_daq_lists.at(daqListNumber);
|
|
378
|
+
|
|
379
|
+
entry.mode = mode;
|
|
380
|
+
entry.prescaler = prescaler;
|
|
381
|
+
// The use of a prescaler is only used for DAQ lists with DIRECTION = DAQ.
|
|
382
|
+
|
|
383
|
+
entry.priority = priority;
|
|
384
|
+
entry.event_channel_number = eventChannelNumber;
|
|
385
|
+
|
|
386
|
+
if (!m_daq_event_info.contains(eventChannelNumber)) {
|
|
387
|
+
throw std::runtime_error("Invalid Event channel number: " + std::to_string(eventChannelNumber) + "\n");
|
|
388
|
+
}
|
|
389
|
+
auto& event = m_daq_event_info.at(eventChannelNumber);
|
|
390
|
+
|
|
391
|
+
event.m_daq_lists.emplace(daqListNumber);
|
|
392
|
+
|
|
393
|
+
if ((mode & DIRECTION_STIM) == DIRECTION_STIM) {
|
|
394
|
+
// std::cout << "\tSTIM-MODE!!!\n";
|
|
395
|
+
|
|
396
|
+
m_stim_lists.emplace(daqListNumber);
|
|
397
|
+
|
|
398
|
+
// std::cout << "\t\tEvent: " << event.m_name << " ==> " << event.m_cycle_time << " - " << event.m_periodic <<
|
|
399
|
+
// std::endl;
|
|
400
|
+
calculate_scheduler_period(event.m_cycle_time);
|
|
401
|
+
}
|
|
402
|
+
}
|
|
403
|
+
|
|
404
|
+
void startStopDaqList(std::uint16_t mode, std::uint16_t daqListNumber) {
|
|
405
|
+
if (!m_activate) {
|
|
406
|
+
return;
|
|
407
|
+
}
|
|
408
|
+
if (!validateEntryNumber(daqListNumber)) {
|
|
409
|
+
return;
|
|
410
|
+
}
|
|
411
|
+
auto& entry = m_daq_lists.at(daqListNumber);
|
|
412
|
+
/*
|
|
413
|
+
* 00 = stop
|
|
414
|
+
* 01 = start
|
|
415
|
+
* 02 = select
|
|
416
|
+
*/
|
|
417
|
+
if (mode == 0) {
|
|
418
|
+
entry.mode &= ~(SELECTED | RUNNING);
|
|
419
|
+
} else if (mode == 1) {
|
|
420
|
+
entry.mode |= (RUNNING);
|
|
421
|
+
} else if (mode == 2) {
|
|
422
|
+
entry.mode |= (SELECTED);
|
|
423
|
+
}
|
|
424
|
+
|
|
425
|
+
// std::cout << "START_STOP_DAQ_LIST " << mode << ":" << daqListNumber << std::endl;
|
|
426
|
+
}
|
|
427
|
+
|
|
428
|
+
void startStopSynch(std::uint16_t mode) {
|
|
429
|
+
if (!m_activate) {
|
|
430
|
+
return;
|
|
431
|
+
}
|
|
432
|
+
// std::cout << "START_STOP_SYNCH " << mode << ":" << std::endl;
|
|
433
|
+
|
|
434
|
+
// send(0x00, { 0x04, 0x20, 0x30, 0x40, 0x50, 0x60, 0x70, 0x80, 0x90, 0xa0, 0xb0 });
|
|
435
|
+
|
|
436
|
+
for (auto dl : m_stim_lists) {
|
|
437
|
+
// std::cout << "\tRunning list: " << dl << std::endl;
|
|
438
|
+
}
|
|
439
|
+
auto idx = 0;
|
|
440
|
+
for (auto dl : m_daq_lists) {
|
|
441
|
+
// std::cout << "DAQ-L: " << idx << " " << dl.mode << " - " << dl.event_channel_number << ":" << dl.prescaler <<
|
|
442
|
+
// std::endl;
|
|
443
|
+
idx++;
|
|
444
|
+
}
|
|
445
|
+
}
|
|
446
|
+
|
|
447
|
+
void writeDaqMultiple(/* const std::vector<DaqElement>&*/ std::uint16_t daqElements) {
|
|
448
|
+
if (!m_activate) {
|
|
449
|
+
return;
|
|
450
|
+
}
|
|
451
|
+
}
|
|
452
|
+
|
|
453
|
+
void dtoCtrProperties(
|
|
454
|
+
std::uint16_t modifier, std::uint16_t eventChannel, std::uint16_t relatedEventChannel, std::uint16_t mode
|
|
455
|
+
) {
|
|
456
|
+
if (!m_activate) {
|
|
457
|
+
return;
|
|
458
|
+
}
|
|
459
|
+
}
|
|
460
|
+
|
|
461
|
+
void setDaqPackedMode(
|
|
462
|
+
std::uint16_t, std::uint16_t daqListNumber, std::uint16_t daqPackedMode, std::uint16_t dpmTimestampMode = 0,
|
|
463
|
+
std::uint16_t dpmSampleCount = 0
|
|
464
|
+
) {
|
|
465
|
+
if (!m_activate) {
|
|
466
|
+
return;
|
|
467
|
+
}
|
|
468
|
+
if (!validateEntryNumber(daqListNumber)) {
|
|
469
|
+
return;
|
|
470
|
+
}
|
|
471
|
+
// PACKED_MODE
|
|
472
|
+
}
|
|
473
|
+
|
|
474
|
+
void clear() {
|
|
475
|
+
if (!m_activate) {
|
|
476
|
+
return;
|
|
477
|
+
}
|
|
478
|
+
m_daq_lists.clear();
|
|
479
|
+
m_stim_lists.clear();
|
|
480
|
+
m_first_pids.clear();
|
|
481
|
+
}
|
|
482
|
+
|
|
483
|
+
void freeDaq() {
|
|
484
|
+
if (!m_activate) {
|
|
485
|
+
return;
|
|
486
|
+
}
|
|
487
|
+
clear();
|
|
488
|
+
}
|
|
489
|
+
|
|
490
|
+
void allocDaq(std::uint16_t daqCount) {
|
|
491
|
+
if (!m_activate) {
|
|
492
|
+
return;
|
|
493
|
+
}
|
|
494
|
+
m_daq_lists.resize(daqCount);
|
|
495
|
+
std::for_each(m_daq_lists.cbegin(), m_daq_lists.cend(), [](auto elem) { elem.clear(); });
|
|
496
|
+
}
|
|
497
|
+
|
|
498
|
+
void allocOdt(std::uint16_t daqListNumber, std::uint16_t odtCount) {
|
|
499
|
+
if (!m_activate) {
|
|
500
|
+
return;
|
|
501
|
+
}
|
|
502
|
+
if (!validateEntryNumber(daqListNumber)) {
|
|
503
|
+
return;
|
|
504
|
+
}
|
|
505
|
+
m_daq_lists[daqListNumber].resize(odtCount);
|
|
506
|
+
}
|
|
507
|
+
|
|
508
|
+
void allocOdtEntry(std::uint16_t daqListNumber, std::uint16_t odtNumber, std::uint16_t odtEntriesCount) {
|
|
509
|
+
if (!m_activate) {
|
|
510
|
+
return;
|
|
511
|
+
}
|
|
512
|
+
if (!validateEntryNumber(daqListNumber, odtNumber)) {
|
|
513
|
+
return;
|
|
514
|
+
}
|
|
515
|
+
m_daq_lists[daqListNumber].m_odts[odtNumber].resize(odtEntriesCount);
|
|
516
|
+
}
|
|
517
|
+
|
|
518
|
+
void set_first_pid(std::uint16_t daqListNumber, std::uint16_t firstPid) {
|
|
519
|
+
if (!m_activate) {
|
|
520
|
+
return;
|
|
521
|
+
}
|
|
522
|
+
m_first_pids[daqListNumber] = firstPid;
|
|
523
|
+
}
|
|
524
|
+
|
|
525
|
+
void set_policy_feeder(const feed_function_t& fun) {
|
|
526
|
+
m_feed_function = fun;
|
|
527
|
+
}
|
|
528
|
+
|
|
529
|
+
void set_frame_sender(const send_function_t& fun) {
|
|
530
|
+
m_send_function = fun;
|
|
531
|
+
}
|
|
532
|
+
|
|
533
|
+
void send(std::uint8_t stim_list_num, const std::vector<std::uint8_t> frame) {
|
|
534
|
+
if (!m_activate) {
|
|
535
|
+
return;
|
|
536
|
+
}
|
|
537
|
+
if (m_send_function) {
|
|
538
|
+
m_send_function.value()(FakeEnum(stim_list_num), frame);
|
|
539
|
+
}
|
|
540
|
+
}
|
|
541
|
+
|
|
542
|
+
protected:
|
|
543
|
+
|
|
544
|
+
void calculate_scheduler_period(std::size_t value) {
|
|
545
|
+
if (!m_activate) {
|
|
546
|
+
return;
|
|
547
|
+
}
|
|
548
|
+
if (!m_scheduler_period) {
|
|
549
|
+
m_scheduler_period = value;
|
|
550
|
+
}
|
|
551
|
+
if (!m_scheduler_max_value) {
|
|
552
|
+
m_scheduler_max_value = value;
|
|
553
|
+
}
|
|
554
|
+
|
|
555
|
+
// std::cout << "\tSCHED_Value: " << value << " - BEFORE: " << *m_scheduler_period << ":" << *m_scheduler_max_value <<
|
|
556
|
+
// std::endl;
|
|
557
|
+
m_scheduler_period = std::gcd(*m_scheduler_period, value);
|
|
558
|
+
m_scheduler_max_value = std::lcm(*m_scheduler_max_value, value);
|
|
559
|
+
// std::cout << "\tSCHED_Period: " << *m_scheduler_period << " max: " << *m_scheduler_max_value << std::endl;
|
|
560
|
+
}
|
|
561
|
+
|
|
562
|
+
bool validateEntryNumber(
|
|
563
|
+
std::uint16_t daqListNumber, std::optional<std::uint16_t> odtNumber = std::nullopt,
|
|
564
|
+
std::optional<std::uint16_t> odtEntryNumber = std::nullopt
|
|
565
|
+
) const {
|
|
566
|
+
if (!m_activate) {
|
|
567
|
+
return false;
|
|
568
|
+
}
|
|
569
|
+
if (daqListNumber >= std::size(m_daq_lists)) {
|
|
570
|
+
return false;
|
|
571
|
+
}
|
|
572
|
+
if (odtNumber) {
|
|
573
|
+
auto entry = m_daq_lists[daqListNumber];
|
|
574
|
+
if (*odtNumber >= std::size(entry.m_odts)) {
|
|
575
|
+
return false;
|
|
576
|
+
}
|
|
577
|
+
}
|
|
578
|
+
if (odtEntryNumber) {
|
|
579
|
+
auto entry = m_daq_lists[daqListNumber].m_odts[*odtNumber];
|
|
580
|
+
if (*odtEntryNumber >= std::size(entry.m_entries)) {
|
|
581
|
+
return false;
|
|
582
|
+
}
|
|
583
|
+
}
|
|
584
|
+
return true;
|
|
585
|
+
}
|
|
586
|
+
|
|
587
|
+
private:
|
|
588
|
+
|
|
589
|
+
bool m_activate;
|
|
590
|
+
StimParameters m_params{};
|
|
591
|
+
std::vector<DynamicListType> m_daq_lists{};
|
|
592
|
+
std::tuple<std::uint16_t, std::uint16_t, std::uint16_t> m_daq_ptr;
|
|
593
|
+
std::optional<std::size_t> m_scheduler_period{ std::nullopt };
|
|
594
|
+
std::optional<std::size_t> m_scheduler_max_value{ std::nullopt };
|
|
595
|
+
std::map<std::uint16_t, DaqEventInfo> m_daq_event_info;
|
|
596
|
+
std::map<std::uint16_t, std::uint16_t> m_first_pids{};
|
|
597
|
+
std::set<std::size_t> m_stim_lists{};
|
|
598
|
+
std::optional<feed_function_t> m_feed_function{ std::nullopt };
|
|
599
|
+
std::optional<send_function_t> m_send_function{ std::nullopt };
|
|
600
|
+
// Scheduler m_scheduler{};
|
|
601
|
+
// bool m_daq_running{ false };
|
|
602
|
+
};
|
|
603
|
+
|
|
604
|
+
#endif // __STIM_HPP
|
|
@@ -0,0 +1,50 @@
|
|
|
1
|
+
#include <pybind11/functional.h>
|
|
2
|
+
#include <pybind11/pybind11.h>
|
|
3
|
+
#include <pybind11/stl.h>
|
|
4
|
+
|
|
5
|
+
#include <mutex>
|
|
6
|
+
|
|
7
|
+
namespace py = pybind11;
|
|
8
|
+
using namespace py::literals;
|
|
9
|
+
|
|
10
|
+
#if defined(_MSC_VER)
|
|
11
|
+
#pragma warning(disable: 4251 4273)
|
|
12
|
+
#endif
|
|
13
|
+
|
|
14
|
+
#include "stim.hpp"
|
|
15
|
+
|
|
16
|
+
PYBIND11_MODULE(stim, m) {
|
|
17
|
+
py::class_<DaqEventInfo>(m, "DaqEventInfo")
|
|
18
|
+
.def(py::init<const std::string&, std::int8_t, std::size_t, std::size_t, std::size_t, std::string_view, bool, bool, bool>(),
|
|
19
|
+
"name"_a, "type_code"_a, "cycle"_a, "max_daq_lists"_a, "priority"_a, "consistency"_a, "daq_supported"_a,
|
|
20
|
+
"stim_supported"_a, "packed_supported"_a
|
|
21
|
+
);
|
|
22
|
+
|
|
23
|
+
py::class_<Stim>(m, "Stim")
|
|
24
|
+
.def(py::init<bool>())
|
|
25
|
+
.def("setDaqEventInfo", &Stim::setDaqEventInfo)
|
|
26
|
+
.def("clear", &Stim::clear)
|
|
27
|
+
.def("freeDaq", &Stim::freeDaq)
|
|
28
|
+
.def("allocDaq", &Stim::allocDaq)
|
|
29
|
+
.def("allocOdt", &Stim::allocOdt)
|
|
30
|
+
.def("allocOdtEntry", &Stim::allocOdtEntry)
|
|
31
|
+
.def("setDaqPtr", &Stim::setDaqPtr)
|
|
32
|
+
.def("clearDaqList", &Stim::clearDaqList)
|
|
33
|
+
.def("writeDaq", &Stim::writeDaq)
|
|
34
|
+
.def("setDaqListMode", &Stim::setDaqListMode)
|
|
35
|
+
.def("startStopDaqList", &Stim::startStopDaqList)
|
|
36
|
+
.def("startStopSynch", &Stim::startStopSynch)
|
|
37
|
+
|
|
38
|
+
.def("set_first_pid", &Stim::set_first_pid)
|
|
39
|
+
.def("set_policy_feeder", [](Stim& self, const py::function& callback) { self.set_policy_feeder(callback); })
|
|
40
|
+
.def("set_frame_sender", [](Stim& self, const py::function& callback) { self.set_frame_sender(callback); });
|
|
41
|
+
|
|
42
|
+
py::class_<FakeEnum>(m, "FakeEnum")
|
|
43
|
+
.def(py::init<std::uint8_t>())
|
|
44
|
+
.def_property_readonly("name", &FakeEnum::get_name)
|
|
45
|
+
.def_property_readonly("value", &FakeEnum::get_value)
|
|
46
|
+
.def("bit_length", &FakeEnum::bit_length)
|
|
47
|
+
.def("to_bytes", &FakeEnum::to_bytes)
|
|
48
|
+
.def("__int__", [](const FakeEnum& self) { return self.get_value(); });
|
|
49
|
+
;
|
|
50
|
+
}
|