#define __ATmega2560__ // Define que estamos utilizando o ATmega2560
#define __AVR_ATmega2560__ // Define que estamos utilizando o ATmega2560
#ifndef F_CPU
#define F_CPU 16000000UL // Define a frequência do microcontrolador (16 MHz)
#endif
#include <stdint.h>
#include <avr/io.h>
#include <avr/pgmspace.h>
#include <stdbool.h>
#include <stdint.h>
#include <util/delay.h>
#include <stdlib.h>
#include <avr/interrupt.h>
#include "usart.h"
#define LED1_PIN PB7 // LED para o PIR1
#define LED2_PIN PB6 // LED para o PIR1
#define BUZZER_PIN PC0
#define PIR1_PIN PC5
#define ROW1_PIN 22
#define ROW2_PIN 23
#define ROW3_PIN 24
#define ROW4_PIN 25
#define COL1_PIN 26
#define COL2_PIN 27
#define COL3_PIN 28
typedef enum {
STAND_BY,
ALARME_ARMADO,
ALARME_DISPARADO
} Estado;
volatile Estado estadoAtual = ALARME_ARMADO;
volatile bool alarmeAtivado = false;
volatile int sensorDisparado = 0;
volatile uint16_t tick;
bool alarmeDisparado_msg = false;
char senha[5] = "1234";
char entrada[5];
int posicao = 0;
char lerKeypad();
char mapearTecla(int linha, int coluna);
void verificarSenha();
void redefinirSenha();
void dispararAlarme();
void ligaLed();
bool debounceSensor(uint8_t pin);
void processarEntradaKeypad();
void configuracao_sistema(void) {
// Configura o timer0 para gerar interrupções a cada 1,3 ms
TCCR0A = 0x02; // WGM[1:0]=10 modo CTC
TCCR0B = 0x04; // CS0[2:0]=100 N=256
TIMSK0 = 0x02; // Ativa OCIE0A
OCR0A = 80; // TOP
TCNT0 = 0x00; // Zera o contador
sei(); // Ativa as interrupções
}
void ligaLed() {
for (int i = 0; i < 4; i++) {
PORTB ^= ((1 << LED1_PIN) );
PORTC |= (1 << BUZZER_PIN); // Liga o buzzer
_delay_ms(50);
PORTB ^= ((1 << LED2_PIN) );
PORTC &= ~(1 << BUZZER_PIN); // Liga o buzzer
}
PORTB |= ((1 << LED1_PIN) );
PORTB ^= ((1 << LED2_PIN) );
}
void configura_pinos() {
// Configura os LEDs como saída
DDRB |= (1 << LED1_PIN) ;
DDRB |= (1 << LED2_PIN) ;
// Configura os sensores PIR como entrada com pull-up
DDRC &= ~(1 << PIR1_PIN) ;
PORTC |= (1 << PIR1_PIN) ;
// Configura o buzzer como saída
DDRC |= (1 << BUZZER_PIN);
// Configura o teclado matricial
DDRA |= 0x0F; // Linhas como saída
DDRA &= ~0xF0; // Colunas como entrada
PORTA |= 0xF0; // Ativa pull-up nas colunas
}
char lerKeypad() {
static char ultimaTecla = '\0';
static bool teclaPressionada = false;
for (int linha = 0; linha < 4; linha++) {
PORTA = ~(1 << linha);
_delay_us(100);
uint8_t colunas = PINA & 0xF0;
if (colunas != 0xF0) {
_delay_ms(40);
colunas = PINA & 0xF0;
if (colunas != 0xF0) {
for (int coluna = 0; coluna < 3; coluna++) {
if ((colunas & (1 << (coluna + 4))) == 0) {
char teclaAtual = mapearTecla(linha, coluna);
if (!teclaPressionada && teclaAtual != ultimaTecla) {
_delay_ms(50);
if ((PINA & (1 << (coluna + 4))) == 0) {
ultimaTecla = teclaAtual;
teclaPressionada = true;
return teclaAtual;
}
}
}
}
}
} else {
teclaPressionada = false;
}
}
ultimaTecla = '\0';
return '\0';
}
char mapearTecla(int linha, int coluna) {
char matriz[4][3] = {
{'1', '2', '3'},
{'4', '5', '6'},
{'7', '8', '9'},
{'*', '0', '#'}
};
return matriz[linha][coluna];
}
int main(void) {
USART0_configura();
configura_pinos();
configuracao_sistema();
while (1) {
switch (estadoAtual) {
case STAND_BY:
if (!alarmeAtivado) {
USART0_transmite_string_FLASH(PSTR("\nInsira a senha para ativar o alarme.\n"));
alarmeAtivado = true; // Garante que a mensagem seja exibida apenas uma vez
}
processarEntradaKeypad();
break;
case ALARME_ARMADO:
if (!alarmeAtivado) {
ligaLed
();
USART0_transmite_string_FLASH(PSTR("\nALARME LIGADO\n"));
alarmeAtivado = true;
}
if (debounceSensor(PIR1_PIN)) {
USART0_transmite_string_FLASH(PSTR("Movimento detectado na casa "));
estadoAtual = ALARME_DISPARADO;
dispararAlarme(1);
alarmeAtivado = false;
alarmeDisparado_msg = true;
}
break;
case ALARME_DISPARADO:
if (alarmeDisparado_msg) {
USART0_transmite_string_FLASH(PSTR("Insira a senha para desarmar.\n"));
alarmeDisparado_msg = false;
}
processarEntradaKeypad();
break;
}
}
}
void processarEntradaKeypad() {
char tecla = lerKeypad();
if (tecla != '\0') {
if (tecla == '#') {
if (posicao == 4) {
verificarSenha();
} else {
USART0_transmite_string_FLASH(PSTR("\nSenha incompleta!\n"));
posicao = 0;
memset(entrada, 0, sizeof(entrada));
}
} else if (tecla == '*') {
if (estadoAtual == STAND_BY && posicao == 4) {
redefinirSenha();
} else {
USART0_transmite_string_FLASH(PSTR("\nEntrada inválida para redefinir senha!\n"));
posicao = 0;
memset(entrada, 0, sizeof(entrada));
}
} else if (posicao < 4) {
entrada[posicao] = tecla;
posicao++;
USART0_transmite_string_FLASH(PSTR("*"));
}
}
}
void verificarSenha() {
entrada[posicao] = '\0';
if (strcmp(entrada, senha) == 0) {
if (estadoAtual == STAND_BY) {
estadoAtual = ALARME_ARMADO;
alarmeAtivado = false; // Garante que o LED pisque ao entrar no estado armado
} else if (estadoAtual == ALARME_DISPARADO) {
estadoAtual = STAND_BY;
ligaLed
(); // Pisca o LED antes de desligá-lo
PORTB &= ~(1 << LED1_PIN); // Desliga o LED
PORTC &= ~(1 << BUZZER_PIN); // Desliga o buzzer
alarmeAtivado = false; // Garante que a mensagem seja exibida ao retornar ao estado STAND_BY
USART0_transmite_string_FLASH(PSTR("\nAlarme desativado!\n"));
dispararAlarme(0);
}
} else {
USART0_transmite_string_FLASH(PSTR("\nSenha incorreta!\n"));
}
posicao = 0;
memset(entrada, 0, sizeof(entrada));
}
void redefinirSenha() {
USART0_transmite_string_FLASH(PSTR("\nDigite a nova senha:\n"));
posicao = 0;
while (posicao < 4) {
char tecla = lerKeypad();
if (tecla != '\0') {
entrada[posicao] = tecla;
posicao++;
USART0_transmite_string_FLASH(PSTR("*"));
}
}
entrada[posicao] = '\0';
strcpy(senha, entrada);
USART0_transmite_string_FLASH(PSTR("\nNova senha salva com sucesso!\n"));
posicao = 0;
memset(entrada, 0, sizeof(entrada));
}
void dispararAlarme(int sensorID) {
sensorDisparado = sensorID;
}
bool debounceSensor(uint8_t pin) {
bool estadoInicial = (PINC & (1 << pin)) != 0;
_delay_ms(50);
bool estadoFinal = (PINC & (1 << pin)) != 0;
return estadoInicial && estadoFinal;
}
ISR(TIMER0_COMPA_vect) {
tick++;
if (tick == 200) {
tick = 0;
switch (sensorDisparado) {
case 1:
PORTB ^= (1 << LED1_PIN);
PORTC ^= (1 << BUZZER_PIN); // Acende o LED1
_delay_ms(100);
PORTB ^= (1 << LED2_PIN);
// Alterna o estado do buzzer
break;
default:
break; // Nenhuma ação se sensorID for inválido
}
}
}