#include <stdio.h>
#include <string.h>
#include <stdlib.h>
#include "pico/stdlib.h"
#include "pico/binary_info.h"
#include "ssd1306.h"
#include "hardware/i2c.h"
#include "hardware/adc.h"
// Definição dos pinos I2C
const uint I2C_SDA = 14;
const uint I2C_SCL = 15;
// Definição dos pinos do Joystick
#define JOY_X 26
#define JOY_Y 27
#define JOY_SW 22
// Definição dos pinos dos LEDs RGB
#define LED_R_PIN 13
#define LED_G_PIN 11
#define LED_B_PIN 12
// Definição dos botões
#define btn_A 5
#define btn_B 6
// Função para configurar os LEDs RGB (vermelho, verde e azul) com os valores de entrada
void set_rgb(uint r, uint g, uint b) {
gpio_put(LED_R_PIN, r);
gpio_put(LED_G_PIN, g);
gpio_put(LED_B_PIN, b);
}
// Função para exibir um menu no display OLED, destacando a opção selecionada
void display_oled(char *menu[], int selected_option) {
struct render_area frame_area = {
.start_column = 0,
.end_column = ssd1306_width - 1,
.start_page = 0,
.end_page = ssd1306_n_pages - 1
};
calculate_render_area_buffer_length(&frame_area);
uint8_t ssd[ssd1306_buffer_length];
memset(ssd, 0, ssd1306_buffer_length);
int base = selected_option - selected_option % 3; // Agrupamento de 3 em 3 opções
//Marca a opçao
for (int i = 0; i < 3 && (base + i) < 7; i++) {
int y_offset = 16 + i * 20;
int text_offset_x = (128 - strlen(menu[base + i]) * 8) / 2;
ssd1306_draw_string(ssd, text_offset_x, y_offset, menu[base + i]);
if ((base + i) == selected_option) {
ssd1306_draw_string(ssd, text_offset_x - 20, y_offset, "x"); // Marca a seleção
}
}
render_on_display(ssd, &frame_area);
}
// Função para exibir mensagens no display OLED
void display_messages(const char *messages[], int count) {
struct render_area frame_area = {
.start_column = 0,
.end_column = ssd1306_width - 1,
.start_page = 0,
.end_page = ssd1306_n_pages - 1
};
calculate_render_area_buffer_length(&frame_area);
uint8_t ssd[ssd1306_buffer_length];
memset(ssd, 0, ssd1306_buffer_length);
for (int i = 0; i < count; i++) {
int text_offset_x = (128 - strlen(messages[i]) * 8) / 2;
int y_offset = 32 + i * 10;
ssd1306_draw_string(ssd, text_offset_x, y_offset, (char *)messages[i]);
}
render_on_display(ssd, &frame_area);
}
// Função para limpar todo o conteudo do display OLED
void clear_display() {
struct render_area frame_area = {
.start_column = 0,
.end_column = ssd1306_width - 1,
.start_page = 0,
.end_page = ssd1306_n_pages - 1
};
calculate_render_area_buffer_length(&frame_area);
uint8_t ssd[ssd1306_buffer_length];
memset(ssd, 0, ssd1306_buffer_length);
render_on_display(ssd, &frame_area);
}
// Função para ler o eixo X do joystick (retorna -1, 0 ou 1)
int read_joy_x() {
adc_select_input(0);
int joy_x = adc_read();
if (joy_x < 1500) return 1; // Joystick movido para direita
else if (joy_x > 2500) return -1; // Joystick movido para esquerda
return 0;
}
// Função para ler o estado do botão do joystick (pressionado ou não)
int read_joy_button() {
return gpio_get(JOY_SW);
}
// Função de inicialização do joystick
void init_joystick() {
gpio_init(JOY_X);
gpio_set_dir(JOY_X, GPIO_IN);
gpio_init(JOY_SW);
gpio_set_dir(JOY_SW, GPIO_IN);
gpio_pull_up(JOY_SW);
adc_init();
}
// Função para exibir um menu interativo baseado na posição do joystick
void menu_interativo() {
int selected_option = 0; // Índice do menu atual
int entered_option = -1; // Armazena a opção em que entrou
int previous_button_state = 1; // Estado anterior do botão
char *menu[] = { "AND", "OR", "NOT", "NAND", "NOR", "XOR", "XNOR" };
display_oled(menu, selected_option);
while (true) {
int joy_x = read_joy_x();
if (joy_x == -1) selected_option--; //navegação
else if (joy_x == 1) selected_option++; // navegação
// Rolagem do menu
if (selected_option < 0) selected_option = 6;
if (selected_option > 6) selected_option = 0;
display_oled(menu, selected_option);
int current_button_state = read_joy_button();
// Detecta clique no botão
if (current_button_state == 0 && previous_button_state == 1) {
if (entered_option == -1) {
entered_option = selected_option;
// Entrou em uma opção, executa a lógica conforme a porta lógica escolhida
switch (selected_option) {
case 0: { // PORTA LÓGICA AND
printf("Entrou na AND\n");
clear_display();
const char *msg[] = { "porta AND", " ", "click Sair" };
display_messages(msg, 3);
while (true) {
bool A = gpio_get(btn_A);
bool B = gpio_get(btn_B);
if (A && B) {
set_rgb(0, 1, 0);
printf("A = 1, B = 1 → AND = 1 → LED verde ON\n");
} else {
set_rgb(1, 0, 0);
printf("A = %d, B = %d → AND = 0 → LED vermelho ON\n", A, B);
}
if (read_joy_button() == 0) break;
sleep_ms(100);
}
set_rgb(0, 0, 0);
display_oled(menu, selected_option);
break;
}
case 1: { // PORTA LÓGICA OR
printf("Entrou na OR\n");
clear_display();
const char *msg[] = { "porta OR", " ", "click Sair" };
display_messages(msg, 3);
while (true) {
bool A = gpio_get(btn_A);
bool B = gpio_get(btn_B);
if (A || B) {
set_rgb(0, 1, 0);
printf("A = %d, B = %d → OR = 1 → LED verde ON\n", A, B);
} else {
set_rgb(1, 0, 0);
printf("A = %d, B = %d → OR = 0 → LED vermelho ON\n", A, B);
}
if (read_joy_button() == 0) break;
sleep_ms(100);
}
set_rgb(0, 0, 0);
display_oled(menu, selected_option);
break;
}
case 2: { // PORTA LÓGICA NOT
printf("Entrou na NOT\n");
clear_display();
const char *msg[] = { "porta NOT", " ", "click Sair" };
display_messages(msg, 3);
while (true) {
bool A = gpio_get(btn_A);
if (A) {
set_rgb(1, 0, 0);
printf("A = %d → NOT = 0 → LED vermelho ON\n", A);
} else {
set_rgb(0, 1, 0);
printf("A = %d → NOT = 1 → LED verde ON\n", A);
}
if (read_joy_button() == 0) break;
sleep_ms(100);
}
set_rgb(0, 0, 0);
display_oled(menu, selected_option);
break;
}
case 3: { // PORTA LÓGICA NAND
printf("Entrou na NAND\n");
clear_display();
const char *msg[] = { "porta NAND", " ", "click Sair" };
display_messages(msg, 3);
while (true) {
bool A = gpio_get(btn_A);
bool B = gpio_get(btn_B);
if (A && B) {
set_rgb(1, 0, 0);
printf("A = %d, B = %d → NAND = 0 → LED vermelho ON\n", A, B);
} else {
set_rgb(0, 1, 0);
printf("A = %d, B = %d → NAND = 1 → LED verde ON\n", A, B);
}
if (read_joy_button() == 0) break;
sleep_ms(100);
}
set_rgb(0, 0, 0);
display_oled(menu, selected_option);
break;
}
case 4: { // PORTA LÓGICA NOR
printf("Entrou na NOR\n");
clear_display();
const char *msg[] = { "porta NOR", " ", "click Sair" };
display_messages(msg, 3);
while (true) {
bool A = gpio_get(btn_A);
bool B = gpio_get(btn_B);
if (!A && !B) {
set_rgb(0, 1, 0);
printf("A = %d, B = %d → NOR = 1 → LED verde ON\n", A, B);
} else {
set_rgb(1, 0, 0);
printf("A = %d, B = %d → NOR = 0 → LED vermelho ON\n", A, B);
}
if (read_joy_button() == 0) break;
sleep_ms(100);
}
set_rgb(0, 0, 0);
display_oled(menu, selected_option);
break;
}
case 5: { // PORTA LÓGICA XOR
printf("Entrou na XOR\n");
clear_display();
const char *msg[] = { "porta XOR", " ", "click Sair" };
display_messages(msg, 3);
while (true) {
bool A = gpio_get(btn_A);
bool B = gpio_get(btn_B);
if ((A && !B) || (!A && B)) {
set_rgb(0, 1, 0);
printf("A = %d, B = %d → XOR = 1 → LED verde ON\n", A, B);
} else {
set_rgb(1, 0, 0);
printf("A = %d, B = %d → XOR = 0 → LED vermelho ON\n", A, B);
}
if (read_joy_button() == 0) break;
sleep_ms(100);
}
set_rgb(0, 0, 0);
display_oled(menu, selected_option);
break;
}
case 6: { // PORTA LÓGICA XNOR
printf("Entrou na XNOR\n");
clear_display();
const char *msg[] = { "porta XNOR", " ", "click Sair" };
display_messages(msg, 3);
while (true) {
bool A = gpio_get(btn_A);
bool B = gpio_get(btn_B);
if ((A && B) || (!A && !B)) {
set_rgb(0, 1, 0);
printf("A = %d, B = %d → XNOR = 1 → LED verde ON\n", A, B);
} else {
set_rgb(1, 0, 0);
printf("A = %d, B = %d → XNOR = 0 → LED vermelho ON\n", A, B);
}
if (read_joy_button() == 0) break;
sleep_ms(100);
}
set_rgb(0, 0, 0);
display_oled(menu, selected_option);
break;
}
}
while (read_joy_button() == 0) sleep_ms(100);
while (read_joy_button() == 1) sleep_ms(100);
entered_option = -1;
display_oled(menu, selected_option);
}
sleep_ms(200);
}
previous_button_state = current_button_state;
sleep_ms(100);
}
}
int main() {
stdio_init_all();
//inicialização dos botões e leds
gpio_init(btn_A);
gpio_set_dir(btn_A, GPIO_IN);
gpio_pull_up(btn_A);
gpio_init(btn_B);
gpio_set_dir(btn_B, GPIO_IN);
gpio_pull_up(btn_B);
gpio_init(LED_G_PIN);
gpio_set_dir(LED_G_PIN, GPIO_OUT);
gpio_init(LED_R_PIN);
gpio_set_dir(LED_R_PIN, GPIO_OUT);
gpio_init(LED_B_PIN);
gpio_set_dir(LED_B_PIN, GPIO_OUT);
// Inicializa comunicação I2C para o display OLED
i2c_init(i2c1, ssd1306_i2c_clock * 1000);
gpio_set_function(I2C_SDA, GPIO_FUNC_I2C);
gpio_set_function(I2C_SCL, GPIO_FUNC_I2C);
gpio_pull_up(I2C_SDA);
gpio_pull_up(I2C_SCL);
ssd1306_init(); // Inicializa o display OLED
clear_display(); // Limpa a tela inicialmente
init_joystick(); // Inicializa o joystick
menu_interativo(); // Começa o menu
return 0;
}