summaryrefslogtreecommitdiff
path: root/gerber/render/excellon_backend.py
diff options
context:
space:
mode:
Diffstat (limited to 'gerber/render/excellon_backend.py')
-rw-r--r--gerber/render/excellon_backend.py98
1 files changed, 89 insertions, 9 deletions
diff --git a/gerber/render/excellon_backend.py b/gerber/render/excellon_backend.py
index eb79f1b..b2c213f 100644
--- a/gerber/render/excellon_backend.py
+++ b/gerber/render/excellon_backend.py
@@ -1,21 +1,29 @@
from .render import GerberContext
+from ..excellon import DrillSlot
from ..excellon_statements import *
class ExcellonContext(GerberContext):
+ MODE_DRILL = 1
+ MODE_SLOT =2
+
def __init__(self, settings):
GerberContext.__init__(self)
+
+ # Statements that we write
self.comments = []
self.header = []
self.tool_def = []
self.body_start = [RewindStopStmt()]
self.body = []
self.start = [HeaderBeginStmt()]
- self.end = [EndOfProgramStmt()]
+ # Current tool and position
self.handled_tools = set()
self.cur_tool = None
+ self.drill_mode = ExcellonContext.MODE_DRILL
+ self.drill_down = False
self._pos = (None, None)
self.settings = settings
@@ -33,9 +41,22 @@ class ExcellonContext(GerberContext):
# Write the digits used - this isn't valid Excellon statement, so we write as a comment
self.comments.append(CommentStmt('FILE_FORMAT=%d:%d' % (self.settings.format[0], self.settings.format[1])))
+ def _get_end(self):
+ """How we end depends on our mode"""
+
+ end = []
+
+ if self.drill_down:
+ end.append(RetractWithClampingStmt())
+ end.append(RetractWithoutClampingStmt())
+
+ end.append(EndOfProgramStmt())
+
+ return end
+
@property
def statements(self):
- return self.start + self.comments + self.header + self.body_start + self.body + self.end
+ return self.start + self.comments + self.header + self.body_start + self.body + self._get_end()
def set_bounds(self, bounds):
pass
@@ -71,6 +92,9 @@ class ExcellonContext(GerberContext):
def _render_drill(self, drill, color):
+ if self.drill_mode != ExcellonContext.MODE_DRILL:
+ self._start_drill_mode()
+
tool = drill.hit.tool
if not tool in self.handled_tools:
self.handled_tools.add(tool)
@@ -84,20 +108,76 @@ class ExcellonContext(GerberContext):
self._pos = drill.position
self.body.append(CoordinateStmt.from_point(point))
+ def _start_drill_mode(self):
+ """
+ If we are not in drill mode, then end the ROUT so we can do basic drilling
+ """
+
+ if self.drill_mode == ExcellonContext.MODE_SLOT:
+
+ # Make sure we are retracted before changing modes
+ last_cmd = self.body[-1]
+ if self.drill_down:
+ self.body.append(RetractWithClampingStmt())
+ self.body.append(RetractWithoutClampingStmt())
+ self.drill_down = False
+
+ # Switch to drill mode
+ self.body.append(DrillModeStmt())
+ self.drill_mode = ExcellonContext.MODE_DRILL
+
+ else:
+ raise ValueError('Should be in slot mode')
+
def _render_slot(self, slot, color):
+ # Set the tool first, before we might go into drill mode
tool = slot.hit.tool
if not tool in self.handled_tools:
self.handled_tools.add(tool)
self.header.append(ExcellonTool.from_tool(tool))
-
- if tool != self.cur_tool:
- self.body.append(ToolSelectionStmt(tool.number))
- self.cur_tool = tool
- # Slots don't use simplified points
- self._pos = slot.end
- self.body.append(SlotStmt.from_points(slot.start, slot.end))
+ if tool != self.cur_tool:
+ self.body.append(ToolSelectionStmt(tool.number))
+ self.cur_tool = tool
+
+ # Two types of drilling - normal drill and slots
+ if slot.hit.slot_type == DrillSlot.TYPE_ROUT:
+
+ # For ROUT, setting the mode is part of the actual command.
+
+ # Are we in the right position?
+ if slot.start != self._pos:
+ if self.drill_down:
+ # We need to move into the right position, so retract
+ self.body.append(RetractWithClampingStmt())
+ self.drill_down = False
+
+ # Move to the right spot
+ point = self._simplify_point(slot.start)
+ self._pos = slot.start
+ self.body.append(CoordinateStmt.from_point(point, mode="ROUT"))
+
+ # Now we are in the right spot, so drill down
+ if not self.drill_down:
+ self.body.append(ZAxisRoutPositionStmt())
+ self.drill_down = True
+
+ # Do a linear move from our current position to the end position
+ point = self._simplify_point(slot.end)
+ self._pos = slot.end
+ self.body.append(CoordinateStmt.from_point(point, mode="LINEAR"))
+
+ self.drill_down = ExcellonContext.MODE_SLOT
+
+ else:
+ # This is a G85 slot, so do this in normally drilling mode
+ if self.drill_mode != ExcellonContext.MODE_DRILL:
+ self._start_drill_mode()
+
+ # Slots don't use simplified points
+ self._pos = slot.end
+ self.body.append(SlotStmt.from_points(slot.start, slot.end))
def _render_inverted_layer(self):
pass