Adafruit-RGB_matrix_Panel(32*16)

Dependencies:   Adafruit-GFX

Committer:
lelect
Date:
Sun May 25 12:32:49 2014 +0000
Revision:
10:db4941188812
Parent:
9:349baf041171
Child:
12:e632883f319f
Fix code for debugging

Who changed what in which revision?

UserRevisionLine numberNew contents of line
lelect 2:6136465ffd3a 1 #define DEBUG
lelect 5:1f8409ee8850 2 #undef DEBUG
lelect 0:06d9443a018f 3 #include "RGBmatrixPanel.h"
lelect 0:06d9443a018f 4 #include "gamma.h"
lelect 0:06d9443a018f 5
lelect 0:06d9443a018f 6 #define nPlanes 4
lelect 0:06d9443a018f 7
lelect 0:06d9443a018f 8 // The fact that the display driver interrupt stuff is tied to the
lelect 0:06d9443a018f 9 // singular Timer1 doesn't really take well to object orientation with
lelect 0:06d9443a018f 10 // multiple RGBmatrixPanel instances. The solution at present is to
lelect 0:06d9443a018f 11 // allow instances, but only one is active at any given time, via its
lelect 0:06d9443a018f 12 // begin() method. The implementation is still incomplete in parts;
lelect 0:06d9443a018f 13 // the prior active panel really should be gracefully disabled, and a
lelect 0:06d9443a018f 14 // stop() method should perhaps be added...assuming multiple instances
lelect 0:06d9443a018f 15 // are even an actual need.
lelect 4:0ff6053c4bb2 16 //static RGBmatrixPanel *activePanel = NULL;
lelect 0:06d9443a018f 17
lelect 0:06d9443a018f 18 // Code common to both the 16x32 and 32x32 constructors:
lelect 2:6136465ffd3a 19 void RGBmatrixPanel::init(uint8_t rows, bool dbuf)
lelect 0:06d9443a018f 20 {
lelect 0:06d9443a018f 21 nRows = rows; // Number of multiplexed rows; actual height is 2X this
lelect 0:06d9443a018f 22 // Allocate and initialize matrix buffer:
lelect 3:aa3762e0dfee 23 int buffsize = 32*nRows*3, // x3 = 3 bytes holds 4 planes "packed"
lelect 0:06d9443a018f 24 allocsize = (dbuf == true) ? (buffsize * 2) : buffsize;
lelect 0:06d9443a018f 25 if(NULL == (matrixbuff[0] = (uint8_t *)malloc(allocsize))) return;
lelect 0:06d9443a018f 26 memset(matrixbuff[0], 0, allocsize);
lelect 0:06d9443a018f 27 // If not double-buffered, both buffers then point to the same address:
lelect 0:06d9443a018f 28 matrixbuff[1] = (dbuf == true) ? &matrixbuff[0][buffsize] : matrixbuff[0];
lelect 0:06d9443a018f 29
lelect 0:06d9443a018f 30 plane = nPlanes - 1;
lelect 0:06d9443a018f 31 row = nRows - 1;
lelect 0:06d9443a018f 32 swapflag = false;
lelect 0:06d9443a018f 33 backindex = 0; // Array index of back buffer
lelect 0:06d9443a018f 34 }
lelect 0:06d9443a018f 35
lelect 0:06d9443a018f 36 // Constructor for 16x32 panel:
lelect 9:349baf041171 37 RGBmatrixPanel::RGBmatrixPanel(PinName r1,PinName g1,PinName b1,PinName r2,PinName g2,PinName b2,PinName a,PinName b, PinName c, PinName sclk, PinName latch, PinName oe, bool dbuf)
lelect 2:6136465ffd3a 38 :Adafruit_GFX(32, 16),
lelect 5:1f8409ee8850 39 _dataBus(r1,g1,b1,r2,g2,b2),
lelect 5:1f8409ee8850 40 _rowBus(a,b,c),
lelect 5:1f8409ee8850 41 _d(NC),
lelect 2:6136465ffd3a 42 _sclk(sclk),
lelect 2:6136465ffd3a 43 _latch(latch),
lelect 5:1f8409ee8850 44 _oe(oe)
lelect 0:06d9443a018f 45 {
lelect 2:6136465ffd3a 46 init(8, dbuf);
lelect 0:06d9443a018f 47 }
lelect 9:349baf041171 48 /*
lelect 0:06d9443a018f 49 // Constructor for 32x32 panel:
lelect 3:aa3762e0dfee 50 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)
lelect 2:6136465ffd3a 51 :Adafruit_GFX(32, 32),
lelect 5:1f8409ee8850 52 _dataBus(r1,g1,b1,r2,g2,b2),
lelect 5:1f8409ee8850 53 _rowBus(a,b,c),
lelect 5:1f8409ee8850 54 _d(d),// Init 32x32-specific elements:
lelect 2:6136465ffd3a 55 _sclk(sclk),
lelect 2:6136465ffd3a 56 _latch(latch),
lelect 5:1f8409ee8850 57 _oe(oe)
lelect 0:06d9443a018f 58 {
lelect 2:6136465ffd3a 59 init(16,dbuf);
lelect 0:06d9443a018f 60 }
lelect 9:349baf041171 61 */
lelect 0:06d9443a018f 62 void RGBmatrixPanel::begin(void)
lelect 0:06d9443a018f 63 {
lelect 0:06d9443a018f 64
lelect 0:06d9443a018f 65 backindex = 0; // Back buffer
lelect 0:06d9443a018f 66 buffptr = matrixbuff[1 - backindex]; // -> front buffer
lelect 4:0ff6053c4bb2 67 // activePanel = this; // For interrupt hander
lelect 0:06d9443a018f 68
lelect 3:aa3762e0dfee 69 // Set up Timer for interrupt:
lelect 4:0ff6053c4bb2 70 #ifndef DEBUG
lelect 5:1f8409ee8850 71 _refresh.attach_us(this,(&RGBmatrixPanel::updateDisplay),100); //updateDisplay() called every 1ms
lelect 4:0ff6053c4bb2 72 #else
lelect 5:1f8409ee8850 73 _refresh.attach(this,(&RGBmatrixPanel::updateDisplay),0.5); //updateDisplay() called every 2s
lelect 4:0ff6053c4bb2 74 #endif
lelect 0:06d9443a018f 75 }
lelect 0:06d9443a018f 76
lelect 0:06d9443a018f 77 // Original RGBmatrixPanel library used 3/3/3 color. Later version used
lelect 0:06d9443a018f 78 // 4/4/4. Then Adafruit_GFX (core library used across all Adafruit
lelect 0:06d9443a018f 79 // display devices now) standardized on 5/6/5. The matrix still operates
lelect 0:06d9443a018f 80 // internally on 4/4/4 color, but all the graphics functions are written
lelect 0:06d9443a018f 81 // to expect 5/6/5...the matrix lib will truncate the color components as
lelect 0:06d9443a018f 82 // needed when drawing. These next functions are mostly here for the
lelect 0:06d9443a018f 83 // benefit of older code using one of the original color formats.
lelect 0:06d9443a018f 84
lelect 0:06d9443a018f 85 // Promote 3/3/3 RGB to Adafruit_GFX 5/6/5
lelect 0:06d9443a018f 86 uint16_t RGBmatrixPanel::Color333(uint8_t r, uint8_t g, uint8_t b)
lelect 0:06d9443a018f 87 {
lelect 0:06d9443a018f 88 // RRRrrGGGgggBBBbb
lelect 0:06d9443a018f 89 return ((r & 0x7) << 13) | ((r & 0x6) << 10) |
lelect 0:06d9443a018f 90 ((g & 0x7) << 8) | ((g & 0x7) << 5) |
lelect 0:06d9443a018f 91 ((b & 0x7) << 2) | ((b & 0x6) >> 1);
lelect 0:06d9443a018f 92 }
lelect 0:06d9443a018f 93
lelect 0:06d9443a018f 94 // Promote 4/4/4 RGB to Adafruit_GFX 5/6/5
lelect 0:06d9443a018f 95 uint16_t RGBmatrixPanel::Color444(uint8_t r, uint8_t g, uint8_t b)
lelect 0:06d9443a018f 96 {
lelect 0:06d9443a018f 97 // RRRRrGGGGggBBBBb
lelect 0:06d9443a018f 98 return ((r & 0xF) << 12) | ((r & 0x8) << 8) |
lelect 0:06d9443a018f 99 ((g & 0xF) << 7) | ((g & 0xC) << 3) |
lelect 0:06d9443a018f 100 ((b & 0xF) << 1) | ((b & 0x8) >> 3);
lelect 0:06d9443a018f 101 }
lelect 0:06d9443a018f 102
lelect 0:06d9443a018f 103 // Demote 8/8/8 to Adafruit_GFX 5/6/5
lelect 0:06d9443a018f 104 // If no gamma flag passed, assume linear color
lelect 0:06d9443a018f 105 uint16_t RGBmatrixPanel::Color888(uint8_t r, uint8_t g, uint8_t b)
lelect 0:06d9443a018f 106 {
lelect 0:06d9443a018f 107 return ((r & 0xF8) << 11) | ((g & 0xFC) << 5) | (b >> 3);
lelect 0:06d9443a018f 108 }
lelect 0:06d9443a018f 109
lelect 0:06d9443a018f 110 // 8/8/8 -> gamma -> 5/6/5
lelect 1:0078213d3fa4 111 uint16_t RGBmatrixPanel::Color888(uint8_t r, uint8_t g, uint8_t b, bool gflag)
lelect 0:06d9443a018f 112 {
lelect 0:06d9443a018f 113 if(gflag) { // Gamma-corrected color?
lelect 1:0078213d3fa4 114 r = gamma[r]; // Gamma correction table maps
lelect 1:0078213d3fa4 115 g = gamma[g]; // 8-bit input to 4-bit output
lelect 1:0078213d3fa4 116 b = gamma[b];
lelect 0:06d9443a018f 117 return (r << 12) | ((r & 0x8) << 8) | // 4/4/4 -> 5/6/5
lelect 0:06d9443a018f 118 (g << 7) | ((g & 0xC) << 3) |
lelect 0:06d9443a018f 119 (b << 1) | ( b >> 3);
lelect 0:06d9443a018f 120 } // else linear (uncorrected) color
lelect 0:06d9443a018f 121 return ((r & 0xF8) << 11) | ((g & 0xFC) << 5) | (b >> 3);
lelect 0:06d9443a018f 122 }
lelect 0:06d9443a018f 123
lelect 1:0078213d3fa4 124 uint16_t RGBmatrixPanel::ColorHSV(long hue, uint8_t sat, uint8_t val, bool gflag)
lelect 0:06d9443a018f 125 {
lelect 0:06d9443a018f 126
lelect 0:06d9443a018f 127 uint8_t r, g, b, lo;
lelect 0:06d9443a018f 128 uint16_t s1, v1;
lelect 0:06d9443a018f 129
lelect 0:06d9443a018f 130 // Hue
lelect 0:06d9443a018f 131 hue %= 1536; // -1535 to +1535
lelect 0:06d9443a018f 132 if(hue < 0) hue += 1536; // 0 to +1535
lelect 0:06d9443a018f 133 lo = hue & 255; // Low byte = primary/secondary color mix
lelect 0:06d9443a018f 134 switch(hue >> 8) { // High byte = sextant of colorwheel
lelect 0:06d9443a018f 135 case 0 :
lelect 0:06d9443a018f 136 r = 255 ;
lelect 0:06d9443a018f 137 g = lo ;
lelect 0:06d9443a018f 138 b = 0 ;
lelect 0:06d9443a018f 139 break; // R to Y
lelect 0:06d9443a018f 140 case 1 :
lelect 0:06d9443a018f 141 r = 255 - lo;
lelect 0:06d9443a018f 142 g = 255 ;
lelect 0:06d9443a018f 143 b = 0 ;
lelect 0:06d9443a018f 144 break; // Y to G
lelect 0:06d9443a018f 145 case 2 :
lelect 0:06d9443a018f 146 r = 0 ;
lelect 0:06d9443a018f 147 g = 255 ;
lelect 0:06d9443a018f 148 b = lo ;
lelect 0:06d9443a018f 149 break; // G to C
lelect 0:06d9443a018f 150 case 3 :
lelect 0:06d9443a018f 151 r = 0 ;
lelect 0:06d9443a018f 152 g = 255 - lo;
lelect 0:06d9443a018f 153 b = 255 ;
lelect 0:06d9443a018f 154 break; // C to B
lelect 0:06d9443a018f 155 case 4 :
lelect 0:06d9443a018f 156 r = lo ;
lelect 0:06d9443a018f 157 g = 0 ;
lelect 0:06d9443a018f 158 b = 255 ;
lelect 0:06d9443a018f 159 break; // B to M
lelect 0:06d9443a018f 160 default:
lelect 0:06d9443a018f 161 r = 255 ;
lelect 0:06d9443a018f 162 g = 0 ;
lelect 0:06d9443a018f 163 b = 255 - lo;
lelect 0:06d9443a018f 164 break; // M to R
lelect 0:06d9443a018f 165 }
lelect 0:06d9443a018f 166
lelect 0:06d9443a018f 167 // Saturation: add 1 so range is 1 to 256, allowig a quick shift operation
lelect 0:06d9443a018f 168 // on the result rather than a costly divide, while the type upgrade to int
lelect 0:06d9443a018f 169 // avoids repeated type conversions in both directions.
lelect 0:06d9443a018f 170 s1 = sat + 1;
lelect 0:06d9443a018f 171 r = 255 - (((255 - r) * s1) >> 8);
lelect 0:06d9443a018f 172 g = 255 - (((255 - g) * s1) >> 8);
lelect 0:06d9443a018f 173 b = 255 - (((255 - b) * s1) >> 8);
lelect 0:06d9443a018f 174
lelect 0:06d9443a018f 175 // Value (brightness) & 16-bit color reduction: similar to above, add 1
lelect 0:06d9443a018f 176 // to allow shifts, and upgrade to int makes other conversions implicit.
lelect 0:06d9443a018f 177 v1 = val + 1;
lelect 0:06d9443a018f 178 if(gflag) { // Gamma-corrected color?
lelect 2:6136465ffd3a 179 r = gamma[(r * v1) >> 8]; // Gamma correction table maps
lelect 2:6136465ffd3a 180 g = gamma[(g * v1) >> 8]; // 8-bit input to 4-bit output
lelect 2:6136465ffd3a 181 b = gamma[(b * v1) >> 8];
lelect 2:6136465ffd3a 182 //before pgm_read_byte(&gamma[(b * v1) >> 8])
lelect 0:06d9443a018f 183 } else { // linear (uncorrected) color
lelect 0:06d9443a018f 184 r = (r * v1) >> 12; // 4-bit results
lelect 0:06d9443a018f 185 g = (g * v1) >> 12;
lelect 0:06d9443a018f 186 b = (b * v1) >> 12;
lelect 0:06d9443a018f 187 }
lelect 0:06d9443a018f 188 return (r << 12) | ((r & 0x8) << 8) | // 4/4/4 -> 5/6/5
lelect 0:06d9443a018f 189 (g << 7) | ((g & 0xC) << 3) |
lelect 0:06d9443a018f 190 (b << 1) | ( b >> 3);
lelect 0:06d9443a018f 191 }
lelect 0:06d9443a018f 192
lelect 0:06d9443a018f 193 void RGBmatrixPanel::drawPixel(int16_t x, int16_t y, uint16_t c)
lelect 0:06d9443a018f 194 {
lelect 0:06d9443a018f 195 uint8_t r, g, b, bit, limit, *ptr;
lelect 0:06d9443a018f 196 if((x < 0) || (x >= _width) || (y < 0) || (y >= _height)) return;
lelect 0:06d9443a018f 197 switch(rotation) {
lelect 0:06d9443a018f 198 case 1:
lelect 0:06d9443a018f 199 swap(x, y);
lelect 0:06d9443a018f 200 x = _rawWidth - 1 - x;
lelect 0:06d9443a018f 201 break;
lelect 0:06d9443a018f 202 case 2:
lelect 0:06d9443a018f 203 x = _rawWidth - 1 - x;
lelect 0:06d9443a018f 204 y = _rawHeight - 1 - y;
lelect 0:06d9443a018f 205 break;
lelect 0:06d9443a018f 206 case 3:
lelect 0:06d9443a018f 207 swap(x, y);
lelect 0:06d9443a018f 208 y = _rawHeight - 1 - y;
lelect 0:06d9443a018f 209 break;
lelect 0:06d9443a018f 210 }
lelect 0:06d9443a018f 211
lelect 0:06d9443a018f 212 // Adafruit_GFX uses 16-bit color in 5/6/5 format, while matrix needs
lelect 0:06d9443a018f 213 // 4/4/4. Pluck out relevant bits while separating into R,G,B:
lelect 0:06d9443a018f 214 r = c >> 12; // RRRRrggggggbbbbb
lelect 0:06d9443a018f 215 g = (c >> 7) & 0xF; // rrrrrGGGGggbbbbb
lelect 0:06d9443a018f 216 b = (c >> 1) & 0xF; // rrrrrggggggBBBBb
lelect 0:06d9443a018f 217 // Loop counter stuff
lelect 4:0ff6053c4bb2 218 //log_debug("(%X, %X, %X)@(%d,%d)%s",r,g,b,x,y,"\t");
lelect 0:06d9443a018f 219 bit = 2;
lelect 0:06d9443a018f 220 limit = 1 << nPlanes;
lelect 0:06d9443a018f 221
lelect 0:06d9443a018f 222 if(y < nRows) {
lelect 2:6136465ffd3a 223 // Data for the upper half of the display is stored in the lower bits of each byte.
lelect 2:6136465ffd3a 224 ptr = &matrixbuff[backindex][y*_rawWidth*(nPlanes-1) + x]; // Base addr
lelect 4:0ff6053c4bb2 225 // Plane 0 is a tricky case -- its data is spread about, stored in least two bits not used by the other planes.
lelect 4:0ff6053c4bb2 226 ptr[64] &= ~(_BV(1)|_BV(0)); // Plane 0 R,G mask(0b11111100) out in one op
lelect 2:6136465ffd3a 227 if(r & 1) ptr[64] |= _BV(0); // Plane 0 R: 64 bytes ahead, bit 0
lelect 2:6136465ffd3a 228 if(g & 1) ptr[64] |= _BV(1); // Plane 0 G: 64 bytes ahead, bit 1
lelect 2:6136465ffd3a 229 if(b & 1) ptr[32] |= _BV(0); // Plane 0 B: 32 bytes ahead, bit 0
lelect 2:6136465ffd3a 230 else ptr[32] &= ~_BV(0); // Plane 0 B unset; mask out
lelect 0:06d9443a018f 231 // The remaining three image planes are more normal-ish.
lelect 0:06d9443a018f 232 // Data is stored in the high 6 bits so it can be quickly
lelect 0:06d9443a018f 233 // copied to the DATAPORT register w/6 output lines.
lelect 0:06d9443a018f 234 for(; bit < limit; bit <<= 1) {
lelect 5:1f8409ee8850 235 *ptr &= ~(_BV(4)|_BV(3)|_BV(2)) ; // Mask(0b11100011) out R,G,B in one op
lelect 4:0ff6053c4bb2 236 if(r & bit) *ptr |= _BV(2); // Plane N R: bit 2
lelect 4:0ff6053c4bb2 237 if(g & bit) *ptr |= _BV(3); // Plane N G: bit 3
lelect 4:0ff6053c4bb2 238 if(b & bit) *ptr |= _BV(4); // Plane N B: bit 4
lelect 4:0ff6053c4bb2 239 ptr += _rawWidth; // Advance to next bit plane
lelect 0:06d9443a018f 240 }
lelect 0:06d9443a018f 241 } else {
lelect 2:6136465ffd3a 242 // Data for the lower half of the display is stored in the upper bits, except for the plane 0 stuff, using 2 least bits.
lelect 2:6136465ffd3a 243 ptr = &matrixbuff[backindex][(y-nRows)*_rawWidth*(nPlanes-1) + x];
lelect 4:0ff6053c4bb2 244 *ptr &= ~(_BV(1)|_BV(0)); // Plane 0 G,B mask out in one op
lelect 2:6136465ffd3a 245 if(r & 1) ptr[32] |= _BV(1); // Plane 0 R: 32 bytes ahead, bit 1
lelect 4:0ff6053c4bb2 246 else ptr[32] &= ~_BV(1); // Plane 0 R unset; mask out
lelect 2:6136465ffd3a 247 if(g & 1) *ptr |= _BV(0); // Plane 0 G: bit 0
lelect 2:6136465ffd3a 248 if(b & 1) *ptr |= _BV(1); // Plane 0 B: bit 0
lelect 0:06d9443a018f 249 for(; bit < limit; bit <<= 1) {
lelect 4:0ff6053c4bb2 250 *ptr &= ~(_BV(7)|_BV(6)|_BV(5)); // Mask out R,G,B in one op
lelect 2:6136465ffd3a 251 if(r & bit) *ptr |= _BV(5); // Plane N R: bit 5
lelect 2:6136465ffd3a 252 if(g & bit) *ptr |= _BV(6); // Plane N G: bit 6
lelect 2:6136465ffd3a 253 if(b & bit) *ptr |= _BV(7); // Plane N B: bit 7
lelect 2:6136465ffd3a 254 ptr += _rawWidth; // Advance to next bit plane
lelect 0:06d9443a018f 255 }
lelect 0:06d9443a018f 256 }
lelect 0:06d9443a018f 257 }
lelect 0:06d9443a018f 258
lelect 0:06d9443a018f 259 void RGBmatrixPanel::fillScreen(uint16_t c)
lelect 0:06d9443a018f 260 {
lelect 0:06d9443a018f 261 if((c == 0x0000) || (c == 0xffff)) {
lelect 0:06d9443a018f 262 // For black or white, all bits in frame buffer will be identically
lelect 0:06d9443a018f 263 // set or unset (regardless of weird bit packing), so it's OK to just
lelect 0:06d9443a018f 264 // quickly memset the whole thing:
lelect 0:06d9443a018f 265 memset(matrixbuff[backindex], c, 32 * nRows * 3);
lelect 0:06d9443a018f 266 } else {
lelect 0:06d9443a018f 267 // Otherwise, need to handle it the long way:
lelect 0:06d9443a018f 268 Adafruit_GFX::fillScreen(c);
lelect 0:06d9443a018f 269 }
lelect 0:06d9443a018f 270 }
lelect 0:06d9443a018f 271
lelect 0:06d9443a018f 272 // Return address of back buffer -- can then load/store data directly
lelect 0:06d9443a018f 273 uint8_t *RGBmatrixPanel::backBuffer()
lelect 0:06d9443a018f 274 {
lelect 0:06d9443a018f 275 return matrixbuff[backindex];
lelect 0:06d9443a018f 276 }
lelect 0:06d9443a018f 277
lelect 0:06d9443a018f 278 // For smooth animation -- drawing always takes place in the "back" buffer;
lelect 0:06d9443a018f 279 // this method pushes it to the "front" for display. Passing "true", the
lelect 0:06d9443a018f 280 // updated display contents are then copied to the new back buffer and can
lelect 0:06d9443a018f 281 // be incrementally modified. If "false", the back buffer then contains
lelect 0:06d9443a018f 282 // the old front buffer contents -- your code can either clear this or
lelect 0:06d9443a018f 283 // draw over every pixel. (No effect if double-buffering is not enabled.)
lelect 0:06d9443a018f 284 void RGBmatrixPanel::swapBuffers(bool copy)
lelect 0:06d9443a018f 285 {
lelect 4:0ff6053c4bb2 286 log_debug("\r\ncall swapBuffers %s","\r\n");
lelect 0:06d9443a018f 287 if(matrixbuff[0] != matrixbuff[1]) {
lelect 0:06d9443a018f 288 // To avoid 'tearing' display, actual swap takes place in the interrupt
lelect 0:06d9443a018f 289 // handler, at the end of a complete screen refresh cycle.
lelect 0:06d9443a018f 290 swapflag = true; // Set flag here, then...
lelect 2:6136465ffd3a 291 while(swapflag == true) wait_ms(1); // wait for interrupt to clear it
lelect 3:aa3762e0dfee 292 if(copy == true) {
lelect 3:aa3762e0dfee 293 log_debug("\tmemcpy %s","\r\n");
lelect 0:06d9443a018f 294 memcpy(matrixbuff[backindex], matrixbuff[1-backindex], 32 * nRows * 3);
lelect 3:aa3762e0dfee 295 } else {
lelect 3:aa3762e0dfee 296 log_debug("\tnot memcpy %s","\r\n");
lelect 3:aa3762e0dfee 297 }
lelect 0:06d9443a018f 298 }
lelect 0:06d9443a018f 299 }
lelect 0:06d9443a018f 300
lelect 0:06d9443a018f 301 // Dump display contents to the Serial Monitor, adding some formatting to
lelect 0:06d9443a018f 302 // simplify copy-and-paste of data as a PROGMEM-embedded image for another
lelect 0:06d9443a018f 303 // sketch. If using multiple dumps this way, you'll need to edit the
lelect 0:06d9443a018f 304 // output to change the 'img' name for each. Data can then be loaded
lelect 0:06d9443a018f 305 // back into the display using a pgm_read_byte() loop.
lelect 0:06d9443a018f 306 void RGBmatrixPanel::dumpMatrix(void)
lelect 0:06d9443a018f 307 {
lelect 4:0ff6053c4bb2 308 #ifdef DEBUG
lelect 4:0ff6053c4bb2 309 log_debug("\r\ncall dumpMatrix%s","\r\n");
lelect 3:aa3762e0dfee 310 int buffsize=32*nRows*3;
lelect 3:aa3762e0dfee 311 for(int item=0; item<buffsize; item++) {
lelect 3:aa3762e0dfee 312 log_debug("0x%02X",matrixbuff[backindex][item]);
lelect 3:aa3762e0dfee 313 if((item%32)==31) log_debug(",\r\n");
lelect 3:aa3762e0dfee 314 else log_debug(",");
lelect 0:06d9443a018f 315 }
lelect 4:0ff6053c4bb2 316 log_debug("%s","\r\n\r\n");
lelect 4:0ff6053c4bb2 317 #endif
lelect 0:06d9443a018f 318
lelect 0:06d9443a018f 319 }
lelect 0:06d9443a018f 320
lelect 0:06d9443a018f 321 void RGBmatrixPanel::updateDisplay(void)
lelect 0:06d9443a018f 322 {
lelect 5:1f8409ee8850 323 uint8_t *ptr;
lelect 4:0ff6053c4bb2 324 log_debug("\r\ncall updateDisplay\r\n");
lelect 3:aa3762e0dfee 325 _oe=1;
lelect 3:aa3762e0dfee 326 _latch=1;
lelect 3:aa3762e0dfee 327 if(++plane >= nPlanes) { // Advance plane counter. Maxed out?
lelect 0:06d9443a018f 328 plane = 0; // Yes, reset to plane 0, and
lelect 0:06d9443a018f 329 if(++row >= nRows) { // advance row counter. Maxed out?
lelect 3:aa3762e0dfee 330 row= 0; // Yes, reset row counter, then...
lelect 3:aa3762e0dfee 331 if(swapflag == true) { // Swap front/back buffers if requested
lelect 0:06d9443a018f 332 backindex = 1 - backindex;
lelect 3:aa3762e0dfee 333 log_debug("\t\treset swapflag%s","\r\n");
lelect 0:06d9443a018f 334 swapflag = false;
lelect 0:06d9443a018f 335 }
lelect 3:aa3762e0dfee 336 log_debug("\tReset into front buffer[%d]%s",backindex,"\r\n");
lelect 0:06d9443a018f 337 buffptr = matrixbuff[1-backindex]; // Reset into front buffer
lelect 0:06d9443a018f 338 }
lelect 0:06d9443a018f 339 } else if(plane == 1) {
lelect 4:0ff6053c4bb2 340 log_debug("\tupdate row%s","\r\n");
lelect 5:1f8409ee8850 341 _rowBus.write(row);
lelect 0:06d9443a018f 342 }
lelect 3:aa3762e0dfee 343 _oe=0;
lelect 3:aa3762e0dfee 344 _latch=0;
lelect 5:1f8409ee8850 345 ptr = (uint8_t *)buffptr;
lelect 5:1f8409ee8850 346
lelect 4:0ff6053c4bb2 347 log_debug("\t(row@plane)=(%d,%d)\r\n",row,plane);
lelect 4:0ff6053c4bb2 348 if(plane > 0) {
lelect 5:1f8409ee8850 349 //ptr[i]>>2
lelect 3:aa3762e0dfee 350 for(int i=0; i<32; i++) {
lelect 10:db4941188812 351 _dataBus.write((*(ptr+i)>>2));
lelect 3:aa3762e0dfee 352 _sclk=1;
lelect 3:aa3762e0dfee 353 _sclk=0;
lelect 10:db4941188812 354 #if 0
lelect 4:0ff6053c4bb2 355 #ifdef DEBUG
lelect 4:0ff6053c4bb2 356 if(int(_dataBus)==color) {
lelect 4:0ff6053c4bb2 357 log_debug(" %02x",int(_dataBus));
lelect 4:0ff6053c4bb2 358 } else {
lelect 4:0ff6053c4bb2 359 _dataBus=color;
lelect 4:0ff6053c4bb2 360 log_debug(" (%x->%x)%s",color,int(_dataBus),"\0");
lelect 4:0ff6053c4bb2 361 }
lelect 4:0ff6053c4bb2 362 #endif
lelect 10:db4941188812 363 #endif
lelect 3:aa3762e0dfee 364 }
lelect 4:0ff6053c4bb2 365 buffptr += _rawWidth;
lelect 3:aa3762e0dfee 366 } else {
lelect 5:1f8409ee8850 367 //((ptr[i]<<4)|((ptr[i+32]<<2)&0x0C)|((ptr[i+64])&0x03));
lelect 3:aa3762e0dfee 368 for(int i=0; i<32; i++) {
lelect 10:db4941188812 369 _dataBus.write(((ptr[i]<<4)|((ptr[i+32]<<2)&0x0C)|((ptr[i+64])&0x03)));
lelect 3:aa3762e0dfee 370 _sclk=1;
lelect 3:aa3762e0dfee 371 _sclk=0;
lelect 10:db4941188812 372 #if 0
lelect 4:0ff6053c4bb2 373 #ifdef DEBUG
lelect 4:0ff6053c4bb2 374 if(int(_dataBus)==color) {
lelect 4:0ff6053c4bb2 375 log_debug(" %02x",int(_dataBus));
lelect 4:0ff6053c4bb2 376 } else {
lelect 4:0ff6053c4bb2 377 _dataBus=color;
lelect 4:0ff6053c4bb2 378 log_debug(" (%x->%x)%s",color,int(_dataBus),"\0");
lelect 4:0ff6053c4bb2 379 }
lelect 4:0ff6053c4bb2 380 #endif
lelect 10:db4941188812 381 #endif
lelect 0:06d9443a018f 382 }
lelect 0:06d9443a018f 383 }
lelect 5:1f8409ee8850 384
lelect 0:06d9443a018f 385 }
lelect 4:0ff6053c4bb2 386