454 lines
18 KiB
C++
454 lines
18 KiB
C++
|
#include "ESP32-RGB64x32MatrixPanel-I2S-DMA.h"
|
||
|
|
||
|
// Credits: Louis Beaudoin <https://github.com/pixelmatix/SmartMatrix/tree/teensylc>
|
||
|
// and Sprite_TM: https://www.esp32.com/viewtopic.php?f=17&t=3188 and https://www.esp32.com/viewtopic.php?f=13&t=3256
|
||
|
|
||
|
void RGB64x32MatrixPanel_I2S_DMA::configureDMA()
|
||
|
{
|
||
|
// calculate the lowest LSBMSB_TRANSITION_BIT value that will fit in memory
|
||
|
int numDescriptorsPerRow;
|
||
|
lsbMsbTransitionBit = 0;
|
||
|
while(1) {
|
||
|
numDescriptorsPerRow = 1;
|
||
|
for(int i=lsbMsbTransitionBit + 1; i<COLOR_DEPTH_BITS; i++) {
|
||
|
numDescriptorsPerRow += 1<<(i - lsbMsbTransitionBit - 1);
|
||
|
}
|
||
|
|
||
|
int ramrequired = numDescriptorsPerRow * ROWS_PER_FRAME * ESP32_NUM_FRAME_BUFFERS * sizeof(lldesc_t);
|
||
|
ramrequired += 100000; // HACK Hard Coded: Keep at least 100k free!
|
||
|
int largestblockfree = heap_caps_get_largest_free_block(MALLOC_CAP_DMA);
|
||
|
|
||
|
Serial.printf("lsbMsbTransitionBit of %d requires %d RAM, %d available, leaving %d free: \r\n", lsbMsbTransitionBit, ramrequired, largestblockfree, largestblockfree - ramrequired);
|
||
|
|
||
|
if(ramrequired < (largestblockfree))
|
||
|
break;
|
||
|
|
||
|
if(lsbMsbTransitionBit < COLOR_DEPTH_BITS - 1)
|
||
|
lsbMsbTransitionBit++;
|
||
|
else
|
||
|
break;
|
||
|
}
|
||
|
|
||
|
if(numDescriptorsPerRow * ROWS_PER_FRAME * ESP32_NUM_FRAME_BUFFERS * sizeof(lldesc_t) > heap_caps_get_largest_free_block(MALLOC_CAP_DMA)){
|
||
|
assert("Not enough RAM for SmartMatrix descriptors");
|
||
|
Serial.printf("Not enough RAM for SmartMatrix descriptors\r\n");
|
||
|
return;
|
||
|
}
|
||
|
|
||
|
Serial.printf("Raised lsbMsbTransitionBit to %d/%d to fit in RAM\r\n", lsbMsbTransitionBit, COLOR_DEPTH_BITS - 1);
|
||
|
|
||
|
// calculate the lowest LSBMSB_TRANSITION_BIT value that will fit in memory that will meet or exceed the configured refresh rate
|
||
|
while(1) {
|
||
|
int psPerClock = 1000000000000UL/ESP32_I2S_CLOCK_SPEED;
|
||
|
int nsPerLatch = ((PIXELS_PER_LATCH + CLKS_DURING_LATCH) * psPerClock) / 1000;
|
||
|
Serial.printf("ns per latch: %d: \r\n", nsPerLatch);
|
||
|
|
||
|
// add time to shift out LSBs + LSB-MSB transition bit - this ignores fractions...
|
||
|
int nsPerRow = COLOR_DEPTH_BITS * nsPerLatch;
|
||
|
|
||
|
// add time to shift out MSBs
|
||
|
for(int i=lsbMsbTransitionBit + 1; i<COLOR_DEPTH_BITS; i++)
|
||
|
nsPerRow += (1<<(i - lsbMsbTransitionBit - 1)) * (COLOR_DEPTH_BITS - i) * nsPerLatch;
|
||
|
|
||
|
//Serial.printf("nsPerRow: %d: \r\n", nsPerRow);
|
||
|
|
||
|
int nsPerFrame = nsPerRow * ROWS_PER_FRAME;
|
||
|
Serial.printf("nsPerFrame: %d: \r\n", nsPerFrame);
|
||
|
|
||
|
int actualRefreshRate = 1000000000UL/(nsPerFrame);
|
||
|
|
||
|
refreshRate = actualRefreshRate;
|
||
|
|
||
|
Serial.printf("lsbMsbTransitionBit of %d gives %d Hz refresh: \r\n", lsbMsbTransitionBit, actualRefreshRate);
|
||
|
|
||
|
if (actualRefreshRate > 200) // HACK Hard Coded: Minimum frame rate of 160
|
||
|
break;
|
||
|
|
||
|
|
||
|
if(lsbMsbTransitionBit < COLOR_DEPTH_BITS - 1)
|
||
|
lsbMsbTransitionBit++;
|
||
|
else
|
||
|
break;
|
||
|
}
|
||
|
|
||
|
Serial.printf("Raised lsbMsbTransitionBit to %d/%d to meet minimum refresh rate\r\n", lsbMsbTransitionBit, COLOR_DEPTH_BITS - 1);
|
||
|
|
||
|
// TODO: completely fill buffer with data before enabling DMA - can't do this now, lsbMsbTransition bit isn't set in the calc class - also this call will probably have no effect as matrixCalcDivider will skip the first call
|
||
|
//matrixCalcCallback();
|
||
|
|
||
|
// lsbMsbTransition Bit is now finalized - redo descriptor count in case it changed to hit min refresh rate
|
||
|
numDescriptorsPerRow = 1;
|
||
|
for(int i=lsbMsbTransitionBit + 1; i<COLOR_DEPTH_BITS; i++) {
|
||
|
numDescriptorsPerRow += 1<<(i - lsbMsbTransitionBit - 1);
|
||
|
}
|
||
|
|
||
|
Serial.printf("Descriptors for lsbMsbTransitionBit %d/%d with %d rows require %d bytes of DMA RAM\r\n", lsbMsbTransitionBit, COLOR_DEPTH_BITS - 1, ROWS_PER_FRAME, 2 * numDescriptorsPerRow * ROWS_PER_FRAME * sizeof(lldesc_t));
|
||
|
|
||
|
// malloc the DMA linked list descriptors that i2s_parallel will need
|
||
|
int desccount = numDescriptorsPerRow * ROWS_PER_FRAME;
|
||
|
lldesc_t * dmadesc_a = (lldesc_t *)heap_caps_malloc(desccount * sizeof(lldesc_t), MALLOC_CAP_DMA);
|
||
|
assert("Can't allocate descriptor buffer a");
|
||
|
if(!dmadesc_a) {
|
||
|
Serial.printf("Could not malloc descriptor buffer a.");
|
||
|
return;
|
||
|
}
|
||
|
|
||
|
lldesc_t * dmadesc_b = (lldesc_t *)heap_caps_malloc(desccount * sizeof(lldesc_t), MALLOC_CAP_DMA);
|
||
|
assert("Could not malloc descriptor buffer b.");
|
||
|
if(!dmadesc_b) {
|
||
|
Serial.printf("can't malloc");
|
||
|
return;
|
||
|
}
|
||
|
|
||
|
Serial.printf("SmartMatrix Mallocs Complete\r\n");
|
||
|
Serial.printf("Heap Memory Available: %d bytes total, %d bytes largest free block: \r\n", heap_caps_get_free_size(0), heap_caps_get_largest_free_block(0));
|
||
|
Serial.printf("8-bit Accessible Memory Available: %d bytes total, %d bytes largest free block: \r\n", heap_caps_get_free_size(MALLOC_CAP_8BIT), heap_caps_get_largest_free_block(MALLOC_CAP_8BIT));
|
||
|
Serial.printf("32-bit Memory Available: %d bytes total, %d bytes largest free block: \r\n", heap_caps_get_free_size(MALLOC_CAP_32BIT), heap_caps_get_largest_free_block(MALLOC_CAP_32BIT));
|
||
|
Serial.printf("DMA Memory Available: %d bytes total, %d bytes largest free block: \r\n", heap_caps_get_free_size(MALLOC_CAP_DMA), heap_caps_get_largest_free_block(MALLOC_CAP_DMA));
|
||
|
|
||
|
lldesc_t *prevdmadesca = 0;
|
||
|
lldesc_t *prevdmadescb = 0;
|
||
|
int currentDescOffset = 0;
|
||
|
|
||
|
// fill DMA linked lists for both frames
|
||
|
for(int j=0; j<ROWS_PER_FRAME; j++) {
|
||
|
// first set of data is LSB through MSB, single pass - all color bits are displayed once, which takes care of everything below and inlcluding LSBMSB_TRANSITION_BIT
|
||
|
// TODO: size must be less than DMA_MAX - worst case for SmartMatrix Library: 16-bpp with 256 pixels per row would exceed this, need to break into two
|
||
|
link_dma_desc(&dmadesc_a[currentDescOffset], prevdmadesca, &(matrixUpdateFrames[0].rowdata[j].rowbits[0].data), sizeof(rowBitStruct) * COLOR_DEPTH_BITS);
|
||
|
prevdmadesca = &dmadesc_a[currentDescOffset];
|
||
|
link_dma_desc(&dmadesc_b[currentDescOffset], prevdmadescb, &(matrixUpdateFrames[1].rowdata[j].rowbits[0].data), sizeof(rowBitStruct) * COLOR_DEPTH_BITS);
|
||
|
prevdmadescb = &dmadesc_b[currentDescOffset];
|
||
|
currentDescOffset++;
|
||
|
//Serial.printf("row %d: \r\n", j);
|
||
|
|
||
|
for(int i=lsbMsbTransitionBit + 1; i<COLOR_DEPTH_BITS; i++) {
|
||
|
// binary time division setup: we need 2 of bit (LSBMSB_TRANSITION_BIT + 1) four of (LSBMSB_TRANSITION_BIT + 2), etc
|
||
|
// because we sweep through to MSB each time, it divides the number of times we have to sweep in half (saving linked list RAM)
|
||
|
// we need 2^(i - LSBMSB_TRANSITION_BIT - 1) == 1 << (i - LSBMSB_TRANSITION_BIT - 1) passes from i to MSB
|
||
|
//Serial.printf("buffer %d: repeat %d times, size: %d, from %d - %d\r\n", nextBufdescIndex, 1<<(i - LSBMSB_TRANSITION_BIT - 1), (COLOR_DEPTH_BITS - i), i, COLOR_DEPTH_BITS-1);
|
||
|
for(int k=0; k < 1<<(i - lsbMsbTransitionBit - 1); k++) {
|
||
|
link_dma_desc(&dmadesc_a[currentDescOffset], prevdmadesca, &(matrixUpdateFrames[0].rowdata[j].rowbits[i].data), sizeof(rowBitStruct) * (COLOR_DEPTH_BITS - i));
|
||
|
prevdmadesca = &dmadesc_a[currentDescOffset];
|
||
|
link_dma_desc(&dmadesc_b[currentDescOffset], prevdmadescb, &(matrixUpdateFrames[1].rowdata[j].rowbits[i].data), sizeof(rowBitStruct) * (COLOR_DEPTH_BITS - i));
|
||
|
prevdmadescb = &dmadesc_b[currentDescOffset];
|
||
|
|
||
|
currentDescOffset++;
|
||
|
//Serial.printf("i %d, j %d, k %d\r\n", i, j, k);
|
||
|
}
|
||
|
}
|
||
|
}
|
||
|
|
||
|
//End markers
|
||
|
dmadesc_a[desccount-1].eof = 1;
|
||
|
dmadesc_b[desccount-1].eof = 1;
|
||
|
dmadesc_a[desccount-1].qe.stqe_next=(lldesc_t*)&dmadesc_a[0];
|
||
|
dmadesc_b[desccount-1].qe.stqe_next=(lldesc_t*)&dmadesc_b[0];
|
||
|
|
||
|
Serial.printf("Performing I2S setup.\n");
|
||
|
|
||
|
i2s_parallel_config_t cfg={
|
||
|
.gpio_bus={R1_PIN, G1_PIN, B1_PIN, R2_PIN, G2_PIN, B2_PIN, LAT_PIN, OE_PIN, A_PIN, B_PIN, C_PIN, D_PIN, E_PIN, -1, -1, -1},
|
||
|
.gpio_clk=CLK_PIN,
|
||
|
.clkspeed_hz=ESP32_I2S_CLOCK_SPEED, //ESP32_I2S_CLOCK_SPEED, // formula used is 80000000L/(cfg->clkspeed_hz + 1), must result in >=2. Acceptable values 26.67MHz, 20MHz, 16MHz, 13.34MHz...
|
||
|
.bits=MATRIX_I2S_MODE, //MATRIX_I2S_MODE,
|
||
|
.bufa=0,
|
||
|
.bufb=0,
|
||
|
desccount,
|
||
|
desccount,
|
||
|
dmadesc_a,
|
||
|
dmadesc_b
|
||
|
};
|
||
|
|
||
|
//Setup I2S
|
||
|
i2s_parallel_setup_without_malloc(&I2S1, &cfg);
|
||
|
|
||
|
Serial.printf("I2S setup done.\n");
|
||
|
|
||
|
// Just os we know
|
||
|
dma_configuration_success = true;
|
||
|
|
||
|
} // end initMatrixDMABuff
|
||
|
|
||
|
void RGB64x32MatrixPanel_I2S_DMA::updateMatrixDMABuffer(int16_t x_coord, int16_t y_coord, uint8_t red, uint8_t green, uint8_t blue)
|
||
|
{
|
||
|
|
||
|
if ( !dma_configuration_success)
|
||
|
assert("DMA configuration in begin() not performed or completed successfully.");
|
||
|
|
||
|
// Need to check that the co-ordinate is within range, or it'll break everything big time.
|
||
|
if ( x_coord < 0 || y_coord < 0 || x_coord > MATRIX_WIDTH || y_coord > MATRIX_HEIGHT)
|
||
|
{
|
||
|
return;
|
||
|
}
|
||
|
|
||
|
// What half of the HUB75 panel are we painting too?
|
||
|
bool paint_top_half = true;
|
||
|
if ( y_coord > ROWS_PER_FRAME-1) // co-ords start at zero, y_coord = 15 = 16 (rows per frame)
|
||
|
{
|
||
|
y_coord -= ROWS_PER_FRAME; // if it's 16, subtract 16. Array position 0 again.
|
||
|
paint_top_half = false;
|
||
|
}
|
||
|
|
||
|
for(int color_depth_idx=0; color_depth_idx<COLOR_DEPTH_BITS; color_depth_idx++) // color depth - 8 iterations
|
||
|
{
|
||
|
uint16_t mask = (1 << color_depth_idx); // 24 bit color
|
||
|
|
||
|
// The destination for the pixel bitstream
|
||
|
rowBitStruct *p = &matrixUpdateFrames[backbuf_id].rowdata[y_coord].rowbits[color_depth_idx]; //matrixUpdateFrames location to write to uint16_t's
|
||
|
|
||
|
int v=0; // the output bitstream
|
||
|
|
||
|
// if there is no latch to hold address, output ADDX lines directly to GPIO and latch data at end of cycle
|
||
|
int gpioRowAddress = y_coord;
|
||
|
|
||
|
// normally output current rows ADDX, special case for LSB, output previous row's ADDX (as previous row is being displayed for one latch cycle)
|
||
|
if(color_depth_idx == 0)
|
||
|
gpioRowAddress = y_coord-1;
|
||
|
|
||
|
if (gpioRowAddress & 0x01) v|=BIT_A; // 1
|
||
|
if (gpioRowAddress & 0x02) v|=BIT_B; // 2
|
||
|
if (gpioRowAddress & 0x04) v|=BIT_C; // 4
|
||
|
if (gpioRowAddress & 0x08) v|=BIT_D; // 8
|
||
|
if (gpioRowAddress & 0x10) v|=BIT_E; // 16
|
||
|
|
||
|
// need to disable OE after latch to hide row transition
|
||
|
if((x_coord) == 0) v|=BIT_OE;
|
||
|
|
||
|
// drive latch while shifting out last bit of RGB data
|
||
|
if((x_coord) == PIXELS_PER_LATCH-1) v|=BIT_LAT;
|
||
|
|
||
|
// turn off OE after brightness value is reached when displaying MSBs
|
||
|
// MSBs always output normal brightness
|
||
|
// LSB (!color_depth_idx) outputs normal brightness as MSB from previous row is being displayed
|
||
|
//if((color_depth_idx > lsbMsbTransitionBit || !color_depth_idx) && ((x_coord) >= brightness)) v|=BIT_OE;
|
||
|
|
||
|
// special case for the bits *after* LSB through (lsbMsbTransitionBit) - OE is output after data is shifted, so need to set OE to fractional brightness
|
||
|
if(color_depth_idx && color_depth_idx <= lsbMsbTransitionBit) {
|
||
|
// divide brightness in half for each bit below lsbMsbTransitionBit
|
||
|
int lsbBrightness = brightness >> (lsbMsbTransitionBit - color_depth_idx + 1);
|
||
|
// if((x_coord) >= lsbBrightness) v|=BIT_OE;
|
||
|
}
|
||
|
|
||
|
// need to turn off OE one clock before latch, otherwise can get ghosting
|
||
|
if((x_coord)==PIXELS_PER_LATCH-1) v|=BIT_OE;
|
||
|
|
||
|
|
||
|
|
||
|
/* When using the Adafruit drawPixel, we only have one pixel co-ordinate and color to draw (duh)
|
||
|
* so we can't paint a top and bottom half (or whatever row split the panel is) at the same time.
|
||
|
* Need to be smart and check the DMA buffer to see what the other half thinks (pun intended)
|
||
|
* and persis this when we refresh.
|
||
|
*
|
||
|
* The DMA buffer order has also been reversed (fer to the last code in this function)
|
||
|
* so we have to check for this and check ther correct possition of the MATRIX_DATA_STORAGE_TYPE
|
||
|
* data.
|
||
|
*/
|
||
|
int16_t tmp_x_coord = x_coord;
|
||
|
if(x_coord%2)
|
||
|
{
|
||
|
tmp_x_coord -= 1;
|
||
|
} else {
|
||
|
tmp_x_coord += 1;
|
||
|
} // end reordering
|
||
|
|
||
|
if (paint_top_half)
|
||
|
{ // Need to copy what the RGB status is for the bottom pixels
|
||
|
|
||
|
// Set the color of the pixel of interest
|
||
|
if (green & mask)
|
||
|
v|=BIT_G1;
|
||
|
if (blue & mask)
|
||
|
v|=BIT_B1;
|
||
|
if (red & mask)
|
||
|
v|=BIT_R1;
|
||
|
|
||
|
// Persist what was painted to the other half of the frame equiv. pixel
|
||
|
if (p->data[tmp_x_coord] & BIT_R2)
|
||
|
v|=BIT_R2;
|
||
|
|
||
|
if (p->data[tmp_x_coord] & BIT_G2)
|
||
|
v|=BIT_G2;
|
||
|
|
||
|
if (p->data[tmp_x_coord] & BIT_B2)
|
||
|
v|=BIT_B2;
|
||
|
}
|
||
|
else
|
||
|
{ // Do it the other way around
|
||
|
|
||
|
// Color to set
|
||
|
if (red & mask)
|
||
|
v|=BIT_R2;
|
||
|
if (green & mask)
|
||
|
v|=BIT_G2;
|
||
|
if (blue & mask)
|
||
|
v|=BIT_B2;
|
||
|
|
||
|
// Copy
|
||
|
if (p->data[tmp_x_coord] & BIT_R1)
|
||
|
v|=BIT_R1;
|
||
|
|
||
|
if (p->data[tmp_x_coord] & BIT_G1)
|
||
|
v|=BIT_G1;
|
||
|
|
||
|
if (p->data[tmp_x_coord] & BIT_B1)
|
||
|
v|=BIT_B1;
|
||
|
|
||
|
} // paint
|
||
|
|
||
|
|
||
|
// 16 bit parallel mode
|
||
|
//Save the calculated value to the bitplane memory in reverse order to account for I2S Tx FIFO mode1 ordering
|
||
|
if(x_coord%2){
|
||
|
p->data[(x_coord)-1] = v;
|
||
|
} else {
|
||
|
p->data[(x_coord)+1] = v;
|
||
|
} // end reordering
|
||
|
|
||
|
} // color depth loop (8)
|
||
|
|
||
|
|
||
|
|
||
|
//Show our work!
|
||
|
i2s_parallel_flip_to_buffer(&I2S1, backbuf_id);
|
||
|
//swapBuffer();
|
||
|
|
||
|
|
||
|
} // updateDMABuffer
|
||
|
|
||
|
|
||
|
|
||
|
|
||
|
|
||
|
|
||
|
|
||
|
/*
|
||
|
void RGB64x32MatrixPanel_I2S_DMA::updateMatrixDMABuffer(uint16_t x, uint16_t y, uint8_t red, uint8_t green, uint8_t blue)
|
||
|
{
|
||
|
if ( !dma_configuration_success)
|
||
|
assert("DMA configuration in begin() not performed or completed successfully.");
|
||
|
|
||
|
// Pixel index sanity checking.
|
||
|
int16_t idx = x + y * MATRIX_WIDTH;
|
||
|
if (idx < 0 || idx >= MATRIX_HEIGHT * MATRIX_WIDTH)
|
||
|
{
|
||
|
//Serial.printf("Provided coordinates out of range");
|
||
|
return;
|
||
|
}
|
||
|
|
||
|
|
||
|
for (unsigned int y=0; y<MATRIX_HEIGHT/MATRIX_ROWS_IN_PARALLEL; y++) // half height - 16 iterations
|
||
|
{
|
||
|
unsigned char currentRow = y;
|
||
|
|
||
|
for(int j=0; j<COLOR_DEPTH_BITS; j++) // color depth - 8 iterations
|
||
|
{
|
||
|
uint16_t mask = (1 << (j)); // 24 bit color
|
||
|
|
||
|
//MATRIX_DATA_STORAGE_TYPE *p=matrixUpdateFrames[backbuf_id].rowdata[y].rowbits[pl].data; //matrixUpdateFrames
|
||
|
rowBitStruct *p=&matrixUpdateFrames[backbuf_id].rowdata[currentRow].rowbits[j]; //matrixUpdateFrames location to write to
|
||
|
|
||
|
int i=0;
|
||
|
while(i < PIXELS_PER_LATCH) // row pixels (64) iterations
|
||
|
{
|
||
|
for(int k=0; k < MATRIX_WIDTH; k++) // row pixel width 64 iterations
|
||
|
{
|
||
|
int v=0; // the output bitstream
|
||
|
|
||
|
//#if (CLKS_DURING_LATCH == 0)
|
||
|
// if there is no latch to hold address, output ADDX lines directly to GPIO and latch data at end of cycle
|
||
|
int gpioRowAddress = currentRow;
|
||
|
|
||
|
// normally output current rows ADDX, special case for LSB, output previous row's ADDX (as previous row is being displayed for one latch cycle)
|
||
|
if(j == 0)
|
||
|
gpioRowAddress = currentRow-1;
|
||
|
|
||
|
if (gpioRowAddress & 0x01) v|=BIT_A; // 1
|
||
|
if (gpioRowAddress & 0x02) v|=BIT_B; // 2
|
||
|
if (gpioRowAddress & 0x04) v|=BIT_C; // 4
|
||
|
if (gpioRowAddress & 0x08) v|=BIT_D; // 8
|
||
|
if (gpioRowAddress & 0x10) v|=BIT_E; // 16
|
||
|
|
||
|
// need to disable OE after latch to hide row transition
|
||
|
if((i+k) == 0) v|=BIT_OE;
|
||
|
|
||
|
// drive latch while shifting out last bit of RGB data
|
||
|
if((i+k) == PIXELS_PER_LATCH-1) v|=BIT_LAT;
|
||
|
//#endif
|
||
|
|
||
|
// turn off OE after brightness value is reached when displaying MSBs
|
||
|
// MSBs always output normal brightness
|
||
|
// LSB (!j) outputs normal brightness as MSB from previous row is being displayed
|
||
|
if((j > lsbMsbTransitionBit || !j) && ((i+k) >= brightness)) v|=BIT_OE;
|
||
|
|
||
|
// special case for the bits *after* LSB through (lsbMsbTransitionBit) - OE is output after data is shifted, so need to set OE to fractional brightness
|
||
|
if(j && j <= lsbMsbTransitionBit) {
|
||
|
// divide brightness in half for each bit below lsbMsbTransitionBit
|
||
|
int lsbBrightness = brightness >> (lsbMsbTransitionBit - j + 1);
|
||
|
if((i+k) >= lsbBrightness) v|=BIT_OE;
|
||
|
}
|
||
|
|
||
|
// need to turn off OE one clock before latch, otherwise can get ghosting
|
||
|
if((i+k)==PIXELS_PER_LATCH-1) v|=BIT_OE;
|
||
|
|
||
|
|
||
|
//#if 0
|
||
|
//
|
||
|
// int c1=getpixel(pix, k, y);
|
||
|
// int c2=getpixel(pix, k, y+(MATRIX_HEIGHT/2));
|
||
|
//
|
||
|
// if (c1 & (mask<<16)) v|=BIT_R1;
|
||
|
// if (c1 & (mask<<8)) v|=BIT_G1;
|
||
|
// if (c1 & (mask<<0)) v|=BIT_B1;
|
||
|
// if (c2 & (mask<<16)) v|=BIT_R2;
|
||
|
// if ( c2 & (mask<<8)) v|=BIT_G2;
|
||
|
// if (c2 & (mask<<0)) v|=BIT_B2;
|
||
|
//
|
||
|
//#else
|
||
|
|
||
|
struct rgb24 c1( 255,0,0);
|
||
|
struct rgb24 c2 = { 255,255,255 };
|
||
|
// struct rgb24 c2 = { 0,0,255 };
|
||
|
|
||
|
|
||
|
if (c1.red & mask)
|
||
|
v|=BIT_R1;
|
||
|
if (c1.green & mask)
|
||
|
v|=BIT_G1;
|
||
|
if (c1.blue & mask)
|
||
|
v|=BIT_B1;
|
||
|
if (c2.red & mask)
|
||
|
v|=BIT_R2;
|
||
|
if (c2.green & mask)
|
||
|
v|=BIT_G2;
|
||
|
if (c2.blue & mask)
|
||
|
v|=BIT_B2;
|
||
|
|
||
|
//#endif
|
||
|
|
||
|
|
||
|
// 16 bit parallel mode
|
||
|
//Save the calculated value to the bitplane memory in reverse order to account for I2S Tx FIFO mode1 ordering
|
||
|
if(k%2){
|
||
|
p->data[(i+k)-1] = v;
|
||
|
} else {
|
||
|
p->data[(i+k)+1] = v;
|
||
|
} // end reordering
|
||
|
|
||
|
} // end for MATRIX_WIDTH
|
||
|
|
||
|
i += MATRIX_WIDTH;
|
||
|
|
||
|
} // end pixels per latch loop (64)
|
||
|
} // color depth loop (8)
|
||
|
|
||
|
} // end half matrix length
|
||
|
|
||
|
|
||
|
//Show our work!
|
||
|
i2s_parallel_flip_to_buffer(&I2S1, backbuf_id);
|
||
|
swapBuffer();
|
||
|
|
||
|
|
||
|
} // updateDMABuffer
|
||
|
*/
|