From 5d2d0a41951f9db18c0f58714a4e784025293c7d Mon Sep 17 00:00:00 2001 From: "Salvador E. Tropea" Date: Mon, 14 Feb 2022 13:49:56 -0300 Subject: [PATCH] Added MacroFab XYRS support - Internal BoM options: - `angle_positive` - `csv.hide_header` - `footprint_populate_values` - `footprint_type_values` - `units` mils - Columns: - `Footprint Type` - `Footprint Populate` - `Footprint X-Size` - `Footprint Y-Size` --- CHANGELOG.md | 5 +- README.md | 13 +++- docs/README.in | 7 ++ docs/samples/MacroFab_XYRS.kibot.yaml | 65 +++++++++++++++++ docs/samples/generic_plot.kibot.yaml | 10 ++- kibot/bom/bom.py | 20 ++++- kibot/bom/columnlist.py | 24 ++++++ kibot/bom/csv_writer.py | 7 +- kibot/gs.py | 16 ++++ kibot/kicad/v5_sch.py | 6 +- kibot/kiplot.py | 1 + kibot/out_bom.py | 37 +++++++++- tests/reference/5_1_6/light_control.XYRS | 73 +++++++++++++++++++ tests/reference/5_1_7/light_control.XYRS | 1 + tests/reference/6_0_0/light_control.XYRS | 1 + .../6_0_0/light_control_cpl_jlc_nc.csv | 63 +--------------- tests/test_plot/test_position.py | 12 +++ .../simple_position_rot_6.kibot.yaml | 64 ++++++++++++++++ 18 files changed, 347 insertions(+), 78 deletions(-) create mode 100644 docs/samples/MacroFab_XYRS.kibot.yaml create mode 100644 tests/reference/5_1_6/light_control.XYRS create mode 120000 tests/reference/5_1_7/light_control.XYRS create mode 120000 tests/reference/6_0_0/light_control.XYRS mode change 100644 => 120000 tests/reference/6_0_0/light_control_cpl_jlc_nc.csv create mode 100644 tests/yaml_samples/simple_position_rot_6.kibot.yaml diff --git a/CHANGELOG.md b/CHANGELOG.md index 7898403e..2c386922 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -24,6 +24,9 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0 space. This helps for cases like "10K 1%". - `count_smd_tht` option to compute SMD/THT stats. (#113) - option to add text to the `join` list. (#108) + - two other options for the sorting criteria. + - XYRS support (you can generate position files using it) + - CSV `hide_header` option - Generic filter: options to match if a field is/isn't defined. - Excellon drill: added `route_mode_for_oval_holes` option. - Default global `dir` option. @@ -61,8 +64,6 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0 - Added global options to define the PCB details (`pcb_material`, `solder_mask_color`, `silk_screen_color` and `pcb_finish`) - Report generation (for design house) (#93) -- Internal BoM: two other options for the sorting criteria. -- Internal BoM: XYRS support (you can generate position files using it) ### Changed - Internal BoM: now components with different Tolerance, Voltage, Current diff --git a/README.md b/README.md index a9f6a9db..34d09a73 100644 --- a/README.md +++ b/README.md @@ -795,6 +795,7 @@ Next time you need this list just use an alias, like this: - `name`: [string=''] Name to identify this source. If empty we use the name of the schematic. - `number`: [number=1] Number of boards to build (components multiplier). Use negative to substract. - `ref_id`: [string=''] A prefix to add to all the references from this project. + - `angle_positive`: [boolean=true] Always use positive values for the footprint rotation. - `bottom_negative_x`: [boolean=false] Use negative X coordinates for footprints on bottom layer (for XYRS). - `columns`: [list(dict)|list(string)] List of columns to display. Can be just the name of the field. @@ -847,6 +848,7 @@ Next time you need this list just use an alias, like this: - `count_smd_tht`: [boolean=false] Show the stats about how many of the components are SMD/THT. You must provide the PCB. - `csv`: [dict] Options for the CSV, TXT and TSV formats. * Valid keys: + - `hide_header`: [boolean=false] Hide the header line (names of the columns). - `hide_pcb_info`: [boolean=false] Hide project information. - `hide_stats_info`: [boolean=false] Hide statistics information. - `quote_all`: [boolean=false] Enclose all values using double quotes. @@ -859,6 +861,8 @@ Next time you need this list just use an alias, like this: - `exclude_filter`: [string|list(string)='_mechanical'] Name of the filter to exclude components from BoM processing. The default filter excludes test points, fiducial marks, mounting holes, etc. - `fit_field`: [string='Config'] Field name used for internal filters. + - `footprint_populate_values`: [string|list(string)='no,yes'] Values for the `Footprint Populate` column. + - `footprint_type_values`: [string|list(string)='SMD,THT,VIRTUAL'] Values for the `Footprint Type` column. - `format`: [string=''] [HTML,CSV,TXT,TSV,XML,XLSX] format for the BoM. Defaults to CSV or a guess according to the options.. - `group_connectors`: [boolean=true] Connectors with the same footprints will be grouped together, independent of the name of the connector. @@ -899,7 +903,7 @@ Next time you need this list just use an alias, like this: - `ref_separator`: [string=' '] Separator used for the list of references. - `sort_style`: [string='type_value'] [type_value,type_value_ref,ref] Sorting criteria. - `source_by_id`: [boolean=false] Generate the `Source BoM` column using the reference ID instead of the project name. - - `units`: [string='millimeters'] [millimeters,inches] Units used for the positions ('Footprint X' and 'Footprint Y' columns). + - `units`: [string='millimeters'] [millimeters,inches,mils] Units used for the positions ('Footprint X' and 'Footprint Y' columns). - `use_alt`: [boolean=false] Print grouped references in the alternate compressed style eg: R1-R7,R18. - `use_aux_axis_as_origin`: [boolean=true] Use the auxiliary axis as origin for coordinates (KiCad default) (for XYRS). - `variant`: [string=''] Board variant, used to determine which components @@ -2786,6 +2790,13 @@ The following fields contains the needed information: - `Footprint Rot` - `Footprint Side` +Additionally we support: + +- `Footprint Type` (SMD, THT, VIRTUAL) +- `Footprint X-Size` +- `Footprint Y-Size` +- `Footprint Populate` + ## Credits - **KiBot project**: Salvador E. Tropea (@set-soft) diff --git a/docs/README.in b/docs/README.in index 9fc3c89d..1d0c1a27 100644 --- a/docs/README.in +++ b/docs/README.in @@ -1391,6 +1391,13 @@ The following fields contains the needed information: - `Footprint Rot` - `Footprint Side` +Additionally we support: + +- `Footprint Type` (SMD, THT, VIRTUAL) +- `Footprint X-Size` +- `Footprint Y-Size` +- `Footprint Populate` + ## Credits - **KiBot project**: Salvador E. Tropea (@set-soft) diff --git a/docs/samples/MacroFab_XYRS.kibot.yaml b/docs/samples/MacroFab_XYRS.kibot.yaml new file mode 100644 index 00000000..91849ecd --- /dev/null +++ b/docs/samples/MacroFab_XYRS.kibot.yaml @@ -0,0 +1,65 @@ +# MacroFab compatible XYRS +# https://help.macrofab.com/knowledge/macrofab-required-design-files +kibot: + version: 1 + +filters: + - name: fix_rotation + comment: 'Adjust rotation for JLC' + type: rot_footprint + + - name: only_smd + comment: 'Only SMD parts' + type: generic + exclude_virtual: true + exclude_tht: true + +variants: + - name: rotated + comment: 'Just a place holder for the rotation filter' + type: kibom + variant: rotated + pre_transform: fix_rotation + dnf_filter: only_smd + +outputs: + - name: 'position' + comment: "Pick and place file, XYRS style" + type: bom + options: + variant: rotated + output: '%f.XYRS' + units: mils + group_fields: [] + sort_style: ref + use_aux_axis_as_origin: true + ignore_dnf: false + footprint_populate_values: '0,1' + footprint_type_values: '1,2,0' + csv: + separator: ' ' + hide_pcb_info: true + hide_stats_info: true + hide_header: true + columns: + - field: References + name: Designator + - field: Footprint X + name: X-Loc + - field: Footprint Y + name: Y-Loc + - field: Footprint Rot + name: Rotation + - field: Footprint Side + name: Side + - field: Footprint Type + name: Type + - field: Footprint X-Size + name: X-Size + - field: Footprint Y-Size + name: Y-Size + - field: Value + - field: Footprint + - field: Footprint Populate + name: Populate + - field: MPN diff --git a/docs/samples/generic_plot.kibot.yaml b/docs/samples/generic_plot.kibot.yaml index 1d4853f7..04ccf381 100644 --- a/docs/samples/generic_plot.kibot.yaml +++ b/docs/samples/generic_plot.kibot.yaml @@ -87,6 +87,8 @@ outputs: number: 1 # [string=''] A prefix to add to all the references from this project ref_id: '' + # [boolean=true] Always use positive values for the footprint rotation + angle_positive: true # [boolean=false] Use negative X coordinates for footprints on bottom layer (for XYRS) bottom_negative_x: false # [list(dict)|list(string)] List of columns to display. @@ -158,6 +160,8 @@ outputs: count_smd_tht: false # [dict] Options for the CSV, TXT and TSV formats csv: + # [boolean=false] Hide the header line (names of the columns) + hide_header: false # [boolean=false] Hide project information hide_pcb_info: false # [boolean=false] Hide statistics information @@ -179,6 +183,10 @@ outputs: exclude_filter: '_mechanical' # [string='Config'] Field name used for internal filters fit_field: 'Config' + # [string|list(string)='no,yes'] Values for the `Footprint Populate` column + footprint_populate_values: 'no,yes' + # [string|list(string)='SMD,THT,VIRTUAL'] Values for the `Footprint Type` column + footprint_type_values: 'SMD,THT,VIRTUAL' # [string=''] [HTML,CSV,TXT,TSV,XML,XLSX] format for the BoM. # Defaults to CSV or a guess according to the options. format: 'CSV' @@ -247,7 +255,7 @@ outputs: sort_style: 'type_value' # [boolean=false] Generate the `Source BoM` column using the reference ID instead of the project name source_by_id: false - # [string='millimeters'] [millimeters,inches] Units used for the positions ('Footprint X' and 'Footprint Y' columns) + # [string='millimeters'] [millimeters,inches,mils] Units used for the positions ('Footprint X' and 'Footprint Y' columns) units: 'millimeters' # [boolean=false] Print grouped references in the alternate compressed style eg: R1-R7,R18 use_alt: false diff --git a/kibot/bom/bom.py b/kibot/bom/bom.py index 03d43fe7..cc29ebe1 100644 --- a/kibot/bom/bom.py +++ b/kibot/bom/bom.py @@ -303,7 +303,8 @@ class ComponentGroup(object): fld=value, ref=ref)) self.fields[field] += " " + value - def update_fields(self, conv, bottom_negative_x, x_origin, y_origin, usealt=False): + def update_fields(self, conv, bottom_negative_x, x_origin, y_origin, angle_positive, footprint_populate_values, + footprint_type_values, usealt=False): for c in self.components: for f, v in c.get_user_fields(): self.update_field(f, v, c.ref) @@ -336,8 +337,20 @@ class ComponentGroup(object): pos_x = -pos_x self.fields[ColumnList.COL_FP_X_L] = "{:.4f}".format(pos_x) self.fields[ColumnList.COL_FP_Y_L] = "{:.4f}".format(-(comp.footprint_y - y_origin) * conv) - self.fields[ColumnList.COL_FP_ROT_L] = "{:.4f}".format(comp.footprint_rot) + rot = comp.footprint_rot + if angle_positive: + rot = rot % 360 + self.fields[ColumnList.COL_FP_ROT_L] = "{:.4f}".format(rot) self.fields[ColumnList.COL_FP_SIDE_L] = "bottom" if comp.bottom else "top" + type = 0 + if comp.tht: + type = 1 + if comp.virtual: + type = 2 + self.fields[ColumnList.COL_FP_TYPE_L] = footprint_type_values[type] + self.fields[ColumnList.COL_FP_FIT_L] = footprint_populate_values[comp.fitted] + self.fields[ColumnList.COL_FP_XS_L] = "{:.4f}".format(comp.footprint_w * conv) + self.fields[ColumnList.COL_FP_YS_L] = "{:.4f}".format(comp.footprint_h * conv) self.fields[ColumnList.COL_FP_LIB_L] = comp.footprint_lib self.fields[ColumnList.COL_SHEETPATH_L] = comp.sheet_path_h if not self.fields[ColumnList.COL_DESCRIPTION_L]: @@ -466,7 +479,8 @@ def group_components(cfg, components): # Sort the references within each group g.sort_components() # Fill the columns - g.update_fields(cfg.conv_units, cfg.bottom_negative_x, x_origin, y_origin, cfg.use_alt ) + g.update_fields(cfg.conv_units, cfg.bottom_negative_x, x_origin, y_origin, cfg.angle_positive, + cfg.footprint_populate_values, cfg.footprint_type_values, cfg.use_alt) if cfg.normalize_values: g.fields[ColumnList.COL_VALUE_L] = normalize_value(g.components[0], decimal_point) # Sort the groups diff --git a/kibot/bom/columnlist.py b/kibot/bom/columnlist.py index b30f9550..ca3cc01a 100644 --- a/kibot/bom/columnlist.py +++ b/kibot/bom/columnlist.py @@ -39,6 +39,14 @@ class ColumnList: COL_FP_ROT_L = COL_FP_ROT.lower() COL_FP_SIDE = 'Footprint Side' COL_FP_SIDE_L = COL_FP_SIDE.lower() + COL_FP_TYPE = 'Footprint Type' + COL_FP_TYPE_L = COL_FP_TYPE.lower() + COL_FP_FIT = 'Footprint Populate' + COL_FP_FIT_L = COL_FP_FIT.lower() + COL_FP_XS = 'Footprint X-Size' + COL_FP_XS_L = COL_FP_XS.lower() + COL_FP_YS = 'Footprint Y-Size' + COL_FP_YS_L = COL_FP_YS.lower() COL_PART = 'Part' COL_PART_L = COL_PART.lower() COL_PART_LIB = 'Part Lib' @@ -87,6 +95,18 @@ class ColumnList: COL_SOURCE_BOM, ] + # Not included by default + COLUMNS_EXTRA = [ + COL_FP_X, + COL_FP_Y, + COL_FP_ROT, + COL_FP_SIDE, + COL_FP_TYPE, + COL_FP_FIT, + COL_FP_XS, + COL_FP_YS, + ] + # Default columns # These columns are 'immutable' COLUMNS_PROTECTED_L = { @@ -104,6 +124,10 @@ class ColumnList: COL_FP_Y_L, COL_FP_ROT_L, COL_FP_SIDE_L, + COL_FP_TYPE_L, + COL_FP_FIT_L, + COL_FP_XS_L, + COL_FP_YS_L, COL_FP_LIB_L } diff --git a/kibot/bom/csv_writer.py b/kibot/bom/csv_writer.py index 7fb05740..41746c96 100644 --- a/kibot/bom/csv_writer.py +++ b/kibot/bom/csv_writer.py @@ -1,6 +1,6 @@ # -*- coding: utf-8 -*- -# Copyright (c) 2020-2021 Salvador E. Tropea -# Copyright (c) 2020-2021 Instituto Nacional de TecnologĂ­a Industrial +# Copyright (c) 2020-2022 Salvador E. Tropea +# Copyright (c) 2020-2022 Instituto Nacional de TecnologĂ­a Industrial # Copyright (c) 2016-2020 Oliver Henry Walters (@SchrodingersGat) # License: MIT # Project: KiBot (formerly KiPlot) @@ -89,7 +89,8 @@ def write_csv(filename, ext, groups, headings, head_names, cfg): with open(filename, "wt") as f: writer = csv.writer(f, delimiter=delimiter, lineterminator="\n", quoting=quoting) # Headers - writer.writerow(head_names) + if not cfg.csv.hide_header: + writer.writerow(head_names) # Body for group in groups: if cfg.ignore_dnf and not group.is_fitted(): diff --git a/kibot/gs.py b/kibot/gs.py index f00113a3..306ff623 100644 --- a/kibot/gs.py +++ b/kibot/gs.py @@ -4,6 +4,7 @@ # License: GPL-3.0 # Project: KiBot (formerly KiPlot) import os +import pcbnew from datetime import datetime, date from sys import exit from .misc import EXIT_BAD_ARGS, W_DATEFORMAT, KICAD_VERSION_5_99 @@ -188,6 +189,21 @@ class GS(object): return m.GetCenter() return m.GetPosition() + @staticmethod + def get_fp_size(m): + if GS.ki5(): + pads = m.Pads() + r = pcbnew.EDA_RECT() + for pad in pads: + r.Merge(pad.GetBoundingBox()) + rot = m.GetOrientationDegrees() + if rot == 270 or rot == 90: + return (r.GetHeight(), r.GetWidth()) + return (r.GetWidth(), r.GetHeight()) + # KiCad 6 + r = m.GetFpPadsLocalBbox() + return (r.GetWidth(), r.GetHeight()) + @staticmethod def ki6(): return GS.kicad_version_n >= KICAD_VERSION_5_99 diff --git a/kibot/kicad/v5_sch.py b/kibot/kicad/v5_sch.py index d2bb668b..c4e59bb5 100644 --- a/kibot/kicad/v5_sch.py +++ b/kibot/kicad/v5_sch.py @@ -871,6 +871,8 @@ class SchematicComponent(object): - footprint_rot: angle to rotate the part in the pick & place. - footprint_x: x position of the part in the pick & place. - footprint_y: y position of the part in the pick & place. + - footprint_w: width of the footprint (pads only). + - footprint_h: height of the footprint (pads only) - qty: ammount of this part used. """ ref_re = re.compile(r'([^\d]+)([\?\d]+)') @@ -892,8 +894,8 @@ class SchematicComponent(object): self.fixed = False self.bottom = False self.footprint_rot = 0.0 - self.footprint_x = 0 - self.footprint_y = 0 + self.footprint_x = self.footprint_y = 0 + self.footprint_w = self.footprint_h = 0 self.qty = 1 self.annotation_error = False # KiCad 5 PCB flags (mutually exclusive) diff --git a/kibot/kiplot.py b/kibot/kiplot.py index 655c9568..72c1c979 100644 --- a/kibot/kiplot.py +++ b/kibot/kiplot.py @@ -280,6 +280,7 @@ def get_board_comps_data(comps): center = GS.get_center(m) c.footprint_x = center.x c.footprint_y = center.y + (c.footprint_w, c.footprint_h) = GS.get_fp_size(m) attrs = m.GetAttributes() if GS.ki5(): # KiCad 5 diff --git a/kibot/out_bom.py b/kibot/out_bom.py index d69e25e0..faf7d7ac 100644 --- a/kibot/out_bom.py +++ b/kibot/out_bom.py @@ -217,6 +217,8 @@ class BoMCSV(Optionable): with document: self.separator = ',' """ CSV Separator. TXT and TSV always use tab as delimiter """ + self.hide_header = False + """ Hide the header line (names of the columns) """ self.hide_pcb_info = False """ Hide project information """ self.hide_stats_info = False @@ -385,22 +387,31 @@ class BoMOptions(BaseOptions): self.count_smd_tht = False """ Show the stats about how many of the components are SMD/THT. You must provide the PCB """ self.units = 'millimeters' - """ [millimeters,inches] Units used for the positions ('Footprint X' and 'Footprint Y' columns) """ + """ [millimeters,inches,mils] Units used for the positions ('Footprint X' and 'Footprint Y' columns) """ self.bottom_negative_x = False """ Use negative X coordinates for footprints on bottom layer (for XYRS) """ self.use_aux_axis_as_origin = True """ Use the auxiliary axis as origin for coordinates (KiCad default) (for XYRS) """ + self.angle_positive = True + """ Always use positive values for the footprint rotation """ self.sort_style = 'type_value' """ [type_value,type_value_ref,ref] Sorting criteria """ + self.footprint_populate_values = Optionable + """ [string|list(string)='no,yes'] Values for the `Footprint Populate` column """ + self.footprint_type_values = Optionable + """ [string|list(string)='SMD,THT,VIRTUAL'] Values for the `Footprint Type` column """ self._format_example = 'CSV' + self._footprint_populate_values_example = 'no,yes' + self._footprint_type_values_example = 'SMD,THT,VIRTUAL' super().__init__() @staticmethod def _get_columns(): """ Create a list of valid columns """ + cols = ColumnList.COLUMNS_DEFAULT + ColumnList.COLUMNS_EXTRA if GS.sch: - return GS.sch.get_field_names(ColumnList.COLUMNS_DEFAULT) - return ColumnList.COLUMNS_DEFAULT + return GS.sch.get_field_names(cols) + return cols def _guess_format(self): """ Figure out the format """ @@ -556,6 +567,19 @@ class BoMOptions(BaseOptions): # List of distributors self.distributors = Optionable.force_list(self.distributors) self.no_distributors = Optionable.force_list(self.no_distributors) + # Column values + self.footprint_populate_values = Optionable.force_list(self.footprint_populate_values) + if not self.footprint_populate_values: + self.footprint_populate_values = ['no', 'yes'] + if len(self.footprint_populate_values) != 2: + raise KiPlotConfigurationError("The `footprint_populate_values` must contain two values ({})". + format(self.footprint_populate_values)) + self.footprint_type_values = Optionable.force_list(self.footprint_type_values) + if not self.footprint_type_values: + self.footprint_type_values = ['SMD', 'THT', 'VIRTUAL'] + if len(self.footprint_type_values) != 3: + raise KiPlotConfigurationError("The `footprint_type_values` must contain three values ({})". + format(self.footprint_type_values)) # Columns valid_columns = self._get_columns() (self.columns, self.column_levels, self.column_comments, self.column_rename, @@ -588,7 +612,12 @@ class BoMOptions(BaseOptions): self.revision = GS.sch_rev self.debug_level = GS.debug_level self.kicad_version = GS.kicad_version - self.conv_units = 1.0/IU_PER_MM if self.units == 'millimeters' else 0.001/IU_PER_MILS + if self.units == 'millimeters': + self.conv_units = 1.0/IU_PER_MM + elif self.units == 'mils': + self.conv_units = 1.0/IU_PER_MILS + else: # Inches + self.conv_units = 0.001/IU_PER_MILS # Get the components list from the schematic comps = GS.sch.get_components() get_board_comps_data(comps) diff --git a/tests/reference/5_1_6/light_control.XYRS b/tests/reference/5_1_6/light_control.XYRS new file mode 100644 index 00000000..f0b7e75b --- /dev/null +++ b/tests/reference/5_1_6/light_control.XYRS @@ -0,0 +1,73 @@ +C1 362.2047 1265.7480 270.0000 top 1 61.4173 25.1969 1uF R_0402_1005Metric 1 CL05A105KA5NQNC +C2 401.5748 1265.7480 270.0000 top 1 61.4173 25.1969 0.1uF R_0402_1005Metric 1 CL05B104KO5NNNC +C3 614.2520 1406.7520 270.0000 top 1 96.4567 37.4016 4.7uF R_0603_1608Metric 1 CL10A475KO8NNNC +C4 653.5433 814.9606 270.0000 top 1 96.4567 37.4016 1uF R_0603_1608Metric 1 CL10A105KB8NNNC +C5 614.1732 1208.6614 180.0000 top 1 96.4567 37.4016 22uF R_0603_1608Metric 1 CL10A226MQ8NRNC +C6 374.2520 1575.7480 270.0000 top 1 61.4173 25.1969 4.7uF R_0402_1005Metric 1 CL05A475MP5NRNC +C7 774.2520 1545.7480 90.0000 top 1 61.4173 25.1969 10uF R_0402_1005Metric 1 CL05A106MQ5NUNC +C8 824.2520 1545.7480 90.0000 top 1 61.4173 25.1969 0.1uF R_0402_1005Metric 1 CL05B104KO5NNNC +D1 523.6220 826.7717 180.0000 top 1 165.3543 47.2441 D_Schottky D_SOD-123 1 B5819W SL +D2 291.3386 1307.0866 90.0000 top 1 165.3543 47.2441 D_Schottky D_SOD-123 1 B5819W SL +D3 661.4173 516.3780 270.0000 top 1 165.3543 47.2441 D_Schottky D_SOD-123 1 B5819W SL +D4 1161.4173 476.3780 270.0000 top 1 165.3543 47.2441 D_Schottky D_SOD-123 1 B5819W SL +D5 1704.2520 555.7480 270.0000 top 1 165.3543 47.2441 D_Schottky D_SOD-123 1 B5819W SL +D6 1862.2047 889.7638 0.0000 top 1 165.3543 47.2441 D_Schottky D_SOD-123 1 B5819W SL +D7 913.3858 516.3780 270.0000 top 1 165.3543 47.2441 D_Schottky D_SOD-123 1 B5819W SL +D8 1452.7559 472.4409 270.0000 top 1 165.3543 47.2441 D_Schottky D_SOD-123 1 B5819W SL +D9 1858.2677 649.6063 0.0000 top 1 165.3543 47.2441 D_Schottky D_SOD-123 1 B5819W SL +D10 1858.2677 1129.9213 0.0000 top 1 165.3543 47.2441 D_Schottky D_SOD-123 1 B5819W SL +D11 1885.8268 1503.9370 0.0000 top 1 96.4567 37.4016 Green LED_0603_1608Metric 1 19-217/GHC-YR1S2/3T +D12 2015.7480 1503.9370 0.0000 top 1 96.4567 37.4016 Green LED_0603_1608Metric 1 19-217/GHC-YR1S2/3T +D13 2145.6693 1503.9370 0.0000 top 1 96.4567 37.4016 Red LED_0603_1608Metric 1 +D14 2271.6535 1503.9370 0.0000 top 1 96.4567 37.4016 Red LED_0603_1608Metric 1 +J1 275.5906 1125.9843 270.0000 top 2 232.2835 94.4882 Screw_Terminal_01x02 TerminalBlock_Phoenix_PT-1,5-2-3.5-H_1x02_P3.50mm_Horizontal 0 +J2 134.2520 1415.7480 270.0000 top 1 322.8346 172.2441 USB_B_Micro USB_Micro-B_Molex-105017-0001 1 +J3 578.7402 236.2205 0.0000 top 2 232.2835 94.4882 Screw_Terminal_01x02 TerminalBlock_Phoenix_PT-1,5-2-3.5-H_1x02_P3.50mm_Horizontal 0 +J4 1219.6063 236.2205 0.0000 top 2 232.2835 94.4882 Screw_Terminal_01x02 TerminalBlock_Phoenix_PT-1,5-2-3.5-H_1x02_P3.50mm_Horizontal 0 +J5 1864.1732 236.2205 0.0000 top 2 232.2835 94.4882 Screw_Terminal_01x02 TerminalBlock_Phoenix_PT-1,5-2-3.5-H_1x02_P3.50mm_Horizontal 0 +J6 2104.2520 822.8346 90.0000 top 2 232.2835 94.4882 Screw_Terminal_01x02 TerminalBlock_Phoenix_PT-1,5-2-3.5-H_1x02_P3.50mm_Horizontal 0 +J7 899.6063 236.2205 0.0000 top 2 232.2835 94.4882 Screw_Terminal_01x02 TerminalBlock_Phoenix_PT-1,5-2-3.5-H_1x02_P3.50mm_Horizontal 0 +J8 1541.3386 236.2205 0.0000 top 2 232.2835 94.4882 Screw_Terminal_01x02 TerminalBlock_Phoenix_PT-1,5-2-3.5-H_1x02_P3.50mm_Horizontal 0 +J9 2104.2520 492.1260 90.0000 top 2 232.2835 94.4882 Screw_Terminal_01x02 TerminalBlock_Phoenix_PT-1,5-2-3.5-H_1x02_P3.50mm_Horizontal 0 +J10 2104.2520 1149.6063 90.0000 top 2 232.2835 94.4882 Screw_Terminal_01x02 TerminalBlock_Phoenix_PT-1,5-2-3.5-H_1x02_P3.50mm_Horizontal 0 +J11 275.5906 807.0866 270.0000 top 2 232.2835 94.4882 Screw_Terminal_01x02 TerminalBlock_Phoenix_PT-1,5-2-3.5-H_1x02_P3.50mm_Horizontal 0 +J12 354.3307 415.3543 180.0000 top 2 263.7795 76.7717 Conn_01x03 JST_XH_B3B-XH-A_1x03_P2.50mm_Vertical 0 +Q1 754.2520 1415.7480 180.0000 top 1 114.1732 106.2992 Q_NPN_BEC SOT-23 1 SS8050 +Q2 754.2520 1265.7480 180.0000 top 1 114.1732 106.2992 Q_NPN_BEC SOT-23 1 SS8050 +Q3 779.5276 495.7480 90.0000 top 1 114.1732 106.2992 Q_NMOS_GSD SOT-23 1 AO3400A +Q4 1283.4646 452.7559 90.0000 top 1 114.1732 106.2992 Q_NMOS_GDS SOT-23 1 AO3400A +Q5 1834.2520 475.7480 90.0000 top 1 114.1732 106.2992 Q_NMOS_GDS SOT-23 1 AO3400A +Q6 1881.8898 1007.8740 180.0000 top 1 114.1732 106.2992 Q_NMOS_GDS SOT-23 1 AO3400A +Q7 1031.4961 445.7480 90.0000 top 1 114.1732 106.2992 Q_NMOS_GDS SOT-23 1 AO3400A +Q8 1570.8661 485.7480 90.0000 top 1 114.1732 106.2992 Q_NMOS_GDS SOT-23 1 AO3400A +Q9 1881.8898 767.7165 180.0000 top 1 114.1732 106.2992 Q_NMOS_GDS SOT-23 1 AO3400A +Q10 1881.8898 1248.0315 180.0000 top 1 114.1732 106.2992 Q_NMOS_GDS SOT-23 1 AO3400A +R1 614.2520 1565.7480 180.0000 top 1 61.4173 25.1969 10kR R_0402_1005Metric 1 0402WGF1002TCE +R2 614.2520 1515.7480 180.0000 top 1 61.4173 25.1969 10kR R_0402_1005Metric 1 0402WGF1002TCE +R3 324.2520 1575.7480 270.0000 top 1 61.4173 25.1969 10kR R_0402_1005Metric 1 0402WGF1002TCE +R4 814.2520 605.7480 90.0000 top 1 61.4173 25.1969 100R R_0402_1005Metric 1 0402WGF1000TCE +R5 1267.7165 543.3071 0.0000 top 1 61.4173 25.1969 100R R_0402_1005Metric 1 0402WGF1000TCE +R6 1704.7244 673.2283 180.0000 top 1 61.4173 25.1969 100R R_0402_1005Metric 1 0402WGF1000TCE +R7 1787.4016 979.7244 90.0000 top 1 61.4173 25.1969 100R R_0402_1005Metric 1 0402WGF1000TCE +R8 1074.2520 540.7480 180.0000 top 1 61.4173 25.1969 100R R_0402_1005Metric 1 0402WGF1000TCE +R9 1540.8661 596.3780 0.0000 top 1 61.4173 25.1969 100R R_0402_1005Metric 1 0402WGF1000TCE +R10 1789.2520 765.7480 270.0000 top 1 61.4173 25.1969 100R R_0402_1005Metric 1 0402WGF1000TCE +R11 1784.2520 1224.4094 270.0000 top 1 61.4173 25.1969 100R R_0402_1005Metric 1 0402WGF1000TCE +R12 1897.6378 1444.8819 0.0000 top 1 61.4173 25.1969 47R R_0402_1005Metric 1 19-217/GHC-YR1S2/3T +R13 2007.8740 1444.8819 0.0000 top 1 61.4173 25.1969 47R R_0402_1005Metric 1 0402WGF470JTCE +R14 2122.0472 1444.8819 0.0000 top 1 61.4173 25.1969 150R R_0402_1005Metric 1 0402WGF1500TCE +R15 2244.0945 1444.8819 0.0000 top 1 61.4173 25.1969 150R R_0402_1005Metric 1 0402WGF1500TCE +R16 952.7559 724.4094 180.0000 top 1 61.4173 25.1969 10kR R_0402_1005Metric 1 0402WGF1002TCE +R17 754.2520 615.7480 0.0000 top 1 61.4173 25.1969 10kR R_0402_1005Metric 1 0402WGF1002TCE +R18 1349.2520 545.7480 180.0000 top 1 61.4173 25.1969 10kR R_0402_1005Metric 1 0402WGF1002TCE +R19 1669.2520 730.7480 0.0000 top 1 61.4173 25.1969 10kR R_0402_1005Metric 1 0402WGF1002TCE +R20 1729.2520 965.7480 90.0000 top 1 61.4173 25.1969 10kR R_0402_1005Metric 1 0402WGF1002TCE +R21 999.2520 540.7480 0.0000 top 1 61.4173 25.1969 10kR R_0402_1005Metric 1 0402WGF1002TCE +R22 1604.2520 595.7480 270.0000 top 1 61.4173 25.1969 10kR R_0402_1005Metric 1 0402WGF1002TCE +R23 1669.2520 785.7480 0.0000 top 1 61.4173 25.1969 10kR R_0402_1005Metric 1 0402WGF1002TCE +R24 1784.2520 1304.8425 270.0000 top 1 61.4173 25.1969 10kR R_0402_1005Metric 1 0402WGF1002TCE +SW1 472.4409 1725.7480 0.0000 top 1 275.5906 177.1654 SW_Push TS-1187A 1 TS-1187A-C-D-B +U1 602.3622 1031.4961 180.0000 top 1 326.7717 240.1575 AZ1117-3.3 SOT-223-3_TabPin2 1 AZ1117CH-3.3TRG1 +U2 468.6614 1415.7480 270.0000 top 1 185.0394 185.0394 CP2104 QFN-24-1EP_4x4mm_P0.5mm_EP2.6x2.6mm 1 CP2104-F03-GMR +U3 1274.2520 1245.7480 0.0000 top 1 748.0315 746.4567 ESP32-WROOM-32 ESP32-WROOM-32 1 +U4 1098.4252 704.7244 90.0000 top 2 59.0551 359.0551 DHT11 Aosong_DHT11_5.5x12.0_P2.54mm 0 diff --git a/tests/reference/5_1_7/light_control.XYRS b/tests/reference/5_1_7/light_control.XYRS new file mode 120000 index 00000000..7d173c61 --- /dev/null +++ b/tests/reference/5_1_7/light_control.XYRS @@ -0,0 +1 @@ +../5_1_6/light_control.XYRS \ No newline at end of file diff --git a/tests/reference/6_0_0/light_control.XYRS b/tests/reference/6_0_0/light_control.XYRS new file mode 120000 index 00000000..7d173c61 --- /dev/null +++ b/tests/reference/6_0_0/light_control.XYRS @@ -0,0 +1 @@ +../5_1_6/light_control.XYRS \ No newline at end of file diff --git a/tests/reference/6_0_0/light_control_cpl_jlc_nc.csv b/tests/reference/6_0_0/light_control_cpl_jlc_nc.csv deleted file mode 100644 index c66683e9..00000000 --- a/tests/reference/6_0_0/light_control_cpl_jlc_nc.csv +++ /dev/null @@ -1,62 +0,0 @@ -Designator,Val,Package,Mid X,Mid Y,Rotation,Layer -C1,1uF,R_0402_1005Metric,111.2000,-69.8500,-90.0000,top -C2,0.1uF,R_0402_1005Metric,112.2000,-69.8500,-90.0000,top -C3,4.7uF,R_0603_1608Metric,117.6020,-66.2685,-90.0000,top -C4,1uF,R_0603_1608Metric,118.6000,-81.3000,-90.0000,top -C5,22uF,R_0603_1608Metric,117.6000,-71.3000,180.0000,top -C6,4.7uF,R_0402_1005Metric,111.5060,-61.9760,-90.0000,top -C7,10uF,R_0402_1005Metric,121.6660,-62.7380,90.0000,top -C8,0.1uF,R_0402_1005Metric,122.9360,-62.7380,90.0000,top -D1,D_Schottky,D_SOD-123,115.3000,-81.0000,180.0000,top -D2,D_Schottky,D_SOD-123,109.4000,-68.8000,90.0000,top -D3,D_Schottky,D_SOD-123,118.8000,-88.8840,-90.0000,top -D4,D_Schottky,D_SOD-123,131.5000,-89.9000,-90.0000,top -D5,D_Schottky,D_SOD-123,145.2880,-87.8840,-90.0000,top -D6,D_Schottky,D_SOD-123,149.3000,-79.4000,0.0000,top -D7,D_Schottky,D_SOD-123,125.2000,-88.8840,-90.0000,top -D8,D_Schottky,D_SOD-123,138.9000,-90.0000,-90.0000,top -D9,D_Schottky,D_SOD-123,149.2000,-85.5000,0.0000,top -D10,D_Schottky,D_SOD-123,149.2000,-73.3000,0.0000,top -D11,Green,LED_0603_1608Metric,149.9000,-63.8000,0.0000,top -D12,Green,LED_0603_1608Metric,153.2000,-63.8000,0.0000,top -D13,Red,LED_0603_1608Metric,156.5000,-63.8000,0.0000,top -D14,Red,LED_0603_1608Metric,159.7000,-63.8000,0.0000,top -J2,USB_B_Micro,USB_Micro-B_Molex-105017-0001,105.4100,-66.0400,-90.0000,top -Q1,Q_NPN_BEC,SOT-23,121.1580,-66.0400,180.0000,top -Q2,Q_NPN_BEC,SOT-23,121.1580,-69.8500,180.0000,top -Q3,Q_NMOS_GSD,SOT-23,121.8000,-89.4080,90.0000,top -Q4,Q_NMOS_GDS,SOT-23,134.6000,-90.5000,90.0000,top -Q5,Q_NMOS_GDS,SOT-23,148.5900,-89.9160,90.0000,top -Q6,Q_NMOS_GDS,SOT-23,149.8000,-76.4000,180.0000,top -Q7,Q_NMOS_GDS,SOT-23,128.2000,-90.6780,90.0000,top -Q8,Q_NMOS_GDS,SOT-23,141.9000,-89.6620,90.0000,top -Q9,Q_NMOS_GDS,SOT-23,149.8000,-82.5000,180.0000,top -Q10,Q_NMOS_GDS,SOT-23,149.8000,-70.3000,180.0000,top -R1,10kR,R_0402_1005Metric,117.6020,-62.2300,180.0000,top -R2,10kR,R_0402_1005Metric,117.6020,-63.5000,180.0000,top -R3,10kR,R_0402_1005Metric,110.2360,-61.9760,-90.0000,top -R4,100R,R_0402_1005Metric,122.6820,-86.6140,90.0000,top -R5,100R,R_0402_1005Metric,134.2000,-88.2000,0.0000,top -R6,100R,R_0402_1005Metric,145.3000,-84.9000,180.0000,top -R7,100R,R_0402_1005Metric,147.4000,-77.1150,90.0000,top -R8,100R,R_0402_1005Metric,129.2860,-88.2650,180.0000,top -R9,100R,R_0402_1005Metric,141.1380,-86.8520,0.0000,top -R10,100R,R_0402_1005Metric,147.4470,-82.5500,-90.0000,top -R11,100R,R_0402_1005Metric,147.3200,-70.9000,-90.0000,top -R12,47R,R_0402_1005Metric,150.2000,-65.3000,0.0000,top -R13,47R,R_0402_1005Metric,153.0000,-65.3000,0.0000,top -R14,150R,R_0402_1005Metric,155.9000,-65.3000,0.0000,top -R15,150R,R_0402_1005Metric,159.0000,-65.3000,0.0000,top -R16,10kR,R_0402_1005Metric,126.2000,-83.6000,180.0000,top -R17,10kR,R_0402_1005Metric,121.1580,-86.3600,0.0000,top -R18,10kR,R_0402_1005Metric,136.2710,-88.1380,180.0000,top -R19,10kR,R_0402_1005Metric,144.3990,-83.4390,0.0000,top -R20,10kR,R_0402_1005Metric,145.9230,-77.4700,90.0000,top -R21,10kR,R_0402_1005Metric,127.3810,-88.2650,0.0000,top -R22,10kR,R_0402_1005Metric,142.7480,-86.8680,-90.0000,top -R23,10kR,R_0402_1005Metric,144.3990,-82.0420,0.0000,top -R24,10kR,R_0402_1005Metric,147.3200,-68.8570,-90.0000,top -SW1,SW_Push,TS-1187A,114.0000,-58.1660,0.0000,top -U1,AZ1117-3.3,SOT-223-3_TabPin2,117.3000,-75.8000,180.0000,top -U2,CP2104,QFN-24-1EP_4x4mm_P0.5mm_EP2.6x2.6mm,113.9040,-66.0400,270.0000,top -U3,ESP32-WROOM-32,ESP32-WROOM-32,134.3660,-70.3580,0.0000,top diff --git a/tests/reference/6_0_0/light_control_cpl_jlc_nc.csv b/tests/reference/6_0_0/light_control_cpl_jlc_nc.csv new file mode 120000 index 00000000..7c9b5fbb --- /dev/null +++ b/tests/reference/6_0_0/light_control_cpl_jlc_nc.csv @@ -0,0 +1 @@ +../5_1_6/light_control_cpl_jlc_nc.csv \ No newline at end of file diff --git a/tests/test_plot/test_position.py b/tests/test_plot/test_position.py index d7368002..733b2799 100644 --- a/tests/test_plot/test_position.py +++ b/tests/test_plot/test_position.py @@ -250,6 +250,7 @@ def test_position_rot_4(test_dir): def test_position_rot_5(test_dir): + """ Generate a JLC compatible position file using the Internal BoM """ prj = 'light_control' ctx = context.TestContext(test_dir, 'test_position_rot_5', prj, 'simple_position_rot_5', POS_DIR) ctx.run() @@ -259,6 +260,17 @@ def test_position_rot_5(test_dir): ctx.clean_up(keep_project=True) +def test_position_rot_6(test_dir): + """ Generate a MacroFab XYRS compatible position file using the Internal BoM """ + prj = 'light_control' + ctx = context.TestContext(test_dir, 'test_position_rot_6', prj, 'simple_position_rot_6', POS_DIR) + ctx.run() + output = prj+'.XYRS' + ctx.expect_out_file(output) + ctx.compare_txt(output) + ctx.clean_up(keep_project=True) + + def test_rot_bottom(test_dir): ctx = context.TestContext(test_dir, 'test_rot_bottom', 'comp_bottom', 'simple_position_rot_bottom', POS_DIR) ctx.run() diff --git a/tests/yaml_samples/simple_position_rot_6.kibot.yaml b/tests/yaml_samples/simple_position_rot_6.kibot.yaml new file mode 100644 index 00000000..f17e03e6 --- /dev/null +++ b/tests/yaml_samples/simple_position_rot_6.kibot.yaml @@ -0,0 +1,64 @@ +# MacroFab compatible XYRS +kibot: + version: 1 + +filters: + - name: fix_rotation + comment: 'Adjust rotation for JLC' + type: rot_footprint + + - name: only_smd + comment: 'Only SMD parts' + type: generic + exclude_virtual: true + exclude_tht: true + +variants: + - name: rotated + comment: 'Just a place holder for the rotation filter' + type: kibom + variant: rotated + pre_transform: fix_rotation + dnf_filter: only_smd + +outputs: + - name: 'position' + comment: "Pick and place file, XYRS style" + type: bom + options: + variant: rotated + output: '%f.XYRS' + units: mils + group_fields: [] + sort_style: ref + use_aux_axis_as_origin: true + ignore_dnf: false + footprint_populate_values: '0,1' + footprint_type_values: '1,2,0' + csv: + separator: ' ' + hide_pcb_info: true + hide_stats_info: true + hide_header: true + columns: + - field: References + name: Designator + - field: Footprint X + name: X-Loc + - field: Footprint Y + name: Y-Loc + - field: Footprint Rot + name: Rotation + - field: Footprint Side + name: Side + - field: Footprint Type + name: Type + - field: Footprint X-Size + name: X-Size + - field: Footprint Y-Size + name: Y-Size + - field: Value + - field: Footprint + - field: Footprint Populate + name: Populate + - field: MPN