Added board view export.

Closes #69
This commit is contained in:
Salvador E. Tropea 2021-04-20 13:22:56 -03:00
parent 1d44a6a551
commit cfe61c9b7e
6 changed files with 211 additions and 2 deletions

View File

@ -16,6 +16,7 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0
- New KiCost variant style.
- `skip_if_no_field` and `invert` options to the regex used in the generic
filter.
- Board view file format export (#69)
- Basic KiCost support (experimental).
- Basic internal BoM and KiCost integration (experimental)
- Experimental mechanism to change 3D models according to the variant.

View File

@ -54,7 +54,7 @@ For example, it's common that you might want for each board rev:
* Check ERC/DRC one last time (using [KiCad Automation Scripts](https://github.com/INTI-CMNB/kicad-automation-scripts/))
* Gerbers, drills and drill maps for a fab in their favourite format
* Fab docs for the assembler, including the BoM (Bill of Materials) and costs spreadsheet
* Fab docs for the assembler, including the BoM (Bill of Materials), costs spreadsheet and board view
* Pick and place files
* PCB 3D model in STEP format
@ -608,6 +608,19 @@ Next time you need this list just use an alias, like this:
#### Supported outputs:
* BoardView
* Type: `boardview`
* Description: Exports the PCB in board view format.
This format allows simple pads and connections navigation, mainly for circuit debug.
The output can be loaded using Open Board View (https://openboardview.org/)
* Valid keys:
- `comment`: [string=''] A comment for documentation purposes.
- `dir`: [string='.'] Output directory for the generated files.
- `name`: [string=''] Used to identify this particular output definition.
- `options`: [dict] Options for the `boardview` output.
* Valid keys:
- `output`: [string='%f-%i%v.%x'] Filename for the output (%i=boardview, %x=brd). Affected by global options.
* BoM (Bill of Materials)
* Type: `bom`
* Description: Used to generate the BoM in CSV, HTML, TSV, TXT, XML or XLSX format using the internal BoM.
@ -2239,6 +2252,7 @@ The internal list of rotations is:
- **Interactive HTML BoM**: @qu1ck
- **PcbDraw**: Jan Mrázek (@yaqwsx)
- **KiCost**: Dave Vandenbout (@devbisme) and Hildo Guillardi Júnior (@hildogjr)
- **KiCAD to Boardview exporter**: @whitequark
- **Contributors**:
- **Error filters ideas**: Leandro Heck (@leoheck)
- **GitHub Actions Integration/SVG output**: @nerdyscout

View File

@ -54,7 +54,7 @@ For example, it's common that you might want for each board rev:
* Check ERC/DRC one last time (using [KiCad Automation Scripts](https://github.com/INTI-CMNB/kicad-automation-scripts/))
* Gerbers, drills and drill maps for a fab in their favourite format
* Fab docs for the assembler, including the BoM (Bill of Materials) and costs spreadsheet
* Fab docs for the assembler, including the BoM (Bill of Materials), costs spreadsheet and board view
* Pick and place files
* PCB 3D model in STEP format
@ -1232,6 +1232,7 @@ The internal list of rotations is:
- **Interactive HTML BoM**: @qu1ck
- **PcbDraw**: Jan Mrázek (@yaqwsx)
- **KiCost**: Dave Vandenbout (@devbisme) and Hildo Guillardi Júnior (@hildogjr)
- **KiCAD to Boardview exporter**: @whitequark
- **Contributors**:
- **Error filters ideas**: Leandro Heck (@leoheck)
- **GitHub Actions Integration/SVG output**: @nerdyscout

View File

@ -29,6 +29,17 @@ preflight:
update_xml: true
outputs:
# BoardView:
# This format allows simple pads and connections navigation, mainly for circuit debug.
# The output can be loaded using Open Board View (https://openboardview.org/)
- name: 'boardview_example'
comment: 'Exports the PCB in board view format.'
type: 'boardview'
dir: 'Example/boardview_dir'
options:
# [string='%f-%i%v.%x'] Filename for the output (%i=boardview, %x=brd). Affected by global options
output: '%f-%i%v.%x'
# BoM (Bill of Materials):
# Is compatible with KiBoM, but doesn't need to update the XML netlist because the components
# are loaded from the schematic.

174
kibot/out_boardview.py Normal file
View File

@ -0,0 +1,174 @@
# -*- coding: utf-8 -*-
# Copyright (c) 2021 Salvador E. Tropea
# Copyright (c) 2021 Instituto Nacional de Tecnología Industrial
# Copyright (c) 2018-2020 @whitequark
# License: GPL-3.0
# Project: KiBot (formerly KiPlot)
# Adapted from: https://github.com/whitequark/kicad-boardview
import re
from pcbnew import SHAPE_POLY_SET
from .gs import GS
from .optionable import BaseOptions
from .macros import macros, document, output_class # noqa: F401
from . import log
logger = log.get_logger(__name__)
def skip_module(module, tp=False):
refdes = module.GetReference()
if refdes == "REF**":
return True
if tp and not refdes.startswith("TP"):
return True
if not tp and refdes.startswith("TP"):
return True
return False
def coord(nanometers):
milliinches = nanometers * 5 // 127000
return milliinches
def y_coord(obj, maxy, y):
if obj.IsFlipped():
return coord(maxy - y)
else:
return coord(y)
def pad_sort_key(name):
if re.match(r"^\d+$", name):
return (0, int(name))
else:
return (1, name)
def convert(pcb, brd):
# Board outline
outlines = SHAPE_POLY_SET()
pcb.GetBoardPolygonOutlines(outlines, "")
outline = outlines.Outline(0)
outline_points = [outline.Point(n) for n in range(outline.PointCount())]
outline_maxx = max(map(lambda p: p.x, outline_points))
outline_maxy = max(map(lambda p: p.y, outline_points))
brd.write("0\n") # unknown
brd.write("BRDOUT: {count} {width} {height}\n"
.format(count=len(outline_points) + outline.IsClosed(),
width=coord(outline_maxx),
height=coord(outline_maxy)))
for point in outline_points:
brd.write("{x} {y}\n"
.format(x=coord(point.x),
y=coord(point.y)))
if outline.IsClosed():
brd.write("{x} {y}\n"
.format(x=coord(outline_points[0].x),
y=coord(outline_points[0].y)))
brd.write("\n")
# Nets
net_info = pcb.GetNetInfo()
net_items = [net_info.GetNetItem(n) for n in range(1, net_info.GetNetCount())]
brd.write("NETS: {count}\n"
.format(count=len(net_items)))
for net_item in net_items:
brd.write("{code} {name}\n"
.format(code=net_item.GetNet(),
name=net_item.GetNetname()))
brd.write("\n")
# Parts
module_list = pcb.GetModules()
modules = []
while module_list:
if not skip_module(module_list):
modules.append(module_list)
module_list = module_list.Next()
brd.write("PARTS: {count}\n".format(count=len(modules)))
pin_at = 0
for module in modules:
module_bbox = module.GetBoundingBox()
brd.write("{ref} {x1} {y1} {x2} {y2} {pin} {side}\n"
.format(ref=module.GetReference(),
x1=coord(module_bbox.GetLeft()),
y1=y_coord(module, outline_maxy, module_bbox.GetTop()),
x2=coord(module_bbox.GetRight()),
y2=y_coord(module, outline_maxy, module_bbox.GetBottom()),
pin=pin_at,
side=1 + module.IsFlipped()))
pin_at += module.GetPadCount()
brd.write("\n")
# Pins
module_list = pcb.GetModules()
pads = []
while module_list:
if not skip_module(module_list):
pads_list = module_list.PadsList()
for pad in sorted(pads_list, key=lambda pad: pad_sort_key(pad.GetName())):
pads.append(pad)
module_list = module_list.Next()
brd.write("PINS: {count}\n".format(count=len(pads)))
for pad in pads:
pad_pos = pad.GetPosition()
brd.write("{x} {y} {net} {side}\n"
.format(x=coord(pad_pos.x),
y=y_coord(pad, outline_maxy, pad_pos.y),
net=pad.GetNetCode(),
side=1 + pad.IsFlipped()))
brd.write("\n")
# Nails
module_list = pcb.GetModules()
testpoints = []
while module_list:
if not skip_module(module_list, tp=True):
pads_list = module_list.PadsList()
for pad in sorted(pads_list, key=lambda pad: pad_sort_key(pad.GetName())):
testpoints.append((module_list, pad))
module_list = module_list.Next()
brd.write("NAILS: {count}\n".format(count=len(testpoints)))
for module, pad in testpoints:
pad_pos = pad.GetPosition()
brd.write("{probe} {x} {y} {net} {side}\n"
.format(probe=module.GetReference()[2:],
x=coord(pad_pos.x),
y=y_coord(pad, outline_maxy, pad_pos.y),
net=pad.GetNetCode(),
side=1 + pad.IsFlipped()))
brd.write("\n")
class BoardViewOptions(BaseOptions):
def __init__(self):
with document:
self.output = GS.def_global_output
""" Filename for the output (%i=boardview, %x=brd) """
super().__init__()
self._expand_id = 'boardview'
self._expand_ext = 'brd'
def run(self, output):
with open(output, 'wt') as f:
convert(GS.board, f)
@output_class
class BoardView(BaseOutput): # noqa: F821
""" BoardView
Exports the PCB in board view format.
This format allows simple pads and connections navigation, mainly for circuit debug.
The output can be loaded using Open Board View (https://openboardview.org/) """
def __init__(self):
super().__init__()
with document:
self.options = BoardViewOptions
""" [dict] Options for the `boardview` output """

View File

@ -0,0 +1,8 @@
# Example KiBot config file
kibot:
version: 1
outputs:
- name: 'Board View Test'
comment: "Example of board view export"
type: boardview