KurtE
Senior Member+
Thought about just adding this to the RA8876 thread, BUT there is an interesting issue having to do (I think) with SPI doing DMA transfer from DMAMEM not getting the right bits...
Note for those with RA8876, this is a version of the embeded picture sketch that I have been playing with, but I made it for the current MASTER branch without PRs
that is it uses: tft.putPicture(start_x, start_y, image_width, image_height, (const unsigned char*)image);
So it might be interesting to see if you see similar results.
The whole sketch is included.
Some bits and pieces to explain what is happening.
The main image is converted part of the sketch:
And I have function that clears centers the image and draws the rest of the screen to some color. It also puts up text showing how long the call in this case to putPicture took. It also draws a second number of how long it took including the output of the first number. This was done as the internal code in RA8876 calls async SPI.transfer(buffer, nullptr, size, event) so the transfer is still happening when the first call returned, but then any other call will wait for current transfer to complete before it then does it's outputs. So when I output the image which is stored in PROGMEM, it looks like:
But if I copy this image from PROGMEM to DMAMEM it does not all get through... To show it, I earlier fill the whole very large array with the color RED. The main loop code:
The one from DMAMEM does not always draw the same: But often times looks like:
You see the red streaks...
Now if we unwind the putPicture code:
Which is:
So after it configures stuff it calls the SPI transfer...
And note, the SPI transfer function in this case has:
To try to flush all: 243800 * 2 bytes from the cache.
Suggestions?
EDIT: Looks like I should have rotated the first picture 180 degrees, but...
Note for those with RA8876, this is a version of the embeded picture sketch that I have been playing with, but I made it for the current MASTER branch without PRs
that is it uses: tft.putPicture(start_x, start_y, image_width, image_height, (const unsigned char*)image);
So it might be interesting to see if you see similar results.
The whole sketch is included.
Some bits and pieces to explain what is happening.
The main image is converted part of the sketch:
Code:
// Generated by : ImageConverter 565 Online
// Generated from : T4.1-Cardlike.gif
// Time generated : Sat, 08 Aug 20 02:16:56 +0200 (Server timezone: CET)
// Image Size : 575x424 pixels
// Memory usage : 487600 bytes
const unsigned short teensy41_Cardlike[243800] PROGMEM={
0xCE79, 0xEF7D, 0xDEFB, 0xEF7D, 0xDEFB, 0xEF7D, 0xDEFB, 0xEF7D, 0xDEFB, 0xEF7D, 0xDEFB, 0xCE79, 0xEF7D, 0xDEFB, 0xEF7D, 0xDEFB, // 0x0010 (16) pixels
0xEF7D, 0xDEFB, 0xEF7D, 0xDEFB, 0xEF7D, 0xDEFB, 0xEF7D, 0xDEFB, 0xEF7D, 0xDEFB, 0xEF7D, 0xCE79, 0xDEFB, 0xDF7D, 0xEEFD, 0xDF7D, // 0x0020 (32) pixels
0xEEFD, 0xDF7D, 0xEEFD, 0xDF7D, 0xEEFD, 0xDF7D, 0xEEFD, 0xDF7D, 0xEEFD, 0xDF7D, 0xEEFD, 0xDF7D, 0xEEFD, 0xDF7D, 0xEEFD, 0xDF7D, // 0x0030 (48) pixels
...
And I have function that clears centers the image and draws the rest of the screen to some color. It also puts up text showing how long the call in this case to putPicture took. It also draws a second number of how long it took including the output of the first number. This was done as the internal code in RA8876 calls async SPI.transfer(buffer, nullptr, size, event) so the transfer is still happening when the first call returned, but then any other call will wait for current transfer to complete before it then does it's outputs. So when I output the image which is stored in PROGMEM, it looks like:
But if I copy this image from PROGMEM to DMAMEM it does not all get through... To show it, I earlier fill the whole very large array with the color RED. The main loop code:
Code:
void loop(void) {
tft.setFont(ComicSansMS_24);
tft.fillScreen(RED);
// Lets put something into the DMAMMEM that is different...
for (uint32_t i = 0; i < sizeof(teensy41_Cardlike_dmamem)/sizeof(teensy41_Cardlike_dmamem[0]); i++)
teensy41_Cardlike_dmamem[i] = RED;
Serial.print("Display T4.1 Extended card ");
drawImage(575, 424, (uint16_t*)teensy41_Cardlike, BLUE);
if (DelayOrStep()) return;
Serial.print("DMAMEM Display T4.1 Extended card ");
// Lets make a DMAMEM version of the card to see if it likes it or not...
memcpy((void *)teensy41_Cardlike_dmamem, (const void *)teensy41_Cardlike, sizeof(teensy41_Cardlike));
drawImage(575, 424, (uint16_t*)teensy41_Cardlike_dmamem, GREEN);
if (DelayOrStep()) return;
//
Serial.print("DMAMEM 2nd time Display T4.1 Extended card ");
drawImage(575, 424, (uint16_t*)teensy41_Cardlike_dmamem, RED);
if (DelayOrStep()) return;
}
You see the red streaks...
Now if we unwind the putPicture code:
Code:
void RA8876_t3::putPicture(ru16 x, ru16 y, ru16 w, ru16 h, const unsigned char *data) {
//The putPicture_16bppData8 function in the base class is not ideal - it damages the activeWindow setting
//It also is harder to make it DMA.
//Ra8876_Lite::putPicture_16bppData8(x, y, w, h, data);
//Using the BTE function is faster and will use DMA if available
bteMpuWriteWithROPData8(currentPage, width(), x, y, //Source 1 is ignored for ROP 12
currentPage, width(), x, y, w, h, //destination address, pagewidth, x/y, width/height
RA8876_BTE_ROP_CODE_12,
data);
}
Which is:
Code:
void RA8876_t3::bteMpuWriteWithROPData8(ru32 s1_addr,ru16 s1_image_width,ru16 s1_x,ru16 s1_y,ru32 des_addr,ru16 des_image_width,
ru16 des_x,ru16 des_y,ru16 width,ru16 height,ru8 rop_code,const unsigned char *data)
{
bteMpuWriteWithROP(s1_addr, s1_image_width, s1_x, s1_y, des_addr, des_image_width, des_x, des_y, width, height, rop_code);
startSend();
_pspi->transfer(RA8876_SPI_DATAWRITE);
#ifdef SPI_HAS_TRANSFER_ASYNC
activeDMA = true;
_pspi->transfer(data, NULL, width*height*2, finishedDMAEvent);
#else
//If you try _pspi->transfer(data, length) then this tries to write received data into the data buffer
//but if we were given a PROGMEM (unwriteable) data pointer then _pspi->transfer will lock up totally.
//So we explicitly tell it we don't care about any return data.
_pspi->transfer(data, NULL, width*height*2);
endSend(true);
#endif
}
And note, the SPI transfer function in this case has:
Code:
if (buf) {
_dmaTX->sourceBuffer((uint8_t*)write_data, count);
_dmaTX->TCD->SLAST = 0; // Finish with it pointing to next location
if ((uint32_t)write_data >= 0x20200000u) arm_dcache_flush(write_data, count);
Suggestions?
EDIT: Looks like I should have rotated the first picture 180 degrees, but...