#include "TimerOne.h"

// group preset channel steps
// steps are the bits in the byte

byte patternData[8][8][8] = {0};

byte currentGroup = 0;
byte currentPreset = 0;

byte nextPreset = 0;


// the following are used in the UI
byte active_group = 0;
byte active_preset = 0;
byte active_channel = 0;

// each bit in this corresponds to one preset that should be in the loop or not
// 00000101 means that preset 0 and preset 2 should be in the loop.
// 00000011 means that preset 0 and preset 1 should be in the loop.
byte loopPresets = B00000011;


byte tick = 0;

// this is the different output channels
byte triggerOutputData = 0;


enum Mode : byte {
  normal = 0,
  select_pattern = 1,
  select_group = 2,
};









void onClock() {
  tick++;
  tick %= 8;
  Serial.print(tick);
  Serial.print(" ");


  // reset output trigger data
  triggerOutputData = 0;
  // loop over channels
  for (byte channel = 0; channel < 8; channel++) {

    // check current step bit
    //bit = (number >> n) & 1U;

    if ( (patternData[currentGroup][currentPreset][channel] >> tick) & 1U ) {
      triggerOutputData |= 1UL << channel;
    }
  }
  Serial.println(triggerOutputData, BIN);


  writeOutputs();

  // only for now, otherwise this should be in the main loop, but I dont
  // want output on serial forever!!
  show_home();





  // check if we are at the end of a preset (after 8 steps) and if so
  // go to the next preset
  if (tick == 7) {
    // check next(current) preset by checking loopsPresets
    for (byte i = 0; i < 8; i++) {
      // right shifting and & comparing with 00000001 (masking) to step through
      // byte to see which ones active and therefore part of the loop.

      if (loopPresets >> ((currentPreset + 1 + i) % 8) & 1U) {

        Serial.print(" next preset is ");
        Serial.print((currentPreset + 1 + i) % 8);
        Serial.println(" | ");
        nextPreset = (currentPreset + 1 + i) % 8;
        break;
      }
    }
    currentPreset = nextPreset;
  }

}

void writeOutputs() {
  // this needs more work!!


  // split data, because we need two ports 
  // (need some pins in PORTD for serial communication and clock in)
  byte lower = triggerOutputData & B00001111;
  byte higher = triggerOutputData & B11110000;

  bitClear(PORTB, 0);
  bitClear(PORTB, 1);
  bitClear(PORTB, 2);
  bitClear(PORTB, 3);
  PORTB = PORTB | lower;

  bitClear(PORTD, 5);
  bitClear(PORTD, 6);
  bitClear(PORTD, 7);
  bitClear(PORTD, 8);
  PORTD = PORTD | higher;

}

void setup() {
  
  Serial.begin(9600);

  // set output pins:
  // this should be pins D11 to D8, rightmost is D8, leftmost D11
  DDRB = DDRB | B00001111;  // set to output without changing anything that is not 1
  DDRD = DDRD | B11110000;
  

  // put in some example pattern data
  patternData[0][0][0] = B10001000; // first group first preset first  channel (kick)
  patternData[0][0][1] = B00100010; // first group first preset second channel (snare)
  patternData[0][0][2] = B11111111; // first group first preset third  channel (hihat)

  patternData[0][1][0] = B10101010; // first group second preset first  channel (kick)

  Timer1.initialize(900000);
  Timer1.attachInterrupt(onClock);

}

void loop() {
  // put your main code here, to run repeatedly:

}


//for (byte i = 0; i<8; i++) {
// right shifting and & comparing with 00000001 (masking) to step through
// byte to see which ones active and therefore part of the loop.

//Serial.print(loopPresets >> i & 1U, BIN);
//Serial.print(" ");
//if (loopPresets >> i & 1U) {
//  Serial.print(i);
//  Serial.print(",");
//}
//    }
//    Serial.print(" are in the loop. ");

void show_home() {
  // show pattern and active step in lower two rows
  // -> set all to black
  Serial.print("|ui>:");
  for(int i=0; i<8; i++) {
    
    Serial.print((patternData[active_group][active_preset][active_channel] >> i) & 1U);
    // -> turn on LED i, color = green
    
  }
  // -> turn on LED of active step in red

  Serial.print(">|");

  // show current pattern and group as colors on righ two lower upper buttons
}