GCC Code Coverage Report
Directory: emc/rs274ngc/ Exec Total Coverage
File: emc/rs274ngc/interp_cycles.cc Lines: 188 721 26.1 %
Date: 2016-10-27 Branches: 127 1502 8.5 %

Line Exec Source
1
/********************************************************************
2
* Description: interp_cycles.cc
3
*
4
*   The bulk of the functions here control how canned cycles are
5
*   interpreted.
6
*
7
* Author:
8
* License: GPL Version 2
9
* System: Linux
10
*
11
* Copyright (c) 2004 All rights reserved.
12
*
13
********************************************************************/
14
#include <unistd.h>
15
#include <stdio.h>
16
#include <stdlib.h>
17
#include <math.h>
18
#include <string.h>
19
#include <ctype.h>
20
#include <sys/types.h>
21
#include <sys/stat.h>
22
#include "rs274ngc.hh"
23
#include "rs274ngc_return.hh"
24
#include "interp_internal.hh"
25
#include "rs274ngc_interp.hh"
26
27
/****************************************************************************/
28
29
/*! convert_cycle_g81
30
31
Returned Value: int (INTERP_OK)
32
33
Side effects: See below
34
35
Called by:
36
   convert_cycle_xy
37
   convert_cycle_yz
38
   convert_cycle_zx
39
40
For the XY plane, this implements the following RS274/NGC cycle, which
41
is usually drilling:
42
1. Move the z-axis only at the current feed rate to the specified bottom_z.
43
2. Retract the z-axis at traverse rate to clear_z.
44
45
See [NCMS, page 99].
46
47
CYCLE_MACRO has positioned the tool at (x, y, r, a, b, c) when this starts.
48
49
For the XZ and YZ planes, this makes analogous motions.
50
51
*/
52
53
55
int Interp::convert_cycle_g81(block_pointer block,
54
                              CANON_PLANE plane, //!< selected plane
55
                              double x,  //!< x-value where cycle is executed
56
                              double y,  //!< y-value where cycle is executed
57
                              double clear_z,    //!< z-value of clearance plane
58
                              double bottom_z)   //!< value of z at bottom of cycle
59
{
60
55
    cycle_feed(block, plane, x, y, bottom_z);
61
55
    cycle_traverse(block, plane, x, y, clear_z);
62
63
55
  return INTERP_OK;
64
}
65
66
/****************************************************************************/
67
68
/*! convert_cycle_g82
69
70
Returned Value: int (INTERP_OK)
71
72
Side effects: See below
73
74
Called by:
75
   convert_cycle_xy
76
   convert_cycle_yz
77
   convert_cycle_zx
78
79
For the XY plane, this implements the following RS274/NGC cycle, which
80
is usually drilling:
81
1. Move the z_axis only at the current feed rate to the specified z-value.
82
2. Dwell for the given number of seconds.
83
3. Retract the z-axis at traverse rate to the clear_z.
84
85
CYCLE_MACRO has positioned the tool at (x, y, r, a, b, c) when this starts.
86
87
For the XZ and YZ planes, this makes analogous motions.
88
89
*/
90
91
int Interp::convert_cycle_g82(block_pointer block,
92
                              CANON_PLANE plane, //!< selected plane
93
                              double x,  //!< x-value where cycle is executed
94
                              double y,  //!< y-value where cycle is executed
95
                              double clear_z,    //!< z-value of clearance plane
96
                              double bottom_z,   //!< value of z at bottom of cycle
97
                              double dwell)      //!< dwell time
98
{
99
  cycle_feed(block, plane, x, y, bottom_z);
100
  DWELL(dwell);
101
  cycle_traverse(block, plane, x, y, clear_z);
102
103
  return INTERP_OK;
104
}
105
106
/****************************************************************************/
107
108
/*! convert_cycle_g83
109
110
Returned Value: int (INTERP_OK)
111
112
Side effects: See below
113
114
Called by:
115
   convert_cycle_xy
116
   convert_cycle_yz
117
   convert_cycle_zx
118
119
For the XY plane, this implements the following RS274/NGC cycle,
120
which is usually peck drilling:
121
1. Move the z-axis only at the current feed rate downward by delta or
122
   to the specified bottom_z, whichever is less deep.
123
2. Rapid back out to the R plane.
124
3. Rapid back down to the current hole bottom, backed off a bit.
125
4. Repeat steps 1, 2, and 3 until the specified bottom_z is reached.
126
5. Retract the z-axis at traverse rate to clear_z.
127
128
CYCLE_MACRO has positioned the tool at (x, y, r, a, b, c) when this starts.
129
130
The rapid out and back in causes any long stringers (which are common
131
when drilling in aluminum) to be cut off and clears chips from the
132
hole.
133
134
For the XZ and YZ planes, this makes analogous motions.
135
136
*/
137
138
int Interp::convert_cycle_g83(block_pointer block,
139
                              CANON_PLANE plane, //!< selected plane
140
                              double x,  //!< x-value where cycle is executed
141
                              double y,  //!< y-value where cycle is executed
142
                              double r,  //!< initial z-value
143
                              double clear_z,    //!< z-value of clearance plane
144
                              double bottom_z,   //!< value of z at bottom of cycle
145
                              double delta)      //!< size of z-axis feed increment
146
{
147
  double current_depth;
148
  double rapid_delta;
149
150
  /* Moved the check for negative Q values here as a sign
151
     may be used with user defined M functions
152
     Thanks to Billy Singleton for pointing it out... */
153
  CHKS((delta <= 0.0), NCE_NEGATIVE_OR_ZERO_Q_VALUE_USED);
154
155
  rapid_delta = G83_RAPID_DELTA;
156
  if (_setup.length_units == CANON_UNITS_MM)
157
    rapid_delta = (rapid_delta * 25.4);
158
159
  for (current_depth = (r - delta);
160
       current_depth > bottom_z; current_depth = (current_depth - delta)) {
161
    cycle_feed(block, plane, x, y, current_depth);
162
    cycle_traverse(block, plane, x, y, r);
163
    cycle_traverse(block, plane, x, y, current_depth + rapid_delta);
164
  }
165
  cycle_feed(block, plane, x, y, bottom_z);
166
  cycle_traverse(block, plane, x, y, clear_z);
167
168
  return INTERP_OK;
169
}
170
171
/****************************************************************************/
172
173
/*! convert_cycle_g73
174
175
Returned Value: int (INTERP_OK)
176
177
Side effects: See below
178
179
Called by:
180
   convert_cycle_xy
181
   convert_cycle_yz
182
   convert_cycle_zx
183
184
For the XY plane, this implements the following RS274/NGC cycle,
185
which is usually peck drilling:
186
1. Move the z-axis only at the current feed rate downward by delta or
187
   to the specified bottom_z, whichever is less deep.
188
2. Rapid back out a bit.
189
4. Repeat steps 1, 2, and 3 until the specified bottom_z is reached.
190
5. Retract the z-axis at traverse rate to clear_z.
191
192
CYCLE_MACRO has positioned the tool at (x, y, r, a, b, c) when this starts.
193
194
The rapid out and back in causes any long stringers (which are common
195
when drilling in aluminum) to be cut off and clears chips from the
196
hole.
197
198
For the XZ and YZ planes, this makes analogous motions.
199
200
*/
201
202
int Interp::convert_cycle_g73(block_pointer block,
203
                              CANON_PLANE plane, //!< selected plane
204
                              double x,  //!< x-value where cycle is executed
205
                              double y,  //!< y-value where cycle is executed
206
                              double r,  //!< initial z-value
207
                              double clear_z,    //!< z-value of clearance plane
208
                              double bottom_z,   //!< value of z at bottom of cycle
209
                              double delta)      //!< size of z-axis feed increment
210
{
211
  double current_depth;
212
  double rapid_delta;
213
214
  /* Moved the check for negative Q values here as a sign
215
     may be used with user defined M functions
216
     Thanks to Billy Singleton for pointing it out... */
217
  CHKS((delta <= 0.0), NCE_NEGATIVE_OR_ZERO_Q_VALUE_USED);
218
219
  rapid_delta = G83_RAPID_DELTA;
220
  if (_setup.length_units == CANON_UNITS_MM)
221
    rapid_delta = (rapid_delta * 25.4);
222
223
  for (current_depth = (r - delta);
224
       current_depth > bottom_z; current_depth = (current_depth - delta)) {
225
    cycle_feed(block, plane, x, y, current_depth);
226
    cycle_traverse(block, plane, x, y, current_depth + rapid_delta);
227
  }
228
  cycle_feed(block, plane, x, y, bottom_z);
229
  cycle_traverse(block, plane, x, y, clear_z);
230
231
  return INTERP_OK;
232
}
233
234
/****************************************************************************/
235
236
/*! convert_cycle_g84
237
238
Returned Value: int
239
   If the spindle is not turning clockwise, this returns
240
     NCE_SPINDLE_NOT_TURNING_CLOCKWISE_IN_G84.
241
   Otherwise, it returns INTERP_OK.
242
243
Side effects: See below
244
245
Called by:
246
   convert_cycle_xy
247
   convert_cycle_yz
248
   convert_cycle_zx
249
250
For the XY plane, this implements the following RS274/NGC cycle,
251
which is right-hand tapping:
252
1. Start speed-feed synchronization.
253
2. Move the z-axis only at the current feed rate to the specified bottom_z.
254
3. Stop the spindle.
255
4. Start the spindle counterclockwise.
256
5. Retract the z-axis at current feed rate to clear_z.
257
6. If speed-feed synch was not on before the cycle started, stop it.
258
7. Stop the spindle.
259
8. Start the spindle clockwise.
260
261
CYCLE_MACRO has positioned the tool at (x, y, r, a, b, c) when this starts.
262
The direction argument must be clockwise.
263
264
For the XZ and YZ planes, this makes analogous motions.
265
266
*/
267
268
int Interp::convert_cycle_g84(block_pointer block,
269
                              CANON_PLANE plane, //!< selected plane
270
                              double x,  //!< x-value where cycle is executed
271
                              double y,  //!< y-value where cycle is executed
272
                              double clear_z,    //!< z-value of clearance plane
273
                              double bottom_z,   //!< value of z at bottom of cycle
274
                              CANON_DIRECTION direction, //!< direction spindle turning at outset
275
                              CANON_SPEED_FEED_MODE mode)        //!< the speed-feed mode at outset
276
{
277
  CHKS((direction != CANON_CLOCKWISE),
278
      NCE_SPINDLE_NOT_TURNING_CLOCKWISE_IN_G84);
279
#if 0
280
  START_SPEED_FEED_SYNCH();
281
  cycle_feed(block, plane, x, y, bottom_z);
282
  STOP_SPINDLE_TURNING();
283
  START_SPINDLE_COUNTERCLOCKWISE();
284
  cycle_feed(block, plane, x, y, clear_z);
285
  if (mode != CANON_SYNCHED)
286
    STOP_SPEED_FEED_SYNCH();
287
  STOP_SPINDLE_TURNING();
288
  START_SPINDLE_CLOCKWISE();
289
#endif
290
291
  return INTERP_OK;
292
}
293
294
/****************************************************************************/
295
296
/*! convert_cycle_g85
297
298
Returned Value: int (INTERP_OK)
299
300
Side effects:
301
   A number of moves are made as described below.
302
303
Called by:
304
   convert_cycle_xy
305
   convert_cycle_yz
306
   convert_cycle_zx
307
308
For the XY plane, this implements the following RS274/NGC cycle,
309
which is usually boring or reaming:
310
1. Move the z-axis only at the current feed rate to the specified z-value.
311
2. Retract the z-axis at the current feed rate to clear_z.
312
313
CYCLE_MACRO has positioned the tool at (x, y, r, ?, ?) when this starts.
314
315
For the XZ and YZ planes, this makes analogous motions.
316
317
*/
318
319
int Interp::convert_cycle_g85(block_pointer block,
320
                              CANON_PLANE plane, //!< selected plane
321
                              double x,  //!< x-value where cycle is executed
322
                              double y,  //!< y-value where cycle is executed
323
                              double r,  // retract plane
324
                              double clear_z,    //!< z-value of clearance plane
325
                              double bottom_z)   //!< value of z at bottom of cycle
326
{
327
  cycle_feed(block, plane, x, y, bottom_z);
328
  cycle_feed(block, plane, x, y, r);
329
  cycle_traverse(block, plane, x, y, clear_z);
330
331
  return INTERP_OK;
332
}
333
334
/****************************************************************************/
335
336
/*! convert_cycle_g86
337
338
Returned Value: int
339
   If the spindle is not turning clockwise or counterclockwise,
340
   this returns NCE_SPINDLE_NOT_TURNING_IN_G86.
341
   Otherwise, it returns INTERP_OK.
342
343
Side effects:
344
   A number of moves are made as described below.
345
346
Called by:
347
   convert_cycle_xy
348
   convert_cycle_yz
349
   convert_cycle_zx
350
351
For the XY plane, this implements the RS274/NGC following cycle,
352
which is usually boring:
353
1. Move the z-axis only at the current feed rate to bottom_z.
354
2. Dwell for the given number of seconds.
355
3. Stop the spindle turning.
356
4. Retract the z-axis at traverse rate to clear_z.
357
5. Restart the spindle in the direction it was going.
358
359
CYCLE_MACRO has positioned the tool at (x, y, r, a, b, c) when this starts.
360
361
For the XZ and YZ planes, this makes analogous motions.
362
363
*/
364
365
int Interp::convert_cycle_g86(block_pointer block,
366
                              CANON_PLANE plane, //!< selected plane
367
                              double x,  //!< x-value where cycle is executed
368
                              double y,  //!< y-value where cycle is executed
369
                              double clear_z,    //!< z-value of clearance plane
370
                              double bottom_z,   //!< value of z at bottom of cycle
371
                              double dwell,      //!< dwell time
372
                              CANON_DIRECTION direction) //!< direction spindle turning at outset
373
{
374
  CHKS(((direction != CANON_CLOCKWISE) &&
375
       (direction != CANON_COUNTERCLOCKWISE)),
376
      NCE_SPINDLE_NOT_TURNING_IN_G86);
377
378
  cycle_feed(block, plane, x, y, bottom_z);
379
  DWELL(dwell);
380
  STOP_SPINDLE_TURNING();
381
  cycle_traverse(block, plane, x, y, clear_z);
382
  if (direction == CANON_CLOCKWISE)
383
    START_SPINDLE_CLOCKWISE();
384
  else
385
    START_SPINDLE_COUNTERCLOCKWISE();
386
387
  return INTERP_OK;
388
}
389
390
/****************************************************************************/
391
392
/*! convert_cycle_g87
393
394
Returned Value: int
395
   If the spindle is not turning clockwise or counterclockwise,
396
   this returns NCE_SPINDLE_NOT_TURNING_IN_G87.
397
   Otherwise, it returns INTERP_OK.
398
399
Side effects:
400
   A number of moves are made as described below. This cycle is a
401
   modified version of [Monarch, page 5-24] since [NCMS, pages 98 - 100]
402
   gives no clue as to what the cycle is supposed to do. [KT] does not
403
   have a back boring cycle. [Fanuc, page 132] in "Canned cycle II"
404
   describes the G87 cycle as given here, except that the direction of
405
   spindle turning is always clockwise and step 7 below is omitted
406
   in [Fanuc].
407
408
Called by:
409
   convert_cycle_xy
410
   convert_cycle_yz
411
   convert_cycle_zx
412
413
For the XY plane, this implements the following RS274/NGC cycle, which
414
is usually back boring.  The situation is that you have a through hole
415
and you want to counterbore the bottom of hole. To do this you put an
416
L-shaped tool in the spindle with a cutting surface on the UPPER side
417
of its base. You stick it carefully through the hole when it is not
418
spinning and is oriented so it fits through the hole, then you move it
419
so the stem of the L is on the axis of the hole, start the spindle,
420
and feed the tool upward to make the counterbore. Then you get the
421
tool out of the hole.
422
423
1. Move at traverse rate parallel to the XY-plane to the point
424
   with x-value offset_x and y-value offset_y.
425
2. Stop the spindle in a specific orientation.
426
3. Move the z-axis only at traverse rate downward to the bottom_z.
427
4. Move at traverse rate parallel to the XY-plane to the x,y location.
428
5. Start the spindle in the direction it was going before.
429
6. Move the z-axis only at the given feed rate upward to the middle_z.
430
7. Move the z-axis only at the given feed rate back down to bottom_z.
431
8. Stop the spindle in the same orientation as before.
432
9. Move at traverse rate parallel to the XY-plane to the point
433
   with x-value offset_x and y-value offset_y.
434
10. Move the z-axis only at traverse rate to the clear z value.
435
11. Move at traverse rate parallel to the XY-plane to the specified x,y
436
    location.
437
12. Restart the spindle in the direction it was going before.
438
439
CYCLE_MACRO has positioned the tool at (x, y, r, a, b, c) before this starts.
440
441
It might be useful to add a check that clear_z > middle_z > bottom_z.
442
Without the check, however, this can be used to counterbore a hole in
443
material that can only be accessed through a hole in material above it.
444
445
For the XZ and YZ planes, this makes analogous motions.
446
447
*/
448
449
int Interp::convert_cycle_g87(block_pointer block,
450
                              CANON_PLANE plane, //!< selected plane
451
                              double x,  //!< x-value where cycle is executed
452
                              double offset_x,   //!< x-axis offset position
453
                              double y,  //!< y-value where cycle is executed
454
                              double offset_y,   //!< y-axis offset position
455
                              double r,  //!< z_value of r_plane
456
                              double clear_z,    //!< z-value of clearance plane
457
                              double middle_z,   //!< z-value of top of back bore
458
                              double bottom_z,   //!< value of z at bottom of cycle
459
                              CANON_DIRECTION direction) //!< direction spindle turning at outset
460
{
461
  CHKS(((direction != CANON_CLOCKWISE) &&
462
       (direction != CANON_COUNTERCLOCKWISE)),
463
      NCE_SPINDLE_NOT_TURNING_IN_G87);
464
465
  cycle_traverse(block, plane, offset_x, offset_y, r);
466
  STOP_SPINDLE_TURNING();
467
  ORIENT_SPINDLE(0.0, direction);
468
  cycle_traverse(block, plane, offset_x, offset_y, bottom_z);
469
  cycle_traverse(block, plane, x, y, bottom_z);
470
  if (direction == CANON_CLOCKWISE)
471
    START_SPINDLE_CLOCKWISE();
472
  else
473
    START_SPINDLE_COUNTERCLOCKWISE();
474
  cycle_feed(block, plane, x, y, middle_z);
475
  cycle_feed(block, plane, x, y, bottom_z);
476
  STOP_SPINDLE_TURNING();
477
  ORIENT_SPINDLE(0.0, direction);
478
  cycle_traverse(block, plane, offset_x, offset_y, bottom_z);
479
  cycle_traverse(block, plane, offset_x, offset_y, clear_z);
480
  cycle_traverse(block, plane, x, y, clear_z);
481
  if (direction == CANON_CLOCKWISE)
482
    START_SPINDLE_CLOCKWISE();
483
  else
484
    START_SPINDLE_COUNTERCLOCKWISE();
485
486
  return INTERP_OK;
487
}
488
489
/****************************************************************************/
490
491
/*! convert_cycle_g88
492
493
Returned Value: int
494
   If the spindle is not turning clockwise or counterclockwise, this
495
   returns NCE_SPINDLE_NOT_TURNING_IN_G88.
496
   Otherwise, it returns INTERP_OK.
497
498
Side effects: See below
499
500
Called by:
501
   convert_cycle_xy
502
   convert_cycle_yz
503
   convert_cycle_zx
504
505
For the XY plane, this implements the following RS274/NGC cycle,
506
which is usually boring:
507
1. Move the z-axis only at the current feed rate to the specified z-value.
508
2. Dwell for the given number of seconds.
509
3. Stop the spindle turning.
510
4. Stop the program so the operator can retract the spindle manually.
511
5. Restart the spindle.
512
513
CYCLE_MACRO has positioned the tool at (x, y, r, a, b, c) when this starts.
514
515
For the XZ and YZ planes, this makes analogous motions.
516
517
*/
518
519
int Interp::convert_cycle_g88(block_pointer block,
520
                              CANON_PLANE plane, //!< selected plane
521
                              double x,  //!< x-value where cycle is executed
522
                              double y,  //!< y-value where cycle is executed
523
                              double bottom_z,   //!< value of z at bottom of cycle
524
                              double dwell,      //!< dwell time
525
                              CANON_DIRECTION direction) //!< direction spindle turning at outset
526
{
527
  CHKS(((direction != CANON_CLOCKWISE) &&
528
       (direction != CANON_COUNTERCLOCKWISE)),
529
      NCE_SPINDLE_NOT_TURNING_IN_G88);
530
531
  cycle_feed(block, plane, x, y, bottom_z);
532
  DWELL(dwell);
533
  STOP_SPINDLE_TURNING();
534
  PROGRAM_STOP();               /* operator retracts the spindle here */
535
  if (direction == CANON_CLOCKWISE)
536
    START_SPINDLE_CLOCKWISE();
537
  else
538
    START_SPINDLE_COUNTERCLOCKWISE();
539
540
  return INTERP_OK;
541
}
542
543
/****************************************************************************/
544
545
/*! convert_cycle_g89
546
547
Returned Value: int (INTERP_OK)
548
549
Side effects: See below
550
551
Called by:
552
   convert_cycle_xy
553
   convert_cycle_yz
554
   convert_cycle_zx
555
556
This implements the following RS274/NGC cycle, which is intended for boring:
557
1. Move the z-axis only at the current feed rate to the specified z-value.
558
2. Dwell for the given number of seconds.
559
3. Retract the z-axis at the current feed rate to clear_z.
560
561
CYCLE_MACRO has positioned the tool at (x, y, r, a, b, c) when this starts.
562
563
For the XZ and YZ planes, this makes analogous motions.
564
565
*/
566
567
int Interp::convert_cycle_g89(block_pointer block,
568
                              CANON_PLANE plane, //!< selected plane
569
                              double x,  //!< x-value where cycle is executed
570
                              double y,  //!< y-value where cycle is executed
571
                              double clear_z,    //!< z-value of clearance plane
572
                              double bottom_z,   //!< value of z at bottom of cycle
573
                              double dwell)      //!< dwell time
574
{
575
  cycle_feed(block, plane, x, y, bottom_z);
576
  DWELL(dwell);
577
  cycle_feed(block, plane, x, y, clear_z);
578
579
  return INTERP_OK;
580
}
581
582
static const char* plane_name(CANON_PLANE p) {
583
  switch(p) {
584
    case CANON_PLANE_XY: return "XY";
585
    case CANON_PLANE_YZ: return "YZ";
586
    case CANON_PLANE_XZ: return "XZ";
587
    case CANON_PLANE_UV: return "UV";
588
    case CANON_PLANE_VW: return "VW";
589
    case CANON_PLANE_UW: return "UW";
590
    default:             return "invalid";
591
  }
592
}
593
594
/****************************************************************************/
595
596
/*! convert_cycle
597
598
Returned Value: int
599
   If any of the specific functions called returns an error code,
600
   this returns that code.
601
   If any of the following errors occur, this returns the error code shown.
602
   Otherwise, it returns INTERP_OK.
603
   1. The r-value is not given the first time this code is called after
604
      some other motion mode has been in effect:
605
      NCE_R_CLEARANCE_PLANE_UNSPECIFIED_IN_CYCLE
606
   2. The l number is zero: NCE_CANNOT_DO_ZERO_REPEATS_OF_CYCLE
607
   3. The currently selected plane in not XY, YZ, or XZ.
608
      NCE_BUG_PLANE_NOT_XY_YZ_OR_XZ
609
610
Side effects:
611
   A number of moves are made to execute a canned cycle. The current
612
   position is reset. The values of the cycle attributes in the settings
613
   may be reset.
614
615
Called by: convert_motion
616
617
This function makes a couple checks and then calls one of three
618
functions, according to which plane is currently selected.
619
620
See the documentation of convert_cycle_xy for most of the details.
621
622
*/
623
624
37
int Interp::convert_cycle(int motion,    //!< a g-code between G_81 and G_89, a canned cycle
625
                         block_pointer block,   //!< pointer to a block of RS274 instructions
626
                         setup_pointer settings)        //!< pointer to machine settings
627
{
628
  CANON_PLANE plane;
629
630
37
  CHKS((settings->feed_rate == 0.0), _("Cannot feed with zero feed rate"));
631
37
  CHKS((settings->feed_mode == INVERSE_TIME), _("Cannot use inverse time feed with canned cycles"));
632
37
  CHKS((settings->cutter_comp_side), _("Cannot use canned cycles with cutter compensation on"));
633
634
37
  plane = settings->plane;
635
37
  if (!block->r_flag) {
636
    if (settings->motion_mode == motion)
637
      block->r_number = settings->cycle_r;
638
    else
639
      ERS(NCE_R_CLEARANCE_PLANE_UNSPECIFIED_IN_CYCLE);
640
  }
641
642
37
  CHKS((block->l_number == 0), NCE_CANNOT_DO_ZERO_REPEATS_OF_CYCLE);
643
37
  if (block->l_number == -1)
644
19
    block->l_number = 1;
645
646
37
  switch(plane) {
647
  case CANON_PLANE_XY:
648
  case CANON_PLANE_XZ:
649
  case CANON_PLANE_YZ:
650
37
    CHKS(block->u_flag, "Cannot put a U in a canned cycle in the %s plane",
651
	plane_name(settings->plane));
652
37
    CHKS(block->v_flag, "Cannot put a V in a canned cycle in the %s plane",
653
	plane_name(settings->plane));
654
37
    CHKS(block->w_flag, "Cannot put a W in a canned cycle in the %s plane",
655
	plane_name(settings->plane));
656
    break;
657
658
  case CANON_PLANE_UV:
659
  case CANON_PLANE_VW:
660
  case CANON_PLANE_UW:
661
    CHKS(block->x_flag, "Cannot put an X in a canned cycle in the %s plane",
662
	plane_name(settings->plane));
663
    CHKS(block->y_flag, "Cannot put a Y in a canned cycle in the %s plane",
664
	plane_name(settings->plane));
665
    CHKS(block->z_flag, "Cannot put a Z in a canned cycle in the %s plane",
666
	plane_name(settings->plane));
667
  }
668
669
37
  if (plane == CANON_PLANE_XY) {
670
13
    CHP(convert_cycle_xy(motion, block, settings));
671
24
  } else if (plane == CANON_PLANE_YZ) {
672
12
    CHP(convert_cycle_yz(motion, block, settings));
673
12
  } else if (plane == CANON_PLANE_XZ) {
674
12
    CHP(convert_cycle_zx(motion, block, settings));
675
  } else if (plane == CANON_PLANE_UV) {
676
    CHP(convert_cycle_uv(motion, block, settings));
677
  } else if (plane == CANON_PLANE_VW) {
678
    CHP(convert_cycle_vw(motion, block, settings));
679
  } else if (plane == CANON_PLANE_UW) {
680
    CHP(convert_cycle_wu(motion, block, settings));
681
  } else
682
    ERS(NCE_BUG_PLANE_NOT_XY_YZ_OR_XZ);
683
684
37
  settings->cycle_l = block->l_number;
685
37
  settings->cycle_r = block->r_number;
686
37
  settings->motion_mode = motion;
687
37
  return INTERP_OK;
688
}
689
690
/****************************************************************************/
691
692
/*! convert_cycle_xy
693
694
Returned Value: int
695
   If any of the specific functions called returns an error code,
696
   this returns that code.
697
   If any of the following errors occur, this returns the error code shown.
698
   Otherwise, it returns INTERP_OK.
699
   1. The z-value is not given the first time this code is called after
700
      some other motion mode has been in effect:
701
      NCE_Z_VALUE_UNSPECIFIED_IN_XY_PLANE_CANNED_CYCLE
702
   2. The r clearance plane is below the bottom_z:
703
      NCE_R_LESS_THAN_Z_IN_CYCLE_IN_XY_PLANE
704
   3. the distance mode is neither absolute or incremental:
705
      NCE_BUG_DISTANCE_MODE_NOT_G90_OR_G91
706
   4. G82, G86, G88, or G89 is called when it is not already in effect,
707
      and no p number is in the block:
708
      NCE_DWELL_TIME_P_WORD_MISSING_WITH_G82
709
      NCE_DWELL_TIME_P_WORD_MISSING_WITH_G86
710
      NCE_DWELL_TIME_P_WORD_MISSING_WITH_G88
711
      NCE_DWELL_TIME_P_WORD_MISSING_WITH_G89
712
   5. G83 is called when it is not already in effect,
713
      and no q number is in the block: NCE_Q_WORD_MISSING_WITH_G83_OR_M66
714
   6. G87 is called when it is not already in effect,
715
      and any of the i number, j number, or k number is missing:
716
      NCE_I_WORD_MISSING_WITH_G87
717
      NCE_J_WORD_MISSING_WITH_G87
718
      NCE_K_WORD_MISSING_WITH_G87
719
   7. the G code is not between G_81 and G_89.
720
      NCE_BUG_FUNCTION_SHOULD_NOT_HAVE_BEEN_CALLED
721
722
Side effects:
723
   A number of moves are made to execute the g-code
724
725
Called by: convert_cycle
726
727
The function does not require that any of x,y,z, or r be specified in
728
the block, except that if the last motion mode command executed was
729
not the same as this one, the r-value and z-value must be specified.
730
731
This function is handling the repeat feature of RS274/NGC, wherein
732
the L word represents the number of repeats [NCMS, page 99]. We are
733
not allowing L=0, contrary to the manual. We are allowing L > 1
734
in absolute distance mode to mean "do the same thing in the same
735
place several times", as provided in the manual, although this seems
736
abnormal.
737
738
In incremental distance mode, x, y, and r values are treated as
739
increments to the current position and z as an increment from r.  In
740
absolute distance mode, x, y, r, and z are absolute. In g87, i and j
741
will always be increments, regardless of the distance mode setting, as
742
implied in [NCMS, page 98], but k (z-value of top of counterbore) will
743
be an absolute z-value in absolute distance mode, and an increment
744
(from bottom z) in incremental distance mode.
745
746
If the r position of a cycle is above the current_z position, this
747
retracts the z-axis to the r position before moving parallel to the
748
XY plane.
749
750
In the code for this function, there is a nearly identical "for" loop
751
in every case of the switch. The loop is the done with a compiler
752
macro, "CYCLE_MACRO" so that the code is easy to read, automatically
753
kept identical from case to case and, and much shorter than it would
754
be without the macro. The loop could be put outside the switch, but
755
then the switch would run every time around the loop, not just once,
756
as it does here. The loop could also be placed in the called
757
functions, but then it would not be clear that all the loops are the
758
same, and it would be hard to keep them the same when the code is
759
modified.  The macro would be very awkward as a regular function
760
because it would have to be passed all of the arguments used by any of
761
the specific cycles, and, if another switch in the function is to be
762
avoided, it would have to passed a function pointer, but the different
763
cycle functions have different arguments so the type of the pointer
764
could not be declared unless the cycle functions were re-written to
765
take the same arguments (in which case most of them would have several
766
unused arguments).
767
768
The motions within the CYCLE_MACRO (but outside a specific cycle) are
769
a straight traverse parallel to the selected plane to the given
770
position in the plane and a straight traverse of the third axis only
771
(if needed) to the r position.
772
773
The CYCLE_MACRO is defined here but is also used in convert_cycle_yz
774
and convert_cycle_zx. The variables aa, bb, and cc are used in
775
CYCLE_MACRO and in the other two functions just mentioned. Those
776
variables represent the first axis of the selected plane, the second
777
axis of the selected plane, and third axis which is perpendicular to
778
the selected plane.  In this function aa represents x, bb represents
779
y, and cc represents z. This usage makes it possible to have only one
780
version of each of the cycle functions.  The cycle_traverse and
781
cycle_feed functions help accomplish this.
782
783
The height of the retract move at the end of each repeat of a cycle is
784
determined by the setting of the retract_mode: either to the r
785
position (if the retract_mode is R_PLANE) or to the original
786
z-position (if that is above the r position and the retract_mode is
787
not R_PLANE). This is a slight departure from [NCMS, page 98], which
788
does not require checking that the original z-position is above r.
789
790
The rotary axes may not move during a canned cycle.
791
792
*/
793
794
13
int Interp::convert_cycle_xy(int motion, //!< a g-code between G_81 and G_89, a canned cycle
795
                            block_pointer block,        //!< pointer to a block of RS274 instructions
796
                            setup_pointer settings)     //!< pointer to machine settings
797
{
798
  double aa;
799
13
  double aa_increment=0.;
800
  double bb;
801
13
  double bb_increment=0.;
802
  double cc;
803
  double clear_cc;
804
  double i;
805
  double j;
806
  double k;
807
  double old_cc;
808
13
  double radius_increment = 0.;
809
13
  double theta_increment = 0.;
810
  CANON_PLANE plane;
811
  double r;
812
  int repeat;
813
  CANON_MOTION_MODE save_mode;
814
  double save_tolerance;
815
13
  double current_cc = settings->current_z;
816
817
13
  plane = CANON_PLANE_XY;
818
13
  if (settings->motion_mode != motion) {
819
9
    CHKS((!block->z_flag),
820
        _readers[(int)'z']? NCE_Z_VALUE_UNSPECIFIED_IN_XY_PLANE_CANNED_CYCLE: _("G17 canned cycle is not possible on a machine without Z axis"));
821
  }
822
  block->z_number =
823
13
    block->z_flag ? block->z_number : settings->cycle_cc;
824
13
  if(settings->cycle_il_flag) {
825
4
      old_cc = settings->cycle_il;
826
  } else {
827
9
      old_cc = settings->cycle_il = current_cc;
828
9
      settings->cycle_il_flag = true;
829
  }
830
831
13
  if (settings->distance_mode == MODE_ABSOLUTE) {
832
    double radius, theta;
833
7
    aa_increment = 0.0;
834
7
    bb_increment = 0.0;
835
7
    r = block->r_number;
836
7
    cc = block->z_number;
837
7
    if(block->radius_flag)
838
        radius = block->radius;
839
    else
840
7
        radius = hypot(settings->current_y, settings->current_x);
841
7
    if(block->theta_flag)
842
        theta = D2R(block->theta);
843
    else
844
7
        theta = atan2(settings->current_y, settings->current_x);
845
7
    if(block->radius_flag || block->theta_flag) {
846
        aa = radius * cos(theta);
847
        bb = radius * sin(theta);
848
    } else {
849
7
        aa = block->x_flag ? block->x_number : settings->current_x;
850
7
        bb = block->y_flag ? block->y_number : settings->current_y;
851
    }
852
6
  } else if (settings->distance_mode == MODE_INCREMENTAL) {
853
6
    if (block->x_flag) aa_increment = block->x_number;
854
6
    if (block->y_flag) bb_increment = block->y_number;
855
6
    if (block->radius_flag) radius_increment = block->radius;
856
6
    if (block->theta_flag) theta_increment = D2R(block->theta);
857
6
    r = (block->r_number + old_cc);
858
6
    cc = (r + block->z_number); /* [NCMS, page 98] */
859
6
    aa = settings->current_x;
860
6
    bb = settings->current_y;
861
  } else
862
    ERS(NCE_BUG_DISTANCE_MODE_NOT_G90_OR_G91);
863
13
  CHKS((r < cc), NCE_R_LESS_THAN_Z_IN_CYCLE_IN_XY_PLANE);
864
865
  // First motion of a canned cycle (maybe): if we're below the R plane,
866
  // rapid straight up to the R plane.
867
13
  if (old_cc < r) {
868
    STRAIGHT_TRAVERSE(block->line_number, settings->current_x, settings->current_y, r,
869
                      settings->AA_current, settings->BB_current, settings->CC_current,
870
8
                      settings->u_current, settings->v_current, settings->w_current);
871
8
    old_cc = r;
872
8
    current_cc = old_cc;
873
  }
874
13
  clear_cc = (settings->retract_mode == R_PLANE) ? r : old_cc;
875
876
13
  save_mode = GET_EXTERNAL_MOTION_CONTROL_MODE();
877
13
  save_tolerance = GET_EXTERNAL_MOTION_CONTROL_TOLERANCE();
878
13
  if (save_mode != CANON_EXACT_PATH)
879
13
    SET_MOTION_CONTROL_MODE(CANON_EXACT_PATH, 0);
880
881
13
  switch (motion) {
882
  case G_81:
883
13
      CYCLE_MACRO(convert_cycle_g81(block, CANON_PLANE_XY, aa, bb, clear_cc, cc))
884
      break;
885
  case G_82:
886
    CHKS(((settings->motion_mode != G_82) && (block->p_number == -1.0)),
887
        NCE_DWELL_TIME_P_WORD_MISSING_WITH_G82);
888
    block->p_number =
889
      block->p_number == -1.0 ? settings->cycle_p : block->p_number;
890
    CYCLE_MACRO(convert_cycle_g82(block, CANON_PLANE_XY, aa, bb, clear_cc, cc,
891
                                  block->p_number))
892
      settings->cycle_p = block->p_number;
893
    break;
894
  case G_73:
895
    CHKS(((settings->motion_mode != G_73) && (block->q_number == -1.0)),
896
        NCE_Q_WORD_MISSING_WITH_G73);
897
    block->q_number =
898
      block->q_number == -1.0 ? settings->cycle_q : block->q_number;
899
    CYCLE_MACRO(convert_cycle_g73(block, CANON_PLANE_XY, aa, bb, r, clear_cc, cc,
900
                                  block->q_number))
901
      settings->cycle_q = block->q_number;
902
    break;
903
  case G_83:
904
    CHKS(((settings->motion_mode != G_83) && (block->q_number == -1.0)),
905
        NCE_Q_WORD_MISSING_WITH_G83);
906
    block->q_number =
907
      block->q_number == -1.0 ? settings->cycle_q : block->q_number;
908
    CYCLE_MACRO(convert_cycle_g83(block, CANON_PLANE_XY, aa, bb, r, clear_cc, cc,
909
                                  block->q_number))
910
      settings->cycle_q = block->q_number;
911
    break;
912
  case G_84:
913
      CYCLE_MACRO(convert_cycle_g84(block, CANON_PLANE_XY, aa, bb, clear_cc, cc,
914
                                  settings->spindle_turning,
915
                                  settings->speed_feed_mode)) break;
916
  case G_85:
917
      CYCLE_MACRO(convert_cycle_g85(block, CANON_PLANE_XY, aa, bb, r, clear_cc, cc))
918
      break;
919
  case G_86:
920
    CHKS(((settings->motion_mode != G_86) && (block->p_number == -1.0)),
921
        NCE_DWELL_TIME_P_WORD_MISSING_WITH_G86);
922
    block->p_number =
923
      block->p_number == -1.0 ? settings->cycle_p : block->p_number;
924
    CYCLE_MACRO(convert_cycle_g86(block, CANON_PLANE_XY, aa, bb, clear_cc, cc,
925
                                  block->p_number,
926
                                  settings->spindle_turning)) settings->
927
      cycle_p = block->p_number;
928
    break;
929
  case G_87:
930
    if (settings->motion_mode != G_87) {
931
      CHKS((!block->i_flag), NCE_I_WORD_MISSING_WITH_G87);
932
      CHKS((!block->j_flag), NCE_J_WORD_MISSING_WITH_G87);
933
      CHKS((!block->k_flag), NCE_K_WORD_MISSING_WITH_G87);
934
    }
935
    i = block->i_flag ? block->i_number : settings->cycle_i;
936
    j = block->j_flag ? block->j_number : settings->cycle_j;
937
    k = block->k_flag ? block->k_number : settings->cycle_k;
938
    settings->cycle_i = i;
939
    settings->cycle_j = j;
940
    settings->cycle_k = k;
941
    if (settings->distance_mode == MODE_INCREMENTAL) {
942
      k = (cc + k);             /* k always absolute in function call below */
943
    }
944
    CYCLE_MACRO(convert_cycle_g87(block, CANON_PLANE_XY, aa, (aa + i), bb,
945
                                  (bb + j), r, clear_cc, k, cc,
946
                                  settings->spindle_turning)) break;
947
  case G_88:
948
    CHKS(((settings->motion_mode != G_88) && (block->p_number == -1.0)),
949
        NCE_DWELL_TIME_P_WORD_MISSING_WITH_G88);
950
    block->p_number =
951
      block->p_number == -1.0 ? settings->cycle_p : block->p_number;
952
    CYCLE_MACRO(convert_cycle_g88(block, CANON_PLANE_XY, aa, bb, cc,
953
                                  block->p_number,
954
                                  settings->spindle_turning)) settings->
955
      cycle_p = block->p_number;
956
    break;
957
958
  case G_89:
959
    CHKS(((settings->motion_mode != G_89) && (block->p_number == -1.0)),
960
        NCE_DWELL_TIME_P_WORD_MISSING_WITH_G89);
961
    block->p_number =
962
      block->p_number == -1.0 ? settings->cycle_p : block->p_number;
963
    CYCLE_MACRO(convert_cycle_g89(block, CANON_PLANE_XY, aa, bb, clear_cc, cc,
964
                                  block->p_number))
965
      settings->cycle_p = block->p_number;
966
    break;
967
  default:
968
    ERS(NCE_BUG_FUNCTION_SHOULD_NOT_HAVE_BEEN_CALLED);
969
  }
970
13
  settings->current_x = aa;     /* CYCLE_MACRO updates aa and bb */
971
13
  settings->current_y = bb;
972
13
  settings->current_z = clear_cc;
973
13
  settings->cycle_cc = block->z_number;
974
975
13
  if (save_mode != CANON_EXACT_PATH)
976
13
    SET_MOTION_CONTROL_MODE(save_mode, save_tolerance);
977
978
  return INTERP_OK;
979
}
980
981
982
983
int Interp::convert_cycle_uv(int motion, //!< a g-code between G_81 and G_89, a canned cycle
984
                            block_pointer block,        //!< pointer to a block of RS274 instructions
985
                            setup_pointer settings)     //!< pointer to machine settings
986
{
987
  double aa;
988
  double aa_increment=0.;
989
  double bb;
990
  double bb_increment=0.;
991
  double cc;
992
  double clear_cc;
993
  double i;
994
  double j;
995
  double k;
996
  double old_cc;
997
  double radius_increment = 0.;
998
  double theta_increment = 0.;
999
  CANON_PLANE plane;
1000
  double r;
1001
  int repeat;
1002
  CANON_MOTION_MODE save_mode;
1003
  double save_tolerance;
1004
  double current_cc = settings->w_current;
1005
1006
  plane = CANON_PLANE_UV;
1007
  if (settings->motion_mode != motion) {
1008
    CHKS((!block->w_flag),
1009
        _readers[(int)'w']? NCE_W_VALUE_UNSPECIFIED_IN_UV_PLANE_CANNED_CYCLE: _("G17.1 canned cycle is not possible on a machine without W axis"));
1010
  }
1011
  block->w_number =
1012
    block->w_flag ? block->w_number : settings->cycle_cc;
1013
  if(settings->cycle_il_flag) {
1014
      old_cc = settings->cycle_il;
1015
  } else {
1016
      old_cc = settings->cycle_il = current_cc;
1017
      settings->cycle_il_flag = true;
1018
  }
1019
1020
  if (settings->distance_mode == MODE_ABSOLUTE) {
1021
    aa_increment = 0.0;
1022
    bb_increment = 0.0;
1023
    r = block->r_number;
1024
    cc = block->w_number;
1025
    aa = block->u_flag ? block->u_number : settings->u_current;
1026
    bb = block->v_flag ? block->v_number : settings->v_current;
1027
  } else if (settings->distance_mode == MODE_INCREMENTAL) {
1028
    if (block->u_flag) aa_increment = block->u_number;
1029
    if (block->v_flag) bb_increment = block->v_number;
1030
    r = (block->r_number + old_cc);
1031
    cc = (r + block->w_number); /* [NCMS, page 98] */
1032
    aa = settings->u_current;
1033
    bb = settings->v_current;
1034
  } else
1035
    ERS(NCE_BUG_DISTANCE_MODE_NOT_G90_OR_G91);
1036
  CHKS((r < cc), NCE_R_LESS_THAN_W_IN_CYCLE_IN_UV_PLANE);
1037
1038
  if (old_cc < r) {
1039
    STRAIGHT_TRAVERSE(block->line_number, settings->current_x, settings->current_y, settings->current_z,
1040
                      settings->AA_current, settings->BB_current, settings->CC_current,
1041
                      settings->u_current, settings->v_current, r);
1042
    old_cc = r;
1043
    current_cc = old_cc;
1044
  }
1045
  clear_cc = (settings->retract_mode == R_PLANE) ? r : old_cc;
1046
1047
  save_mode = GET_EXTERNAL_MOTION_CONTROL_MODE();
1048
  save_tolerance = GET_EXTERNAL_MOTION_CONTROL_TOLERANCE();
1049
  if (save_mode != CANON_EXACT_PATH)
1050
    SET_MOTION_CONTROL_MODE(CANON_EXACT_PATH, 0);
1051
1052
  switch (motion) {
1053
  case G_81:
1054
      CYCLE_MACRO(convert_cycle_g81(block, CANON_PLANE_UV, aa, bb, clear_cc, cc))
1055
      break;
1056
  case G_82:
1057
    CHKS(((settings->motion_mode != G_82) && (block->p_number == -1.0)),
1058
        NCE_DWELL_TIME_P_WORD_MISSING_WITH_G82);
1059
    block->p_number =
1060
      block->p_number == -1.0 ? settings->cycle_p : block->p_number;
1061
    CYCLE_MACRO(convert_cycle_g82(block, CANON_PLANE_UV, aa, bb, clear_cc, cc,
1062
                                  block->p_number))
1063
      settings->cycle_p = block->p_number;
1064
    break;
1065
  case G_83:
1066
    CHKS(((settings->motion_mode != G_83) && (block->q_number == -1.0)),
1067
        NCE_Q_WORD_MISSING_WITH_G83);
1068
    block->q_number =
1069
      block->q_number == -1.0 ? settings->cycle_q : block->q_number;
1070
    CYCLE_MACRO(convert_cycle_g83(block, CANON_PLANE_UV, aa, bb, r, clear_cc, cc,
1071
                                  block->q_number))
1072
      settings->cycle_q = block->q_number;
1073
    break;
1074
  case G_73:
1075
    CHKS(((settings->motion_mode != G_73) && (block->q_number == -1.0)),
1076
        NCE_Q_WORD_MISSING_WITH_G73);
1077
    block->q_number =
1078
      block->q_number == -1.0 ? settings->cycle_q : block->q_number;
1079
    CYCLE_MACRO(convert_cycle_g73(block, CANON_PLANE_UV, aa, bb, r, clear_cc, cc,
1080
                                  block->q_number))
1081
      settings->cycle_q = block->q_number;
1082
    break;
1083
  case G_84:
1084
    CYCLE_MACRO(convert_cycle_g84(block, CANON_PLANE_UV, aa, bb, clear_cc, cc,
1085
                                  settings->spindle_turning,
1086
                                  settings->speed_feed_mode)) break;
1087
  case G_85:
1088
    CYCLE_MACRO(convert_cycle_g85(block, CANON_PLANE_UV, aa, bb, r, clear_cc, cc))
1089
      break;
1090
  case G_86:
1091
    CHKS(((settings->motion_mode != G_86) && (block->p_number == -1.0)),
1092
        NCE_DWELL_TIME_P_WORD_MISSING_WITH_G86);
1093
    block->p_number =
1094
      block->p_number == -1.0 ? settings->cycle_p : block->p_number;
1095
    CYCLE_MACRO(convert_cycle_g86(block, CANON_PLANE_UV, aa, bb, clear_cc, cc,
1096
                                  block->p_number,
1097
                                  settings->spindle_turning)) settings->
1098
      cycle_p = block->p_number;
1099
    break;
1100
  case G_87:
1101
    if (settings->motion_mode != G_87) {
1102
      CHKS((!block->i_flag), NCE_I_WORD_MISSING_WITH_G87);
1103
      CHKS((!block->j_flag), NCE_J_WORD_MISSING_WITH_G87);
1104
      CHKS((!block->k_flag), NCE_K_WORD_MISSING_WITH_G87);
1105
    }
1106
    i = block->i_flag ? block->i_number : settings->cycle_i;
1107
    j = block->j_flag ? block->j_number : settings->cycle_j;
1108
    k = block->k_flag ? block->k_number : settings->cycle_k;
1109
    settings->cycle_i = i;
1110
    settings->cycle_j = j;
1111
    settings->cycle_k = k;
1112
    if (settings->distance_mode == MODE_INCREMENTAL) {
1113
      k = (cc + k);             /* k always absolute in function call below */
1114
    }
1115
    CYCLE_MACRO(convert_cycle_g87(block, CANON_PLANE_UV, aa, (aa + i), bb,
1116
                                  (bb + j), r, clear_cc, k, cc,
1117
                                  settings->spindle_turning)) break;
1118
  case G_88:
1119
    CHKS(((settings->motion_mode != G_88) && (block->p_number == -1.0)),
1120
        NCE_DWELL_TIME_P_WORD_MISSING_WITH_G88);
1121
    block->p_number =
1122
      block->p_number == -1.0 ? settings->cycle_p : block->p_number;
1123
    CYCLE_MACRO(convert_cycle_g88(block, CANON_PLANE_UV, aa, bb, cc,
1124
                                  block->p_number,
1125
                                  settings->spindle_turning)) settings->
1126
      cycle_p = block->p_number;
1127
    break;
1128
  case G_89:
1129
    CHKS(((settings->motion_mode != G_89) && (block->p_number == -1.0)),
1130
        NCE_DWELL_TIME_P_WORD_MISSING_WITH_G89);
1131
    block->p_number =
1132
      block->p_number == -1.0 ? settings->cycle_p : block->p_number;
1133
    CYCLE_MACRO(convert_cycle_g89(block, CANON_PLANE_UV, aa, bb, clear_cc, cc,
1134
                                  block->p_number))
1135
      settings->cycle_p = block->p_number;
1136
    break;
1137
  default:
1138
    ERS(NCE_BUG_FUNCTION_SHOULD_NOT_HAVE_BEEN_CALLED);
1139
  }
1140
  settings->u_current = aa;     /* CYCLE_MACRO updates aa and bb */
1141
  settings->v_current = bb;
1142
  settings->w_current = clear_cc;
1143
  settings->cycle_cc = block->w_number;
1144
1145
  if (save_mode != CANON_EXACT_PATH)
1146
    SET_MOTION_CONTROL_MODE(save_mode, save_tolerance);
1147
1148
  return INTERP_OK;
1149
}
1150
1151
/****************************************************************************/
1152
1153
/*! convert_cycle_yz
1154
1155
Returned Value: int
1156
   If any of the specific functions called returns an error code,
1157
   this returns that code.
1158
   If any of the following errors occur, this returns the error code shown.
1159
   Otherwise, it returns INTERP_OK.
1160
   1. The x-value is not given the first time this code is called after
1161
      some other motion mode has been in effect:
1162
      NCE_X_VALUE_UNSPECIFIED_IN_YZ_PLANE_CANNED_CYCLE
1163
   2. The r clearance plane is below the bottom_x:
1164
      NCE_R_LESS_THAN_X_IN_CYCLE_IN_YZ_PLANE
1165
   3. the distance mode is neither absolute or incremental:
1166
      NCE_BUG_DISTANCE_MODE_NOT_G90_OR_G91
1167
   4. G82, G86, G88, or G89 is called when it is not already in effect,
1168
      and no p number is in the block:
1169
      NCE_DWELL_TIME_P_WORD_MISSING_WITH_G82
1170
      NCE_DWELL_TIME_P_WORD_MISSING_WITH_G86
1171
      NCE_DWELL_TIME_P_WORD_MISSING_WITH_G88
1172
      NCE_DWELL_TIME_P_WORD_MISSING_WITH_G89
1173
   5. G83 is called when it is not already in effect,
1174
      and no q number is in the block: NCE_Q_WORD_MISSING_WITH_G83
1175
   6. G87 is called when it is not already in effect,
1176
      and any of the i number, j number, or k number is missing:
1177
      NCE_I_WORD_MISSING_WITH_G87
1178
      NCE_J_WORD_MISSING_WITH_G87
1179
      NCE_K_WORD_MISSING_WITH_G87
1180
   7. the G code is not between G_81 and G_89.
1181
      NCE_BUG_FUNCTION_SHOULD_NOT_HAVE_BEEN_CALLED
1182
1183
Side effects:
1184
   A number of moves are made to execute a canned cycle.
1185
1186
Called by: convert_cycle
1187
1188
See the documentation of convert_cycle_xy. This function is entirely
1189
similar. In this function aa represents y, bb represents z, and cc
1190
represents x.
1191
1192
The CYCLE_MACRO is defined just before the convert_cycle_xy function.
1193
1194
Tool length offsets work only when the tool axis is parallel to the
1195
Z-axis, so if this function is used, tool length offsets should be
1196
turned off, and the NC code written to take tool length into account.
1197
1198
*/
1199
1200
12
int Interp::convert_cycle_yz(int motion, //!< a g-code between G_81 and G_89, a canned cycle
1201
                            block_pointer block,        //!< pointer to a block of RS274/NGC instructions
1202
                            setup_pointer settings)     //!< pointer to machine settings
1203
{
1204
  double aa;
1205
12
  double aa_increment=0.;
1206
  double bb;
1207
12
  double bb_increment=0.;
1208
  double cc;
1209
  double clear_cc;
1210
  double i;
1211
  double j;
1212
  double k;
1213
  double old_cc;
1214
12
  double radius_increment = 0.;
1215
12
  double theta_increment = 0.;
1216
  CANON_PLANE plane;
1217
  double r;
1218
  int repeat;
1219
  CANON_MOTION_MODE save_mode;
1220
  double save_tolerance; //save the current tolerance, to restore it lateron
1221
12
  double current_cc = settings->current_x;
1222
1223
12
  plane = CANON_PLANE_YZ;
1224
12
  if (settings->motion_mode != motion) {
1225
8
    CHKS((!block->x_flag),
1226
        _readers[(int)'x']? NCE_X_VALUE_UNSPECIFIED_IN_YZ_PLANE_CANNED_CYCLE: _("G19 canned cycle is not possible on a machine without X axis"));
1227
  }
1228
  block->x_number =
1229
12
    block->x_flag ? block->x_number : settings->cycle_cc;
1230
12
  if(settings->cycle_il_flag) {
1231
4
      old_cc = settings->cycle_il;
1232
  } else {
1233
8
      old_cc = settings->cycle_il = current_cc;
1234
8
      settings->cycle_il_flag = true;
1235
  }
1236
1237
12
  if (settings->distance_mode == MODE_ABSOLUTE) {
1238
6
    aa_increment = 0.0;
1239
6
    bb_increment = 0.0;
1240
6
    r = block->r_number;
1241
6
    cc = block->x_number;
1242
6
    aa = block->y_flag ? block->y_number : settings->current_y;
1243
6
    bb = block->z_flag ? block->z_number : settings->current_z;
1244
6
  } else if (settings->distance_mode == MODE_INCREMENTAL) {
1245
6
    if (block->y_flag) aa_increment = block->y_number;
1246
6
    if (block->z_flag) bb_increment = block->z_number;
1247
6
    r = (block->r_number + old_cc);
1248
6
    cc = (r + block->x_number); /* [NCMS, page 98] */
1249
6
    aa = settings->current_y;
1250
6
    bb = settings->current_z;
1251
  } else
1252
    ERS(NCE_BUG_DISTANCE_MODE_NOT_G90_OR_G91);
1253
12
  CHKS((r < cc), NCE_R_LESS_THAN_X_IN_CYCLE_IN_YZ_PLANE);
1254
1255
12
  if (old_cc < r) {
1256
    STRAIGHT_TRAVERSE(block->line_number, r, settings->current_y, settings->current_z,
1257
                      settings->AA_current, settings->BB_current, settings->CC_current,
1258
8
                      settings->u_current, settings->v_current, settings->w_current);
1259
8
    old_cc = r;
1260
8
    current_cc = old_cc;
1261
  }
1262
12
  clear_cc = (settings->retract_mode == R_PLANE) ? r : old_cc;
1263
1264
12
  save_mode = GET_EXTERNAL_MOTION_CONTROL_MODE();
1265
12
  save_tolerance = GET_EXTERNAL_MOTION_CONTROL_TOLERANCE();
1266
12
  if (save_mode != CANON_EXACT_PATH)
1267
12
    SET_MOTION_CONTROL_MODE(CANON_EXACT_PATH, 0);
1268
1269
12
  switch (motion) {
1270
  case G_81:
1271
12
    CYCLE_MACRO(convert_cycle_g81(block, CANON_PLANE_YZ, aa, bb, clear_cc, cc))
1272
      break;
1273
  case G_82:
1274
    CHKS(((settings->motion_mode != G_82) && (block->p_number == -1.0)),
1275
        NCE_DWELL_TIME_P_WORD_MISSING_WITH_G82);
1276
    block->p_number =
1277
      block->p_number == -1.0 ? settings->cycle_p : block->p_number;
1278
    CYCLE_MACRO(convert_cycle_g82(block, CANON_PLANE_YZ, aa, bb, clear_cc, cc,
1279
                                  block->p_number))
1280
      settings->cycle_p = block->p_number;
1281
    break;
1282
  case G_73:
1283
    CHKS(((settings->motion_mode != G_73) && (block->q_number == -1.0)),
1284
        NCE_Q_WORD_MISSING_WITH_G73);
1285
    block->q_number =
1286
      block->q_number == -1.0 ? settings->cycle_q : block->q_number;
1287
    CYCLE_MACRO(convert_cycle_g73(block, CANON_PLANE_YZ, aa, bb, r, clear_cc, cc,
1288
                                  block->q_number))
1289
      settings->cycle_q = block->q_number;
1290
    break;
1291
  case G_83:
1292
    CHKS(((settings->motion_mode != G_83) && (block->q_number == -1.0)),
1293
        NCE_Q_WORD_MISSING_WITH_G83);
1294
    block->q_number =
1295
      block->q_number == -1.0 ? settings->cycle_q : block->q_number;
1296
    CYCLE_MACRO(convert_cycle_g83(block, CANON_PLANE_YZ, aa, bb, r, clear_cc, cc,
1297
                                  block->q_number))
1298
      settings->cycle_q = block->q_number;
1299
    break;
1300
  case G_84:
1301
    CYCLE_MACRO(convert_cycle_g84(block, CANON_PLANE_YZ, aa, bb, clear_cc, cc,
1302
                                  settings->spindle_turning,
1303
                                  settings->speed_feed_mode)) break;
1304
  case G_85:
1305
    CYCLE_MACRO(convert_cycle_g85(block, CANON_PLANE_YZ, aa, bb, r, clear_cc, cc))
1306
      break;
1307
  case G_86:
1308
    CHKS(((settings->motion_mode != G_86) && (block->p_number == -1.0)),
1309
        NCE_DWELL_TIME_P_WORD_MISSING_WITH_G86);
1310
    block->p_number =
1311
      block->p_number == -1.0 ? settings->cycle_p : block->p_number;
1312
    CYCLE_MACRO(convert_cycle_g86(block, CANON_PLANE_YZ, aa, bb, clear_cc, cc,
1313
                                  block->p_number,
1314
                                  settings->spindle_turning)) settings->
1315
      cycle_p = block->p_number;
1316
    break;
1317
  case G_87:
1318
    if (settings->motion_mode != G_87) {
1319
      CHKS((!block->i_flag), NCE_I_WORD_MISSING_WITH_G87);
1320
      CHKS((!block->j_flag), NCE_J_WORD_MISSING_WITH_G87);
1321
      CHKS((!block->k_flag), NCE_K_WORD_MISSING_WITH_G87);
1322
    }
1323
    i = block->i_flag ? block->i_number : settings->cycle_i;
1324
    j = block->j_flag ? block->j_number : settings->cycle_j;
1325
    k = block->k_flag ? block->k_number : settings->cycle_k;
1326
    settings->cycle_i = i;
1327
    settings->cycle_j = j;
1328
    settings->cycle_k = k;
1329
    if (settings->distance_mode == MODE_INCREMENTAL) {
1330
      i = (cc + i);             /* i always absolute in function call below */
1331
    }
1332
    CYCLE_MACRO(convert_cycle_g87(block, CANON_PLANE_YZ, aa, (aa + j), bb,
1333
                                  (bb + k), r, clear_cc, i, cc,
1334
                                  settings->spindle_turning)) break;
1335
  case G_88:
1336
    CHKS(((settings->motion_mode != G_88) && (block->p_number == -1.0)),
1337
        NCE_DWELL_TIME_P_WORD_MISSING_WITH_G88);
1338
    block->p_number =
1339
      block->p_number == -1.0 ? settings->cycle_p : block->p_number;
1340
    CYCLE_MACRO(convert_cycle_g88(block, CANON_PLANE_YZ, aa, bb, cc,
1341
                                  block->p_number,
1342
                                  settings->spindle_turning)) settings->
1343
      cycle_p = block->p_number;
1344
    break;
1345
  case G_89:
1346
    CHKS(((settings->motion_mode != G_89) && (block->p_number == -1.0)),
1347
        NCE_DWELL_TIME_P_WORD_MISSING_WITH_G89);
1348
    block->p_number =
1349
      block->p_number == -1.0 ? settings->cycle_p : block->p_number;
1350
    CYCLE_MACRO(convert_cycle_g89(block, CANON_PLANE_YZ, aa, bb, clear_cc, cc,
1351
                                  block->p_number))
1352
      settings->cycle_p = block->p_number;
1353
    break;
1354
  default:
1355
    ERS(NCE_BUG_FUNCTION_SHOULD_NOT_HAVE_BEEN_CALLED);
1356
  }
1357
12
  settings->current_y = aa;     /* CYCLE_MACRO updates aa and bb */
1358
12
  settings->current_z = bb;
1359
12
  settings->current_x = clear_cc;
1360
12
  settings->cycle_cc = block->x_number;
1361
1362
12
  if (save_mode != CANON_EXACT_PATH)
1363
12
    SET_MOTION_CONTROL_MODE(save_mode, save_tolerance);
1364
1365
  return INTERP_OK;
1366
}
1367
1368
1369
int Interp::convert_cycle_vw(int motion, //!< a g-code between G_81 and G_89, a canned cycle
1370
                            block_pointer block,        //!< pointer to a block of RS274/NGC instructions
1371
                            setup_pointer settings)     //!< pointer to machine settings
1372
{
1373
  double aa;
1374
  double aa_increment=0.;
1375
  double bb;
1376
  double bb_increment=0.;
1377
  double cc;
1378
  double clear_cc;
1379
  double i;
1380
  double j;
1381
  double k;
1382
  double old_cc;
1383
  double radius_increment = 0.;
1384
  double theta_increment = 0.;
1385
  CANON_PLANE plane;
1386
  double r;
1387
  int repeat;
1388
  CANON_MOTION_MODE save_mode;
1389
  double save_tolerance; //save the current tolerance, to restore it lateron
1390
  double current_cc = settings->u_current;
1391
1392
  plane = CANON_PLANE_VW;
1393
  if (settings->motion_mode != motion) {
1394
    CHKS((!block->u_flag),
1395
        _readers[(int)'u']? NCE_U_VALUE_UNSPECIFIED_IN_VW_PLANE_CANNED_CYCLE: _("G19.1 canned cycle is not possible on a machine without U axis"));
1396
  }
1397
  block->u_number =
1398
    block->u_flag ? block->u_number : settings->cycle_cc;
1399
  if(settings->cycle_il_flag) {
1400
      old_cc = settings->cycle_il;
1401
  } else {
1402
      old_cc = settings->cycle_il = current_cc;
1403
      settings->cycle_il_flag = true;
1404
  }
1405
1406
  if (settings->distance_mode == MODE_ABSOLUTE) {
1407
    aa_increment = 0.0;
1408
    bb_increment = 0.0;
1409
    r = block->r_number;
1410
    cc = block->u_number;
1411
    aa = block->v_flag ? block->v_number : settings->v_current;
1412
    bb = block->w_flag ? block->w_number : settings->w_current;
1413
  } else if (settings->distance_mode == MODE_INCREMENTAL) {
1414
    if (block->v_flag) aa_increment = block->v_number;
1415
    if (block->w_flag) bb_increment = block->w_number;
1416
    r = (block->r_number + old_cc);
1417
    cc = (r + block->u_number); /* [NCMS, page 98] */
1418
    aa = settings->v_current;
1419
    bb = settings->w_current;
1420
  } else
1421
    ERS(NCE_BUG_DISTANCE_MODE_NOT_G90_OR_G91);
1422
  CHKS((r < cc), NCE_R_LESS_THAN_U_IN_CYCLE_IN_VW_PLANE);
1423
1424
  if (old_cc < r) {
1425
    STRAIGHT_TRAVERSE(block->line_number, settings->current_x, settings->current_y, settings->current_z,
1426
                      settings->AA_current, settings->BB_current, settings->CC_current,
1427
                      r, settings->v_current, settings->w_current);
1428
    old_cc = r;
1429
    current_cc = old_cc;
1430
  }
1431
  clear_cc = (settings->retract_mode == R_PLANE) ? r : old_cc;
1432
1433
  save_mode = GET_EXTERNAL_MOTION_CONTROL_MODE();
1434
  save_tolerance = GET_EXTERNAL_MOTION_CONTROL_TOLERANCE();
1435
  if (save_mode != CANON_EXACT_PATH)
1436
    SET_MOTION_CONTROL_MODE(CANON_EXACT_PATH, 0);
1437
1438
  switch (motion) {
1439
  case G_81:
1440
    CYCLE_MACRO(convert_cycle_g81(block, CANON_PLANE_VW, aa, bb, clear_cc, cc))
1441
      break;
1442
  case G_82:
1443
    CHKS(((settings->motion_mode != G_82) && (block->p_number == -1.0)),
1444
        NCE_DWELL_TIME_P_WORD_MISSING_WITH_G82);
1445
    block->p_number =
1446
      block->p_number == -1.0 ? settings->cycle_p : block->p_number;
1447
    CYCLE_MACRO(convert_cycle_g82(block, CANON_PLANE_VW, aa, bb, clear_cc, cc,
1448
                                  block->p_number))
1449
      settings->cycle_p = block->p_number;
1450
    break;
1451
  case G_83:
1452
    CHKS(((settings->motion_mode != G_83) && (block->q_number == -1.0)),
1453
        NCE_Q_WORD_MISSING_WITH_G83);
1454
    block->q_number =
1455
      block->q_number == -1.0 ? settings->cycle_q : block->q_number;
1456
    CYCLE_MACRO(convert_cycle_g83(block, CANON_PLANE_VW, aa, bb, r, clear_cc, cc,
1457
                                  block->q_number))
1458
      settings->cycle_q = block->q_number;
1459
    break;
1460
  case G_73:
1461
    CHKS(((settings->motion_mode != G_73) && (block->q_number == -1.0)),
1462
        NCE_Q_WORD_MISSING_WITH_G73);
1463
    block->q_number =
1464
      block->q_number == -1.0 ? settings->cycle_q : block->q_number;
1465
    CYCLE_MACRO(convert_cycle_g73(block, CANON_PLANE_VW, aa, bb, r, clear_cc, cc,
1466
                                  block->q_number))
1467
      settings->cycle_q = block->q_number;
1468
    break;
1469
  case G_84:
1470
    CYCLE_MACRO(convert_cycle_g84(block, CANON_PLANE_VW, aa, bb, clear_cc, cc,
1471
                                  settings->spindle_turning,
1472
                                  settings->speed_feed_mode)) break;
1473
  case G_85:
1474
    CYCLE_MACRO(convert_cycle_g85(block, CANON_PLANE_VW, aa, bb, r, clear_cc, cc))
1475
      break;
1476
  case G_86:
1477
    CHKS(((settings->motion_mode != G_86) && (block->p_number == -1.0)),
1478
        NCE_DWELL_TIME_P_WORD_MISSING_WITH_G86);
1479
    block->p_number =
1480
      block->p_number == -1.0 ? settings->cycle_p : block->p_number;
1481
    CYCLE_MACRO(convert_cycle_g86(block, CANON_PLANE_VW, aa, bb, clear_cc, cc,
1482
                                  block->p_number,
1483
                                  settings->spindle_turning)) settings->
1484
      cycle_p = block->p_number;
1485
    break;
1486
  case G_87:
1487
    if (settings->motion_mode != G_87) {
1488
      CHKS((!block->i_flag), NCE_I_WORD_MISSING_WITH_G87);
1489
      CHKS((!block->j_flag), NCE_J_WORD_MISSING_WITH_G87);
1490
      CHKS((!block->k_flag), NCE_K_WORD_MISSING_WITH_G87);
1491
    }
1492
    i = block->i_flag ? block->i_number : settings->cycle_i;
1493
    j = block->j_flag ? block->j_number : settings->cycle_j;
1494
    k = block->k_flag ? block->k_number : settings->cycle_k;
1495
    settings->cycle_i = i;
1496
    settings->cycle_j = j;
1497
    settings->cycle_k = k;
1498
    if (settings->distance_mode == MODE_INCREMENTAL) {
1499
      i = (cc + i);             /* i always absolute in function call below */
1500
    }
1501
    CYCLE_MACRO(convert_cycle_g87(block, CANON_PLANE_VW, aa, (aa + j), bb,
1502
                                  (bb + k), r, clear_cc, i, cc,
1503
                                  settings->spindle_turning)) break;
1504
  case G_88:
1505
    CHKS(((settings->motion_mode != G_88) && (block->p_number == -1.0)),
1506
        NCE_DWELL_TIME_P_WORD_MISSING_WITH_G88);
1507
    block->p_number =
1508
      block->p_number == -1.0 ? settings->cycle_p : block->p_number;
1509
    CYCLE_MACRO(convert_cycle_g88(block, CANON_PLANE_VW, aa, bb, cc,
1510
                                  block->p_number,
1511
                                  settings->spindle_turning)) settings->
1512
      cycle_p = block->p_number;
1513
    break;
1514
  case G_89:
1515
    CHKS(((settings->motion_mode != G_89) && (block->p_number == -1.0)),
1516
        NCE_DWELL_TIME_P_WORD_MISSING_WITH_G89);
1517
    block->p_number =
1518
      block->p_number == -1.0 ? settings->cycle_p : block->p_number;
1519
    CYCLE_MACRO(convert_cycle_g89(block, CANON_PLANE_VW, aa, bb, clear_cc, cc,
1520
                                  block->p_number))
1521
      settings->cycle_p = block->p_number;
1522
    break;
1523
  default:
1524
    ERS(NCE_BUG_FUNCTION_SHOULD_NOT_HAVE_BEEN_CALLED);
1525
  }
1526
  settings->v_current = aa;     /* CYCLE_MACRO updates aa and bb */
1527
  settings->w_current = bb;
1528
  settings->u_current = clear_cc;
1529
  settings->cycle_cc = block->u_number;
1530
1531
  if (save_mode != CANON_EXACT_PATH)
1532
    SET_MOTION_CONTROL_MODE(save_mode, save_tolerance);
1533
1534
  return INTERP_OK;
1535
}
1536
1537
1538
/****************************************************************************/
1539
1540
/*! convert_cycle_zx
1541
1542
Returned Value: int
1543
   If any of the specific functions called returns an error code,
1544
   this returns that code.
1545
   If any of the following errors occur, this returns the ERROR code shown.
1546
   Otherwise, it returns INTERP_OK.
1547
   1. The y-value is not given the first time this code is called after
1548
      some other motion mode has been in effect:
1549
      NCE_Y_VALUE_UNSPECIFIED_IN_XZ_PLANE_CANNED_CYCLE
1550
   2. The r clearance plane is below the bottom_y:
1551
      NCE_R_LESS_THAN_Y_IN_CYCLE_IN_XZ_PLANE
1552
   3. the distance mode is neither absolute or incremental:
1553
      NCE_BUG_DISTANCE_MODE_NOT_G90_OR_G91
1554
   4. G82, G86, G88, or G89 is called when it is not already in effect,
1555
      and no p number is in the block:
1556
      NCE_DWELL_TIME_P_WORD_MISSING_WITH_G82
1557
      NCE_DWELL_TIME_P_WORD_MISSING_WITH_G86
1558
      NCE_DWELL_TIME_P_WORD_MISSING_WITH_G88
1559
      NCE_DWELL_TIME_P_WORD_MISSING_WITH_G89
1560
   5. G83 is called when it is not already in effect,
1561
      and no q number is in the block: NCE_Q_WORD_MISSING_WITH_G83
1562
   6. G87 is called when it is not already in effect,
1563
      and any of the i number, j number, or k number is missing:
1564
      NCE_I_WORD_MISSING_WITH_G87
1565
      NCE_J_WORD_MISSING_WITH_G87
1566
      NCE_K_WORD_MISSING_WITH_G87
1567
   7. the G code is not between G_81 and G_89.
1568
      NCE_BUG_FUNCTION_SHOULD_NOT_HAVE_BEEN_CALLED
1569
1570
Side effects:
1571
   A number of moves are made to execute a canned cycle.
1572
1573
Called by: convert_cycle
1574
1575
See the documentation of convert_cycle_xy. This function is entirely
1576
similar. In this function aa represents z, bb represents x, and cc
1577
represents y.
1578
1579
The CYCLE_MACRO is defined just before the convert_cycle_xy function.
1580
1581
Tool length offsets work only when the tool axis is parallel to the
1582
Z-axis, so if this function is used, tool length offsets should be
1583
turned off, and the NC code written to take tool length into account.
1584
1585
It is a little distracting that this function uses zx in some places
1586
and xz in others; uniform use of zx would be nice, since that is the
1587
order for a right-handed coordinate system. Also with that usage,
1588
permutation of the symbols x, y, and z would allow for automatically
1589
converting the convert_cycle_xy function (or convert_cycle_yz) into
1590
the convert_cycle_xz function. However, the canonical interface uses
1591
CANON_PLANE_XZ.
1592
1593
*/
1594
1595
12
int Interp::convert_cycle_zx(int motion, //!< a g-code between G_81 and G_89, a canned cycle
1596
                            block_pointer block,        //!< pointer to a block of RS274 instructions
1597
                            setup_pointer settings)     //!< pointer to machine settings
1598
{
1599
  double aa;
1600
12
  double aa_increment=0.;
1601
  double bb;
1602
12
  double bb_increment=0.;
1603
  double cc;
1604
  double clear_cc;
1605
  double i;
1606
  double j;
1607
  double k;
1608
  double old_cc;
1609
12
  double radius_increment = 0.;
1610
12
  double theta_increment = 0.;
1611
  CANON_PLANE plane;
1612
  double r;
1613
  int repeat;
1614
  CANON_MOTION_MODE save_mode;
1615
  double save_tolerance; //save current path-following tolerance, to restore it lateron
1616
12
  double current_cc = settings->current_y;
1617
1618
12
  plane = CANON_PLANE_XZ;
1619
12
  if (settings->motion_mode != motion) {
1620
8
    CHKS((!block->y_flag),
1621
        _readers[(int)'y']? NCE_Y_VALUE_UNSPECIFIED_IN_XZ_PLANE_CANNED_CYCLE: _("G18 canned cycle is not possible on a machine without Y axis"));
1622
  }
1623
  block->y_number =
1624
12
    block->y_flag ? block->y_number : settings->cycle_cc;
1625
12
  if(settings->cycle_il_flag) {
1626
4
      old_cc = settings->cycle_il;
1627
  } else {
1628
8
      old_cc = settings->cycle_il = current_cc;
1629
8
      settings->cycle_il_flag = true;
1630
  }
1631
1632
12
  if (settings->distance_mode == MODE_ABSOLUTE) {
1633
6
    aa_increment = 0.0;
1634
6
    bb_increment = 0.0;
1635
6
    r = block->r_number;
1636
6
    cc = block->y_number;
1637
6
    aa = block->z_flag ? block->z_number : settings->current_z;
1638
6
    bb = block->x_flag ? block->x_number : settings->current_x;
1639
6
  } else if (settings->distance_mode == MODE_INCREMENTAL) {
1640
6
    if (block->z_flag) aa_increment = block->z_number;
1641
6
    if (block->x_flag) bb_increment = block->x_number;
1642
6
    r = (block->r_number + old_cc);
1643
6
    cc = (r + block->y_number); /* [NCMS, page 98] */
1644
6
    aa = settings->current_z;
1645
6
    bb = settings->current_x;
1646
  } else
1647
    ERS(NCE_BUG_DISTANCE_MODE_NOT_G90_OR_G91);
1648
12
  CHKS((r < cc), NCE_R_LESS_THAN_Y_IN_CYCLE_IN_XZ_PLANE);
1649
1650
12
  if (old_cc < r) {
1651
    STRAIGHT_TRAVERSE(block->line_number, settings->current_x, r, settings->current_z,
1652
                      settings->AA_current, settings->BB_current, settings->CC_current,
1653
8
                      settings->u_current, settings->v_current, settings->w_current);
1654
8
    old_cc = r;
1655
8
    current_cc = old_cc;
1656
  }
1657
12
  clear_cc = (settings->retract_mode == R_PLANE) ? r : old_cc;
1658
1659
12
  save_mode = GET_EXTERNAL_MOTION_CONTROL_MODE();
1660
12
  save_tolerance = GET_EXTERNAL_MOTION_CONTROL_TOLERANCE();
1661
12
  if (save_mode != CANON_EXACT_PATH)
1662
12
    SET_MOTION_CONTROL_MODE(CANON_EXACT_PATH, 0);
1663
1664
12
  switch (motion) {
1665
  case G_81:
1666
12
    CYCLE_MACRO(convert_cycle_g81(block, CANON_PLANE_XZ, aa, bb, clear_cc, cc))
1667
      break;
1668
  case G_82:
1669
    CHKS(((settings->motion_mode != G_82) && (block->p_number == -1.0)),
1670
        NCE_DWELL_TIME_P_WORD_MISSING_WITH_G82);
1671
    block->p_number =
1672
      block->p_number == -1.0 ? settings->cycle_p : block->p_number;
1673
    CYCLE_MACRO(convert_cycle_g82(block, CANON_PLANE_XZ, aa, bb, clear_cc, cc,
1674
                                  block->p_number))
1675
      settings->cycle_p = block->p_number;
1676
    break;
1677
  case G_73:
1678
    CHKS(((settings->motion_mode != G_73) && (block->q_number == -1.0)),
1679
        NCE_Q_WORD_MISSING_WITH_G73);
1680
    block->q_number =
1681
      block->q_number == -1.0 ? settings->cycle_q : block->q_number;
1682
    CYCLE_MACRO(convert_cycle_g73(block, CANON_PLANE_XZ, aa, bb, r, clear_cc, cc,
1683
                                  block->q_number))
1684
      settings->cycle_q = block->q_number;
1685
    break;
1686
  case G_83:
1687
    CHKS(((settings->motion_mode != G_83) && (block->q_number == -1.0)),
1688
        NCE_Q_WORD_MISSING_WITH_G83);
1689
    block->q_number =
1690
      block->q_number == -1.0 ? settings->cycle_q : block->q_number;
1691
    CYCLE_MACRO(convert_cycle_g83(block, CANON_PLANE_XZ, aa, bb, r, clear_cc, cc,
1692
                                  block->q_number))
1693
      settings->cycle_q = block->q_number;
1694
    break;
1695
  case G_84:
1696
    CYCLE_MACRO(convert_cycle_g84(block, CANON_PLANE_XZ, aa, bb, clear_cc, cc,
1697
                                  settings->spindle_turning,
1698
                                  settings->speed_feed_mode)) break;
1699
  case G_85:
1700
    CYCLE_MACRO(convert_cycle_g85(block, CANON_PLANE_XZ, aa, bb, r, clear_cc, cc))
1701
      break;
1702
  case G_86:
1703
    CHKS(((settings->motion_mode != G_86) && (block->p_number == -1.0)),
1704
        NCE_DWELL_TIME_P_WORD_MISSING_WITH_G86);
1705
    block->p_number =
1706
      block->p_number == -1.0 ? settings->cycle_p : block->p_number;
1707
    CYCLE_MACRO(convert_cycle_g86(block, CANON_PLANE_XZ, aa, bb, clear_cc, cc,
1708
                                  block->p_number,
1709
                                  settings->spindle_turning)) settings->
1710
      cycle_p = block->p_number;
1711
    break;
1712
  case G_87:
1713
    if (settings->motion_mode != G_87) {
1714
      CHKS((!block->i_flag), NCE_I_WORD_MISSING_WITH_G87);
1715
      CHKS((!block->j_flag), NCE_J_WORD_MISSING_WITH_G87);
1716
      CHKS((!block->k_flag), NCE_K_WORD_MISSING_WITH_G87);
1717
    }
1718
    i = block->i_flag ? block->i_number : settings->cycle_i;
1719
    j = block->j_flag ? block->j_number : settings->cycle_j;
1720
    k = block->k_flag ? block->k_number : settings->cycle_k;
1721
    settings->cycle_i = i;
1722
    settings->cycle_j = j;
1723
    settings->cycle_k = k;
1724
    if (settings->distance_mode == MODE_INCREMENTAL) {
1725
      j = (cc + j);             /* j always absolute in function call below */
1726
    }
1727
    CYCLE_MACRO(convert_cycle_g87(block, CANON_PLANE_XZ, aa, (aa + k), bb,
1728
                                  (bb + i), r, clear_cc, j, cc,
1729
                                  settings->spindle_turning)) break;
1730
  case G_88:
1731
    CHKS(((settings->motion_mode != G_88) && (block->p_number == -1.0)),
1732
        NCE_DWELL_TIME_P_WORD_MISSING_WITH_G88);
1733
    block->p_number =
1734
      block->p_number == -1.0 ? settings->cycle_p : block->p_number;
1735
    CYCLE_MACRO(convert_cycle_g88(block, CANON_PLANE_XZ, aa, bb, cc,
1736
                                  block->p_number,
1737
                                  settings->spindle_turning)) settings->
1738
      cycle_p = block->p_number;
1739
    break;
1740
  case G_89:
1741
    CHKS(((settings->motion_mode != G_89) && (block->p_number == -1.0)),
1742
        NCE_DWELL_TIME_P_WORD_MISSING_WITH_G89);
1743
    block->p_number =
1744
      block->p_number == -1.0 ? settings->cycle_p : block->p_number;
1745
    CYCLE_MACRO(convert_cycle_g89(block, CANON_PLANE_XZ, aa, bb, clear_cc, cc,
1746
                                  block->p_number))
1747
      settings->cycle_p = block->p_number;
1748
    break;
1749
  default:
1750
    ERS(NCE_BUG_FUNCTION_SHOULD_NOT_HAVE_BEEN_CALLED);
1751
  }
1752
12
  settings->current_z = aa;     /* CYCLE_MACRO updates aa and bb */
1753
12
  settings->current_x = bb;
1754
12
  settings->current_y = clear_cc;
1755
12
  settings->cycle_cc = block->y_number;
1756
1757
12
  if (save_mode != CANON_EXACT_PATH)
1758
12
    SET_MOTION_CONTROL_MODE(save_mode, save_tolerance);
1759
1760
  return INTERP_OK;
1761
}
1762
1763
int Interp::convert_cycle_wu(int motion, //!< a g-code between G_81 and G_89, a canned cycle
1764
                            block_pointer block,        //!< pointer to a block of RS274 instructions
1765
                            setup_pointer settings)     //!< pointer to machine settings
1766
{
1767
  double aa;
1768
  double aa_increment=0.;
1769
  double bb;
1770
  double bb_increment=0.;
1771
  double cc;
1772
  double clear_cc;
1773
  double i;
1774
  double j;
1775
  double k;
1776
  double old_cc;
1777
  double radius_increment = 0.;
1778
  double theta_increment = 0.;
1779
  CANON_PLANE plane;
1780
  double r;
1781
  int repeat;
1782
  CANON_MOTION_MODE save_mode;
1783
  double save_tolerance; //save current path-following tolerance, to restore it lateron
1784
  double current_cc = settings->v_current;
1785
1786
  plane = CANON_PLANE_UW;
1787
  if (settings->motion_mode != motion) {
1788
    CHKS((!block->v_flag),
1789
        _readers[(int)'v']? NCE_V_VALUE_UNSPECIFIED_IN_UW_PLANE_CANNED_CYCLE: _("G18.1 canned cycle is not possible on a machine without V axis"));
1790
  }
1791
  block->v_number =
1792
    block->v_flag ? block->v_number : settings->cycle_cc;
1793
  if(settings->cycle_il_flag) {
1794
      old_cc = settings->cycle_il;
1795
  } else {
1796
      old_cc = settings->cycle_il = current_cc;
1797
      settings->cycle_il_flag = true;
1798
  }
1799
1800
  if (settings->distance_mode == MODE_ABSOLUTE) {
1801
    aa_increment = 0.0;
1802
    bb_increment = 0.0;
1803
    r = block->r_number;
1804
    cc = block->v_number;
1805
    aa = block->w_flag ? block->w_number : settings->w_current;
1806
    bb = block->u_flag ? block->u_number : settings->u_current;
1807
  } else if (settings->distance_mode == MODE_INCREMENTAL) {
1808
    if (block->w_flag) aa_increment = block->w_number;
1809
    if (block->u_flag) bb_increment = block->u_number;
1810
    r = (block->r_number + old_cc);
1811
    cc = (r + block->v_number); /* [NCMS, page 98] */
1812
    aa = settings->w_current;
1813
    bb = settings->u_current;
1814
  } else
1815
    ERS(NCE_BUG_DISTANCE_MODE_NOT_G90_OR_G91);
1816
  CHKS((r < cc), NCE_R_LESS_THAN_V_IN_CYCLE_IN_UW_PLANE);
1817
1818
  if (old_cc < r) {
1819
    STRAIGHT_TRAVERSE(block->line_number, settings->current_x, settings->current_y, settings->current_z,
1820
                      settings->AA_current, settings->BB_current, settings->CC_current,
1821
                      settings->u_current, r, settings->w_current);
1822
    old_cc = r;
1823
    current_cc = old_cc;
1824
  }
1825
  clear_cc = (settings->retract_mode == R_PLANE) ? r : old_cc;
1826
1827
  save_mode = GET_EXTERNAL_MOTION_CONTROL_MODE();
1828
  save_tolerance = GET_EXTERNAL_MOTION_CONTROL_TOLERANCE();
1829
  if (save_mode != CANON_EXACT_PATH)
1830
    SET_MOTION_CONTROL_MODE(CANON_EXACT_PATH, 0);
1831
1832
  switch (motion) {
1833
  case G_81:
1834
    CYCLE_MACRO(convert_cycle_g81(block, CANON_PLANE_UW, aa, bb, clear_cc, cc))
1835
      break;
1836
  case G_82:
1837
    CHKS(((settings->motion_mode != G_82) && (block->p_number == -1.0)),
1838
        NCE_DWELL_TIME_P_WORD_MISSING_WITH_G82);
1839
    block->p_number =
1840
      block->p_number == -1.0 ? settings->cycle_p : block->p_number;
1841
    CYCLE_MACRO(convert_cycle_g82(block, CANON_PLANE_UW, aa, bb, clear_cc, cc,
1842
                                  block->p_number))
1843
      settings->cycle_p = block->p_number;
1844
    break;
1845
  case G_73:
1846
    CHKS(((settings->motion_mode != G_73) && (block->q_number == -1.0)),
1847
        NCE_Q_WORD_MISSING_WITH_G73);
1848
    block->q_number =
1849
      block->q_number == -1.0 ? settings->cycle_q : block->q_number;
1850
    CYCLE_MACRO(convert_cycle_g73(block, CANON_PLANE_UW, aa, bb, r, clear_cc, cc,
1851
                                  block->q_number))
1852
      settings->cycle_q = block->q_number;
1853
    break;
1854
  case G_83:
1855
    CHKS(((settings->motion_mode != G_83) && (block->q_number == -1.0)),
1856
        NCE_Q_WORD_MISSING_WITH_G83);
1857
    block->q_number =
1858
      block->q_number == -1.0 ? settings->cycle_q : block->q_number;
1859
    CYCLE_MACRO(convert_cycle_g83(block, CANON_PLANE_UW, aa, bb, r, clear_cc, cc,
1860
                                  block->q_number))
1861
      settings->cycle_q = block->q_number;
1862
    break;
1863
  case G_84:
1864
    CYCLE_MACRO(convert_cycle_g84(block, CANON_PLANE_UW, aa, bb, clear_cc, cc,
1865
                                  settings->spindle_turning,
1866
                                  settings->speed_feed_mode)) break;
1867
  case G_85:
1868
    CYCLE_MACRO(convert_cycle_g85(block, CANON_PLANE_UW, aa, bb, r, clear_cc, cc))
1869
      break;
1870
  case G_86:
1871
    CHKS(((settings->motion_mode != G_86) && (block->p_number == -1.0)),
1872
        NCE_DWELL_TIME_P_WORD_MISSING_WITH_G86);
1873
    block->p_number =
1874
      block->p_number == -1.0 ? settings->cycle_p : block->p_number;
1875
    CYCLE_MACRO(convert_cycle_g86(block, CANON_PLANE_UW, aa, bb, clear_cc, cc,
1876
                                  block->p_number,
1877
                                  settings->spindle_turning)) settings->
1878
      cycle_p = block->p_number;
1879
    break;
1880
  case G_87:
1881
    if (settings->motion_mode != G_87) {
1882
      CHKS((!block->i_flag), NCE_I_WORD_MISSING_WITH_G87);
1883
      CHKS((!block->j_flag), NCE_J_WORD_MISSING_WITH_G87);
1884
      CHKS((!block->k_flag), NCE_K_WORD_MISSING_WITH_G87);
1885
    }
1886
    i = block->i_flag ? block->i_number : settings->cycle_i;
1887
    j = block->j_flag ? block->j_number : settings->cycle_j;
1888
    k = block->k_flag ? block->k_number : settings->cycle_k;
1889
    settings->cycle_i = i;
1890
    settings->cycle_j = j;
1891
    settings->cycle_k = k;
1892
    if (settings->distance_mode == MODE_INCREMENTAL) {
1893
      j = (cc + j);             /* j always absolute in function call below */
1894
    }
1895
    CYCLE_MACRO(convert_cycle_g87(block, CANON_PLANE_UW, aa, (aa + k), bb,
1896
                                  (bb + i), r, clear_cc, j, cc,
1897
                                  settings->spindle_turning)) break;
1898
  case G_88:
1899
    CHKS(((settings->motion_mode != G_88) && (block->p_number == -1.0)),
1900
        NCE_DWELL_TIME_P_WORD_MISSING_WITH_G88);
1901
    block->p_number =
1902
      block->p_number == -1.0 ? settings->cycle_p : block->p_number;
1903
    CYCLE_MACRO(convert_cycle_g88(block, CANON_PLANE_UW, aa, bb, cc,
1904
                                  block->p_number,
1905
                                  settings->spindle_turning)) settings->
1906
      cycle_p = block->p_number;
1907
    break;
1908
  case G_89:
1909
    CHKS(((settings->motion_mode != G_89) && (block->p_number == -1.0)),
1910
        NCE_DWELL_TIME_P_WORD_MISSING_WITH_G89);
1911
    block->p_number =
1912
      block->p_number == -1.0 ? settings->cycle_p : block->p_number;
1913
    CYCLE_MACRO(convert_cycle_g89(block, CANON_PLANE_UW, aa, bb, clear_cc, cc,
1914
                                  block->p_number))
1915
      settings->cycle_p = block->p_number;
1916
    break;
1917
  default:
1918
    ERS(NCE_BUG_FUNCTION_SHOULD_NOT_HAVE_BEEN_CALLED);
1919
  }
1920
  settings->w_current = aa;     /* CYCLE_MACRO updates aa and bb */
1921
  settings->u_current = bb;
1922
  settings->v_current = clear_cc;
1923
  settings->cycle_cc = block->v_number;
1924
1925
  if (save_mode != CANON_EXACT_PATH)
1926
    SET_MOTION_CONTROL_MODE(save_mode, save_tolerance);
1927
1928
  return INTERP_OK;
1929
}
1930
/****************************************************************************/
1931
1932
/*! cycle_feed
1933
1934
Returned Value: int (INTERP_OK)
1935
1936
Side effects:
1937
  STRAIGHT_FEED is called.
1938
1939
Called by:
1940
  convert_cycle_g81
1941
  convert_cycle_g82
1942
  convert_cycle_g83
1943
  convert_cycle_g84
1944
  convert_cycle_g85
1945
  convert_cycle_g86
1946
  convert_cycle_g87
1947
  convert_cycle_g88
1948
  convert_cycle_g89
1949
1950
This writes a STRAIGHT_FEED command appropriate for a cycle move with
1951
respect to the given plane. No rotary axis motion takes place.
1952
1953
*/
1954
1955
55
int Interp::cycle_feed(block_pointer block,
1956
                       CANON_PLANE plane,        //!< currently selected plane
1957
                       double end1,      //!< first coordinate value
1958
                       double end2,      //!< second coordinate value
1959
                       double end3)      //!< third coordinate value
1960
{
1961
55
    if (plane == CANON_PLANE_XY)
1962
        STRAIGHT_FEED(block->line_number, end1, end2, end3,
1963
                      _setup.AA_current, _setup.BB_current, _setup.CC_current,
1964
19
                      _setup.u_current, _setup.v_current, _setup.w_current);
1965
36
    else if (plane == CANON_PLANE_YZ)
1966
        STRAIGHT_FEED(block->line_number, end3, end1, end2,
1967
                      _setup.AA_current, _setup.BB_current, _setup.CC_current,
1968
18
                      _setup.u_current, _setup.v_current, _setup.w_current);
1969
18
    else if (plane == CANON_PLANE_XZ)
1970
        STRAIGHT_FEED(block->line_number, end2, end3, end1,
1971
                      _setup.AA_current, _setup.BB_current, _setup.CC_current,
1972
18
                      _setup.u_current, _setup.v_current, _setup.w_current);
1973
    else if (plane == CANON_PLANE_UV)
1974
        STRAIGHT_FEED(block->line_number, _setup.current_x, _setup.current_y, _setup.current_z,
1975
                      _setup.AA_current, _setup.BB_current, _setup.CC_current,
1976
                      end1, end2, end3);
1977
    else if (plane == CANON_PLANE_VW)
1978
        STRAIGHT_FEED(block->line_number, _setup.current_x, _setup.current_y, _setup.current_z,
1979
                      _setup.AA_current, _setup.BB_current, _setup.CC_current,
1980
                      end3, end1, end2);
1981
    else // (plane == CANON_PLANE_UW)
1982
        STRAIGHT_FEED(block->line_number, _setup.current_x, _setup.current_y, _setup.current_z,
1983
                      _setup.AA_current, _setup.BB_current, _setup.CC_current,
1984
                      end2, end3, end1);
1985
55
    return INTERP_OK;
1986
}
1987
1988
/****************************************************************************/
1989
1990
/*! cycle_traverse
1991
1992
Returned Value: int (INTERP_OK)
1993
1994
Side effects:
1995
  STRAIGHT_TRAVERSE is called.
1996
1997
Called by:
1998
  convert_cycle
1999
  convert_cycle_g81
2000
  convert_cycle_g82
2001
  convert_cycle_g83
2002
  convert_cycle_g86
2003
  convert_cycle_g87
2004
  convert_cycle_xy (via CYCLE_MACRO)
2005
  convert_cycle_yz (via CYCLE_MACRO)
2006
  convert_cycle_zx (via CYCLE_MACRO)
2007
2008
This writes a STRAIGHT_TRAVERSE command appropriate for a cycle
2009
move with respect to the given plane. No rotary axis motion takes place.
2010
2011
*/
2012
2013
125
int Interp::cycle_traverse(block_pointer block,
2014
                           CANON_PLANE plane,    //!< currently selected plane
2015
                           double end1,  //!< first coordinate value
2016
                           double end2,  //!< second coordinate value
2017
                           double end3)  //!< third coordinate value
2018
{
2019
2020
125
    if (plane == CANON_PLANE_XY)
2021
        STRAIGHT_TRAVERSE(block->line_number, end1, end2, end3,
2022
                          _setup.AA_current, _setup.BB_current, _setup.CC_current,
2023
43
                          _setup.u_current, _setup.v_current, _setup.w_current);
2024
82
    else if (plane == CANON_PLANE_YZ)
2025
        STRAIGHT_TRAVERSE(block->line_number, end3, end1, end2,
2026
                          _setup.AA_current, _setup.BB_current, _setup.CC_current,
2027
41
                          _setup.u_current, _setup.v_current, _setup.w_current);
2028
41
    else if (plane == CANON_PLANE_XZ)
2029
        STRAIGHT_TRAVERSE(block->line_number, end2, end3, end1,
2030
                          _setup.AA_current, _setup.BB_current, _setup.CC_current,
2031
41
                          _setup.u_current, _setup.v_current, _setup.w_current);
2032
    else if (plane == CANON_PLANE_UV)
2033
        STRAIGHT_TRAVERSE(block->line_number, _setup.current_x, _setup.current_y, _setup.current_z,
2034
                          _setup.AA_current, _setup.BB_current, _setup.CC_current,
2035
                          end1, end2, end3);
2036
    else if (plane == CANON_PLANE_VW)
2037
        STRAIGHT_TRAVERSE(block->line_number, _setup.current_x, _setup.current_y, _setup.current_z,
2038
                          _setup.AA_current, _setup.BB_current, _setup.CC_current,
2039
                          end3, end1, end2);
2040
    else // (plane == CANON_PLANE_UW)
2041
        STRAIGHT_TRAVERSE(block->line_number, _setup.current_x, _setup.current_y, _setup.current_z,
2042
                          _setup.AA_current, _setup.BB_current, _setup.CC_current,
2043
                          end2, end3, end1);
2044
125
    return INTERP_OK;
2045
}