#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"
// Definição dos pinos I2C
const uint I2C_SDA = 14;
const uint I2C_SCL = 15;
// Definição dos pinos dos LEDs
#define LED_R_PIN 13
#define LED_G_PIN 11
#define LED_B_PIN 12
// Definição do pino do botão
#define BTN_A_PIN 5
// Função para exibir mensagens no display OLED, centralizando no meio (x e y)
void display_oled(char *messages[], size_t num_lines){
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);
// Criação de um buffer zerado
uint8_t ssd[ssd1306_buffer_length];
memset(ssd, 0, ssd1306_buffer_length);
int total_text_height = num_lines * 8; // Altura total do texto (8 pixels por linha)
int y_offset = (64 - total_text_height) / 2; // Calcula o deslocamento vertical para centralizar
for (uint i = 0; i < num_lines; i++)
{
// Calcula o deslocamento horizontal para centralizar cada linha
int offset_x = (128 - (strlen(messages[i]) * 8)) / 2; // 8 pixels por caractere
if (offset_x < 0)
{
offset_x = 0;
}
// Escreve a mensagem no buffer, centralizada
ssd1306_draw_string(ssd, offset_x, y_offset, messages[i]);
y_offset += 8; // Avança para a próxima linha (8 pixels de altura por linha)
}
// Renderiza o conteúdo no display
render_on_display(ssd, &frame_area);
}
// Função para limpar o 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); // Zera o buffer
render_on_display(ssd, &frame_area); // Limpa o display
}
int A_state = 0; // Estado do botão
// Função do Sinal Aberto e para exibir mensagem no display
void SinalAberto(){
// Acende somente o LED verde
gpio_put(LED_R_PIN, 0);
gpio_put(LED_G_PIN, 1);
gpio_put(LED_B_PIN, 0);
// Mensagem para o display
char *atravessar[] = {"SINAL ABERTO", "ATRAVESSE","COM CUIDADO"};
display_oled(atravessar, 3); // Exibe a mensagem no display
}
// Função para o Sinal de Atenção e mensagem no display
void SinalAtencao(){
// Acende o LED verde e vermelho (mistura para formar o amarelo)
gpio_put(LED_R_PIN, 1);
gpio_put(LED_G_PIN, 1);
gpio_put(LED_B_PIN, 0);
// Mensagem para o display
char *atencao[] = {"SINAL DE ATENCAO", "PREPARE-SE"};
display_oled(atencao, 2); // Exibe a mensagem no display
}
// Função para o Sinal Fechado e mensagem no display
void SinalFechado(){
// Acende somente o LED vermelho
gpio_put(LED_R_PIN, 1);
gpio_put(LED_G_PIN, 0);
gpio_put(LED_B_PIN, 0);
// Mensagem para o display
char *aguarde[] = {"SINAL FECHADO", "AGUARDE"};
display_oled(aguarde, 2); // Exibe a mensagem no display
}
// Função para esperar um determinado tempo e verificar se o botão foi pressionado
int WaitWithRead(int timeMS){
for (int i = 0; i < timeMS; i = i + 100)
{
A_state = !gpio_get(BTN_A_PIN); // Lê o estado do botão
if (A_state == 1)
{
return 1;
}
sleep_ms(100);
}
return 0;
}
int main()
{
stdio_init_all();
// Inicialização do barramento I2C
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);
// Inicialização do display OLED
ssd1306_init();
clear_display();
// inicia os pinos do leds e define como saida
gpio_init(LED_R_PIN);
gpio_set_dir(LED_R_PIN, GPIO_OUT);
gpio_init(LED_G_PIN);
gpio_set_dir(LED_G_PIN, GPIO_OUT);
gpio_init(LED_B_PIN);
gpio_set_dir(LED_B_PIN, GPIO_OUT);
// Configuração do botão
gpio_init(BTN_A_PIN);
gpio_set_dir(BTN_A_PIN, GPIO_IN);
gpio_pull_up(BTN_A_PIN); // Ativa pull-up no botão
// Estado inicial: Sinal vermelho para pedestres
SinalFechado();
while (true)
{
// Verifica se o botão foi pressionado
A_state = WaitWithRead(10000);
if (A_state)
{
SinalAtencao(); // Troca para amarelo (atenção)
sleep_ms(2000);
SinalAberto(); // Troca para verde (atravessar)
sleep_ms(10000); // Tempo para o pedestre atravessar
SinalFechado(); // Volta para vermelho (fechado)
}
}
return 0;
}