= O Codes [[cha:O-Codes]] (((O Codes))) //// ATTENTION TRANSLATORS before translating this document copy the base document into this copy to get the latest version. Untranslated documents are not kept up to date with the English documents. Do not translate anchors or links, translate only the text of a link after the comma. Anchor [[anchor-name]] Link <> Make sure the documents build after translating. //// O-codes provide for flow control in NC programs. Each block has an associated number, which is the number used after O. Care must be taken to properly match the O-numbers. O codes use the letter 'O' not the number zero as the first character in the number like O100. .Numbering Example ---- o100 sub (notice that the if-endif block uses a different number) o110 if [#2 GT 5] (some code here) o110 endif (some more code here) o100 endsub ---- The behavior is undefined if: * The same number is used for more than one block * Other words are used on a line with an O- word * Comments are used on a line with an O-word [NOTE] Using the lower case o makes it easier to distinguish from a 0 that might have been mistyped. For example o100 is easier to see than O100 that it is not a 0. == Subroutines[[sec:subroutines]](((Subroutines))) (((sub)))(((endsub)))(((return)))(((call))) Subroutines extend from a 'O- sub' to an 'O- endsub' . The lines between 'O- sub' and 'O- endsub' are not executed until the subroutine is called with 'O- call'. .Subroutine Example ---- o100 sub G53 G0 X0 Y0 Z0 (rapid move to machine home) o100 endsub ... o100 call (call the subroutine here) M2 ---- See <> & <> & <> sections for more information. .O- Return Inside a subroutine, 'O- return' can be executed. This immediately returns to the calling code, just as though 'O- endsub' was encountered. .O- Return Example ---- o100 sub o110 if [#2 GT 5] (test if parameter #2 is greater than 5) o100 return (return to top of subroutine if test is true) o110 endif (some code here that only gets executed if parameter #2 is less than 5) o100 endsub ---- See the <> & <> sections for more information. .O- Call 'O- Call' takes up to 30 optional arguments, which are passed to the subroutine as '#1', '#2' , ..., #N. Parameters from #N+1 to #30 have the same value as in the calling context. On return from the subroutine, the values of parameters #1 through #30 (regardless of the number of arguments) will be restored to the values they had before the call. Parameters #1 - #30 are local to the subroutine. Because '1 2 3' is parsed as the number 123, the parameters must be enclosed in square brackets. The following calls a subroutine with 3 arguments: .O- Call Example ---- o200 call [1] [2] [3] ---- Subroutine bodies may not be nested. They may only be called after they are defined. They may be called from other functions, and may call themselves recursively if it makes sense to do so. The maximum subroutine nesting level is 10. Subroutines do not have 'return values', but they may change the value of parameters above #30 and those changes will be visible to the calling code. Subroutines may also change the value of global named parameters. == Looping[[sec:looping]](((Looping)))(((do)))(((while)))(((endwhile)))(((break)))(((continue))) The 'while loop' has two structures: 'while/endwhile', and 'do/while'. In each case, the loop is exited when the 'while' condition evaluates to false. The difference is when the test condition is done. The 'do/while' loop runs the code in the loop then checks the test condition. The 'while/endwhile' loop does the test first. .While Endwhile Example ---- (draw a sawtooth shape) G0 X1 Y0 (move to start position) #1 = 1 (assign parameter #1 the value of 0) F25 (set a feed rate) o101 while [#1 LT 10] G1 X0 G1 Y[#1/10] X1 #1 = [#1+1] (increment the test counter) o101 endwhile M2 (end program) ---- .Do While Example ---- #1 = 0 (assign parameter #1 the value of 0) o100 do o110 if [#1 EQ 2] #1 = 3 (assign the value of 3 to parameter #1) o100 continue (skip to start of loop) o110 endif (some code here) #1 = [#1 + 1] (increment the test counter) o100 while [#1 GT 3] ---- Inside a while loop, 'O- break' immediately exits the loop, and 'O- continue' immediately skips to the next evaluation of the 'while' condition. If it is still true, the loop begins again at the top. If it is false, it exits the loop. == Conditional[[sec:conditional]] (((Conditional: if, elseif, else, endif)))(((if)))(((else)))(((elseif)))(((endif))) The 'if' conditional consists of a group of statements with the same 'o' number that start with 'if' and end with 'endif'. Optional 'elseif' and 'else' conditions may be between the starting 'if' and the ending 'endif'. If the 'if' conditional evaluates to true then the group of statements following the 'if' up to the next conditional line are executed. If the 'if' conditional evaluates to false then the 'elseif' conditions are evaluated in order until one evaluates to true. If the 'elseif' condition is true then the statements following the 'elseif' up to the next conditional line are executed. If none of the 'if' or 'elseif' conditions evaluate to true then the statements following the 'else' are executed. When a condition is evaluated to true no more conditions are evaluated in the group. .If Endif Example ---- o101 if [#31 EQ 3] (if parameter #31 is equal to 3 set S2000) S2000 o101 endif ---- .If ElseIf Else EndIf Example ---- o102 if [#2 GT 5] (if parameter #2 is greater than 5 set F100) F100 o102 elseif [#2 LT 2] (else if parameter #2 is less than 2 set F200) F200 o102 else (else if parameter #2 is 2 through 5 set F150) F150 o102 endif ---- == Repeat(((Repeat))) The 'repeat' will execute the statements inside of the repeat/endrepeat the specified number of times. The example shows how you might mill a diagonal series of shapes starting at the present position. .Repeat Example ---- (Mill 5 diagonal shapes) G91 (Incremental mode) o103 repeat [5] ... (insert milling code here) G0 X1 Y1 (diagonal move to next position) o103 endrepeat G90 (Absolute mode) ---- == Indirection(((Indirection))) The O-number may be given by a parameter and/or calculation. .Indirection Example ---- o[#101+2] call ---- .Computing values in O-words For more information on computing values see the following sections * <> * <> * <> * <> == Calling Files(((Calling Files))) To call a separate file with a subroutine name the file the same as your call and include a sub and endsub in the file. The file must be in the directory pointed to by 'PROGRAM_PREFIX' or 'SUBROUTINE_PATH' in the ini file. The file name can include *lowercase* letters, numbers, dash, and underscore only. A named subroutine file can contain only a single subroutine definition. .Named File Example ---- o call ---- .Numbered File Example ---- o123 call ---- In the called file you must include the oxxx sub and endsub and the file must be a valid file. .Called File Example ---- (filename myfile.ngc) o sub (code here) o endsub M2 ---- [NOTE] The file names are lowercase letters only so 'o' is converted to 'o' by the interpreter. // vim: set syntax=asciidoc: