Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

adding .ato file generation as an optional export #113

Open
wants to merge 1 commit into
base: master
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
58 changes: 55 additions & 3 deletions easyeda2kicad/__main__.py
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,7 @@
import sys
from textwrap import dedent
from typing import List
from pathlib import Path

from easyeda2kicad import __version__
from easyeda2kicad.easyeda.easyeda_api import EasyedaApi
Expand All @@ -26,6 +27,7 @@
from easyeda2kicad.kicad.export_kicad_footprint import ExporterFootprintKicad
from easyeda2kicad.kicad.export_kicad_symbol import ExporterSymbolKicad
from easyeda2kicad.kicad.parameters_kicad_symbol import KicadVersion
from easyeda2kicad.atopile.export_ato import ExporterAto


def get_parser() -> argparse.ArgumentParser:
Expand All @@ -39,6 +41,18 @@ def get_parser() -> argparse.ArgumentParser:

parser.add_argument("--lcsc_id", help="LCSC id", required=True, type=str)

parser.add_argument(
"--ato", help="Get atopile file definition of this id", required=False, action="store_true"
)

parser.add_argument(
"--ato_file_path",
required=False,
metavar="file.ato",
help="Output dir for .ato file",
type=str,
)

parser.add_argument(
"--symbol", help="Get symbol of this id", required=False, action="store_true"
)
Expand Down Expand Up @@ -114,9 +128,9 @@ def valid_arguments(arguments: dict) -> bool:
return False

if arguments["full"]:
arguments["symbol"], arguments["footprint"], arguments["3d"] = True, True, True
arguments["ato"], arguments["symbol"], arguments["footprint"], arguments["3d"] = True, True, True, True

if not any([arguments["symbol"], arguments["footprint"], arguments["3d"]]):
if not any([arguments["ato"], arguments["symbol"], arguments["footprint"], arguments["3d"]]):
logging.error(
"Missing action arguments\n"
" easyeda2kicad --lcsc_id=C2040 --footprint\n"
Expand Down Expand Up @@ -158,7 +172,7 @@ def valid_arguments(arguments: dict) -> bool:
"easyeda2kicad",
)
if not os.path.isdir(default_folder):
os.makedirs(default_folder, exist_ok=True)
os.mkdir(default_folder)

base_folder = default_folder
lib_name = "easyeda2kicad"
Expand Down Expand Up @@ -254,6 +268,44 @@ def main(argv: List[str] = sys.argv[1:]) -> int:
logging.error(f"Failed to fetch data from EasyEDA API for part {component_id}")
return 1


# ---------------- ATOPILE ----------------
if arguments["ato"]:
importer = EasyedaSymbolImporter(easyeda_cp_cad_data=cad_data)
easyeda_symbol: EeSymbol = importer.get_symbol()
# print(easyeda_symbol)
component_name=easyeda_symbol.info.name
# ato file path should be the the base directory of output argument /elec/src
ato_full_path = f"{arguments['ato_file_path']}/{component_name}.ato"
is_ato_already_in_lib_folder = os.path.isfile(ato_full_path)

if not arguments["overwrite"] and is_ato_already_in_lib_folder:
logging.error("Use --overwrite to update the older ato file")
return 1

footprint_importer = EasyedaFootprintImporter(easyeda_cp_cad_data=cad_data)
easyeda_footprint = footprint_importer.get_footprint()
package_name=easyeda_footprint.info.name

exporter = ExporterAto(
symbol = easyeda_symbol,
component_id = component_id,
component_name = component_name,
footprint = package_name
)
# print(exporter.output)
exporter.export(
ato_full_path = ato_full_path
)


logging.info(
f"Created Atopile file for ID : {component_id}\n"
f" Symbol name : {easyeda_symbol.info.name}\n"
f" Library path : {ato_full_path}"
)


# ---------------- SYMBOL ----------------
if arguments["symbol"]:
importer = EasyedaSymbolImporter(easyeda_cp_cad_data=cad_data)
Expand Down
98 changes: 98 additions & 0 deletions easyeda2kicad/atopile/export_ato.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,98 @@
# Global imports
import logging
from pathlib import Path

log = logging.getLogger(__name__)

from easyeda2kicad.easyeda.parameters_easyeda import (
EasyedaPinType,
EeSymbol,
)

ee_pin_type_to_ato_pin_type = {
EasyedaPinType.unspecified: None,
EasyedaPinType._input: "input",
EasyedaPinType.output: "output",
EasyedaPinType.bidirectional: "bidirectional",
EasyedaPinType.power: "power",
}
ee_pin_rotation_to_vis_side = {0: "right", 90: "bottom", 180: "left", 270: "top"}


def add_pin_vis(name, pos):
return f"""
- name: {name}
index: 0
private: false
port: {pos}"""


def convert_to_ato(
ee_symbol: EeSymbol, component_id: str, component_name: str, footprint: str
) -> str:
# replace spaces, dashes and slashes with underscores in component_name
component_name = component_name.replace(" ", "_").replace("-", "_").replace("/", "_")
ato_str = f"component {component_name}:\n"
ato_str += f' footprint = "{footprint}"\n'
ato_str += f' lcsc_id = "{component_id}"\n'
ato_str += f" # pins\n"
ato_str_types = " # pin types\n"
ato_str_vis = """
STM32F103C8T6:
ports:
- name: top
location: top
- name: right
location: right
- name: left
location: left
- name: bottom
location: bottom
pins:"""
for ee_pin in ee_symbol.pins:
signal = ee_pin.name.text.replace(" ", "").replace("-", "_").replace("/", "_")
# add an underscore to the start of the signal name if it starts with a number
if signal[0].isdigit():
signal = "_" + signal
pin = ee_pin.settings.spice_pin_number.replace(" ", "")
ato_str += f" signal {signal} ~ pin p{pin}\n"
ato_pin_type = ee_pin_type_to_ato_pin_type[ee_pin.settings.type]
if ato_pin_type:
ato_str_types += f" {signal}.type = {ato_pin_type}\n"
location = ee_pin_rotation_to_vis_side[ee_pin.settings.rotation]
ato_str_vis += add_pin_vis(signal, location)

return ato_str + "\n" + ato_str_types, ato_str_vis


class ExporterAto:
def __init__(self, symbol, component_id: str, component_name: str, footprint: str):
self.input: EeSymbol = symbol
self.output = (
convert_to_ato(
ee_symbol=self.input,
component_id=component_id,
component_name=component_name,
footprint=footprint,
)
if isinstance(self.input, EeSymbol)
else logging.error("Unknown input symbol format")
)

def export(self, ato_full_path: str) -> str:
# Get the directory of the file
ato_dir = Path(ato_full_path).parent
ato_dir.mkdir(parents=True, exist_ok=True)
log.log(level=logging.INFO, msg=ato_full_path)
with open(file=ato_full_path, mode="w", encoding="utf-8") as my_lib:
my_lib.write(self.output[0])
log.log(level=logging.INFO, msg="ATO file written")

ato_vis_path = ato_full_path.split(".ato")[0] + ".vis.yaml"
log.log(level=logging.INFO, msg=ato_vis_path)
with open(
file=ato_vis_path,
mode="w",
encoding="utf-8",
) as my_lib:
my_lib.write(self.output[1])
2 changes: 1 addition & 1 deletion requirements.txt
Original file line number Diff line number Diff line change
@@ -1,3 +1,3 @@
pre-commit>=2.17.0
pydantic>=2.0.0
requests>2.0.0
pre-commit>=2.17.0