pyxcp 0.23.3__cp312-cp312-win_arm64.whl → 0.25.6__cp312-cp312-win_arm64.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.
Files changed (87) hide show
  1. pyxcp/__init__.py +1 -1
  2. pyxcp/asamkeydll.exe +0 -0
  3. pyxcp/cmdline.py +15 -30
  4. pyxcp/config/__init__.py +73 -20
  5. pyxcp/cpp_ext/aligned_buffer.hpp +168 -0
  6. pyxcp/cpp_ext/bin.hpp +7 -6
  7. pyxcp/cpp_ext/cpp_ext.cp310-win_arm64.pyd +0 -0
  8. pyxcp/cpp_ext/cpp_ext.cp311-win_arm64.pyd +0 -0
  9. pyxcp/cpp_ext/cpp_ext.cp312-win_arm64.pyd +0 -0
  10. pyxcp/cpp_ext/daqlist.hpp +241 -73
  11. pyxcp/cpp_ext/extension_wrapper.cpp +123 -15
  12. pyxcp/cpp_ext/framing.hpp +360 -0
  13. pyxcp/cpp_ext/mcobject.hpp +5 -3
  14. pyxcp/cpp_ext/sxi_framing.hpp +332 -0
  15. pyxcp/daq_stim/__init__.py +182 -45
  16. pyxcp/daq_stim/optimize/binpacking.py +2 -2
  17. pyxcp/daq_stim/scheduler.cpp +8 -8
  18. pyxcp/daq_stim/stim.cp310-win_arm64.pyd +0 -0
  19. pyxcp/daq_stim/stim.cp311-win_arm64.pyd +0 -0
  20. pyxcp/daq_stim/stim.cp312-win_arm64.pyd +0 -0
  21. pyxcp/errormatrix.py +2 -2
  22. pyxcp/examples/run_daq.py +5 -3
  23. pyxcp/examples/xcp_policy.py +6 -6
  24. pyxcp/examples/xcp_read_benchmark.py +2 -2
  25. pyxcp/examples/xcp_skel.py +1 -2
  26. pyxcp/examples/xcp_unlock.py +10 -12
  27. pyxcp/examples/xcp_user_supplied_driver.py +1 -2
  28. pyxcp/examples/xcphello.py +2 -15
  29. pyxcp/examples/xcphello_recorder.py +2 -2
  30. pyxcp/master/__init__.py +1 -0
  31. pyxcp/master/errorhandler.py +248 -13
  32. pyxcp/master/master.py +838 -250
  33. pyxcp/recorder/.idea/.gitignore +8 -0
  34. pyxcp/recorder/.idea/misc.xml +4 -0
  35. pyxcp/recorder/.idea/modules.xml +8 -0
  36. pyxcp/recorder/.idea/recorder.iml +6 -0
  37. pyxcp/recorder/.idea/sonarlint/issuestore/3/8/3808afc69ac1edb9d760000a2f137335b1b99728 +7 -0
  38. pyxcp/recorder/.idea/sonarlint/issuestore/9/a/9a2aa4db38d3115ed60da621e012c0efc0172aae +0 -0
  39. pyxcp/recorder/.idea/sonarlint/issuestore/b/4/b49006702b459496a8e8c94ebe60947108361b91 +0 -0
  40. pyxcp/recorder/.idea/sonarlint/issuestore/index.pb +7 -0
  41. pyxcp/recorder/.idea/sonarlint/securityhotspotstore/3/8/3808afc69ac1edb9d760000a2f137335b1b99728 +0 -0
  42. pyxcp/recorder/.idea/sonarlint/securityhotspotstore/9/a/9a2aa4db38d3115ed60da621e012c0efc0172aae +0 -0
  43. pyxcp/recorder/.idea/sonarlint/securityhotspotstore/b/4/b49006702b459496a8e8c94ebe60947108361b91 +0 -0
  44. pyxcp/recorder/.idea/sonarlint/securityhotspotstore/index.pb +7 -0
  45. pyxcp/recorder/.idea/vcs.xml +10 -0
  46. pyxcp/recorder/__init__.py +5 -10
  47. pyxcp/recorder/converter/__init__.py +4 -10
  48. pyxcp/recorder/reader.hpp +0 -1
  49. pyxcp/recorder/reco.py +1 -0
  50. pyxcp/recorder/rekorder.cp310-win_arm64.pyd +0 -0
  51. pyxcp/recorder/rekorder.cp311-win_arm64.pyd +0 -0
  52. pyxcp/recorder/rekorder.cp312-win_arm64.pyd +0 -0
  53. pyxcp/recorder/unfolder.hpp +129 -107
  54. pyxcp/recorder/wrap.cpp +3 -8
  55. pyxcp/scripts/xcp_fetch_a2l.py +2 -2
  56. pyxcp/scripts/xcp_id_scanner.py +1 -2
  57. pyxcp/scripts/xcp_info.py +66 -51
  58. pyxcp/scripts/xcp_profile.py +1 -2
  59. pyxcp/tests/test_daq.py +1 -1
  60. pyxcp/tests/test_framing.py +262 -0
  61. pyxcp/tests/test_master.py +210 -100
  62. pyxcp/tests/test_transport.py +138 -42
  63. pyxcp/timing.py +1 -1
  64. pyxcp/transport/__init__.py +8 -5
  65. pyxcp/transport/base.py +187 -143
  66. pyxcp/transport/can.py +117 -13
  67. pyxcp/transport/eth.py +55 -20
  68. pyxcp/transport/hdf5_policy.py +167 -0
  69. pyxcp/transport/sxi.py +126 -52
  70. pyxcp/transport/transport_ext.cp310-win_arm64.pyd +0 -0
  71. pyxcp/transport/transport_ext.cp311-win_arm64.pyd +0 -0
  72. pyxcp/transport/transport_ext.cp312-win_arm64.pyd +0 -0
  73. pyxcp/transport/transport_ext.hpp +214 -0
  74. pyxcp/transport/transport_wrapper.cpp +249 -0
  75. pyxcp/transport/usb_transport.py +47 -31
  76. pyxcp/types.py +0 -13
  77. pyxcp/{utils.py → utils/__init__.py} +3 -4
  78. pyxcp/utils/cli.py +78 -0
  79. pyxcp-0.25.6.dist-info/METADATA +341 -0
  80. pyxcp-0.25.6.dist-info/RECORD +153 -0
  81. {pyxcp-0.23.3.dist-info → pyxcp-0.25.6.dist-info}/WHEEL +1 -1
  82. pyxcp/examples/conf_sxi.json +0 -9
  83. pyxcp/examples/conf_sxi.toml +0 -7
  84. pyxcp-0.23.3.dist-info/METADATA +0 -219
  85. pyxcp-0.23.3.dist-info/RECORD +0 -131
  86. {pyxcp-0.23.3.dist-info → pyxcp-0.25.6.dist-info}/entry_points.txt +0 -0
  87. {pyxcp-0.23.3.dist-info → pyxcp-0.25.6.dist-info/licenses}/LICENSE +0 -0
@@ -1,12 +1,14 @@
1
1
  #!/usr/bin/env python
2
2
 
3
- # from pprint import pprint
3
+ from contextlib import suppress
4
+ import json
4
5
  from time import time_ns
5
- from typing import Dict, List, Optional, TextIO
6
+ from typing import Any, Dict, List, Optional, TextIO, Tuple, Union
7
+
8
+ from pyxcp.cpp_ext.cpp_ext import DaqList, PredefinedDaqList
6
9
 
7
10
  from pyxcp import types
8
11
  from pyxcp.config import get_application
9
- from pyxcp.cpp_ext.cpp_ext import DaqList
10
12
  from pyxcp.daq_stim.optimize import make_continuous_blocks
11
13
  from pyxcp.daq_stim.optimize.binpacking import first_fit_decreasing
12
14
  from pyxcp.recorder import DaqOnlinePolicy as _DaqOnlinePolicy
@@ -14,7 +16,6 @@ from pyxcp.recorder import DaqRecorderPolicy as _DaqRecorderPolicy
14
16
  from pyxcp.recorder import MeasurementParameters
15
17
  from pyxcp.utils import CurrentDatetime
16
18
 
17
-
18
19
  DAQ_ID_FIELD_SIZE = {
19
20
  "IDF_ABS_ODT_NUMBER": 1,
20
21
  "IDF_REL_ODT_NUMBER_ABS_DAQ_LIST_NUMBER_BYTE": 2,
@@ -29,11 +30,90 @@ DAQ_TIMESTAMP_SIZE = {
29
30
  }
30
31
 
31
32
 
33
+ def load_daq_lists_from_json(file_path: str) -> List[DaqList]:
34
+ """Load and validate DAQ-list from JSON file."""
35
+ with open(file_path, "r", encoding="utf-8") as f:
36
+ config = json.load(f)
37
+
38
+ if not isinstance(config, list):
39
+ raise ValueError("DAQ configuration must be a JSON array (list)")
40
+
41
+ daq_lists: List[DaqList] = []
42
+ for idx, entry in enumerate(config):
43
+ if not isinstance(entry, dict):
44
+ raise TypeError(f"Entry {idx} must be an object/dict")
45
+
46
+ required = {"name", "event_num", "stim", "enable_timestamps", "measurements", "priority", "prescaler"}
47
+ missing = required - set(entry.keys())
48
+ if missing:
49
+ raise ValueError(f"Entry {idx} missing required keys: {missing}")
50
+
51
+ # Basic type conversions / checks
52
+ name = entry["name"]
53
+ if not isinstance(name, str):
54
+ raise TypeError(f"Entry {idx} 'name' must be a string")
55
+
56
+ try:
57
+ event_num = int(entry["event_num"])
58
+ except Exception as e:
59
+ raise TypeError(f"Entry {idx} 'event_num' must be an integer") from e
60
+
61
+ stim = bool(entry["stim"])
62
+ enable_timestamps = bool(entry["enable_timestamps"])
63
+
64
+ try:
65
+ priority = int(entry["priority"])
66
+ prescaler = int(entry["prescaler"])
67
+ except Exception as e:
68
+ raise TypeError(f"Entry {idx} 'priority' and 'prescaler' must be integers") from e
69
+
70
+ measurements_raw = entry["measurements"]
71
+ if not isinstance(measurements_raw, list):
72
+ raise TypeError(f"Entry {idx} 'measurements' must be a list")
73
+
74
+ measurements: List[Tuple[str, int, int, str]] = []
75
+ for m_idx, m in enumerate(measurements_raw):
76
+ if not (isinstance(m, (list, tuple)) and len(m) == 4):
77
+ raise ValueError(f"Entry {idx} measurement {m_idx} must be a 4-element list/tuple")
78
+ m_name, m_addr, m_offset, m_type = m
79
+
80
+ if not isinstance(m_name, str):
81
+ raise TypeError(f"Entry {idx} measurement {m_idx} name must be a string")
82
+ try:
83
+ m_addr = int(m_addr)
84
+ except Exception as e:
85
+ raise TypeError(f"Entry {idx} measurement {m_idx} address must be an integer") from e
86
+ try:
87
+ m_offset = int(m_offset)
88
+ except Exception as e:
89
+ raise TypeError(f"Entry {idx} measurement {m_idx} offset must be an integer") from e
90
+ if not isinstance(m_type, str):
91
+ raise TypeError(f"Entry {idx} measurement {m_idx} type must be a string")
92
+
93
+ measurements.append((m_name, m_addr, m_offset, m_type))
94
+
95
+ daq_kwargs: Dict[str, Any] = {
96
+ "name": name,
97
+ "event_num": event_num,
98
+ "stim": stim,
99
+ "enable_timestamps": enable_timestamps,
100
+ "measurements": measurements,
101
+ "priority": priority,
102
+ "prescaler": prescaler,
103
+ }
104
+
105
+ daq_lists.append(DaqList(**daq_kwargs))
106
+
107
+ return daq_lists
108
+
109
+
32
110
  class DaqProcessor:
33
- def __init__(self, daq_lists: List[DaqList]):
34
- # super().__init__()
111
+ def __init__(self, daq_lists: List[Union[DaqList, PredefinedDaqList]]):
35
112
  self.daq_lists = daq_lists
113
+ self.is_predefined = [isinstance(d, PredefinedDaqList) for d in daq_lists]
36
114
  self.log = get_application().log
115
+ # Flag indicating a fatal OS-level error occurred during DAQ (e.g., disk full, out-of-memory)
116
+ self._fatal_os_error: bool = False
37
117
 
38
118
  def setup(self, start_datetime: Optional[CurrentDatetime] = None, write_multiple: bool = True):
39
119
  if not self.xcp_master.slaveProperties.supportsDaq:
@@ -42,13 +122,14 @@ class DaqProcessor:
42
122
  if start_datetime is None:
43
123
  start_datetime = CurrentDatetime(time_ns())
44
124
  self.start_datetime = start_datetime
45
- # print(self.start_datetime)
46
125
  try:
47
126
  processor = self.daq_info.get("processor")
48
127
  properties = processor.get("properties")
49
128
  resolution = self.daq_info.get("resolution")
50
- if properties["configType"] == "STATIC":
51
- raise TypeError("DAQ configuration is static, cannot proceed.")
129
+ if properties["configType"] == "STATIC" and not all(self.is_predefined):
130
+ raise TypeError(
131
+ "DAQ configuration is static, but in your configuration are only dynamic DAQ lists -- cannot proceed."
132
+ )
52
133
  self.supports_timestampes = properties["timestampSupported"]
53
134
  self.supports_prescaler = properties["prescalerSupported"]
54
135
  self.supports_pid_off = properties["pidOffSupported"]
@@ -71,22 +152,24 @@ class DaqProcessor:
71
152
  max_payload_size = min(max_odt_entry_size, max_dto - header_len)
72
153
  # First ODT may contain timestamp.
73
154
  self.selectable_timestamps = False
155
+ max_payload_size_first = max_payload_size
74
156
  if not self.supports_timestampes:
75
- max_payload_size_first = max_payload_size
76
- # print("NO TIMESTAMP SUPPORT")
157
+ self.log.info("No timestamp support")
77
158
  else:
78
159
  if self.ts_fixed:
79
- # print("Fixed timestamp")
160
+ self.log.debug("Fixed timestamps")
80
161
  max_payload_size_first = max_payload_size - self.ts_size
81
162
  else:
82
- # print("timestamp variable.")
163
+ self.log.debug("Variable timestamps.")
83
164
  self.selectable_timestamps = True
84
-
85
165
  except Exception as e:
86
166
  raise TypeError(f"DAQ_INFO corrupted: {e}") from e
87
167
 
88
168
  # DAQ optimization.
89
- for daq_list in self.daq_lists:
169
+ # For dynamic DaqList instances, compute physical layout; skip for PredefinedDaqList.
170
+ for idx, daq_list in enumerate(self.daq_lists):
171
+ if isinstance(daq_list, PredefinedDaqList):
172
+ continue
90
173
  if self.selectable_timestamps:
91
174
  if daq_list.enable_timestamps:
92
175
  max_payload_size_first = max_payload_size - self.ts_size
@@ -97,34 +180,47 @@ class DaqProcessor:
97
180
  byte_order = 0 if self.xcp_master.slaveProperties.byteOrder == "INTEL" else 1
98
181
  self._first_pids = []
99
182
  daq_count = len(self.daq_lists)
100
- self.xcp_master.freeDaq()
101
-
102
- # Allocate
103
- self.xcp_master.allocDaq(daq_count)
104
- measurement_list = []
105
- for i, daq_list in enumerate(self.daq_lists, self.min_daq):
106
- measurements = daq_list.measurements_opt
107
- measurement_list.append((i, measurements))
108
- odt_count = len(measurements)
109
- self.xcp_master.allocOdt(i, odt_count)
110
- # Iterate again over ODT entries -- we need to respect sequencing requirements.
111
- for i, measurements in measurement_list:
112
- for j, measurement in enumerate(measurements):
113
- entry_count = len(measurement.entries)
114
- self.xcp_master.allocOdtEntry(i, j, entry_count)
115
- # Write DAQs
116
- for i, daq_list in enumerate(self.daq_lists, self.min_daq):
117
- measurements = daq_list.measurements_opt
118
- for j, measurement in enumerate(measurements):
119
- if len(measurement.entries) == 0:
120
- continue # CAN special case: No room for data in first ODT.
121
- self.xcp_master.setDaqPtr(i, j, 0)
122
- for entry in measurement.entries:
123
- self.xcp_master.writeDaq(0xFF, entry.length, entry.ext, entry.address)
183
+
184
+ # Decide whether DAQ allocation must be performed.
185
+ config_static = self.daq_info.get("processor", {}).get("properties", {}).get("configType") == "STATIC"
186
+
187
+ if not config_static:
188
+ # For dynamic configuration, program only dynamic (non-predefined) DAQ lists.
189
+ self.xcp_master.freeDaq()
190
+ # Allocate the number of DAQ lists required.
191
+ self.xcp_master.allocDaq(daq_count)
192
+ measurement_list = []
193
+ for i, daq_list in enumerate(self.daq_lists, self.min_daq):
194
+ if isinstance(daq_list, PredefinedDaqList):
195
+ # Skip allocation for predefined DAQ lists.
196
+ continue
197
+ measurements = daq_list.measurements_opt
198
+ measurement_list.append((i, measurements))
199
+ odt_count = len(measurements)
200
+ self.xcp_master.allocOdt(i, odt_count)
201
+ # Iterate again over ODT entries -- we need to respect sequencing requirements.
202
+ for i, measurements in measurement_list:
203
+ for j, measurement in enumerate(measurements):
204
+ entry_count = len(measurement.entries)
205
+ self.xcp_master.allocOdtEntry(i, j, entry_count)
206
+ # Write DAQs (only for dynamic lists)
207
+ for i, daq_list in enumerate(self.daq_lists, self.min_daq):
208
+ if isinstance(daq_list, PredefinedDaqList):
209
+ continue
210
+ measurements = daq_list.measurements_opt
211
+ for j, measurement in enumerate(measurements):
212
+ if len(measurement.entries) == 0:
213
+ continue # CAN special case: No room for data in first ODT.
214
+ self.xcp_master.setDaqPtr(i, j, 0)
215
+ for entry in measurement.entries:
216
+ self.xcp_master.writeDaq(0xFF, entry.length, entry.ext, entry.address)
217
+ else:
218
+ # STATIC configuration on the slave: skip allocation and programming; lists/ODTs are predefined.
219
+ pass
124
220
 
125
221
  # arm DAQ lists -- this is technically a function on its own.
126
- for i, daq_list in enumerate(self.daq_lists, self.min_daq):
127
- # print(daq_list.name, daq_list.event_num, daq_list.stim)
222
+ first_daq_list = 0 if config_static else self.min_daq
223
+ for i, daq_list in enumerate(self.daq_lists, first_daq_list):
128
224
  mode = 0x00
129
225
  if self.supports_timestampes and (self.ts_fixed or (self.selectable_timestamps and daq_list.enable_timestamps)):
130
226
  mode = 0x10
@@ -142,8 +238,6 @@ class DaqProcessor:
142
238
  )
143
239
  res = self.xcp_master.startStopDaqList(0x02, i)
144
240
  self._first_pids.append(res.firstPid)
145
- if start_datetime:
146
- pass
147
241
  self.measurement_params = MeasurementParameters(
148
242
  byte_order,
149
243
  header_len,
@@ -164,6 +258,26 @@ class DaqProcessor:
164
258
  self.xcp_master.startStopSynch(0x01)
165
259
 
166
260
  def stop(self):
261
+ # If a fatal OS error occurred during acquisition, skip sending stop to the slave to avoid
262
+ # cascading timeouts/unrecoverable errors and shut down transport gracefully instead.
263
+ if getattr(self, "_fatal_os_error", False):
264
+ with suppress(Exception):
265
+ self.log.error(
266
+ "DAQ stop skipped due to previous fatal OS error (e.g., disk full or out-of-memory). Closing transport."
267
+ )
268
+ try:
269
+ # Best-effort: stop listener and close transport so threads finish cleanly.
270
+ if hasattr(self.xcp_master, "transport") and self.xcp_master.transport is not None:
271
+ # Signal listeners to stop
272
+ with suppress(Exception):
273
+ if hasattr(self.xcp_master.transport, "closeEvent"):
274
+ self.xcp_master.transport.closeEvent.set()
275
+
276
+ # Close transport connection
277
+ with suppress(Exception):
278
+ self.xcp_master.transport.close()
279
+ finally:
280
+ return
167
281
  self.xcp_master.startStopSynch(0x00)
168
282
 
169
283
  def first_pids(self):
@@ -171,7 +285,6 @@ class DaqProcessor:
171
285
 
172
286
 
173
287
  class DaqRecorder(DaqProcessor, _DaqRecorderPolicy):
174
-
175
288
  def __init__(self, daq_lists: List[DaqList], file_name: str, prealloc: int = 200, chunk_size: int = 1):
176
289
  DaqProcessor.__init__(self, daq_lists)
177
290
  _DaqRecorderPolicy.__init__(self)
@@ -219,7 +332,31 @@ class DaqToCsv(DaqOnlinePolicy):
219
332
  out_file.write(f"{hdr}\n")
220
333
 
221
334
  def on_daq_list(self, daq_list: int, timestamp0: int, timestamp1: int, payload: list):
222
- self.files[daq_list].write(f"{timestamp0},{timestamp1},{', '.join([str(x) for x in payload])}\n")
335
+ # Guard against hard OS errors (e.g., disk full) during file writes.
336
+ if getattr(self, "_fatal_os_error", False):
337
+ return
338
+ try:
339
+ self.files[daq_list].write(f"{timestamp0},{timestamp1},{', '.join([str(x) for x in payload])}\n")
340
+ except (OSError, MemoryError) as ex:
341
+ # Mark fatal condition to alter shutdown path and avoid further writes/commands.
342
+ self._fatal_os_error = True
343
+ with suppress(Exception):
344
+ self.log.critical(f"DAQ file write failed: {ex.__class__.__name__}: {ex}. Initiating graceful shutdown.")
345
+
346
+ # Stop listener to prevent more DAQ traffic and avoid thread crashes.
347
+ with suppress(Exception):
348
+ if hasattr(self.xcp_master, "transport") and self.xcp_master.transport is not None:
349
+ if hasattr(self.xcp_master.transport, "closeEvent"):
350
+ self.xcp_master.transport.closeEvent.set()
351
+ # Best-effort: close any opened files to flush buffers and release resources.
352
+ with suppress(Exception):
353
+ for f in getattr(self, "files", {}).values():
354
+ with suppress(Exception):
355
+ f.flush()
356
+ with suppress(Exception):
357
+ f.close()
358
+ # Do not re-raise; allow the system to continue to a controlled shutdown.
359
+ return
223
360
 
224
361
  def finalize(self):
225
362
  self.log.debug("DaqCsv::finalize()")
@@ -1,6 +1,6 @@
1
1
  #!/usr/bin/env python
2
- """Bin-packing algorithms.
3
- """
2
+ """Bin-packing algorithms."""
3
+
4
4
  from typing import List, Optional
5
5
 
6
6
  from pyxcp.cpp_ext.cpp_ext import Bin
@@ -10,10 +10,10 @@ VOID CALLBACK TimerRoutine(PVOID lpParam, BOOLEAN TimerOrWaitFired) {
10
10
  std::printf("TimerRoutine lpParam is NULL\n");
11
11
  return;
12
12
  }
13
-
13
+
14
14
  const auto* param = static_cast<const int*>(lpParam);
15
15
  std::printf("Timer routine called. Parameter is %d.\n", *param);
16
-
16
+
17
17
  if (TimerOrWaitFired) {
18
18
  std::printf("The wait timed out.\n");
19
19
  } else {
@@ -30,10 +30,10 @@ namespace {
30
30
 
31
31
  #if defined(_M_X64) || defined(_M_IX86) || defined(__SSE__)
32
32
  #include <xmmintrin.h>
33
-
33
+
34
34
  void mul4_vectorized(float* ptr) {
35
35
  if (ptr == nullptr) return;
36
-
36
+
37
37
  __m128 f = _mm_loadu_ps(ptr);
38
38
  f = _mm_mul_ps(f, f);
39
39
  _mm_storeu_ps(ptr, f);
@@ -41,10 +41,10 @@ namespace {
41
41
 
42
42
  #elif defined(_M_ARM64) || defined(__ARM_NEON)
43
43
  #include <arm_neon.h>
44
-
44
+
45
45
  void mul4_vectorized(float* ptr) {
46
46
  if (ptr == nullptr) return;
47
-
47
+
48
48
  float32x4_t f = vld1q_f32(ptr);
49
49
  f = vmulq_f32(f, f);
50
50
  vst1q_f32(ptr, f);
@@ -54,9 +54,9 @@ namespace {
54
54
  // Scalar fallback
55
55
  void mul4_vectorized(float* ptr) {
56
56
  if (ptr == nullptr) return;
57
-
57
+
58
58
  for (size_t i = 0; i < VECTOR_SIZE; ++i) {
59
59
  ptr[i] *= ptr[i];
60
60
  }
61
61
  }
62
- #endif
62
+ #endif
Binary file
Binary file
Binary file
pyxcp/errormatrix.py CHANGED
@@ -1,6 +1,6 @@
1
1
  #!/usr/bin/env python
2
- """Types and structures to support error-handling as specified by XCP.
3
- """
2
+ """Types and structures to support error-handling as specified by XCP."""
3
+
4
4
  import enum
5
5
  from collections import namedtuple
6
6
 
pyxcp/examples/run_daq.py CHANGED
@@ -129,8 +129,9 @@ else:
129
129
  ),
130
130
  ]
131
131
 
132
- daq_parser = DaqToCsv(DAQ_LISTS) # Record to CSV file(s).
133
- # daq_parser = DaqRecorder(DAQ_LISTS, "run_daq", 2) # Record to ".xmraw" file.
132
+
133
+ # daq_parser = DaqToCsv(DAQ_LISTS) # Record to CSV file(s).
134
+ daq_parser = DaqRecorder(DAQ_LISTS, "run_daq_21092025_01", 8) # Record to ".xmraw" file.
134
135
 
135
136
  with ap.run(policy=daq_parser) as x:
136
137
  try:
@@ -149,7 +150,8 @@ with ap.run(policy=daq_parser) as x:
149
150
  print("start DAQ lists.")
150
151
  daq_parser.start() # Start DAQ lists.
151
152
 
152
- time.sleep(5.0 * 60.0) # Run for 15 minutes.
153
+ # time.sleep(2.0 * 60.0)
154
+ time.sleep(0.25 * 60.0 * 60.0) # Run for 15 minutes.
153
155
 
154
156
  print("Stop DAQ....")
155
157
  daq_parser.stop() # Stop DAQ lists.
@@ -1,6 +1,6 @@
1
1
  #!/usr/bin/env python
2
- """Demostrates how to use frame recording policies including recorder extension.
3
- """
2
+ """Demostrates how to use frame recording policies including recorder extension."""
3
+
4
4
  from pprint import pprint
5
5
 
6
6
  from pyxcp.cmdline import ArgumentParser
@@ -11,11 +11,11 @@ ap = ArgumentParser(description="pyXCP frame recording policy example.")
11
11
 
12
12
  LOG_FILE = "pyxcp"
13
13
 
14
- policy = FrameRecorderPolicy(LOG_FILE)
15
- use_recorder = True
14
+ # policy = FrameRecorderPolicy(LOG_FILE)
15
+ # use_recorder = True
16
16
 
17
- # policy = StdoutPolicy() # You may also try this one.
18
- # use_recorder = False
17
+ policy = StdoutPolicy() # You may also try this one.
18
+ use_recorder = False
19
19
 
20
20
  with ap.run(policy=policy) as x:
21
21
  x.connect()
@@ -1,6 +1,6 @@
1
1
  #!/usr/bin/env python
2
- """Very basic hello-world example.
3
- """
2
+ """Very basic hello-world example."""
3
+
4
4
  import time
5
5
 
6
6
  import matplotlib.pyplot as plt
@@ -1,6 +1,5 @@
1
1
  #!/usr/bin/env python
2
- """Use this as a copy-and-paste template for your own scripts.
3
- """
2
+ """Use this as a copy-and-paste template for your own scripts."""
4
3
 
5
4
  from pyxcp.cmdline import ArgumentParser
6
5
 
@@ -1,20 +1,13 @@
1
1
  #!/usr/bin/env python
2
- """Very basic hello-world example.
3
- """
4
- from pyxcp.cmdline import ArgumentParser
5
-
6
-
7
- """
8
- """
2
+ """Very basic hello-world example."""
9
3
 
4
+ import argparse
10
5
 
11
- def callout(master, args):
12
- if args.sk_dll:
13
- master.seedNKeyDLL = args.sk_dll
6
+ from pyxcp.cmdline import ArgumentParser
14
7
 
15
8
 
16
- ap = ArgumentParser(callout)
17
- ap.parser.add_argument(
9
+ parser = argparse.ArgumentParser(description="XCP unlock example")
10
+ parser.add_argument(
18
11
  "-s",
19
12
  "--sk-dll",
20
13
  dest="sk_dll",
@@ -23,7 +16,12 @@ ap.parser.add_argument(
23
16
  default=None,
24
17
  )
25
18
 
19
+ ap = ArgumentParser(parser)
20
+
26
21
  with ap.run() as x:
22
+ if ap.args.sk_dll:
23
+ x.seedNKeyDLL = ap.args.sk_dll
24
+
27
25
  x.connect()
28
26
 
29
27
  print("")
@@ -1,6 +1,6 @@
1
1
  #!/usr/bin/env python
2
2
 
3
- from typing import Dict, List, Optional
3
+ from typing import Optional
4
4
 
5
5
  import can
6
6
 
@@ -9,7 +9,6 @@ from pyxcp.transport.can import CanInterfaceBase
9
9
 
10
10
 
11
11
  class CustomCANInterface(CanInterfaceBase):
12
-
13
12
  def init(self):
14
13
  """Initialize the CAN interface here."""
15
14
 
@@ -1,5 +1,6 @@
1
1
  #!/usr/bin/env python
2
2
  """Very basic hello-world example."""
3
+
3
4
  from pprint import pprint
4
5
 
5
6
  from pyxcp.cmdline import ArgumentParser
@@ -9,21 +10,7 @@ from pyxcp.utils import decode_bytes
9
10
  daq_info = False
10
11
 
11
12
 
12
- def callout(master, args):
13
- global daq_info
14
- if args.daq_info:
15
- daq_info = True
16
-
17
-
18
- ap = ArgumentParser(description="pyXCP hello world.", callout=callout)
19
- ap.parser.add_argument(
20
- "-d",
21
- "--daq-info",
22
- dest="daq_info",
23
- help="Display DAQ-info",
24
- default=False,
25
- action="store_true",
26
- )
13
+ ap = ArgumentParser(description="pyXCP hello world.")
27
14
 
28
15
  with ap.run() as x:
29
16
  x.connect()
@@ -1,6 +1,6 @@
1
1
  #!/usr/bin/env python
2
- """Very basic hello-world example.
3
- """
2
+ """Very basic hello-world example."""
3
+
4
4
  from pprint import pprint
5
5
 
6
6
  from pyxcp.cmdline import ArgumentParser
pyxcp/master/__init__.py CHANGED
@@ -6,4 +6,5 @@
6
6
 
7
7
  .. [1] XCP Specification, Part 2 - Protocol Layer Specification
8
8
  """
9
+
9
10
  from .master import Master # noqa: F401