Add PixelStomp MUX driver (DAT=9, LD=10, CLK=11, DI=12)
- New PixelStompMux class with shift register read/write - Read 10 buttons via DI (active LOW) - Drive 10 LEDs via DAT (shift out + latch) - LED startup animation uses MUX - Switch polling reads from MUX shift register - MUX instance shared between switch and LED drivers
This commit is contained in:
@@ -0,0 +1,110 @@
|
||||
#include "pixel_stomp_mux.h"
|
||||
#include <Arduino.h>
|
||||
|
||||
static const char* TAG = "MUX";
|
||||
|
||||
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) {
|
||||
}
|
||||
|
||||
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);
|
||||
|
||||
Serial.printf("[MUX] Init DAT=%d LD=%d CLK=%d DI=%d\n",
|
||||
pin_dat, pin_ld, pin_clk, pin_di);
|
||||
}
|
||||
|
||||
uint16_t PixelStompMux::read_buttons() {
|
||||
pulse_pin(pin_ld, HIGH);
|
||||
delayMicroseconds(5);
|
||||
pulse_pin(pin_ld, LOW);
|
||||
delayMicroseconds(5);
|
||||
|
||||
uint16_t state = shift_in(NUM_INPUTS);
|
||||
last_button_state = state;
|
||||
|
||||
return state;
|
||||
}
|
||||
|
||||
bool PixelStompMux::is_button_pressed(uint8_t index) {
|
||||
if (index >= NUM_INPUTS) return false;
|
||||
|
||||
uint16_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(5);
|
||||
pulse_pin(pin_ld, LOW);
|
||||
}
|
||||
|
||||
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::clear_all() {
|
||||
write_leds(0x0000);
|
||||
Serial.println("[MUX] All LEDs off");
|
||||
}
|
||||
|
||||
void PixelStompMux::dump() {
|
||||
uint16_t buttons = read_buttons();
|
||||
Serial.printf("[MUX] Buttons: 0x%03X LEDs: 0x%03X\n", buttons, current_led_state);
|
||||
|
||||
for (int i = 0; i < NUM_INPUTS; i++) {
|
||||
bool pressed = !(buttons & (1 << i));
|
||||
bool led_on = current_led_state & (1 << i);
|
||||
if (pressed || led_on) {
|
||||
Serial.printf(" [%d] Button:%s LED:%s\n", i,
|
||||
pressed ? "PRESS" : "off",
|
||||
led_on ? "ON" : "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);
|
||||
pulse_pin(pin_clk, HIGH);
|
||||
pulse_pin(pin_clk, LOW);
|
||||
}
|
||||
}
|
||||
|
||||
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) {
|
||||
data |= (1 << i);
|
||||
}
|
||||
pulse_pin(pin_clk, HIGH);
|
||||
pulse_pin(pin_clk, LOW);
|
||||
}
|
||||
|
||||
return data;
|
||||
}
|
||||
|
||||
void PixelStompMux::pulse_pin(uint8_t pin, uint8_t level, uint16_t duration_us) {
|
||||
digitalWrite(pin, level);
|
||||
delayMicroseconds(duration_us);
|
||||
}
|
||||
Reference in New Issue
Block a user