//ALESSANDRA KIMIE HIRO - GRUPO 2 - AULA SÍNCRONA 21.01.2025
#include <stdio.h>
#include "pico/stdlib.h"
#include <string.h>
#define SET 1
#define RESET 0
#define COMP 4
// Arrays para armazenar as senhas inseridas (máximo de 4 caracteres)
char senha1[COMP+1] = {0};
char senha2[COMP+1] = {0};
// Define os pinos GPIO para as linhas e para as colunas do teclado
const uint8_t Linha[] = {2, 3, 4, 5}; // Linhas do teclado (conectadas ao microcontrolador)
const uint8_t Coluna[] ={6, 7, 8, 9}; // Colunas do teclado (conectadas ao microcontrolador)
// Mapeamento das teclas em uma matriz 4x4
char teclas[4][4] = {
{'1', '2', '3', 'A'},
{'4', '5', '6', 'B'},
{'7', '8', '9', 'C'},
{'*', '0', '#', 'D'}
};
// Definição dos pinos para os segmentos do display de 7 segmentos
const uint8_t segment_pins[] = {21, 22, 26, 27, 28, 20, 19};
// Pinos para controlar a multiplexação dos displays
const uint8_t mux_display_pins[] = {10, 11, 12, 13};
const uint8_t num_display = 4; // Número de displays a serem usados (4 displays)
// Definição dos pinos para os LEDs (Indicação de acesso correto/incorreto)
const uint8_t LedR = 15; // LED Vermelho (Erro)
const uint8_t LedG = 14; // LED Verde (Acesso autorizado)
// Mapeamento dos dígitos para os segmentos dos displays de 7 segmentos
const int display[16][7] = {
{1, 1, 1, 1, 1, 1, 0}, // 0
{0, 1, 1, 0, 0, 0, 0}, // 1
{1, 1, 0, 1, 1, 0, 1}, // 2
{1, 1, 1, 1, 0, 0, 1}, // 3
{0, 1, 1, 0, 0, 1, 1}, // 4
{1, 0, 1, 1, 0, 1, 1}, // 5
{1, 0, 1, 1, 1, 1, 1}, // 6
{1, 1, 1, 0, 0, 0, 0}, // 7
{1, 1, 1, 1, 1, 1, 1}, // 8
{1, 1, 1, 0, 0, 1, 1}, // 9
{1, 1, 1, 0, 1, 1, 1}, // A
{0, 0, 1, 1, 1, 1, 1}, // B
{1, 0, 0, 1, 1, 1, 0}, // C
{0, 1, 1, 1, 1, 0, 1}, // D
{0, 1, 1, 0, 1, 1, 1}, // #
{1, 1, 0, 0, 0, 1, 1} // *
};
// Função para configuracao incial
void setup(){
// Inicializa os LEDs e os configura como saídas
gpio_init(LedR);
gpio_init(LedG);
gpio_set_dir(LedR, GPIO_OUT);
gpio_set_dir(LedG, GPIO_OUT);
gpio_put(LedR, 0); // Inicializa o LED vermelho apagado
gpio_put(LedG, 0); // Inicializa o LED verde apagado
// Configuração das linhas do teclado como saídas e as colunas como entradas
for (int i = 0; i < 4; i++) {
gpio_init(Linha[i]);
gpio_set_dir(Linha[i], GPIO_OUT);
gpio_put(Linha[i], RESET); // Define inicialmente as linhas como LOW
gpio_init(Coluna[i]);
gpio_set_dir(Coluna[i], GPIO_IN); // Colunas como entradas
gpio_pull_down(Coluna[i]); // Habilita o pull-down para forçar as colunas a zero
}
// Configuração dos pinos dos segmentos do display
for (int i = 0; i < 7; i++) {
gpio_init(segment_pins[i]);
gpio_set_dir(segment_pins[i], GPIO_OUT); // Configura como saída
}
// Configuração dos pinos de multiplexação dos displays
for (int i = 0; i < num_display; i++) {
gpio_init(mux_display_pins[i]);
gpio_set_dir(mux_display_pins[i], GPIO_OUT);
gpio_put(mux_display_pins[i], 1); // Desativa os displays inicialmente (desliga os displays)
}
}
// Função para realizar a leitura do teclado (matriz 4x4) e retornar a tecla pressionada
char leitura_teclado() {
for (int row = 0; row < 4; row++) {
// Define a linha atual para HIGH
gpio_put(Linha[row], SET);
for (int col = 0; col < 4; col++) {
if (gpio_get(Coluna[col])) { // Verifica se a coluna correspondente foi pressionada
sleep_ms(100); // Aguarda um tempo para estabilizar o sinal
while (gpio_get(Coluna[col])); // Espera a tecla ser liberada
gpio_put(Linha[row], RESET); // Reseta a linha atual para LOW
return teclas[row][col]; // Retorna a tecla pressionada
}
}
gpio_put(Linha[row], RESET); // Reseta a linha atual após a verificação
}
return 0; // Retorna 0 se nenhuma tecla foi pressionada
}
// Função para converter um caractere em seu valor numérico correspondente
int charToNum(char c) {
if (c >= '0' && c <= '9') {
return c - '0'; // Converte caracteres de '0'-'9' para 0-9
} else if (c >= 'A' && c <= 'F') { // Suporta apenas letras maiúsculas 'A' a 'F'
return c - 'A' + 10; // Converte 'A'-'F' para 10-15
} else if (c == '#') {
return 14; // Converte '#' para 14
} else if (c == '*') {
return 15; // Converte '*' para 15
} else {
return -1; // Retorna -1 para caracteres inválidos
}
}
// Função para capturar a senha digitada pelo usuário
void get_senha(char *senha, int tam) {
char senhadisp[COMP]; // Variável para armazenar os números correspondentes aos caracteres
int index = 0;
// Lê a senha digitada até atingir o comprimento especificado
while (index < tam) {
char key = leitura_teclado(); // Lê a tecla pressionada
if (key != 0) {
printf("%c", key); // Exibe o caractere pressionado
senha[index] = key; // Armazena o caractere na senha
senhadisp[index] = charToNum(key); // Converte o caractere para o número correspondente
index++; // Incrementa o índice da senha
sleep_ms(100); // Delay para evitar leituras rápidas demais
}
// Exibe os dígitos da senha no display durante a digitação
for (int i = 0; i < index; i++) {
show_digit(i, senhadisp[i]); // Mostra cada dígito no display
}
}
senha[tam] = '\0'; // Finaliza a string da senha com o caractere nulo
printf("\n Processando...\n");
// Exibe a senha final por 0,4 segundos para confirmação
absolute_time_t start_time = get_absolute_time();
while (absolute_time_diff_us(start_time, get_absolute_time()) < 400000) { // 0,4 segundo
for (int i = 0; i < index; i++) {
show_digit(i, charToNum(senha[i])); // Exibe a senha nos displays
}
}
clear_digits(); // Limpa os displays após a exibição da senha
}
// Função para comparar duas senhas
bool compare_senhas(const char *senha1, const char *senha2) {
return strcmp(senha1, senha2) == 0; // Retorna verdadeiro se as senhas forem iguais
}
// Função para mostrar um dígito específico em um display selecionado
void show_digit(uint8_t digits, uint8_t digit){
// Desativa todos os displays de catodo comum
for (int i = 0; i < num_display; i++) {
gpio_put(mux_display_pins[i], 1);
}
// Ativa os segmentos correspondentes ao dígito
for (int i = 0; i < 7; i++) {
gpio_put(segment_pins[i], display[digit][i]); // Configura os pinos dos segmentos
}
// Ativa o display desejado
gpio_put(mux_display_pins[digits], 0);
}
// Função para limpar todos os displays
void clear_digits(void) {
for (int i = 0; i < num_display; i++) {
gpio_put(mux_display_pins[i], 1); // Desativa todos os displays
}
}
// Função principal
int main() {
stdio_init_all();
setup(); // Configuracao inicial
printf("Cadastro da senha do cofre com 4 digitos!\n");
get_senha(senha1, COMP); // Solicita a senha do usuário
printf("\nSenha gravada!\n");
int cont = 0; // Contador de tentativas de senha
bool acesso = 1; // Flag de controle para acesso ao cofre
// Loop para tentativas de acesso
while (acesso) {
printf("Digite a senha do cofre de 4 digitos!\n");
get_senha(senha2, COMP); // Solicita a senha para acesso
if (compare_senhas(senha2, senha1)) { // Verifica se a senha inserida é correta
printf("\nSenha Correta: Acesso ao cofre!\n");
gpio_put(LedG, 1); // Acende o LED verde para indicar acesso autorizado
acesso = !acesso; // Encerra o loop se a senha for correta
}
else {
printf("\nSenha Incorreta: Acesso ao cofre negado !\n");
cont++; // Incrementa o contador de tentativas
gpio_put(LedR, 1); // Acende o LED vermelho para indicar erro
sleep_ms(500); // Aguarda meio segundo
gpio_put(LedR, 0); // Apaga o LED vermelho
}
sleep_ms(50); // Estabilização do sistema após cada tentativa
// Bloqueia o sistema por 5 segundos após 3 tentativas erradas
if (cont > 2) {
printf("\n Três tentativas bloqueadas por 5 segundos!\n");
gpio_put(LedR, 1); // Acende o LED vermelho para indicar bloqueio
sleep_ms(5000); // Aguarda 5 segundos de bloqueio
gpio_put(LedR, 0); // Apaga o LED vermelho após o bloqueio
cont = 0; // Reseta o contador de tentativas
}
}
}