/* Multumiri speciale: Razvan Tataroiu * Bufferul este format din WIDTH blocuri de cate 288 de octeti fiecare. * Un bloc semnifica o unitate elementara ce trebuie transmisa serial * catre driverele de led-uri, la un moment dat de timp. Optimizarea consta * in faptul ca scrierile se fac simultan catre toate cele 6 seriale, * motiv pentru care octetii in sine din buffer reprezinta 0 sau 1 pe bitii * corespunzatori serialei din portul E: * PORTE0=SOUT1_L * ... * In cadrul unui bloc de 288 de octeti, avem date pentru 8 LED-uri (are sens, * fiindca fiecare driver controleaza 8 LED-uri, iar datele sunt gata mixed * in cadrul octetilor, pentru toate driverele. * Datele elementare pentru 1 LED (de fapt, 6 LED-uri, ca sunt 6 seriale) * ocupa 36 de octeti: 288 / 8, sau 12 octeti per canal de culoare * 3 (R,G,B). * Scrierea unui pixel presupune setarea tuturor acestor 36 de octeti cu * valorile MSB-first ale culorilor. Ordinea octetilor in bloc este: * R[11], G[11], B[11], ... R[0], G[0], B[0]. * Din col se selecteaza bloc_par sau bloc_impar. * Din row se selecteaza driverul (shift) */ void setPixel(uint8_t *buf, unsigned row, unsigned col, uint8_t r, uint8_t g, uint8_t b, uint8_t width) { unsigned bloc_impar = wrapAround((col + width / 2), width) * 288; unsigned bloc_par = col * 288; unsigned offset = 36 * ((row >> 1) & 0x7); unsigned impar = row & 0x1; unsigned blk = (impar) ? bloc_impar : bloc_par; unsigned msb = 1 << 7; unsigned and_mask; unsigned or_mask; unsigned shift; unsigned index; unsigned i, j; unsigned tmp; /* Shift = driverul destinatie: 0->2 = left, 3->5 = right */ shift = 2 - ((row >> 4) & 0x3); if (impar) shift += 3; or_mask = 1 << shift; and_mask = ~or_mask; index = blk + offset; /* Scriem in buffer bitii, pe rand, pentru r, g si b. * For-ul fiind pana la 12, iar valorile fiind pe 8 biti, * cei mai nesemnificativi 4 biti vor fi automat 0 */ for (i = 0; i < 12; i ++) { tmp = buf[index] & and_mask; buf[index] = (r & msb) ? (tmp | or_mask) : (tmp); r <<= 1; index ++; } for (i = 0; i < 12; i ++) { tmp = buf[index] & and_mask; buf[index] = (g & msb) ? (tmp | or_mask) : (tmp); g <<= 1; index ++; } for (i = 0; i < 12; i ++) { tmp = buf[index] & and_mask; buf[index] = (b & msb) ? (tmp | or_mask) : (tmp); b <<= 1; index ++; } } void process2() { int i, j; int width, height; uint8_t buf[288 * (STD_WIDTH + 1)]; width = BitmapInfo->bmiHeader.biWidth; height = BitmapInfo->bmiHeader.biHeight; /* Imaginile sunt stocate "de jos in sus" intr-un * bitmap, motiv pentru care trebuie sa le rasturnam * ("height - i - 1" vs "i") aici */ for (i = 0; i < height; i ++) for (j = 0; j < width; j ++) setPixel(buf, height - i - 1, j, matR[i][j], matG[i][j], matB[i][j], width); printf("#define IMAGE_WIDTH %d\n", width); printf("uint8_t buf[] = {\n"); for (i = 0; i < 288 * width; i ++) { printf("%3d", buf[i]); if (i % 16 == 15) printf(",\n"); else if (i != 288 * width) printf(", "); } printf("};\n\n"); }