// ***********************************************************************************
// **** PROGRAM = DOMOWY SYSTEM ALARMOWY (C) 2010 LUCIDSCIENCE.COM
// **** PLATFORMA = ATMEGA88P & KLAWIATURA 12-PRZYCISKOWA
// **** PRDKO ZEGARA = 8 MHZ, WEWNTRZNY
// ***********************************************************************************
#include <mega88p.h>
#include <delay.h>
#include <sleep.h>

// ***********************************************************************************
// **** WYSANIE KRTKIEGO SYGNAU DO BRZCZYKA
// ***********************************************************************************
void BEEP1() {
  unsigned char ctr1;

  // POJEDYNCZY KRTKI SYGNA
  for (ctr1 = 0; ctr1 < 50; ctr1++) {
    PORTC.0 = 0;
    PORTC.1 = 1;
    delay_us(400);
    PORTC.0 = 1;
    PORTC.1 = 0;
    delay_us(400);
  }
}

// ***********************************************************************************
// **** SYGNA POTWIERDZAJCY POLECENIE
// ***********************************************************************************
void BEEP2() {
  unsigned char ctr1;

  // WCZENIE DIOD
  PORTB.1 = 1;
  PORTB.2 = 1;

  // CZSTOTLIWO SYGNAU 1
  delay_ms(250);
  for (ctr1 = 0; ctr1 < 100; ctr1++) {
    PORTC.0 = 0;
    PORTC.1 = 1;
    delay_us(500);
    PORTC.0 = 1;
    PORTC.1 = 0;
    delay_us(500);
  }
  delay_ms(100);

  // CZSTOTLIWO SYGNAU 2
  for (ctr1 = 0; ctr1 < 200; ctr1++) {
    PORTC.0 = 0;
    PORTC.1 = 1;
    delay_us(200);
    PORTC.0 = 1;
    PORTC.1 = 0;
    delay_us(200);
  }
  delay_ms(100);

  // CZSTOTLIWO SYGNAU 3
  for (ctr1 = 0; ctr1 < 150; ctr1++) {
    PORTC.0 = 0;
    PORTC.1 = 1;
    delay_us(300);
    PORTC.0 = 1;
    PORTC.1 = 0;
    delay_us(300);
  }
  delay_ms(250);

  // WYCZENIE DIOD
  PORTB.1 = 0;
  PORTB.2 = 0;
}

// ***********************************************************************************
// **** WPROWADZENIE AVR W TRYB OSZCZDZANIA ENERGII
// ***********************************************************************************
void SLEEP() {

  // WYCZENIE DIOD I SYGNAU
  PORTB.1 = 0;
  PORTB.2 = 0;
  BEEP2();

  // WEJCIE W TRYB OSZCZDZANIA ENERGII
  #asm("sei")
  sleep_enable();
  powerdown();
}

// ***********************************************************************************
// **** WYBUDZENIE Z TRYBU OSZCZDZANIA ENERGII PO ZMIANIE NA PINIE ALARMOWYM
// ***********************************************************************************
interrupt [PCINT2] void pin_change_isr2(void) {
  sleep_disable();
  #asm("cli")
}

// ***********************************************************************************
// **** ODCZYT KLAWIATURY I ZWROT WARTOCI ASCII
// ***********************************************************************************
unsigned char KEYPAD() {
  unsigned char key;
  unsigned char scn;
  key = 0;

  // SKANOWANIE KLAWISZY W KOLUMNIE 1
  PORTD.4 = 0;
  delay_ms(1);
  scn = (PIND & 15);
  PORTD.4 = 1;

  // ZAMIANA KLAWISZA NA ASCII
  if (scn == 14) key = '1';
  if (scn == 13) key = '4';
  if (scn == 11) key = '7';
  if (scn == 7) key = '*';

  // SKANOWANIE KLAWISZY W KOLUMNIE 2
  PORTD.5 = 0;
  delay_ms(1);
  scn = (PIND & 15);
  PORTD.5 = 1;

  // ZAMIANA KLAWISZA NA ASCII
  if (scn == 14) key = '2';
  if (scn == 13) key = '5';
  if (scn == 11) key = '8';
  if (scn == 7) key = '0';

  // SKANOWANIE KLAWISZY W KOLUMNIE 3
  PORTD.6 = 0;
  delay_ms(1);
  scn = (PIND & 15);
  PORTD.6 = 1;

  // ZAMIANA KLAWISZA NA ASCII
  if (scn == 14) key = '3';
  if (scn == 13) key = '6';
  if (scn == 11) key = '9';
  if (scn == 7) key = '#';

  // WYSANIE SYGNAU PO NACINICIU KLAWISZA
  if (key != 0){
    for (scn = 0; scn < 50; scn++) {
      PORTC.0 = 0;
      PORTC.1 = 1;
      delay_us(200);
      PORTC.0 = 1;
      PORTC.1 = 0;
      delay_us(200);
    }
  }

  // WSTRZYMANIE NA CZAS NACINICIA KLAWISZA
  scn = 0;
  while (scn != 45) {
    scn = 0;
    PORTD.4 = 0;
    delay_ms(1);
    scn = scn + (PIND & 15);
    PORTD.4 = 1;
    PORTD.5 = 0;
    delay_ms(1);
    scn = scn + (PIND & 15);
    PORTD.5 = 1;
    PORTD.6 = 0;
    delay_ms(1);
    scn = scn + (PIND & 15);
    PORTD.6 = 1;
  }

  // ZWROT WARTOCI KLAWISZA
  delay_ms(100);
  return(key);
}

// ***********************************************************************************
// **** ZMIENNE PROGRAMU I KONFIGURACJA PORTU
// ***********************************************************************************
void main(void) {

  // GWNE ZMIENNE PROGRAMU
  unsigned char ctr1;
  unsigned char ctr2;
  unsigned int ctr3;
  unsigned char mode;
  unsigned char code[4];

  // WEJCIA WIERSZY KLAWIATURY 3X4
  DDRD.0 = 0;
  DDRD.1 = 0;
  DDRD.2 = 0;
  DDRD.3 = 0;
  PORTD.0 = 1;
  PORTD.1 = 1;
  PORTD.2 = 1;
  PORTD.3 = 1;

  // WYJCIA KOLUMN KLAWIATURY 3X4
  DDRD.4 = 1;
  DDRD.5 = 1;
  DDRD.6 = 1;
  PORTD.4 = 1;
  PORTD.5 = 1;
  PORTD.6 = 1;

  // WYJCIE ZIELONEJ DIODY
  DDRB.1 = 1;

  // WYJCIE CZERWONEJ DIODY
  DDRB.2 = 1;

  // WYJCIE BRZCZYKA PIEZOELEKTRYCZNEGO
  DDRC.1 = 0;
  DDRC.1 = 1;

  // WEJCIE WYZWALACZA ALARMU
  DDRD.7 = 0;
  PORTD.7 = 1;

  // WYJCIE SYRENY ALARMU
  DDRB.0 = 1;

  // ***********************************************************************************
  // **** INICJALIZACJA PROGRAMU
  // ***********************************************************************************

  // WCZENIE PRZERWA ZMIANY STANU PINU
  EICRA = 0x00;
  EIMSK = 0x00;
  PCICR = 0x04;
  PCMSK2 = 0x80;
  PCIFR = 0x04;

  // WYSANIE SYGNAU STARTOWEGO
  delay_ms(1000);
  for (ctr1 = 0; ctr1 < 4; ctr1++) {
    BEEP1();
    PORTB.1 = 1;
    PORTB.2 = 1;
    delay_ms(100);
    PORTB.1 = 0;
    PORTB.2 = 0;
    delay_ms(100);
  }

  // WEJCIE SYSTEMU W STAN BEZCZYNNOCI
  mode = 0;
  ctr1 = 0;
  ctr2 = 0;
  ctr3 = 0;

  // USTAWIENIE KODU DOSTPU
  code[0] = '1';
  code[1] = '2';
  code[2] = '3';
  code[3] = '4';

  // ***********************************************************************************
  // **** GWNA PTLA PROGRAMU
  // ***********************************************************************************
  while (1) {

    // ***********************************************************************************
    // **** TRYB 0 : BEZCZYNNY I NIEUZBROJONY
    // ***********************************************************************************
    while (mode == 0) {

      // WYCZENIE ZEWNTRZNEGO ALARMU
      PORTB.0 = 0;

      // ZAPALENIE ZIELONEJ DIODY
      PORTB.1 = 1;
      PORTB.2 = 0;

      // SPRAWDZENIE HASA
      if (ctr1 == 0 && KEYPAD() == code[0]) ctr1 = 1;
      if (ctr1 == 1 && KEYPAD() == code[1]) ctr1 = 2;
      if (ctr1 == 2 && KEYPAD() == code[2]) ctr1 = 3;
      if (ctr1 == 3 && KEYPAD() == code[3]) ctr1 = 4;

      // UZBROJENIE SYSTEMU PO WPROWADZENIU HASA
      if (ctr1 == 4) {
        ctr1 = 0;
        ctr2 = 0;
        ctr3 = 0;
        mode = 1;
      }
    }

    // ***********************************************************************************
    // **** TRYB 1: ALARM UZBROJONY PO ODLICZENIU 60 SEKUND
    // ***********************************************************************************
    while (mode == 1) {

      // SYGNA PO 60 SEKUNDACH
      for (ctr1 = 0; ctr1 < 60; ctr1++) {
        BEEP1();
        PORTB.2 = 1;
        delay_ms(500);
        PORTB.2 = 0;
        delay_ms(500);
      }

      // UZBROJENIE SYSTEMU I TRYB OSZCZDZANIA ENERGII
      SLEEP();
      ctr1 = 0;
      ctr2 = 0;
      ctr3 = 0;
      mode = 2;
    }

    // ***********************************************************************************
    // **** TRYB 2: ALARM WYZWOLONY PO ODLICZENIU 60 SEKUND
    // ***********************************************************************************
    while (mode == 2) {

      // SYGNA ALARMOWY
      for (ctr1 = 0; ctr1 < 50; ctr1++) {
      PORTC.0 = 0;
      PORTC.1 = 1;
      PORTB.2 = 1;
      delay_us(150);
      PORTC.0 = 1;
      PORTC.1 = 0;
      PORTB.2 = 0;
      delay_us(150);
      }

      // AKTYWACJA SYRENY W CIGU 60 SEKUND
      ctr3++;
      if (ctr3 == 400) mode = 3;

      // ODCZYT HASA
      if (ctr2 == 0 && KEYPAD() == code[0]) ctr2 = 1;
      if (ctr2 == 1 && KEYPAD() == code[1]) ctr2 = 2;
      if (ctr2 == 2 && KEYPAD() == code[2]) ctr2 = 3;
      if (ctr2 == 3 && KEYPAD() == code[3]) ctr2 = 4;

      // WEJCIE W TRYB BEZCZYNNOCI PO WPROWADZENIU HASA
      if (ctr2 == 4) {
        PORTB.1 = 0;
        PORTB.2 = 0;
        ctr1 = 0;
        ctr2 = 0;
        ctr3 = 0;
        mode = 0;
        BEEP2();
      }
    }

    // ***********************************************************************************
    // **** TRYB 3: WCZENIE SYRENY ALARMOWEJ
    // ***********************************************************************************
    while (mode == 3) {

      // WCZENIE ZEWNTRZNEGO ALARMU
      PORTB.0 = 1;

      // TRYB OSZCZDZANIA ENERGII I OCZEKIWANIE NA HASO
      SLEEP();
      ctr1 = 0;
      ctr2 = 0;
      ctr3 = 0;
      mode = 2;
    }

    // KONIEC GWNEJ PTLI
  }
}
