Repository navigation
Expand file tree
/
Copy pathgcode-cycles.c
More file actions
246 lines (220 loc) · 9.22 KB
/
Copy pathgcode-cycles.c
File metadata and controls
246 lines (220 loc) · 9.22 KB
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
/*
============================================================================
Name : gcode-cycles.c
Author : Radu - Eosif Mihailescu
Version : 1.0 (2013-08-06)
Copyright : (C) 2012 Radu - Eosif Mihailescu <radu.mihailescu@linux360.ro>
Description : Canned Cycle Expansion Generator Code
============================================================================
*/
#include <math.h>
#include <stdarg.h>
#include <stddef.h>
#include <stdint.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include "gcode-commons.h"
#include "gcode-cycles.h"
#include "gcode-math.h"
#include "gcode-debugcon.h"
#include "gcode-machine.h"
#include "gcode-parameters.h"
static uint8_t curSlice;
static char *slices[GCODE_CYCLE_MAXSLICES];
static bool _add_generated_line(const char *format, ...) {
va_list ap;
va_start(ap, format);
vsnprintf(slices[0], GCODE_CYCLE_BUFSLICE, format, ap);
va_end(ap);
if((strlen(slices[curSlice]) + strlen(slices[0])) >= GCODE_CYCLE_BUFSLICE) {
if(curSlice < GCODE_CYCLE_MAXSLICES - 1)
slices[++curSlice] = (char *)calloc(GCODE_CYCLE_BUFSLICE, 1);
else {
display_machine_message("PER: Canned cycle injection buffer overflow!");
return false;
}
}
strncat(slices[curSlice], slices[0], GCODE_CYCLE_BUFSLICE);
slices[0][0] = '\0';
return true;
}
static void _reset_slices(void) {
uint8_t i;
for(i = curSlice; i > 1; i--)
free((void *)slices[i]);
curSlice = 1;
slices[curSlice][0] = '\0';
}
static char *_build_cycle(void) {
uint8_t i;
size_t size = 0;
char *cycle;
for(i = curSlice; i; i--) size += strlen(slices[i]);
cycle = (char *)calloc(size + 1, 1);
for(i = 1; i <= curSlice; i++) strncat(cycle, slices[i], size);
_reset_slices();
return cycle;
}
bool init_cycles(void *data) {
slices[0] = (char *)calloc(GCODE_CYCLE_BUFSLICE, 1);
slices[1] = (char *)calloc(GCODE_CYCLE_BUFSLICE, 1);
_reset_slices();
GCODE_DEBUG("Canned Cycles up, using %d bytes injection buffer",
GCODE_CYCLE_BUFSLICE * GCODE_CYCLE_MAXSLICES);
return true;
}
char *generate_cycles(TGCodeState state, double X, double Y, double Z) {
//TODO: factor feedRetract out as it's superfluous.
bool feedRetract = false, firstTime = true, fixedR = false;
uint16_t peckSteps;
double extraMove, howFarDown = 0.0;
/* Repetitions */
while(state.L--) {
/* First preparatory move */
_add_generated_line("G00 X" GCODE_REAL_FORMAT " Y" GCODE_REAL_FORMAT "\n",
X, Y);
/* If we're in relative mode, we need to fix R *after* the first iteration
* because R is initially relative to lastZ and thereafter needs to be
* relative to Z. */
if(firstTime)
firstTime = false;
else if(!fixedR) {
if(state.system.absolute == GCODE_RELATIVE) state.R = -Z;
fixedR = true;
}
/* Second preparatory move */
_add_generated_line("G00 Z" GCODE_REAL_FORMAT "\n", state.R);
/* Actual canned cycle */
switch(state.cycle) {
case GCODE_CYCLE_DRILL_ND:
case GCODE_CYCLE_DRILL_WD:
case GCODE_CYCLE_BORING_ND_NS:
case GCODE_CYCLE_BORING_WD_WS:
case GCODE_CYCLE_BORING_MANUAL:
case GCODE_CYCLE_BORING_WD_NS:
_add_generated_line("G01 Z" GCODE_REAL_FORMAT "\n", Z);
if(state.cycle == GCODE_CYCLE_DRILL_WD ||
state.cycle == GCODE_CYCLE_BORING_WD_WS ||
state.cycle == GCODE_CYCLE_BORING_MANUAL ||
state.cycle == GCODE_CYCLE_BORING_WD_NS)
_add_generated_line("G04 P" GCODE_REAL_FORMAT "\n", state.P);
if(state.cycle == GCODE_CYCLE_BORING_WD_WS ||
state.cycle == GCODE_CYCLE_BORING_MANUAL)
_add_generated_line("M05\n");
if(state.cycle == GCODE_CYCLE_BORING_MANUAL)
_add_generated_line("M01\n");
if(state.cycle == GCODE_CYCLE_BORING_ND_NS ||
state.cycle == GCODE_CYCLE_BORING_WD_NS)
feedRetract = true;
break;
case GCODE_CYCLE_TAP_LH:
case GCODE_CYCLE_TAP_RH:
/* Stop spindle, disable overrides, per revolution */
_add_generated_line("M05 M49 G95 F" GCODE_REAL_FORMAT "\n", state.K);
/* Start spindle, exact stop check, feed in */
_add_generated_line("M%02d G09 G01 Z" GCODE_REAL_FORMAT "\n",
(state.cycle == GCODE_CYCLE_TAP_LH ? 4 : 3),
Z);
/* Spindle will stop at end of move, but better safe than sorry */
_add_generated_line("M05\n");
/* Reverse spindle, exact stop check, feed out */
_add_generated_line("M%02d G09 G01 Z" GCODE_REAL_FORMAT "\n",
(state.cycle == GCODE_CYCLE_TAP_RH ? 4 : 3),
state.R);
/* Spindle will stop at end of move, but better safe than sorry */
_add_generated_line("M05\n");
/* Restore feed mode and value, enable overrides */
_add_generated_line("G%2d M48 F" GCODE_REAL_FORMAT "\n",
state.feedMode, state.F);
/* Start spindle */
_add_generated_line("M%02d\n",
(state.cycle == GCODE_CYCLE_TAP_LH ? 4 : 3));
break;
case GCODE_CYCLE_BORING_BACK:
_add_generated_line("G91 G00 X" GCODE_REAL_FORMAT " Y" GCODE_REAL_FORMAT "\n",
state.I, state.J);
_add_generated_line("M05\n");
_add_generated_line("M19\n");
_add_generated_line("G%02d G00 Z" GCODE_REAL_FORMAT "\n",
state.system.absolute, Z);
_add_generated_line("G00 X" GCODE_REAL_FORMAT " Y" GCODE_REAL_FORMAT "\n",
(state.system.absolute == GCODE_ABSOLUTE ?
X : -state.I),
(state.system.absolute == GCODE_ABSOLUTE ?
Y : -state.J));
//TODO: make it start in the same direction it was turning before
_add_generated_line("M03\n");
_add_generated_line("G01 Z" GCODE_REAL_FORMAT "\n", state.K);
_add_generated_line("G01 Z" GCODE_REAL_FORMAT "\n",
(state.system.absolute == GCODE_ABSOLUTE ?
Z : -state.K));
_add_generated_line("M05\n");
_add_generated_line("M19\n");
_add_generated_line("G91 G00 X" GCODE_REAL_FORMAT " Y" GCODE_REAL_FORMAT "\n",
state.I, state.J);
/* This does the final move here: we need it in order to satisfy the
* condition that every cycle ends in the same spot it started */
_add_generated_line("G%02d G00 Z" GCODE_REAL_FORMAT "\n",
state.system.absolute, state.R);
_add_generated_line("G00 X" GCODE_REAL_FORMAT " Y" GCODE_REAL_FORMAT "\n",
(state.system.absolute == GCODE_ABSOLUTE ?
X : -state.I),
(state.system.absolute == GCODE_ABSOLUTE ?
Y : -state.J));
//TODO: make it start in the same direction it was turning before
_add_generated_line("M03\n");
break;
case GCODE_CYCLE_DRILL_PP:
case GCODE_CYCLE_DRILL_PF:
/* Calculate how many movements by Q we need to cover Z. The quotient
* is the number of steps. If there is any remainder, that will be an
* extra move towards Z proper */
peckSteps = (uint16_t)trunc(
state.R -
(state.system.absolute == GCODE_ABSOLUTE ? Z : 0) / state.Q);
extraMove = fmod(
state.R -
(state.system.absolute == GCODE_ABSOLUTE ? Z : 0), state.Q);
/* Perform the pecks */
while(peckSteps--) {
/* Z goes down, so feed by -Q in relative mode */
_add_generated_line("G91 G01 Z" GCODE_REAL_FORMAT "\n", -state.Q);
if(state.cycle == GCODE_CYCLE_DRILL_PP)
/* Partial retract: traverse up by +Q/2 */
_add_generated_line("G00 Z" GCODE_REAL_FORMAT "\n", state.Q / 2);
else {
/* Full retract: traverse up to where we began, traverse down to
* where we were before less Q/2 */
howFarDown += state.Q;
_add_generated_line("G00 Z" GCODE_REAL_FORMAT "\n", howFarDown);
_add_generated_line("G00 Z" GCODE_REAL_FORMAT "\n",
-(howFarDown - state.Q / 2));
}
_add_generated_line("G01 Z" GCODE_REAL_FORMAT "\n", -(state.Q / 2));
}
/* Still extraMove to go until we reach Z */
if(fpclassify(extraMove) == FP_NORMAL)
_add_generated_line("G01 Z" GCODE_REAL_FORMAT "\n", -extraMove);
/* Restore previous measurement mode */
_add_generated_line("G%02d\n", state.system.absolute);
break;
}
/* Final move */
if(state.cycle != GCODE_CYCLE_BORING_BACK)
_add_generated_line("G%02d Z" GCODE_REAL_FORMAT "\n", (int)feedRetract,
state.R);
}
/* Any extras ? */
if(state.cycle == GCODE_CYCLE_BORING_WD_WS ||
state.cycle == GCODE_CYCLE_BORING_MANUAL)
//TODO: make it start in the same direction it was turning before
_add_generated_line("M03\n");
return _build_cycle();
}
bool done_cycles(void) {
_reset_slices();
free((void *)slices[0]);
free((void *)slices[1]);
return true;
}