|
32 | 32 | raise Exception("{} doesn't exist".format(board_header))
|
33 | 33 |
|
34 | 34 | with open(interfaces_json) as interfaces_fh:
|
35 |
| - interfaces = json.load(interfaces_fh) |
| 35 | + interface_pins = json.load(interfaces_fh) |
| 36 | + allowed_interfaces = interface_pins["interfaces"] |
| 37 | + allowed_pins = set(interface_pins["pins"]) |
36 | 38 | # convert instance-keys to integers (allowed by Python but not by JSON)
|
37 |
| - for interface in interfaces: |
38 |
| - for instance in list(interfaces[interface]): |
39 |
| - interfaces[interface][int(instance)] = interfaces[interface].pop(instance) |
| 39 | + for interface in allowed_interfaces: |
| 40 | + instances = allowed_interfaces[interface]["instances"] |
| 41 | + # can't modify a list that we're iterating over, so iterate over a copy |
| 42 | + instances_copy = list(instances) |
| 43 | + for instance in instances_copy: |
| 44 | + instance_num = int(instance) |
| 45 | + instances[instance_num] = instances.pop(instance) |
40 | 46 |
|
41 | 47 | DefineType = namedtuple("DefineType", ["name", "value", "resolved_value", "lineno"])
|
42 | 48 |
|
|
69 | 75 | if include_suggestion == expected_include_suggestion:
|
70 | 76 | has_include_suggestion = True
|
71 | 77 | else:
|
72 |
| - raise Exception("{}:{} Suggests including \"{}\" but file is named \"{}\"".format(board_header, lineno, include_suggestion, expected_include_suggestion)) |
| 78 | + raise Exception(r"{}:{} Suggests including \"{}\" but file is named \"{}\"".format(board_header, lineno, include_suggestion, expected_include_suggestion)) |
73 | 79 | # look for "#ifndef BLAH_BLAH"
|
74 | 80 | m = re.match(r"^#ifndef (\w+)\s*$", line)
|
75 | 81 | if m:
|
|
83 | 89 | value = m.group(2)
|
84 | 90 | # check all uppercase
|
85 | 91 | if name != name.upper():
|
86 |
| - raise Exception("{}:{} Expected \"{}\" to be all uppercase".format(board_header, lineno, name)) |
| 92 | + raise Exception(r"{}:{} Expected \"{}\" to be all uppercase".format(board_header, lineno, name)) |
87 | 93 | # check that adjacent #ifndef and #define lines match up
|
88 | 94 | if last_ifndef_lineno + 1 == lineno:
|
89 | 95 | if last_ifndef != name:
|
|
145 | 151 | warnings.warn("{}:{} Both {} and {} claim to be pin {}".format(board_header, lineno, pins[resolved_value][0].name, name, resolved_value))
|
146 | 152 | pins[resolved_value].append(define)
|
147 | 153 | else:
|
148 |
| - if not (0 <= resolved_value <= 29): |
149 |
| - raise Exception("{}:{} Pin {} for {} is outside of the allowed range".foramt(board_header, lineno, resolved_value, name)) |
| 154 | + if resolved_value not in allowed_pins: |
| 155 | + raise Exception("{}:{} Pin {} for {} isn't a valid pin-number".format(board_header, lineno, resolved_value, name)) |
150 | 156 | pins[resolved_value] = [define]
|
151 | 157 |
|
152 | 158 | #import pprint; pprint.pprint(dict(sorted(defines.items(), key=lambda x: x[1].lineno)))
|
153 | 159 |
|
154 | 160 | # check for invalid DEFAULT mappings
|
155 | 161 | for name, define in defines.items():
|
156 |
| - m = re.match(r"^(PICO_DEFAULT_(\w+))_(\w+)_PIN$", name) |
| 162 | + m = re.match("^(PICO_DEFAULT_([A-Z0-9]+))_([A-Z0-9]+)_PIN$", name) |
157 | 163 | if m:
|
158 | 164 | instance_name = m.group(1)
|
159 | 165 | interface = m.group(2)
|
160 | 166 | function = m.group(3)
|
161 | 167 | if interface == "WS2812":
|
162 | 168 | continue
|
163 |
| - if interface not in interfaces: |
| 169 | + if interface not in allowed_interfaces: |
164 | 170 | raise Exception("{}:{} {} is defined but {} isn't in {}".format(board_header, define.lineno, name, interface, interfaces_json))
|
165 | 171 | if instance_name not in defines:
|
166 | 172 | raise Exception("{}:{} {} is defined but {} isn't defined".format(board_header, define.lineno, name, instance_name))
|
167 | 173 | instance_define = defines[instance_name]
|
168 |
| - instance = instance_define.resolved_value |
169 |
| - if instance not in interfaces[interface]: |
170 |
| - raise Exception("{}:{} {} is set to an invalid instance {}".format(board_header, instance_define.lineno, instance_define, instance)) |
171 |
| - if function not in interfaces[interface][instance]: |
| 174 | + instance_num = instance_define.resolved_value |
| 175 | + if instance_num not in allowed_interfaces[interface]["instances"]: |
| 176 | + raise Exception("{}:{} {} is set to an invalid instance {}".format(board_header, instance_define.lineno, instance_define, instance_num)) |
| 177 | + interface_instance = allowed_interfaces[interface]["instances"][instance_num] |
| 178 | + if function not in interface_instance: |
172 | 179 | raise Exception("{}:{} {} is defined but {} isn't a valid function for {}".format(board_header, define.lineno, name, function, instance_define))
|
173 |
| - if define.resolved_value not in interfaces[interface][instance][function]: |
174 |
| - raise Exception("{}:{} {} is set to {} which isn't a valid pin for {} on {} {}".format(board_header, define.lineno, name, define.resolved_value, function, interface, instance)) |
| 180 | + if define.resolved_value not in interface_instance[function]: |
| 181 | + raise Exception("{}:{} {} is set to {} which isn't a valid pin for {} on {} {}".format(board_header, define.lineno, name, define.resolved_value, function, interface, instance_num)) |
| 182 | + |
| 183 | +def list_to_string_with(lst, joiner): |
| 184 | + elems = len(lst) |
| 185 | + if elems == 0: |
| 186 | + return "" |
| 187 | + elif elems == 1: |
| 188 | + return str(lst[0]) |
| 189 | + else: |
| 190 | + return "{} {} {}".format(", ".join(str(l) for l in lst[:-1]), joiner, lst[-1]) |
| 191 | + |
| 192 | +# check that each used DEFAULT interface includes (at least) the expected pin-functions |
| 193 | +for name, define in defines.items(): |
| 194 | + m = re.match("^PICO_DEFAULT_([A-Z0-9]+)$", name) |
| 195 | + if m: |
| 196 | + interface = m.group(1) |
| 197 | + if interface not in allowed_interfaces: |
| 198 | + raise Exception("{}:{} {} is defined but {} isn't in {}".format(board_header, define.lineno, name, interface, interfaces_json)) |
| 199 | + if "expected_functions" in allowed_interfaces[interface]: |
| 200 | + expected_functions = allowed_interfaces[interface]["expected_functions"] |
| 201 | + if "required" in expected_functions: |
| 202 | + for function in expected_functions["required"]: |
| 203 | + expected_function_pin = "{}_{}_PIN".format(name, function) |
| 204 | + if expected_function_pin not in defines: |
| 205 | + raise Exception("{}:{} {} is defined but {} isn't defined".format(board_header, define.lineno, name, expected_function_pin)) |
| 206 | + if "one_of" in expected_functions: |
| 207 | + expected_function_pins = list("{}_{}_PIN".format(name, function) for function in expected_functions["one_of"]) |
| 208 | + if not any(func_pin in defines for func_pin in expected_function_pins): |
| 209 | + raise Exception("{}:{} {} is defined but none of {} are defined".format(board_header, define.lineno, name, list_to_string_with(expected_function_pins, "or"))) |
175 | 210 |
|
176 | 211 | if not has_include_guard:
|
177 | 212 | raise Exception("{} has no include-guard (expected {})".format(board_header, expected_include_guard))
|
|
0 commit comments