From e076b62190b0dd7ed6ef672a0f4e01ca736984ad Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?B=C3=A1n=20D=C3=A9nes?= Date: Sun, 4 Dec 2022 20:58:46 +0100 Subject: [PATCH] Per-footprint mirror overrides, better coordinate support --- roadmap.md | 9 +-- src/pcbs.js | 27 +++++-- test/helpers/mock_footprints.js | 24 +++--- test/pcbs/mock_footprints.yaml | 8 +- .../mock_footprints___pcbs_main.kicad_pcb | 73 ++++++++++++++++--- 5 files changed, 106 insertions(+), 35 deletions(-) diff --git a/roadmap.md b/roadmap.md index d54b04d..e34d9ec 100644 --- a/roadmap.md +++ b/roadmap.md @@ -6,18 +6,11 @@ ### Major -- Restructure pcb point/footprint filtering - - Use the same `what`/`where` infrastructure as outlines - - Collapse params/nets/anchors into a single hierarchy from the user's POV - - Add per-footprint mirror support - - Add some way for footprints to be able to "resist" the mirroring-related special treatment of negative X shift, rotation, etc. - Merge, generalize, uniform-ize and externalize footprints! - onnx-like incremental opset versioning - Template for creating them, built-in variables they can use, documentation, external links, etc. - Add access to whole set of points + filtering logic, so they can implement their own connection logic as well maybe (see daisy chaining) - - footprint parameters inside the body should be `p.params.field` instead of `p.param.field` so it actually matches the options that you pass in - - Also considering how (or, on which layer) they define their silks, universal mirroring behaviour, etc. - - Rename class to designator in this context (https://en.wikipedia.org/wiki/Reference_designator#Designators) + - Also considering how (or, on which layer) they define their silks, universal mirroring behaviour (see ixy/xy/sxy note), etc. ### Minor diff --git a/src/pcbs.js b/src/pcbs.js index be8fce4..3289d12 100644 --- a/src/pcbs.js +++ b/src/pcbs.js @@ -157,11 +157,21 @@ const footprint = exports._footprint = (points, net_indexer, component_indexer, a.unexpected(config, name, ['what', 'params']) const what = a.in(config.what, `${name}.what`, Object.keys(footprint_types)) const fp = footprint_types[what] - const params = config.params || {} - a.unexpected(params, `${name}.params`, Object.keys(fp.params)) - const parsed_params = {} + const original_params = config.params || {} + // param sanitization + // we unset the mirror config, as it would be an unexpected field + let params = u.deepcopy(original_params) + delete params.mirror + // but still override with it when applicable + if (point.meta.mirrored && original_params.mirror !== undefined) { + const mirror_overrides = a.sane(original_params.mirror, `${name}.params.mirror`, 'object')() + params = prep.extend(params, mirror_overrides) + } + a.unexpected(params, `${name}.params`, Object.keys(fp.params)) + // parsing parameters + const parsed_params = {} for (const [param_name, param_def] of Object.entries(fp.params)) { // expand param definition shorthand @@ -219,12 +229,19 @@ const footprint = exports._footprint = (points, net_indexer, component_indexer, // footprint positioning parsed_params.at = `(at ${point.x} ${-point.y} ${point.r})` parsed_params.rot = point.r - parsed_params.xy = (x, y) => { + parsed_params.ixy = (x, y) => { + const sign = point.meta.mirrored ? -1 : 1 + return `${sign * x} ${y}` + } + const xyfunc = (x, y, resist=true) => { const new_anchor = anchor({ - shift: [x, -y] + shift: [x, -y], + resist: resist }, '_internal_footprint_xy', points, point)(units) return `${new_anchor.x} ${-new_anchor.y}` } + parsed_params.xy = (x, y) => xyfunc(x, y, true) + parsed_params.sxy = (x, y) => xyfunc(x, y, false) // allowing footprints to add dynamic nets parsed_params.local_net = suffix => { diff --git a/test/helpers/mock_footprints.js b/test/helpers/mock_footprints.js index 8a6b47f..749d26c 100644 --- a/test/helpers/mock_footprints.js +++ b/test/helpers/mock_footprints.js @@ -8,19 +8,19 @@ exports.inject = (ergogen) => { body: p => { return ` - (module trace_test (layer F.Cu) (tedit 5CF31DEF) + (module trace_test (layer ${p.side}.Cu) (tedit 5CF31DEF) ${p.at /* parametric position */} - (pad 1 smd rect (at 0 0 ${p.rot}) (size 1 1) (layers F.Cu F.Paste F.Mask) + (pad 1 smd rect (at ${p.ixy(0, 0)} ${p.rot}) (size 1 1) (layers ${p.side}.Cu ${p.side}.Paste ${p.side}.Mask) ${p.P1.str} (solder_mask_margin 0.2)) - (pad 2 smd rect (at 5 5 ${p.rot}) (size 1 1) (layers F.Cu F.Paste F.Mask) + (pad 2 smd rect (at ${p.ixy(5, 5)} ${p.rot}) (size 1 1) (layers ${p.side}.Cu ${p.side}.Paste ${p.side}.Mask) ${p.P1.str} (solder_mask_margin 0.2)) ) - (segment (start ${p.xy(0, 0)}) (end ${p.xy(5, 5)}) (width 0.25) (layer F.Cu) (net ${p.P1.index})) + (segment (start ${p.sxy(0, 0)}) (end ${p.sxy(5, 5)}) (width 0.25) (layer ${p.side}.Cu) (net ${p.P1.index})) ` } @@ -35,14 +35,14 @@ exports.inject = (ergogen) => { body: p => { return ` - (module zone_test (layer F.Cu) (tedit 5CF31DEF) + (module zone_test (layer ${p.side}.Cu) (tedit 5CF31DEF) ${p.at /* parametric position */} - (pad 1 smd rect (at 0 0 ${p.rot}) (size 1 1) (layers F.Cu F.Paste F.Mask) + (pad 1 smd rect (at 0 0 ${p.rot}) (size 1 1) (layers ${p.side}.Cu ${p.side}.Paste ${p.side}.Mask) ${p.P1.str} (solder_mask_margin 0.2)) - (pad 2 smd rect (at 5 5 ${p.rot}) (size 1 1) (layers F.Cu F.Paste F.Mask) + (pad 2 smd rect (at 5 5 ${p.rot}) (size 1 1) (layers ${p.side}.Cu ${p.side}.Paste ${p.side}.Mask) ${p.P1.str} (solder_mask_margin 0.2)) ) @@ -66,17 +66,17 @@ exports.inject = (ergogen) => { body: p => { return ` - (module dynamic_net_test (layer F.Cu) (tedit 5CF31DEF) + (module dynamic_net_test (layer ${p.side}.Cu) (tedit 5CF31DEF) ${p.at /* parametric position */} - (pad 1 smd rect (at 0 0 ${p.rot}) (size 1 1) (layers F.Cu F.Paste F.Mask) + (pad 1 smd rect (at 0 0 ${p.rot}) (size 1 1) (layers ${p.side}.Cu ${p.side}.Paste ${p.side}.Mask) ${p.local_net('1').str} (solder_mask_margin 0.2)) - (pad 1 smd rect (at 0 0 ${p.rot}) (size 1 1) (layers F.Cu F.Paste F.Mask) + (pad 1 smd rect (at 0 0 ${p.rot}) (size 1 1) (layers ${p.side}.Cu ${p.side}.Paste ${p.side}.Mask) ${p.local_net('2').str} (solder_mask_margin 0.2)) - (pad 1 smd rect (at 0 0 ${p.rot}) (size 1 1) (layers F.Cu F.Paste F.Mask) + (pad 1 smd rect (at 0 0 ${p.rot}) (size 1 1) (layers ${p.side}.Cu ${p.side}.Paste ${p.side}.Mask) ${p.local_net('3').str} (solder_mask_margin 0.2)) ) @@ -94,7 +94,7 @@ exports.inject = (ergogen) => { body: p => { return ` - (module anchor_test (layer F.Cu) (tedit 5CF31DEF) + (module anchor_test (layer ${p.side}.Cu) (tedit 5CF31DEF) ${p.at /* parametric position */} diff --git a/test/pcbs/mock_footprints.yaml b/test/pcbs/mock_footprints.yaml index e3614a7..ddce5b0 100644 --- a/test/pcbs/mock_footprints.yaml +++ b/test/pcbs/mock_footprints.yaml @@ -1,4 +1,5 @@ points.zones.matrix: + mirror: 10 outlines: edge: - what: rectangle @@ -12,9 +13,14 @@ pcbs: footprints: trace: what: trace_test - where: + where: true + adjust: shift: [1, 1] rotate: 30 + params: + side: F + mirror: + side: B zone: what: zone_test where: diff --git a/test/pcbs/mock_footprints___pcbs_main.kicad_pcb b/test/pcbs/mock_footprints___pcbs_main.kicad_pcb index f3a1b49..d9b38b3 100644 --- a/test/pcbs/mock_footprints___pcbs_main.kicad_pcb +++ b/test/pcbs/mock_footprints___pcbs_main.kicad_pcb @@ -94,9 +94,9 @@ (net 0 "") (net 1 "P1") -(net 2 "T3_1") -(net 3 "T3_2") -(net 4 "T3_3") +(net 2 "T6_1") +(net 3 "T6_2") +(net 4 "T6_3") (net_class Default "This is the default net class." (clearance 0.2) @@ -107,9 +107,9 @@ (uvia_drill 0.1) (add_net "") (add_net "P1") -(add_net "T3_1") -(add_net "T3_2") -(add_net "T3_3") +(add_net "T6_1") +(add_net "T6_2") +(add_net "T6_3") ) @@ -131,6 +131,57 @@ + (module trace_test (layer B.Cu) (tedit 5CF31DEF) + + (at 19 -1 -30) + + (pad 1 smd rect (at 0 0 -30) (size 1 1) (layers B.Cu B.Paste B.Mask) + (net 1 "P1") (solder_mask_margin 0.2)) + + (pad 2 smd rect (at -5 5 -30) (size 1 1) (layers B.Cu B.Paste B.Mask) + (net 1 "P1") (solder_mask_margin 0.2)) + + ) + + (segment (start 19 -1) (end 12.169872999999999 0.8301270000000001) (width 0.25) (layer B.Cu) (net 1)) + + + + + (module trace_test (layer B.Cu) (tedit 5CF31DEF) + + (at 19 -1 -30) + + (pad 1 smd rect (at 0 0 -30) (size 1 1) (layers B.Cu B.Paste B.Mask) + (net 1 "P1") (solder_mask_margin 0.2)) + + (pad 2 smd rect (at -5 5 -30) (size 1 1) (layers B.Cu B.Paste B.Mask) + (net 1 "P1") (solder_mask_margin 0.2)) + + ) + + (segment (start 19 -1) (end 12.169872999999999 0.8301270000000001) (width 0.25) (layer B.Cu) (net 1)) + + + + + (module trace_test (layer F.Cu) (tedit 5CF31DEF) + + (at 1 -1 30) + + (pad 1 smd rect (at 0 0 30) (size 1 1) (layers F.Cu F.Paste F.Mask) + (net 1 "P1") (solder_mask_margin 0.2)) + + (pad 2 smd rect (at 5 5 30) (size 1 1) (layers F.Cu F.Paste F.Mask) + (net 1 "P1") (solder_mask_margin 0.2)) + + ) + + (segment (start 1 -1) (end 7.830127 0.8301270000000001) (width 0.25) (layer F.Cu) (net 1)) + + + + (module zone_test (layer F.Cu) (tedit 5CF31DEF) (at 1 -1 30) @@ -158,13 +209,13 @@ (at 0 0 0) (pad 1 smd rect (at 0 0 0) (size 1 1) (layers F.Cu F.Paste F.Mask) - (net 2 "T3_1") (solder_mask_margin 0.2)) + (net 2 "T6_1") (solder_mask_margin 0.2)) (pad 1 smd rect (at 0 0 0) (size 1 1) (layers F.Cu F.Paste F.Mask) - (net 3 "T3_2") (solder_mask_margin 0.2)) + (net 3 "T6_2") (solder_mask_margin 0.2)) (pad 1 smd rect (at 0 0 0) (size 1 1) (layers F.Cu F.Paste F.Mask) - (net 4 "T3_3") (solder_mask_margin 0.2)) + (net 4 "T6_3") (solder_mask_margin 0.2)) ) @@ -184,6 +235,10 @@ (gr_line (start 9.5 9.5) (end 9.5 -9.5) (angle 90) (layer Edge.Cuts) (width 0.15)) (gr_line (start 9.5 -9.5) (end -9.5 -9.5) (angle 90) (layer Edge.Cuts) (width 0.15)) (gr_line (start -9.5 -9.5) (end -9.5 9.5) (angle 90) (layer Edge.Cuts) (width 0.15)) +(gr_line (start 10.5 9.5) (end 29.5 9.5) (angle 90) (layer Edge.Cuts) (width 0.15)) +(gr_line (start 29.5 9.5) (end 29.5 -9.5) (angle 90) (layer Edge.Cuts) (width 0.15)) +(gr_line (start 29.5 -9.5) (end 10.5 -9.5) (angle 90) (layer Edge.Cuts) (width 0.15)) +(gr_line (start 10.5 -9.5) (end 10.5 9.5) (angle 90) (layer Edge.Cuts) (width 0.15)) )