vindar / ILI9341_T4

Optimized ILI9341 screen driver library for Teensy 4/4.1, with vsync and diff. updates.
GNU Lesser General Public License v2.1
70 stars 12 forks source link

Two displays on one Teensy possible? #4

Closed DIYLAB-DE closed 2 years ago

DIYLAB-DE commented 2 years ago

Hi Arvind,

would it be theoretically possible to run two displays on one Teensy with your driver?

Kind regards Bruno

vindar commented 2 years ago

Hello Bruno,

I have never tried it but it should work theoretically since the driver does not use any global variable/state. However, the two displays will need to be on different SPI ports because the way asynchronous updates are handled prevent having other devices on the same port (appart from the touchscreen associated with the display).

So, one display using SPI0 and the other one using SPI1, each one with its own ILI934Driver instance and its own internal framebuffer/diff buffers should be ok.

This means that each display will need about 170kb of ram (for its internal fb and its diff buffers). Then another 150k for the shared memory fb where drawing is done. Thus, using two displays with double buffering/async mode will require almost 500kb of ram.

I do not have two displays at hand right now to try it. If you do please let me know whether it works or not.

DIYLAB-DE commented 2 years ago

Hi Arvind,

that sounds good, I'll be happy to test it and report back. Now I have to get a Teensy 4.1 first, because SPI1 is so hard to reach with the Teensy 4.0.

Kind regards Bruno

DIYLAB-DE commented 2 years ago

Hi Arvind,

it works perfectly! Feel free to take the code and maybe improve it: https://github.com/DIYLAB-DE/DualDisplay_T4

Kind regards Bruno

vindar commented 2 years ago

Hi Bruno,

Great to know it is working :-)

I just had a quick look at your code. Since you are redrawing fb0 and fb1 completely at each frame, you only need 1 framebuffer. You can remove fb1 and just use fb0 to draw both screens (because as soon as tftX.update() returns, fb0 can be reused without waiting for the upload to complete since the data is cached in the internal framebuffer). This will save 150K of RAM on the Teensy.

I will add this example to the library when I return from vacation. Thank you very much !

DIYLAB-DE commented 2 years ago

Oh, have a great rest of your vacation! And bring back great ideas ;o)

vindar commented 2 years ago

I just added your example with two displays to the library. Thank you !

donnersm commented 2 years ago

I am thinking of this too... I was about to try something else....wouldn't it work if i add an external AND gate to the CE pin of the display that i can control using another output on the Teensy.....then just before writing to it, enable the pin of the display i want to use.... that way i can put several displays in parallel? or what about simply defining another display using a different ce pin while the other pins are connected the same....( so without that extra and gate) Although, two displays as described here is also cool despite the fact that it takes almost a double number of pins on the teensy...

vindar commented 2 years ago

Hello

The problem is that the library use async write to the SPI bus via DMA while your program is running. Theoretically. you can indeed connect two displays to the same SPI bus with different CE pins but then you must make sure that both display are never updated simultaneously. In practice this means that you must wait each time for upload of a display to complete before starting the upload to the other one. But then, async write become basically useless so you might as well use a lighter driver (like ILI9341_t3) in that case...

donnersm commented 2 years ago

I also found out that the internal mem of teensy is limited. I use two buffers per display( static background image buffer and a working buffer that changes all the time) with two displays ideally i would need 4 buffers….each buffer is full display size….. then 4 buffers is more mem then is available in the teensy

vindar commented 2 years ago

The Teensy 4 has quite a lot of memory for a MCU: 1GB total but that is divided in two memory portions (DTCM and DMAMEM). So there is enough room for 4 full memory buffers (4 x 150Kb = 600Kb). However, if you have completely 'static' buffers, then these can go into FLASHMEM to save RAM (the teensy has 8GB flash memory) ... But yes, there certainly are tight memory constraints when working with large framebuffer and/or multiple screens !

donnersm commented 2 years ago

I changed to Teensy 4.1 and added extra 8M ram on the intended footprint..memory problem is solved Two displays are running smoothly without visible delay. Each display is directly connected to its own SPI bus. I do run into a problem that at some ( random) point in time both display freeze and the Teensy is non responsive. This only happens with two displays. Each display has it;s own set of buffers

// FIRST SCREEN IS WIRED TO SPI0 
#define PIN_SCK0        13  // mandatory 
#define PIN_MISO0       12  // mandatory
#define PIN_MOSI0       11  // mandatory
#define PIN_DC0         10  // mandatory
#define PIN_CS0          9  // mandatory (but can be any digital pin)
#define PIN_RESET0       6  // could be omitted (set to 255) yet it is better to use (any) digital pin whenever possible.
#define PIN_BACKLIGHT0 5  // optional. Set this only if the screen LED pin is connected directly to the Teensy 
#define PIN_TOUCH_IRQ0 255  // optional. Set this only if touch is connected on the same spi bus (otherwise, set it to 255)
#define PIN_TOUCH_CS0  255  // optional. Set this only if touch is connected on the same spi bus (otherwise, set it to 255)

// SECOND SCREEN IS WIRED TO SPI1 
#define PIN_SCK1        27  // mandatory 
#define PIN_MISO1        1  // mandatory
#define PIN_MOSI1       26  // mandatory
#define PIN_DC1          0  // mandatory
#define PIN_CS1         30  // mandatory (but can be any digital pin)
#define PIN_RESET1      29  // could be omitted (set to 255) yet it is better to use (any) digital pin whenever possible.
#define PIN_BACKLIGHT1 255  // optional. Set this only if the screen LED pin is connected directly to the Teensy 
#define PIN_TOUCH_IRQ1 255  // optional. Set this only if touch is connected on the same spi bus (otherwise, set it to 255)
#define PIN_TOUCH_CS1  255  // optional. Set this only if touch is connected on the same spi bus (otherwise, set it to 255)

#define SPI_SPEED           20000000  // SPI speed was 4
#define SPI_SPEED2         20000000  // SPI speed
// framebuffers
DMAMEM uint16_t internalBuffer[240 * 320] = { 0 }; // used for internal buffering
DMAMEM  uint16_t internalBuffer1[240 * 320] = { 0 }; // used for internal buffering
        uint16_t frontBuffer[240 * 320] = { 0 };    // paint in this buffer
EXTMEM uint16_t frontBuffer1[240 * 320] = { 0 };     // background buffer
EXTMEM uint16_t backBuffer[240 * 320] = { 0 };     // background buffer
EXTMEM uint16_t backBuffer1[240 * 320] = { 0 };     // background buffer

// samplebuffers
int16_t samplesLeft[2048] = { 0 };
int16_t samplesRight[2048] = { 0 };

// screen driver objects
ILI9341_T4::ILI9341Driver tft(PIN_CS0, PIN_DC0, PIN_SCK0, PIN_MOSI0, PIN_MISO0, PIN_RESET0, PIN_TOUCH_CS0, PIN_TOUCH_IRQ0); // for screen on SPI0
ILI9341_T4::ILI9341Driver tft1(PIN_CS1, PIN_DC1, PIN_SCK1, PIN_MOSI1, PIN_MISO1, PIN_RESET1, PIN_TOUCH_CS1, PIN_TOUCH_IRQ1); // for screen on SPI1

// two diff buffers
ILI9341_T4::DiffBuffStatic<8000> diff1;
ILI9341_T4::DiffBuffStatic<8000> diff2;

// two diff buffers for second display
ILI9341_T4::DiffBuffStatic<8000> diff3;
ILI9341_T4::DiffBuffStatic<8000> diff4;

// images that encapsulates framebuffers
Image<RGB565> im(frontBuffer, 240, 320);
EXTMEM Image<RGB565> im1(frontBuffer1, 240, 320);
EXTMEM Image<RGB565> bg(backBuffer, 240, 320);
EXTMEM Image<RGB565> bg1(backBuffer1, 240, 320);

while (!tft.begin(SPI_SPEED)) delay(1000);

tft.setScroll(0);
tft.setFramebuffers(internalBuffer); // set 1 internal framebuffer -> activate float buffering
tft.setDiffBuffers(&diff1, &diff2);  // set the 2 diff buffers => activate differential updates 
tft.setDiffGap(16);                   // use a small gap for the diff buffers
tft.setRefreshRate(120);             // around 120hz for the display refresh rate 
tft.setVSyncSpacing(2);              // set framerate = refreshrate/2 (and enable vsync at the same time) 

while (!tft1.begin(SPI_SPEED2)) delay(1000);
tft1.setScroll(0);
tft1.setFramebuffers(internalBuffer1); // set 1 internal framebuffer -> activate float buffering
tft1.setDiffBuffers(&diff3, &diff4);  // set the 2 diff buffers => activate differential updates 
tft1.setDiffGap(16);                   // use a small gap for the diff buffers
tft1.setRefreshRate(120);             // around 120hz for the display refresh rate 
tft1.setVSyncSpacing(2);              // set framerate = refreshrate/2 (and enable vsync at the same time) `

I played around with memory, moved it around from internal ram to external ram etc. And I also tried increasing the spacing in between buffers tft.setDiffGap(16) disabling the DiffBuffers makes it slow but it also doesn't solve the freeze issue So far no success...all is working fine until, at some random point in time...all freezes up again. It's not related to the ext mem, because I had the same issue with the teensy 4.0 without that extra mem..( I got rid of some extra buffers to free mem for it to work at all)

I am not sure if this is an issue with the ILI9341_T4.h or with the tgx.h Maybe there is a variable in one of those that overflows, not accounting for two displays? Any help is appreciated.

vindar commented 2 years ago

Hi,

My initial guess would be an interrupt related problem (but then removing all diff buffers should solve it which you say is not the case). It is strange.... I am on holiday this week and I do not have access to a Teensy 4 and two displays right now but I will check this next week when I come home. Do you have a complete (simple) example that I can run to test the freezing ? Thanks.

donnersm commented 2 years ago
I modified the example sketch CrazyClock_ALT to be used with two displays. To keep it compact, the frontbuffer is copied to each display so both displays will show the same...yet,,,same problem...Freeze at random times
I'm using teensy 4.1 with 8Mb ram added ( but not used in this sketch)
seem behavior occurs with teensy 4.0 without that extra ram.
libraries and memory used:
_Memory Usage on Teensy 4.1:
  FLASH: code:107172, data:381328, headers:9160   free for files:7628804
   RAM1: variables:283776, code:91224, padding:7080   free for local variables:142208
   RAM2: variables:344032  free for malloc/new:180256
Using library ILI9341_T4-main at version 0.1 in folder: C:\Users\chord\Documents\Arduino\libraries\ILI9341_T4-main 
Using library SPI at version 1.0 in folder: C:\Program Files (x86)\Arduino\hardware\teensy\avr\libraries\SPI 
Using library tgx-main at version 0.5 in folder: C:\Users\chord\Documents\Arduino\libraries\tgx-main_ 

Here is the modified sketch:

/********************************************************************
*
* tgx library: Crazy clock demo.
*
* This example show how to use blitting of rotated/rescaled sprites
* with transparency. 
*
* EXAMPLE FOR TEENSY 4 / 4.1
*
* DISPLAY: ILI9341 (320x240)
*
* CREDIT : Created by Bruno@diylab.de. Thanks !
********************************************************************/

// This example runs on teensy 4.0/4.1 with ILI9341 via SPI. 
// the screen driver library : https://github.com/vindar/ILI9341_T4
#include <ILI9341_T4.h> 

// the tgx library 
#include <tgx.h> 
#include <font_tgx_OpenSans_Bold.h>

// let's not burden ourselves with the tgx:: prefix
using namespace tgx;

// the sprites
#include "green.h"  // the clock, RGB565 format, no transparency
#include "long_hand.h"  // long hand, RGB32 format (with transparency)
#include "small_hand.h" // small hand, RGB32 format (with transparency)

#define SPI_SPEED       40000000

// DEFAULT WIRING USING SPI 0 ON TEENSY 4/4.1
// Recall that DC must be on a valid cs pin !!! 
#define PIN_SCK     13      // mandatory 
#define PIN_MISO    12      // mandatory
#define PIN_MOSI    11      // mandatory
#define PIN_DC      10      // mandatory
#define PIN_CS      9       // mandatory (but can be any digital pin)
#define PIN_RESET   6       // could be omitted (set to 255) yet it is better to use (any) digital pin whenever possible.
#define PIN_BACKLIGHT 5   // optional. Set this only if the screen LED pin is connected directly to the Teensy 
#define PIN_TOUCH_IRQ 255   // optional. Set this only if touch is connected on the same spi bus (otherwise, set it to 255)
#define PIN_TOUCH_CS  255   // optional. Set this only if touch is connected on the same spi bus (otherwise, set it to 255)

// ALTERNATE WIRING USING SPI 1 ON TEENSY 4/4.1
// Recall that DC must be on a valid cs pin !!! 
// SECOND SCREEN IS WIRED TO SPI1 
#define PIN_SCK1        27  // mandatory 
#define PIN_MISO1        1  // mandatory
#define PIN_MOSI1       26  // mandatory
#define PIN_DC1          0  // mandatory
#define PIN_CS1         30  // mandatory (but can be any digital pin)
#define PIN_RESET1      29  // could be omitted (set to 255) yet it is better to use (any) digital pin whenever possible.
#define PIN_BACKLIGHT1 255  // optional. Set this only if the screen LED pin is connected directly to the Teensy 
#define PIN_TOUCH_IRQ1 255  // optional. Set this only if touch is connected on the same spi bus (otherwise, set it to 255)
#define PIN_TOUCH_CS1  255  // optional. Set this only if touch is connected on the same spi bus (otherwise, set it to 255)

// the screen driver object
ILI9341_T4::ILI9341Driver tft(PIN_CS, PIN_DC, PIN_SCK, PIN_MOSI, PIN_MISO, PIN_RESET, PIN_TOUCH_CS, PIN_TOUCH_IRQ);

// added code for second display
ILI9341_T4::ILI9341Driver tft1(PIN_CS1, PIN_DC1, PIN_SCK1, PIN_MOSI1, PIN_MISO1, PIN_RESET1, PIN_TOUCH_CS1, PIN_TOUCH_IRQ1); // for screen on SPI1

// 2 x 10K diff buffers (used by tft) for differential updates (in DMAMEM)
DMAMEM ILI9341_T4::DiffBuffStatic<6000> diff1;
DMAMEM ILI9341_T4::DiffBuffStatic<6000> diff2;

// added code for second display
DMAMEM ILI9341_T4::DiffBuffStatic<6000> diff3;
DMAMEM ILI9341_T4::DiffBuffStatic<6000> diff4;

// screen dimension (landscape mode)
static const int SLX = 320;
static const int SLY = 240;

// main screen framebuffer (150K in DTCM for fastest access)
uint16_t fb[SLX * SLY];

// internal framebuffer (150K in DMAMEM) used by the ILI9431_T4 library for double buffering.
DMAMEM uint16_t internal_fb[SLX * SLY];

// For second display
DMAMEM uint16_t internal_fb1[SLX * SLY];

// image that encapsulates fb.
Image<RGB565> im(fb, SLX, SLY);

/* draw the clock with given angle, scale and opacity */
void drawClock(float angle, float scale= 1.0f, float opacity = 1.0f)
    {
    if (opacity == 1.0f)
        { // the clock does not use trnasparency so we can use the faster method when opacity = 1.0f 
        im.blitScaledRotated(green, { 120,120 }, { 160,120 }, scale, angle);  
        }
    else 
        {
        im.blitScaledRotated(green, { 120,120 }, { 160,120 }, scale, angle, opacity);  
        }
    } 

/* draw the small hand with given angle, scale and opacity */
void drawSmallHand(float angle, float scale= 1.0f, float opacity = 1.0f)
    { 
    // always use the method with blending, even when opacity = 1.0f because the hand has transparency
    im.blitScaledRotated(small_hand, { 22,117 }, { 160,120 }, 0.55f * scale, angle, opacity);
    } 

/* draw long hand with given angle, scale and opacity */
void drawLongHand(float angle, float scale= 1.0f, float opacity = 1.0f)
    {
    // always use the method with blending, even when opacity = 1.0f because the hand has transparency
    im.blitScaledRotated(long_hand, { 14,197 }, { 160,120 }, 0.5f * scale, angle, opacity);
    } 

void setup()
    {
    Serial.begin(9600);

    // output debug infos to serial port. 
    tft.output(&Serial);                

    // initialize the ILI9341 screen
    while (!tft.begin(SPI_SPEED))
        {
        Serial.println("Initialization error...");
        delay(1000);
        }

    // same for second display
    while (!tft1.begin(SPI_SPEED))
        {
        Serial.println("Initialization error...");
        delay(1000);
        }

    // ok. turn on backlight
    pinMode(PIN_BACKLIGHT, OUTPUT);
    digitalWrite(PIN_BACKLIGHT, HIGH);

    // setup the screen driver 
    tft.setRotation(3); // portrait mode
    tft.setFramebuffers(internal_fb); // double buffering
    tft.setDiffBuffers(&diff1, &diff2); // 2 diff buffers
    tft.setDiffGap(4); // small gap
    tft.setRefreshRate(240); // refresh at 60hz
    tft.setVSyncSpacing(2);

    // added for second display 
    tft1.setRotation(3); // portrait mode
    tft1.setFramebuffers(internal_fb1); // double buffering
    tft1.setDiffBuffers(&diff3, &diff4); // 2 diff buffers
    tft1.setDiffGap(4); // small gap
    tft1.setRefreshRate(240); // refresh at 60hz
    tft1.setVSyncSpacing(2);

    }

// used to keep track of the elapsed time
elapsedMillis em;  

void loop()
{
    int t;

    // PART 0 : title
    em = 0;
    while(em < 3000)
        {
        int y1 = (em < 1000) ? (130 * em) / 1000 - 50 : 80;
        int y2 = (em < 1000) ? 240 - (110 * em) / 1000 : 130;
        im.fillScreen(RGB565_Black);  
        im.drawText("TGX library",iVec2{110,y1}, RGB565_Red, font_tgx_OpenSans_Bold_18, true);
        im.drawText("Crazy clock demo",iVec2{35,y2}, RGB565_White, font_tgx_OpenSans_Bold_28, true);      
        tft.update(fb);
        //added for second display, a copy of display 0
        tft1.update(fb);
        yield(); // to keep the board responsive
        }

    // PART 1 : the clock appears. 
    em = 0;
    while ((t = em) < 1000)
        {      
        float sc = 0.1f + 0.9f*t/1000.0f;
        im.fillScreen(RGB565_Black);  
        im.drawText("TGX library",iVec2{110,80}, RGB565_Red, font_tgx_OpenSans_Bold_18, true, 1.0f - t/1000.0f);
        im.drawText("Crazy clock demo",iVec2{35,130}, RGB565_White, font_tgx_OpenSans_Bold_28, true, 1.0f - t/1000.0f);
        drawClock(200 - t/5, sc);
        drawSmallHand(t/10, sc);
        drawLongHand(t/2, sc); 
        tft.update(fb);
        //added for second display, a copy of display 0
        tft1.update(fb);
        yield(); // to keep the board responsive
        }

    // PART 2: rotation
    em = 0;
    while ((t = em) < 10000)
        {
        im.fillScreen(RGB565_Black);  
        drawClock(0, 1.0f);
        drawSmallHand(100 +360*sin(t / 1500.0f), 1.0f);
        drawLongHand(500*cos(t / 5000.0f), 1.0f); 
        tft.update(fb); 
        //added for second display, a copy of display 0
        tft1.update(fb);             
        yield(); // to keep the board responsive
        }  

   // PART 3: changing hands sizes
    while ((t = em) < 20000)
        {
        im.fillScreen(RGB565_Black);  
        drawClock(0, 1.0f);
        drawSmallHand(100 +360*sin(t / 1500.0f), 0.292893 + abs(sin( 0.7853981 + (t-10000.0f) / 3000.0f)));
        drawLongHand(500*cos(t / 5000.0f), 0.292893 + abs(cos( 0.7853981 + (t-10000.0f) / 3000.0f))); 
        tft.update(fb); 
        //added for second display, a copy of display 0
        tft1.update(fb);             
        yield(); // to keep the board responsive
        }      

   // PART 4: rotating the whole clock
    while ((t = em) < 35000)
        {
        im.fillScreen(RGB565_Black);  
        drawClock( 150.0f*sin((t-20000.0f) / 2000.0f), 1.0f);
        drawSmallHand(100 +360*sin(t / 1500.0f), 0.292893 + abs(sin( 0.7853981 + (t-10000.0f) / 3000.0f)));
        drawLongHand(500*cos(t / 5000.0f), 0.292893 + abs(cos( 0.7853981 + (t-10000.0f) / 3000.0f))); 
        tft.update(fb);
        //added for second display, a copy of display 0
        tft1.update(fb);              
        yield(); // to keep the board responsive
        }  

    // PART 5: fading
    while ((t = em) < 40000)
        {
        im.fillScreen(RGB565_Black);  
        drawClock( 150.0f*sin((t-20000.0f) / 2000.0f), 1.0f - (t - 35000.0f)/5000.0f, 1.0f - (t - 35000.0f)/5000.0f);
        drawSmallHand(100 +360*sin(t / 1500.0f), 0.292893 + abs(sin( 0.7853981 + (t-10000.0f) / 3000.0f)), 1.0f - (t - 35000.0f)/5000.0f);
        drawLongHand(500*cos(t / 5000.0f), 0.292893 + abs(cos( 0.7853981 + (t-10000.0f) / 3000.0f)), 1.0f - (t - 35000.0f)/5000.0f); 
        tft.update(fb); 
        //added for second display, a copy of display 0
        tft1.update(fb);             
        yield();
        }  

    // wait a bit before starting over.
     delay(2000);
    }

/** end of file */
donnersm commented 2 years ago

O, I also tried the sketch example dual display that was written by diy-lab. Used a compiled version and also the hex file...both will freeze at some point in time

vindar commented 2 years ago

Thanks, I will test it as soon I as come back. How long does it takes to freeze usually ?

donnersm commented 2 years ago

Some times seconds other times minutes… the longest i had so far was 30 mins.

Verstuurd vanaf mijn iPhone

Op 5 mei 2022 om 20:49 heeft Arvind Singh @.***> het volgende geschreven:

 Thanks, I will test it as soon I as come back. How long does it takes to freeze usually ?

— Reply to this email directly, view it on GitHub, or unsubscribe. You are receiving this because you commented.

donnersm commented 2 years ago

I did some more digging that might save you some time in bug finding... So with the clock sketch, I update the displays like so: tft0.update(frontBuffer, false) tft1.update(frontBuffer, false) however, this will result in a freeze op the teensy at random times... But, And this might help you, If I change at least one of the two lines to tft0.update( frontbuffer, true), my display will become slow but it no longer freezes the teensy. So my guess is that your first initial reaction that it is related to the diff buffers might be right....

Although.....this seems to work for the clock sketch but am not so sure for the other sketches...With one tft.update ( fb, true) I tried compensating for the speed loss by increading the SPi Clock....that worked but then the freeze is also back hmmm...s

vindar commented 2 years ago

Hi,

I tried your code and indeed I can reproduce the bug. I will try to dig into this and see if I can find why the hanging occurs...

donnersm commented 2 years ago

That would be super! and highly appreciated!

vindar commented 2 years ago

Hi,

I just committed some changes that should (hopefully) solve the freezing bug. It looks like the problem was related to interrupt priorities for the intervalTimer objects.

I have been running your test example for a night without freeze. Please let me know if you still encounter the bug.

donnersm commented 2 years ago

I will try that tommorow and let it run over night....I'll let you know asap.Thanks!

perlix commented 2 years ago

Using the dual-display technique for playing 3D videos, I also experience these sporadic random freezes. Would be nice if the changes solve this. Will try it over the weekend and let you know my results as well.

vindar commented 2 years ago

Ok thanks.

I have been running a dual screen demo example for 24h now without freeze... I am not sure the bug is really solved but the problem looks at least mitigated.

donnersm commented 2 years ago

I also have some code to speed up the external ram to compensate for the loss of speed with 2 display and external ram. Will share that as well when i complete my test

donnersm commented 2 years ago

I have been running my sketch (2d) with two displays for 3 days without freeze. Good Work! Using the external added DRAM to compensate for the small DMAMEM. Although it is still pretty fast, a little slowdown of speed is visible on the display. I was able to compensate that by speeding up the internal BUS speed for the DRAM, using the following code in the setup()

// turn on clock (TODO: increase clock speed later, slow & cautious for first release) CCM_CCGR7 |= CCM_CCGR7_FLEXSPI2(CCM_CCGR_OFF); CCM_CBCMR = (CCM_CBCMR & ~(CCM_CBCMR_FLEXSPI2_PODF_MASK | CCM_CBCMR_FLEXSPI2_CLK_SEL_MASK)) | CCM_CBCMR_FLEXSPI2_PODF(4) | CCM_CBCMR_FLEXSPI2_CLK_SEL(2); CCM_CCGR7 |= CCM_CCGR7_FLEXSPI2(CCM_CCGR_ON); I also created a PCB for two displays. IT will be available on my github in about three weeks when I publish my build open source)

perlix commented 2 years ago

No more freezes here as well. Thanks!

vindar commented 2 years ago

Good to know that it is working ok now :-) Thank you for reporting the bug and testing the fix !

@donnersm Thanks for the code snippet, I will try it later and I will also have a look at your PCB: it should be very interesting.

I close the issue now since it is resolved.

donnersm commented 1 year ago

I will provide the example in the next few days. Thanks

Verstuurd vanaf mijn iPhone

Op 5 mei 2022 om 00:45 heeft Arvind Singh @.***> het volgende geschreven:

 Hi,

My initial guess would be an interrupt related problem (but then removing all diff buffers should solve it which you say is not the case). It is strange.... I am on holiday this week and I do not have access to a Teensy 4 and two displays right now but I will check this next week when I come home. Do you have a complete (simple) example that I can run to test the freezing ? Thanks.

— Reply to this email directly, view it on GitHub, or unsubscribe. You are receiving this because you commented.