/***************** Optimized step sequencer *****************
  Author: Antoine Laloux
*************************************************************/

const uint8_t CLOCK_PIN = 10;
const uint8_t RESET_PIN = 11;
const uint8_t STEP_MAX_PIN = 21;

const uint8_t OUT_PINS[16] = {
  12, 13, 14, 15, 16, 17, 18, 19,
  2, 3, 4, 5, 6, 7, 8, 9
};

uint8_t cont = 0;

void setAllOutputsLow() {
  for (uint8_t i = 0; i < 16; ++i) {
    digitalWrite(OUT_PINS[i], LOW);
  }
}

void setStepOutput(uint8_t stepIndex) {
  setAllOutputsLow();
  digitalWrite(OUT_PINS[stepIndex], HIGH);
}

void setup() {
  for (uint8_t i = 0; i < 16; ++i) {
    pinMode(OUT_PINS[i], OUTPUT);
  }

  pinMode(CLOCK_PIN, INPUT);
  pinMode(RESET_PIN, INPUT);

  setAllOutputsLow();
}

void loop() {
  if (digitalRead(RESET_PIN) == HIGH) {
    cont = 0;
  }

  const uint8_t stepMax = map(analogRead(STEP_MAX_PIN), 0, 1023, 1, 16);

  setStepOutput(cont);

  while (digitalRead(CLOCK_PIN) == LOW && digitalRead(RESET_PIN) == LOW) {
  }

  while (digitalRead(CLOCK_PIN) == HIGH && digitalRead(RESET_PIN) == LOW) {
  }

  setAllOutputsLow();

  while (digitalRead(CLOCK_PIN) == LOW && digitalRead(RESET_PIN) == LOW) {
  }

  if (digitalRead(RESET_PIN) == LOW) {
    cont = (cont + 1) & 0x0F;

    if (stepMax == cont) {
      cont = 0;
    }
  }
}