Skip to content

Commit

Permalink
Add option to show DNP components in outline mode
Browse files Browse the repository at this point in the history
Fixes #75
  • Loading branch information
qu1ck committed Jun 25, 2019
1 parent 4a24edf commit d61bd56
Show file tree
Hide file tree
Showing 6 changed files with 64 additions and 37 deletions.
3 changes: 3 additions & 0 deletions DATAFORMAT.md
Original file line number Diff line number Diff line change
Expand Up @@ -30,6 +30,7 @@ pcbdata = {
},
// Describes footprints.
// See footprint structure description below.
// index of entry corresponds to component's numeric ID
"modules": [
footprint1,
footprint2,
Expand All @@ -48,6 +49,8 @@ pcbdata = {
"both": [bomrow1, bomrow2, ...],
"F": [bomrow1, bomrow2, ...],
"B": [bomrow1, bomrow2, ...],
// numeric IDs of DNP components that are not in BOM
"skipped": [id1, id2, ...]
},
// Contains parsed stroke data from newstroke font for
// characters used on the pcb.
Expand Down
63 changes: 35 additions & 28 deletions InteractiveHtmlBom/core/ibom.py
Original file line number Diff line number Diff line change
Expand Up @@ -46,15 +46,11 @@ def warn(self, msg):
wx.LogWarning(msg)


log = None # type: Logger
log = None # type: Logger or None


def skip_component(m, config, extra_data, filter_layer):
# type: (Component, Config, dict, str) -> bool
# filter part by layer
if filter_layer is not None and filter_layer != m.layer:
return True

def skip_component(m, config, extra_data):
# type: (Component, Config, dict) -> bool
# skip blacklisted components
ref_prefix = re.findall('^[A-Z]*', m.ref)[0]
if m.ref in config.component_blacklist:
Expand All @@ -65,6 +61,10 @@ def skip_component(m, config, extra_data, filter_layer):
if config.blacklist_empty_val and m.val in ['', '~']:
return True

# skip virtual components if needed
if config.blacklist_virtual and m.attr == 'Virtual':
return True

# skip components with dnp field not empty
if config.dnp_field and m.ref in extra_data \
and config.dnp_field in extra_data[m.ref] \
Expand All @@ -87,15 +87,14 @@ def skip_component(m, config, extra_data, filter_layer):
return False


def generate_bom(pcb_modules, config, extra_data, filter_layer=None):
# type: (list, Config, dict, str) -> list
def generate_bom(pcb_modules, config, extra_data):
# type: (list, Config, dict) -> dict
"""
Generate BOM from pcb layout.
:param pcb_modules: list of modules on the pcb
:param config: Config object
:param extra_data: Extra fields data
:param filter_layer: include only parts for given layer
:return: BOM table (qty, value, footprint, refs)
:return: dict of BOM tables (qty, value, footprint, refs) and dnp components
"""

def convert(text):
Expand All @@ -114,18 +113,16 @@ def natural_sort(l):

# build grouped part list
warning_shown = False
skipped_components = []
part_groups = {}
for i, m in enumerate(pcb_modules):
if skip_component(m, config, extra_data, filter_layer):
if skip_component(m, config, extra_data):
skipped_components.append(i)
continue

# group part refs by value and footprint
norm_value = units.componentValue(m.val)

# skip virtual components if needed
if config.blacklist_virtual and m.attr == 'Virtual':
continue

extras = []
if config.extra_fields:
if m.ref in extra_data:
Expand All @@ -134,11 +131,9 @@ def natural_sort(l):
else:
# Some components are on pcb but not in schematic data.
# Show a warning about possibly outdated netlist/xml file.
# Doing it only once when generating full bom is enough.
if filter_layer is None:
log.warn(
'Component %s is missing from schematic data.' % m.ref)
warning_shown = True
log.warn(
'Component %s is missing from schematic data.' % m.ref)
warning_shown = True
extras = [''] * len(config.extra_fields)

group_key = (norm_value, tuple(extras), m.footprint, m.attr)
Expand Down Expand Up @@ -169,7 +164,23 @@ def sort_func(row):
config.component_sort_order.append('~')
bom_table = sorted(bom_table, key=sort_func)

return bom_table
result = {
'both': bom_table,
'skipped': skipped_components
}

for layer in ['F', 'B']:
filtered_table = []
for row in bom_table:
filtered_refs = [ref for ref in row[3]
if pcb_modules[ref[1]].layer == layer]
if filtered_refs:
filtered_table.append((len(filtered_refs), row[1],
row[2], filtered_refs, row[4]))

result[layer] = sorted(filtered_table, key=sort_func)

return result


def open_file(filename):
Expand Down Expand Up @@ -274,14 +285,10 @@ def main(parser, config, logger):
if not pcbdata or not components:
logger.error('Parsing failed.')
return
pcbdata["bom"]["both"] = generate_bom(components, config, extra_fields)

# build BOM
for layer in ['F', 'B']:
bom_table = generate_bom(components, config, extra_fields,
filter_layer=layer)
pcbdata["bom"][layer] = bom_table
pcbdata["bom"] = generate_bom(components, config, extra_fields)

# build BOM
bom_file = generate_file(pcb_file_dir, pcb_file_name, pcbdata, config)

if config.open_browser:
Expand Down
4 changes: 4 additions & 0 deletions InteractiveHtmlBom/web/ibom.html
Original file line number Diff line number Diff line change
Expand Up @@ -71,6 +71,10 @@
<input id="valuesCheckbox" type="checkbox" checked onchange="valuesVisible(this.checked)">
Values
</label>
<label class="menu-label">
<input id="dnpOutlineCheckbox" type="checkbox" checked onchange="dnpOutline(this.checked)">
DNP components outlined
</label>
<label class="menu-label">
<input id="highlightpin1Checkbox" type="checkbox" onchange="setHighlightPin1(this.checked)">
Highlight first pin
Expand Down
10 changes: 10 additions & 0 deletions InteractiveHtmlBom/web/ibom.js
Original file line number Diff line number Diff line change
Expand Up @@ -46,6 +46,12 @@ function valuesVisible(value) {
redrawIfInitDone();
}

function dnpOutline(value) {
writeStorage("dnpOutline", value);
renderDnpOutline = value;
redrawIfInitDone();
}

function setDarkMode(value) {
if (value) {
topmostdiv.classList.add("dark");
Expand Down Expand Up @@ -775,6 +781,10 @@ function initDefaults() {
document.getElementById("valuesCheckbox").checked = b;
valuesVisible(b);

b = getStorageBooleanOrDefault("dnpOutline", false);
document.getElementById("dnpOutlineCheckbox").checked = b;
dnpOutline(b);

b = getStorageBooleanOrDefault("redrawOnDrag", config.redraw_on_drag);
document.getElementById("dragCheckbox").checked = b;
setRedrawOnDrag(b);
Expand Down
17 changes: 10 additions & 7 deletions InteractiveHtmlBom/web/render.js
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,7 @@ var boardRotation = 0;
var renderPads = true;
var renderReferences = true;
var renderValues = true;
var renderDnpOutline = false;

function deg2rad(deg) {
return deg * Math.PI / 180;
Expand Down Expand Up @@ -182,7 +183,7 @@ function drawCircle(ctx, radius, ctxmethod) {
ctxmethod();
}

function drawPad(ctx, pad, color, outline) {
function drawPad(ctx, pad, color, outline, hole) {
ctx.save();
ctx.translate(...pad.pos);
ctx.rotate(deg2rad(pad.angle));
Expand All @@ -208,7 +209,8 @@ function drawPad(ctx, pad, color, outline) {
} else if (pad.shape == "custom") {
drawPolygons(ctx, color, pad.polygons, ctxmethod);
}
if (pad.type == "th" && !outline) {
if (pad.type == "th" && hole) {
ctxmethod = ctx.fill.bind(ctx);
ctx.fillStyle = "#CCCCCC";
if (pad.drillshape == "oblong") {
drawOblong(ctx, "#CCCCCC", pad.drillsize, ctxmethod);
Expand All @@ -219,7 +221,7 @@ function drawPad(ctx, pad, color, outline) {
ctx.restore();
}

function drawModule(ctx, layer, scalefactor, module, padcolor, outlinecolor, highlight) {
function drawModule(ctx, layer, scalefactor, module, padcolor, outlinecolor, highlight, outline) {
if (highlight) {
// draw bounding box
if (module.layer == layer) {
Expand Down Expand Up @@ -248,9 +250,9 @@ function drawModule(ctx, layer, scalefactor, module, padcolor, outlinecolor, hig
if (renderPads) {
for (var pad of module.pads) {
if (pad.layers.includes(layer)) {
drawPad(ctx, pad, padcolor, false);
drawPad(ctx, pad, padcolor, outline, true);
if (pad.pin1 && highlightpin1) {
drawPad(ctx, pad, outlinecolor, true);
drawPad(ctx, pad, outlinecolor, true, false);
}
}
}
Expand All @@ -271,14 +273,15 @@ function drawModules(canvas, layer, scalefactor, highlight) {
var style = getComputedStyle(topmostdiv);
var padcolor = style.getPropertyValue('--pad-color');
var outlinecolor = style.getPropertyValue('--pin1-outline-color');
if (highlight > 0) {
if (highlight) {
padcolor = style.getPropertyValue('--pad-color-highlight');
outlinecolor = style.getPropertyValue('--pin1-outline-color-highlight');
}
for (var i = 0; i < pcbdata.modules.length; i++) {
var mod = pcbdata.modules[i];
var outline = renderDnpOutline && pcbdata.bom.skipped.includes(i);
if (!highlight || highlightedModules.includes(i)) {
drawModule(ctx, layer, scalefactor, mod, padcolor, outlinecolor, highlight);
drawModule(ctx, layer, scalefactor, mod, padcolor, outlinecolor, highlight, outline);
}
}
}
Expand Down
4 changes: 2 additions & 2 deletions InteractiveHtmlBom/web/util.js
Original file line number Diff line number Diff line change
Expand Up @@ -177,8 +177,8 @@ function initUtils() {
"([GgMmKkUuNnPp])?" +
"([0-9]*)" +
"(\\b.*)?$", "");
for (var bomtable of Object.values(pcbdata.bom)) {
for (var row of bomtable) {
for (var bom_type of ["both", "F", "B"]) {
for (var row of pcbdata.bom[bom_type]) {
row.push(parseValue(row[1], row[3][0][0]));
}
}
Expand Down

0 comments on commit d61bd56

Please sign in to comment.