Adafruit-RGB_matrix_Panel(32*16)

Dependencies:   Adafruit-GFX

Revision:
3:aa3762e0dfee
Parent:
2:6136465ffd3a
Child:
4:0ff6053c4bb2
--- a/RGBmatrixPanel.cpp	Sat May 24 11:43:34 2014 +0000
+++ b/RGBmatrixPanel.cpp	Sat May 24 17:33:23 2014 +0000
@@ -1,4 +1,5 @@
 #define DEBUG
+#undef DEBUG
 #include "RGBmatrixPanel.h"
 #include "gamma.h"
 
@@ -19,7 +20,7 @@
 {
     nRows = rows; // Number of multiplexed rows; actual height is 2X this
     // Allocate and initialize matrix buffer:
-    int buffsize  = 32 * nRows * 3, // x3 = 3 bytes holds 4 planes "packed"
+    int buffsize  = 32*nRows*3, // 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);
@@ -33,29 +34,27 @@
 }
 
 // Constructor for 16x32 panel:
-RGBmatrixPanel::RGBmatrixPanel(PinName a, PinName b, PinName c, PinName sclk, PinName latch, PinName oe, bool dbuf)
+RGBmatrixPanel::RGBmatrixPanel(PinName r1,PinName r2,PinName g1,PinName g2,PinName b1,PinName b2,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)
+     _d(NC),
+     _dataBus(r1,g1,b1,r2,g2,b2),
+     _rowBus(c,b,a)
 {
     init(8, dbuf);
 }
 
 // Constructor for 32x32 panel:
-RGBmatrixPanel::RGBmatrixPanel(PinName a, PinName b, PinName c, PinName d, PinName sclk, PinName latch, PinName oe, bool dbuf)
+RGBmatrixPanel::RGBmatrixPanel(PinName r1,PinName r2,PinName g1,PinName g2,PinName b1,PinName b2,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:
+     _d(d),// Init 32x32-specific elements:
+     _dataBus(r1,g1,b1,r2,g2,b2),
+     _rowBus(c,b,a)
 {
     init(16,dbuf);
 }
@@ -74,14 +73,15 @@
     DATAPORT = 0;
     */
 
-    // Set up Timer1 for interrupt:
+    // Set up Timer for interrupt:
+    _refresh.attach(activePanel,(&RGBmatrixPanel::updateDisplay),0.001);   //updateDisplay() called every 1ms
     /*
-    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
-    */
+     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
@@ -242,7 +242,7 @@
         // 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[0] &= ~(_BV(2)|_BV(3)|_BV(4));             // Mask(0b0001110) out R,G,B in one op
+            ptr[0] &= ~(_BV(2)|_BV(3)|_BV(4));             // Mask(0b00011100) 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
@@ -293,14 +293,18 @@
 // 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");
+    log_debug("call swapBuffers %s","\r\n");
     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) wait_ms(1); // wait for interrupt to clear it
-        if(copy == true)
+        if(copy == true) {
+            log_debug("\tmemcpy %s","\r\n");
             memcpy(matrixbuff[backindex], matrixbuff[1-backindex], 32 * nRows * 3);
+        } else {
+            log_debug("\tnot memcpy %s","\r\n");
+        }
     }
 }
 
@@ -312,19 +316,19 @@
 void RGBmatrixPanel::dumpMatrix(void)
 {
     log_debug("call dumpMatrix%s","\r\n");
-    int i, buffsize=32*nRows*3;
-    for(i=0; i<buffsize; i++) {
-        if(i%(32*nRows)==0) {
+    int buffsize=32*nRows*3;
+    for(int item=0; item<buffsize; item++) {
+        if(item%(32*nRows)==0) {
+            for(int i=0; i<32*5; i++) {
+                log_debug("-%c",'\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)    log_debug(",\r\n");
-            else                log_debug(",");
-        }
+        log_debug("0x%02X",matrixbuff[backindex][item]);
+        if((item%32)==31)    log_debug(",\r\n");
+        else                log_debug(",");
     }
-    log_debug("\n};%s","\r\n");
+    log_debug("%s","\r\n");
 }
 
 // -------------------- Interrupt handler stuff --------------------
@@ -382,41 +386,25 @@
 
 void RGBmatrixPanel::updateDisplay(void)
 {
-    /*
-    uint8_t  i, tick, tock, *ptr;
-    uint16_t t, duration;
-
-    *oeport  |= oepin;  // Disable LED output during row/plane switchover
-    *latport |= latpin; // Latch data loaded during *prior* interrupt
-
-    // Calculate time to next interrupt BEFORE incrementing plane #.
-    // This is because duration is the display time for the data loaded
-    // on the PRIOR interrupt.  CALLOVERHEAD is subtracted from the
-    // result because that time is implicit between the timer overflow
-    // (interrupt triggered) and the initial LEDs-off line at the start
-    // of this method.
-    t = (nRows > 8) ? LOOPTIME : (LOOPTIME * 2);
-    duration = ((t + CALLOVERHEAD * 2) << plane) - CALLOVERHEAD;
-
-    // Borrowing a technique here from Ray's Logic:
-    // www.rayslogic.com/propeller/Programming/AdafruitRGB/AdafruitRGB.htm
-    // This code cycles through all four planes for each scanline before
-    // advancing to the next line.  While it might seem beneficial to
-    // advance lines every time and interleave the planes to reduce
-    // vertical scanning artifacts, in practice with this panel it causes
-    // a green 'ghosting' effect on black pixels, a much worse artifact.
-
-    if(++plane >= nPlanes) {      // Advance plane counter.  Maxed out?
+    //log_debug("call updateDisplay\t(plane,row)=(%d,%d)\r\n",plane,row);
+    _oe=1;
+    _latch=1;
+    if(++plane >= nPlanes) {        // Advance plane counter.  Maxed out?
         plane = 0;                  // Yes, reset to plane 0, and
         if(++row >= nRows) {        // advance row counter.  Maxed out?
-            row     = 0;              // Yes, reset row counter, then...
-            if(swapflag == true) {    // Swap front/back buffers if requested
+            row= 0;                 // Yes, reset row counter, then...
+            if(swapflag == true) {  // Swap front/back buffers if requested
                 backindex = 1 - backindex;
+                log_debug("\t\treset swapflag%s","\r\n");
                 swapflag  = false;
             }
+            log_debug("\tReset into front buffer[%d]%s",backindex,"\r\n");
             buffptr = matrixbuff[1-backindex]; // Reset into front buffer
         }
     } else if(plane == 1) {
+        log_debug("\r\n\tset row@(%d,%d)\r\n",plane,row);
+
+        /*
         // Plane 0 was loaded on prior interrupt invocation and is about to
         // latch now, so update the row address lines before we do that:
         if(row & 0x1)   *addraport |=  addrapin;
@@ -429,58 +417,40 @@
             if(row & 0x8) *addrdport |=  addrdpin;
             else          *addrdport &= ~addrdpin;
         }
+        */
     }
-
+    _rowBus=row;
+    _oe=0;
+    _latch=0;
     // buffptr, being 'volatile' type, doesn't take well to optimization.
     // A local register copy can speed some things up:
-    ptr = (uint8_t *)buffptr;
-
-    ICR1      = duration; // Set interval for next interrupt
-    TCNT1     = 0;        // Restart interrupt timer
-    *oeport  &= ~oepin;   // Re-enable output
-    *latport &= ~latpin;  // Latch down
-
-    // Record current state of SCLKPORT register, as well as a second
-    // copy with the clock bit set.  This makes the innnermost data-
-    // pushing loops faster, as they can just set the PORT state and
-    // not have to load/modify/store bits every single time.  It's a
-    // somewhat rude trick that ONLY works because the interrupt
-    // handler is set ISR_BLOCK, halting any other interrupts that
-    // might otherwise also be twiddling the port at the same time
-    // (else this would clobber them).
-    tock = SCLKPORT;
-    tick = tock | sclkpin;
-
-    if(plane > 0) { // 188 ticks from TCNT1=0 (above) to end of function
-
-        // Planes 1-3 copy bytes directly from RAM to PORT without unpacking.
-        // The least 2 bits (used for plane 0 data) are presumed masked out
-        // by the port direction bits.
+    uint8_t *ptr = (uint8_t *)buffptr;
+    /*
+            ICR1      = duration; // Set interval for next interrupt
+            TCNT1     = 0;        // Restart interrupt timer
+            *oeport  &= ~oepin;   // Re-enable output
+            *latport &= ~latpin;  // Latch down
 
-        // 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(                 \
-      "ld  __tmp_reg__, %a[ptr]+"    "\n\t"   \
-      "out %[data]    , __tmp_reg__" "\n\t"   \
-      "out %[clk]     , %[tick]"     "\n\t"   \
-      "out %[clk]     , %[tock]"     "\n"     \
-      :: [ptr]  "e" (ptr),                    \
-         [data] "I" (_SFR_IO_ADDR(DATAPORT)), \
-         [clk]  "I" (_SFR_IO_ADDR(SCLKPORT)), \
-         [tick] "r" (tick),                   \
-         [tock] "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
-
+            // Record current state of SCLKPORT register, as well as a second
+            // copy with the clock bit set.  This makes the innnermost data-
+            // pushing loops faster, as they can just set the PORT state and
+            // not have to load/modify/store bits every single time.  It's a
+            // somewhat rude trick that ONLY works because the interrupt
+            // handler is set ISR_BLOCK, halting any other interrupts that
+            // might otherwise also be twiddling the port at the same time
+            // (else this would clobber them).
+            tock = SCLKPORT;
+            tick = tock | sclkpin;
+    */
+    if(plane > 0) { // 188 ticks from TCNT1=0 (above) to end of function
+        for(int i=0; i<32; i++) {
+            _dataBus=(ptr[i] << 6) | ((ptr[i+32] << 4)&0x30) | ((ptr[i+64] << 2)&0x0C)>>2;
+            _sclk=1;
+            _sclk=0;
+        }
         buffptr += 32;
-
-    } else { // 920 ticks from TCNT1=0 (above) to end of function
-
+    } else {
+        // 920 ticks from TCNT1=0 (above) to end of function
         // Planes 1-3 (handled above) formatted their data "in place,"
         // their layout matching that out the output PORT register (where
         // 6 bits correspond to output data lines), maximizing throughput
@@ -490,14 +460,12 @@
         // 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++) {
-            DATAPORT =
-                ( ptr[i]    << 6)         |
-                ((ptr[i+32] << 4) & 0x30) |
-                ((ptr[i+64] << 2) & 0x0C);
-            SCLKPORT = tick; // Clock lo
-            SCLKPORT = tock; // Clock hi
+        for(int i=0; i<32; i++) {
+            _dataBus=(ptr[i] << 6) | ((ptr[i+32] << 4)&0x30) | ((ptr[i+64] << 2)&0x0C)>>2;
+            _sclk=1;
+            _sclk=0;
+            log_debug("\t\t %02x@(%d,%d)",_dataBus.read(),plane,row);
         }
+        //buffptr += 32;
     }
-    */
 }