Adafruit-RGB_matrix_Panel(32*16)
Dependencies: Adafruit-GFX
Revision 2:6136465ffd3a, committed 2014-05-24
- Comitter:
- lelect
- Date:
- Sat May 24 11:43:34 2014 +0000
- Parent:
- 1:0078213d3fa4
- Child:
- 3:aa3762e0dfee
- Commit message:
- log_debug add;
Changed in this revision
RGBmatrixPanel.cpp | Show annotated file Show diff for this revision Revisions of this file |
RGBmatrixPanel.h | Show annotated file Show diff for this revision Revisions of this file |
--- a/RGBmatrixPanel.cpp Sat May 24 08:38:23 2014 +0000 +++ b/RGBmatrixPanel.cpp Sat May 24 11:43:34 2014 +0000 @@ -1,10 +1,7 @@ +#define DEBUG #include "RGBmatrixPanel.h" #include "gamma.h" -#define DATAPORT PORTD -#define DATADIR DDRD -#define SCLKPORT PORTB - #define nPlanes 4 // The fact that the display driver interrupt stuff is tied to the @@ -18,7 +15,7 @@ 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, bool dbuf) +void RGBmatrixPanel::init(uint8_t rows, bool dbuf) { nRows = rows; // Number of multiplexed rows; actual height is 2X this // Allocate and initialize matrix buffer: @@ -29,28 +26,6 @@ // If not double-buffered, both buffers then point to the same address: matrixbuff[1] = (dbuf == true) ? &matrixbuff[0][buffsize] : matrixbuff[0]; - // Save pin numbers for use by begin() method later. - _a = a; - _a = a; - _b = b; - _c = c; - _sclk = sclk; - _latch = latch; - _oe = oe; - - // Look up port registers and pin masks ahead of time, - // avoids many slow digitalWrite() calls later. - sclkpin = digitalPinToBitMask(sclk); - latport = portOutputRegister(digitalPinToPort(latch)); - latpin = digitalPinToBitMask(latch); - oeport = portOutputRegister(digitalPinToPort(oe)); - oepin = digitalPinToBitMask(oe); - addraport = portOutputRegister(digitalPinToPort(a)); - addrapin = digitalPinToBitMask(a); - addrbport = portOutputRegister(digitalPinToPort(b)); - addrbpin = digitalPinToBitMask(b); - addrcport = portOutputRegister(digitalPinToPort(c)); - addrcpin = digitalPinToBitMask(c); plane = nPlanes - 1; row = nRows - 1; swapflag = false; @@ -58,22 +33,31 @@ } // Constructor for 16x32 panel: -RGBmatrixPanel::RGBmatrixPanel(uint8_t a, uint8_t b, uint8_t c, uint8_t sclk, uint8_t latch, uint8_t oe, bool dbuf) - :Adafruit_GFX(32, 16) +RGBmatrixPanel::RGBmatrixPanel(PinName a, PinName b, PinName c, PinName sclk, PinName latch, PinName oe, bool dbuf) + :Adafruit_GFX(32, 16), + _sclk(sclk), + _latch(latch), + _oe(oe), + _a(a), + _b(b), + _c(c), + _d(NC) { - init(8, a, b, c, sclk, latch, oe, dbuf); + init(8, dbuf); } // 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, bool dbuf) - :Adafruit_GFX(32, 32) +RGBmatrixPanel::RGBmatrixPanel(PinName a, PinName b, PinName c, PinName d, PinName sclk, PinName latch, PinName oe, bool dbuf) + :Adafruit_GFX(32, 32), + _sclk(sclk), + _latch(latch), + _oe(oe), + _a(a), + _b(b), + _c(c), + _d(d)// Init 32x32-specific elements: { - init(16, a, b, c, sclk, latch, oe, dbuf); - - // Init a few extra 32x32-specific elements: - _d = d; - addrdport = portOutputRegister(digitalPinToPort(d)); - addrdpin = digitalPinToBitMask(d); + init(16,dbuf); } void RGBmatrixPanel::begin(void) @@ -83,35 +67,21 @@ buffptr = matrixbuff[1 - backindex]; // -> front buffer activePanel = this; // For interrupt hander - // Enable all comm & address pins as outputs, set default states: - pinMode(_sclk , OUTPUT); - SCLKPORT &= ~sclkpin; // Low - pinMode(_latch, OUTPUT); - *latport &= ~latpin; // Low - pinMode(_oe , OUTPUT); - *oeport |= oepin; // High (disable output) - pinMode(_a , OUTPUT); - *addraport &= ~addrapin; // Low - pinMode(_b , OUTPUT); - *addrbport &= ~addrbpin; // Low - pinMode(_c , OUTPUT); - *addrcport &= ~addrcpin; // Low - if(nRows > 8) { - pinMode(_d , OUTPUT); - *addrdport &= ~addrdpin; // Low - } - // The high six bits of the data port are set as outputs; // Might make this configurable in the future, but not yet. + /* DATADIR = B11111100; DATAPORT = 0; + */ // Set up Timer1 for interrupt: + /* TCCR1A = _BV(WGM11); // Mode 14 (fast PWM), OC1A off TCCR1B = _BV(WGM13) | _BV(WGM12) | _BV(CS10); // Mode 14, no prescale ICR1 = 100; TIMSK1 |= _BV(TOIE1); // Enable Timer1 interrupt sei(); // Enable global interrupts + */ } // Original RGBmatrixPanel library used 3/3/3 color. Later version used @@ -216,9 +186,10 @@ // to allow shifts, and upgrade to int makes other conversions implicit. v1 = val + 1; if(gflag) { // Gamma-corrected color? - r = pgm_read_byte(&gamma[(r * v1) >> 8]); // Gamma correction table maps - g = pgm_read_byte(&gamma[(g * v1) >> 8]); // 8-bit input to 4-bit output - b = pgm_read_byte(&gamma[(b * v1) >> 8]); + r = gamma[(r * v1) >> 8]; // Gamma correction table maps + g = gamma[(g * v1) >> 8]; // 8-bit input to 4-bit output + b = gamma[(b * v1) >> 8]; + //before pgm_read_byte(&gamma[(b * v1) >> 8]) } else { // linear (uncorrected) color r = (r * v1) >> 12; // 4-bit results g = (g * v1) >> 12; @@ -258,41 +229,39 @@ limit = 1 << nPlanes; if(y < nRows) { - // Data for the upper half of the display is stored in the lower - // bits of each byte. - ptr = &[backindex][y * _rawWidth * (nPlanes - 1) + x]; // Base addr + // Data for the upper half of the display is stored in the lower bits of each byte. + ptr = &matrixbuff[backindex][y*_rawWidth*(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[64] &= ~(_BV(0)|_BV(1)); // Plane 0 R,G mask(0b11111100) out in one op + if(r & 1) ptr[64] |= _BV(0); // Plane 0 R: 64 bytes ahead, bit 0 + if(g & 1) ptr[64] |= _BV(1); // Plane 0 G: 64 bytes ahead, bit 1 + if(b & 1) ptr[32] |= _BV(0); // Plane 0 B: 32 bytes ahead, bit 0 + else ptr[32] &= ~_BV(0); // 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. 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 - if(g & bit) *ptr |= B00001000; // Plane N G: bit 3 - if(b & bit) *ptr |= B00010000; // Plane N B: bit 4 - ptr += WIDTH; // Advance to next bit plane + ptr[0] &= ~(_BV(2)|_BV(3)|_BV(4)); // Mask(0b0001110) out R,G,B in one op + if(r & bit) *ptr |= _BV(2); // Plane N R: bit 2 + if(g & bit) *ptr |= _BV(3); // Plane N G: bit 3 + if(b & bit) *ptr |= _BV(4); // Plane N B: bit 4 + ptr += _rawWidth; // Advance to next bit plane } } else { - // Data for the lower half of the display is stored in the upper - // 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(g & 1) *ptr |= B00000001; // Plane 0 G: bit 0 - if(b & 1) *ptr |= B00000010; // Plane 0 B: bit 0 + // Data for the lower half of the display is stored in the upper bits, except for the plane 0 stuff, using 2 least bits. + ptr = &matrixbuff[backindex][(y-nRows)*_rawWidth*(nPlanes-1) + x]; + *ptr &= ~(_BV(0)|_BV(1)); // Plane 0 G,B mask out in one op + if(r & 1) ptr[32] |= _BV(1); // Plane 0 R: 32 bytes ahead, bit 1 + else ptr[32] &= ~_BV(2); // Plane 0 R unset; mask out + if(g & 1) *ptr |= _BV(0); // Plane 0 G: bit 0 + if(b & 1) *ptr |= _BV(1); // Plane 0 B: bit 0 for(; bit < limit; bit <<= 1) { - *ptr &= ~B11100000; // Mask out R,G,B in one op - if(r & bit) *ptr |= B00100000; // Plane N R: bit 5 - if(g & bit) *ptr |= B01000000; // Plane N G: bit 6 - if(b & bit) *ptr |= B10000000; // Plane N B: bit 7 - ptr += WIDTH; // Advance to next bit plane + *ptr &= ~(_BV(5)|_BV(6)|_BV(7)); // Mask out R,G,B in one op + if(r & bit) *ptr |= _BV(5); // Plane N R: bit 5 + if(g & bit) *ptr |= _BV(6); // Plane N G: bit 6 + if(b & bit) *ptr |= _BV(7); // Plane N B: bit 7 + ptr += _rawWidth; // Advance to next bit plane } } } @@ -324,11 +293,12 @@ // draw over every pixel. (No effect if double-buffering is not enabled.) void RGBmatrixPanel::swapBuffers(bool copy) { + log_debug("call swapBuffers %s",copy?"TRUE":"FALSE"); if(matrixbuff[0] != matrixbuff[1]) { // To avoid 'tearing' display, actual swap takes place in the interrupt // handler, at the end of a complete screen refresh cycle. swapflag = true; // Set flag here, then... - while(swapflag == true) delay(1); // wait for interrupt to clear it + while(swapflag == true) wait_ms(1); // wait for interrupt to clear it if(copy == true) memcpy(matrixbuff[backindex], matrixbuff[1-backindex], 32 * nRows * 3); } @@ -341,33 +311,30 @@ // back into the display using a pgm_read_byte() loop. void RGBmatrixPanel::dumpMatrix(void) { - - int i, buffsize = 32 * nRows * 3; - - Serial.print("\n\n" - "#include <avr/pgmspace.h>\n\n" - "static const uint8_t PROGMEM img[] = {\n "); - + log_debug("call dumpMatrix%s","\r\n"); + int i, buffsize=32*nRows*3; for(i=0; i<buffsize; i++) { - Serial.print("0x"); - if(matrixbuff[backindex][i] < 0x10) Serial.print('0'); - Serial.print(matrixbuff[backindex][i],HEX); + if(i%(32*nRows)==0) { + log_debug("-%s","\r\n"); + } + log_debug("0x%c",'\0'); + log_debug("%02X",matrixbuff[backindex][i]); if(i < (buffsize - 1)) { - if((i & 7) == 7) Serial.print(",\n "); - else Serial.print(','); + if((i & 7) == 7) log_debug(",\r\n"); + else log_debug(","); } } - Serial.println("\n};"); + log_debug("\n};%s","\r\n"); } // -------------------- Interrupt handler stuff -------------------- - +/* ISR(TIMER1_OVF_vect, ISR_BLOCK) // ISR_BLOCK important -- see notes later { activePanel->updateDisplay(); // Call refresh func for active display TIFR1 |= TOV1; // Clear Timer1 interrupt flag } - +*/ // Two constants are used in timing each successive BCM interval. // These were found empirically, by checking the value of TCNT1 at // certain positions in the interrupt code. @@ -415,6 +382,7 @@ void RGBmatrixPanel::updateDisplay(void) { + /* uint8_t i, tick, tock, *ptr; uint16_t t, duration; @@ -492,7 +460,7 @@ // 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 -#define pew asm volatile( \ + #define pew asm volatile( \ "ld __tmp_reg__, %a[ptr]+" "\n\t" \ "out %[data] , __tmp_reg__" "\n\t" \ "out %[clk] , %[tick]" "\n\t" \ @@ -531,4 +499,5 @@ SCLKPORT = tock; // Clock hi } } + */ }
--- a/RGBmatrixPanel.h Sat May 24 08:38:23 2014 +0000 +++ b/RGBmatrixPanel.h Sat May 24 11:43:34 2014 +0000 @@ -1,15 +1,27 @@ #include "mbed.h" #include "Adafruit_GFX.h" +#ifndef _BV +#define _BV(bit) (1<<(bit)) +#endif + + +#ifdef DEBUG +#define log_debug(format, ...) std::printf(format, ## __VA_ARGS__) +#else +#define log_debug(...) +#endif + + class RGBmatrixPanel : public Adafruit_GFX { public: // Constructor for 16x32 panel: - RGBmatrixPanel(uint8_t a, uint8_t b, uint8_t c, uint8_t sclk, uint8_t latch, uint8_t oe, bool dbuf); + RGBmatrixPanel(PinName a, PinName b, PinName c, PinName sclk, PinName latch, PinName oe, bool dbuf); // 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, bool dbuf); + RGBmatrixPanel(PinName a, PinName b, PinName c, PinName d, PinName sclk, PinName latch, PinName oe, bool dbuf); void begin(void); virtual void drawPixel(int16_t x, int16_t y, uint16_t c); @@ -33,12 +45,9 @@ volatile bool 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, bool dbuf); + void init(uint8_t rows, bool dbuf); - // PORT register pointers, pin bitmasks, pin numbers: - volatile uint8_t *latport, *oeport, *addraport, *addrbport, *addrcport, *addrdport; - uint8_t sclkpin, latpin, oepin, addrapin, addrbpin, addrcpin, addrdpin; - uint8_t _sclk, _latch, _oe, _a, _b, _c, _d; + DigitalOut _sclk, _latch, _oe, _a, _b, _c, _d; // Counters/pointers for interrupt handler: volatile uint8_t row, plane;