Skip to content

Commit beb9736

Browse files
authored
Prefer part selector footprint by smaller area (#375)
A cleaner version of sorting parts instead of by footprint name before, which mostly worked for 0402, ..., but did awful things for diodes. Also replaces the smd-min-package with a footprint (courtyard) area range. The default is set around 0603 (4mm^2). Removes a bunch of footprint refinements on example designs, these mostly were to get reasonable diode / FET selections. The area-minimization now handles it. Some examples go from SOD-123 to SOD-323. The footprint area calculator does not handle arcs, that may be future work. Some cleanup of the existing parts tables, to unify sorting criteria and deduplicate code. A future PR will refactor those parts more.
1 parent 568ce9b commit beb9736

File tree

95 files changed

+13034
-532
lines changed

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

95 files changed

+13034
-532
lines changed

edg/BoardTop.py

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -42,7 +42,7 @@ def refinements(self) -> Refinements:
4242

4343
(Speaker, ConnectorSpeaker),
4444
], class_values=[
45-
(SmdStandardPackage, ['smd_min_package'], '0603'),
45+
(SelectorArea, ['footprint_area'], Range.from_lower(4.0)), # at least 0603
4646
]
4747
)
4848

edg/abstract_parts/AbstractCapacitor.py

Lines changed: 0 additions & 14 deletions
Original file line numberDiff line numberDiff line change
@@ -168,20 +168,6 @@ class CapacitorStandardFootprint(Capacitor, StandardFootprint[Capacitor]):
168168
},
169169
}
170170

171-
SMD_FOOTPRINT_MAP = {
172-
'01005': None,
173-
'0201': 'Capacitor_SMD:C_0201_0603Metric',
174-
'0402': 'Capacitor_SMD:C_0402_1005Metric',
175-
'0603': 'Capacitor_SMD:C_0603_1608Metric',
176-
'0805': 'Capacitor_SMD:C_0805_2012Metric',
177-
'1206': 'Capacitor_SMD:C_1206_3216Metric',
178-
'1210': 'Capacitor_SMD:C_1210_3225Metric',
179-
'1806': None,
180-
'1812': 'Capacitor_SMD:C_1812_4532Metric',
181-
'2010': None,
182-
'2512': 'Capacitor_SMD:C_2512_6332Metric',
183-
}
184-
185171

186172
@non_library
187173
class TableCapacitor(CapacitorStandardFootprint, PartsTableFootprintSelector):

edg/abstract_parts/AbstractFerriteBead.py

Lines changed: 0 additions & 14 deletions
Original file line numberDiff line numberDiff line change
@@ -63,20 +63,6 @@ class FerriteBeadStandardFootprint(FerriteBead, StandardFootprint[FerriteBead]):
6363
},
6464
}
6565

66-
SMD_FOOTPRINT_MAP = {
67-
'01005': None,
68-
'0201': 'Inductor_SMD:L_0201_0603Metric',
69-
'0402': 'Inductor_SMD:L_0402_1005Metric',
70-
'0603': 'Inductor_SMD:L_0603_1608Metric',
71-
'0805': 'Inductor_SMD:L_0805_2012Metric',
72-
'1206': 'Inductor_SMD:L_1206_3216Metric',
73-
'1210': 'Inductor_SMD:L_1210_3225Metric',
74-
'1806': None,
75-
'1812': 'Inductor_SMD:L_1812_4532Metric',
76-
'2010': 'Inductor_SMD:L_2010_5025Metric',
77-
'2512': 'Inductor_SMD:L_2512_6332Metric',
78-
}
79-
8066

8167
@non_library
8268
class TableFerriteBead(FerriteBeadStandardFootprint, PartsTableFootprintSelector):

edg/abstract_parts/AbstractFuse.py

Lines changed: 0 additions & 14 deletions
Original file line numberDiff line numberDiff line change
@@ -71,20 +71,6 @@ class FuseStandardFootprint(Fuse, StandardFootprint[Fuse]):
7171
},
7272
}
7373

74-
SMD_FOOTPRINT_MAP = {
75-
'01005': None,
76-
'0201': 'Resistor_SMD:R_0201_0603Metric',
77-
'0402': 'Resistor_SMD:R_0402_1005Metric',
78-
'0603': 'Resistor_SMD:R_0603_1608Metric',
79-
'0805': 'Resistor_SMD:R_0805_2012Metric',
80-
'1206': 'Resistor_SMD:R_1206_3216Metric',
81-
'1210': 'Resistor_SMD:R_1210_3225Metric',
82-
'1806': None,
83-
'1812': 'Resistor_SMD:R_1812_4532Metric',
84-
'2010': 'Resistor_SMD:R_2010_5025Metric',
85-
'2512': 'Resistor_SMD:R_2512_6332Metric',
86-
}
87-
8874

8975
@non_library
9076
class TableFuse(FuseStandardFootprint, PartsTableFootprintSelector):

edg/abstract_parts/AbstractInductor.py

Lines changed: 0 additions & 14 deletions
Original file line numberDiff line numberDiff line change
@@ -120,20 +120,6 @@ class InductorStandardFootprint(Inductor, StandardFootprint[Inductor]):
120120
},
121121
}
122122

123-
SMD_FOOTPRINT_MAP = {
124-
'01005': None,
125-
'0201': 'Inductor_SMD:L_0201_0603Metric',
126-
'0402': 'Inductor_SMD:L_0402_1005Metric',
127-
'0603': 'Inductor_SMD:L_0603_1608Metric',
128-
'0805': 'Inductor_SMD:L_0805_2012Metric',
129-
'1206': 'Inductor_SMD:L_1206_3216Metric',
130-
'1210': 'Inductor_SMD:L_1210_3225Metric',
131-
'1806': None,
132-
'1812': 'Inductor_SMD:L_1812_4532Metric',
133-
'2010': 'Inductor_SMD:L_2010_5025Metric',
134-
'2512': 'Inductor_SMD:L_2512_6332Metric',
135-
}
136-
137123

138124
@non_library
139125
class TableInductor(InductorStandardFootprint, PartsTableFootprintSelector):

edg/abstract_parts/AbstractLed.py

Lines changed: 0 additions & 14 deletions
Original file line numberDiff line numberDiff line change
@@ -48,20 +48,6 @@ class LedStandardFootprint(Led, StandardFootprint[Led]):
4848
},
4949
}
5050

51-
SMD_FOOTPRINT_MAP = {
52-
'01005': None,
53-
'0201': None,
54-
'0402': 'LED_SMD:LED_0402_1005Metric',
55-
'0603': 'LED_SMD:LED_0603_1608Metric',
56-
'0805': 'LED_SMD:LED_0805_2012Metric',
57-
'1206': 'LED_SMD:LED_1206_3216Metric',
58-
'1210': None,
59-
'1806': None,
60-
'1812': None,
61-
'2010': None,
62-
'2512': None,
63-
}
64-
6551

6652
@non_library
6753
class TableLed(LedStandardFootprint, PartsTableFootprintSelector):

edg/abstract_parts/AbstractResistor.py

Lines changed: 0 additions & 14 deletions
Original file line numberDiff line numberDiff line change
@@ -95,20 +95,6 @@ class ResistorStandardFootprint(Resistor, StandardFootprint[Resistor]):
9595
},
9696
}
9797

98-
SMD_FOOTPRINT_MAP = {
99-
'01005': None,
100-
'0201': 'Resistor_SMD:R_0201_0603Metric',
101-
'0402': 'Resistor_SMD:R_0402_1005Metric',
102-
'0603': 'Resistor_SMD:R_0603_1608Metric',
103-
'0805': 'Resistor_SMD:R_0805_2012Metric',
104-
'1206': 'Resistor_SMD:R_1206_3216Metric',
105-
'1210': 'Resistor_SMD:R_1210_3225Metric',
106-
'1806': None,
107-
'1812': None,
108-
'2010': 'Resistor_SMD:R_2010_5025Metric',
109-
'2512': 'Resistor_SMD:R_2512_6332Metric',
110-
}
111-
11298

11399
@non_library
114100
class TableResistor(ResistorStandardFootprint, PartsTableFootprintSelector):

edg/abstract_parts/SelectorArea.py

Lines changed: 57 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,57 @@
1+
from typing import Optional
2+
3+
from pydantic import RootModel
4+
import os
5+
6+
from ..electronics_model import *
7+
from .PartsTable import PartsTableRow
8+
from .PartsTablePart import PartsTableFootprintSelector
9+
10+
11+
class FootprintJson(RootModel): # script relpath imports are weird so this is duplicated here
12+
root: dict[str, float] # footprint name -> area
13+
14+
15+
class FootprintAreaTable:
16+
_table: Optional[FootprintJson] = None
17+
18+
@classmethod
19+
def area_of(cls, footprint: str) -> float:
20+
"""Returns the area of a footprint, returning infinity if unavailable"""
21+
if cls._table is None:
22+
with open(os.path.join(os.path.dirname(__file__), "resources", "kicad_footprints.json"), 'r') as f:
23+
cls._table = FootprintJson.model_validate_json(f.read())
24+
return cls._table.root.get(footprint) or float('inf')
25+
26+
27+
@abstract_block
28+
class SelectorArea(BlockInterfaceMixin[Block]):
29+
"""A base mixin that defines a footprint_area range specification for blocks that automatically select parts.
30+
Provides no implementation, only defines the specification parameter.
31+
32+
Some common areas for SMD parts:
33+
01005 R=0.72 C=0.72 D=0.72
34+
0201 R=0.98 C=0.98 D=0.98
35+
0402 R=1.7484 C=1.6744 D=1.7484
36+
0603 R=4.3216 C=4.3216 D=4.3216
37+
0805 R=6.384 C=6.664 D=6.384
38+
1206 R=10.2144 C=10.58 D=10.2144
39+
1812 R=23.01 C=23.4 D=23.01
40+
2512 R=29.3376 D=29.3376
41+
"""
42+
@init_in_parent
43+
def __init__(self, *args, footprint_area: RangeLike = RangeExpr.ALL, **kwargs):
44+
super().__init__(*args, **kwargs)
45+
self.footprint_area = self.ArgParameter(footprint_area)
46+
47+
48+
@non_library
49+
class PartsTableAreaSelector(SelectorArea, PartsTableFootprintSelector):
50+
"""Defines an implementation for the area selector using parts tables and KICAD_FOOTPRINT."""
51+
def __init__(self, *args, **kwargs):
52+
super().__init__(*args, **kwargs)
53+
self.generator_param(self.footprint_area)
54+
55+
def _row_filter(self, row: PartsTableRow) -> bool:
56+
return super()._row_filter(row) and \
57+
(Range.exact(FootprintAreaTable.area_of(row[self.KICAD_FOOTPRINT])).fuzzy_in(self.get(self.footprint_area)))

edg/abstract_parts/SmdStandardPackage.py

Lines changed: 0 additions & 66 deletions
This file was deleted.

edg/abstract_parts/__init__.py

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -21,7 +21,7 @@
2121
from .Categories import MultipackDevice
2222

2323
from .ESeriesUtil import ESeriesUtil
24-
from .SmdStandardPackage import SmdStandardPackage, SmdStandardPackageSelector
24+
from .SelectorArea import SelectorArea, PartsTableAreaSelector, FootprintAreaTable
2525

2626
from .AbstractDevices import Battery
2727
from .AbstractConnector import BananaJack, BananaSafetyJack, RfConnector, RfConnectorTestPoint, UflConnector

0 commit comments

Comments
 (0)