Rewrite MUX: WS2812C LEDs (NeoPixel) + 74HC165 buttons

PixelStomp MUX uses:
- WS2812C LEDs: one data line via DAT (GPIO 9), NeoPixel protocol
- 74HC165 shift register: LD/CLK/DI for reading 8 button states

Changes:
- Use Adafruit NeoPixel library for LED control
- Proper 74HC165 parallel-load shift-in for buttons
- 8 switches + 8 LEDs (was incorrectly 10)
- Diagnostic commands: dump, ledtest, red, green, blue, read
This commit is contained in:
2026-06-23 13:38:51 +00:00
parent 2dfd016b76
commit 07e5cd8994
8 changed files with 122 additions and 139 deletions
+44 -80
View File
@@ -3,116 +3,85 @@
PixelStompMux::PixelStompMux(uint8_t dat, uint8_t ld, uint8_t clk, uint8_t di)
: pin_dat(dat), pin_ld(ld), pin_clk(clk), pin_di(di),
last_button_state(0), current_led_state(0) {
strip(nullptr), last_button_state(0) {
}
void PixelStompMux::begin() {
pinMode(pin_dat, OUTPUT);
pinMode(pin_ld, OUTPUT);
pinMode(pin_clk, OUTPUT);
pinMode(pin_di, INPUT_PULLUP);
digitalWrite(pin_dat, LOW);
digitalWrite(pin_ld, LOW);
digitalWrite(pin_clk, LOW);
strip = new Adafruit_NeoPixel(NUM_LEDS, pin_dat, NEO_GRB + NEO_KHZ800);
strip->begin();
strip->setBrightness(50);
strip->clear();
strip->show();
Serial.printf("[MUX] Init DAT=%d LD=%d CLK=%d DI=%d\n",
pin_dat, pin_ld, pin_clk, pin_di);
Serial.println("[MUX] GPIO probe:");
Serial.printf(" DI (GPIO %d) reads: %d (should be 1 with pullup)\n",
pin_di, digitalRead(pin_di));
for (int i = 0; i < 3; i++) {
digitalWrite(pin_clk, HIGH);
delayMicroseconds(10);
digitalWrite(pin_clk, LOW);
delayMicroseconds(10);
}
Serial.printf(" DI after 3 CLK pulses: %d\n", digitalRead(pin_di));
digitalWrite(pin_ld, HIGH);
delayMicroseconds(10);
digitalWrite(pin_ld, LOW);
delayMicroseconds(10);
Serial.printf(" DI after LD pulse: %d\n", digitalRead(pin_di));
Serial.printf("[MUX] 74HC165 for %d buttons, WS2812C for %d LEDs\n",
NUM_BUTTONS, NUM_LEDS);
}
uint16_t PixelStompMux::read_buttons() {
pulse_pin(pin_ld, HIGH);
delayMicroseconds(10);
pulse_pin(pin_ld, LOW);
delayMicroseconds(10);
uint8_t PixelStompMux::read_buttons() {
digitalWrite(pin_ld, HIGH);
delayMicroseconds(5);
digitalWrite(pin_ld, LOW);
delayMicroseconds(5);
uint16_t state = shift_in(NUM_INPUTS);
last_button_state = state;
return state;
last_button_state = shift_in_74hc165();
return last_button_state;
}
bool PixelStompMux::is_button_pressed(uint8_t index) {
if (index >= NUM_INPUTS) return false;
uint16_t state = read_buttons();
if (index >= NUM_BUTTONS) return false;
uint8_t state = read_buttons();
return !(state & (1 << index));
}
void PixelStompMux::write_leds(uint16_t led_state) {
current_led_state = led_state;
shift_out(led_state, NUM_OUTPUTS);
pulse_pin(pin_ld, HIGH);
delayMicroseconds(10);
pulse_pin(pin_ld, LOW);
void PixelStompMux::set_led_color(uint8_t index, uint8_t r, uint8_t g, uint8_t b) {
if (index >= NUM_LEDS || !strip) return;
strip->setPixelColor(index, strip->Color(r, g, b));
}
void PixelStompMux::set_led(uint8_t index, bool on) {
if (index >= NUM_OUTPUTS) return;
if (on) {
current_led_state |= (1 << index);
} else {
current_led_state &= ~(1 << index);
}
write_leds(current_led_state);
void PixelStompMux::set_led_brightness(uint8_t brightness) {
if (strip) strip->setBrightness(brightness);
}
void PixelStompMux::clear_all() {
write_leds(0x0000);
Serial.println("[MUX] All LEDs off");
if (strip) {
strip->clear();
strip->show();
}
Serial.println("[MUX] LEDs cleared");
}
void PixelStompMux::show() {
if (strip) strip->show();
}
void PixelStompMux::dump() {
uint16_t buttons = read_buttons();
Serial.printf("[MUX] Buttons: 0x%03X LEDs: 0x%03X\n", buttons, current_led_state);
uint8_t buttons = read_buttons();
Serial.printf("[MUX] Buttons: 0x%02X (binary: ", buttons);
for (int i = 7; i >= 0; i--) {
Serial.print((buttons >> i) & 1);
}
Serial.println(")");
for (int i = 0; i < NUM_INPUTS; i++) {
for (int i = 0; i < NUM_BUTTONS; i++) {
bool pressed = !(buttons & (1 << i));
bool led_on = current_led_state & (1 << i);
Serial.printf(" [%d] Button:%s LED:%s\n", i,
pressed ? "PRESS" : "off",
led_on ? "ON" : "off");
Serial.printf(" [%d] %s\n", i, pressed ? "PRESS" : "off");
}
}
void PixelStompMux::shift_out(uint16_t data, uint8_t bits) {
for (int i = bits - 1; i >= 0; i--) {
digitalWrite(pin_dat, (data >> i) & 1);
delayMicroseconds(1);
digitalWrite(pin_clk, HIGH);
delayMicroseconds(1);
digitalWrite(pin_clk, LOW);
delayMicroseconds(1);
}
}
uint8_t PixelStompMux::shift_in_74hc165() {
uint8_t data = 0;
uint16_t PixelStompMux::shift_in(uint8_t bits) {
uint16_t data = 0;
for (int i = bits - 1; i >= 0; i--) {
bool bit = digitalRead(pin_di);
if (bit) {
for (int i = NUM_BUTTONS - 1; i >= 0; i--) {
if (digitalRead(pin_di)) {
data |= (1 << i);
}
digitalWrite(pin_clk, HIGH);
@@ -123,8 +92,3 @@ uint16_t PixelStompMux::shift_in(uint8_t bits) {
return data;
}
void PixelStompMux::pulse_pin(uint8_t pin, uint8_t level, uint16_t duration_us) {
digitalWrite(pin, level);
delayMicroseconds(duration_us);
}