[Global options][Add] Option to remove solder mask apertures

`remove_solder_mask_for_dnp` similar to `remove_solder_paste_for_dnp`
but applied to the solder mask apertures.

Closes #476
This commit is contained in:
Salvador E. Tropea 2023-08-04 12:31:17 -03:00
parent 9c6ca87214
commit abeea7ec03
7 changed files with 50 additions and 11 deletions

View File

@ -7,6 +7,9 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0
## [1.6.4] - UNRELEASED
### Added
- Global options:
- `remove_solder_mask_for_dnp` similar to `remove_solder_paste_for_dnp` but
applied to the solder mask apertures. (#476)
- BoM:
- Support for ${field} expansion. (#471)
- iBoM:

View File

@ -876,6 +876,7 @@ global:
- `pcb_material`: [string='FR4'] PCB core material. Currently used for documentation and to choose default colors.
Currently known are FR1 to FR5.
- `remove_adhesive_for_dnp`: [boolean=true] When applying filters and variants remove the adhesive (glue) for components that won't be included.
- `remove_solder_mask_for_dnp`: [boolean=false] When applying filters and variants remove the solder mask apertures for components that won't be included.
- `remove_solder_paste_for_dnp`: [boolean=true] When applying filters and variants remove the solder paste for components that won't be included.
- `resources_dir`: [string='kibot_resources'] Directory where various resources are stored. Currently we support colors and fonts.
They must be stored in sub-dirs. I.e. kibot_resources/fonts/MyFont.ttf

View File

@ -233,6 +233,8 @@ class Globals(FiltersOptions):
""" When applying filters and variants remove the solder paste for components that won't be included """
self.remove_adhesive_for_dnp = True
""" When applying filters and variants remove the adhesive (glue) for components that won't be included """
self.remove_solder_mask_for_dnp = False
""" When applying filters and variants remove the solder mask apertures for components that won't be included """
self.restore_project = False
""" Restore the KiCad project after execution.
Note that this option will undo operations like `set_text_variables` """

View File

@ -165,6 +165,7 @@ class GS(object):
global_pcb_finish = None
global_pcb_material = None
global_remove_solder_paste_for_dnp = None
global_remove_solder_mask_for_dnp = None
global_remove_adhesive_for_dnp = None
global_resources_dir = None
global_restore_project = None

View File

@ -377,9 +377,10 @@ class VariantOptions(BaseOptions):
def remove_paste_and_glue(self, board, comps_hash):
""" Remove from solder paste layers the filtered components. """
if comps_hash is None or not (GS.global_remove_solder_paste_for_dnp or GS.global_remove_adhesive_for_dnp):
if comps_hash is None or not (GS.global_remove_solder_paste_for_dnp or GS.global_remove_adhesive_for_dnp or
GS.remove_solder_mask_for_dnp):
return
logger.debug('Removing paste and glue')
logger.debug('Removing paste, mask and/or glue')
exclude = LSET()
fpaste = board.GetLayerID('F.Paste')
bpaste = board.GetLayerID('B.Paste')
@ -390,19 +391,24 @@ class VariantOptions(BaseOptions):
badhes = board.GetLayerID('B.Adhes')
old_fadhes = []
old_badhes = []
old_fmask = []
old_bmask = []
rescue = board.GetLayerID(GS.work_layer)
fmask = board.GetLayerID('F.Mask')
bmask = board.GetLayerID('B.Mask')
if GS.global_remove_solder_mask_for_dnp:
exclude.addLayer(fmask)
exclude.addLayer(bmask)
for m in GS.get_modules_board(board):
ref = m.GetReference()
c = comps_hash.get(ref, None)
if c and c.included and not c.fitted:
# Remove all pads from *.Paste
if GS.global_remove_solder_paste_for_dnp:
if GS.global_remove_solder_paste_for_dnp or GS.global_remove_solder_mask_for_dnp:
old_c_layers = []
for p in m.Pads():
pad_layers = p.GetLayerSet()
is_front = fpaste in pad_layers.Seq()
is_front = (fpaste in pad_layers.Seq()) or (fmask in pad_layers.Seq())
old_c_layers.append(pad_layers.FmtHex())
pad_layers.removeLayerSet(exclude)
if len(pad_layers.Seq()) == 0:
@ -412,7 +418,7 @@ class VariantOptions(BaseOptions):
logger.warning(W_WRONGPASTE+'Pad with solder paste, but no copper or solder mask aperture in '+ref)
p.SetLayerSet(pad_layers)
old_layers.append(old_c_layers)
logger.debugl(3, '- Removed paste from '+ref)
logger.debugl(3, '- Removed paste/mask from '+ref)
# Remove any graphical item in the *.Adhes layers
if GS.global_remove_adhesive_for_dnp:
found = False
@ -428,24 +434,42 @@ class VariantOptions(BaseOptions):
found = True
if found:
logger.debugl(3, '- Removed adhesive from '+ref)
if GS.global_remove_solder_mask_for_dnp:
found = False
for gi in m.GraphicalItems():
l_gi = gi.GetLayer()
if l_gi == fmask:
gi.SetLayer(rescue)
old_fmask.append(gi)
found = True
if l_gi == bmask:
gi.SetLayer(rescue)
old_bmask.append(gi)
found = True
if found:
logger.debugl(3, '- Removed mask from '+ref)
# Store the data to undo the above actions
self.old_layers = old_layers
self.old_fadhes = old_fadhes
self.old_badhes = old_badhes
self.old_fmask = old_fmask
self.old_bmask = old_bmask
self._fadhes = fadhes
self._badhes = badhes
self._fmask = fmask
self._bmask = bmask
return exclude
def restore_paste_and_glue(self, board, comps_hash):
if comps_hash is None:
return
logger.debug('Restoring paste and glue')
if GS.global_remove_solder_paste_for_dnp:
logger.debug('Restoring paste, mask and/or glue')
if GS.global_remove_solder_paste_for_dnp or GS.global_remove_solder_mask_for_dnp:
for m in GS.get_modules_board(board):
ref = m.GetReference()
c = comps_hash.get(ref, None)
if c and c.included and not c.fitted:
logger.debugl(3, '- Restoring paste for '+ref)
logger.debugl(3, '- Restoring paste/mask for '+ref)
restore = self.old_layers.pop(0)
for p in m.Pads():
pad_layers = p.GetLayerSet()
@ -457,6 +481,10 @@ class VariantOptions(BaseOptions):
gi.SetLayer(self._fadhes)
for gi in self.old_badhes:
gi.SetLayer(self._badhes)
for gi in self.old_fmask:
gi.SetLayer(self._fmask)
for gi in self.old_bmask:
gi.SetLayer(self._bmask)
def remove_fab(self, board, comps_hash):
""" Remove from Fab the excluded components. """

View File

@ -150,13 +150,14 @@ def test_gerber_variant_1(test_dir):
# R3 is a component added to the PCB, included in all cases
# variant: default directory: gerber components: R1, R2 and R3
check_layers_exist(ctx, 'gerber', prj, ALL_LAYERS, '')
check_components(ctx, 'gerber', prj, ['F_Paste', 'F_Adhes'], '', ['C1', 'C2'], ['R1', 'R2', 'R3'])
check_components(ctx, 'gerber', prj, ['F_Paste', 'F_Adhes', 'F_Mask'], '', ['C1', 'C2'], ['R1', 'R2', 'R3'])
# variant: production directory: production components: R1, R2, R3 and C2
check_layers_exist(ctx, 'production', prj, ALL_LAYERS, '_(production)')
check_components(ctx, 'production', prj, ['F_Paste', 'F_Adhes'], '_(production)', ['C1'], ['R1', 'R2', 'R3', 'C2'])
check_components(ctx, 'production', prj, ['F_Paste', 'F_Adhes', 'F_Mask'], '_(production)', ['C1'],
['R1', 'R2', 'R3', 'C2'])
# variant: test directory: test components: R1, R3 and C2
check_layers_exist(ctx, 'test', prj, ALL_LAYERS, '_(test)')
check_components(ctx, 'test', prj, ['F_Paste', 'F_Adhes'], '_(test)', ['R2'], ['C1', 'R1', 'R3', 'C2'])
check_components(ctx, 'test', prj, ['F_Paste', 'F_Adhes', 'F_Mask'], '_(test)', ['R2'], ['C1', 'R1', 'R3', 'C2'])
ctx.clean_up(keep_project=True)

View File

@ -2,6 +2,9 @@
kibot:
version: 1
global:
remove_solder_mask_for_dnp: true
variants:
- name: 'production'
comment: 'Production variant'