Playing around with yet another version of ILI9341_t3 library (ILI9341_t3n)

Kurt, thanks for updating the function to draw fonts using the frame buffer! It's so cool to play around with, but I just can't get it working in my program. I really wish I could narrow it down but I can't seem to reproduce it in an example sketch. Since I can't and I have very involved hardware, I don't expect any help or anything, just complaining because I can't use this awesome feature until I figure it out.
As you said, not sure what I can do to help debug your setup. Might help to know what is hooked up to what...
Here is the quick and dirty test program I have tried some stuff out on, including make sure some of the new gradient fills are working...

I assume you did a sync up to the stuff in github...

Let me know if there is something for me to look at.

Kurt

EDIT: Forgot to mention, the test app, waits for you to enter something at the terminal window, and then redraws a sample screen. Each time alternating with FB OFF (black background), FB ON (read background)
 

Attachments

  • zzz-161103a.zip
    87.5 KB · Views: 166
Now doing some testing with my new board... Most of the test works.

Tried adding a readRect/writeRect to my test screen, works with my Frame Buffer, does not work with reading from the actual screen... Debugging. Also found that I have not updated this code to properly work with SPI1 and SPI2 as code relies on popping off 3 entries from the receive queue, which only holds 1 item... So still need to update readPixel and readRect.
 
As you said, not sure what I can do to help debug your setup. Might help to know what is hooked up to what...
Here is the quick and dirty test program I have tried some stuff out on, including make sure some of the new gradient fills are working...

I assume you did a sync up to the stuff in github...

Let me know if there is something for me to look at.

Kurt

EDIT: Forgot to mention, the test app, waits for you to enter something at the terminal window, and then redraws a sample screen. Each time alternating with FB OFF (black background), FB ON (read background)

I don't think it's a hardware issue because I'm using the base _t3 library, your variant, and frank's variant all on the same hardware for different testing. But yeah, I think I'll just have to track it down at this point because there's too much involved to expect anyone to replicate what I've got going on. I've started adding things in one at a time to the working test to see what might break it but no luck yet! If I uncover anything that could help others I'll be sure to share.
 
Thanks Paul,

Having fun, the main reason I made this version was to allow it to work with all of the different SPI configurations on the new Teensy boards. But then Frank's great work inspired me to add Frame buffer support...

SandalHat: It would be good to know what IO pins you are using to connect up the display. The main difference with my version and the others is that I abstracted out the SPI code, to hopefully make it work on the all three SPI ports on a T3.5/6 and it is possible I missed some pin or the like. Or I missed a change that was made...

Thanks again

Update: Fixed one compatibility issue, looks like drawing with fontChar support was added in main library to advance the cursor correctly when CR is used... So merged in that fix
 
Last edited:
As you good people have vastly improved display driver code, have become interested in a display upgrade for our box, so a display-related question - spec sheet available for this display? Is this representative?

http://download.mikroe.com/documents/datasheets/tft-320x240px-mi0283qt-9a-v1.3-datasheet.pdf

Most interested in ratings for ambient temperature, input V immunity, ESD immunity, and if suitable assembly to meet CISPR22 class B limits for ITE; that is, is the unit happy to do I/O with low dv/dt on digital stream?

Thanks much.
 
This sounds very cool! Did I miss a note on Touch? >> To use Touch it would have to use an alternate SPI? Or on SAME SPI use the Interrupt detection code to stop and start the AUTO DMA updates and go SLOW MO normal during touch event. That should be easy to do right inside the TOUCH library code if there is an easy way to detect and disable/enable the AUTO refresh of the ILI9341. Probably take 5 minutes with those details. Would add a global and that 'detect' test on TOUCH Start (and wait for all clear on the display CS?) and global check on TOUCH Stop.

ILI9163C :: The ILI9341 has 4.68 times the pixels - if this worked on that 1.4" 128x128 display work Sumotoy did it would be really fast and take about 32K ram and could run on some T_3.2's?
 
Hi Defragster,

Probably more a question for Frank's DMA version. Mine just uses normal SPI stuff, so the touch should be the same. The main thing in mine is you can turn on frame buffer support and then all graphics go to the memory instead of screen and then the explicitly call an update screen call that takes the memory image and outputs it. I know that this may not be as good of an approach for things like video output, but nice for things where you may have more things you wish to update...
 
Busted - you can tell I'm watching this stuff go by but not tracking without time to look specifically. That explains the difference I missed, and indeed the Touch with your buffered mod should work without any change - If I understand ... as long as a Touch isn't tested/processed while the 'background' DMA is busy? - so it might need a way to process a DMA_wait()? Perhaps just a check for the equivalent of display CS asserted in the Touch code?

Indeed for dynamic, but not LIVE updates your scheme seems like a good improvement (given RAM) to minimize processor load/wait and flash/flicker with on the fly updates to the active screen space. I did a cross post to Frank's thread.

The noted use of your scheme on the ILI9163C would be awesome - even on a T_3.2 using only half of RAM (is it two bytes per pixel?).
 
Quick update and follow up with the opaque drawFontChar,

I updated my own library to have a version of the code that works like drawChar does with opaque. So it does one spi begin transaction at the start with the full rectangle to be output and computes each pixel in order. So should run more or less same speed as fillRect...

As part of this found I had not implemented version of drawChar tha output to the FB in opaque mode. Now does, likewise for this new drawFontChar.

Code probably still needs a little cleanup to reduce some duplicated code.
 
Is there an Eagle schematic library component for this display? An afternoon of searching finds nothing suitable. The closest is an Adafruit ILI9325.
 
I don't know of any. Also I am not an Eagle user, I use Diptrace.

Not sure which of the displays you as asking about. For my own stuff, I sort of setup a diptrace pattern, for the 2.8" touch display, that I initially used to help me layout my board similar to Frank's flexiboard, but then now just use a 1x14 connector and I also added mounting holes that match...
 
Currently I am working on trying to integrate the ability to set an origin and clipping rectangle to this library, to semi match the work that Blackketter has done as part of his fork of the main ili9341_t3 library and has a current outstanding pull request.

I think I have lots of the pieces in place, but need to do a lot of testing plus update some more locations in the code. I have pushed up a version of the code up to my github project under a new branch: Offset_Clip_rect.

I have not actually updated any of my test code to use these, but so far at least it looks like they still work in the default mode.

Just made a pass through updating the drawChar code to hopefully properly handle the clipping rectangle. The code needs to do things like only output those pixels that are actually contained in the clip rectangle (so you need to first calculate that before you call setAddr for the rectangle of colors that will be updated. You then need to synchronize where you are in the font char...

I need to also do this within my new transparent drawFontChar code.

But as part of this, there are several things I am not sure what is the correct or desired thing to do.
Example: Should readRect and readPixel use the offsets? Should they clip as well?

When you set a clipping rectangle and you do a text output, the includes CR, should the code set X to 0 or to the origin of the clip rectangle or to the X Offset? ...

Note: the places I can see where I may wish to use something like the clip rectangle is suppose I wish to draw something like a button, with a Font and I don't want all of the space below the actual text to be drawn to align with the font spacing...

Now back to playing around
 
Hello from a new Teensy and ILI9341 user!
I just got the Teensy 3.5 and 3.6 boards, as well as the 2.2 and 2.8-inch TFTs from PJRC. Already fixed a bug in fillRectHGradient() and submitted a pull request :)
I've been reading/skimming through the existing threads about the ILI9341 libraries. Thank you Paul, Kurt, Frank, and others for all the hard work and continuous improvements!

Should readRect and readPixel use the offsets? Should they clip as well?
Personally it feels like clipping should only apply to drawing commands. I can't see much reason to clip the data that's read from the screen. The origin offset should probably apply to reading - it would be strange to draw something at x,y, and not get the same value back by reading from x,y.

When you set a clipping rectangle and you do a text output, the includes CR, should the code set X to 0 or to the origin of the clip rectangle or to the X Offset?
Clip rectangle should be independent - if you set the clip region and output multiple lines of text (or draw shapes), everything should appear as if it was drawn normally, but only change the pixels inside the clip region.


I'm very interested in contributing more - should I start a separate thread for my questions/discussion, or post in the original ILI9341_t3 thread?
 
Last edited:
Hi Michael : Thanks for the feedback.

I agree that the clipping should probably be for write operations only...

I have also left the drawText to wrap as you mentioned, otherwise could be confusing. However I do see it could be beneficial inside things like some text rectangle you wish to use that only uses part of the screen...

In case anyone is following, I just uploaded some more changes to handle clipping and origin. In particular font characters. In non opaque it was being handled by every single draw operation it did. But for opaque, I had to carefully update the rectangle being updated and offset the appropriate amount in the character... Still need to test it!
 
A separate text output rectangle would indeed be useful. Maybe there should be a setTextRect() to define the text output area? After calling the function, any subsequent text output would be limited to that rectangle instead of the entire screen (and wrap accordingly). It could then still be used together with the clip rect to make text partially hidden if needed - either for optimization or more advanced UI like a scrollable text field.

Are you just doing testing manually by writing new code, or do you have some existing test cases set up? I've been thinking of writing a small unit test framework to read back the image data after performing drawing commands, and compare the output to previously recorded bitmaps. This would help catch any regressions or differences between the several forks of the library. I would probably start by using the existing example code to get some initial output data, and then see if some variations are needed to cover more cases. And when bugs are found and fixed, relevant test cases can be added to avoid further breakages.
 
Hi Michael,

For now I will probably pass on adding new things like that. I was mainly trying to bring in all of the things that were in open Pull requests that looked interesting.

Some of the drawFontChar stuff, including such as opaque support, but wondered if it could be done like it is with drawChar so did that, now working on the Origin, clipping code. Again lot of these API and functional changes are in the PR (https://github.com/PaulStoffregen/ILI9341_t3/pull/13)

Testing, so far, I am simply using some of my own Test stuff, to see what obviously breaks or does not break.

Yes it would be great to have a complete automated test suite to goes through many of the permutations of the API, including boundary cases, like when I used to work... It would be great if someone wrote at least a simple subset of it and we added it as a Example APP for the display

As for reading out the pixels, I was running into issues with it awhile ago and it appears like, was not fully following the specification for the read. It was working for me earlier but not on my current touch screen from PJRC. At appears that when we are reading pixel data we should be sending out 0x3f bytes not 0x00. I made that change and the reading started working.
That change is currently in the PR: https://github.com/PaulStoffregen/ILI9341_t3/pull/36

The current test I am running to see if some of the graphic primitives work, both in normal mode as well as in my Frame buffer mode, simply draws a test screen (each time I enter a line at the terminal window). It alternates from Normal to Frame buffer, so I can see if something is not drawing or drawing wrong.

I then added a second screen, that simply draws a sample screen with the Bold Font that is part of the library in several different sizes. It draws in the current (Frame buffer or not) mode and if the line I entered started with 't' it draws it transparent. If it starts with a 'o' it draws it opaque. Found several cases I needed to fix in my code with this, when for example the font characters were not fully drawn within what I thought was bounding rectangle...

Next up, I will probably throw in it something like a 'c' - command, which adds a clip rectangle, maybe for center half of screen, and then try the different combinations and see what things look like they are working right. Then maybe a command to set the origin and again...

Again this currently is not a great test, I just keep throwing stuff in it as I find things that are not working (mostly with the Frame buffer code)
Code:
#include <font_Arial.h>
#include <font_ArialBoldX.h>
#include <ILI9341_t3n.h>

#include <SPIN.h>
#include "SPI.h"
#define KURTS_FLEXI
#ifdef KURTS_FLEXI
#define TFT_DC 22
#define TFT_CS 15
#define TFT_RST -1
#define TFT_SCK 14
#define TFT_MISO 12
#define TFT_MOSI 7
#define DEBUG_PIN 13
#else
#define TFT_DC  9
#define TFT_CS 10
#define TFT_RST 7
#define TFT_SCK 13
#define TFT_MISO 12
#define TFT_MOSI 11
#endif
ILI9341_t3n tft = ILI9341_t3n(TFT_CS, TFT_DC, TFT_RST, TFT_MOSI, TFT_SCK, TFT_MISO, &SPIN);
Adafruit_GFX_Button button;
uint8_t use_fb = 0;

void setup() {
  while (!Serial && (millis() < 4000)) ;
  Serial.begin(115200);
  tft.begin();
  tft.fillScreen(ILI9341_BLACK);

  // read diagnostics (optional but can help debug problems)
  uint8_t x = tft.readcommand8(ILI9341_RDMODE);
  Serial.print("Display Power Mode: 0x"); Serial.println(x, HEX);
  x = tft.readcommand8(ILI9341_RDMADCTL);
  Serial.print("MADCTL Mode: 0x"); Serial.println(x, HEX);
  x = tft.readcommand8(ILI9341_RDPIXFMT);
  Serial.print("Pixel Format: 0x"); Serial.println(x, HEX);
  x = tft.readcommand8(ILI9341_RDIMGFMT);
  Serial.print("Image Format: 0x"); Serial.println(x, HEX);
  x = tft.readcommand8(ILI9341_RDSELFDIAG);
  Serial.print("Self Diagnostic: 0x"); Serial.println(x, HEX);
#ifdef DEBUG_PIN
  pinMode(DEBUG_PIN, OUTPUT);
#endif

  button.initButton(&tft, 200, 100, 100, 40, ILI9341_GREEN, ILI9341_YELLOW, ILI9341_RED, "UP", 1);

  drawTestScreen();
}

uint16_t pixel_data[2500];

void drawTestScreen() {
  Serial.printf("Use FB: %d ", use_fb); Serial.flush();
  uint32_t start_time = millis();
  tft.useFrameBuffer(use_fb);
  tft.fillScreen(use_fb ? ILI9341_RED : ILI9341_BLACK);
  tft.setRotation(3);
  //tft.setFont(Inconsolata_60);
  tft.setFont(Arial_24_Bold);
  tft.setTextColor(ILI9341_WHITE);
  tft.setCursor(0, 0);
  tft.println("Test");
  tft.setTextColor(ILI9341_WHITE, ILI9341_RED);
  tft.println("text");
  tft.setFontAdafruit();
  tft.setTextSize(2);
  tft.setTextColor(ILI9341_WHITE);
  tft.println("01234");
  tft.setTextColor(ILI9341_WHITE, ILI9341_GREEN);
  tft.println("5,6,7,8,9");  

  tft.drawRect(0, 150, 100, 50, ILI9341_WHITE);
  tft.drawLine(0, 150, 100, 50, ILI9341_GREEN);
  tft.fillRectVGradient(125, 150, 50, 50, ILI9341_GREEN, ILI9341_YELLOW);
  tft.fillRectHGradient(200, 150, 50, 50, ILI9341_YELLOW, ILI9341_GREEN);
  // Try a read rect and write rect
#ifdef DEBUG_PIN
  digitalWrite(DEBUG_PIN, HIGH);
#endif

  tft.readRect(0, 0, 50, 50, pixel_data);

#ifdef DEBUG_PIN
  digitalWrite(DEBUG_PIN, LOW);
#endif
  tft.setFontAdafruit();
  button.drawButton();

  tft.writeRect(250, 0, 50, 50, pixel_data);
  tft.updateScreen();

  Serial.println(millis() - start_time, DEC);

  use_fb = !use_fb;

}

void drawTextScreen(bool fOpaque) {
  uint32_t start_time = millis();
  tft.useFrameBuffer(use_fb);
  tft.fillScreen(use_fb ? ILI9341_RED : ILI9341_BLACK);
  tft.setRotation(3);
  tft.setFont(Arial_40_Bold);
  if (fOpaque)
    tft.setTextColor(ILI9341_WHITE, use_fb ? ILI9341_BLACK : ILI9341_RED);
  else
    tft.setTextColor(ILI9341_WHITE);
  tft.setCursor(0, 5);
  tft.println("AbCdEfGhIj");
  tft.setFont(Arial_28_Bold);
  tft.println("0123456789!@#$");
 #if 1
  tft.setFont(Arial_20_Bold);
  tft.println("abcdefghijklmnopq");
  tft.setFont(Arial_14_Bold);
  tft.println("ABCDEFGHIJKLMNOPQRST");
  tft.setFont(Arial_10_Bold);
  tft.println("0123456789zyxwvutu");
 #endif 
  tft.updateScreen();

  Serial.printf("Use FB: %d OP: %d, DT: %d\n", use_fb, fOpaque, millis()-start_time); 
}

void loop(void) {
  // See if any text entered
  int ich;
  if ((ich=Serial.read()) != -1) {
    while (Serial.read() != -1) ;

    if (ich == 'o')
      drawTextScreen(1);
    else if (ich == 't')
      drawTextScreen(0);
    else    
      drawTestScreen();
  }

}
 
Yeah, I didn't mean you should add more functionality right now, just wanted to throw the idea out there. I might even end up contributing the patch myself.
I'll start working on the test framework, and probably start a separate thread once I make sufficient progress. Thanks for your test code, I'll look through it for inspiration :)

I posted a comment on your pull request for readRect() - I'm not seeing the same issue with the existing code with 0x00.
 
Thanks, the test app, I posted above was not working, without the change. I do a readRect followed by a writeRect which should copy a character or two from the left hand of the display toward the right hand side. Will look more later. Right now debugging clip rectangle stuff.

Hacked the code above that if I enter the 'c' command, when you create one of the other displays, it will clear the clip rectangle, set the frame buffer mode, fill the whole screen with light gray, setup a rectangle that is centered with about half the width and height, draw a dark gray rectangle. It then sets the clip rectangle one pixel inside of this rectangle and then does the code for the screen...

Fixed a few issues so far. Right now debugging Opaque text...
 
Your test is working fine for me, on both the 2.2-inch screen and the 2.8-inch touchscreen. I tried with both ILI9341_t3 and ILI9341_t3n. Would be interesting to verify it's it's really a hardware issue, or maybe something else is different between our setups.

I was able to reproduce the unrelated issue of readRect() not reading the last pixel, though that's certainly just a software bug: https://github.com/PaulStoffregen/ILI9341_t3/issues/29
 
It is interesting. I tried again with pushing a 0 instead of 0x3f and the read returned 0...

I actually changed it to a #define in the last update to github (Note: still working in the Offset_Clip_rect branch).

Updated test program:
Code:
#include <font_Arial.h>
#include <font_ArialBoldX.h>
#include <ILI9341_t3n.h>

#include <SPIN.h>
#include "SPI.h"
#define KURTS_FLEXI
#ifdef KURTS_FLEXI
#define TFT_DC 22
#define TFT_CS 15
#define TFT_RST -1
#define TFT_SCK 14
#define TFT_MISO 12
#define TFT_MOSI 7
#define DEBUG_PIN 13
#else
#define TFT_DC  9
#define TFT_CS 10
#define TFT_RST 7
#define TFT_SCK 13
#define TFT_MISO 12
#define TFT_MOSI 11
#endif
ILI9341_t3n tft = ILI9341_t3n(TFT_CS, TFT_DC, TFT_RST, TFT_MOSI, TFT_SCK, TFT_MISO, &SPIN);
Adafruit_GFX_Button button;
uint8_t use_fb = 0;
uint8_t use_clip_rect = 0;

void setup() {
  while (!Serial && (millis() < 4000)) ;
  Serial.begin(115200);
  tft.begin();
  tft.setRotation(3);
  tft.fillScreen(ILI9341_BLACK);

  // read diagnostics (optional but can help debug problems)
  uint8_t x = tft.readcommand8(ILI9341_RDMODE);
  Serial.print("Display Power Mode: 0x"); Serial.println(x, HEX);
  x = tft.readcommand8(ILI9341_RDMADCTL);
  Serial.print("MADCTL Mode: 0x"); Serial.println(x, HEX);
  x = tft.readcommand8(ILI9341_RDPIXFMT);
  Serial.print("Pixel Format: 0x"); Serial.println(x, HEX);
  x = tft.readcommand8(ILI9341_RDIMGFMT);
  Serial.print("Image Format: 0x"); Serial.println(x, HEX);
  x = tft.readcommand8(ILI9341_RDSELFDIAG);
  Serial.print("Self Diagnostic: 0x"); Serial.println(x, HEX);
#ifdef DEBUG_PIN
  pinMode(DEBUG_PIN, OUTPUT);
#endif

  button.initButton(&tft, 200, 100, 100, 40, ILI9341_GREEN, ILI9341_YELLOW, ILI9341_RED, "UP", 1);

  drawTestScreen();
}

uint16_t pixel_data[2500];

void SetupOrClearClipRect() {
  if (use_clip_rect) {
    tft.setClipRect();  // make sure we clear the whole screen
    tft.fillScreen(ILI9341_LIGHTGREY);
    int x = tft.width() / 4;
    int y = tft.height() / 4;
    int w = tft.width() / 2;
    int h = tft.height() / 2;
    tft.drawRect(x, y, w, h, ILI9341_ORANGE);
    tft.updateScreen();
    tft.setClipRect(x + 1, y + 1, w - 2, h - 2);
    delay(250);

  } else {
    tft.setClipRect();
  }
}


void drawTestScreen() {
  Serial.printf("Use FB: %d ", use_fb); Serial.flush();
  tft.useFrameBuffer(use_fb);
  SetupOrClearClipRect();
  uint32_t start_time = millis();
  tft.fillScreen(use_fb ? ILI9341_RED : ILI9341_BLACK);
  //tft.setFont(Inconsolata_60);
  tft.setFont(Arial_24_Bold);
  tft.setTextColor(ILI9341_WHITE);
  tft.setCursor(0, 0);
  tft.println("Test");
  tft.setTextColor(ILI9341_WHITE, ILI9341_RED);
  tft.println("text");
  tft.setFontAdafruit();
  tft.setTextSize(2);
  tft.setTextColor(ILI9341_WHITE);
  tft.println("01234");
  tft.setTextColor(ILI9341_WHITE, ILI9341_GREEN);
  tft.println("56789!@#$%");

  tft.drawRect(0, 150, 100, 50, ILI9341_WHITE);
  tft.drawLine(0, 150, 100, 50, ILI9341_GREEN);
  tft.fillRectVGradient(125, 150, 50, 50, ILI9341_GREEN, ILI9341_YELLOW);
  tft.fillRectHGradient(200, 150, 50, 50, ILI9341_YELLOW, ILI9341_GREEN);
  // Try a read rect and write rect
#ifdef DEBUG_PIN
  digitalWrite(DEBUG_PIN, HIGH);
#endif

  tft.readRect(0, 0, 50, 50, pixel_data);

#ifdef DEBUG_PIN
  digitalWrite(DEBUG_PIN, LOW);
#endif
  tft.setFontAdafruit();
  button.drawButton();

  tft.writeRect(250, 0, 50, 50, pixel_data);
  tft.updateScreen();

  Serial.println(millis() - start_time, DEC);

  use_fb = !use_fb;

}

void drawTextScreen(bool fOpaque) {
  SetupOrClearClipRect();
  uint32_t start_time = millis();
  tft.useFrameBuffer(use_fb);
  tft.fillScreen(use_fb ? ILI9341_RED : ILI9341_BLACK);
  tft.setFont(Arial_40_Bold);
  if (fOpaque)
    tft.setTextColor(ILI9341_WHITE, use_fb ? ILI9341_BLACK : ILI9341_RED);
  else
    tft.setTextColor(ILI9341_WHITE);
  tft.setCursor(0, 5);
  tft.println("AbCdEfGhIj");
  tft.setFont(Arial_28_Bold);
  tft.println("0123456789!@#$");
#if 1
  tft.setFont(Arial_20_Bold);
  tft.println("abcdefghijklmnopq");
  tft.setFont(Arial_14_Bold);
  tft.println("ABCDEFGHIJKLMNOPQRST");
  tft.setFont(Arial_10_Bold);
  tft.println("0123456789zyxwvutu");
#endif
  tft.updateScreen();

  Serial.printf("Use FB: %d OP: %d, DT: %d\n", use_fb, fOpaque, millis() - start_time);
}

void loop(void) {
  // See if any text entered
  int ich;
  if ((ich = Serial.read()) != -1) {
    while (Serial.read() != -1) ;
    if (ich == 'c') {
      use_clip_rect = !use_clip_rect;
      if (use_clip_rect) Serial.println("Clip Rectangle Turned on");
      else Serial.println("Clip Rectangle turned off");
      return;
    }
    if (ich == 'o')
      drawTextScreen(1);
    else if (ich == 't')
      drawTextScreen(0);
    else
      drawTestScreen();
  }

}
This has the 'c' command to put in a clip rectangle in center. Found several issues, hopefully fixed. Will probably next add command to do offset, and maybe variations of where the clip rectangle goes...
 
Not sure who else may be interested, but yesterday I then started experimenting with test case optionally setting origin at 50, 50 to see how things responded. My test program is a set of kludges, but does allow me to try several combinations.

The first thing I found with this, is it then shifted some of the location of my test case that did readRect/writeRect to where some of the writeRect was clipped. And it was all screwed up.
Earlier just did simple clipping, like we do in fillRect. The problem is that you need to synchronize which words are in the pcolors array go with which actual pixels on the screen.
I can easily ignore everything where the y goes outside of the lower clip rectangle as we are done then. For all the rows that are above our top clip rectangle, can advance the pcolors by the number of clipped rows * width. For left and right, I now remember how many pixels were clipped on the left and on the right and advance the pcolors by that many at the start of a row output and end of row output, similar to what happens with draw text...

Sort of messy!
Code:
void ILI9341_t3n::writeRect(int16_t x, int16_t y, int16_t w, int16_t h, const uint16_t *pcolors)
{

	x+=_originx;
	y+=_originy;
	uint16_t x_clip_start = 0;  // How many entries at start of colors to skip at start of row
	uint16_t x_clip_end = 0;    // how many color entries to skip at end of row for clipping
	// Rectangular clipping 

	// See if the whole thing out of bounds...
	if((x >= _displayclipx2) || (y >= _displayclipy2)) return;
	if (((x+w) <= _displayclipx1) || ((y+h) <= _displayclipy1)) return;

	// In these cases you can not do simple clipping, as we need to synchronize the colors array with the
	// We can clip the height as when we get to the last visible we don't have to go any farther. 
	// also maybe starting y as we will advance the color array. 
 	if(y < _displayclipy1) {
 		int dy = (_displayclipy1 - y);
 		h -= dy; 
 		pcolors += (dy*w); // Advance color array to 
 		y = _displayclipy1; 	
 	}

	if((y + h - 1) >= _displayclipy2) h = _displayclipy2 - y;

	// For X see how many items in color array to skip at start of row and likewise end of row 
	if(x < _displayclipx1) {
		x_clip_start = _displayclipx1-x; 
		w -= x_clip_start; 
		x = _displayclipx1; 	
	}
	if((x + w - 1) >= _displayclipx2) {
		x_clip_end = w;
		w = _displayclipx2  - x;
		x_clip_end -= w; 
	} 

	if (_use_fbtft) {
		uint16_t * pfbPixel_row = &_pfbtft[ y*_width + x];
		for (;h>0; h--) {
			uint16_t * pfbPixel = pfbPixel_row;
			pcolors += x_clip_start;
			for (int i = 0 ;i < w; i++) {
				*pfbPixel++ = *pcolors++;
			}
			pfbPixel_row += _width;
			pcolors += x_clip_end;

		}
		return;	
	}

   	beginSPITransaction();
	setAddr(x, y, x+w-1, y+h-1);
	writecommand_cont(ILI9341_RAMWR);
	for(y=h; y>0; y--) {
		pcolors += x_clip_start;
		for(x=w; x>1; x--) {
			writedata16_cont(*pcolors++);
		}
		writedata16_last(*pcolors++);
		pcolors += x_clip_end;
	}
	endSPITransaction();
}

Now need to update writeRect8BPP should be easy to copy and paste here. then writeRect4BPP/writeRect2BPP/writeRect1BPP. These ones will be a little more complicated as you can't just increment words or bytes by an amount, but maybe partial units...
 
Update:

I believe I have updated all of the functions now like writeRect8BPP to work with the offsetting and clipping. After I implemented the 1BPP and the 2BPP, I made a version called:
writeRectNBPP, where N could be 1, 2, 4, 8. I then had the 1, 2 and 4 version simply call this one. I left the 8 one as it's own as it increments in full bytes...

I then decided to make my Frame Buffer code in here optional. So I added a #define which only get's defined on T3.5 and T3.6 and only if there is not a don't define defined... Might be able to use Frank's stuff to allow per sketch options.

I then decided to go ahead and merge all of this back into my master branch.

Later I may add additional #ifdef code, like maybe disable some of the clipping code. But for now I think I will get back to other interrupts.

Update: I also decided to update the Readme as part of my SPIN class as it might be useful
 
Last edited:
I haven't had a chance to try your latest updates yet, but I have some questions about earlier changes you added to readRect:
https://github.com/KurtE/ILI9341_t3n/commit/bed92a1baf8013c220af4ce14c5dd552e26e02b7

Code:
_pkinetisk_spi->PUSHR = 0 | (pcs_data << 16) | SPI_PUSHR_CTAS(0)| SPI_PUSHR_CONT | SPI_PUSHR_EOQ;

_pkinetisk_spi->PUSHR = 0 | (pcs_data << 16) | SPI_PUSHR_CTAS(0)| SPI_PUSHR_CONT;

Why is this is pushing two dummy bytes instead of just one?

Code:
while ((_pkinetisk_spi->SR & SPI_SR_EOQF) == 0)  {
	// maybe keep queue with something in it, while waiting for that EOQF 
	if ((_pkinetisk_spi->SR & (15 << 12)) == 0) {
   		_pkinetisk_spi->PUSHR = READ_PIXEL_PUSH_BYTE | (pcs_data << 16) | SPI_PUSHR_CTAS(0)| SPI_PUSHR_CONT;
		c--;			
	}
}

_pkinetisk_spi->SR = SPI_SR_EOQF;  // make sure it is clear
while ((_pkinetisk_spi->SR & 0xf0)) {
	dummy = _pkinetisk_spi->POPR;	// Read a DUMMY byte but only once
}

Trying to keep the TX FIFO full while waiting for the read is a nice idea, but isn't there a chance that this could cause a problem by reading actual pixel data if it's added to the RX FIFO before the dummy byte is read out?
 
Back
Top