//Pins
const int acq_led_pin = PB5; //D13-->PB5
const int acqPB = PIND2; //D2-->PD2
const int acq_sw = 2;

//Counter and compare values
//Timer Prescaler 1 --> fclk=16MHz
//CS12,CS11,CS10 101        100      011     010      001  TCCR1B
//Prescaler     1024        256      64      8     ***1***
//fclk          15.625kHz  62.5kHz  250kHz  2MHz  ***16MHz***
//Tclk          64us       16us     4us     0.5us    62.5ns
//t1_comp
//1000Hz   1ms  15.625     62.5     250    2000     16000
//500Hz    2ms  31.250    125       500    4000   ***32000***
//250Hz    4ms  62.500    250      1000    8000     64000
const uint16_t t1_load = 0;
//const uint16_t t1_comp = 32000;//500Hz; 2ms sampling rate
const uint16_t t1_comp = 64000;//250Hz; 4ms sampling rate

//volatile unsigned long samples = 0;
//const uint16_t fs=500;//Hz
const uint16_t fs=250;//Hz
const uint8_t fsLow=lowByte(fs);
const uint8_t fsHigh=highByte(fs);
const uint16_t acqtime = 30; //seconds  Acq time
const uint8_t acqTimeLow=lowByte(acqtime);
const uint8_t acqTimeHigh=highByte(acqtime);
unsigned long maxSamples = acqtime * fs; //500samples/sec --> 2ms/samp
volatile bool flgSyncSent = false; //byte string sent

//===================Setup==============================================================================

void setup() {
  Serial.begin(9600);//115200
  LED_Init();
  timer_init();
  ADC_INIT();
  //ADCSRA |= 1 << ADSC; //Start first conversion
  //Serial.println("Initialization Finished");
  //Serial.println(LED_BUILTIN);
  //Serial.write(0x41);
  // Serial.write(0x42);
//Serial.print("fsHigh : ");Serial.println(fsHigh,HEX);
//Serial.print("fsLow : ");Serial.println(fsLow,HEX);
//Serial.print("acqTimeHigh: ");Serial.println(acqTimeHigh,HEX);
//Serial.print("acqTimeLow: ");Serial.println(acqTimeLow,HEX);
}//End setup()

//=========================================Subroutines==================================================
//-----------------------------LED INIT---------------------------------------------------------------
void LED_Init() {

  //--------------------PORTB----------------------------------------------------------------------------

  // PORTB – The Port B Data Register (spec 13.4.2)
  //b7       b6       b5       b4       b3       b2       b1     b0
  //PB7      PB6      PB5      PB4      PB3      PB2      PB1   PB0
  //OSC2     OSC1     D13      D12      D11      D10      D9     D8
  //0        0        0        0       0        0        0      0   1: Input Pin w/ pullup 0: Output
  //                  acq_led_pin

  //DDRB: Port B Data Direction Register (spec 13.4.3)
  //b7       b6       b5       b4       b3       b2       b1     b0
  //DDB7     DDB6     DDB5     DDB4     DDB3     DDB2     DDB1   DDB0
  //OSC2     OSC1     D13      D12      D11      D10      D9     D8
  //0        0        1        1        0        0        0      0     1: Output 0: Input

  //PINB: Port B Input Pins Address (spec 13.4.4)
  //b7       b6       b5       b4       b3       b2       b1     b0
  //PINB7    PINB6    PINB5    PINB4    PINB3    PINB2    PINB1  PINB0
  //OSC2     OSC1     D13      D12      D11      D10      D9     D8

  //-----------------PORTC-------------------------------------------------------------------------------

  // PORTC – The Port C Data Register (spec 13.4.5)
  //b7       b6       b5       b4       b3       b2       b1     b0
  //PC7      PC6      PC5      PC4      PC3      PC2      PC1   PC0
  //-        RESET    A5       A4       A3       A2       A1    A0
  //0        0        0        0        0        0        0     0   1: Input Pin w/ pullup 0: Output

  //DDRC: Port C Data Direction Register (spec 13.4.6)
  //b7       b6       b5       b4       b3       b2       b1     b0
  //DDC7     DDC6     DDC5     DDC4     DDC3     DDC2     DDC1   DDC0
  //-        RESET    A5       A4       A3       A2       A1    A0
  //0        0        1        1        0        0        0      0     1: Output 0: Input

  //PINC: Port C Input Pins Address (spec 13.4.7)
  //b7       b6       b5       b4       b3       b2       b1     b0
  //PINC7    PINC6    PINC5    PINC4    PINC3    PINC2    PINC1  PINC0
  //-        RESET    A5       A4       A3       A2       A1    A0

  //------------------PORTD--------------------------------------------------------------------------------

  //PORTD – The Port D Data Register (spec 13.4.8)
  //b7       b6       b5       b4       b3       b2       b1     b0
  //PD7      PD6      PD5      PD4      PD3      PD2      PD1    PD0
  //D7       D6       D5       D4       D3       D2       D1     D0
  //0        0        0        0        0        1        0      0   1: Input Pin w/ pullup 0: Output
  //                                             acqPB

  //DDRD: Port D Data Direction Register (spec 13.4.9)
  //b7       b6       b5       b4       b3       b2       b1     b0
  //DDD7     DDD6     DDD5     DDD4     DDD3     DDD2     DDD1   DDD0
  //D7       D6       D5       D4       D3       D2       D1     D0
  //0        0        0        0        0        0        0      0     1: Output 0: Input

  //PIND: Port D Input Pins Address (spec 13.4.10)
  //b7       b6       b5       b4       b3       b2       b1     b0
  //PIND7    PIND6    PIND5    PIND4    PIND3    PIND2    PIND1  PIND0
  //D7       D6       D5       D4       D3       D2       D1     D0

  //--------------------------------------------------------------------------------------------------------

  DDRB = 0b00100000;
  PORTB = 0b00000000;//Set output low to turn off on board LED

  DDRD = 0b00000000;
  PORTD = 0b00000100;
}

//-------------------------------------Timer Counter Setup----------------------------------------------
void timer_init() {
  //SREG: AVR Status Register
  //b7       b6       b5       b4       b3       b2       b1     b0
  //I        T        H        S        V        N        Z       C
  //1

  //TCCR1A: Timer Counter Control Reg 1A (spec 15.11.1)
  //b7       b6       b5       b4       b3       b2       b1     b0
  //COM1A1   COM1A0   COM1B1   COM1B0   -        -        WGM11  WGM10
  //0        0        0        0        0        0        0      0     CTC,

  //TCCR1B: Timer Counter Control Reg 1B (spec 15.11.2)
  //b7       b6       b5       b4       b3       b2       b1     b0
  //ICNC1    ICES1    -        WGM13    WGM12    CS12     CS11   CS10
  // 0       0        0        0        1        0        0      1     CTC Mode, fclk/1 ==16MHz

  //TIMSK1: Timer/counter1 Interrupt Mask Register (spec 15.11.8)
  //b7       b6       b5       b4       b3       b2       b1     b0
  //-         -       ICIE1    -        -        OCIE1B   OCIE1A TOIE1
  //0         0       0        0        0        0        1      0     Interruot on output compare 1A

  //SREG=0b10000000;//Global Interrupt Enable (SEI() -->I=1; CLI()--->I=0)
  TCNT1 = 0; //Init Timer/Counter1 Register
  TCCR1A = 0b00000000;
  TCCR1B = 0b00001001;
  TIMSK1 = 0b00000010;
  OCR1A = t1_comp;//
  sei();
}//timer_init()

//--------------------------------------ADC Setup-------------------------------------------------------
void ADC_INIT() {
  //ADCSRA: ADC Control and Status Register A (Spec 23.9.2)
  //b7       b6       b5       b4       b3       b2       b1       b0
  //ADEN     ADSC    ADATE     ADIF     ADIE     ADPS2    ADPS1    ADPS0
  //1        0        0        0        0        1        1        1
  //ADC Enable. Auto Trigger off, fadc,clk=fclk/128 =125kHz

  //ADCSRB: ADC Control and Status Register B (Spec 23.9.4)
  //b7       b6       b5       b4       b3       b2       b1       b0
  //-       ACME      -        -        -        ADTS2    ADTS1    ADTS0
  //1        0        0        0        0        0        0        0      Free Run Mode

  //ADMUX: ADC Multiplexer Selection Register (Spec 23.9.1)
  //b7       b6       b5       b4       b3       b2       b1       b0
  //REFS1    REFS0    ADLAR    -        MUX3     MUX2     MUX1     MUX0
  //0        1        0        0        0        0        0        1    AREF, A0 input

  ADCSRA = 0b10000111;
  ADCSRB = 0b00000000;
  ADMUX = 0b01000000;

  ADCSRA |= 1 << ADSC; //Start first conversion

}//END  ADC_INIT()

//-------------------------------------Send Sync--------------------------------------------------
void sendSync(bool j) {
  static byte sync[2][6] = {{0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa}, {0x55, 0x55, 0x55, 0x55, 0x55, 0x55}};
  //Serial.print("flgSyncSent 1: ");Serial.println(flgSyncSent);
static byte buff[10]={0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, fsLow, fsHigh, acqTimeLow, acqTimeHigh};
  if (flgSyncSent == false) {
 //   Serial.print("Serial.availableForWrite(): ");Serial.println(Serial.availableForWrite());
   Serial.write(buff,10);
  /*
    for (int i = 0; i <= 9; i++) {
      //Serial.write(sync[i]);
      Serial.println(buff[i]);
    }//End for
   */
    flgSyncSent = true;
  }
 
  //Serial.print("flgSyncSent 2: ");Serial.println(flgSyncSent);
}
//-------------------------------------ALT ADC Read----------------------------------------------
int16_t adc_read(byte channel, bool j) {
  //Select ADC Channel
  ADMUX &= 0b11110000;
  ADMUX |= channel;
  //Serial.println(ADMUX, HEX);

  ADCSRA |= (1 << ADSC); //Start Conversion

  sendSync(j);
  //Wait for conversion to complete
  while (bitRead(ADCSRA, ADSC) == 1) {
    // Serial.println("wait");
  }
  //  Serial.print("Serial.availableForWrite() 2: ");Serial.println(Serial.availableForWrite());
//byte buff[2]={ADCH,ADCL};//Big Endian
byte buff[2]={ADCL,ADCH};//little Endian
Serial.write(buff,2);
 // Serial.write(ADCH);//Send MSB
 // Serial.write(ADCL);// Send LSB

  return ADCL | (ADCH << 8);
}//END adc_read()


//===============================Loop==================================================================
void loop() {
  delay(10);//Fake do something
}
//=======================ISR======================================

ISR(TIMER1_COMPA_vect) {
  // Serial.println("ISR(TIMER1_COMPB_vect)");
  static unsigned long samples = 0;
  static byte numPbPress = 0;
  static bool flgAcqEcg = false;
  int pBpress;
  int16_t val;

  if ((flgAcqEcg == 1) && (samples <= maxSamples)) {
    val = adc_read(0, 0); //Mux channel 0; sync j 0xAA
    //Serial.println(val);
    //Serial.write(val);
    samples++;
  }
  //Serial.print("samples: ");Serial.println(samples);
  //pBpress = PIND & (1 << acqPB); //Read State of Acq pushbutton
  //pBpress = pBpress >> acqPB; //Extrat Bit
  pBpress = (PIND & (1 << acqPB)) >> acqPB; // Read State of Acq pushbutton and Extracy Bit
  if (pBpress == 0) {
    numPbPress += 1;
  } else {
    numPbPress = 0;
  }

  if (numPbPress == 5) {
    flgAcqEcg = !flgAcqEcg;//Toggle flg

    //if (flgAcqEcg == false) {
    //  flgSyncSent = false;
    //  sendSync(1);//Send 0x55 sync
    //  flgSyncSent = false;
   // }
    PORTB ^= (1 << acq_led_pin);
  }

  if (samples >= maxSamples) {
    flgAcqEcg = false;
    //flgSyncSent = false;
    //sendSync(1);//Send 0x55 sync
    //flgSyncSent = false;
    PORTB &= ~(1 << acq_led_pin);
    samples = 0;
  }
  //Serial.print("flgSyncSent 3: ");Serial.println(flgSyncSent);
  //Serial.print("availableForWrite(): "); Serial.println( Serial.availableForWrite());
  //Serial.print("numPbPress: "); Serial.println(numPbPress);
  // Serial.print("PIND2: ");Serial.println(PIND2,HEX);
  //Serial.print("PIND: ");Serial.println(PIND,HEX);
  //Serial.print("pBpress: ");Serial.println(pBpress);

}// END ISR