/** Copyright (C) 2012-2013 by Autodesk, Inc. All rights reserved. Tormach 15LSlantPRO Lathe post processor configuration. Changes for Tormach 15LSlantPRO Lathe: Copyright (C) 2015-2016 Adam Silver Tormach 15LSlantPRO Lathe: initial thread depth algorithm: Copyright (C) 2014-2016 Tormach, Inc. $Revision: 00001 $ $Date: 2016-17-03 18:56:45 +0200 (to, 17 mar 2016) $ FORKID {88B77760-269E-4d46-8588-30814E7AC681} Changes: 2015-27-07 : OnCyclePoint: var external = getParameter("operation:turningMode") == "outer" ? true : false; Added support for gang tooling 2015-11-08 : Revamped maximumSpind;eSpeed to take the operation value over the default. Fixed gang tool exit on last gang tool call - added 'g_currToolIsGang' 2015-15-08 : improved logic to determine inital X and Z moves in an op. X before Z if first Z below 'stock-upper-z'level 2015-02-09 : fixed a linear motion bug where G94/95 wasn't being generated when feed rates are used for rapid motion 2015-15-09 : added detection for errant M4s 2015-17-09 : added support for tools that cut from the +X side of the part, eg, turret tools 2015-09-11 : fixed mm/min for surface speed. fixed logic in selecting spindle speed for setting up CSS 2015-18-11 : fixed threading values for HSM users 2015-19-11 : removed 'useRadius' 'using_QCTP' properties ( deprecated ). Add support for 'Action's from local files 2015-20-11 : Commented out all 'debugOut's Fixed: first line of 'action' file not being displayed. Added _calcCT - calculates cycle times for imported code. 2015-21-11 : Replaced 'g_bigOlNumber' with javascript 'Infinity' re-factored all the 'action' code Added 'toolInfo' array. action now can look up binding ops for tool info, rpm, etc. Fixed bug calculating total cycle time. Fixed possible bug with gang tool between op G30 generation. Fixed threading Z report always zero. 2015-23-11 : Re-edited under Netbeans, fixed lexical errors. 2015-24-11 : Removed the active feed code that isn't used 2015-27-11 : Encapsulated tool comment generation Moved ToolInfo code to top of post. 2015-03-12 : replaced boolean tests against 'turret' with toolInfo.toolType. added 'tormachMillLathing' property - minimal support for lathing on Tormach Mill. 2015-04-12 : Very wierd bug where the ToolInfo[0].toolNum is being corrupted with the tool number fomr ToolInfo[1]. No tool header or tool call was being invoked because an tool change between sections wasn't being detected. Solution is a hack for now. 2015-04-12 : Above bug fixed: getToolInfo: '! sectionId' does NOT mean 'sectionId === undefined' 2015-05-12 : Added 'Document' and 'CAM' to intital header 2015-08-12 : Added '_getToolX' for helping get minimum 'X' values for internal cutting ops. Helps to setup boring bars, internal threading. Removed control variable for threading, replaced with 'isFirstCyclePoint'. Fixed logic error in lathe mode prompt ( QCTP, GANG, TURRET). 2015-24-12 : Added normal text passThroughs. 2015-31-12 : encapsulated: 'spindle', 'retract', 'coolant', 'tooling' 2016-03-01 : encapsulated: the 'feedType', 'optionalSection', 'endingRadiusCompensation' global vars ; did some code clean-up in 'onSection', 'onClose', 'writeParkTool'. 2016-06-01 : MinGangZ calcs on deltas of gang tool lengths not actual tool length. Multi line support for passThroughs 2016-08-01 : some more cleanup in 'onOpen', added 'lineNumber' object 2016-11-01 : fixed 'PassThrough's on inital section ( for looping ) 2016-18-01 : fixed bug on writing G30 before first tool call 2016-20-01 : Added 'warnings' buffer object 2016-23-01 : Fixed: No G96/G97 or clamp on 'tormachMillLathing'; no G95 on 'tormachMillLathing' 2016-29-01 : Fixed: fails if action name can't be matched - no ToolInfo, no currentSection 2016-21-02 : Fixed: won't work on MAC. properties.writeToolinfo changed to properties.writeToolingInfo - these names can;t be the same! 2016-23-02 : Fixed: G4 - Pxxx outputs in milliseconds, not seconds. 2016-28-02 : Removed: bounding '%' lines. Fixed: last G30 in gang tool mode no longer writes an M0. 2016-02-03 : Added: property.partLoadTime. This adds to total cycle time. Total cycle time also put in terms of hours. Added: Loop state object to keep track of looping and not issue final M0 if in a loop. Removed : No M0s generated is a pure gang tool setup. Moved: 'writeG30' to the tools 'collection'. Added: warning is constant surface speed is detected in tormachMillLathing 2016-04-03 : Changed: Threading to: 1) evaluate on 'last' cycle point not first to get more correct final z 2) support back to front threading 2016-08-03 : Suppressed: OnRapid during threading - generates extra Z moves. 2016-17-03 : Fixed: to report correct gcode generation time. 2016-04-30 . ........MODIFIED FOR LINUXCNC :Changed the file extension to .ngc :Added these options in the properties window. use_goto_position:true, // in use if partcatcher is in use goto_x_position:-15, //for using goto position with parting tool goto_z_position:0.6, //for using goto position with parting tool springpasses: 2, //for using more than one springpass when threading :Changed these options in the properties window. maximumSpindleSpeed: 3000, // specifies the maximum spindle speed for any op gangToolSafeMargin: 25, // the extra margin for gang tool pull back :Changed some variables to forceDecimal:false because it added a decimal to integers without a zero :Changed the maxToolNum to 199 :Changed the tool change format :Changed the G30 function to G00 Z "gangToolSafeMargin" instead :Added an option to use more than 1 springpass Becomes true if Springpass is selected and if the property springpass is over 1 :Added an option to use a GoTo function. Becomes true if the properties use_goto_position are set to true and if you are using the operation TurningPart goto_x_position:-15, //for using goto position with parting tool goto_z_position:0.6, //for using goto position with parting tool == OUTSTANDING ISSUES ======================================================================================= */ var g_description = "Linuxcnc"; vendor = "Adam Silver"; vendorUrl = "http://www.autodesk.com"; legal = "Copyright (C) 2012-2013 by Autodesk, Inc. ; (C) 2015-2016 Adam Silver ; Algorythm for calculating initial thread depth: (C) 2015 Tormach, Inc."; certificationLevel = 2; minimumRevision = 24000; extension = "ngc"; programNameIsInteger = false; setCodePage("ascii"); capabilities = CAPABILITY_MILLING | CAPABILITY_TURNING; tolerance = spatial(0.002, MM); minimumChordLength = spatial(0.01, MM); minimumCircularRadius = spatial(0.01, MM); maximumCircularRadius = spatial(1000, MM); minimumCircularSweep = toRad(0.01); maximumCircularSweep = toRad(180); allowHelicalMoves = true; allowedCircularPlanes = undefined; // allow any circular motion setWriteInvocations(false); setWriteStack(false); //user-defined properties properties = { use_goto_position:true, // in use if partcatcher is in use goto_x_position:-15, //for using goto position with parting tool goto_z_position:0.6, //for using goto position with parting tool springpasses: 2, //for using more than one springpass when threading writeMachine: true, // write machine showSequenceNumbers: false, // show sequence numbers sequenceNumberStart: 10, // first sequence number sequenceNumberIncrement: 1, // increment for sequence numbers rapidFeed: 60, // 60 IPM on Tormach?? manualToolChangeTime: 45, // seconds to change a tool optionalStop: true, // optional stop separateWordsWithSpace: true, // specifies that the words should be separated with a white space maximumSpindleSpeed: 3000, // specifies the maximum spindle speed for any op using_GangTooling: true, // uses gang tooling tormachMillLathing: false, // turn on if using Tormach mill as vertical lathe forceX_first_onFirstMove: true, // forces the X value to be the first block on the initial move showNotes: false, // specifies that operation notes should be output. debugOutput: false, // prints debugging info in post gangToolSafeMargin: 25, // the extra margin for gang tool pull back writeToolingInfo: true, // prints out the tool info header warnings: true, // issues a warning is something is found out of kilter partLoadTime: 65, // time it takes to reload a part in the holding device ( in seconds ) // actionsFilePath : "C:\\Users\\Public\\Documents\\Autodesk\\Inventor HSM 2015\\Actions", // actions code file folder // passThroughFilePath : "C:\\Users\\Public\\Documents\\Autodesk\\Inventor HSM 2015\\PassthroughCode" // pass through code file folder actionsFilePath : "/Users/adamvs/Autodesk/Fusion 360 CAM/Actions", // actions code file folder passThroughFilePath : "/Users/adamvs/Autodesk/Fusion 360 CAM/PassthroughCode" // pass through code file folder }; //-------------------------------------------------------------------------------------------------------------- // encapsulate info about extern gcode files being used in 'action'. function extFileRec( tooling, binding, type, modifer ) { this.binding = String( ( binding !== undefined ) ? binding : "" ); this.type = ( type !== undefined ) ? type : ""; this.tool = ""; this.modifier = ( modifer !== undefined ) ? modifer : "suppress"; this.maxZ = Infinity; this.minX = Infinity; this.ct = 0; this.css = true; this.rpm = 750; this.M3 = false; this.M5 = false; this.M8 = false; this.M9 = false; this.data = new Array( ); this.toolInfo = tooling.findToolFromSectionName( this.binding ); this.rawfile; //---member functions------------------------------- this.hasData = function( ) { return this.data.length; }; this.noData = function( ) { return this.data.length === 0; }; this.noBindingFound = function( ) { return this.toolInfo === undefined; }; //---private function ------------------------------ this._findTool = function ( ) { // debugOut( " _findTool: " + " rawfile: " + this.rawfile ); var items = String( this.rawfile ).match( new RegExp( /[T][0-9]+[0-9]?/ ) ); if ( items && items.length >= 1 ) { var ts = items[ 0 ]; this.tool = parseInt( String( ts ).slice( 1, 3 ) ); } }; this._calcCT = function ( ) { // start at some G30 // assume G90 for now... // debugOut( " _calcCT: toolInfo : " + this.binding ); var rpm = ( this.toolInfo && this.toolInfo.valid( ) ) ? this.toolInfo.rpm : 750; var feedtype = ( this.toolInfo && this.toolInfo.valid( ) ) ? this.toolInfo.feedMode : 95; var surfaceSpeed = ( this.toolInfo && this.toolInfo.valid( ) ) ? this.toolInfo.surfaceSpeed : 250; var factor = unit === MM ? 25.4 : 1; var _x = ( this.toolInfo && this.toolInfo.valid( ) ) ? this.toolInfo.toolCuttingDir === toolType.XMINUS ? -2 : this.toolInfo.toolCuttingDir === toolType.XPLUS ? 2 : 0 : 0; var _z = 4.5; var _g = 0; var _rapid = properties.rapidFeed * factor; var _f = _rapid; var re = new RegExp( /[gGxXyzZiIkKrRpPfF][-+]?[0-9]*\.?[0-9]+/g ); // get an average diameter for CSS, so that some reasonable RPM can be gotten. if ( feedtype === 95 ) { var x_total = 0; var x_count = 0; var x_av = 0; var x_items = String( this.rawfile ).match( new RegExp( /[Xx][-+]?[0-9]*\.?[0-9]+/g ) ); for ( var x in x_items ) { x_total += Number( String( x_items[ x ] ).substr( 1 ) ); ++x_count; } x_av = ( x_count > 0 ) ? x_total / x_count : 1; rpm = surfaceSpeed / ( ( Math.abs( x_av ) * Math.PI ) / ( unit === MM ? 1000 : 12 ) ); // debugOut( " _calcCT: name: " + this.binding + " x_av: " + x_av + " x_count: " + x_count + " surfaceSpeed: " + surfaceSpeed + " rpm: " + rpm ); } _x *= factor; _z *= factor; // debugOut( " _calcCT: " + " initial x: " + _x + " feedtype: " + feedtype ); for ( var i in this.data ) { var codes = String( this.data[ i ] ).match( re ); var deltaX = 0; var deltaZ = 0; var _i = 0; var _k = 0; var _m = 0; var timeInSeconds = 0; // debugOut( " _calcCT : line= " + data[ i ] ); for ( var j in codes ) { var code = String( codes[ j ] ).toUpperCase( ); var codeType = code.charAt( 0 ); var val = Number( String( codes[ j ] ).substr( 1 ) ); // debugOut( " _calcCT : code = " + code + " type = " + codeType + " ... code Val = " + val ); switch ( codeType ) { case 'G': // stick in this modal group... if ( val >= 0 && val <= 4 ) _g = val; if ( val === 94 || val === 95 ) feedtype = val; break; case 'X': deltaX = Math.abs( _x - val ); _x = val; break; case 'Z': deltaZ = Math.abs( _z - val ); _z = val; break; case 'F': // _f needs to be in units per minute... _f = ( feedtype === 94 ) ? val : val * rpm; break; case 'I': _i = val; break; case 'K': _k = val; break; case 'M': _m = val; break; case 'P': if ( _g === 4 || _m !== 0 ) timeInSeconds = val; break; } } // for j in codes // eval the time deltaX /= 2; // we're dealing with radial movements not diameter. var length = deltaX + deltaZ; // the 'nand' case if ( deltaX > 0 && deltaZ > 0 ) // the 'and' case length = Math.sqrt( ( deltaX * deltaX ) + ( deltaZ * deltaZ ) ); // cheapo approximation of arcs .. just add 15% if ( _g === 2 || _g === 3 ) length *= 1.15; if ( _g === 0 ) timeInSeconds += length / _rapid * 60; else if ( _f > 0 && _g !== 4 && _m === 0 ) timeInSeconds += length / _f * 60; // debugOut( "_caltCT : G" + _g + " F" + _f + " rpm: " + rpm + " .. length = " + length + " I:" + _i + " timeInSeconds: " + timeInSeconds ); this.ct += timeInSeconds; } // debugOut( "_caltCT : ct" + this.ct ); }; this._findLeastZ = function( ) { var items = String( this.rawfile ).match( new RegExp( /[Zz][-+]?[0-9]*\.?[0-9]+/g ) ); // debugOut( " _findLeastZ: " + " rawfile: " + this.rawfile ); for ( var i in items ) this.maxZ = Math.min( this.maxZ, String( items[ i ] ).substr( 1 ) ); }; this._findLeastX = function( ) { // this is valuable if using a boring bar clos to it's min bore spec. var items = String( this.rawfile ).match( new RegExp( /[Xx][-+]?[0-9]*\.?[0-9]+/g ) ); var xSide = ( this.toolInfo && this.toolInfo.valid( ) ) ? this.toolInfo.toolCuttingDir === toolType.XMINUS ? -1 : this.toolInfo.toolCuttingDir === toolType.XPLUS ? 1 : 0 : 0; // if its a gang tool .. minX is always zero... if ( this.toolInfo.turningMode === "inner" ) { for ( var i in items ) this.minX = Math.min( this.minX, String( items[ i ] ).substr( 1 ) ); } if ( this.minX === Infinity ) this.minX = 0; this.minX *= xSide; }; this._parseMCodes = function( ) { var items = String( this.rawfile ).match( new RegExp( /[mM][35789]/g ) ); // debugOut( " _parseMCodes: " + " items: " + items.length ); for ( var i in items ) { String( items[ i ] ).toUpperCase( ); switch ( items[ i ] ) { case "M3": this.M3 = true; break; case "M5": this.M5 = true; break; case "M7": case "M8": this.M8 = true; break; case "M9": this.M9 = true; break; } } // debugOut( " _parseMCodes: " + " M3?:" + this.M3 + " M5?:" + this.M5 + " M8?:" + this.M8 + " M9?:" + this.M9 ); }; this.insertCoolant = function( coolantStr ) { var re = new RegExp( /[Zz][-+]?[0-9]*\.?[0-9]+/ ); for ( var line in this.data ) { if ( String( this.data[ line ] ).match( re ) ) { this.data[ line ] = this.data[ line ] + " " + coolantStr; return; } } }; } // end 'function extFileRec' var permittedCommentChars = " abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789.[]*&%#@!|/:;=_-"; var gFormat = createFormat({prefix:"G", decimals:1}); var mFormat = createFormat({prefix:"M", decimals:1}); var spatialFormat = createFormat({decimals:(unit === MM ? 3 : 4), forceDecimal:false}); var xFormat = createFormat({decimals:(unit === MM ? 3 : 4), forceDecimal:false, scale : 2 }); // diameter mode var xrFormat = createFormat({decimals:(unit === MM ? 3 : 4), forceDecimal:false }); // diameter mode var iFormat = createFormat({decimals:(unit === MM ? 3 : 4), forceDecimal:false}); // radius mode var zFormat = createFormat({decimals:(unit === MM ? 3 : 4), forceDecimal:false}); var rFormat = createFormat({decimals:(unit === MM ? 3 : 4), forceDecimal:false}); // radius var pFormat = createFormat({decimals:(unit === MM ? 3 : 4), forceDecimal:false}); // thread pitch var iThreadFormat = createFormat({decimals:(unit === MM ? 3 : 4), forceDecimal:false}); // thread offset fro drive line var jThreadFormat = createFormat({decimals:(unit === MM ? 3 : 4), forceDecimal:false}); // thread initial thread depth var kThreadFormat = createFormat({decimals:(unit === MM ? 3 : 4), forceDecimal:false, scale:2 }); // thread depth, diameter mode var kTapFormat = createFormat({decimals:(unit === MM ? 3 : 4), forceDecimal:false }); // thread pitch var rThreadFormat = createFormat({decimals:1, forceDecimal:false, zeropad:true}); var qThreadFormat = createFormat({decimals:1, forceDecimal:false, zeropad:true}); var hThreadFormat = createFormat({decimals:0}); var feedFormat = createFormat({decimals:(unit === MM ? 4 : 5), forceDecimal:false}); var toolFormat = createFormat({decimals:0}); var rpmFormat = createFormat({decimals:0}); var secFormat = createFormat({decimals:3, forceDecimal:false}); // seconds - range 0.001-99999.999 var dwellFormat = createFormat({decimals:2, forceDecimal:false}); // milliseconds // range 1-9999 var taperFormat = createFormat({decimals:1, scale:DEG}); var timeFormat = createFormat({width:2, zeropad:true, decimals:0}); var infoFormat = createFormat({decimals:4}); var xOutput = createVariable({prefix:"X"}, xFormat ); var xrOutput = createVariable({prefix:"X"}, xrFormat ); var zOutput = createVariable({prefix:"Z"}, zFormat); var feedOutput = createVariable({prefix:"F"}, feedFormat); var sOutput = createVariable({prefix:"S", force:true}, rpmFormat); var dOutput = createVariable({prefix:"D", force:true}, rpmFormat); var pOutput = createVariable({prefix:"P", force:true}, pFormat); var iThreadOutput = createVariable({prefix:"I", force:true}, iThreadFormat); var jThreadOutput = createVariable({prefix:"J", force:true}, jThreadFormat); var kThreadOutput = createVariable({prefix:"K", force:true}, kThreadFormat); var kTapOutput = createVariable({prefix:"K", force:true}, kTapFormat); var rThreadOutput = createVariable({prefix:"R", force:true}, rThreadFormat); var qThreadOutput = createVariable({prefix:"Q", force:true}, qThreadFormat); var hThreadOutput = createVariable({prefix:"H", force:true}, hThreadFormat); //circular output var kOutput = createReferenceVariable({prefix:"K", force:true}, zFormat); var iOutput = createReferenceVariable({prefix:"I", force:true}, iFormat); // no scaling var g92ROutput = createVariable({prefix:"R"}, zFormat); // no scaling var gMotionModal = createModal({}, gFormat); // modal group 1 // G0-G3, ... var gPlaneModal = createModal({onchange:function () {gMotionModal.reset();}}, gFormat); // modal group 3 // G17-19 var gAbsIncModal = createModal({}, gFormat); // modal group 4 // G90-91 // only for B and C mode var gFeedModeModal = createModal({}, gFormat); // modal group 5 // G98-99 / G94-95 var gSpindleModeModal = createModal({}, gFormat); // modal group 5 // G96-97 var gUnitModal = createModal({}, gFormat); // modal group 6 // G20-21 var gCycleModal = createModal({}, gFormat); // modal group 9 // G81, ... var gRetractModal = createModal({}, gFormat); // modal group 10 // G98-99 var gDiamModal = createModal({}, gFormat); // modal group 10 // G07 //fixed settings var ge = { BINDING : 0, TYPE : 1, NAME : 2, MODIFIER : 3 }; var toolType = { NOTYPE : -99, XMINUS : -1, GANG : 0, XPLUS : 1 }; var tool30Type = { NORMAL : 0, ZONLY : 1 }; var pState = { OPENING : 0, IN_SECTIONS : 1, LAST_SECTION: 2, CLOSING: 3 }; var partingtool = false; //-------------------------------------------------------------------------------------------------------------- // encapsulate the array of external files used in actions. function actionsInfo ( tooling, warnings ) { this.actions = [ ]; this.toolingCollectionRef = tooling; this._stowFileData = function( parms, folder ) { var lines = [ ]; var action = new extFileRec( this.toolingCollectionRef, parms[ ge.BINDING ], "action", parms[ ge.MODIFIER ] ); action.rawfile = _onGetLocalTextFile( folder, parms[ ge.NAME ], action.data ); if ( action.noData( ) ) return; if ( action.noBindingFound( ) ) { warnings.pushWarning( " Section: '" + parms[ ge.BINDING ] + "' not found to bind." ); // error(localize( " Section: '" + parms[ ge.BINDING ] + "' not found to bind." ) ); return; } action._findLeastZ( ); action._findLeastX( ); action._calcCT( ); action._findTool( ); action._parseMCodes( ); this.actions.push( action ); }; this.stowAction = function( actionString ) { var items = String( actionString ).split( ":" ); if ( items.length < 3 && items.length > 4 ) error(localize( "actions are BindingName:Type:Data[:actionType] - Eg, BarPull:file:barpull6.nc" ) ); // if no modifier create a default// switch ( items[ ge.TYPE ] ) { case "file": // if no modifier then default to suppress. if ( items.length === 3 ) items.push( "suppress" ); this._stowFileData( items, properties.actionsFilePath ); break; } }; this.findActionRec = function( name ) { var nameItems = String( name ).split( ":" ); for ( var i in this.actions ) { // debugOut( " finding - g_actions[ i ].binding" + g_actions[ i ].binding + " name: " + name ); if ( this.actions[ i ].binding === nameItems[ nameItems.length - 1 ] ) return this.actions[ i ]; } // debugOut( " findActionRec:" + name + " NOT found!" ); return undefined; }; this.findActionForCurrentSection = function ( ) { if ( currentSection ) return this.findActionRec( currentSection.getParameter( "operation-comment" ) ); return undefined; }; this.postActionData = function( ) {// debugOut( "**postActionData: op-comment: " + currentSection.getParameter( "operation-comment" ) ); var action = this.findActionForCurrentSection( ); _postLocalTextFile( action.data ); }; this.insertActionCoolant = function( coolantType ) { if ( coolantType !== COOLANT_THROUGH_TOOL && coolantType != COOLANT_FLOOD ) return; var action = this.findActionForCurrentSection( ); // debugOut( "insertActionCoolant : data: " + action.data ); if ( ! action || action.M8 === true ) return; // there was no M8 in the imported file, but the tool is set for coolant // iterate through the gcode at append M8 at the first 'Z' movement. var coolantStr = coolantType === COOLANT_THROUGH_TOOL ? "M88" : "M8"; action.insertCoolant( coolantStr ); }; this.getActionModifier = function( section ) { if ( section === undefined ) section = currentSection; if ( section ) { var action = this.findActionRec( section.getParameter( "operation-comment" ) ); if ( action ) return action.modifier; } return ""; }; this.actionIsSuppress = function( section ) { return this.getActionModifier( section ) === "suppress"; }; this.actionIsPrepend = function( section ) { return this.getActionModifier( section ) === "prepend"; }; this.actionIsAppend = function( section ) { return this.getActionModifier( section ) === "append"; }; } //-------------------------------------------------------------------------------------------------------------- // encapsulate special information about tools used beyond the 'postprocessors' tool data. function toolRecord ( section_Id, warnings ) { // create an 'empty' object this.sectionId = -1; this.sectionName = ""; this.sectionMatchName = ""; this.toolNum = 0; this.toolCuttingDir = undefined; this.toolType = undefined; this.toolOnGangPlate = false; this.toolDiam = 0; this.feedMode = undefined; this.spindleMode = undefined; this.surfaceSpeed = 0; this.turningMode = "outer"; this.isDrill = false; this.isTurningTool = true; this.orientation = 0; this.clampRPM = 0; this.rpm = 0; this.toolLength = 0; this.maxToolNum = 199; // DO NOT CHANGE this.compOffset = 0; this.tool30Type = tool30Type.NORMAL; this.c_barPullerToolNum = 199; // DO NOT CHANGE this.isLastTool = false; this.toolIsNewTool = true; if ( section_Id < 0 || section_Id >= getNumberOfSections( ) ) { error( " toolRec - ctor : sectionId out of range " ); return; } var section = getSection( section_Id ); var secName = section.getParameter( "operation-comment" ); var tool = section.getTool( ); var isLastSection = section_Id === getNumberOfSections( ) - 1; var prevSection = section_Id > 0 ? getSection( section_Id - 1 ) : undefined; if ( tool.getSpindleMode( ) == SPINDLE_CONSTANT_SURFACE_SPEED && properties.tormachMillLathing ) warnings.pushWarning( " Tool: " + tool.number + " Constant Surface Speed not supported in mill lathing." ); this.sectionId = section_Id; this.sectionName = section.getParameter( "operation-comment" ); var nameItems = String( secName ).split( ":" ); if ( nameItems.length > 0 ) this.sectionMatchName = new String( nameItems[ nameItems.length - 1 ] ); // debugOut( " toolRecord ctor: sectionMatchName: " + this.sectionMatchName ) this.toolNum = tool.number; this.isDrill = tool.isDrill( ); this.isTurningTool = tool.isTurningTool( ); // #KLUDGE if ( isStockTranferOp( section ) ) this.toolNum = this.c_barPullerToolNum; if ( section.hasParameter( "operation:turningMode") && section.getParameter( "operation:turningMode" ) === "inner" ) this.turningMode = "inner"; this.toolCuttingDir = tool.turret > 0 ? toolType.XPLUS : tool.manualToolChange ? toolType.XMINUS : toolType.GANG; // #KLUDGE if ( this.toolCuttingDir === toolType.GANG ) this.toolOnGangPlate = true; else if ( tool.comment.length > 0 ) { var comment_items = String( tool.comment ).split( ":" ); for ( var n in comment_items ) if ( /gang/i.test( comment_items[ n ] ) ) { this.toolOnGangPlate = true; break; } } this.toolType = tool.getType( ); this.toolDiam = tool.getDiameter( ); this.feedMode = section.feedMode === FEED_PER_REVOLUTION ? 95 : 94; this.spindleMode = tool.getSpindleMode( ); this.surfaceSpeed = tool.surfaceSpeed * ( ( unit === MM ) ? 1/1000.0 : 1/12.0 ); this.rpm = tool.spindleRPM; var toolDescript = this.toolNum === this.c_barPullerToolNum ? " Stock Transfer" : " " + tool.vendor + " " + tool.description ; this.toolingComment = "-- tool: " + this.toolNum + toolDescript; this.toolLine = this.toolNum + " " + tool.vendor + " " + tool.description + " " + tool.comment; this.compOffset = tool.isTurningTool( ) ? tool.compensationOffset : tool.lengthOffset; this.toolLength = tool.bodyLength; if ( prevSection !== undefined ) this.toolIsNewTool = prevSection.getTool( ).number !== this.toolNum; // check tool metrics - issue warnings switch ( this.toolType ) { case TOOL_TAP_RIGHT_HAND: case TOOL_TAP_LEFT_HAND: if ( tool.threadPitch > this.toolDiam / 3 ) warnings.pushWarning( " Tool: " + this.toolNum + " - pitch it too large" ); if ( this.toolType === TOOL_TAP_LEFT_HAND && tool.isClockwise( ) ) warnings.pushWarning( " Tool: " + this.toolNum + " M3 on left hand tap" ); if ( this.toolType === TOOL_TAP_RIGHT_HAND && ! tool.isClockwise( ) ) warnings.pushWarning( " Tool: " + this.toolNum + " M4 on right hand tap" ); break; case TOOL_TURNING_BORING: if ( section.getFinalPosition( ).z < section.getInitialPosition( ).z ) warnings.pushWarning( " Tool: " + this.toolNum + " may retract through part" ); // if ( section.getFinalPosition( ).z < section.getInitialPosition( ).z ) // warnings.pushWarning( " Tool: " + this.toolNum + " may retract through part" ); break; case TOOL_DRILL: if ( ! tool.isClockwise( ) ) warnings.pushWarning( " Tool: " + this.toolNum + " M4 detected on drill" ); break; case TOOL_DRILL_CENTER: if ( ! tool.isClockwise( ) ) warnings.pushWarning( " Tool: " + this.toolNum + " M4 detected on center drill" ); break; case TOOL_DRILL_SPOT: if ( ! tool.isClockwise( ) ) warnings.pushWarning( " Tool: " + this.toolNum + " M4 detected on spot drill" ); break; default: if ( ! tool.isClockwise( ) ) warnings.pushWarning( " Tool: " + this.toolNum + " M4 detected on this tool" ); break; } this.writeToolHeader = function( section ) { if ( properties.writeToolingInfo ) { writeComment("=============================================================="); writeComment( "Tool: " + this.toolLine ); writeComment( "Time: " + formatCycleTime( _getToolCT( getCurrentSectionId( ) ) ) ); writeComment( " Z: " + zFormat.format( _getToolZ( getCurrentSectionId( ) ) ) ); } else writeComment( "Tool: " + this.toolLine ); if ( section.hasParameter( "operation-comment" ) ) writeComment( " Op: " + section.getParameter( "operation-comment" ) ); }; this.writeOpHeader = function( section ) { var comment = section.hasParameter( "operation-comment" ) ? section.getParameter( "operation-comment" ) : undefined; if ( properties.writeToolingInfo ) { writeComment(".. .. .. .. .. .. .. .. .. .. .. .. .."); if ( comment !== undefined ) { writeComment( " Op: " + comment); writeComment( "Time: " + formatCycleTime( currentSection.getCycleTime( ) ) ); writeComment( " Z: " + zFormat.format( currentSection.getGlobalZRange( ).getMinimum( ) ) ); } } else if ( comment !== undefined ) writeComment( " Op: " + comment); }; this.writeToolCallCmd = function( section ) { if ( this.toolNum > this.maxToolNum ) warning(localize("Tool number exceeds maximum value.")); var compensationOffset = isStockTranferOp( section ) ? this.c_barPullerToolNum : this.compOffset; if ( compensationOffset > this.maxToolNum ) { error( localize( "Compensation offset is out of range." ) ); return false; } writeBlock("T" + toolFormat.format( this.toolNum ) + " M6 G43" ); return true; }; this.writeHeader = function ( ) { if ( this.toolIsNewTool ) this.writeToolHeader( currentSection ); else this.writeOpHeader( currentSection ); }; this.isGang = function( ) { return this.toolCuttingDir === toolType.GANG; }; this.valid = function( ) { return this.toolNum !== 0 && this.sectionName !== "" && this.sectionName.length > 0; }; this.matchName = function ( name ) { return this.sectionMatchName.search( name ) >= 0; }; this.setLastTool = function( ) { this.isLastTool = true; }; this.set30Type = function( ) { this.tool30Type = tool30Type.ZONLY; }; // debugOut( " ToolInfo: sectionId: " + this.sectionId + " toolNum: " + this.toolNum ); } //-------------------------------------------------------------------------------------------------------------- // encapsulate an array of toolRecord objects above, plus info about the set // of tooling as a whole function toolingInfo( warnings ) { this.tooling = [ ]; this.xPlusCount = 0; this.xMinusCount = 0; this.gangCount = 0; this.adjacentGangToolingCount = 0; this.maxGangToolSafeZ = properties.gangToolSafeMargin; this.maxTurretToolZ = properties.gangToolSafeMargin; this.maxQCTPToolZ = properties.gangToolSafeMargin; this.approxG30RoundTrips = 0; this.manualToolChangTime = 0; this.gangIndexTime = 0; this.promptString = ""; this.totalToolChangeTime = 0; this.initalized = false; this.tool0_state = true; this.isPureGangToolMode = false; var numberOfSections = getNumberOfSections( ); var numberOfTools = 0; var adjacentXPlusTooling = 0; var lastToolType = toolType.NOTYPE; var lastGangToolLen = 0; var maxDeltaLengthOnGang = 0; var lastToolNum = -1; var trLast = undefined; for (var i = 0; i < numberOfSections; ++i ) { var tr = new toolRecord( i, warnings ); var section = getSection( i ); if ( tr.toolNum !== lastToolNum ) { var holderHeadLength = section.hasParameter( "operation:tool_holderHeadLength" ) ? section.getParameter( "operation:tool_holderHeadLength" ) : 1; // #HACK holderHeadLength = holderHeadLength > 5.5 ? holderHeadLength / 25.4 : holderHeadLength; // adjust for metric value if ( tr.toolOnGangPlate ) { // Toggle and lock the state of this.adjacentGangTooling // if there are two adjacent gang ops using different tools ++this.gangCount; if ( lastToolType === toolType.GANG ) { ++this.adjacentGangToolingCount; maxDeltaLengthOnGang = Math.max( maxDeltaLengthOnGang, Math.abs( lastGangToolLen - tr.toolLength ) ); this.maxGangToolSafeZ = Math.max( this.maxGangToolSafeZ, maxDeltaLengthOnGang ); trLast.set30Type( ); } lastToolType = toolType.GANG; lastGangToolLen = tr.toolLength; } if ( tr.toolCuttingDir === toolType.XMINUS ) { ++this.xMinusCount; if ( tr.toolOnGangPlate === false ) { lastToolType = toolType.XMINUS; this.maxQCTPToolZ = Math.max( this.maxQCTPToolZ, tr.toolLength !== 0 ? tr.toolLength : holderHeadLength ); } } else if ( tr.toolCuttingDir === toolType.XPLUS ) { ++this.xPlusCount; if ( lastToolType === toolType.XPLUS ) ++adjacentXPlusTooling; if ( tr.toolOnGangPlate === false ) { lastToolType = toolType.XPLUS; this.maxTurretToolZ = Math.max( this.maxTurretToolZ, tr.toolLength !== 0 ? tr.toolLength : holderHeadLength ); } } lastToolNum = tr.toolNum; ++numberOfTools; } this.tooling.push( tr ); if ( i === numberOfSections - 1 ) tr.setLastTool( ); trLast = tr; } this.initalized = true; if ( this.adjacentGangToolingCount > 0 && properties.using_GangTooling ) { this.promptString = " **** PUT LATHE INTO GANG TOOL MODE ***"; if ( this.xMinusCount <=1 && this.xPlusCount <= 1 ) this.isPureGangToolMode = true; } else if ( this.xMinusCount > 0 && this.xPlusCount === 0 ) this.promptString = " **** PUT LATHE INTO QCTP MODE ***"; else if ( this.xMinusCount <= 1 && this.xPlusCount > 0 ) this.promptString = " **** PUT LATHE INTO TURRET MODE ***"; else if ( this.xMinusCount > 0 && this.xPlusCount > 0 ) this.promptString = " **** PUT LATHE INTO TURRET MODE ***"; // debugOut( " toolingInfo: xMinusCount: " + this.xMinusCount + " xPlusCount: " + this.xPlusCount + " gangCount: " + this.gangCount ); // attemp to calulate the total tool change time... var factor = unit === MM ? 25.4 : 1; var _rapid = properties.rapidFeed * factor; var normalG30Count = properties.using_GangTooling === true ? numberOfTools - this.adjacentGangToolingCount : numberOfTools; if ( properties.using_GangTooling === true ) this.totalToolChangeTime = this.adjacentGangToolingCount * ( this.maxGangToolSafeZ + properties.gangToolSafeMargin ) / _rapid * 60; this.totalToolChangeTime += normalG30Count * ( this.maxTurretToolZ + properties.gangToolSafeMargin ) / _rapid * 60; this.totalToolChangeTime += adjacentXPlusTooling * 2; // two seconds to change turret tool. this.totalToolChangeTime += this.xMinusCount * properties.manualToolChangeTime; // two seconds to change turret tool. this.getLatheModePrompt = function( ) { return this.promptString; }; this.usesGangOptimization = function( ) { return this.adjacentGangTooling > 0; }; this.hasXMinusTools = function( ) { return this.xMinusCount > 0; }; this.recommendedGangZ = function( ) { return this.maxGangToolSafeZ + properties.gangToolSafeMargin; }; this.getToolChangeTime = function( ) { return this.totalToolChangeTime; }; this.isTool0 = function( ) { var ret = this.tool0_state; this.tool0_state = false; return ret; }; this.getToolInfo = function( sectionId ) { if ( sectionId === undefined ) sectionId = getCurrentSectionId( ); if ( sectionId >= 0 || sectionId < getNumberOfSections( ) ) return this.tooling[ sectionId ]; error( " getToolInfo: sectionId not valid " + sectionId ); return undefined; }; this.getTN = function( section ) { if ( section === undefined ) section = getSection( getCurrentSectionId( ) ); var toolRecord = this.tooling[ section.getId( ) ]; // debugOut( " getTN: section.getId( ): " + section.getId( ) + " toolNum Found: " + toolRecord.toolNum ); if ( toolRecord.valid( ) ) return toolRecord.toolNum; error( " getTN: toolRecord not valid " ); return 0; }; this.findToolFromSectionName = function( name ) { for ( var n in this.tooling ) { if ( this.tooling[ n ].matchName( name ) ) return this.tooling[ n ]; } return undefined; }; this.writeG30 = function( loopStack ) { var isTool0 = this.isTool0( ); var tr = this.getToolInfo( ); if ( properties.using_GangTooling ) { if ( tr.tool30Type === tool30Type.ZONLY && !isTool0 ) { writeln(""); writeComment("...pull back to safe Z..."); writeBlock( gFormat.format(00) + " " + zOutput.format( this.recommendedGangZ( ) ) ); } else { writeln(""); writeComment("...pull back to safe Z..."); writeBlock( gFormat.format(00) + " " + zOutput.format( this.recommendedGangZ( ) ) ); // writeln(""); // writeBlock( gFormat.format(30) ); // if ( ! this.isPureGangToolMode && ! tr.isLastTool ) // writeBlock( mFormat.format(0) ); // else if ( ! this.isPureGangToolMode && tr.isLastTool && loopStack.isOpen( ) ) // writeBlock( mFormat.format(0) ); } } else { writeln(""); //properties.tormachMillLathing ? writeBlock( gFormat.format(30) ) : writeBlock( gFormat.format(30), "Z #5422" ); } }; this.getToolChangeTime = function( ) { return this.totalToolChangeTime; }; } //-------------------------------------------------------------------------------------------------------------- // encapsulate the retract state function retract( ) { this.retractState = false; this.isRetracted = function( ) { return this.retractState; }; this.onMove = function( ) { this.retractState = false; }; this.doRetract = function( tooling, loopStack ) { if ( this.retractState === false ) tooling.writeG30( loopStack ); this.retractState = true; }; } //-------------------------------------------------------------------------------------------------------------- // encapsulate the coolant state function coolant( ) { this.coolantMode = COOLANT_OFF; this.coolantOnFirstZ = COOLANT_OFF; this.zStateOff = function( ) { this.coolantOnFirstZ = 0; }; this.getCoolantMode = function( ) { return this.coolantMode; }; this.coolantOnZ = function( _z ) { var ret; if ( this.coolantOnFirstZ && _z ) { ret = mFormat.format( ( this.coolantOnFirstZ === COOLANT_FLOOD ) ? 8 : 88 ); this.coolantOnFirstZ = 0; } return ret; }; this.setCoolant = function( actions, coolant ) { if ( coolant === this.coolantMode ) return; // coolant is already in same state var m = undefined; if ( coolant === COOLANT_OFF ) { var action = actions.findActionForCurrentSection( ); if ( action === undefined || action.M9 === false ) writeBlock(mFormat.format( ( this.coolantMode === COOLANT_THROUGH_TOOL ) ? 89 : 9 ) ); this.coolantMode = COOLANT_OFF; return; } switch ( coolant ) { case COOLANT_FLOOD: this.coolantOnFirstZ = COOLANT_FLOOD; break; case COOLANT_THROUGH_TOOL: this.coolantOnFirstZ = COOLANT_THROUGH_TOOL; break; default: onUnsupportedCoolant( coolant ); m = 9; } if ( m ) writeBlock( mFormat.format( m ) ); this.coolantMode = coolant; }; } //-------------------------------------------------------------------------------------------------------------- // encapsulate the spindle state function spindle( ) { this.spindleState = COMMAND_STOP_SPINDLE; this.spindleDir = 5; this.setSpindleDir = function( spindleDir ) { this.spindleDir = spindleDir; }; this.setSpindle = function( newState ) { this.spindleState = newState; }; this.setWriteSpindle = function( newState ) { if ( this.spindleState === newState ) return; switch ( this.spindleState = newState ) { case COMMAND_SPINDLE_CLOCKWISE: this.spindleDir = 3; break; case COMMAND_SPINDLE_COUNTERCLOCKWISE: this.spindleDir = 4; break; case COMMAND_STOP_SPINDLE: default: this.spindleDir = 5; break; } var m = mFormat.format( this.spindleDir ); writeBlock( m ); }; this.writeSpindleCmd = function( section ) { var mSpindle = section.getTool( ).clockwise ? 3 : 4; var toolSpindleSpeed = 5000; var tool = section.getTool( ); gSpindleModeModal.reset( ); var spindleDir = section.getTool( ).clockwise ? COMMAND_SPINDLE_CLOCKWISE : COMMAND_SPINDLE_COUNTERCLOCKWISE; // The maxSpindleSpeed value propagates down from what's in the tool lib // The user can override this in the Tool setup tab, either way this parameter // is set. if ( properties.tormachMillLathing === true ) { writeBlock( sOutput.format( tool.spindleRPM /*Math.min( tool.spindleRPM, properties.maximumSpindleSpeed )*/ ), mFormat.format( mSpindle ) ); this.spindleState = spindleDir; return; } if ( section.hasParameter( "operation:tool_maximumSpindleSpeed" ) ) toolSpindleSpeed = section.getParameter( "operation:tool_maximumSpindleSpeed" ); if ( tool.getSpindleMode( ) == SPINDLE_CONSTANT_SURFACE_SPEED ) { // So currentSection.getMaximumSpindleSpeed() should propogate to the setup box or // "operation:tool_maximumSpindleSpeed"... var maximumSpindleSpeed = Math.min( toolSpindleSpeed, properties.maximumSpindleSpeed ); // debugOut( ";*** currentSection.getMaximumSpindleSpeed: " + currentSection.getMaximumSpindleSpeed( ), // ";*** tool.maximumSpindleSpeed: " + tool.maximumSpindleSpeed, // ";*** properties.maximumSpindleSpeed: " + properties.maximumSpindleSpeed ); if ( tool.surfaceSpeed > 0 && maximumSpindleSpeed > 0 ) { writeBlock( gSpindleModeModal.format(96), sOutput.format( section.getTool( ).surfaceSpeed * ( ( unit === MM ) ? 1/1000.0 : 1/12.0) ), dOutput.format( maximumSpindleSpeed ), mFormat.format( mSpindle ) ); this.spindleState = spindleDir; } } else if ( tool.spindleRPM > 0 ) { writeBlock( gSpindleModeModal.format(97), sOutput.format( tool.spindleRPM ), mFormat.format( mSpindle ) ); this.spindleState = spindleDir; } }; } //-------------------------------------------------------------------------------------------------------------- // encapsulate the feed type state function feedType( ) { this.ftState = 0; this.setFTyp = function( section ) { this.ftState = section.feedMode === FEED_PER_REVOLUTION ? 95 : 94; }; this.getFTyp = function( ) { return this.ftState; }; this.hasFTyp = function( ) { return this.ftState !== 0; }; this.emitAndReset = function( reset, formatter ) { var ret = ""; if ( this.ftState !==0 && reset === false ) { ret = formatter.format( this.ftState ); this.ftState = 0; } return ret; }; } //-------------------------------------------------------------------------------------------------------------- // encapsulate the optional;section state function optionalState( ) { this.optionalSection = false; this.isOptionalState = function( ) { return this.optionalSection === true; }; this.transitionToCurState = function( ) { var ret = this.optionalSection === true && ! currentSection.isOptional( ); this.optionalSection = currentSection.isOptional( ); return ret; }; } //-------------------------------------------------------------------------------------------------------------- // encapsulate the optional;section state function pendingRadiusComp( ) { this.pendingRadiusComp = -1; this.isPending = function( ) { return this.pendingRadiusComp >= 0; }; this.setPendingRadiusComp = function( newState ) { this.pendingRadiusComp = newState; }; this.reset = function( ) { this.pendingRadiusComp = -1; }; } //-------------------------------------------------------------------------------------------------------------- // encapsulate sequence numbers function lineNumber( ) { this.currLineNumber = properties.sequenceNumberStart; this.nextLineNumber = function( optional ) { if ( properties.showSequenceNumbers === false ) return ""; var ret = optional ? "/" : ""; ret += nFormat.format( this.currLineNumber % 100000 ); this.currLineNumber += properties.sequenceNumberIncrement; return ret; }; } //-------------------------------------------------------------------------------------------------------------- // encapsulate program state function programState( ) { this.pState = pState.OPENING; this.pStateIsPreSection = function( ) { return this.pState === pState.OPENING; }; this.IsLastSection = function( ) { return this.pState === pState.LAST_SECTION; }; this.setInSection = function( ) { this.pState = pState.IN_SECTIONS; }; this.setLastSection = function( ) { this.pState = pState.LAST_SECTION; }; this.setClosing = function( ) { this.pState = pState.CLOSING; }; } //-------------------------------------------------------------------------------------------------------------- // encapsulate passthrough buffer function passThroughBuffer( ) { this.ptBuffer = [ ]; this.bPtr = 0; this.add = function( text ) { this.ptBuffer.push( text ); }; this.empty = function( ) { return this.ptBuffer.length === 0; }; this.next = function( ) { if ( this.bPtr === this.ptBuffer.length ) return undefined; var ret = this.ptBuffer[ this.bPtr ]; ++this.bPtr; return ret; }; this.dump = function( ) { if ( this.bPtr === this.ptBuffer.length ) return undefined; writeln( "" ); while ( this.bPtr < this.ptBuffer.length ) writeln( this.ptBuffer[ this.bPtr++ ] ); }; this.reset = function( ) { this.bPtr = 0; }; } //-------------------------------------------------------------------------------------------------------------- // encapsulate warnings .. may be expanded buffer function warnings_( ) { this.warningBuffer = [ ]; this.pushWarning = function( warningString ) { // check to see if warnings were instantiated. if ( warningString && warningString.length > 0 ) this.warningBuffer.push( " *** WARNING :" + warningString ); }; this.dump = function( ) { if ( properties.warnings === false ) return; if ( this.warningBuffer.length > 0 ) writeComment( " **** WARNINGS *************************************** "); for ( var n in this.warningBuffer ) writeComment( this.warningBuffer[ n ] ); }; } //-------------------------------------------------------------------------------------------------------------- // encapsulate loop counting .. function loopStack_( ) { this.loopCount = 0; this.parsePassThrough = function( passthroughStr ) { if ( String( passthroughStr ).match( new RegExp( /o[0-9]+\srepeat/i ) ) ) ++this.loopCount; else if ( String( passthroughStr ).match( new RegExp( /o[0-9]+\sendrepeat/i ) ) ) --this.loopCount; }; this.isOpen = function( ) { return this.loopCount > 0; } ; } //-------------------------------------------------------------------------------------------------------------- // encapsulate loop counting .. function rapidMoveControl( ) { this.removeUntil = false; this.removeLast = false; this.removeAll = false; this.isCyclePoint = false; this.hitCount = 0; this.onSection = function( actions ) { this.isCyclePoint = currentSection.hasParameter( "operation:strategy" ) && currentSection.getParameter( "operation:strategy" ) === "turningThread"; if ( this.isCyclePoint ) this.removeUntil = true; if ( actions.actionIsSuppress( ) ) this.removeAll = true; }; this.rapidSuppress = function( ) { ++this.hitCount; if ( this.removeUntil === true || this.removeAll === true ) return true; return false; }; this.resetUntil = function( ) { this.removeUntil = false; }; this.reset = function( ) { this.removeUntil = false; this.removeLast = false; this.removeAll = false; this.isCyclePoint = false; this.hitCount = 0; }; } // inial program info var g_fileGenerated; //collected state var g_sectionCount = 0; var g_sequenceNumber; var g_currentWorkOffset; var g_optionalState; var g_pendingRadiusComp; var g_passThroughBuffer; var g_rapidMoveControl; var g_fTyp; // state variable to control G93-G95 var g_pState; var g_retract; var g_coolant; var g_spindle; var g_tooling; var g_warnings; var g_loopStack; var g_actions; //================================================================================================== // action stuff // check to see if this is a bar pulling op function isStockTranferOp( section ) { if ( section === undefined ) section = currentSection; if ( ! section ) return false; return section.getTool( ).number === 0 && section.hasParameter( "operation-strategy" ) && section.getParameter( "operation-strategy" ) === "turningStockTransfer"; } //================================================================================================== // Tool Info stuff // attemps to get a minimum X value for // internal operations... function _getToolX( sectionId ) { if ( sectionId === undefined ) sectionId = getCurrentSectionId( ); var ti = g_tooling.getToolInfo( sectionId ); var numberOfSections = getNumberOfSections( ); var baseNumber = 100000; var xSide = ti.valid( ) ? ti.toolCuttingDir === toolType.XMINUS ? -1 : ti.toolCuttingDir === toolType.XPLUS ? 1 : 0 : 0; var xRet = baseNumber; for( ; sectionId < numberOfSections; ++sectionId ) { var section = getSection( sectionId ); if ( g_tooling.getTN( section ) !== ti.toolNum ) break; var action = g_actions.findActionRec( section.getParameter( "operation-comment" ) ); if ( action !== undefined && action.modifier === "suppress" ) { xRet = action.minX; continue; } else if ( section.hasParameter( "operation-strategy" ) && section.getParameter( "operation-strategy" ) === "turningThread" ) { if ( section.hasParameter( "operation:turningMode" ) && section.getParameter( "operation:turningMode" ) === "inner" ) { xRet = Math.abs( section.getGlobalBoundingBox( ).lower.x ) * xSide; } } else if ( section.hasParameter( "operation:turningMode" ) && section.getParameter( "operation:turningMode" ) === "inner" ) { xRet = Math.min( Math.abs( xRet ), Math.abs( section.getGlobalBoundingBox( ).lower.x ) ); xRet *= xSide; } } // debugOut( "_getToolX: xRet: " + xRet ); return Math.abs( xRet ) === baseNumber ? 0 : xRet; } // does a look ahead to get the the cycle time for // the current tool function _getToolZ( sectionId ) { if ( sectionId === undefined ) sectionId = getCurrentSectionId( ); var toolNum = g_tooling.getTN( getSection( sectionId ) ); var numberOfSections = getNumberOfSections( ); var zRet = Infinity; for( ; sectionId < numberOfSections; ++sectionId ) { var section = getSection( sectionId ); if ( g_tooling.getTN( section ) !== toolNum ) break; var sectionZ = section.getGlobalZRange( ).getMinimum( ); var action = g_actions.findActionRec( section.getParameter( "operation-comment" ) ); if ( action !== undefined ) { if ( action.modifier === "suppress" ) sectionZ = action.maxZ; else sectionZ = Math.min( sectionZ, action.maxZ ); } // special case for threading .. else if ( section.hasParameter( "operation-strategy" ) && section.getParameter( "operation-strategy" ) === "turningThread" ) { var incZ = section.hasParameter( "incrementalZ" ) ? section.getParameter( "incrementalZ" ) : 0; var outer = section.hasParameter( "operation:turningMode" ) && section.getParameter( "operation:turningMode" ) === "outer"; var startZ = section.getBoundingBox( ).upper.z; var sectionMetric = section.hasParameter( "operation:metric" ) && section.getParameter( "operation:metric" ) > 0; // debugOut( "_getToolZ: section.getParameter( \"incrementalZ\" ) " + incZ ); incZ = ( sectionMetric === false && Math.abs( incZ ) > 5 ) ? incZ / 25.4 : incZ; // HACK: to get this in proper units. sectionZ = incZ !== 0 ? incZ + startZ : 0; // debugOut( "_getToolZ: ( unit !== MM && incZ > 5 ) " + incZ ); // debugOut( "_getToolZ: section.section.getBoundingBox( ).upper.z " + startZ ); } zRet = Math.min( zRet, sectionZ ); } return zRet === Infinity ? 0 : zRet; } // does a look ahead to get the the cycle time for // the current tool function _getToolCT( sectionId ) { if ( sectionId === undefined ) sectionId = getCurrentSectionId( ); var toolNum = g_tooling.getTN( getSection( sectionId ) ); var numberOfSections = getNumberOfSections( ); var rapidIPM = properties.rapidFeed ? properties.rapidFeed : 60; var ctRet = 0; var factor = unit === MM ? 25.4 : 1; for( ; sectionId < numberOfSections; ++sectionId ) { var section = getSection( sectionId ); if ( g_tooling.getTN( section ) !== toolNum ) break; var sectionCt = section.getCycleTime( ); var action = g_actions.findActionRec( section.getParameter( "operation-comment" ) ); sectionCt += section.getRapidDistance( ) / ( rapidIPM * factor * 60 ); if ( action !== undefined ) { sectionCt += action.ct; if ( action.modifier === "suppress" ) sectionCt = action.ct; } ctRet += sectionCt; } return ctRet; } //================================================================================================== // setup X for diameter QCTP function _getTrueX( _x ) { var ti = g_tooling.getToolInfo( getCurrentSectionId( ) ); if ( ti.toolCuttingDir == toolType.XPLUS ) return _x; if ( g_tooling.hasXMinusTools( ) || properties.using_GangTooling ) _x = -_x; return _x; } function writeX(_x) { return properties.tormachMillLathing ? xrOutput.format( _getTrueX( _x ) ) : xOutput.format( _getTrueX( _x ) ); } /** Writes the specified block. */ function writeBlock( ) { writeWords2( g_sequenceNumber.nextLineNumber( ), arguments); } function formatComment( text ) { if ( text === undefined ) return ";"; return ";" + " " + text; } /** Output a comment. */ function writeComment( text ) { writeln( formatComment( text ) ); } // formats cycle time function formatCycleTime( ct ) { var d = new Date(1899, 11, 31, 0, 0, ct + 0.5, 0); return timeFormat.format( d.getHours( ) ) + ":" + timeFormat.format( d.getMinutes( ) ) + ":" + timeFormat.format( d.getSeconds( ) ); } function onParameter( ) { // these come after 'onOpen' ... if (typeof( arguments[ 0 ] ) === 'string' && arguments[ 0 ] === "document-path" ) writeComment( " Document: " + arguments[ 1 ] ); else if (typeof( arguments[ 0 ] ) === 'string' && arguments[ 0 ] === "generated-by" ) writeComment( " CAM: " + arguments[ 1 ] ); else if (typeof( arguments[ 0 ] ) === 'string' && arguments[ 0 ] === "generated-at" ) g_fileGenerated = " ***LOCKED*** : " + new Date( ).toString( ); // come before first section... else if (typeof( arguments[ 0 ] ) === 'string' && arguments[ 0 ] === "action" ) g_actions.stowAction( arguments[ 1 ] ); } function onOpen( ) { // this must go first... g_warnings = new warnings_( ); g_tooling = new toolingInfo( g_warnings ); // then this can go... g_fTyp = new feedType( ); g_pState = new programState( ); g_optionalState = new optionalState( ); g_pendingRadiusComp = new pendingRadiusComp( ); g_passThroughBuffer = new passThroughBuffer( ); g_retract = new retract( ); g_coolant= new coolant( ); g_spindle = new spindle( ); g_actions = new actionsInfo( g_tooling, g_warnings ); g_sequenceNumber = new lineNumber( ); g_loopStack = new loopStack_( ); g_rapidMoveControl = new rapidMoveControl( ); writeln("%"); writeln("(*********************************************************)"); writeln("(* Linuxcnc Lathe Post Processsor r20160408 *)"); writeln("(*********************************************************)"); if ( !properties.separateWordsWithSpace ) setWordSeparator( "" ); writeProgramStart( ); } function onComment( message ) { writeComment( message ); } /** Force output of X, and Z. */ function forceXZ() { xOutput.reset(); zOutput.reset(); } /** Force output of X, Z, and F on next output. */ function forceAny() { forceXZ(); feedOutput.reset( ); g_rapidMoveControl.reset( ); } function getSpindle() { return SPINDLE_PRIMARY; } // formats the tool line in the header to display min Z and CycleTime function _entryFixup( entry, minZ, minX, ct, maxComment ) { var zCol = maxComment + 3; var xCol = zCol + 15; var ctCol = xCol + 15; for( var i = entry.length; i < zCol; ++i ) entry += " "; entry += "Z : " + zFormat.format( minZ ); for( var i = entry.length; i < xCol; ++i ) entry += " "; if ( minX != 0 ) entry += "X : " + xFormat.format( minX ); for( var i = entry.length; i < ctCol; ++i ) entry += " "; return entry += "CT: " + formatCycleTime( ct ); } function writeProgramStart( ) { if ( programName ) { writeComment( " program: " + programName ); if ( programComment ) writeComment( " " + programComment ); writeComment( ); } } // Returns the tool information in an array. function writeInitMachineState( ) { if ( properties.tormachMillLathing == false ) writeBlock( gFormat.format(7) ); writeBlock( gPlaneModal.format(18) ); switch ( unit ) { case IN: writeBlock( gUnitModal.format( 20 ) ); break; case MM: writeBlock( gUnitModal.format( 21 ) ); break; } writeBlock( gFormat.format(54) ); writeBlock( gFormat.format(40 )); writeBlock( gAbsIncModal.format(90) ); } function writeToolInfo( ) { if ( properties.writeToolingInfo === false ) return; var result = [ ]; var lastToolIndex = 0; var minimumZ; var tn_ = -1; var numberOfSections = getNumberOfSections(); var maxComment = 0; var totalCT = 0; // preload all the 'action' commands for ( var i = 0; i < numberOfSections; ++i ) { var section = getSection( i ); var secTn = g_tooling.getTN( section ); if ( secTn !== tn_) { maxComment = Math.max( g_tooling.getToolInfo( i ).toolingComment.length, maxComment ); tn_ = secTn; } } tn_= 0; var lastToolSectionId = -1; var ct = 0; var toolDescription = ""; for ( var i = 0; i < numberOfSections; ++i ) { var section = getSection( i ); var currTN = g_tooling.getTN( section ); // the next tool is up... if ( currTN !== tn_) { // fix up the last tool entry...on the first iteration tn_ will be 0 if ( tn_ > 0 ) { totalCT += ( ct = _getToolCT( lastToolSectionId ) ); result[ lastToolIndex ] = _entryFixup( result[ lastToolIndex ], _getToolZ( lastToolSectionId ), _getToolX( lastToolSectionId ), ct , maxComment ); } tn_ = currTN; lastToolIndex = result.length; lastToolSectionId = i; result.push( g_tooling.getToolInfo( i ).toolingComment ); } // currTN != tn_ result.push( new String( " op: " + section.getParameter( "operation-comment" ) ) ); } // for totalCT += ( ct = _getToolCT( lastToolSectionId ) ); if ( result.length > 0 ) result[ lastToolIndex ] = _entryFixup( result[ lastToolIndex ], _getToolZ( lastToolSectionId ), _getToolX( lastToolSectionId ), ct, maxComment ); // warning to put lathe into right mode... writeComment( ); if ( properties.tormachMillLathing === false ) { writeComment( g_tooling.getLatheModePrompt( ) ); writeComment( ); } var totalPartTime = totalCT + g_tooling.getToolChangeTime( ) + properties.partLoadTime; writeComment("Tool / Op list .............................................................................."); for ( var i in result ) writeComment( result[ i ] ); writeComment( ); writeComment( "Approximate tool change time: ................ : " + formatCycleTime( g_tooling.getToolChangeTime( ) ) ); writeComment( "Approximate part load time: .................. : " + formatCycleTime( properties.partLoadTime ) ); writeComment( "total cycle time ( with approx tool change time ): " + formatCycleTime( totalPartTime ) + " (" + secFormat.format( totalPartTime / 3600 ) + " hrs. )" ); writeComment( ); } function writeInitialHeaderInfo( ) { writeComment( " Post Processor: " + g_description ); // writeComment( " Material: " + getParameter( "inventor:Material" ) ); writeComment( ); writeComment( g_fileGenerated ); writeComment( ); writeComment( ); } function writeSectionNotes( section ) { if ( properties.showNotes && section.hasParameter( "notes" ) ) { var notes = section.getParameter( "notes" ); if ( notes ) { var lines = String(notes).split( "\n" ); for ( var line in lines) { var comment = lines[line].replace( new RegExp( /^[\\s]+/g ), "" ).replace( new RegExp( /[\\s]+$/g ), ""); if ( comment ) { if ( line === 0 ) writeComment( "Note: " + comment ); else writeComment( " " + comment ); } } } } } function abortOnSectionTypeError( ) { if ( currentSection.getType( ) === TYPE_TURNING ) return false; if ( hasParameter( "operation-strategy" ) && getParameter( "operation-strategy" ) === "drill" ) return false; if ( currentSection.getType( ) === TYPE_MILLING ) error( localize( "Milling toolpath is not supported." ) ); else error( localize( "Non-turning toolpath is not supported." ) ); return true; } function onSection( ) { // needs to be done here because all the external file 'action' stuff // is gotten between onOpen and onSection if ( isFirstSection( ) ) { writeInitialHeaderInfo( ); writeToolInfo( ); g_warnings.dump( ); writeInitMachineState( ); writeParkTool( ); g_passThroughBuffer.dump( ); } g_pState.setInSection( ); if ( isLastSection( ) ) g_pState.setLastSection( ); if ( abortOnSectionTypeError( ) ) return; var forceToolAndRetract = g_optionalState.transitionToCurState( ); var toolInf = g_tooling.getToolInfo( ); var sectionHasToolChange = forceToolAndRetract || isFirstSection( ) || ( currentSection.getForceToolChange && currentSection.getForceToolChange( ) ) || ( toolInf.toolNum !== g_tooling.getTN( getPreviousSection( ) ) ); // for some very wierd reason this doesn't work ??? var newWorkOffset = isFirstSection( ) || ( getPreviousSection( ).workOffset !== currentSection.workOffset ); // work offset changes if ( sectionHasToolChange || newWorkOffset ) forceXZ( ); writeln( "" ); toolInf.writeHeader( ); writeSectionNotes( currentSection ); if ( sectionHasToolChange && ! toolInf.writeToolCallCmd( currentSection ) ) return; if ( g_actions.actionIsPrepend( ) ) g_actions.postActionData( ); //set coolant after we have positioned at Z g_coolant.setCoolant( g_actions, tool.coolant ); forceAny( ); gMotionModal.reset( ); gFeedModeModal.reset( ); g_rapidMoveControl.onSection( g_actions ); g_fTyp.setFTyp( currentSection ); g_spindle.writeSpindleCmd( currentSection ); setRotation( currentSection.workPlane ); var actionModifier = g_actions.getActionModifier( ); var initialPosition = getFramePosition(currentSection.getInitialPosition( )); if ( ! g_retract.isRetracted( ) && actionModifier !== "suppress" ) { //TAG: need to retract along X or Z if ( getCurrentPosition( ).z < initialPosition.z) { writeBlock( gMotionModal.format( 0 ), zOutput.format( initialPosition.z ) ); // g_retract.onMove( ); I think this is wrong, it's not in the G30 state. } } if ( sectionHasToolChange ) { gMotionModal.reset( ); if ( actionModifier !== "suppress" ) { var m = g_coolant.coolantOnZ( initialPosition.z ); var upperZ = 0; if ( hasParameter( "stock-upper-z" ) ) upperZ = getParameter( "stock-upper-z" ); // TODO: Force X move before Z. revisit this logic to handle transition fomr X+ to X- tooling if ( ! isStockTranferOp( ) && ( toolInf.isGang( ) || properties.forceX_first_onFirstMove || initialPosition.z <= upperZ ) ) { writeBlock( gMotionModal.format(0), writeX(initialPosition.x) ); writeBlock( zOutput.format(initialPosition.z), m ); g_retract.onMove( ); } else if ( ! isStockTranferOp( ) ) { writeBlock( gMotionModal.format(0), writeX(initialPosition.x), zOutput.format(initialPosition.z), m ); g_retract.onMove( ); } gMotionModal.reset( ); } else { // actionModifier == "suppress" g_actions.insertActionCoolant( g_coolant.getCoolantMode( ) ); g_coolant.zStateOff( ); } } if ( sectionHasToolChange || g_retract.isRetracted( ) ) gPlaneModal.reset(); ++g_sectionCount; } function onDwell( seconds ) { if (seconds > 99.999) warning( localize("Dwelling time is out of range.") ); writeBlock( gFormat.format( 4 ), "P" + dwellFormat.format( seconds ) ); } function onRadiusCompensation( ) { g_pendingRadiusComp.setPendingRadiusComp( radiusCompensation ); } function onRapid(_x, _y, _z) { if ( g_rapidMoveControl.rapidSuppress( ) ) return; var x = writeX(_x); var z = zOutput.format(_z); var m = g_coolant.coolantOnZ( z ); if ( x || z ) { if ( g_pendingRadiusComp.isPending( ) ) { g_pendingRadiusComp.reset( ); switch ( radiusCompensation ) { case RADIUS_COMPENSATION_LEFT: writeBlock(gMotionModal.format(0), gFormat.format(41), x, z, m); break; case RADIUS_COMPENSATION_RIGHT: writeBlock(gMotionModal.format(0), gFormat.format(42), x, z, m); break; default: writeBlock(gMotionModal.format(0), gFormat.format(40), x, z, m); } } else writeBlock(gMotionModal.format(0), x, z, m); g_retract.onMove( ); feedOutput.reset(); } } function onFirstFeed( _reset ) { if ( ! g_actions.actionIsSuppress( ) ) return g_fTyp.emitAndReset( _reset, gFeedModeModal ); return ""; } function onLinear(_x, _y, _z, feed) { if ( g_actions.actionIsSuppress( ) ) return; var x = writeX(_x); var z = zOutput.format(_z); var f = feedOutput.format( feed ); var g = onFirstFeed( !( x || z ) && f && getNextRecord( ).isMotion( ) ); if (x || z) { if ( g_pendingRadiusComp.isPending( ) ) { g_pendingRadiusComp.reset( ); writeBlock(gPlaneModal.format(18)); switch (radiusCompensation) { case RADIUS_COMPENSATION_LEFT: writeBlock(g, gMotionModal.format(1), gFormat.format(41), x, z, f); break; case RADIUS_COMPENSATION_RIGHT: writeBlock(g, gMotionModal.format(1), gFormat.format(42), x, z, f); break; default: writeBlock(g, gMotionModal.format(1), gFormat.format(40), x, z, f); } } else writeBlock(g, gMotionModal.format(1), x, z, f); g_retract.onMove( ); } else if (f) { if (getNextRecord().isMotion()) { // try not to output feed without motion feedOutput.reset(); // force feed on next line } else { writeBlock(g, gMotionModal.format(1), f); } } } function onCircular(clockwise, cx, cy, cz, x, y, z, feed) { if ( g_actions.actionIsSuppress( ) ) return; var g = onFirstFeed( ); if ( isSpeedFeedSynchronizationActive( ) ) { error(localize("Speed-feed synchronization is not supported for circular moves.")); return; } if ( g_pendingRadiusComp.isPending( ) ) { error(localize("Radius compensation cannot be activated/deactivated for a circular move.")); return; } var start = getCurrentPosition( ); switch (getCircularPlane()) { case PLANE_XY: error(localize("XY plane not allowed")); return; case PLANE_ZX: // debugOut( "; ***cx= " + cx, "; ***cz= " + cz, "; ***start.x= " + start.x, "; ***start.z= " + start.z ); var inverted = g_tooling.getToolInfo( getCurrentSectionId( ) ).toolCuttingDir === toolType.XPLUS; var G2or3 = inverted ? clockwise ? 2 : 3 : clockwise ? 2 : 3; var iVal = inverted ? -( _getTrueX( start.x ) - _getTrueX( cx ) ) : _getTrueX( cx ) - _getTrueX( start.x ); writeBlock( gMotionModal.format( G2or3 ), writeX( x ), zOutput.format(z), iOutput.format( iVal, 0), kOutput.format( ( cz - start.z ), 0), feedOutput.format( feed ) ); g_retract.onMove( ); break; case PLANE_YZ: error(localize("YZ plane not allowed")); return; default: linearize(tolerance); } } function onCycle( ) { switch ( cycleType ) { case "stock-transfer" : if ( g_actions.actionIsPrepend( ) ) g_actions.postActionData( ); break; } } function getCommonCycle(x, y, z, r) { forceXZ( ); // force xyz on first drill hole of any cycle return [ writeX( x ), zOutput.format( z ),"R" + spatialFormat.format( r ) ]; } function onCyclePoint(x, y, z) { if ( g_actions.actionIsSuppress( ) ) return; switch ( cycleType ) { case "thread-turning": if ( ! isLastCyclePoint( ) ) return; g_retract.onMove( ); g_rapidMoveControl.resetUntil( ); var backFromFront = hasParameter( "operation:applyStockOffsetBackFromFront" ) && getParameter( "operation:applyStockOffsetBackFromFront" ) === 1; var pos = backFromFront ? currentSection.getFinalPosition( ) : currentSection.getInitialPosition( ); var g76_z = backFromFront ? pos.z : z; debugOut( "onCyclePoint: backFromFront = " + backFromFront + " z Value: " + z + " pos.z: " + pos.z ); debugOut( "onCyclePoint: currentSection.getFinalPosition = " + currentSection.getFinalPosition( ) + " currentSection.getInitialPosition: " + currentSection.getInitialPosition( )); if ( pos ) { writeBlock( writeX( pos.x ) ); backFromFront ? writeBlock( zOutput.format( z ) ) : writeBlock( zOutput.format( pos.z ) ); } if ( backFromFront ) z = currentSection.getInitialPosition( ).z; var external = false; var inverted = getSection( getCurrentSectionId( ) ).getTool( ).turret > 0; // for HSM Inventor/Fusion if ( hasParameter( "operation:turningMode" ) ) external = getParameter( "operation:turningMode" ) === "outer" ? true : false; // for HSMWorks else if ( hasParameter( "operation:top" ) ) { var tc = getParameter( "operation:top" ); if ( Math.abs( tc ) < Math.abs( cycle.retract ) ) external = true; } var r = -cycle.incrementalX; // positive if taper goes down - delta radius var threadsPerInch = 1.0/cycle.pitch; // per mm for metric var p = 1/threadsPerInch; var driveLine = cycle.retract; var threadCrest; if ( external ) { if ( hasParameter( "operation:outerRadius_value" ) ) threadCrest = getParameter("operation:outerRadius_value"); else if ( hasParameter( "operation:top" ) ) threadCrest = getParameter( "operation:top" ); } else { if ( hasParameter( "operation:innerRadius_value" ) ) threadCrest = getParameter("operation:innerRadius_value"); else if ( hasParameter( "operation:top" ) ) threadCrest = getParameter( "operation:top" ); } var threadDepth = getParameter("operation:threadDepth"); var numPasses = getParameter("operation:numberOfStepdowns"); var iVal = ( driveLine - threadCrest ) * 2; var rootLine = ( threadCrest - threadDepth ) * 2; var jVal = _calcThreadPasses( iVal, threadCrest * 2, rootLine, numPasses); var rVal = getParameter("operation:infeedMode") === "constant" ? 1 : 2; var qVal = getParameter("operation:infeedAngle"); //var hVal = getParameter("operation:nullPass"); if (properties.springpasses > 1){ writeComment("Springpasses in properties section is set to " + properties.springpasses +" !"); var hVal = properties.springpasses; } else{ var hVal = getParameter("operation:nullPass"); } // debugOut( "p= " + p, "driveline= " + driveLine, "threadCrest= " + threadCrest, "threadDepth= " + threadDepth ); writeBlock( gMotionModal.format(76), pOutput.format( p ), zOutput.format( g76_z ), iThreadOutput.format( inverted ? -iVal : iVal ), jThreadOutput.format( jVal ), kThreadOutput.format( threadDepth ), rThreadOutput.format( rVal ), qThreadOutput.format( qVal ), hVal > 0 ? hThreadOutput.format( hVal ) : "" ); return; case "drilling": case "counter-boring": case "chip-breaking": case "deep-drilling": case "reaming": g_retract.onMove( ); expandCyclePoint(x, y, z); return; case "tapping": var threadsPerInch = getParameter("operation:tool_threadPitch"); // per mm for metric writeBlock( gMotionModal.format(33.1), zOutput.format(z), kTapOutput.format( threadsPerInch ) ); g_retract.onMove( ); return; } } function onCycleEnd( ) { if ( ! cycleExpanded ) { switch ( cycleType ) { case "thread-turning": feedOutput.reset(); xOutput.reset(); zOutput.reset(); break; case "drilling": case "counter-boring": case "chip-breaking": case "deep-drilling": case "reaming": writeBlock(gCycleModal.format(80)); break; case "stock-transfer": break; } } } function onCommand(command) { switch (command) { case COMMAND_COOLANT_OFF: g_coolant.setCoolant( g_actions, COOLANT_OFF ); return; case COMMAND_COOLANT_ON: g_coolant.setCoolant( g_actions, COOLANT_FLOOD ); return; case COMMAND_STOP: writeBlock( mFormat.format( 0 ) ); return; case COMMAND_OPTIONAL_STOP: writeBlock( mFormat.format( 1 ) ); break; case COMMAND_END: writeBlock( mFormat.format( 2 ) ); break; case COMMAND_STOP_SPINDLE: var action = g_actions.findActionForCurrentSection( ); if ( action && action.M5 === true ) g_spindle.setSpindle( command ); // fall through... case COMMAND_SPINDLE_CLOCKWISE: case COMMAND_SPINDLE_COUNTERCLOCKWISE: g_spindle.setWriteSpindle( command ); break; case COMMAND_START_SPINDLE: onCommand(tool.clockwise ? COMMAND_SPINDLE_CLOCKWISE : COMMAND_SPINDLE_COUNTERCLOCKWISE); return; default: // onUnsupportedCommand(command); } } function writeParkTool( ) { onCommand( COMMAND_COOLANT_OFF ); onCommand( COMMAND_STOP_SPINDLE ); //Use GoTo function with parting tool if(partingtool===true && properties.use_goto_position === true){ partingtool=false; writeln(""); writeComment("...Goto Position with parting tool..."); writeBlock( gFormat.format( 0 ) + " " + zOutput.format(properties.goto_z_position)) writeBlock("X" + properties.goto_x_position) writeBlock( mFormat.format( 0 ) ) } g_retract.doRetract( g_tooling, g_loopStack ); } function onSectionEnd( ) { if ( g_actions.actionIsSuppress( ) || g_actions.actionIsAppend( ) ) g_actions.postActionData( ); var parkTool = isLastSection( ) || ( g_optionalState.isOptionalState( ) && ! nextSection.isOptional( ) ) || ( currentSection.getForceToolChange && currentSection.getForceToolChange( ) ) || ( g_tooling.getTN( ) !== g_tooling.getTN( getNextSection( ) ) ); //Use GoTo function with parting tool var strategyVal = getParameter("operation:strategy"); if(strategyVal === "turningPart"){ partingtool=true; } if ( parkTool ) writeParkTool( ); forceAny( ); } function onClose() { writeln(""); g_pState.setClosing( ); forceXZ( ); writeParkTool( ); onImpliedCommand(COMMAND_END); onImpliedCommand(COMMAND_STOP_SPINDLE); writeBlock( mFormat.format( 30 ) ); // stop program, spindle stop, coolant off } function _calcThreadPasses( toolClear, majDiam, minDiam, requestPasses ) { var depth = Math.abs( toolClear ); var kNumber = Math.abs( majDiam - minDiam ); var fullDiamDepth = depth; var endDepth= kNumber + fullDiamDepth; var rMax = endDepth - depth; var rMin = rMax / requestPasses; var rMid = ( rMin + rMax ) / 2; for (var i = 1; i <= 100; ++i ) { var tPass_ = 0; var tDepth_ = depth; while ( tDepth_ < endDepth ) { tPass_ = tPass_ + 1; tDepth_ = fullDiamDepth + rMid * Math.sqrt( tPass_ ); // SQR( tPass_ ) = POW( tPass_, 1 /2 ) if ( tPass_ >= 999 ) { break; } } if ( tPass_ === requestPasses ) { return rMid; } else if ( tPass_ > requestPasses ) { rMin = rMid; rMid = ( rMin + rMax ) / 2; } else { rMax = rMid; rMid = ( rMin + rMax ) / 2; } } return 0; } function onPassThrough( text ) { if ( String( text ).search( "file:" ) === 0 ) { var lines = [ ]; var filenames = String( text ).split( ":" ); _onGetLocalTextFile( properties.passThroughFilePath, filenames[ 1 ], lines ); _postLocalTextFile( lines ); writeParkTool( ); } else { var lines = String( text ).split( "|" ); for ( var i in lines ) { var lineText = lines[ i ]; g_loopStack.parsePassThrough( lineText ); if ( g_pState.pStateIsPreSection( ) ) g_passThroughBuffer.add( lineText ); else { if ( g_pState.IsLastSection( ) ) writeln( "" ); writeln( lineText ); } } } } function _onGetLocalTextFile( path, fn, target ) { var filename = fn; var filepath = new String( path ); var rawfile; var re = new RegExp( /(A-Za-z0-9_)\\(A-Za-z0-9_)/ ); var pathDelim = String( filepath ).match( re ) ? "\\" : "/"; if ( filepath.length === 0 ) writeComment( " Error : no file or path" + filepath ); else { if ( String( filepath ).charAt( filepath.length -1 ) !== pathDelim ) filepath += pathDelim; if ( ! FileSystem.isFolder( filepath ) ) { writeln( "" ); writeComment( "**error**error**error" ); writeComment( " Error folder: " + filepath + " not found ! "); writeComment( "**error**error**error" ); return ""; } filepath += filename; if ( ! FileSystem.isFile( filepath ) ) { writeln( "" ); writeComment( "**error**error**error" ); writeComment( " Error file: " + filepath + " not found ! "); writeComment( "**error**error**error" ); return ""; } try { var txt = loadText( filepath, "utf-8"); if ( txt.length > 0 ) { var lines = String( txt ).split( "\r\n" ); rawfile = lines.join( ); for ( var i in lines ) target.push( new String( lines[ i ] ) ); } } catch ( e ) { writeln( "" ); writeComment( "**error**error**error" ); writeComment( " Error can't load" + filepath + " may not be text"); writeComment( "**error**error**error" ); return ""; } } return rawfile; } function _postLocalTextFile( lines ) { if ( ! lines ) return; var re = new RegExp( /([Gg][0-3]+)|([XxZz][-+]?[0-9]*\.?[0-9]+)/ ); for ( var i in lines ) { if ( g_retract.isRetracted( ) && String( lines[ i ] ).match( re ) ) g_retract.onMove( ); writeln( lines[ i ] ); } } function debugOut( ) { if ( ! properties.debugOutput ) return; if ( arguments.length <= 1 ) return; if ( typeof arguments[ 0 ] === 'boolean' && arguments[ 0 ] ) for (var i = 1, j = arguments.length; i < j; ++i) writeln( "*debug: " + arguments[ i ] ); }