/*
 * Controle de 132 LEDs usando Charlieplexing (Animação de Texto)
 *
 * Esta versão adiciona a funcionalidade de alternar entre um padrão animado
 * (chase light) e um padrão estático (letra 'A'). O array `ledStates`
 * atua como uma matriz virtual na memória, permitindo criar qualquer padrão.
 *
 * Autoria: Gemini
 */
// Pinos do Arduino usados para o Charlieplexing
// Nota: O código original usava 12 pinos, que podem controlar 132 LEDs.
// A lógica a seguir foi adaptada para esta configuração.
const byte LED_PINS[] = { 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13 };
const byte NUM_PINS = sizeof(LED_PINS);
const int TOTAL_LEDS = NUM_PINS * (NUM_PINS - 1);
// Tabela de mapeamento para ligar um LED específico
// A primeira dimensão representa o pino ANODO (+), a segunda o pino CATODO (-)
// A matriz mapeia o índice do LED para os pinos correspondentes.
int LED_MAP[NUM_PINS][NUM_PINS];
// Array para armazenar o estado de cada LED (true = ligado, false = desligado)
bool ledStates[TOTAL_LEDS] = {false};
// Variáveis de temporização para o loop principal
unsigned long previousPatternMillis = 0;
const int patternInterval = 50; // Intervalo para o modo de perseguição (em ms)
const int modeChangeInterval = 5000; // Intervalo para alternar modos (em ms)
int currentLedInPattern = 0;
bool isChaseMode = true;
void setup() {
  // Inicializa a tabela de mapeamento
  int ledIndex = 0;
  for (byte i = 0; i < NUM_PINS; i++) {
    for (byte j = 0; j < NUM_PINS; j++) {
      if (i == j) {
        LED_MAP[i][j] = -1; // Combinação inválida
      } else {
        LED_MAP[i][j] = ledIndex++;
      }
    }
  }
  // Configura todos os pinos como INPUT para evitar curto-circuito
  for (byte i = 0; i < NUM_PINS; i++) {
    pinMode(LED_PINS[i], INPUT);
  }
}
void loop() {
  unsigned long currentMillis = millis();
  // Executa a função de varredura constantemente para evitar cintilação
  scanLEDs();
  // Alterna entre o modo de perseguição e o modo de padrão estático
  if (currentMillis - previousPatternMillis >= modeChangeInterval) {
    previousPatternMillis = currentMillis;
    isChaseMode = !isChaseMode;
  }
  if (isChaseMode) {
    runChaseAnimation();
  } else {
    displayLetterA();
  }
}
/*
 * Executa a animação de perseguição de luz.
 */
void runChaseAnimation() {
  unsigned long currentMillis = millis();
  if (currentMillis - previousPatternMillis >= patternInterval) {
    previousPatternMillis = currentMillis;
    // Desliga todos os LEDs e liga apenas o próximo na sequência
    for (int i = 0; i < TOTAL_LEDS; i++) {
      ledStates[i] = false;
    }
    ledStates[currentLedInPattern] = true;
    
    // Incrementa o índice para o próximo LED na sequência
    currentLedInPattern++;
    if (currentLedInPattern >= TOTAL_LEDS) {
      currentLedInPattern = 0;
    }
  }
}
/*
 * Desenha a letra 'A' na matriz de LEDs.
 */
void displayLetterA() {
  // Desliga todos os LEDs para garantir um novo desenho
  for (int i = 0; i < TOTAL_LEDS; i++) {
    ledStates[i] = false;
  }
  
  // Define os índices dos LEDs que formam a letra 'A'.
  // Estes índices são baseados no mapeamento de 12 pinos.
  // Padrão de exemplo para uma 'A' maiúscula simples
  // Pode ser adaptado para uma matriz virtual 2D
  setLED(5, true); // topo
  setLED(16, true);
  setLED(27, true);
  setLED(38, true);
  setLED(49, true);
  setLED(60, true); // barra horizontal
  setLED(61, true);
  setLED(62, true);
  setLED(71, true);
  setLED(82, true);
  setLED(93, true);
  setLED(104, true);
  setLED(115, true);
}
/*
 * Função de varredura (scanning) para atualizar o estado de todos os LEDs.
 * Esta função é chamada repetidamente e não usa 'delay()'.
 */
void scanLEDs() {
  static int i = 0; // Pinos Anodo
  static int j = 0; // Pinos Catodo
  
  // Encontra a próxima combinação válida de pinos para varrer
  do {
    j++;
    if (j >= NUM_PINS) {
      j = 0;
      i++;
      if (i >= NUM_PINS) {
        i = 0;
      }
    }
  } while (i == j);
  // Desliga os pinos da varredura anterior para evitar correntes parasitas
  pinMode(LED_PINS[i], INPUT);
  pinMode(LED_PINS[j], INPUT);
  int ledIndex = LED_MAP[i][j];
  if (ledIndex != -1 && ledStates[ledIndex]) {
    // Liga o LED atual se ele estiver no estado 'true'
    pinMode(LED_PINS[i], OUTPUT);
    pinMode(LED_PINS[j], OUTPUT);
    digitalWrite(LED_PINS[i], HIGH); // Anodo
    digitalWrite(LED_PINS[j], LOW);  // Catodo
  }
}
/*
 * Função auxiliar para ligar ou desligar um LED específico.
 * @param ledIndex O índice do LED (de 0 a 131).
 * @param state    O estado para o LED (true para ligado, false para desligado).
 */
void setLED(int ledIndex, bool state) {
  if (ledIndex >= 0 && ledIndex < TOTAL_LEDS) {
    ledStates[ledIndex] = state;
  }
}
2
3
4
5
6
7
8
9
10
11
12
13