## CAM support

The purpose of the CAM support is to provide a unified interface to export a board in different file formats using different exporter plugins. The interface consists of a CLI layer (each export plugin's "cam" option) and an optional GUI (the CAM plugin).

### CAM export support in multi-layer plugins with '-x plugin --cam'

This section is about the syntax used by the exporters that export multiple layers (e.g. gerber, ps, png).

Each CAM-plugin-compatible exporter plugin offers an option called "cam". The syntax and capabilities are the same for all exporter's cam option.

The syntax is:

    outfile=[global-opts] layergrp,layergrp,...

where:

- outfile is the output file name template that substitutes %%:
  - %name% is substituted with the layer group name
  - %base% is substituted with the base name of the output file path (the file name without directories)
  - %top_offs% is substituted with the layer group offset from the top (top layer group being 0); only layer groups with the same material considered
  - %bot_offs% is substituted with the layer group offset from the bottom (bottom layer group being 0); only layer groups with the same material considered
- optionally [global-opts]: a comma separated list of group-global (but per-output-file) options in [] brackets. Options supported:
  - okempty-group: warning suppression: do not warn when none of the layer groups referenced for an outfile exists (outfile can not be created or will be empty)
  - okempty-content: warning suppression: do not warn when all layer groups for an outfile were empty (outfile is normally created and valid, but is empty as no object got exported)
  - okempty: shorthand that enables both okempty-group and okempty-content
  - flip_x: set conf node editor/view/flip_x (x coords are mirrored)
  - flip_y: set conf node editor/view/flip_y (y coords are mirrored)
  - force_nonempty: export even if groups i empty and the exporter would normally not export empty groups
- layergrp: one or more layer group addresses separated by comma (syntax is documented in layer addressing appendix.)

Examples:

directive | explanation
--- | ---
bot.gbr=@bottom_copper,@bottom_silk | export layer groups called bottom_copper and bottom_silk (by group name)
asm_top.ps=top-virtual(purpose=assy) | export the top assembly layer group (by type)
fabrication.ps=virtual(purpose=fab) | export the first virtual layer group with 'fab' purpose
gnd=copper:2 | export the second copper layer group from the top (the first internal copper layer group under the top copper layer group, if it is a multilayer board; for 2 layer boards this will be the bottom copper layer group)
gnd=intern-copper:1 | similar to the above, but addresses the first internal copper layer group explicitly so it can not end up being the bottom copper layer group
pwr=copper:-2 | export the second copper layer group from the bottom (the first internal copper layer group above the bottom copper layer group, if it is a multilayer board; for 2 layer boards this will be the top copper layer group)
gnd=intern-copper:-1 | similar to the above, but addresses the last internal copper layer group explicitly so it can not end up being the top copper layer group
pst.gbr=top-paste(bloat=0.1mm),bottom-paste(bloat=0.1mm) | export the top and bottom paste groups in the same file with all objects bloated up by 0.1mm
plated_drills.cnc=virtual(purpose=pdrill) | export plated drilled holes (padstack side effects, but no slots)
unplated_drills.cnc=virtual(purpose=udrill) | export unplated drilled holes (padstack side effects, but no slots)
unplated_drills.cnc=[okempty] virtual(purpose=udrill) | same as the previous, but do not print a warning if there was no unplated drill in the design

If multiple layer groups match a layergrp specification, all matching layer groups are exported. If the file name is a static string, they are all merged. If the file name is templated, it is possible to export the layer groups in multiple files. For example:

directive | explanation
--- | ---
copper.gbr=copper | export all copper layers to copper.gbr
copper-%top_offs%.gbr=copper | export all copper layers to numbered copper-N.gbr files where N is the offset from the top side, starting from 0 (for top copper)
copper-%name%.gbr=copper | export all copper layers to numbered copper-N.gbr files where N is the full name of the group being exported

### CAM export support in no-layer plugins with '-x plugin --cam'

This section is about the syntax used by the exporters export global digest of the board and not layers (e.g. XY).

For these exporters the above apply with no layergrp specified. In the simplest for this means the '=' and the rest of the line is omitted. However, if supplement needs to be passed, the syntax is filename=(supplement). For example the XY exporter can be used with

    --cam foo.xy

or a partial excellon export can be done using:

    --cam foo.exc=(partial)

The --cam option in these exporters are implemented for two reasons:

- to provide an unified syntax for the output file name
- to allow a CAM job to use these exporters

### partial export

In partial exporting the rendering code in core will draw only those object that have the EXPORTSEL flag set. The flag is normally set by a query() action using an expression.

A typical use of this feature is to export plugged/filled vias into a separate file, assuming the padstacks have a specific attribute set.

### CAM plugin (CAM jobs) with '-x cam'

The CAM plugin is a way to manage output "jobs": collections of cam export settings for reproducing export packages in various formats.

...

A job is a script that contains zero or more export directives, separated by semicolons or newlines. An export directive is one of these:

    desc text
    plugin name [--option value] [--option value] ...
    write outfile=layergrp[,layergrp,...]

desc is a free form one-liner that describes what the job is for. Multiple desc directives may be present (to bypass the limitation that the text can not contain newlines).

The plugin directive selects a plugin and sets plugin specific options. The plugin and options are active until the next plugin directive or the end of the script. The first outfile directive must be preceeded by a plugin directive.

The write directive argument has the same syntax as the cam argument for each cam-capable exporter, see above. Each write is a call to an exporter the same way as if pcb-rnd was called with --cam and -x with the exporter and options taken from the last plugin directive.

For example, the following config tree defines a job called doc_png that generates two 600 DPI images from the sides of the board, copper and silk combined, all in the doc/ dir (that is created if necessary):

    li:pcb-rnd-conf-v1 {
    	ha:overwrite {
    		ha:plugins {
    			ha:cam {
    				li:jobs {
    					doc_png {
    						desc export top and bottom copper and silk in 600 DPI pngs
    						plugin png --dpi 600
    						write top.png=top-copper,top-silk
    						write bottom.png=bottom-copper,bottom-silk
    					}
    				}
    			}
    		}
    	}
    }

Once the above subtree is loaded in the config, the following action triggers the export:

    cam(call, doc_png)

If the command partial appears in the job, a query() is executed with the expression specified in the command's argument, marking matching objects with the EXPORTSEL flag. The full command is used to remove the EXPORTSEL flag from all objects. Note: to export only marked objects, the write command will typically need the partial supplement. A typical use case is exporting filled vias in a separate file, using a custom object attribute called "process":

    li:pcb-rnd-conf-v1 {
    	ha:overwrite {
    		ha:plugins {
    			ha:cam {
    				li:jobs {
    					holes {
    						desc export all holes in excellon files, sorted by whether they are filled
    						plugin excellon
    						partial @.a.process == "filled"
    						write filled.exc=(partial)
    						full
    						partial @.a.process != "filled"
    						write unfilled.exc=(partial)
    						full
    						write all.exc
    					}
    				}
    			}
    		}
    	}
    }

Note: the first full command is used to cancel the effect of the first partial command. Without full, at the second partial all the "filled" vias would still be marked and unfilled.exc would contain both filled and unfilled vias.

### Tips for using with various exporters

When exporting to ps, consider using the --no-show-toc. It is possible to combine multiple layers (e.g. top silk and top copper, which may be useful for a single-layer board) using the --single-page option.

The plugin field has the same values command line -x has. The list of currently available exporter names can be acquired by running

    pcb-rnd -x

Note: this list contains all exporter plugins currently available (depends on your configure time options and plugin availability). Some export plugins can not do per layer exporting and those will not support CAM exporting either.