diff --git a/docs/fabrication/jlcpcb.md b/docs/fabrication/jlcpcb.md index 92900074..b6af6c54 100644 --- a/docs/fabrication/jlcpcb.md +++ b/docs/fabrication/jlcpcb.md @@ -61,6 +61,41 @@ the intended origin in footprint editor and mark the coordinates. Note that first the rotation correction is applied, then the translation. Usually, you will need only the rotation correction. +## Correction Pattern Files + +Specifying corrections for individual components can quickly become tedious. +It is also possible to specify correction patterns using CSV files. The +correction pattern files have the following format: + +``` +"Pattern","X correction","Y correction","Rotation" +"^U101$",0,0,180 +"^COS1333TR$",0,0,-90 +":PinHeader_2x06_P2.54mm_",1.27,6.35,90 +":SOIC-8_3.9x4.9mm_P1.27mm",0,0,-90 +":VQFN-20-1EP_3x3mm_P0.4mm_EP1.7x1.7mm",0,0,-90 +":SS5U100_TO-277",0.8,0,0 +":SOT-23",0,0,180 +``` + +The X and Y correction values are in millimeters and refer to the +component footprint original orientation. The rotation correction is in degrees, +with positive values meaning counter-clockwise rotation. + +The Pattern field is a regular expression that is matched against the +reference, value and footprint fields of the component (in this order). For +all footprints, the first matching pattern and field values are used. The +pattern is matched against the whole string, so you should use `^` and `$` +characters to match the beginning and the end of the string if you want to +match the whole string. + +In the example above, the first row matches a specific component with +reference `U101`. The second row matches all components with value +`COS1333TR`. The following rows match all components with a given footprint. +For footprints, the pattern is matched against the whole footprint name, +including the library - for example, `Package_TO_SOT_SMD:SOT-23-5`. To only +match the name part, all footprint patterns in the example start with `:`. + ## Using Corrections to Configure Jumpers If your board features solder jumpers you can use the corrections to specify @@ -69,7 +104,7 @@ Ohm resistor in suitable size. Then specify an order code of the zero Ohm resistor for the jumper and adjust correction so it fits the default position. Note that you can specify multiple correction fields by `--corrections `. The first found correction field is +separated list of correction field names>`. The first found correction field is used. This allows you to keep several configuration of the solder jumpers in your design e.g., in fields `JLCPCB_CORRECTION_CFG_1` and `JLCPCB_CORRECTION_CFG_2`. Then you can simply change the board configuration by diff --git a/kikit/fab/common.py b/kikit/fab/common.py index 0fbef8d1..0acfa0b2 100644 --- a/kikit/fab/common.py +++ b/kikit/fab/common.py @@ -63,12 +63,14 @@ class FormatError(Exception): @dataclass class CorrectionPattern: """Single correction pattern to match a component against.""" - footprint: re.Pattern - part_id: re.Pattern + pattern: re.Pattern x_correction: float y_correction: float rotation: float +class CorrectionPatternError(Exception): + pass + def layerToSide(layer): if layer == pcbnew.F_Cu: return "T" @@ -112,7 +114,7 @@ def readCorrectionPatterns(filename): - Regexp to match to the part id (ignored at the moment) - X correction - Y correction - - Rotation + - Rotation (positive is counterclockwise) """ corrections = OrderedDict() correctionPatterns = [] @@ -124,27 +126,31 @@ def readCorrectionPatterns(filename): reader = csv.reader(csvfile, dialect) first = True for row in reader: + if len(row) != 4: + raise CorrectionPatternError(f"Invalid number of fields in {row}") if has_header and first: first = False continue correctionPatterns.append( CorrectionPattern( re.compile(row[0]), - re.compile(row[1]), + float(row[1]), float(row[2]), float(row[3]), - float(row[4]), ) ) return correctionPatterns def applyCorrectionPattern(correctionPatterns, footprint): - # FIXME: part ID is currently ignored - # GetUniStringLibId returns the full footprint name including the + footprintReference = footprint.GetReference() + footprintValue = footprint.GetValue() + # GetFPIDAsString returns the full footprint name including the # library in the form of "Resistor_SMD:R_0402_1005Metric" - footprintName = str(footprint.GetFPID().GetUniStringLibId()) + footprintName = footprint.GetFPIDAsString() + cps = lambda x: corpat.pattern.search(x) for corpat in correctionPatterns: - if corpat.footprint.match(footprintName): + # try to match reference, value or footprint + if cps(footprintReference) or cps(footprintValue) or cps(footprintName): return (corpat.x_correction, corpat.y_correction, corpat.rotation) return (0, 0, 0)