From b40df07cea6d701f7270e198286b3741622c21fe Mon Sep 17 00:00:00 2001 From: protonmaster Date: Wed, 30 Oct 2013 22:29:07 +1300 Subject: [PATCH 1/3] Update RGBmatrixPanel.cpp --- RGBmatrixPanel.cpp | 89 +++++++++++++++++++++++++++++++--------------- 1 file changed, 60 insertions(+), 29 deletions(-) diff --git a/RGBmatrixPanel.cpp b/RGBmatrixPanel.cpp index 81fdb89..3f1a7de 100644 --- a/RGBmatrixPanel.cpp +++ b/RGBmatrixPanel.cpp @@ -51,6 +51,13 @@ performance and/or lower CPU utilization: #define DATAPORT PORTA #define DATADIR DDRA #define SCLKPORT PORTB + + #elif defined(__SAM3X8E__) + // Arduino Due uses the SAM3X8E. + #define DATAPORT PORTC + #define DATADIR tobedefined + #define SCLKPORT tobedefined + #elif defined(__AVR_ATmega32U4__) // Arduino Leonardo is still a work in progress -- DO NOT USE!!! // Unlike the Uno, digital pins 2-7 do NOT map to a contiguous port @@ -79,12 +86,13 @@ static RGBmatrixPanel *activePanel = NULL; // Code common to both the 16x32 and 32x32 constructors: void RGBmatrixPanel::init(uint8_t rows, uint8_t a, uint8_t b, uint8_t c, - uint8_t sclk, uint8_t latch, uint8_t oe, boolean dbuf) { + uint8_t sclk, uint8_t latch, uint8_t oe, boolean dbuf, uint8_t pwidth) { nRows = rows; // Number of multiplexed rows; actual height is 2X this + nPanels = pwidth; // Allocate and initialize matrix buffer: - int buffsize = 32 * nRows * 3, // x3 = 3 bytes holds 4 planes "packed" + int buffsize = 32 * nRows * 3 * nPanels, // x3 = 3 bytes holds 4 planes "packed" allocsize = (dbuf == true) ? (buffsize * 2) : buffsize; if(NULL == (matrixbuff[0] = (uint8_t *)malloc(allocsize))) return; memset(matrixbuff[0], 0, allocsize); @@ -122,19 +130,19 @@ void RGBmatrixPanel::init(uint8_t rows, uint8_t a, uint8_t b, uint8_t c, // Constructor for 16x32 panel: RGBmatrixPanel::RGBmatrixPanel( uint8_t a, uint8_t b, uint8_t c, - uint8_t sclk, uint8_t latch, uint8_t oe, boolean dbuf) : - Adafruit_GFX(32, 16) { + uint8_t sclk, uint8_t latch, uint8_t oe, boolean dbuf, uint8_t pwidth) : + Adafruit_GFX(32*pwidth, 16) { - init(8, a, b, c, sclk, latch, oe, dbuf); + init(8, a, b, c, sclk, latch, oe, dbuf, pwidth); } // Constructor for 32x32 panel: RGBmatrixPanel::RGBmatrixPanel( uint8_t a, uint8_t b, uint8_t c, uint8_t d, - uint8_t sclk, uint8_t latch, uint8_t oe, boolean dbuf) : - Adafruit_GFX(32, 32) { + uint8_t sclk, uint8_t latch, uint8_t oe, boolean dbuf, uint8_t pwidth) : + Adafruit_GFX(32*pwidth, 32) { - init(16, a, b, c, sclk, latch, oe, dbuf); + init(16, a, b, c, sclk, latch, oe, dbuf, pwidth); // Init a few extra 32x32-specific elements: _d = d; @@ -296,14 +304,17 @@ void RGBmatrixPanel::drawPixel(int16_t x, int16_t y, uint16_t c) { ptr = &matrixbuff[backindex][y * WIDTH * (nPlanes - 1) + x]; // Base addr // Plane 0 is a tricky case -- its data is spread about, // stored in least two bits not used by the other planes. - ptr[64] &= ~B00000011; // Plane 0 R,G mask out in one op - if(r & 1) ptr[64] |= B00000001; // Plane 0 R: 64 bytes ahead, bit 0 - if(g & 1) ptr[64] |= B00000010; // Plane 0 G: 64 bytes ahead, bit 1 - if(b & 1) ptr[32] |= B00000001; // Plane 0 B: 32 bytes ahead, bit 0 - else ptr[32] &= ~B00000001; // Plane 0 B unset; mask out + ptr=ptr+64*nPanels; + *ptr &= ~B00000011; // Plane 0 R,G mask out in one op + if(r & 1) *ptr |= B00000001; // Plane 0 R: 64 bytes ahead, bit 0 + if(g & 1) *ptr |= B00000010; // Plane 0 G: 64 bytes ahead, bit 1 + ptr=ptr-32*nPanels; + if(b & 1) *ptr |= B00000001; // Plane 0 B: 32 bytes ahead, bit 0 + else *ptr &= ~B00000001; // Plane 0 B unset; mask out // The remaining three image planes are more normal-ish. // Data is stored in the high 6 bits so it can be quickly // copied to the DATAPORT register w/6 output lines. + ptr=ptr-32*nPanels; for(; bit < limit; bit <<= 1) { *ptr &= ~B00011100; // Mask out R,G,B in one op if(r & bit) *ptr |= B00000100; // Plane N R: bit 2 @@ -316,8 +327,8 @@ void RGBmatrixPanel::drawPixel(int16_t x, int16_t y, uint16_t c) { // bits, except for the plane 0 stuff, using 2 least bits. ptr = &matrixbuff[backindex][(y - nRows) * WIDTH * (nPlanes - 1) + x]; *ptr &= ~B00000011; // Plane 0 G,B mask out in one op - if(r & 1) ptr[32] |= B00000010; // Plane 0 R: 32 bytes ahead, bit 1 - else ptr[32] &= ~B00000010; // Plane 0 R unset; mask out + if(r & 1) ptr[32*nPanels] |= B00000010; // Plane 0 R: 32 bytes ahead, bit 1 + else ptr[32*nPanels] &= ~B00000010; // Plane 0 R unset; mask out if(g & 1) *ptr |= B00000001; // Plane 0 G: bit 0 if(b & 1) *ptr |= B00000010; // Plane 0 B: bit 0 for(; bit < limit; bit <<= 1) { @@ -335,7 +346,7 @@ void RGBmatrixPanel::fillScreen(uint16_t c) { // For black or white, all bits in frame buffer will be identically // set or unset (regardless of weird bit packing), so it's OK to just // quickly memset the whole thing: - memset(matrixbuff[backindex], c, 32 * nRows * 3); + memset(matrixbuff[backindex], c, 32 * nRows * 3 * nPanels); } else { // Otherwise, need to handle it the long way: Adafruit_GFX::fillScreen(c); @@ -360,7 +371,7 @@ void RGBmatrixPanel::swapBuffers(boolean copy) { swapflag = true; // Set flag here, then... while(swapflag == true) delay(1); // wait for interrupt to clear it if(copy == true) - memcpy(matrixbuff[backindex], matrixbuff[1-backindex], 32 * nRows * 3); + memcpy(matrixbuff[backindex], matrixbuff[1-backindex], 32 * nRows * 3 * nPanels); } } @@ -371,7 +382,7 @@ void RGBmatrixPanel::swapBuffers(boolean copy) { // back into the display using a pgm_read_byte() loop. void RGBmatrixPanel::dumpMatrix(void) { - int i, buffsize = 32 * nRows * 3; + int i, buffsize = 32 * nRows * 3 * nPanels; Serial.print("\n\n" "#include \n\n" @@ -409,7 +420,7 @@ ISR(TIMER1_OVF_vect, ISR_BLOCK) { // ISR_BLOCK important -- see notes later // Both numbers are rounded up slightly to allow a little wiggle room // should different compilers produce slightly different results. #define CALLOVERHEAD 60 // Actual value measured = 56 -#define LOOPTIME 200 // Actual value measured = 188 +#define LOOPTIME 350 // Actual value measured = 188 // The "on" time for bitplane 0 (with the shortest BCM interval) can // then be estimated as LOOPTIME + CALLOVERHEAD * 2. Each successive // bitplane then doubles the prior amount of time. We can then @@ -444,6 +455,7 @@ ISR(TIMER1_OVF_vect, ISR_BLOCK) { // ISR_BLOCK important -- see notes later void RGBmatrixPanel::updateDisplay(void) { uint8_t i, tick, tock, *ptr; uint16_t t, duration; + uint8_t panelcount; *oeport |= oepin; // Disable LED output during row/plane switchover *latport |= latpin; // Latch data loaded during *prior* interrupt @@ -516,6 +528,7 @@ void RGBmatrixPanel::updateDisplay(void) { // The least 2 bits (used for plane 0 data) are presumed masked out // by the port direction bits. +#if defined(__AVR__) // A tiny bit of inline assembly is used; compiler doesn't pick // up on opportunity for post-increment addressing mode. // 5 instruction ticks per 'pew' = 160 ticks total @@ -525,16 +538,33 @@ void RGBmatrixPanel::updateDisplay(void) { asm volatile("out %0,%1" :: "I"(_SFR_IO_ADDR(SCLKPORT)),"r"(tick)); \ asm volatile("out %0,%1" :: "I"(_SFR_IO_ADDR(SCLKPORT)),"r"(tock)); - // Loop is unrolled for speed: - pew pew pew pew pew pew pew pew - pew pew pew pew pew pew pew pew - pew pew pew pew pew pew pew pew - pew pew pew pew pew pew pew pew - + + for (panelcount = 0; panelcount < nPanels; panelcount++) + { + // Loop is unrolled for speed: + pew pew pew pew pew pew pew pew + pew pew pew pew pew pew pew pew + pew pew pew pew pew pew pew pew + pew pew pew pew pew pew pew pew + } + // From the "Unsolved Mysteries" department: "buffptr += 32" doesn't // work here, scrambles the display. "buffptr = ptr" does, even though // both should produce the same results. Couldn't tell you why. buffptr = ptr; +#else // Code for none AVR (i.e. Duo and ARM based systems) + for(i=0; i<(32*nPanels); i++) + { + DATAPORT = ptr[i]; + SCLKPORT = tick; // Clock lo + SCLKPORT = tock; // Clock hi + } + buffptr += (32*nPanels); +#endif + + + + } else { // 920 ticks from TCNT1=0 (above) to end of function @@ -547,13 +577,14 @@ void RGBmatrixPanel::updateDisplay(void) { // output for plane 0 is handled while plane 3 is being displayed... // because binary coded modulation is used (not PWM), that plane // has the longest display interval, so the extra work fits. - for(i=0; i<32; i++) { + for(i=0; i<(32*nPanels); i++) { DATAPORT = - ( ptr[i] << 6) | - ((ptr[i+32] << 4) & 0x30) | - ((ptr[i+64] << 2) & 0x0C); + ( ptr[i] << 6) | + ((ptr[i+(32*nPanels)] << 4) & 0x30) | + ((ptr[i+(64*nPanels)] << 2) & 0x0C); SCLKPORT = tick; // Clock lo SCLKPORT = tock; // Clock hi + } } } From b85759db290de5592d8a17d223471fa7a1d545a8 Mon Sep 17 00:00:00 2001 From: protonmaster Date: Wed, 30 Oct 2013 22:30:37 +1300 Subject: [PATCH 2/3] Update RGBmatrixPanel.h --- RGBmatrixPanel.h | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/RGBmatrixPanel.h b/RGBmatrixPanel.h index 85051fe..24b81fd 100644 --- a/RGBmatrixPanel.h +++ b/RGBmatrixPanel.h @@ -12,11 +12,11 @@ class RGBmatrixPanel : public Adafruit_GFX { // Constructor for 16x32 panel: RGBmatrixPanel(uint8_t a, uint8_t b, uint8_t c, - uint8_t sclk, uint8_t latch, uint8_t oe, boolean dbuf); + uint8_t sclk, uint8_t latch, uint8_t oe, boolean dbuf, uint8_t pwidth); // Constructor for 32x32 panel (adds 'd' pin): RGBmatrixPanel(uint8_t a, uint8_t b, uint8_t c, uint8_t d, - uint8_t sclk, uint8_t latch, uint8_t oe, boolean dbuf); + uint8_t sclk, uint8_t latch, uint8_t oe, boolean dbuf,uint8_t pwidth); void begin(void), @@ -38,12 +38,12 @@ class RGBmatrixPanel : public Adafruit_GFX { private: uint8_t *matrixbuff[2]; - uint8_t nRows, nPlanes, backindex; + uint8_t nRows, nPlanes, backindex, nPanels; boolean swapflag; // Init/alloc code common to both constructors: void init(uint8_t rows, uint8_t a, uint8_t b, uint8_t c, - uint8_t sclk, uint8_t latch, uint8_t oe, boolean dbuf); + uint8_t sclk, uint8_t latch, uint8_t oe, boolean dbuf, uint8_t pwidth); // PORT register pointers, pin bitmasks, pin numbers: volatile uint8_t From b8ef6138f470c8ba016ad7a01056eb003549611c Mon Sep 17 00:00:00 2001 From: protonmaster Date: Sat, 7 Dec 2013 13:58:24 +1300 Subject: [PATCH 3/3] Update RGBmatrixPanel.h Made init parameters clearer. --- RGBmatrixPanel.h | 8 +++++++- 1 file changed, 7 insertions(+), 1 deletion(-) diff --git a/RGBmatrixPanel.h b/RGBmatrixPanel.h index 24b81fd..fe42da4 100644 --- a/RGBmatrixPanel.h +++ b/RGBmatrixPanel.h @@ -13,8 +13,14 @@ class RGBmatrixPanel : public Adafruit_GFX { // Constructor for 16x32 panel: RGBmatrixPanel(uint8_t a, uint8_t b, uint8_t c, uint8_t sclk, uint8_t latch, uint8_t oe, boolean dbuf, uint8_t pwidth); + /* Parameters + a, b, c are the pins used for addressing the rows + cclk, latch and oe are the pins used for Serial Clock, Latach and Output Enable + dbuf enables double buffering. This will use 2x RAM for frame buffer, but will give nice smooth animation + pwidth is the number of Panels used together in a multi panel configuration + */ - // Constructor for 32x32 panel (adds 'd' pin): + // Constructor for 32x32 panel (adds 'd' pin): (THIS HAS NOT BEEN TESTED WITH MULTIPLE PANELS) RGBmatrixPanel(uint8_t a, uint8_t b, uint8_t c, uint8_t d, uint8_t sclk, uint8_t latch, uint8_t oe, boolean dbuf,uint8_t pwidth);