//-U lfuse:w:0xa2:m -U hfuse:w:0xd9:m
// avrdude -p m8 -c avrispv2 -P /dev/ttyACM0 -U lfuse:w:0xa2:m -U hfuse:w:0xd9:m
#define VERSION_STR "D KeySafe Version: 3.2.5\n"
/* History 
 * ---------------------------
 * 2021-04-25 - 3.2.0  -> INIT Initial Status Open changed on aktive Code.
 * 2021-05-12 - 3.2.1  -> BFIX Prevent duplicate acceptence of Lock Codes.
 * 2021-05-20 - 3.2.2  -> BFIX Prevent Timeupdate after Timeout. Fix not running Timer.
 * 2021-09-27 - 3.2.3  -> DBG  Debug Version zur Fehlersuche mit Ausgabe der Übertragungswerte. -NOT INCLUDED-
 * 2021-11-01 - 3.2.4  -> DBG  Debug Version eingrenzen auf btea error. -NOT INCLUDED-
 * 2021-11-08 - 3.2.5  -> ENHT Memory Safing spritnf() removed + Text constans + better Send Methods
 * 2022-01-31 - 3.2.6  -> ---  Handling of ATMEGA8 and ATMEGA88V + Auto Baud Calc via ATMEL LIB
 * 
 * INIT = Intial Version
 * BFIX = Bugfix non breaking Changes
 * BBUG = Breaking Bugfix - Changes in more then 1 Component
 * ENHT = Enhancement Erweiterung
 */

#define BAUD 9600UL      // Baudrate

#include <util/delay.h>
#include <inttypes.h>
#include <stdlib.h>
#include <stdio.h>

#include <avr/io.h>
#include <avr/interrupt.h>
#include <avr/sleep.h>
#include <avr/power.h>
#include <avr/eeprom.h>
#include <util/setbaud.h>

// ATMEGA8 -> ATMEGA88 Migration Guide http://ww1.microchip.com/downloads/en/AppNotes/doc2553.pdf --> AT8-88 Migration.pdf
#ifdef __AVR_ATmega88__ 
  #if F_CPU == 1000000UL
   #pragma message ( "Using ATMEGA88V at 1Mhz!" )
   #define F_CPU 1000000UL
   #define __U2X   U2X0
   #define __UDR UDR0
   #define __UCSRB UCSR0B 
   #define __UCSRC UCSR0C
   #define __RXEN  RXEN0
   #define __TXEN  TXEN0
   #define __UCSRC UCSR0C 
   #define __URSEL UMSEL01
   #define __UCSZ0 UCSZ00 
   #define __UCSZ1 UCSZ01
   #define __UBRRL UBRR0L
   #define __UBRRH UBRR0H
   #define __UCSRA UCSR0A
   #define __RXC   RXC0
   #define __UDRE  UDRE0
   #define __GICR  EIMSK
   #define __TCCR2 TCCR2B 
   #define __TIMSK TIMSK2
   #define __TCR2UB TCR2AUB
   #define __TIFR   TIFR2
   #define __OCR2   OCR2A
   #define __OCR2UB OCR2AUB
   //Interrupt
   #define __MCUCR EICRA
  #else
   #error ATMEGA88V but wrong F_CPU Speed
  #endif 
#endif

#ifdef __AVR_ATmega8__
  #if F_CPU == 2000000UL
   #pragma message ( "Using ATMEGA8A-AU at 2Mhz!" )
   #define F_CPU   2000000UL
   #define __U2X   U2X
   #define __UDR   UDR
   #define __UCSRB UCSRB 
   #define __UCSRC UCSRC 
   #define __RXEN  RXEN
   #define __TXEN  TXEN
   #define __UCSRC UCSRC 
   #define __URSEL URSEL
   #define __UCSZ0 UCSZ0
   #define __UCSZ1 UCSZ1
   #define __UBRRL UBRRL
   #define __UBRRH UBRRH
   #define __UCSRA UCSRA
   #define __RXC   RXC
   #define __UDRE  UDRE
   #define __GICR  GICR
   #define __TCCR2 TCCR2
   #define __TIMSK TIMSK
   #define __TCR2UB TCR2UB
   #define __TIFR   TIFR
   #define __OCR2   OCR2
   #define __OCR2UB OCR2UB
   #define __MCUCR MCUCR
  #else
   #error ATMEGA8 but wrong F_CPU Speed
  #endif
#endif



#define EEPROM_DEF 0xFF

#define BTDEBUG 0


// Original KeySave Meiner

#define BT_EN_REGISTER DDRC
#define BT_EN_PORT     PORTC
#define BT_EN_PIN      PC5

#define BT_RTX_PORT    PORTD
#define BT_TRX_REG     DDRD
#define BT_RX_PIN      PD0
#define BT_TX_PIN      PD1

#define LED_REGISTER   DDRC
#define LED_PORT       PORTC
#define LED_RED_PIN    PC0
#define LED_GREEN_PIN  PC1
#define LED_BLUE_PIN   PC2


// Board 
/*
#define BT_EN_REGISTER DDRC
#define BT_EN_PORT     PORTC
#define BT_EN_PIN      PC0

#define BT_RTX_PORT    PORTD
#define BT_TRX_REG     DDRD
#define BT_RX_PIN      PD0
#define BT_TX_PIN      PD1

#define LED_REGISTER   DDRC
#define LED_PORT       PORTC
#define LED_RED_PIN    PC5
#define LED_GREEN_PIN  PC4
#define LED_BLUE_PIN   PC3
*/

#define STAT_NO_BYTES_READ 0
#define STAT_START_FOUND 1
#define STAT_UPD_MASTERCODE   2
#define STAT_SET_LOCKCODE     3
#define STAT_READY 4
#define STAT_ERROR 5

#define DELTA 0x9e3779b9
#define MX (((z>>5^y<<2) + (y>>3^z<<4)) ^ ((sum^y) + (key[(p&3)^e] ^ z)))

//#define BAUD_PRESCALE (((F_CPU / (BAUDRATE * 16UL))) - 1)	/* Define prescale value for BT Module */




#define BT_INPUT_BUFFER   50 //Largest command is 49 including \0 !U10,10,10,10,$\n\0


#define TXT__D_DebugOut            "D Debug Out: "
#define TXT__I_MasterCodeUpdate    "I MasterCodeUpdate - "
#define TXT__I_LockCodeUpdate      "I LockCodeUpdate - "
#define TXT____vorbereiten         "vorbereiten\n"
#define TXT____erledigt            "erledigt\n"
#define TXT__E_Datenfehler         "E Datenfehler (bufidx,status,ichar,char,errCode): "
#define TXT__E_LockCodeUpdate      "E LockCodeUpdate - "


uint32_t             gEi_MasterKeyU32[4] EEMEM; // EEPORM
uint16_t             gEi_Req_Counter EEMEM; 

uint32_t             gul__MasterKeyU32[4];
uint16_t             gu_Req_Counter =0;
uint32_t             gul_lockInfo[] = {0,0}; //Element 1 = Time; Element 2 = (1Bit)ShowRemainingToSub (30Bit) Scrambled VerificationCode

volatile uint8_t     gi_wakeup_pressed = 0;
volatile uint8_t     gi_intrusion_detected = 1; // Will be set to 0 on Activation


/**
 *@desc   This Function initalizes Bluetooth Module with Baud
 *@param  BAUDRATE    The Baud Rate for the Module
 */
void USART_init(void){
    //Flag for Baud Rate Calculated with util/setbaud.h
   __UBRRH = UBRRH_VALUE;   /* Load UBRRL with lower 8 bit of prescale value */
   __UBRRL = UBRRL_VALUE;   /* Load UBRRH with upper 8 bit of prescale value */

    // Ganz wichtig der Double Speed Modus fuer 1Mhz bekommen wir sonst keine Baud hin.
    // https://cache.amobbs.com/bbs_upload782111/files_22/ourdev_508497.html  --> AVR Baud Rate Tables.pdf
    // https://alexandria.atmel.com/pr/GUID-ED37252C-1496-4275-BAEF-5152050ED2C2-en-US-2/index.html?GUID-65A53416-8DE2-468E-99CF-09F480AEF734 --> AVR306_ Using the AVR USART on tinyAVR and megaAVR devices.pdf
    #if USE_2X
    /* U2X-Modus erforderlich */
    __UCSRA |= (1 << __U2X);
    #else
    /* U2X-Modus nicht erforderlich */
    __UCSRA &= ~(1 << __U2X);
    #endif

   __UCSRB |= (1 << __RXEN) | (1 << __TXEN);                    /* Enable USART transmitter and receiver */
   __UCSRC |= (1 << __URSEL)| (1 << __UCSZ0) | (1 << __UCSZ1);	/* Write USCRC for 8 bit data and 1 stop bit */ 


}

void USART_deinit(void){
   BT_RTX_PORT |= (1<<BT_TX_PIN);   // TX Pin High sonst senden wir etwas
   __UCSRB &= ~(1 << __TXEN);           // Disable TX
   __UCSRB &= ~(1 << __RXEN);           // Disable RX
   __UCSRC &= ~(1 << __URSEL);
   __UCSRC &= ~(1 << __UCSZ0);
   __UCSRC &= ~(1 << __UCSZ1);	
   BT_RTX_PORT &= ~(1<<BT_TX_PIN);  // TX Pin LOW
   BT_EN_PORT &= ~(1<<BT_EN_PIN);
   
   BT_TRX_REG  &= ~(1 << BT_RX_PIN);   // RX Pin to Input
   BT_RTX_PORT &= ~(1<<BT_RX_PIN);     // RX Pin Pullup off (Tri-State)
}


#define USART_sendChar(c) while (!(__UCSRA & (1<<__UDRE))); __UDR=c;

/**
 *@desc   This Function sends Data to UART
 *@param  str         The string to send
 */
void USART_sendStr(const char *ptr){
   while (*ptr != 0){
      USART_sendChar(*ptr);
      ptr++;
   }
}
void USART_sendUint32t(uint32_t data){
   char buffer[11];
   ultoa(data,buffer,10);
   USART_sendStr(buffer);
}
void USART_sendUint16t(uint16_t data){
   char buffer[6];
   ultoa(data,buffer,10);
   USART_sendStr(buffer);
}
void USART_sendUint8t(uint8_t data){
   char buffer[4];
   ultoa(data,buffer,10);
   USART_sendStr(buffer);
}


uint16_t getCurrentVoltage(void){
  uint16_t adc_result = 0;  //Gesamtergebnis der Messung des ADC
  ADMUX |= (1<<REFS0) | (1<<REFS1) ; //VCC als Referenzspannung für den AD-Wandler
  ADMUX |= (1<<MUX3) | (1<<MUX2) | (1<<MUX1);  //1.3V Referenzspannung als Eingang für ADC 
  _delay_ms(2000);  //warten bis sich die Referenzspannung eingestellt hat
  ADCSRA |= (1<<ADEN);   //ADC aktivieren
  for (uint8_t i=0; i < 11; i++){
      ADCSRA |= (1<<ADSC);  //Messung starten
      while(!(ADCSRA&(1<<ADIF))){
         //warten bis Messung beendet ist
      }
      //Ergebnisse des ADC zwischenspeichern. Wichtig: zuerst ADCL auslesen, dann ADCH
      if (i != 0){  adc_result = (adc_result + ADCW); }
      ADCSRA |= (1<<ADIF); //Bit Freigeben
  }
  ADCSRA = 0;  
  return adc_result;
}


// INT0 -> intrusion_detection
ISR(INT0_vect){ 
   gi_intrusion_detected = 1; 
   LED_PORT |= (1<<LED_RED_PIN);
   _delay_ms(3000);
   LED_PORT &= ~(1<<LED_RED_PIN);
   __GICR &= ~(1 << INT0);            //Disable this interrupt
}  

// INT1 -> Trigger Show remaining_time
ISR(INT1_vect){ 
   gi_wakeup_pressed = 1;
   LED_PORT |= (1<<LED_GREEN_PIN);
   _delay_ms(100);
   LED_PORT &= ~(1<<LED_GREEN_PIN);
}  

// Timer2 Interrupt (Occurs every 8 Seconds)
ISR(TIMER2_OVF_vect) {
   if (gul_lockInfo[0] > 8){ 
      gul_lockInfo[0] = gul_lockInfo[0] - 8;
   }else{
      gul_lockInfo[0] = 0;
   }
}

//TinyEncryptionAlgorythem
void btea(uint32_t *v, int n, uint32_t key[4]) {
   uint32_t y, z, sum;
   unsigned p, rounds, e;
   if (n > 1) {          /* Coding Part */
      rounds = 6 + 52/n;
      sum = 0;
      z = v[n-1];
      do {
         sum += DELTA;
         e = (sum >> 2) & 3;
         for (p=0; p<n-1; p++) {
            y = v[p+1]; 
            z = v[p] += MX;
         }
         y = v[0];
         z = v[n-1] += MX;
      } while (--rounds);
   } else if (n < -1) {  /* Decoding Part */
      n = -n;
      rounds = 6 + 52/n;
      sum = rounds*DELTA;
      y = v[0];
      do {
         e = (sum >> 2) & 3;
         for (p=n-1; p>0; p--) {
            z = v[p-1];
            y = v[p] -= MX;
         }
         z = v[n-1];
         y = v[0] -= MX;
         sum -= DELTA;
      } while (--rounds);
   }
}

void getStatus(void){
   uint32_t cryptblocks[2];
   
   cryptblocks[0] = gul_lockInfo[0];
   cryptblocks[1] = gul_lockInfo[1];
   if (gi_intrusion_detected == 0){
      cryptblocks[1] &= ~(1UL << 31);         // Clear Bit i
   }else{
      cryptblocks[1] |= 1UL << 31;            // Set Bit i
   }
      
   for (int8_t i=15; i >= 0; i--){              // Integriere die 16 Bit vom Request Counter in den CodeBlock an die letzten 16 Bit
      if ( (gu_Req_Counter >> i) & 1U ){        // Check bit from Refcounter
         cryptblocks[1] |= 1UL << i;            // Set Bit i
      }else{
         cryptblocks[1] &= ~(1UL << i);         // Clear Bit i
      }      
   } 
 
   btea(cryptblocks,2, gul__MasterKeyU32);
   
   USART_sendStr("!R");
   USART_sendUint16t(getCurrentVoltage());
   USART_sendChar(',');
   USART_sendUint8t(gi_intrusion_detected);
   USART_sendChar(',');
   //     Bit31 nicht gesetzt (ShowSubRemainingTime)  &&      Lock Zeit != 0    &&     Nicht geoeffnet
   if ( (! (gul_lockInfo[1] >> 31) & 1U )             && (gul_lockInfo[0] != 0) && (gi_intrusion_detected == 0) ){
      USART_sendChar('N');
   }else{
      USART_sendUint32t(gul_lockInfo[0]);
   }
   USART_sendChar(',');
   USART_sendUint32t(cryptblocks[0]);
   USART_sendChar(',');
   USART_sendUint32t(cryptblocks[1]);
   USART_sendStr(",$\n");
}

void updateMasterCode(void){
   USART_sendStr(TXT__I_MasterCodeUpdate); USART_sendStr(TXT____vorbereiten);
   gu_Req_Counter=0;
   eeprom_write_word(&gEi_Req_Counter, gu_Req_Counter);
   eeprom_write_dword(&gEi_MasterKeyU32[0], gul__MasterKeyU32[0]); 
   eeprom_write_dword(&gEi_MasterKeyU32[1], gul__MasterKeyU32[1]);
   eeprom_write_dword(&gEi_MasterKeyU32[2], gul__MasterKeyU32[2]);
   eeprom_write_dword(&gEi_MasterKeyU32[3], gul__MasterKeyU32[3]);
   USART_sendStr(TXT__I_MasterCodeUpdate); USART_sendStr(TXT____erledigt);
   gi_intrusion_detected = 0;
   getStatus();
   gi_intrusion_detected = 1;
}


/* 
   Command List:
   ==============
   !U....,...,...,$   = Update Master Code
   !L....,...,...,$   = Set Lock Code
   !G                 = Get Status
*/

void get_BTData(uint8_t timeout_active){
   for (uint8_t i=0; i < 4; i++){                                    // Blink LED while Init gives BT time to bootup
      LED_PORT ^= (1 << LED_BLUE_PIN);
      _delay_ms(200);
   }


  _delay_ms(2000);
   BT_EN_PORT |= (1<<BT_EN_PIN);
  _delay_ms(2000);
 
   for (uint8_t i=0; i < 6; i++){                                    // Blink LED while Init gives BT time to bootup
      LED_PORT ^= (1 << LED_BLUE_PIN);
      _delay_ms(200);
   }
   
   
  _delay_ms(2000);
   USART_init();                                                 // INIT BT with 9600 Baud


   LED_PORT |= (1<<LED_BLUE_PIN);                                    // LED BLUE - BT is ready

   uint8_t  status     = STAT_NO_BYTES_READ;
   while (status != STAT_READY){
      //Read from BT
      
      uint8_t  bufidx     = 0;
      status   = STAT_NO_BYTES_READ;
      char     c;
      char     buffer[BT_INPUT_BUFFER];
      
      while(1){
         if (timeout_active == 0){
            while (!(__UCSRA & (1<<__RXC))){}                             //Bit not ready
         }else{
            uint32_t timeout=0;
            while (!(__UCSRA & (1<<__RXC))){                              //Bit not ready
               timeout++;      
               if (timeout > (15500000UL)){ //ca 1 Minute 15    4294967295 (MAX)
                  status=STAT_ERROR; 
                  break;
               }
            }
            if (status == STAT_ERROR){ break; }
         }
         
         c = __UDR;

         if (c == '!'){                      //Start of my Data
            status = STAT_START_FOUND;
            bufidx = 0;
            continue;
         }else if (c == '$'){                //End of my Data
            if (bufidx > 0){
               buffer[bufidx] = '$';
               bufidx++;
               buffer[bufidx] = '\0';
               break;
            }
            status = STAT_NO_BYTES_READ;
            bufidx=0;
         }else if (c == '\n'){ 
            continue;
         }
         
         if ((status == STAT_START_FOUND) && (bufidx < (BT_INPUT_BUFFER-2))){ //Keep space for $ and \0
            buffer[bufidx] = c;
            bufidx++;
         }else{
            //ERROR
            USART_sendStr(TXT__E_Datenfehler); USART_sendUint8t(bufidx); USART_sendUint8t(status); USART_sendUint8t((unsigned int)c);USART_sendChar(c);USART_sendStr(",E1\n");
            LED_PORT |= (1<<LED_RED_PIN); _delay_ms(600);  LED_PORT &= ~(1<<LED_RED_PIN);
            bufidx = 0;
            status = STAT_NO_BYTES_READ;
         }
      }
      if (status == STAT_ERROR){ break; }
      
      //Process Command
      if (buffer[0] == 'U'){
         status=STAT_UPD_MASTERCODE;
      }else if (buffer[0] == 'L'){
         status=STAT_SET_LOCKCODE;
      }else if (buffer[0] == 'G'){
         getStatus();
         if (timeout_active == 0){  //Wir sind noch im Initmode also machen wir weiter 
            status   = STAT_NO_BYTES_READ;
            bufidx=0;
            continue;
         }else{
            status = STAT_READY;
            bufidx=0;
            break;
         }
      }else if (buffer[0] == 'V'){
         USART_sendStr(VERSION_STR);
         status = STAT_NO_BYTES_READ;
         bufidx=0;
         continue;
#if defined BTDEBUG && BTDEBUG == 1
      }else if (buffer[0] == 'X'){
         USART_sendStr(TXT__D_DebugOut); USART_sendUint32t(gul__MasterKeyU32[0]); USART_sendUint32t(gul__MasterKeyU32[1]);USART_sendUint32t(gul__MasterKeyU32[2]);USART_sendUint32t(gul__MasterKeyU32[3]);USART_sendChar('\n');
         status = STAT_NO_BYTES_READ;
         bufidx=0;
         continue;
#endif
      }else{
         // Invalid Command --> Ignore
         LED_PORT |= (1<<LED_RED_PIN); _delay_ms(600);  LED_PORT &= ~(1<<LED_RED_PIN);
         USART_sendStr("E Ungueltiger Befehl:");
         USART_sendStr(buffer);
         USART_sendChar('\n');
         status = STAT_NO_BYTES_READ;
         bufidx=0;
         continue;
      }
      
      // We only parase if we are in a propreate mode. --> Parse out Long Values
      if ((status == STAT_UPD_MASTERCODE) || (status == STAT_SET_LOCKCODE)){
         char     uint_str_buffer[11];   // 11 = size of value of unit32_t (10 chars)
         uint8_t  str_buf_idx = 0;
         uint8_t  sub_idx     = 0;
         uint32_t lul_lockInfo[] = {0,0};

         for (uint8_t i=1; i < bufidx; i++){
            if ((str_buf_idx < 11) && ((buffer[i] == '0') || (buffer[i] == '1') || (buffer[i] == '2') || (buffer[i] == '3') || 
                                       (buffer[i] == '4') || (buffer[i] == '5') || (buffer[i] == '6') || (buffer[i] == '7') || 
                                       (buffer[i] == '8') || (buffer[i] == '9')  )){
               uint_str_buffer[str_buf_idx] = buffer[i];
               str_buf_idx++;
               uint_str_buffer[str_buf_idx] = '\0';
               continue;
            }else if (buffer[i] == ','){
               //End of Block
               if ((status == STAT_UPD_MASTERCODE)&&(sub_idx < 5)){
                  uint_str_buffer[str_buf_idx] = '\0';
                  gul__MasterKeyU32[sub_idx] = strtoul(uint_str_buffer, NULL,0);
                  sub_idx++;
                  str_buf_idx=0;
               }else if ((status==STAT_SET_LOCKCODE) && (sub_idx <2)){
                  uint_str_buffer[str_buf_idx] = '\0';
                  lul_lockInfo[sub_idx] = strtoul(uint_str_buffer, NULL,0);
                  #if defined BTDEBUG && BTDEBUG == 1
                     USART_sendStr(TXT__D_DebugOut);
                     USART_sendStr(uint_str_buffer);
                     USART_sendChar('\n');
                  #endif
                  sub_idx++;
                  str_buf_idx=0;
               }else{
                  //To much Elements
                  LED_PORT |= (1<<LED_RED_PIN); _delay_ms(600);  LED_PORT &= ~(1<<LED_RED_PIN);
                  USART_sendStr(TXT__E_Datenfehler); USART_sendUint8t(bufidx); USART_sendUint8t(status); USART_sendUint8t(sub_idx);USART_sendChar(c);USART_sendStr(",E2 Zu viele Elemente\n");
                  sub_idx = 0;
                  bufidx = 0;
                  str_buf_idx=0;
                  lul_lockInfo[0] = 0;
                  lul_lockInfo[1] = 0;
                  status = STAT_NO_BYTES_READ;
                  break;
               }
            }else if (buffer[i] == '$'){
               #if defined BTDEBUG && BTDEBUG == 1
                  USART_sendStr("D Befehlsende gefunden\n");
               #endif
               if ((status==STAT_UPD_MASTERCODE) && (sub_idx ==4)){
                  updateMasterCode();
               }else if ((status==STAT_SET_LOCKCODE) && (sub_idx == 2)){
                  USART_sendStr(TXT__I_LockCodeUpdate); USART_sendStr(TXT____vorbereiten);

                  btea(lul_lockInfo,-2, gul__MasterKeyU32);
                  USART_sendStr(TXT__I_LockCodeUpdate); USART_sendStr("entschluesselt\n");
                  
                  if (lul_lockInfo[1] == gul_lockInfo[1]){
                      USART_sendStr("E LockCode bereits aktiv! --> Lockcode update abgebrochen\n");
                      sub_idx = 0;
                      bufidx = 0;
                      str_buf_idx=0;
                      lul_lockInfo[0] = 0;
                      lul_lockInfo[1] = 0;
                      status = STAT_NO_BYTES_READ;
                      break;
                  }
                
                  USART_sendStr(TXT__I_LockCodeUpdate); USART_sendStr("aktivieren\n");
                  gu_Req_Counter++;
                  eeprom_write_word(&gEi_Req_Counter, gu_Req_Counter);
                                    
                  if ((timeout_active != 0) && (gi_intrusion_detected != 0)){
                     USART_sendStr(TXT__E_LockCodeUpdate); USART_sendStr("KeySafe war offen\n");
                     sub_idx = 0;
                     bufidx = 0;
                     str_buf_idx=0;
                     lul_lockInfo[0] = 0;
                     lul_lockInfo[1] = 0;
                     status = STAT_NO_BYTES_READ;
                     getStatus();
                     break;
                  }else if ((timeout_active != 0) && (gul_lockInfo[0] < 60)){
                     USART_sendStr(TXT__E_LockCodeUpdate); USART_sendStr("Restzeit zu kurz < 60 Sec.\n");
                     sub_idx = 0;
                     bufidx = 0;
                     str_buf_idx=0;
                     lul_lockInfo[0] = 0;
                     lul_lockInfo[1] = 0;
                     status = STAT_NO_BYTES_READ;
                     getStatus();
                     break;
                  }else{
                     USART_sendStr("I KeySafe ist in 5 Sekunden aktiv.\n");
                     gul_lockInfo[0] = lul_lockInfo[0];
                     gul_lockInfo[1] = lul_lockInfo[1];
                     gi_intrusion_detected = 0; // Nur bei Initial
                  }
                  
                  getStatus();
                  status = STAT_READY;
                  break;
               }else{
                  LED_PORT |= (1<<LED_RED_PIN); _delay_ms(600);  LED_PORT &= ~(1<<LED_RED_PIN);
                  USART_sendStr(TXT__E_Datenfehler); USART_sendUint8t(bufidx); USART_sendUint8t(status); USART_sendUint8t(sub_idx);USART_sendChar(c);USART_sendStr(",E3\n");
               }
               status = STAT_NO_BYTES_READ;
               sub_idx = 0;
               bufidx = 0;
               break;
            }else{
               //To much Elements
               LED_PORT |= (1<<LED_RED_PIN); _delay_ms(600);  LED_PORT &= ~(1<<LED_RED_PIN);
               USART_sendStr(TXT__E_Datenfehler); USART_sendUint8t(bufidx); USART_sendUint8t(status); USART_sendUint8t((unsigned int)c);USART_sendChar(c);USART_sendStr(",E4 (LongParse)\n");
               status = STAT_NO_BYTES_READ;
               sub_idx = 0;
               bufidx = 0;
               break;
            }
         }
      }
   }
      
   _delay_ms(5000);
   LED_PORT &= ~(1<<LED_BLUE_PIN);
   USART_deinit();   
}  

void if_wakup_key_pressed(void){
   if (gi_wakeup_pressed == 1){
      if (gi_intrusion_detected == 0){
         if (gul_lockInfo[0] == 0){          //Fertig
            LED_PORT |= (1<<LED_GREEN_PIN);
            _delay_ms(3000);
            LED_PORT &= ~(1<<LED_GREEN_PIN);
         }else{
            for (uint8_t i=0; i < 15; i++){
               LED_PORT |= (1<<LED_GREEN_PIN);
               _delay_ms(200);
               LED_PORT &= ~(1<<LED_GREEN_PIN);
               _delay_ms(50);
            }
         }
      }else{
         LED_PORT |= (1<<LED_RED_PIN);
         _delay_ms(3000);
         LED_PORT &= ~(1<<LED_RED_PIN);
      }
      if (!( PIND & (1<<PIND3))) {             //INT 1  (PIN ist noch low)
         get_BTData(1);
      }
      gi_wakeup_pressed = 0;
   }
}

void goto_deep_sleep(void){
   //disable Timer
   __TCCR2 &= ~(1<< CS22);
   __TCCR2 &= ~(1<< CS21);
   __TCCR2 &= ~(1<< CS20);
   __TIMSK &= ~(1 << TOIE2);

   while (1){
      __GICR &= ~(1 << INT1);                  // externen Interrupt sperren  WICHTIG! falls der externe LOW Puls an INT1 sehr lange dauert
      cli();                                 //Disable Interrupts

      if_wakup_key_pressed();

      __GICR |= (1 << INT1);                      //enable interrupt 1      //WAKEUP
      sei();
      ADCSRA = 0;  
      set_sleep_mode(SLEEP_MODE_PWR_DOWN);
      sleep_mode();                             // in den Schlafmodus wechseln
	}
}

int main(void){
   ADCSRA = 0; 
   // Direction Registers
   DDRB = 0x00;            // B as input
   DDRC = 0x00;            // D as Input
   DDRD = 0x00;            // D as Input
   
   // Set Output Registers
   BT_EN_REGISTER |= (1 << BT_EN_PIN);        // Bluetooth PWR Controll
   LED_REGISTER   |= (1 << LED_RED_PIN);      // LED as output
   LED_REGISTER   |= (1 << LED_GREEN_PIN);    // LED as output
   LED_REGISTER   |= (1 << LED_BLUE_PIN);     // LED as output

   // Ports to LOW (GND no Pullup)
   PORTB = 0x00;
   PORTC = 0x00;
   PORTD = 0x00;
   
   gi_intrusion_detected = 1;
   
   // Read EEPROM
   gu_Req_Counter       = eeprom_read_word( &gEi_Req_Counter    );
   gul__MasterKeyU32[0] = eeprom_read_dword(&gEi_MasterKeyU32[0]);
   gul__MasterKeyU32[1] = eeprom_read_dword(&gEi_MasterKeyU32[1]);
   gul__MasterKeyU32[2] = eeprom_read_dword(&gEi_MasterKeyU32[2]);
   gul__MasterKeyU32[3] = eeprom_read_dword(&gEi_MasterKeyU32[3]);
   
   //Start countdown
   for (uint8_t i=0; i <4; i++){
      LED_PORT ^= (1 << LED_GREEN_PIN);
      _delay_ms(250);
      LED_PORT ^= (1 << LED_RED_PIN);
      _delay_ms(250);
      LED_PORT ^= (1 << LED_BLUE_PIN);
      _delay_ms(250);
   }

   get_BTData(0);       // INIT MODE
      
  
   //Start countdown
   for (uint8_t i=0; i <10; i++){
      LED_PORT ^= (1 << LED_GREEN_PIN);
      _delay_ms(150);
   }
   
   // Use Interrupt 0 for intrusion_detection
   PORTD |= (1<<PD2);                  // Pullup auf INT0 (PD2) an 
   __MCUCR &= (2<<ISC01) & (2<<ISC00);   // levelgesteuerter Interrupt an INT0
   __GICR |= (1 << INT0);                // externen Interrupt freigeben
   
   PORTD |= (1<<PD3);                  // Pullup auf INT1 (PD3) an 
   __MCUCR &= (2<<ISC11) & (2<<ISC10);   // levelgesteuerter Interrupt an INT1
   __GICR |= (1 << INT1);                // externen Interrupt freigeben
   
   gi_intrusion_detected = 0;
   gi_wakeup_pressed = 0;
   
   // Configure Timer2 (Countdown Timer)
   ASSR  = (1<< AS2);                                 // Timer2 asynchron takten
   _delay_ms(2000);                                   // Einschwingzeit des 32kHz Quarzes
   //__TCCR2  = 6;                                      // Vorteiler 256 -> 2s Überlaufperiode
   __TCCR2 |= (1 << CS22) | (1 << CS21) | (1 << CS20);  // Prescaler 1024 -> 8s Überlaufperiode
   while((ASSR & (1<< __TCR2UB)));                      // Warte auf das Ende des Zugriffs
   __TIFR   = (1<<TOV2);                                // Interrupts löschen (*)
   __TIMSK |= (1<<TOIE2);                               // Timer overflow Interrupt freischalten

   sei();                                             // Activate Interrupts

   
   while ((gul_lockInfo[0] > 0) && (gi_intrusion_detected==0)){
      
      if_wakup_key_pressed();

      __GICR |= (1 << INT1);                      //enable interrupt 1      //WAKEUP
      cli();
      sei();

       ADCSRA = 0;  
      // WICHTIG!
      // Wenn der Timer2 im asynchronen Modus periodisch zum Wecken aus dem Sleep Mode genutzt wird, dann muss vor dem Wiedereintritt mindestens
      // 1 Oszillatortakt des Timers abgewartet werden (~30us), um die Interruptlogik wieder zu aktivieren, anderenfalls wacht der AVR nicht mehr auf.
      // Die folgenden zwei Zeilen tun dies. Nur wenn sichergestellt ist, dass der Interrupt + Hauptschleife länger als 30µs dauern, kann man den Test weglassen
      __OCR2 = 0;                       			// Dummyzugriff
      while((ASSR & (1<< __OCR2UB)));   			// Warte auf das Ende des Zugriffs
   
      // Go to sleep
      set_sleep_mode(SLEEP_MODE_PWR_SAVE);
      sleep_mode();                   			// in den Schlafmodus wechseln
   
      // hier wachen wir wieder auf
      //__GICR &= ~(1 << INT0);             // externen Interrupt sperren  WICHTIG! falls der externe LOW Puls an INT0 sehr lange dauert
      __GICR &= ~(1 << INT1);               // externen Interrupt sperren  WICHTIG! falls der externe LOW Puls an INT1 sehr lange dauert
      cli();
      sei();
   }
   
   //Finished
   __GICR &= ~(1<<INT0);                       //disable interrupt 0
   __GICR |= (1 << INT1);                      //enable interrupt 1      //WAKEUP
      
   

   for (uint8_t i=0; i <10; i++){
      LED_PORT ^= (1 << LED_GREEN_PIN);
      _delay_ms(300);
   }


   goto_deep_sleep();
}