24 #if defined(ARDUINO) && ARDUINO >= 100
29 #include <pins_arduino.h>
31 #include <avr/interrupt.h>
211 #define DMD_PIN_PHASE_LSB 6 // A
212 #define DMD_PIN_PHASE_MSB 7 // B
213 #define DMD_PIN_LATCH 8 // SCLK
214 #define DMD_PIN_OUTPUT_ENABLE 9 // nOE
215 #define DMD_PIN_SPI_SS SS // SPI Slave Select
216 #define DMD_PIN_SPI_MOSI MOSI // SPI Master Out, Slave In (R)
217 #define DMD_PIN_SPI_MISO MISO // SPI Master In, Slave Out
218 #define DMD_PIN_SPI_SCK SCK // SPI Serial Clock (CLK)
221 #define DMD_NUM_COLUMNS 32 // Number of columns in a panel.
222 #define DMD_NUM_ROWS 16 // Number of rows in a panel.
225 #define DMD_REFRESH_MS 5
226 #define DMD_REFRESH_US 5000
238 :
Bitmap(widthPanels * DMD_NUM_COLUMNS, heightPanels * DMD_NUM_ROWS)
239 , _doubleBuffer(false)
244 , lastRefresh(millis())
247 fb0 = displayfb = fb;
250 pinMode(DMD_PIN_SPI_SCK, OUTPUT);
251 pinMode(DMD_PIN_SPI_MOSI, OUTPUT);
252 pinMode(DMD_PIN_SPI_SS, OUTPUT);
253 digitalWrite(DMD_PIN_SPI_SCK, LOW);
254 digitalWrite(DMD_PIN_SPI_MOSI, LOW);
255 digitalWrite(DMD_PIN_SPI_SS, HIGH);
258 SPCR &= ~(_BV(DORD));
264 pinMode(DMD_PIN_PHASE_LSB, OUTPUT);
265 pinMode(DMD_PIN_PHASE_MSB, OUTPUT);
266 pinMode(DMD_PIN_LATCH, OUTPUT);
267 pinMode(DMD_PIN_OUTPUT_ENABLE, OUTPUT);
268 digitalWrite(DMD_PIN_PHASE_LSB, LOW);
269 digitalWrite(DMD_PIN_PHASE_MSB, LOW);
270 digitalWrite(DMD_PIN_LATCH, LOW);
271 digitalWrite(DMD_PIN_OUTPUT_ENABLE, LOW);
272 digitalWrite(DMD_PIN_SPI_MOSI, HIGH);
316 if (doubleBuffer != _doubleBuffer) {
320 unsigned int size = _stride * _height;
321 fb1 = (uint8_t *)malloc(size);
326 memset(fb1, 0xFF, size);
333 _doubleBuffer =
false;
400 memcpy(fb, displayfb, _stride * _height);
422 unsigned long currentTime = millis();
423 if ((currentTime - lastRefresh) >= DMD_REFRESH_MS) {
424 lastRefresh = currentTime;
430 static inline void spiSend(byte value)
433 while (!(SPSR & _BV(SPIF)))
438 static const uint8_t flipBits[256] PROGMEM = {
439 0x00, 0x80, 0x40, 0xC0, 0x20, 0xA0, 0x60, 0xE0, 0x10, 0x90, 0x50, 0xD0,
440 0x30, 0xB0, 0x70, 0xF0, 0x08, 0x88, 0x48, 0xC8, 0x28, 0xA8, 0x68, 0xE8,
441 0x18, 0x98, 0x58, 0xD8, 0x38, 0xB8, 0x78, 0xF8, 0x04, 0x84, 0x44, 0xC4,
442 0x24, 0xA4, 0x64, 0xE4, 0x14, 0x94, 0x54, 0xD4, 0x34, 0xB4, 0x74, 0xF4,
443 0x0C, 0x8C, 0x4C, 0xCC, 0x2C, 0xAC, 0x6C, 0xEC, 0x1C, 0x9C, 0x5C, 0xDC,
444 0x3C, 0xBC, 0x7C, 0xFC, 0x02, 0x82, 0x42, 0xC2, 0x22, 0xA2, 0x62, 0xE2,
445 0x12, 0x92, 0x52, 0xD2, 0x32, 0xB2, 0x72, 0xF2, 0x0A, 0x8A, 0x4A, 0xCA,
446 0x2A, 0xAA, 0x6A, 0xEA, 0x1A, 0x9A, 0x5A, 0xDA, 0x3A, 0xBA, 0x7A, 0xFA,
447 0x06, 0x86, 0x46, 0xC6, 0x26, 0xA6, 0x66, 0xE6, 0x16, 0x96, 0x56, 0xD6,
448 0x36, 0xB6, 0x76, 0xF6, 0x0E, 0x8E, 0x4E, 0xCE, 0x2E, 0xAE, 0x6E, 0xEE,
449 0x1E, 0x9E, 0x5E, 0xDE, 0x3E, 0xBE, 0x7E, 0xFE, 0x01, 0x81, 0x41, 0xC1,
450 0x21, 0xA1, 0x61, 0xE1, 0x11, 0x91, 0x51, 0xD1, 0x31, 0xB1, 0x71, 0xF1,
451 0x09, 0x89, 0x49, 0xC9, 0x29, 0xA9, 0x69, 0xE9, 0x19, 0x99, 0x59, 0xD9,
452 0x39, 0xB9, 0x79, 0xF9, 0x05, 0x85, 0x45, 0xC5, 0x25, 0xA5, 0x65, 0xE5,
453 0x15, 0x95, 0x55, 0xD5, 0x35, 0xB5, 0x75, 0xF5, 0x0D, 0x8D, 0x4D, 0xCD,
454 0x2D, 0xAD, 0x6D, 0xED, 0x1D, 0x9D, 0x5D, 0xDD, 0x3D, 0xBD, 0x7D, 0xFD,
455 0x03, 0x83, 0x43, 0xC3, 0x23, 0xA3, 0x63, 0xE3, 0x13, 0x93, 0x53, 0xD3,
456 0x33, 0xB3, 0x73, 0xF3, 0x0B, 0x8B, 0x4B, 0xCB, 0x2B, 0xAB, 0x6B, 0xEB,
457 0x1B, 0x9B, 0x5B, 0xDB, 0x3B, 0xBB, 0x7B, 0xFB, 0x07, 0x87, 0x47, 0xC7,
458 0x27, 0xA7, 0x67, 0xE7, 0x17, 0x97, 0x57, 0xD7, 0x37, 0xB7, 0x77, 0xF7,
459 0x0F, 0x8F, 0x4F, 0xCF, 0x2F, 0xAF, 0x6F, 0xEF, 0x1F, 0x9F, 0x5F, 0xDF,
460 0x3F, 0xBF, 0x7F, 0xFF
481 if (!digitalRead(DMD_PIN_SPI_SS))
485 int stride4 = _stride * 4;
490 bool flipRow = ((_height & 0x10) == 0);
491 for (
int y = 0; y < _height; y += 16) {
494 data0 = displayfb + _stride * (y + phase);
495 data1 = data0 + stride4;
496 data2 = data1 + stride4;
497 data3 = data2 + stride4;
498 for (
int x = _stride; x > 0; --x) {
507 data0 = displayfb + _stride * (y + 16 - phase) - 1;
508 data1 = data0 - stride4;
509 data2 = data1 - stride4;
510 data3 = data2 - stride4;
511 for (
int x = _stride; x > 0; --x) {
512 spiSend(pgm_read_byte(&(flipBits[*data3--])));
513 spiSend(pgm_read_byte(&(flipBits[*data2--])));
514 spiSend(pgm_read_byte(&(flipBits[*data1--])));
515 spiSend(pgm_read_byte(&(flipBits[*data0--])));
522 digitalWrite(DMD_PIN_OUTPUT_ENABLE, LOW);
523 digitalWrite(DMD_PIN_LATCH, HIGH);
524 digitalWrite(DMD_PIN_LATCH, LOW);
526 digitalWrite(DMD_PIN_PHASE_MSB, HIGH);
528 digitalWrite(DMD_PIN_PHASE_MSB, LOW);
530 digitalWrite(DMD_PIN_PHASE_LSB, HIGH);
532 digitalWrite(DMD_PIN_PHASE_LSB, LOW);
533 digitalWrite(DMD_PIN_OUTPUT_ENABLE, HIGH);
534 phase = (phase + 1) & 0x03;
566 unsigned long numCycles = (F_CPU / 2000000) * DMD_REFRESH_US;
569 #define TIMER1_RESOLUTION 65536UL
571 if (numCycles < TIMER1_RESOLUTION) {
573 prescaler = _BV(CS10);
574 }
else if (numCycles < TIMER1_RESOLUTION * 8) {
576 prescaler = _BV(CS11);
578 }
else if (numCycles < TIMER1_RESOLUTION * 64) {
580 prescaler = _BV(CS11) | _BV(CS10);
582 }
else if (numCycles < TIMER1_RESOLUTION * 256) {
584 prescaler = _BV(CS12);
586 }
else if (numCycles < TIMER1_RESOLUTION * 1024) {
588 prescaler = _BV(CS12) | _BV(CS10);
592 prescaler = _BV(CS12) | _BV(CS10);
593 numCycles = TIMER1_RESOLUTION - 1;
599 uint8_t saveSREG = SREG;
603 TCCR1B = (TCCR1B & ~(_BV(CS12) | _BV(CS11) | _BV(CS10))) | prescaler;
606 TIMSK1 |= _BV(TOIE1);
617 TIMSK1 &= ~_BV(TOIE1);
653 if (F_CPU >= 32000000)
654 TCCR2B = _BV(CS22) | _BV(CS21);
655 else if (F_CPU >= 16000000)
656 TCCR2B = _BV(CS22) | _BV(CS20);
657 else if (F_CPU >= 8000000)
660 TCCR2B = _BV(CS21) | _BV(CS20);
677 TIMSK2 &= ~_BV(TOIE2);
void disableTimer1()
Disables Timer1 overflow interrupts.
void loop()
Performs regular display refresh activities from the application's main loop.
void disableTimer2()
Disables Timer2 overflow interrupts.
Represents a monochrome bitmap within main memory.
bool doubleBuffer() const
Returns true if the display is double-buffered; false if single-buffered. The default is false...
void swapBuffers()
Swaps the buffers that are used for rendering to the display.
void enableTimer1()
Enables Timer1 overflow interrupts for updating this display.
~DMD()
Destroys this dot matrix display handler.
uint8_t Color
Type that represents the color of a pixel in a bitmap.
void swapBuffersAndCopy()
Swaps the buffers that are used for rendering to the display and copies the former back buffer conten...
DMD(int widthPanels=1, int heightPanels=1)
Constructs a new dot matrix display handler for a display that is widthPanels x heightPanels in size...
void enableTimer2()
Enables Timer2 overflow interrupts for updating this display.
static Color fromRGB(uint8_t r, uint8_t g, uint8_t b)
Converts an RGB value into a pixel color value.
static const Color White
Color value corresponding to "white". If the bitmap is displayed on a LED array, then it may have a d...
void refresh()
Refresh the display.
void setDoubleBuffer(bool doubleBuffer)
Enables or disables double-buffering according to doubleBuffer.
static const Color Black
Color value corresponding to "black".