LED_shit/main/display.c
2025-12-01 21:24:54 +00:00

360 lines
9.4 KiB
C
Raw Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

#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 09 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
}