#include <SPI.h>
const uint8_t LATCH_PIN = 10;
const uint8_t LATCH_PIN_MASK = PB2;
const uint8_t OE_PIN = 12;
const uint8_t OE_PIN_MASK = PB4;
const int NUM_ROWS = 8;
uint16_t matrix[NUM_ROWS] = {
0b1111111111111111,
0b1000000000000001,
0b1000000000000001,
0b1000000000000001,
0b1000000000000001,
0b1000000000000001,
0b1000000000000001,
0b1111111111111111,
};
uint8_t currentRow = 0;
void setPixel(uint8_t x, uint8_t y) {
if (x >= 16 || y >= NUM_ROWS)
return;
matrix[y] |= (1 << (16 - 1 - x));
}
void clearPixel(uint8_t x, uint8_t y) {
if (x >= 16 || y >= NUM_ROWS)
return;
matrix[y] &= ~(1 << (16 - 1 - x));
}
static inline uint8_t reverse8(uint8_t b) {
b = (b & 0xF0) >> 4 | (b & 0x0F) << 4;
b = (b & 0xCC) >> 2 | (b & 0x33) << 2;
b = (b & 0xAA) >> 1 | (b & 0x55) << 1;
return b;
}
void showRow(uint8_t row) {
uint8_t rowByte = ~(1 << row);
uint8_t colA = (matrix[row] >> 8) & 0xFF;
uint8_t colB = matrix[row] & 0xFF;
PORTB &= ~(1 << LATCH_PIN_MASK);
PORTB |= (1 << OE_PIN_MASK);
SPI.transfer(rowByte); // Row multiplexing SR
SPI.transfer(reverse8(colB)); // Region B SR
SPI.transfer(reverse8(colA)); // Rebion A SR
PORTB |= (1 << LATCH_PIN_MASK);
PORTB &= ~(1 << OE_PIN_MASK);
}
void setupTimer()
{
OCR2A = 200; // compare match at 200 ticks
TCCR2A = (1 << WGM21); // CTC mode
TCCR2B = (1 << CS21); // prescaler 8
TCNT2 = 0x00; // clear counter
TIMSK2 = (1 << OCIE2A); // enable compare match interrupt
}
void setup() {
pinMode(LATCH_PIN, OUTPUT);
digitalWrite(LATCH_PIN, HIGH);
SPI.begin();
SPI.beginTransaction(SPISettings(8000000, MSBFIRST, SPI_MODE0));
// setupTimer();
}
void loop() {
memset(matrix, 0, NUM_ROWS * sizeof(uint16_t));
static float phase = 0;
for (uint8_t x = 0; x < 16; x++) {
float angle = (x / 16.0) * 2 * PI + phase;
float value = sin(angle);
uint8_t y = (uint8_t)((value + 1) * 3.5);
setPixel(x, y);
}
phase += 0.3;
if (phase > 2 * PI) phase -= 2 * PI; // Wrap around
for (uint8_t r = 0; r < NUM_ROWS; ++r) {
showRow(r);
// matrix[r] = ~matrix[r];
// delayMicroseconds(1000);
delay(10);
}
}
// ISR(TIMER2_COMPA_vect)
// {
// showRow(currentRow++);
// if(currentRow >= NUM_ROWS)
// currentRow = 0;
// }
A
B
Row Multiplexer
Pink: CLOCK
Grey: LATCH
White: DATA