From 421b4202ccae819a256f053588c8e1d6a730f27f Mon Sep 17 00:00:00 2001 From: grabowski Date: Tue, 13 Oct 2026 16:32:25 +0700 Subject: [PATCH] Product repository template Layout, proplan.toml, README/CHANGELOG, placeholder product image, .gitignore, KiBot/release/docgen workflows and TEMPLATE.md. Source of truth: contrib/product-template in B4L/proplan (cargo test --test product_template checks it as Gitea 1.27 creates a repository from it). --- .gitea/template | 9 ++ .gitea/workflows/docgen.yml | 54 +++++++++++ .gitea/workflows/kibot.yml | 48 ++++++++++ .gitea/workflows/release.yml | 57 ++++++++++++ .gitignore | 37 ++++++++ CHANGELOG.md | 7 ++ README.md | 25 +++++ TEMPLATE.md | 168 ++++++++++++++++++++++++++++++++++ assets/README.md | 4 + assets/product.png | Bin 0 -> 15925 bytes docs/README.md | 5 + docs/datasheets/README.md | 4 + docs/tex/README.md | 3 + external/README.md | 5 + firmware/README.md | 7 ++ firmware/lib/README.md | 3 + hardware/$REPO_NAME/README.md | 11 +++ hardware/lib/README.md | 6 ++ kibot.yaml | 78 ++++++++++++++++ mech/README.md | 4 + proplan.toml | 24 +++++ sim/README.md | 4 + software/README.md | 5 + test/README.md | 5 + 24 files changed, 573 insertions(+) create mode 100644 .gitea/template create mode 100644 .gitea/workflows/docgen.yml create mode 100644 .gitea/workflows/kibot.yml create mode 100644 .gitea/workflows/release.yml create mode 100644 .gitignore create mode 100644 CHANGELOG.md create mode 100644 README.md create mode 100644 TEMPLATE.md create mode 100644 assets/README.md create mode 100644 assets/product.png create mode 100644 docs/README.md create mode 100644 docs/datasheets/README.md create mode 100644 docs/tex/README.md create mode 100644 external/README.md create mode 100644 firmware/README.md create mode 100644 firmware/lib/README.md create mode 100644 hardware/$REPO_NAME/README.md create mode 100644 hardware/lib/README.md create mode 100644 kibot.yaml create mode 100644 mech/README.md create mode 100644 proplan.toml create mode 100644 sim/README.md create mode 100644 software/README.md create mode 100644 test/README.md diff --git a/.gitea/template b/.gitea/template new file mode 100644 index 0000000..9169111 --- /dev/null +++ b/.gitea/template @@ -0,0 +1,9 @@ +# Files Gitea fills in when a repository is created from this template: the +# new repository's name and description go into their text and their path +# (the board folder under hardware/ is renamed to the repository's name). +# Gitea 1.27: plain globs only. Everything else (workflows, TEMPLATE.md) is +# copied as it is. +proplan.toml +README.md +CHANGELOG.md +hardware/*/README.md diff --git a/.gitea/workflows/docgen.yml b/.gitea/workflows/docgen.yml new file mode 100644 index 0000000..5263f26 --- /dev/null +++ b/.gitea/workflows/docgen.yml @@ -0,0 +1,54 @@ +name: Fabrication document + +# With a docs/input.md (typecad-docgen front matter, as in PowerModule): +# builds the fabrication document of the first board and pushes it to the +# docu branch, so main stays free of generated files. Adapted from +# LVSolarBuck and PowerModule. +on: + push: + branches: [main] + paths: + - 'docs/input.md' + - 'hardware/**' + - '.gitea/workflows/docgen.yml' + +jobs: + docgen: + runs-on: kicad10_auto + steps: + - uses: actions/checkout@v4 + + - name: Inputs + id: inputs + run: | + pcb=$(find hardware -mindepth 2 -maxdepth 2 -name '*.kicad_pcb' | sort | head -1) + if [ -f docs/input.md ] && [ -n "$pcb" ]; then + echo "pcb=$pcb" >> "$GITHUB_OUTPUT" + else + echo "No docs/input.md or no board yet: nothing to build." + fi + + - name: Build + if: steps.inputs.outputs.pcb != '' + run: | + mkdir -p output-docs + typecad-docgen docs/input.md "${{ steps.inputs.outputs.pcb }}" -o output-docs/index.html + + - name: Push to the docu branch + if: steps.inputs.outputs.pcb != '' + env: + GITEA_TOKEN: ${{ secrets.GITEA_TOKEN }} + run: | + git config --global user.email "${{ gitea.actor }}@noreply.localhost" + git config --global user.name "${{ gitea.actor }}" + REPO_URL=$(git config --get remote.origin.url) + AUTHED_URL=${REPO_URL/https:\/\//https:\/\/${GITEA_TOKEN}@} + git clone --depth 1 --branch docu "$AUTHED_URL" docu || git clone --depth 1 "$AUTHED_URL" docu + cd docu + git checkout -B docu + git rm -rq . || true + cp -r ../output-docs/* . + git add -A + if git diff --cached --quiet; then echo "No changes"; exit 0; fi + git commit -m "chore: fabrication document" + git push --force "$AUTHED_URL" docu diff --git a/.gitea/workflows/kibot.yml b/.gitea/workflows/kibot.yml new file mode 100644 index 0000000..2dd9401 --- /dev/null +++ b/.gitea/workflows/kibot.yml @@ -0,0 +1,48 @@ +name: KiBot + +# Checks every board (hardware/*/*.kicad_pro): ERC, DRC, schematic PDF, +# gerbers, drill, pick and place, BOM; the outputs are kept as an artifact. +# Adapted from LVSolarBuck (runner label kicad10_auto). Without a board yet +# the job ends right away. +on: + push: + branches: [main] + paths: + - 'hardware/**' + - 'kibot.yaml' + - '.gitea/workflows/kibot.yml' + pull_request: + paths: + - 'hardware/**' + - 'kibot.yaml' + workflow_dispatch: + +jobs: + boards: + runs-on: kicad10_auto + steps: + - uses: actions/checkout@v4 + + - name: Find boards + id: boards + run: | + found=$(find hardware -mindepth 2 -maxdepth 2 -name '*.kicad_pro' | sort | tr '\n' ' ') + echo "projects=$found" >> "$GITHUB_OUTPUT" + if [ -z "$found" ]; then echo "No KiCad project under hardware/ yet."; fi + + - name: KiBot + if: steps.boards.outputs.projects != '' + run: | + for pro in ${{ steps.boards.outputs.projects }}; do + dir=$(dirname "$pro"); board=$(basename "$dir") + echo "== $board" + (cd "$dir" && kibot -c "$GITHUB_WORKSPACE/kibot.yaml" -d "$GITHUB_WORKSPACE/Generated/$board" -v) \ + || echo "::warning::KiBot reported problems for $board" + done + + - name: Keep the outputs + if: steps.boards.outputs.projects != '' + uses: https://github.com/christopherHX/gitea-upload-artifact@v4 + with: + name: kibot-outputs + path: Generated diff --git a/.gitea/workflows/release.yml b/.gitea/workflows/release.yml new file mode 100644 index 0000000..b4b4df3 --- /dev/null +++ b/.gitea/workflows/release.yml @@ -0,0 +1,57 @@ +name: Release outputs + +# On a tag v* (a prototype stage): the KiBot outputs of every board, zipped per +# board, attached to the tag's release (created when missing). The job token +# must be allowed to write releases. Adapted from LVSolarBuck; runs for the +# first time at the first tag. +on: + push: + tags: ['v*'] + +jobs: + release: + runs-on: kicad10_auto + steps: + - uses: actions/checkout@v4 + + - name: KiBot outputs per board + run: | + mkdir -p dist + for pro in $(find hardware -mindepth 2 -maxdepth 2 -name '*.kicad_pro' | sort); do + dir=$(dirname "$pro"); board=$(basename "$dir") + (cd "$dir" && kibot -c "$GITHUB_WORKSPACE/kibot.yaml" -d "$GITHUB_WORKSPACE/out/$board") \ + || echo "::warning::KiBot reported problems for $board" + python3 -c 'import shutil, sys; shutil.make_archive(sys.argv[1], "zip", sys.argv[2])' \ + "dist/$board-${GITHUB_REF_NAME}" "out/$board" + done + ls -la dist + + - name: Attach to the release + env: + TOKEN: ${{ secrets.GITEA_TOKEN }} + run: | + python3 - <<'EOF' + import json, os, pathlib, urllib.error, urllib.request, uuid + api = f"{os.environ['GITHUB_SERVER_URL']}/api/v1/repos/{os.environ['GITHUB_REPOSITORY']}" + tag = os.environ["GITHUB_REF_NAME"] + auth = {"Authorization": f"token {os.environ['TOKEN']}"} + + def call(method, url, body=None, ctype="application/json"): + req = urllib.request.Request(url, data=body, method=method, headers={**auth, "Content-Type": ctype}) + with urllib.request.urlopen(req) as r: + return json.load(r) + + try: + rel = call("GET", f"{api}/releases/tags/{tag}") + except urllib.error.HTTPError as e: + if e.code != 404: + raise + rel = call("POST", f"{api}/releases", json.dumps({"tag_name": tag, "name": tag}).encode()) + for f in sorted(pathlib.Path("dist").glob("*.zip")): + b = uuid.uuid4().hex + head = (f"--{b}\r\nContent-Disposition: form-data; name=\"attachment\"; filename=\"{f.name}\"\r\n" + "Content-Type: application/zip\r\n\r\n").encode() + body = head + f.read_bytes() + f"\r\n--{b}--\r\n".encode() + call("POST", f"{api}/releases/{rel['id']}/assets?name={f.name}", body, f"multipart/form-data; boundary={b}") + print("attached", f.name) + EOF diff --git a/.gitignore b/.gitignore new file mode 100644 index 0000000..dfae03e --- /dev/null +++ b/.gitignore @@ -0,0 +1,37 @@ +# KiCad: backups, locks, local settings, caches +*-backups/ +*.kicad_prl +*.lck +*.bak +*.bck +*.kicad_pcb-bak +*.kicad_sch-bak +_autosave-* +fp-info-cache +\#auto_saved_files\# + +# FreeCAD backups +*.FCBak +*.FCStd1 + +# IDE build output and tool caches +Debug/ +Release/ +build/ +__pycache__/ +*.pyc +.venv/ +node_modules/ +.history/ +.claude/ +.vscode/ +.idea/ + +# Generated output: CI builds it and attaches it to the release +Generated/ +Fabrication/ +kibot_output_*/ + +# OS +.DS_Store +Thumbs.db diff --git a/CHANGELOG.md b/CHANGELOG.md new file mode 100644 index 0000000..cef4f91 --- /dev/null +++ b/CHANGELOG.md @@ -0,0 +1,7 @@ +# Changelog: $REPO_NAME + +One section per prototype stage, newest first; the heading is the tag. + +## v0.1 (planned) + +- First boards. diff --git a/README.md b/README.md new file mode 100644 index 0000000..c5b40d9 --- /dev/null +++ b/README.md @@ -0,0 +1,25 @@ +# $REPO_NAME + +$REPO_DESCRIPTION + +Created from [B4L/product-template](https://git.b4l.co.th/B4L/product-template). +TEMPLATE.md explains the layout, the rules and `proplan.toml`. + +| Folder | What goes there | +|---|---| +| `assets/` | the product image (`assets/product.png`, shown by proplan), renders | +| `hardware/$REPO_NAME/` | the KiCad project of the board | +| `hardware/lib/` | symbols, footprints and 3D models shared by the boards | +| `firmware/` | MCU code, one folder per target; `firmware/lib/` for shared drivers | +| `external/` | third-party code as git submodules | +| `software/` | host tools and apps | +| `mech/` | FreeCAD sources and STEP exports | +| `sim/` | LTspice/ngspice models, calculation scripts and notebooks | +| `test/` | bench results per prototype stage (`test/v0.1/`) | +| `docs/` | documentation; `docs/datasheets/` for vendor PDFs, `docs/tex/` for LaTeX | + +## Prototype stages + +Each prototype is a git tag (`v0.1`, `v0.2`, ...). CI builds gerbers, BOM and +schematic PDFs for the tag and attaches them to its release; CHANGELOG.md says +what each stage changes. In proplan the prototype stage links the tag. diff --git a/TEMPLATE.md b/TEMPLATE.md new file mode 100644 index 0000000..86dc5e8 --- /dev/null +++ b/TEMPLATE.md @@ -0,0 +1,168 @@ +# B4L product repository template + +Every B4L product repository has the same layout, so people and proplan find +the product image, the boards, the firmware and the libraries in the same +place. This file explains the layout, the rules and `proplan.toml`. It is +copied into every repository created from the template; keep it as the +reference. + +## Create a product repository + +In Gitea: **New Repository**, choose the template **B4L/product-template**, +tick **Git Content**, give the repository the product's name and a +description. Gitea puts the name into `README.md`, `CHANGELOG.md`, +`proplan.toml` and the board folder under `hardware/` (the files listed in +`.gitea/template`). Then: + +1. Replace `assets/product.png` with a photo or render of the product (PNG, + JPEG or WebP, at most 5 MB). +2. Create the KiCad project in the board folder (KiCad: File, New Project; the + project file is `hardware//.kicad_pro`). +3. Commit and push. The KiBot workflow checks the board on every push. +4. Tag the first prototype `v0.1` when its boards are ordered, and link the + tag to the stage on the project's Prototypes tab in proplan. + +## Layout + +| Path | What goes there | +|---|---| +| `proplan.toml` | the manifest proplan reads (below) | +| `README.md`, `CHANGELOG.md` | what the product is; one changelog section per stage (`## v0.2`) | +| `assets/product.png` | the product image | +| `hardware//` | one KiCad project per board | +| `hardware/lib/` | symbols, footprints and 3D models shared by the boards | +| `firmware//` | MCU code (STM32CubeIDE or CMake), `firmware/lib/` for shared drivers | +| `external/` | third-party code as git submodules (e.g. ST's USB-PD middleware) | +| `software//` | host tools and apps | +| `mech/` | FreeCAD sources and STEP exports | +| `sim/` | LTspice/ngspice, calculation scripts and notebooks | +| `test//` | bench results per stage (`test/v0.1/`) | +| `docs/`, `docs/datasheets/`, `docs/tex/` | documentation, vendor PDFs, LaTeX sources | +| `.gitea/workflows/` | KiBot, release outputs, fabrication document | + +## Rules + +- A board revision is a tag (`v0.1`, `v0.2`), never a copied folder + (`kicad_v1_5/` next to `kicad_v1_6/`). A real variant built side by side + (48 V and 24 V, 2-board and 3-board) is its own folder under `hardware/` and + its own `[[boards]]` entry. +- Generated output (gerbers, BOMs, production zips, PDFs, plots) is built by CI + and attached to the release; it is not committed. +- Vendor datasheets go to `docs/datasheets/`, not the repository root. +- Third-party code is a git submodule in `external/` and is not edited here. +- IDE build output and tool caches (`Debug/`, `__pycache__/`, `.claude/`, + KiCad backups) stay out; `.gitignore` covers them. + +## proplan.toml + +proplan reads this file and the image it names, nothing else of the +repository's content: at the default branch for the Code tab, and at a stage's +tagged commit for the stage's card (so the card shows the product as it was at +that tag). Every key is optional. + +```toml +schema = 1 # 1; a newer schema is refused + +[product] +name = "papir" # default: the repository's name +image = "assets/product.png" # PNG, JPEG or WebP, at most 5 MB; none when left out + +[[boards]] # one per KiCad project, as many as needed +name = "papir" # default: the folder's last part +path = "hardware/papir" # required + +[paths] # each default: the folder of the same name +firmware = "firmware" +software = "software" +mech = "mech" +sim = "sim" +test = "test" +docs = "docs" +external = "external" +``` + +Paths are relative to the repository root (no leading `/`, no `..`). A board, +a path written under `[paths]` or the image that does not exist is reported on +the Code tab ("proplan.toml: missing ..."); a path +left out that does not exist is simply not shown. Unknown keys are ignored. + +## Adopting the layout in an existing repository + +An existing repository does not have to move anything: a `proplan.toml` that +names the current folders is enough, and history and open work stay as they +are. Moving folders to the template's names can follow later. + +papir (KiCad project in `papir/`, firmware in `code/`): + +```toml +[[boards]] +name = "papir" +path = "papir" + +[paths] +firmware = "code" +software = "pirnet" +mech = "mech" +docs = "docs" +``` + +LVSolarBuck (the current board in `kicad48V-R/LVSolarBuck`, firmware in `code64/`): + +```toml +[product] +image = "housing.png" + +[[boards]] +name = "LVSolarBuck" +path = "kicad48V-R/LVSolarBuck" + +[paths] +firmware = "code64" +sim = "ltspice" +test = "testing" +docs = "docs" +``` + +PowerModule (three board variants): + +```toml +[product] +image = "images/render-display.png" + +[[boards]] +name = "PowerModule" +path = "kicad/PowerModule" + +[[boards]] +name = "PowerModule48" +path = "kicad/PowerModule48" + +[[boards]] +name = "PowerModule48PD" +path = "kicad/PowerModule48PD" + +[paths] +firmware = "code" +software = "tools" +sim = "ltspice" +test = "testing" +docs = "tex" +external = "external" +``` + +## CI + +- `.gitea/workflows/kibot.yml`: on a push that touches `hardware/`, KiBot runs + ERC and DRC and builds schematic PDF, gerbers, drill files, pick and place + and BOM for every board (`hardware/*/*.kicad_pro`); the outputs are kept as a + workflow artifact. +- `.gitea/workflows/release.yml`: on a tag `v*`, the same outputs are zipped + per board and attached to the tag's release (created when missing). The + Actions token must be allowed to write releases. +- `.gitea/workflows/docgen.yml`: with a `docs/input.md` (typecad-docgen front + matter, as in PowerModule), builds the fabrication document of the first + board and pushes it to the `docu` branch. + +All three use the runner label `kicad10_auto` (as LVSolarBuck). They were +adapted from LVSolarBuck and PowerModule and run for the first time when the +first board is committed and tagged; check that first run. diff --git a/assets/README.md b/assets/README.md new file mode 100644 index 0000000..70cbbae --- /dev/null +++ b/assets/README.md @@ -0,0 +1,4 @@ +# Assets + +`product.png` is the product image proplan shows (PNG, JPEG or WebP, at most +5 MB). Renders and photos for documents go here too. diff --git a/assets/product.png b/assets/product.png new file mode 100644 index 0000000000000000000000000000000000000000..3d8934d702122b3110462b9d69ee0dcb8bb386b0 GIT binary patch literal 15925 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 DF0Q2) literal 0 HcmV?d00001 diff --git a/docs/README.md b/docs/README.md new file mode 100644 index 0000000..951fb52 --- /dev/null +++ b/docs/README.md @@ -0,0 +1,5 @@ +# Documentation + +Datasheets of the parts in `docs/datasheets/`, LaTeX sources in `docs/tex/`. +A `docs/input.md` (typecad-docgen front matter) turns on the fabrication +document workflow. diff --git a/docs/datasheets/README.md b/docs/datasheets/README.md new file mode 100644 index 0000000..80d1205 --- /dev/null +++ b/docs/datasheets/README.md @@ -0,0 +1,4 @@ +# Datasheets + +Vendor datasheets and application notes (PDF), named after the part, for +example `stm32c542-datasheet.pdf`. diff --git a/docs/tex/README.md b/docs/tex/README.md new file mode 100644 index 0000000..b0dfbad --- /dev/null +++ b/docs/tex/README.md @@ -0,0 +1,3 @@ +# LaTeX sources + +Sources of the developer documentation. diff --git a/external/README.md b/external/README.md new file mode 100644 index 0000000..e0b2801 --- /dev/null +++ b/external/README.md @@ -0,0 +1,5 @@ +# External code + +Third-party code as git submodules, never edited here, for example: + + git submodule add https://github.com/STMicroelectronics/stm32-mw-usbpd-core external/stm32-mw-usbpd-core diff --git a/firmware/README.md b/firmware/README.md new file mode 100644 index 0000000..ac3e798 --- /dev/null +++ b/firmware/README.md @@ -0,0 +1,7 @@ +# Firmware + +MCU code, one folder per target (an STM32CubeIDE or CMake project each), for +example `firmware/main-mcu/`. Drivers shared by the targets go to +`firmware/lib/`; third-party stacks (HAL, USB-PD middleware) are submodules in +`external/`. IDE build folders (`Debug/`, `Release/`, `build/`) are not +committed. diff --git a/firmware/lib/README.md b/firmware/lib/README.md new file mode 100644 index 0000000..cc6d0f9 --- /dev/null +++ b/firmware/lib/README.md @@ -0,0 +1,3 @@ +# Shared firmware code + +Drivers and modules used by more than one firmware target. diff --git a/hardware/$REPO_NAME/README.md b/hardware/$REPO_NAME/README.md new file mode 100644 index 0000000..9ddbd4f --- /dev/null +++ b/hardware/$REPO_NAME/README.md @@ -0,0 +1,11 @@ +# $REPO_NAME board + +The KiCad project of $REPO_NAME lives here: create it with KiCad (File, New +Project) as `hardware/$REPO_NAME/$REPO_NAME.kicad_pro`. + +- A revision of this board is a git tag (`v0.1`), not a copy of this folder. +- A real variant built next to it (48 V, 2-board) gets its own folder under + `hardware/` and its own `[[boards]]` entry in `proplan.toml`. +- Shared symbols, footprints and 3D models go to `hardware/lib/`. +- Gerbers, BOMs and PDFs are built by CI (`.gitea/workflows/kibot.yml`); do not + commit them. diff --git a/hardware/lib/README.md b/hardware/lib/README.md new file mode 100644 index 0000000..8a5ac15 --- /dev/null +++ b/hardware/lib/README.md @@ -0,0 +1,6 @@ +# Shared KiCad libraries + +Symbols (`*.kicad_sym`), footprints (`*.pretty/`) and 3D models (`3dmodels/`) +used by more than one board. Add them to the board projects as project +libraries with a path relative to the project (KiCad's KIPRJMOD variable), so +the repository works on every computer. diff --git a/kibot.yaml b/kibot.yaml new file mode 100644 index 0000000..824b43b --- /dev/null +++ b/kibot.yaml @@ -0,0 +1,78 @@ +# KiBot outputs for every board; the workflows run KiBot inside each board +# folder (hardware//). Adapted from LVSolarBuck's kibot.yaml. +kibot: + version: 1 + +preflight: + erc: + warnings_as_errors: false + dont_stop: true + drc: + warnings_as_errors: false + dont_stop: true + check_zone_fills: true + +outputs: + - name: schematic_pdf + comment: Schematic PDF + type: pdf_sch_print + dir: Schematic + + - name: gerbers + comment: Gerber files + type: gerber + dir: Gerbers + options: + exclude_edge_layer: true + exclude_pads_from_silkscreen: true + plot_footprint_refs: true + plot_footprint_values: false + create_gerber_job_file: true + subtract_mask_from_silk: true + layers: + - copper + - F.Paste + - B.Paste + - F.Silkscreen + - B.Silkscreen + - F.Mask + - B.Mask + - Edge.Cuts + + - name: drill + comment: Drill files + type: excellon + dir: Gerbers + options: + metric_units: true + pth_and_npth_single_file: false + + - name: position + comment: Pick and place + type: position + dir: Assembly + options: + format: CSV + units: millimeters + separate_files_for_front_and_back: true + only_smd: false + + - name: bom + comment: Bill of materials + type: bom + dir: BoM + options: + format: CSV + + - name: fabrication + comment: Fabrication package + type: compress + dir: . + options: + output: '%f-fabrication.%x' + format: ZIP + files: + - from_output: gerbers + dest: / + - from_output: drill + dest: / diff --git a/mech/README.md b/mech/README.md new file mode 100644 index 0000000..2fe45f3 --- /dev/null +++ b/mech/README.md @@ -0,0 +1,4 @@ +# Mechanics + +FreeCAD sources (`*.FCStd`) and STEP exports of enclosures, holders and +heatsinks. FreeCAD backups (`*.FCBak`, `*.FCStd1`) are not committed. diff --git a/proplan.toml b/proplan.toml new file mode 100644 index 0000000..3221895 --- /dev/null +++ b/proplan.toml @@ -0,0 +1,24 @@ +# proplan.toml: what proplan reads from this repository. The Code tab shows +# whether the folders named here exist, the product image appears on the +# project and on each prototype stage. Every key is optional; an omitted path +# means the folder of the same name. TEMPLATE.md has the full reference. +schema = 1 + +[product] +name = "$REPO_NAME" +image = "assets/product.png" + +# One entry per KiCad project. A real variant (48 V, 2-board) is another +# entry with its own folder; a revision is a git tag, never a folder copy. +[[boards]] +name = "$REPO_NAME" +path = "hardware/$REPO_NAME" + +[paths] +firmware = "firmware" +software = "software" +mech = "mech" +sim = "sim" +test = "test" +docs = "docs" +external = "external" diff --git a/sim/README.md b/sim/README.md new file mode 100644 index 0000000..f93381d --- /dev/null +++ b/sim/README.md @@ -0,0 +1,4 @@ +# Simulation and calculations + +Circuit simulations (LTspice, ngspice) and calculation scripts or notebooks +(compensator, heatsink, inductor). Large generated results are not committed. diff --git a/software/README.md b/software/README.md new file mode 100644 index 0000000..8a71fb4 --- /dev/null +++ b/software/README.md @@ -0,0 +1,5 @@ +# Software + +Host tools and apps (diagnostics, configuration, test rigs), one folder per +tool, for example `software/diag/` with its own README and pyproject.toml or +Cargo.toml. diff --git a/test/README.md b/test/README.md new file mode 100644 index 0000000..d8e822a --- /dev/null +++ b/test/README.md @@ -0,0 +1,5 @@ +# Bench results + +One folder per prototype stage: `test/v0.1/`, `test/v0.2/`, with photos, +scope captures, measurements and short notes. Attach the key results to the +stage in proplan too.