summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--stm32/mw.j243
-rwxr-xr-xstm32/run.py168
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)