Source code for jitxlib.landpatterns.dual
from typing import overload
from collections.abc import Iterable, Sequence
from jitx.shapes import Shape
from jitx.shapes.composites import rectangle
from jitx.transform import Transform
from .grid_layout import GridPosition, GridLandpatternGenerator, ColumnMajorOrder
from .pads import GridPadShapeGeneratorMixin
from .leads import LeadProfileMixin
[docs]
class DualColumnLeadShape(LeadProfileMixin, GridPadShapeGeneratorMixin):
def _pad_shape(self, pos: GridPosition) -> Shape:
profiles = self._lead_profiles_optional
if profiles is None:
return super()._pad_shape(pos)
p = _oneway(profiles)
w, h = p.compute_placements(self._density_level).pad_size
return self._pad_rectangle(w, h)
def _pad_rectangle(self, width: float, height: float) -> Shape:
return rectangle(width, height)
def _oneway[T](seq: Sequence[T]) -> T:
return seq[0]
[docs]
class DualColumn(
ColumnMajorOrder,
DualColumnLeadShape,
GridLandpatternGenerator,
):
"""Dual Column Pad Generator
This class constructs the pad grid for dual column (otherwise called dual
row) component such as a SOIC or SOP.
The idea is that the grid gets constructed in a way that is conducive
for making the landpattern. For example:
.. code-block:: text
Left-Row Col 0 Col 1 Right-Row
0 1 8 3
1 2 7 2
2 3 6 1
3 4 5 0
Notice how Column 1 is rotated 180 degrees relative to Column 0.
"""
_num_cols = 2
@overload
def __init__(self, *, num_rows: int): ...
@overload
def __init__(self, *, num_leads: int): ...
def __init__(self, *, num_rows: int | None = None, num_leads: int | None = None):
super().__init__()
if num_rows is not None:
self._num_rows = num_rows
elif num_leads is not None:
if num_leads % 2 != 0:
raise ValueError("num_leads must be a multiple of 2")
self._num_rows = num_leads // 2
else:
raise ValueError("Either num_rows or num_leads must be specified")
def _generate_layout(self) -> Iterable[GridPosition]:
placement = _oneway(self._lead_placements())
for c in range(self._num_cols):
# For column 0 (negative X half-plane) - no rotation applied
# This places pads 1-> N/2 in ascending order.
# For column 1 (positive X half-plane) - 180 rotation applied
# This places pads (N/2 + 1) -> N in descending order
rot = 180.0 * c
offset = Transform.rotate(rot) * Transform.translate(
-placement.center / 2.0, 0.0
)
num_rows = self._num_rows
center_row = (num_rows - 1) / 2.0
for r in range(num_rows):
y = (center_row - r) * placement.pitch
tx = offset * Transform.translate(0.0, y)
yield GridPosition(r, c, tx)