#include "driver/i2c.h" #include "esp_log.h" #include "display.h" #define DISP_ADDR 0x70 #define I2C_PORT I2C_NUM_0 const char *TAG = "DISPLAY"; // Mapa de bits real do teu módulo #define SEG_A (1 << 0) // topo #define SEG_B (1 << 1) // cima direita #define SEG_C (1 << 2) // baixo direita #define SEG_D (1 << 3) // baixo #define SEG_E (1 << 4) // baixo esquerda #define SEG_F (1 << 5) // cima esquerda // verticais do meio #define SEG_ML (1 << 6) // meio-esquerda #define SEG_MR (1 << 7) // meio-direita // parte alfanumérica (topo) #define SEG_TL (1 << 8) // top-left extra #define SEG_TM (1 << 9) // top-middle (horizontal) #define SEG_TR (1 << 10) // top-right extra // parte alfanumérica (baixo) #define SEG_BL (1 << 11) // bottom-left extra #define SEG_BM (1 << 12) // bottom-middle (horizontal) #define SEG_BR (1 << 13) // bottom-right extra #define SEG_DP (1 << 14) // ponto decimal // "segmento do meio" clássico (g) = as duas barrinhas #define SEG_G (SEG_ML | SEG_MR) // ------------------------------ // DISPLAY INIT // ------------------------------ void display_init(void) { uint8_t cmd1 = 0x21; // oscillator ON i2c_master_write_to_device(I2C_PORT, DISP_ADDR, &cmd1, 1, 20 / portTICK_PERIOD_MS); uint8_t cmd2 = 0x81; // display ON, blink OFF i2c_master_write_to_device(I2C_PORT, DISP_ADDR, &cmd2, 1, 20 / portTICK_PERIOD_MS); uint8_t cmd3 = 0xEF; // brightness i2c_master_write_to_device(I2C_PORT, DISP_ADDR, &cmd3, 1, 20 / portTICK_PERIOD_MS); display_clear(); } // ------------------------------ // CLEAR DISPLAY // ------------------------------ void display_clear(void) { uint8_t buf[17] = {0}; buf[0] = 0x00; i2c_master_write_to_device(I2C_PORT, DISP_ADDR, buf, sizeof(buf), 20 / portTICK_PERIOD_MS); } // -------------------------------------------------------- // RAW WRITE — 14 segmentos (cada dígito = 16 bits) // -------------------------------------------------------- void display_raw(int pos, uint16_t mask) { if (pos < 0 || pos > 3) return; uint8_t buf[3]; buf[0] = pos * 2; buf[1] = mask & 0xFF; buf[2] = (mask >> 8) & 0xFF; i2c_master_write_to_device(I2C_PORT, DISP_ADDR, buf, 3, 20 / portTICK_PERIOD_MS); } // -------------------------------------------------------- // Tabela alfanumérica 14 segmentos // (corrigido: H com os 2 segmentos horizontais g1/g2) // -------------------------------------------------------- static uint16_t charset(char c) { switch (c) { //------------------------------------------------------ // NÚMEROS (PERFEITOS) //------------------------------------------------------ case '0': return SEG_A | SEG_B | SEG_C | SEG_D | SEG_E | SEG_F; case '1': return SEG_B | SEG_C; case '2': return SEG_A | SEG_B | SEG_G | SEG_E | SEG_D; case '3': return SEG_A | SEG_B | SEG_G | SEG_C | SEG_D; case '4': return SEG_F | SEG_G | SEG_B | SEG_C; case '5': return SEG_A | SEG_F | SEG_G | SEG_C | SEG_D; case '6': return SEG_A | SEG_F | SEG_G | SEG_E | SEG_D | SEG_C; case '7': return SEG_A | SEG_B | SEG_C; case '8': return SEG_A | SEG_B | SEG_C | SEG_D | SEG_E | SEG_F | SEG_G; case '9': return SEG_A | SEG_B | SEG_C | SEG_D | SEG_F | SEG_G; //------------------------------------------------------ // LETRAS A-Z (todas as possíveis) //------------------------------------------------------ // A case 'A': case 'a': return SEG_A | SEG_B | SEG_C | SEG_E | SEG_F | SEG_G; // B (tipo “8” mais quadrado) case 'B': case 'b': return SEG_A | SEG_B | SEG_C | SEG_D | SEG_E | SEG_F | SEG_G; // C case 'C': case 'c': return SEG_A | SEG_F | SEG_E | SEG_D; // D case 'D': case 'd': return SEG_B | SEG_C | SEG_D | SEG_E | SEG_G; // E case 'E': case 'e': return SEG_A | SEG_F | SEG_G | SEG_E | SEG_D; // F case 'F': case 'f': return SEG_A | SEG_F | SEG_G | SEG_E; // G case 'G': case 'g': return SEG_A | SEG_F | SEG_E | SEG_D | SEG_C | SEG_G; // H case 'H': case 'h': return SEG_F | SEG_E | SEG_G | SEG_B | SEG_C; // I case 'I': case 'i': return SEG_B | SEG_C; // J case 'J': case 'j': return SEG_B | SEG_C | SEG_D; // K (usa diagonais internas TL/TR + ML/MR) case 'K': case 'k': return SEG_F | SEG_E | SEG_G | SEG_TR | SEG_BR; // L case 'L': case 'l': return SEG_F | SEG_E | SEG_D; // M case 'M': case 'm': return SEG_F | SEG_E | SEG_TL | SEG_TR | SEG_B | SEG_C; // N case 'N': case 'n': return SEG_F | SEG_E | SEG_TL | SEG_BR | SEG_C | SEG_B; // O case 'O': case 'o': return SEG_A | SEG_B | SEG_C | SEG_D | SEG_E | SEG_F; // P case 'P': case 'p': return SEG_A | SEG_B | SEG_F | SEG_G | SEG_E; // Q (tipo O + diagonal extra) case 'Q': case 'q': return SEG_A | SEG_B | SEG_C | SEG_D | SEG_E | SEG_F | SEG_BR; // R case 'R': case 'r': return SEG_A | SEG_B | SEG_F | SEG_G | SEG_E | SEG_BR; // S case 'S': case 's': return SEG_A | SEG_F | SEG_G | SEG_C | SEG_D; // T case 'T': case 't': return SEG_A | SEG_TM | SEG_BR; // U case 'U': case 'u': return SEG_F | SEG_E | SEG_D | SEG_C | SEG_B; // V case 'V': case 'v': return SEG_F | SEG_E | SEG_D | SEG_B | SEG_TR; // W case 'W': case 'w': return SEG_F | SEG_E | SEG_D | SEG_C | SEG_B | SEG_BR | SEG_TR; // X case 'X': case 'x': return SEG_TL | SEG_TR | SEG_ML | SEG_MR | SEG_BL | SEG_BR; // Y case 'Y': case 'y': return SEG_F | SEG_B | SEG_G | SEG_C | SEG_D; // Z case 'Z': case 'z': return SEG_A | SEG_TR | SEG_G | SEG_BL | SEG_D; //------------------------------------------------------ // SÍMBOLOS ESPECIAIS //------------------------------------------------------ case '-': return SEG_G; case '_': return SEG_D; case '=': return SEG_G | SEG_BM; case '*': return SEG_TM | SEG_BM | SEG_ML | SEG_MR; case '/': return SEG_TR | SEG_BL; case '\\': return SEG_TL | SEG_BR; case '|': return SEG_B | SEG_C; case ':': return SEG_DP | SEG_BR; case '.': return SEG_DP; case '\'': return SEG_TR; case '"': return SEG_TR | SEG_TL; case ' ': return 0; default: return 0; // desconhecido → apagado } } // -------------------------------------------------------- // display_char() // -------------------------------------------------------- void display_char(int pos, char c) { uint16_t mask = charset(c); display_raw(pos, mask); } // -------------------------------------------------------- // display_text() (4 caracteres) // -------------------------------------------------------- void display_text(const char *txt) { for (int i = 0; i < 4; i++) { char c = txt[i]; if (c == 0) c = ' '; display_char(i, c); } } // -------------------------------------------------------- // display_number() // Mantida para compatibilidade com 7-segment // -------------------------------------------------------- // Dígitos 0–9 usando os segmentos definidos acima static const uint16_t digit_mask[10] = { // 0: a b c d e f [0] = SEG_A | SEG_B | SEG_C | SEG_D | SEG_E | SEG_F, // 1: b c [1] = SEG_B | SEG_C, // 2: a b g e d [2] = SEG_A | SEG_B | SEG_G | SEG_E | SEG_D, // 3: a b g c d [3] = SEG_A | SEG_B | SEG_G | SEG_C | SEG_D, // 4: f g b c [4] = SEG_F | SEG_G | SEG_B | SEG_C, // 5: a f g c d [5] = SEG_A | SEG_F | SEG_G | SEG_C | SEG_D, // 6: a f g e d c [6] = SEG_A | SEG_F | SEG_G | SEG_E | SEG_D | SEG_C, // 7: a b c [7] = SEG_A | SEG_B | SEG_C, // 8: tudo [8] = SEG_A | SEG_B | SEG_C | SEG_D | SEG_E | SEG_F | SEG_G, // 9: a b c d f g [9] = SEG_A | SEG_B | SEG_C | SEG_D | SEG_F | SEG_G, }; void display_digit(int pos, uint8_t val) { if (pos < 0 || pos > 3) return; if (val > 9) val = 0; uint16_t mask = digit_mask[val]; display_raw(pos, mask); } void display_number(int num) { if (num < 0) num = 0; if (num > 9999) num = 9999; display_digit(3, num % 10); display_digit(2, (num / 10) % 10); display_digit(1, (num / 100) % 10); display_digit(0, (num / 1000) % 10); } void display_set_time(int horas, int minutos) { if (horas < 0) horas = 0; if (horas > 99) horas = 99; if (minutos < 0) minutos = 0; if (minutos > 59) minutos = 59; int h1 = horas / 10; int h2 = horas % 10; int m1 = minutos / 10; int m2 = minutos % 10; uint16_t dig1 = digit_mask[h2] | SEG_DP; //dot betwen hours display_digit(0, h1); display_raw(1, dig1); display_digit(2, m1); display_digit(3, m2); } void display_debug_segment(uint16_t bitmask) { display_raw(0, bitmask); // acende só o dígito 0 }