Mercurial > public > ostc4
changeset 623:ba83a8ef9bad
Improvment frame Handling:
In previous version, especially during fast menu operations, from time to time a flicker (in case of cyclic updated views) or corrupted menus appeared. Possible root cause is a interferance in the chain: refresh display (~100ms) => release frame (in parallel to) provide frame (~45ms) => clear frame (~45ms). to improve the behaviour the clear frame loop is not iterated until all bufferes are cleared (before one buffer every~45ms). getFrame() does now iterate through all frame buffers instead reusing the first possible (to avoid ghoust views and to provide more time to housekeeping function for cleanup)
author | Ideenmodellierer |
---|---|
date | Sun, 07 Feb 2021 22:04:43 +0100 |
parents | 8f78faf88fc5 |
children | 930f1bbe0ac2 |
files | Discovery/Src/base.c Discovery/Src/gfx_engine.c |
diffstat | 2 files changed, 67 insertions(+), 38 deletions(-) [+] |
line wrap: on
line diff
--- a/Discovery/Src/base.c Wed Feb 03 21:45:48 2021 +0100 +++ b/Discovery/Src/base.c Sun Feb 07 22:04:43 2021 +0100 @@ -292,6 +292,7 @@ uint32_t base_tempLightLevel = 0; static uint8_t wasFirmwareUpdateCheckBattery = 0; static uint8_t DoDisplayRefresh = 0; /* trigger to refresh display data */ +static uint8_t DoHousekeeping = 0; /* trigger to cleanup the frame buffers */ /* Private function prototypes -----------------------------------------------*/ static void SystemClock_Config(void); @@ -497,6 +498,10 @@ deco_loop(); TriggerButtonAction(); + if(DoHousekeeping) + { + DoHousekeeping = housekeepingFrame(); + } if(DoDisplayRefresh) /* set every 100ms by timer interrupt */ { DoDisplayRefresh = 0; @@ -509,7 +514,8 @@ updateMiniLiveLogbook(1); RefreshDisplay(); - TimeoutControl(); /* exit menus if needed */ + DoHousekeeping = 0; /* make sure frames are not cleared before they are transferred */ + TimeoutControl(); /* exit menus if needed */ #ifdef ENABLE_MOTION_CONTROL if((stateUsed->mode == MODE_DIVE) && (settingsGetPointer()->MotionDetection != MOTION_DETECT_OFF)) /* handle motion events in divemode only */ @@ -648,7 +654,7 @@ if (GPIO_Pin == VSYNC_IRQ_PIN) // rechts, unten { GFX_change_LTDC(); - housekeepingFrame(); + DoHousekeeping = 1; /* #ifdef DEMOMODE static uint8_t countCall = 0;
--- a/Discovery/Src/gfx_engine.c Wed Feb 03 21:45:48 2021 +0100 +++ b/Discovery/Src/gfx_engine.c Sun Feb 07 22:04:43 2021 +0100 @@ -3375,27 +3375,45 @@ uint32_t getFrame(uint8_t callerId) { + static uint8_t lastFrameProvided = 0; uint8_t i; - i = 0; - while((i < MAXFRAMES) && (frame[i].status != CLEAR)) +/* first iteration: look for a clear frame */ + i = lastFrameProvided; + do + { i++; + if(i == MAXFRAMES) + { + i = 0; + } + } while((i != lastFrameProvided) && (frame[i].status != CLEAR)); if((i < MAXFRAMES) && (frame[i].status == CLEAR)) { frame[i].status = BLOCKED; frame[i].caller = callerId; + lastFrameProvided = i; return frame[i].StartAddress; } - i = 0; - while((i < MAXFRAMES) && (frame[i].status != RELEASED)) +/* second iteration: look for a frame which may be reused after clearing */ + i = lastFrameProvided; + do + { i++; + if(i == MAXFRAMES) + { + i = 0; + } + }while((i < MAXFRAMES) && (frame[i].status != RELEASED)); + if((i < MAXFRAMES) && (frame[i].status == RELEASED)) { GFX_clear_frame_immediately(frame[i].StartAddress); frame[i].status = BLOCKED; + lastFrameProvided = i; return frame[i].StartAddress; } return 0; @@ -3458,47 +3476,52 @@ } -void housekeepingFrame(void) +uint8_t housekeepingFrame(void) { static uint8_t countLogClear = 0; + uint8_t i; + uint8_t retVal = 1; - if(DMA2D_at_work != 255) - return; - - /* new for debug hw 151202 */ - for(int i=1;i<MAXFRAMECOUNTER;i++) + if(DMA2D_at_work == 255) { - frameCounter[i] = 0; - } - for(int i=1;i<MAXFRAMES;i++) - { - if(frame[i].status == BLOCKED) + /* new for debug hw 151202 */ + for(i=1;i<MAXFRAMECOUNTER;i++) + { + frameCounter[i] = 0; + } + for(int i=1;i<MAXFRAMES;i++) { - if(frame[i].caller < (MAXFRAMECOUNTER - 2)) - frameCounter[frame[i].caller]++; + if(frame[i].status == BLOCKED) + { + if(frame[i].caller < (MAXFRAMECOUNTER - 2)) + frameCounter[frame[i].caller]++; + else + frameCounter[MAXFRAMECOUNTER-3]++; + } + else + if(frame[i].status == RELEASED) + frameCounter[MAXFRAMECOUNTER-2]++; else - frameCounter[MAXFRAMECOUNTER-3]++; + frameCounter[MAXFRAMECOUNTER-1]++; + } + + i = 0; + /* skip frame cleaning for actual frames which have not yet been replaced by new top/bottom frames */ + while((i < MAXFRAMES) && ((frame[i].status != RELEASED) || (frame[i].StartAddress == GFX_get_pActualFrameTop()) || (frame[i].StartAddress == GFX_get_pActualFrameBottom()))) + i++; + + if((i < MAXFRAMES) && (frame[i].status == RELEASED)) + { + if(frame[i].caller == 15) + countLogClear++; + GFX_clear_frame_dma2d(i); } else - if(frame[i].status == RELEASED) - frameCounter[MAXFRAMECOUNTER-2]++; - else - frameCounter[MAXFRAMECOUNTER-1]++; + { + retVal = 0; /* no more frame to be cleaned found */ + } } - - - uint8_t i; - - i = 0; - while((i < MAXFRAMES) && ((frame[i].status != RELEASED) || (frame[i].StartAddress == GFX_get_pActualFrameTop()) || (frame[i].StartAddress == GFX_get_pActualFrameBottom()))) - i++; - - if((i < MAXFRAMES) && (frame[i].status == RELEASED)) - { - if(frame[i].caller == 15) - countLogClear++; - GFX_clear_frame_dma2d(i); - } + return retVal; }