diff options
Diffstat (limited to 'src/gdisp')
-rw-r--r-- | src/gdisp/driver.h | 36 | ||||
-rw-r--r-- | src/gdisp/gdisp_gdisp.c | 106 |
2 files changed, 124 insertions, 18 deletions
diff --git a/src/gdisp/driver.h b/src/gdisp/driver.h index 82435589..5213e5ae 100644 --- a/src/gdisp/driver.h +++ b/src/gdisp/driver.h @@ -37,6 +37,17 @@ * @{ */ /** + * @brief The display hardware can benefit from being de-initialized when usage is complete. + * @details Can be set to TRUE, FALSE or HARDWARE_AUTODETECT + * + * @note HARDWARE_AUTODETECT is only meaningful when GDISP_TOTAL_CONTROLLERS > 1 + * @note This is most useful for displays such as remote network displays. + */ + #ifndef GDISP_HARDWARE_DEINIT + #define GDISP_HARDWARE_DEINIT HARDWARE_DEFAULT + #endif + + /** * @brief The display hardware can benefit from being flushed. * @details Can be set to TRUE, FALSE or HARDWARE_AUTODETECT * @@ -215,7 +226,7 @@ struct GDisplay { struct GDriver d; // This must be the first element - #define gvmt(g) ((const GDISPVMT const *)(g)->d.vmt) // For ease of access to the vmt member + #define gvmt(g) ((const GDISPVMT const *)((g)->d.vmt)) // For ease of access to the vmt member struct GDISPControl { coord_t Width; @@ -278,6 +289,7 @@ struct GDisplay { typedef struct GDISPVMT { GDriverVMT vmtdriver; bool_t (*init)(GDisplay *g); + void (*deinit)(GDisplay *g); void (*writestart)(GDisplay *g); // Uses p.x,p.y p.cx,p.cy void (*writepos)(GDisplay *g); // Uses p.x,p.y void (*writecolor)(GDisplay *g); // Uses p.color @@ -318,6 +330,17 @@ typedef struct GDISPVMT { */ LLDSPEC bool_t gdisp_lld_init(GDisplay *g); + #if GDISP_HARDWARE_DEINIT || defined(__DOXYGEN__) + /** + * @brief The driver is being de-initialized + * @pre GDISP_HARDWARE_FLUSH is TRUE + * + * @param[in] g The driver structure + * + */ + LLDSPEC void gdisp_lld_deinit(GDisplay *g); + #endif + #if GDISP_HARDWARE_FLUSH || defined(__DOXYGEN__) /** * @brief Flush the current drawing operations to the display @@ -559,6 +582,7 @@ typedef struct GDISPVMT { #else #define gdisp_lld_init(g) gvmt(g)->init(g) + #define gdisp_lld_deinit(g) gvmt(g)->deinit(g) #define gdisp_lld_flush(g) gvmt(g)->flush(g) #define gdisp_lld_write_start(g) gvmt(g)->writestart(g) #define gdisp_lld_write_pos(g) gvmt(g)->writepos(g) @@ -594,12 +618,18 @@ typedef struct GDISPVMT { // Routines needed by the general driver VMT bool_t _gdispInitDriver(GDriver *g, int driverinstance, int systeminstance); - void _gdispDeinitDriver(GDriver *g); + void _gdispPostInitDriver(GDriver *g); + void _gdispDeInitDriver(GDriver *g); // Build the VMT const GDISPVMT const GDISP_DRIVER_VMT[1] = {{ - { GDRIVER_TYPE_DISPLAY, 0, sizeof(GDisplay), _gdispInitDriver, _gdispDeinitDriver }, + { GDRIVER_TYPE_DISPLAY, 0, sizeof(GDisplay), _gdispInitDriver, _gdispPostInitDriver, _gdispDeInitDriver }, gdisp_lld_init, + #if GDISP_HARDWARE_DEINIT + gdisp_lld_deinit, + #else + 0, + #endif #if GDISP_HARDWARE_STREAM_WRITE gdisp_lld_write_start, #if GDISP_HARDWARE_STREAM_POS diff --git a/src/gdisp/gdisp_gdisp.c b/src/gdisp/gdisp_gdisp.c index 5b99da6c..a34788b2 100644 --- a/src/gdisp/gdisp_gdisp.c +++ b/src/gdisp/gdisp_gdisp.c @@ -55,10 +55,12 @@ GDisplay *GDISP; #define MUTEX_INIT(g) gfxMutexInit(&(g)->mutex) #define MUTEX_ENTER(g) gfxMutexEnter(&(g)->mutex) #define MUTEX_EXIT(g) gfxMutexExit(&(g)->mutex) + #define MUTEX_DEINIT(g) gfxMutexDestroy(&(g)->mutex) #else #define MUTEX_INIT(g) #define MUTEX_ENTER(g) #define MUTEX_EXIT(g) + #define MUTEX_DEINIT(g) #endif #define NEED_CLIPPING (GDISP_HARDWARE_CLIP != TRUE && (GDISP_NEED_VALIDATION || GDISP_NEED_CLIP)) @@ -564,18 +566,68 @@ static void line_clip(GDisplay *g) { void _gdispInit(void) { + // Both GDISP_CONTROLLER_LIST and GDISP_CONTROLLER_DISPLAYS are defined - create the required numbers of each controller + #if defined(GDISP_CONTROLLER_LIST) && defined(GDISP_CONTROLLER_DISPLAYS) + { + int i, cnt; + + extern GDriverVMTList GDISP_CONTROLLER_LIST; + static const struct GDriverVMT const * dclist[GDISP_TOTAL_CONTROLLERS] = {GDISP_CONTROLLER_LIST}; + static const unsigned dnlist[GDISP_TOTAL_CONTROLLERS] = {GDISP_CONTROLLER_DISPLAYS}; + + for(i = 0; i < GDISP_TOTAL_CONTROLLERS; i++) { + for(cnt = dnlist[i]; cnt; cnt--) + gdriverRegister(dclist[i]); + } + } + + // Only GDISP_CONTROLLER_LIST is defined - create one of each controller + #elif defined(GDISP_CONTROLLER_LIST) + { + int i; + + extern GDriverVMTList GDISP_CONTROLLER_LIST; + static const struct GDriverVMT const * dclist[GDISP_TOTAL_CONTROLLERS] = {GDISP_CONTROLLER_LIST}; + + for(i = 0; i < GDISP_TOTAL_CONTROLLERS; i++) + gdriverRegister(dclist[i]); + } + + // Only GDISP_TOTAL_DISPLAYS is defined - create the required number of the one controller + #elif GDISP_TOTAL_DISPLAYS > 1 + { + int cnt; + + extern GDriverVMTList GDISPVMT_OnlyOne; + + for(cnt = 0; cnt < GDISP_TOTAL_DISPLAYS; cnt++) + gdriverRegister(GDISPVMT_OnlyOne); + } + + // One and only one display + #else + { + extern GDriverVMTList GDISPVMT_OnlyOne; + + gdriverRegister(GDISPVMT_OnlyOne); + } + #endif + // Re-clear the display after the timeout if we added the logo #if GDISP_STARTUP_LOGO_TIMEOUT > 0 - GDisplay *g; + { + GDisplay *g; - gfxSleepMilliseconds(GDISP_STARTUP_LOGO_TIMEOUT); - initDone = TRUE; + gfxSleepMilliseconds(GDISP_STARTUP_LOGO_TIMEOUT); - for(g = (GDisplay *)gdriverGetNext(GDRIVER_TYPE_DISPLAY, 0); g; g = (GDisplay *)gdriverGetNext(GDRIVER_TYPE_DISPLAY, (GDriver *)g)) { - gdispGClear(g, GDISP_STARTUP_COLOR); - #if GDISP_HARDWARE_FLUSH - gdispGFlush(g); - #endif + for(g = (GDisplay *)gdriverGetNext(GDRIVER_TYPE_DISPLAY, 0); g; g = (GDisplay *)gdriverGetNext(GDRIVER_TYPE_DISPLAY, (GDriver *)g)) { + gdispGClear(g, GDISP_STARTUP_COLOR); + #if GDISP_HARDWARE_FLUSH + gdispGFlush(g); + #endif + } + + initDone = TRUE; } #endif @@ -605,22 +657,32 @@ bool_t _gdispInitDriver(GDriver *g, int driverinstance, int systeminstance) { MUTEX_ENTER(gd); ret = gdisp_lld_init(gd); MUTEX_EXIT(gd); - if (!ret) return FALSE; + return ret; - // Set orientation, clip, blankscreen, startup logo and then flush + #undef gd +} + +void _gdispPostInitDriver(GDriver *g) { + #define gd ((GDisplay *)g) + + // Set orientation, clip #if defined(GDISP_DEFAULT_ORIENTATION) && GDISP_NEED_CONTROL && GDISP_HARDWARE_CONTROL gdispGControl(gd, GDISP_CONTROL_ORIENTATION, (void *)GDISP_DEFAULT_ORIENTATION); #endif #if GDISP_NEED_VALIDATION || GDISP_NEED_CLIP gdispGSetClip(gd, 0, 0, gd->g.Width, gd->g.Height); #endif + + // Clear the Screen gdispGClear(gd, GDISP_STARTUP_COLOR); + // Display the startup logo if this is a static initialised display #if GDISP_STARTUP_LOGO_TIMEOUT > 0 if (!initDone) StartupLogoDisplay(gd); #endif + // Flush #if GDISP_HARDWARE_FLUSH gdispGFlush(gd); #endif @@ -629,14 +691,28 @@ bool_t _gdispInitDriver(GDriver *g, int driverinstance, int systeminstance) { if (!GDISP) GDISP = gd; - return TRUE; - #undef gd } -void _gdispDeinitDriver(GDriver *g) { - (void) g; - // For now do nothing +void _gdispDeInitDriver(GDriver *g) { + #define gd ((GDisplay *)g) + + if (GDISP == gd) + GDISP = (GDisplay *)gdriverGetInstance(GDRIVER_TYPE_DISPLAY, 0); + + #if GDISP_HARDWARE_DEINIT + #if GDISP_HARDWARE_DEINIT == HARDWARE_AUTODETECT + if (gvmt(gd)->deinit) + #endif + { + MUTEX_ENTER(gd); + gdisp_lld_deinit(gd); + MUTEX_EXIT(gd); + } + #endif + MUTEX_DEINIT(gd); + + #undef gd } GDisplay *gdispGetDisplay(unsigned display) { |