Skip to content

Commit

Permalink
[Added][IPC2581] New output to generate IPC-DPMX files
Browse files Browse the repository at this point in the history
  • Loading branch information
set-soft committed Feb 26, 2025
1 parent 1aa698b commit 8c26d8e
Show file tree
Hide file tree
Showing 18 changed files with 475 additions and 62 deletions.
1 change: 1 addition & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -9,6 +9,7 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0
### Added
- New outputs:
- ODB: Exports the PCB in ODB++ format (KiCad 9) (#782)
- IPC2581: Exports the PCB in IPC-2581 (IPC-DPMX) format (KiCad 9)
- CLI:
- `--variant` to specify which variants will be generated (See #737)
- `--defs-from-project` allows using KiCad variables for the preprocessor
Expand Down
52 changes: 52 additions & 0 deletions docs/samples/generic_plot.kibot.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -1782,6 +1782,58 @@ outputs:
environment: 'names'
# [string='%f-%i%I%v.%x'] Filename for the output (%i=info, %x=txt). Affected by global options
output: '%f-%i%I%v.%x'
# IPC-DPMX (IPC-2581):
# Only available for KiCad 9 and newer.
# The requested fields are optional
- name: 'ipc2581_example'
comment: 'Exports the PCB in the Digital Product Model Exchange IPC format.'
type: 'ipc2581'
dir: 'Example/ipc2581_dir'
options:
# [boolean=true] Compress the XML file as a *zip* file
compress: true
# [string|list(string)='_null'] Name of the filter to mark components as not fitted.
# Is a short-cut to use for simple cases where a variant is an overkill.
# Can be used to fine-tune a variant for a particular output that needs extra filtering done before the
# variant
dnf_filter: '_null'
# [string|list(string)='_null'] Name of the filter to exclude components from processing.
# Is a short-cut to use for simple cases where a variant is an overkill.
# Can be used to fine-tune a variant for a particular output that needs extra filtering done before the
# variant
exclude_filter: '_null'
# [string='_field_dist_part_number'] Name of the field used for the distributor part number.
# Use the `field_dist_part_number` global variable to define `_field_dist_part_number`
field_dist_part_number: '_field_dist_part_number'
# [string='_field_distributor'] Name of the field used for the distributor.
# Use the `field_distributor` global variable to define `_field_distributor`
field_distributor: '_field_distributor'
# [string=''] Name of the field used as an internal ID.
# Leave empty to create unique IDs
field_internal_id: ''
# [string='_field_manufacturer'] Name of the field used for the manufacturer.
# Use the `field_manufacturer` global variable to define `_field_manufacturer`
field_manufacturer: '_field_manufacturer'
# [string='_field_part_number'] Name of the field used for the manufacturer part number.
# Use the `field_part_number` global variable to define `_field_part_number`
field_part_number: '_field_part_number'
# [string='%f-%i%I%v.%x'] Filename for the output (%i=IPC-2581, %x=zip/xml)
# The extension depends on the compress option. Affected by global options
output: '%f-%i%I%v.%x'
# [string|list(string)='_null'] Name of the filter to transform fields before applying other filters.
# Is a short-cut to use for simple cases where a variant is an overkill.
# Can be used to fine-tune a variant for a particular output that needs extra filtering done before the
# variant
pre_transform: '_null'
# [number=6] Number of decimals used to represent the values
precision: 6
# [string='millimeters'] [millimeters,inches] Units used for the positions. Affected by global options.
# Note that when using *mils* as global units this option becomes *inches*
units: 'millimeters'
# [string=''] Board variant to apply
variant: ''
# [string='C'] [B,C] Which implementation of the IPC-2581 standard will be generated
version: 'C'
# KiBoM (KiCad Bill of Materials):
# For more information: https://github.com/INTI-CMNB/KiBoM
# Note that this output is provided as a compatibility tool.
Expand Down
1 change: 1 addition & 0 deletions docs/source/Changelog.rst
Original file line number Diff line number Diff line change
Expand Up @@ -22,6 +22,7 @@ Added
- New outputs:

- ODB: Exports the PCB in ODB++ format (KiCad 9) (#782)
- IPC2581: Exports the PCB in IPC-2581 (IPC-DPMX) format (KiCad 9)

- CLI:

Expand Down
40 changes: 40 additions & 0 deletions docs/source/configuration/outputs/IPC2581Options.rst
Original file line number Diff line number Diff line change
@@ -0,0 +1,40 @@
.. _IPC2581Options:


IPC2581Options parameters
~~~~~~~~~~~~~~~~~~~~~~~~~

- **output** :index:`: <pair: output - ipc2581 - options; output>` [:ref:`string <string>`] (default: ``'%f-%i%I%v.%x'``) Filename for the output (%i=IPC-2581, %x=zip/xml)
The extension depends on the compress option. Affected by global options.
- ``compress`` :index:`: <pair: output - ipc2581 - options; compress>` [:ref:`boolean <boolean>`] (default: ``true``) Compress the XML file as a *zip* file.
- ``dnf_filter`` :index:`: <pair: output - ipc2581 - options; dnf_filter>` [:ref:`string <string>` | :ref:`list(string) <list(string)>`] (default: ``'_null'``) Name of the filter to mark components as not fitted.
Is a short-cut to use for simple cases where a variant is an overkill. |br|
Can be used to fine-tune a variant for a particular output that needs extra filtering done before the
variant.

- ``exclude_filter`` :index:`: <pair: output - ipc2581 - options; exclude_filter>` [:ref:`string <string>` | :ref:`list(string) <list(string)>`] (default: ``'_null'``) Name of the filter to exclude components from processing.
Is a short-cut to use for simple cases where a variant is an overkill. |br|
Can be used to fine-tune a variant for a particular output that needs extra filtering done before the
variant.

- ``field_dist_part_number`` :index:`: <pair: output - ipc2581 - options; field_dist_part_number>` [:ref:`string <string>`] (default: ``'_field_dist_part_number'``) Name of the field used for the distributor part number.
Use the `field_dist_part_number` global variable to define `_field_dist_part_number`.
- ``field_distributor`` :index:`: <pair: output - ipc2581 - options; field_distributor>` [:ref:`string <string>`] (default: ``'_field_distributor'``) Name of the field used for the distributor.
Use the `field_distributor` global variable to define `_field_distributor`.
- ``field_internal_id`` :index:`: <pair: output - ipc2581 - options; field_internal_id>` [:ref:`string <string>`] (default: ``''``) Name of the field used as an internal ID.
Leave empty to create unique IDs.
- ``field_manufacturer`` :index:`: <pair: output - ipc2581 - options; field_manufacturer>` [:ref:`string <string>`] (default: ``'_field_manufacturer'``) Name of the field used for the manufacturer.
Use the `field_manufacturer` global variable to define `_field_manufacturer`.
- ``field_part_number`` :index:`: <pair: output - ipc2581 - options; field_part_number>` [:ref:`string <string>`] (default: ``'_field_part_number'``) Name of the field used for the manufacturer part number.
Use the `field_part_number` global variable to define `_field_part_number`.
- ``pre_transform`` :index:`: <pair: output - ipc2581 - options; pre_transform>` [:ref:`string <string>` | :ref:`list(string) <list(string)>`] (default: ``'_null'``) Name of the filter to transform fields before applying other filters.
Is a short-cut to use for simple cases where a variant is an overkill. |br|
Can be used to fine-tune a variant for a particular output that needs extra filtering done before the
variant.

- ``precision`` :index:`: <pair: output - ipc2581 - options; precision>` [:ref:`number <number>`] (default: ``6``) Number of decimals used to represent the values.
- ``units`` :index:`: <pair: output - ipc2581 - options; units>` [:ref:`string <string>`] (default: ``'millimeters'``) (choices: "millimeters", "inches") Units used for the positions. Affected by global options.
Note that when using *mils* as global units this option becomes *inches*.
- ``variant`` :index:`: <pair: output - ipc2581 - options; variant>` [:ref:`string <string>`] (default: ``''``) Board variant to apply.
- ``version`` :index:`: <pair: output - ipc2581 - options; version>` [:ref:`string <string>`] (default: ``'C'``) (choices: "B", "C") Which implementation of the IPC-2581 standard will be generated.

49 changes: 49 additions & 0 deletions docs/source/configuration/outputs/ipc2581.rst
Original file line number Diff line number Diff line change
@@ -0,0 +1,49 @@
.. Automatically generated by KiBot, please don't edit this file
.. index::
pair: IPC-DPMX (IPC-2581); ipc2581

IPC-DPMX (IPC-2581)
~~~~~~~~~~~~~~~~~~~

Exports the PCB in the Digital Product Model Exchange IPC format.
Only available for KiCad 9 and newer. |br|
The requested fields are optional

Type: ``ipc2581``

Categories: **PCB/export**, **PCB/fabrication**

Parameters:

- **comment** :index:`: <pair: output - ipc2581; comment>` [:ref:`string <string>`] (default: ``''``) A comment for documentation purposes. It helps to identify the output.
- **dir** :index:`: <pair: output - ipc2581; dir>` [:ref:`string <string>`] (default: ``'./'``) Output directory for the generated files.
If it starts with `+` the rest is concatenated to the default dir.
- **name** :index:`: <pair: output - ipc2581; name>` [:ref:`string <string>`] (default: ``''``) Used to identify this particular output definition.
Avoid using `_` as first character. These names are reserved for KiBot.
- **options** :index:`: <pair: output - ipc2581; options>` [:ref:`IPC2581Options parameters <IPC2581Options>`] [:ref:`dict <dict>`] (default: empty dict, default values used) Options for the `ipc2581` output.
- **type** :index:`: <pair: output - ipc2581; type>` 'ipc2581'
- ``category`` :index:`: <pair: output - ipc2581; category>` [:ref:`string <string>` | :ref:`list(string) <list(string)>`] (default: ``''``) [:ref:`comma separated <comma_sep>`] The category for this output. If not specified an internally defined
category is used. |br|
Categories looks like file system paths, i.e. **PCB/fabrication/gerber**. |br|
Using '.' or './' as a category puts the file at the root. |br|
The categories are currently used for `navigate_results` and `navigate_results_rb`.

- ``disable_run_by_default`` :index:`: <pair: output - ipc2581; disable_run_by_default>` [:ref:`string <string>` | :ref:`boolean <boolean>`] (default: ``''``) Use it to disable the `run_by_default` status of other output.
Useful when this output extends another and you don't want to generate the original. |br|
Use the boolean true value to disable the output you are extending.
- ``extends`` :index:`: <pair: output - ipc2581; extends>` [:ref:`string <string>`] (default: ``''``) Copy the `options` section from the indicated output.
Used to inherit options from another output of the same type.
- ``groups`` :index:`: <pair: output - ipc2581; groups>` [:ref:`string <string>` | :ref:`list(string) <list(string)>`] (default: ``''``) One or more groups to add this output. In order to catch typos
we recommend to add outputs only to existing groups. You can create an empty group if
needed.

- ``output_id`` :index:`: <pair: output - ipc2581; output_id>` [:ref:`string <string>`] (default: ``''``) Text to use for the %I expansion content. To differentiate variations of this output.
- ``priority`` :index:`: <pair: output - ipc2581; priority>` [:ref:`number <number>`] (default: ``50``) (range: 0 to 100) Priority for this output. High priority outputs are created first.
Internally we use 10 for low priority, 90 for high priority and 50 for most outputs.
- ``run_by_default`` :index:`: <pair: output - ipc2581; run_by_default>` [:ref:`boolean <boolean>`] (default: ``true``) When enabled this output will be created when no specific outputs are requested.

.. toctree::
:caption: Used dicts

IPC2581Options
8 changes: 7 additions & 1 deletion docs/source/configuration/sup_globals.rst
Original file line number Diff line number Diff line change
Expand Up @@ -96,9 +96,15 @@
- ``field_current`` :index:`: <pair: global options; field_current>` [:ref:`string <string>` | :ref:`list(string) <list(string)>`] (default: ``['current', 'i']``) Name/s of the field/s used for the current raiting.
You can use `_field_current` as field name to use it in most places.

- ``field_dist_part_number`` :index:`: <pair: global options; field_dist_part_number>` [:ref:`string <string>`] (default: ``''``) The name of the schematic field that contains the distributor part number.
You can use `_field_dist_part_number` as field name to use it in most places.
- ``field_distributor`` :index:`: <pair: global options; field_distributor>` [:ref:`string <string>`] (default: ``''``) The name of the schematic field that contains the distributor.
You can use `_field_distributor` as field name to use it in most places.
- ``field_lcsc_part`` :index:`: <pair: global options; field_lcsc_part>` [:ref:`string <string>`] (default: ``''``) The name of the schematic field that contains the part number for the LCSC/JLCPCB distributor.
When empty KiBot will try to discover it. |br|
You can use `_field_lcsc_part` as field name to use it in most places.
- ``field_manufacturer`` :index:`: <pair: global options; field_manufacturer>` [:ref:`string <string>`] (default: ``''``) The name of the schematic field that contains the manufacturer.
You can use `_field_manufacturer` as field name to use it in most places.
- ``field_package`` :index:`: <pair: global options; field_package>` [:ref:`string <string>` | :ref:`list(string) <list(string)>`] (default: ``['package', 'pkg']``) Name/s of the field/s used for the package, not footprint.
I.e. 0805, SOT-23, etc. Used for the value split filter. |br|
You can use `_field_package` as field name to use it in most places.
Expand Down Expand Up @@ -212,7 +218,7 @@
- ``time_format`` :index:`: <pair: global options; time_format>` [:ref:`string <string>`] (default: ``'%H-%M-%S'``) Format used for the time we started the script. Uses the `strftime` format.
- ``time_reformat`` :index:`: <pair: global options; time_reformat>` [:ref:`boolean <boolean>`] (default: ``true``) Tries to reformat the PCB/SCH date using the `date_format`.
This assumes you let KiCad fill this value and hence the time is in ISO format (YY-MM-DD).
- ``units`` :index:`: <pair: global options; units>` [:ref:`string <string>`] (default: ``''``) (choices: "millimeters", "inches", "mils") Default units. Affects `position`, `bom` and `panelize` outputs and
- ``units`` :index:`: <pair: global options; units>` [:ref:`string <string>`] (default: ``''``) (choices: "millimeters", "inches", "mils") Default units. Affects `position`, `bom`, `panelize` and 'odb' outputs, and
the `erc` and `drc` preflights. Also KiCad 6 dimensions.
- ``use_dir_for_preflights`` :index:`: <pair: global options; use_dir_for_preflights>` [:ref:`boolean <boolean>`] (default: ``true``) Use the global `dir` as subdir for the preflights.
- ``use_os_env_for_expand`` :index:`: <pair: global options; use_os_env_for_expand>` [:ref:`boolean <boolean>`] (default: ``true``) In addition to KiCad text variables also use the OS environment variables when expanding `${VARIABLE}`.
Expand Down
1 change: 1 addition & 0 deletions docs/source/configuration/sup_outputs.rst
Original file line number Diff line number Diff line change
Expand Up @@ -28,6 +28,7 @@ Notes:
outputs/hpgl_sch_print
outputs/ibom
outputs/info
outputs/ipc2581
outputs/kibom
outputs/kicanvas
outputs/kicost
Expand Down
14 changes: 13 additions & 1 deletion kibot/globals.py
Original file line number Diff line number Diff line change
Expand Up @@ -299,7 +299,7 @@ def __init__(self):
""" Tries to reformat the PCB/SCH date using the `date_format`.
This assumes you let KiCad fill this value and hence the time is in ISO format (YY-MM-DD) """
self.units = ''
""" [millimeters,inches,mils] Default units. Affects `position`, `bom` and `panelize` outputs and
""" [millimeters,inches,mils] Default units. Affects `position`, `bom`, `panelize` and 'odb' outputs, and
the `erc` and `drc` preflights. Also KiCad 6 dimensions """
self.use_dir_for_preflights = True
""" Use the global `dir` as subdir for the preflights """
Expand All @@ -321,6 +321,15 @@ def __init__(self):
self.field_part_number = ''
""" The name of the schematic field that contains the manufacturer part number.
You can use `_field_part_number` as field name to use it in most places """
self.field_manufacturer = ''
""" The name of the schematic field that contains the manufacturer.
You can use `_field_manufacturer` as field name to use it in most places """
self.field_dist_part_number = ''
""" The name of the schematic field that contains the distributor part number.
You can use `_field_dist_part_number` as field name to use it in most places """
self.field_distributor = ''
""" The name of the schematic field that contains the distributor.
You can use `_field_distributor` as field name to use it in most places """
self.allow_blind_buried_vias = True
""" Allow the use of buried vias. This value is only used for KiCad 7+.
For KiCad 5 and 6 use the design rules settings, stored in the project """
Expand Down Expand Up @@ -528,6 +537,9 @@ def config(self, parent):
self.field_temp_coef = Optionable.force_list(self.field_temp_coef)
self.field_power = Optionable.force_list(self.field_power)
self.field_part_number = Optionable.force_list(self.field_part_number)
self.field_manufacturer = Optionable.force_list(self.field_manufacturer)
self.field_dist_part_number = Optionable.force_list(self.field_dist_part_number)
self.field_distributor = Optionable.force_list(self.field_distributor)
# Transfer options to the GS globals
for option in filter(lambda x: x[0] != '_', self.__dict__.keys()):
gl = 'global_'+option
Expand Down
3 changes: 3 additions & 0 deletions kibot/gs.py
Original file line number Diff line number Diff line change
Expand Up @@ -170,7 +170,10 @@ class GS(object):
global_extra_pth_drill = None
global_field_3D_model = None
global_field_current = None
global_field_dist_part_number = None
global_field_distributor = None
global_field_lcsc_part = None
global_field_manufacturer = None
global_field_package = None
global_field_part_number = None
global_field_power = None
Expand Down
15 changes: 12 additions & 3 deletions kibot/kiplot.py
Original file line number Diff line number Diff line change
@@ -1,8 +1,8 @@
# -*- coding: utf-8 -*-
# Copyright (c) 2020-2024 Salvador E. Tropea
# Copyright (c) 2020-2024 Instituto Nacional de Tecnología Industrial
# Copyright (c) 2020-2025 Salvador E. Tropea
# Copyright (c) 2020-2025 Instituto Nacional de Tecnología Industrial
# Copyright (c) 2018 John Beard
# License: GPL-3.0
# License: AGPL-3.0
# Project: KiBot (formerly KiPlot)
# Adapted from: https://github.com/johnbeard/kiplot
"""
Expand All @@ -19,6 +19,7 @@
from glob import glob
from importlib.util import spec_from_file_location, module_from_spec

from .bom.columnlist import ColumnList
from .gs import GS
from .registrable import RegOutput
from .misc import (PLOT_ERROR, CORRUPTED_PCB, EXIT_BAD_ARGS, CORRUPTED_SCH, version_str2tuple,
Expand Down Expand Up @@ -1334,6 +1335,14 @@ def generate_examples(start_dir, dry, types):
Popen(['x-www-browser', index])


def get_columns():
""" Create a list of valid columns """
if GS.sch:
cols = deepcopy(ColumnList.COLUMNS_DEFAULT)
return (GS.sch.get_field_names(cols), ColumnList.COLUMNS_EXTRA)
return (ColumnList.COLUMNS_DEFAULT, ColumnList.COLUMNS_EXTRA)


# To avoid circular dependencies: Optionable needs it, but almost everything needs Optionable
GS.load_board = load_board
GS.load_sch = load_sch
Expand Down
Loading

0 comments on commit 8c26d8e

Please sign in to comment.