#include "stdio.h"
#include "pico/stdlib.h"
#include "hardware/clocks.h"
#include "hardware/pll.h"
#include "hardware/timer.h"
#include "hardware/irq.h"
#include "ssd1306.h"
// Definição dos pinos GPIO
#define LED_RED_PIN 11
#define LED_GREEN_PIN 13
#define PIR_MOTION_PIN 27
#define BTN_MIC_SIMULADOR_PIN 28
#define BUZZER_PIN 2
#define SSD1306_SDA_PIN 14
#define SSD1306_SCL_PIN 15
// Definição de constantes
#define BLINK_TIME 300 // Constante para o Led quando o Sistema está no modo ALERTA
#define IDLE_TIME 400 // Constante para o Led quando o Sistema está no modo OSIOCO
#define BUZZER_DELAY 100 // Tempo de delay do Buzzer
#define MHZ 1000000 // MHZ do clock
#define ALARM_TIME 10000 // Tempo do alarme em milissegundos
#define SSD1306_WIDTH 128 // Largura do display OLED
#define SSD1306_HEIGHT 64 // Altura do display OLED
#define SSD1306_I2C_ADDRESS 0x3C // Endereço I2C do display OLED
#define SSD1306_I2C_INSTANCE i2c1 // Instância I2C para o display
// Variáveis globais de controle
volatile bool sendingMessage = false; // Indica se a mensagem está sendo enviada
volatile bool alarmRinging = false; // Indica se o alarme está tocando
ssd1306_t disp; // Variável que representa o display SSD1306
// Função para inicializar os pinos GPIO
void initSettingsGpio()
{
// Inicializa LED vermelho
gpio_init(LED_RED_PIN);
gpio_set_dir(LED_RED_PIN, GPIO_OUT);
// Inicializa LED verde
gpio_init(LED_GREEN_PIN);
gpio_set_dir(LED_GREEN_PIN, GPIO_OUT);
// Inicializa PIR (sensor de movimento)
gpio_init(PIR_MOTION_PIN);
gpio_set_dir(PIR_MOTION_PIN, GPIO_IN);
gpio_pull_down(PIR_MOTION_PIN);
// Inicializa botão que simula o microfone
gpio_init(BTN_MIC_SIMULADOR_PIN);
gpio_set_dir(BTN_MIC_SIMULADOR_PIN, GPIO_IN);
gpio_pull_down(BTN_MIC_SIMULADOR_PIN);
// Inicializa buzzer
gpio_init(BUZZER_PIN);
gpio_set_dir(BUZZER_PIN, GPIO_OUT);
// Inicializa o display OLED SSD1306 via I2C
i2c_init(i2c1, 400000);
gpio_set_function(SSD1306_SDA_PIN, GPIO_FUNC_I2C);
gpio_set_function(SSD1306_SCL_PIN, GPIO_FUNC_I2C);
gpio_pull_up(SSD1306_SDA_PIN);
gpio_pull_up(SSD1306_SCL_PIN);
}
// Função para configurar o clock do sistema
void configureSystemClock(uint frequency)
{
pll_init(pll_sys, 1, frequency * MHZ, 12 * MHZ, frequency * MHZ);
clock_configure(clk_sys,
CLOCKS_CLK_SYS_CTRL_SRC_VALUE_CLKSRC_CLK_SYS_AUX,
CLOCKS_CLK_SYS_CTRL_AUXSRC_VALUE_CLKSRC_PLL_SYS,
frequency * MHZ,
frequency * MHZ);
}
// Função para piscar os LEDs (vermelho e verde)
void blinkLeds(bool red, bool green, uint32_t time_ms)
{
gpio_put(LED_RED_PIN, red);
gpio_put(LED_GREEN_PIN, green);
sleep_ms(time_ms);
gpio_put(LED_RED_PIN, false);
gpio_put(LED_GREEN_PIN, false);
sleep_ms(time_ms);
}
// Função para emitir som do buzzer
void beepBuzzer()
{
gpio_put(BUZZER_PIN, 1);
sleep_ms(BUZZER_DELAY);
gpio_put(BUZZER_PIN, 0);
}
// Função para desenhar texto no display OLED
void drawTextInDisplay(const char *message)
{
ssd1306_clear(&disp);
int text_width = strlen(message) * 6; // 6 é o tamanho aproximado de cada caractere em escala 1
int text_height = 8; // Altura do texto para escala 1
// Calcula as posições para centralizar o texto
int posX = (SSD1306_WIDTH - text_width) / 2;
int posY = (SSD1306_HEIGHT - text_height) / 2;
ssd1306_draw_string(&disp, posX, posY, 1, message); // Desenha o texto centralizado
ssd1306_show(&disp); // Atualiza o display
}
// Função para limpar o texto do display OLED
void clearTextInDisplay()
{
ssd1306_clear(&disp);
ssd1306_show(&disp);
}
// Callback que é chamado após o envio da mensagem
bool sendMessageToBaseCallback(alarm_id_t id, void *user_data)
{
drawTextInDisplay("Mensagem Enviada!!!");
printf("Mensagem Enviada com Sucesso!!!\n");
sendingMessage = false;
return false;
}
// Função que simula o envio de uma mensagem para um dispositivo edge
void sendMessageToBase()
{
uint32_t current_time_ms = to_ms_since_boot(get_absolute_time());
uint32_t seconds = current_time_ms / 1000;
uint32_t minutes = seconds / 60;
uint32_t hours = minutes / 60;
uint32_t days = hours / 24;
uint32_t hour_of_day = hours % 24;
uint32_t minute_of_hour = minutes % 60;
uint32_t second_of_minute = seconds % 60;
sendingMessage = true;
printf("Tentando enviar mensagem para o dispositivo edge: Dia %d, Hora %02d:%02d:%02d\n", days, hour_of_day, minute_of_hour, second_of_minute);
add_alarm_in_ms(6000, sendMessageToBaseCallback, NULL, false);
}
// Callback chamado quando o tempo do alarme se esgota
bool startAlarmCallback()
{
alarmRinging = false;
printf("O tempo do alarme acabou!\n");
drawTextInDisplay("O alarme acabou!");
return false;
}
// Função para disparar o alarme
void startAlarm()
{
alarmRinging = true;
add_alarm_in_ms(ALARM_TIME, startAlarmCallback, NULL, false);
printf("Alarme Disparado!\n");
drawTextInDisplay("Alarme Disparado!");
}
// Função de callback para as interrupções dos GPIOs
void gpio_irq_callback(int gpio, uint32_t events)
{
if (!sendingMessage && !alarmRinging)
{
printf("--------------------------------------------\n");
if (gpio == BTN_MIC_SIMULADOR_PIN)
{
printf("Som Captado!!!\n");
}
if (gpio == PIR_MOTION_PIN)
{
printf("Movimento Detectado!!!\n");
}
startAlarm();
sendMessageToBase();
}
}
// Função principal do programa
int main()
{
stdio_init_all(); // Inicializa a comunicação serial
configureSystemClock(133); // Configura o clock do sistema para 133 MHz
initSettingsGpio(); // Inicializa os pinos GPIO
ssd1306_init(&disp, SSD1306_WIDTH, SSD1306_HEIGHT, SSD1306_I2C_ADDRESS, SSD1306_I2C_INSTANCE); // Inicializa o display OLED
// Configura as interrupções dos GPIOs
gpio_set_irq_enabled_with_callback(BTN_MIC_SIMULADOR_PIN, GPIO_IRQ_EDGE_RISE, true, gpio_irq_callback);
gpio_set_irq_enabled_with_callback(PIR_MOTION_PIN, GPIO_IRQ_EDGE_RISE, true, gpio_irq_callback);
// Mensagem de Inicialização do sistema
printf("Sistema iniciado...\n");
drawTextInDisplay("Sistema iniciando...");
// Loop principal
while (true)
{
// Verifica se o alarme está tocando ou se a mensagem ainda está sendo enviada
if (alarmRinging || sendingMessage)
{
// Emite som no buzzer e faz o LED piscar enquanto o alarme ou o envio da mensagem não terminam
beepBuzzer();
drawTextInDisplay("Sistema em Alerta!");
blinkLeds(true, false, BLINK_TIME);
clearTextInDisplay();
}
else
{
// Exibe a mensagem "Sistema funcionando" no display
drawTextInDisplay("Sistema Funcionando!");
// Quando o alarme terminar ou a mensagem for enviada, pisca o LED verde por um tempo de inatividade
blinkLeds(false, true, IDLE_TIME);
}
// Faz uma pequena pausa para evitar sobrecarga no loop
sleep_ms(100);
}
return 0;
}