Mercurial > public > ostc4
view 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 source
/** ****************************************************************************** * @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; } } */ }