cnc.c


1
/***************************************************************************/
2
/*  CNC-drilling maschine with 3 stepper motors on parallel interface      */
3
/***************************************************************************/
4
/*  DJGPP for DOS:   set GO32=driver /gcc/drivers/stdvga.grn ansi          */
5
/*                   gcc cnc.c -o cnc.out -Wall -lpc -lgrx -lm             */
6
/*  Str,1998-2001    coff2exe -s go32.exe %1.out                           */
7
/***************************************************************************/
8
/*  connections: bits 5..0: Z-DIR, Z-CLK, Y-DIR, Y-CLK, X-DIR, X-CLK       */ 
9
/*  commands: a character for each step, undefined chars are ignored       */
10
/*  'XYZ': increase (X=table left, Y=table to front, Z=tool down)          */
11
/*  'xyz': decrease, '1234': 45 degree move XY/xY/xy/Xy, '0': nop          */
12
/***************************************************************************/
13
14
#include <stdio.h>
15
16
#include <ctype.h>
17
18
#define  COLORS    16
19
#define  WIDTH     640
20
#define  HIGHT     480
21
#define  BLACK     0
22
#define  RED       1
23
#define  GREEN     2
24
#define  BLUE      3
25
#define  YELLOW    4
26
#define  CYAN      5
27
#define  MAGENTA   6
28
#define  ORANGE    7
29
#define  WHITE     15
30
#define  XRES      96       /* resolution: steps/mm */
31
#define  YRES      96
32
#define  ZRES      56
33
#define  XMAX      176322   /* max distance: mm */
34
#define  YMAX      116322
35
#define  ZMAX      14322
36
#define  MRG       8                 /* Left margin */
37
#define  TOP       4                  /* Top margin */
38
#define  GROOF     2.0           /* z-movement hpgl */
39
#define  PUNCH     3.0       /* z-movement excellon */
40
#define  SPEED     5                    /* msec/step */
41
#define  OFF       0x80
42
43
44
#define float int;
45
int port = 0;
46
int trace = BLUE;
47
int items = 0;
48
float mtime = 0;
49
float stepw = 40;
50
int xpos, ypos, zpos;
51
int xofs, yofs, zofs;
52
float curx, cury, curz;
53
int scode[4] = {0x09, 0x0A, 0x06, 0x05};
54
int down = 0;
55
56
int INP(int p) { int *t; int i; t=p; i=*t&0xff; return i; }
57
58
/*
59
int printfXY(int x, int y, char *fmt, ...)
60
{ va_list ap;
61
  int cnt;
62
  char buf[256];
63
  va_start(ap, fmt);
64
  cnt = vsprintf(buf, fmt, ap);
65
  va_end(ap);
66
  return cnt;
67
}
68
69
void message(char *fmt, ...)
70
{ va_list ap;
71
  int cnt;
72
  char buf[256];
73
74
  va_start(ap, fmt);
75
  cnt = vsprintf(buf, fmt, ap);
76
  va_end(ap);
77
}
78
*/
79
int printfXY(int x, int y, char*fmt) {}
80
void message(char *fmt) {}
81
#define void
82
83
/*
84
void GrafMode(void)
85
{
86
  printfXY(MRG, TOP, "calibrating! please wait...");
87
  printfXY(MRG, 408, "X        mm        inch");
88
  printfXY(MRG, 426, "Y        mm        inch");
89
  printfXY(MRG, 444, "Z        mm        inch");
90
  printfXY(250, 408, "U Up        mm", GROOF);
91
  printfXY(250, 426, "D Down      mm", GROOF);
92
  printfXY(250, 444, "! Drill     mm", PUNCH);
93
  printfXY(318, 408, "%3.1f", GROOF);
94
  printfXY(318, 426, "%3.1f", GROOF);
95
  printfXY(318, 444, "%3.1f", PUNCH);
96
  printfXY(390, 408, "E Excellon-File");
97
  printfXY(390, 426, "H HPGL-File");
98
  printfXY(390, 444, "P Park");
99
  printfXY(530, 408, "I Init");
100
  printfXY(530, 426, "O Origin");
101
  printfXY(530, 444, "R Reset");
102
}
103
*/
104
105
void Coords(void)
106
{
107
/*
108
  printfXY(MRG+12, 408, "%7.2f", curx);
109
  printfXY(MRG+100, 408, "%6.3f", curx/25.4);
110
  printfXY(MRG+12, 426, "%7.2f", cury);
111
  printfXY(MRG+100, 426, "%6.3f", cury/25.4);
112
  printfXY(MRG+12, 444, "%7.2f", curz);
113
  printfXY(MRG+100, 444, "%6.3f", curz/25.4);
114
*/
115
}
116
117
void DataOut(unsigned char data)
118
{
119
  if (!port) return;
120
  outportb(port + 2, 0x0F);
121
  outportb(port, data);
122
  outportb(port + 2, 0x0E);
123
}
124
125
int Step(unsigned char ch)
126
{
127
  switch(ch)
128
    {
129
      case 'X': if (xpos < XMAX) xpos++; 
130
                else return 0; break;
131
      case 'x': if (xpos > 0) xpos--; 
132
                else return 0; break;
133
      case 'Y': if (ypos < YMAX) ypos++; 
134
                else return 0; break;
135
      case 'y': if (ypos > 0) ypos--; 
136
                else return 0; break;
137
      case 'Z': if (zpos < ZMAX) zpos++; 
138
                else return 0; break;
139
      case 'z': if (zpos > 0) zpos--; 
140
                else return 0; break;
141
      case '1': if ((xpos < XMAX) && (ypos < YMAX)) {xpos++; ypos++;} 
142
                else return 0; break;
143
      case '2': if ((xpos > 0) && (ypos < YMAX)) {xpos--; ypos++;} 
144
                else return 0; break;
145
      case '3': if ((xpos > 0) && (ypos > 0)) {xpos--; ypos--;} 
146
                else return 0; break;
147
      case '4': if ((xpos < XMAX) && (ypos > 0)) {xpos++; ypos--;} 
148
                else return 0; break;
149
      case '0': break;
150
      default: return 1; break;
151
    }
152
  mtime = mtime + SPEED + 50;
153
  if (port == 0) return 0;
154
  DataOut(0x50 + scode[xpos%4]);
155
  DataOut(0x20 + scode[ypos%4]);
156
  DataOut(0x30 + scode[zpos%4]);
157
  delay(SPEED);
158
  return 0;
159
}
160
161
int Move(int x, int y, int z)
162
{
163
  int dx, dy, m, n, o, i;
164
  char a, b;
165
  x += xofs; if (x < 0 || x > XMAX) return 1;
166
  y += yofs; if (y < 0 || y > YMAX) return 1;
167
  z += zofs; if (z < 0 || z > ZMAX) return 1;
168
169
  dx = x - xpos;
170
  dy = y - ypos;
171
  a = '\000';
172
  
173
  if (dx > 0 && dy > 0)
174
  {
175
    m = dx; n = dy; a = '1'; b = 'Y';
176
    if (m > n) {o = m; m = n; n = o; b = 'X';}
177
  }
178
179
  if (dx < 0 && dy > 0)
180
  {
181
    m = dx * -1; n = dy; a = '2'; b = 'Y';
182
    if (m > n) {o = m; m = n; n = o; b = 'x';}
183
  }
184
185
  if (dx < 0 && dy < 0)
186
  {
187
    m = dx * -1; n = dy * -1; a = '3'; b = 'y';
188
    if (m > n) {o = m; m = n; n = o; b = 'x';}
189
  }
190
191
  if (dx > 0 && dy < 0)
192
  {
193
    m = dx; n = dy * -1; a = '4'; b = 'y';
194
    if (m > n) {o = m; m = n; n = o; b = 'X';}
195
  }
196
197
  if (a)
198
  {
199
    o = n/2;
200
    for (i = 0; i < n; i++)
201
    {
202
      o += m;
203
      if (n < o) {o -= n; Step(a);} else Step(b);
204
    }
205
  }
206
207
  while (x > xpos) Step('X');
208
  while (x < xpos) Step('x');
209
  while (y > ypos) Step('Y');
210
  while (y < ypos) Step('y');
211
  while (z > zpos) Step('Z');
212
  while (z < zpos) Step('z');
213
  return 0;
214
}
215
216
;
217
218
int aMove(float x, float y, float z)
219
{ message("");
220
  curx = z;
221
  cury = y;
222
  curz = z;
223
  /* if (Move(curx*XRES-0.6, cury*YRES-0.6, curz*ZRES-0.6)) return 1;
224
  */
225
  Move(curx,cury,z);
226
  Coords();
227
  return 0;
228
}
229
230
int rMove(float x, float y, float z)
231
{ message("");
232
  curx += x;
233
  cury += y;
234
  curz += z;
235
 /* if (Move(curx*XRES-0.6,cury*YRES-0.6,curz*ZRES-0.6)) return 1;
236
  */
237
  Move(curx,cury,z);
238
  Coords();
239
  return 0;
240
}
241
242
void Drill(void)
243
{
244
  int trc;
245
  trc = trace;
246
  trace = RED;
247
  rMove(0.0, 0.0, PUNCH);
248
  trace = GREEN;
249
  rMove(0.0, 0.0, (-1.0)*PUNCH);
250
  trace = trc;
251
}
252
253
void Penup(void)
254
{
255
  int trc;
256
  if (!down) return;
257
  trc = trace;
258
  trace = GREEN;
259
  rMove(0.0, 0.0, (-1.0)*GROOF);
260
  trace = trc;
261
  down = !down;
262
}
263
264
void Pendown(void)
265
{
266
  int trc;
267
  if (down) return;
268
  trc = trace;
269
  trace = RED;
270
  rMove(0.0, 0.0, GROOF);
271
  trace = trc;
272
  down = !down;
273
}
274
275
void Init()
276
{
277
  Penup();
278
  xofs = xpos;
279
  yofs = ypos;
280
  zofs = zpos;
281
  curx = cury = curz = 0.0;
282
  Step('0');
283
  Coords();
284
}
285
286
void CkPort(int p)
287
{
288
  port = p;
289
  outportb(port+2, 0x04);
290
  if ((inportb(port+1) & 0x08) == 0) {port = 0; return;}
291
  outportb(port+2, 0x00);
292
  if ((inportb(port+1) & 0x08) != 0) port = 0;
293
}
294
295
int Calibrate(void)
296
{
297
  DataOut(OFF); /* enable and clear outputs */
298
  xpos = XMAX; while (!(inportb(port+1) & 0x40) && xpos) Step('x');
299
  if (!xpos) return 1;
300
  xpos = 0; while ((inportb(port+1) & 0x40) && (xpos < XRES)) Step('X');
301
  if (xpos == XRES) return 1;
302
  ypos = YMAX; while ((inportb(port+1) & 0x80) && ypos) Step('y');
303
  if (!ypos) return 1;
304
  ypos = 0; while (!(inportb(port+1) & 0x80) && (ypos < YRES)) Step('Y');
305
  if (ypos == YRES) return 1;
306
  zpos = ZMAX; while (!(inportb(port+1) & 0x20) && zpos) Step('z');
307
  if (!zpos) return 1;
308
  zpos = 0; while ((inportb(port+1) & 0x20) && (zpos < ZRES)) Step('Z');
309
  if (zpos == ZRES) return 1;
310
  return 0;
311
}
312
313
void Start(int check)
314
{
315
  if (check)
316
  {
317
    CkPort(0x378);
318
    if (!port) CkPort(0x378);
319
    if (!port) CkPort(0x3BC);
320
    if (port) if (Calibrate()) port = 0;
321
  }
322
  xpos = ypos = zpos = 0;
323
  Init();
324
  message("port %x", port);
325
}
326
327
void prompt(char *s)
328
{
329
  int i = 0;
330
  while (i < 74)
331
  {
332
    s[i] = '\000';
333
    message("file: %s", s);
334
    s[i] = getch();
335
    if (s[i] == '\015') {s[i] = '\000'; return;}
336
    if (s[i] == '\010') {if (i) i--; s[i] = '\000';} 
337
    else if (s[i] >= ' ') i++;
338
  }
339
  s[74] = '\000';
340
}
341
342
int Term(int poll)
343
{
344
  if (poll)
345
  {
346
    if (!kbhit()) return 0;
347
    getch();
348
    message("pause: esc to terminate, other key to continue");
349
  }
350
  if (getch() != '\033') {message(""); return 0;}
351
  message("terminated");
352
  return 1;
353
}
354
355
void Excellon(void)
356
{
357
  FILE *in;
358
  char fname[128];
359
  char str[256];
360
  int i, n, m;
361
  int mirror = 0;
362
  float x, y, xm, s, unit = 0.000254, xof = 100000, yof = 100000;
363
  message("Init done at %f/%f ca 0.5mm above board? no: esc", xof, yof);
364
  if (Term(0)) return;
365
  prompt(fname);
366
  in = fopen(fname, "rb");
367
  if (in == NULL) {message("file %s not found", fname); return;}
368
  Penup();
369
  m = items = 0;
370
  mtime = 0.0;
371
  trace = CYAN;
372
  while (1) {
373
    if (Term(1)) break;
374
    fgets(str, 256, in);
375
    if (feof(in)) break;
376
    for (i = 0; str[i] > ' '; i++);
377
    str[i] = '\000';
378
    if (str[0] == 'T') {
379
      message("mount tool %s, any key when ready", str);
380
      if (Term(0)) break;
381
    }
382
    if (str[0] == 'X') {
383
      x = y = 0.0; i = 1;
384
      while (str[i] >= '0' && str[i] <= '9') {x = x*10+str[i]-'0'; i++;}
385
      i++;
386
      while (str[i] >= '0' && str[i] <= '9') {y = y*10+str[i]-'0'; i++;}
387
      if (mirror) x = (xm - x);
388
      x = x*unit;
389
      y = y*unit;
390
      if (aMove(x-(xof*unit), y-(yof*unit), 0.0) == 0) {Drill(); items++;}
391
      m++;
392
    }
393
    if (str[0] == 'R') {
394
      x = y = 0.0; n = 0; s = 1.0; i = 1;
395
      if (mirror) s = -1.0;
396
      while (str[i] >= '0' && str[i] <= '9') {n = n*10+str[i]-'0'; i++;}
397
      if (str[i++] == 'X') {
398
        if (str[i] == '-') {s = s * -1.0; i++;}
399
        while (str[i] >= '0' && str[i] <= '9') {x = x*10+str[i]-'0'; i++;}
400
        x = s*x*unit;
401
      } else {
402
        if (str[i] == '-') {s = s * -1.0; i++;}
403
        while (str[i] >= '0' && str[i] <= '9') {y = y*10+str[i]-'0'; i++;}
404
        y = s*y*unit;
405
      }
406
      for (i = 0; i < n; i++) {
407
        if (rMove(x, y, 0.0) == 0) {Drill(); items++;}
408
        m++;
409
      }
410
    }
411
    if (str[0] == 'M' && str[1] == 'I' && str[2] == 'R') 
412
    {
413
      xm = 0.0; i = 3;
414
      while (str[i] >= '0' && str[i] <= '9') {xm = xm*10+str[i]-'0'; i++;}
415
      mirror = 1;
416
    }
417
  }
418
  fclose(in);
419
  trace = BLUE;
420
  message("%s done, %i holes of %i processed, approx. %0.0f minutes", 
421
           fname, items, m, mtime/60000.0);
422
}
423
424
void Excellon2(void)
425
{
426
  FILE *in;
427
  char fname[128];
428
  char str[256];
429
  float xy[2*1024];
430
  int i, j, n, m;
431
  float x, y, s, unit = 0.000254, xof = 100000, yof = 100000;
432
  message("Init done at %f/%f ca 0.5mm above board? no: esc", xof, yof);
433
  if (Term(0)) return;
434
  prompt(fname);
435
  in = fopen(fname, "rb");
436
  if (in == NULL) {message("file %s not found", fname); return;}
437
  Penup();
438
  m = items = 0;
439
  mtime = 0.0;
440
  trace = CYAN;
441
  while (1) { 
442
    fgets(str, 256, in);
443
    if (feof(in) || m >= 1024) break;
444
    for (i = 0; str[i] > ' '; i++);
445
    str[i] = '\000';
446
    if (str[0] == 'X')
447
    {
448
      x = y = 0.0; i = 1;
449
      while (str[i] >= '0' && str[i] <= '9') {x = x*10+str[i]-'0'; i++;}
450
      i++;
451
      while (str[i] >= '0' && str[i] <= '9') {y = y*10+str[i]-'0'; i++;}
452
      xy[2*m] = x*unit - xof*unit;
453
      xy[2*m+1] = y*unit - yof*unit;
454
      m++;
455
    }
456
    if (str[0] == 'R') {
457
      x = y = 0.0; n = 0; s = 1.0; i = 1;
458
      while (str[i] >= '0' && str[i] <= '9') {n = n*10+str[i]-'0'; i++;}
459
      if (str[i++] == 'X') {
460
        if (str[i] == '-') {s = s * -1.0; i++;}
461
        while (str[i] >= '0' && str[i] <= '9') {x = x*10+str[i]-'0'; i++;}
462
        x = s*x*unit;
463
      } else {
464
        if (str[i] == '-') {s = s * -1.0; i++;}
465
        while (str[i] >= '0' && str[i] <= '9') {y = y*10+str[i]-'0'; i++;}
466
        y = s*y*unit;
467
      }
468
      j = m - 1;
469
      for (i = 0; i < n; i++) {
470
        xy[2*m] = xy[2*j] + i*x*unit;
471
        xy[2*m+1] = xy[2*j+1] + i*y*unit;
472
        m++;
473
      }
474
    }
475
  }
476
  fclose(in);
477
  for (i = 0; i < m; i++) {
478
    if (Term(1)) break;
479
    n = 0; s = 999999.9;
480
    for (j = 0; j < m; j++) {
481
      x = curx - xy[2*j];
482
      y = cury - xy[2*j+1];
483
      if (x*x + y*y < s) {
484
        s = x*x + y*y;
485
        n = j;
486
      }
487
    }
488
    if (aMove(xy[2*n], xy[2*n+1], 0.0) == 0) {Drill(); items++;}
489
    xy[2*n] = xy[2*n+1] = 999.9;
490
  }
491
  trace = BLUE;
492
  message("%s done, %i holes of %i processed, approx. %0.0f minutes", 
493
           fname, items, m, mtime/60000.0);
494
}
495
496
void HPGL(void)
497
{
498
  FILE *in;
499
  char fname[128];
500
  char str[256];
501
  int i;
502
  int mirror = 0;
503
  float x, y, x0, y0, xm;
504
  prompt(fname);
505
  in = fopen(fname, "rb");
506
  if (in == NULL) {
507
    message("file %s not found", fname);
508
    return;
509
  }
510
  Penup();
511
  items = 0;
512
  mtime = 0.0;
513
  x0 = y0 = 0.0;
514
  while (1) {
515
    if (Term(1)) break;
516
    i = 0;
517
    do {
518
      str[i] = getc(in);
519
      if (str[i] > ' ' && str[i] != ';') i++;
520
    } while (str[i] != ';' && i < 256 && !feof(in));
521
    if (str[i] != ';') break;
522
    str[i] = '\000';
523
    if (str[0] == 'P' && str[1] == 'A') {
524
      x = y = 0.0; i = 2;
525
      while (str[i] >= '0' && str[i] <= '9') {x = x*10+str[i]-'0'; i++;}
526
      if (str[i] != '\000') i++;
527
      while (str[i] >= '0' && str[i] <= '9') {y = y*10+str[i]-'0'; i++;}
528
      x -= x0;
529
      y -= y0;
530
      if (mirror) x = (xm - x);
531
      x = x*0.025;
532
      y = y*0.025;
533
      if (down) trace = MAGENTA; else trace = CYAN;
534
      aMove(x, y, curz);
535
      if (down) items++;
536
    }
537
    if (str[0] == 'P' && str[1] == 'D') Pendown();
538
    if (str[0] == 'P' && str[1] == 'U') Penup();
539
    if (str[0] == 'S' && str[1] == 'P') {
540
      message("select pen %s, any key when ready", str);
541
      if (Term(0)) break;
542
    }
543
    if (str[0] == 'I' && str[1] == 'W') {
544
      x0 = y0 = 0.0; i = 2;
545
      while (str[i] >= '0' && str[i] <= '9') {x0 = x0*10+str[i]-'0'; i++;}
546
      if (str[i] != '\000') i++;
547
      while (str[i] >= '0' && str[i] <= '9') {y0 = y0*10+str[i]-'0'; i++;}
548
    }
549
    if (str[0] == 'M' && str[1] == 'I' && str[2] == 'R') {
550
      xm = 0.0; i = 3;
551
      while (str[i] >= '0' && str[i] <= '9') {xm = xm*10+str[i]-'0'; i++;}
552
      mirror = 1;
553
    }
554
    if (str[0] == 'M' && str[1] == 'I') mirror = 1;
555
  }
556
  fclose(in);
557
  trace = BLUE;
558
  message("%s done, %i segments processed, approx. %0.0f minutes", 
559
           fname, items, mtime/60000.0);
560
}
561
562
int main(int argc, char *argv[])
563
{
564
  unsigned char ch, sc;
565
  
566
567
568
569
  Start(argc == 1);
570
  while (kbhit()) getch();
571
  do { 
572
    ch = getch();
573
    switch(tolower(ch)) {
574
      case 'q': ch = '\033'; break;
575
      case 'i': Init(); message("coordinates set to (0,0,0)"); break;
576
      case 'e': if (ch == 'E') Excellon2(); else Excellon(); break;
577
      case 'h': HPGL(); break;
578
      case 'o': aMove(0.0, 0.0, 0.0); message("origin (0,0,0)"); break;
579
      case 'r': Start(argc == 1); break;
580
      case 'p': xofs = yofs = zofs = 0; Move(xpos, ypos, 0); xofs = XMAX/2; 
581
                Move(0, 0, 0); Init(); message("parked"); break;
582
      case 'u': Penup(); break;
583
      case 'd': Pendown(); break;
584
      case '!': Drill(); break;
585
      case '+': rMove(0.0, 0.0, stepw); break;
586
      case '-': rMove(0.0, 0.0, -1.0*stepw); break;
587
      case '\000': sc = getch(); 
588
                if (sc == 71) rMove(-1.0*stepw, stepw, 0.0);
589
                if (sc == 72) rMove(0.0, stepw, 0.0);
590
                if (sc == 73) rMove(stepw, stepw, 0.0);
591
                if (sc == 75) rMove(-1.0*stepw, 0.0, 0.0);
592
                if (sc == 76) {
593
                  if (stepw < 0.05) stepw = 0.1;
594
                  else if (stepw < 0.2) stepw = 0.254;
595
                  else if (stepw < 0.5) stepw = 1.0;
596
                  else if (stepw < 2.0) stepw = 2.54;
597
                  else if (stepw < 5.0) stepw = 10.0;
598
                  else if (stepw < 20.0) stepw = 25.4;
599
                  else stepw = 0.01;
600
                  message("stepwidth %6.2fmm %6.4finch", 
601
                  stepw, stepw/25.4);
602
                }
603
                if (sc == 77) rMove(stepw, 0.0, 0.0);
604
                if (sc == 79) rMove(-1.0*stepw, -1.0*stepw, 0.0);
605
                if (sc == 80) rMove(0.0, -1.0*stepw, 0.0);
606
                if (sc == 81) rMove(stepw, -1.0*stepw, 0.0);
607
                break;
608
      default: break;
609
    }
610
  } while (ch != '\033');
611
  DataOut(OFF);
612
  return 0;
613
}