diff options
-rw-r--r-- | stm32/mw.j2 | 43 | ||||
-rwxr-xr-x | stm32/run.py | 168 |
2 files changed, 211 insertions, 0 deletions
diff --git a/stm32/mw.j2 b/stm32/mw.j2 new file mode 100644 index 0000000..dfb722b --- /dev/null +++ b/stm32/mw.j2 @@ -0,0 +1,43 @@ +{# +{{ part["Part Number"] }} is a chip from [[Manufacturer:STMicroelectronics]] in their ''[[Chip family:{{ part["Series"] }}]]'' family. +{{ part["General Description"] }} +#} + += Shared parameters = + +{% for field, value in shared_fields.items() %} +* {{ field }}: {{ value }} +{% endfor %} + += Distinct parameters = + +<table> + +<tr> +<td></td> +{% for part in parts %} +<th> +{{ part["Part Number"][-2:] }} +</th> +{% endfor %} +</tr> + +{% for field in distinct_fields if field not in ["General Description", "Part Number"] %} +<tr> +<th>{{ field }}</th> +{% for part in parts %} +{% set value = part[field] %} +<td> +{% if value is string or value is number %} +{{ value }} +{% elif value %} +{% for v in value %} +{{ v }}<br/> +{% endfor %} +{% endif %} +</td> +{% endfor %} +</tr> +{% endfor %} + +</table> diff --git a/stm32/run.py b/stm32/run.py new file mode 100755 index 0000000..097dbd2 --- /dev/null +++ b/stm32/run.py @@ -0,0 +1,168 @@ +#!/usr/bin/env python3 + +import re +import shutil +from collections import defaultdict +from jinja2 import Environment, FileSystemLoader, select_autoescape +from openpyxl import load_workbook +from pathlib import Path +from itertools import groupby + +env = Environment( + loader=FileSystemLoader("."), + trim_blocks=True, + lstrip_blocks=True, + autoescape=select_autoescape(['html', 'xml']) +) + +files = [ + ("STM32 High Performance MCUs.xlsx", "High Performance"), + ("STM32 Mainstream MCUs.xlsx", "Mainstream"), + ("STM32 Ultra Low Power MCUs.xlsx", "Ultra Low Power"), + ("STM32 Wireless MCUs.xlsx", "Wireless"), +] + +series_r = r"^(STM32F.|STM32H.|STM32L[012356789]|STM32L4[RS]|STM32L4|STM32WB).*" + +def load_file(filename, line): + wb = load_workbook(filename=filename) + ws = wb.active + + header = ws[6] + + fields = [cell.value for cell in header] + +# print("Header") +# print(fields) + + parts = {} + + split_set = set([ + "Package", + "Other timer functions", + "Parallel Interfaces", + "Additional Serial Interfaces", + "Crypto-HASH", + "USB Type", + "Connectivity supported", + "Operating Temperature (°C) min", + "Operating Temperature (°C) max", + "Supply Current (µA) (Lowest power mode) typ", + "Display controller", + ]) + field_re = r" +" + + for row in ws.iter_rows(min_row=7): + part_number = row[0].value + parts[part_number] = part = {} + + for idx, cell in enumerate(row): + v = cell.value + v = None if v == "-" else v + if v is None: + continue + + field = fields[idx] + field = field.strip() + field = re.sub(field_re, " ", field) + if field in split_set: + v = list(v.split(",")) + + try: + if isinstance(v, list): + v = [int(x) for x in v] + else: + v = int(v) + except ValueError: + pass + + part[field] = v + part["Line"] = line + part["Series"] = re.findall(series_r, part["Part Number"])[0] + part["00 FLASH"] = part["FLASH Size (kB) (Prog)"] + # This is probably a bug in the spreadsheet. + part["00 RAM"] = part["RAM Size (kB)"] if "RAM Size (kB)" in part else None + + if False: + for part in parts.values(): + for k, v in part.items(): + if isinstance(v, list): + print(k) + for item in v: + print(" {}".format(item)) + else: + print("{}: {}".format(k, v)) + + if False: + break + + process_parts(parts) + +def process_parts(parts): + r = r"^(STM32F.|STM32H.|STM32L[012356789]|STM32L4[RS]|STM32L4|STM32WB).*" + subfamily = lambda p: p["Part Number"][0:9] + +# for p in parts.values(): +# x = subfamily(p) +# print("{} => {}".format(p["Part Number"], x)) + + if False: + for part_number, part in parts.items(): + path = out_dir / "Chip:{}.mw".format(part_number) + with open(path, "w") as out: + template = env.get_template("mw.j2") + out.write(template.render(part=part)) + + for subfamily, values in groupby(sorted(parts.values(), key=subfamily), key=subfamily): + values = list(values) +# print("{}, len={}".format(subfamily, len(values))) + write_parts(subfamily, values) + +def write_parts(subfamily, parts): + fields = list(next(parts.__iter__()).keys()) + +# [print("fieldXXX:{}".format(f)) for f in fields] + print("subfamily: {}".format(subfamily)) + + distinct_fields = set() + + shared_fields = {} + for field in fields: + if field in distinct_fields: + continue + + first = True + for part in parts: + part_number = part["Part Number"] + if first: + value = part[field] + shared_fields[field] = value + first = False + else: + field_value = part[field] if field in part else None + if field_value != value: + distinct_fields.add(field) + del shared_fields[field] + break + +# print("shared_fields={}".format(shared_fields)) +# print("distinct_fields={}".format(list(distinct_fields))) + +# parts = sorted(parts, key=lambda p: (p["00 FLASH"], p["00 RAM"])) + + path = out_dir / "Chip:{}.mw".format(subfamily) + with open(path, "w") as out: + template = env.get_template("mw.j2") + out.write(template.render( + fields=fields, + shared_fields=shared_fields, + distinct_fields=sorted(distinct_fields), + parts=parts)) + +out_dir = Path("mw") +if out_dir.exists(): + shutil.rmtree(out_dir) +out_dir.mkdir() + +for filename, line in files: + load_file(filename, line) |