Forum Rule: Always post complete source code & details to reproduce any issue!
Page 1 of 4 1 2 3 ... LastLast
Results 1 to 25 of 95

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

  1. #1
    Senior Member KurtE's Avatar
    Join Date
    Jan 2014
    Posts
    2,848

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

    As I have mentioned in some of the Beta threads for T3.5/T3.6, I hacked up a version of the ILI9341_t3 library, to make a version of it that I can use on any of the SPI busses on the processor.

    So I created a duplicate of the library that I called ILI9341_t3n (https://github.com/KurtE/ILI9341_t3n)

    Some of the interesting things I ran into included, the other SPI buses do not have the FIFO queue (or the do but they have 1 entry). To handle some of this stuff I broke out all of the standard functions that were in the ILI9341_t3 library and made a new library SPIN (https://github.com/KurtE/spin), which created a virtual interface for SPI and implementations for the different Queue.

    I also found while testing stuff out on the new processors, that on some of these, there are only 1 hardware CS brought out. So I made the library handle it. In these cases the DC pin needs to be on the Hardware SPI CS pin.

    Anyway I have been off and on playing around with this code and at one point had 3 displays hooked up to the T3.6. Sometimes with all of them on the 3 different SPI busses and sometimes two on 1...

    Recently I became inspired by Franks work on the DMA version of the library as talked about in: https://forum.pjrc.com/threads/36706...eensy-3-6-only. So I decided to play with it for a few days. I think his stuff will work great for his intended application of showing videos and the like.

    But I am not sure how I would apply it to the typical things I do. Most of the time, I end up setting up things like a set of buttons and text and the like, and as such I don't need continuous updates. However I do like the idea of using a logical frame buffer. As I can see several places where doing a set of graphic primitives in the background and then update the screen would be useful. Example I may wish to do something like scrolling text.

    So today I started to add an optional FrameBuffer to the ILI9341_t3n. I added three new methods, whose names may change:
    Code:
    	uint8_t useFBTFT(boolean b);		// use the frame buffer?  First call will allocate
    	void	freeFBTFT(void);			// explicit call to release the buffer
    	void	updateScreen(void);			// call to say update the screen now.
    Currently on the first call to useFBTFT - it will do a malloc for the frame buffer... Normally I don't like malloc, but...

    When in FB mode, I do all of the outputs to the frame buffer. Example drawPixel:
    Code:
    void ILI9341_t3n::drawPixel(int16_t x, int16_t y, uint16_t color) {
    
    	if((x < 0) ||(x >= _width) || (y < 0) || (y >= _height)) return;
    
    	if (_use_fbtft) {
    		_pfbtft[y*_width + x] = color;
    
    	} else {
    		beginSPITransaction();
    		setAddr(x, y, x, y);
    		writecommand_cont(ILI9341_RAMWR);
    		writedata16_last(color);
    		endSPITransaction();
    	}
    }
    The updateScreen then writes the contents of the FB out to the screen. Currently this does a complete screen update. I may update the calls like drawPixel to keep a bounding rectangle of all of the writes since the last update and only output those to the screen. That might come in handy for things like only update the scrolling text region.

    I still need to update some of the query functions, to optionally read from the buffer instead of asking the screen for the data, plus needs a lot more testing.

    But I did hack up some of the graphic Test program , to add some duplicates of some of the other tests, like, filled rectangles and filled rounded rects, and I believe they are about 4 times faster.

    I would paste in some of the timings, from the Serial monitor, but I disconnected USB cable and it no longer allows me to select the text...

    Not sure if anyone will be interested or not, but if so I updated github with the WIP.

    Anyway just having some fun!

    Kurt

  2. #2
    I'll definitely give it try as soon as get a chance. Out of curiousity, does this handle the additional high res fonts that can be used with the ili9341_t3?

  3. #3
    Senior Member KurtE's Avatar
    Join Date
    Jan 2014
    Posts
    2,848
    Hi Sandalhat,

    I forked this during the beta for T3.6 from the ILI9341_t3 project, so assuming this was not added in the last month or two, should work. Today I went through and edited more (hopefully all) of the examples to use the right object. So for example I now have DemoSauce running on my machine.

    But I have not modified it yet to try out the off screen frame stuff... May be fun to try...

  4. #4
    Thanks for the response. I tried it last night, but just with the graphictest as a quick test. The imported font rendered some garbage on the screen and almost seemed to ignore setCursor. I'll play around with it more when I get a chance. If I find anything that I can fix myself I'll try to see if I can figure out how to do a pull request, haha.

  5. #5
    Senior Member KurtE's Avatar
    Join Date
    Jan 2014
    Posts
    2,848
    Warning on Graphic Test, I think I have several #ifdef and #define for some different configurations. I think the current one up there was configured to be the same as Frank's DMA version.

    I should probably get it (and my setup) back to a more default configuration.

  6. #6
    Yeah, I noticed that on the graphic test. I think I got it set up right though because before I tested the font it worked fine. I'm using the same font file with the regular _t3 library, and it works. However, I was using 8 point with your library to try and avoid making any other changes and I haven't tried 8 point yet with _t3. On the subject, I'm actually not sure that I've tried setFontScale with these fonts so maybe it's as simple as that. Will investigate.

  7. #7
    Senior Member KurtE's Avatar
    Join Date
    Jan 2014
    Posts
    2,848
    I am still playing around. I found doing things like in drawFastHLine to setup a pointer to the first pixel to change and then increment it, that the code is a lot faster than using indexing for each item. I still have some more experimenting to see if some things like fillScreen can be made faster. Current stuff looks like:
    Code:
    void ILI9341_t3n::fillScreen(uint16_t color)
    {
    	if (_use_fbtft) {
    		uint16_t *pfbPixel = _pfbtft;
    		uint16_t *pfbtft_end = &_pfbtft[(ILI9341_TFTWIDTH*ILI9341_TFTHEIGHT)];	// setup 
    		while (pfbPixel < pfbtft_end) {
    			*pfbPixel++ = color;
    		}
    
    	} else {
    		fillRect(0, 0, _width, _height, color);
    	}
    }
    So I simply blasting out 16 bit values until I reach the end of the buffer... But I know in Frank's code he builds a 32 bit value and blasts that out. Actually he has code to output 32*2 entries at a time before he checks he reached the end. So maybe fun to experiment and see how much things can speed up. I am sorry to say I don't know the processor well enough. I know some processors have built in instructions and register usage setup to optimize simple loops like this.

    With the Graphic Test program, as I mentioned, I duplicated a couple of the tests to see if Frame buffer would speed them up. Ones like Screen fills make no sense to do (unless you don't want to actually see the N different colored screens).

    But in thes cases it appears to help.
    Code:
    LI9341 Test!
    MOSI:11 MISO:12 SCK:13
    
    After TFT Begin
    200
    Display Power Mode: 0xCE
    MADCTL Mode: 0x24
    Pixel Format: 0x2
    Image Format: 0x0
    Self Diagnostic: 0xE0
    Benchmark                Time (microseconds)
    Screen fill              225039
    Text                     11705
    Lines                    58387
    Horiz/Vert Lines         18413
    Rectangles (outline)     11686
    Rectangles (filled)      468220
    Circles (filled)         70709
    Circles (outline)        56549
    Triangles (outline)      14121
    Triangles (filled)       154477
    Rounded rects (outline)  25385
    Rounded rects (filled)   510986
    Hit key to continue
    Done!
    Rectangles (filled) FB     79409
    Hit key to continue
    Done!
    Rounded rects (filled) FB   77390
    Hit key to continue
    Done!
    So for Rectangles Filled went from 468220 to 79409
    Rounded Rects filled: 468220 to 77390

    However things are not always easy to simply update like this and speed up. For example I tried demoSauce and only turned on Frame buffer around the actual draw a page and it slowed things down, not speed up. So I think I need to figure out how the transitions work.

    As part of this I have added changes to readPixel and readRect and writeRect to also optionally work with FB.

    However at least one of the transitions also uses scrollRect, so now trying to remember how it works and see if I should emulate it....

    Now back to playing around

  8. #8
    Senior Member KurtE's Avatar
    Join Date
    Jan 2014
    Posts
    2,848
    Probably just talking to myself
    Quote Originally Posted by KurtE View Post
    I am still playing around. I found doing things like in drawFastHLine to setup a pointer to the first pixel to change and then increment it, that the code is a lot faster than using indexing for each item. I still have some more experimenting to see if some things like fillScreen can be made faster. Current stuff looks like:
    Code:
    void ILI9341_t3n::fillScreen(uint16_t color)
    {
    	if (_use_fbtft) {
    		uint16_t *pfbPixel = _pfbtft;
    		uint16_t *pfbtft_end = &_pfbtft[(ILI9341_TFTWIDTH*ILI9341_TFTHEIGHT)];	// setup 
    		while (pfbPixel < pfbtft_end) {
    			*pfbPixel++ = color;
    		}
    
    	} else {
    		fillRect(0, 0, _width, _height, color);
    	}
    }
    So I simply blasting out 16 bit values until I reach the end of the buffer... But I know in Frank's code he builds a 32 bit value and blasts that out. Actually he has code to output 32*2 entries at a time before he checks he reached the end. So maybe fun to experiment and see how much things can speed up. I am sorry to say I don't know the processor well enough. I know some processors have built in instructions and register usage setup to optimize simple loops like this.
    But was curious about does 32 bit instead of 16 help much and likewise doing 32 updates between end checks help... So did a quick and dirty test...
    Code:
    uint16_t *_pfbtft = NULL;
    #define ILI9341_TFTWIDTH  240
    #define ILI9341_TFTHEIGHT 320
    #define ILI9341_BLACK       0x0000      /*   0,   0,   0 */
    #define ILI9341_BLUE        0x001F      /*   0,   0, 255 */
    #define ILI9341_GREEN       0x07E0      /*   0, 255,   0 */
    #define ILI9341_RED         0xF800      /* 255,   0,   0 */
    
    
    void setup() {
      while (!Serial && (millis() < 5000)) ;
      Serial.begin(115200);
      delay(250);
      Serial.println("Start test");
      // use pointer to make like my code.
      _pfbtft = (uint16_t *)malloc(ILI9341_TFTWIDTH * ILI9341_TFTHEIGHT * 2);
    }
    
    void Fill16(uint16_t color) {
      uint16_t *pfbPixel = _pfbtft;
      uint16_t *pfbtft_end = &_pfbtft[(ILI9341_TFTWIDTH * ILI9341_TFTHEIGHT)]; // setup
      while (pfbPixel < pfbtft_end) {
        *pfbPixel++ = color;
      }
    }
    
    void Fill32(uint16_t color) {
      uint32_t color32 = (color << 16) | color;
    
      uint32_t *pfbPixel = (uint32_t *)_pfbtft;
      uint32_t *pfbtft_end = (uint32_t *)((uint16_t *)&_pfbtft[(ILI9341_TFTWIDTH * ILI9341_TFTHEIGHT)]); // setup
      while (pfbPixel < pfbtft_end) {
        *pfbPixel++ = color32;
      }
    }
    
    void Fill32m(uint16_t color) {
      uint32_t color32 = (color << 16) | color;
    
      uint32_t *pfbPixel = (uint32_t *)_pfbtft;
      uint32_t *pfbtft_end = (uint32_t *)((uint16_t *)&_pfbtft[(ILI9341_TFTWIDTH * ILI9341_TFTHEIGHT)]); // setup
      while (pfbPixel < pfbtft_end) {
        *pfbPixel++ = color32; *pfbPixel++ = color32; *pfbPixel++ = color32;*pfbPixel++ = color32;
        *pfbPixel++ = color32; *pfbPixel++ = color32; *pfbPixel++ = color32;*pfbPixel++ = color32;
        *pfbPixel++ = color32; *pfbPixel++ = color32; *pfbPixel++ = color32;*pfbPixel++ = color32;
        *pfbPixel++ = color32; *pfbPixel++ = color32; *pfbPixel++ = color32;*pfbPixel++ = color32;
        *pfbPixel++ = color32; *pfbPixel++ = color32; *pfbPixel++ = color32;*pfbPixel++ = color32;
        *pfbPixel++ = color32; *pfbPixel++ = color32; *pfbPixel++ = color32;*pfbPixel++ = color32;
        *pfbPixel++ = color32; *pfbPixel++ = color32; *pfbPixel++ = color32;*pfbPixel++ = color32;
        *pfbPixel++ = color32; *pfbPixel++ = color32; *pfbPixel++ = color32;*pfbPixel++ = color32;
      }
    }
    
    void loop() {
      uint32_t start_time;
    
      Serial.print("16 bit time ");
      start_time = micros();
      Fill16(ILI9341_BLACK);
      Fill16(ILI9341_BLUE);
      Fill16(ILI9341_GREEN);
      Fill16(ILI9341_RED);
      Serial.println(micros()-start_time, DEC); Serial.flush(); // make sure not to interfer with time of next test
    
      Serial.print("32 bit time ");
      start_time = micros();
      Fill32(ILI9341_BLACK);
      Fill32(ILI9341_BLUE);
      Fill32(ILI9341_GREEN);
      Fill32(ILI9341_RED);
      Serial.println(micros()-start_time, DEC); Serial.flush(); // make sure not to interfer with time of next test
    
      Serial.print("32m bit time ");
      start_time = micros();
      Fill32m(ILI9341_BLACK);
      Fill32m(ILI9341_BLUE);
      Fill32m(ILI9341_GREEN);
      Fill32m(ILI9341_RED);
      Serial.println(micros()-start_time, DEC); Serial.flush(); // make sure not to interfer with time of next test
      Serial.println();
      delay(500);
    }
    Some timing outputs:
    Code:
    16 bit time 6833
    32 bit time 3417
    32m bit time 1119
    
    16 bit time 6833
    32 bit time 3420
    32m bit time 1119
    
    16 bit time 6834
    32 bit time 3417
    32m bit time 1119
    So the answer is YES it does help. So will update my actual code. Next question will be if it helps here, should I check other primitives like fillRect, fastDrawHorizontalLine ...

  9. #9
    Senior Member KurtE's Avatar
    Join Date
    Jan 2014
    Posts
    2,848
    Integrated the change into fillScreen. Decided that worked there so put code into fillRect and drawFastHLine, that if x and w are even numbers to do 32 bit writes there as well.

    Reran my graphictest updates to see if that helped. It appears to as, the fast versions of the tests went from about: 79409 and 77390

    To about: 74096, 73868

    So updated github...

  10. #10
    I'm following the thread at least, so you're not talking to yourself! I haven't had enough time to really be productive in the conversation unfortunately. I tested the font again and still no luck but I haven't looked closely enough at what's going on. The included font files have to be modified because they include ili9341_t3. That include has to be updated to your library at least. It compiles and tries to run then, but strange things happen with the text. Something shows up on screen, but it immediately disappears.

  11. #11
    Senior Member KurtE's Avatar
    Join Date
    Jan 2014
    Posts
    2,848
    If you upload copy of test, I will try to take look

  12. #12
    Quote Originally Posted by KurtE View Post
    If you upload copy of test, I will try to take look
    I discarded the test, but it was basically this, which uses a font file from here:

    Code:
    #include <SPIN.h>
    #include "SPI.h"
    #include "ILI9341_t3n.h"
    #include <font_Inconsolata-Regular.h> //from linked library but pointing back to the ili9341_t3n instead of the regular ili9341_t3
    
    #define TFT_DC  15
    #define TFT_CS 10
    #define TFT_RST 4
    #define TFT_SCK 13
    #define TFT_MISO 12
    #define TFT_MOSI 11
    ILI9341_t3n tft = ILI9341_t3n(TFT_CS, TFT_DC, TFT_RST, TFT_MOSI, TFT_SCK, TFT_MISO, &SPIN);
    
    void setup() {
    
      tft.begin();
      tft.useFBTFT(1);
      tft.fillScreen(ILI9341_BLACK);
      tft.setRotation(3);
      tft.setFont(Inconsolata_60);
      tft.setTextColor(ILI9341_WHITE);
      tft.setCursor(0,0);
      tft.println("Test");
      tft.println("text");
      tft.updateScreen();
        
    }
    
    
    void loop(void) {
      
    }
    Although skimming through your library files, it looks like the functions to draw the text characters are not able to use the frame buffer, so I'm just overwriting the text immediately with the buffered frame. Is it expected to be able to print text to the frame buffer?

  13. #13
    Senior Member defragster's Avatar
    Join Date
    Feb 2015
    Posts
    4,685
    Kurt:
    In July I noticed errors in graphicstest.ino. It made the two functions below draw out of bounds and waste time and report higher times. {assuming I found the right code}

    I mentioned it in a post that got no traction and never propagated it back. Watching the MickMake youtube on the T_3.6 made me remember it.

    Can you check my math on this and let me know if you end up doing a pull with your efforts, or I can.

    If I did a pull I'd want to add a SUM TOTAL line for all tests as a quick way to see next gain.

    Code:
    unsigned long testFilledRects(uint16_t color1, uint16_t color2) {
      unsigned long start, t = 0;
      int           n, i, i2,
                    cx = tft.width()  / 2 - 1,
                    cy = tft.height() / 2 - 1;
    
      tft.fillScreen(ILI9341_BLACK);
      n = min(tft.width(), tft.height())-1;

    Code:
    unsigned long testFilledRoundRects() {
      unsigned long start;
      int           i, i2,
                    cx = tft.width()  / 2 - 1,
                    cy = tft.height() / 2 - 1;
    
      tft.fillScreen(ILI9341_BLACK);
      start = micros();
      for(i=min(tft.width(), tft.height())-1; i>20; i-=6) {
    Last edited by defragster; 10-31-2016 at 05:09 AM.

  14. #14
    Senior Member KurtE's Avatar
    Join Date
    Jan 2014
    Posts
    2,848
    Quote Originally Posted by sandalhat View Post
    I discarded the test, but it was basically this, which uses a font file from here:

    Although skimming through your library files, it looks like the functions to draw the text characters are not able to use the frame buffer, so I'm just overwriting the text immediately with the buffered frame. Is it expected to be able to print text to the frame buffer?
    Thanks, I am now seeing a few more functions to update, including the one that draws fon't characters. I also see that rectangle calls HLine/VLine which is still going direct... Will either update these functions or see if they can simply use the FastHorizontal/Vertical functions.

    Quote Originally Posted by defragster View Post
    Kurt:
    In July I noticed errors in graphicstest.ino. It made the two functions below draw out of bounds and waste time and report higher times. {assuming I found the right code}

    I mentioned it in a post that got no traction and never propagated it back. Watching the MickMake youtube on the T_3.6 made me remember it.
    Will take a look, thanks

    Kurt

  15. #15
    Senior Member KurtE's Avatar
    Join Date
    Jan 2014
    Posts
    2,848
    Quick update: I pushed up changes to fix the drawing of font characters, plus drawing rectangles and drawing lines. Test program looks like:
    Code:
    #include <SPIN.h>
    #include "SPI.h"
    #include "ILI9341_t3n.h"
    #include "font_Inconsolata-Regular.h" //from linked library but pointing back to the ili9341_t3n instead of the regular ili9341_t3
    
    #define TFT_DC  9
    #define TFT_CS 10
    #define TFT_RST 7
    #define TFT_SCK 13
    #define TFT_MISO 12
    #define TFT_MOSI 11
    ILI9341_t3n tft = ILI9341_t3n(TFT_CS, TFT_DC, TFT_RST, TFT_MOSI, TFT_SCK, TFT_MISO, &SPIN);
    
    uint8_t use_fb = 0;
    
    void setup() {
      while (!Serial && (millis() < 4000)) ;
      Serial.begin(115200);
      tft.begin();
      tft.fillScreen(ILI9341_BLACK);
    }
    
    void drawFontText() {
      Serial.printf("Use FB: %d ", use_fb); Serial.flush();
      uint32_t start_time = millis();
      tft.useFBTFT(use_fb);
      tft.fillScreen(use_fb ? ILI9341_RED : ILI9341_BLACK);
      tft.setRotation(3);
      tft.setFont(Inconsolata_60);
      tft.setTextColor(ILI9341_WHITE);
      tft.setCursor(0, 0);
      tft.println("Test");
      tft.println("text");
    
      tft.drawRect(0, 150, 200, 50, ILI9341_WHITE);
      tft.drawLine(0, 150, 200, 50, ILI9341_GREEN);
      tft.updateScreen();
      Serial.println(millis() - start_time, DEC);
    
      use_fb = !use_fb;
    
    }
    
    void loop(void) {
      // See if any text entered
      if (Serial.read() != -1) {
        while (Serial.read() != -1) ;
        drawFontText();
      }
    
    }
    So I can enter a text line (typically empty) and switch between drawing with or without frame buffer.

    Defragster: Taking a look at the function:
    Code:
    unsigned long testFilledRects(uint16_t color1, uint16_t color2) {
      unsigned long start, t = 0;
      int           n, i, i2,
                    cx = tft.width()  / 2 - 1,
                    cy = tft.height() / 2 - 1;
    
      tft.fillScreen(ILI9341_BLACK);
      n = min(tft.width(), tft.height());
      for(i=n; i>0; i-=6) {
        i2    = i / 2;
        start = micros();
        tft.fillRect(cx-i2, cy-i2, i, i, color1);
        t    += micros() - start;
        // Outlines are not included in timing results
        tft.drawRect(cx-i2, cy-i2, i, i, color2);
      }
    
      return t;
    }
    Quick sanity test. Assume width=240, height=320
    cx = 119, cy=159, n=240, i=240, i2=120 so first fillRect(-1, 39, 240, 240, color1). So the problem is the -1... Which looks like also looks like maybe need to update the graphic primitives to check for this...

    Frank, if you are reading this, maybe need to change your DMA version as well...

  16. #16
    How fast can the 3.6 render text to the ILI9341 via SPI (i.e., full refreshes of all text per second)? If I wanted to display the following four lines of voltage/current readings (in different colors) on the screen in a format like:

    1.000V/20.000mA
    2.000V/10.000mA
    3.000V/5.000mA
    4.000V/1.000mA

    or perhaps if it is more efficent:

    1.000V/20.000mA - 2.000V/10.000mA
    3.000V/5.000mA - 4.000V/1.000mA

    How many times per second could I refresh it?

    And what about libraries that support 480x320 display. These can be had for about $6 (shipping included) from AliExpress:

    https://www.aliexpress.com/item/3-2-...605255967.html
    Last edited by SharpEars; 10-31-2016 at 04:18 PM.

  17. #17
    Senior Member defragster's Avatar
    Join Date
    Feb 2015
    Posts
    4,685
    Quote Originally Posted by KurtE View Post
    Defragster: Taking a look at the function:
    ...
    Quick sanity test. Assume width=240, height=320
    cx = 119, cy=159, n=240, i=240, i2=120 so first fillRect(-1, 39, 240, 240, color1). So the problem is the -1... Which looks like also looks like maybe need to update the graphic primitives to check for this...
    Kurt - not sure that came across right? The -1 was the fix :: min(tft.width(), tft.height()) -1

    Those params are zero based right? So without the -1 it is out of bounds and it sits a long time in the display code getting over that.

  18. #18
    Senior Member KurtE's Avatar
    Join Date
    Jan 2014
    Posts
    2,848
    Hi SharEars,

    Short Answer: It depends...

    Longer Answer:

    Most all of this is dictated, by speed of SPI, and is pretty fixed to draw a full screen. That is to draw a full screen, you need to output:
    Header stuff: with more or less bounding rectangle, plus memory command to start memory write: 1+2+2+1+2+2+1 bytes, followed by 320x240*2 bytes. So you can compute the theoretical frames per second, by knowing how long it takes to output each byte... There is some fudge time between commands.

    Also Which library you use, will make a difference. If for example you use Frank's DMA version, which might work great for this, His code simply uses DMA to keep blasting the bytes out for each frame, one after another, and only needs the commands (bounding rectangles and write command) to be output once... However there is no synchronization done of frames, so you may have partial text on one screen and the rest of the update happens on the next. But you will probably never notice it. Also note: this completely takes over the SPI buss. So you can not use any other SPI devices on it, while the screen code is running.

    With what I am doing here, you are in control of when the screen updates. You do your outputs for a screen and then say update me now... This does require startup code to run, so I will output less frames per second.

    However I will probably be updating my frame code, that after you tell a frame to output, it will keep a bounding rectangle of all of the pixels that changed after that point, and when you say to update me now, use that to update. So for example if all of your text that is changing is not spread out, it would only need to update a fraction of the screen.

    Also note: the standard ILI9341_t3 works pretty darn good by itself. That is if you drawText especially non-transparent, it outputs to SPI more or less at full speed. You may need to do some fudging if the text output does not always output the same number of bits... Like if one time you output 12v and next 5v, you may need to either output a blank first or do a fillrect...

  19. #19
    Senior Member KurtE's Avatar
    Join Date
    Jan 2014
    Posts
    2,848
    Quote Originally Posted by defragster View Post
    Kurt - not sure that came across right? The -1 was the fix :: min(tft.width(), tft.height()) -1

    Those params are zero based right? So without the -1 it is out of bounds and it sits a long time in the display code getting over that.
    Thanks defragster,

    I was first trying to understand the problem to understand your fix.

    Your fix is probably the simplest: So cx = 119, cy=159, n=239, i=239, i2=119 so first fillRect(0, 40, 239, 239, color1).
    So would work fine. Would not do the last X...

    Option 2: could maybe change cx, cy to not subtract 1... would probably call with (0, 40, 240, 240, color1);

    Option 3: (may want to regardless of 1 and 2): Fix underlying code to handle this.
    I have code in my FB code (as does Frank), that does something like:
    Code:
    			uint16_t * pfbPixel_row = &_pfbtft[ y*_width + x];
    			for (;h>0; h--) {
    				uint16_t * pfbPixel = pfbPixel_row;
    				for (int i = 0 ;i < w; i++) {
    					*pfbPixel++ = color;
    				}
    				pfbPixel_row += _width;
    			}
    DMA version:
    Code:
    	for(int i=h-1; i>=0; i--) {
    		for(int j=w-1; j>=0;j--) {
    			screen[y + i][x + j] = color;
    		}
    	}
    It is bad enough with -1 on x, luckily not -1 on y or could get good random location in array updated...
    There is code at the beginning of this function, that looks like:
    Code:
    	if((x >= _width) || (y >= _height)) return;
    	if((x + w - 1) >= _width)  w = _width  - x;
    	if((y + h - 1) >= _height) h = _height - y;
    but maybe should add additional tests/fixes, maybe like:
    Code:
    	if((x >= _width) || (y >= _height)) return;
    	if(x < 0) {	w += x; x = 0; 	}
    	if(y < 0) {	h += y; y = 0; 	}
    	if((x + w - 1) >= _width)  w = _width  - x;
    	if((y + h - 1) >= _height) h = _height - y;
    So basically add in some clipping on beginning sides...
    Does that make sense?

    Kurt
    Last edited by KurtE; 10-31-2016 at 04:58 PM.

  20. #20
    Senior Member defragster's Avatar
    Join Date
    Feb 2015
    Posts
    4,685
    opps on confusion - glad I could share the pain I felt finding it - I found it seeing the rectangles not draw right in two orientations - then had to slow it down and find the code. Fixing the caller code would make the test better. Did you note the faster speed after the fix?

    Indeed the library does act oddly on out of bounds - a clean fix there would be good too. I saw it take a long time - but that was months ago and assumed the expectation was well formed inputs and fast direct action in the library - but sanity/safety should prevail. I'll look at your post again soon . . . already late being somewhere.

  21. #21
    Senior Member KurtE's Avatar
    Join Date
    Jan 2014
    Posts
    2,848
    Thanks,

    I have not fixed the user code yet. First did updates to library code, which I updated to github... Did speed up maybe little 468220 -> 468029 Next to fix the issue you found.

    Question is, should I also make fixes to main ILI9341_t3n library (probably should) and do Pull Request...

    Kurt

  22. #22
    Senior Member Frank B's Avatar
    Join Date
    Apr 2014
    Location
    Germany
    Posts
    4,080
    Hm,
    i don't think that a test for x=-1 is needed in the non-dma version. It results in a funny screen, and the user can fix the bug. he has to do it anyway.

  23. #23
    Senior Member KurtE's Avatar
    Join Date
    Jan 2014
    Posts
    2,848
    Quote Originally Posted by Frank B View Post
    Hm,
    i don't think that a test for x=-1 is needed in the non-dma version. It results in a funny screen, and the user can fix the bug. he has to do it anyway.
    I am sort of torn here. I agree with you with many usages of the library, that it may not be necessary, but then probably equally valid to not test for x>=_width as well. But I know I always want to check it in the cases where I am using memory as a frame buffer...

    I do see cases, where it might be useful to properly check the bounds, like for example suppose, my app, has graphic entries on the screen, that allows the user to move things around with the touch screen. It is possible the user may position some of the elements where they are only partially visible... Sort of like of my windows on my screen...

    It is interesting, I received email due to comment on PR:
    These and other clipping bugs are also fixed in #13 along with a feature that allows arbitrary clipping rectangles on the screen.
    So again I am on the fence...

  24. #24
    Senior Member defragster's Avatar
    Join Date
    Feb 2015
    Posts
    4,685
    Torn is where I was with the library behavior - "assumed the expectation was well formed inputs and fast direct action in the library" - it is up to the user to do the right thing - only critical to not crater destructively - and not waste time bounds checking.

    An aberrant case and they flash so fast you can't see the issue - but it was biasing the timed results. Somehow I was hacking it to rotate and saw the failure in the user code.

    If there are clipping changes pending that will supersede then not bothering to change the library is sensible.

  25. #25
    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.

Posting Permissions

  • You may not post new threads
  • You may not post replies
  • You may not post attachments
  • You may not edit your posts
  •