Mercurial > public > ostc4
diff Discovery/Src/gfx_engine.c @ 38:5f11787b4f42
include in ostc4 repository
author | heinrichsweikamp |
---|---|
date | Sat, 28 Apr 2018 11:52:34 +0200 |
parents | |
children | e97deb6e2705 |
line wrap: on
line diff
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/Discovery/Src/gfx_engine.c Sat Apr 28 11:52:34 2018 +0200 @@ -0,0 +1,4074 @@ +/** + ****************************************************************************** + * @file gfx_engine.c + * @author heinrichs weikamp gmbh + * @version V0.0.2 + * @date 30-April-2014 + * @brief Main source file of GFX Graphic Engine + * This file provides firmware functions to manage the following + * functions to draw on the screen: + * + write string to display + * + ****************************************************************************** + * @attention + * + * <h2><center>© COPYRIGHT(c) 2014 heinrichs weikamp</center></h2> + * + ****************************************************************************** + */ + +/* Includes ------------------------------------------------------------------*/ + +#include <stdlib.h> +#include <stdint.h> + +#include "stm32f4xx_hal.h" + +#include "gfx.h" +#include "gfx_engine.h" +#include "gfx_fonts.h" +#include "gfx_colors.h" +#include "ostc.h" +#include "settings.h" +#include "text_multilanguage.h" + +/* Exported variables --------------------------------------------------------*/ + +/* Private types -------------------------------------------------------------*/ + +typedef struct +{ + uint32_t Xdelta; + uint32_t Ydelta; + uint8_t invert; + uint8_t color; + uint8_t dualFont; + uint8_t resize; + uint32_t font; + uint8_t spaceMode; + uint8_t singleSpaceWithSizeOfNextChar; + uint8_t useTinyFont; + uint32_t TinyFont; + int8_t TinyFontExtraYdelta; + tFont *actualFont; + uint8_t doubleSize; +} GFX_CfgWriteString; + +typedef struct +{ + uint32_t pBuffer; + uint32_t height; + uint32_t width; + uint32_t leftStart; + uint32_t bottomStart; +} GFX_layerSingle; +/* +typedef struct +{ + GFX_layerSingle top; + GFX_layerSingle bottom; +} GFX_layersTopBottom; +*/ +typedef struct +{ + uint32_t pActualTopBuffer; + uint32_t pNextTopBuffer[2]; + GFX_layerSingle actualBottom; + GFX_layerSingle nextBottom[2]; + uint8_t boolNextTop; + uint8_t boolNextBottom; +} GFX_layerControl; + +typedef struct +{ + uint32_t StartAddress; + int8_t status; + uint8_t caller; +} SFrameList; + +enum FRAMESTATE +{ + CLEAR = 0, + BLOCKED, + RELEASED +}; + +enum LOGOSTATE +{ + LOGOOFF = 0, + LOGOSTART = 1, + LOGOSTOP = 255 +}; + +// should be 43 +#define MAXFRAMES 39 + +#define SDRAM_BANK_ADDR ((uint32_t)0xD0000000) +#define FBGlobalStart SDRAM_BANK_ADDR +#define FBOffsetEachIndex (800*480*2) + +#define SDRAM_DOUBLE_BUFFER_ONE ((uint32_t)(FBGlobalStart + (MAXFRAMES * FBOffsetEachIndex))) +#define SDRAM_DOUBLE_BUFFER_TWO ((uint32_t)(SDRAM_DOUBLE_BUFFER_ONE + (2 * FBOffsetEachIndex))) +#define SDRAM_DOUBLE_BUFFER_END ((uint32_t)(SDRAM_DOUBLE_BUFFER_TWO + (2 * FBOffsetEachIndex))) + +/* Semi Private variables ---------------------------------------------------------*/ + +DMA2D_HandleTypeDef Dma2dHandle; +LTDC_HandleTypeDef LtdcHandle; + +/* Private variables ---------------------------------------------------------*/ + +uint8_t DMA2D_at_work = 0; + +GFX_layerControl FrameHandler = { 0 }; + +uint32_t pInvisibleFrame = 0; +uint32_t pLogoFrame = 0; +uint8_t logoStatus; +uint32_t pBackgroundHwFrame = 0; +uint8_t backgroundHwStatus; + +SFrameList frame[MAXFRAMES]; + +#define MAXFRAMECOUNTER (28) +uint8_t frameCounter[MAXFRAMECOUNTER] = { 0 }; + +_Bool lock_changeLTDC = 0; + +/* ITM Trace-----------------------------------------------------------------*/ + +#include "stdio.h" + +#define ITM_Port8(n) (*((volatile unsigned char *)(0xE0000000+4*n))) +#define ITM_Port16(n) (*((volatile unsigned short*)(0xE0000000+4*n))) +#define ITM_Port32(n) (*((volatile unsigned long *)(0xE0000000+4*n))) + +#define DEMCR (*((volatile unsigned long *)(0xE000EDFC))) +#define TRCENA 0x01000000 + +struct __FILE { int handle; /* Add whatever needed */ }; +FILE __stdout; +FILE __stdin; + +int fputc(int ch, FILE *f) { + if (DEMCR & TRCENA) { + while (ITM_Port32(0) == 0); + ITM_Port8(0) = ch; + } + return(ch); +} + +uint32_t MinU32GFX(uint32_t a, uint32_t b) +{ + return ((a<b)?a:b); +} + + +uint32_t MaxU32GFX(uint32_t a, uint32_t b) +{ + return((a>b)?a:b); +} + +/* Private function prototypes -----------------------------------------------*/ + +static uint32_t GFX_write_char(GFX_DrawCfgWindow* hgfx, GFX_CfgWriteString* cfg, uint8_t character, tFont *Font); +static uint32_t GFX_write_substring(GFX_CfgWriteString* cfg, GFX_DrawCfgWindow* hgfx, uint8_t textId, int8_t nextCharFor2Byte); +uint32_t GFX_write__Modify_Xdelta__Centered(GFX_CfgWriteString* cfg, GFX_DrawCfgWindow* hgfx, const char *pText); +uint32_t GFX_write__Modify_Xdelta__RightAlign(GFX_CfgWriteString* cfg, GFX_DrawCfgWindow* hgfx, const char *pTextInput); +static void GFX_Error_Handler(void); +static void GFX_Dma2d_TransferComplete(DMA2D_HandleTypeDef* Dma2dHandle); +static void GFX_Dma2d_TransferError(DMA2D_HandleTypeDef* Dma2dHandle); +void GFX_clear_frame_dma2d(uint8_t frameId); + +uint32_t GFX_doubleBufferOne(void); +uint32_t GFX_doubleBufferTwo(void); + + +/* Exported functions --------------------------------------------------------*/ + +uint8_t GFX_logoStatus(void) +{ + return logoStatus; +} + + +void GFX_helper_font_memory_list(const tFont *Font) +{ + int i; + uint8_t character; + + // ----------------------------- + + for(character = 0x20; character < 0xFF; character++) + { + for(i=0;i<Font->length;i++) + { + if(Font->chars[i].code == character) + { + printf("%02x: 0x%0lx 0x%0lx\n\r",(uint8_t)character, (uint32_t)(Font->chars[i].image->data),((uint32_t)(Font->chars[i+1].image->data)-(uint32_t)(Font->chars[i].image->data))); + break; + } + } + } +} + + + +void GFX_SetWindowLayer0(uint32_t pDestination, int16_t XleftGimpStyle, int16_t XrightGimpStyle, int16_t YtopGimpStyle, int16_t YbottomGimpStyle) +{ + int16_t XSize, YSize, X0, Y0; + + if(XleftGimpStyle < 0) XleftGimpStyle = 0; + if(XrightGimpStyle < 0) XrightGimpStyle = 0; + if(XleftGimpStyle > 799) XleftGimpStyle = 800; + if(XrightGimpStyle > 799) XrightGimpStyle = 800; + + if(YtopGimpStyle < 0) YtopGimpStyle = 0; + if(YbottomGimpStyle < 0) YbottomGimpStyle = 0; + if(YtopGimpStyle > 479) YtopGimpStyle = 480; + if(YbottomGimpStyle > 479) YbottomGimpStyle = 480; + +/* + XSize = YbottomGimpStyle - YtopGimpStyle; + YSize = XrightGimpStyle - XleftGimpStyle; + if((XSize <= 0) || (YSize <= 0)) + return; + X0 = 479 - YbottomGimpStyle; + Y0 = XleftGimpStyle; + while((LTDC->CPSR & LTDC_CPSR_CYPOS) <= (uint32_t)800); + HAL_LTDC_SetWindowSize(&LtdcHandle, XSize, YSize, LayerIdx); + HAL_LTDC_SetWindowPosition(&LtdcHandle, X0, Y0,LayerIdx); + HAL_LTDC_SetAddress(&LtdcHandle, pDestination, LayerIdx); +*/ + + XSize = XrightGimpStyle - XleftGimpStyle; + YSize = YbottomGimpStyle - YtopGimpStyle; + if((XSize <= 0) || (YSize <= 0)) + return; + Y0 = 479 - YbottomGimpStyle; + X0 = XleftGimpStyle; + + GFX_SetFrameBottom(pDestination, X0, Y0, XSize, YSize); +} + + +void GFX_logoAutoOff(void) +{ + if(logoStatus == LOGOOFF) + logoStatus = LOGOSTART; +} + +/* +uint8_t GFX_printf_firmware(char *text) +{ + uint8_t zahl, ptr; + + ptr = 0; + zahl = settingsGetPointer()->firmwareVersion16to32bit.ub.first; + if(zahl >= 10) + { + text[ptr++] = '0' + (zahl / 10); + zahl = zahl - ((zahl / 10 ) * 10); + } + text[ptr++] = '0' + zahl; + text[ptr++] = '.'; + + zahl = settingsGetPointer()->firmwareVersion16to32bit.ub.second; + if(zahl >= 10) + { + text[ptr++] = '0' + (zahl / 10); + zahl = zahl - ((zahl / 10 ) * 10); + } + text[ptr++] = '0' + zahl; + text[ptr++] = '.'; + + zahl = settingsGetPointer()->firmwareVersion16to32bit.ub.third; + if(zahl >= 10) + { + text[ptr++] = '0' + (zahl / 10); + zahl = zahl - ((zahl / 10 ) * 10); + } + text[ptr++] = '0' + zahl; + + if(settingsGetPointer()->firmwareVersion16to32bit.ub.betaFlag) + { + text[ptr++] = ' '; + text[ptr++] = 'b'; + text[ptr++] = 'e'; + text[ptr++] = 't'; + text[ptr++] = 'a'; + } + text[ptr] = 0; + + return ptr; +} +*/ + +void GFX_hwBackgroundOn(void) +{ + backgroundHwStatus = LOGOSTART; +} + + +void GFX_hwBackgroundOff(void) +{ + backgroundHwStatus = LOGOSTOP; +} + + +void GFX_build_hw_background_frame(void) +{ + GFX_DrawCfgScreen tLogoTemp; + SWindowGimpStyle windowGimp; + + pBackgroundHwFrame = getFrame(1); + backgroundHwStatus = 0; + + tLogoTemp.FBStartAdress = pBackgroundHwFrame; + tLogoTemp.ImageHeight = 480; + tLogoTemp.ImageWidth = 800; + tLogoTemp.LayerIndex = 1; + + windowGimp.left = (800 - 400) / 2; + windowGimp.top = 0;//(480 - 46) / 2; + + GFX_draw_image_color(&tLogoTemp, windowGimp, &ImgHWcolor); +/* + char localtext[256]; + uint8_t ptr = 0; + + localtext[ptr++] = ' '; + localtext[ptr++] = ' '; + localtext[ptr++] = 'O'; + localtext[ptr++] = 'S'; + localtext[ptr++] = ' '; + ptr += GFX_printf_firmware(&localtext[ptr]); + localtext[ptr] = 0; + + write_content_simple(&tLogoTemp, 0, 800, 240-24, &FontT24,localtext,CLUT_Font020); +*/ +} + + + + +void GFX_build_logo_frame(void) +{ + GFX_DrawCfgScreen tLogoTemp; + SWindowGimpStyle windowGimp; + + pLogoFrame = getFrame(1); + logoStatus = LOGOOFF; + + tLogoTemp.FBStartAdress = pLogoFrame; + tLogoTemp.ImageHeight = 480; + tLogoTemp.ImageWidth = 800; + tLogoTemp.LayerIndex = 1; + + windowGimp.left = (800 - 400) / 2; + windowGimp.top = (480 - 46) / 2; + + GFX_draw_image_color(&tLogoTemp, windowGimp, &ImgHWcolor); +/* + char localtext[256]; + uint8_t ptr = 0; + + localtext[ptr++] = ' '; + localtext[ptr++] = ' '; + localtext[ptr++] = 'O'; + localtext[ptr++] = 'S'; + localtext[ptr++] = ' '; + ptr += GFX_printf_firmware(&localtext[ptr]); + localtext[ptr] = 0; + + write_content_simple(&tLogoTemp, 0, 800, 240-24, &FontT24,localtext,CLUT_Font020); +*/ +} + + +void GFX_init(uint32_t * pDestinationOut) +{ + frame[0].StartAddress = FBGlobalStart; + GFX_clear_frame_immediately(frame[0].StartAddress); + frame[0].status = CLEAR; + frame[0].caller = 0; + + for(int i=1;i<MAXFRAMES;i++) + { + frame[i].StartAddress = frame[i-1].StartAddress + FBOffsetEachIndex; + GFX_clear_frame_immediately(frame[i].StartAddress); + frame[i].status = CLEAR; + frame[i].caller = 0; + } + + for(int i=1;i<MAXFRAMECOUNTER;i++) + { + frameCounter[i] = 0; + } + + pInvisibleFrame = getFrame(2); + *pDestinationOut = pInvisibleFrame; + + GFX_build_logo_frame(); + GFX_build_hw_background_frame(); + + /* Register to memory mode with ARGB8888 as color Mode */ + Dma2dHandle.Init.Mode = DMA2D_R2M; + Dma2dHandle.Init.ColorMode = DMA2D_ARGB4444;//to fake AL88, before: DMA2D_ARGB8888; + Dma2dHandle.Init.OutputOffset = 0; + + /* DMA2D Callbacks Configuration */ + Dma2dHandle.XferCpltCallback = GFX_Dma2d_TransferComplete; + Dma2dHandle.XferErrorCallback = GFX_Dma2d_TransferError; + + Dma2dHandle.Instance = DMA2D; + + /* DMA2D Initialisation */ + if(HAL_DMA2D_Init(&Dma2dHandle) != HAL_OK) + GFX_Error_Handler(); + + if(HAL_DMA2D_ConfigLayer(&Dma2dHandle, 1) != HAL_OK) + GFX_Error_Handler(); + + DMA2D_at_work = 255; +} + + +void GFX_init1_no_DMA(uint32_t * pDestinationOut, uint8_t blockFrames) +{ + frame[0].StartAddress = FBGlobalStart; + GFX_clear_frame_immediately(frame[0].StartAddress); + frame[0].status = CLEAR; + frame[0].caller = 0; + + for(int i=1;i<MAXFRAMES;i++) + { + frame[i].StartAddress = frame[i-1].StartAddress + FBOffsetEachIndex; + GFX_clear_frame_immediately(frame[i].StartAddress); + frame[i].status = CLEAR; + frame[i].caller = 0; + } + + for(int i=0;i<blockFrames;i++) + { + frame[i].status = BLOCKED; + frame[i].caller = 1; + } + + pInvisibleFrame = getFrame(2); + *pDestinationOut = pInvisibleFrame; + + GFX_build_logo_frame(); + GFX_build_hw_background_frame(); +} + + +void GFX_init2_DMA(void) +{ + /* Register to memory mode with ARGB8888 as color Mode */ + Dma2dHandle.Init.Mode = DMA2D_R2M; + Dma2dHandle.Init.ColorMode = DMA2D_ARGB4444;//to fake AL88, before: DMA2D_ARGB8888; + Dma2dHandle.Init.OutputOffset = 0; + + /* DMA2D Callbacks Configuration */ + Dma2dHandle.XferCpltCallback = GFX_Dma2d_TransferComplete; + Dma2dHandle.XferErrorCallback = GFX_Dma2d_TransferError; + + Dma2dHandle.Instance = DMA2D; + + /* DMA2D Initialisation */ + if(HAL_DMA2D_Init(&Dma2dHandle) != HAL_OK) + GFX_Error_Handler(); + + if(HAL_DMA2D_ConfigLayer(&Dma2dHandle, 1) != HAL_OK) + GFX_Error_Handler(); + + DMA2D_at_work = 255; +} + + + +void GFX_SetFrameTop(uint32_t pDestination) +{ + lock_changeLTDC = 1; + uint8_t boolNextTop = !FrameHandler.boolNextTop; + + if(pDestination == 0) + pDestination = pInvisibleFrame; + + FrameHandler.pNextTopBuffer[boolNextTop] = pDestination; + FrameHandler.boolNextTop = boolNextTop; + lock_changeLTDC = 0; +} + + +void GFX_SetFrameBottom(uint32_t pDestination, uint32_t x0, uint32_t y0, uint32_t width, uint32_t height) +{ + lock_changeLTDC = 1; + uint8_t boolNextBottom = !FrameHandler.boolNextBottom; + + if(pDestination == 0) + pDestination = pInvisibleFrame; + + FrameHandler.nextBottom[boolNextBottom].pBuffer = pDestination; + FrameHandler.nextBottom[boolNextBottom].height = height; + FrameHandler.nextBottom[boolNextBottom].width = width; + FrameHandler.nextBottom[boolNextBottom].leftStart = x0; + FrameHandler.nextBottom[boolNextBottom].bottomStart = y0; + FrameHandler.boolNextBottom = boolNextBottom; + lock_changeLTDC = 0; +} + + +void GFX_SetFramesTopBottom(uint32_t pTop, uint32_t pBottom, uint32_t heightBottom) +{ + GFX_SetFrameTop(pTop); + GFX_SetFrameBottom(pBottom, 0, 0, 800, heightBottom); +} + + +uint32_t GFX_get_pActualFrameTop(void) +{ + return FrameHandler.pActualTopBuffer; +} + + +uint32_t GFX_get_pActualFrameBottom(void) +{ + return FrameHandler.actualBottom.pBuffer; +} + + +void GFX_start_VSYNC_IRQ(void) +{ + GPIO_InitTypeDef GPIO_InitStructure; + + GPIO_InitStructure.Mode = GPIO_MODE_IT_FALLING; + GPIO_InitStructure.Pull = GPIO_NOPULL; + GPIO_InitStructure.Speed = GPIO_SPEED_LOW; + GPIO_InitStructure.Pin = VSYNC_IRQ_PIN; + HAL_GPIO_Init(VSYNC_IRQ_GPIO_PORT, &GPIO_InitStructure); + + HAL_NVIC_SetPriority(VSYNC_IRQ_EXTI_IRQn, 1, 0); + HAL_NVIC_EnableIRQ(VSYNC_IRQ_EXTI_IRQn); +} + + +void GFX_change_LTDC(void) +{ + if(lock_changeLTDC == 1) + return; + + uint32_t pTop = 0; + uint32_t pBot = 0; + uint32_t heightBot = 0; + uint32_t widthBot = 0; + uint32_t leftStartBot = 0; + uint32_t bottomStartBot = 0; + uint8_t change_position = 0; + uint8_t change_size = 0; + + // Top Frame + pTop = FrameHandler.pNextTopBuffer[FrameHandler.boolNextTop]; + if(FrameHandler.pActualTopBuffer != pTop) + { + HAL_LTDC_SetAddress(&LtdcHandle, pTop, 1); + FrameHandler.pActualTopBuffer = pTop; + } + + // Bottom Frame + if(logoStatus != LOGOOFF) + { + switch(logoStatus) + { + case LOGOSTART: + HAL_LTDC_SetAlpha(&LtdcHandle, 0, 1); + HAL_LTDC_SetAlpha(&LtdcHandle, 34, 0); + HAL_LTDC_ConfigCLUT(&LtdcHandle, (uint32_t *)indexHWcolor, indexHWcolorSIZE, 0); + HAL_LTDC_SetAddress(&LtdcHandle, pLogoFrame, 0); + HAL_LTDC_SetWindowSize(&LtdcHandle, 480, 800, 0); + HAL_LTDC_SetWindowPosition(&LtdcHandle, 0, 0, 0); + logoStatus = 2; + break; + + case LOGOSTOP: + HAL_LTDC_SetAlpha(&LtdcHandle, 255, 1); + HAL_LTDC_ConfigCLUT(&LtdcHandle, ColorLUT, CLUT_END, 0); + + pBot = FrameHandler.nextBottom[FrameHandler.boolNextBottom].pBuffer; + heightBot = FrameHandler.nextBottom[FrameHandler.boolNextBottom].height; + widthBot = FrameHandler.nextBottom[FrameHandler.boolNextBottom].width; + leftStartBot = FrameHandler.nextBottom[FrameHandler.boolNextBottom].leftStart; + bottomStartBot = FrameHandler.nextBottom[FrameHandler.boolNextBottom].bottomStart; + HAL_LTDC_SetWindowSize(&LtdcHandle, heightBot, widthBot, 0); + HAL_LTDC_SetWindowPosition(&LtdcHandle, bottomStartBot, leftStartBot, 0); + HAL_LTDC_SetAddress(&LtdcHandle, pBot, 0); + HAL_LTDC_SetAlpha(&LtdcHandle, 255, 0); + FrameHandler.actualBottom.height = heightBot; + FrameHandler.actualBottom.width = widthBot; + FrameHandler.actualBottom.leftStart = leftStartBot; + FrameHandler.actualBottom.bottomStart = bottomStartBot; + FrameHandler.actualBottom.pBuffer = pBot; + + logoStatus = LOGOOFF; + if(backgroundHwStatus == 2) + { + backgroundHwStatus = LOGOSTART; + } + break; + default: + if(logoStatus < 35) + { + logoStatus++; + if(logoStatus <= 15) + HAL_LTDC_SetAlpha(&LtdcHandle, 17*logoStatus, 0); + } + else + { + logoStatus +=20; + HAL_LTDC_SetAlpha(&LtdcHandle, logoStatus-55, 1); + HAL_LTDC_SetAlpha(&LtdcHandle, 255+55-logoStatus, 0); + } + break; + } + return; + } + else if (backgroundHwStatus != LOGOOFF) + { + switch(backgroundHwStatus) + { + case LOGOSTART: + HAL_LTDC_ConfigCLUT(&LtdcHandle, (uint32_t *)indexHWcolor, indexHWcolorSIZE, 0); + HAL_LTDC_SetAddress(&LtdcHandle, pBackgroundHwFrame, 0); + HAL_LTDC_SetWindowSize(&LtdcHandle, 480, 800, 0); + HAL_LTDC_SetWindowPosition(&LtdcHandle, 0, 0, 0); + backgroundHwStatus = 2; + break; + + case LOGOSTOP: + HAL_LTDC_ConfigCLUT(&LtdcHandle, ColorLUT, CLUT_END, 0); + pBot = FrameHandler.nextBottom[FrameHandler.boolNextBottom].pBuffer; + heightBot = FrameHandler.nextBottom[FrameHandler.boolNextBottom].height; + widthBot = FrameHandler.nextBottom[FrameHandler.boolNextBottom].width; + leftStartBot = FrameHandler.nextBottom[FrameHandler.boolNextBottom].leftStart; + bottomStartBot = FrameHandler.nextBottom[FrameHandler.boolNextBottom].bottomStart; + HAL_LTDC_SetWindowSize(&LtdcHandle, heightBot, widthBot, 0); + HAL_LTDC_SetWindowPosition(&LtdcHandle, bottomStartBot, leftStartBot, 0); + HAL_LTDC_SetAddress(&LtdcHandle, pBot, 0); + HAL_LTDC_SetAlpha(&LtdcHandle, 255, 0); + FrameHandler.actualBottom.height = heightBot; + FrameHandler.actualBottom.width = widthBot; + FrameHandler.actualBottom.leftStart = leftStartBot; + FrameHandler.actualBottom.bottomStart = bottomStartBot; + FrameHandler.actualBottom.pBuffer = pBot; + backgroundHwStatus = LOGOOFF; + break; + + default: + break; + } + return; + } + else + { + pBot = FrameHandler.nextBottom[FrameHandler.boolNextBottom].pBuffer; + heightBot = FrameHandler.nextBottom[FrameHandler.boolNextBottom].height; + widthBot = FrameHandler.nextBottom[FrameHandler.boolNextBottom].width; + leftStartBot = FrameHandler.nextBottom[FrameHandler.boolNextBottom].leftStart; + bottomStartBot = FrameHandler.nextBottom[FrameHandler.boolNextBottom].bottomStart; + + if(FrameHandler.actualBottom.pBuffer == pBot) + pBot = 0; + + if((FrameHandler.actualBottom.height != heightBot) || (FrameHandler.actualBottom.width != widthBot)) + change_size = 1; + + if((FrameHandler.actualBottom.leftStart != leftStartBot) || (FrameHandler.actualBottom.bottomStart != bottomStartBot)) + change_position = 1; + + if(pBot || change_size || change_position) + { + if(heightBot && widthBot) + HAL_LTDC_SetWindowSize(&LtdcHandle, heightBot, widthBot, 0); + + if(change_position || leftStartBot || bottomStartBot) + HAL_LTDC_SetWindowPosition(&LtdcHandle, bottomStartBot, leftStartBot, 0); + + if(pBot) + HAL_LTDC_SetAddress(&LtdcHandle, pBot, 0); + + if(change_size) + { + FrameHandler.actualBottom.height = heightBot; + FrameHandler.actualBottom.width = widthBot; + } + if(change_position) + { + FrameHandler.actualBottom.leftStart = leftStartBot; + FrameHandler.actualBottom.bottomStart = bottomStartBot; + } + if(pBot) + FrameHandler.actualBottom.pBuffer = pBot; + } + } +} + +uint8_t GFX_is_colorschemeDiveStandard(void) +{ + return (ColorLUT[CLUT_Font027] == 0x00FFFFFF); +} + + +void change_CLUT_entry(uint8_t entryToChange, uint8_t entryUsedForChange) +{ +/* bug fix + static uint8_t counter = 0; + + if(entryToChange == 0x1C) + counter++; +*/ + ColorLUT[entryToChange] = ColorLUT[entryUsedForChange]; + HAL_LTDC_ConfigCLUT(&LtdcHandle, ColorLUT, CLUT_END, 1); + if(logoStatus == LOGOOFF) + HAL_LTDC_ConfigCLUT(&LtdcHandle, ColorLUT, CLUT_END, 0); +} + + +void GFX_use_colorscheme(uint8_t colorscheme) +{ + uint8_t ColorSchemeStart; + + if(colorscheme > 3) + colorscheme = 0; + + ColorSchemeStart = CLUT_Colorscheme0 + (8 * colorscheme); + for(int i=1; i<8; i++) + { + ColorLUT[CLUT_Font027 + i] = ColorLUT[ColorSchemeStart + i]; + } + change_CLUT_entry(CLUT_Font027, ColorSchemeStart); +} + + +void GFX_VGA_transform(uint32_t pSource, uint32_t pDestination) +{ + int h, v; + uint32_t offsetSource, offsetSourceStartOfLine; + + offsetSourceStartOfLine = 480 + 480 - 2; + for(v=0;v<480;v++) + { + offsetSource = offsetSourceStartOfLine; + for(h=0;h<640;h++) + { + *(__IO uint8_t*)pDestination = *(uint8_t*)(pSource + offsetSource); + pDestination++; + offsetSource += 1; + *(__IO uint8_t*)pDestination = *(uint8_t*)(pSource + offsetSource); + pDestination++; + offsetSource += 480 + 479; + } + offsetSourceStartOfLine -= 2; + } +} + +HAL_StatusTypeDef GFX_SetBackgroundColor(uint32_t LayerIdx, uint8_t red, uint8_t green, uint8_t blue) +{ + uint32_t tmp = 0; + uint32_t tmp1 = 0; + + /* Process locked */ + __HAL_LOCK(&LtdcHandle); + + /* Change LTDC peripheral state */ + LtdcHandle.State = HAL_LTDC_STATE_BUSY; + + /* Check the parameters */ + assert_param(IS_LTDC_LAYER(LayerIdx)); + + /* Copy new layer configuration into handle structure */ + LtdcHandle.LayerCfg[LayerIdx].Backcolor.Red = red; + LtdcHandle.LayerCfg[LayerIdx].Backcolor.Green = green; + LtdcHandle.LayerCfg[LayerIdx].Backcolor.Blue = blue; + + /* Configure the LTDC Layer */ + tmp = ((uint32_t)(green) << 8); + tmp1 = ((uint32_t)(red) << 16); + __HAL_LTDC_LAYER(&LtdcHandle, LayerIdx)->DCCR &= ~(LTDC_LxDCCR_DCBLUE | LTDC_LxDCCR_DCGREEN | LTDC_LxDCCR_DCRED | LTDC_LxDCCR_DCALPHA); + __HAL_LTDC_LAYER(&LtdcHandle, LayerIdx)->DCCR = (blue | tmp | tmp1 | 0xFF); + + /* Sets the Reload type */ + LtdcHandle.Instance->SRCR = LTDC_SRCR_IMR; + + /* Initialize the LTDC state*/ + LtdcHandle.State = HAL_LTDC_STATE_READY; + + /* Process unlocked */ + __HAL_UNLOCK(&LtdcHandle); + +return HAL_OK; +} + + +void GFX_clear_frame_immediately(uint32_t pDestination) +{ + uint32_t i; + + for(i = 200*480; i > 0; i--) + { + *(__IO uint16_t*)pDestination = 0; + pDestination += 2; + *(__IO uint16_t*)pDestination = 0; + pDestination += 2; + *(__IO uint16_t*)pDestination = 0; + pDestination += 2; + *(__IO uint16_t*)pDestination = 0; + pDestination += 2; + } +} + + +void GFX_clear_window_immediately(GFX_DrawCfgWindow* hgfx) +{ + uint32_t pDestination, i, j; + uint16_t left, width, bottom, height, nextlineStep; + + pDestination = (uint32_t)hgfx->Image->FBStartAdress; + + left = hgfx->WindowX0; + width = 1 + hgfx->WindowX1 - left; + bottom = hgfx->WindowY0; + height = 1 + hgfx->WindowY1 - bottom; + nextlineStep = hgfx->Image->ImageHeight - height; + nextlineStep *= 2; + + pDestination += 2 * bottom; + pDestination += 2 * hgfx->Image->ImageHeight * left; + + for(j = width; j > 0; j--) + { + for(i = height; i > 0; i--) + { + *(__IO uint16_t*)pDestination = 0; + pDestination += 2; + } + pDestination += nextlineStep; + } +} + + +void GFX_clear_frame_dma2d(uint8_t frameId) +{ + if(frameId >= MAXFRAMES) + return; + + DMA2D_at_work = frameId; + + if (HAL_DMA2D_Start_IT(&Dma2dHandle, 0x0000000000, frame[frameId].StartAddress, 480, 800) != HAL_OK) + GFX_Error_Handler(); +} + + +void GFX_fill_buffer(uint32_t pDestination, uint8_t alpha, uint8_t color) +{ + + union al88_u + { + uint8_t al8[2]; + uint16_t al88; + }; + + union al88_u colorcombination; + uint32_t i; + + colorcombination.al8[0] = color; + colorcombination.al8[1] = alpha; + + for(i = 800*480; i > 0; i--) + { + *(__IO uint16_t*)pDestination = colorcombination.al88; + pDestination += 2; + } +} + + +void gfx_flip(point_t *p1, point_t *p2) +{ + point_t temp; + + temp = *p1; + *p1 = *p2; + *p2 = temp; +} + + +static inline void gfx_brush(uint8_t thickness, GFX_DrawCfgScreen *hgfx, uint16_t x0, uint16_t y0, uint8_t color) +{ + uint32_t pDestination; + uint8_t offset = thickness/2; + + pDestination = hgfx->FBStartAdress + 2*(x0 - offset)*hgfx->ImageHeight + 2*(y0-offset); + for(int x=thickness;x>0;x--) + { + for(int y=thickness;y>0;y--) + { + *(__IO uint16_t*)pDestination = 0xFF00 + color; + pDestination +=2; + } + pDestination += 2*(hgfx->ImageHeight - thickness); + } +} + + +void GFX_draw_thick_line(uint8_t thickness, GFX_DrawCfgScreen *hgfx, point_t start, point_t stop, uint8_t color) +{ + if(thickness < 2) + GFX_draw_line(hgfx, start, stop, color); + + int x0 = start.x; + int y0 = start.y; + int x1 = stop.x; + int y1 = stop.y; + int dx = abs(x1-x0), sx = x0<x1 ? 1 : -1; + int dy = abs(y1-y0), sy = y0<y1 ? 1 : -1; + int err = (dx>dy ? dx : -dy)/2, e2; + + + if(start.x == stop.x) + { + if(start.y > stop.y) gfx_flip(&start,&stop); + for (int j = stop.y - start.y; j > 0; j--) + { + gfx_brush(thickness,hgfx,start.x,start.y++,color); + } + } + else + if(start.y == stop.y) + { + if(start.x > stop.x) gfx_flip(&start,&stop); + + for (int j = stop.x - start.x; j > 0; j--) + { + gfx_brush(thickness,hgfx,start.x++,start.y,color); + } + } + else // diagonal + { + for(;;) + { + gfx_brush(thickness,hgfx,x0,y0,color); + if (x0==x1 && y0==y1) break; + e2 = err; + if (e2 >-dx) { err -= dy; x0 += sx; } + if (e2 < dy) { err += dx; y0 += sy; } + } + } +} + + +void GFX_draw_line(GFX_DrawCfgScreen *hgfx, point_t start, point_t stop, uint8_t color) +{ + uint32_t pDestination; + uint32_t j; + + if(start.x == stop.x) + { + if(start.y > stop.y) gfx_flip(&start,&stop); + pDestination = (uint32_t)hgfx->FBStartAdress; + pDestination += start.x * hgfx->ImageHeight * 2; + pDestination += start.y * 2; + for (j = stop.y - start.y; j > 0; j--) + { + *(__IO uint16_t*)pDestination = 0xFF00 + color; + pDestination += 2; + } + } + else + if(start.y == stop.y) + { + if(start.x > stop.x) gfx_flip(&start,&stop); + pDestination = (uint32_t)hgfx->FBStartAdress; + pDestination += start.x * hgfx->ImageHeight * 2; + pDestination += start.y * 2; + for (j = stop.x - start.x; j > 0; j--) + { + *(__IO uint16_t*)pDestination = 0xFF00 + color; + pDestination += hgfx->ImageHeight * 2; + } + } + else // diagonal + { + int x0 = start.x; + int y0 = start.y; + int x1 = stop.x; + int y1 = stop.y; + int dx = abs(x1-x0), sx = x0<x1 ? 1 : -1; + int dy = abs(y1-y0), sy = y0<y1 ? 1 : -1; + int err = (dx>dy ? dx : -dy)/2, e2; + + for(;;) + { + pDestination = (uint32_t)hgfx->FBStartAdress; + pDestination += ((x0 * hgfx->ImageHeight) + y0) * 2; + *(__IO uint16_t*)pDestination = 0xFF00 + color; + if (x0==x1 && y0==y1) break; + e2 = err; + if (e2 >-dx) { err -= dy; x0 += sx; } + if (e2 < dy) { err += dx; y0 += sy; } + } + } +} + + +void GFX_draw_image_monochrome(GFX_DrawCfgScreen *hgfx, SWindowGimpStyle window, const tImage *image, uint8_t color) +{ + uint32_t pDestination; + uint32_t j; + point_t start, stop; + + start.x = window.left; + start.y = (hgfx->ImageHeight - image->height - window.top); + stop.y = start.y + image->height; + stop.x = start.x + image->width; + j = 0; + + for(int xx = start.x; xx < stop.x; xx++) + { + pDestination = (uint32_t)hgfx->FBStartAdress; + pDestination += xx * hgfx->ImageHeight * 2; + pDestination += start.y * 2; + for(int yy = start.y; yy < stop.y; yy++) + { + *(__IO uint8_t*)pDestination = color; + pDestination += 1; + *(__IO uint8_t*)pDestination = image->data[j++]; + pDestination += 1; + } + } +} + + +void GFX_draw_image_color(GFX_DrawCfgScreen *hgfx, SWindowGimpStyle window, const tImage *image) +{ + uint32_t pDestination; + uint32_t j; + point_t start, stop; + + start.x = window.left; + start.y = (hgfx->ImageHeight - image->height - window.top); + stop.y = start.y + image->height; + stop.x = start.x + image->width; + j = 0; + + for(int xx = start.x; xx < stop.x; xx++) + { + pDestination = (uint32_t)hgfx->FBStartAdress; + pDestination += xx * hgfx->ImageHeight * 2; + pDestination += start.y * 2; + for(int yy = start.y; yy < stop.y; yy++) + { + *(__IO uint8_t*)pDestination = image->data[j++]; + pDestination += 1; + *(__IO uint8_t*)pDestination = 0xFF; + pDestination += 1; + } + } +} + + +int16_Point_t switchToOctantZeroFrom(uint8_t octant, int16_t x, int16_t y) +{ + int16_Point_t answer; + switch(octant) + { + case 0:// return (x,y); + answer.x = x; + answer.y = y; + break; + case 1:// return (y,x); + answer.x = y; + answer.y = x; + break; + case 2:// return (y, -x); + answer.x = y; + answer.y = -x; + break; + case 3:// return (-x, y); + answer.x = -x; + answer.y = y; + break; + case 4:// return (-x, -y); + answer.x = -x; + answer.y = -y; + break; + case 5:// return (-y, -x); + answer.x = -y; + answer.y = -x; + break; + case 6:// return (-y, x); + answer.x = -y; + answer.y = x; + break; + case 7:// return (x, -y); + answer.x = x; + answer.y = -y; + break; + } + return answer; +} + +/* this is NOT fast nor optimized */ +void GFX_draw_pixel(GFX_DrawCfgScreen *hgfx, int16_t x, int16_t y, uint8_t color) +{ + uint32_t pDestination; + + pDestination = (uint32_t)hgfx->FBStartAdress; + pDestination += x * hgfx->ImageHeight * 2; + pDestination += y * 2; + + *(__IO uint8_t*)pDestination = color; + pDestination += 1; + *(__IO uint8_t*)pDestination = 0xFF; +} + + +/* store the quarter circle for given radius */ +void GFX_draw_circle_with_MEMORY(uint8_t use_memory, GFX_DrawCfgScreen *hgfx, point_t center, uint8_t radius, int8_t color) +{ +} + +/* this is NOT fast nor optimized */ +void GFX_draw_circle(GFX_DrawCfgScreen *hgfx, point_t center, uint8_t radius, int8_t color) +{ + int x, y; + int l; + int r2, y2; + int y2_new; + int ty; + + /* cos pi/4 = 185363 / 2^18 (approx) */ + l = (radius * 185363) >> 18; + + /* hw */ + l += 1; + + /* At x=0, y=radius */ + y = radius; + + r2 = y2 = y * y; + ty = (2 * y) - 1; + y2_new = r2 + 3; + + for (x = 0; x <= l; x++) { + y2_new -= (2 * x) - 3; + + if ((y2 - y2_new) >= ty) { + y2 -= ty; + y -= 1; + ty -= 2; + } + + GFX_draw_pixel (hgfx, x + center.x, y + center.y, color); + GFX_draw_pixel (hgfx, x + center.x, -y + center.y, color); + GFX_draw_pixel (hgfx, -x + center.x, y + center.y, color); + GFX_draw_pixel (hgfx, -x + center.x, -y + center.y, color); + + GFX_draw_pixel (hgfx, y + center.x, x + center.y, color); + GFX_draw_pixel (hgfx, y + center.x, -x + center.y, color); + GFX_draw_pixel (hgfx, -y + center.x, x + center.y, color); + GFX_draw_pixel (hgfx, -y + center.x, -x + center.y, color); + } +} + + +void GFX_draw_colorline(GFX_DrawCfgScreen *hgfx, point_t start, point_t stop, uint8_t color) +{ + uint32_t pDestination; + uint32_t j; + uint32_t temp; + + if(start.x == stop.x) + { + if(stop.y < start.y) + { + temp = stop.y; + stop.y = start.y; + start.y = temp; + } + pDestination = (uint32_t)hgfx->FBStartAdress; + pDestination += start.x * hgfx->ImageHeight * 2; + pDestination += start.y * 2; + for (j = stop.y - start.y; j > 0; j--) + { + *(__IO uint8_t*)pDestination = color; + pDestination += 1; + *(__IO uint8_t*)pDestination = 0xFF; + pDestination += 1; + } + } + else + if(start.y == stop.y) + { + if(stop.x < start.x) + { + temp = stop.x; + stop.x = start.x; + start.x = temp; + } + pDestination = (uint32_t)hgfx->FBStartAdress; + pDestination += start.x * hgfx->ImageHeight * 2; + pDestination += start.y * 2; + for (j = stop.x - start.x; j > 0; j--) + { + *(__IO uint8_t*)pDestination = color; + pDestination += 1; + *(__IO uint8_t*)pDestination = 0xFF; + pDestination -= 1; + pDestination += hgfx->ImageHeight * 2; + } + } + else // diagonal Bresenham's_line_algorithm + { + int x0 = start.x; + int y0 = start.y; + int x1 = stop.x; + int y1 = stop.y; + int dx = abs(x1-x0), sx = x0<x1 ? 1 : -1; + int dy = abs(y1-y0), sy = y0<y1 ? 1 : -1; + int err = (dx>dy ? dx : -dy)/2, e2; + + for(;;) + { + pDestination = (uint32_t)hgfx->FBStartAdress; + pDestination += ((x0 * hgfx->ImageHeight) + y0) * 2; + *(__IO uint8_t*)pDestination = color; + pDestination += 1; + *(__IO uint8_t*)pDestination = 0xFF; + if (x0==x1 && y0==y1) break; + e2 = err; + if (e2 >-dx) { err -= dy; x0 += sx; } + if (e2 < dy) { err += dx; y0 += sy; } + } + } +} + + +void GFX_draw_Grid(GFX_DrawCfgScreen *hgfx, SWindowGimpStyle window, int vlines, float vdeltaline, int hlines, float hdeltalines, uint8_t color) +{ + point_t p1; + point_t p2; + int winthight = window.bottom - window.top; + int winwidth = window.right - window.left; + float deltaline = 0; + + if(vlines > 0) + { + deltaline = ((float)winwidth) /vlines; + + p1.y = 479 - window.top; + p2.y = 479 - window.bottom; + for(int i = 0; i <= vlines; i++) + { + p1.x = window.left + (int)(i * deltaline + 0.5f); + p2.x = p1.x ; + GFX_draw_colorline(hgfx, p1,p2, color ); + } + } + if(vdeltaline > 0) + { + p1.y = 479 - window.top; + p2.y = 479 - window.bottom; + for(int i = 0; i < winwidth/vdeltaline; i++) + { + p1.x = window.left + (int)(i * vdeltaline + 0.5f); + p2.x = p1.x ; + GFX_draw_colorline(hgfx, p1,p2, color ); + } + } + if(hlines > 0) + { + deltaline = ((float)winthight)/hlines; + p1.x = window.left; + p2.x = window.right; + for(int i = 0; i <= hlines; i++) + { + p1.y = 479 - window.top - (int)(i * deltaline + 0.5f); + p2.y = p1.y; + GFX_draw_colorline(hgfx, p1,p2, color ); + } + } +} + +/* drawVeilUntil ist auff�llen des Bereichs unter der Kurve mit etwas hellerer Farbe + * Xdivide ist nichr benutzt, wird weggelassen in dieser Version + */ +/* +void GFX_graph_print(GFX_DrawCfgScreen *hgfx, const SWindowGimpStyle *window, uint16_t drawVeilUntil, uint8_t Xdivide, uint16_t dataMin, uint16_t dataMax, uint16_t *data, uint16_t datalength, uint8_t color, uint8_t *colour_data) +{ + if(window->bottom > 479) + return; + if(window->top > 479) + return; + if(window->right > 799) + return; + if(window->left > 799) + return; + if(window->bottom < 0) + return; + if(window->top < 0) + return; + if(window->right < 0) + return; + if(window->left < 0) + return; + if(window->bottom <= window->top) + return; + if(window->right <= window->left) + return; + + uint16_t windowwidth = (uint16_t)window->right - (uint16_t)window->left; + + if(dataMax == dataMin) + dataMax++; + + uint8_t invert = 0; + if(dataMin > dataMax) + { + uint16_t dataFlip; + dataFlip = dataMin; + dataMin = dataMax; + dataMax = dataFlip; + invert = 1; + } + else + invert = 0; + + uint16_t dataDelta = 0; + dataDelta = dataMax - dataMin; + + uint8_t colormask = color; + + uint16_t loopX, loopData; + loopX = 0; + loopData = 0; + while((loopX <= windowwidth) & (loopData < datalength)) + { + + } + + + uint32_t pDestination_zero_veil = 0; + uint32_t pDestination = 0; + uint32_t pDestinationOld = 0; + int windowwidth = -1; + int windowheight = -1; + int w1 = -1; + int w2 = -1; + int value = -1; + uint8_t colormask = 0; + + // preparation + windowheight = window->bottom - window->top; + windowwidth = window->right - window->left; + pDestination_zero_veil = hgfx->FBStartAdress + 2 * ( (479 - (drawVeilUntil - 2) ) + ( (window->left) * hgfx->ImageHeight) ); + + while((w1 <= windowwidth) & (w2 < datalength)) + { + // before + if(colour_data != NULL) + { + colormask = color + colour_data[w2]; + } + pDestination = hgfx->FBStartAdress + 2 * ( (479 - (window->top + value) ) + ( (w1 + window->left) * hgfx->ImageHeight) ); + + // after + pDestination_zero_veil += (window->left) * hgfx->ImageHeight; + } +} +*/ + + + +// =============================================================================== +// GFX_graph_print +/// @brief Print all those nice curves, especially in logbook und miniLiveLogGraph +/// @version 0.0.2 hw 160519 +/// +/// 151022 hw -bug fix +/// - die aktuelle Version macht keine Linien mehr �ber die gesamte Bildschirmh�he. +/// - daf�r sind L�cher in der Kurve (z.B. Temperaturgraph Tauchgang Matthias 17.10.15 15:19) +/// +/// more details about range can be found in show_logbook_logbook_show_log_page2() - temperature graph +/// +/// @param window: top and bottom is only the range used by the data of the graph, not the entire screen / scale +/// @param drawVeilUntil: ist auff�llen des Bereichs unter der Kurve mit etwas hellerer Farbe +/// @param Xdivide: wird bisher nichr benutzt. +// =============================================================================== + + +void GFX_graph_print(GFX_DrawCfgScreen *hgfx, const SWindowGimpStyle *window, int16_t drawVeilUntil, uint8_t Xdivide, uint16_t dataMin, uint16_t dataMax, uint16_t *data, uint16_t datalength, uint8_t color, uint8_t *colour_data) +{ + //uint32_t pDestination,pDestination_old, + uint32_t pDestination_tmp,pDestination_end, pDestination_start, pDestination_zero_veil; + + uint32_t max = 0; + int windowheight = -1; + int windowwidth = -1; + int i = -1; + int w1 = -1; + int w2 = -1; + + uint32_t h_ulong = 0; + uint32_t h_ulong_old = 0; + _Bool invert = 0; + + uint16_t dataDelta = 0; + uint16_t dataDeltaHalve = 0; + uint16_t dataTemp = 0; + + uint8_t colorDataTemp; + uint8_t colormask = 0; + + if(dataMin > dataMax) + { + uint16_t dataFlip; + dataFlip = dataMin; + dataMin = dataMax; + dataMax = dataFlip; + invert = 1; + } + else + invert = 0; + + colormask = color; + + + if(window->bottom > 479) + return; + if(window->top > 479) + return; + if(window->right > 799) + return; + if(window->left > 799) + return; + if(window->bottom < 0) + return; + if(window->top < 0) + return; + if(window->right < 0) + return; + if(window->left < 0) + return; + if(window->bottom <= window->top) + return; + if(window->right <= window->left) + return; + + windowheight = window->bottom - window->top ; + windowwidth = window->right - window->left; + w1 = 0; + w2 = 0; + if(dataMax == dataMin) + dataMax++; + dataDelta = (unsigned long)(dataMax - dataMin); + dataDeltaHalve = dataDelta / 2; + while((w1 <= windowwidth) & (w2 < datalength)) + { + int tmp = (10 * w1 * (long)datalength)/windowwidth; + w2 = tmp/10; + int rest = tmp - w2*10; + if(rest >= 5) + w2++; + + if((datalength - 1) < w2) + w2 = datalength-1; + + if(colour_data != NULL) + { + colorDataTemp = colour_data[w2]; + colormask = color + colorDataTemp; + } + + dataTemp = data[w2]; + if(Xdivide > 1) + { + w2++; + for(i=1;i<Xdivide;i++) + { + if(data[w2]>dataTemp) + dataTemp = data[w2]; + w2++; + } + } + + if(dataTemp > dataMin) + dataTemp -= dataMin; + else + dataTemp = 0; + + if(invert) + { + if(dataTemp < dataDelta) + dataTemp = dataDelta - dataTemp; + else + dataTemp = 0; + } + + h_ulong = (unsigned long)dataTemp; + h_ulong *= windowheight; + h_ulong += dataDeltaHalve; + h_ulong /= dataDelta; + + if(h_ulong > (window->bottom - window->top)) + h_ulong = (window->bottom - window->top); + + if(drawVeilUntil > 0) + { + pDestination_zero_veil = hgfx->FBStartAdress + 2 * ( (479 - (drawVeilUntil - 2) ) + ( (w1 + window->left) * hgfx->ImageHeight) ); + } + else if(drawVeilUntil < 0 ) + { + pDestination_zero_veil = hgfx->FBStartAdress + 2 * ( (479 + (drawVeilUntil) ) + ( (w1 + window->left) * hgfx->ImageHeight) ); + } + + if(h_ulong + window->top > max) + { + max = h_ulong + window->top; + } + +// hw 160519 wof�r ist das? Damit funktioniert Temperatur 25,5�C nicht! +// if((dataMax == 255) || (data[w2] != 255)) +// { + //output_content[pointer] = colormask; + //output_mask[pointer] = true; + if(w1 > 0) + { + pDestination_start = hgfx->FBStartAdress + (2 * ((479 - (window->top)) + ((w1 + window->left) * hgfx->ImageHeight))); + pDestination_end = pDestination_start; + if(h_ulong >= h_ulong_old) + { + pDestination_start -= 2 * h_ulong_old; + pDestination_end -= 2 * h_ulong; + } + else + { + pDestination_start -= 2 * h_ulong; + pDestination_end -= 2 * h_ulong_old; + } + + // deco stops + if(drawVeilUntil < 0) + { + pDestination_tmp = pDestination_end; + while(pDestination_tmp <= pDestination_zero_veil) + { + *(__IO uint8_t*)pDestination_tmp = colormask; + pDestination_tmp -= 1; + *(__IO uint8_t*)pDestination_tmp = 0x80; + pDestination_tmp += 3; + } + } + else + { + // regular graph with veil underneath if requested + // von oben nach unten + // von grossen pDestination Werten zu kleinen pDestination Werten + pDestination_tmp = pDestination_start; + while(pDestination_tmp >= pDestination_end) + { + *(__IO uint8_t*)pDestination_tmp = colormask; + pDestination_tmp += 1; + *(__IO uint8_t*)pDestination_tmp = 0xFF; + pDestination_tmp -= 3; + } + while((drawVeilUntil > 0) && (pDestination_tmp >= pDestination_zero_veil)) + { + *(__IO uint8_t*)pDestination_tmp = colormask; + pDestination_tmp += 1; + *(__IO uint8_t*)pDestination_tmp = 0x20; + pDestination_tmp -= 3; + } + } + } + h_ulong_old = h_ulong; +// } + w1++; + w2++; + } +} + + +void GFX_draw_header(GFX_DrawCfgScreen *hgfx, uint8_t colorId) +{ + uint32_t pDestination; + point_t start, stop, now; + uint8_t alpha; + + /* display coordinate system */ + start.y = 400; + stop.y = 479; + + start.x = 0; + stop.x = 799; + + now.y = start.y; + now.x = start.x; + + while (now.x <= stop.x) + { + now.y = start.y; + pDestination = (uint32_t)hgfx->FBStartAdress; + pDestination += now.x * hgfx->ImageHeight * 2; + pDestination += now.y * 2; + now.x += 1; + + alpha = 27; + while(alpha < 246) + { + alpha += 9; + *(__IO uint8_t*)pDestination = colorId; + pDestination += 1; + *(__IO uint8_t*)pDestination = alpha; + pDestination += 1; + now.y += 1; + } + + while(now.y <= stop.y) + { + *(__IO uint8_t*)pDestination = colorId; + pDestination += 1; + *(__IO uint8_t*)pDestination = 0xFF; + pDestination += 1; + now.y += 1; + } + } +} + +void GFX_draw_box2(GFX_DrawCfgScreen *hgfx, point_t start, point_t stop, uint8_t color, uint8_t roundCorners) +{ + point_t point2, point4; + + if(roundCorners) + { + point2.x = stop.x - start.x; + point2.y = stop.y - start.y; + GFX_draw_box(hgfx,start,point2,1,color); + } + else + { + point2.x = stop.x; + point2.y = start.y; + + point4.x = start.x; + point4.y = stop.y; + + GFX_draw_line(hgfx,start,point2,color); + GFX_draw_line(hgfx,point2,stop,color); + GFX_draw_line(hgfx,stop,point4,color); + GFX_draw_line(hgfx,point4,start,color); + } +} + +void GFX_draw_box(GFX_DrawCfgScreen *hgfx, point_t LeftLow, point_t WidthHeight, uint8_t Style, uint8_t color) +{ + uint32_t pDestination, pStart; + uint32_t j; + uint32_t lineWidth, lineHeight; + int x, y; + uint8_t intensity; + + typedef struct { + int x; + int y; + uint8_t intensity; + } corner_t; + const corner_t corner[16] = { + {3,3,255}, // nur einmal + {9,0,242}, + {8,0,194}, + {7,0,115}, + {6,0,36}, + {9,1,33}, + {8,1,84}, + {7,1,161}, + {6,1,255}, + {5,1,242}, + {4,1,36}, + {6,2,33}, + {5,2,84}, + {4,2,255}, + {3,2,84}, + {4,3,110} + }; + + lineWidth = WidthHeight.x; + lineHeight = WidthHeight.y; + + pStart = (uint32_t)hgfx->FBStartAdress; + pStart += LeftLow.x * hgfx->ImageHeight * 2; + pStart += LeftLow.y * 2; + + // Untere Linie + pDestination = pStart; + if(Style) + { + pDestination += 2 * 10 * hgfx->ImageHeight; + lineWidth -= 18; + } + for (j = lineWidth; j > 0; j--) + { + *(__IO uint16_t*)pDestination = 0xFF00 + color; + pDestination += hgfx->ImageHeight * 2; + } + + // Obere Linie + pDestination = pStart + 2 * WidthHeight.y; + if(Style) + { + pDestination += 2 * 10 * hgfx->ImageHeight; + } + + for (j = lineWidth; j > 0; j--) + { + *(__IO uint16_t*)pDestination = 0xFF00 + color; + pDestination += hgfx->ImageHeight * 2; + } + + // Linke Linie + pDestination = pStart; + if(Style) + { + pDestination += 2 * 10; + lineHeight -= 18; + } + + for (j = lineHeight; j > 0; j--) + { + *(__IO uint16_t*)pDestination = 0xFF00 + color; + pDestination += 2; + } + + // Rechte Linie + pDestination = pStart + 2 * WidthHeight.x * hgfx->ImageHeight; + if(Style) + { + pDestination += 2 * 10; + } + + for (j = lineHeight; j > 0; j--) + { + *(__IO uint16_t*)pDestination = 0xFF00 + color; + pDestination += 2; + } + + // Ecken wenn notwendig == Style + if(Style) + { + // links unten + pDestination = pStart; + x = corner[0].x; + y = corner[0].y; + intensity = corner[0].intensity; + *(__IO uint16_t*)(pDestination + 2 * (y + (x * hgfx->ImageHeight))) = (intensity << 8) + color; + + for(j = 15; j > 0; j--) + { + x = corner[j].x; + y = corner[j].y; + intensity = corner[j].intensity; + *(__IO uint16_t*)(pDestination + 2 * (y + (x * hgfx->ImageHeight))) = (intensity << 8) + color; + *(__IO uint16_t*)(pDestination + 2 * (x + (y * hgfx->ImageHeight))) = (intensity << 8) + color; + } + // links oben + pDestination = pStart + 2 * WidthHeight.y; + x = corner[0].x; + y = corner[0].y; + intensity = corner[0].intensity; + *(__IO uint16_t*)(pDestination + 2 * (-y + (x * hgfx->ImageHeight))) = (intensity << 8) + color; + + for(j = 15; j > 0; j--) + { + x = corner[j].x; + y = corner[j].y; + intensity = corner[j].intensity; + *(__IO uint16_t*)(pDestination + 2 * (-y + (x * hgfx->ImageHeight))) = (intensity << 8) + color; + *(__IO uint16_t*)(pDestination + 2 * (-x + (y * hgfx->ImageHeight))) = (intensity << 8) + color; + } + // rechts unten + pDestination = pStart + 2 * WidthHeight.x * hgfx->ImageHeight; + x = corner[0].x; + y = corner[0].y; + intensity = corner[0].intensity; + *(__IO uint16_t*)(pDestination + 2 * (y - (x * hgfx->ImageHeight))) = (intensity << 8) + color; + + for(j = 15; j > 0; j--) + { + x = corner[j].x; + y = corner[j].y; + intensity = corner[j].intensity; + *(__IO uint16_t*)(pDestination + 2 * (y - (x * hgfx->ImageHeight))) = (intensity << 8) + color; + *(__IO uint16_t*)(pDestination + 2 * (x - (y * hgfx->ImageHeight))) = (intensity << 8) + color; + } + // rechts oben + pDestination = pStart + 2 * WidthHeight.y + 2 * WidthHeight.x * hgfx->ImageHeight; + x = corner[0].x; + y = corner[0].y; + intensity = corner[0].intensity; + *(__IO uint16_t*)(pDestination - 2 * (y + (x * hgfx->ImageHeight))) = (intensity << 8) + color; + + for(j = 15; j > 0; j--) + { + x = corner[j].x; + y = corner[j].y; + intensity = corner[j].intensity; + *(__IO uint16_t*)(pDestination - 2 * (y + (x * hgfx->ImageHeight))) = (intensity << 8) + color; + *(__IO uint16_t*)(pDestination - 2 * (x + (y * hgfx->ImageHeight))) = (intensity << 8) + color; + } + } +} + + + + +/** + ****************************************************************************** + * @brief GFX write label. / Write string with defined color + * @author heinrichs weikamp gmbh + * @version V0.0.1 + * @date 07-July-2014 + ****************************************************************************** + * + * @param hgfx: check gfx_engine.h. + * @param color: 16bit Alpha+CLUT. + * @retval None + */ + +uint32_t GFX_write_label(const tFont *Font, GFX_DrawCfgWindow* hgfx, const char *pText, uint8_t color) +{ + return GFX_write_string_color(Font, hgfx, pText, 0, color); +} + + +/** + ****************************************************************************** + * @brief GFX writeGfx_write_label_varstring. / Write string with all parameters and font color options + * @author Peter Ryser + * @version V0.0.1 + * @date 22-April-2014 + ****************************************************************************** + * + * @param XleftGimpStyle: + * @param XrightGimpStyle: + * @param YtopGimpStyle: + * @param color: + * @param tFont: + * @param text: text to be printed + * @retval None + */ + +void Gfx_write_label_var(GFX_DrawCfgScreen *screenInput, uint16_t XleftGimpStyle, uint16_t XrightGimpStyle, uint16_t YtopGimpStyle, const tFont *Font, const uint8_t color, const char *text) +{ + + GFX_DrawCfgWindow hgfx; + + if(XrightGimpStyle > 799) + XrightGimpStyle = 799; + if(XleftGimpStyle >= XrightGimpStyle) + XleftGimpStyle = 0; + if(YtopGimpStyle > 479) + YtopGimpStyle = 479; + hgfx.Image = screenInput; + hgfx.WindowNumberOfTextLines = 1; + hgfx.WindowLineSpacing = 0; + hgfx.WindowTab = 0; + hgfx.WindowX0 = XleftGimpStyle; + hgfx.WindowX1 = XrightGimpStyle; + hgfx.WindowY1 = 479 - YtopGimpStyle; + if(hgfx.WindowY1 < Font->height) + hgfx.WindowY0 = 0; + else + hgfx.WindowY0 = hgfx.WindowY1 - Font->height; + + GFX_write_label(Font, &hgfx, text, color); +} + +/** + ****************************************************************************** + * @brief GFX write string. / Write string with all parameters and font options + * @author heinrichs weikamp gmbh + * @version V0.0.1 + * @date 22-April-2014 + ****************************************************************************** + * + * @param hgfx: check gfx_engine.h. + * @param color: 32bit ARGB8888. + * @retval None + */ + +uint16_t GFX_return_offset(const tFont *Font, char *pText, uint8_t position) +{ + char character; + uint16_t digit, i; + uint8_t found; + uint16_t distance; + + if(position == 0) + return 0; + + distance = 0; + for(digit = 0; digit < position; digit++) + { + character = pText[digit]; + if(character == 0) + return 0; + + found = 0; + for(i=0;i<Font->length;i++) + { + if(Font->chars[i].code == character) + { + found = 1; + break; + } + } + if(found) + { + distance += (uint16_t)(Font->chars[i].image->width); + if(Font == &FontT144) + distance += 3; + else + if(Font == &FontT105) + distance += 2; + } + } + return distance; + + /* FEHLT: + if(*pText < ' ') + if((*pText) & 0x80) + + if(((tFont *)settings.font == &FontT105) && settings.dualFont && ((*pText == '.') || (*pText == ':'))) + settings.font = (uint32_t)&FontT54; + */ +} + +void GFX_clean_line(GFX_DrawCfgWindow* hgfx, uint32_t line_number) +{ + uint16_t height; + uint32_t pDestination, i, j; + uint16_t left, width, bottom, nextlineStep; + + bottom = hgfx->WindowY0; + + if(hgfx->WindowNumberOfTextLines && line_number && (line_number <= hgfx->WindowNumberOfTextLines)) + { + bottom += hgfx->WindowLineSpacing * (hgfx->WindowNumberOfTextLines - line_number); + height = hgfx->WindowLineSpacing; + } + else + { + height = 1 + hgfx->WindowY1 - bottom; + } + + pDestination = (uint32_t)hgfx->Image->FBStartAdress; + + left = hgfx->WindowX0; + width = 1 + hgfx->WindowX1 - left; + nextlineStep = hgfx->Image->ImageHeight - height; + nextlineStep *= 2; + pDestination += 2 * bottom; + pDestination += 2 * hgfx->Image->ImageHeight * left; + + for(j = width; j > 0; j--) + { + for(i = height; i > 0; i--) + { + *(__IO uint16_t*)pDestination = 0; + pDestination += 2; + } + pDestination += nextlineStep; + } +} + + +void GFX_clean_area(GFX_DrawCfgScreen *tMscreen, uint16_t XleftGimpStyle, uint16_t XrightGimpStyle, uint16_t YtopGimpStyle, uint16_t YBottomGimpStyle) +{ + uint16_t height; + uint32_t pDestination, i, j; + int32_t left, width, bottom, nextlineStep; + + bottom = tMscreen->ImageHeight - YBottomGimpStyle; + height = 1 + YBottomGimpStyle - YtopGimpStyle; + + if(bottom < 0) + bottom = 0; + if(height > tMscreen->ImageHeight) + height = tMscreen->ImageHeight; + + pDestination = tMscreen->FBStartAdress; + + left = XleftGimpStyle; + width = 1 + XrightGimpStyle - left; + if(width < 1) + width = 1; + + if(width > tMscreen->ImageWidth) + width = tMscreen->ImageWidth; + + nextlineStep = tMscreen->ImageHeight - height; + nextlineStep *= 2; + pDestination += 2 * bottom; + pDestination += 2 * tMscreen->ImageHeight * left; + + for(j = width; j > 0; j--) + { + for(i = height; i > 0; i--) + { + *(__IO uint16_t*)pDestination = 0; + pDestination += 2; + } + pDestination += nextlineStep; + } +} + + +uint32_t GFX_write_string(const tFont *Font, GFX_DrawCfgWindow* hgfx, const char *pText, uint32_t line_number) +{ + return GFX_write_string_color(Font, hgfx, pText, line_number, 0); +} + +uint32_t GFX_write_string_color(const tFont *Font, GFX_DrawCfgWindow* hgfx, const char *pText, uint32_t line_number, uint8_t color) +{ + if(hgfx->Image->FBStartAdress < FBGlobalStart) + return 0; + + GFX_CfgWriteString settings; + uint32_t newXdelta; + uint8_t minimal = 0; +// uint32_t try_again; + + if(hgfx->WindowNumberOfTextLines && line_number && (line_number <= hgfx->WindowNumberOfTextLines)) + { + settings.Ydelta = hgfx->WindowLineSpacing * (hgfx->WindowNumberOfTextLines - line_number); + } + else + { + settings.Ydelta = 0; + } + settings.font = (uint32_t)Font; + settings.Xdelta = 0; + settings.color = color; + settings.invert = 0; + settings.resize = 0; + settings.dualFont = 0; + settings.spaceMode = 0; + settings.singleSpaceWithSizeOfNextChar = 0; + settings.useTinyFont = 0; + settings.TinyFontExtraYdelta = 0; + settings.TinyFont = (uint32_t)Font; + settings.doubleSize = 0; + + if((*pText) == TXT_MINIMAL) // for customtext and anything with Sonderzeichen + minimal = 1; + else + minimal = 0; + + if(Font == &FontT144) + settings.TinyFont = (uint32_t)&FontT84; + else + if(Font == &FontT105) + settings.TinyFont = (uint32_t)&FontT54; + else + if(Font == &FontT54) + { + settings.TinyFont = (uint32_t)&FontT48; + settings.TinyFontExtraYdelta = -9; + } + else + if(Font == &FontT48) + { + settings.TinyFont = (uint32_t)&FontT24; + settings.TinyFontExtraYdelta = 6; + } + else + if(Font == &FontT42) + { + settings.TinyFont = (uint32_t)&FontT24; + settings.TinyFontExtraYdelta = 2; + } + + settings.actualFont = (tFont *)settings.font; + + while ((*pText != 0) && (settings.Xdelta != 0x0000FFFF))// und fehlend: Abfrage window / image size + { +// try_again = 0; + + if((*pText == '\177') && !minimal) + { + if(settings.singleSpaceWithSizeOfNextChar) + { + settings.singleSpaceWithSizeOfNextChar = 0; + pText++; + settings.Xdelta += *pText; + } + else + settings.singleSpaceWithSizeOfNextChar = 1; + } + else + if(*pText < ' ') + { + /* Xdelta -inline- changes */ + if((*pText == '\t') && !minimal) + settings.Xdelta = hgfx->WindowTab - hgfx->WindowX0; + else + if(*pText == '\r') // carriage return, no newline + settings.Xdelta = 0; + else + if((*pText == '\001') && !minimal) // center + settings.Xdelta = GFX_write__Modify_Xdelta__Centered(&settings, hgfx, pText+1); + else + if((*pText == '\002') && !minimal) // right + settings.Xdelta = GFX_write__Modify_Xdelta__RightAlign(&settings, hgfx, pText+1); + else + if((*pText == '\003') && !minimal) // doubleSize + settings.doubleSize = 1; + else + /* Xdelta -up/down changes */ + if((*pText == '\f') && !minimal) // form feed = top align + { + if((hgfx->WindowY1 - hgfx->WindowY0) >= ((tFont *)settings.font)->height) + { + settings.Ydelta = hgfx->WindowY1 - hgfx->WindowY0; + settings.Ydelta -= ((tFont *)settings.font)->height; + } + } + else + if(*pText == '\n') // newline, no carriage return + { + if(hgfx->WindowNumberOfTextLines && (line_number < hgfx->WindowNumberOfTextLines)) + { + line_number++; + settings.Ydelta = hgfx->WindowLineSpacing * (hgfx->WindowNumberOfTextLines - line_number); + } + } + else + /* Font style changes */ + if(*pText == '\a') + settings.invert = 1; + else + if((*pText == '\016') && !minimal) + { + if(settings.dualFont == 0) + settings.dualFont = 1; + else + settings.actualFont = (tFont *)settings.TinyFont; + } + else + if((*pText == '\017') && !minimal) + { + settings.dualFont = 0; + settings.actualFont = (tFont *)settings.font; + } + else + if((*pText == '\005') && !minimal) + { + newXdelta = GFX_write_char(hgfx, &settings, 'a', (tFont *)&Awe48); + settings.Xdelta = newXdelta; + } + else + if((*pText == '\006') && !minimal) + { + newXdelta = GFX_write_char(hgfx, &settings, 'b', (tFont *)&Awe48); + settings.Xdelta = newXdelta; + } + else + if((*pText >= '\020') && (*pText <= '\032') && !minimal) + settings.color = *pText - '\020'; + else + if((*pText == '\034') && !minimal) + settings.spaceMode = 1; + else + if((*pText == '\035') && !minimal) + settings.spaceMode = 0; + } + else + if(((*pText) == TXT_2BYTE) && !minimal) + { + pText++; + settings.Xdelta = GFX_write_substring(&settings, hgfx, (uint8_t)TXT_2BYTE, (int8_t)*pText); + } + else + if(((*pText) & 0x80) && !minimal) + settings.Xdelta = GFX_write_substring(&settings, hgfx, (uint8_t)*pText, 0); + else + if(!settings.invert && (*pText == ' ')) + { + if(settings.spaceMode == 0) + settings.Xdelta += ((tFont *)settings.font)->spacesize; + else + settings.Xdelta += ((tFont *)settings.font)->spacesize2Monospaced; + } + else + if((settings.spaceMode == 1) && (*pText == ' ')) + settings.Xdelta += ((tFont *)settings.font)->spacesize2Monospaced; + else + { + if(((tFont *)settings.font == &FontT144) && ((*pText == '.') || (*pText == ':'))) + settings.actualFont = (tFont *)settings.TinyFont; + else + if(((tFont *)settings.font == &FontT105) && settings.dualFont && ((*pText == '.') || (*pText == ':'))) + settings.actualFont = (tFont *)settings.TinyFont; + + if(settings.actualFont == (tFont *)settings.TinyFont) + settings.Ydelta += settings.TinyFontExtraYdelta; + + newXdelta = GFX_write_char(hgfx, &settings, *(uint8_t *)pText, settings.actualFont); + settings.Xdelta = newXdelta; + + if(settings.actualFont == (tFont *)settings.TinyFont) + settings.Ydelta -= settings.TinyFontExtraYdelta; + } + if(pText != 0) /* for TXT_2BYTE */ + pText++; + } + return settings.Ydelta; +} + +/* Private functions ---------------------------------------------------------*/ +/****************************************************************************** + Static Function +*******************************************************************************/ + +/** + ****************************************************************************** + * @brief GFX write substring. / Write string without parameters + * @author heinrichs weikamp gmbh + * @version V0.0.1 + * @date 22-April-2014 + ****************************************************************************** + * + * @param hgfx: check gfx_engine.h. + * @param color: 32bit ARGB8888. + * @retval None + */ + +static uint32_t GFX_write_substring(GFX_CfgWriteString* cfg, GFX_DrawCfgWindow* hgfx, uint8_t textId, int8_t nextCharFor2Byte) +{ + uint8_t i, j; + uint32_t found; + uint32_t pText; + uint8_t gfx_selected_language; +#ifndef BOOTLOADER_STANDALONE + SSettings *pSettings; + pSettings = settingsGetPointer(); + gfx_selected_language = pSettings->selected_language; + if(gfx_selected_language >= LANGUAGE_END) +#endif + gfx_selected_language = 0; +// ----------------------------- + if(textId != (uint8_t)TXT_2BYTE) + { + found = 0; + j = 0; + for(i=(uint8_t)TXT_Language;i<(uint8_t)TXT_END;i++) + { + if(text_array[j].code == textId) + { + found = 1; + break; + } + j++; + } + if(!found) + return cfg->Xdelta; +// ----------------------------- + pText = (uint32_t)text_array[j].text[gfx_selected_language]; + if(!pText) + pText = (uint32_t)text_array[j].text[0]; + else + if(*(char*)pText == 0) + pText = (uint32_t)text_array[j].text[0]; + } +// ----------------------------- + else + { + if(!nextCharFor2Byte) + return cfg->Xdelta; + + found = 0; + for(j=0;j<(uint8_t)TXT2BYTE_END-(uint8_t)TXT2BYTE_START;j++) + { + if((uint8_t)text_array2[j].code == (uint8_t)nextCharFor2Byte) + { + found = 1; + break; + } + } + if(!found) + return cfg->Xdelta; +// ----------------------------- + pText = (uint32_t)text_array2[j].text[gfx_selected_language]; + if(!pText) + pText = (uint32_t)text_array2[j].text[0]; + else + if(*(char*)pText == 0) + pText = (uint32_t)text_array2[j].text[0]; + } +// ----------------------------- + + if(cfg->actualFont == (tFont *)cfg->TinyFont) + cfg->Ydelta += cfg->TinyFontExtraYdelta; + + while (*(char*)pText != 0)// und fehlend: Abfrage window / image size + { + if(*(char*)pText == '\t') + cfg->Xdelta = hgfx->WindowTab - hgfx->WindowX0; + else + if(*(char*)pText == ' ') + cfg->Xdelta += ((tFont *)cfg->actualFont)->spacesize; + else + cfg->Xdelta = GFX_write_char(hgfx, cfg, *(uint8_t *)pText, (tFont *)cfg->actualFont); + + pText++; + } + + if(cfg->actualFont == (tFont *)cfg->TinyFont) + cfg->Ydelta -= cfg->TinyFontExtraYdelta; + + return cfg->Xdelta; +} + + +/** + ****************************************************************************** + * @brief GFX write char. / Write non-inverted, non-colored with entire 8 bit range + * @author heinrichs weikamp gmbh + * @version V0.0.1 + * @date 22-April-2014 + ****************************************************************************** + * + * @param hgfx: check gfx_engine.h. + * @param Ydelta: input + * @param character: character + * @param *Font: pointer to font to be used for this char + * @retval Ydelta: 0x0000FFFF if not successful or char_truncated + */ + +static uint32_t GFX_write_char_doubleSize(GFX_DrawCfgWindow* hgfx, GFX_CfgWriteString* cfg, uint8_t character, tFont *Font) +{ + uint32_t i, j; + uint32_t width, height; + uint32_t found; + uint32_t pDestination; + uint32_t pDestinationColor; + uint32_t pSource; + uint32_t OffsetDestination; + uint32_t width_left; + uint32_t height_left; + uint32_t char_truncated_WidthFlag; + uint32_t char_truncated_Height; + uint8_t fill; + uint32_t widthFont, heightFont; + uint32_t nextLine; + + + if(hgfx->Image->ImageWidth <= (hgfx->WindowX0 + cfg->Xdelta)) + return 0x0000FFFF; + + // ----------------------------- + found = 0; + for(i=0;i<Font->length;i++) + { + if(Font->chars[i].code == character) + { + found = 1; + break; + } + } + if(!found) + return cfg->Xdelta; + + pSource = ((uint32_t)Font->chars[i].image->data); + pDestination = 1 + (uint32_t)hgfx->Image->FBStartAdress; + + heightFont = Font->chars[i].image->height; + widthFont = Font->chars[i].image->width; + + height = heightFont*2; + width = widthFont*2; + + OffsetDestination = 2 * (hgfx->Image->ImageHeight - height); + + pDestination += (hgfx->WindowX0 + cfg->Xdelta) * hgfx->Image->ImageHeight * 2; + pDestination += (hgfx->WindowY0 + cfg->Ydelta) * 2; + nextLine = hgfx->Image->ImageHeight * 2; + +// ----------------------------- + char_truncated_WidthFlag = 0; + width_left = hgfx->Image->ImageWidth - (hgfx->WindowX0 + cfg->Xdelta); + if(width_left < width) + { + char_truncated_WidthFlag = 1; + width = width_left; + widthFont = width/2; + } +// ----------------------------- + char_truncated_Height = 0; + height_left = hgfx->Image->ImageHeight - (hgfx->WindowY0 + cfg->Ydelta); + if(height_left < height) + { + char_truncated_Height = height - height_left; + if((char_truncated_Height & 1) != 0) + { + height_left -= 1; + char_truncated_Height += 1; + } + height = height_left; + heightFont = height/2; + } + OffsetDestination += 2 * char_truncated_Height; +// ----------------------------- + if(height == 0) + return 0x0000FFFF; +// ----------------------------- + + if((cfg->color > 0) ) + { + pDestinationColor = pDestination - 1; + + for(i = width; i > 0; i--) + { + for (j = height; j > 0; j--) + { + *(__IO uint32_t*)pDestinationColor = cfg->color; + pDestinationColor += 2; + } + pDestinationColor += OffsetDestination; + } + } + + if(cfg->singleSpaceWithSizeOfNextChar) + { + cfg->singleSpaceWithSizeOfNextChar = 0; + + if(cfg->invert) + fill = 0xFF; + else + fill = 0; + + height /= 2; + for(i = width; i > 0; i--) + { + for (j = height; j > 0; j--) + { + *(__IO uint8_t*)pDestination = fill; + pDestination += 2; + *(__IO uint8_t*)pDestination = fill; + pDestination += 2; + } + pDestination += OffsetDestination; + } + } + else + if(cfg->invert) + { + if((heightFont & 3) == 0) /* unroll for perfomance, by 4 if possible, by 2 (16bit) otherwise */ + { + heightFont /= 4; + for(i = widthFont; i > 0; i--) + { + if(*(uint8_t*)pSource != 0x01) + { + for (j = heightFont; j > 0; j--) + { + *(__IO uint8_t*)pDestination = 0xFF - *(uint8_t*)pSource; + *(__IO uint8_t*)(pDestination + nextLine) = 0xFF - *(uint8_t*)pSource; + pDestination += 2; + *(__IO uint8_t*)pDestination = 0xFF - *(uint8_t*)pSource; + *(__IO uint8_t*)(pDestination + nextLine) = 0xFF - *(uint8_t*)pSource; + pSource++; + pDestination += 2; + + *(__IO uint8_t*)pDestination = 0xFF - *(uint8_t*)pSource; + *(__IO uint8_t*)(pDestination + nextLine) = 0xFF - *(uint8_t*)pSource; + pDestination += 2; + *(__IO uint8_t*)pDestination = 0xFF - *(uint8_t*)pSource; + *(__IO uint8_t*)(pDestination + nextLine) = 0xFF - *(uint8_t*)pSource; + pSource++; + pDestination += 2; + + *(__IO uint8_t*)pDestination = 0xFF - *(uint8_t*)pSource; + *(__IO uint8_t*)(pDestination + nextLine) = 0xFF - *(uint8_t*)pSource; + pDestination += 2; + *(__IO uint8_t*)pDestination = 0xFF - *(uint8_t*)pSource; + *(__IO uint8_t*)(pDestination + nextLine) = 0xFF - *(uint8_t*)pSource; + pSource++; + pDestination += 2; + + *(__IO uint8_t*)pDestination = 0xFF - *(uint8_t*)pSource; + *(__IO uint8_t*)(pDestination + nextLine) = 0xFF - *(uint8_t*)pSource; + pDestination += 2; + *(__IO uint8_t*)pDestination = 0xFF - *(uint8_t*)pSource; + *(__IO uint8_t*)(pDestination + nextLine) = 0xFF - *(uint8_t*)pSource; + pSource++; + pDestination += 2; + } + pSource += char_truncated_Height; + } + else + { + pSource++; + for (j = height; j > 0; j--) + { + *(__IO uint8_t*)pDestination = 0xFF; + *(__IO uint8_t*)(pDestination + nextLine) = 0xFF; + pDestination += 2; + *(__IO uint8_t*)pDestination = 0xFF; + *(__IO uint8_t*)(pDestination + nextLine) = 0xFF; + pDestination += 2; + *(__IO uint8_t*)pDestination = 0xFF; + *(__IO uint8_t*)(pDestination + nextLine) = 0xFF; + pDestination += 2; + *(__IO uint8_t*)pDestination = 0xFF; + *(__IO uint8_t*)(pDestination + nextLine) = 0xFF; + pDestination += 2; + *(__IO uint8_t*)pDestination = 0xFF; + *(__IO uint8_t*)(pDestination + nextLine) = 0xFF; + pDestination += 2; + *(__IO uint8_t*)pDestination = 0xFF; + *(__IO uint8_t*)(pDestination + nextLine) = 0xFF; + pDestination += 2; + *(__IO uint8_t*)pDestination = 0xFF; + *(__IO uint8_t*)(pDestination + nextLine) = 0xFF; + pDestination += 2; + *(__IO uint8_t*)pDestination = 0xFF; + *(__IO uint8_t*)(pDestination + nextLine) = 0xFF; + pDestination += 2; + } + } + pDestination += OffsetDestination + nextLine; + } + } + else + { + heightFont /= 2; + for(i = widthFont; i > 0; i--) + { + if(*(uint8_t*)pSource != 0x01) + { + for (j = heightFont; j > 0; j--) + { + *(__IO uint8_t*)pDestination = 0xFF - *(uint8_t*)pSource; + *(__IO uint8_t*)(pDestination + nextLine) = 0xFF - *(uint8_t*)pSource; + pDestination += 2; + *(__IO uint8_t*)pDestination = 0xFF - *(uint8_t*)pSource; + *(__IO uint8_t*)(pDestination + nextLine) = 0xFF - *(uint8_t*)pSource; + pSource++; + pDestination += 2; + + *(__IO uint8_t*)pDestination = 0xFF - *(uint8_t*)pSource; + *(__IO uint8_t*)(pDestination + nextLine) = 0xFF - *(uint8_t*)pSource; + pDestination += 2; + *(__IO uint8_t*)pDestination = 0xFF - *(uint8_t*)pSource; + *(__IO uint8_t*)(pDestination + nextLine) = 0xFF - *(uint8_t*)pSource; + pSource++; + pDestination += 2; + } + pSource += char_truncated_Height; + } + else + { + pSource++; + for (j = heightFont; j > 0; j--) + { + *(__IO uint8_t*)pDestination = 0xFF; + *(__IO uint8_t*)(pDestination + nextLine) = 0xFF; + pDestination += 2; + *(__IO uint8_t*)pDestination = 0xFF; + *(__IO uint8_t*)(pDestination + nextLine) = 0xFF; + pDestination += 2; + *(__IO uint8_t*)pDestination = 0xFF; + *(__IO uint8_t*)(pDestination + nextLine) = 0xFF; + pDestination += 2; + *(__IO uint8_t*)pDestination = 0xFF; + *(__IO uint8_t*)(pDestination + nextLine) = 0xFF; + pDestination += 2; + } + } + pDestination += OffsetDestination + nextLine; + } + } + } + else + { + if((heightFont & 3) == 0) /* unroll for perfomance, by 4 if possible, by 2 (16bit) otherwise */ + { + heightFont /= 4; + for(i = widthFont; i > 0; i--) + { + if(*(uint8_t*)pSource != 0x01) + { + for (j = heightFont; j > 0; j--) + { + *(__IO uint8_t*)pDestination = *(uint8_t*)pSource; + *(__IO uint8_t*)(pDestination + nextLine) = *(uint8_t*)pSource; + pDestination += 2; + *(__IO uint8_t*)pDestination = *(uint8_t*)pSource; + *(__IO uint8_t*)(pDestination + nextLine) = *(uint8_t*)pSource; + pSource++; + pDestination += 2; + + *(__IO uint8_t*)pDestination = *(uint8_t*)pSource; + *(__IO uint8_t*)(pDestination + nextLine) = *(uint8_t*)pSource; + pDestination += 2; + *(__IO uint8_t*)pDestination = *(uint8_t*)pSource; + *(__IO uint8_t*)(pDestination + nextLine) = *(uint8_t*)pSource; + pSource++; + pDestination += 2; + + *(__IO uint8_t*)pDestination = *(uint8_t*)pSource; + *(__IO uint8_t*)(pDestination + nextLine) = *(uint8_t*)pSource; + pDestination += 2; + *(__IO uint8_t*)pDestination = *(uint8_t*)pSource; + *(__IO uint8_t*)(pDestination + nextLine) = *(uint8_t*)pSource; + pSource++; + pDestination += 2; + + *(__IO uint8_t*)pDestination = *(uint8_t*)pSource; + *(__IO uint8_t*)(pDestination + nextLine) = *(uint8_t*)pSource; + pDestination += 2; + *(__IO uint8_t*)pDestination = *(uint8_t*)pSource; + *(__IO uint8_t*)(pDestination + nextLine) = *(uint8_t*)pSource; + pSource++; + pDestination += 2; + } + pSource += char_truncated_Height; + } + else + { + pSource++; + pDestination += 2 * height; + } + pDestination += OffsetDestination + nextLine; + } + } + else + { + heightFont /= 2; + for(i = widthFont; i > 0; i--) + { + if(*(uint8_t*)pSource != 0x01) + { + for (j = heightFont; j > 0; j--) + { + *(__IO uint8_t*)pDestination = *(uint8_t*)pSource; + *(__IO uint8_t*)(pDestination + nextLine) = *(uint8_t*)pSource; + pDestination += 2; + *(__IO uint8_t*)pDestination = *(uint8_t*)pSource; + *(__IO uint8_t*)(pDestination + nextLine) = *(uint8_t*)pSource; + pSource++; + pDestination += 2; + + *(__IO uint8_t*)pDestination = *(uint8_t*)pSource; + *(__IO uint8_t*)(pDestination + nextLine) = *(uint8_t*)pSource; + pDestination += 2; + *(__IO uint8_t*)pDestination = *(uint8_t*)pSource; + *(__IO uint8_t*)(pDestination + nextLine) = *(uint8_t*)pSource; + pSource++; + pDestination += 2; + } + pSource += char_truncated_Height; + } + else + { + pSource++; + pDestination += 2 * height; + } + pDestination += OffsetDestination + nextLine; + } + } + } + +// ----------------------------- + + if(Font == &FontT144) + width += 6; + else + if(Font == &FontT105) + width += 4; + +// ----------------------------- + + if(char_truncated_WidthFlag) + return 0x0000FFFF; + else + return cfg->Xdelta + width; + +} + + +/** + ****************************************************************************** + * @brief GFX write char. / Write non-inverted, non-colored with entire 8 bit range + * @author heinrichs weikamp gmbh + * @version V0.0.1 + * @date 22-April-2014 + ****************************************************************************** + * + * @param hgfx: check gfx_engine.h. + * @param Ydelta: input + * @param character: character + * @param *Font: pointer to font to be used for this char + * @retval Ydelta: 0x0000FFFF if not successful or char_truncated + */ + +static uint32_t GFX_write_char(GFX_DrawCfgWindow* hgfx, GFX_CfgWriteString* cfg, uint8_t character, tFont *Font) +{ + if(cfg->doubleSize) + { + return GFX_write_char_doubleSize(hgfx, cfg, character, Font); + } + + uint32_t i, j; + uint32_t width, height; + uint32_t found; + uint32_t pDestination; + uint32_t pDestinationColor; + uint32_t pSource; + uint32_t OffsetDestination; + uint32_t width_left; + uint32_t height_left; + uint32_t char_truncated_WidthFlag; + uint32_t char_truncated_Height; + uint8_t fill; + + if(hgfx->Image->ImageWidth <= (hgfx->WindowX0 + cfg->Xdelta)) + return 0x0000FFFF; + + // ----------------------------- + found = 0; + for(i=0;i<Font->length;i++) + { + if(Font->chars[i].code == character) + { + found = 1; + break; + } + } + if(!found) + return cfg->Xdelta; +// ----------------------------- +/* + if(Font == &Font144) + cfg->Xdelta += 3; + else + if(Font == &Font84) + cfg->Xdelta += 2; +*/ +// ----------------------------- + + + pSource = ((uint32_t)Font->chars[i].image->data); + pDestination = 1 + (uint32_t)hgfx->Image->FBStartAdress; + + height = Font->chars[i].image->height; + width = Font->chars[i].image->width; + + OffsetDestination = 2 * (hgfx->Image->ImageHeight - height); + + pDestination += (hgfx->WindowX0 + cfg->Xdelta) * hgfx->Image->ImageHeight * 2; + pDestination += (hgfx->WindowY0 + cfg->Ydelta) * 2; + + + +// ----------------------------- + char_truncated_WidthFlag = 0; + width_left = hgfx->Image->ImageWidth - (hgfx->WindowX0 + cfg->Xdelta); + if(width_left < width) + { + char_truncated_WidthFlag = 1; + width = width_left; + } +// ----------------------------- + char_truncated_Height = 0; + height_left = hgfx->Image->ImageHeight - (hgfx->WindowY0 + cfg->Ydelta); + if(height_left < height) + { + char_truncated_Height = height - height_left; + if((char_truncated_Height & 1) != 0) + { + height_left -= 1; + char_truncated_Height += 1; + } + height = height_left; + } + OffsetDestination += 2 * char_truncated_Height; +// ----------------------------- + if(height == 0) + return 0x0000FFFF; +// ----------------------------- + + if((cfg->color > 0) )//&& (cfg->color < 6)) + { + pDestinationColor = pDestination - 1; + + for(i = width; i > 0; i--) + { + for (j = height; j > 0; j--) + { + *(__IO uint32_t*)pDestinationColor = cfg->color;//ColorLUT[cfg->color - 1]; + pDestinationColor += 2; + } + pDestinationColor += OffsetDestination; + } + } + + if(cfg->singleSpaceWithSizeOfNextChar) + { + cfg->singleSpaceWithSizeOfNextChar = 0; + + if(cfg->invert) + fill = 0xFF; + else + fill = 0; + + height /= 2; + for(i = width; i > 0; i--) + { + for (j = height; j > 0; j--) + { + *(__IO uint8_t*)pDestination = fill; + pDestination += 2; + *(__IO uint8_t*)pDestination = fill; + pDestination += 2; + } + pDestination += OffsetDestination; + } + } + else + if(cfg->invert) + { + if((height & 3) == 0) /* unroll for perfomance, by 4 if possible, by 2 (16bit) otherwise */ + { + height /= 4; + for(i = width; i > 0; i--) + { + if(*(uint8_t*)pSource != 0x01) + { + for (j = height; j > 0; j--) + { + *(__IO uint8_t*)pDestination = 0xFF - *(uint8_t*)pSource; + pSource++; + pDestination += 2; + *(__IO uint8_t*)pDestination = 0xFF - *(uint8_t*)pSource; + pSource++; + pDestination += 2; + *(__IO uint8_t*)pDestination = 0xFF - *(uint8_t*)pSource; + pSource++; + pDestination += 2; + *(__IO uint8_t*)pDestination = 0xFF - *(uint8_t*)pSource; + pSource++; + pDestination += 2; + } + pSource += char_truncated_Height; + } + else + { + pSource++; + for (j = height; j > 0; j--) + { + *(__IO uint8_t*)pDestination = 0xFF; + pDestination += 2; + *(__IO uint8_t*)pDestination = 0xFF; + pDestination += 2; + *(__IO uint8_t*)pDestination = 0xFF; + pDestination += 2; + *(__IO uint8_t*)pDestination = 0xFF; + pDestination += 2; + } + } + pDestination += OffsetDestination; + } + } + else + { + height /= 2; + for(i = width; i > 0; i--) + { + if(*(uint8_t*)pSource != 0x01) + { + for (j = height; j > 0; j--) + { + *(__IO uint8_t*)pDestination = 0xFF - *(uint8_t*)pSource; + pSource++; + pDestination += 2; + *(__IO uint8_t*)pDestination = 0xFF - *(uint8_t*)pSource; + pSource++; + pDestination += 2; + } + pSource += char_truncated_Height; + } + else + { + pSource++; + for (j = height; j > 0; j--) + { + *(__IO uint8_t*)pDestination = 0xFF; + pDestination += 2; + *(__IO uint8_t*)pDestination = 0xFF; + pDestination += 2; + } + } + pDestination += OffsetDestination; + } + } + } + else + { + if((height & 3) == 0) /* unroll for perfomance, by 4 if possible, by 2 (16bit) otherwise */ + { + height /= 4; + for(i = width; i > 0; i--) + { + if(*(uint8_t*)pSource != 0x01) + { + for (j = height; j > 0; j--) + { + *(__IO uint8_t*)pDestination = *(uint8_t*)pSource; + pSource++; + pDestination += 2; + *(__IO uint8_t*)pDestination = *(uint8_t*)pSource; + pSource++; + pDestination += 2; + *(__IO uint8_t*)pDestination = *(uint8_t*)pSource; + pSource++; + pDestination += 2; + *(__IO uint8_t*)pDestination = *(uint8_t*)pSource; + pSource++; + pDestination += 2; + } + pSource += char_truncated_Height; + } + else + { + pSource++; + pDestination += 2 * height * 4; + } + pDestination += OffsetDestination; + } + } + else + { + height /= 2; + for(i = width; i > 0; i--) + { + if(*(uint8_t*)pSource != 0x01) + { + for (j = height; j > 0; j--) + { + *(__IO uint8_t*)pDestination = *(uint8_t*)pSource; + pSource++; + pDestination += 2; + *(__IO uint8_t*)pDestination = *(uint8_t*)pSource; + pSource++; + pDestination += 2; + } + pSource += char_truncated_Height; + } + else + { + pSource++; + pDestination += 2 * height * 2; + } + pDestination += OffsetDestination; + } + } + } + +// ----------------------------- + + if(Font == &FontT144) + width += 3; + else + if(Font == &FontT105) + width += 2; +/* + else + if(Font == &Font144) + width += 3; + else + if(Font == &Font84) + width += 1; +*/ +// ----------------------------- + + if(char_truncated_WidthFlag) + return 0x0000FFFF; + else + return cfg->Xdelta + width; +} + + +/** + ****************************************************************************** + * @brief GFX write Modify helper for center and right align. + * @author heinrichs weikamp gmbh + * @version V0.0.1 + * @date 17-March-2015 + ****************************************************************************** + * + * @param *cText: output + * @param *pTextInput: input + * @param gfx_selected_language: gfx_selected_language + * @retval counter and *cText content + */ +int8_t GFX_write__Modify_helper(char *cText, const char *pTextInput, uint8_t gfx_selected_language) +{ + uint32_t pText, backup; + uint8_t textId; + int8_t counter; + uint32_t found; + uint32_t j; + + pText = (uint32_t)pTextInput; + counter = 0; + while((counter < 100) && (*(char*)pText != 0) && (*(char*)pText != '\r')) + { + if((*(char*)pText) == TXT_2BYTE) + { + backup = pText; + + found = 0; + j = 0; + textId = (int8_t)*(char*)(pText + 1); + if(textId != 0) + { + for(j=0;j<(uint8_t)TXT2BYTE_END-(uint8_t)TXT2BYTE_START;j++) + { + if((uint8_t)text_array2[j].code == (uint8_t)textId) + { + found = 1; + break; + } + } + if(found) + { + pText = (uint32_t)text_array2[j].text[gfx_selected_language]; + if(!pText) + pText = (uint32_t)text_array2[j].text[0]; + else + if(*(char*)pText == 0) + pText = (uint32_t)text_array2[j].text[0]; + + while((counter < 100) && (*(char*)pText != 0)) + cText[counter++] = *(char*)pText++; + } + pText = backup + 2; + } + else + pText = 0; + } + if((*(char*)pText) & 0x80) + { + backup = pText; + + found = 0; + j = 0; + textId = (uint8_t)*(char*)pText; + for(uint8_t ii=(uint8_t)TXT_Language;ii<(uint8_t)TXT_END;ii++) + { + if(text_array[j].code == textId) + { + found = 1; + break; + } + j++; + } + if(found) + { + pText = (uint32_t)text_array[j].text[gfx_selected_language]; + if(!pText) + pText = (uint32_t)text_array[j].text[0]; + else + if(*(char*)pText == 0) + pText = (uint32_t)text_array[j].text[0]; + + while((counter < 100) && (*(char*)pText != 0)) + cText[counter++] = *(char*)pText++; + } + pText = backup + 1; + } + else + { + cText[counter++] = *(char*)pText++; + } + } + cText[counter] = 0; + return counter; +} + + +/** + ****************************************************************************** + * @brief GFX write Modify Ydelta for align. / calc Ydelta for start + * @author heinrichs weikamp gmbh + * @version V0.0.1 + * @date 22-April-2014 + ****************************************************************************** + * + * @param *hgfx: check gfx_engine.h. + * @param *cfg: Ydelta, Font + * @param *pText: character + * @retval Ydelta: 0 if text has to start left ( and probably does not fit) + */ + +uint32_t GFX_write__Modify_Xdelta__Centered(GFX_CfgWriteString* cfg, GFX_DrawCfgWindow* hgfx, const char *pTextInput) +{ + char cText[101]; + uint32_t result; + uint32_t Xsum; + uint32_t i, j; + uint8_t gfx_selected_language; + uint32_t pText; + +#ifndef BOOTLOADER_STANDALONE + SSettings *pSettings; + pSettings = settingsGetPointer(); + gfx_selected_language = pSettings->selected_language; + if(gfx_selected_language >= LANGUAGE_END) +#endif + gfx_selected_language = 0; +// ----------------------------- + + GFX_write__Modify_helper(cText,pTextInput,gfx_selected_language); + + pText = (uint32_t)&cText[0]; + Xsum = 0; + j = 0; + while (*(char*)pText != 0)// und fehlend: Abfrage window / image size + { + for(i=0;i<((tFont *)cfg->font)->length;i++) + { + if(((tFont *)cfg->font)->chars[i].code == *(char*)pText) + { + Xsum += ((tFont *)cfg->font)->chars[i].image->width; + break; + } + } + pText++; + j++; + if(((tFont *)cfg->font == &FontT144) && (*(char*)pText != 0)) + Xsum += 3; + else + if(((tFont *)cfg->font == &FontT105) && (*(char*)pText != 0)) + Xsum += 2; + } + pText -= j; + + if(cfg->doubleSize) + Xsum *= 2; + + result = hgfx->WindowX1 - hgfx->WindowX0; + if(Xsum < result) + { + result -= Xsum; + result /= 2; + } + else + result = 0; + return result; +} + + +uint32_t GFX_write__Modify_Xdelta__RightAlign(GFX_CfgWriteString* cfg, GFX_DrawCfgWindow* hgfx, const char *pTextInput) +{ + char cText[101]; + uint32_t result; + uint32_t Xsum; + uint32_t i, j; + tFont *font; + uint8_t gfx_selected_language; + uint32_t pText; + uint8_t setToTinyFont = 0; + +#ifndef BOOTLOADER_STANDALONE + SSettings *pSettings; + pSettings = settingsGetPointer(); + gfx_selected_language = pSettings->selected_language; + if(gfx_selected_language >= LANGUAGE_END) +#endif + gfx_selected_language = 0; +// ----------------------------- + + GFX_write__Modify_helper(cText,pTextInput,gfx_selected_language); + pText = (uint32_t)&cText[0]; + +// ----------------------------- + + setToTinyFont = 0; + font = (tFont *)cfg->font; + Xsum = 0; + j = 0; + + while (*(char*)pText != 0)// und fehlend: Abfrage window / image size + { + if((font == &FontT144) && (*(char*)pText == '.')) + { + font = (tFont *)&FontT84; + } + else + if((font == &FontT105) && (*(char*)pText == '\16')) // two times to start tiny font + { + if(!setToTinyFont) + setToTinyFont = 1; + else + font = (tFont *)&FontT54; + } + else + if((font == &FontT105) && cfg->dualFont && ((*(char*)pText == '.') || (*(char*)pText == ':'))) + { + font = (tFont *)&FontT54; + } + + if(*(char*)pText == ' ') + { + Xsum += font->spacesize; + } + else + { + for(i=0;i<font->length;i++) + { + if(font->chars[i].code == *(char*)pText) + { + Xsum += font->chars[i].image->width; + break; + } + } + } + pText++; + j++; + if((font == &FontT144) && (*(char*)pText != 0)) + Xsum += 3; + else + if((font == &FontT105) && (*(char*)pText != 0)) + Xsum += 2; + } + pText -= j; + + if(cfg->doubleSize) + Xsum *= 2; + + result = hgfx->WindowX1 - hgfx->WindowX0 - 1; + if(Xsum < result) + result -= Xsum; + else + result = 0; + + return result; +} + + + +void GFX_LTDC_Init(void) +{ + /* + HSYNC=10 (9+1) + HBP=10 (19-10+1) + ActiveW=480 (499-10-10+1) + HFP=8 (507-480-10-10+1) + + VSYNC=2 (1+1) + VBP=2 (3-2+1) + ActiveH=800 (803-2-2+1) + VFP=2 (805-800-2-2+1) + */ + + /* Timing configuration */ + /* Horizontal synchronization width = Hsync - 1 */ + LtdcHandle.Init.HorizontalSync = 9; + /* Vertical synchronization height = Vsync - 1 */ + LtdcHandle.Init.VerticalSync = 1; + /* Accumulated horizontal back porch = Hsync + HBP - 1 */ + LtdcHandle.Init.AccumulatedHBP = 19; + /* Accumulated vertical back porch = Vsync + VBP - 1 */ + LtdcHandle.Init.AccumulatedVBP = 3; + /* Accumulated active width = Hsync + HBP + Active Width - 1 */ + LtdcHandle.Init.AccumulatedActiveW = 499;//500;//499; + /* Accumulated active height = Vsync + VBP + Active Heigh - 1 */ + LtdcHandle.Init.AccumulatedActiveH = 803; + /* Total width = Hsync + HBP + Active Width + HFP - 1 */ + LtdcHandle.Init.TotalWidth = 507;//508;//507; + /* Total height = Vsync + VBP + Active Heigh + VFP - 1 */ + LtdcHandle.Init.TotalHeigh = 805; + + /* Configure R,G,B component values for LCD background color */ + LtdcHandle.Init.Backcolor.Red= 0; + LtdcHandle.Init.Backcolor.Blue= 0; + LtdcHandle.Init.Backcolor.Green= 0; + + /* LCD clock configuration */ + /* PLLSAI_VCO Input = HSE_VALUE/PLL_M = 1 Mhz */ + /* PLLSAI_VCO Output = PLLSAI_VCO Input * PLLSAIN = 192 Mhz */ + /* PLLLCDCLK = PLLSAI_VCO Output/PLLSAIR = 192/4 = 48 Mhz */ + /* LTDC clock frequency = PLLLCDCLK / LTDC_PLLSAI_DIVR_8 = 48/4 = 6Mhz */ + +/* done in main.c SystemClockConfig + + PeriphClkInitStruct.PeriphClockSelection = RCC_PERIPHCLK_LTDC; + PeriphClkInitStruct.PLLSAI.PLLSAIN = 192; + PeriphClkInitStruct.PLLSAI.PLLSAIR = 4; + PeriphClkInitStruct.PLLSAIDivR = RCC_PLLSAIDIVR_8; + HAL_RCCEx_PeriphCLKConfig(&PeriphClkInitStruct); +*/ + /* Polarity */ + LtdcHandle.Init.HSPolarity = LTDC_HSPOLARITY_AL; + LtdcHandle.Init.VSPolarity = LTDC_VSPOLARITY_AL; + LtdcHandle.Init.DEPolarity = LTDC_DEPOLARITY_AL; + LtdcHandle.Init.PCPolarity = LTDC_PCPOLARITY_IIPC;//LTDC_PCPOLARITY_IPC; + + LtdcHandle.Instance = LTDC; + + /* Configure the LTDC */ + if(HAL_LTDC_Init(&LtdcHandle) != HAL_OK) // auch init der GPIO Pins + { + /* Initialization Error */ + GFX_Error_Handler(); + } +} + +void GFX_VGA_LTDC_Init_test(void) +{ + + LtdcHandle.Init.HorizontalSync = 48; + /* Vertical synchronization height = Vsync - 1 */ + LtdcHandle.Init.VerticalSync = 3; + /* Accumulated horizontal back porch = Hsync + HBP - 1 */ + LtdcHandle.Init.AccumulatedHBP = 48 + 40 - 1; + /* Accumulated vertical back porch = Vsync + VBP - 1 */ + LtdcHandle.Init.AccumulatedVBP = 3 + 29 - 1; + /* Accumulated active width = Hsync + HBP + Active Width - 1 */ + LtdcHandle.Init.AccumulatedActiveW = 800 + 48 + 40 - 1;//499;//500;//499; + /* Accumulated active height = Vsync + VBP + Active Heigh - 1 */ + LtdcHandle.Init.AccumulatedActiveH = 480 + 3 + 29 - 1; + /* Total width = Hsync + HBP + Active Width + HFP - 1 */ + LtdcHandle.Init.TotalWidth = 800 + 48 + 40 - 1 + 40;//508;//507; + /* Total height = Vsync + VBP + Active Heigh + VFP - 1 */ + LtdcHandle.Init.TotalHeigh = 480 + 3 + 29 - 1 + 13; + + /* Configure R,G,B component values for LCD background color */ + LtdcHandle.Init.Backcolor.Red= 0; + LtdcHandle.Init.Backcolor.Blue= 0; + LtdcHandle.Init.Backcolor.Green= 0; + + /* LCD clock configuration */ + /* PLLSAI_VCO Input = HSE_VALUE/PLL_M = 1 Mhz */ + /* PLLSAI_VCO Output = PLLSAI_VCO Input * PLLSAIN = 192 Mhz */ + /* PLLLCDCLK = PLLSAI_VCO Output/PLLSAIR = 192/4 = 48 Mhz */ + /* LTDC clock frequency = PLLLCDCLK / LTDC_PLLSAI_DIVR_8 = 48/4 = 6Mhz */ + +/* done in main.c SystemClockConfig + + PeriphClkInitStruct.PeriphClockSelection = RCC_PERIPHCLK_LTDC; + PeriphClkInitStruct.PLLSAI.PLLSAIN = 192; + PeriphClkInitStruct.PLLSAI.PLLSAIR = 4; + PeriphClkInitStruct.PLLSAIDivR = RCC_PLLSAIDIVR_8; + HAL_RCCEx_PeriphCLKConfig(&PeriphClkInitStruct); +*/ + /* Polarity */ + LtdcHandle.Init.HSPolarity = LTDC_HSPOLARITY_AL; + LtdcHandle.Init.VSPolarity = LTDC_VSPOLARITY_AL; + LtdcHandle.Init.DEPolarity = LTDC_DEPOLARITY_AL; + LtdcHandle.Init.PCPolarity = LTDC_PCPOLARITY_IPC;//LTDC_PCPOLARITY_IPC; + + LtdcHandle.Instance = LTDC; + + /* Configure the LTDC */ + if(HAL_LTDC_Init(&LtdcHandle) != HAL_OK) // auch init der GPIO Pins + { + /* Initialization Error */ + GFX_Error_Handler(); + } +} + + +void GFX_VGA_LTDC_Init_org(void) +{ + + LtdcHandle.Init.HorizontalSync = 96; + /* Vertical synchronization height = Vsync - 1 */ + LtdcHandle.Init.VerticalSync = 2; + /* Accumulated horizontal back porch = Hsync + HBP - 1 */ + LtdcHandle.Init.AccumulatedHBP = 96 + 48; + /* Accumulated vertical back porch = Vsync + VBP - 1 */ + LtdcHandle.Init.AccumulatedVBP = 2 + 35; + /* Accumulated active width = Hsync + HBP + Active Width - 1 */ + LtdcHandle.Init.AccumulatedActiveW = 96 + 48 + 800;//499;//500;//499; + /* Accumulated active height = Vsync + VBP + Active Heigh - 1 */ + LtdcHandle.Init.AccumulatedActiveH = 2 + 35 + 480; + /* Total width = Hsync + HBP + Active Width + HFP - 1 */ + LtdcHandle.Init.TotalWidth = 96 + 48 + 800 + 12;//508;//507; + /* Total height = Vsync + VBP + Active Heigh + VFP - 1 */ + LtdcHandle.Init.TotalHeigh = 2 + 35 + 480 + 12; + + /* Configure R,G,B component values for LCD background color */ + LtdcHandle.Init.Backcolor.Red= 0; + LtdcHandle.Init.Backcolor.Blue= 0; + LtdcHandle.Init.Backcolor.Green= 0; + + /* LCD clock configuration */ + /* PLLSAI_VCO Input = HSE_VALUE/PLL_M = 1 Mhz */ + /* PLLSAI_VCO Output = PLLSAI_VCO Input * PLLSAIN = 192 Mhz */ + /* PLLLCDCLK = PLLSAI_VCO Output/PLLSAIR = 192/4 = 48 Mhz */ + /* LTDC clock frequency = PLLLCDCLK / LTDC_PLLSAI_DIVR_8 = 48/4 = 6Mhz */ + +/* done in main.c SystemClockConfig + + PeriphClkInitStruct.PeriphClockSelection = RCC_PERIPHCLK_LTDC; + PeriphClkInitStruct.PLLSAI.PLLSAIN = 192; + PeriphClkInitStruct.PLLSAI.PLLSAIR = 4; + PeriphClkInitStruct.PLLSAIDivR = RCC_PLLSAIDIVR_8; + HAL_RCCEx_PeriphCLKConfig(&PeriphClkInitStruct); +*/ + /* Polarity */ + LtdcHandle.Init.HSPolarity = LTDC_HSPOLARITY_AL; + LtdcHandle.Init.VSPolarity = LTDC_VSPOLARITY_AH; + LtdcHandle.Init.DEPolarity = LTDC_DEPOLARITY_AL; + LtdcHandle.Init.PCPolarity = LTDC_PCPOLARITY_IPC;//LTDC_PCPOLARITY_IPC; + + LtdcHandle.Instance = LTDC; + + /* Configure the LTDC */ + if(HAL_LTDC_Init(&LtdcHandle) != HAL_OK) // auch init der GPIO Pins + { + /* Initialization Error */ + GFX_Error_Handler(); + } +} + +void GFX_VGA_LTDC_Init(void) +//void GFX_VGA_LTDC_Init_640x480(void) +{ + + LtdcHandle.Init.HorizontalSync = 96; + /* Vertical synchronization height = Vsync - 1 */ + LtdcHandle.Init.VerticalSync = 2; + /* Accumulated horizontal back porch = Hsync + HBP - 1 */ + LtdcHandle.Init.AccumulatedHBP = 96 + 48; + /* Accumulated vertical back porch = Vsync + VBP - 1 */ + LtdcHandle.Init.AccumulatedVBP = 2 + 35; + /* Accumulated active width = Hsync + HBP + Active Width - 1 */ + LtdcHandle.Init.AccumulatedActiveW = 96 + 48 + 640;//499;//500;//499; + /* Accumulated active height = Vsync + VBP + Active Heigh - 1 */ + LtdcHandle.Init.AccumulatedActiveH = 2 + 35 + 480; + /* Total width = Hsync + HBP + Active Width + HFP - 1 */ + LtdcHandle.Init.TotalWidth = 96 + 48 + 640 + 12;//508;//507; + /* Total height = Vsync + VBP + Active Heigh + VFP - 1 */ + LtdcHandle.Init.TotalHeigh = 2 + 35 + 480 + 12; + + /* Configure R,G,B component values for LCD background color */ + LtdcHandle.Init.Backcolor.Red= 0; + LtdcHandle.Init.Backcolor.Blue= 0; + LtdcHandle.Init.Backcolor.Green= 0; + + /* LCD clock configuration */ + /* PLLSAI_VCO Input = HSE_VALUE/PLL_M = 1 Mhz */ + /* PLLSAI_VCO Output = PLLSAI_VCO Input * PLLSAIN = 192 Mhz */ + /* PLLLCDCLK = PLLSAI_VCO Output/PLLSAIR = 192/4 = 48 Mhz */ + /* LTDC clock frequency = PLLLCDCLK / LTDC_PLLSAI_DIVR_8 = 48/4 = 6Mhz */ + +/* done in main.c SystemClockConfig + + PeriphClkInitStruct.PeriphClockSelection = RCC_PERIPHCLK_LTDC; + PeriphClkInitStruct.PLLSAI.PLLSAIN = 192; + PeriphClkInitStruct.PLLSAI.PLLSAIR = 4; + PeriphClkInitStruct.PLLSAIDivR = RCC_PLLSAIDIVR_8; + HAL_RCCEx_PeriphCLKConfig(&PeriphClkInitStruct); +*/ + /* Polarity */ + LtdcHandle.Init.HSPolarity = LTDC_HSPOLARITY_AL; + LtdcHandle.Init.VSPolarity = LTDC_VSPOLARITY_AH; + LtdcHandle.Init.DEPolarity = LTDC_DEPOLARITY_AL; + LtdcHandle.Init.PCPolarity = LTDC_PCPOLARITY_IPC;//LTDC_PCPOLARITY_IPC; + + LtdcHandle.Instance = LTDC; + + /* Configure the LTDC */ + if(HAL_LTDC_Init(&LtdcHandle) != HAL_OK) // auch init der GPIO Pins + { + /* Initialization Error */ + GFX_Error_Handler(); + } +} + + +void GFX_LTDC_LayerDefaultInit(uint16_t LayerIndex, uint32_t FB_Address) +{ + LTDC_LayerCfgTypeDef Layercfg; + + /* Layer Init */ + Layercfg.WindowX0 = 0; + Layercfg.WindowX1 = 480; + Layercfg.WindowY0 = 0; + Layercfg.WindowY1 = 800; + Layercfg.PixelFormat = LTDC_PIXEL_FORMAT_AL88;//LTDC_PIXEL_FORMAT_ARGB8888; + Layercfg.FBStartAdress = FB_Address; + Layercfg.Alpha = 255; + Layercfg.Alpha0 = 0; + Layercfg.Backcolor.Blue = 0; + Layercfg.Backcolor.Green = 0; + Layercfg.Backcolor.Red = 0; + Layercfg.BlendingFactor1 = LTDC_BLENDING_FACTOR1_PAxCA; + Layercfg.BlendingFactor2 = LTDC_BLENDING_FACTOR2_PAxCA; + Layercfg.ImageWidth = 480; + Layercfg.ImageHeight = 800; + + HAL_LTDC_ConfigCLUT(&LtdcHandle, ColorLUT, CLUT_END, LayerIndex); + HAL_LTDC_ConfigLayer(&LtdcHandle, &Layercfg, LayerIndex); + HAL_LTDC_EnableCLUT(&LtdcHandle, LayerIndex); +} + +void GFX_VGA_LTDC_LayerDefaultInit(uint16_t LayerIndex, uint32_t FB_Address) +{ + LTDC_LayerCfgTypeDef Layercfg; + + /* Layer Init */ + Layercfg.WindowX0 = 0; + Layercfg.WindowX1 = 640; + Layercfg.WindowY0 = 0; + Layercfg.WindowY1 = 480; + Layercfg.PixelFormat = LTDC_PIXEL_FORMAT_AL88;//LTDC_PIXEL_FORMAT_ARGB8888; + Layercfg.FBStartAdress = FB_Address; + Layercfg.Alpha = 255; + Layercfg.Alpha0 = 0; + Layercfg.Backcolor.Blue = 0; + Layercfg.Backcolor.Green = 0; + Layercfg.Backcolor.Red = 0; + Layercfg.BlendingFactor1 = LTDC_BLENDING_FACTOR1_PAxCA; + Layercfg.BlendingFactor2 = LTDC_BLENDING_FACTOR2_PAxCA; + Layercfg.ImageWidth = 640; + Layercfg.ImageHeight = 480; + + HAL_LTDC_ConfigCLUT(&LtdcHandle, ColorLUT, CLUT_END, LayerIndex); + HAL_LTDC_ConfigLayer(&LtdcHandle, &Layercfg, LayerIndex); + HAL_LTDC_EnableCLUT(&LtdcHandle, LayerIndex); +} + +void GFX_LTDC_LayerTESTInit(uint16_t LayerIndex, uint32_t FB_Address) +{ + LTDC_LayerCfgTypeDef Layercfg; + + /* Layer Init */ + Layercfg.WindowX0 = 0; + Layercfg.WindowX1 = 390; + Layercfg.WindowY0 = 0; + Layercfg.WindowY1 = 800; + Layercfg.PixelFormat = LTDC_PIXEL_FORMAT_AL88;//LTDC_PIXEL_FORMAT_ARGB8888; + Layercfg.FBStartAdress = FB_Address; + Layercfg.Alpha = 255; + Layercfg.Alpha0 = 255; + Layercfg.Backcolor.Blue = 0; + Layercfg.Backcolor.Green = 0; + Layercfg.Backcolor.Red = 200; + Layercfg.BlendingFactor1 = LTDC_BLENDING_FACTOR1_PAxCA; + Layercfg.BlendingFactor2 = LTDC_BLENDING_FACTOR2_PAxCA; + Layercfg.ImageWidth = 480; + Layercfg.ImageHeight = 800; + + HAL_LTDC_ConfigCLUT(&LtdcHandle, ColorLUT, CLUT_END, LayerIndex); + HAL_LTDC_ConfigLayer(&LtdcHandle, &Layercfg, LayerIndex); + HAL_LTDC_EnableCLUT(&LtdcHandle, LayerIndex); +} + + +uint32_t GFX_doubleBufferOne(void) +{ + return SDRAM_DOUBLE_BUFFER_ONE; +} + + +uint32_t GFX_doubleBufferTwo(void) +{ + return SDRAM_DOUBLE_BUFFER_TWO; +} + +/* +void doubleBufferClear(uint32_t pDestination) +{ + for(uint32_t i = 2*200*480; i > 0; i--) + { + *(__IO uint16_t*)pDestination = 0; + pDestination += 2; + *(__IO uint16_t*)pDestination = 0; + pDestination += 2; + *(__IO uint16_t*)pDestination = 0; + pDestination += 2; + *(__IO uint16_t*)pDestination = 0; + pDestination += 2; + } +} + + +void GFX_doubleBufferClearOne(void) +{ + doubleBufferClear(SDRAM_DOUBLE_BUFFER_ONE); +} + + +void GFX_doubleBufferClearTwo(void) +{ + doubleBufferClear(SDRAM_DOUBLE_BUFFER_TWO); +} +*/ + +uint32_t getFrameByNumber(uint8_t ZeroToMaxFrames) +{ + if(ZeroToMaxFrames >= MAXFRAMES) + return 0; + else + return frame[ZeroToMaxFrames].StartAddress; +} + +uint32_t getFrame(uint8_t callerId) +{ + uint8_t i; + + i = 0; + while((i < MAXFRAMES) && (frame[i].status != CLEAR)) + i++; + + if((i < MAXFRAMES) && (frame[i].status == CLEAR)) + { + frame[i].status = BLOCKED; + frame[i].caller = callerId; + return frame[i].StartAddress; + } + + i = 0; + while((i < MAXFRAMES) && (frame[i].status != RELEASED)) + i++; + + if((i < MAXFRAMES) && (frame[i].status == RELEASED)) + { + GFX_clear_frame_immediately(frame[i].StartAddress); + frame[i].status = BLOCKED; + return frame[i].StartAddress; + } + return 0; +} + + +void GFX_forceReleaseFramesWithId(uint8_t callerId) +{ + for(int i=0; i<MAXFRAMES; i++) + if((frame[i].caller == callerId) && (frame[i].status == BLOCKED)) + frame[i].status = RELEASED; +} + + +void releaseAllFramesExcept(uint8_t callerId, uint32_t frameStartAddress) +{ + for(int i=0; i<MAXFRAMES; i++) + if((frame[i].caller == callerId) && (frame[i].status == BLOCKED) && (frame[i].StartAddress != frameStartAddress)) + frame[i].status = RELEASED; +} + + +uint8_t releaseFrame(uint8_t callerId, uint32_t frameStartAddress) +{ + static uint8_t countErrorCalls = 0; + + if(frameStartAddress < FBGlobalStart) + return 2; + + + uint8_t i; + + i = 0; + while((i < MAXFRAMES) && (frame[i].StartAddress != frameStartAddress)) + i++; + + if((i < MAXFRAMES) && (frame[i].StartAddress == frameStartAddress)) + { + if(frame[i].caller == callerId) + { + frame[i].status = RELEASED; + return 1; + } + else + countErrorCalls++; + } + return 0; +} + + +uint16_t blockedFramesCount(void) +{ + uint16_t count = MAXFRAMES; + + for(int i = 0;i<MAXFRAMES;i++) + if(frame[i].status == BLOCKED) + count--; + + return count; +} + + +uint8_t getFrameCount(uint8_t frameId) +{ + if(frameId < (MAXFRAMECOUNTER - 3)) + return frameCounter[frameId]; + else + return frameCounter[MAXFRAMECOUNTER - 2]; +} + + +void housekeepingFrame(void) +{ + static uint8_t countLogClear = 0; + + if(DMA2D_at_work != 255) + return; + + /* new for debug hw 151202 */ + for(int i=1;i<MAXFRAMECOUNTER;i++) + { + frameCounter[i] = 0; + } + for(int i=1;i<MAXFRAMES;i++) + { + 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-1]++; + } + + + 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); + } +} + + +static void GFX_Dma2d_TransferComplete(DMA2D_HandleTypeDef* Dma2dHandle) +{ + if(DMA2D_at_work < MAXFRAMES) + frame[DMA2D_at_work].status = CLEAR; + + DMA2D_at_work = 255; +} + + +static void GFX_Dma2d_TransferError(DMA2D_HandleTypeDef* Dma2dHandle) +{ + +} + +static void GFX_Error_Handler(void) +{ + /* Turn LED3 on */ +// BSP_LED_On(LED3); + while(1) + { + } +} + +void write_content_simple(GFX_DrawCfgScreen *tMscreen, uint16_t XleftGimpStyle, uint16_t XrightGimpStyle, uint16_t YtopGimpStyle, const tFont *Font, const char *text, uint8_t color) +{ + GFX_DrawCfgWindow hgfx; + + if(XrightGimpStyle > 799) + XrightGimpStyle = 799; + if(XleftGimpStyle >= XrightGimpStyle) + XleftGimpStyle = 0; + if(YtopGimpStyle > 479) + YtopGimpStyle = 479; + hgfx.Image = tMscreen; + hgfx.WindowNumberOfTextLines = 1; + hgfx.WindowLineSpacing = 0; + hgfx.WindowTab = 0; + hgfx.WindowX0 = XleftGimpStyle; + hgfx.WindowX1 = XrightGimpStyle; + hgfx.WindowY1 = 479 - YtopGimpStyle; + if(hgfx.WindowY1 < Font->height) + hgfx.WindowY0 = 0; + else + hgfx.WindowY0 = hgfx.WindowY1 - Font->height; + + GFX_write_string_color(Font, &hgfx, text, 0, color); +} + + +void gfx_write_topline_simple(GFX_DrawCfgScreen *tMscreen, const char *text, uint8_t color) +{ + GFX_DrawCfgWindow hgfx; + const tFont *Font = &FontT48; + + hgfx.Image = tMscreen; + hgfx.WindowNumberOfTextLines = 1; + hgfx.WindowLineSpacing = 0; + hgfx.WindowTab = 0; + hgfx.WindowX0 = 20; + hgfx.WindowX1 = 779; + hgfx.WindowY1 = 479; + hgfx.WindowY0 = hgfx.WindowY1 - Font->height; + + GFX_write_label(Font, &hgfx, text, color); + +} + + +void gfx_write_page_number(GFX_DrawCfgScreen *tMscreen, uint8_t page, uint8_t total, uint8_t color) +{ + GFX_DrawCfgWindow hgfx; + const tFont *Font = &FontT48; + char text[7]; + uint8_t i, secondDigitPage, secondDigitTotal; + + hgfx.Image = tMscreen; + hgfx.WindowNumberOfTextLines = 1; + hgfx.WindowLineSpacing = 0; + hgfx.WindowTab = 0; + hgfx.WindowX1 = 779; + hgfx.WindowX0 = hgfx.WindowX1 - (25*5); + hgfx.WindowY1 = 479; + hgfx.WindowY0 = hgfx.WindowY1 - Font->height; + + if(page > 99) + page = 99; + if(total > 99) + total = 99; + + i = 0; + text[i++] = '\002'; + + secondDigitPage = page / 10; + page -= secondDigitPage * 10; + + secondDigitTotal = total / 10; + total -= secondDigitTotal * 10; + + if(secondDigitPage) + text[i++] = '0' + secondDigitPage; + text[i++] = '0' + page; + + text[i++] = '/'; + + if(secondDigitTotal) + text[i++] = '0' + secondDigitTotal; + text[i++] = '0' + total; + + text[i] = 0; + + GFX_clear_window_immediately(&hgfx); + GFX_write_label(Font, &hgfx, text, color); +} + + +uint8_t gfx_number_to_string(uint8_t max_digits, _Bool fill, char *pText, uint32_t input) +{ + uint8_t digits[10]; + uint32_t number, divider; + int first; + uint8_t out; + + number = input; + first = 0; + divider = 1000000000; + for(int i=9;i>=0;i--) + { + digits[i] = (uint8_t)(number / divider); + number -= digits[i] * divider; + divider /= 10; + if((first == 0) && (digits[i] != 0)) + first = i; + } + + if((first + 1) > max_digits) + { + for(int i = 0; i<max_digits; i++) + pText[i] = '9'; + out = max_digits; + } + else if(fill) + { + int i = 0; + for(int k = max_digits; k>0; k--) + pText[i++] = digits[k -1] + '0'; + out = max_digits; + } + else + { + int i = 0; + for(int k = first; k>=0; k--) + pText[i++] = digits[k] + '0'; + out = i; + } + + return out; +} + + + /* output is + * 0-> + * | + * v + * + * input is + * + * -> + * A + * | + * 0 + */ +void GFX_screenshot(void) +{ + uint32_t pSource = GFX_get_pActualFrameTop(); + uint32_t pSourceBottom =GFX_get_pActualFrameBottom(); + uint32_t pBottomNew = getFrame(99); + uint32_t pDestination = GFX_doubleBufferOne(); + uint32_t sourceNow; + + + uint32_t bot_leftStart = FrameHandler.actualBottom.leftStart; // x0 z.B. 0 + uint32_t bot_bottomStart = FrameHandler.actualBottom.bottomStart; // y0 z.B. 25 + uint32_t bot_width = FrameHandler.actualBottom.width; // 800 + uint32_t bot_height = FrameHandler.actualBottom.height; // 390 + + struct split + { + uint8_t blue; + uint8_t green; + uint8_t red; + uint8_t alpha; + }; + + union inout_u + { + uint32_t in; + struct split out; + }; + + union inout_u value; + +/* test + uint32_t pSourceTemp = pSource + (2*479); + for (int j = 0xFFFF; j > 0x00FF; j -= 0x0100) + { + *(__IO uint16_t*)pSourceTemp = j; + pSourceTemp += 480*2; + } +*/ + // Top Layer + const unsigned width = 800, height = 480; + const uint32_t heightX2 = height*2; + + for(unsigned y = 0; y < height; y++) + { + sourceNow = pSource + 2 * ((height - 1) - y); + for(unsigned x = 0; x < width; x++) + { +// sourceNow += 2 * height * x + 2 * (height - 1 - y); + value.in = ColorLUT[*(__IO uint8_t*)(sourceNow)]; + value.out.alpha = *(__IO uint8_t*)(sourceNow + 1); + + *(__IO uint8_t*)(pDestination++) = value.out.red; + *(__IO uint8_t*)(pDestination++) = value.out.green; + *(__IO uint8_t*)(pDestination++) = value.out.blue; + *(__IO uint8_t*)(pDestination++) = value.out.alpha; + sourceNow += heightX2; + } + } + + // Bottom Layer + // build newBottom + pSource = pSourceBottom; + for(unsigned x = bot_leftStart; x < bot_leftStart+bot_width; x++) + { + for(unsigned y = bot_bottomStart; y < bot_bottomStart+bot_height; y++) + { + pDestination = pBottomNew + (2 * y); + pDestination += heightX2 * x; + *(__IO uint16_t*)(pDestination) = *(__IO uint16_t*)(pSource); + pSource += 2; + } + } + + // output Bottom Layer + pSource = pBottomNew; + pDestination = GFX_doubleBufferTwo(); + + for(unsigned y = 0; y < height; y++) + { + sourceNow = pSource + 2 * ((height - 1) - y); + for(unsigned x = 0; x < width; x++) + { +// sourceNow = pSource + 2 * height * x + 2 * (height - 1 - y); + value.in = ColorLUT[*(__IO uint8_t*)(sourceNow)]; + value.out.alpha = *(__IO uint8_t*)(sourceNow + 1); + + *(__IO uint8_t*)(pDestination++) = value.out.red; + *(__IO uint8_t*)(pDestination++) = value.out.green; + *(__IO uint8_t*)(pDestination++) = value.out.blue; + *(__IO uint8_t*)(pDestination++) = value.out.alpha; + sourceNow += heightX2; + } + } + releaseFrame(99,pBottomNew); +/* + // das kommt dazu! + unsigned yEnd = 480 - FrameHandler.actualBottom.bottomStart; + unsigned yStart = yEnd - FrameHandler.actualBottom.height; + + if(yStart > 0) + { + for(unsigned y = 0; y < yStart; y++) + for(unsigned x = 0; x < width; x++) + { + *(__IO uint8_t*)(pDestination++) = 0; + *(__IO uint8_t*)(pDestination++) = 0; + *(__IO uint8_t*)(pDestination++) = 0; + *(__IO uint8_t*)(pDestination++) = 0; + } + } + for(unsigned y = yStart; y < yEnd; y++) + for(unsigned x = 0; x < width; x++) + { + sourceNow = pSource + 2 * height * x + 2 * (height - 1 - y); + value.in = ColorLUT[*(__IO uint8_t*)(sourceNow)]; + value.out.alpha = *(__IO uint8_t*)(sourceNow + 1); + + *(__IO uint8_t*)(pDestination++) = value.out.red; + *(__IO uint8_t*)(pDestination++) = value.out.green; + *(__IO uint8_t*)(pDestination++) = value.out.blue; + *(__IO uint8_t*)(pDestination++) = value.out.alpha; + } + if(yEnd < 480) + { + for(unsigned y = yEnd; y < 480; y++) + for(unsigned x = 0; x < width; x++) + { + *(__IO uint8_t*)(pDestination++) = 0; + *(__IO uint8_t*)(pDestination++) = 0; + *(__IO uint8_t*)(pDestination++) = 0; + *(__IO uint8_t*)(pDestination++) = 0; + } + } +*/ +}