//-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(); }