Skip to content

Commit 1392be7

Browse files
authored
Support multi-pin assigns in footprint pinning (#509)
... and refactors some examples to use this. Also restructures STM microcontrollers to use the new system pindef style from #508 . Updates the STM32F103 JLC metadata to reflect the part choice change from a prior PR. Resolves #504
1 parent 5e0be14 commit 1392be7

26 files changed

Lines changed: 382 additions & 574 deletions

edg/abstract_parts/BaseIoControllerWrapped.py

Lines changed: 7 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -121,8 +121,10 @@ def _remap_assigns_to_value(assigns: Dict[str, Tuple[Optional[str], Optional[str
121121
return pin_assigns
122122

123123
def _make_pinning(
124-
self, fixed_pinning: Dict[str, Union[Passive, HasPassivePort]], remapping: Dict[str, str]
125-
) -> Dict[str, Union[Passive, HasPassivePort]]:
124+
self,
125+
fixed_pinning: Mapping[Union[Iterable[str], str], Union[Passive, HasPassivePort]],
126+
remapping: Dict[str, str],
127+
) -> Mapping[Union[Iterable[str], str], Union[Passive, HasPassivePort]]:
126128
"""Creates the footprint pinning dict for the wrapped footprint, given the fixed pinning and
127129
remapping from pin name to this footprint's pin number.
128130
This generates pinning for all BaseIoController IOs.
@@ -132,9 +134,10 @@ def _make_pinning(
132134
"""
133135
remapped_pin_assigns = self._remap_model_pin_assigns(remapping, self.get(self.pin_assigns))
134136
pin_dict = self._generator_pin_dict()
135-
fixed_pinning.update(self._remap_to_footprint_pinning(remapped_pin_assigns, pin_dict))
137+
pinning = dict(fixed_pinning)
138+
pinning.update(self._remap_to_footprint_pinning(remapped_pin_assigns, pin_dict))
136139
self.assign(self.actual_pin_assigns, self._remap_assigns_to_value(remapped_pin_assigns))
137-
return fixed_pinning
140+
return pinning
138141

139142

140143
class BaseIoControllerWrapper(BaseIoController):

edg/abstract_parts/IoController.py

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,5 @@
11
from itertools import chain
2-
from typing import List, Dict, Tuple, Type, Optional, Any, Union, Callable
2+
from typing import List, Dict, Tuple, Type, Optional, Any, Union, Callable, Mapping, Iterable
33
from typing_extensions import override
44
from deprecated import deprecated
55

@@ -272,15 +272,15 @@ def contents(self) -> None:
272272
self.generator_param(self.pin_assigns)
273273
self._generator_param_all_ios() # defined in contents() so subclass __init__ can define additional _io_ports
274274

275-
def _system_pinmap(self) -> Dict[str, Union[Passive, HasPassivePort]]:
275+
def _system_pinmap(self) -> Mapping[Union[Iterable[str], str], Union[Passive, HasPassivePort]]:
276276
"""Implement me. Defines the fixed pin mappings from pin number to port."""
277277
raise NotImplementedError
278278

279279
def _io_pinmap(self) -> PinMapUtil:
280280
"""Implement me. Defines the assignable IO pinmaps."""
281281
raise NotImplementedError
282282

283-
def _make_pinning(self) -> Dict[str, Union[Passive, HasPassivePort]]:
283+
def _make_pinning(self) -> Mapping[Union[Iterable[str], str], Union[Passive, HasPassivePort]]:
284284
allocation_list = []
285285
for io_port in self._io_ports:
286286
if isinstance(io_port, Vector): # derive Vector connections from requested

edg/electronics_model/CircuitBlock.py

Lines changed: 43 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
11
from __future__ import annotations
22

3-
from typing import Generic, Any, Optional, List, Mapping, Dict, Union, TYPE_CHECKING
3+
from typing import Generic, Any, Optional, Mapping, Dict, Union, TYPE_CHECKING, Tuple, Iterable, overload, Set
44

55
from deprecated import deprecated
66
from typing_extensions import TypeVar, override
@@ -36,12 +36,42 @@ def __init__(self, *args: Any, **kwargs: Any) -> None:
3636
self.fp_pnp_offset_x = self.Parameter(FloatExpr())
3737
self.fp_pnp_offset_y = self.Parameter(FloatExpr())
3838

39-
# TODO: allow value to be taken from parameters, ideally w/ string concat from params
39+
@overload
4040
def footprint(
4141
self,
4242
refdes: StringLike,
4343
footprint: StringLike,
44-
pinning: Mapping[str, Union["Passive", "HasPassivePort"]],
44+
pinning: Mapping[str, Union[Passive, HasPassivePort]],
45+
mfr: Optional[StringLike] = None,
46+
part: Optional[StringLike] = None,
47+
value: Optional[StringLike] = None,
48+
datasheet: Optional[StringLike] = None,
49+
pnp_rot: Optional[float] = None,
50+
pnp_offset: Optional[tuple[float, float]] = None,
51+
) -> None: ...
52+
53+
@overload
54+
def footprint(
55+
self,
56+
refdes: StringLike,
57+
footprint: StringLike,
58+
pinning: Mapping[Union[Iterable[str], str], Union[Passive, HasPassivePort]],
59+
mfr: Optional[StringLike] = None,
60+
part: Optional[StringLike] = None,
61+
value: Optional[StringLike] = None,
62+
datasheet: Optional[StringLike] = None,
63+
pnp_rot: Optional[float] = None,
64+
pnp_offset: Optional[tuple[float, float]] = None,
65+
) -> None: ...
66+
67+
def footprint(
68+
self,
69+
refdes: StringLike,
70+
footprint: StringLike,
71+
pinning: Union[
72+
Mapping[str, Union[Passive, HasPassivePort]],
73+
Mapping[Union[Iterable[str], str], Union[Passive, HasPassivePort]],
74+
],
4575
mfr: Optional[StringLike] = None,
4676
part: Optional[StringLike] = None,
4777
value: Optional[StringLike] = None,
@@ -75,12 +105,21 @@ def footprint(
75105
self.fp_is_footprint = self.Metadata("")
76106

77107
pinning_array = []
108+
assigned_pins: Set[str] = set()
78109
for pin_name, pin_port in pinning.items():
79110
if isinstance(pin_port, HasPassivePort):
80111
pin_port = pin_port.net
81112
if not isinstance(pin_port, (CircuitPort, Passive)):
82113
raise EdgTypeError(f"Footprint(...) pin", pin_port, Passive)
83-
pinning_array.append(f"{pin_name}={pin_port._name_from(self)}")
114+
115+
if isinstance(pin_name, str):
116+
pin_tuples: Tuple[str, ...] = (pin_name,)
117+
else:
118+
pin_tuples = tuple(iter(pin_name))
119+
for pin in pin_tuples:
120+
pinning_array.append(f"{pin}={pin_port._name_from(self)}")
121+
assert pin not in assigned_pins, f"duplicate pin name {pin} in footprint pinning"
122+
assigned_pins.add(pin)
84123
self.assign(self.fp_pinning, pinning_array)
85124

86125
self.assign(self.fp_footprint, footprint)

edg/electronics_model/KiCadSchematicBlock.py

Lines changed: 1 addition & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -86,12 +86,11 @@ def __init__(
8686
@override
8787
def generate(self) -> None:
8888
super().generate()
89-
mapping = {pin_name: self.ports.append_elt(Passive(), pin_name) for pin_name in self.get(self.kicad_pins)}
9089
self.ports.defined()
9190
self.footprint(
9291
self.kicad_refdes_prefix,
9392
self.kicad_footprint,
94-
mapping,
93+
{pin_name: self.ports.append_elt(Passive(), pin_name) for pin_name in self.get(self.kicad_pins)},
9594
part=self.kicad_part,
9695
value=self.kicad_value,
9796
datasheet=self.kicad_datasheet,

edg/parts/connector/UsbPorts.py

Lines changed: 5 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -61,22 +61,14 @@ def contents(self) -> None:
6161
"J",
6262
"Connector_USB:USB_C_Receptacle_XKB_U262-16XN-4BVC11",
6363
{
64-
"A1": self.gnd,
65-
"B12": self.gnd,
66-
"A4": self.pwr,
67-
"B9": self.pwr,
68-
"A5": self.cc.cc1,
69-
"A6": self.usb.dp,
70-
"A7": self.usb.dm,
64+
("A1", "B12", "B1", "A12"): self.gnd,
65+
("A4", "B9", "B4", "A9"): self.pwr,
66+
("A6", "B6"): self.usb.dp,
67+
("A7", "B7"): self.usb.dm,
7168
# 'A8': sbu1,
7269
# 'B8': sbu2
73-
"B7": self.usb.dm,
74-
"B6": self.usb.dp,
70+
"A5": self.cc.cc1,
7571
"B5": self.cc.cc2,
76-
"B4": self.pwr,
77-
"A9": self.pwr,
78-
"B1": self.gnd,
79-
"A12": self.gnd,
8072
"S1": self.shield,
8173
},
8274
mfr="Sparkfun",

edg/parts/display/oled/Nhd_312_25664uc.py

Lines changed: 2 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -43,16 +43,11 @@ def contents(self) -> None:
4343
"2": self.vdd,
4444
# '3': # no connect
4545
"4": self.dc,
46-
"5": self.vss, # R/nW in parallel interface
47-
"6": self.vss, # E/nRD in parallel interface
46+
("5", "6"): self.vss, # R/nW, E/nRD in parallel interface
4847
"7": self.sclk,
4948
"8": self.sdin,
5049
# '9' # no connect # DB2 in parallel interface
51-
"10": self.vss, # DB3 in parallel interface
52-
"11": self.vss, # DB4 in parallel interface
53-
"12": self.vss, # DB5 in parallel interface
54-
"13": self.vss, # DB6 in parallel interface
55-
"14": self.vss, # DB7 in parallel interface
50+
("10", "11", "12", "13", "14"): self.vss, # DB3-DB7 in parallel interface
5651
# '15': # no connect
5752
"16": self.nres,
5853
"17": self.ncs,

edg/parts/human_interface/Joystick_Xbox.py

Lines changed: 2 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -30,12 +30,9 @@ def contents(self) -> None:
3030
"edg:Joystick_XboxElite2",
3131
{
3232
"1": self.sw,
33-
"2": self.gnd,
34-
"3": self.gnd,
33+
("2", "3", "8"): self.gnd,
34+
("5", "6"): self.pwr,
3535
"4": self.ax1,
36-
"5": self.pwr,
37-
"6": self.pwr,
3836
"7": self.ax2,
39-
"8": self.gnd,
4037
},
4138
)

edg/parts/interface/UsbInterface_Ft232h.py

Lines changed: 3 additions & 14 deletions
Original file line numberDiff line numberDiff line change
@@ -94,22 +94,11 @@ def contents(self) -> None:
9494
"37": self.vcca,
9595
"38": self.vcccore,
9696
"39": self.vccd,
97-
"12": self.vccio,
98-
"24": self.vccio,
99-
"46": self.vccio,
97+
("12", "24", "46"): self.vccio,
10098
"8": self.vpll,
10199
"3": self.vphy,
102-
"4": self.gnd, # AGND
103-
"9": self.gnd, # AGND
104-
"41": self.gnd, # AGND
105-
"10": self.gnd,
106-
"11": self.gnd,
107-
"22": self.gnd,
108-
"23": self.gnd,
109-
"35": self.gnd,
110-
"36": self.gnd,
111-
"47": self.gnd,
112-
"48": self.gnd,
100+
("4", "9", "41"): self.gnd, # AGND
101+
("10", "11", "22", "23", "35", "36", "47", "48"): self.gnd,
113102
"1": self.osc.xtal_in,
114103
"2": self.osc.xtal_out,
115104
"5": self.ref,

edg/parts/interface/UsbPd_Fusb302b.py

Lines changed: 2 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -34,19 +34,16 @@ def contents(self) -> None:
3434
{
3535
"1": self.cc.cc2,
3636
"2": self.vbus,
37-
"3": self.vdd,
38-
"4": self.vdd,
37+
("3", "4"): self.vdd,
3938
"5": self.int_n,
4039
"6": self.i2c.scl,
4140
"7": self.i2c.sda,
42-
"8": self.gnd,
43-
"9": self.gnd,
41+
("8", "9", "15"): self.gnd,
4442
"10": self.cc.cc1,
4543
"11": self.cc.cc1,
4644
"12": self.vconn,
4745
"13": self.vconn,
4846
"14": self.cc.cc2,
49-
"15": self.gnd,
5047
},
5148
mfr="ON Semiconductor",
5249
part="FUSB302B11MPX", # actual several compatible variants

edg/parts/microcontroller/Esp32.py

Lines changed: 2 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -114,13 +114,10 @@ def generate(self) -> None:
114114
)
115115

116116
@override
117-
def _system_pinmap(self) -> Dict[str, Union[Passive, HasPassivePort]]:
117+
def _system_pinmap(self) -> Mapping[Union[Iterable[str], str], Union[Passive, HasPassivePort]]:
118118
return {
119119
"2": self.pwr,
120-
"1": self.gnd,
121-
"15": self.gnd,
122-
"38": self.gnd,
123-
"39": self.gnd, # EP
120+
("1", "15", "38", "39"): self.gnd,
124121
"3": self.chip_pu,
125122
"25": self.io0,
126123
"24": self.io2,
@@ -267,7 +264,6 @@ class Esp32_Wroom_32(
267264

268265
def __init__(self) -> None:
269266
super().__init__()
270-
self.ic: Esp32_Wroom_32_Device
271267
self.generator_param(self.reset.is_connected())
272268

273269
@override

0 commit comments

Comments
 (0)