/*
  XYLOBOT by Antoine Laloux
  Prototype développé pour le spectacle EXTRA BAL des CRAPAUDS SONNEURS
  www.lescrapaudssonneurs.fr
  Optimized version
  Author: Antoine Laloux
*/

#include <MIDI.h>

const uint8_t LED_PINS[25] = {
  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
};

const byte MIDI_NOTE_MIN = 60;
const byte MIDI_NOTE_MAX = 84;
const uint8_t STRIKE_MS = 15;

MIDI_CREATE_DEFAULT_INSTANCE();

inline int noteToIndex(byte pitch) {
  if (pitch < MIDI_NOTE_MIN || pitch > MIDI_NOTE_MAX) {
    return -1;
  }
  return pitch - MIDI_NOTE_MIN;
}

inline uint8_t ledIdleState(uint8_t idx) {
  return (idx == 24) ? LOW : HIGH;
}

inline uint8_t ledHitState(uint8_t idx) {
  return (idx == 24) ? HIGH : LOW;
}

void MyHandleNoteOff(byte channel, byte pitch, byte velocity) {
  (void)channel;
  (void)velocity;

  const int idx = noteToIndex(pitch);
  if (idx >= 0) {
    digitalWrite(LED_PINS[idx], ledIdleState(idx));
  }
}

void MyHandleNoteOn(byte channel, byte pitch, byte velocity) {
  (void)channel;
  (void)velocity;

  const int idx = noteToIndex(pitch);
  if (idx >= 0) {
    digitalWrite(LED_PINS[idx], ledHitState(idx));
    delay(STRIKE_MS);
    digitalWrite(LED_PINS[idx], ledIdleState(idx));
  }
}

void setup() {
  for (uint8_t i = 0; i < 25; ++i) {
    pinMode(LED_PINS[i], OUTPUT);
    digitalWrite(LED_PINS[i], ledIdleState(i));
  }

  MIDI.begin(MIDI_CHANNEL_OMNI);
  MIDI.setHandleNoteOn(MyHandleNoteOn);
  MIDI.setHandleNoteOff(MyHandleNoteOff);
}

void loop() {
  MIDI.read();
}