Adafruit Led Matrix 64x32 Lib

Dependents:   Adafruit-64x32-PWM-Demo

Committer:
davidr99
Date:
Tue Oct 24 02:59:55 2017 +0000
Revision:
1:99abd7449a45
Parent:
0:cdc5e3a73147
Child:
2:e37a437cf602
Added FastIO for NUCLEO-F767ZI

Who changed what in which revision?

UserRevisionLine numberNew contents of line
davidr99 0:cdc5e3a73147 1 #include "LedMatrix.h"
davidr99 1:99abd7449a45 2 #include "FastIO.h"
davidr99 1:99abd7449a45 3 #include "rtos.h"
davidr99 1:99abd7449a45 4
davidr99 1:99abd7449a45 5 #if (defined(TARGET_STM32F303K8))
davidr99 0:cdc5e3a73147 6
davidr99 0:cdc5e3a73147 7 BusOut ABCD(D5,D6,D7,D8); // Row address.
davidr99 1:99abd7449a45 8 FastOut<D3> LAT; // Data latch - active low (pulse up after data load)
davidr99 1:99abd7449a45 9 FastOut<D4> OE; // Output enable - active low (hold high during data load, bring low after LAT pulse)
davidr99 1:99abd7449a45 10
davidr99 1:99abd7449a45 11 FastOut<D9> CLK; // Data clock - rising edge
davidr99 1:99abd7449a45 12 FastOut<D10> R1; // RED Serial in for upper half
davidr99 1:99abd7449a45 13 FastOut<D11> G1; // GREEN Serial in for upper half
davidr99 1:99abd7449a45 14 FastOut<D12> B1; // BLUE Serial in for upper half
davidr99 1:99abd7449a45 15 FastOut<D13> R2; // RED Serial in for lower half
davidr99 1:99abd7449a45 16 FastOut<A0> G2; // GREEN Serial in for lower half
davidr99 1:99abd7449a45 17 FastOut<A1> B2; // BLUE Serial in for lower half
davidr99 1:99abd7449a45 18
davidr99 1:99abd7449a45 19 #elif (defined(TARGET_STM32F767ZI))
davidr99 0:cdc5e3a73147 20
davidr99 1:99abd7449a45 21 BusOut ABCD(A0,A1,A2,A3); // Row address.
davidr99 1:99abd7449a45 22 FastOut<PD_2> OE; // Output enable - active low (hold high during data load, bring low after LAT pulse)
davidr99 1:99abd7449a45 23 FastOut<PG_2> LAT; // Data latch - active low (pulse up after data load)
davidr99 1:99abd7449a45 24 FastOut<PG_3> CLK; // Data clock - rising edge
davidr99 1:99abd7449a45 25
davidr99 1:99abd7449a45 26 FastOut<PD_7> R1; // RED Serial in for upper half
davidr99 1:99abd7449a45 27 FastOut<PD_6> G1; // GREEN Serial in for upper half
davidr99 1:99abd7449a45 28 FastOut<PD_5> B1; // BLUE Serial in for upper half
davidr99 1:99abd7449a45 29 FastOut<PD_4> R2; // RED Serial in for lower half
davidr99 1:99abd7449a45 30 FastOut<PD_3> G2; // GREEN Serial in for lower half
davidr99 1:99abd7449a45 31 FastOut<A4> B2; // BLUE Serial in for lower half
davidr99 1:99abd7449a45 32
davidr99 1:99abd7449a45 33 #endif
davidr99 0:cdc5e3a73147 34
davidr99 0:cdc5e3a73147 35 LedMatrix::LedMatrix() : Adafruit_GFX(WIDTH, HEIGHT)
davidr99 0:cdc5e3a73147 36 {
davidr99 1:99abd7449a45 37 tickCount = 0;
davidr99 1:99abd7449a45 38 shownBuffer = 0;
davidr99 1:99abd7449a45 39 drawBuffer = 0;
davidr99 1:99abd7449a45 40 refreshed = false;
davidr99 0:cdc5e3a73147 41 }
davidr99 0:cdc5e3a73147 42
davidr99 0:cdc5e3a73147 43 // Promote 3/3/3 RGB to Adafruit_GFX 5/6/5
davidr99 0:cdc5e3a73147 44 uint16_t LedMatrix::Color333(uint8_t r, uint8_t g, uint8_t b) {
davidr99 0:cdc5e3a73147 45 // RRRrrGGGgggBBBbb
davidr99 0:cdc5e3a73147 46 return ((r & 0x7) << 13) | ((r & 0x6) << 10) |
davidr99 0:cdc5e3a73147 47 ((g & 0x7) << 8) | ((g & 0x7) << 5) |
davidr99 0:cdc5e3a73147 48 ((b & 0x7) << 2) | ((b & 0x6) >> 1);
davidr99 0:cdc5e3a73147 49 }
davidr99 0:cdc5e3a73147 50
davidr99 0:cdc5e3a73147 51 // Promote 4/4/4 RGB to Adafruit_GFX 5/6/5
davidr99 0:cdc5e3a73147 52 uint16_t LedMatrix::Color444(uint8_t r, uint8_t g, uint8_t b) {
davidr99 0:cdc5e3a73147 53 // RRRRrGGGGggBBBBb
davidr99 0:cdc5e3a73147 54 return ((r & 0xF) << 12) | ((r & 0x8) << 8) |
davidr99 0:cdc5e3a73147 55 ((g & 0xF) << 7) | ((g & 0xC) << 3) |
davidr99 0:cdc5e3a73147 56 ((b & 0xF) << 1) | ((b & 0x8) >> 3);
davidr99 0:cdc5e3a73147 57 }
davidr99 0:cdc5e3a73147 58
davidr99 0:cdc5e3a73147 59 // Demote 8/8/8 to Adafruit_GFX 5/6/5
davidr99 0:cdc5e3a73147 60 // If no gamma flag passed, assume linear color
davidr99 0:cdc5e3a73147 61 uint16_t LedMatrix::Color888(uint8_t r, uint8_t g, uint8_t b) {
davidr99 0:cdc5e3a73147 62 return ((uint16_t)(r & 0xF8) << 8) | ((uint16_t)(g & 0xFC) << 3) | (b >> 3);
davidr99 0:cdc5e3a73147 63 }
davidr99 0:cdc5e3a73147 64
davidr99 0:cdc5e3a73147 65 // 8/8/8 -> gamma -> 5/6/5
davidr99 0:cdc5e3a73147 66 uint16_t LedMatrix::Color888(
davidr99 0:cdc5e3a73147 67 uint8_t r, uint8_t g, uint8_t b, bool gflag) {
davidr99 0:cdc5e3a73147 68 if(gflag) { // Gamma-corrected color?
davidr99 0:cdc5e3a73147 69 r = gamma[r]; // Gamma correction table maps
davidr99 0:cdc5e3a73147 70 g = gamma[g]; // 8-bit input to 4-bit output
davidr99 0:cdc5e3a73147 71 b = gamma[b];
davidr99 0:cdc5e3a73147 72 return ((uint16_t)r << 12) | ((uint16_t)(r & 0x8) << 8) | // 4/4/4->5/6/5
davidr99 0:cdc5e3a73147 73 ((uint16_t)g << 7) | ((uint16_t)(g & 0xC) << 3) |
davidr99 0:cdc5e3a73147 74 ( b << 1) | ( b >> 3);
davidr99 0:cdc5e3a73147 75 } // else linear (uncorrected) color
davidr99 0:cdc5e3a73147 76 return ((uint16_t)(r & 0xF8) << 8) | ((uint16_t)(g & 0xFC) << 3) | (b >> 3);
davidr99 0:cdc5e3a73147 77 }
davidr99 0:cdc5e3a73147 78
davidr99 0:cdc5e3a73147 79 uint16_t LedMatrix::ColorHSV(
davidr99 0:cdc5e3a73147 80 long hue, uint8_t sat, uint8_t val, bool gflag) {
davidr99 0:cdc5e3a73147 81
davidr99 0:cdc5e3a73147 82 uint8_t r, g, b, lo;
davidr99 0:cdc5e3a73147 83 uint16_t s1, v1;
davidr99 0:cdc5e3a73147 84
davidr99 0:cdc5e3a73147 85 // Hue
davidr99 0:cdc5e3a73147 86 hue %= 1536; // -1535 to +1535
davidr99 0:cdc5e3a73147 87 if(hue < 0) hue += 1536; // 0 to +1535
davidr99 0:cdc5e3a73147 88 lo = hue & 255; // Low byte = primary/secondary color mix
davidr99 0:cdc5e3a73147 89 switch(hue >> 8) { // High byte = sextant of colorwheel
davidr99 0:cdc5e3a73147 90 case 0 : r = 255 ; g = lo ; b = 0 ; break; // R to Y
davidr99 0:cdc5e3a73147 91 case 1 : r = 255 - lo; g = 255 ; b = 0 ; break; // Y to G
davidr99 0:cdc5e3a73147 92 case 2 : r = 0 ; g = 255 ; b = lo ; break; // G to C
davidr99 0:cdc5e3a73147 93 case 3 : r = 0 ; g = 255 - lo; b = 255 ; break; // C to B
davidr99 0:cdc5e3a73147 94 case 4 : r = lo ; g = 0 ; b = 255 ; break; // B to M
davidr99 0:cdc5e3a73147 95 default: r = 255 ; g = 0 ; b = 255 - lo; break; // M to R
davidr99 0:cdc5e3a73147 96 }
davidr99 0:cdc5e3a73147 97
davidr99 0:cdc5e3a73147 98 // Saturation: add 1 so range is 1 to 256, allowig a quick shift operation
davidr99 0:cdc5e3a73147 99 // on the result rather than a costly divide, while the type upgrade to int
davidr99 0:cdc5e3a73147 100 // avoids repeated type conversions in both directions.
davidr99 0:cdc5e3a73147 101 s1 = sat + 1;
davidr99 0:cdc5e3a73147 102 r = 255 - (((255 - r) * s1) >> 8);
davidr99 0:cdc5e3a73147 103 g = 255 - (((255 - g) * s1) >> 8);
davidr99 0:cdc5e3a73147 104 b = 255 - (((255 - b) * s1) >> 8);
davidr99 0:cdc5e3a73147 105
davidr99 0:cdc5e3a73147 106 // Value (brightness) & 16-bit color reduction: similar to above, add 1
davidr99 0:cdc5e3a73147 107 // to allow shifts, and upgrade to int makes other conversions implicit.
davidr99 0:cdc5e3a73147 108 v1 = val + 1;
davidr99 0:cdc5e3a73147 109 if(gflag) { // Gamma-corrected color?
davidr99 0:cdc5e3a73147 110 r = gamma[(r * v1) >> 8]; // Gamma correction table maps
davidr99 0:cdc5e3a73147 111 g = gamma[(g * v1) >> 8]; // 8-bit input to 4-bit output
davidr99 0:cdc5e3a73147 112 b = gamma[(b * v1) >> 8];
davidr99 0:cdc5e3a73147 113 } else { // linear (uncorrected) color
davidr99 0:cdc5e3a73147 114 r = (r * v1) >> 12; // 4-bit results
davidr99 0:cdc5e3a73147 115 g = (g * v1) >> 12;
davidr99 0:cdc5e3a73147 116 b = (b * v1) >> 12;
davidr99 0:cdc5e3a73147 117 }
davidr99 0:cdc5e3a73147 118 return (r << 12) | ((r & 0x8) << 8) | // 4/4/4 -> 5/6/5
davidr99 0:cdc5e3a73147 119 (g << 7) | ((g & 0xC) << 3) |
davidr99 0:cdc5e3a73147 120 (b << 1) | ( b >> 3);
davidr99 0:cdc5e3a73147 121 }
davidr99 0:cdc5e3a73147 122
davidr99 0:cdc5e3a73147 123
davidr99 1:99abd7449a45 124 void LedMatrix::drawPixel(int16_t x, int16_t y, uint16_t c)
davidr99 0:cdc5e3a73147 125 {
davidr99 1:99abd7449a45 126 int r, g, b;
davidr99 1:99abd7449a45 127
davidr99 1:99abd7449a45 128 r = (c >> 10) & 0x1F; // RRRRRgggggbbbbb
davidr99 1:99abd7449a45 129 g = (c >> 5) & 0x1F; // rrrrrGGGGGbbbbb
davidr99 1:99abd7449a45 130 b = c & 0x1F; // rrrrrgggggBBBBB
davidr99 1:99abd7449a45 131
davidr99 1:99abd7449a45 132 for(int p=0;p<PLANES;p++)
davidr99 1:99abd7449a45 133 {
davidr99 1:99abd7449a45 134 if (y >= HEIGHT_DEV_2)
davidr99 1:99abd7449a45 135 {
davidr99 1:99abd7449a45 136 // Keep last 3 bits (B2G2R2b1g1r1)
davidr99 1:99abd7449a45 137 gm[drawBuffer][p][y - HEIGHT_DEV_2][x] = (gm[drawBuffer][p][y - HEIGHT_DEV_2][x] & 0b111000) + ((r >> p) & 1) + (((g >> p) & 1) << 1) + (((b >> p) & 1) << 2);
davidr99 1:99abd7449a45 138 }
davidr99 1:99abd7449a45 139 else
davidr99 1:99abd7449a45 140 {
davidr99 1:99abd7449a45 141 // keep first 3 bits (b2g2r2B1G1R1)
davidr99 1:99abd7449a45 142 gm[drawBuffer][p][y][x] = (gm[drawBuffer][p][y][x] & 0b000111) + ((((r >> p) & 1) + (((g << 1) >> p) & 2) + (((b << 2) >> p) & 4)) << 3);
davidr99 1:99abd7449a45 143 }
davidr99 1:99abd7449a45 144 }
davidr99 0:cdc5e3a73147 145 }
davidr99 0:cdc5e3a73147 146
davidr99 0:cdc5e3a73147 147 void LedMatrix::Init()
davidr99 0:cdc5e3a73147 148 {
davidr99 0:cdc5e3a73147 149 // Set up things to a known state
davidr99 0:cdc5e3a73147 150 CLK = LOW;
davidr99 0:cdc5e3a73147 151 LAT = LOW;
davidr99 0:cdc5e3a73147 152 OE = HIGH; //display off
davidr99 0:cdc5e3a73147 153 ABCD = 0;
davidr99 0:cdc5e3a73147 154 plane=0;
davidr99 1:99abd7449a45 155 currRow=0;
davidr99 0:cdc5e3a73147 156 }
davidr99 0:cdc5e3a73147 157
davidr99 0:cdc5e3a73147 158 void LedMatrix::WrRow(unsigned char Row)
davidr99 0:cdc5e3a73147 159 {
davidr99 0:cdc5e3a73147 160 // Write specified row (and row+8) to display. Valid input: 0 to 7.
davidr99 0:cdc5e3a73147 161 ABCD=(HEIGHT_DEV_2-1)-Row; // Set row address
davidr99 1:99abd7449a45 162 char *val = (char *) &gm[shownBuffer][plane][Row][WIDTH-1];
davidr99 1:99abd7449a45 163
davidr99 0:cdc5e3a73147 164 for(int col=(WIDTH-1); col >= 0; col--) { // To daisychain more displays, I guess you would have to increase this counter to n*32 columns. Might mirror though.
davidr99 1:99abd7449a45 165 int value = *val;
davidr99 1:99abd7449a45 166
davidr99 1:99abd7449a45 167 R1 = (value & 1); // Red bit, upper half
davidr99 1:99abd7449a45 168 G1 = (value & 2); // Green bit, upper half
davidr99 1:99abd7449a45 169 B1 = (value & 4); // Blue bit, upper half
davidr99 0:cdc5e3a73147 170
davidr99 1:99abd7449a45 171 R2 = (value & 8); // Red bit, lower half
davidr99 1:99abd7449a45 172 G2 = (value & 16); // Green bit, lower half
davidr99 1:99abd7449a45 173 B2 = (value & 32); // Blue bit, lower half
davidr99 0:cdc5e3a73147 174 CLK = HIGH; // tick (clock bit in)
davidr99 1:99abd7449a45 175 for(int h=0;h<5;h++);
davidr99 0:cdc5e3a73147 176 CLK = LOW; // tock
davidr99 1:99abd7449a45 177 for(int h=0;h<5;h++);
davidr99 1:99abd7449a45 178 val--;
davidr99 0:cdc5e3a73147 179 }
davidr99 0:cdc5e3a73147 180 LAT = HIGH; // Latch entire row
davidr99 1:99abd7449a45 181 for(int h=0;h<5;h++);
davidr99 0:cdc5e3a73147 182 LAT = LOW;
davidr99 0:cdc5e3a73147 183 }
davidr99 0:cdc5e3a73147 184
davidr99 1:99abd7449a45 185 void LedMatrix::CopyBuffer(char oldBuffer, char newBuffer)
davidr99 0:cdc5e3a73147 186 {
davidr99 1:99abd7449a45 187 char *oldBuff = (char *) &gm[oldBuffer][0][0][0];
davidr99 1:99abd7449a45 188 char *newBuff = (char *) &gm[newBuffer][0][0][0];
davidr99 0:cdc5e3a73147 189
davidr99 1:99abd7449a45 190 for(uint32_t buf = 0;buf<(PLANES * HEIGHT_DEV_2 * WIDTH);buf++)
davidr99 0:cdc5e3a73147 191 {
davidr99 1:99abd7449a45 192 *newBuff = *oldBuff;
davidr99 1:99abd7449a45 193 newBuff++;
davidr99 1:99abd7449a45 194 oldBuff++;
davidr99 1:99abd7449a45 195 }
davidr99 1:99abd7449a45 196 }
davidr99 1:99abd7449a45 197
davidr99 1:99abd7449a45 198 void LedMatrix::SetDoubleBuffer(bool setDoubleBuffer)
davidr99 1:99abd7449a45 199 {
davidr99 1:99abd7449a45 200 if (setDoubleBuffer)
davidr99 1:99abd7449a45 201 {
davidr99 1:99abd7449a45 202 shownBuffer = 1;
davidr99 1:99abd7449a45 203 drawBuffer = 0;
davidr99 1:99abd7449a45 204 }
davidr99 1:99abd7449a45 205 else
davidr99 1:99abd7449a45 206 {
davidr99 1:99abd7449a45 207 shownBuffer = 0;
davidr99 1:99abd7449a45 208 drawBuffer = 0;
davidr99 0:cdc5e3a73147 209 }
davidr99 0:cdc5e3a73147 210 }
davidr99 0:cdc5e3a73147 211
davidr99 1:99abd7449a45 212 void LedMatrix::Swap(bool copyBuffer)
davidr99 0:cdc5e3a73147 213 {
davidr99 1:99abd7449a45 214 if (shownBuffer == 0)
davidr99 0:cdc5e3a73147 215 {
davidr99 1:99abd7449a45 216 shownBuffer = 1;
davidr99 1:99abd7449a45 217 drawBuffer = 0;
davidr99 0:cdc5e3a73147 218 }
davidr99 0:cdc5e3a73147 219 else
davidr99 0:cdc5e3a73147 220 {
davidr99 1:99abd7449a45 221 drawBuffer = 1;
davidr99 1:99abd7449a45 222 shownBuffer = 0;
davidr99 1:99abd7449a45 223 }
davidr99 1:99abd7449a45 224
davidr99 1:99abd7449a45 225 if (copyBuffer)
davidr99 1:99abd7449a45 226 {
davidr99 1:99abd7449a45 227 CopyBuffer(shownBuffer, drawBuffer);
davidr99 0:cdc5e3a73147 228 }
davidr99 1:99abd7449a45 229 }
davidr99 1:99abd7449a45 230
davidr99 1:99abd7449a45 231 // Break painting up into 8 rows to keep CPU int time down
davidr99 1:99abd7449a45 232 void LedMatrix::Paint()
davidr99 1:99abd7449a45 233 {
davidr99 1:99abd7449a45 234 if ((plane >= 1 && tickCount >= (1 << (plane - 1)) && currRow == 0 && !refreshed)
davidr99 1:99abd7449a45 235 || (refreshed && tickCount >= (1 << (PLANES - 1))))
davidr99 1:99abd7449a45 236 {
davidr99 0:cdc5e3a73147 237 OE = HIGH; // Disable output
davidr99 1:99abd7449a45 238 if (refreshed)
davidr99 1:99abd7449a45 239 {
davidr99 1:99abd7449a45 240 tickCount = 0;
davidr99 1:99abd7449a45 241 refreshed = false;
davidr99 1:99abd7449a45 242 }
davidr99 1:99abd7449a45 243 }
davidr99 1:99abd7449a45 244
davidr99 1:99abd7449a45 245 // Write graphics memory to display
davidr99 1:99abd7449a45 246 if (tickCount >= (1 << plane) && !refreshed)
davidr99 1:99abd7449a45 247 {
davidr99 1:99abd7449a45 248 tickCount = 0;
davidr99 1:99abd7449a45 249 OE = HIGH; // Disable output
davidr99 1:99abd7449a45 250 WrRow(currRow);
davidr99 0:cdc5e3a73147 251 OE = LOW; // Enable output
davidr99 1:99abd7449a45 252 currRow++;
davidr99 1:99abd7449a45 253
davidr99 1:99abd7449a45 254 if (currRow >= HEIGHT_DEV_2)
davidr99 1:99abd7449a45 255 {
davidr99 1:99abd7449a45 256 currRow = 0;
davidr99 1:99abd7449a45 257
davidr99 1:99abd7449a45 258 if (plane >= (PLANES - 1))
davidr99 1:99abd7449a45 259 {
davidr99 1:99abd7449a45 260 plane = 0;
davidr99 1:99abd7449a45 261 refreshed = true;
davidr99 1:99abd7449a45 262 }
davidr99 1:99abd7449a45 263 else
davidr99 1:99abd7449a45 264 {
davidr99 1:99abd7449a45 265 plane++;
davidr99 1:99abd7449a45 266 }
davidr99 1:99abd7449a45 267 }
davidr99 0:cdc5e3a73147 268 }
davidr99 1:99abd7449a45 269 else
davidr99 1:99abd7449a45 270 {
davidr99 1:99abd7449a45 271 tickCount++;
davidr99 1:99abd7449a45 272 }
davidr99 0:cdc5e3a73147 273 }