--- /opt/flatcam/camlib-orig.py	2018-08-21 16:45:35.000000000 -0700
+++ /opt/flatcam/camlib.py	2018-12-06 13:17:03.029385563 -0800
@@ -5,6 +5,12 @@
 # Date: 2/5/2014                                           #
 # MIT Licence                                              #
 ############################################################
+# modified for laser output using M106/M107
+# modified to change G00 and G01 to be G0 and G1 cmds as needed by marlin
+# modified to eliminate spurious Fxxxx cmds on a line by itself (marlin ignores)
+# 21 Aug 2018 by Lawrence Glaister VE7IT
+
 #from __future__ import division
 #from scipy import optimize
 #import traceback
@@ -53,6 +59,7 @@
 
 
 from svgparse import *
+import time
 
 import logging
 
@@ -2773,7 +2780,7 @@
 
     defaults = {
         "zdownrate": None,
-        "coordinate_format": "X%.4fY%.4f"
+        "coordinate_format": "X%.4f Y%.4f"
     }
 
     def __init__(self,
@@ -2784,7 +2791,8 @@
                  z_cut=-0.002,
                  tooldia=0.0,
                  zdownrate=None,
-                 spindlespeed=None):
+                 spindlespeed=None,
+                 laser=None):
 
         Geometry.__init__(self)
         self.kind = kind
@@ -2796,12 +2804,15 @@
         self.unitcode = {"IN": "G20", "MM": "G21"}
         # TODO: G04 Does not exist. It's G4 and now we are handling in postprocessing.
         #self.pausecode = "G04 P1"
-        self.feedminutecode = "G94"
-        self.absolutecode = "G90"
+        self.feedminutecode = "G94  (feed/min)"
+        self.absolutecode = "G90  (absolute units)"
         self.gcode = ""
         self.input_geometry_bounds = None
         self.gcode_parsed = None
         self.steps_per_circ = 20  # Used when parsing G-code arcs
+        self.laser_on= "\nG4 P0\nM106 S255 (laser ON)\nG4 P0\n"
+        self.laser_off="\nG4 P0\nM107 S0   (laser OFF)\nG4 P0\n"
 
         if zdownrate is not None:
             self.zdownrate = float(zdownrate)
@@ -2875,17 +2886,17 @@
         self.gcode = []
 
         # Basic G-Code macros
-        t = "G00 " + CNCjob.defaults["coordinate_format"] + "\n"
-        down = "G01 Z%.4f\n" % self.z_cut
-        up = "G00 Z%.4f\n" % self.z_move
-        up_to_zero = "G01 Z0\n"
+        t = "G0 " + CNCjob.defaults["coordinate_format"] + "\n"
+        down = "G1 Z%.4f\n" % self.z_cut
+        up = "G0 Z%.4f\n" % self.z_move
+        up_to_zero = "G1 Z0\n"
 
         # Initialization
-        gcode = self.unitcode[self.units.upper()] + "\n"
+        gcode = self.unitcode[self.units.upper()] + "  (units)\n"
         gcode += self.absolutecode + "\n"
         gcode += self.feedminutecode + "\n"
         gcode += "F%.2f\n" % self.feedrate
-        gcode += "G00 Z%.4f\n" % self.z_move  # Move to travel height
+        gcode += "G0 Z%.4f\n" % self.z_move  # Move to travel height
 
         if self.spindlespeed is not None:
             # Spindle start with configured speed
@@ -2901,7 +2912,7 @@
             if tool in points:
                 # Tool change sequence (optional)
                 if toolchange:
-                    gcode += "G00 Z%.4f\n" % toolchangez
+                    gcode += "G0 Z%.4f\n" % toolchangez
                     gcode += "T%d\n" % int(tool)  # Indicate tool slot (for automatic tool changer)
                     gcode += "M5\n"  # Spindle Stop
                     gcode += "M6\n"  # Tool change
@@ -2981,17 +2992,23 @@
             self.gcode = ""
 
         # Initial G-Code
-        self.gcode = self.unitcode[self.units.upper()] + "\n"
+        self.gcode += "( Gcode file generated by flatcam )\n"
+        self.gcode += "( " + time.strftime("%Y-%m-%d %H:%M:%S") + " )\n"
+        self.gcode += self.unitcode[self.units.upper()] + "  (units)\n"
+        self.gcode += self.laser_off
         self.gcode += self.absolutecode + "\n"
-        self.gcode += self.feedminutecode + "\n"
+        self.gcode += self.feedminutecode + "\n"        
+        # ve7it marlin on 3d printers doesnt like Fxxx on a line by itself
+        self.gcode += "G1 Z%.4f " % self.z_move  # Move (up) to travel height
         self.gcode += "F%.2f\n" % self.feedrate
-        self.gcode += "G00 Z%.4f\n" % self.z_move  # Move (up) to travel height
+
         if self.spindlespeed is not None:
             self.gcode += "M03 S%d\n" % int(self.spindlespeed)  # Spindle start with configured speed
         else:
-            self.gcode += "M03\n"  # Spindle start
+            self.gcode += "M03  (spindle on)\n"  # Spindle start
         #self.gcode += self.pausecode + "\n"
-
+ 
         ## Iterate over geometry paths getting the nearest each time.
         log.debug("Starting G-Code...")
         path_count = 0
@@ -3046,10 +3063,10 @@
                             depth = z_cut
 
                         # Cut at specific depth and do not lift the tool.
-                        # Note: linear2gcode() will use G00 to move to the
+                        # Note: linear2gcode() will use G0 to move to the
                         # first point in the path, but it should be already
                         # at the first point if the tool is down (in the material).
-                        # So, an extra G00 should show up but is inconsequential.
+                        # So, an extra G0 should show up but is inconsequential.
                         if type(geo) == LineString or type(geo) == LinearRing:
                             self.gcode += self.linear2gcode(geo, tolerance=tolerance,
                                                             zcut=depth,
@@ -3075,7 +3092,7 @@
                             geo.coords = list(geo.coords)[::-1]
 
                     # Lift the tool
-                    self.gcode += "G00 Z%.4f\n" % self.z_move
+                    self.gcode += "G0 Z%.4f\n" % self.z_move
                     # self.gcode += "( End of path. )\n"
 
                 # Did deletion at the beginning.
@@ -3094,8 +3111,9 @@
         log.debug("%s paths traced." % path_count)
 
         # Finish
-        self.gcode += "G00 Z%.4f\n" % self.z_move  # Stop cutting
-        self.gcode += "G00 X0Y0\n"
+        self.gcode += self.laser_off        
+        self.gcode += "G0 Z%.4f\n" % self.z_move  # Stop cutting
+        self.gcode += "G0 X0Y0\n"
         self.gcode += "M05\n"  # Spindle stop
 
     @staticmethod
@@ -3314,7 +3332,7 @@
         if feedrate is None:
             feedrate = self.feedrate
 
-        t = "G0%d " + CNCjob.defaults["coordinate_format"] + "\n"
+        t = "G%d " + CNCjob.defaults["coordinate_format"] + "\n"
 
         # Simplify paths?
         if tolerance > 0:
@@ -3335,10 +3353,11 @@
             # Different feedrate for vertical cut?
             if self.zdownrate is not None:
                 gcode += "F%.2f\n" % downrate
-                gcode += "G01 Z%.4f\n" % zcut       # Start cutting
+                gcode += "G1 Z%.4f\n" % zcut       # Start cutting
                 gcode += "F%.2f\n" % feedrate       # Restore feedrate
             else:
-                gcode += "G01 Z%.4f\n" % zcut       # Start cutting
+                gcode += "G1 Z%.4f\n" % zcut       # Start cutting
+            gcode += self.laser_on            
 
         # Cutting...
         for pt in path[1:]:
@@ -3346,25 +3365,28 @@
 
         # Up to travelling height.
         if up:
-            gcode += "G00 Z%.4f\n" % ztravel  # Stop cutting
+            gcode += "G0 Z%.4f\n" % ztravel  # Stop cutting
+            gcode += self.laser_off            
 
         return gcode
 
     def point2gcode(self, point):
         gcode = ""
-        #t = "G0%d X%.4fY%.4f\n"
-        t = "G0%d " + CNCjob.defaults["coordinate_format"] + "\n"
+        #t = "G%d X%.4fY%.4f\n"
+        t = "G%d " + CNCjob.defaults["coordinate_format"] + "\n"
         path = list(point.coords)
         gcode += t % (0, path[0][0], path[0][1])  # Move to first point
 
         if self.zdownrate is not None:
             gcode += "F%.2f\n" % self.zdownrate
-            gcode += "G01 Z%.4f\n" % self.z_cut       # Start cutting
+            gcode += "G1 Z%.4f\n" % self.z_cut       # Start cutting
             gcode += "F%.2f\n" % self.feedrate
         else:
-            gcode += "G01 Z%.4f\n" % self.z_cut       # Start cutting
-
-        gcode += "G00 Z%.4f\n" % self.z_move      # Stop cutting
+            gcode += "G1 Z%.4f\n" % self.z_cut       # Start cutting
+        gcode += self.laser_on
+        gcode += "G4 P500  (1/2 sec point burn)\n"
+        gcode += self.laser_off
+        gcode += "G0 Z%.4f\n" % self.z_move      # Stop cutting
         return gcode
 
     def scale(self, factor):
