#include <stdio.h>
#include "pico/stdlib.h"
//definicoes globais
#define ROW 4
#define COLUM 3
#define LED_VERDE 27
#define LED_VERMELHO 28
#define SECURITY_BUZZER 26
#define BLOCK_TIME_IN_MS 10000
// O objetivo deste projeto é criar um sistema embarcado que permita o
// controle de um cofre digital por meio de uma senha de 4 dígitos. A senha
// deve ser inserida utilizando um teclado matricial, e o estado do cofre (aberto
// ou fechado) será indicado por dois LEDs: um LED verde, que acenderá
// quando o cofre estiver aberto, e um LED vermelho, que piscará em caso de
// senha incorreta. Além disso, após três tentativas incorretas consecutivas,
// o sistema deve entrar em um modo de bloqueio temporário, desativando a
// entrada de novas tentativas por um período determinado.
// Embarcatech 2024 - Projeto 7 - cofre inteligente versao com mais implementacoes
// autor: Luis Ferlim
// luisferlim.com
//o display de 7 seguimentos sera implementado depois
//definicao dos pinos
const uint8_t columPins[COLUM] = {3, 4, 5};
const uint8_t rowPins[ROW] = {6, 7, 8, 9};
const uint8_t displayPins[] = {10, 11, 12 , 13 , 14 ,15 , 16};
const uint8_t displaySelectPins[] = {17, 18, 19, 20};
//por algum motivo tive que colocar 5 na posição porque restava lixo nas variaveis fazendo com que a
//verificacao nao fosse possivel
char keypadInput;
//coloque aqui a senha de 4 digitos que deseja
char key [5] = "3#85";
char attempt[5] = "";
uint8_t result;
uint8_t attemptWordPos;
uint8_t TENTATIVAS = 3;
bool validacao;
const char keyMap [ROW][COLUM] = {
{'#', '0', '*'},
{'9', '8', '7'},
{'6', '5', '4'},
{'3', '2', '1'}
};
//mapeamento dos digitos a serem mostrados
const uint8_t digits [13][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
{0,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,1,0,1,1}, //9
{1,1,0,0,0,1,1}, //*
{0,1,1,0,1,1,1}, //#
{0,0,0,1,0,0,0}, //_
};
//assinaturas
void init();
void limpaDisplay();
void cicloEntrada();
void atualizaDisplay();
void desligaDisplays(); //auxiliar de atualizaDisplay
uint8_t verificaTentativas(uint8_t tentativasRestantes);
uint8_t converteEntrada(char entrada); //auxiliar de atualizaDisplay
char leitura();
bool verificacao();
int main() {
stdio_init_all();
init();
attemptWordPos = 0;
while (true) {
cicloEntrada();
}
}
void cicloEntrada() {
keypadInput = leitura();
if (keypadInput != '\0') {
//coloca na string de tentativa
attempt[attemptWordPos] = keypadInput;
printf("tentativa: %s\n", attempt);
printf("entrada: %c\n", keypadInput);
// aqui ficaria o codigo para atualizar display
attemptWordPos++;
atualizaDisplay();
//verificacao ( a cada 4 entradas)
if (attemptWordPos == 4) {
limpaDisplay(); //limpa o display
validacao = verificacao();
TENTATIVAS--;
//retorno ao usuario
//a senha inserida esta correta
if (validacao) {
printf("Sistema liberado\n");
for (;;) {
limpaDisplay();
gpio_put(LED_VERDE, validacao);
}
} else {
printf("Senha incorreta\n");
gpio_put(LED_VERMELHO, !validacao);
//mais ou menos um delay de 2000 ms
for (int time = 0; time < 2000; time ++){
limpaDisplay();
sleep_ms(1);
}
}
gpio_put(LED_VERMELHO, 0);
//verifica o bloqueio
TENTATIVAS = verificaTentativas(TENTATIVAS);
}
sleep_ms(40);
} else{
atualizaDisplay();
}
}
bool verificacao() {
result = strcmp(key, attempt);
if (result == 0) {
return 1;
} else {
attemptWordPos = 0;
return 0;
}
}
char leitura() {
for (int row = 0; row < ROW; row ++) {
gpio_put(rowPins[row], 1); //coloca em nivel alto, util para quando formos verificar o pull down
for (int colum = 0; colum < COLUM; colum++) {
//verifica o estado de cada item na coluna
if (gpio_get(columPins[colum])) {
gpio_put(rowPins[row], 0);
return keyMap [row][colum];
}
}
gpio_put(rowPins[row], 0); //poe a linha atual em nivel baixo
}
return '\0';
}
//seta tudo para _
void limpaDisplay(){
for (int i = 0; i< 4; i++){
gpio_put(displaySelectPins[i], 0);
}
for (int i = 0; i<7; i++){
gpio_put(displayPins[i], digits[12][i]);
}
}
//dependendo de quantos digitos foram inseridos, gera uma saida para o display de sete seguimentos
void atualizaDisplay(){
if (attemptWordPos == 1){
//mostra o digito na posicao 0 e seta os demais para '_'
//codigo simples de multiplexacao
for (int time = 0; time < 15; time ++){
desligaDisplays();
for (int i = 0; i < 7; i++){
gpio_put(displayPins[i], digits[converteEntrada(attempt[0])][i]);
}
gpio_put(displaySelectPins[0], 0);
sleep_ms(5);
desligaDisplays();
for (int i = 0; i < 7; i++){
gpio_put(displayPins[i], digits[12][i]);
}
gpio_put(displaySelectPins[1], 0);
sleep_ms(5);
desligaDisplays();
for (int i = 0; i < 7; i++){
gpio_put(displayPins[i], digits[12][i]);
}
gpio_put(displaySelectPins[2], 0);
sleep_ms(5);
desligaDisplays();
for (int i = 0; i < 7; i++){
gpio_put(displayPins[i], digits[12][i]);
}
gpio_put(displaySelectPins[3], 0);
sleep_ms(5);
}
} else if (attemptWordPos == 2){
//mostra o digito na posicao 0 e 1 e seta os demais para '_'
for (int time = 0; time < 15; time ++){
desligaDisplays();
for (int i = 0; i < 7; i++){
gpio_put(displayPins[i], digits[converteEntrada(attempt[0])][i]);
}
gpio_put(displaySelectPins[0], 0);
sleep_ms(5);
desligaDisplays();
for (int i = 0; i < 7; i++){
gpio_put(displayPins[i], digits[converteEntrada(attempt[1])][i]);
}
gpio_put(displaySelectPins[1], 0);
sleep_ms(5);
desligaDisplays();
for (int i = 0; i < 7; i++){
gpio_put(displayPins[i], digits[12][i]);
}
gpio_put(displaySelectPins[2], 0);
sleep_ms(5);
desligaDisplays();
for (int i = 0; i < 7; i++){
gpio_put(displayPins[i], digits[12][i]);
}
gpio_put(displaySelectPins[3], 0);
sleep_ms(5);
}
} else if (attemptWordPos == 3){
//mostra o digito na posicao 0, 1 e 2 e seta o da posicao 3 para para '_'
for (int time = 0; time < 15; time ++){
desligaDisplays();
for (int i = 0; i < 7; i++){
gpio_put(displayPins[i], digits[converteEntrada(attempt[0])][i]);
}
gpio_put(displaySelectPins[0], 0);
sleep_ms(5);
desligaDisplays();
for (int i = 0; i < 7; i++){
gpio_put(displayPins[i], digits[converteEntrada(attempt[1])][i]);
}
gpio_put(displaySelectPins[1], 0);
sleep_ms(5);
desligaDisplays();
for (int i = 0; i < 7; i++){
gpio_put(displayPins[i], digits[converteEntrada(attempt[2])][i]);
}
gpio_put(displaySelectPins[2], 0);
sleep_ms(5);
desligaDisplays();
for (int i = 0; i < 7; i++){
gpio_put(displayPins[i], digits[12][i]);
}
gpio_put(displaySelectPins[3], 0);
sleep_ms(5);
}
} else if (attemptWordPos == 4){
for (int time = 0; time < 15; time ++){
desligaDisplays();
for (int i = 0; i < 7; i++){
gpio_put(displayPins[i], digits[converteEntrada(attempt[0])][i]);
}
gpio_put(displaySelectPins[0], 0);
sleep_ms(5);
desligaDisplays();
for (int i = 0; i < 7; i++){
gpio_put(displayPins[i], digits[converteEntrada(attempt[1])][i]);
}
gpio_put(displaySelectPins[1], 0);
sleep_ms(5);
desligaDisplays();
for (int i = 0; i < 7; i++){
gpio_put(displayPins[i], digits[converteEntrada(attempt[2])][i]);
}
gpio_put(displaySelectPins[2], 0);
sleep_ms(5);
desligaDisplays();
for (int i = 0; i < 7; i++){
gpio_put(displayPins[i], digits[converteEntrada(attempt[3])][i]);
}
gpio_put(displaySelectPins[3], 0);
sleep_ms(5);
}
}
}
uint8_t verificaTentativas(uint8_t tentativasRestantes){
if (tentativasRestantes == 0) {
printf("Sistema bloqueado\n");
gpio_put(LED_VERMELHO, 1);
gpio_put(SECURITY_BUZZER, 1);
sleep_ms(BLOCK_TIME_IN_MS);
gpio_put(LED_VERMELHO, 0);
gpio_put(SECURITY_BUZZER, 0);
//reiniciando o sistema
printf("Sistema reiniciando\n");
return 3;
}
return tentativasRestantes;
}
//funcao para converter uma entrada do keypad e tranformar numa posicao dos digitos
uint8_t converteEntrada(char entrada){
switch (entrada){
case '1': return 1;
case '2': return 2;
case '3': return 3;
case '4': return 4;
case '5': return 5;
case '6': return 6;
case '7': return 7;
case '8': return 8;
case '9': return 9;
case '*': return 10;
case '0': return 0;
case '#': return 11;
default: printf("erro");
}
}
//funcao para desligar todos os displays e evitar a fadiga de codigo
void desligaDisplays(){
gpio_put(displaySelectPins[0], 1);
gpio_put(displaySelectPins[1], 1);
gpio_put(displaySelectPins[2], 1);
gpio_put(displaySelectPins[3], 1);
}
//inicializacao e definicao das portas
void init () {
//iniciando os pinos da linha do keypad
for (int i = 0; i < ROW; i++) {
gpio_init(rowPins[i]);
gpio_set_dir(rowPins[i], GPIO_OUT);
gpio_put(rowPins[i], 0);
}
//iniciando os pinos da coluna do keypad
for (int i = 0; i < COLUM; i++) {
gpio_init(columPins[i]);
gpio_set_dir(columPins[i], GPIO_IN);
gpio_pull_down(columPins[i]);
}
//iniciando os pinos do display (catodo comum)
for (int i =0; i< 7; i++){
gpio_init(displayPins[i]);
gpio_set_dir(displayPins[i], GPIO_OUT);
gpio_put(displayPins[i], digits[12][i]);
}
// inicia os pinos de selecao do display - todos como _
for (int i =0; i < 4; i++){
gpio_init(displaySelectPins[i]);
gpio_set_dir(displaySelectPins[i], GPIO_OUT);
gpio_put(displaySelectPins[i], 0);
}
//outras inicializacoes
gpio_init(LED_VERMELHO);
gpio_init(LED_VERDE);
gpio_init(SECURITY_BUZZER);
gpio_set_dir(LED_VERMELHO, GPIO_OUT);
gpio_set_dir(LED_VERDE, GPIO_OUT);
gpio_set_dir(SECURITY_BUZZER, GPIO_OUT);
}