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 |
|
} |