// Based on https://github.com/SebiTimeWaster/ICN2053_ESP32_LedWall #define PIN_CLK 2 #define PIN_LE 27 #define PIN_OE 5 #define PIN_A 21 #define PIN_B 22 #define PIN_C 23 #define PIN_D 25 #define PIN_E 26 #define PIN_R1 14 #define PIN_G1 15 #define PIN_B1 16 #define PIN_R2 17 #define PIN_G2 18 #define PIN_B2 19 const int panelWidth = 128; const int numScanLines = 32; const int numLeds = 16; const int chips = panelWidth / numLeds; uint8_t pins[14] = {PIN_CLK, PIN_LE, PIN_OE, PIN_A, PIN_B, PIN_C, PIN_D, PIN_E, PIN_R1, PIN_G1, PIN_B1, PIN_R2, PIN_G2, PIN_B2}; void IRAM_ATTR sendPwmClock(uint16_t clocks) { while (clocks--) { digitalWrite(PIN_OE, 1); digitalWrite(PIN_OE, 0); } } void IRAM_ATTR sendClock() { digitalWrite(PIN_CLK, 1); digitalWrite(PIN_CLK, 0); } void IRAM_ATTR sendLatch(uint8_t clocks) { digitalWrite(PIN_LE, 0); sendClock(); digitalWrite(PIN_LE, 1); while(clocks--) { sendClock(); } digitalWrite(PIN_LE, 0); } void IRAM_ATTR writePixel(uint8_t rgbrgb) { uint32_t k = ((uint32_t) rgbrgb) << 14; GPIO.out = (GPIO.out & ~0x000FC000) | k; // Same as // digitalWrite(PIN_R1, v & 1); // digitalWrite(PIN_G1, v & 2); // digitalWrite(PIN_B1, v & 4); // digitalWrite(PIN_R2, v & 8); // digitalWrite(PIN_G2, v & 16); // digitalWrite(PIN_B2, v & 24); // but in a "single cycle" } void IRAM_ATTR SendPixel(uint16_t r1, uint16_t g1, uint16_t b1, uint16_t r2, uint16_t g2, uint16_t b2, uint8_t doLatch) { for (int i = 0; i < 16; i++) { uint16_t mask = 0x8000 >> i; uint8_t r1b = (r1 & mask) > 0; uint8_t r2b = (r2 & mask) > 0; uint8_t g1b = (g1 & mask) > 0; uint8_t g2b = (g2 & mask) > 0; uint8_t b1b = (b1 & mask) > 0; uint8_t b2b = (b2 & mask) > 0; uint8_t rgbrgb = (r1b << 0) | (g1b << 1) | (b1b << 2) | (r2b << 3) | (g2b << 4) | (b2b << 5); writePixel(rgbrgb); if (i == 15 && doLatch) { digitalWrite(PIN_LE, 1); } sendClock(); } digitalWrite(PIN_LE, 0); } void sendConfiguration(uint16_t data, uint8_t latches) { uint8_t num = chips; uint16_t dataMask; latches = 16 - latches; // send config data to all chips involved (4 per 64 pixel), then latch for 1 clock while(num--) { for(uint8_t x = 0; x < 16; x++) { dataMask = 0x8000 >> x; writePixel(data & dataMask ? 0x3F : 0); // Write all color channels exactly the same, which is the same as: // digitalWrite(PIN_R1, data & dataMask ? 1 : 0); // digitalWrite(PIN_G1, data & dataMask ? 1 : 0); // digitalWrite(PIN_B1, data & dataMask ? 1 : 0); // digitalWrite(PIN_R2, data & dataMask ? 1 : 0); // digitalWrite(PIN_G2, data & dataMask ? 1 : 0); // digitalWrite(PIN_B2, data & dataMask ? 1 : 0); // but in a "single cycle" if(num == 0 && x == latches) { // Latch only on the last chip digitalWrite(PIN_LE, 1); } sendClock(); } digitalWrite(PIN_LE, 0); } } void IRAM_ATTR sendScanline(uint8_t line) { delayMicroseconds(10); // Avoids ghosting... uint32_t scanLine = 0x00000000; if(line & 0x1) scanLine += 1; if(line >> 1 & 0x1) scanLine += 2; if(line >> 2 & 0x1) scanLine += 4; if(line >> 3 & 0x1) scanLine += 16; if(line >> 4 & 0x1) scanLine += 32; GPIO.out = (GPIO.out & ~0x06E00000) | (scanLine << 21); // which is the same as: // digitalWrite(PIN_A, line & 1) // digitalWrite(PIN_B, line & 2) // digitalWrite(PIN_C, line & 4) // digitalWrite(PIN_D, line & 8) // digitalWrite(PIN_E, line & 16) // but in a "single cycle" } uint16_t Translate8To16Bit[256] = {0,46,92,139,186,233,280,327,375,422,470,519,567,615,664,713,762,812,861,911,961,1011,1061,1112,1163,1214,1265,1317,1368,1420,1473,1525,1578,1631,1684,1737,1791,1844,1899,1953,2007,2062,2117,2173,2228,2284,2340,2397,2453,2510,2568,2625,2683,2741,2799,2858,2917,2976,3036,3096,3156,3216,3277,3338,3399,3461,3523,3586,3648,3711,3775,3838,3902,3967,4032,4097,4162,4228,4294,4361,4428,4495,4563,4631,4699,4768,4838,4907,4978,5048,5119,5191,5262,5335,5407,5481,5554,5628,5703,5778,5853,5929,6006,6083,6160,6238,6317,6396,6476,6556,6636,6718,6799,6882,6965,7048,7132,7217,7302,7388,7475,7562,7650,7739,7828,7918,8008,8099,8191,8284,8377,8472,8567,8662,8759,8856,8954,9053,9153,9253,9355,9457,9560,9664,9769,9875,9982,10090,10199,10309,10420,10532,10645,10760,10875,10991,11109,11228,11348,11469,11591,11715,11840,11967,12094,12223,12354,12486,12620,12755,12891,13030,13169,13311,13454,13599,13746,13895,14045,14198,14352,14509,14667,14828,14991,15157,15324,15494,15667,15842,16020,16200,16383,16569,16758,16951,17146,17345,17547,17752,17961,18174,18391,18612,18837,19067,19301,19539,19783,20032,20286,20546,20812,21083,21361,21646,21938,22237,22544,22859,23183,23516,23859,24211,24575,24950,25338,25739,26153,26583,27029,27493,27975,28478,29003,29553,30130,30736,31375,32051,32767,33530,34345,35221,36167,37195,38322,39567,40959,42537,44359,46514,49151,52551,57343,65535}; #define BLACK { 0, 0, 0} #define RED {255, 0, 0} #define GREEN { 0,255, 0} #define BLUE { 0, 0,255} #define WHITE {255,255,255} uint8_t scanLines[numScanLines*2][panelWidth][3] = { {BLACK,BLACK,BLACK,BLACK,BLACK,BLACK,BLACK}, {BLACK,BLACK,BLACK,BLACK,BLACK,BLACK,BLACK}, { BLACK, BLACK, RED ,BLUE,BLUE,BLUE,RED , BLUE, BLUE,RED ,RED ,RED ,BLUE, BLUE, RED ,RED ,RED ,RED ,BLUE, BLUE, RED ,BLUE,BLUE,BLUE,RED , BLUE, BLUE,RED ,RED ,RED ,RED , BLUE, BLUE,BLUE,RED ,BLUE,BLUE, BLUE }, { BLACK, BLACK, RED ,BLUE,BLUE,BLUE,RED , BLUE, RED ,BLUE,BLUE,BLUE,RED , BLUE, RED ,BLUE,BLUE,BLUE,RED , BLUE, RED ,BLUE,BLUE,RED ,BLUE, BLUE, RED ,BLUE,BLUE,BLUE,BLUE, BLUE, BLUE,BLUE,RED ,BLUE,BLUE, BLUE }, { BLACK, BLACK, RED ,BLUE,BLUE,BLUE,RED , BLUE, RED ,BLUE,BLUE,BLUE,RED , BLUE, RED ,BLUE,BLUE,BLUE,RED , BLUE, RED ,BLUE,RED ,BLUE,BLUE, BLUE, RED ,BLUE,BLUE,BLUE,BLUE, BLUE, BLUE,BLUE,RED ,BLUE,BLUE, BLUE }, { BLACK, BLACK, RED ,BLUE,RED ,BLUE,RED , BLUE, RED ,BLUE,BLUE,BLUE,RED , BLUE, RED ,RED ,RED ,RED ,BLUE, BLUE, RED ,RED ,BLUE,BLUE,BLUE, BLUE, BLUE,RED ,RED ,RED ,BLUE, BLUE, BLUE,BLUE,RED ,BLUE,BLUE, BLUE }, { BLACK, BLACK, RED ,BLUE,RED ,BLUE,RED , BLUE, RED ,BLUE,BLUE,BLUE,RED , BLUE, RED ,BLUE,RED ,BLUE,BLUE, BLUE, RED ,BLUE,RED ,BLUE,BLUE, BLUE, BLUE,BLUE,BLUE,BLUE,RED , BLUE, BLUE,BLUE,RED ,BLUE,BLUE, BLUE }, { BLACK, BLACK, RED ,BLUE,RED ,BLUE,RED , BLUE, RED ,BLUE,BLUE,BLUE,RED , BLUE, RED ,BLUE,BLUE,RED ,BLUE, BLUE, RED ,BLUE,BLUE,RED ,BLUE, BLUE, BLUE,BLUE,BLUE,BLUE,RED , BLUE, BLUE,BLUE,BLUE,BLUE,BLUE, BLUE }, { BLACK, BLACK, BLUE,RED ,BLUE,RED ,BLUE, BLUE, BLUE,RED ,RED ,RED ,BLUE, BLUE, RED ,BLUE,BLUE,BLUE,RED , BLUE, RED ,BLUE,BLUE,BLUE,RED , BLUE, RED ,RED ,RED ,RED ,BLUE, BLUE, BLUE,BLUE,RED ,BLUE,BLUE, BLUE }, {BLACK,BLACK,BLACK,BLACK,BLACK,BLACK,BLACK}, {BLACK,BLACK,BLACK,BLACK,BLACK,BLACK,BLACK}, { BLACK, BLACK, RED ,BLUE,BLUE,BLUE,RED , BLUE, BLUE,RED ,RED ,RED ,BLUE, BLUE, RED ,RED ,RED ,RED ,BLUE, BLUE, RED ,BLUE,BLUE,BLUE,RED , BLUE, BLUE,RED ,RED ,RED ,RED , BLUE, BLUE,BLUE,RED ,BLUE,BLUE, BLUE }, { BLACK, BLACK, RED ,BLUE,BLUE,BLUE,RED , BLUE, RED ,BLUE,BLUE,BLUE,RED , BLUE, RED ,BLUE,BLUE,BLUE,RED , BLUE, RED ,BLUE,BLUE,RED ,BLUE, BLUE, RED ,BLUE,BLUE,BLUE,BLUE, BLUE, BLUE,BLUE,RED ,BLUE,BLUE, BLUE }, { BLACK, BLACK, RED ,BLUE,BLUE,BLUE,RED , BLUE, RED ,BLUE,BLUE,BLUE,RED , BLUE, RED ,BLUE,BLUE,BLUE,RED , BLUE, RED ,BLUE,RED ,BLUE,BLUE, BLUE, RED ,BLUE,BLUE,BLUE,BLUE, BLUE, BLUE,BLUE,RED ,BLUE,BLUE, BLUE }, { BLACK, BLACK, RED ,BLUE,RED ,BLUE,RED , BLUE, RED ,BLUE,BLUE,BLUE,RED , BLUE, RED ,RED ,RED ,RED ,BLUE, BLUE, RED ,RED ,BLUE,BLUE,BLUE, BLUE, BLUE,RED ,RED ,RED ,BLUE, BLUE, BLUE,BLUE,RED ,BLUE,BLUE, BLUE }, { BLACK, BLACK, RED ,BLUE,RED ,BLUE,RED , BLUE, RED ,BLUE,BLUE,BLUE,RED , BLUE, RED ,BLUE,RED ,BLUE,BLUE, BLUE, RED ,BLUE,RED ,BLUE,BLUE, BLUE, BLUE,BLUE,BLUE,BLUE,RED , BLUE, BLUE,BLUE,RED ,BLUE,BLUE, BLUE }, { BLACK, BLACK, RED ,BLUE,RED ,BLUE,RED , BLUE, RED ,BLUE,BLUE,BLUE,RED , BLUE, RED ,BLUE,BLUE,RED ,BLUE, BLUE, RED ,BLUE,BLUE,RED ,BLUE, BLUE, BLUE,BLUE,BLUE,BLUE,RED , BLUE, BLUE,BLUE,BLUE,BLUE,BLUE, BLUE }, { BLACK, BLACK, BLUE,RED ,BLUE,RED ,BLUE, BLUE, BLUE,RED ,RED ,RED ,BLUE, BLUE, RED ,BLUE,BLUE,BLUE,RED , BLUE, RED ,BLUE,BLUE,BLUE,RED , BLUE, RED ,RED ,RED ,RED ,BLUE, BLUE, BLUE,BLUE,RED ,BLUE,BLUE, BLUE }, {BLACK,BLACK,BLACK,BLACK,BLACK,BLACK,BLACK}, {BLACK,BLACK,BLACK,BLACK,BLACK,BLACK,BLACK}, { BLACK, BLACK, RED ,BLUE,BLUE,BLUE,RED , BLUE, BLUE,RED ,RED ,RED ,BLUE, BLUE, RED ,RED ,RED ,RED ,BLUE, BLUE, RED ,BLUE,BLUE,BLUE,RED , BLUE, BLUE,RED ,RED ,RED ,RED , BLUE, BLUE,BLUE,RED ,BLUE,BLUE, BLUE }, { BLACK, BLACK, RED ,BLUE,BLUE,BLUE,RED , BLUE, RED ,BLUE,BLUE,BLUE,RED , BLUE, RED ,BLUE,BLUE,BLUE,RED , BLUE, RED ,BLUE,BLUE,RED ,BLUE, BLUE, RED ,BLUE,BLUE,BLUE,BLUE, BLUE, BLUE,BLUE,RED ,BLUE,BLUE, BLUE }, { BLACK, BLACK, RED ,BLUE,BLUE,BLUE,RED , BLUE, RED ,BLUE,BLUE,BLUE,RED , BLUE, RED ,BLUE,BLUE,BLUE,RED , BLUE, RED ,BLUE,RED ,BLUE,BLUE, BLUE, RED ,BLUE,BLUE,BLUE,BLUE, BLUE, BLUE,BLUE,RED ,BLUE,BLUE, BLUE }, { BLACK, BLACK, RED ,BLUE,RED ,BLUE,RED , BLUE, RED ,BLUE,BLUE,BLUE,RED , BLUE, RED ,RED ,RED ,RED ,BLUE, BLUE, RED ,RED ,BLUE,BLUE,BLUE, BLUE, BLUE,RED ,RED ,RED ,BLUE, BLUE, BLUE,BLUE,RED ,BLUE,BLUE, BLUE }, { BLACK, BLACK, RED ,BLUE,RED ,BLUE,RED , BLUE, RED ,BLUE,BLUE,BLUE,RED , BLUE, RED ,BLUE,RED ,BLUE,BLUE, BLUE, RED ,BLUE,RED ,BLUE,BLUE, BLUE, BLUE,BLUE,BLUE,BLUE,RED , BLUE, BLUE,BLUE,RED ,BLUE,BLUE, BLUE }, { BLACK, BLACK, RED ,BLUE,RED ,BLUE,RED , BLUE, RED ,BLUE,BLUE,BLUE,RED , BLUE, RED ,BLUE,BLUE,RED ,BLUE, BLUE, RED ,BLUE,BLUE,RED ,BLUE, BLUE, BLUE,BLUE,BLUE,BLUE,RED , BLUE, BLUE,BLUE,BLUE,BLUE,BLUE, BLUE }, { BLACK, BLACK, BLUE,RED ,BLUE,RED ,BLUE, BLUE, BLUE,RED ,RED ,RED ,BLUE, BLUE, RED ,BLUE,BLUE,BLUE,RED , BLUE, RED ,BLUE,BLUE,BLUE,RED , BLUE, RED ,RED ,RED ,RED ,BLUE, BLUE, BLUE,BLUE,RED ,BLUE,BLUE, BLUE }, {BLACK,BLACK,BLACK,BLACK,BLACK,BLACK,BLACK}, {BLACK,BLACK,BLACK,BLACK,BLACK,BLACK,BLACK}, { BLACK, BLACK, RED ,BLUE,BLUE,BLUE,RED , BLUE, BLUE,RED ,RED ,RED ,BLUE, BLUE, RED ,RED ,RED ,RED ,BLUE, BLUE, RED ,BLUE,BLUE,BLUE,RED , BLUE, BLUE,RED ,RED ,RED ,RED , BLUE, BLUE,BLUE,RED ,BLUE,BLUE, BLUE }, { BLACK, BLACK, RED ,BLUE,BLUE,BLUE,RED , BLUE, RED ,BLUE,BLUE,BLUE,RED , BLUE, RED ,BLUE,BLUE,BLUE,RED , BLUE, RED ,BLUE,BLUE,RED ,BLUE, BLUE, RED ,BLUE,BLUE,BLUE,BLUE, BLUE, BLUE,BLUE,RED ,BLUE,BLUE, BLUE }, { BLACK, BLACK, RED ,BLUE,BLUE,BLUE,RED , BLUE, RED ,BLUE,BLUE,BLUE,RED , BLUE, RED ,BLUE,BLUE,BLUE,RED , BLUE, RED ,BLUE,RED ,BLUE,BLUE, BLUE, RED ,BLUE,BLUE,BLUE,BLUE, BLUE, BLUE,BLUE,RED ,BLUE,BLUE, BLUE }, { BLACK, BLACK, RED ,BLUE,RED ,BLUE,RED , BLUE, RED ,BLUE,BLUE,BLUE,RED , BLUE, RED ,RED ,RED ,RED ,BLUE, BLUE, RED ,RED ,BLUE,BLUE,BLUE, BLUE, BLUE,RED ,RED ,RED ,BLUE, BLUE, BLUE,BLUE,RED ,BLUE,BLUE, BLUE }, { BLACK, BLACK, RED ,BLUE,RED ,BLUE,RED , BLUE, RED ,BLUE,BLUE,BLUE,RED , BLUE, RED ,BLUE,RED ,BLUE,BLUE, BLUE, RED ,BLUE,RED ,BLUE,BLUE, BLUE, BLUE,BLUE,BLUE,BLUE,RED , BLUE, BLUE,BLUE,RED ,BLUE,BLUE, BLUE }, { BLACK, BLACK, RED ,BLUE,RED ,BLUE,RED , BLUE, RED ,BLUE,BLUE,BLUE,RED , BLUE, RED ,BLUE,BLUE,RED ,BLUE, BLUE, RED ,BLUE,BLUE,RED ,BLUE, BLUE, BLUE,BLUE,BLUE,BLUE,RED , BLUE, BLUE,BLUE,BLUE,BLUE,BLUE, BLUE }, { BLACK, BLACK, BLUE,RED ,BLUE,RED ,BLUE, BLUE, BLUE,RED ,RED ,RED ,BLUE, BLUE, RED ,BLUE,BLUE,BLUE,RED , BLUE, RED ,BLUE,BLUE,BLUE,RED , BLUE, RED ,RED ,RED ,RED ,BLUE, BLUE, BLUE,BLUE,RED ,BLUE,BLUE, BLUE }, {BLACK,BLACK,BLACK,BLACK,BLACK,BLACK,BLACK}, {BLACK,BLACK,BLACK,BLACK,BLACK,BLACK,BLACK}, { BLACK, BLACK, RED ,BLUE,BLUE,BLUE,RED , BLUE, BLUE,RED ,RED ,RED ,BLUE, BLUE, RED ,RED ,RED ,RED ,BLUE, BLUE, RED ,BLUE,BLUE,BLUE,RED , BLUE, BLUE,RED ,RED ,RED ,RED , BLUE, BLUE,BLUE,RED ,BLUE,BLUE, BLUE }, { BLACK, BLACK, RED ,BLUE,BLUE,BLUE,RED , BLUE, RED ,BLUE,BLUE,BLUE,RED , BLUE, RED ,BLUE,BLUE,BLUE,RED , BLUE, RED ,BLUE,BLUE,RED ,BLUE, BLUE, RED ,BLUE,BLUE,BLUE,BLUE, BLUE, BLUE,BLUE,RED ,BLUE,BLUE, BLUE }, { BLACK, BLACK, RED ,BLUE,BLUE,BLUE,RED , BLUE, RED ,BLUE,BLUE,BLUE,RED , BLUE, RED ,BLUE,BLUE,BLUE,RED , BLUE, RED ,BLUE,RED ,BLUE,BLUE, BLUE, RED ,BLUE,BLUE,BLUE,BLUE, BLUE, BLUE,BLUE,RED ,BLUE,BLUE, BLUE }, { BLACK, BLACK, RED ,BLUE,RED ,BLUE,RED , BLUE, RED ,BLUE,BLUE,BLUE,RED , BLUE, RED ,RED ,RED ,RED ,BLUE, BLUE, RED ,RED ,BLUE,BLUE,BLUE, BLUE, BLUE,RED ,RED ,RED ,BLUE, BLUE, BLUE,BLUE,RED ,BLUE,BLUE, BLUE }, { BLACK, BLACK, RED ,BLUE,RED ,BLUE,RED , BLUE, RED ,BLUE,BLUE,BLUE,RED , BLUE, RED ,BLUE,RED ,BLUE,BLUE, BLUE, RED ,BLUE,RED ,BLUE,BLUE, BLUE, BLUE,BLUE,BLUE,BLUE,RED , BLUE, BLUE,BLUE,RED ,BLUE,BLUE, BLUE }, { BLACK, BLACK, RED ,BLUE,RED ,BLUE,RED , BLUE, RED ,BLUE,BLUE,BLUE,RED , BLUE, RED ,BLUE,BLUE,RED ,BLUE, BLUE, RED ,BLUE,BLUE,RED ,BLUE, BLUE, BLUE,BLUE,BLUE,BLUE,RED , BLUE, BLUE,BLUE,BLUE,BLUE,BLUE, BLUE }, { BLACK, BLACK, BLUE,RED ,BLUE,RED ,BLUE, BLUE, BLUE,RED ,RED ,RED ,BLUE, BLUE, RED ,BLUE,BLUE,BLUE,RED , BLUE, RED ,BLUE,BLUE,BLUE,RED , BLUE, RED ,RED ,RED ,RED ,BLUE, BLUE, BLUE,BLUE,RED ,BLUE,BLUE, BLUE }, {BLACK,BLACK,BLACK,BLACK,BLACK,BLACK,BLACK}, {BLACK,BLACK,BLACK,BLACK,BLACK,BLACK,BLACK}, { BLACK, BLACK, RED ,BLUE,BLUE,BLUE,RED , BLUE, BLUE,RED ,RED ,RED ,BLUE, BLUE, RED ,RED ,RED ,RED ,BLUE, BLUE, RED ,BLUE,BLUE,BLUE,RED , BLUE, BLUE,RED ,RED ,RED ,RED , BLUE, BLUE,BLUE,RED ,BLUE,BLUE, BLUE }, { BLACK, BLACK, RED ,BLUE,BLUE,BLUE,RED , BLUE, RED ,BLUE,BLUE,BLUE,RED , BLUE, RED ,BLUE,BLUE,BLUE,RED , BLUE, RED ,BLUE,BLUE,RED ,BLUE, BLUE, RED ,BLUE,BLUE,BLUE,BLUE, BLUE, BLUE,BLUE,RED ,BLUE,BLUE, BLUE }, { BLACK, BLACK, RED ,BLUE,BLUE,BLUE,RED , BLUE, RED ,BLUE,BLUE,BLUE,RED , BLUE, RED ,BLUE,BLUE,BLUE,RED , BLUE, RED ,BLUE,RED ,BLUE,BLUE, BLUE, RED ,BLUE,BLUE,BLUE,BLUE, BLUE, BLUE,BLUE,RED ,BLUE,BLUE, BLUE }, { BLACK, BLACK, RED ,BLUE,RED ,BLUE,RED , BLUE, RED ,BLUE,BLUE,BLUE,RED , BLUE, RED ,RED ,RED ,RED ,BLUE, BLUE, RED ,RED ,BLUE,BLUE,BLUE, BLUE, BLUE,RED ,RED ,RED ,BLUE, BLUE, BLUE,BLUE,RED ,BLUE,BLUE, BLUE }, { BLACK, BLACK, RED ,BLUE,RED ,BLUE,RED , BLUE, RED ,BLUE,BLUE,BLUE,RED , BLUE, RED ,BLUE,RED ,BLUE,BLUE, BLUE, RED ,BLUE,RED ,BLUE,BLUE, BLUE, BLUE,BLUE,BLUE,BLUE,RED , BLUE, BLUE,BLUE,RED ,BLUE,BLUE, BLUE }, { BLACK, BLACK, RED ,BLUE,RED ,BLUE,RED , BLUE, RED ,BLUE,BLUE,BLUE,RED , BLUE, RED ,BLUE,BLUE,RED ,BLUE, BLUE, RED ,BLUE,BLUE,RED ,BLUE, BLUE, BLUE,BLUE,BLUE,BLUE,RED , BLUE, BLUE,BLUE,BLUE,BLUE,BLUE, BLUE }, { BLACK, BLACK, BLUE,RED ,BLUE,RED ,BLUE, BLUE, BLUE,RED ,RED ,RED ,BLUE, BLUE, RED ,BLUE,BLUE,BLUE,RED , BLUE, RED ,BLUE,BLUE,BLUE,RED , BLUE, RED ,RED ,RED ,RED ,BLUE, BLUE, BLUE,BLUE,RED ,BLUE,BLUE, BLUE }, {BLACK,BLACK,BLACK,BLACK,BLACK,BLACK,BLACK}, {BLACK,BLACK,BLACK,BLACK,BLACK,BLACK,BLACK}, }; void InitBuffer() { for (int k = 0; k < numScanLines * 2; k++) { for (int p = 0; p < panelWidth; p++) { uint8_t *pixel = scanLines[k][p]; if (pixel[0] == 0 && pixel[1] == 0 && pixel[2] == 0) { // Set black pixels to gray pixel[0] = 0x10; pixel[1] = 0x10; pixel[2] = 0x10; } } } } inline void preActiveCommand() { sendLatch(14); // Pre-active command } inline void switchBuffers() { sendLatch(2); // VSync Command } inline void resetCounters() { sendLatch(10); // Reset all chips PWM Counters } const uint32_t firstPanelOffset = 0; const uint32_t secondPanelOffset = (numScanLines) * panelWidth * 3; void IRAM_ATTR WriteFrame() { uint16_t r1 = 0, g1 = 0, b1 = 0, r2 = 0, g2 = 0, b2 = 0; for (int k = 0; k < numScanLines; k++) { uint8_t *currentScanLine0 = (uint8_t *)scanLines[k]; uint8_t *currentScanLine1 = (uint8_t *)scanLines[k+numScanLines]; for (int l = 0; l < numLeds; l++) { for (int c = 0; c < chips; c++) { uint32_t currentPixel = c*numLeds+l; r1 = Translate8To16Bit[currentScanLine0[currentPixel*3 + 0]]; g1 = Translate8To16Bit[currentScanLine0[currentPixel*3 + 1]]; b1 = Translate8To16Bit[currentScanLine0[currentPixel*3 + 2]]; r2 = Translate8To16Bit[currentScanLine1[currentPixel*3 + 0]]; g2 = Translate8To16Bit[currentScanLine1[currentPixel*3 + 1]]; b2 = Translate8To16Bit[currentScanLine1[currentPixel*3 + 2]]; SendPixel(r1,g1,b1,r2,g2,b2, c == chips - 1); } sendPwmClock(64); } } delay(1); switchBuffers(); } void setup() { for (uint8_t x = 0; x < 14; x++) { pinMode(pins[x], OUTPUT); digitalWrite(pins[x], LOW); } resetCounters(); // Reset preActiveCommand(); // Pre-activate command // Sending configuration to register 1, in which: // 1 00 11111 0 0 111011 // 1 => Lower ghost elimination (enabled) // 00 => (Reserved, default 00) // 11111 => Number of scanlines (default 4, we set to 32) // 0 => Grayscale Mode ( 0 => 14 bit, 1 => 13 bit) // 0 => Double GCLK Rate (0 => Active on positive border, 1 => Active on both borders) // 101011 => 64 step programable gain from 12.5% to 200% (default 101011) sendConfiguration(0b1001111100101011, 4); // Write config register 1 (4 latches) preActiveCommand(); // Pre-activate command // Sending configuration to register 2 // 00010 0 000001 000 0 // 00010 => Reserved (default 00010) // 0 => Double Refresh Rate (requires half all GCLK cycles) // 000001 => Reserved (default 00001) // 000 => Dim Line Compensation (000 default) // 0 => Reserved sendConfiguration(0b0001000000010000, 8); // Write config register 2 (4 latches) delay(1); InitBuffer(); WriteFrame(); delay(1); } void loop() { for (int l = 0; l < 32; l++) { sendScanline(l); sendPwmClock(513); } }