   // PwmLaserOffsetMM.js
   //
   // This file is a plug-in for the QCAD/CAM software.
   // Do NOT edit this file. Your changes will be lost when the software is 
   // updated or reinstalled. 
   //
   // Post Processor Configuration file for a PWM Laser router 
   // Supporting grbl 0.9i (EleksLaser EL01)
   // Supporting grbl 1.1f (Shield3Laser)
   // >> Experimental; use at own risk <<
   //
   // Rev Date        By   Description
   // -   14-11-2018  HJS  Copied from Laser Offset mm.js
   //                      Comments, info added, file altered.
   //                      File Header changed. Footer changed.
   // A   10-12-2018  HJS  Tool change enabled
   // B   28-12-2018  HJS  Info added
   // C   15-01-2019  HJS  Released for QCAD/CAM
   // D   12-04-2019  HJS  Info offset toolpath added,
   //                      Info Laser Drill added
   //                      Laser Dril in Point burn mode added
   //
   // ===Laser control=========================================================
   // Pulse Width Modulation (PWM) -lasers are not switched On and Off, but are
   // controlled by the pulsewidth of a base-frequency.  Electronical the pulse
   // width is variable between 0...100%.  
   // The Tool Spindle Speed parameter S is used to set the laser intensity.
   // CNC-machine dependable the S-parameter has to be controlled between
   // 0...100 (percent), 0...1000 (promille)(Elekslaser), 0...12000.,  ....
   //
   // Special care and notice should be taken to the right G-code laser control
   // sequence.  A PWM-laser-module is seldom a simple G/M-code switched ON/OFF,
   // but is G-code sequence controlled by 'setting the power' first, and 
   // 'setting the lasermode' second.  Check your laser module documentation
   // for the correct order.
   //
   // ===Fixed tool as Multiple tool==========================================
   // PWM lasers can be also been used as 'multi-tool', by defining the same 
   // fixed laser multiple times as tool in the tool list, with subsequent 
   // different settings for  different purposes;
   // Example: First laser-tool for surface carving,
   //          Second laser-tool for deep carving,
   //          Third laser-tool with virtual diameter for rough cutting.
   //          Fourth laser-tool defined as a drill. 
   // Virtual tool diameter-settings also allows UX- and UY-preset settings as 
   // executable roughing and finishing toolpaths.
   //
   // ===Offset toolpath=======================================================
   // A well focussed low power laser (Tool 1) has an effective tool-diameter 
   // of about 0,08 mm.  Offsiding a toolpath (left- or rightside) sets the 
   // toolpath at an offset distance of 0,04 mm to the CAD-line entity.
   // Create a second tool for the same fixed laser as Tool 2 with an 
   // (imaginary) tool-diameter of 0,12 mm.  This might create (left- or rightside)
   // toolpaths at an offset distance of 0,06 mm. Executing a second offside path
   // with this imaginairy tool, will widen the first offsided toolpath with a small
   // overlap.
   //
   // ===Laser drill===========================================================
   // In grbl a laser can be used as a 'drill' in 'point burn mode':
   // N01 G0 X10 Y10      ; move laser to coordinate
   // N02 S1000 M03       ; max power, laser on
   // N03 G04 P0.5        ; dwell (=wait) for time P in seconds
   // N04 S0 M05          ; switch laser to low power in Off-mode
   // In QCAD drill-dwell-time is not a toolpath parameter (yet). 
   // In this post processor using a laser as drill tool, a negative (!)
   // toolpath's Cut Depth is used for setting the dwell time for the 
   // point burn mode.
   //
   // ========================================================================
  
  
   // PWM Lasercode is derived by the GCodeMM.js post processor
include("GCodeMM.js");


   // Define post processor function ...
function PwmLaserOffsetMM(documentInterface, camDocumentInterface) {
    GCodeMM.call(this, documentInterface, camDocumentInterface);

   // >> Pre setting post processing variables << ===========================
   // 
   // File path
   this.outputOffsetPath = true;
    
   // Generated coords in decimals tolerance.
   //    Warning: If the CNC-machine errors: "Invalid gcode ID:33",
   //    the arc-coord values do not match up to x,y-values;
   //    the decimal-setting should be raised to 5 decimals.
   //    The arc- /spline-settings should be defaulted.
   this.decimals = 4
    
   // If a toolpath-tab is found; while cutting skip the tab:
   this.stopAtTab = true;
   
   // Preset first block nummber
   this.lineNumber = 10
    
   // Preset adding value for next block number
   this.lineNumberIncrement = 10

   
   // >> Disabled G-code fields <<============================================
   // Most Lasers do not use Z movements. However, using the laser as a drill 
   // requires a specific Z movement-parameter.
   this.rapidMoveZ = [];         // Disable rapid switch z-level
   this.linearMoveZ = [];        // Disable carving/cutting at cut depth
   this.firstLinearMoveZ = [];   // Ditto
   this.firstPointMoveZ = [];    // Disable z process movement
   // this.pointMoveZ = []       // Not switched off, but ..
   this.pointMoveZ =             // Redefine as ..
      ["[N] [S] M03",            // Laser power S, Laser On-mode (CW)
       "[N] G04 P[ZD#]",         // Wait for time P in seconds. Use toolpath's
                                 // negative (!) Cut Depth)-value
       "[N] S0 M05",             // Power low, set off-mode
       ";"                       // Pass separator
      ]; 
    
     
   // >> INIT << ============================================================
   // PWM-Laser-machine (EleksLaser EL01 and Shield3Laser) inits at startup:
   // G0       ; Reset movements
   // G54      ; Set current pos as Workpiece Coords System 0,0
   // G17      ; Polar plane executable
   // G21      ; mm units
   // G90      ; Absoluut coords
   // G94      ; Feed per minute
   // M0       ; Mandatory Stop
   // M5       ; Tool Off
   // M9       ; Cooling Off
   // T0       ; Select Tool zero (fixed tool)
   // F0.      ; Feed Rate 0.0
   // S0.      ; Spindle Speed 0.0
    
    
   // >> File header and footer << ==========================================
   // Header:  A header are the first lines in G-code file, used for 
   //          Information, Reset, Preset and Setup.
   //
   // Fire hazard prevention caused by stalled laser; preset Feed Rate 
   // max:"F1000".  Safety First; Reset Laser module mode and set zero 
   // with "[N] S0 M05".
   this.header = 
      ["; Grbl G-code file generated by QCAD/CAM (RibbonSoft)",
       "; File: [FILENAME] on: [DATETIME]",
       "; Post processor: PwmLaserOffsetMM Rev D.",
       ";",
       "; >>> Preset parameters <<<",
       "; Home position at         : [XH],[YH],[ZH]",
       "; Startpoint at            : [X1],[Y1],[Z1]",
       "; Vertical Safety distance : [ZS] ;[ZS!] ;[ZS#]",
       "; Clearance distance       : [ZU]",
       "; Z Safety distance        : [ZS]",
       "; Z Up movement clearance  : [ZU]",
       "; Z Up Pass clearance      : [ZUP]",
       "; Z Start height           : [Z_START]",
       "; Z End Depth              : [Z_END]",
       "; Default Cutting Depth    : [ZD] mm",
       "; ",
       "; >>> PreSetting Laser <<< ",
       "[N] F1000 S0 M05",
       ";",
      ];

   // Footer:   With laser always Safety First! 
   //           "S0 M05"      ;Switch Off Laser
   //           Homing: $H not supported by EleksLaser
   // Warning:  grbl-version dependable the use of M2 and M30 will vary.
   //           UGS will send M30, but can't show the response.
   //           However, an EleksLaser will send it own response.
   this.footer = ["; ",
                  "; Homing Tool ", 
                  "[N] S0 M05",
                  "[N] G0 X0 Y0",
                  "[N] M30",
                  "; READY"
                 ];


   // >> Tool change <<=======================================================
   // Tool change: default "[T] M06" disabled when using a continue or fixed
   // laser.  (grbl does not support M06 yet).
   this.toolHeader = [];
   this.toolFooter = [];
 
    
   // >> Toolpath change <<===================================================
   // Start every toolpath with its CAM-toolpath name
   this.toolpathHeader = 
       ["; >>> Toolpath: [TOOLPATH_NAME] <<< "];
   // this.toolpathFirstHeader = this.toolPathHeader;
   // Add empty line after every completed toolpath
   this.toolpathFooter = [";"];
   // Note: in the G-code file a "G0"-movement is added after this separator
   //       to move the tool to the next toolpath's start position.
 
   // >> Contour <<===========================================================
   // Before/after every contour within toolpath
   // this.contourHeader = [];
   // this.contourFooter = [";"];
   
   
   // >> singleZPass <<=======================================================
   // Before/after every single Z pass
   // this.singleZPassHeader = [];
   // this.singleZpassHeader = ["[N] Drilling? [T] [F] [S] M03"];
   // nthis.singleZPassFooter = [";"];
   
   
   // >> multiZPass <<========================================================
   // Before/after every multiple Z passes
   // this.multiZPassHeader = [];
   // this.multiZPassFooter = [";"];
   
   
   // >> zPass <<=============================================================
   // Redefine the zpass header as regular G-code block for selecting
   // the desired Tool, Feed, Speed and switching the laser On.
   this.zPassHeader = ["[N] [T] [F] [S] M03"];
   this.zPassFirstHeader = this.zPassHeader;

   // Toolpath: Laser Off.
   // Redefine the zpass footer as regular G-code block, by adding
   // the correct Laser Off sequence and separator.
   this.zPassFooter = ["[N] S0 M05",
                        ";"];
    
   // Update last toolpath 
   this.zPassLastFooter = this.zPassFooter;
 
   // One of the disabled linear Z moves is corrupting the construction of the
   // 'G01' block. (Lost in space).
   // Work Around G1-Bug; Re-activate linearMove routine:
   this.linearMove = ["[N] G1 [X] [Y]"];
    
 }

PwmLaserOffsetMM.prototype = new GCodeMM();
PwmLaserOffsetMM.displayName = "PWM Laser (Offset, mm)";



