// Motor and clock parameters
// 2048 * 90 / 12 / 60 = 256
#define STEPS_PER_MIN 256

// one minute per micro seconds. Theoretically it should be 60000000,
// and can be used to adjust the clock speed.
#define MIN_PER_USEC (60000500LL)

#define SAFETY_MOTION (STEPS_PER_MIN)

// wait for a single step of stepper
int delaytime = 6;

// ports used to control the stepper motor
// if your motor rotate to the opposite direction, 
// change the order as {2, 3, 4, 5};
int port[4] = {22, 21, 2, 1};

// sequence of stepper motor control
int seq[4][4] = {
  {  LOW,  LOW, HIGH,  LOW},
  {  LOW,  LOW,  LOW, HIGH},
  { HIGH,  LOW,  LOW,  LOW},
  {  LOW, HIGH,  LOW,  LOW}
};

void rotate(int step) {
  static int phase = 0;
  int i, j;
  int delta = (step > 0) ? 1 : 3;
  int dt = delaytime * 3;

  step = (step > 0) ? step : -step;
  for(j = 0; j < step; j++) {
    phase = (phase + delta) % 4;
    for(i = 0; i < 4; i++) {
      digitalWrite(port[i], seq[phase][i]);
    }
    delay(dt);
    if(dt > delaytime) dt--;
  }
  // power cut
  for(i = 0; i < 4; i++) {
    digitalWrite(port[i], LOW);
  }
}

void setup() {
  pinMode(port[0], OUTPUT);
  pinMode(port[1], OUTPUT);
  pinMode(port[2], OUTPUT);
  pinMode(port[3], OUTPUT);

  rotate(-STEPS_PER_MIN * 2); // initialize
}

void loop() {
  static uint64_t prev_cnt = -1;
  uint64_t cnt, usec;

  usec = (uint64_t)millis() * (uint64_t)1000; 
  cnt = usec / MIN_PER_USEC;
  if(prev_cnt == cnt) {
    return;
  }
  prev_cnt = cnt;
  
  rotate(STEPS_PER_MIN + SAFETY_MOTION ); // go too far a bit
  rotate(-SAFETY_MOTION); // alignment
}
