/*
Charlyplexing: 12 LEDs with 4 Pins.
Serial Commands:
0 .. 9 switches a LED on
a .. l switches a LED off
2024-04-01 by noiasca : initial version
2024-04-27 reversed anode/cathode
*/
class Charlyplexing {
protected:
const uint16_t interval = 2; // interval / speed of refresh
uint8_t pin[4]; // an array with 4 pins
uint32_t previousMillis = 0; // time management
uint8_t row = 0; // current row
uint8_t col = 0; // current column
uint8_t i = 0; // current index
uint16_t mask = 0; // 4 x 4 pins = 16, but only 12 bits are needed
public:
Charlyplexing (uint8_t a, uint8_t b, uint8_t c, uint8_t d) {
pin[0] = a;
pin[1] = b;
pin[2] = c;
pin[3] = d;
}
void digitalWriteFast(uint8_t pin, uint8_t val) {
uint8_t bit = digitalPinToBitMask(pin);
uint8_t port = digitalPinToPort(pin);
volatile uint8_t *out = portOutputRegister(port);
if (val == LOW) {
*out &= ~bit;
} else {
*out |= bit;
}
}
void set(uint8_t pin, uint8_t level) {
if (level == LOW)
mask &= ~(1 << pin);
else
mask |= (1 << pin);
Serial.print(pin); Serial.print(" now "); Serial.print(level); Serial.print(' '); Serial.println(mask, BIN);
}
void update(uint32_t currentMillis = millis()) {
//if (currentMillis != previousMillis ) {
if (currentMillis - previousMillis >= interval) {
if (col != row) {
//deactivate previous column
pinMode(pin[col], INPUT);
++i;
}
// next candidate
++col;
if (col >= sizeof(pin)) {
col = 0; // wraparound col
digitalWriteFast(pin[row], LOW);
pinMode(pin[row], INPUT); // deactivate old row
++row; // next row
if (row >= sizeof(pin)) {
row = 0; // wraparound row
i = 0;
}
pinMode(pin[row], OUTPUT);
digitalWriteFast(pin[row], HIGH);
}
if (col != row && (((mask >> i) & 1) == HIGH)) {
// activate actual
pinMode(pin[col], OUTPUT);
//Serial.print("r="); Serial.print(row); Serial.print(" c="); Serial.println(col);
previousMillis = currentMillis;
}
}
}
};
Charlyplexing charly(12, 11, 10, 9);
void serialHandle() {
int in = Serial.read();
switch (in) {
case -1 : return;
case '0' ... '9': charly.set(in - '0', HIGH); break;
case 'a' ... 'l': charly.set(in - 'a', LOW); break;
}
}
void setup() {
Serial.begin(115200);
Serial.println("Charly");
// charly.set(0, HIGH); // switch on LED
// charly.set(1, HIGH);
// charly.set(2, HIGH);
// charly.set(3, HIGH);
// charly.set(4, HIGH);
// charly.set(5, HIGH);
// charly.set(6, HIGH);
// charly.set(7, HIGH);
// charly.set(8, HIGH);
// charly.set(9, HIGH);
charly.set(10, HIGH);
charly.set(11, HIGH);
}
void loop() {
charly.update(); // give the charlyplexing matrix some time to operate
serialHandle(); // handle Serial interface
}