Adafruit Led Matrix 64x32 Lib
Dependents: Adafruit-64x32-PWM-Demo
LedMatrix.cpp
- Committer:
- davidr99
- Date:
- 2017-10-24
- Revision:
- 1:99abd7449a45
- Parent:
- 0:cdc5e3a73147
- Child:
- 2:e37a437cf602
File content as of revision 1:99abd7449a45:
#include "LedMatrix.h" #include "FastIO.h" #include "rtos.h" #if (defined(TARGET_STM32F303K8)) BusOut ABCD(D5,D6,D7,D8); // Row address. FastOut<D3> LAT; // Data latch - active low (pulse up after data load) FastOut<D4> OE; // Output enable - active low (hold high during data load, bring low after LAT pulse) FastOut<D9> CLK; // Data clock - rising edge FastOut<D10> R1; // RED Serial in for upper half FastOut<D11> G1; // GREEN Serial in for upper half FastOut<D12> B1; // BLUE Serial in for upper half FastOut<D13> R2; // RED Serial in for lower half FastOut<A0> G2; // GREEN Serial in for lower half FastOut<A1> B2; // BLUE Serial in for lower half #elif (defined(TARGET_STM32F767ZI)) BusOut ABCD(A0,A1,A2,A3); // Row address. FastOut<PD_2> OE; // Output enable - active low (hold high during data load, bring low after LAT pulse) FastOut<PG_2> LAT; // Data latch - active low (pulse up after data load) FastOut<PG_3> CLK; // Data clock - rising edge FastOut<PD_7> R1; // RED Serial in for upper half FastOut<PD_6> G1; // GREEN Serial in for upper half FastOut<PD_5> B1; // BLUE Serial in for upper half FastOut<PD_4> R2; // RED Serial in for lower half FastOut<PD_3> G2; // GREEN Serial in for lower half FastOut<A4> B2; // BLUE Serial in for lower half #endif LedMatrix::LedMatrix() : Adafruit_GFX(WIDTH, HEIGHT) { tickCount = 0; shownBuffer = 0; drawBuffer = 0; refreshed = false; } // Promote 3/3/3 RGB to Adafruit_GFX 5/6/5 uint16_t LedMatrix::Color333(uint8_t r, uint8_t g, uint8_t b) { // RRRrrGGGgggBBBbb return ((r & 0x7) << 13) | ((r & 0x6) << 10) | ((g & 0x7) << 8) | ((g & 0x7) << 5) | ((b & 0x7) << 2) | ((b & 0x6) >> 1); } // Promote 4/4/4 RGB to Adafruit_GFX 5/6/5 uint16_t LedMatrix::Color444(uint8_t r, uint8_t g, uint8_t b) { // RRRRrGGGGggBBBBb return ((r & 0xF) << 12) | ((r & 0x8) << 8) | ((g & 0xF) << 7) | ((g & 0xC) << 3) | ((b & 0xF) << 1) | ((b & 0x8) >> 3); } // Demote 8/8/8 to Adafruit_GFX 5/6/5 // If no gamma flag passed, assume linear color uint16_t LedMatrix::Color888(uint8_t r, uint8_t g, uint8_t b) { return ((uint16_t)(r & 0xF8) << 8) | ((uint16_t)(g & 0xFC) << 3) | (b >> 3); } // 8/8/8 -> gamma -> 5/6/5 uint16_t LedMatrix::Color888( uint8_t r, uint8_t g, uint8_t b, bool gflag) { if(gflag) { // Gamma-corrected color? r = gamma[r]; // Gamma correction table maps g = gamma[g]; // 8-bit input to 4-bit output b = gamma[b]; return ((uint16_t)r << 12) | ((uint16_t)(r & 0x8) << 8) | // 4/4/4->5/6/5 ((uint16_t)g << 7) | ((uint16_t)(g & 0xC) << 3) | ( b << 1) | ( b >> 3); } // else linear (uncorrected) color return ((uint16_t)(r & 0xF8) << 8) | ((uint16_t)(g & 0xFC) << 3) | (b >> 3); } uint16_t LedMatrix::ColorHSV( long hue, uint8_t sat, uint8_t val, bool gflag) { uint8_t r, g, b, lo; uint16_t s1, v1; // Hue hue %= 1536; // -1535 to +1535 if(hue < 0) hue += 1536; // 0 to +1535 lo = hue & 255; // Low byte = primary/secondary color mix switch(hue >> 8) { // High byte = sextant of colorwheel case 0 : r = 255 ; g = lo ; b = 0 ; break; // R to Y case 1 : r = 255 - lo; g = 255 ; b = 0 ; break; // Y to G case 2 : r = 0 ; g = 255 ; b = lo ; break; // G to C case 3 : r = 0 ; g = 255 - lo; b = 255 ; break; // C to B case 4 : r = lo ; g = 0 ; b = 255 ; break; // B to M default: r = 255 ; g = 0 ; b = 255 - lo; break; // M to R } // Saturation: add 1 so range is 1 to 256, allowig a quick shift operation // on the result rather than a costly divide, while the type upgrade to int // avoids repeated type conversions in both directions. s1 = sat + 1; r = 255 - (((255 - r) * s1) >> 8); g = 255 - (((255 - g) * s1) >> 8); b = 255 - (((255 - b) * s1) >> 8); // Value (brightness) & 16-bit color reduction: similar to above, add 1 // to allow shifts, and upgrade to int makes other conversions implicit. v1 = val + 1; if(gflag) { // Gamma-corrected color? 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]; } else { // linear (uncorrected) color r = (r * v1) >> 12; // 4-bit results g = (g * v1) >> 12; b = (b * v1) >> 12; } return (r << 12) | ((r & 0x8) << 8) | // 4/4/4 -> 5/6/5 (g << 7) | ((g & 0xC) << 3) | (b << 1) | ( b >> 3); } void LedMatrix::drawPixel(int16_t x, int16_t y, uint16_t c) { int r, g, b; r = (c >> 10) & 0x1F; // RRRRRgggggbbbbb g = (c >> 5) & 0x1F; // rrrrrGGGGGbbbbb b = c & 0x1F; // rrrrrgggggBBBBB for(int p=0;p<PLANES;p++) { if (y >= HEIGHT_DEV_2) { // Keep last 3 bits (B2G2R2b1g1r1) 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); } else { // keep first 3 bits (b2g2r2B1G1R1) gm[drawBuffer][p][y][x] = (gm[drawBuffer][p][y][x] & 0b000111) + ((((r >> p) & 1) + (((g << 1) >> p) & 2) + (((b << 2) >> p) & 4)) << 3); } } } void LedMatrix::Init() { // Set up things to a known state CLK = LOW; LAT = LOW; OE = HIGH; //display off ABCD = 0; plane=0; currRow=0; } void LedMatrix::WrRow(unsigned char Row) { // Write specified row (and row+8) to display. Valid input: 0 to 7. ABCD=(HEIGHT_DEV_2-1)-Row; // Set row address char *val = (char *) &gm[shownBuffer][plane][Row][WIDTH-1]; 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. int value = *val; R1 = (value & 1); // Red bit, upper half G1 = (value & 2); // Green bit, upper half B1 = (value & 4); // Blue bit, upper half R2 = (value & 8); // Red bit, lower half G2 = (value & 16); // Green bit, lower half B2 = (value & 32); // Blue bit, lower half CLK = HIGH; // tick (clock bit in) for(int h=0;h<5;h++); CLK = LOW; // tock for(int h=0;h<5;h++); val--; } LAT = HIGH; // Latch entire row for(int h=0;h<5;h++); LAT = LOW; } void LedMatrix::CopyBuffer(char oldBuffer, char newBuffer) { char *oldBuff = (char *) &gm[oldBuffer][0][0][0]; char *newBuff = (char *) &gm[newBuffer][0][0][0]; for(uint32_t buf = 0;buf<(PLANES * HEIGHT_DEV_2 * WIDTH);buf++) { *newBuff = *oldBuff; newBuff++; oldBuff++; } } void LedMatrix::SetDoubleBuffer(bool setDoubleBuffer) { if (setDoubleBuffer) { shownBuffer = 1; drawBuffer = 0; } else { shownBuffer = 0; drawBuffer = 0; } } void LedMatrix::Swap(bool copyBuffer) { if (shownBuffer == 0) { shownBuffer = 1; drawBuffer = 0; } else { drawBuffer = 1; shownBuffer = 0; } if (copyBuffer) { CopyBuffer(shownBuffer, drawBuffer); } } // Break painting up into 8 rows to keep CPU int time down void LedMatrix::Paint() { if ((plane >= 1 && tickCount >= (1 << (plane - 1)) && currRow == 0 && !refreshed) || (refreshed && tickCount >= (1 << (PLANES - 1)))) { OE = HIGH; // Disable output if (refreshed) { tickCount = 0; refreshed = false; } } // Write graphics memory to display if (tickCount >= (1 << plane) && !refreshed) { tickCount = 0; OE = HIGH; // Disable output WrRow(currRow); OE = LOW; // Enable output currRow++; if (currRow >= HEIGHT_DEV_2) { currRow = 0; if (plane >= (PLANES - 1)) { plane = 0; refreshed = true; } else { plane++; } } } else { tickCount++; } }