Adafruit-RGB_matrix_Panel(32*16)

Dependencies:   Adafruit-GFX

Revision:
2:6136465ffd3a
Parent:
1:0078213d3fa4
Child:
3:aa3762e0dfee
--- 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
         }
     }
+    */
 }