-
Notifications
You must be signed in to change notification settings - Fork 2
/
Copy pathcard_config.py
278 lines (228 loc) · 6.72 KB
/
card_config.py
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
"""Load a card config file."""
from __future__ import annotations
from dataclasses import dataclass, field
from functools import cache
from pathlib import Path
from typing import Any, Optional, Union
from dacite import from_dict
from yaml import CLoader, load
@dataclass
class ConfigObject:
"""Object in config."""
data_type: str = "uint32"
"""Data type of the object."""
length: int = 1
"""Length of an octet string object (only used when `data_type` is set to ``"octet_str"``)."""
access_type: str = "rw"
"""
Access type of object over the CAN bus, can be ``"rw"``, ``"ro"``, ``"wo"``, or ``"const"``.
"""
default: Any = None
"""Default value of object."""
description: str = ""
"""Description of object."""
value_descriptions: dict[str, int] = field(default_factory=dict)
"""Optional: Can be used to define enum values for an unsigned integer data types."""
bit_definitions: dict[str, Union[int, str]] = field(default_factory=dict)
"""Optional: Can be used to define bitfield of an unsigned integer data types."""
unit: str = ""
"""Optional engineering unit for the object."""
scale_factor: float = 1
"""Can be used to scale a integer value to a engineering (float) value."""
low_limit: Optional[int] = None
"""
The lower raw limit for value. No need to set this if it limit is the lower limit of the data
type.
"""
high_limit: Optional[int] = None
"""
The higher raw limit for value. No need to set this if it limit is the higher limit of the data
type.
"""
@dataclass
class GenerateSubindex(ConfigObject):
"""
Used to generate subindexes for an array.
Example:
.. code-block:: yaml
- index: 0x4000
name: my_array
object_type: array
generate_subindexes:
subindexes: fixed_length
name: item
length: 10
data_type: uint16
access_type: ro
unit: C
scale_factor: 0.001
will generate the equivalent of
.. code-block:: yaml
- index: 0x4000
name: my_array
object_type: array
subindexes:
generate_subindexes:
- subindex: 1
name: item_1
data_type: uint16
access_type: ro
unit: C
scale_factor: 0.001
- subindex: 2
name: item_2
data_type: uint16
access_type: ro
unit: C
scale_factor: 0.001
...
- subindex: 9
name: item_9
data_type: uint16
access_type: ro
unit: C
scale_factor: 0.001
- subindex: 10
name: item_10
data_type: uint16
access_type: ro
unit: C
scale_factor: 0.001
"""
name: str = ""
"""Names of objects to generate."""
subindexes: Union[str, int] = 0
"""Subindexes of objects to generate."""
@dataclass
class SubindexObject(ConfigObject):
"""
Object at subindex.
Example:
.. code-block:: yaml
subindex: 0x1
name: length
data_type: uint8
description: number of files in fread cache
access_type: ro
"""
name: str = ""
"""Name of object, must be in lower_snake_case."""
subindex: int = 0
"""
Subindex of object, start at subindex 1 (subindex 0 aka highest_index_supported will be
generated).
"""
@dataclass
class IndexObject(ConfigObject):
"""
Object at index.
Example:
.. code-block:: yaml
tpdos:
- num: 1
fields:
- [system, storage_percent]
- [system, ram_percent]
event_timer_ms: 30000
"""
name: str = ""
"""Name of object, must be in lower_snake_case."""
index: int = 0
"""Index of object, fw/sw common object are in 0x3000, card objects are in 0x4000."""
object_type: str = "variable"
"""Object type; must be ``"variable"``, ``"array"``, or ``"record"``."""
subindexes: list[SubindexObject] = field(default_factory=list)
"""Defines subindexes for records and arrays."""
generate_subindexes: Optional[GenerateSubindex] = None
"""Used to generate subindexes for arrays."""
@dataclass
class Tpdo:
"""
TPDO.
Example:
.. code-block:: yaml
tpdos:
- num: 1
fields:
- [system, storage_percent]
- [system, ram_percent]
event_timer_ms: 30000
"""
num: int
"""TPDO number, 1-16."""
rtr: bool = False
"""TPDO supports RTR."""
transmission_type: str = "timer"
"""Transmission type of TPDO. Must be ``"timer"`` or ``"sync"``."""
sync: int = 0
"""Send this TPDO every x SYNCs. 0 for acycle. Max 240."""
sync_start_value: int = 0
"""
When set to 0, the count of sync is not process for this TPDO.
When set to 1, the count of sync is processed for this TPDO .
"""
event_timer_ms: int = 0
"""Send the TPDO periodicly in milliseconds."""
inhibit_time_ms: int = 0
"""Delay after boot before the event timer starts in milliseconds."""
fields: list[list[str]] = field(default_factory=list)
"""Index and subindexes of objects to map to the TPDO."""
@dataclass
class Rpdo:
"""
RPDO section.
Example:
.. code-block:: yaml
rpdos:
- num: 1
card: c3
tpdo_num: 1
"""
num: int
"""TPDO number to use, 1-16."""
card: str
"""Card the TPDO is from."""
tpdo_num: int
"""TPDO number, 1-16."""
@dataclass
class CardConfig:
"""
YAML card config.
Example:
.. code-block:: yaml
std_objects:
- device_type
- error_register
...
objects:
- index: 0x3000
name: satellite_id
...
tpdos:
- num: 1
fields:
- [satellite_id]
...
rpdos:
- num: 1
card: c3
tpdo_num: 1
...
"""
std_objects: list[str] = field(default_factory=list)
"""Standard object to include in OD."""
objects: list[IndexObject] = field(default_factory=list)
"""Unique card objects."""
tpdos: list[Tpdo] = field(default_factory=list)
"""TPDOs for the card."""
rpdos: list[Rpdo] = field(default_factory=list)
"""RPDOs for the card."""
fram: list[list[str]] = field(default_factory=list)
"""C3 only. List of index and subindex for the c3 to save the values of to F-RAM."""
@classmethod
@cache
def from_yaml(cls, config_path: Path) -> CardConfig:
"""Load a card YAML config file."""
with config_path.open() as f:
config_raw = load(f, Loader=CLoader)
return from_dict(data_class=cls, data=config_raw)