kicad/generate_jst.py

149 lines
5.0 KiB
Python
Raw Normal View History

2022-10-29 15:26:27 -06:00
import time
import zipfile
from pathlib import Path
from tempfile import TemporaryDirectory
from typing import Literal, Optional, Union
import numpy as np
import regex as re
from selenium import webdriver
from selenium.webdriver.support.select import By
from fp_generator import INCH, Footprint
dir_ = Path(__file__).parent
PARTS = [
# JST-SH, Right angle
*[f"SM{i:02d}B-SRSS-TB" for i in range(2, 16)],
# JST-SH, Vertical
# *[f"BM{i:02d}B-SRSS-TB" for i in range(2, 16)],
]
def round2grid(val: float, direction: Optional[Literal["up", "down"]] = None, grid: float = 0.005 * INCH):
if direction == "up":
val = val + grid / 2
elif direction == "down":
val = val - grid / 2
return np.round(val / grid) * grid
def download_step(part: Union[str, int], headless: bool = True) -> None:
print(part)
with TemporaryDirectory(prefix=str(dir_ / "tmp") + "/") as tmp:
tmp = Path(tmp)
chrome_options = webdriver.ChromeOptions()
chrome_options.add_experimental_option(
"prefs",
{"download.default_directory": str(tmp)},
)
if headless:
chrome_options.add_argument("--headless")
with webdriver.Chrome(
options=chrome_options,
) as browser:
browser.get(
f"https://www.jst-mfg.com/product/index.php?type=10&series=231&doc=2&filename={part.upper()}.zip"
)
browser.implicitly_wait(10)
browser.find_element(by=By.ID, value="company").send_keys("N/A")
browser.find_element(by=By.ID, value="section").send_keys("N/A")
browser.find_element(by=By.ID, value="name").send_keys("Brendan Haines")
browser.find_element(by=By.ID, value="address").send_keys("7415 Spy Glass Ct")
browser.find_element(by=By.ID, value="tel").send_keys("(505) 738-6174")
browser.find_element(by=By.ID, value="email").send_keys("brendan.haines@gmail.com")
# browser.find_element(by=By.ID, value="url").send_keys("")
browser.find_element(by=By.XPATH, value="//input[@type='button' and @value='I agree']").click()
# wait for download to finish
while len(list((Path(tmp).glob("*.zip")))) == 0:
time.sleep(0.1)
# print(list((Path(tmp).glob("*.zip"))))
# unzip
with zipfile.ZipFile(tmp / f"{part.upper()}.zip") as zip:
zip.extractall(path=tmp)
# move
2022-10-29 21:25:03 -06:00
(Path(tmp) / f"{part.upper()}.STEP").rename(dir_ / "jst.pretty" / "step" / f"{part.upper()}.stp")
2022-10-29 15:26:27 -06:00
def footprint(part: str, lib: Optional[Union[Path, str]] = None):
print(part)
if lib is None:
lib = dir_ / "jst.pretty"
lib = Path(lib)
if part.startswith("SM"):
# Right angle
match = re.match(r"SM(\d\d)B-SRSS-TB", part)
pins = int(match[1])
fp = Footprint(part, lib=lib, description=f"connector, JST-SH, 1x{pins:02f}, RA")
2022-10-29 15:26:27 -06:00
fp.add_text("reference", "REF**", (5.55 + (0.025 + 0.005) * INCH), 0, rotation=90, layer="F.SilkS")
fp.add_text("value", "VAL**", 4 * 0.025 * INCH, 0, rotation=90, layer="F.Fab")
fp.add_text("user", r"${REFERENCE}**", 2 * 0.025 * INCH, 0, rotation=90, layer="F.Fab")
a, b = {
2: (1, 4),
3: (2, 5),
4: (3, 6),
5: (4, 7),
6: (5, 8),
7: (6, 9),
8: (7, 10),
9: (8, 11),
10: (9, 12),
11: (10, 13),
12: (11, 14),
13: (12, 15),
14: (13, 16),
15: (14, 17),
20: (19, 22),
}[pins]
# fp.add_line((0.05 * INCH, -0.05 * INCH), (0.05 * INCH, 0.05 * INCH), layer="F.SilkS")
for pad in range(pins):
fp.add_pad(
pad + 1,
4 + (5.55 - 4) / 2,
-1.0 * (pins - 1) / 2 + 1.0 * pad,
size=(5.55 - 4, 0.6),
shape="rect",
)
# mechanical holes
for s in [1, -1]:
fp.add_pad(0, 1.8 / 2, s * (1.0 * (pins - 1) / 2 + 0.7 + 1.2 / 2), size=(1.8, 1.2), shape="rect")
fp.add_model(
2022-10-29 21:25:03 -06:00
lib / "step" / f"{part}.stp",
2022-10-29 15:26:27 -06:00
(4, 0, -0.3),
rotate=(-90, 0, 90),
)
fp.add_rect((0.2, -b / 2), (0.2 + 4.25, b / 2), layer="F.Fab")
for s in [1, -1]:
fp.add_line(
(0.190 * INCH, s * round2grid((a + 0.6) / 2 + 0.010 * INCH, "up")),
(0.190 * INCH, s * round2grid(b / 2 + 0.010 * INCH, "up")),
layer="F.SilkS",
)
fp.add_line(
(0.190 * INCH, s * round2grid(b / 2 + 0.010 * INCH, "up")),
(round2grid(1.8 + 0.010 * INCH), s * round2grid(b / 2 + 0.010 * INCH, "up")),
layer="F.SilkS",
)
fp.write()
2022-10-29 15:26:27 -06:00
else:
raise NotImplementedError
if __name__ == "__main__":
from multiprocessing import Pool
pool = Pool(10)
# pool.map(download_step, PARTS)
for part in PARTS:
footprint(part)
pool.close()