#include <stdio.h>

// this particular program defines its zero as the center of the rectangle to be cut...

float x = 0.0, y = 0.0, z = 0.0; // in mm * 100
#define WIDTH 1.25   // 1.25mm cutting head
int spindle_speed = 6000,
    z_plunge_speed = 200, z_retract_speed = 500,
    xymove_speed = 500, xycut_speed = 200,
    xy_speed = 0, current_default_speed = 0;

void gcode(char *s) {
  fprintf(stdout, "%s\n", s);
}

void setheight(float absz, int zspeed) {
  z = absz; current_default_speed = zspeed;
  fprintf(stdout, "G1 Z%0.1f F%0d\n", z, zspeed);
}

void retract(void) {
  setheight(10.0, z_retract_speed);
}

void penup(void) {
  setheight(5.0, z_plunge_speed);
  xy_speed = xymove_speed;
}

void pendown(void) {
  setheight(-0.2, z_plunge_speed);
  xy_speed = xycut_speed;
}

void gotoxy(float x, float y) {
  if (xy_speed != current_default_speed) {
    current_default_speed = xy_speed;
    fprintf(stdout, "G1 X%0.3f Y%0.3f F%0d\n", x, y, xy_speed);
  } else {
    fprintf(stdout, "G1 X%0.3f Y%0.3f\n", x, y);
  }
}

void move(float dx, float dy) {
  x += dx; y += dy;
  gotoxy(x, y);
}

void north(float dy) {
  move(0.0, dy);
}

void south(float dy) {
  move(0.0, -dy);
}

void east(float dx) {
  move(dx, 0.0);
}

void west(float dx) {
  move(-dx, 0.0);
}

void start_spindle(int speed) {
  //fprintf(stdout, "M3 S%0d\n", speed); // assuming your spindle output hasn't blown up :-(
}

void stop_spindle(void) {
  //gcode("M5");
}

void finished(void) {
  gcode("M30");
}

int main(int argc, char **argv) {
  // to do: parameters w h in mm
  float width = WIDTH;

  gcode("G90"); // absolute positioning system
  penup();
  gotoxy(-width/2.0, -width/2.0); // ensure true center
  start_spindle(spindle_speed);
  pendown();
  north(width);
  east(width);
  south(width);
  west(width + WIDTH);
  do {
    width += (WIDTH*2.0);
    north(width-WIDTH);
    east(width);
    south(width);
    west(width + WIDTH);
  } while (width < 65.0); // 6.5cm x 6.5cm
  penup();
  stop_spindle();
  gotoxy(width/2.0, width/2.0); // park at top right, easier to remove piece
  retract();
  finished();
  fflush(stdout);
  return 0;
}