Adafruit-RGB_matrix_Panel(32*16)

Dependencies:   Adafruit-GFX

Committer:
lelect
Date:
Mon May 26 09:14:54 2014 +0000
Revision:
13:0ceb1b8893e9
Parent:
12:e632883f319f
update doxygen

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 12:e632883f319f 192 uint16_t RGBmatrixPanel::ColorHSV(float hue, float sat, float val, bool gflag)
lelect 12:e632883f319f 193 {
lelect 12:e632883f319f 194 int i = floor(hue * 6);
lelect 12:e632883f319f 195 float f = hue*6-i;
lelect 12:e632883f319f 196 float p = val*(1-sat);
lelect 12:e632883f319f 197 float q = val*(1-f*sat);
lelect 12:e632883f319f 198 float t = val*(1-(1-f)*sat);
lelect 12:e632883f319f 199 float r = 0,g=0,b=0;
lelect 12:e632883f319f 200 switch(i % 6) {
lelect 12:e632883f319f 201 case 0:
lelect 12:e632883f319f 202 r = val;
lelect 12:e632883f319f 203 g = t;
lelect 12:e632883f319f 204 b = p;
lelect 12:e632883f319f 205 break;
lelect 12:e632883f319f 206 case 1:
lelect 12:e632883f319f 207 r = q;
lelect 12:e632883f319f 208 g = val;
lelect 12:e632883f319f 209 b = p;
lelect 12:e632883f319f 210 break;
lelect 12:e632883f319f 211 case 2:
lelect 12:e632883f319f 212 r = p;
lelect 12:e632883f319f 213 g = val;
lelect 12:e632883f319f 214 b = t;
lelect 12:e632883f319f 215 break;
lelect 12:e632883f319f 216 case 3:
lelect 12:e632883f319f 217 r = p;
lelect 12:e632883f319f 218 g = q;
lelect 12:e632883f319f 219 b = val;
lelect 12:e632883f319f 220 break;
lelect 12:e632883f319f 221 case 4:
lelect 12:e632883f319f 222 r = t;
lelect 12:e632883f319f 223 g = p;
lelect 12:e632883f319f 224 b = val;
lelect 12:e632883f319f 225 break;
lelect 12:e632883f319f 226 case 5:
lelect 12:e632883f319f 227 r = val;
lelect 12:e632883f319f 228 g = p;
lelect 12:e632883f319f 229 b = q;
lelect 12:e632883f319f 230 break;
lelect 12:e632883f319f 231 }
lelect 12:e632883f319f 232 return Color888(r*255,g*255,b*255,gflag);
lelect 12:e632883f319f 233 }
lelect 0:06d9443a018f 234 void RGBmatrixPanel::drawPixel(int16_t x, int16_t y, uint16_t c)
lelect 0:06d9443a018f 235 {
lelect 0:06d9443a018f 236 uint8_t r, g, b, bit, limit, *ptr;
lelect 0:06d9443a018f 237 if((x < 0) || (x >= _width) || (y < 0) || (y >= _height)) return;
lelect 0:06d9443a018f 238 switch(rotation) {
lelect 0:06d9443a018f 239 case 1:
lelect 0:06d9443a018f 240 swap(x, y);
lelect 0:06d9443a018f 241 x = _rawWidth - 1 - x;
lelect 0:06d9443a018f 242 break;
lelect 0:06d9443a018f 243 case 2:
lelect 0:06d9443a018f 244 x = _rawWidth - 1 - x;
lelect 0:06d9443a018f 245 y = _rawHeight - 1 - y;
lelect 0:06d9443a018f 246 break;
lelect 0:06d9443a018f 247 case 3:
lelect 0:06d9443a018f 248 swap(x, y);
lelect 0:06d9443a018f 249 y = _rawHeight - 1 - y;
lelect 0:06d9443a018f 250 break;
lelect 0:06d9443a018f 251 }
lelect 0:06d9443a018f 252
lelect 0:06d9443a018f 253 // Adafruit_GFX uses 16-bit color in 5/6/5 format, while matrix needs
lelect 0:06d9443a018f 254 // 4/4/4. Pluck out relevant bits while separating into R,G,B:
lelect 0:06d9443a018f 255 r = c >> 12; // RRRRrggggggbbbbb
lelect 0:06d9443a018f 256 g = (c >> 7) & 0xF; // rrrrrGGGGggbbbbb
lelect 0:06d9443a018f 257 b = (c >> 1) & 0xF; // rrrrrggggggBBBBb
lelect 0:06d9443a018f 258 // Loop counter stuff
lelect 0:06d9443a018f 259 bit = 2;
lelect 0:06d9443a018f 260 limit = 1 << nPlanes;
lelect 0:06d9443a018f 261 if(y < nRows) {
lelect 2:6136465ffd3a 262 // Data for the upper half of the display is stored in the lower bits of each byte.
lelect 2:6136465ffd3a 263 ptr = &matrixbuff[backindex][y*_rawWidth*(nPlanes-1) + x]; // Base addr
lelect 4:0ff6053c4bb2 264 // 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 265 ptr[64] &= ~(_BV(1)|_BV(0)); // Plane 0 R,G mask(0b11111100) out in one op
lelect 2:6136465ffd3a 266 if(r & 1) ptr[64] |= _BV(0); // Plane 0 R: 64 bytes ahead, bit 0
lelect 2:6136465ffd3a 267 if(g & 1) ptr[64] |= _BV(1); // Plane 0 G: 64 bytes ahead, bit 1
lelect 2:6136465ffd3a 268 if(b & 1) ptr[32] |= _BV(0); // Plane 0 B: 32 bytes ahead, bit 0
lelect 2:6136465ffd3a 269 else ptr[32] &= ~_BV(0); // Plane 0 B unset; mask out
lelect 0:06d9443a018f 270 // The remaining three image planes are more normal-ish.
lelect 0:06d9443a018f 271 // Data is stored in the high 6 bits so it can be quickly
lelect 0:06d9443a018f 272 // copied to the DATAPORT register w/6 output lines.
lelect 0:06d9443a018f 273 for(; bit < limit; bit <<= 1) {
lelect 5:1f8409ee8850 274 *ptr &= ~(_BV(4)|_BV(3)|_BV(2)) ; // Mask(0b11100011) out R,G,B in one op
lelect 4:0ff6053c4bb2 275 if(r & bit) *ptr |= _BV(2); // Plane N R: bit 2
lelect 4:0ff6053c4bb2 276 if(g & bit) *ptr |= _BV(3); // Plane N G: bit 3
lelect 4:0ff6053c4bb2 277 if(b & bit) *ptr |= _BV(4); // Plane N B: bit 4
lelect 4:0ff6053c4bb2 278 ptr += _rawWidth; // Advance to next bit plane
lelect 0:06d9443a018f 279 }
lelect 0:06d9443a018f 280 } else {
lelect 2:6136465ffd3a 281 // 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 282 ptr = &matrixbuff[backindex][(y-nRows)*_rawWidth*(nPlanes-1) + x];
lelect 4:0ff6053c4bb2 283 *ptr &= ~(_BV(1)|_BV(0)); // Plane 0 G,B mask out in one op
lelect 2:6136465ffd3a 284 if(r & 1) ptr[32] |= _BV(1); // Plane 0 R: 32 bytes ahead, bit 1
lelect 4:0ff6053c4bb2 285 else ptr[32] &= ~_BV(1); // Plane 0 R unset; mask out
lelect 2:6136465ffd3a 286 if(g & 1) *ptr |= _BV(0); // Plane 0 G: bit 0
lelect 2:6136465ffd3a 287 if(b & 1) *ptr |= _BV(1); // Plane 0 B: bit 0
lelect 0:06d9443a018f 288 for(; bit < limit; bit <<= 1) {
lelect 4:0ff6053c4bb2 289 *ptr &= ~(_BV(7)|_BV(6)|_BV(5)); // Mask out R,G,B in one op
lelect 2:6136465ffd3a 290 if(r & bit) *ptr |= _BV(5); // Plane N R: bit 5
lelect 2:6136465ffd3a 291 if(g & bit) *ptr |= _BV(6); // Plane N G: bit 6
lelect 2:6136465ffd3a 292 if(b & bit) *ptr |= _BV(7); // Plane N B: bit 7
lelect 2:6136465ffd3a 293 ptr += _rawWidth; // Advance to next bit plane
lelect 0:06d9443a018f 294 }
lelect 0:06d9443a018f 295 }
lelect 0:06d9443a018f 296 }
lelect 0:06d9443a018f 297
lelect 0:06d9443a018f 298 void RGBmatrixPanel::fillScreen(uint16_t c)
lelect 0:06d9443a018f 299 {
lelect 0:06d9443a018f 300 if((c == 0x0000) || (c == 0xffff)) {
lelect 0:06d9443a018f 301 // For black or white, all bits in frame buffer will be identically
lelect 0:06d9443a018f 302 // set or unset (regardless of weird bit packing), so it's OK to just
lelect 0:06d9443a018f 303 // quickly memset the whole thing:
lelect 0:06d9443a018f 304 memset(matrixbuff[backindex], c, 32 * nRows * 3);
lelect 0:06d9443a018f 305 } else {
lelect 0:06d9443a018f 306 // Otherwise, need to handle it the long way:
lelect 0:06d9443a018f 307 Adafruit_GFX::fillScreen(c);
lelect 0:06d9443a018f 308 }
lelect 0:06d9443a018f 309 }
lelect 0:06d9443a018f 310
lelect 0:06d9443a018f 311 // Return address of back buffer -- can then load/store data directly
lelect 0:06d9443a018f 312 uint8_t *RGBmatrixPanel::backBuffer()
lelect 0:06d9443a018f 313 {
lelect 0:06d9443a018f 314 return matrixbuff[backindex];
lelect 0:06d9443a018f 315 }
lelect 0:06d9443a018f 316
lelect 0:06d9443a018f 317 // For smooth animation -- drawing always takes place in the "back" buffer;
lelect 0:06d9443a018f 318 // this method pushes it to the "front" for display. Passing "true", the
lelect 0:06d9443a018f 319 // updated display contents are then copied to the new back buffer and can
lelect 0:06d9443a018f 320 // be incrementally modified. If "false", the back buffer then contains
lelect 0:06d9443a018f 321 // the old front buffer contents -- your code can either clear this or
lelect 0:06d9443a018f 322 // draw over every pixel. (No effect if double-buffering is not enabled.)
lelect 0:06d9443a018f 323 void RGBmatrixPanel::swapBuffers(bool copy)
lelect 0:06d9443a018f 324 {
lelect 0:06d9443a018f 325 if(matrixbuff[0] != matrixbuff[1]) {
lelect 0:06d9443a018f 326 // To avoid 'tearing' display, actual swap takes place in the interrupt
lelect 0:06d9443a018f 327 // handler, at the end of a complete screen refresh cycle.
lelect 0:06d9443a018f 328 swapflag = true; // Set flag here, then...
lelect 2:6136465ffd3a 329 while(swapflag == true) wait_ms(1); // wait for interrupt to clear it
lelect 3:aa3762e0dfee 330 if(copy == true) {
lelect 0:06d9443a018f 331 memcpy(matrixbuff[backindex], matrixbuff[1-backindex], 32 * nRows * 3);
lelect 3:aa3762e0dfee 332 }
lelect 0:06d9443a018f 333 }
lelect 0:06d9443a018f 334 }
lelect 0:06d9443a018f 335
lelect 0:06d9443a018f 336 // Dump display contents to the Serial Monitor, adding some formatting to
lelect 0:06d9443a018f 337 // simplify copy-and-paste of data as a PROGMEM-embedded image for another
lelect 0:06d9443a018f 338 // sketch. If using multiple dumps this way, you'll need to edit the
lelect 0:06d9443a018f 339 // output to change the 'img' name for each. Data can then be loaded
lelect 0:06d9443a018f 340 // back into the display using a pgm_read_byte() loop.
lelect 0:06d9443a018f 341 void RGBmatrixPanel::dumpMatrix(void)
lelect 0:06d9443a018f 342 {
lelect 4:0ff6053c4bb2 343 #ifdef DEBUG
lelect 4:0ff6053c4bb2 344 log_debug("\r\ncall dumpMatrix%s","\r\n");
lelect 3:aa3762e0dfee 345 int buffsize=32*nRows*3;
lelect 3:aa3762e0dfee 346 for(int item=0; item<buffsize; item++) {
lelect 3:aa3762e0dfee 347 log_debug("0x%02X",matrixbuff[backindex][item]);
lelect 3:aa3762e0dfee 348 if((item%32)==31) log_debug(",\r\n");
lelect 3:aa3762e0dfee 349 else log_debug(",");
lelect 0:06d9443a018f 350 }
lelect 4:0ff6053c4bb2 351 log_debug("%s","\r\n\r\n");
lelect 4:0ff6053c4bb2 352 #endif
lelect 0:06d9443a018f 353
lelect 0:06d9443a018f 354 }
lelect 0:06d9443a018f 355
lelect 0:06d9443a018f 356 void RGBmatrixPanel::updateDisplay(void)
lelect 0:06d9443a018f 357 {
lelect 3:aa3762e0dfee 358 _oe=1;
lelect 3:aa3762e0dfee 359 _latch=1;
lelect 3:aa3762e0dfee 360 if(++plane >= nPlanes) { // Advance plane counter. Maxed out?
lelect 0:06d9443a018f 361 plane = 0; // Yes, reset to plane 0, and
lelect 0:06d9443a018f 362 if(++row >= nRows) { // advance row counter. Maxed out?
lelect 3:aa3762e0dfee 363 row= 0; // Yes, reset row counter, then...
lelect 3:aa3762e0dfee 364 if(swapflag == true) { // Swap front/back buffers if requested
lelect 0:06d9443a018f 365 backindex = 1 - backindex;
lelect 0:06d9443a018f 366 swapflag = false;
lelect 0:06d9443a018f 367 }
lelect 0:06d9443a018f 368 buffptr = matrixbuff[1-backindex]; // Reset into front buffer
lelect 0:06d9443a018f 369 }
lelect 0:06d9443a018f 370 } else if(plane == 1) {
lelect 5:1f8409ee8850 371 _rowBus.write(row);
lelect 0:06d9443a018f 372 }
lelect 3:aa3762e0dfee 373 _oe=0;
lelect 3:aa3762e0dfee 374 _latch=0;
lelect 4:0ff6053c4bb2 375 if(plane > 0) {
lelect 3:aa3762e0dfee 376 for(int i=0; i<32; i++) {
lelect 13:0ceb1b8893e9 377 _dataBus.write((*(buffptr+i)>>2));
lelect 3:aa3762e0dfee 378 _sclk=1;
lelect 3:aa3762e0dfee 379 _sclk=0;
lelect 3:aa3762e0dfee 380 }
lelect 4:0ff6053c4bb2 381 buffptr += _rawWidth;
lelect 3:aa3762e0dfee 382 } else {
lelect 3:aa3762e0dfee 383 for(int i=0; i<32; i++) {
lelect 13:0ceb1b8893e9 384 _dataBus.write(((buffptr[i]<<4)|((buffptr[i+32]<<2)&0x0C)|((buffptr[i+64])&0x03)));
lelect 3:aa3762e0dfee 385 _sclk=1;
lelect 3:aa3762e0dfee 386 _sclk=0;
lelect 0:06d9443a018f 387 }
lelect 0:06d9443a018f 388 }
lelect 5:1f8409ee8850 389
lelect 0:06d9443a018f 390 }
lelect 4:0ff6053c4bb2 391