#include "9by04gk.h"
#define PIN_DIN 11
#define PIN_CLK 12
#define PIN_LE 10
#define PIN_STROBE 13
// Bufor wyświetlacza – 9 znaków
static uint32_t vfd_buf[9] = {0};
static uint8_t refresh_pos = 0;
void shift24(uint32_t value) {
for (int i = 23; i >= 0; i--) {
digitalWrite(PIN_CLK, LOW);
digitalWrite(PIN_DIN, (value >> i) & 1);
delayMicroseconds(1);
digitalWrite(PIN_CLK, HIGH);
delayMicroseconds(1);
}
}
void vfd_send(uint32_t value) {
static uint32_t last = 0xFFFFFFFF;
if (value != last) {
Serial.printf("VFD: 0x%08lX\n", value);
last = value;
}
digitalWrite(PIN_LE, LOW);
shift24(value);
digitalWrite(PIN_LE, HIGH);
delayMicroseconds(1);
digitalWrite(PIN_LE, LOW);
// STROBE LOW = aktywne wyjścia
digitalWrite(PIN_STROBE, LOW);
}
void vfd_blank() {
digitalWrite(PIN_STROBE, HIGH);
}
// Załaduj string do bufora (max 9 znaków)
void vfd_set(const char *str) {
for (int i = 0; i < 9; i++) {
uint8_t ch = (*str) ? ((uint8_t)*str++ & 0x7F) : ' ';
vfd_buf[i] = font_9by04gk[ch];
Serial.printf("vfd_buf[%d] = 0x%08lX (char: %c)\n", i, vfd_buf[i], ch);
}
}
// Odświeżanie multipleksowane - wywołuj co 1-3ms
// UWAGA: SN75518N ma 32 wyjścia (Q1-Q32)
// Q1-Q15 = segmenty (15 bitów)
// Q16-Q24 = gridy (9 bitów)
// Wysyłamy 24 bity: [grid_bits (9 bitów)] [segment_bits (15 bitów)]
void vfd_refresh() {
// Pobierz maskę segmentów dla aktualnej cyfry
uint32_t seg_mask = vfd_buf[refresh_pos] & 0x7FFF; // Tylko 15 bitów segmentów
// Ustaw bit grid (aktywny grid ma 1, pozostałe 0)
// Grid bity na pozycjach 23-15 (bo wysyłamy 24 bity)
uint32_t grid_mask = (1UL << (refresh_pos + 15)); // Grid1 = bit15, Grid2 = bit16, ... Grid9 = bit23
// Połącz grid i segmenty
uint32_t data = grid_mask | seg_mask;
vfd_send(data);
refresh_pos = (refresh_pos + 1) % 9;
}
void setup() {
Serial.begin(115200);
pinMode(PIN_DIN, OUTPUT);
pinMode(PIN_CLK, OUTPUT);
pinMode(PIN_LE, OUTPUT);
pinMode(PIN_STROBE, OUTPUT);
digitalWrite(PIN_STROBE, HIGH);
digitalWrite(PIN_LE, LOW);
// Test różnych znaków
vfd_set("ABCDEFGHI");
Serial.println("Gotowy - multipleksowanie SN75518N");
}
void loop() {
// Odświeżaj wyświetlacz
vfd_refresh();
delayMicroseconds(3000); // 3ms na cyfrę
// Zmieniaj tekst co 3 sekundy
static unsigned long last_change = 0;
static int test_idx = 0;
if (millis() - last_change > 3000) {
last_change = millis();
const char *test_texts[] = {
"HELLO ",
"WORLD ",
"123456789",
"VFD TEST ",
"9BY-04GK ",
"ABCDEFGHI",
"JKLMNOPQR"
};
vfd_set(test_texts[test_idx % 7]);
test_idx++;
}
}SPI → SN75518N (VFD)
ESP GPIO11 → SN: DIN
ESP GPIO12 → SN: CLK
ESP GPIO10 → SN: LE
ESP GPIO13 → SN: STROBE
ESP 3.3V → SN: VCC1
ESP GND → SN: GND
+33V → SN: VCC2 (z zasilacza B5, nie z ESP!)
SN75518N → VFD 9BY-04GK
SN: Q1 → VFD: G9
SN: Q2 → VFD: G8
SN: Q3 → VFD: G7
SN: Q4 → VFD: G6
SN: Q5 → VFD: G5
SN: Q6 → VFD: G4
SN: Q7 → VFD: G3
SN: Q8 → VFD: G2
SN: Q9 → VFD: G1
SN: Q10 → VFD: a
SN: Q11 → VFD: j
SN: Q12 → VFD: h
SN: Q13 → VFD: k
SN: Q14 → VFD: b
SN: Q15 → VFD: f
SN: Q16 → VFD: g
SN: Q17 → VFD: m
SN: Q18 → VFD: c
SN: Q19 → VFD: e
SN: Q20 → VFD: v
SN: Q21 → VFD: n
SN: Q22 → VFD: p
SN: Q23 → VFD: d
SN: Q24 → VFD: dp
I²C → TDA8421
ESP GPIO8 → TDA8421: SDA
ESP GPIO9 → TDA8421: SCL
ESP 3.3V → TDA8421: VCC
ESP GND → TDA8421: GND
IR odbiornik
ESP 3.3V → IR: VCC
ESP GND → IR: GND
IR: OUT → rezystor 10kΩ → ESP GPIO14
LED z rezystorami 330Ω
ESP GPIO15 → R330 → LED FLAT → GND
ESP GPIO16 → R330 → LED LOUDNESS → GND
ESP GPIO17 → R330 → LED PSEUDO → GND
ESP GPIO18 → R330 → LED SLEEP → GND
ESP GPIO19 → R330 → LED SPATIAL → GND
ESP GPIO20 → R330 → LED EQ → GND
ESP GPIO21 → R330 → LED STAND-BY → GND
Przyciski (każdy: jeden pin do GPIO, drugi do GND)
ESP GPIO22 → btn TREBLE+
ESP GPIO23 → btn TREBLE-
ESP GPIO24 → btn BASS+
ESP GPIO25 → btn BASS-
ESP GPIO26 → btn VOLUME+
ESP GPIO27 → btn VOLUME-
ESP GPIO28 → btn BALANCE P
ESP GPIO29 → btn BALANCE L
ESP GPIO30 → btn SPATIAL/PSEUDO
ESP GPIO31 → btn TUNER
ESP GPIO32 → btn LOUDNESS
ESP GPIO33 → btn PHONO/FILTER
ESP GPIO34 → btn TAPE
ESP GPIO39 → btn CD
ESP GPIO40 → btn MUTING
ESP GPIO41 → btn EQ
ESP GPIO42 → btn AUX
ESP GPIO2 → btn STAND-BY
Enkodery KY-040 (każdy: CLK, DT, SW, VCC, GND)
enc_vol: CLK→GPIO3 DT→GPIO4 SW→GPIO5 VCC→3.3V GND→GND
enc_bass: CLK→GPIO6 DT→GPIO7 SW→GPIO1 VCC→3.3V GND→GND
enc_treble: CLK→GPIO43 DT→GPIO44 SW→GPIO45 VCC→3.3V GND→GND
enc_balance:CLK→GPIO46 DT→GPIO47 SW→GPIO48 VCC→3.3V GND→GND
RELAY głośników
GPIO8 → (wolne w Wokwi, w sprzęcie: SDA → TDA8421)
GPIO9 → (wolne w Wokwi, w sprzęcie: SCL → TDA8421)