220 lines
5.5 KiB
C
220 lines
5.5 KiB
C
#include <stdio.h>
|
|
#include <string.h>
|
|
|
|
#include "esp_rom_sys.h"
|
|
#include "esp_task_wdt.h"
|
|
#include "freertos/FreeRTOS.h"
|
|
#include "freertos/task.h"
|
|
#include "driver/gpio.h"
|
|
#include "nvs_flash.h"
|
|
#include "esp_system.h"
|
|
#include "esp_log.h"
|
|
#include "esp_wifi.h"
|
|
#include "esp_event.h"
|
|
#include "esp_netif.h"
|
|
#include "esp_sntp.h"
|
|
|
|
#include "eeprom_virtual.h"
|
|
#include "eeprom_tls.h"
|
|
#include "eeprom_animacao.h"
|
|
|
|
#include "wifi_config_portal.h"
|
|
#include "mqtt_handler.h"
|
|
|
|
#include "led_driver.h"
|
|
#include "led_effects.h"
|
|
|
|
#include "creditos.h"
|
|
#include "led_task.h"
|
|
|
|
#include "driver/i2c.h"
|
|
#include "i2c_helper.h"
|
|
#include "display.h"
|
|
#include <stdbool.h>
|
|
|
|
bool modo_bloqueado = false; // definição oficial
|
|
|
|
#define SDA_PIN 21
|
|
#define SCL_PIN 22
|
|
#define I2C_PORT I2C_NUM_0
|
|
|
|
static const char *TAG = "APP";
|
|
static uint32_t segundos = 0;
|
|
static bool wifi_ready = false;
|
|
|
|
typedef struct {
|
|
int total_creditos;
|
|
int total_saidas;
|
|
} contadores_t;
|
|
|
|
|
|
// ============================
|
|
// Task contador simples
|
|
// ============================
|
|
void segundos_task(void *pv) {
|
|
while (1) {
|
|
vTaskDelay(pdMS_TO_TICKS(1000));
|
|
segundos++;
|
|
}
|
|
}
|
|
|
|
uint32_t get_segundos(void) {
|
|
return segundos;
|
|
}
|
|
|
|
|
|
// ============================
|
|
// Callback Wi-Fi pronto
|
|
// ============================
|
|
static void on_wifi_connected(void) {
|
|
wifi_ready = true;
|
|
|
|
ESP_LOGI(TAG, "✅ Wi-Fi conectado — iniciando MQTT...");
|
|
mqtt_handler_start();
|
|
|
|
ESP_LOGI(TAG, "🕒 SNTP...");
|
|
esp_sntp_setoperatingmode(SNTP_OPMODE_POLL);
|
|
esp_sntp_setservername(0, "pool.ntp.org");
|
|
esp_sntp_init();
|
|
|
|
ESP_LOGI(TAG, "💡 Inicializando driver LED...");
|
|
led_driver_init();
|
|
|
|
ESP_LOGI(TAG, "🎬 Iniciando tasks LED e Créditos...");
|
|
xTaskCreate(led_task, "led_task", 8192, NULL, 5, NULL);
|
|
xTaskCreate(creditos_task, "creditos_task", 8192, NULL, 5, NULL);
|
|
}
|
|
|
|
|
|
// ============================
|
|
// Stack Overflow Handler
|
|
// ============================
|
|
void vApplicationStackOverflowHook(TaskHandle_t xTask, char *pcTaskName)
|
|
{
|
|
esp_rom_printf("\n🧨 Stack overflow em %s!\n", pcTaskName);
|
|
esp_task_wdt_reset();
|
|
vTaskDelay(pdMS_TO_TICKS(1000));
|
|
esp_restart();
|
|
}
|
|
|
|
|
|
// Configuração básica do I2C
|
|
i2c_config_t cfg = {
|
|
.mode = I2C_MODE_MASTER,
|
|
.sda_io_num = SDA_PIN,
|
|
.scl_io_num = SCL_PIN,
|
|
.sda_pullup_en = GPIO_PULLUP_ENABLE,
|
|
.scl_pullup_en = GPIO_PULLUP_ENABLE,
|
|
.master.clk_speed = 100000
|
|
};
|
|
|
|
void ht16_init()
|
|
{
|
|
uint8_t cmd1 = 0x21; // liga oscilador
|
|
i2c_master_write_to_device(I2C_PORT, 0x70, &cmd1, 1, 10 / portTICK_PERIOD_MS);
|
|
|
|
uint8_t cmd2 = 0x81; // display ON, sem piscar
|
|
i2c_master_write_to_device(I2C_PORT, 0x70, &cmd2, 1, 10 / portTICK_PERIOD_MS);
|
|
|
|
uint8_t cmd3 = 0xEF; // brilho máximo
|
|
i2c_master_write_to_device(I2C_PORT, 0x70, &cmd3, 1, 10 / portTICK_PERIOD_MS);
|
|
}
|
|
|
|
|
|
|
|
void ht16_test()
|
|
{
|
|
uint8_t buf[17] = {0};
|
|
buf[0] = 0x00; // endereço inicial
|
|
|
|
buf[7] = 0b0111111; // acende apenas o dígito 0
|
|
// (que mostra um "0" bonitinho)
|
|
|
|
|
|
// Os outros dígitos ficam a 0 = apagados
|
|
|
|
i2c_master_write_to_device(I2C_PORT, 0x70, buf, sizeof(buf), 20 / portTICK_PERIOD_MS);
|
|
}
|
|
|
|
void i2c_scan()
|
|
{
|
|
printf("\n--- A fazer scan ao I2C ---\n");
|
|
// --- SCAN I2C ---
|
|
for (uint8_t addr = 1; addr < 127; addr++) {
|
|
i2c_cmd_handle_t cmd = i2c_cmd_link_create();
|
|
i2c_master_start(cmd);
|
|
i2c_master_write_byte(cmd, (addr << 1) | I2C_MASTER_WRITE, true);
|
|
i2c_master_stop(cmd);
|
|
|
|
esp_err_t r = i2c_master_cmd_begin(I2C_PORT, cmd, 20 / portTICK_PERIOD_MS);
|
|
i2c_cmd_link_delete(cmd);
|
|
|
|
if (r == ESP_OK) {
|
|
printf("ENCONTRADO I2C: 0x%02X\n", addr);
|
|
}
|
|
}
|
|
}
|
|
|
|
// ============================
|
|
// MAIN
|
|
// ============================
|
|
void app_main(void) {
|
|
|
|
// -------- EEPROM virtual --------
|
|
eeprom_virtual_init();
|
|
|
|
contadores_t contadores = {100, 25};
|
|
eeprom_virtual_write_bin("contadores", &contadores, sizeof(contadores));
|
|
ESP_LOGI("EEPROM", "💾 Gravado: total_creditos=%d, total_saidas=%d",
|
|
contadores.total_creditos, contadores.total_saidas);
|
|
|
|
contadores_t lidos = {0};
|
|
size_t len = sizeof(lidos);
|
|
if (eeprom_virtual_read_bin("contadores", &lidos, &len) == ESP_OK) {
|
|
ESP_LOGI("EEPROM", "📖 Lido: total_creditos=%d, total_saidas=%d",
|
|
lidos.total_creditos, lidos.total_saidas);
|
|
} else {
|
|
ESP_LOGW("EEPROM", "⚠️ Falha ao ler dados!");
|
|
}
|
|
|
|
// -------- NVS normal --------
|
|
ESP_ERROR_CHECK(nvs_flash_init());
|
|
|
|
animacao_load();
|
|
ESP_LOGI("ANIM", "🎨 Animação carregada = %u", animacao);
|
|
|
|
|
|
|
|
i2c_init(); // <- o helper entra aqui
|
|
display_init(); // <- inicializa o HT16K33
|
|
i2c_scan();
|
|
display_text_top("INIT");
|
|
|
|
|
|
|
|
|
|
// -------- Wi-Fi --------
|
|
wifi_config_t cfg;
|
|
bool have_creds = false;
|
|
|
|
if (esp_wifi_get_config(WIFI_IF_STA, &cfg) == ESP_OK) {
|
|
if (strlen((char *)cfg.sta.ssid) > 0) {
|
|
ESP_LOGI(TAG, "📂 Credenciais no NVS: SSID=%s", cfg.sta.ssid);
|
|
have_creds = true;
|
|
}
|
|
}
|
|
|
|
wifi_config_portal_init(on_wifi_connected, have_creds);
|
|
|
|
// -------- Criar tasks iniciais --------
|
|
xTaskCreate(segundos_task, "segundos_task", 4096, NULL, 5, NULL);
|
|
|
|
// -------- Loop principal --------
|
|
while (1) {
|
|
if (wifi_ready) {
|
|
mqtt_handler_loop();
|
|
}
|
|
vTaskDelay(pdMS_TO_TICKS(100));
|
|
}
|
|
}
|