#!/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)