RA8876 Parallel Display Library Testing

@wwatson - I converted my version over to using the
tft.pushPixels16bitAsync(pixels, x, y, cx, cy);
Which appears to be working nicely.

The only thing I still notice different between the SPI version and Parallel is that the fillScreen code
Code:
useCanavas();
fillScreen(RED);
I think does maybe updates then versus the SPI version where it gets then drawn again when the picture finishes loading the image,
Will investigate more.

Question: is there a good #define as part of the library that a sketch should use, to know which version of the library it is using:
SPI or FlexIO, potentially if setup for a FlexIO that supports DMA or not...
 
Question: is there a good #define as part of the library that a sketch should use, to know which version of the library it is using:
SPI or FlexIO, potentially if setup for a FlexIO that supports DMA or not...
Unfortunately no. Probably should detect which Teensy device type is being used and error out if it is the wrong branch. I struggled with how the library should be laid out :unsure: Having it one branch and being a huge library with lots of defines to select or maybe separate libraries for each Teensy device. Either way I am open to suggestions at this point :D
 
Well today has been kind of a rough day to get things done for me from after this morning. Hopefully tomorrow will be better. Did get writerect working for rotation 2 and 3 but not sure why I had to it that way but want to test more before I push the changes.

This is what rotation 2 and 3 like now. Had to add (width()- w) - start_x and height() - start_y?
Code:
        case 2:
            {
                uint16_t *rotated_buffer_alloc = (uint16_t*)malloc(w * h * 2 + 32);
                if (!rotated_buffer_alloc) return; // failed to allocate.
                uint16_t *rotated_buffer = (uint16_t *)(((uintptr_t)rotated_buffer_alloc + 32) & ~((uintptr_t)(31)));
                // unrolled to bte call
                //Using the BTE function is faster and will use DMA if available
                // We reverse the colors in the row...
                // lets reverse data per row...
                while (h) {
                    for (int i = 0; i < w; i++) rotated_buffer[w-i-1] = *pcolors++;
                if(BUS_WIDTH == 8) {
                    bteMpuWriteWithROPData8(currentPage, width(), start_x, start_y,  //Source 1 is ignored for ROP 12
                              currentPage, width(), (width()- w) - start_x , start_y, w, 1,     //destination address, pagewidth, x/y, width/height
                              RA8876_BTE_ROP_CODE_12,
                              ( const unsigned char *)rotated_buffer);
                } else {
                    bteMpuWriteWithROPData16(currentPage, width(), start_x, start_y,  //Source 1 is ignored for ROP 12
                              currentPage, width(), (width()- w) - start_x, start_y, w, 1,     //destination address, pagewidth, x/y, width/height
                              RA8876_BTE_ROP_CODE_12,
                              ( const unsigned short *)rotated_buffer);
                }                   
                    start_y++;
                    h--;
                }
                free((void*)rotated_buffer_alloc);
            }
            break;
        case 3:
            {
                start_y += h;
                while (h) {
                    //Serial.printf("DP %x, %d, %d %d\n", rotated_row, h, start_x, y);
                if(BUS_WIDTH == 8) {
                    bteMpuWriteWithROPData8(currentPage, height(), start_y, start_x,  //Source 1 is ignored for ROP 12
                                  currentPage, height(), height() - start_y, start_x, 1, w,     //destination address, pagewidth, x/y, width/height
                                  RA8876_BTE_ROP_CODE_12,
                                  ( const unsigned char *)pcolors);
                                
                } else {
                    bteMpuWriteWithROPData16(currentPage, height(), start_y, start_x,  //Source 1 is ignored for ROP 12
                                  currentPage, height(),  height() - start_y, start_x, 1, w,     //destination address, pagewidth, x/y, width/height
                                  RA8876_BTE_ROP_CODE_12,
                                  ( const unsigned short *)pcolors);
                }
                    start_y--;
                    h--;
                    pcolors += w;
                }
            }
            break;
    }
 
Well today has been kind of a rough day to get things done for me from after this morning. Hopefully tomorrow will be better. Did get writerect working for rotation 2 and 3 but not sure why I had to it that way but want to test more before I push the changes.

This is what rotation 2 and 3 like now. Had to add (width()- w) - start_x and height() - start_y?
Code:
        case 2:
            {
                uint16_t *rotated_buffer_alloc = (uint16_t*)malloc(w * h * 2 + 32);
                if (!rotated_buffer_alloc) return; // failed to allocate.
                uint16_t *rotated_buffer = (uint16_t *)(((uintptr_t)rotated_buffer_alloc + 32) & ~((uintptr_t)(31)));
                // unrolled to bte call
                //Using the BTE function is faster and will use DMA if available
                // We reverse the colors in the row...
                // lets reverse data per row...
                while (h) {
                    for (int i = 0; i < w; i++) rotated_buffer[w-i-1] = *pcolors++;
                if(BUS_WIDTH == 8) {
                    bteMpuWriteWithROPData8(currentPage, width(), start_x, start_y,  //Source 1 is ignored for ROP 12
                              currentPage, width(), (width()- w) - start_x , start_y, w, 1,     //destination address, pagewidth, x/y, width/height
                              RA8876_BTE_ROP_CODE_12,
                              ( const unsigned char *)rotated_buffer);
                } else {
                    bteMpuWriteWithROPData16(currentPage, width(), start_x, start_y,  //Source 1 is ignored for ROP 12
                              currentPage, width(), (width()- w) - start_x, start_y, w, 1,     //destination address, pagewidth, x/y, width/height
                              RA8876_BTE_ROP_CODE_12,
                              ( const unsigned short *)rotated_buffer);
                }                  
                    start_y++;
                    h--;
                }
                free((void*)rotated_buffer_alloc);
            }
            break;
        case 3:
            {
                start_y += h;
                while (h) {
                    //Serial.printf("DP %x, %d, %d %d\n", rotated_row, h, start_x, y);
                if(BUS_WIDTH == 8) {
                    bteMpuWriteWithROPData8(currentPage, height(), start_y, start_x,  //Source 1 is ignored for ROP 12
                                  currentPage, height(), height() - start_y, start_x, 1, w,     //destination address, pagewidth, x/y, width/height
                                  RA8876_BTE_ROP_CODE_12,
                                  ( const unsigned char *)pcolors);
                               
                } else {
                    bteMpuWriteWithROPData16(currentPage, height(), start_y, start_x,  //Source 1 is ignored for ROP 12
                                  currentPage, height(),  height() - start_y, start_x, 1, w,     //destination address, pagewidth, x/y, width/height
                                  RA8876_BTE_ROP_CODE_12,
                                  ( const unsigned short *)pcolors);
                }
                    start_y--;
                    h--;
                    pcolors += w;
                }
            }
            break;
    }
I hope things are better for you as well. Unfortunately I do not have my SPI version of the RA8876 setup right now. Will have to wire it up and test this as well as the Ra8876_t41_8p library. It is nice that I can use both Ra8876_t3 and Ra8876_t41_8p in the libraries folder without conflict. Tested that already and their is no conflict :) This may be another way to go. Setting up seperate libraries on GitHub...
 
Well today has been kind of a rough day to get things done for me from after this morning. Hopefully tomorrow will be better. Did get writerect working for rotation 2 and 3 but not sure why I had to it that way but want to test more before I push the changes.
I know that feeling. Been there... (actually most days)

Luckily I do now have both setups. That is I have two RA8876, one configured for SPI4 and the other for Parallel. I have the 2nd version of adapter board:
1719363751568.png

Not great, but it handles both RA8876 and RA8875 3.5 and the jumpers/shunts also allo RA8875 4"
Unfortunately no. Probably should detect which Teensy device type is being used and error out if it is the wrong branch. I struggled with how the library should be laid out :unsure: Having it one branch and being a huge library with lots of defines to select or maybe separate libraries for each Teensy device. Either way I am open to suggestions at this point :D
With our ILI9486 version we tried to avoid the differences between 4.1 and MMOD, as the real difference was the T4.1 you mostly are restricted to FlexIO3 whereas MMOD you typically use FlexIO2. And FleXio2 has DMA whereas FlexIO3 does not. So I try to detect that, to configure how the
FlexIO code works... As Maybe on DevBoard 5 I might choose to setup on 2 or maybe on 3...

I do think having to use a different branch of the same library is problematic, as I may typically play around with different setups. Best way to handle it? good question! I am old school (or is that an old dog, who has difficulties with new tricks ?) Some might say maybe setup with Templates? Or if I was a true purist and doing it for a living, verus not an older hacker doing it for the fun of it, I would probably look into refactering all of the code, where all of the higher level primitives call into lower level primitives for the different setups, but typically those never are pure and often a PIA. For example, look at some of the setups built around a HAL, and we end up spending most of our time trying to work around the HAL...

Sorry, I probably have blabbed enough in this post.
 
I know that feeling. Been there... (actually most days)

Luckily I do now have both setups. That is I have two RA8876, one configured for SPI4 and the other for Parallel. I have the 2nd version of adapter board:
View attachment 34797
Not great, but it handles both RA8876 and RA8875 3.5 and the jumpers/shunts also allo RA8875 4"

With our ILI9486 version we tried to avoid the differences between 4.1 and MMOD, as the real difference was the T4.1 you mostly are restricted to FlexIO3 whereas MMOD you typically use FlexIO2. And FleXio2 has DMA whereas FlexIO3 does not. So I try to detect that, to configure how the
FlexIO code works... As Maybe on DevBoard 5 I might choose to setup on 2 or maybe on 3...

I do think having to use a different branch of the same library is problematic, as I may typically play around with different setups. Best way to handle it? good question! I am old school (or is that an old dog, who has difficulties with new tricks ?) Some might say maybe setup with Templates? Or if I was a true purist and doing it for a living, verus not an older hacker doing it for the fun of it, I would probably look into refactering all of the code, where all of the higher level primitives call into lower level primitives for the different setups, but typically those never are pure and often a PIA. For example, look at some of the setups built around a HAL, and we end up spending most of our time trying to work around the HAL...

Sorry, I probably have blabbed enough in this post.
I agree. I never have been a good programmer like you guys. Just kind of learn as I go. So, it's kinda hard to keep up and I really appreciate all of the hard work and time you guys have put in to help :D Probably will start with having each each branch check for the right hardware.
Thanks for the input...
 
I agree. I never have been a good programmer like you guys. Just kind of learn as I go. So, it's kinda hard to keep up and I really appreciate all of the hard work and time you guys have put in to help :D Probably will start with having each each branch check for the right hardware.
Thanks for the input...
I believe you have done a great job on this, as well as many other projects up here! Hopefully we are all having some fun!

When I mentioned things like refactoring, there are several of the libraries that I have played with, that comment applies to!
For example, at times I think about, it would be nice to refactoring several of the display libraries, like ILI9341_t3n, ILI9488_t3, HX8357_t.., ST7789..
To maybe have a common graphics library like Adafruit_GFX, and some lower-level common SPI code base.... That way makes it easier to extend, and fix common issues, maybe even document things. But then quickly run out of energy.

We are trying some, on a few of the newer projects, like the work that @mjs513 and a little from me, have done on some of the camera stuff and the ILI948x libraries. They both have some factoring in them.

The Camera stuff is using similar factoring like the Arducam library for the GIGA. Likewise, the parallel code for the ILI948x is setup with two libraries. A GFX library with the common higher level display functions, the other library to implement that does the primitive functions...

I might try a hack, to allow me to build for either parallel version or SPI version, by maybe having two copies (git clone) to two different directories.
Maybe add a new Header file for one or both of them. For example, in the 8080_T41 branch maybe have a file, maybe named:
RA8876_8080_t41.h (or the like. This header file simply has in it: #include "RA8876_t3.h"
It may also have some define in it, that allows me to determine in my sketch which version was included, and change things like pass DC into the constructor, changes in the Begin method...

And my test sketches for this branch could include it instead of directly the main header file... Yes, it is a kludge but might be sufficient for now.

Do whichever way you are comfortable with and hopefully continue to have fun
 
agree. I never have been a good programmer like you guys. Just kind of learn as I go. So, it's kinda hard to keep up and I really appreciate all of the hard work and time you guys have put in to help :D Probably will start with having each each branch check for the right hardware.
Thanks for the input...
Hey - don't include me that about being a good programmer - I find it just has hard to keep up sometimes especially with stuff like FlexIO!!!! PS I find google has become my best friend for how to do things in c++!!! As well as looking at how others have done things :) The main idea is to have fun as Kurt said.

But as @KurtE mentioned maybe renaming each library like I did for the t41_p so we can keep both versions active is a good place to start.
 
Well been playing with write rectangle functions: writeRect and writeRotatedRect. Came to the conclusion that something is still messed up with rotation!

Using the attached sketch for rotated rectangles that basically uses flexio_teensy_mm.c as a test image:

Code:
  for(uint8_t rotation = 0;  rotation < 4; rotation++) {
    tft.setRotation(rotation);
    displayRotation(rotation);
    nextPage();

    uint16_t *rotatedImage = tft.rotateImageRect(480, 320, flexio_teensy_mm, rotation);
    tft.writeRotatedRect(0, 0, 480, 320, rotatedImage );  // 480x320
    delete[] rotatedImage;
    nextPage();
  }

Still finding rotation 0 and 2 work but 1 and 3 not working. Has to be someplace in the bte calls. Example:
For rotation 0
IMG_1295.png

IMG_1296.png


But for rotation 1:
IMG_1297.png
IMG_1298.png


Its not using the whole screen - havent been able to figure it out:
 

Attachments

  • writeRotatedRect_ra8876-240626a.zip
    184.7 KB · Views: 34
@KurtE @mjs513 - Thanks for the pep talk :) Sometimes I take things to seriously. Comes from doing diagnostics for 40 or so years as a mechanic. I ran into the same problem with rectangles and completely forgot about it. Just ran RA8876_pictureEmbed using RA8876_t41_p from yesterday and is seems to be working ok. Don't remember what I changed. I'll test your new version of RA8876_t41_p...
 
@wwatson.

Think I got writerotatedrect sorted out but wtiterect still needs work I think. Rotations 0/2 work when writing an image like flexio_teensy_mm but with rotations 1/3 get the 2d fail messages. Was beginning to sort through it but got tired.

The example I posted probably shows it clearer than the embed picture sketch.
 
@wwatson.

Think I got writerotatedrect sorted out but wtiterect still needs work I think. Rotations 0/2 work when writing an image like flexio_teensy_mm but with rotations 1/3 get the 2d fail messages. Was beginning to sort through it but got tired.

The example I posted probably shows it clearer than the embed picture sketch.
Yeah, I am playing with that write now. I wonder if it has something to do with using internal fonts? I also noticed that in the readRect sketch some of the rotations, the copied color bars when written are one pixel off in both vertical and horizontal positioning. I not so bored now😅
 
Been playing both with @mjs513 version for Parallel and now master branch for SPI...
Note: I am making some of the same changes to this branch as I did to get Adafruit fonts working on the 8080 branch.

Also to hopefully not load in another library to find the ili9341_font.h file if you include some of Mikes ILI font library.

I am trying to get a limited version of my frame buffer test sketch. Started with the 8080 version for ILI948x.

Partially an exercise to see what APIS we don't have here, and which ones work or don't work.
I know we so far don't have frame buffer and Aync...

Things I had to comment out or the like to get the sketch to compile:
Code:
readPixel
readRect
//    tft.fillRectVGradient(125, 150, 50, 50, GREEN, YELLOW);
//    tft.fillRectHGradient(200, 150, 50, 50, YELLOW, GREEN);
//    tft.writeRect8BPP(200, 50, 50, 50, (uint8_t *)pixel_data, palette);
//    tft.writeRect1BPP(75, 100, 16, 16, pict1bpp, palette);
//    tft.writeRect2BPP(75, 125, 32, 16, pict2bpp, palette);
 //   tft.writeRectNBPP(15, 125, 32, 16, 2, pict2bpp, palette);
And I know this portion of code, will cause everything to screw up:
Code:
#if 0
    tft.setFontAdafruit();
    tft.setTextSize(2);
    tft.setTextColor(WHITE);
    tft.println("01234");
    tft.setTextColor(WHITE, GREEN);
    tft.println("56789!@#$%");
#endif
In the picture below, the top screen again is the SPI screen with those line ifdefed out
The bottom screen is the 8080 code with them include (#if 1)

So problem with us setting the default Adafruit font. Investigating
1719429560650.png
 
Yeah, I am playing with that write now. I wonder if it has something to do with using internal fonts? I also noticed that in the readRect sketch some of the rotations, the copied color bars when written are one pixel off in both vertical and horizontal positioning. I not so bored now
Yep. If you look close I added a 1or 2 pixel shift to add a border around the first so doesn't surprise me.

I am trying to get a limited version of my frame buffer test sketch. Started with the 8080 version for ILI948x.

Partially an exercise to see what APIS we don't have here, and which ones work or don't work.
I know we so far don't have frame buffer and Aync...
closest we got is a useCanvas() which draws to a second page and swaps with the current page using updateScreen(). Havent really tested it yet

getPixel should work to draw the colorbar - extracted that code piece in the other sketch.

for setFontAdrafruit you could substitute setFont(const GFXfont *f) - a little longer but..
 
@mjs513 - Switched to graphic fonts in the writerotatedrect sketch and that worked correctly. So now to see why the internal fonts screw up...
 
@wwatson - what font are you using - right now writeTRotatedRect_RA8876 using on arial_14:
tft.setFont(Arial_14);

this is when it tries to use writeRect without rotation first.

IMG_1302.png
 
@mjs513 - I sent you an update to your library .cpp file that hopefully fixed the default font output: setFont(); or setFontAdafruit();

@wwatson - I created a PR with this on the master branch. Plus the other font things I did yesterday for the other branch...
Take a look and see what you think:
1719445049255.png
 
@mjs513 - This is the writeRotatedRect_ra8876.ino file oout of the testcases folder:
MM_Image.jpg

And graphic font which is good in all rotations:
Internal_Font_rotate.jpg

Here the graphic font is working when rotated.
And the sketch:
Code:
// Set which Display we are using and at what speed
// Currently I have options for both MICROMOD and T42 to make it
// easier for testing

#include "Arduino.h"
#include "RA8876_t41_p.h"
#include "font_Arial.h"
#include "flexio_teensy_mm.c"
#include "T41_top_card.c"

uint8_t dc = 13;
uint8_t cs = 11;
uint8_t rst = 12;

RA8876_t41_p tft = RA8876_t41_p(dc,cs,rst); //(dc, cs, rst)

void setup() {
    Serial.begin(115200);
    delay(1000);
    if (CrashReport) {
        Serial.print(CrashReport);
    }

  tft.begin(20); // 20 is working in 8bit and 16bit mode on T41
  tft.graphicMode(true);
  tft.setTextCursor(0,0);
  tft.setFont(Arial_14);


  for(uint8_t rotation = 0;  rotation < 4; rotation++) {
    tft.setRotation(rotation);
    displayRotation(rotation);
    delay(1000);
    tft.fillScreen(BLACK);
  }

  tft.setRotation(0);

}

void loop() {
  for(uint8_t rotation = 0;  rotation < 4; rotation++) {
    tft.setRotation(rotation);
    displayRotation(rotation);
    nextPage();

    uint16_t *rotatedImage = tft.rotateImageRect(400, 272, td_t4_top, rotation);
    tft.writeRotatedRect(CENTER, CENTER, 400, 272, rotatedImage );  // 480x320
    free(rotatedImage);
    nextPage();
    rotatedImage = tft.rotateImageRect(480, 320, flexio_teensy_mm, rotation);
    tft.writeRotatedRect(CENTER, CENTER, 480, 320, rotatedImage );  // 480x320
    free(rotatedImage);
    nextPage();
    tft.writeRect(CENTER, CENTER, 480, 320, flexio_teensy_mm );  // 480x320
    nextPage();
  }
}

void nextPage()
{
  Serial.println("Press anykey to continue");
  while (Serial.read() == -1) ;
  while (Serial.read() != -1) ;

  tft.fillScreen(BLACK);
}

void displayRotation(uint8_t rotation) {
  tft.fillScreen(RED);
  tft.setCursor(tft.width()/2, tft.height()/2, true);
  tft.printf("Rotation: %d", rotation);
  Serial.printf("WIDTH: %d, HEIGHT: %d\n", tft.width(), tft.height());
  tft.setCursor(200, 300);
  Serial.printf("  Set cursor(200, 300), retrieved(%d %d)",
                tft.getCursorX(), tft.getCursorY());
  tft.setCursor(50, 50);
  tft.write('0');
  tft.setCursor(tft.width() - 50, 50);
  tft.write('1');
  tft.setCursor(50, tft.height() - 50);
  tft.write('2');
  tft.setCursor(tft.width() - 50, tft.height() - 50);
  tft.write('3');
}

Weird, it all seems to be working on my end. Also:
Code:
 Used: /home/wwatson/Arduino/libraries/ILI9341_fonts
 Not used: /home/wwatson/arduino-1.8.19-1.59/hardware/teensy/avr/libraries/ILI9341_t3
Using library Ra8876LiteTeensy-RA8876_t41_p at version 1.0.0 in folder: /home/wwatson/Arduino/libraries/Ra8876LiteTeensy-RA8876_t41_p
Using library FlexIO_t4 at version 1.0.0 in folder: /home/wwatson/arduino-1.8.19-1.59/hardware/teensy/avr/libraries/FlexIO_t4
Using library ILI9341_fonts at version 1.0 in folder: /home/wwatson/Arduino/libraries/ILI9341_fonts
/home/wwatson/arduino-1.8.19-1.59/hardware/teensy/../tools/teensy_post_compile -file=writeRotatedRect_ra8876.ino -path=/tmp/arduino_build_515922 -tools=/home/wwatson/arduino-1.8.19-1.59/hardware/teensy/../tools -board=TEENSY41 -reboot -port=/sys/devices/pci0000:00/0000:00:02.1/0000:01:00.0/usb1/1-2 -portlabel=/dev/ttyACM0 Serial -portprotocol=Teensy
Not sure what's happening on your setup:(
EDIT: Sorry, graphic fonts are working when rotated but internal fonts are not...
 
Last edited:
Not sure what's happening on your setup:(
Not sure either - copied your version and got the same thing:

Code:
Multiple libraries were found for "font_Arial.h"
  Used: D:\Users\Merli\Documents\Arduino\libraries\ILI9341_fonts-master
  Not used: C:\Users\Merli\AppData\Local\Arduino15\packages\teensy\hardware\avr\1.59.0\libraries\ILI9341_t3
Using library Ra8876Lite-8080-T41 at version 1.0.0 in folder: D:\Users\Merli\Documents\Arduino\libraries\RA8876_t41_p
Using library FlexIO_t4 at version 1.0.0 in folder: C:\Users\Merli\AppData\Local\Arduino15\packages\teensy\hardware\avr\1.59.0\libraries\FlexIO_t4
Using library ILI9341_fonts at version 1.0 in folder: D:\Users\Merli\Documents\Arduino\libraries\ILI9341_fonts-master

Have to investigate more in the morning
 
@KurtE and @wwatson

Lied a bit.
1. Updated the _p branch to @KurtE's drawChar changes
and
2. Figured out my issue with the sketch. Chanaged clock from 20 to 18 and it worked.

EDIT: Back to running at 20Mhz. Forgot to uncomment delaynanoseconds (missed a change)
Code:
delayNanoseconds(10);  // Initially setup for the T4.1 board
Change pushed to branch
 
Last edited:
Back
Top