pcb_util.py 4.2 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113
  1. #!/usr/bin/env python3
  2. # Copyright 2015-2021 Scott Bezek and the splitflap contributors
  3. #
  4. # Licensed under the Apache License, Version 2.0 (the "License");
  5. # you may not use this file except in compliance with the License.
  6. # You may obtain a copy of the License at
  7. #
  8. # http://www.apache.org/licenses/LICENSE-2.0
  9. #
  10. # Unless required by applicable law or agreed to in writing, software
  11. # distributed under the License is distributed on an "AS IS" BASIS,
  12. # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
  13. # See the License for the specific language governing permissions and
  14. # limitations under the License.
  15. import argparse
  16. import logging
  17. import os
  18. import pcbnew
  19. import tempfile
  20. from contextlib import contextmanager
  21. from export_util import (
  22. get_versioned_contents
  23. )
  24. logging.basicConfig(level=logging.DEBUG)
  25. logger = logging.getLogger(__name__)
  26. @contextmanager
  27. def versioned_board(filename, release_search_prefix):
  28. _, versioned_contents = get_versioned_contents(filename, release_search_prefix)
  29. with tempfile.NamedTemporaryFile(suffix='.kicad_pcb', mode='w') as temp_pcb:
  30. logger.debug('Writing to %s', temp_pcb.name)
  31. temp_pcb.write(versioned_contents)
  32. temp_pcb.flush()
  33. logger.debug('Load board')
  34. board = pcbnew.LoadBoard(temp_pcb.name)
  35. yield board
  36. @contextmanager
  37. def get_plotter(pcb_filename, build_directory, release_prefix):
  38. with versioned_board(pcb_filename, release_prefix) as board:
  39. yield Plotter(board, build_directory)
  40. class Plotter(object):
  41. def __init__(self, board, build_directory):
  42. self.board = board
  43. self.build_directory = build_directory
  44. self.plot_controller = pcbnew.PLOT_CONTROLLER(board)
  45. self.plot_options = self.plot_controller.GetPlotOptions()
  46. self.plot_options.SetOutputDirectory(build_directory)
  47. self.plot_options.SetPlotFrameRef(False)
  48. # self.plot_options.SetLineWidth(pcbnew.FromMM(0.35))
  49. self.plot_options.SetScale(1)
  50. self.plot_options.SetUseAuxOrigin(True)
  51. self.plot_options.SetMirror(False)
  52. self.plot_options.SetExcludeEdgeLayer(True)
  53. def plot(self, layer, plot_format):
  54. layer_name = self.board.GetLayerName(layer)
  55. logger.info('Plotting layer %s (kicad layer=%r)', layer_name, layer)
  56. self.plot_controller.SetLayer(layer)
  57. self.plot_controller.OpenPlotfile(layer_name, plot_format , 'Plot')
  58. output_filename = self.plot_controller.GetPlotFileName()
  59. self.plot_controller.PlotLayer()
  60. self.plot_controller.ClosePlot()
  61. return output_filename
  62. def plot_drill(self):
  63. board_name = os.path.splitext(os.path.basename(self.board.GetFileName()))[0]
  64. logger.info('Plotting drill file')
  65. drill_writer = pcbnew.EXCELLON_WRITER(self.board)
  66. drill_writer.SetMapFileFormat(pcbnew.PLOT_FORMAT_PDF)
  67. mirror = False
  68. minimalHeader = False
  69. offset = pcbnew.wxPoint(0, 0)
  70. merge_npth = True
  71. drill_writer.SetOptions(mirror, minimalHeader, offset, merge_npth)
  72. metric_format = True
  73. drill_writer.SetFormat(metric_format)
  74. generate_drill = True
  75. generate_map = True
  76. drill_writer.CreateDrillandMapFilesSet(self.build_directory, generate_drill, generate_map)
  77. drill_file_name = os.path.join(
  78. self.build_directory,
  79. '%s.drl' % (board_name,)
  80. )
  81. map_file_name = os.path.join(
  82. self.build_directory,
  83. '%s-drl_map.pdf' % (board_name,)
  84. )
  85. return drill_file_name, map_file_name
  86. if __name__ == '__main__':
  87. parser = argparse.ArgumentParser(description='Test pcb util')
  88. parser.add_argument('--release-prefix', type=str, required=True, help='Tag prefix to check if this is a tagged/versioned release. E.g. "releases/" for tags like "releases/v1.0"')
  89. parser.add_argument('input_file', help='Input .kicad_pcb file')
  90. args = parser.parse_args()
  91. with versioned_board(args.input_file, args.release_prefix) as board:
  92. logger.info('Loaded %s', board.GetFileName())
  93. for module in board.GetModules():
  94. logger.info('Module %s: %s', module.GetReference(), module.GetValue())