GCC Code Coverage Report
Directory: emc/rs274ngc/ Exec Total Coverage
File: emc/rs274ngc/interp_check.cc Lines: 70 75 93.3 %
Date: 2016-10-27 Branches: 201 338 59.5 %

Line Exec Source
1
/********************************************************************
2
* Description: interp_check.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
#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
/*! check_g_codes
30
31
Returned Value: int
32
   If any of the following errors occur, this returns the error shown.
33
   Otherwise, it returns INTERP_OK.
34
   1. NCE_DWELL_TIME_MISSING_WITH_G4
35
   2. NCE_MUST_USE_G0_OR_G1_WITH_G53
36
   3. NCE_CANNOT_USE_G53_INCREMENTAL
37
   4. NCE_LINE_WITH_G10_DOES_NOT_HAVE_L2
38
   5. NCE_P_VALUE_NOT_AN_INTEGER_WITH_G10_L2
39
   6. NCE_P_VALUE_OUT_OF_RANGE_WITH_G10_L2
40
   7. NCE_BUG_BAD_G_CODE_MODAL_GROUP_0
41
42
Side effects: none
43
44
Called by: check_items
45
46
This runs checks on g_codes from a block of RS274/NGC instructions.
47
Currently, all checks are on g_codes in modal group 0.
48
49
The read_g function checks for errors which would foul up the reading.
50
The enhance_block function checks for logical errors in the use of
51
axis values by g-codes in modal groups 0 and 1.
52
This function checks for additional logical errors in g_codes.
53
54
[Fanuc, page 45, note 4] says there is no maximum for how many g_codes
55
may be put on the same line, [NCMS] says nothing one way or the other,
56
so the test for that is not used.
57
58
We are suspending any implicit motion g_code when a g_code from our
59
group 0 is used.  The implicit motion g_code takes effect again
60
automatically after the line on which the group 0 g_code occurs.  It
61
is not clear what the intent of [Fanuc] is in this regard. The
62
alternative is to require that any implicit motion be explicitly
63
cancelled.
64
65
Not all checks on g_codes are included here. Those checks that are
66
sensitive to whether other g_codes on the same line have been executed
67
yet are made by the functions called by convert_g.
68
69
Our reference sources differ regarding what codes may be used for
70
dwell time.  [Fanuc, page 58] says use "p" or "x". [NCMS, page 23] says
71
use "p", "x", or "u". We are allowing "p" only, since it is consistent
72
with both sources and "x" would be confusing. However, "p" is also used
73
with G10, where it must be an integer, so reading "p" values is a bit
74
more trouble than would be nice.
75
76
*/
77
78
6553
int Interp::check_g_codes(block_pointer block,   //!< pointer to a block to be checked
79
                         setup_pointer settings)        //!< pointer to machine settings
80
{
81
  int mode0, mode1;
82
  int p_int;
83
84
6553
  mode0 = block->g_modes[0];
85
6553
  mode1 = block->g_modes[1];
86
6553
  if (mode0 == -1) {
87
82
  } else if (mode0 == G_4) {
88
3
    CHKS((block->p_number == -1.0), NCE_DWELL_TIME_MISSING_WITH_G4);
89
3
    CHKS((mode1 == G_2 || mode1 == G_3), _("G4 not allowed with G2 or G3 because they both use P"));
90
79
  } else if (mode0 == G_10) {
91
58
    (block->p_number >= 0) ? p_int = (int) (block->p_number +0.5) :p_int = (int) (block->p_number -0.5);
92
58
    CHKS((block->l_number != 2 && block->l_number != 1 && block->l_number != 20 && block->l_number != 10 && block->l_number != 11), _("Line with G10 does not have L1, L10, L11, L2, or L20"));
93
58
    CHKS((((block->p_number + 0.0001) - p_int) > 0.0002),  _("P value not an integer with G10"));
94
58
    CHKS((((block->l_number == 2 || block->l_number == 20) && ((p_int < 0) || (p_int > 9)))), _("P value out of range (0-9) with G10 L%d"), block->l_number);
95
58
    CHKS((((block->l_number == 1 || block->l_number == 10 || block->l_number == 11) && p_int < 1)), _("P value out of range with G10 L%d"), block->l_number);
96
21
  } else if (mode0 == G_28) {
97
21
  } else if (mode0 == G_30) {
98
21
  } else if (mode0 == G_5_3) {
99
1
      CHKS(((mode1 != G_5_2) && (mode1 != -1)), _("Between G5.2 and G5.3 codes, only additional G5.2 codes are allowed."));
100
20
  } else if (mode1 == G_5_2){
101
20
  } else if (mode0 == G_28_1 || mode0 == G_30_1) {
102
20
  } else if (mode0 == G_52) {
103
18
  } else if (mode0 == G_53) {
104
8
    CHKS(((block->motion_to_be != G_0) && (block->motion_to_be != G_1)),
105
        NCE_MUST_USE_G0_OR_G1_WITH_G53);
106
8
    CHKS(((block->g_modes[3] == G_91) ||
107
         ((block->g_modes[3] != G_90) &&
108
          (settings->distance_mode == MODE_INCREMENTAL))),
109
        NCE_CANNOT_USE_G53_INCREMENTAL);
110
10
  } else if (mode0 == G_92) {
111
7
  } else if ((mode0 == G_92_1) || (mode0 == G_92_2) || (mode0 == G_92_3)) {
112
  } else
113
    ERS(NCE_BUG_BAD_G_CODE_MODAL_GROUP_0);
114
  return INTERP_OK;
115
}
116
117
/****************************************************************************/
118
119
/*! check_items
120
121
Returned Value: int
122
   If any one of check_g_codes, check_m_codes, and check_other_codes
123
   returns an error code, this returns that code.
124
   Otherwise, it returns INTERP_OK.
125
126
Side effects: none
127
128
Called by: parse_line
129
130
This runs checks on a block of RS274 code.
131
132
The functions named read_XXXX check for errors which would foul up the
133
reading. This function checks for additional logical errors.
134
135
A block has an array of g_codes, which are initialized to -1
136
(meaning no code). This calls check_g_codes to check the g_codes.
137
138
A block has an array of m_codes, which are initialized to -1
139
(meaning no code). This calls check_m_codes to check the m_codes.
140
141
Items in the block which are not m or g codes are checked by
142
check_other_codes.
143
144
*/
145
146
6553
int Interp::check_items(block_pointer block,     //!< pointer to a block to be checked
147
                       setup_pointer settings)  //!< pointer to machine settings
148
{
149
150
6553
  CHP(check_g_codes(block, settings));
151
6553
  CHP(check_m_codes(block));
152
6553
  CHP(check_other_codes(block));
153
  return INTERP_OK;
154
}
155
156
/****************************************************************************/
157
158
/*! check_m_codes
159
160
Returned Value: int
161
   If any of the following errors occur, this returns the error code shown.
162
   Otherwise, it returns INTERP_OK.
163
   1. There are too many m codes in the block: NCE_TOO_MANY_M_CODES_ON_LINE
164
165
Side effects: none
166
167
Called by: check_items
168
169
This runs checks on m_codes from a block of RS274/NGC instructions.
170
171
The read_m function checks for errors which would foul up the
172
reading. This function checks for additional errors in m_codes.
173
174
*/
175
176
6553
int Interp::check_m_codes(block_pointer block)   //!< pointer to a block to be checked
177
{
178
179
6553
  CHKS((block->m_count > MAX_EMS), NCE_TOO_MANY_M_CODES_ON_LINE);
180
  return INTERP_OK;
181
}
182
183
/****************************************************************************/
184
185
/*! check_other_codes
186
187
Returned Value: int
188
   If any of the following errors occur, this returns the error code shown.
189
   Otherwise, it returns INTERP_OK.
190
   1. An A-axis value is given with a canned cycle (g80 to g89):
191
      NCE_CANNOT_PUT_AN_A_IN_CANNED_CYCLE
192
   2. A B-axis value is given with a canned cycle (g80 to g89):
193
      NCE_CANNOT_PUT_A_B_IN_CANNED_CYCLE
194
   3. A C-axis value is given with a canned cycle (g80 to g89):
195
      NCE_CANNOT_PUT_A_C_IN_CANNED_CYCLE
196
   4. A d word is in a block with no cutter_radius_compensation_on command:
197
      NCE_D_WORD_WITH_NO_G41_OR_G42
198
   5. An h_number is in a block with no tool length offset setting:
199
      NCE_H_WORD_WITH_NO_G43
200
   6. An i_number is in a block with no G code that uses it:
201
      NCE_I_WORD_WITH_NO_G2_OR_G3_OR_G87_TO_USE_IT
202
   7. A j_number is in a block with no G code that uses it:
203
      NCE_J_WORD_WITH_NO_G2_OR_G3_OR_G87_TO_USE_IT
204
   8. A k_number is in a block with no G code that uses it:
205
      NCE_K_WORD_WITH_NO_G2_OR_G3_OR_G87_TO_USE_IT
206
   9. A l_number is in a block with no G code that uses it:
207
      NCE_L_WORD_WITH_NO_CANNED_CYCLE_OR_G10
208
  10. A p_number is in a block with no G code that uses it:
209
      NCE_P_WORD_WITH_NO_G4_G10_G64_G82_G86_G88_G89
210
  11. A q_number is in a block with no G code that uses it:
211
      NCE_Q_WORD_WITH_NO_G83_OR_M66
212
  12. An r_number is in a block with no G code that uses it:
213
      NCE_R_WORD_WITH_NO_G_CODE_THAT_USES_IT
214
  13. A k word is missing from a G33 block:
215
      NCE_K_WORD_MISSING_WITH_G33
216
  14. An e word is in a block with no G76 or M66 to use it:
217
      NCE_E_WORD_WITH_NO_G76_OR_M66_TO_USE_IT
218
219
Side effects: none
220
221
Called by: check_items
222
223
This runs checks on codes from a block of RS274/NGC code which are
224
not m or g codes.
225
226
The functions named read_XXXX check for errors which would foul up the
227
reading. This function checks for additional logical errors in codes.
228
229
*/
230
231
6553
int Interp::check_other_codes(block_pointer block)       //!< pointer to a block of RS274/NGC instructions
232
{
233
  int motion;
234
235
6553
  motion = block->motion_to_be;
236
237
  // bypass ALL checks, argspec takes care of that
238
6553
  if (IS_USER_GCODE(motion)) {
239
      return INTERP_OK;
240
  }
241
  // bypass ALL checks, argspec takes care of that
242
6553
  if (has_user_mcode(&(_setup),block)) {
243
      return INTERP_OK;
244
    }
245
6553
  if (block->a_flag) {
246
3
    CHKS(is_a_cycle(motion), NCE_CANNOT_PUT_AN_A_IN_CANNED_CYCLE);
247
  }
248
6551
  if (block->b_flag) {
249
    CHKS(is_a_cycle(motion), NCE_CANNOT_PUT_A_B_IN_CANNED_CYCLE);
250
  }
251
6551
  if (block->c_flag) {
252
    CHKS(is_a_cycle(motion), NCE_CANNOT_PUT_A_C_IN_CANNED_CYCLE);
253
  }
254
6551
  if (block->d_flag) {
255
62
    CHKS(((block->g_modes[7] != G_41) && (block->g_modes[7] != G_42) &&
256
        (block->g_modes[7] != G_41_1) && (block->g_modes[7] != G_42_1) &&
257
	(block->g_modes[14] != G_96)),
258
        _("D word with no G41, G41.1, G42, G42.1, or G96 to use it"));
259
  }
260
261
6551
  if (block->e_flag) {
262
1
    CHKS(((motion != G_76) && (block->m_modes[5] != 66) &&
263
      (block->m_modes[5] != 67) && (block->m_modes[5] != 68)),
264
       _("E word with no G76, M66, M67 or M68 to use it"));
265
  }
266
267
6551
  if (block->h_flag) {
268
1
    CHKS((block->g_modes[8] != G_43 && motion != G_76 && block->g_modes[8] != G_43_2),
269
      _("H word with no G43 or G76 to use it"));
270
  }
271
272
6551
  if (block->i_flag) {    /* could still be useless if yz_plane arc */
273
399
    CHKS(((motion != G_2) && (motion != G_3) && (motion != G_5) && (motion != G_5_1) &&
274
          (motion != G_76) && (motion != G_87) && (block->g_modes[0] != G_10)),
275
        _("I word with no G2, G3, G5, G5.1, G10, G76, or G87 to use it"));
276
  }
277
278
6551
  if (block->j_flag) {    /* could still be useless if xz_plane arc */
279
455
    CHKS(((motion != G_2) && (motion != G_3) && (motion != G_5) && (motion != G_5_1) &&
280
          (motion != G_76) && (motion != G_87) && (block->g_modes[0] != G_10)),
281
        _("J word with no G2, G3, G5, G5.1, G10, G76 or G87 to use it"));
282
  }
283
284
6551
  if (block->k_flag) {    /* could still be useless if xy_plane arc */
285
70
    CHKS(((motion != G_2) && (motion != G_3) && (motion != G_33) &&
286
        (motion != G_33_1) && (motion != G_76) && (motion != G_87)),
287
        _("K word with no G2, G3, G33, G33.1, G76, or G87 to use it"));
288
  }
289
290
6551
  if (block->l_number != -1) {
291
78
    CHKS((((motion < G_81) || (motion > G_89)) && (motion != G_76) &&
292
         (motion != G_5_2) && (motion != G_73) &&
293
         (block->g_modes[0] != G_10) &&
294
         (block->g_modes[7] != G_41) && (block->g_modes[7] != G_41_1) &&
295
         (block->g_modes[7] != G_42) && (block->g_modes[7] != G_42_1) &&
296
	 (block->m_modes[5] != 66)),
297
         _("L word with no G10, cutter compensation, canned cycle, digital/analog input, or NURBS code"));
298
  }
299
300
6551
  if (block->p_flag) {
301
72
      CHKS(((block->g_modes[0] != G_10) && (block->g_modes[0] != G_4) && (block->g_modes[13] != G_64) &&
302
          (motion != G_76) && (motion != G_82) && (motion != G_86) && (motion != G_88) &&
303
          (motion != G_89) && (motion != G_5) && (motion != G_5_2) &&
304
          (motion != G_2) && (motion != G_3) &&
305
          (block->m_modes[9] != 50) && (block->m_modes[9] != 51) && (block->m_modes[9] != 52) &&
306
          (block->m_modes[9] != 53) && (block->m_modes[5] != 62) && (block->m_modes[5] != 63) &&
307
          (block->m_modes[5] != 64) && (block->m_modes[5] != 65) && (block->m_modes[5] != 66) &&
308
          (block->m_modes[7] != 19) && (block->user_m != 1)),
309
          _("P word with no G2 G3 G4 G10 G64 G5 G5.2 G76 G82 G86 G88 G89"
310
            " or M50 M51 M52 M53 M62 M63 M64 M65 M66 or user M code to use it"));
311
72
      int p_value = round_to_int(block->p_number);
312
72
      CHKS(((motion == G_2 || motion == G_3 || (block->m_modes[7] == 19)) &&
313
	    fabs(p_value - block->p_number) > 0.001),
314
	   _("P value not an integer with M19 G2 or G3"));
315
72
      CHKS((block->m_modes[7] == 19) && ((p_value > 2) || p_value < 0),
316
	   _("P value must be 0,1,or 2 with M19"));
317
72
      CHKS(((motion == G_2 || motion == G_3) && round_to_int(block->p_number) < 1),
318
          _("P value should be 1 or greater with G2 or G3"));
319
  }
320
321
6551
  if (block->q_number != -1.0) {
322
4
      CHKS((motion != G_83) && (motion != G_73) && (motion != G_5) && (block->user_m != 1) && (motion != G_76) &&
323
	   (block->m_modes[5] != 66) && (block->m_modes[5] != 67) && (block->m_modes[5] != 68) &&
324
	   (block->g_modes[0] != G_10) && (block->m_modes[6] != 61) && (block->g_modes[13] != G_64) &&
325
	   (block->m_modes[7] != 19),
326
	   _("Q word with no G5, G10, G64, G73, G76, G83, M19, M66, M67, M68 or user M code that uses it"));
327
  }
328
329
6551
  if (block->r_flag) {
330
67
    CHKS(((motion != G_2) && (motion != G_3) && (motion != G_76) &&
331
         ((motion < G_81) || (motion > G_89)) && (motion != G_73) &&
332
         (block->g_modes[7] != G_41_1) && (block->g_modes[7] != G_42_1) &&
333
         (block->g_modes[0] != G_10) && (block->m_modes[7] != 19) ),
334
        NCE_R_WORD_WITH_NO_G_CODE_THAT_USES_IT);
335
67
    CHKS((block->m_modes[7] == 19) && ((block->r_number > 360.0) || (block->r_number < 0.0)),
336
	   _("R value must be within 0..360 with M19"));
337
  }
338
339
6551
  if (!block->s_flag) {
340
6544
    CHKS((block->g_modes[14] == G_96), NCE_S_WORD_MISSING_WITH_G96);
341
  }
342
343
6551
  if (motion == G_33 || motion == G_33_1) {
344
    CHKS((!block->k_flag), NCE_K_WORD_MISSING_WITH_G33);
345
    CHKS((block->f_flag), NCE_F_WORD_USED_WITH_G33);
346
  }
347
348
6551
  if (motion == G_76) {
349
    // pitch
350
1
    CHKS((block->p_number == -1), NCE_P_WORD_MISSING_WITH_G76);
351
352
1
    CHKS((!block->i_flag || !block->j_flag || !block->k_flag),
353
            NCE_I_J_OR_K_WORDS_MISSING_WITH_G76);
354
  }
355
356
  return INTERP_OK;
357
}