Source code for jitxlib.landpatterns.generators.header

"""
The Pin Header Landpattern Generator
====================================

Pin headers are through-hole or surface-mount connectors with pins arranged
in rows. This module provides generators for creating header landpatterns.

The Header landpattern has three entry points:

- :py:class:`~Header`: Complete generator with linear numbering
- :py:class:`~HeaderDecorated`: With silkscreen but no numbering
- :py:class:`~HeaderBase`: Basic pads only

Lead Types:
    - :py:class:`~jitxlib.landpatterns.leads.THLead`: Through-hole pins
    - :py:class:`~jitxlib.landpatterns.leads.SMDLead`: Surface-mount pins

2x5 through-hole header::

    >>> from jitx import Component, Port
    >>> from jitxlib.landpatterns.generators.header import Header
    >>> from jitxlib.landpatterns.leads import THLead
    >>> from jitx.toleranced import Toleranced as T
    >>>
    >>> class PinHeader2x5(Component):
    ...     pins = [Port() for _ in range(10)]
    ...     def __init__(self):
    ...         self.landpattern = Header(
    ...             num_leads=10,
    ...             num_rows=2,
    ...             lead=THLead(
    ...                 length=T(3.0, 0.1),  # Pin length
    ...                 width=T(0.64, 0.05), # Pin diameter
    ...             ),
    ...             pitch=2.54,  # Standard 0.1" pitch
    ...         )

1x6 SMD header::

    >>> from jitxlib.landpatterns.leads import SMDLead
    >>>
    >>> class SMDHeader1x6(Component):
    ...     pins = [Port() for _ in range(6)]
    ...     def __init__(self):
    ...         self.landpattern = Header(
    ...             num_leads=6,
    ...             num_rows=1,
    ...             lead=SMDLead(
    ...                 length=T(1.5, 0.1),
    ...                 width=T(0.5, 0.05),
    ...             ),
    ...             pitch=2.0,
    ...         )
"""

from collections.abc import Iterable
from typing import override

from jitx.shapes import Shape
from jitx.shapes.composites import rectangle
from jitx.shapes.primitive import Circle
from jitx.transform import Transform

from .. import LandpatternGenerator
from ..courtyard import ExcessCourtyard
from ..grid_layout import ColumnMajorOrder, GridPosition, LinearNumbering
from ..grid_planner import GridPlannerMixin
from ..ipc import DensityLevelMixin
from ..leads import SMDLead, THLead
from ..pads import GridPadShapeGeneratorMixin, IPCTHPadConfig
from ..silkscreen.outlines import SilkscreenOutline


[docs] class HeaderBase( ColumnMajorOrder, DensityLevelMixin, GridPlannerMixin, GridPadShapeGeneratorMixin, LandpatternGenerator, ): """Pin Header Landpattern Generator Base""" def __init__( self, num_leads: int, num_rows: int, lead: SMDLead | THLead, pitch: float | tuple[float, float], ): super().__init__() self.pad_config(IPCTHPadConfig()) if num_leads <= 0: raise ValueError("num_leads must be positive") if num_rows <= 0: raise ValueError("num_rows must be positive") if num_leads % num_rows != 0: raise ValueError("num_leads must be a multiple of num_rows") self._num_leads = num_leads self._num_rows = num_rows self._num_cols = num_leads // num_rows self.__pitch = pitch self.__lead = lead @override def _pad_shape(self, pos: GridPosition) -> Shape: match self.__lead: case SMDLead(): dims = self.__lead.pad_size(self._density_level) return rectangle(dims[0], dims[1]) case THLead(): return Circle(diameter=self.__lead.width.typ) case _: raise ValueError("Invalid lead type") @override def _generate_layout(self) -> Iterable[GridPosition]: if isinstance(self.__pitch, tuple): hpitch, vpitch = self.__pitch else: hpitch = self.__pitch vpitch = self.__pitch x_base = -hpitch * (self._num_cols - 1) / 2.0 y_base = vpitch * (self._num_rows - 1) / 2.0 for c in range(self._num_cols): col_x = x_base + c * hpitch for r in range(self._num_rows): row_y = y_base - r * vpitch yield GridPosition(r, c, Transform.translate(col_x, row_y))
[docs] class HeaderDecorated(SilkscreenOutline, ExcessCourtyard, HeaderBase): pass