Merge pull request 'removing_github_actions' (#3) from removing_github_actions into main

Reviewed-on: #3
This commit is contained in:
2026-01-22 17:44:08 -08:00
28 changed files with 2117 additions and 1404 deletions

41
.github/rename.py vendored
View File

@@ -1,41 +0,0 @@
from pathlib import Path
import os
import sys
from ruamel.yaml import YAML
# renames the main project in the template dir and in the project settings
def rename_project(project_name, new_name = "template"):
"""renames the kicad project"""
project_path = str(Path(f"Hardware/{project_name}_PROJECT"))
files = os.listdir(project_path)
for index, file in enumerate(files):
print(file)
os.rename(os.path.join(project_path, file), os.path.join(project_path, file.replace(project_name, new_name)))
os.rename(project_path, project_path.replace(project_name, new_name))
pcb_path = str(Path(f"Hardware/{project_name}_PCB"))
os.rename(pcb_path, pcb_path.replace(project_name, new_name))
doc_path = str(Path(f"Hardware/{project_name}_DOCS"))
os.rename(doc_path, doc_path.replace(project_name, new_name))
def main():
yaml : YAML = YAML()
with open(Path("project_settings.yaml"), "r") as yaml_file:
settings = yaml.load(yaml_file)
print(f"{settings['project_name']=}")
print(f"{settings=}")
rename_project(settings["project_name"], sys.argv[1])
settings["project_name"] = sys.argv[1]
settings["needs_setup"] = False
# have to just print it out a rewrite over .project_settings because this guy
# is dumb and doesnt just let you write these out to string
with open(Path("project_settings.yaml"), "w", encoding=("utf-8")) as file:
yaml.dump(settings, file)
if __name__ == "__main__":
main()

View File

@@ -1,46 +0,0 @@
# look it would be piss easy to just keep it as a CSV but we can post process to add cool things like cost to each of the parts
import csv
import sys
import chevron
import datetime
from pprint import pprint
file_path_delimter = "\\" if sys.platform == "win32" else "/"
def load_bom(filename : str) -> dict:
out_dict = {
"parts" : [],
"time" : str(datetime.datetime.now().time()),
"date" : str(datetime.datetime.now().date().strftime("%d-%m-%Y")),
"total_cost" : 0,
"total_parts" : 0,
"project_name" : filename.strip(".csv").strip("bom").split(file_path_delimter)[-1]
}
with open(filename, "r") as csv_file:
for row in csv.DictReader(csv_file):
part_cost = 0
out_dict["total_parts"] += 1
out_dict["parts"].append(
{
"Reference" : row["Refs"],
"Value" : row["Value"],
"Quantity" : row["Qty"],
"part_number" : row["Footprint"],
"cost" : part_cost, # add some API call somewhere here
}
)
return out_dict
def main():
report_hash = load_bom(sys.argv[1])
# pprint(report_hash)
with open(sys.argv[2], "r") as txt:
out = chevron.render(txt.read(), report_hash)
with open(sys.argv[3], "w") as md:
md.write(out)
if __name__ == "__main__":
main()

View File

@@ -1,57 +0,0 @@
from violation import Violation
import datetime
import json
from pprint import pprint
def process_violation_list(drc_json : dict, list_name : str) -> None:
if list_name in drc_json.keys():
unconnected_items_errors = []
unconnected_items_warns = []
number_of_errors = 0
number_of_warns = 0
for violation in drc_json[list_name]:
v = Violation(violation, "drc")
if (v.violation_type == "error"):
unconnected_items_errors.append(v)
number_of_errors += 1
if (v.violation_type == "warn"):
unconnected_items_warns.append(v)
number_of_warns += 1
drc_json[list_name] = {
"errors" : unconnected_items_errors,
"warns" : unconnected_items_warns,
"number_of_errors" : number_of_errors,
"number_of_warns" : number_of_warns,
}
else:
drc_json.setdefault(list_name, {})
drc_json[list_name].setdefault("number_of_errors", 0)
drc_json[list_name].setdefault("number_of_warns", 0)
def process_report(report : str) -> dict:
out_dict : dict = json.loads(report)
number_of_errors = 0;
number_of_errors = 0;
process_violation_list(out_dict, "unconnected_items")
process_violation_list(out_dict, "violations")
process_violation_list(out_dict, "schematic_parity")
out_dict.setdefault(
"total_errors",
out_dict["unconnected_items"]["number_of_errors"] +
out_dict["violations"]["number_of_errors"] +
out_dict["schematic_parity"]["number_of_errors"]
)
out_dict.setdefault(
"total_warns",
out_dict["unconnected_items"]["number_of_warns"] +
out_dict["violations"]["number_of_warns"] +
out_dict["schematic_parity"]["number_of_warns"]
)
return out_dict

View File

@@ -1,53 +0,0 @@
from violation import Violation
import datetime
import json
class Sheet:
def __init__(self, json_obj : dict) -> None:
self.name : str = json_obj["path"]
self.name_md : str = self.name.replace(" ", "-")
self.number_of_errors : int = 0
self.number_of_warns : int = 0
self.errors : list[Violation] = list()
self.warns : list[Violation] = list()
for violation in json_obj["violations"]:
v = Violation(violation, "erc")
if (v.violation_type == "error"):
self.errors.append(v)
self.number_of_errors += 1
if (v.violation_type == "warn"):
self.warns.append(v)
self.number_of_warns += 1
def to_dict(self) -> dict:
out_dict = self.__dict__
errors_strings = []
warns_strings = []
for error in out_dict["errors"]:
errors_strings.append(error.__dict__)
out_dict["errors"] = errors_strings
for warn in out_dict["warns"]:
warns_strings.append(warn.__dict__)
out_dict["warns"] = warns_strings
return out_dict
def process_report(report : str) -> dict:
out_dict : dict = json.loads(report)
sheets = [Sheet(sheet) for sheet in out_dict["sheets"]]
out_dict["sheets"] = [sheet.to_dict() for sheet in sheets]
out_dict.setdefault(
"total_errors",
sum(sheet.number_of_errors for sheet in sheets)
)
out_dict.setdefault(
"total_warns",
sum(sheet.number_of_warns for sheet in sheets)
)
return out_dict

View File

@@ -1,50 +0,0 @@
# usage: python process_json_reports.py report.json template.mustache outfile.md project_name
import chevron
import sys
import datetime
import json
import process_erc_json
import process_drc_json
from pprint import pprint
def load_report(filename : str, project_name : str) -> dict:
out_dict : dict = {}
with open(filename, "r") as js:
if ("erc" in filename.lower()):
out_dict = process_erc_json.process_report(js.read())
if ("drc" in filename.lower()):
out_dict = process_drc_json.process_report(js.read())
out_dict.setdefault(
"time",
str(datetime.datetime.now().time())
)
out_dict.setdefault(
"date",
str(datetime.datetime.now().date().strftime("%d-%m-%Y"))
)
out_dict.setdefault(
"project_name",
project_name
)
out_dict.setdefault(
"has_violations",
True if out_dict["total_warns"] + out_dict["total_errors"] else None
)
return out_dict
def main():
report_hash = load_report(sys.argv[1], sys.argv[4])
# pprint(report_hash)
with open(sys.argv[2], "r") as txt:
out = chevron.render(txt.read(), report_hash)
with open(sys.argv[3], "w") as md:
md.write(out)
if __name__ == "__main__":
main()

View File

@@ -1,94 +0,0 @@
import chevron
import sys
import datetime
import json
import glob
from pathlib import Path
from pprint import pprint
# erc
# {
# "project_name" : "string",
# "passing_erc" : "bool",
# "erc_summary_link" : "link",
# }
# drc
# {
# "project_name" : "string",
# "passing_drc" : "bool",
# "drc_summary_link" : "link",
# }
# project
# {
# "project_name" : "string",
# "project_link" : "link",
# "schematic_link" : "link",
# "gerber_link" : "link",
# "bom_report_link" : "link",
# "bom_csv_link" : "link"
# }
EXTRAS_FILENAME = "readme_extras.json"
def load_json_file(filename : str) -> dict:
with open(Path(f"{filename}/{filename}"), "r") as js:
return json.loads(js.read())
def create_hash(filenames : list[str]) -> dict:
report_outs = filenames
report_outs.remove("readme_extras.json")
extras = {}
with open("readme_extras.json", "r") as js:
extras = json.loads(js.read())
reports_dicts : list[dict] = []
for report_name in report_outs:
reports_dicts.append(load_json_file(report_name))
readme_hash = {
**extras,
"projects" : [],
"did_error" : False,
"multiple_projects" : None
}
for report in reports_dicts:
for project in readme_hash["projects"]:
if project["project_name"] == report["project_name"]:
for key in report.keys():
project.setdefault(key, report[key])
break
else:
readme_hash["projects"].append(report)
pprint(readme_hash)
for project in readme_hash["projects"]:
readme_hash["did_error"] |= not project["passing_erc"]
readme_hash["did_error"] |= not project["passing_drc"]
project.setdefault("passing_erc_emoji", "" if project["passing_erc"] == "true" else "")
project.setdefault("passing_drc_emoji", "" if project["passing_drc"] == "true" else "")
readme_hash["multiple_projects"] = True if len(readme_hash["projects"]) > 1 else None
pprint(readme_hash)
return readme_hash
def main():
print(sys.argv)
readme_template, *args = sys.argv[1:]
report_hash = create_hash(args)
with open(readme_template, "r") as txt:
out = chevron.render(txt.read(), report_hash)
with open("README.md", "w") as md:
md.write(out)
if __name__ == "__main__":
main()

View File

@@ -1,3 +0,0 @@
chevron
pathlib
ruamel.yaml

View File

@@ -1,18 +0,0 @@
class Violation:
def __init__(self, violation : dict, violation_report_type : str = ["erc", "drc"]) -> None:
self.violation_type : str = \
"warn" if violation["severity"] == "warning" else "error"
self.name : str = violation["description"]
self.content : str = ""
# this violation_report_type purely exists because of a bug
# in kicads json output format where json output on erc reports
# the position in decimeters
for item in violation["items"]:
item_string = item["description"]
x : float = float(item["pos"]["x"]) * (100.0 if (violation_report_type == "erc") else 1.0)
y : float = float(item["pos"]["y"]) * (100.0 if (violation_report_type == "erc") else 1.0)
# print(f"{x=}")
item_string += f" at [x = {x:.4}mm, y = {y:.4}mm]\n"
self.content += item_string

View File

@@ -1,29 +0,0 @@
{{! hash schema }}
{{! {
"project_name" : "the name of the project",
"time" : "the name of the project",
"date" : "the name of the project",
"total_parts" : "number",
"total_cost" : "number",
"parts" : [
{
"Reference" : "part_reference" ,
"Value" : "the value of the part" ,
"Quantity" : "number" ,
"part_number" : "the part number" ,
"cost" : "number"
}
]
} }}
# 📄 BOM for {{project_name}} 📄
report created at {{time}} on {{date}}.
{{project_name}} has a total of {{total_parts}} parts with a cost of ${{total_cost}}.
| Reference | Value | Quantity | part number | cost |
| --------- | ----- | -------- | ----------- | ---- |
{{#parts}}
| {{Reference}} | {{Value}} | {{Quantity}} | {{part_number}} | ${{cost}} |
{{/parts}}
| | total | {{total_parts}} | total | ${{total_cost}} |

View File

@@ -1,133 +0,0 @@
{{! hash schema }}
{{! {
"date" : "the date of creation",
"time" : "the time of creation",
"total_warns" : "number",
"total_errors" : "number",
"has_violations" : "flag to say if the project has a violation",
"violations" : {
"number_of_errors" : "number",
"number_of_warns" : "number",
"warns" : [
{
"name" : "string",
"content" : "string"
}
],
"errors" : [
{
"name" : "string",
"content" : "string"
}
]
},
"unconnected_items" : {
"number_of_errors" : "number",
"number_of_warns" : "number",
"warns" : [
{
"name" : "string",
"content" : "string"
}
],
"errors" : [
{
"name" : "string",
"content" : "string"
}
]
},
"schematic_parity" :{
"number_of_errors" : "number",
"number_of_warns" : "number",
"warns" : [
{
"name" : "string",
"content" : "string"
}
],
"errors" : [
{
"name" : "string",
"content" : "string"
}
]
}
} }}
# 📟 {{project_name}} DRC report 📟
report created at {{time}} 🕧 on {{date}} 🗓️.
the design rule check found:
- {{total_errors}} errors in your design 😱
- {{total_warns}} warns in your design 🫨
{{#has_violations}}
number of errors and warns breakdown per sheet:
| error type | number of errors 🔴 | number of warns 🟠 |
| ----------------------------------------- | -------------------------------------- | ------------------------------------- |
| [violations](#violations) ❌ | {{violations.number_of_errors}} | {{violations.number_of_warns}} |
| [unconnected items](#unconnected-items) ⛓️‍💥| {{unconnected_items.number_of_errors}} | {{unconnected_items.number_of_warns}} |
| [schematic parity](#schematic-parity) 🔗 | {{schematic_parity.number_of_errors}} | {{schematic_parity.number_of_warns}} |
| total | {{total_errors}} | {{total_warns}} |
below is a more in-depth breakdown of the errors and warns per error type.
note you should only use this for quickly checking that the project
you uploaded has no error or warn. YOU SHOULD *NOT* use this to actually
run the drc in kicad so you can see where is erroring.
# violations
## errors : {{violations.number_of_errors}}
{{#violations.errors}}
### {{name}}
{{content}}
{{loction}}
{{/violations.errors}}
## warns : {{violations.number_of_warns}}
{{#violations.warns}}
### {{name}}
{{content}}
{{loction}}
{{/violations.warns}}
# unconnected items
## errors : {{unconnected_items.number_of_errors}}
{{#unconnected_items.errors}}
### {{name}}
{{content}}
{{loction}}
{{/unconnected_items.errors}}
## warns : {{unconnected_items.number_of_warns}}
{{#unconnected_items.warns}}
### {{name}}
{{content}}
{{loction}}
{{/unconnected_items.warns}}
# schematic parity
## errors : {{schematic_parity.number_of_errors}}
{{#schematic_parity.errors}}
### {{name}}
{{content}}
{{loction}}
{{/schematic_parity.errors}}
## warns : {{schematic_parity.number_of_warns}}
{{#schematic_parity.warns}}
### {{name}}
{{content}}
{{loction}}
{{/schematic_parity.warns}}
{{/has_violations}}
{{^has_violations}}
the design had no errors or warns, good job. ✅✅
{{/has_violations}}

View File

@@ -1,73 +0,0 @@
{{! hash schema }}
{{! {
"date" : "the date of creation",
"time" : "the time of creation",
"total_warns" : "number",
"total_errors" : "number",
"has_violations" : "flag to say if the project has a violation",
"sheets" : [
{
"name" : "string",
"name_md" : "just name but i replaced the spaces with hyphens",
"number_of_errors" : "number",
"number_of_warns" : "number",
"warns" : [
{
"name" : "string",
"content" : "string"
}
],
"errors" : [
{
"name" : "string",
"content" : "string"
}
]
}
]
} }}
# ⚡{{project_name}} ERC report ⚡
report created at {{time}} 🕧 on {{date}} 🗓️.
the electronic rules check found:
- {{total_errors}} errors in your design 😱
- {{total_warns}} warns in your design 🫨
{{#has_violations}}
number of errors and warns breakdown per sheet:
| sheet name 📄| number of errors 🔴 | number of warns 🟠 |
| ---------- | ---------------- | --------------- |
{{#sheets}}
| [{{name}}](#{{name_md}}) | {{number_of_errors}} | {{number_of_warns}} |
{{/sheets}}
| total | {{total_errors}}| {{total_warns}}|
below is a more in-depth breakdown of the errors and warn per sheets.
note you should only use this for quickly checking that the project
you uploaded has no error or warn. YOU SHOULD *NOT* use this to actually
run your ERC in kicad so you can see where is erroring.
{{#sheets}}
# {{name}}
## errors : {{number_of_errors}}
{{#errors}}
### {{name}}
{{content}}
{{/errors}}
## warns : {{number_of_warns}}
{{#warns}}
### {{name}}
{{content}}
{{/warns}}
{{/sheets}}
{{/has_violations}}
{{^has_violations}}
the design had no errors or warns, good job. ✅✅
{{/has_violations}}

View File

@@ -1,5 +0,0 @@
# how the templates work
templates work by using a json file to fill in the templating spots. for more information on the templates checkout [mustache templates](https://mustache.github.io/). these templates use a json file format as what they call a "hash" to fill out the templates. the hashs for each of these templates are layout at the top of each of the `.mustache` files in a comment. These are also the hashes outputted by the processing scripts. usages for these scripts are at the top of the file.
if any schema says bool this actually means the value is either something or either doesnt exist/null.

View File

@@ -1,153 +0,0 @@
{{! hash schema }}
{{! {
"badge" : "the ci badge",
"lastest_action_run_link" : "link to the lastest action",
"did_error" : "to check if errors occured in the pipeline",
"title" : "the tiltle of the project, can be set in project_settings or it will use the repo name",
"multiple_projects" : "bool",
"projects" : [
{
"project_name" : "string",
"project_link" : "link",
"passing_erc" : "bool",
"passing_erc_emoji" : "string",
"erc_summary_link" : "link",
"passing_drc" : "bool",
"passing_drc_emoji" : "string",
"drc_summary_link" : "link",
"gerber_link" : "link",
"schematic_link" : "link",
"bom_report_link" : "link",
"bom_csv_link" : "link"
}
]
} }}
# kicad project {{title}}
{{badge}}
{{! [![.github/workflows/main.yaml](https://github.com/sirlilpanda/kicad-project-template/actions/workflows/main.yaml/badge.svg)](https://github.com/sirlilpanda/kicad-project-template/actions/workflows/main.yaml) }}
a cool table showing the workflow of all the kicad projects.
| project_name | DRC | ERC |
| ------------ | --- | --- |
{{#projects}}
| {{project_name}} | [{{passing_erc_emoji}}]({{erc_summary_link}})| [{{passing_drc_emoji}}]({{drc_summary_link}}) |
{{/projects}}
for a quick guide check [project setup](#project-setup)
This is a simple project template for new kicad projects. This template has some basic setup already completed such as workflows for auto creating all the things you forget when creating a kicad project such as:
{{^multiple_projects}}
{{#projects}}
- [gerbers]({{gerber_link}})
- [bom]({{bom_report_link}})
- [schematic pdf]({{schematic_link}})
{{/projects}}
{{/multiple_projects}}
{{#multiple_projects}}
| project_name | schematic | bom | bom report | gerbers |
| ------------ | --------- | --- | ---------- | ------- |
{{#projects}}
| [{{project_name}}]({{project_link}}) | [{{project_name}}_schematic.pdf]({{schematic_link}}) | [{{project_name}}_bill_of_materials.csv]({{bom_csv_link}}) | [{{project_name}}_bom_report.md]({{bom_report_link}}) | [{{project_name}}_grbr.zip]({{gerber_link}}) |
{{/projects}}
{{/multiple_projects}}
This workflow will also run the design rules check on the PCB and schematic to ensure that you upload a working PCB. These reports are uploaded as summaries within the github [actions tab]({{lastest_action_run_link}}). This template has a simple schematic PCB in it (because DRC fails on an empty PCB). Shown below is the example PCB.
![example pcb with battery diode and resistor](res/image.png)
besides from that the project also has:
- common predefined trace widths
- smallest vias size [JLCPBC allows](https://jlcpcb.com/capabilities/Capabilities#Drilling)
- custom net colours in the schematic editor
- `red` for +V
- `blue` for -V
- `grey` for ground
to create a repo from this template follow this [guide](https://docs.github.com/en/repositories/creating-and-managing-repositories/creating-a-repository-from-a-template)
contained in this template are:
---
- `.github/` : all files relating to github actions and other admin see [here](https://docs.github.com/en/communities/setting-up-your-project-for-healthy-contributions) for more example of what can be placed in it
- `report_processing` : where the python scripts are stored for processing the json report data from kicad
- `report_templates` : where the template for said reports are stored
- `workflows/` : this is where the github actions are kept
- `main.yaml` : the main github action that will auto generate all files required and run DRC and ERC
- `rename.py` : the script for renaming the project
- `hardware/` : this is where the kicad projects live note this can be changed
- `docs/` : this is where the generate docs are placed by default
- `BOM/` : where the bill of materials and price breakdown are kept
- `bill_of_materials.csv`: the auto generated bom for the kicad project
- `bom_report.md` : a report for the bill of materials
- `template_schematic.pdf` : the schematic for the kicad project, auto generated by the github action
- `pcbs/` : this is where the auto generated gerbers for the kicad project are stored
- `res/` : where resources are stored for the README
- `.gitignore`: a slightly modified gitignore from the [standard one](https://github.com/github/gitignore/blob/main/KiCad.gitignore)
- `project_settings.yaml` : where the settings for this project is stored
- `README.md` : this file, suggest you change this one creating your project
## project settings
there are currently very few project settings that can be changed (will will be change in the future) these are:
| setting | description |
| --------------------------- | ----------------------------------------------------------------- |
| has_been_set_up | a flag to tell the setup action if the project has been set up |
| project_name | the name of the project, this will be set to the name of the repo |
| production_formats | the output production format for the PCBs |
| dynamic_read_me | allow the readme to be updated using the given template |
| bom_template_path | the template used to write the bom report files |
| erc_report_template_path | the template used to write the erc report files |
| drc_report_template_path | the template used to write the drc report files |
| readme_template_path | the template used to write projects readme |
| schematic_output_name | the name suffix of the generated schematics |
| bom_csv_output_name | the name suffix of the generated bom csv file |
| bom_report_output_name | the name suffix of the generated bom report |
| production_file_output_name | the name suffix of the generated production file |
| schematic_output_path | the output path of the generated schematics files |
| bom_csv_output_path | the output path of the generated bom csv file |
| bom_report_output_path | the output path of the generated bom report |
| production_file_output_path | the output path of the generated production file |
## project setup
### creating a new repo with the template
creating a new template from a repo is simple:
1. click on the button in the top right hand corner called `use this template`
![alt text](res/image-5.png)
2. when the drop down menu appears click on `create a new repository`
![alt text](res/image-6.png)
3. once you click you will be brought to this page, note that the repo name you choose here will be the name that you kicad project is called.
![alt text](res/image-7.png)
after these steps you then need to configure the repo settings to do their magic see [configuring repo settings](#configuring-repo-settings) for what to do next.
### configuring repo settings
once you have created a new repo with the template, you ill have to configure the github action settings. this is because you will get an error that looks something along these lines:
![alt text](res/image-4.png)
where the action can not commit the changes due to not having permissions follow these steps:
1. open the repo setting
![alt text](res/image-1.png)
2. then head in to actions : General
![alt text](res/image-2.png)
3. then scroll down to workflow permissions and ensure that both
`Read and write permissions` and `Allow GitHub Actions to create and approve pull requests` are ticked as seen below
![alt text](res/image-3.png)
this should fix the problem if not, go harass stack overflow they need it
Once all of these steps have been followed the workflow should be passing, however the `README.md` will only update on the next push request.
## editing the readme
As this repo can and will automatically update the repo corresponding to the given readme template. If you dont want to use this you can always disable this by setting the `dynamic_read_me` to `false`. but if you want some very cool features like auto updating tables to show what projects are passing the rules check or simple links to parts of your directory. then have a look at the template readme and learn [mustache](https://mustache.github.io/)
## improvements

View File

@@ -1,539 +0,0 @@
on:
push:
branches: [main, master, workflow_testing]
concurrency:
group: ${{ github.workflow }}-${{ github.ref }}
cancel-in-progress: true
env:
ERC_JOB_NAME : "⚡ERC report⚡"
DRC_JOB_NAME : "📟 DRC report 📟"
jobs:
setup_new_project: # this job only exists for project creation
runs-on: ubuntu-latest
name: set up project
steps:
- name: Checkout
uses: actions/checkout@v4
# reads the project_setting.yaml file allowing you to access it with steps.id.outputs.[key]
- name: read yaml file
uses: juliojimenez/yamler@v1.1.0
id: yaml
with:
yaml-file: ${{ github.workspace }}/project_settings.yaml
- name: check setup
run: |
echo ${{steps.yaml.outputs.needs_setup}}
- name: Setting up Python and chevron to processes failed reports
# workflows really need some more work done on them
if: ${{ !cancelled() && steps.yaml.outputs.needs_setup == 'true' && github.repository != 'sirlilpanda/kicad-project-template'}}
uses: actions/setup-python@v5
with:
python-version: '3.10'
cache: 'pip'
- name: installing requirements
if: ${{ !cancelled() && steps.yaml.outputs.needs_setup == 'true' && github.repository != 'sirlilpanda/kicad-project-template'}}
run: pip install -r ${{ github.workspace }}/.github/report_processing/requirements.txt
- name: rename project if setup has not been completed
if: ${{ !cancelled() && steps.yaml.outputs.needs_setup == 'true' && github.repository != 'sirlilpanda/kicad-project-template'}}
run: python ${{ github.workspace }}/.github/rename.py ${{github.event.repository.name}}
- name: commit production files
if: ${{ !cancelled() && steps.yaml.outputs.needs_setup == 'true' && github.repository != 'sirlilpanda/kicad-project-template'}}
uses: EndBug/add-and-commit@v9
with:
default_author: github_actions
message: 'setup project'
push: true
add: "."
setup_matrixs:
outputs:
projects: ${{ steps.projects.outputs.projects }}
runs-on: ubuntu-latest
name: matrix setup 🗓️
needs: setup_new_project
steps:
- name: Checkout
uses: actions/checkout@v4
- name: Setting up Python
# workflows really need some more work done on them
uses: actions/setup-python@v5
with:
python-version: '3.10'
cache: 'pip'
- name: installing requirements
run: pip install pyyaml
- name: creating list start
run:
echo -n "projects=[" >> temp.txt
# this find commad outputs path1,path2,path3 with out the .kicad_pro ext
# .kicad_pro ext is removed because the erc and drc steps want either a
# .kicad_sch or .kicad_pcb file it also makes it easier to name files
# with the project name
# this output will look like
# projects=["path/projet_name", "path/projet_name2", ...]
- name: get kicad project names
run:
find . -type f -name "*.kicad_pro" -exec sh -c 'echo -n "\"${0%.kicad_pro}\","' {} \; | sed 's/.\{1\}$//' >> temp.txt
- name: creating list end
run:
echo "]" >> temp.txt
- name: list output
run:
cat temp.txt
- name: creating list end
id: projects
run:
cat temp.txt >> "$GITHUB_OUTPUT"
# basename is used here to remove the rest of the path from the find
#
DRC:
runs-on: ubuntu-latest
name: "📟 DRC report 📟"
needs: setup_matrixs
strategy:
matrix:
project_path: ${{ fromJSON(needs.setup_matrixs.outputs.projects) }}
steps:
- name: check matrix
run: basename ${{ matrix.project_path }}
- name: setting env
run:
echo "PROJECT_NAME=$(basename ${{ matrix.project_path }})" >> $GITHUB_ENV
- name: Checkout
uses: actions/checkout@v4
- name: read-yaml-file
uses: juliojimenez/yamler@v1.1.0
id: yaml
with:
yaml-file: ${{ github.workspace }}/project_settings.yaml
- name: Setting up Python and chevron to processes reports
# workflows really need some more work done on them
uses: actions/setup-python@v5
with:
python-version: '3.10'
cache: 'pip'
- name: installing requirements
run: pip install -r ${{ github.workspace }}/.github/report_processing/requirements.txt
- name: Run KiCad DRC
id: drc
uses: sparkengineering/kicad-action@v4
with:
kicad_pcb: ${{ matrix.project_path }}.kicad_pcb
pcb_drc: true
report_format: json
pcb_drc_file: drc.json
- name: checking files were created
run:
ls -R
- name: creating DRC report in markdown
if: ${{ always() }}
run: python
${{ github.workspace }}/.github/report_processing/process_json_reports.py
${{ github.workspace }}/$(dirname ${{matrix.project_path}})/drc.json
${{ github.workspace }}/${{steps.yaml.outputs.drc_report_template_path}}
${{ github.workspace }}/${{ env.PROJECT_NAME }}_drc.md
${{ env.PROJECT_NAME }}
- name: upload report summary
if: ${{ always() }}
run: cat ${{ github.workspace }}/${{ env.PROJECT_NAME }}_drc.md >> $GITHUB_STEP_SUMMARY
- name: get summary url
if: ${{always()}}
id: exp
uses: pl-strflt/job-summary-url-action@v1
with:
job: "${{env.DRC_JOB_NAME}} (${{matrix.project_path}})"
- name: create files to upload
if: ${{always()}}
run: |
echo "{\"passing_drc\":\"${{steps.drc.conclusion != 'failure'}}\",\"project_name\":\"${{env.PROJECT_NAME}}\", \"drc_summary_link\":\"${{ steps.exp.outputs.job_summary_url }}\"}" >> ${{env.PROJECT_NAME}}_drc.json
- name: upload data for readme updating
if: ${{always()}}
uses: actions/upload-artifact@v4
with:
name: ${{env.PROJECT_NAME}}_drc.json
path: ${{env.PROJECT_NAME}}_drc.json
ERC:
runs-on: ubuntu-latest
name: "⚡ERC report⚡"
needs: setup_matrixs
strategy:
matrix:
project_path: ${{ fromJSON(needs.setup_matrixs.outputs.projects) }}
steps:
- name: check matrix
run: basename ${{ matrix.project_path }}
- name: setting env
run:
echo "PROJECT_NAME=$(basename ${{ matrix.project_path }})" >> $GITHUB_ENV
- name: setting env
run:
echo "PROJECT_NAME=$(basename ${{ matrix.project_path }})" >> $GITHUB_ENV
- name: Checkout
uses: actions/checkout@v4
- name: read-yaml-file
uses: juliojimenez/yamler@v1.1.0
id: yaml
with:
yaml-file: ${{ github.workspace }}/project_settings.yaml
- name: Setting up Python and chevron to processes reports
# workflows really need some more work done on them
uses: actions/setup-python@v5
with:
python-version: '3.10'
cache: 'pip'
- name: installing requirements
run: pip install -r ${{ github.workspace }}/.github/report_processing/requirements.txt
- name: Run KiCad ERC
id: erc
uses: sparkengineering/kicad-action@v4
with:
kicad_sch: ${{ matrix.project_path }}.kicad_sch
sch_erc: true
report_format: json
sch_erc_file: erc.json
- name: checking files were created
run:
ls -R
- name: creating ERC report in markdown
if: ${{ always() }}
run: python
${{ github.workspace }}/.github/report_processing/process_json_reports.py
${{ github.workspace }}/$(dirname ${{matrix.project_path}})/erc.json
${{ github.workspace }}/${{steps.yaml.outputs.erc_report_template_path}}
${{ github.workspace }}/${{ env.PROJECT_NAME }}_erc.md
${{ env.PROJECT_NAME }}
- name: upload report summary
if: ${{ always() }}
run: cat ${{ github.workspace }}/${{ env.PROJECT_NAME }}_erc.md >> $GITHUB_STEP_SUMMARY
- name: get summary url
if: ${{always()}}
id: exp
uses: pl-strflt/job-summary-url-action@v1
with:
job: "${{env.ERC_JOB_NAME}} (${{matrix.project_path}})"
- name: print summary url
if: ${{always()}}
run: echo '${{ steps.exp.outputs.job_summary_url }}'
shell: bash
- name: create files to upload
if: ${{always()}}
run: |
echo "{\"passing_erc\":\"${{steps.erc.conclusion != 'failure'}}\",\"project_name\":\"${{env.PROJECT_NAME}}\", \"erc_summary_link\":\"${{ steps.exp.outputs.job_summary_url }}\"}" >> ${{env.PROJECT_NAME}}_erc.json
- name: upload data for readme updating
if: ${{always()}}
uses: actions/upload-artifact@v4
with:
name: ${{env.PROJECT_NAME}}_erc.json
path: ${{env.PROJECT_NAME}}_erc.json
production_job:
runs-on: ubuntu-latest
name: creating production files bom sch gerbers 📂
needs: setup_matrixs
strategy:
matrix:
project_path: ${{ fromJSON(needs.setup_matrixs.outputs.projects) }}
steps:
- name: Checkout
uses: actions/checkout@v4
- name: read-yaml-file
uses: juliojimenez/yamler@v1.1.0
id: yaml
with:
yaml-file: ${{ github.workspace }}/project_settings.yaml
- name: setting env
run:
echo "PROJECT_NAME=$(basename ${{ matrix.project_path }})" >> $GITHUB_ENV
- name: setting env
run: | # | the / here is defined in the project settings
echo "schematic_file=${{env.PROJECT_NAME}}${{steps.yaml.outputs.schematic_output_name}}.pdf" >> $GITHUB_ENV
echo "bill_of_materials_file=${{env.PROJECT_NAME}}${{steps.yaml.outputs.bom_csv_output_name}}.csv" >> $GITHUB_ENV
echo "production_format_file=${{env.PROJECT_NAME}}${{steps.yaml.outputs.production_file_output_name}}.zip" >> $GITHUB_ENV
echo "bom_report_file=${{env.PROJECT_NAME}}${{steps.yaml.outputs.bom_report_output_name}}.md" >> $GITHUB_ENV
- name: checking envs
run:
echo "${{env.schematic_file}}"
echo "${{env.bill_of_materials_file}}"
echo "${{env.production_format_file}}"
echo "${{env.bom_report_file}}"
- name: setting env
run:
echo "PROJECT_NAME=$(basename ${{ matrix.project_path }})" >> $GITHUB_ENV
- name: setting env
run: | # | the / here is defined in the project settings
echo "schematic_file=${{env.PROJECT_NAME}}${{steps.yaml.outputs.schematic_output_name}}.pdf" >> $GITHUB_ENV
echo "bill_of_materials_file=${{env.PROJECT_NAME}}${{steps.yaml.outputs.bom_csv_output_name}}.csv" >> $GITHUB_ENV
echo "production_format_file=${{env.PROJECT_NAME}}${{steps.yaml.outputs.production_file_output_name}}.zip" >> $GITHUB_ENV
echo "bom_report_file=${{env.PROJECT_NAME}}${{steps.yaml.outputs.bom_report_output_name}}.md" >> $GITHUB_ENV
- name: checking envs
run:
echo "${{env.schematic_file}}"
echo "${{env.bill_of_materials_file}}"
echo "${{env.production_format_file}}"
echo "${{env.bom_report_file}}"
- name: Setting up Python and chevron to processes reports
# workflows really need some more work done on them
if: ${{ !cancelled() }}
uses: actions/setup-python@v5
with:
python-version: '3.10'
cache: 'pip'
- name: installing requirements
if: ${{ !cancelled() }}
run: pip install -r ${{ github.workspace }}/.github/report_processing/requirements.txt
- name: Export production files
id: production
uses: sparkengineering/kicad-action@v4
if: '!cancelled()'
with:
kicad_sch: ${{ matrix.project_path }}.kicad_sch
sch_pdf: true # Generate PDF
sch_bom: true # Generate BOM
kicad_pcb: ${{ matrix.project_path }}.kicad_pcb
pcb_gerbers: true # Generate Gerbers
- name: Moving production files to correct location
if: ${{ !cancelled() && steps.production.conclusion == 'success' }}
run: |
mv ${{ github.workspace }}/$(dirname ${{matrix.project_path}})/sch.pdf ${{ github.workspace }}/${{env.schematic_file}}
mv ${{ github.workspace }}/$(dirname ${{matrix.project_path}})/bom.csv ${{ github.workspace }}/${{env.bill_of_materials_file}}
mv ${{ github.workspace }}/$(dirname ${{matrix.project_path}})/gbr.zip ${{ github.workspace }}/${{env.production_format_file}}
- name: creating BOM report in markdown
if: ${{ !cancelled() }}
run: python
${{ github.workspace }}/.github/report_processing/process_bom_files.py
${{ github.workspace }}/${{env.bill_of_materials_file}}
${{ github.workspace }}/${{steps.yaml.outputs.bom_template_path}}
${{ github.workspace }}/${{env.bom_report_file}}
- name: upload report'
uses: actions/upload-artifact@v4
with:
name: production-files-${{env.PROJECT_NAME}}.zip
path: |
${{ github.workspace }}/${{env.schematic_file}}
${{ github.workspace }}/${{env.bill_of_materials_file}}
${{ github.workspace }}/${{env.production_format_file}}
${{ github.workspace }}/${{env.bom_report_file}}
- name: data for readme updating
if: ${{always()}}
run: |
echo "{" >> ${{env.PROJECT_NAME}}_project.json
echo "\"schematic_link\":\"https://github.com/${{ github.repository }}/tree/${{ github.ref_name }}/${{env.schematic_file}}\"," >> ${{env.PROJECT_NAME}}_project.json
echo "\"bom_csv_link\":\"https://github.com/${{ github.repository }}/tree/${{ github.ref_name }}/${{env.bill_of_materials_file}}\"," >> ${{env.PROJECT_NAME}}_project.json
echo "\"bom_report_link\":\"https://github.com/${{ github.repository }}/tree/${{ github.ref_name }}/${{env.bom_report_file}}\"," >> ${{env.PROJECT_NAME}}_project.json
echo "\"gerber_link\":\"https://github.com/${{ github.repository }}/tree/${{ github.ref_name }}/${{env.production_format_file}}\"," >> ${{env.PROJECT_NAME}}_project.json
echo "\"project_link\":\"https://github.com/${{ github.repository }}/tree/${{ github.ref_name }}/$(dirname ${{matrix.project_path}})\"," >> ${{env.PROJECT_NAME}}_project.json
echo "\"project_name\":\"${{env.PROJECT_NAME}}\"" >> ${{env.PROJECT_NAME}}_project.json
echo "}" >> ${{env.PROJECT_NAME}}_project.json
- name: upload report
if: ${{always()}}
uses: actions/upload-artifact@v4
with:
name: ${{env.PROJECT_NAME}}_project.json
path: ${{env.PROJECT_NAME}}_project.json
readme_job:
runs-on: ubuntu-latest
name: update readme
if: ${{ always() }}
needs: [DRC, ERC, production_job]
steps:
- name: Checkout
uses: actions/checkout@v4
- name: read-yaml-file
uses: juliojimenez/yamler@v1.1.0
id: yaml
with:
yaml-file: ${{ github.workspace }}/project_settings.yaml
- name: download ercs files
if: ${{ steps.yaml.outputs.dynamic_read_me == 'true' }}
uses: actions/download-artifact@v4
with:
pattern: "*_erc.json"
path: ${{ github.workspace }}
- name: download drcs files
if: ${{ steps.yaml.outputs.dynamic_read_me == 'true' }}
uses: actions/download-artifact@v4
with:
pattern: "*_drc.json"
path: ${{ github.workspace }}
- name: download production json files
if: ${{ steps.yaml.outputs.dynamic_read_me == 'true' }}
uses: actions/download-artifact@v4
with:
pattern: "*_project.json"
path: ${{ github.workspace }}
- name: Setting up Python
if: ${{ steps.yaml.outputs.dynamic_read_me == 'true' }}
uses: actions/setup-python@v5
with:
python-version: '3.10'
cache: 'pip'
- name: installing requirements
if: ${{ !cancelled() && steps.yaml.outputs.dynamic_read_me == 'true' }}
run: pip install -r ${{ github.workspace }}/.github/report_processing/requirements.txt
- name: create extra info for readme hash
if: ${{ steps.yaml.outputs.dynamic_read_me == 'true' }}
run: |
echo "{" >> readme_extras.json
echo "\"badge\" : \"[![.github/workflows/main.yaml](https://github.com/${{github.repository}}/actions/workflows/main.yaml/badge.svg?branch=${{github.ref_name}})](https://github.com/${{github.repository}}/actions/workflows/main.yaml)\"," >> readme_extras.json
echo "\"lastest_action_run_link\" : \"https://github.com/${{github.repository}}/actions/runs/${{ github.run_id }}\"," >> readme_extras.json
echo "\"title\" : \"${{steps.yaml.outputs.project_name}}\"" >> readme_extras.json
echo "}" >> readme_extras.json
- name: show extras
run:
cat readme_extras.json
- name: create new readme
if: ${{ steps.yaml.outputs.dynamic_read_me == 'true' }}
run:
python
${{ github.workspace }}/.github/report_processing/process_output_files.py
${{ github.workspace }}/${{steps.yaml.outputs.readme_template_path}} *.json
- name: upload data for readme updating
if: ${{ steps.yaml.outputs.dynamic_read_me == 'true' }}
uses: actions/upload-artifact@v4
with:
name: README.md
path: README.md
- name: list everything
if: ${{always()}}
run: ls -R
upload_job:
runs-on: ubuntu-latest
name: commit production files
if: ${{ always() }}
needs: [readme_job]
steps:
- name: Checkout
uses: actions/checkout@v4
- name: read-yaml-file
uses: juliojimenez/yamler@v1.1.0
id: yaml
with:
yaml-file: ${{ github.workspace }}/project_settings.yaml
- name: download production files
uses: actions/download-artifact@v4
with:
pattern: production-files-*
path: ${{ github.workspace }}
- name: download readme
uses: actions/download-artifact@v4
with:
name: README.md
path: ${{ github.workspace }}
- name: check downloads
run: ls -R
- name: Moving files to correct location
run: |
mv ${{ github.workspace }}/production-files-*/*${{steps.yaml.outputs.schematic_output_name}}.pdf ${{ github.workspace }}/${{steps.yaml.outputs.schematic_output_path}}
mv ${{ github.workspace }}/production-files-*/*${{steps.yaml.outputs.bom_csv_output_name}}.csv ${{ github.workspace }}/${{steps.yaml.outputs.bom_csv_output_path}}
mv ${{ github.workspace }}/production-files-*/*${{steps.yaml.outputs.bom_report_output_name}}.md ${{ github.workspace }}/${{steps.yaml.outputs.bom_report_output_path}}
mv ${{ github.workspace }}/production-files-*/*${{steps.yaml.outputs.production_file_output_name}}.zip ${{ github.workspace }}/${{steps.yaml.outputs.production_file_output_path}}
- name: commit production files
uses: EndBug/add-and-commit@v9
with:
default_author: github_actions
message: 'production files'
push: true
pull: '--rebase --autostash'
tag_push: '--force' # just makes life easier
tag: 'v1.0.0 --force'
add: |
${{ github.workspace }}/*${{steps.yaml.outputs.schematic_output_name}}.pdf
${{ github.workspace }}/*${{steps.yaml.outputs.bom_csv_output_name}}.csv
${{ github.workspace }}/*${{steps.yaml.outputs.bom_report_output_name}}.md
${{ github.workspace }}/*${{steps.yaml.outputs.production_file_output_name}}.zip
${{ github.workspace }}/README.md
- name: list everything
if: ${{always()}}
run: ls -R

2
.gitignore vendored
View File

@@ -29,3 +29,5 @@ Hardware/*/*.xml
Hardware/*/*.csv Hardware/*/*.csv
__pycache__/ __pycache__/
temp/

216
.hooks/kicad_cli_tools.py Normal file
View File

@@ -0,0 +1,216 @@
# yes we are using json because
# i dont want to install a yaml
# parser on the users computer
import json
import os
import subprocess
import csv
from enum import Enum
from pathlib import Path
from os import listdir
from os.path import isfile, join
KICAD_CLI_PATH = "kicad-cli"
TEMP_FILE_PATH = "docs/"
PCB_IMAGE_OUTPUT_PATH = "res/"
PCB_PDF_OUTPUT_PATH = "docs/"
PCB_PDF_FILE_SUFFIX = "_pcb"
SCHEMATIC_OUTPUT_PATH = "docs/"
SCHEMATIC_FILE_SUFFIX = "_schematic"
BOM_OUTPUT_PATH = "docs/"
BOM_REPORT_NAME = "_bom"
TEMP_DRC_REPORT_NAME = "_drc"
TEMP_ERC_REPORT_NAME = "_erc"
# quiet
KICAD_CLI_STDOUT=subprocess.DEVNULL
# verbose
# KICAD_CLI_STDOUT=subprocess.STDOUT
class OutputReportType(Enum):
JSON = 1
REPORT = 2
def get_file_extension(self) -> str:
if (self == OutputReportType.JSON):
return "json"
if (self == OutputReportType.REPORT):
return "rpt"
return "txt"
# this is a thin vale on the kicad cli tool
class KicadProject:
def __init__(self, path : Path) -> None:
self.project_path = path.parent
self.project_name = path.name.removesuffix(".kicad_pro")
self.created_files : list[Path] = []
print(f"{self.project_path=}")
print(f"{self.project_name=}")
def erc_check(
self,
report_format : OutputReportType = OutputReportType.JSON,
return_report : bool = False
) -> None | dict | str:
format_type = report_format.name.lower()
pcb_file_path = self.project_path / f"{self.project_name}.kicad_sch"
erc_report_path = Path(TEMP_FILE_PATH) / f"{self.project_name}{TEMP_ERC_REPORT_NAME}.{report_format.get_file_extension()}"
retcode = subprocess.call(
f'{KICAD_CLI_PATH} sch erc {pcb_file_path} --output {erc_report_path} --format {format_type}',
shell=True,
stdout=KICAD_CLI_STDOUT
)
if (retcode != 0):
print(f"erc check failed return code {retcode}")
exit(1)
self.created_files.append(erc_report_path)
if (return_report):
with open(erc_report_path, "r") as txt:
if format_type == OutputReportType.JSON:
return json.loads(txt.read())
if format_type == OutputReportType.RPT:
return txt.read()
def drc_check(
self,
report_format : OutputReportType = OutputReportType.JSON,
return_report : bool = False
) -> None | dict | str:
format_type = report_format.name.lower()
pcb_file_path = self.project_path / f"{self.project_name}.kicad_pcb"
drc_report_path = Path(TEMP_FILE_PATH) / f"{self.project_name}{TEMP_DRC_REPORT_NAME}.{report_format.get_file_extension()}"
print(f"{format_type=}, {drc_report_path=}")
retcode = subprocess.call(
f'{KICAD_CLI_PATH} pcb drc {pcb_file_path} --output {drc_report_path} --format {format_type}',
shell=True,
stdout=KICAD_CLI_STDOUT
)
print(f"{retcode=}")
if (retcode != 0):
print(f"drc check failed return code {retcode}")
exit(1)
self.created_files.append(drc_report_path)
if (return_report):
with open(drc_report_path, "r") as txt:
if format_type == OutputReportType.JSON:
return json.loads(txt.read())
if format_type == OutputReportType.RPT:
return txt.read()
def process_bom(
self,
return_csv : bool = False
) -> None | list[list[str]]:
sch_file_path = self.project_path / f"{self.project_name}.kicad_sch"
bom_output_path = Path(BOM_OUTPUT_PATH) / f"{self.project_name}{BOM_REPORT_NAME}.csv"
retcode = subprocess.call(
f'{KICAD_CLI_PATH} sch export bom {sch_file_path} --output {bom_output_path}',
shell=True,
stdout=KICAD_CLI_STDOUT
)
if (retcode != 0):
print(f"process_bom failed return code {retcode}")
exit(1)
self.created_files.append(bom_output_path)
if (return_csv):
with open(bom_output_path, "r") as csvfile:
bom_csv = csv.reader(csvfile, delimiter=',', quotechar='"')
return [row for row in bom_csv]
def get_image(self,
image_type : str = "png",
height : int = 900,
width : int = 1600,
side : str = "top",
background : str = "default",
preset : str = "follow_pcb_editor",
zoom : int = 2,
) -> None:
"""
image_typ = "png" | "jpg"
side = "top" | "bottom" | "left" | "right" | "front" | "back"
background = "default" | "transparent" | "opaque"
"""
pcb_file_path = self.project_path / f"{self.project_name}.kicad_pcb"
render_output_path = Path(PCB_IMAGE_OUTPUT_PATH) / f"{self.project_name}_render.{image_type}"
retcode = subprocess.call(
f'{KICAD_CLI_PATH} pcb render {pcb_file_path} --output {render_output_path} --preset {preset} --zoom {zoom} ',
shell=True,
stdout=KICAD_CLI_STDOUT
)
if (retcode != 0):
print(f"get_image failed return code {retcode}")
exit(1)
self.created_files.append(render_output_path)
# i am not giving you the pdf to output if you want to do that yourself go ahead
def create_schmatic_pdf(self) -> None:
sch_file_path = self.project_path / f"{self.project_name}.kicad_sch"
sch_report_path = Path(SCHEMATIC_OUTPUT_PATH) / f"{self.project_name}{SCHEMATIC_FILE_SUFFIX}.pdf"
retcode = subprocess.call(
f'{KICAD_CLI_PATH} sch export pdf {sch_file_path} --output {sch_report_path}',
shell=True,
stdout=KICAD_CLI_STDOUT
)
if (retcode != 0):
print(f"create_schmatic_pdf failed return code {retcode}")
exit(1)
self.created_files.append(sch_report_path)
def create_pcb_pdf(self, layers : list[str] = ["F.Cu", "B.Cu"]) -> None:
pcb_file_path = self.project_path / f"{self.project_name}.kicad_pcb"
pcb_report_path = Path(PCB_PDF_OUTPUT_PATH) / f"{self.project_name}{PCB_PDF_FILE_SUFFIX}.pdf"
retcode = subprocess.call(
f'{KICAD_CLI_PATH} pcb export pdf {pcb_file_path} --output {pcb_report_path} --layers {",".join(layers)}',
shell=True,
stdout=KICAD_CLI_STDOUT
)
if (retcode != 0):
print(f"create_pcb_pdf failed return code {retcode}")
exit(1)
self.created_files.append(pcb_report_path)
def commit_files(files: list[Path], commit_message : str) -> None:
for file in files:
# add & commit, could use the return code however these should never fail
print(f"adding and commiting {file}")
ret_add = subprocess.call(f"git add {file}", shell=True)
ret_commit = subprocess.call(f"git commit -m \"{commit_message}\"", shell=True)
def main() -> None:
# find all kicad project files to operate on
for path in Path(".").rglob('*.kicad_pro'):
k = KicadProject(path)
k.drc_check(report_format= OutputReportType.REPORT)
k.erc_check(report_format= OutputReportType.REPORT)
k.process_bom()
k.create_schmatic_pdf()
k.get_image()
commit_files(k.created_files, "auto commited")
if __name__ == "__main__":
try:
main()
exit(0)
except Exception as e:
exit(1)

123
README.md
View File

@@ -1,115 +1,18 @@
# kicad project template # How to use this template
[![.github/workflows/main.yaml](https://github.com/sirlilpanda/kicad-project-template/actions/workflows/main.yaml/badge.svg?branch=main)](https://github.com/sirlilpanda/kicad-project-template/actions/workflows/main.yaml)
a cool table showing the workflow of all the kicad projects. custom keyboard
| project_name | DRC | ERC |
| ------------ | --- | --- |
| template | [](https://github.com/sirlilpanda/kicad-project-template/actions/runs/14507154830/attempts/1#summary-40698563204)| [](https://github.com/sirlilpanda/kicad-project-template/actions/runs/14507154830/attempts/1#summary-40698563199) |
for a quick guide check [project setup](#project-setup) ![rendered pcb](res/keyboard_render.png)
This is a simple project template for new kicad projects. This template has some basic setup already completed such as workflows for auto creating all the things you forget when creating a kicad project such as: the code for creating all of this lives in `.hooks/`
- [gerbers](https://github.com/sirlilpanda/kicad-project-template/tree/main/template_gerber.zip) ## setup
- [bom](https://github.com/sirlilpanda/kicad-project-template/tree/main/template_bom_report.md) dependencies:
- [schematic pdf](https://github.com/sirlilpanda/kicad-project-template/tree/main/template_schematic.pdf) - python3.9+ (used for crossplatfrom scripting)
- kicad-cli
to set up the hooks just run
This workflow will also run the design rules check on the PCB and schematic to ensure that you upload a working PCB. These reports are uploaded as summaries within the github [actions tab](https://github.com/sirlilpanda/kicad-project-template/actions/runs/14507154830). This template has a simple schematic PCB in it (because DRC fails on an empty PCB). Shown below is the example PCB. ```
python setup.py
![example pcb with battery diode and resistor](res/image.png) ```
This script will add a line in the `.git/hooks/pre-push` to auto run `.hooks/kicad_cli_tools.py`
besides from that the project also has:
- common predefined trace widths
- smallest vias size [JLCPBC allows](https://jlcpcb.com/capabilities/Capabilities#Drilling)
- custom net colours in the schematic editor
- `red` for +V
- `blue` for -V
- `grey` for ground
to create a repo from this template follow this [guide](https://docs.github.com/en/repositories/creating-and-managing-repositories/creating-a-repository-from-a-template)
contained in this template are:
---
- `.github/` : all files relating to github actions and other admin see [here](https://docs.github.com/en/communities/setting-up-your-project-for-healthy-contributions) for more example of what can be placed in it
- `report_processing` : where the python scripts are stored for processing the json report data from kicad
- `report_templates` : where the template for said reports are stored
- `workflows/` : this is where the github actions are kept
- `main.yaml` : the main github action that will auto generate all files required and run DRC and ERC
- `rename.py` : the script for renaming the project
- `hardware/` : this is where the kicad projects live note this can be changed
- `docs/` : this is where the generate docs are placed by default
- `BOM/` : where the bill of materials and price breakdown are kept
- `bill_of_materials.csv`: the auto generated bom for the kicad project
- `bom_report.md` : a report for the bill of materials
- `template_schematic.pdf` : the schematic for the kicad project, auto generated by the github action
- `pcbs/` : this is where the auto generated gerbers for the kicad project are stored
- `res/` : where resources are stored for the README
- `.gitignore`: a slightly modified gitignore from the [standard one](https://github.com/github/gitignore/blob/main/KiCad.gitignore)
- `project_settings.yaml` : where the settings for this project is stored
- `README.md` : this file, suggest you change this one creating your project
## project settings
there are currently very few project settings that can be changed (will will be change in the future) these are:
| setting | description |
| --------------------------- | ----------------------------------------------------------------- |
| has_been_set_up | a flag to tell the setup action if the project has been set up |
| project_name | the name of the project, this will be set to the name of the repo |
| production_formats | the output production format for the PCBs |
| dynamic_read_me | allow the readme to be updated using the given template |
| bom_template_path | the template used to write the bom report files |
| erc_report_template_path | the template used to write the erc report files |
| drc_report_template_path | the template used to write the drc report files |
| readme_template_path | the template used to write projects readme |
| schematic_output_name | the name suffix of the generated schematics |
| bom_csv_output_name | the name suffix of the generated bom csv file |
| bom_report_output_name | the name suffix of the generated bom report |
| production_file_output_name | the name suffix of the generated production file |
| schematic_output_path | the output path of the generated schematics files |
| bom_csv_output_path | the output path of the generated bom csv file |
| bom_report_output_path | the output path of the generated bom report |
| production_file_output_path | the output path of the generated production file |
## project setup
### creating a new repo with the template
creating a new template from a repo is simple:
1. click on the button in the top right hand corner called `use this template`
![alt text](res/image-5.png)
2. when the drop down menu appears click on `create a new repository`
![alt text](res/image-6.png)
3. once you click you will be brought to this page, note that the repo name you choose here will be the name that you kicad project is called.
![alt text](res/image-7.png)
after these steps you then need to configure the repo settings to do their magic see [configuring repo settings](#configuring-repo-settings) for what to do next.
### configuring repo settings
once you have created a new repo with the template, you ill have to configure the github action settings. this is because you will get an error that looks something along these lines:
![alt text](res/image-4.png)
where the action can not commit the changes due to not having permissions follow these steps:
1. open the repo setting
![alt text](res/image-1.png)
2. then head in to actions : General
![alt text](res/image-2.png)
3. then scroll down to workflow permissions and ensure that both
`Read and write permissions` and `Allow GitHub Actions to create and approve pull requests` are ticked as seen below
![alt text](res/image-3.png)
this should fix the problem if not, go harass stack overflow they need it
Once all of these steps have been followed the workflow should be passing, however the `README.md` will only update on the next push request.
## editing the readme
As this repo can and will automatically update the repo corresponding to the given readme template. If you dont want to use this you can always disable this by setting the `dynamic_read_me` to `false`. but if you want some very cool features like auto updating tables to show what projects are passing the rules check or simple links to parts of your directory. then have a look at the template readme and learn [mustache](https://mustache.github.io/)
## improvements

154
docs/keyboard_bom.csv Normal file
View File

@@ -0,0 +1,154 @@
"Refs","Value","Footprint","Qty","DNP"
"C1","100n","Capacitor_SMD:C_0603_1608Metric","1",""
"C2","100n","Capacitor_SMD:C_0603_1608Metric","1",""
"C3","100n","Capacitor_SMD:C_0603_1608Metric","1",""
"C4","100n","Capacitor_SMD:C_0603_1608Metric","1",""
"D1","NeoPixel_THT","key_switches:Untitled","1",""
"D2","NeoPixel_THT","key_switches:Untitled","1",""
"D3","NeoPixel_THT","key_switches:Untitled","1",""
"D4","NeoPixel_THT","key_switches:Untitled","1",""
"D5","NeoPixel_THT","key_switches:Untitled","1",""
"D6","NeoPixel_THT","key_switches:Untitled","1",""
"D7","NeoPixel_THT","key_switches:Untitled","1",""
"D8","NeoPixel_THT","key_switches:Untitled","1",""
"D9","NeoPixel_THT","key_switches:Untitled","1",""
"D10","NeoPixel_THT","key_switches:Untitled","1",""
"D11","NeoPixel_THT","key_switches:Untitled","1",""
"D12","NeoPixel_THT","key_switches:Untitled","1",""
"D13","NeoPixel_THT","key_switches:Untitled","1",""
"D14","NeoPixel_THT","key_switches:Untitled","1",""
"D15","NeoPixel_THT","key_switches:Untitled","1",""
"D16","NeoPixel_THT","key_switches:Untitled","1",""
"D17","NeoPixel_THT","key_switches:Untitled","1",""
"D18","NeoPixel_THT","key_switches:Untitled","1",""
"D19","NeoPixel_THT","key_switches:Untitled","1",""
"D20","NeoPixel_THT","key_switches:Untitled","1",""
"D21","NeoPixel_THT","key_switches:Untitled","1",""
"D22","NeoPixel_THT","key_switches:Untitled","1",""
"D23","NeoPixel_THT","key_switches:Untitled","1",""
"D24","NeoPixel_THT","key_switches:Untitled","1",""
"D25","NeoPixel_THT","key_switches:Untitled","1",""
"D26","NeoPixel_THT","key_switches:Untitled","1",""
"D27","NeoPixel_THT","key_switches:Untitled","1",""
"D28","NeoPixel_THT","key_switches:Untitled","1",""
"D29","NeoPixel_THT","key_switches:Untitled","1",""
"D30","NeoPixel_THT","key_switches:Untitled","1",""
"D31","NeoPixel_THT","key_switches:Untitled","1",""
"D32","NeoPixel_THT","key_switches:Untitled","1",""
"D33","NeoPixel_THT","key_switches:Untitled","1",""
"D34","NeoPixel_THT","key_switches:Untitled","1",""
"D35","NeoPixel_THT","key_switches:Untitled","1",""
"D36","NeoPixel_THT","key_switches:Untitled","1",""
"D37","NeoPixel_THT","key_switches:Untitled","1",""
"D38","NeoPixel_THT","key_switches:Untitled","1",""
"D39","NeoPixel_THT","key_switches:Untitled","1",""
"D40","NeoPixel_THT","key_switches:Untitled","1",""
"D41","NeoPixel_THT","key_switches:Untitled","1",""
"D42","NeoPixel_THT","key_switches:Untitled","1",""
"D43","NeoPixel_THT","key_switches:Untitled","1",""
"D44","NeoPixel_THT","key_switches:Untitled","1",""
"D45","NeoPixel_THT","key_switches:Untitled","1",""
"D46","NeoPixel_THT","key_switches:Untitled","1",""
"D47","NeoPixel_THT","key_switches:Untitled","1",""
"D48","NeoPixel_THT","key_switches:Untitled","1",""
"D49","NeoPixel_THT","key_switches:Untitled","1",""
"D50","NeoPixel_THT","key_switches:Untitled","1",""
"D51","NeoPixel_THT","key_switches:Untitled","1",""
"D52","NeoPixel_THT","key_switches:Untitled","1",""
"D53","NeoPixel_THT","key_switches:Untitled","1",""
"D54","NeoPixel_THT","key_switches:Untitled","1",""
"D55","NeoPixel_THT","key_switches:Untitled","1",""
"D56","NeoPixel_THT","key_switches:Untitled","1",""
"D57","NeoPixel_THT","key_switches:Untitled","1",""
"D58","NeoPixel_THT","key_switches:Untitled","1",""
"D59","NeoPixel_THT","key_switches:Untitled","1",""
"D60","NeoPixel_THT","key_switches:Untitled","1",""
"D61","NeoPixel_THT","key_switches:Untitled","1",""
"D62","NeoPixel_THT","key_switches:Untitled","1",""
"D63","NeoPixel_THT","key_switches:Untitled","1",""
"D64","NeoPixel_THT","key_switches:Untitled","1",""
"D65","NeoPixel_THT","key_switches:Untitled","1",""
"D66","NeoPixel_THT","key_switches:Untitled","1",""
"D67","NeoPixel_THT","key_switches:Untitled","1",""
"D68","NeoPixel_THT","key_switches:Untitled","1",""
"D69","NeoPixel_THT","key_switches:Untitled","1",""
"D70","NeoPixel_THT","key_switches:Untitled","1",""
"J1","AudioJack2","Connector_Audio:Jack_3.5mm_PJ320E_Horizontal","1",""
"J2","AudioJack2","Connector_Audio:Jack_3.5mm_PJ320E_Horizontal","1",""
"J3","Conn_01x10_Socket","Connector_Molex:Molex_CLIK-Mate_502382-1070_1x10-1MP_P1.25mm_Vertical","1",""
"R1","TBD","Resistor_SMD:R_0603_1608Metric","1",""
"R2","TBD","Resistor_SMD:R_0603_1608Metric","1",""
"R3","TBD","Resistor_SMD:R_0603_1608Metric","1",""
"R4","TBD","Resistor_SMD:R_0603_1608Metric","1",""
"SW1","CherryMX","CherryMX_KailhSocket_LTST-A683CEGBW-Rotated:CherryMX_1.00u_KailhSocket","1",""
"SW2","CherryMX","CherryMX_KailhSocket_LTST-A683CEGBW-Rotated:CherryMX_1.00u_KailhSocket","1",""
"SW3","CherryMX","CherryMX_KailhSocket_LTST-A683CEGBW-Rotated:CherryMX_1.00u_KailhSocket","1",""
"SW4","CherryMX","CherryMX_KailhSocket_LTST-A683CEGBW-Rotated:CherryMX_1.00u_KailhSocket","1",""
"SW5","CherryMX","CherryMX_KailhSocket_LTST-A683CEGBW-Rotated:CherryMX_1.00u_KailhSocket","1",""
"SW6","CherryMX","CherryMX_KailhSocket_LTST-A683CEGBW-Rotated:CherryMX_1.00u_KailhSocket","1",""
"SW7","CherryMX","CherryMX_KailhSocket_LTST-A683CEGBW-Rotated:CherryMX_1.00u_KailhSocket","1",""
"SW8","CherryMX","CherryMX_KailhSocket_LTST-A683CEGBW-Rotated:CherryMX_1.00u_KailhSocket","1",""
"SW9","CherryMX","CherryMX_KailhSocket_LTST-A683CEGBW-Rotated:CherryMX_1.00u_KailhSocket","1",""
"SW10","CherryMX","CherryMX_KailhSocket_LTST-A683CEGBW-Rotated:CherryMX_1.00u_KailhSocket","1",""
"SW11","CherryMX","CherryMX_KailhSocket_LTST-A683CEGBW-Rotated:CherryMX_1.00u_KailhSocket","1",""
"SW12","CherryMX","CherryMX_KailhSocket_LTST-A683CEGBW-Rotated:CherryMX_1.00u_KailhSocket","1",""
"SW13","CherryMX","CherryMX_KailhSocket_LTST-A683CEGBW-Rotated:CherryMX_1.00u_KailhSocket","1",""
"SW14","CherryMX","CherryMX_KailhSocket_LTST-A683CEGBW-Rotated:CherryMX_1.00u_KailhSocket","1",""
"SW15","CherryMX","CherryMX_KailhSocket_LTST-A683CEGBW-Rotated:CherryMX_1.00u_KailhSocket","1",""
"SW16","CherryMX","CherryMX_KailhSocket_LTST-A683CEGBW-Rotated:CherryMX_1.00u_KailhSocket","1",""
"SW17","CherryMX","CherryMX_KailhSocket_LTST-A683CEGBW-Rotated:CherryMX_1.00u_KailhSocket","1",""
"SW18","CherryMX","CherryMX_KailhSocket_LTST-A683CEGBW-Rotated:CherryMX_1.00u_KailhSocket","1",""
"SW19","CherryMX","CherryMX_KailhSocket_LTST-A683CEGBW-Rotated:CherryMX_1.00u_KailhSocket","1",""
"SW20","CherryMX","CherryMX_KailhSocket_LTST-A683CEGBW-Rotated:CherryMX_1.00u_KailhSocket","1",""
"SW21","CherryMX","CherryMX_KailhSocket_LTST-A683CEGBW-Rotated:CherryMX_1.00u_KailhSocket","1",""
"SW22","CherryMX","CherryMX_KailhSocket_LTST-A683CEGBW-Rotated:CherryMX_1.00u_KailhSocket","1",""
"SW23","CherryMX","CherryMX_KailhSocket_LTST-A683CEGBW-Rotated:CherryMX_1.00u_KailhSocket","1",""
"SW24","CherryMX","CherryMX_KailhSocket_LTST-A683CEGBW-Rotated:CherryMX_1.00u_KailhSocket","1",""
"SW25","CherryMX","CherryMX_KailhSocket_LTST-A683CEGBW-Rotated:CherryMX_1.00u_KailhSocket","1",""
"SW26","CherryMX","CherryMX_KailhSocket_LTST-A683CEGBW-Rotated:CherryMX_1.00u_KailhSocket","1",""
"SW27","CherryMX","CherryMX_KailhSocket_LTST-A683CEGBW-Rotated:CherryMX_1.00u_KailhSocket","1",""
"SW28","CherryMX","CherryMX_KailhSocket_LTST-A683CEGBW-Rotated:CherryMX_1.00u_KailhSocket","1",""
"SW29","CherryMX","CherryMX_KailhSocket_LTST-A683CEGBW-Rotated:CherryMX_1.00u_KailhSocket","1",""
"SW30","CherryMX","CherryMX_KailhSocket_LTST-A683CEGBW-Rotated:CherryMX_1.00u_KailhSocket","1",""
"SW31","CherryMX","CherryMX_KailhSocket_LTST-A683CEGBW-Rotated:CherryMX_1.00u_KailhSocket","1",""
"SW32","CherryMX","CherryMX_KailhSocket_LTST-A683CEGBW-Rotated:CherryMX_1.00u_KailhSocket","1",""
"SW33","CherryMX","CherryMX_KailhSocket_LTST-A683CEGBW-Rotated:CherryMX_1.00u_KailhSocket","1",""
"SW34","CherryMX","CherryMX_KailhSocket_LTST-A683CEGBW-Rotated:CherryMX_1.00u_KailhSocket","1",""
"SW35","CherryMX","CherryMX_KailhSocket_LTST-A683CEGBW-Rotated:CherryMX_1.00u_KailhSocket","1",""
"SW36","CherryMX","CherryMX_KailhSocket_LTST-A683CEGBW-Rotated:CherryMX_1.00u_KailhSocket","1",""
"SW37","CherryMX","CherryMX_KailhSocket_LTST-A683CEGBW-Rotated:CherryMX_1.00u_KailhSocket","1",""
"SW38","CherryMX","CherryMX_KailhSocket_LTST-A683CEGBW-Rotated:CherryMX_1.00u_KailhSocket","1",""
"SW39","CherryMX","CherryMX_KailhSocket_LTST-A683CEGBW-Rotated:CherryMX_1.00u_KailhSocket","1",""
"SW40","CherryMX","CherryMX_KailhSocket_LTST-A683CEGBW-Rotated:CherryMX_1.00u_KailhSocket","1",""
"SW41","CherryMX","CherryMX_KailhSocket_LTST-A683CEGBW-Rotated:CherryMX_1.00u_KailhSocket","1",""
"SW42","CherryMX","CherryMX_KailhSocket_LTST-A683CEGBW-Rotated:CherryMX_1.00u_KailhSocket","1",""
"SW43","CherryMX","CherryMX_KailhSocket_LTST-A683CEGBW-Rotated:CherryMX_1.00u_KailhSocket","1",""
"SW44","CherryMX","CherryMX_KailhSocket_LTST-A683CEGBW-Rotated:CherryMX_1.00u_KailhSocket","1",""
"SW45","CherryMX","CherryMX_KailhSocket_LTST-A683CEGBW-Rotated:CherryMX_1.00u_KailhSocket","1",""
"SW46","CherryMX","CherryMX_KailhSocket_LTST-A683CEGBW-Rotated:CherryMX_1.00u_KailhSocket","1",""
"SW47","CherryMX","CherryMX_KailhSocket_LTST-A683CEGBW-Rotated:CherryMX_1.00u_KailhSocket","1",""
"SW48","CherryMX","CherryMX_KailhSocket_LTST-A683CEGBW-Rotated:CherryMX_1.00u_KailhSocket","1",""
"SW49","CherryMX","CherryMX_KailhSocket_LTST-A683CEGBW-Rotated:CherryMX_1.00u_KailhSocket","1",""
"SW50","CherryMX","CherryMX_KailhSocket_LTST-A683CEGBW-Rotated:CherryMX_1.00u_KailhSocket","1",""
"SW51","CherryMX","CherryMX_KailhSocket_LTST-A683CEGBW-Rotated:CherryMX_1.00u_KailhSocket","1",""
"SW52","CherryMX","CherryMX_KailhSocket_LTST-A683CEGBW-Rotated:CherryMX_1.00u_KailhSocket","1",""
"SW53","CherryMX","CherryMX_KailhSocket_LTST-A683CEGBW-Rotated:CherryMX_1.00u_KailhSocket","1",""
"SW54","CherryMX","CherryMX_KailhSocket_LTST-A683CEGBW-Rotated:CherryMX_1.00u_KailhSocket","1",""
"SW55","CherryMX","CherryMX_KailhSocket_LTST-A683CEGBW-Rotated:CherryMX_1.00u_KailhSocket","1",""
"SW56","CherryMX","CherryMX_KailhSocket_LTST-A683CEGBW-Rotated:CherryMX_1.00u_KailhSocket","1",""
"SW57","CherryMX","CherryMX_KailhSocket_LTST-A683CEGBW-Rotated:CherryMX_1.00u_KailhSocket","1",""
"SW58","CherryMX","CherryMX_KailhSocket_LTST-A683CEGBW-Rotated:CherryMX_1.00u_KailhSocket","1",""
"SW59","CherryMX","CherryMX_KailhSocket_LTST-A683CEGBW-Rotated:CherryMX_1.00u_KailhSocket","1",""
"SW60","CherryMX","CherryMX_KailhSocket_LTST-A683CEGBW-Rotated:CherryMX_1.00u_KailhSocket","1",""
"SW61","CherryMX","CherryMX_KailhSocket_LTST-A683CEGBW-Rotated:CherryMX_1.00u_KailhSocket","1",""
"SW62","CherryMX","CherryMX_KailhSocket_LTST-A683CEGBW-Rotated:CherryMX_1.00u_KailhSocket","1",""
"SW63","CherryMX","CherryMX_KailhSocket_LTST-A683CEGBW-Rotated:CherryMX_1.00u_KailhSocket","1",""
"SW64","CherryMX","CherryMX_KailhSocket_LTST-A683CEGBW-Rotated:CherryMX_1.00u_KailhSocket","1",""
"SW65","CherryMX","CherryMX_KailhSocket_LTST-A683CEGBW-Rotated:CherryMX_1.00u_KailhSocket","1",""
"SW66","CherryMX","CherryMX_KailhSocket_LTST-A683CEGBW-Rotated:CherryMX_1.00u_KailhSocket","1",""
"SW67","CherryMX","CherryMX_KailhSocket_LTST-A683CEGBW-Rotated:CherryMX_1.00u_KailhSocket","1",""
"SW68","CherryMX","CherryMX_KailhSocket_LTST-A683CEGBW-Rotated:CherryMX_1.00u_KailhSocket","1",""
"SW69","CherryMX","CherryMX_KailhSocket_LTST-A683CEGBW-Rotated:CherryMX_1.00u_KailhSocket","1",""
"SW70","CherryMX","CherryMX_KailhSocket_LTST-A683CEGBW-Rotated:CherryMX_1.00u_KailhSocket","1",""
"UC1","PCA9506BS","Package_DFN_QFN:QFN-56-1EP_8x8mm_P0.5mm_EP4.3x4.3mm","1",""
"UC2","PCA9506BS","Package_DFN_QFN:QFN-56-1EP_8x8mm_P0.5mm_EP4.3x4.3mm","1",""
1 Refs Value Footprint Qty DNP
2 C1 100n Capacitor_SMD:C_0603_1608Metric 1
3 C2 100n Capacitor_SMD:C_0603_1608Metric 1
4 C3 100n Capacitor_SMD:C_0603_1608Metric 1
5 C4 100n Capacitor_SMD:C_0603_1608Metric 1
6 D1 NeoPixel_THT key_switches:Untitled 1
7 D2 NeoPixel_THT key_switches:Untitled 1
8 D3 NeoPixel_THT key_switches:Untitled 1
9 D4 NeoPixel_THT key_switches:Untitled 1
10 D5 NeoPixel_THT key_switches:Untitled 1
11 D6 NeoPixel_THT key_switches:Untitled 1
12 D7 NeoPixel_THT key_switches:Untitled 1
13 D8 NeoPixel_THT key_switches:Untitled 1
14 D9 NeoPixel_THT key_switches:Untitled 1
15 D10 NeoPixel_THT key_switches:Untitled 1
16 D11 NeoPixel_THT key_switches:Untitled 1
17 D12 NeoPixel_THT key_switches:Untitled 1
18 D13 NeoPixel_THT key_switches:Untitled 1
19 D14 NeoPixel_THT key_switches:Untitled 1
20 D15 NeoPixel_THT key_switches:Untitled 1
21 D16 NeoPixel_THT key_switches:Untitled 1
22 D17 NeoPixel_THT key_switches:Untitled 1
23 D18 NeoPixel_THT key_switches:Untitled 1
24 D19 NeoPixel_THT key_switches:Untitled 1
25 D20 NeoPixel_THT key_switches:Untitled 1
26 D21 NeoPixel_THT key_switches:Untitled 1
27 D22 NeoPixel_THT key_switches:Untitled 1
28 D23 NeoPixel_THT key_switches:Untitled 1
29 D24 NeoPixel_THT key_switches:Untitled 1
30 D25 NeoPixel_THT key_switches:Untitled 1
31 D26 NeoPixel_THT key_switches:Untitled 1
32 D27 NeoPixel_THT key_switches:Untitled 1
33 D28 NeoPixel_THT key_switches:Untitled 1
34 D29 NeoPixel_THT key_switches:Untitled 1
35 D30 NeoPixel_THT key_switches:Untitled 1
36 D31 NeoPixel_THT key_switches:Untitled 1
37 D32 NeoPixel_THT key_switches:Untitled 1
38 D33 NeoPixel_THT key_switches:Untitled 1
39 D34 NeoPixel_THT key_switches:Untitled 1
40 D35 NeoPixel_THT key_switches:Untitled 1
41 D36 NeoPixel_THT key_switches:Untitled 1
42 D37 NeoPixel_THT key_switches:Untitled 1
43 D38 NeoPixel_THT key_switches:Untitled 1
44 D39 NeoPixel_THT key_switches:Untitled 1
45 D40 NeoPixel_THT key_switches:Untitled 1
46 D41 NeoPixel_THT key_switches:Untitled 1
47 D42 NeoPixel_THT key_switches:Untitled 1
48 D43 NeoPixel_THT key_switches:Untitled 1
49 D44 NeoPixel_THT key_switches:Untitled 1
50 D45 NeoPixel_THT key_switches:Untitled 1
51 D46 NeoPixel_THT key_switches:Untitled 1
52 D47 NeoPixel_THT key_switches:Untitled 1
53 D48 NeoPixel_THT key_switches:Untitled 1
54 D49 NeoPixel_THT key_switches:Untitled 1
55 D50 NeoPixel_THT key_switches:Untitled 1
56 D51 NeoPixel_THT key_switches:Untitled 1
57 D52 NeoPixel_THT key_switches:Untitled 1
58 D53 NeoPixel_THT key_switches:Untitled 1
59 D54 NeoPixel_THT key_switches:Untitled 1
60 D55 NeoPixel_THT key_switches:Untitled 1
61 D56 NeoPixel_THT key_switches:Untitled 1
62 D57 NeoPixel_THT key_switches:Untitled 1
63 D58 NeoPixel_THT key_switches:Untitled 1
64 D59 NeoPixel_THT key_switches:Untitled 1
65 D60 NeoPixel_THT key_switches:Untitled 1
66 D61 NeoPixel_THT key_switches:Untitled 1
67 D62 NeoPixel_THT key_switches:Untitled 1
68 D63 NeoPixel_THT key_switches:Untitled 1
69 D64 NeoPixel_THT key_switches:Untitled 1
70 D65 NeoPixel_THT key_switches:Untitled 1
71 D66 NeoPixel_THT key_switches:Untitled 1
72 D67 NeoPixel_THT key_switches:Untitled 1
73 D68 NeoPixel_THT key_switches:Untitled 1
74 D69 NeoPixel_THT key_switches:Untitled 1
75 D70 NeoPixel_THT key_switches:Untitled 1
76 J1 AudioJack2 Connector_Audio:Jack_3.5mm_PJ320E_Horizontal 1
77 J2 AudioJack2 Connector_Audio:Jack_3.5mm_PJ320E_Horizontal 1
78 J3 Conn_01x10_Socket Connector_Molex:Molex_CLIK-Mate_502382-1070_1x10-1MP_P1.25mm_Vertical 1
79 R1 TBD Resistor_SMD:R_0603_1608Metric 1
80 R2 TBD Resistor_SMD:R_0603_1608Metric 1
81 R3 TBD Resistor_SMD:R_0603_1608Metric 1
82 R4 TBD Resistor_SMD:R_0603_1608Metric 1
83 SW1 CherryMX CherryMX_KailhSocket_LTST-A683CEGBW-Rotated:CherryMX_1.00u_KailhSocket 1
84 SW2 CherryMX CherryMX_KailhSocket_LTST-A683CEGBW-Rotated:CherryMX_1.00u_KailhSocket 1
85 SW3 CherryMX CherryMX_KailhSocket_LTST-A683CEGBW-Rotated:CherryMX_1.00u_KailhSocket 1
86 SW4 CherryMX CherryMX_KailhSocket_LTST-A683CEGBW-Rotated:CherryMX_1.00u_KailhSocket 1
87 SW5 CherryMX CherryMX_KailhSocket_LTST-A683CEGBW-Rotated:CherryMX_1.00u_KailhSocket 1
88 SW6 CherryMX CherryMX_KailhSocket_LTST-A683CEGBW-Rotated:CherryMX_1.00u_KailhSocket 1
89 SW7 CherryMX CherryMX_KailhSocket_LTST-A683CEGBW-Rotated:CherryMX_1.00u_KailhSocket 1
90 SW8 CherryMX CherryMX_KailhSocket_LTST-A683CEGBW-Rotated:CherryMX_1.00u_KailhSocket 1
91 SW9 CherryMX CherryMX_KailhSocket_LTST-A683CEGBW-Rotated:CherryMX_1.00u_KailhSocket 1
92 SW10 CherryMX CherryMX_KailhSocket_LTST-A683CEGBW-Rotated:CherryMX_1.00u_KailhSocket 1
93 SW11 CherryMX CherryMX_KailhSocket_LTST-A683CEGBW-Rotated:CherryMX_1.00u_KailhSocket 1
94 SW12 CherryMX CherryMX_KailhSocket_LTST-A683CEGBW-Rotated:CherryMX_1.00u_KailhSocket 1
95 SW13 CherryMX CherryMX_KailhSocket_LTST-A683CEGBW-Rotated:CherryMX_1.00u_KailhSocket 1
96 SW14 CherryMX CherryMX_KailhSocket_LTST-A683CEGBW-Rotated:CherryMX_1.00u_KailhSocket 1
97 SW15 CherryMX CherryMX_KailhSocket_LTST-A683CEGBW-Rotated:CherryMX_1.00u_KailhSocket 1
98 SW16 CherryMX CherryMX_KailhSocket_LTST-A683CEGBW-Rotated:CherryMX_1.00u_KailhSocket 1
99 SW17 CherryMX CherryMX_KailhSocket_LTST-A683CEGBW-Rotated:CherryMX_1.00u_KailhSocket 1
100 SW18 CherryMX CherryMX_KailhSocket_LTST-A683CEGBW-Rotated:CherryMX_1.00u_KailhSocket 1
101 SW19 CherryMX CherryMX_KailhSocket_LTST-A683CEGBW-Rotated:CherryMX_1.00u_KailhSocket 1
102 SW20 CherryMX CherryMX_KailhSocket_LTST-A683CEGBW-Rotated:CherryMX_1.00u_KailhSocket 1
103 SW21 CherryMX CherryMX_KailhSocket_LTST-A683CEGBW-Rotated:CherryMX_1.00u_KailhSocket 1
104 SW22 CherryMX CherryMX_KailhSocket_LTST-A683CEGBW-Rotated:CherryMX_1.00u_KailhSocket 1
105 SW23 CherryMX CherryMX_KailhSocket_LTST-A683CEGBW-Rotated:CherryMX_1.00u_KailhSocket 1
106 SW24 CherryMX CherryMX_KailhSocket_LTST-A683CEGBW-Rotated:CherryMX_1.00u_KailhSocket 1
107 SW25 CherryMX CherryMX_KailhSocket_LTST-A683CEGBW-Rotated:CherryMX_1.00u_KailhSocket 1
108 SW26 CherryMX CherryMX_KailhSocket_LTST-A683CEGBW-Rotated:CherryMX_1.00u_KailhSocket 1
109 SW27 CherryMX CherryMX_KailhSocket_LTST-A683CEGBW-Rotated:CherryMX_1.00u_KailhSocket 1
110 SW28 CherryMX CherryMX_KailhSocket_LTST-A683CEGBW-Rotated:CherryMX_1.00u_KailhSocket 1
111 SW29 CherryMX CherryMX_KailhSocket_LTST-A683CEGBW-Rotated:CherryMX_1.00u_KailhSocket 1
112 SW30 CherryMX CherryMX_KailhSocket_LTST-A683CEGBW-Rotated:CherryMX_1.00u_KailhSocket 1
113 SW31 CherryMX CherryMX_KailhSocket_LTST-A683CEGBW-Rotated:CherryMX_1.00u_KailhSocket 1
114 SW32 CherryMX CherryMX_KailhSocket_LTST-A683CEGBW-Rotated:CherryMX_1.00u_KailhSocket 1
115 SW33 CherryMX CherryMX_KailhSocket_LTST-A683CEGBW-Rotated:CherryMX_1.00u_KailhSocket 1
116 SW34 CherryMX CherryMX_KailhSocket_LTST-A683CEGBW-Rotated:CherryMX_1.00u_KailhSocket 1
117 SW35 CherryMX CherryMX_KailhSocket_LTST-A683CEGBW-Rotated:CherryMX_1.00u_KailhSocket 1
118 SW36 CherryMX CherryMX_KailhSocket_LTST-A683CEGBW-Rotated:CherryMX_1.00u_KailhSocket 1
119 SW37 CherryMX CherryMX_KailhSocket_LTST-A683CEGBW-Rotated:CherryMX_1.00u_KailhSocket 1
120 SW38 CherryMX CherryMX_KailhSocket_LTST-A683CEGBW-Rotated:CherryMX_1.00u_KailhSocket 1
121 SW39 CherryMX CherryMX_KailhSocket_LTST-A683CEGBW-Rotated:CherryMX_1.00u_KailhSocket 1
122 SW40 CherryMX CherryMX_KailhSocket_LTST-A683CEGBW-Rotated:CherryMX_1.00u_KailhSocket 1
123 SW41 CherryMX CherryMX_KailhSocket_LTST-A683CEGBW-Rotated:CherryMX_1.00u_KailhSocket 1
124 SW42 CherryMX CherryMX_KailhSocket_LTST-A683CEGBW-Rotated:CherryMX_1.00u_KailhSocket 1
125 SW43 CherryMX CherryMX_KailhSocket_LTST-A683CEGBW-Rotated:CherryMX_1.00u_KailhSocket 1
126 SW44 CherryMX CherryMX_KailhSocket_LTST-A683CEGBW-Rotated:CherryMX_1.00u_KailhSocket 1
127 SW45 CherryMX CherryMX_KailhSocket_LTST-A683CEGBW-Rotated:CherryMX_1.00u_KailhSocket 1
128 SW46 CherryMX CherryMX_KailhSocket_LTST-A683CEGBW-Rotated:CherryMX_1.00u_KailhSocket 1
129 SW47 CherryMX CherryMX_KailhSocket_LTST-A683CEGBW-Rotated:CherryMX_1.00u_KailhSocket 1
130 SW48 CherryMX CherryMX_KailhSocket_LTST-A683CEGBW-Rotated:CherryMX_1.00u_KailhSocket 1
131 SW49 CherryMX CherryMX_KailhSocket_LTST-A683CEGBW-Rotated:CherryMX_1.00u_KailhSocket 1
132 SW50 CherryMX CherryMX_KailhSocket_LTST-A683CEGBW-Rotated:CherryMX_1.00u_KailhSocket 1
133 SW51 CherryMX CherryMX_KailhSocket_LTST-A683CEGBW-Rotated:CherryMX_1.00u_KailhSocket 1
134 SW52 CherryMX CherryMX_KailhSocket_LTST-A683CEGBW-Rotated:CherryMX_1.00u_KailhSocket 1
135 SW53 CherryMX CherryMX_KailhSocket_LTST-A683CEGBW-Rotated:CherryMX_1.00u_KailhSocket 1
136 SW54 CherryMX CherryMX_KailhSocket_LTST-A683CEGBW-Rotated:CherryMX_1.00u_KailhSocket 1
137 SW55 CherryMX CherryMX_KailhSocket_LTST-A683CEGBW-Rotated:CherryMX_1.00u_KailhSocket 1
138 SW56 CherryMX CherryMX_KailhSocket_LTST-A683CEGBW-Rotated:CherryMX_1.00u_KailhSocket 1
139 SW57 CherryMX CherryMX_KailhSocket_LTST-A683CEGBW-Rotated:CherryMX_1.00u_KailhSocket 1
140 SW58 CherryMX CherryMX_KailhSocket_LTST-A683CEGBW-Rotated:CherryMX_1.00u_KailhSocket 1
141 SW59 CherryMX CherryMX_KailhSocket_LTST-A683CEGBW-Rotated:CherryMX_1.00u_KailhSocket 1
142 SW60 CherryMX CherryMX_KailhSocket_LTST-A683CEGBW-Rotated:CherryMX_1.00u_KailhSocket 1
143 SW61 CherryMX CherryMX_KailhSocket_LTST-A683CEGBW-Rotated:CherryMX_1.00u_KailhSocket 1
144 SW62 CherryMX CherryMX_KailhSocket_LTST-A683CEGBW-Rotated:CherryMX_1.00u_KailhSocket 1
145 SW63 CherryMX CherryMX_KailhSocket_LTST-A683CEGBW-Rotated:CherryMX_1.00u_KailhSocket 1
146 SW64 CherryMX CherryMX_KailhSocket_LTST-A683CEGBW-Rotated:CherryMX_1.00u_KailhSocket 1
147 SW65 CherryMX CherryMX_KailhSocket_LTST-A683CEGBW-Rotated:CherryMX_1.00u_KailhSocket 1
148 SW66 CherryMX CherryMX_KailhSocket_LTST-A683CEGBW-Rotated:CherryMX_1.00u_KailhSocket 1
149 SW67 CherryMX CherryMX_KailhSocket_LTST-A683CEGBW-Rotated:CherryMX_1.00u_KailhSocket 1
150 SW68 CherryMX CherryMX_KailhSocket_LTST-A683CEGBW-Rotated:CherryMX_1.00u_KailhSocket 1
151 SW69 CherryMX CherryMX_KailhSocket_LTST-A683CEGBW-Rotated:CherryMX_1.00u_KailhSocket 1
152 SW70 CherryMX CherryMX_KailhSocket_LTST-A683CEGBW-Rotated:CherryMX_1.00u_KailhSocket 1
153 UC1 PCA9506BS Package_DFN_QFN:QFN-56-1EP_8x8mm_P0.5mm_EP4.3x4.3mm 1
154 UC2 PCA9506BS Package_DFN_QFN:QFN-56-1EP_8x8mm_P0.5mm_EP4.3x4.3mm 1

View File

@@ -0,0 +1,123 @@
"Refs","Value","Footprint","Qty","DNP"
"C1","100n","","1",""
"C2","1u","","1",""
"C3","1u","","1",""
"C4","10u","","1",""
"C5","1u","","1",""
"C6","100n","","1",""
"C7","100n","","1",""
"C8","100n","","1",""
"C9","100n","","1",""
"C10","100n","","1",""
"C11","1u","","1",""
"C12","1u","","1",""
"C13","100n","","1",""
"C14","1u","","1",""
"C15","100n","","1",""
"C16","100n","","1",""
"C17","1u","Capacitor_SMD:C_0603_1608Metric","1",""
"C18","100n","","1",""
"C19","1u","","1",""
"C20","100n","","1",""
"C21","100n","","1",""
"C22","1u","","1",""
"C23","C","","1",""
"C24","C","","1",""
"C25","22u","Capacitor_SMD:C_0603_1608Metric","1",""
"C26","100n","","1",""
"C27","100n","","1",""
"C28","1u","","1",""
"C29","100n","","1",""
"C30","10u","","1",""
"C31","100n","Capacitor_SMD:C_0603_1608Metric","1",""
"C32","100n","","1",""
"C33","10u","","1",""
"C34","100n","","1",""
"C35","1u","Capacitor_SMD:C_0603_1608Metric","1",""
"C36","10u","","1",""
"C37","100n","","1",""
"C39","1u","Capacitor_SMD:C_0603_1608Metric","1",""
"C52","1u","Capacitor_SMD:C_0603_1608Metric","1",""
"C56","1u","Capacitor_SMD:C_0603_1608Metric","1",""
"D1","NUP2105L","Package_TO_SOT_SMD:SOT-23","1",""
"D2","TSM24A","Package_TO_SOT_SMD:SOT-23","1",""
"D3","LED","","1",""
"D4","LED","","1",""
"D5","LED","","1",""
"D24","LED","Diode_SMD:D_0603_1608Metric","1",""
"D25","LED","Diode_SMD:D_0603_1608Metric","1",""
"D26","LED","Diode_SMD:D_0603_1608Metric","1",""
"J1","USB_C_Receptacle_USB2.0_14P","","1",""
"J2","USB_A","","1",""
"J3","USB_A","","1",""
"J4","USB_A","","1",""
"Q1","PMOS","","1",""
"Q2","LRC L8050QLT1G","","1",""
"Q3","LRC L8050QLT1G","","1",""
"R1","0","","1",""
"R2","100k","","1",""
"R3","100k","","1",""
"R4","100k","","1",""
"R5","12k","","1",""
"R6","0R","","1",""
"R7","0R","","1",""
"R8","0R","","1",""
"R9","0R","","1",""
"R10","0R","","1",""
"R11","0R","","1",""
"R12","0R","","1",""
"R13","0R","","1",""
"R14","0R","","1","DNP"
"R15","0R","","1","DNP"
"R16","0R","","1",""
"R17","10k","","1",""
"R18","10k","","1",""
"R19","10k","","1",""
"R20","10k","","1",""
"R21","10k","","1",""
"R22","10k","","1",""
"R23","50k","","1",""
"R24","100k","","1",""
"R25","1k","","1",""
"R26","100k","","1",""
"R27","100","","1",""
"R28","22k","","1",""
"R29","1k","","1",""
"R30","1k","","1",""
"R31","0","Resistor_SMD:R_0603_1608Metric","1",""
"R32","1k","","1",""
"R33","1k","","1",""
"R34","10k","","1",""
"R35","10k","","1",""
"R36","0","","1",""
"R37","0","","1",""
"R38","0","","1",""
"R39","10k","","1",""
"R63","10k","Resistor_SMD:R_0603_1608Metric","1",""
"R64","10k","Resistor_SMD:R_0603_1608Metric","1",""
"R65","10k","Resistor_SMD:R_0603_1608Metric","1",""
"R66","3.8k","Resistor_SMD:R_0603_1608Metric","1",""
"R67","0","Resistor_SMD:R_0603_1608Metric","1",""
"R68","10k","Resistor_SMD:R_0603_1608Metric","1",""
"R69","0","Resistor_SMD:R_0603_1608Metric","1",""
"R70","10k","Resistor_SMD:R_0603_1608Metric","1",""
"R73","0","Resistor_SMD:R_0603_1608Metric","1",""
"R76","560","Resistor_SMD:R_0603_1608Metric","1",""
"R77","560","Resistor_SMD:R_0603_1608Metric","1",""
"R78","560","Resistor_SMD:R_0603_1608Metric","1",""
"SW1","SW_Nidec_CAS-120A1","Button_Switch_SMD:Nidec_Copal_CAS-120A","1",""
"SW2","SW_Push","Button_Switch_SMD:SW_SPST_PTS810","1",""
"SW8","SW_Push","Button_Switch_SMD:SW_SPST_PTS810","1",""
"SW9","SW_Push","Button_Switch_SMD:SW_SPST_PTS810","1",""
"SW10","SW_Push","Button_Switch_SMD:SW_SPST_PTS810","1",""
"SW11","OS102011MS2QN1","Button_Switch_THT:SW_Slide-03_Wuerth-WS-SLTV_10x2.5x6.4_P2.54mm","1",""
"U1","STUSB4500QTR","Package_DFN_QFN:QFN-24-1EP_4x4mm_P0.5mm_EP2.7x2.7mm","1",""
"U2","USB2534","Package_DFN_QFN:QFN-36-1EP_6x6mm_P0.5mm_EP3.7x3.7mm","1",""
"U3","LM3235-H","Package_SO:SOIC-8_3.9x4.9mm_P1.27mm","1",""
"U4","LM3235-H","Package_SO:SOIC-8_3.9x4.9mm_P1.27mm","1",""
"U5","LM3235-H","Package_SO:SOIC-8_3.9x4.9mm_P1.27mm","1",""
"U6","USBLC6-2SC6","Package_TO_SOT_SMD:SOT-23-6","1",""
"U7","CH340X","Package_SO:MSOP-10_3x3mm_P0.5mm","1",""
"U8","TS3USB30EDGSR","Package_SO:VSSOP-10_3x3mm_P0.5mm","1",""
"U13","ESP32-S3-WROOM-2","RF_Module:ESP32-S3-WROOM-2","1",""
"Y1","Crystal","","1",""
1 Refs Value Footprint Qty DNP
2 C1 100n 1
3 C2 1u 1
4 C3 1u 1
5 C4 10u 1
6 C5 1u 1
7 C6 100n 1
8 C7 100n 1
9 C8 100n 1
10 C9 100n 1
11 C10 100n 1
12 C11 1u 1
13 C12 1u 1
14 C13 100n 1
15 C14 1u 1
16 C15 100n 1
17 C16 100n 1
18 C17 1u Capacitor_SMD:C_0603_1608Metric 1
19 C18 100n 1
20 C19 1u 1
21 C20 100n 1
22 C21 100n 1
23 C22 1u 1
24 C23 C 1
25 C24 C 1
26 C25 22u Capacitor_SMD:C_0603_1608Metric 1
27 C26 100n 1
28 C27 100n 1
29 C28 1u 1
30 C29 100n 1
31 C30 10u 1
32 C31 100n Capacitor_SMD:C_0603_1608Metric 1
33 C32 100n 1
34 C33 10u 1
35 C34 100n 1
36 C35 1u Capacitor_SMD:C_0603_1608Metric 1
37 C36 10u 1
38 C37 100n 1
39 C39 1u Capacitor_SMD:C_0603_1608Metric 1
40 C52 1u Capacitor_SMD:C_0603_1608Metric 1
41 C56 1u Capacitor_SMD:C_0603_1608Metric 1
42 D1 NUP2105L Package_TO_SOT_SMD:SOT-23 1
43 D2 TSM24A Package_TO_SOT_SMD:SOT-23 1
44 D3 LED 1
45 D4 LED 1
46 D5 LED 1
47 D24 LED Diode_SMD:D_0603_1608Metric 1
48 D25 LED Diode_SMD:D_0603_1608Metric 1
49 D26 LED Diode_SMD:D_0603_1608Metric 1
50 J1 USB_C_Receptacle_USB2.0_14P 1
51 J2 USB_A 1
52 J3 USB_A 1
53 J4 USB_A 1
54 Q1 PMOS 1
55 Q2 LRC L8050QLT1G 1
56 Q3 LRC L8050QLT1G 1
57 R1 0 1
58 R2 100k 1
59 R3 100k 1
60 R4 100k 1
61 R5 12k 1
62 R6 0R 1
63 R7 0R 1
64 R8 0R 1
65 R9 0R 1
66 R10 0R 1
67 R11 0R 1
68 R12 0R 1
69 R13 0R 1
70 R14 0R 1 DNP
71 R15 0R 1 DNP
72 R16 0R 1
73 R17 10k 1
74 R18 10k 1
75 R19 10k 1
76 R20 10k 1
77 R21 10k 1
78 R22 10k 1
79 R23 50k 1
80 R24 100k 1
81 R25 1k 1
82 R26 100k 1
83 R27 100 1
84 R28 22k 1
85 R29 1k 1
86 R30 1k 1
87 R31 0 Resistor_SMD:R_0603_1608Metric 1
88 R32 1k 1
89 R33 1k 1
90 R34 10k 1
91 R35 10k 1
92 R36 0 1
93 R37 0 1
94 R38 0 1
95 R39 10k 1
96 R63 10k Resistor_SMD:R_0603_1608Metric 1
97 R64 10k Resistor_SMD:R_0603_1608Metric 1
98 R65 10k Resistor_SMD:R_0603_1608Metric 1
99 R66 3.8k Resistor_SMD:R_0603_1608Metric 1
100 R67 0 Resistor_SMD:R_0603_1608Metric 1
101 R68 10k Resistor_SMD:R_0603_1608Metric 1
102 R69 0 Resistor_SMD:R_0603_1608Metric 1
103 R70 10k Resistor_SMD:R_0603_1608Metric 1
104 R73 0 Resistor_SMD:R_0603_1608Metric 1
105 R76 560 Resistor_SMD:R_0603_1608Metric 1
106 R77 560 Resistor_SMD:R_0603_1608Metric 1
107 R78 560 Resistor_SMD:R_0603_1608Metric 1
108 SW1 SW_Nidec_CAS-120A1 Button_Switch_SMD:Nidec_Copal_CAS-120A 1
109 SW2 SW_Push Button_Switch_SMD:SW_SPST_PTS810 1
110 SW8 SW_Push Button_Switch_SMD:SW_SPST_PTS810 1
111 SW9 SW_Push Button_Switch_SMD:SW_SPST_PTS810 1
112 SW10 SW_Push Button_Switch_SMD:SW_SPST_PTS810 1
113 SW11 OS102011MS2QN1 Button_Switch_THT:SW_Slide-03_Wuerth-WS-SLTV_10x2.5x6.4_P2.54mm 1
114 U1 STUSB4500QTR Package_DFN_QFN:QFN-24-1EP_4x4mm_P0.5mm_EP2.7x2.7mm 1
115 U2 USB2534 Package_DFN_QFN:QFN-36-1EP_6x6mm_P0.5mm_EP3.7x3.7mm 1
116 U3 LM3235-H Package_SO:SOIC-8_3.9x4.9mm_P1.27mm 1
117 U4 LM3235-H Package_SO:SOIC-8_3.9x4.9mm_P1.27mm 1
118 U5 LM3235-H Package_SO:SOIC-8_3.9x4.9mm_P1.27mm 1
119 U6 USBLC6-2SC6 Package_TO_SOT_SMD:SOT-23-6 1
120 U7 CH340X Package_SO:MSOP-10_3x3mm_P0.5mm 1
121 U8 TS3USB30EDGSR Package_SO:VSSOP-10_3x3mm_P0.5mm 1
122 U13 ESP32-S3-WROOM-2 RF_Module:ESP32-S3-WROOM-2 1
123 Y1 Crystal 1

View File

@@ -0,0 +1,13 @@
** Drc report for keyboard_controller.kicad_pcb **
** Created on 2026-01-23T14:42:49+1300 **
** Found 1 DRC violations **
[invalid_outline]: Board has malformed outline (no edges found on Edge.Cuts layer)
Local override; error
@(0.0000 mm, 0.0000 mm): PCB
** Found 0 unconnected pads **
** Found 0 Footprint errors **
** End of Report **

View File

@@ -0,0 +1,251 @@
ERC report (2026-01-23T14:42:49+1300, Encoding UTF8)
***** Sheet /
[hier_label_mismatch]: Sheet pin PWR_3V3 has no matching hierarchical label inside the sheet
; error
@(124.46 mm, 55.88 mm): Hierarchical Sheet Pin PWR_3V3
[pin_not_connected]: Pin not connected
; error
@(124.46 mm, 55.88 mm): Hierarchical Sheet Pin PWR_3V3
[hier_label_mismatch]: Sheet pin PWR_5V has no matching hierarchical label inside the sheet
; error
@(124.46 mm, 58.42 mm): Hierarchical Sheet Pin PWR_5V
[pin_not_connected]: Pin not connected
; error
@(124.46 mm, 58.42 mm): Hierarchical Sheet Pin PWR_5V
[pin_not_connected]: Pin not connected
; error
@(153.67 mm, 72.39 mm): Hierarchical Sheet Pin MCU_USB_N
[pin_not_connected]: Pin not connected
; error
@(156.21 mm, 72.39 mm): Hierarchical Sheet Pin MCU_USB_P
[pin_not_connected]: Pin not connected
; error
@(173.99 mm, 72.39 mm): Hierarchical Sheet Pin PROG_BOOT
[pin_not_connected]: Pin not connected
; error
@(176.53 mm, 72.39 mm): Hierarchical Sheet Pin PROG_EN
[pin_not_connected]: Pin not connected
; error
@(179.07 mm, 72.39 mm): Hierarchical Sheet Pin PROG_TXD
[pin_not_connected]: Pin not connected
; error
@(181.61 mm, 72.39 mm): Hierarchical Sheet Pin PROG_RXD
[label_dangling]: Label not connected to anything
; error
@(138.43 mm, 115.57 mm): Hierarchical Label 'USB_PD_ALERT'
[label_dangling]: Label not connected to anything
; error
@(106.68 mm, 67.31 mm): Hierarchical Label 'SCL'
[label_dangling]: Label not connected to anything
; error
@(106.68 mm, 69.85 mm): Hierarchical Label 'SDA'
[label_dangling]: Label not connected to anything
; error
@(106.68 mm, 72.39 mm): Hierarchical Label 'USB_PD_ALERT'
[label_dangling]: Label not connected to anything
; error
@(106.68 mm, 95.25 mm): Hierarchical Label 'USB_D-'
[label_dangling]: Label not connected to anything
; error
@(106.68 mm, 97.79 mm): Hierarchical Label 'USB_D+'
[label_dangling]: Label not connected to anything
; error
@(106.68 mm, 115.57 mm): Hierarchical Label 'PROG_TXD'
[label_dangling]: Label not connected to anything
; error
@(106.68 mm, 118.11 mm): Hierarchical Label 'PROG_RXD'
[label_dangling]: Label not connected to anything
; error
@(237.49 mm, 135.89 mm): Label 'DEBUG_LED_0'
[label_dangling]: Label not connected to anything
; error
@(237.49 mm, 138.43 mm): Label 'DEBUG_LED_1'
[label_dangling]: Label not connected to anything
; error
@(237.49 mm, 140.97 mm): Label 'DEBUG_LED_2'
[label_dangling]: Label not connected to anything
; error
@(118.11 mm, 100.33 mm): Hierarchical Label 'PROG_TXD'
[label_dangling]: Label not connected to anything
; error
@(118.11 mm, 102.87 mm): Hierarchical Label 'PROG_RXD'
[label_dangling]: Label not connected to anything
; error
@(139.70 mm, 113.03 mm): Hierarchical Label 'PROG_EN'
[label_dangling]: Label not connected to anything
; error
@(139.70 mm, 138.43 mm): Hierarchical Label 'PROG_BOOT'
[unconnected_wire_endpoint]: Unconnected wire endpoint
; warning
@(121.92 mm, 85.09 mm): Horizontal Wire, length 2.54 mm
[unconnected_wire_endpoint]: Unconnected wire endpoint
; warning
@(119.38 mm, 87.63 mm): Horizontal Wire, length 5.08 mm
[unconnected_wire_endpoint]: Unconnected wire endpoint
; warning
@(116.84 mm, 90.17 mm): Horizontal Wire, length 7.62 mm
[lib_symbol_mismatch]: Symbol 'USB_C_Receptacle_USB2.0_14P' doesn't match copy in library 'Connector'
; warning
@(58.42 mm, 104.14 mm): Symbol J1 [USB_C_Receptacle_USB2.0_14P]
[lib_symbol_mismatch]: Symbol 'STUSB4500QTR' doesn't match copy in library 'Interface_USB'
; warning
@(158.75 mm, 102.87 mm): Symbol U1 [STUSB4500QTR]
[lib_symbol_issues]: The current configuration does not include the symbol library 'keyboard_core_lib'
; warning
@(95.25 mm, 73.66 mm): Symbol U2 [USB2534]
[lib_symbol_issues]: The current configuration does not include the symbol library 'keyboard_core_lib'
; warning
@(219.71 mm, 39.37 mm): Symbol U3 [LM3525-H]
[lib_symbol_issues]: The current configuration does not include the symbol library 'keyboard_core_lib'
; warning
@(219.71 mm, 78.74 mm): Symbol U4 [LM3525-H]
[lib_symbol_issues]: The current configuration does not include the symbol library 'keyboard_core_lib'
; warning
@(219.71 mm, 118.11 mm): Symbol U5 [LM3525-H]
[lib_symbol_mismatch]: Symbol 'LED' doesn't match copy in library 'Device'
; warning
@(250.19 mm, 146.05 mm): Symbol D24 [LED]
[lib_symbol_mismatch]: Symbol 'LED' doesn't match copy in library 'Device'
; warning
@(259.08 mm, 146.05 mm): Symbol D25 [LED]
[lib_symbol_mismatch]: Symbol 'LED' doesn't match copy in library 'Device'
; warning
@(267.97 mm, 146.05 mm): Symbol D26 [LED]
[lib_symbol_mismatch]: Symbol 'USB_A' doesn't match copy in library 'Connector'
; warning
@(114.30 mm, 64.77 mm): Symbol J4 [USB_A]
[lib_symbol_mismatch]: Symbol 'USB_A' doesn't match copy in library 'Connector'
; warning
@(252.73 mm, 60.96 mm): Symbol J2 [USB_A]
[lib_symbol_mismatch]: Symbol 'USB_A' doesn't match copy in library 'Connector'
; warning
@(252.73 mm, 109.22 mm): Symbol J3 [USB_A]
***** Sheet /MCU/
[hier_label_mismatch]: Hierarchical label EN has no matching sheet pin in the parent sheet
; error
@(53.34 mm, 46.99 mm): Hierarchical Label 'EN'
[pin_not_connected]: Pin not connected
; error
@(96.52 mm, 49.53 mm): Symbol U13 Pin 39 [IO1, Bidirectional, Line]
[pin_not_connected]: Pin not connected
; error
@(96.52 mm, 54.61 mm): Symbol U13 Pin 15 [IO3, Bidirectional, Line]
[pin_not_connected]: Pin not connected
; error
@(96.52 mm, 57.15 mm): Symbol U13 Pin 4 [IO4, Bidirectional, Line]
[hier_label_mismatch]: Hierarchical label BOOT has no matching sheet pin in the parent sheet
; error
@(102.87 mm, 46.99 mm): Hierarchical Label 'BOOT'
[pin_not_connected]: Pin not connected
; error
@(96.52 mm, 59.69 mm): Symbol U13 Pin 5 [IO5, Bidirectional, Line]
[pin_not_connected]: Pin not connected
; error
@(96.52 mm, 62.23 mm): Symbol U13 Pin 6 [IO6, Bidirectional, Line]
[pin_not_connected]: Pin not connected
; error
@(96.52 mm, 64.77 mm): Symbol U13 Pin 7 [IO7, Bidirectional, Line]
[pin_not_connected]: Pin not connected
; error
@(96.52 mm, 74.93 mm): Symbol U13 Pin 19 [IO11, Bidirectional, Line]
[pin_not_connected]: Pin not connected
; error
@(96.52 mm, 77.47 mm): Symbol U13 Pin 20 [IO12, Bidirectional, Line]
[pin_not_connected]: Pin not connected
; error
@(96.52 mm, 80.01 mm): Symbol U13 Pin 21 [IO13, Bidirectional, Line]
[hier_label_mismatch]: Hierarchical label SCL has no matching sheet pin in the parent sheet
; error
@(106.68 mm, 67.31 mm): Hierarchical Label 'SCL'
[pin_not_connected]: Pin not connected
; error
@(96.52 mm, 82.55 mm): Symbol U13 Pin 22 [IO14, Bidirectional, Line]
[hier_label_mismatch]: Hierarchical label SDA has no matching sheet pin in the parent sheet
; error
@(106.68 mm, 69.85 mm): Hierarchical Label 'SDA'
[hier_label_mismatch]: Hierarchical label USB_PD_ALERT has no matching sheet pin in the parent sheet
; error
@(106.68 mm, 72.39 mm): Hierarchical Label 'USB_PD_ALERT'
[power_pin_not_driven]: Input Power pin not driven by any Output Power pins
; error
@(135.89 mm, 33.02 mm): Symbol #PWR0154 Pin 1 [Power input, Line]
[hier_label_mismatch]: Hierarchical label USB_D- has no matching sheet pin in the parent sheet
; error
@(106.68 mm, 95.25 mm): Hierarchical Label 'USB_D-'
[hier_label_mismatch]: Hierarchical label USB_D+ has no matching sheet pin in the parent sheet
; error
@(106.68 mm, 97.79 mm): Hierarchical Label 'USB_D+'
[hier_label_mismatch]: Hierarchical label PROG_TXD has no matching sheet pin in the parent sheet
; error
@(106.68 mm, 115.57 mm): Hierarchical Label 'PROG_TXD'
[hier_label_mismatch]: Hierarchical label PROG_RXD has no matching sheet pin in the parent sheet
; error
@(106.68 mm, 118.11 mm): Hierarchical Label 'PROG_RXD'
***** Sheet /keyboard_interface/
***** Sheet /USB_hub/
[power_pin_not_driven]: Input Power pin not driven by any Output Power pins
; error
@(71.12 mm, 99.06 mm): Symbol U2 Pin 14 [VDD_1V2, Power input, Line]
[power_pin_not_driven]: Input Power pin not driven by any Output Power pins
; error
@(200.66 mm, 20.32 mm): Symbol #PWR050 Pin 1 [Power input, Line]
[pin_to_pin]: Pins of type Power output and Power output are connected
; error
@(233.68 mm, 39.37 mm): Symbol U3 Pin 6 [OUT, Power output, Line]
@(233.68 mm, 36.83 mm): Symbol U3 Pin 8 [OUT, Power output, Line]
[pin_to_pin]: Pins of type Power output and Power output are connected
; error
@(233.68 mm, 78.74 mm): Symbol U4 Pin 6 [OUT, Power output, Line]
@(233.68 mm, 76.20 mm): Symbol U4 Pin 8 [OUT, Power output, Line]
[pin_to_pin]: Pins of type Power output and Power output are connected
; error
@(233.68 mm, 118.11 mm): Symbol U5 Pin 6 [OUT, Power output, Line]
@(233.68 mm, 115.57 mm): Symbol U5 Pin 8 [OUT, Power output, Line]
[no_connect_connected]: A pin with a “no connection” flag is connected
; warning
@(119.38 mm, 60.96 mm): Symbol U2 Pin 2 [USBD1_P, Bidirectional, Line]
@(119.38 mm, 60.96 mm): No Connect
***** Sheet /USB_output_n_prog/
[power_pin_not_driven]: Input Power pin not driven by any Output Power pins
; error
@(64.77 mm, 46.99 mm): Symbol #PWR031 Pin 1 [Power input, Line]
[pin_not_driven]: Input pin not driven by any Output pins
; error
@(109.22 mm, 102.87 mm): Symbol U7 Pin 9 [RXD, Input, Line]
[pin_to_pin]: Pins of type Open emitter and Output are connected
; error
@(128.27 mm, 123.19 mm): Symbol Q2 Pin 3 [E, Open emitter, Line]
@(109.22 mm, 120.65 mm): Symbol U7 Pin 4 [~{RTS}, Output, Line]
[pin_to_pin]: Pins of type Open emitter and Output are connected
; error
@(128.27 mm, 128.27 mm): Symbol Q3 Pin 3 [E, Open emitter, Line]
@(109.22 mm, 118.11 mm): Symbol U7 Pin 6 [TNOW/~{DTR}, Output, Line]
***** Sheet /USB_input/
[power_pin_not_driven]: Input Power pin not driven by any Output Power pins
; error
@(50.80 mm, 128.27 mm): Symbol #PWR03 Pin 1 [Power input, Line]
[power_pin_not_driven]: Input Power pin not driven by any Output Power pins
; error
@(58.42 mm, 128.27 mm): Symbol #PWR02 Pin 1 [Power input, Line]
[power_pin_not_driven]: Input Power pin not driven by any Output Power pins
; error
@(152.40 mm, 64.77 mm): Symbol U1 Pin 24 [VDD, Power input, Line]
[power_pin_not_driven]: Input Power pin not driven by any Output Power pins
; error
@(162.56 mm, 58.42 mm): Symbol #PWR01 Pin 1 [Power input, Line]
[pin_not_driven]: Input pin not driven by any Output pins
; error
@(143.51 mm, 110.49 mm): Symbol U1 Pin 7 [SCL, Input, Line]
[power_pin_not_driven]: Input Power pin not driven by any Output Power pins
; error
@(219.71 mm, 36.83 mm): Symbol #PWR027 Pin 1 [Power input, Line]
***** Sheet /POWER/
** ERC messages: 76 Errors 60 Warnings 16

Binary file not shown.

1063
docs/keyboard_drc.rpt Normal file

File diff suppressed because it is too large Load Diff

254
docs/keyboard_erc.rpt Normal file
View File

@@ -0,0 +1,254 @@
ERC report (2026-01-23T14:42:45+1300, Encoding UTF8)
***** Sheet /
[pin_not_connected]: Pin not connected
; error
@(68.58 mm, 209.55 mm): Symbol #PWR061 Pin 1 [Power input, Line]
[pin_not_connected]: Pin not connected
; error
@(74.93 mm, 209.55 mm): Symbol #PWR0240 Pin 1 [Power input, Line]
[power_pin_not_driven]: Input Power pin not driven by any Output Power pins
; error
@(41.91 mm, 220.98 mm): Symbol #PWR03 Pin 1 [Power input, Line]
[power_pin_not_driven]: Input Power pin not driven by any Output Power pins
; error
@(3.81 mm, 236.22 mm): Symbol #PWR01 Pin 1 [Power input, Line]
[label_dangling]: Label not connected to anything
; error
@(71.12 mm, 262.89 mm): Label 'IO1_3_L'
[label_dangling]: Label not connected to anything
; error
@(71.12 mm, 265.43 mm): Label 'IO1_4_L'
[label_dangling]: Label not connected to anything
; error
@(71.12 mm, 267.97 mm): Label 'IO1_5_L'
[pin_not_connected]: Pin not connected
; error
@(288.29 mm, 138.43 mm): Symbol D15 Pin 3 [DOUT, Output, Line]
[label_dangling]: Label not connected to anything
; error
@(71.12 mm, 323.85 mm): Label 'IO4_0_L'
[label_dangling]: Label not connected to anything
; error
@(71.12 mm, 341.63 mm): Label 'IO4_7_L'
[label_dangling]: Label not connected to anything
; error
@(553.72 mm, 232.41 mm): Label 'IO0_0_R'
[label_dangling]: Label not connected to anything
; error
@(553.72 mm, 234.95 mm): Label 'IO0_1_R'
[label_dangling]: Label not connected to anything
; error
@(553.72 mm, 237.49 mm): Label 'IO0_2_R'
[lib_symbol_mismatch]: Symbol 'NeoPixel_THT' doesn't match copy in library 'LED'
; warning
@(113.03 mm, 48.26 mm): Symbol D65 [NeoPixel_THT]
[lib_symbol_mismatch]: Symbol 'NeoPixel_THT' doesn't match copy in library 'LED'
; warning
@(128.27 mm, 48.26 mm): Symbol D66 [NeoPixel_THT]
[lib_symbol_mismatch]: Symbol 'NeoPixel_THT' doesn't match copy in library 'LED'
; warning
@(143.51 mm, 48.26 mm): Symbol D67 [NeoPixel_THT]
[lib_symbol_mismatch]: Symbol 'NeoPixel_THT' doesn't match copy in library 'LED'
; warning
@(158.75 mm, 48.26 mm): Symbol D68 [NeoPixel_THT]
[lib_symbol_mismatch]: Symbol 'NeoPixel_THT' doesn't match copy in library 'LED'
; warning
@(173.99 mm, 48.26 mm): Symbol D69 [NeoPixel_THT]
[lib_symbol_mismatch]: Symbol 'NeoPixel_THT' doesn't match copy in library 'LED'
; warning
@(189.23 mm, 48.26 mm): Symbol D70 [NeoPixel_THT]
[lib_symbol_mismatch]: Symbol 'NeoPixel_THT' doesn't match copy in library 'LED'
; warning
@(204.47 mm, 48.26 mm): Symbol D59 [NeoPixel_THT]
[lib_symbol_mismatch]: Symbol 'NeoPixel_THT' doesn't match copy in library 'LED'
; warning
@(219.71 mm, 48.26 mm): Symbol D58 [NeoPixel_THT]
[lib_symbol_mismatch]: Symbol 'NeoPixel_THT' doesn't match copy in library 'LED'
; warning
@(234.95 mm, 48.26 mm): Symbol D57 [NeoPixel_THT]
[lib_symbol_mismatch]: Symbol 'NeoPixel_THT' doesn't match copy in library 'LED'
; warning
@(250.19 mm, 48.26 mm): Symbol D56 [NeoPixel_THT]
[lib_symbol_mismatch]: Symbol 'NeoPixel_THT' doesn't match copy in library 'LED'
; warning
@(265.43 mm, 48.26 mm): Symbol D55 [NeoPixel_THT]
[lib_symbol_mismatch]: Symbol 'NeoPixel_THT' doesn't match copy in library 'LED'
; warning
@(280.67 mm, 48.26 mm): Symbol D54 [NeoPixel_THT]
[lib_symbol_mismatch]: Symbol 'NeoPixel_THT' doesn't match copy in library 'LED'
; warning
@(295.91 mm, 48.26 mm): Symbol D53 [NeoPixel_THT]
[lib_symbol_mismatch]: Symbol 'NeoPixel_THT' doesn't match copy in library 'LED'
; warning
@(295.91 mm, 80.01 mm): Symbol D44 [NeoPixel_THT]
[lib_symbol_mismatch]: Symbol 'NeoPixel_THT' doesn't match copy in library 'LED'
; warning
@(311.15 mm, 48.26 mm): Symbol D52 [NeoPixel_THT]
[lib_symbol_mismatch]: Symbol 'NeoPixel_THT' doesn't match copy in library 'LED'
; warning
@(295.91 mm, 107.95 mm): Symbol D30 [NeoPixel_THT]
[lib_symbol_mismatch]: Symbol 'NeoPixel_THT' doesn't match copy in library 'LED'
; warning
@(311.15 mm, 80.01 mm): Symbol D43 [NeoPixel_THT]
[lib_symbol_mismatch]: Symbol 'NeoPixel_THT' doesn't match copy in library 'LED'
; warning
@(295.91 mm, 138.43 mm): Symbol D15 [NeoPixel_THT]
[lib_symbol_mismatch]: Symbol 'NeoPixel_THT' doesn't match copy in library 'LED'
; warning
@(311.15 mm, 107.95 mm): Symbol D29 [NeoPixel_THT]
[lib_symbol_mismatch]: Symbol 'NeoPixel_THT' doesn't match copy in library 'LED'
; warning
@(326.39 mm, 48.26 mm): Symbol D64 [NeoPixel_THT]
[lib_symbol_mismatch]: Symbol 'NeoPixel_THT' doesn't match copy in library 'LED'
; warning
@(326.39 mm, 80.01 mm): Symbol D42 [NeoPixel_THT]
[lib_symbol_mismatch]: Symbol 'NeoPixel_THT' doesn't match copy in library 'LED'
; warning
@(311.15 mm, 138.43 mm): Symbol D14 [NeoPixel_THT]
[lib_symbol_mismatch]: Symbol 'NeoPixel_THT' doesn't match copy in library 'LED'
; warning
@(326.39 mm, 107.95 mm): Symbol D28 [NeoPixel_THT]
[lib_symbol_mismatch]: Symbol 'NeoPixel_THT' doesn't match copy in library 'LED'
; warning
@(341.63 mm, 48.26 mm): Symbol D51 [NeoPixel_THT]
[lib_symbol_mismatch]: Symbol 'NeoPixel_THT' doesn't match copy in library 'LED'
; warning
@(341.63 mm, 80.01 mm): Symbol D41 [NeoPixel_THT]
[lib_symbol_mismatch]: Symbol 'NeoPixel_THT' doesn't match copy in library 'LED'
; warning
@(326.39 mm, 138.43 mm): Symbol D13 [NeoPixel_THT]
[lib_symbol_mismatch]: Symbol 'NeoPixel_THT' doesn't match copy in library 'LED'
; warning
@(341.63 mm, 107.95 mm): Symbol D27 [NeoPixel_THT]
[lib_symbol_mismatch]: Symbol 'NeoPixel_THT' doesn't match copy in library 'LED'
; warning
@(356.87 mm, 48.26 mm): Symbol D50 [NeoPixel_THT]
[lib_symbol_mismatch]: Symbol 'NeoPixel_THT' doesn't match copy in library 'LED'
; warning
@(356.87 mm, 80.01 mm): Symbol D40 [NeoPixel_THT]
[lib_symbol_mismatch]: Symbol 'NeoPixel_THT' doesn't match copy in library 'LED'
; warning
@(341.63 mm, 138.43 mm): Symbol D12 [NeoPixel_THT]
[lib_symbol_mismatch]: Symbol 'NeoPixel_THT' doesn't match copy in library 'LED'
; warning
@(356.87 mm, 107.95 mm): Symbol D26 [NeoPixel_THT]
[lib_symbol_mismatch]: Symbol 'NeoPixel_THT' doesn't match copy in library 'LED'
; warning
@(372.11 mm, 48.26 mm): Symbol D49 [NeoPixel_THT]
[lib_symbol_mismatch]: Symbol 'NeoPixel_THT' doesn't match copy in library 'LED'
; warning
@(372.11 mm, 80.01 mm): Symbol D39 [NeoPixel_THT]
[lib_symbol_mismatch]: Symbol 'NeoPixel_THT' doesn't match copy in library 'LED'
; warning
@(356.87 mm, 138.43 mm): Symbol D11 [NeoPixel_THT]
[lib_symbol_mismatch]: Symbol 'NeoPixel_THT' doesn't match copy in library 'LED'
; warning
@(372.11 mm, 107.95 mm): Symbol D25 [NeoPixel_THT]
[lib_symbol_mismatch]: Symbol 'NeoPixel_THT' doesn't match copy in library 'LED'
; warning
@(387.35 mm, 48.26 mm): Symbol D63 [NeoPixel_THT]
[lib_symbol_mismatch]: Symbol 'NeoPixel_THT' doesn't match copy in library 'LED'
; warning
@(387.35 mm, 80.01 mm): Symbol D38 [NeoPixel_THT]
[lib_symbol_mismatch]: Symbol 'NeoPixel_THT' doesn't match copy in library 'LED'
; warning
@(372.11 mm, 138.43 mm): Symbol D10 [NeoPixel_THT]
[lib_symbol_mismatch]: Symbol 'NeoPixel_THT' doesn't match copy in library 'LED'
; warning
@(387.35 mm, 107.95 mm): Symbol D24 [NeoPixel_THT]
[lib_symbol_mismatch]: Symbol 'NeoPixel_THT' doesn't match copy in library 'LED'
; warning
@(402.59 mm, 48.26 mm): Symbol D48 [NeoPixel_THT]
[lib_symbol_mismatch]: Symbol 'NeoPixel_THT' doesn't match copy in library 'LED'
; warning
@(402.59 mm, 80.01 mm): Symbol D37 [NeoPixel_THT]
[lib_symbol_mismatch]: Symbol 'NeoPixel_THT' doesn't match copy in library 'LED'
; warning
@(387.35 mm, 138.43 mm): Symbol D9 [NeoPixel_THT]
[lib_symbol_mismatch]: Symbol 'NeoPixel_THT' doesn't match copy in library 'LED'
; warning
@(402.59 mm, 107.95 mm): Symbol D23 [NeoPixel_THT]
[lib_symbol_mismatch]: Symbol 'NeoPixel_THT' doesn't match copy in library 'LED'
; warning
@(417.83 mm, 48.26 mm): Symbol D47 [NeoPixel_THT]
[lib_symbol_mismatch]: Symbol 'NeoPixel_THT' doesn't match copy in library 'LED'
; warning
@(417.83 mm, 80.01 mm): Symbol D36 [NeoPixel_THT]
[lib_symbol_mismatch]: Symbol 'NeoPixel_THT' doesn't match copy in library 'LED'
; warning
@(402.59 mm, 138.43 mm): Symbol D8 [NeoPixel_THT]
[lib_symbol_mismatch]: Symbol 'NeoPixel_THT' doesn't match copy in library 'LED'
; warning
@(417.83 mm, 107.95 mm): Symbol D22 [NeoPixel_THT]
[lib_symbol_mismatch]: Symbol 'NeoPixel_THT' doesn't match copy in library 'LED'
; warning
@(433.07 mm, 48.26 mm): Symbol D46 [NeoPixel_THT]
[lib_symbol_mismatch]: Symbol 'NeoPixel_THT' doesn't match copy in library 'LED'
; warning
@(417.83 mm, 138.43 mm): Symbol D7 [NeoPixel_THT]
[lib_symbol_mismatch]: Symbol 'NeoPixel_THT' doesn't match copy in library 'LED'
; warning
@(433.07 mm, 80.01 mm): Symbol D35 [NeoPixel_THT]
[lib_symbol_mismatch]: Symbol 'NeoPixel_THT' doesn't match copy in library 'LED'
; warning
@(433.07 mm, 107.95 mm): Symbol D21 [NeoPixel_THT]
[lib_symbol_mismatch]: Symbol 'NeoPixel_THT' doesn't match copy in library 'LED'
; warning
@(448.31 mm, 48.26 mm): Symbol D62 [NeoPixel_THT]
[lib_symbol_mismatch]: Symbol 'NeoPixel_THT' doesn't match copy in library 'LED'
; warning
@(433.07 mm, 138.43 mm): Symbol D6 [NeoPixel_THT]
[lib_symbol_mismatch]: Symbol 'NeoPixel_THT' doesn't match copy in library 'LED'
; warning
@(448.31 mm, 80.01 mm): Symbol D34 [NeoPixel_THT]
[lib_symbol_mismatch]: Symbol 'NeoPixel_THT' doesn't match copy in library 'LED'
; warning
@(448.31 mm, 107.95 mm): Symbol D20 [NeoPixel_THT]
[lib_symbol_mismatch]: Symbol 'NeoPixel_THT' doesn't match copy in library 'LED'
; warning
@(463.55 mm, 48.26 mm): Symbol D61 [NeoPixel_THT]
[lib_symbol_mismatch]: Symbol 'NeoPixel_THT' doesn't match copy in library 'LED'
; warning
@(448.31 mm, 138.43 mm): Symbol D5 [NeoPixel_THT]
[lib_symbol_mismatch]: Symbol 'NeoPixel_THT' doesn't match copy in library 'LED'
; warning
@(463.55 mm, 80.01 mm): Symbol D33 [NeoPixel_THT]
[lib_symbol_mismatch]: Symbol 'NeoPixel_THT' doesn't match copy in library 'LED'
; warning
@(463.55 mm, 107.95 mm): Symbol D19 [NeoPixel_THT]
[lib_symbol_mismatch]: Symbol 'NeoPixel_THT' doesn't match copy in library 'LED'
; warning
@(478.79 mm, 48.26 mm): Symbol D60 [NeoPixel_THT]
[lib_symbol_mismatch]: Symbol 'NeoPixel_THT' doesn't match copy in library 'LED'
; warning
@(463.55 mm, 138.43 mm): Symbol D4 [NeoPixel_THT]
[lib_symbol_mismatch]: Symbol 'NeoPixel_THT' doesn't match copy in library 'LED'
; warning
@(478.79 mm, 80.01 mm): Symbol D32 [NeoPixel_THT]
[lib_symbol_mismatch]: Symbol 'NeoPixel_THT' doesn't match copy in library 'LED'
; warning
@(478.79 mm, 107.95 mm): Symbol D18 [NeoPixel_THT]
[lib_symbol_mismatch]: Symbol 'NeoPixel_THT' doesn't match copy in library 'LED'
; warning
@(494.03 mm, 48.26 mm): Symbol D45 [NeoPixel_THT]
[lib_symbol_mismatch]: Symbol 'NeoPixel_THT' doesn't match copy in library 'LED'
; warning
@(478.79 mm, 138.43 mm): Symbol D3 [NeoPixel_THT]
[lib_symbol_mismatch]: Symbol 'NeoPixel_THT' doesn't match copy in library 'LED'
; warning
@(494.03 mm, 80.01 mm): Symbol D31 [NeoPixel_THT]
[lib_symbol_mismatch]: Symbol 'NeoPixel_THT' doesn't match copy in library 'LED'
; warning
@(494.03 mm, 107.95 mm): Symbol D17 [NeoPixel_THT]
[lib_symbol_mismatch]: Symbol 'NeoPixel_THT' doesn't match copy in library 'LED'
; warning
@(494.03 mm, 138.43 mm): Symbol D2 [NeoPixel_THT]
[lib_symbol_mismatch]: Symbol 'NeoPixel_THT' doesn't match copy in library 'LED'
; warning
@(509.27 mm, 107.95 mm): Symbol D16 [NeoPixel_THT]
[lib_symbol_mismatch]: Symbol 'NeoPixel_THT' doesn't match copy in library 'LED'
; warning
@(509.27 mm, 138.43 mm): Symbol D1 [NeoPixel_THT]
** ERC messages: 83 Errors 13 Warnings 70

BIN
docs/keyboard_schematic.pdf Normal file

Binary file not shown.

Binary file not shown.

After

Width:  |  Height:  |  Size: 5.7 KiB

BIN
res/keyboard_render.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 138 KiB

28
setup.py Normal file
View File

@@ -0,0 +1,28 @@
import sys
import os
import stat
from pathlib import Path
PYTHON_BIN = sys.executable
HOOK_SCRIPT_PATH = Path(".hooks/kicad_cli_tools.py")
HOOK_TYPE = "pre-push"
HOOK_PATH = Path(f".git/hooks/{HOOK_TYPE}")
# used if the hook path already exists we dont want to over write anything you have in there
# we would append however all of the default hooks have and `exit 0` which means it wont run
OLD_HOOK_PATH = Path(f".git/hooks/{HOOK_TYPE}-old")
if (os.path.exists(HOOK_PATH)):
os.rename(HOOK_PATH, OLD_HOOK_PATH)
with open(HOOK_PATH, "w") as txt:
txt.writelines([
"#!/bin/sh\n", #shebang
f"{PYTHON_BIN} {HOOK_SCRIPT_PATH}\n"
"exit 0\n" #make sure she closes
])
# make sure its executable
st = os.stat(HOOK_PATH)
os.chmod(HOOK_PATH, st.st_mode | stat.S_IEXEC)