/* ==============================\
EmbarcaTech
Francisco Alexandro
⢀⡀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀
⢻⣿⡗⢶⣤⣀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⣀⣠⣄
⠀⢻⣇⠀⠈⠙⠳⣦⣀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⣀⣤⠶⠛⠋⣹⣿⡿
⠀⠀⠹⣆⠀⠀⠀⠀⠙⢷⣄⣀⣀⣀⣤⣤⣤⣄⣀⣴⠞⠋⠉⠀⠀⠀⢀⣿⡟⠁
⠀⠀⠀⠙⢷⡀⠀⠀⠀⠀⠉⠉⠉⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⣠⡾⠋⠀⠀
⠀⠀⠀⠀⠈⠻⡶⠂⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⢠⣠⡾⠋⠀⠀⠀⠀
⠀⠀⠀⠀⠀⣼⠃⠀⢠⠒⣆⠀⠀⠀⠀⠀⠀⢠⢲⣄⠀⠀⠀⢻⣆⠀⠀⠀⠀⠀
⠀⠀⠀⠀⢰⡏⠀⠀⠈⠛⠋⠀⢀⣀⡀⠀⠀⠘⠛⠃⠀⠀⠀⠈⣿⡀⠀⠀⠀⠀
⠀⠀⠀⠀⣾⡟⠛⢳⠀⠀⠀⠀⠀⣉⣀⠀⠀⠀⠀⣰⢛⠙⣶⠀⢹⣇⠀⠀⠀⠀
⠀⠀⠀⠀⢿⡗⠛⠋⠀⠀⠀⠀⣾⠋⠀⢱⠀⠀⠀⠘⠲⠗⠋⠀⠈⣿⠀⠀⠀⠀
⠀⠀⠀⠀⠘⢷⡀⠀⠀⠀⠀⠀⠈⠓⠒⠋⠀⠀⠀⠀⠀⠀⠀⠀⠀⢻⡇⠀⠀⠀
⠀⠀⠀⠀⠀⠈⡇⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⢸⣧⠀⠀⠀
⠀⠀⠀⠀⠀⠈⠉⠉⠉⠉⠉⠉⠉⠉⠉⠉⠉⠉⠉⠉⠉⠉⠉⠉⠉⠉⠁⠀⠀⠀
| [Fazendo o cofrinho]
=================================*/
#include <stdio.h>
#include "pico/stdlib.h"
#include "pico/cyw43_arch.h"
#include "hardware/pwm.h"
#define LED_R 15
#define LED_G 14
// pinos do teclado
#define ROWS 4
#define COLS 4
#define BT 27
#define BUZZER 12
int contador = 0;
volatile int tentativas = 0;
uint8_t senha_cadastrada[] = { 1, 2, 3, 4};
uint8_t senha_digitada[] = { 0, 0, 0, 0};
uint8_t display_state[] = { false, false, false, false};
// Definindo as teclas
const char keypad[ROWS][COLS] = {
{ '1', '2', '3', 'A' },
{ '4', '5', '6', 'B' },
{ '7', '8', '9', 'C' },
{ '*', '0', '#', 'D' }
};
const uint8_t row_pins[4] = {16, 17, 18, 19};
const uint8_t col_pins[4] = {20, 21, 22, 26};
// pinos do display
const uint8_t segment_pins[] = {0, 1, 2, 3, 4, 5, 6};
const uint8_t display_pins[] = {7, 8, 9, 10};
// Mapeamento dos dígitos para os segmentos do display
const uint8_t digits[10][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, 1, 0, 1, 1} // 9
};
void initLeds(){
gpio_init(LED_R);
gpio_init(LED_G);
gpio_set_dir(LED_R, GPIO_OUT);
gpio_set_dir(LED_G, GPIO_OUT);
}
initBuzzer(){
gpio_set_function(BUZZER, GPIO_FUNC_PWM);
uint slice = pwm_gpio_to_slice_num(BUZZER);
pwm_set_clkdiv(slice, 1);
}
// inicialização do display
void initDisplay() {
for (int i = 0; i < 7; i++) {
gpio_init(segment_pins[i]);
gpio_set_dir(segment_pins[i], GPIO_OUT);
}
for (int i = 0; i < 4; i++) {
gpio_init(display_pins[i]);
gpio_set_dir(display_pins[i], GPIO_OUT);
gpio_put(display_pins[i], true); // Inicializa todos os displays como "desligados"
}
}
// exibe um dígito especificado
void show_digit(uint8_t display, uint8_t digit) {
// Desliga todos os displays antes de ativar o desejado
for (int i = 0; i < 4; i++) {
gpio_put(display_pins[i], 1);
}
// Define os segmentos para exibir o dígito
for (int i = 0; i < 7; i++) {
gpio_put(segment_pins[i], digits[digit][i]);
}
// Liga o display correspondente
gpio_put(display_pins[display], 0);
}
// inicialização do teclado
void initKeypad() {
for (int i = 0; i < ROWS; i++) {
gpio_init(row_pins[i]);
gpio_set_dir(row_pins[i], GPIO_OUT); // saída
gpio_put(row_pins[i], 0); // Inicializa a linha em baixo
}
for (int i = 0; i < COLS; i++) {
gpio_init(col_pins[i]);
gpio_set_dir(col_pins[i], GPIO_IN);
// aqui estamos deixando a coluna sempre ligada
gpio_pull_up(col_pins[i]);
}
}
// resolvendo o bounce do teclado para leitura correta
bool debounce(uint pin) {
if (!gpio_get(pin)) {
sleep_ms(50); // Aguarda 50ms para estabilizar
return !gpio_get(pin); // Verifica novamente se o estado é estável
}
return false;
}
// Lendo os botões do teclado
char readKey() {
for (int row = 0; row < ROWS; row++) {
gpio_put(row_pins[row], 0); // Ativa a linha (linha baixa)
for (int col = 0; col < COLS; col++) {
if (debounce(col_pins[col])) {
gpio_put(row_pins[row], 1); // Desativa a linha (linha alta)
return keypad[row][col];
}
}
gpio_put(row_pins[row], 1); // Desativa a linha após a verificação
}
return '\0'; // Retorna nulo se nenhuma tecla foi pressionada
}
// Converte o caractere para um número
uint8_t charToDigit(char key) {
if (key >= '0' && key <= '9') {
return key - '0'; // Converte '0'-'9' para 0-9
}
return 0; // Retorna 0 se não for um número válido
}
// exibe o valor digitado (no teclado) no Display
void showInDisplay(char key, int display_selected) {
uint8_t digit = charToDigit(key);
senha_digitada[contador] = digit;
}
void disableAllDisplays(){
for(int i = 0; i < 4; i++){
gpio_put(display_pins[i], false);
}
}
void resetDisplay(){
for(int i = 0; i < 4; i++){
senha_digitada[i] = 0;
}
}
// Verifica se a senha está correta
bool comparePassword(){
for(int i = 0; i < 4; i++){
if(senha_cadastrada[i] != senha_digitada[i]){
return false;
}
}
return true;
}
// Ativa o buzzer em uma frequência e duração especifica
void beepBuzzer(){
pwm_set_gpio_level(BUZZER, 2000);
sleep_ms(700);
pwm_set_gpio_level(BUZZER, 0);
}
void beepBuzzerSenhaCorreta(){
for(int i = 0; i < 2; i++){
pwm_set_gpio_level(BUZZER, 2000);
sleep_ms(200);
pwm_set_gpio_level(BUZZER, 0);
sleep_ms(200);
}
}
// Led piscando quando coloca senha errada
void loopLedSenhaErrada(){
disableAllDisplays();
beepBuzzer();
for(int i = 0; i < 3; i++){
gpio_put(LED_R, 1);
sleep_ms(500);
gpio_put(LED_R, 0);
sleep_ms(500);
}
}
// Lendo a senha
void readingPassword() {
// Enquanto não tiver digitado todos os 4 dígitos
if (contador < 4) {
char tecla = readKey(); // Lê a tecla pressionada
// Se uma tecla foi pressionada
if (tecla != '\0') {
showInDisplay(tecla, contador); // Exibe o número no display
senha_digitada[contador] = charToDigit(tecla); // Salva o dígito
contador++; // Incrementa o contador para a próxima posição
sleep_ms(200); // Atraso para evitar múltiplas leituras
}
}
// Após ter digitado todos os 4 dígitos, verifica a senha
if (contador == 4) {
if (comparePassword()) {
gpio_put(LED_G, 1); // Acende o LED verde para senha correta
beepBuzzerSenhaCorreta();
} else {
tentativas++;
// Acende o LED vermelho para erro
if(tentativas < 3){
loopLedSenhaErrada();
}
resetDisplay(); // Reseta o display
}
contador = 0; // Reseta o contador após a verificação
}
// Exibe os números digitados no display
show_digit(0, senha_digitada[0]);
show_digit(1, senha_digitada[1]);
show_digit(2, senha_digitada[2]);
show_digit(3, senha_digitada[3]);
}
// Bloqueio temporário ao errar a senha 3 vezes
void bloqueioTemporario(){
disableAllDisplays();
gpio_put(LED_R, 1);
sleep_ms(8000);
gpio_put(LED_R, 0);
}
int main() {
stdio_init_all();
initDisplay();
initKeypad();
initLeds();
initBuzzer();
while (true) {
if(tentativas > 2){
bloqueioTemporario();
tentativas = 0;
}
readingPassword();
sleep_ms(50); // atraso para a leitura do teclado
}
return 0;
}