-
Notifications
You must be signed in to change notification settings - Fork 2
/
generate_header.py
153 lines (136 loc) · 5.88 KB
/
generate_header.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
"""Script to generate c++ header file of canbus constants."""
from __future__ import annotations
import argparse
import importlib
import io
import os.path
import sys
from types import ModuleType
from header_generation_utils.header_generation_utils.utils import (
Block,
Languge,
Subsystem,
generate_file_comment,
write_enum_cpp,
write_enum_c,
)
def generate_can_cpp(output: io.StringIO, constants_mod: ModuleType) -> None:
"""Generate source code into output."""
with Block(
output=output,
start="namespace can::ids {\n\n",
terminate="} // namespace can::ids\n",
):
write_enum_cpp(constants_mod.FunctionCode, output)
write_enum_cpp(constants_mod.MessageId, output)
write_enum_cpp(constants_mod.NodeId, output)
write_enum_cpp(constants_mod.ErrorCode, output)
write_enum_cpp(constants_mod.ErrorSeverity, output)
write_enum_cpp(constants_mod.ToolType, output)
write_enum_cpp(constants_mod.SensorType, output)
write_enum_cpp(constants_mod.SensorId, output)
write_enum_cpp(constants_mod.SensorOutputBinding, output)
write_enum_cpp(constants_mod.SensorThresholdMode, output)
write_enum_cpp(constants_mod.PipetteTipActionType, output)
write_enum_cpp(constants_mod.GearMotorId, output)
write_enum_cpp(constants_mod.MotorPositionFlags, output)
write_enum_cpp(constants_mod.MoveStopCondition, output)
write_enum_cpp(constants_mod.PipetteType, output)
write_enum_cpp(constants_mod.MotorUsageValueType, output)
def generate_can_c(output: io.StringIO, constants_mod: ModuleType, arbitration_id: ModuleType) -> None:
"""Generate source code into output."""
can = "CAN"
write_enum_c(constants_mod.FunctionCode, output, can)
write_enum_c(constants_mod.MessageId, output, can)
write_enum_c(constants_mod.NodeId, output, can)
write_enum_c(constants_mod.ErrorCode, output, can)
write_enum_c(constants_mod.ToolType, output, can)
write_enum_c(constants_mod.SensorType, output, can)
write_enum_c(constants_mod.SensorId, output, can)
write_enum_c(constants_mod.SensorOutputBinding, output, can)
write_enum_c(constants_mod.SensorThresholdMode, output, can)
write_enum_c(constants_mod.PipetteTipActionType, output, can)
write_enum_c(constants_mod.GearMotorId, output, can)
write_enum_c(constants_mod.MotorPositionFlags, output, can)
write_enum_c(constants_mod.MoveStopCondition, output, can)
write_arbitration_id_c(output, can, arbitration_id)
write_enum_c(constants_mod.PipetteType, output, can)
write_enum_c(constants_mod.MotorUsageValueType, output, can)
def generate_rearpanel_cpp(output: io.StringIO, constants_mod: ModuleType) -> None:
"""Generate source code into output."""
with Block(
output=output,
start="#include <cstdint>\n\nnamespace rearpanel::ids {\n\n",
terminate="} // namespace rearpanel::ids\n",
):
write_enum_cpp(constants_mod.BinaryMessageId, output, 'uint16_t')
write_enum_cpp(constants_mod.LightTransitionType, output, 'uint8_t')
write_enum_cpp(constants_mod.LightAnimationType, output, 'uint8_t')
def write_arbitration_id_c(output: io.StringIO, prefix: str, arbitration_id: ModuleType) -> None:
"""Generate C arbitration id code."""
output.write(f"/** {arbitration_id.ArbitrationIdParts.__doc__} */\n")
with Block(
output=output,
start="typedef struct {\n",
terminate=f"}} {prefix}{arbitration_id.ArbitrationIdParts.__name__};\n\n",
):
for i in arbitration_id.ArbitrationIdParts._fields_:
output.write(f" unsigned int {i[0]}: {i[2]};\n")
def main() -> None:
"""Entry point."""
parser = argparse.ArgumentParser(
description="Generate a C or C++ header files defining CANBUS constants."
)
parser.add_argument(
"target",
metavar="TARGET",
type=argparse.FileType("w"),
default=sys.stdout,
nargs="?",
help="path of header file to generate; use - or do not specify for stdout",
)
parser.add_argument(
"-s",
"--source-dir",
type=str,
default="",
help="a path containing an importable opentrons_hardware. if not specified, will use installed package",
)
parser.add_argument(
"--language",
metavar="language",
type=Languge,
default=Languge.CPP,
choices=Languge,
nargs="?",
help=f"language to use. can be one of {','.join(l.value for l in Languge)}",
)
parser.add_argument(
"--subsystem",
metavar="subsystem",
type=Subsystem,
default=Subsystem.CAN,
choices=Subsystem,
nargs="?",
help=f"subsystem to generate constants for. can be one of {','.join(s.value for s in Subsystem)}",
)
args = parser.parse_args()
if args.source_dir:
sys.path.append(os.path.join(args.source_dir, os.path.pardir))
constants = importlib.import_module('opentrons_hardware.firmware_bindings.constants')
arbid = importlib.import_module('opentrons_hardware.firmware_bindings.arbitration_id')
rearpanel_constants = importlib.import_module('opentrons_hardware.firmware_bindings.binary_constants')
output = args.target
generate_file_comment(output)
if args.subsystem in {Subsystem.CAN}:
if args.language in {Languge.CPP, Languge.CPP_alt}:
generate_can_cpp(output, constants)
if args.language in {Languge.C}:
generate_can_c(output, constants, arbid)
elif args.subsystem in {Subsystem.REARPANEL}:
if args.language in {Languge.CPP, Languge.CPP_alt}:
generate_rearpanel_cpp(output, rearpanel_constants)
if args.language in {Languge.C}:
raise RuntimeError(f"C header unsupported for subsystem={args.subsystem}")
if __name__ == "__main__":
main()