Forum Rule: Always post complete source code & details to reproduce any issue!
Page 14 of 14 FirstFirst ... 4 12 13 14
Results 326 to 344 of 344

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

  1. #326
    Junior Member
    Join Date
    Jun 2020
    Posts
    12
    Quote Originally Posted by KurtE View Post
    In itself it would have probably 0% difference in possible speed.
    As for Gauge drawing with flicker and the like. I added code to the ili9341_t3n to help speed things up. In particular the code with each graphic primitive in frame buffer mode, would keep a bounding rectangle of what parts of the image changed since the last updateScreen was called and when you call updateScreen it would only update that portion of the display, which in cases of a needle changing a little bit was only a small fraction of the full pixels of the display.
    I'm curious as to how the automatic bounding box works. Does one need to do any more than just set useFrameBuffer(true)? Is it basically an auto "setClipRect()"? Or is it a more sophisticated routine that tightly bounds what's changed? Wouldn't a clipping rectangle get very large on a gauge when the needle is at 45, negating the benefit?

  2. #327
    Senior Member
    Join Date
    Oct 2019
    Posts
    146
    Quote Originally Posted by Slabshaft View Post
    I'm curious as to how the automatic bounding box works. Does one need to do any more than just set useFrameBuffer(true)? Is it basically an auto "setClipRect()"? Or is it a more sophisticated routine that tightly bounds what's changed? Wouldn't a clipping rectangle get very large on a gauge when the needle is at 45, negating the benefit?
    I wish it was automatic You need to define the X,Y pointers and the W,H of the clipping rectangle. One thing that confuses me is the position it starts at is the opposite of the other graphic primitives eg. drawing a char/string you pointer is at the top left corner, whereas ClipRect pointer starts at the bottom left corner.

    Regarding the clipping rectangle at a 45 angle, the rectangle becomes quite big, but still its much faster than a full display refresh. If I'm not mistaking, Kurt has implemented a mechanism that updates only changed pixels within the clipping rectangle on the ILI9341_t3n library - this obviously contributes to performance improvement, no doubt.

  3. #328
    Senior Member+ KurtE's Avatar
    Join Date
    Jan 2014
    Posts
    7,414
    Actually if you are using the frame buffer, and your updates are reasonably in the same area, in theory I have code in place that it remember the bounding rectangle of things that changed since you last did an updateScreen.

    Again this does not work with the Async stuff, only the sync stuff (so far).

    But I believe I have it such that you can enable this by a call like: tft.updateChangedAreasOnly();

    It has been awhile since i played with it so...

  4. #329
    Junior Member
    Join Date
    Jun 2020
    Posts
    12
    I found this in the header file and set _updateChangedAreasOnly to true and saved the header file so the default for me is now "true". Maybe this can be called in the code, but I wasn't sure how. I just ran a test by removing all of my millions of setClipRect() commands . . . and everything is rendering great, so the automatic clipping rectangle seems to be working. Nice!! I think this should work with the dial needle.

    Code:
    #ifdef ENABLE_ILI9341_FRAMEBUFFER
        // Add support for optional frame buffer
        uint16_t	*_pfbtft;						// Optional Frame buffer 
        uint8_t		_use_fbtft;						// Are we in frame buffer mode?
        uint16_t	*_we_allocated_buffer;			// We allocated the buffer; 
    	int16_t  	_changed_min_x, _changed_max_x, _changed_min_y, _changed_max_y;
    	bool 		_updateChangedAreasOnly = false;	// current default off set to
    	void		(*_frame_complete_callback)() = nullptr;
    	bool 		_frame_callback_on_HalfDone = false;

  5. #330
    Senior Member+ KurtE's Avatar
    Join Date
    Jan 2014
    Posts
    7,414
    Again as I mentioned there is a simple member function:
    Code:
    void updateChangedAreasOnly(bool updateChangedOnly) {
    #ifdef ENABLE_ILI9341_FRAMEBUFFER
    		_updateChangedAreasOnly = updateChangedOnly;
    #endif
    	}
    That you can call that sets that variable true or false.

    The interesting thing with needle is if that is all you are changing, then yes can do this automatic. But if you then are updating some text field somewhere else, you may be better off doing them as separate sets of updates to limit just how much of the screen redraws.

  6. #331
    Senior Member
    Join Date
    Oct 2019
    Posts
    146
    Quote Originally Posted by KurtE View Post
    The interesting thing with needle is if that is all you are changing, then yes can do this automatic. But if you then are updating some text field somewhere else, you may be better off doing them as separate sets of updates to limit just how much of the screen redraws.
    I've been thinking, to optimize performance even more, for any text fields that aren't changing, you can compare the current value to its old value and decide if it requires updating. On integers it would be simple enough. But how do you suggest one does this with floats? with a single decimal point, I'm using tft.print(float value,1) to print the values. Do you suggest converting to an integer and multiplying and then comparing?

  7. #332
    Senior Member+ defragster's Avatar
    Join Date
    Feb 2015
    Posts
    12,189
    Quote Originally Posted by Rezo View Post
    I've been thinking, to optimize performance even more, for any text fields that aren't changing, you can compare the current value to its old value and decide if it requires updating. On integers it would be simple enough. But how do you suggest one does this with floats? with a single decimal point, I'm using tft.print(float value,1) to print the values. Do you suggest converting to an integer and multiplying and then comparing?
    That sounds reasonable to try - math and multiply is faster (single op) than SPI rewrite of the number and background.

    Wondering how much overhead is in the tft.print(float value,1)? Since doing the *10 anyhow:
    Code:
    // int32_t?  uint32_t?
    static int32_t old_foo=0x7FFF;
    int32_t foo = floatX*10;
    if ( foo != old_foo ) {
      // prep cursor/field for overwrite
      tft.print( foo/10 );
      tft.print( '.' );
      tft.print( foo%10 );
      old_foo = foo;
    }

  8. #333
    Senior Member
    Join Date
    Oct 2019
    Posts
    146
    Quote Originally Posted by defragster View Post
    That sounds reasonable to try - math and multiply is faster (single op) than SPI rewrite of the number and background.

    Wondering how much overhead is in the tft.print(float value,1)? Since doing the *10 anyhow:
    Code:
    // int32_t?  uint32_t?
    static int32_t old_foo=0x7FFF;
    int32_t foo = floatX*10;
    if ( foo != old_foo ) {
      // prep cursor/field for overwrite
      tft.print( foo/10 );
      tft.print( '.' );
      tft.print( foo%10 );
      old_foo = foo;
    }
    I think we need to convert everything back into a float if possible as you need to set the cursor for each print if I'm not mistaking - could be a hell of a headache to code in.
    In my code I move the curser left<>right based on the size of value - that way I'm able to center the string to the decimal point and it doesn't jump back and forth.


    EDIT:
    this could work:
    Code:
    // int32_t?  uint32_t?
    static int32_t old_foo=0x7FFF;
    int32_t foo = floatX*10;
    float floatX_n = 0; // new float for tft.print
    if ( foo != old_foo ) {
      // prep cursor/field for overwrite
      floatX_n = foo * 0.1f;
      tft.print(floatX_n, 1);
      old_foo = foo;
    }
    Last edited by Rezo; 06-17-2020 at 10:45 AM.

  9. #334
    Senior Member+ KurtE's Avatar
    Join Date
    Jan 2014
    Posts
    7,414
    Again if your goal is to output at 10ths of a unit and only update if it changes, you have multiple ways to do so.

    In many cases I will use fixed point math...

    But you can also do it quick and dirty with floating point...

    Something as simple as:

    Code:
    float last_value = 999999.9999; // some value you won't have.
    
    float new_value = ???
    
    if ((abs(last_value - new_value) >= 0.1) {
        display the new value
        last_value = new_value;
    }
    Obviously there are probably faster ways...

    NOTE: But side note: I just pushed up a minor change to the library, that when you call begin, it sets the pending_rx_count back to zero, in case someone calls
    the begin again and for some reason, the count had not been cleared back to zero...

  10. #335
    Senior Member
    Join Date
    Oct 2019
    Posts
    146
    Quote Originally Posted by KurtE View Post
    Again if your goal is to output at 10ths of a unit and only update if it changes, you have multiple ways to do so.

    In many cases I will use fixed point math...

    But you can also do it quick and dirty with floating point...

    Something as simple as:

    Code:
    float last_value = 999999.9999; // some value you won't have.
    
    float new_value = ???
    
    if ((abs(last_value - new_value) >= 0.1) {
        display the new value
        last_value = new_value;
    }
    Obviously there are probably faster ways...
    That's much cleaner. As mentioned before, I think the speed impact will still be a lot lower than rewriting and unchanged string to the display

  11. #336
    Senior Member
    Join Date
    Oct 2019
    Posts
    146
    I implemented the code above, calculating the absolute value and updating the relevant area of the display if its equal to or greater than 0.1, but it seems to have really slowed down the rate of change, as in, it wasn't updating nearly as fast as it does without the condition set

    Here's an example trying to limit the printout of Boost on the display as it doesn't change much when the car is at idle but as soon as some throttle is applied it will jump up and down quite fast

    Code:
    float intakePressureFinal = 0; // Boost: range is -30 to +30
    float intakePressureFinal_n = 0x7fff0;
    
    if ((abs(intakePressureFinal_n - intakePressureFinal) >= 0.1)) {
          
            if (intakePressureFinal >= 0 && intakePressureFinal < 10){ //Boost is between 0-10
              tft.setCursor(221, 230);
            }
          
            else if (intakePressureFinal > -99 && intakePressureFinal < -10){ // Boost bigger than -10 and smaller than -99
              tft.setCursor(182, 230);
            }
    
            else if (intakePressureFinal >= 10 && intakePressureFinal < 99){ // Boost is bigger than 10 and smaller than 99
              tft.setCursor(193, 230); 
            }
    
            else { // Boost is between -10 and 0
              tft.setCursor(210, 230);
            }
    
            tft.print(intakePressureFinal, 1);
            tft.setClipRect(182, 220, 110, 35);
            tft.updateScreen();
            tft.setClipRect();
            intakePressureFinal_n = intakePressureFinal;
     }
    Perhaps this method is too slow to execute or I ain't doing it right

  12. #337
    Senior Member
    Join Date
    Oct 2019
    Posts
    146
    Been up to some testing on an online C++ complier as I don't have access to a Teensy at the moment - will test the same code later on or tomorrow on a T4/4.1

    Here's the script im using to test the function:
    Code:
    #include <iostream>
    #include "math.h"
    
    using namespace std;
    float intakePressureFinal[5] = {-30.2, -15.2, 1.1, 14.9, 30.0}; // Boost: range is -30 to +30
    float intakePressureFinal_n[5] = {-24.2, -16.2, 1.1, 14.8, 30.2};
    float diff;
    
    
    int main()
    {
        
        for (int i = 0; i < 5 ; i++){
            cout<<"intakePressureFinal: " << intakePressureFinal[i];
            diff = intakePressureFinal_n[i] - intakePressureFinal[i];
            cout<< " || Diff: " << diff;
            if (fabs(diff) >= 0.1) {
                cout<<" || Output: " << intakePressureFinal[i] << "\n";
                intakePressureFinal_n[i] = intakePressureFinal[i];
            }
            else{
                cout<<" || No change \n";
                }
        }
        return 0;
    }
    Output:
    Code:
    intakePressureFinal: -30.2 || Diff: 6 || Output: -30.2                                                                                                                                          
    intakePressureFinal: -15.2 || Diff: -1 || Output: -15.2                                                                                                                                         
    intakePressureFinal: 1.1 || Diff: 0 || No change                                                                                                                                                
    intakePressureFinal: 14.9 || Diff: -0.0999994 || No change                                                                                                                                      
    intakePressureFinal: 30 || Diff: 0.200001 || Output: 30
    If I change intakePressureFinal_n[3] (14.8) to 15.0 I get a different output
    Code:
    intakePressureFinal: -30.2 || Diff: 6 || Output: -30.2                                                                                                                                        
    intakePressureFinal: -15.2 || Diff: -1 || Output: -15.2                                                                                                                                       
    intakePressureFinal: 1.1 || Diff: 0 || No change                                                                                                                                              
    intakePressureFinal: 14.9 || Diff: 0.1 || Output: 14.9                                                                                                                                        
    intakePressureFinal: 30 || Diff: 0.200001 || Output: 30
    But, if I change the value to compare abs to 0.09 from 0.1 it works much better:
    Code:
    if (fabs(intakePressureFinal_n[i]) >= 0.09)
    as I'm not getting a rounded off 0.1 or higher if the old value is smaller than the new value. I believe this is the cause of the "slowness" in updating the numbers on the display - it's just not meeting the conditions when using a difference of 0.1 for a single decimal point of precision.

  13. #338
    Junior Member
    Join Date
    Jan 2019
    Posts
    1
    Has anyone using the Buydisplay 7" with capacitive touch screen. https://www.buydisplay.com/spi-7-inc...h-screen-panel
    I have connected one to a teensy 4.0 Works fine, however the touch screen in showing the touches with x 1024 and y 600 in the top left hand corner. Using the test sketch from https://github.com/mjs513/Ra8876LiteTeensy. When the screen is touched the large dot is opposite of where it is being touched. It is like the touch screen was put on backwards. Please help.
    Tim

  14. #339
    Senior Member+ KurtE's Avatar
    Join Date
    Jan 2014
    Posts
    7,414
    Probably should ask on ra8876 thread, but probably does not take logical rotation into account. I would probably have simple sketch that prints the touch positions, and use map functions to convert

  15. #340
    I don't know if this is the right place to ask, please correct me if wrong! but this was the first ILI9341 library i got to work for me.

    I was wondering if there is there a way to have a "fake frame buffer" that is a copy of whatever was sent to the screen,

    I would like to retrieve the color of pixels that are already being displayed.

    It is for a "live" music driven graphic display sort of like a simplified version of the winamp visualization called "milkdrop"

    I am using a teensy 4 and the PJRC store ILI9341 touchscreen (not using touch currently) with this library. My sketch is based on the settings of the buddabrot example.

    The performance pf the teensy and screen are much better then i was expecting, and i notice the LED (which is used by SPI) is always on, does that mean it is working as fast as it possibly can, with no room for tweaks?

  16. #341
    Senior Member
    Join Date
    Dec 2013
    Location
    East Stroudsburg PA.
    Posts
    285
    The performance pf the teensy and screen are much better then i was expecting, and i notice the LED (which is used by SPI) is always on, does that mean it is working as fast as it possibly can, with no room for tweaks?
    By default the SPI CLOCK speed = 30000000 Mhz (LED pin)
    Code:
    void setup()
    {
      tft.begin(); will use the default SPI CLOCK @ 30000000 MHz.
    }
    I believe KurtE provide the possibility to override this behavior by doing this at run time:
    Code:
    void setup()
    {
      tft.begin(100000000, 2000000); // ILI9341_SPICLOCK 100000000, ILI9341_SPICLOCK_READ 2000000
    }
    NOTE: this of course will work only with short wires no more than 1 inch at this speed.

  17. #342
    Senior Member+ KurtE's Avatar
    Join Date
    Jan 2014
    Posts
    7,414
    yes in my ili9341_t3n library I did add the extra parameters to the begin to allow you to choose an upper speed for SPI. By upper speed I mean that the system will choose the fastest speed it can for your processor that does not exceed the speed you specify.

    With this library we also have the construct built in of using a frame buffer. Where all of the drawing primitives draw into this memory and then you have a method updateScreen that draws those pixels to the screen.

    This frame buffer is just memory that is just an array of pixel 16 bit colors (565), stored in memory in row order... So you can read from this or do what you like.

    Also in most of these libraries, you do have the ability to read a pixel or a rectangle of pixels back. If you are not using the frame buffer, this will do a query over spi to the screen, which is a slower operation. Note, the 2nd speed parameter that @Chris O showed on the begin is the fastest SPI Read speed, and these displays require slower SPI for read operations... But if you are using frame buffer than I simply read the information from it...
    The functions for this are:
    Code:
      uint16_t readPixel(int16_t x, int16_t y);
      void readRect(int16_t x, int16_t y, int16_t w, int16_t h, uint16_t *pcolors);

  18. #343
    This worked well, I even increased the second "MISO" frequency to 30000000 and it works.

    Just aside, I was reading about the imx1170 for some reason, and it's page shows it has "pxp pixel pipeline" and the 1060 also has it!
    is there any way to use the iMx1060 "PxP pixel pipeline" with ILI9341, it seems to do hardware alpha blending and so on on a frame buffer, and supports 565 color. https://mcuxpresso.nxp.com/api_doc/dev/1406/a00062.html

  19. #344
    Junior Member
    Join Date
    May 2019
    Location
    Colorado, USA
    Posts
    13
    Hi Kurt, I am using your t3n library on an HX8357 based display with great results! One thing I have not been able to find is a way to display a .bmp or .jpg file. I did see where you convert a file and include it in your program, but I wanted to get a .jpg or .bmp file directly off the SD card and out to the display. I was able to do this with an Arduino Due and the adafruit library, but have not been able to figure out how to do it with the Teensy 4.1. Click image for larger version. 

Name:	IMG_20200917_165248168_HDR.jpg 
Views:	4 
Size:	101.4 KB 
ID:	21772
    Thanks,
    Len

Posting Permissions

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