GCC Code Coverage Report
Directory: emc/rs274ngc/ Exec Total Coverage
File: emc/rs274ngc/interp_execute.cc Lines: 78 120 65.0 %
Date: 2016-10-27 Branches: 122 221 55.2 %

Line Exec Source
1
/********************************************************************
2
* Description: interp_execute.cc
3
*
4
*   Derived from a work by Thomas Kramer
5
*
6
* Author:
7
* License: GPL Version 2
8
* System: Linux
9
*
10
* Copyright (c) 2004 All rights reserved.
11
*
12
* Last change:
13
********************************************************************/
14
#ifndef _GNU_SOURCE
15
#define _GNU_SOURCE
16
#endif
17
#include <unistd.h>
18
#include <stdio.h>
19
#include <stdlib.h>
20
#include <math.h>
21
#include <string.h>
22
#include <ctype.h>
23
#include <sys/types.h>
24
#include <sys/stat.h>
25
#include "rtapi_math.h"
26
#include "rs274ngc.hh"
27
#include "rs274ngc_return.hh"
28
#include "interp_internal.hh"
29
#include "rs274ngc_interp.hh"
30
31
#define RESULT_OK(x) ((x) == INTERP_OK || (x) == INTERP_EXECUTE_FINISH)
32
33
/****************************************************************************/
34
35
/*! execute binary
36
37
Returned value: int
38
   If execute_binary1 or execute_binary2 returns an error code, this
39
   returns that code.
40
   Otherwise, it returns INTERP_OK.
41
42
Side effects: The value of left is set to the result of applying
43
  the operation to left and right.
44
45
Called by: read_real_expression
46
47
This just calls either execute_binary1 or execute_binary2.
48
49
*/
50
51
3335
int Interp::execute_binary(double *left, int operation, double *right)
52
{
53
3335
  if (operation < AND2)
54
1072
    CHP(execute_binary1(left, operation, right));
55
  else
56
2263
    CHP(execute_binary2(left, operation, right));
57
  return INTERP_OK;
58
}
59
60
/****************************************************************************/
61
62
/*! execute_binary1
63
64
Returned Value: int
65
   If any of the following errors occur, this returns the error shown.
66
   Otherwise, it returns INTERP_OK.
67
   1. operation is unknown: NCE_BUG_UNKNOWN_OPERATION
68
   2. An attempt is made to divide by zero: NCE_ATTEMPT_TO_DIVIDE_BY_ZERO
69
   3. An attempt is made to raise a negative number to a non-integer power:
70
      NCE_ATTEMPT_TO_RAISE_NEGATIVE_TO_NON_INTEGER_POWER
71
72
Side effects:
73
   The result from performing the operation is put into what left points at.
74
75
Called by: read_real_expression.
76
77
This executes the operations: DIVIDED_BY, MODULO, POWER, TIMES.
78
79
*/
80
81
1072
int Interp::execute_binary1(double *left,        //!< pointer to the left operand
82
                           int operation,       //!< integer code for the operation
83
                           double *right)       //!< pointer to the right operand
84
{
85
1072
  switch (operation) {
86
  case DIVIDED_BY:
87
582
    CHKS((*right == 0.0), NCE_ATTEMPT_TO_DIVIDE_BY_ZERO);
88
580
    *left = (*left / *right);
89
580
    break;
90
  case MODULO:                 /* always calculates a positive answer */
91
    *left = fmod(*left, *right);
92
    if (*left < 0.0) {
93
      *left = (*left + fabs(*right));
94
    }
95
    break;
96
  case POWER:
97
    CHKS(((*left < 0.0) && (floor(*right) != *right)),
98
        NCE_ATTEMPT_TO_RAISE_NEGATIVE_TO_NON_INTEGER_POWER);
99
    *left = pow(*left, *right);
100
    break;
101
  case TIMES:
102
490
    *left = (*left * *right);
103
490
    break;
104
  default:
105
    ERS(NCE_BUG_UNKNOWN_OPERATION);
106
  }
107
  return INTERP_OK;
108
}
109
110
/****************************************************************************/
111
112
/*! execute_binary2
113
114
Returned Value: int
115
   If any of the following errors occur, this returns the error code shown.
116
   Otherwise, it returns INTERP_OK.
117
   1. operation is unknown: NCE_BUG_UNKNOWN_OPERATION
118
119
Side effects:
120
   The result from performing the operation is put into what left points at.
121
122
Called by: read_real_expression.
123
124
This executes the operations: AND2, EXCLUSIVE_OR, MINUS,
125
NON_EXCLUSIVE_OR, PLUS. The RS274/NGC manual [NCMS] does not say what
126
the calculated value of the three logical operations should be. This
127
function calculates either 1.0 (meaning true) or 0.0 (meaning false).
128
Any non-zero input value is taken as meaning true, and only 0.0 means
129
false.
130
131
132
*/
133
134
2263
int Interp::execute_binary2(double *left,        //!< pointer to the left operand
135
                           int operation,       //!< integer code for the operation
136
                           double *right)       //!< pointer to the right operand
137
{
138
  double diff;
139
2263
  switch (operation) {
140
  case AND2:
141
    *left = ((*left == 0.0) || (*right == 0.0)) ? 0.0 : 1.0;
142
    break;
143
  case EXCLUSIVE_OR:
144
    *left = (((*left == 0.0) && (*right != 0.0))
145
             || ((*left != 0.0) && (*right == 0.0))) ? 1.0 : 0.0;
146
    break;
147
  case MINUS:
148
1126
    *left = (*left - *right);
149
1126
    break;
150
  case NON_EXCLUSIVE_OR:
151
    *left = ((*left != 0.0) || (*right != 0.0)) ? 1.0 : 0.0;
152
    break;
153
  case PLUS:
154
640
    *left = (*left + *right);
155
640
    break;
156
157
  case LT:
158
26
      *left = (*left < *right) ? 1.0 : 0.0;
159
26
      break;
160
  case EQ:
161
276
      diff = *left - *right;
162
276
      diff = (diff < 0) ? -diff : diff;
163
276
      *left = (diff < TOLERANCE_EQUAL) ? 1.0 : 0.0;
164
276
      break;
165
  case NE:
166
117
      diff = *left - *right;
167
117
      diff = (diff < 0) ? -diff : diff;
168
117
      *left = (diff >= TOLERANCE_EQUAL) ? 1.0 : 0.0;
169
117
      break;
170
  case LE:
171
73
      *left = (*left <= *right) ? 1.0 : 0.0;
172
73
      break;
173
  case GE:
174
      *left = (*left >= *right) ? 1.0 : 0.0;
175
      break;
176
  case GT:
177
5
      *left = (*left > *right) ? 1.0 : 0.0;
178
5
      break;
179
180
  default:
181
    ERS(NCE_BUG_UNKNOWN_OPERATION);
182
  }
183
  return INTERP_OK;
184
}
185
186
187
/****************************************************************************/
188
189
/*! execute_block
190
191
Returned Value: int
192
   If convert_stop returns INTERP_EXIT, this returns INTERP_EXIT.
193
   If any of the following functions is called and returns an error code,
194
   this returns that code.
195
     convert_comment
196
     convert_feed_mode
197
     convert_feed_rate
198
     convert_g
199
     convert_m
200
     convert_speed
201
     convert_stop
202
     convert_tool_select
203
   Otherwise, if the probe_flag in the settings is true,
204
   or the input_flag is set to true this returns
205
      INTERP_EXECUTE_FINISH.
206
   Otherwise, it returns INTERP_OK.
207
208
Side effects:
209
   One block of RS274/NGC instructions is executed.
210
211
Called by:
212
   Interp::execute
213
214
This converts a block to zero to many actions. The order of execution
215
of items in a block is critical to safe and effective machine operation,
216
but is not specified clearly in the RS274/NGC documentation.
217
218
Actions are executed in the following order:
219
1. any comment.
220
2. a feed mode setting (g93, g94, g95)
221
3. a feed rate (f) setting if in units_per_minute feed mode.
222
4. a spindle speed (s) setting.
223
5. a tool selection (t).
224
6. "m" commands as described in convert_m (includes tool change).
225
7. any g_codes (except g93, g94) as described in convert_g.
226
8. stopping commands (m0, m1, m2, m30, or m60).
227
228
In inverse time feed mode, the explicit and implicit g code executions
229
include feed rate setting with g1, g2, and g3. Also in inverse time
230
feed mode, attempting a canned cycle cycle (g81 to g89) or setting a
231
feed rate with g0 is illegal and will be detected and result in an
232
error message.
233
234
*/
235
236
4510
int Interp::execute_block(block_pointer block,   //!< pointer to a block of RS274/NGC instructions
237
			  setup_pointer settings) //!< pointer to machine settings
238
{
239
  int status;
240
241
4510
  block->line_number = settings->sequence_number;
242
8558
  if ((block->comment[0] != 0) && ONCE(STEP_COMMENT)) {
243
1012
    status = convert_comment(block->comment);
244
1012
    CHP(status);
245
  }
246
4509
  if ((block->g_modes[GM_SPINDLE_MODE] != -1) && ONCE(STEP_SPINDLE_MODE)) {
247
      status = convert_spindle_mode(block, settings);
248
      CHP(status);
249
  }
250
4561
  if ((block->g_modes[GM_FEED_MODE] != -1) && ONCE(STEP_FEED_MODE)) {
251
13
      status = convert_feed_mode(block->g_modes[GM_FEED_MODE], settings);
252
13
      CHP(status);
253
254
  }
255
4509
  if (block->f_flag){
256
2860
      if ((settings->feed_mode != INVERSE_TIME) && ONCE(STEP_SET_FEED_RATE))  {
257
1707
	  if (STEP_REMAPPED_IN_BLOCK(block, STEP_SET_FEED_RATE)) {
258
	      return (convert_remapped_code(block, settings, STEP_SET_FEED_RATE, 'F'));
259
	  } else {
260
569
	      status = convert_feed_rate(block, settings);
261
569
	      CHP(status);
262
	  }
263
      }
264
      /* INVERSE_TIME is handled elsewhere */
265
  }
266
4537
  if ((block->s_flag) && ONCE(STEP_SET_SPINDLE_SPEED)){
267
21
      if (STEP_REMAPPED_IN_BLOCK(block, STEP_SET_SPINDLE_SPEED)) {
268
	  return (convert_remapped_code(block,settings,STEP_SET_SPINDLE_SPEED,'S'));
269
      } else {
270
7
	  status = convert_speed(block, settings);
271
7
	  CHP(status);
272
      }
273
  }
274
4545
  if ((block->t_flag) && ONCE(STEP_PREPARE)) {
275
27
      if (STEP_REMAPPED_IN_BLOCK(block, STEP_PREPARE)) {
276
	  return (convert_remapped_code(block,settings,STEP_PREPARE,'T'));
277
      } else {
278
9
	  CHP(convert_tool_select(block, settings));
279
      }
280
  }
281
4509
  CHP(convert_m(block, settings));
282
4509
  CHP(convert_g(block, settings));
283
4671
  if ((block->m_modes[4] != -1) && ONCE(STEP_MGROUP4)) {        /* converts m0, m1, m2, m30, or m60 */
284
129
      if (STEP_REMAPPED_IN_BLOCK(block, STEP_MGROUP4)) {
285
	  status = convert_remapped_code(block,settings,STEP_MGROUP4,'M',block->m_modes[4]);
286
      } else {
287
43
	  status = convert_stop(block, settings);
288
      }
289
43
    if (status == INTERP_EXIT) {
290
	return(INTERP_EXIT);
291
    }
292
2
    else if (status != INTERP_OK) {
293
	ERP(status);
294
    }
295
  }
296
4458
  if (settings->probe_flag)
297
      return (INTERP_EXECUTE_FINISH);
298
299
4458
  if (settings->input_flag)
300
      return (INTERP_EXECUTE_FINISH);
301
302
4457
  if (settings->toolchange_flag)
303
      return (INTERP_EXECUTE_FINISH);
304
305
4448
  return INTERP_OK;
306
}
307
308
/****************************************************************************/
309
310
/*! execute_unary
311
312
Returned Value: int
313
   If any of the following errors occur, this returns the error code shown.
314
   Otherwise, it returns INTERP_OK.
315
   1. the operation is unknown: NCE_BUG_UNKNOWN_OPERATION
316
   2. the argument to acos is not between minus and plus one:
317
      NCE_ARGUMENT_TO_ACOS_OUT_RANGE
318
   3. the argument to asin is not between minus and plus one:
319
      NCE_ARGUMENT_TO_ASIN_OUT_RANGE
320
   4. the argument to the natural logarithm is not positive:
321
      NCE_ZERO_OR_NEGATIVE_ARGUMENT_TO_LN
322
   5. the argument to square root is negative:
323
      NCE_NEGATIVE_ARGUMENT_TO_SQRT
324
325
Side effects:
326
   The result from performing the operation on the value in double_ptr
327
   is put into what double_ptr points at.
328
329
Called by: read_unary.
330
331
This executes the operations: ABS, ACOS, ASIN, COS, EXP, FIX, FUP, LN
332
ROUND, SIN, SQRT, TAN
333
334
All angle measures in the input or output are in degrees.
335
336
*/
337
338
307
int Interp::execute_unary(double *double_ptr,    //!< pointer to the operand
339
                         int operation) //!< integer code for the operation
340
{
341
307
  switch (operation) {
342
  case ABS:
343
    if (*double_ptr < 0.0)
344
      *double_ptr = (-1.0 * *double_ptr);
345
    break;
346
  case ACOS:
347
    CHKS(((*double_ptr < -1.0) || (*double_ptr > 1.0)),
348
        NCE_ARGUMENT_TO_ACOS_OUT_OF_RANGE);
349
    *double_ptr = acos(*double_ptr);
350
    *double_ptr = ((*double_ptr * 180.0) / M_PIl);
351
    break;
352
  case ASIN:
353
21
    CHKS(((*double_ptr < -1.0) || (*double_ptr > 1.0)),
354
        NCE_ARGUMENT_TO_ASIN_OUT_OF_RANGE);
355
21
    *double_ptr = asin(*double_ptr);
356
21
    *double_ptr = ((*double_ptr * 180.0) / M_PIl);
357
21
    break;
358
  case COS:
359
84
    *double_ptr = cos((*double_ptr * M_PIl) / 180.0);
360
84
    break;
361
  case EXISTS:
362
    // do nothing here
363
    // result for the EXISTS function is set by Interp:read_unary()
364
    break;
365
  case EXP:
366
    *double_ptr = exp(*double_ptr);
367
    break;
368
  case FIX:
369
    *double_ptr = floor(*double_ptr);
370
    break;
371
  case FUP:
372
4
    *double_ptr = ceil(*double_ptr);
373
4
    break;
374
  case LN:
375
    CHKS((*double_ptr <= 0.0), NCE_ZERO_OR_NEGATIVE_ARGUMENT_TO_LN);
376
    *double_ptr = log(*double_ptr);
377
    break;
378
  case ROUND:
379
    *double_ptr = (double)
380
      ((int) (*double_ptr + ((*double_ptr < 0.0) ? -0.5 : 0.5)));
381
    break;
382
  case SIN:
383
63
    *double_ptr = sin((*double_ptr * M_PIl) / 180.0);
384
63
    break;
385
  case SQRT:
386
135
    CHKS((*double_ptr < 0.0), NCE_NEGATIVE_ARGUMENT_TO_SQRT);
387
135
    *double_ptr = sqrt(*double_ptr);
388
135
    break;
389
  case TAN:
390
    *double_ptr = tan((*double_ptr * M_PIl) / 180.0);
391
    break;
392
  default:
393
    ERS(NCE_BUG_UNKNOWN_OPERATION);
394
  }
395
  return INTERP_OK;
396
}
397