diff options
-rw-r--r-- | gerbonara/aperture_macros/primitive.py | 4 | ||||
-rw-r--r-- | gerbonara/cad/primitives.py | 1 | ||||
-rw-r--r-- | gerbonara/cad/protoboard.py | 52 | ||||
-rw-r--r-- | gerbonara/cad/protoserve.py | 7 | ||||
-rw-r--r-- | gerbonara/cad/protoserve_data/protoserve.html | 48 |
5 files changed, 108 insertions, 4 deletions
diff --git a/gerbonara/aperture_macros/primitive.py b/gerbonara/aperture_macros/primitive.py index 31c5cb9..0c0d54c 100644 --- a/gerbonara/aperture_macros/primitive.py +++ b/gerbonara/aperture_macros/primitive.py @@ -97,8 +97,8 @@ class Circle(Primitive): exposure : Expression diameter : UnitExpression # center x/y - x : UnitExpression - y : UnitExpression + x : UnitExpression = 0 + y : UnitExpression = 0 rotation : Expression = 0 def to_graphic_primitives(self, offset, rotation, variable_binding={}, unit=None, polarity_dark=True): diff --git a/gerbonara/cad/primitives.py b/gerbonara/cad/primitives.py index 9c7d9dc..c659274 100644 --- a/gerbonara/cad/primitives.py +++ b/gerbonara/cad/primitives.py @@ -135,7 +135,6 @@ class Board: force_bounds=force_bounds) def pretty_svg(self, side='top', margin=0, arg_unit=MM, svg_unit=MM, force_bounds=None, inkscape=False, colors=None): - print('Pretty svg', side) return self.layer_stack().to_pretty_svg(side=side, margin=margin, arg_unit=arg_unit, svg_unit=svg_unit, force_bounds=force_bounds, inkscape=inkscape, colors=colors) diff --git a/gerbonara/cad/protoboard.py b/gerbonara/cad/protoboard.py index 7e43945..ff8bfd8 100644 --- a/gerbonara/cad/protoboard.py +++ b/gerbonara/cad/protoboard.py @@ -56,7 +56,7 @@ class ProtoBoard(Board): if not any(bbox_intersect(obj.bounding_box(unit), hole_bbox) for hole_bbox in hole_bboxes): self.add(obj, keepout_errors='ignore') else: - self.add(obj, keepout_errors='skip') + self.add(obj, keepout_errors='ignore') class PropLayout: @@ -715,6 +715,56 @@ class SpikyProto(ObjectGroup): return inst +@dataclass(frozen=True, slots=True) +class StarburstPad(PadStack): + # Starburst pattern inspired by elecfreaks' "flower" protoboard + pitch_x: float = 2.54 + pitch_y: float = 2.54 + trace_width_x: float = 1.4 + trace_width_y: float = 1.4 + clearance: float = 0.5 + drill: float = 0.9 + annular_ring: float = 1.2 + + @property + def apertures(self): + var = ParameterExpression + # parameters: [1: pitch_x, + # 2: trace_width_x, + # 3: pitch_y, + # 4: trace_width_y, + # 5: diagonal_clearance, + # 6: annular_ring_width] + starburst_macro = ApertureMacro('STARB', 6, primitives=( + amp.CenterLine(MM, 1, var(1), var(2)), + amp.CenterLine(MM, 1, var(4), var(3)), + amp.VectorLine(MM, 0, var(5), -var(1)/2, -var(3)/2, var(1)/2, var(3)/2), + amp.VectorLine(MM, 0, var(5), var(1)/2, -var(3)/2, -var(1)/2, var(3)/2), + amp.Circle(MM, 1, var(6)), + )) + + main_ap = ApertureMacroInstance(starburst_macro, (self.pitch_x - self.clearance,# 1 + self.trace_width_x, # 2 + self.pitch_y - self.clearance,# 3 + self.trace_width_y, # 4 + self.clearance, # 5 + self.annular_ring), unit=self.unit) # 6 + + mask_ap = ApertureMacroInstance(starburst_macro, (self.pitch_x, # 1 + self.trace_width_x, # 2 + self.pitch_y, # 3 + self.trace_width_y, # 4 + self.clearance, # 5 + self.annular_ring), unit=self.unit) # 6 + + yield PadStackAperture(main_ap, 'top', 'copper') + yield PadStackAperture(mask_ap, 'top', 'mask') + yield PadStackAperture(main_ap, 'bottom', 'copper') + yield PadStackAperture(mask_ap, 'bottom', 'mask') + + drill = ExcellonTool(self.drill, plated=True, unit=self.unit) + yield PadStackAperture(drill, 'drill', 'plated', 0, 0) + class AlioCell(Positioned): """ Cell primitive for the ALio protoboard designed by arief ibrahim adha and published on hackaday.io at the URL below. Similar to electroniceel's spiky protoboard, this layout has small-ish standard THT pads, but in between diff --git a/gerbonara/cad/protoserve.py b/gerbonara/cad/protoserve.py index a2aa7d6..68f401c 100644 --- a/gerbonara/cad/protoserve.py +++ b/gerbonara/cad/protoserve.py @@ -129,6 +129,13 @@ def deserialize(obj, unit): via_size=via_size ), margin=unit(1.5, MM), unit=unit) + case 'starburst': + trace_width_x = float(obj.get('trace_width_x', 1.8)) + trace_width_y = float(obj.get('trace_width_y', 1.8)) + drill = float(obj.get('hole_dia', 0.9)) + annular_ring = float(obj.get('annular', 1.2)) + return pb.PatternProtoArea(pitch_x, pitch_y, pb.StarburstPad(pitch_x, pitch_y, trace_width_x, trace_width_y, clearance, drill, annular_ring, unit=unit), unit=unit) + case 'rf': pitch = float(obj.get('pitch', 2.54)) hole_dia = float(obj['hole_dia']) diff --git a/gerbonara/cad/protoserve_data/protoserve.html b/gerbonara/cad/protoserve_data/protoserve.html index e1d00b3..e454f87 100644 --- a/gerbonara/cad/protoserve_data/protoserve.html +++ b/gerbonara/cad/protoserve_data/protoserve.html @@ -411,6 +411,7 @@ input[type="text"]:focus:valid { <a href="#" data-placeholder="rf" class="double-sided-only">RF THT area</a> <a href="#" data-placeholder="spiky" class="double-sided-only">Spiky hybrid area</a> <a href="#" data-placeholder="alio" class="double-sided-only">ALio hybrid area</a> + <a href="#" data-placeholder="starburst" class="double-sided-only">THT starburst area</a> </div> </div> </template> @@ -709,6 +710,53 @@ input[type="text"]:focus:valid { </div> </template> + <template id="tpl-g-starburst"> + <div data-type="starburst" class="group starburst"> + <h4>Starburst area</h4> + <span class="content area-controls">(<a href="#" class="area-remove">Remove</a><a href="#" class="area-move">Move</a>)</span> + <label class="proportion">Proportion + <input type="text" name="layout_prop" value="1" pattern="[0-9]+\.?[0-9]*"/> + </label> + + <h5>Area Settings</h5> + <label>Pitch X + <input type="text" name="pitch_x" placeholder="length" value="2.54" pattern="[0-9]+\.?[0-9]*"/> + <span class="unit metric">mm</span> + <span class="unit us">mil</span> + </label> + <label>Pitch Y + <input type="text" name="pitch_y" placeholder="length" value="2.54" pattern="[0-9]+\.?[0-9]*"/> + <span class="unit metric">mm</span> + <span class="unit us">mil</span> + </label> + <label>Drill diameter + <input type="text" name="drill" placeholder="length" value="0.9" pattern="[0-9]+\.?[0-9]*"/> + <span class="unit metric">mm</span> + <span class="unit us">mil</span> + </label> + <label>Annular ring + <input type="text" name="annular" placeholder="length" value="1.2" pattern="[0-9]+\.?[0-9]*"/> + <span class="unit metric">mm</span> + <span class="unit us">mil</span> + </label> + <label>Clearance + <input type="text" name="clearance" placeholder="length" value="0.5" pattern="[0-9]+\.?[0-9]*"/> + <span class="unit metric">mm</span> + <span class="unit us">mil</span> + </label> + <label>Trace width X + <input type="text" name="trace_width_x" placeholder="length" value="1.40" pattern="[0-9]+\.?[0-9]*"/> + <span class="unit metric">mm</span> + <span class="unit us">mil</span> + </label> + <label>Trace width Y + <input type="text" name="trace_width_y" placeholder="length" value="1.40" pattern="[0-9]+\.?[0-9]*"/> + <span class="unit metric">mm</span> + <span class="unit us">mil</span> + </label> + </div> + </template> + <script> document.querySelectorAll('.expand').forEach((elem) => { const checkbox = elem.querySelector(':first-child > input'); |