Files
libretiny/docs/update_docs.py
2022-06-18 21:08:29 +02:00

308 lines
8.7 KiB
Python

# Copyright (c) Kuba Szczodrzyński 2022-05-31.
import re
import sys
from os.path import dirname, join
from typing import Dict, List, Set, Tuple
sys.path.append(join(dirname(__file__), ".."))
from tools.util.fileio import readjson, readtext
from tools.util.markdown import Markdown
from tools.util.obj import get, sizeof
from tools.util.platform import (
get_board_list,
get_board_manifest,
get_families,
get_family,
)
def load_boards() -> Dict[str, dict]:
return {board: get_board_manifest(board) for board in get_board_list()}
def load_chip_type_h() -> str:
code = readtext(
join(
dirname(__file__),
"..",
"arduino",
"libretuya",
"core",
"ChipType.h",
)
)
code = re.sub(r"//.+", "", code)
code = re.sub(r"/\*.+\*/", "", code)
return code
def check_mcus(boards: List[Tuple[str, dict]]) -> bool:
for board_name, board in boards:
# check if all boards' MCUs are defined in families.json
family_name: str = get(board, "build.family")
mcu_name: str = get(board, "build.mcu")
family = get_family(short_name=family_name)
if not family:
print(f"Family '{family_name}' of board '{board_name}' does not exist")
return False
mcus = [mcu.lower() for mcu in family.mcus]
if mcu_name not in mcus:
print(
f"MCU '{mcu_name}' of board '{board_name}' is not defined for family '{family_name}'"
)
return False
return True
def get_family_mcus() -> Set[str]:
out = []
for family in get_families():
out += family.mcus
return set(out)
def get_family_names() -> Set[str]:
return set(family.short_name for family in get_families())
def get_board_mcus(boards: List[Tuple[str, dict]]) -> Set[str]:
out = set()
for _, board in boards:
mcu_name: str = get(board, "build.mcu")
out.add(mcu_name.upper())
return out
def get_enum_keys(code: str, name: str) -> Set[str]:
code = code.partition(f"enum {name}")[2]
code = code.partition(";")[0]
code = code.strip().strip("{}").strip()
code = [line.strip().strip(",").strip() for line in code.split("\n")]
code = filter(None, code)
return set(line.partition(" ")[0].strip() for line in code)
def get_enum_mcus(code: str) -> Set[str]:
return get_enum_keys(code, "ChipType")
def get_enum_families(code: str) -> Set[str]:
return set(family[2:] for family in get_enum_keys(code, "ChipFamily"))
def board_sort(tpl):
return (
get(tpl[1], "vendor"),
get(tpl[1], "build.mcu"),
get(tpl[1], "mcu"),
tpl[0],
)
def write_chips(mcus: List[str]):
md = Markdown(dirname(__file__), "supported_chips")
md.add_list(*mcus)
md.write()
def write_boards(boards: List[Tuple[str, dict]]):
md = Markdown(dirname(__file__), "supported_boards")
header = [
"Name",
"MCU",
"Flash",
"RAM",
"Pins*",
"Wi-Fi",
"BLE",
"ZigBee",
"Family name",
]
rows = []
vendor_prev = ""
for board_name, board in boards:
family = get_family(short_name=get(board, "build.family"))
# add board vendor as a row
vendor = get(board, "vendor")
if vendor_prev != vendor:
rows.append([f"**{vendor}**"])
vendor_prev = vendor
# count total pin count & IO count
pins = "-"
pinout: Dict[str, dict] = get(board, "pcb.pinout")
if pinout:
pinout = [pin for name, pin in pinout.items() if name.isnumeric()]
pins_total = len(pinout)
pins_io = sum(1 for pin in pinout if "ARD" in pin)
pins = f"{pins_total} ({pins_io} I/O)"
# format row values
board_url = f"[{board_name.upper()}](../boards/{board_name}/README.md)"
row = [
board_url,
get(board, "build.mcu").upper(),
sizeof(get(board, "upload.flash_size")),
sizeof(get(board, "upload.maximum_ram_size")),
pins,
"✔️" if "wifi" in get(board, "connectivity") else "",
"✔️" if "ble" in get(board, "connectivity") else "",
"✔️" if "zigbee" in get(board, "connectivity") else "",
f"`{family.name}`",
]
rows.append(row)
md.add_table(header, *rows)
md.write()
def write_unsupported_boards(
series: Dict[str, Dict[str, dict]],
name: str,
supported: List[str],
):
md = Markdown(dirname(__file__), name)
header = [
"Name",
"MCU",
"Flash",
"RAM",
"Pins",
"Wi-Fi",
"BLE",
"ZigBee",
]
rows = []
for series_name in sorted(series):
series_rows = []
series_rows.append([f"**{series_name.upper()} Series**"])
boards = series[series_name]
for board_name, board in sorted(boards.items(), key=board_sort):
if board_name in supported:
continue
row = [
board_name.upper(),
board["mcu"].upper(),
sizeof(board["flash"]),
sizeof(board["ram"]),
str(board["pins_total"]),
"✔️" if "wifi" in board["connectivity"] else "",
"✔️" if "ble" in board["connectivity"] else "",
"✔️" if "zigbee" in board["connectivity"] else "",
]
series_rows.append(row)
if series_rows:
rows += series_rows
md.add_table(header, *rows)
md.write()
def write_families():
md = Markdown(dirname(__file__), "supported_families")
header = [
"Title",
"Name (parent)",
"Code",
"Short name & ID",
"Arduino Core",
"Source SDK",
]
rows = []
for family in get_families():
row = [
# Title
"[{}]({})".format(
family.description,
family.url,
family.name,
)
if family.name
else family.description,
# Name (parent)
f"`{family.name or '-'}`"
if not family.parent
else f"`{family.name}` (`{family.parent}`)",
# Code
f"`{family.code or '-'}`"
if not family.parent
else f"`{family.code}` (`{family.parent_code}`)",
# Short name & ID
"`{}` (0x{:X})".format(
family.short_name,
family.id,
),
# Arduino Core
"✔️" if family.has_arduino_core else "",
# Source SDK
"`{}` ([{}]({}))".format(
family.framework,
family.sdk_name,
family.sdk,
)
if family.name
else "-",
]
rows.append(row)
md.add_table(header, *rows)
md.write()
def write_boards_list(boards: List[Tuple[str, dict]]):
md = Markdown(dirname(__file__), join("..", "boards", "SUMMARY"))
items = []
for board_name, board in boards:
title = get(board, "name")
items.append(f"[{title}](../boards/{board_name}/README.md)")
md.add_list(*items)
md.write()
if __name__ == "__main__":
boards = load_boards()
boards = sorted(boards.items(), key=board_sort)
code = load_chip_type_h()
errors = False
families_json = get_family_names()
families_enum = get_enum_families(code)
if families_json != families_enum:
print(f"Inconsistent JSON families vs ChipType.h families:")
print("- Missing in JSON: " + ", ".join(families_enum - families_json))
print("- Missing in enum: " + ", ".join(families_json - families_enum))
errors = True
mcus_json = get_family_mcus()
mcus_enum = get_enum_mcus(code)
mcus_boards = get_board_mcus(boards)
if mcus_json != mcus_enum:
print(f"Inconsistent JSON family MCUs vs ChipType.h MCUs:")
print("- Missing in JSON: " + ", ".join(mcus_enum - mcus_json))
print("- Missing in enum: " + ", ".join(mcus_json - mcus_enum))
# this is not considered an error (for now)
# errors = True
if not check_mcus(boards):
errors = True
if errors:
exit(1)
write_chips(sorted(mcus_boards.union(mcus_json)))
write_boards(boards)
write_boards_list(boards)
write_families()
boards_all = [
"boards_tuya_all",
]
for name in boards_all:
file = join(dirname(__file__), f"{name}.json")
data = readjson(file)
write_unsupported_boards(
series=data,
name=f"unsupported_{name}",
supported=[tpl[0] for tpl in boards],
)