comparison BootLoader/Src/gfx_engine_mini.c @ 985:aeafa631147d BootloaderOstc5

Exchange shared files with Bootloader specific mini version
author Ideenmodellierer
date Sun, 30 Mar 2025 21:32:37 +0200 (3 weeks ago)
parents
children 45a2bd04b156
comparison
equal deleted inserted replaced
984:41136649b90d 985:aeafa631147d
1 /**
2 ******************************************************************************
3 * @file gfx_engine.c
4 * @author heinrichs weikamp gmbh
5 * @version V0.0.2
6 * @date 30-April-2014
7 * @brief Main source file of GFX Graphic Engine
8 * This file provides firmware functions to manage the following
9 * functions to draw on the screen:
10 * + write string to display
11 *
12 ******************************************************************************
13 * @attention
14 *
15 * <h2><center>&copy; COPYRIGHT(c) 2014 heinrichs weikamp</center></h2>
16 *
17 ******************************************************************************
18 */
19
20 /* Includes ------------------------------------------------------------------*/
21
22 #include <stdlib.h>
23 #include <stdint.h>
24
25 #include "stm32f4xx_hal.h"
26
27 #include "gfx.h"
28 #include "gfx_engine.h"
29 #include "gfx_fonts.h"
30 #include "gfx_colors.h"
31 #include "ostc.h"
32 #include "settings.h"
33 #include "text_multilanguage.h"
34
35 /* Exported variables --------------------------------------------------------*/
36
37 /* Private types -------------------------------------------------------------*/
38
39 #define RING_BUF_SIZE (5u)
40 #define MAX_COLOR_STRING_LENGTH (100u)
41
42 typedef struct
43 {
44 uint32_t Xdelta;
45 uint32_t Ydelta;
46 uint8_t invert;
47 uint8_t color;
48 uint8_t dualFont;
49 uint8_t resize;
50 uint32_t font;
51 uint8_t spaceMode;
52 uint8_t singleSpaceWithSizeOfNextChar;
53 uint8_t useTinyFont;
54 uint32_t TinyFont;
55 int8_t TinyFontExtraYdelta;
56 tFont *actualFont;
57 uint8_t doubleSize;
58 } GFX_CfgWriteString;
59
60 typedef struct
61 {
62 uint32_t pBuffer;
63 uint32_t height;
64 uint32_t width;
65 uint32_t leftStart;
66 uint32_t bottomStart;
67 } GFX_layerSingle;
68 /*
69 typedef struct
70 {
71 GFX_layerSingle top;
72 GFX_layerSingle bottom;
73 } GFX_layersTopBottom;
74 */
75 typedef struct
76 {
77 uint32_t pActualTopBuffer;
78 uint32_t pNextTopBuffer[RING_BUF_SIZE];
79 GFX_layerSingle actualBottom;
80 GFX_layerSingle nextBottom[RING_BUF_SIZE];
81 uint8_t NextTopWrite;
82 uint8_t NextBottomWrite;
83 uint8_t NextTopRead;
84 uint8_t NextBottomRead;
85 } GFX_layerControl;
86
87 typedef struct
88 {
89 uint32_t StartAddress;
90 int8_t status;
91 uint8_t caller;
92 } SFrameList;
93
94 enum FRAMESTATE
95 {
96 CLEAR = 0,
97 BLOCKED,
98 RELEASED
99 };
100
101 enum LOGOSTATE
102 {
103 LOGOOFF = 0,
104 LOGOSTART = 1,
105 LOGOSTOP = 255
106 };
107
108 // should be 43
109 #define MAXFRAMES 39
110
111 #define SDRAM_BANK_ADDR ((uint32_t)0xD0000000)
112 #define FBGlobalStart SDRAM_BANK_ADDR
113 #define FBOffsetEachIndex (800*480*2)
114
115 #define SDRAM_DOUBLE_BUFFER_ONE ((uint32_t)(FBGlobalStart + (MAXFRAMES * FBOffsetEachIndex)))
116 #define SDRAM_DOUBLE_BUFFER_TWO ((uint32_t)(SDRAM_DOUBLE_BUFFER_ONE + (2 * FBOffsetEachIndex)))
117 #define SDRAM_DOUBLE_BUFFER_END ((uint32_t)(SDRAM_DOUBLE_BUFFER_TWO + (2 * FBOffsetEachIndex)))
118
119 /* Semi Private variables ---------------------------------------------------------*/
120
121 DMA2D_HandleTypeDef Dma2dHandle;
122 static LTDC_HandleTypeDef LtdcHandle;
123
124 /* Private variables ---------------------------------------------------------*/
125
126 static uint8_t DMA2D_at_work = 0;
127
128 static GFX_layerControl FrameHandler = { 0 };
129
130 static uint32_t pInvisibleFrame = 0;
131 static uint32_t pLogoFrame = 0;
132 static uint8_t logoStatus;
133 static uint32_t pBackgroundHwFrame = 0;
134 static uint8_t backgroundHwStatus;
135
136 static SFrameList frame[MAXFRAMES];
137
138 static void GFX_clear_frame_immediately(uint32_t pDestination);
139 static void GFX_draw_image_color(GFX_DrawCfgScreen *hgfx, SWindowGimpStyle window, const tImage *image);
140 /* ITM Trace-----------------------------------------------------------------*/
141
142 #include "stdio.h"
143
144 #define ITM_Port8(n) (*((volatile unsigned char *)(0xE0000000+4*n)))
145 #define ITM_Port16(n) (*((volatile unsigned short*)(0xE0000000+4*n)))
146 #define ITM_Port32(n) (*((volatile unsigned long *)(0xE0000000+4*n)))
147
148 #define DEMCR (*((volatile unsigned long *)(0xE000EDFC)))
149 #define TRCENA 0x01000000
150
151 struct __FILE { int handle; /* Add whatever needed */ };
152 FILE __stdout;
153 FILE __stdin;
154
155 int fputc(int ch, FILE *f) {
156 if (DEMCR & TRCENA) {
157 while (ITM_Port32(0) == 0);
158 ITM_Port8(0) = ch;
159 }
160 return(ch);
161 }
162
163 uint32_t MinU32GFX(uint32_t a, uint32_t b)
164 {
165 return ((a<b)?a:b);
166 }
167
168
169 uint32_t MaxU32GFX(uint32_t a, uint32_t b)
170 {
171 return((a>b)?a:b);
172 }
173
174 /* Private function prototypes -----------------------------------------------*/
175
176 static uint32_t GFX_write_char(GFX_DrawCfgWindow* hgfx, GFX_CfgWriteString* cfg, uint8_t character, tFont *Font);
177 static uint32_t GFX_write_substring(GFX_CfgWriteString* cfg, GFX_DrawCfgWindow* hgfx, uint8_t textId, int8_t nextCharFor2Byte);
178 static uint32_t GFX_write__Modify_Xdelta__Centered(GFX_CfgWriteString* cfg, GFX_DrawCfgWindow* hgfx, const char *pText);
179 static uint32_t GFX_write__Modify_Xdelta__RightAlign(GFX_CfgWriteString* cfg, GFX_DrawCfgWindow* hgfx, const char *pTextInput);
180 static void GFX_Error_Handler(void);
181 static void GFX_Dma2d_TransferComplete(DMA2D_HandleTypeDef* Dma2dHandle);
182 static void GFX_Dma2d_TransferError(DMA2D_HandleTypeDef* Dma2dHandle);
183 static void GFX_clear_frame_dma2d(uint8_t frameId);
184
185 static uint32_t GFX_doubleBufferOne(void);
186 static uint32_t GFX_doubleBufferTwo(void);
187
188 static void GFX_LTDC_Init_display1(void);
189
190
191 /* Exported functions --------------------------------------------------------*/
192
193 uint8_t GFX_logoStatus(void)
194 {
195 return logoStatus;
196 }
197
198 void GFX_SetWindowLayer0(uint32_t pDestination, int16_t XleftGimpStyle, int16_t XrightGimpStyle, int16_t YtopGimpStyle, int16_t YbottomGimpStyle)
199 {
200 int16_t XSize, YSize, X0, Y0;
201
202 if(XleftGimpStyle < 0) XleftGimpStyle = 0;
203 if(XrightGimpStyle < 0) XrightGimpStyle = 0;
204 if(XleftGimpStyle > 799) XleftGimpStyle = 800;
205 if(XrightGimpStyle > 799) XrightGimpStyle = 800;
206
207 if(YtopGimpStyle < 0) YtopGimpStyle = 0;
208 if(YbottomGimpStyle < 0) YbottomGimpStyle = 0;
209 if(YtopGimpStyle > 479) YtopGimpStyle = 480;
210 if(YbottomGimpStyle > 479) YbottomGimpStyle = 480;
211
212 /*
213 XSize = YbottomGimpStyle - YtopGimpStyle;
214 YSize = XrightGimpStyle - XleftGimpStyle;
215 if((XSize <= 0) || (YSize <= 0))
216 return;
217 X0 = 479 - YbottomGimpStyle;
218 Y0 = XleftGimpStyle;
219 while((LTDC->CPSR & LTDC_CPSR_CYPOS) <= (uint32_t)800);
220 HAL_LTDC_SetWindowSize(&LtdcHandle, XSize, YSize, LayerIdx);
221 HAL_LTDC_SetWindowPosition(&LtdcHandle, X0, Y0,LayerIdx);
222 HAL_LTDC_SetAddress(&LtdcHandle, pDestination, LayerIdx);
223 */
224
225 XSize = XrightGimpStyle - XleftGimpStyle;
226 YSize = YbottomGimpStyle - YtopGimpStyle;
227 if((XSize <= 0) || (YSize <= 0))
228 return;
229 Y0 = 479 - YbottomGimpStyle;
230 X0 = XleftGimpStyle;
231
232 GFX_SetFrameBottom(pDestination, X0, Y0, XSize, YSize);
233 }
234
235
236 void GFX_logoAutoOff(void)
237 {
238 if(logoStatus == LOGOOFF)
239 logoStatus = LOGOSTART;
240 }
241
242
243 void GFX_hwBackgroundOn(void)
244 {
245 backgroundHwStatus = LOGOSTART;
246 }
247
248
249 void GFX_hwBackgroundOff(void)
250 {
251 backgroundHwStatus = LOGOSTOP;
252 }
253
254 void GFX_build_hw_background_frame(void)
255 {
256 GFX_DrawCfgScreen tLogoTemp;
257 SWindowGimpStyle windowGimp;
258
259 pBackgroundHwFrame = getFrame(1);
260 backgroundHwStatus = 0;
261
262 tLogoTemp.FBStartAdress = pBackgroundHwFrame;
263 tLogoTemp.ImageHeight = 480;
264 tLogoTemp.ImageWidth = 800;
265 tLogoTemp.LayerIndex = 1;
266
267 windowGimp.left = (800 - 400) / 2;
268 windowGimp.top = 0;//(480 - 46) / 2;
269
270 GFX_draw_image_color(&tLogoTemp, windowGimp, &ImgHWcolor);
271 /*
272 char localtext[256];
273 uint8_t ptr = 0;
274
275 localtext[ptr++] = ' ';
276 localtext[ptr++] = ' ';
277 localtext[ptr++] = 'O';
278 localtext[ptr++] = 'S';
279 localtext[ptr++] = ' ';
280 ptr += GFX_printf_firmware(&localtext[ptr]);
281 localtext[ptr] = 0;
282
283 write_content_simple(&tLogoTemp, 0, 800, 240-24, &FontT24,localtext,CLUT_Font020);
284 */
285 }
286
287
288 void GFX_build_logo_frame(void)
289 {
290 GFX_DrawCfgScreen tLogoTemp;
291 SWindowGimpStyle windowGimp;
292
293 pLogoFrame = getFrame(1);
294 logoStatus = LOGOOFF;
295
296 tLogoTemp.FBStartAdress = pLogoFrame;
297 tLogoTemp.ImageHeight = 480;
298 tLogoTemp.ImageWidth = 800;
299 tLogoTemp.LayerIndex = 1;
300
301 windowGimp.left = (800 - 400) / 2;
302 windowGimp.top = (480 - 46) / 2;
303
304 GFX_draw_image_color(&tLogoTemp, windowGimp, &ImgHWcolor);
305 /*
306 char localtext[256];
307 uint8_t ptr = 0;
308
309 localtext[ptr++] = ' ';
310 localtext[ptr++] = ' ';
311 localtext[ptr++] = 'O';
312 localtext[ptr++] = 'S';
313 localtext[ptr++] = ' ';
314 ptr += GFX_printf_firmware(&localtext[ptr]);
315 localtext[ptr] = 0;
316
317 write_content_simple(&tLogoTemp, 0, 800, 240-24, &FontT24,localtext,CLUT_Font020);
318 */
319 }
320
321 void GFX_init(uint32_t * pDestinationOut)
322 {
323 frame[0].StartAddress = FBGlobalStart;
324 GFX_clear_frame_immediately(frame[0].StartAddress);
325 frame[0].status = CLEAR;
326 frame[0].caller = 0;
327
328 for(int i=1;i<MAXFRAMES;i++)
329 {
330 frame[i].StartAddress = frame[i-1].StartAddress + FBOffsetEachIndex;
331 GFX_clear_frame_immediately(frame[i].StartAddress);
332 frame[i].status = CLEAR;
333 frame[i].caller = 0;
334 }
335
336 pInvisibleFrame = getFrame(2);
337 *pDestinationOut = pInvisibleFrame;
338
339 GFX_build_logo_frame();
340 GFX_build_hw_background_frame();
341
342 /* Register to memory mode with ARGB8888 as color Mode */
343 Dma2dHandle.Init.Mode = DMA2D_R2M;
344 Dma2dHandle.Init.ColorMode = DMA2D_ARGB4444;//to fake AL88, before: DMA2D_ARGB8888;
345 Dma2dHandle.Init.OutputOffset = 0;
346
347 /* DMA2D Callbacks Configuration */
348 Dma2dHandle.XferCpltCallback = GFX_Dma2d_TransferComplete;
349 Dma2dHandle.XferErrorCallback = GFX_Dma2d_TransferError;
350
351 Dma2dHandle.Instance = DMA2D;
352
353 /* DMA2D Initialisation */
354 if(HAL_DMA2D_Init(&Dma2dHandle) != HAL_OK)
355 GFX_Error_Handler();
356
357 if(HAL_DMA2D_ConfigLayer(&Dma2dHandle, 1) != HAL_OK)
358 GFX_Error_Handler();
359
360 DMA2D_at_work = 255;
361 }
362 void GFX_init1_no_DMA(uint32_t * pDestinationOut, uint8_t blockFrames)
363 {
364 frame[0].StartAddress = FBGlobalStart;
365 GFX_clear_frame_immediately(frame[0].StartAddress);
366 frame[0].status = CLEAR;
367 frame[0].caller = 0;
368
369 for(int i=1;i<MAXFRAMES;i++)
370 {
371 frame[i].StartAddress = frame[i-1].StartAddress + FBOffsetEachIndex;
372 GFX_clear_frame_immediately(frame[i].StartAddress);
373 frame[i].status = CLEAR;
374 frame[i].caller = 0;
375 }
376
377 for(int i=0;i<blockFrames;i++)
378 {
379 frame[i].status = BLOCKED;
380 frame[i].caller = 1;
381 }
382
383 pInvisibleFrame = getFrame(2);
384 *pDestinationOut = pInvisibleFrame;
385
386 GFX_build_logo_frame();
387 GFX_build_hw_background_frame();
388 }
389
390
391 void GFX_init2_DMA(void)
392 {
393 /* Register to memory mode with ARGB8888 as color Mode */
394 Dma2dHandle.Init.Mode = DMA2D_R2M;
395 Dma2dHandle.Init.ColorMode = DMA2D_ARGB4444;//to fake AL88, before: DMA2D_ARGB8888;
396 Dma2dHandle.Init.OutputOffset = 0;
397
398 /* DMA2D Callbacks Configuration */
399 Dma2dHandle.XferCpltCallback = GFX_Dma2d_TransferComplete;
400 Dma2dHandle.XferErrorCallback = GFX_Dma2d_TransferError;
401
402 Dma2dHandle.Instance = DMA2D;
403
404 /* DMA2D Initialisation */
405 if(HAL_DMA2D_Init(&Dma2dHandle) != HAL_OK)
406 GFX_Error_Handler();
407
408 if(HAL_DMA2D_ConfigLayer(&Dma2dHandle, 1) != HAL_OK)
409 GFX_Error_Handler();
410
411 DMA2D_at_work = 255;
412 }
413
414
415 void GFX_SetFrameTop(uint32_t pDestination)
416 {
417 uint8_t NextTopWork = FrameHandler.NextTopWrite + 1;
418
419 if(NextTopWork == RING_BUF_SIZE)
420 {
421 NextTopWork = 0;
422 }
423
424 if(pDestination == 0)
425 pDestination = pInvisibleFrame;
426
427 FrameHandler.pNextTopBuffer[NextTopWork] = pDestination;
428 FrameHandler.NextTopWrite = NextTopWork;
429 }
430
431
432 void GFX_SetFrameBottom(uint32_t pDestination, uint32_t x0, uint32_t y0, uint32_t width, uint32_t height)
433 {
434 uint8_t NextBottomWork = FrameHandler.NextBottomWrite + 1;
435
436 if(NextBottomWork == RING_BUF_SIZE)
437 {
438 NextBottomWork = 0;
439 }
440
441 if(pDestination == 0)
442 pDestination = pInvisibleFrame;
443
444 FrameHandler.nextBottom[NextBottomWork].pBuffer = pDestination;
445 FrameHandler.nextBottom[NextBottomWork].height = height;
446 FrameHandler.nextBottom[NextBottomWork].width = width;
447 FrameHandler.nextBottom[NextBottomWork].leftStart = x0;
448 FrameHandler.nextBottom[NextBottomWork].bottomStart = y0;
449 FrameHandler.NextBottomWrite = NextBottomWork;
450 }
451
452
453 void GFX_SetFramesTopBottom(uint32_t pTop, uint32_t pBottom, uint32_t heightBottom)
454 {
455 GFX_SetFrameTop(pTop);
456 GFX_SetFrameBottom(pBottom, 0, 0, 800, heightBottom);
457 }
458
459
460 static uint32_t GFX_get_pActualFrameTop(void)
461 {
462 return FrameHandler.pActualTopBuffer;
463 }
464
465
466 static uint32_t GFX_get_pActualFrameBottom(void)
467 {
468 return FrameHandler.actualBottom.pBuffer;
469 }
470
471
472 void GFX_start_VSYNC_IRQ(void)
473 {
474 GPIO_InitTypeDef GPIO_InitStructure;
475
476 GPIO_InitStructure.Mode = GPIO_MODE_IT_FALLING;
477 GPIO_InitStructure.Pull = GPIO_NOPULL;
478 GPIO_InitStructure.Speed = GPIO_SPEED_LOW;
479 GPIO_InitStructure.Pin = VSYNC_IRQ_PIN;
480 HAL_GPIO_Init(VSYNC_IRQ_GPIO_PORT, &GPIO_InitStructure);
481
482 HAL_NVIC_SetPriority(VSYNC_IRQ_EXTI_IRQn, 1, 0);
483 HAL_NVIC_EnableIRQ(VSYNC_IRQ_EXTI_IRQn);
484 }
485
486
487 void GFX_change_LTDC(void)
488 {
489 uint32_t pTop = 0;
490 uint32_t pBot = 0;
491 uint32_t heightBot = 0;
492 uint32_t widthBot = 0;
493 uint32_t leftStartBot = 0;
494 uint32_t bottomStartBot = 0;
495 uint8_t change_position = 0;
496 uint8_t change_size = 0;
497 uint8_t nextBottomBackup = FrameHandler.NextBottomRead; /* Restore entry value in case off logo handling */
498
499 // Top Frame
500 if(FrameHandler.NextTopRead != FrameHandler.NextTopWrite)
501 {
502 FrameHandler.NextTopRead++;
503 if(FrameHandler.NextTopRead == RING_BUF_SIZE)
504 {
505 FrameHandler.NextTopRead = 0;
506 }
507 }
508 pTop = FrameHandler.pNextTopBuffer[FrameHandler.NextTopRead];
509
510 if(FrameHandler.pActualTopBuffer != pTop)
511 {
512 HAL_LTDC_SetAddress(&LtdcHandle, pTop, 1);
513 FrameHandler.pActualTopBuffer = pTop;
514 }
515
516 // Bottom Frame
517 if(FrameHandler.NextBottomRead != FrameHandler.NextBottomWrite)
518 {
519 FrameHandler.NextBottomRead++;
520 if(FrameHandler.NextBottomRead == RING_BUF_SIZE)
521 {
522 FrameHandler.NextBottomRead = 0;
523 }
524 }
525 if(logoStatus != LOGOOFF)
526 {
527 switch(logoStatus)
528 {
529 case LOGOSTART:
530 HAL_LTDC_SetAlpha(&LtdcHandle, 0, 1);
531 HAL_LTDC_SetAlpha(&LtdcHandle, 34, 0);
532 HAL_LTDC_ConfigCLUT(&LtdcHandle, (uint32_t *)indexHWcolor, indexHWcolorSIZE, 0);
533 HAL_LTDC_SetAddress(&LtdcHandle, pLogoFrame, 0);
534 HAL_LTDC_SetWindowSize(&LtdcHandle, 480, 800, 0);
535 HAL_LTDC_SetWindowPosition(&LtdcHandle, 0, 0, 0);
536 logoStatus = 2;
537 FrameHandler.NextBottomRead = nextBottomBackup;
538 break;
539
540 case LOGOSTOP:
541 HAL_LTDC_SetAlpha(&LtdcHandle, 255, 1);
542 HAL_LTDC_ConfigCLUT(&LtdcHandle, ColorLUT, CLUT_END, 0);
543
544 pBot = FrameHandler.nextBottom[FrameHandler.NextBottomRead].pBuffer;
545 heightBot = FrameHandler.nextBottom[FrameHandler.NextBottomRead].height;
546 widthBot = FrameHandler.nextBottom[FrameHandler.NextBottomRead].width;
547 leftStartBot = FrameHandler.nextBottom[FrameHandler.NextBottomRead].leftStart;
548 bottomStartBot = FrameHandler.nextBottom[FrameHandler.NextBottomRead].bottomStart;
549 HAL_LTDC_SetWindowSize(&LtdcHandle, heightBot, widthBot, 0);
550 HAL_LTDC_SetWindowPosition(&LtdcHandle, bottomStartBot, leftStartBot, 0);
551 HAL_LTDC_SetAddress(&LtdcHandle, pBot, 0);
552 HAL_LTDC_SetAlpha(&LtdcHandle, 255, 0);
553 FrameHandler.actualBottom.height = heightBot;
554 FrameHandler.actualBottom.width = widthBot;
555 FrameHandler.actualBottom.leftStart = leftStartBot;
556 FrameHandler.actualBottom.bottomStart = bottomStartBot;
557 FrameHandler.actualBottom.pBuffer = pBot;
558
559 logoStatus = LOGOOFF;
560 if(backgroundHwStatus == 2)
561 {
562 backgroundHwStatus = LOGOSTART;
563 }
564 break;
565 default:
566 if(logoStatus < 35)
567 {
568 logoStatus++;
569 if(logoStatus <= 15)
570 HAL_LTDC_SetAlpha(&LtdcHandle, 17*logoStatus, 0);
571 }
572 else
573 {
574 logoStatus +=20;
575 HAL_LTDC_SetAlpha(&LtdcHandle, logoStatus-55, 1);
576 HAL_LTDC_SetAlpha(&LtdcHandle, 255+55-logoStatus, 0);
577 }
578 FrameHandler.NextBottomRead = nextBottomBackup;
579 break;
580 }
581 return;
582 }
583 else if (backgroundHwStatus != LOGOOFF)
584 {
585
586 switch(backgroundHwStatus)
587 {
588 case LOGOSTART:
589 HAL_LTDC_ConfigCLUT(&LtdcHandle, (uint32_t *)indexHWcolor, indexHWcolorSIZE, 0);
590 HAL_LTDC_SetAddress(&LtdcHandle, pBackgroundHwFrame, 0);
591 HAL_LTDC_SetWindowSize(&LtdcHandle, 480, 800, 0);
592 HAL_LTDC_SetWindowPosition(&LtdcHandle, 0, 0, 0);
593 backgroundHwStatus = 2;
594 FrameHandler.NextBottomRead = nextBottomBackup;
595 break;
596
597 case LOGOSTOP:
598 HAL_LTDC_ConfigCLUT(&LtdcHandle, ColorLUT, CLUT_END, 0);
599 pBot = FrameHandler.nextBottom[FrameHandler.NextBottomRead].pBuffer;
600 heightBot = FrameHandler.nextBottom[FrameHandler.NextBottomRead].height;
601 widthBot = FrameHandler.nextBottom[FrameHandler.NextBottomRead].width;
602 leftStartBot = FrameHandler.nextBottom[FrameHandler.NextBottomRead].leftStart;
603 bottomStartBot = FrameHandler.nextBottom[FrameHandler.NextBottomRead].bottomStart;
604 HAL_LTDC_SetWindowSize(&LtdcHandle, heightBot, widthBot, 0);
605 HAL_LTDC_SetWindowPosition(&LtdcHandle, bottomStartBot, leftStartBot, 0);
606 HAL_LTDC_SetAddress(&LtdcHandle, pBot, 0);
607 HAL_LTDC_SetAlpha(&LtdcHandle, 255, 0);
608 FrameHandler.actualBottom.height = heightBot;
609 FrameHandler.actualBottom.width = widthBot;
610 FrameHandler.actualBottom.leftStart = leftStartBot;
611 FrameHandler.actualBottom.bottomStart = bottomStartBot;
612 FrameHandler.actualBottom.pBuffer = pBot;
613 backgroundHwStatus = LOGOOFF;
614 break;
615
616 default:
617 FrameHandler.NextBottomRead = nextBottomBackup;
618 break;
619 }
620
621 return;
622 }
623 else
624 {
625 pBot = FrameHandler.nextBottom[FrameHandler.NextBottomRead].pBuffer;
626 heightBot = FrameHandler.nextBottom[FrameHandler.NextBottomRead].height;
627 widthBot = FrameHandler.nextBottom[FrameHandler.NextBottomRead].width;
628 leftStartBot = FrameHandler.nextBottom[FrameHandler.NextBottomRead].leftStart;
629 bottomStartBot = FrameHandler.nextBottom[FrameHandler.NextBottomRead].bottomStart;
630
631 if(FrameHandler.actualBottom.pBuffer == pBot)
632 pBot = 0;
633
634 if((FrameHandler.actualBottom.height != heightBot) || (FrameHandler.actualBottom.width != widthBot))
635 change_size = 1;
636
637 if((FrameHandler.actualBottom.leftStart != leftStartBot) || (FrameHandler.actualBottom.bottomStart != bottomStartBot))
638 change_position = 1;
639
640 if(pBot || change_size || change_position)
641 {
642 if(heightBot && widthBot)
643 HAL_LTDC_SetWindowSize(&LtdcHandle, heightBot, widthBot, 0);
644
645 if(change_position || leftStartBot || bottomStartBot)
646 HAL_LTDC_SetWindowPosition(&LtdcHandle, bottomStartBot, leftStartBot, 0);
647
648 if(pBot)
649 HAL_LTDC_SetAddress(&LtdcHandle, pBot, 0);
650
651 if(change_size)
652 {
653 FrameHandler.actualBottom.height = heightBot;
654 FrameHandler.actualBottom.width = widthBot;
655 }
656 if(change_position)
657 {
658 FrameHandler.actualBottom.leftStart = leftStartBot;
659 FrameHandler.actualBottom.bottomStart = bottomStartBot;
660 }
661 if(pBot)
662 FrameHandler.actualBottom.pBuffer = pBot;
663 }
664 }
665 }
666
667 uint8_t GFX_is_colorschemeDiveStandard(void)
668 {
669 return (ColorLUT[CLUT_Font027] == 0x00FFFFFF);
670 }
671
672
673 void change_CLUT_entry(uint8_t entryToChange, uint8_t entryUsedForChange)
674 {
675 /* bug fix
676 static uint8_t counter = 0;
677
678 if(entryToChange == 0x1C)
679 counter++;
680 */
681 ColorLUT[entryToChange] = ColorLUT[entryUsedForChange];
682 HAL_LTDC_ConfigCLUT(&LtdcHandle, ColorLUT, CLUT_END, 1);
683 if(logoStatus == LOGOOFF)
684 HAL_LTDC_ConfigCLUT(&LtdcHandle, ColorLUT, CLUT_END, 0);
685 }
686
687
688 void GFX_use_colorscheme(uint8_t colorscheme)
689 {
690 uint8_t ColorSchemeStart;
691
692 if(colorscheme > 3)
693 colorscheme = 0;
694
695 ColorSchemeStart = CLUT_Colorscheme0 + (8 * colorscheme);
696 for(int i=1; i<8; i++)
697 {
698 ColorLUT[CLUT_Font027 + i] = ColorLUT[ColorSchemeStart + i];
699 }
700 change_CLUT_entry(CLUT_Font027, ColorSchemeStart);
701 }
702
703
704 void GFX_VGA_transform(uint32_t pSource, uint32_t pDestination)
705 {
706 int h, v;
707 uint32_t offsetSource, offsetSourceStartOfLine;
708
709 offsetSourceStartOfLine = 480 + 480 - 2;
710 for(v=0;v<480;v++)
711 {
712 offsetSource = offsetSourceStartOfLine;
713 for(h=0;h<640;h++)
714 {
715 *(__IO uint8_t*)pDestination = *(uint8_t*)(pSource + offsetSource);
716 pDestination++;
717 offsetSource += 1;
718 *(__IO uint8_t*)pDestination = *(uint8_t*)(pSource + offsetSource);
719 pDestination++;
720 offsetSource += 480 + 479;
721 }
722 offsetSourceStartOfLine -= 2;
723 }
724 }
725
726
727 static void GFX_clear_frame_immediately(uint32_t pDestination)
728 {
729 uint32_t i;
730 uint32_t* pfill = (uint32_t*) pDestination;
731
732
733 for(i = 200*480; i > 0; i--)
734 {
735 *pfill++ = 0;
736 *pfill++ = 0;
737 }
738 }
739
740
741 void GFX_clear_window_immediately(GFX_DrawCfgWindow* hgfx)
742 {
743 uint32_t pDestination, i, j;
744 uint16_t left, width, bottom, height, nextlineStep;
745
746 pDestination = (uint32_t)hgfx->Image->FBStartAdress;
747
748 left = hgfx->WindowX0;
749 width = 1 + hgfx->WindowX1 - left;
750 bottom = hgfx->WindowY0;
751 height = 1 + hgfx->WindowY1 - bottom;
752 nextlineStep = hgfx->Image->ImageHeight - height;
753 nextlineStep *= 2;
754
755 pDestination += 2 * bottom;
756 pDestination += 2 * hgfx->Image->ImageHeight * left;
757
758 for(j = width; j > 0; j--)
759 {
760 for(i = height; i > 0; i--)
761 {
762 *(__IO uint16_t*)pDestination = 0;
763 pDestination += 2;
764 }
765 pDestination += nextlineStep;
766 }
767 }
768
769
770 static void GFX_clear_frame_dma2d(uint8_t frameId)
771 {
772 if(frameId >= MAXFRAMES)
773 return;
774
775 DMA2D_at_work = frameId;
776
777 if (HAL_DMA2D_Start_IT(&Dma2dHandle, 0x0000000000, frame[frameId].StartAddress, 480, 800) != HAL_OK)
778 GFX_Error_Handler();
779 }
780
781
782 void GFX_fill_buffer(uint32_t pDestination, uint8_t alpha, uint8_t color)
783 {
784
785 union al88_u
786 {
787 uint8_t al8[2];
788 uint16_t al88;
789 };
790 union al88_u colorcombination;
791 uint32_t i;
792 uint32_t* pfill = (uint32_t*) pDestination;
793 uint32_t fillpattern;
794
795 colorcombination.al8[0] = color;
796 colorcombination.al8[1] = alpha;
797
798 fillpattern = (colorcombination.al88 << 16) | colorcombination.al88;
799 for(i = 800*480/2; i > 0; i--)
800 {
801 *pfill++ = fillpattern;
802 }
803 }
804
805 static void GFX_draw_image_color(GFX_DrawCfgScreen *hgfx, SWindowGimpStyle window, const tImage *image)
806 {
807 uint16_t* pDestination;
808
809 uint32_t j;
810 point_t start, stop;
811
812 start.x = window.left;
813 start.y = (hgfx->ImageHeight - image->height - window.top);
814 stop.y = start.y + image->height;
815 stop.x = start.x + image->width;
816 j = 0;
817
818 for(int xx = start.x; xx < stop.x; xx++)
819 {
820 pDestination = (uint16_t*)hgfx->FBStartAdress;
821 pDestination += xx * hgfx->ImageHeight;
822 pDestination += start.y;
823 for(int yy = start.y; yy < stop.y; yy++)
824 {
825 *(__IO uint16_t*)pDestination++ = 0xFF << 8 | image->data[j++];
826 }
827 }
828 }
829
830
831 /* this is NOT fast nor optimized */
832 static void GFX_draw_pixel(GFX_DrawCfgScreen *hgfx, int16_t x, int16_t y, uint8_t color)
833 {
834 uint16_t* pDestination;
835
836 pDestination = (uint16_t*)hgfx->FBStartAdress;
837 pDestination += x * hgfx->ImageHeight;
838 pDestination += y;
839
840 *(__IO uint16_t*)pDestination = 0xFF << 8 | color;
841 }
842
843 /* this is NOT fast nor optimized */
844 void GFX_draw_circle(GFX_DrawCfgScreen *hgfx, point_t center, uint8_t radius, int8_t color)
845 {
846 int x, y;
847 int l;
848 int r2, y2;
849 int y2_new;
850 int ty;
851
852 /* cos pi/4 = 185363 / 2^18 (approx) */
853 l = (radius * 185363) >> 18;
854
855 /* hw */
856 l += 1;
857
858 /* At x=0, y=radius */
859 y = radius;
860
861 r2 = y2 = y * y;
862 ty = (2 * y) - 1;
863 y2_new = r2 + 3;
864
865 for (x = 0; x <= l; x++) {
866 y2_new -= (2 * x) - 3;
867
868 if ((y2 - y2_new) >= ty) {
869 y2 -= ty;
870 y -= 1;
871 ty -= 2;
872 }
873
874 GFX_draw_pixel (hgfx, x + center.x, y + center.y, color);
875 GFX_draw_pixel (hgfx, x + center.x, -y + center.y, color);
876 GFX_draw_pixel (hgfx, -x + center.x, y + center.y, color);
877 GFX_draw_pixel (hgfx, -x + center.x, -y + center.y, color);
878
879 GFX_draw_pixel (hgfx, y + center.x, x + center.y, color);
880 GFX_draw_pixel (hgfx, y + center.x, -x + center.y, color);
881 GFX_draw_pixel (hgfx, -y + center.x, x + center.y, color);
882 GFX_draw_pixel (hgfx, -y + center.x, -x + center.y, color);
883 }
884 }
885
886
887 void GFX_draw_colorline(GFX_DrawCfgScreen *hgfx, point_t start, point_t stop, uint8_t color)
888 {
889 uint32_t pDestination;
890 uint32_t j;
891 uint32_t temp;
892
893 if(start.x == stop.x)
894 {
895 if(stop.y < start.y)
896 {
897 temp = stop.y;
898 stop.y = start.y;
899 start.y = temp;
900 }
901 pDestination = (uint32_t)hgfx->FBStartAdress;
902 pDestination += start.x * hgfx->ImageHeight * 2;
903 pDestination += start.y * 2;
904 for (j = stop.y - start.y; j > 0; j--)
905 {
906 *(__IO uint8_t*)pDestination = color;
907 pDestination += 1;
908 *(__IO uint8_t*)pDestination = 0xFF;
909 pDestination += 1;
910 }
911 }
912 else
913 if(start.y == stop.y)
914 {
915 if(stop.x < start.x)
916 {
917 temp = stop.x;
918 stop.x = start.x;
919 start.x = temp;
920 }
921 pDestination = (uint32_t)hgfx->FBStartAdress;
922 pDestination += start.x * hgfx->ImageHeight * 2;
923 pDestination += start.y * 2;
924 for (j = stop.x - start.x; j > 0; j--)
925 {
926 *(__IO uint8_t*)pDestination = color;
927 pDestination += 1;
928 *(__IO uint8_t*)pDestination = 0xFF;
929 pDestination -= 1;
930 pDestination += hgfx->ImageHeight * 2;
931 }
932 }
933 else // diagonal Bresenham's_line_algorithm
934 {
935 int x0 = start.x;
936 int y0 = start.y;
937 int x1 = stop.x;
938 int y1 = stop.y;
939 int dx = abs(x1-x0), sx = x0<x1 ? 1 : -1;
940 int dy = abs(y1-y0), sy = y0<y1 ? 1 : -1;
941 int err = (dx>dy ? dx : -dy)/2, e2;
942
943 for(;;)
944 {
945 pDestination = (uint32_t)hgfx->FBStartAdress;
946 pDestination += ((x0 * hgfx->ImageHeight) + y0) * 2;
947 *(__IO uint8_t*)pDestination = color;
948 pDestination += 1;
949 *(__IO uint8_t*)pDestination = 0xFF;
950 if (x0==x1 && y0==y1) break;
951 e2 = err;
952 if (e2 >-dx) { err -= dy; x0 += sx; }
953 if (e2 < dy) { err += dx; y0 += sy; }
954 }
955 }
956 }
957
958 // ===============================================================================
959 // GFX_graph_print
960 /// @brief Print all those nice curves, especially in logbook und miniLiveLogGraph
961 /// @version 0.0.2 hw 160519
962 ///
963 /// 151022 hw -bug fix
964 /// - die aktuelle Version macht keine Linien mehr �ber die gesamte Bildschirmh�he.
965 /// - daf�r sind L�cher in der Kurve (z.B. Temperaturgraph Tauchgang Matthias 17.10.15 15:19)
966 ///
967 /// more details about range can be found in show_logbook_logbook_show_log_page2() - temperature graph
968 ///
969 /// @param window: top and bottom is only the range used by the data of the graph, not the entire screen / scale
970 /// @param drawVeilUntil: ist auff�llen des Bereichs unter der Kurve mit etwas hellerer Farbe
971 /// @param Xdivide: wird bisher nichr benutzt.
972 // ===============================================================================
973
974
975 void GFX_graph_print(GFX_DrawCfgScreen *hgfx, const SWindowGimpStyle *window, const 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)
976 {
977 uint16_t* pDestination_tmp;
978 uint16_t* pDestination_start;
979 uint16_t* pDestination_end;
980 uint16_t* pDestination_zero_veil;
981
982 uint32_t max = 0;
983 int windowheight = -1;
984 int windowwidth = -1;
985 int i = -1;
986 int w1 = -1;
987 int w2 = -1;
988
989 uint32_t h_ulong = 0;
990 uint32_t h_ulong_old = 0;
991 _Bool invert = 0;
992
993 uint16_t dataDelta = 0;
994 uint16_t dataDeltaHalve = 0;
995 uint16_t dataTemp = 0;
996
997 uint8_t colorDataTemp;
998 uint8_t colormask = 0;
999
1000 pDestination_zero_veil = 0;
1001
1002 if(dataMin > dataMax)
1003 {
1004 uint16_t dataFlip;
1005 dataFlip = dataMin;
1006 dataMin = dataMax;
1007 dataMax = dataFlip;
1008 invert = 1;
1009 }
1010 else
1011 invert = 0;
1012
1013 colormask = color;
1014
1015 if(window->bottom > 479)
1016 return;
1017 if(window->top > 479)
1018 return;
1019 if(window->right > 799)
1020 return;
1021 if(window->left > 799)
1022 return;
1023 if(window->bottom < 0)
1024 return;
1025 if(window->top < 0)
1026 return;
1027 if(window->right < 0)
1028 return;
1029 if(window->left < 0)
1030 return;
1031 if(window->bottom <= window->top)
1032 return;
1033 if(window->right <= window->left)
1034 return;
1035
1036 windowheight = window->bottom - window->top ;
1037 windowwidth = window->right - window->left;
1038 w1 = 0;
1039 w2 = 0;
1040 if(dataMax == dataMin)
1041 dataMax++;
1042 dataDelta = (unsigned long)(dataMax - dataMin);
1043 dataDeltaHalve = dataDelta / 2;
1044 while((w1 <= windowwidth) && (w2 < datalength))
1045 {
1046 int tmp = (10 * w1 * (long)datalength)/windowwidth;
1047 w2 = tmp/10;
1048 int rest = tmp - w2*10;
1049 if(rest >= 5)
1050 w2++;
1051
1052 if((datalength - 1) < w2)
1053 w2 = datalength-1;
1054
1055 if(colour_data != NULL)
1056 {
1057 colorDataTemp = colour_data[w2];
1058 colormask = color + colorDataTemp;
1059 }
1060
1061 dataTemp = data[w2];
1062 if(Xdivide > 1)
1063 {
1064 w2++;
1065 for(i=1;i<Xdivide;i++)
1066 {
1067 if(data[w2]>dataTemp)
1068 dataTemp = data[w2];
1069 w2++;
1070 }
1071 }
1072
1073 if(dataTemp > dataMin)
1074 dataTemp -= dataMin;
1075 else
1076 dataTemp = 0;
1077
1078 if(invert)
1079 {
1080 if(dataTemp < dataDelta)
1081 dataTemp = dataDelta - dataTemp;
1082 else
1083 dataTemp = 0;
1084 }
1085
1086 h_ulong = (unsigned long)dataTemp;
1087 h_ulong *= windowheight;
1088 h_ulong += dataDeltaHalve;
1089 h_ulong /= dataDelta;
1090
1091 if(h_ulong > (window->bottom - window->top))
1092 h_ulong = (window->bottom - window->top);
1093
1094 if(drawVeilUntil > 0)
1095 {
1096 pDestination_zero_veil = (uint16_t*)hgfx->FBStartAdress;
1097 pDestination_zero_veil += ((479 - (drawVeilUntil - 2) ) + ((w1 + window->left) * hgfx->ImageHeight) );
1098 }
1099 else if(drawVeilUntil < 0 )
1100 {
1101 pDestination_zero_veil = (uint16_t*)hgfx->FBStartAdress;
1102 pDestination_zero_veil += ((479 + (drawVeilUntil)) + ((w1 + window->left) * hgfx->ImageHeight) );
1103 }
1104
1105 if(h_ulong + window->top > max)
1106 {
1107 max = h_ulong + window->top;
1108 }
1109
1110 // hw 160519 wof�r ist das? Damit funktioniert Temperatur 25,5�C nicht!
1111 // if((dataMax == 255) || (data[w2] != 255))
1112 // {
1113 //output_content[pointer] = colormask;
1114 //output_mask[pointer] = true;
1115 if(dataTemp != 0xFFFF) /* do not draw invalid data pixels */
1116 {
1117 if(w1 > 0)
1118 {
1119 pDestination_start = (uint16_t*)hgfx->FBStartAdress;
1120 pDestination_start += (((479 - (window->top)) + ((w1 + window->left) * hgfx->ImageHeight)));
1121 pDestination_end = pDestination_start;
1122
1123 if(h_ulong >= h_ulong_old)
1124 {
1125 pDestination_start -= h_ulong_old;
1126 pDestination_end -= h_ulong;
1127
1128 }
1129 else
1130 {
1131 if(h_ulong < h_ulong_old)
1132 {
1133 pDestination_start += h_ulong_old;
1134 pDestination_end += h_ulong;
1135 }
1136 else
1137 {
1138 pDestination_start += h_ulong;
1139 pDestination_end += h_ulong_old;
1140 }
1141 }
1142
1143
1144 // deco stops
1145 if(drawVeilUntil < 0)
1146 {
1147 pDestination_tmp = pDestination_end;
1148 while(pDestination_tmp <= pDestination_zero_veil)
1149 {
1150 *(__IO uint16_t*)pDestination_tmp = (0x80 << 8) | colormask;
1151 pDestination_tmp++;
1152 }
1153 }
1154 else
1155 {
1156 // regular graph with veil underneath if requested
1157 // von oben nach unten
1158 // von grossen pDestination Werten zu kleinen pDestination Werten
1159 {
1160 pDestination_tmp = pDestination_start;
1161 while(pDestination_tmp >= pDestination_end)
1162 {
1163 *(__IO uint16_t*)pDestination_tmp = (0xFF << 8) | colormask ;
1164 pDestination_tmp--;
1165 }
1166 }
1167
1168 while((drawVeilUntil > 0) && (pDestination_tmp >= pDestination_zero_veil))
1169 {
1170 *(__IO uint16_t*)pDestination_tmp = (0x20 << 8) | colormask ;
1171 pDestination_tmp--;
1172 }
1173 }
1174 }
1175 h_ulong_old = h_ulong;
1176 }
1177 w1++;
1178 w2++;
1179 }
1180 }
1181
1182
1183 void GFX_draw_header(GFX_DrawCfgScreen *hgfx, uint8_t colorId)
1184 {
1185 uint32_t pDestination;
1186 point_t start, stop, now;
1187 uint8_t alpha;
1188
1189 /* display coordinate system */
1190 start.y = 400;
1191 stop.y = 479;
1192
1193 start.x = 0;
1194 stop.x = 799;
1195
1196 now.y = start.y;
1197 now.x = start.x;
1198
1199 while (now.x <= stop.x)
1200 {
1201 now.y = start.y;
1202 pDestination = (uint32_t)hgfx->FBStartAdress;
1203 pDestination += now.x * hgfx->ImageHeight * 2;
1204 pDestination += now.y * 2;
1205 now.x += 1;
1206
1207 alpha = 27;
1208 while(alpha < 246)
1209 {
1210 alpha += 9;
1211 *(__IO uint8_t*)pDestination = colorId;
1212 pDestination += 1;
1213 *(__IO uint8_t*)pDestination = alpha;
1214 pDestination += 1;
1215 now.y += 1;
1216 }
1217
1218 while(now.y <= stop.y)
1219 {
1220 *(__IO uint8_t*)pDestination = colorId;
1221 pDestination += 1;
1222 *(__IO uint8_t*)pDestination = 0xFF;
1223 pDestination += 1;
1224 now.y += 1;
1225 }
1226 }
1227 }
1228
1229 void GFX_draw_box2(GFX_DrawCfgScreen *hgfx, point_t start, point_t stop, uint8_t color, uint8_t roundCorners)
1230 {
1231 point_t point2, point4;
1232
1233 if(roundCorners)
1234 {
1235 point2.x = stop.x - start.x;
1236 point2.y = stop.y - start.y;
1237 GFX_draw_box(hgfx,start,point2,1,color);
1238 }
1239 else
1240 {
1241 point2.x = stop.x;
1242 point2.y = start.y;
1243
1244 point4.x = start.x;
1245 point4.y = stop.y;
1246
1247 GFX_draw_line(hgfx,start,point2,color);
1248 GFX_draw_line(hgfx,point2,stop,color);
1249 GFX_draw_line(hgfx,stop,point4,color);
1250 GFX_draw_line(hgfx,point4,start,color);
1251 }
1252 }
1253
1254 void GFX_draw_box(GFX_DrawCfgScreen *hgfx, point_t LeftLow, point_t WidthHeight, uint8_t Style, uint8_t color)
1255 {
1256 uint16_t* pDestination;
1257 uint16_t* pStart;
1258 uint32_t j;
1259 uint32_t lineWidth, lineHeight;
1260 int x, y;
1261 uint8_t intensity;
1262 int stepdir;
1263
1264 typedef struct {
1265 int x;
1266 int y;
1267 uint8_t intensity;
1268 } corner_t;
1269 const corner_t corner[16] = {
1270 {3,3,255}, // nur einmal
1271 {9,0,242},
1272 {8,0,194},
1273 {7,0,115},
1274 {6,0,36},
1275 {9,1,33},
1276 {8,1,84},
1277 {7,1,161},
1278 {6,1,255},
1279 {5,1,242},
1280 {4,1,36},
1281 {6,2,33},
1282 {5,2,84},
1283 {4,2,255},
1284 {3,2,84},
1285 {4,3,110}
1286 };
1287
1288 lineWidth = WidthHeight.x;
1289 lineHeight = WidthHeight.y;
1290 pStart = (uint16_t*)hgfx->FBStartAdress;
1291
1292 pStart += LeftLow.x * hgfx->ImageHeight;
1293 pStart += LeftLow.y;
1294 stepdir = 1;
1295
1296 // Untere Linie
1297 pDestination = pStart;
1298 if(Style)
1299 {
1300 pDestination += stepdir * 10 * hgfx->ImageHeight;
1301 lineWidth -= 18;
1302 }
1303 for (j = lineWidth; j > 0; j--)
1304 {
1305
1306 *(__IO uint16_t*)pDestination = 0xFF00 + color;
1307 pDestination += stepdir * hgfx->ImageHeight;
1308 }
1309
1310 // Obere Linie
1311
1312 pDestination = pStart + stepdir * WidthHeight.y;
1313 if(Style)
1314 {
1315 pDestination += stepdir * 10 * hgfx->ImageHeight;
1316 }
1317
1318 for (j = lineWidth; j > 0; j--)
1319 {
1320 *(__IO uint16_t*)pDestination = 0xFF00 + color;
1321 pDestination += stepdir * hgfx->ImageHeight;
1322 }
1323
1324 // Linke Linie
1325 pDestination = pStart;
1326
1327 if(Style)
1328 {
1329 pDestination += stepdir * 10;
1330 lineHeight -= 18;
1331 }
1332
1333 for (j = lineHeight; j > 0; j--)
1334 {
1335 *(__IO uint16_t*)pDestination = 0xFF00 + color;
1336 pDestination += stepdir;
1337 }
1338
1339
1340 // Rechte Linie
1341
1342 pDestination = pStart + stepdir * WidthHeight.x * hgfx->ImageHeight;
1343 if(Style)
1344 {
1345 pDestination += stepdir * 10;
1346 }
1347
1348 for (j = lineHeight; j > 0; j--)
1349 {
1350 *(__IO uint16_t*)pDestination = 0xFF00 + color;
1351 pDestination += stepdir;
1352 }
1353
1354
1355 // Ecken wenn notwendig == Style
1356 if(Style)
1357 {
1358 // links unten
1359 pDestination = pStart;
1360 x = corner[0].x;
1361 y = corner[0].y;
1362 intensity = corner[0].intensity;
1363
1364 *(__IO uint16_t*)(pDestination + stepdir * (y + (x * hgfx->ImageHeight))) = (intensity << 8) + color;
1365
1366 for(j = 15; j > 0; j--)
1367 {
1368 x = corner[j].x;
1369 y = corner[j].y;
1370 intensity = corner[j].intensity;
1371 *(__IO uint16_t*)(pDestination + stepdir * (y + (x * hgfx->ImageHeight))) = (intensity << 8) + color;
1372 *(__IO uint16_t*)(pDestination + stepdir * (x + (y * hgfx->ImageHeight))) = (intensity << 8) + color;
1373 }
1374 // links oben
1375 pDestination = pStart + stepdir * WidthHeight.y;
1376 x = corner[0].x;
1377 y = corner[0].y;
1378 intensity = corner[0].intensity;
1379 *(__IO uint16_t*)(pDestination + stepdir * (-y + (x * hgfx->ImageHeight))) = (intensity << 8) + color;
1380
1381 for(j = 15; j > 0; j--)
1382 {
1383 x = corner[j].x;
1384 y = corner[j].y;
1385 intensity = corner[j].intensity;
1386 *(__IO uint16_t*)(pDestination + stepdir * (-y + (x * hgfx->ImageHeight))) = (intensity << 8) + color;
1387 *(__IO uint16_t*)(pDestination + stepdir * (-x + (y * hgfx->ImageHeight))) = (intensity << 8) + color;
1388 }
1389 // rechts unten
1390 pDestination = pStart + stepdir * WidthHeight.x * hgfx->ImageHeight;
1391 x = corner[0].x;
1392 y = corner[0].y;
1393 intensity = corner[0].intensity;
1394 *(__IO uint16_t*)(pDestination + stepdir * (y - (x * hgfx->ImageHeight))) = (intensity << 8) + color;
1395
1396 for(j = 15; j > 0; j--)
1397 {
1398 x = corner[j].x;
1399 y = corner[j].y;
1400 intensity = corner[j].intensity;
1401 *(__IO uint16_t*)(pDestination + stepdir * (y - (x * hgfx->ImageHeight))) = (intensity << 8) + color;
1402 *(__IO uint16_t*)(pDestination + stepdir * (x - (y * hgfx->ImageHeight))) = (intensity << 8) + color;
1403 }
1404 // rechts oben
1405 pDestination = pStart + stepdir * WidthHeight.y + stepdir * WidthHeight.x * hgfx->ImageHeight;
1406 x = corner[0].x;
1407 y = corner[0].y;
1408 intensity = corner[0].intensity;
1409 *(__IO uint16_t*)(pDestination + stepdir * -1 * (y + (x * hgfx->ImageHeight))) = (intensity << 8) + color;
1410
1411 for(j = 15; j > 0; j--)
1412 {
1413 x = corner[j].x;
1414 y = corner[j].y;
1415 intensity = corner[j].intensity;
1416 *(__IO uint16_t*)(pDestination + stepdir * -1 * (y + (x * hgfx->ImageHeight))) = (intensity << 8) + color;
1417 *(__IO uint16_t*)(pDestination + stepdir * -1 * (x + (y * hgfx->ImageHeight))) = (intensity << 8) + color;
1418 }
1419 }
1420 }
1421
1422
1423 /**
1424 ******************************************************************************
1425 * @brief GFX write label. / Write string with defined color
1426 * @author heinrichs weikamp gmbh
1427 * @version V0.0.1
1428 * @date 07-July-2014
1429 ******************************************************************************
1430 *
1431 * @param hgfx: check gfx_engine.h.
1432 * @param color: 16bit Alpha+CLUT.
1433 * @retval None
1434 */
1435
1436 uint32_t GFX_write_label(const tFont *Font, GFX_DrawCfgWindow* hgfx, const char *pText, uint8_t color)
1437 {
1438 return GFX_write_string_color(Font, hgfx, pText, 0, color);
1439 }
1440
1441
1442 /**
1443 ******************************************************************************
1444 * @brief GFX writeGfx_write_label_varstring. / Write string with all parameters and font color options
1445 heinrichs weikamp gmbh
1446 * @version V0.0.1
1447 * @date 22-April-2014
1448 ******************************************************************************
1449 *
1450 * @param XleftGimpStyle:
1451 * @param XrightGimpStyle:
1452 * @param YtopGimpStyle:
1453 * @param color:
1454 * @param tFont:
1455 * @param text: text to be printed
1456 * @retval None
1457 */
1458
1459 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)
1460 {
1461
1462 GFX_DrawCfgWindow hgfx;
1463
1464 if(XrightGimpStyle > 799)
1465 XrightGimpStyle = 799;
1466 if(XleftGimpStyle >= XrightGimpStyle)
1467 XleftGimpStyle = 0;
1468 if(YtopGimpStyle > 479)
1469 YtopGimpStyle = 479;
1470 hgfx.Image = screenInput;
1471 hgfx.WindowNumberOfTextLines = 1;
1472 hgfx.WindowLineSpacing = 0;
1473 hgfx.WindowTab = 0;
1474
1475 hgfx.WindowX0 = XleftGimpStyle;
1476 hgfx.WindowX1 = XrightGimpStyle;
1477 hgfx.WindowY1 = 479 - YtopGimpStyle;
1478 if(hgfx.WindowY1 < Font->height)
1479 hgfx.WindowY0 = 0;
1480 else
1481 hgfx.WindowY0 = hgfx.WindowY1 - Font->height;
1482 GFX_write_label(Font, &hgfx, text, color);
1483 }
1484
1485 /**
1486 ******************************************************************************
1487 * @brief GFX write string. / Write string with all parameters and font options
1488 * @author heinrichs weikamp gmbh
1489 * @version V0.0.1
1490 * @date 22-April-2014
1491 ******************************************************************************
1492 *
1493 * @param hgfx: check gfx_engine.h.
1494 * @param color: 32bit ARGB8888.
1495 * @retval None
1496 */
1497
1498 uint16_t GFX_return_offset(const tFont *Font, char *pText, uint8_t position)
1499 {
1500 char character;
1501 uint16_t digit, i;
1502 uint8_t found;
1503 uint16_t distance;
1504
1505 if(position == 0)
1506 return 0;
1507
1508 distance = 0;
1509 for(digit = 0; digit < position; digit++)
1510 {
1511 character = pText[digit];
1512 if(character == 0)
1513 return 0;
1514
1515 found = 0;
1516 for(i=0;i<Font->length;i++)
1517 {
1518 if(Font->chars[i].code == character)
1519 {
1520 found = 1;
1521 break;
1522 }
1523 }
1524 if(found)
1525 {
1526 distance += (uint16_t)(Font->chars[i].image->width);
1527 if(Font == &FontT144)
1528 distance += 3;
1529 else
1530 if(Font == &FontT105)
1531 distance += 2;
1532 }
1533 }
1534 return distance;
1535
1536 /* FEHLT:
1537 if(*pText < ' ')
1538 if((*pText) & 0x80)
1539
1540 if(((tFont *)settings.font == &FontT105) && settings.dualFont && ((*pText == '.') || (*pText == ':')))
1541 settings.font = (uint32_t)&FontT54;
1542 */
1543 }
1544
1545 void GFX_clean_line(GFX_DrawCfgWindow* hgfx, uint32_t line_number)
1546 {
1547 uint16_t height;
1548 uint32_t pDestination, i, j;
1549 uint16_t left, width, bottom, nextlineStep;
1550
1551 bottom = hgfx->WindowY0;
1552
1553 if(hgfx->WindowNumberOfTextLines && line_number && (line_number <= hgfx->WindowNumberOfTextLines))
1554 {
1555 bottom += hgfx->WindowLineSpacing * (hgfx->WindowNumberOfTextLines - line_number);
1556 height = hgfx->WindowLineSpacing;
1557 }
1558 else
1559 {
1560 height = 1 + hgfx->WindowY1 - bottom;
1561 }
1562
1563 pDestination = (uint32_t)hgfx->Image->FBStartAdress;
1564
1565 left = hgfx->WindowX0;
1566 width = 1 + hgfx->WindowX1 - left;
1567 nextlineStep = hgfx->Image->ImageHeight - height;
1568 nextlineStep *= 2;
1569 pDestination += 2 * bottom;
1570 pDestination += 2 * hgfx->Image->ImageHeight * left;
1571
1572 for(j = width; j > 0; j--)
1573 {
1574 for(i = height; i > 0; i--)
1575 {
1576 *(__IO uint16_t*)pDestination = 0;
1577 pDestination += 2;
1578 }
1579 pDestination += nextlineStep;
1580 }
1581 }
1582
1583
1584 void GFX_clean_area(GFX_DrawCfgScreen *tMscreen, uint16_t XleftGimpStyle, uint16_t XrightGimpStyle, uint16_t YtopGimpStyle, uint16_t YBottomGimpStyle)
1585 {
1586 uint16_t height;
1587 uint32_t pDestination, i, j;
1588 int32_t left, width, bottom, nextlineStep;
1589
1590 bottom = tMscreen->ImageHeight - YBottomGimpStyle;
1591 height = 1 + YBottomGimpStyle - YtopGimpStyle;
1592
1593 if(bottom < 0)
1594 bottom = 0;
1595 if(height > tMscreen->ImageHeight)
1596 height = tMscreen->ImageHeight;
1597
1598 pDestination = tMscreen->FBStartAdress;
1599
1600 left = XleftGimpStyle;
1601 width = 1 + XrightGimpStyle - left;
1602 if(width < 1)
1603 width = 1;
1604
1605 if(width > tMscreen->ImageWidth)
1606 width = tMscreen->ImageWidth;
1607
1608 nextlineStep = tMscreen->ImageHeight - height;
1609 nextlineStep *= 2;
1610 pDestination += 2 * bottom;
1611 pDestination += 2 * tMscreen->ImageHeight * left;
1612
1613 for(j = width; j > 0; j--)
1614 {
1615 for(i = height; i > 0; i--)
1616 {
1617 *(__IO uint16_t*)pDestination = 0;
1618 pDestination += 2;
1619 }
1620 pDestination += nextlineStep;
1621 }
1622 }
1623
1624
1625 uint32_t GFX_write_string(const tFont *Font, GFX_DrawCfgWindow* hgfx, const char *pText, uint32_t line_number)
1626 {
1627 return GFX_write_string_color(Font, hgfx, pText, line_number, 0);
1628 }
1629
1630 uint32_t GFX_write_string_color(const tFont *Font, GFX_DrawCfgWindow* hgfx, const char *pText, uint32_t line_number, uint8_t color)
1631 {
1632 if(hgfx->Image->FBStartAdress < FBGlobalStart)
1633 return 0;
1634
1635 GFX_CfgWriteString settings;
1636 uint32_t newXdelta;
1637 uint8_t minimal = 0;
1638 // uint32_t try_again;
1639
1640 if(hgfx->WindowNumberOfTextLines && line_number && (line_number <= hgfx->WindowNumberOfTextLines))
1641 {
1642 settings.Ydelta = hgfx->WindowLineSpacing * (hgfx->WindowNumberOfTextLines - line_number);
1643 }
1644 else
1645 {
1646 settings.Ydelta = 0;
1647 }
1648 settings.font = (uint32_t)Font;
1649 settings.Xdelta = 0;
1650 settings.color = color;
1651 settings.invert = 0;
1652 settings.resize = 0;
1653 settings.dualFont = 0;
1654 settings.spaceMode = 0;
1655 settings.singleSpaceWithSizeOfNextChar = 0;
1656 settings.useTinyFont = 0;
1657 settings.TinyFontExtraYdelta = 0;
1658 settings.TinyFont = (uint32_t)Font;
1659 settings.doubleSize = 0;
1660
1661 if((*pText) == TXT_MINIMAL) // for customtext and anything with Sonderzeichen
1662 minimal = 1;
1663 else
1664 minimal = 0;
1665
1666 if(Font == &FontT144)
1667 {
1668 settings.TinyFont = (uint32_t)&FontT84;
1669 settings.Ydelta = 12;
1670 }
1671 else
1672 if(Font == &FontT105)
1673 settings.TinyFont = (uint32_t)&FontT54;
1674 else
1675 if(Font == &FontT54)
1676 {
1677 settings.TinyFont = (uint32_t)&FontT48;
1678 settings.TinyFontExtraYdelta = -9;
1679 }
1680 else
1681 if(Font == &FontT48)
1682 {
1683 settings.TinyFont = (uint32_t)&FontT24;
1684 settings.TinyFontExtraYdelta = 6;
1685 }
1686 else
1687 if(Font == &FontT42)
1688 {
1689 settings.TinyFont = (uint32_t)&FontT24;
1690 settings.TinyFontExtraYdelta = 2;
1691 }
1692
1693 settings.actualFont = (tFont *)settings.font;
1694
1695 while ((*pText != 0) && (settings.Xdelta != 0x0000FFFF))// und fehlend: Abfrage window / image size
1696 {
1697 // try_again = 0;
1698
1699 if((*pText == '\177') && !minimal)
1700 {
1701 if(settings.singleSpaceWithSizeOfNextChar)
1702 {
1703 settings.singleSpaceWithSizeOfNextChar = 0;
1704 pText++;
1705 settings.Xdelta += *pText;
1706 }
1707 else
1708 settings.singleSpaceWithSizeOfNextChar = 1;
1709 }
1710 else
1711 if(*pText < ' ')
1712 {
1713 /* Xdelta -inline- changes */
1714 if((*pText == '\t') && !minimal)
1715 settings.Xdelta = hgfx->WindowTab - hgfx->WindowX0;
1716 else
1717 if(*pText == '\r') // carriage return, no newline
1718 settings.Xdelta = 0;
1719 else
1720 if((*pText == '\001')) // center
1721 settings.Xdelta = GFX_write__Modify_Xdelta__Centered(&settings, hgfx, pText+1);
1722 else
1723 if((*pText == '\002')) // right
1724 settings.Xdelta = GFX_write__Modify_Xdelta__RightAlign(&settings, hgfx, pText+1);
1725 else
1726 if((*pText == '\003') && !minimal) // doubleSize
1727 settings.doubleSize = 1;
1728 else
1729 /* Xdelta -up/down changes */
1730 if((*pText == '\f') && !minimal) // form feed = top align
1731 {
1732 if((hgfx->WindowY1 - hgfx->WindowY0) >= ((tFont *)settings.font)->height)
1733 {
1734 settings.Ydelta = hgfx->WindowY1 - hgfx->WindowY0;
1735 settings.Ydelta -= ((tFont *)settings.font)->height;
1736 }
1737 }
1738 else
1739 if(*pText == '\n') // newline, no carriage return
1740 {
1741 if(hgfx->WindowNumberOfTextLines && (line_number < hgfx->WindowNumberOfTextLines))
1742 {
1743 line_number++;
1744 settings.Ydelta = hgfx->WindowLineSpacing * (hgfx->WindowNumberOfTextLines - line_number);
1745 }
1746 }
1747 else
1748 /* Font style changes */
1749 if(*pText == '\a')
1750 settings.invert = settings.invert ? 0 : 1;
1751 else
1752 if((*pText == '\016') && !minimal)
1753 {
1754 if(settings.dualFont == 0)
1755 settings.dualFont = 1;
1756 else
1757 settings.actualFont = (tFont *)settings.TinyFont;
1758 }
1759 else
1760 if((*pText == '\017') && !minimal)
1761 {
1762 settings.dualFont = 0;
1763 settings.actualFont = (tFont *)settings.font;
1764 }
1765 else
1766 if((*pText >= '\020') && (*pText <= '\032') && !minimal)
1767 settings.color = *pText - '\020';
1768 else
1769 if((*pText == '\034') && !minimal)
1770 settings.spaceMode = 1;
1771 else
1772 if((*pText == '\035') && !minimal)
1773 settings.spaceMode = 0;
1774 }
1775 else
1776 if(((*pText) == TXT_2BYTE) && !minimal)
1777 {
1778 pText++;
1779 settings.Xdelta = GFX_write_substring(&settings, hgfx, (uint8_t)TXT_2BYTE, (int8_t)*pText);
1780 }
1781 else
1782 if(((*pText) & 0x80) && !minimal)
1783 settings.Xdelta = GFX_write_substring(&settings, hgfx, (uint8_t)*pText, 0);
1784 else
1785 if(!settings.invert && (*pText == ' '))
1786 {
1787 if(settings.spaceMode == 0)
1788 settings.Xdelta += ((tFont *)settings.font)->spacesize;
1789 else
1790 settings.Xdelta += ((tFont *)settings.font)->spacesize2Monospaced;
1791 }
1792 else
1793 if((settings.spaceMode == 1) && (*pText == ' '))
1794 settings.Xdelta += ((tFont *)settings.font)->spacesize2Monospaced;
1795 else
1796 {
1797 if(((tFont *)settings.font == &FontT144) && ((*pText == '.') || (*pText == ':')))
1798 settings.actualFont = (tFont *)settings.TinyFont;
1799 else
1800 if(((tFont *)settings.font == &FontT105) && settings.dualFont && ((*pText == '.') || (*pText == ':')))
1801 settings.actualFont = (tFont *)settings.TinyFont;
1802
1803 if(settings.actualFont == (tFont *)settings.TinyFont)
1804 settings.Ydelta += settings.TinyFontExtraYdelta;
1805
1806 newXdelta = GFX_write_char(hgfx, &settings, *(uint8_t *)pText, settings.actualFont);
1807 settings.Xdelta = newXdelta;
1808
1809 if(settings.actualFont == (tFont *)settings.TinyFont)
1810 settings.Ydelta -= settings.TinyFontExtraYdelta;
1811 }
1812 if(pText != 0) /* for TXT_2BYTE */
1813 pText++;
1814 }
1815 return settings.Ydelta;
1816 }
1817
1818 /* Private functions ---------------------------------------------------------*/
1819 /******************************************************************************
1820 Static Function
1821 *******************************************************************************/
1822
1823 /**
1824 ******************************************************************************
1825 * @brief GFX write substring. / Write string without parameters
1826 * @author heinrichs weikamp gmbh
1827 * @version V0.0.1
1828 * @date 22-April-2014
1829 ******************************************************************************
1830 *
1831 * @param hgfx: check gfx_engine.h.
1832 * @param color: 32bit ARGB8888.
1833 * @retval None
1834 */
1835
1836 static uint32_t GFX_write_substring(GFX_CfgWriteString* cfg, GFX_DrawCfgWindow* hgfx, uint8_t textId, int8_t nextCharFor2Byte)
1837 {
1838 uint8_t i, j;
1839 uint32_t found;
1840 uint32_t pText;
1841 uint16_t decodeUTF8;
1842
1843 // -----------------------------
1844 if(textId != (uint8_t)TXT_2BYTE)
1845 {
1846 found = 0;
1847 j = 0;
1848 for(i=(uint8_t)TXT_Language;i<(uint8_t)TXT_END;i++)
1849 {
1850 j++;
1851 }
1852 if(!found)
1853 return cfg->Xdelta;
1854
1855 }
1856 // -----------------------------
1857 else
1858 {
1859 if(!nextCharFor2Byte)
1860 return cfg->Xdelta;
1861
1862 found = 0;
1863
1864 if(!found)
1865 return cfg->Xdelta;
1866 }
1867 // -----------------------------
1868
1869 if(cfg->actualFont == (tFont *)cfg->TinyFont)
1870 cfg->Ydelta += cfg->TinyFontExtraYdelta;
1871
1872 while (*(char*)pText != 0)// und fehlend: Abfrage window / image size
1873 {
1874 if(*(char*)pText == '\t')
1875 cfg->Xdelta = hgfx->WindowTab - hgfx->WindowX0;
1876 else
1877 if((*(char*)pText == ' ') && (cfg->invert == 0)) /* bypass drawing of white space only for not inverted mode */
1878 {
1879 cfg->Xdelta += ((tFont *)cfg->actualFont)->spacesize;
1880 }
1881 else
1882 if((*(char*)pText) & 0x80) /* Identify a UNICODE character other than standard ASCII using the highest bit */
1883 {
1884 decodeUTF8 = ((*(char*)pText) & 0x1F) << 6; /* use 5bits of first byte for upper part of unicode */
1885 pText++;
1886 decodeUTF8 |= (*(char*)pText) & 0x3F; /* add lower 6bits as second part of the unicode */
1887 if (decodeUTF8 <= 0xff) /* The following function has a uint8 input parameter ==> no UNICODEs > 0xff supported */
1888 {
1889 cfg->Xdelta = GFX_write_char(hgfx, cfg, (uint8_t)decodeUTF8, (tFont *)cfg->actualFont);
1890 }
1891 }
1892 else
1893 cfg->Xdelta = GFX_write_char(hgfx, cfg, *(uint8_t *)pText, (tFont *)cfg->actualFont);
1894
1895 pText++;
1896 }
1897
1898 if(cfg->actualFont == (tFont *)cfg->TinyFont)
1899 cfg->Ydelta -= cfg->TinyFontExtraYdelta;
1900
1901 return cfg->Xdelta;
1902 }
1903
1904
1905 /**
1906 ******************************************************************************
1907 * @brief GFX write char. / Write non-inverted, non-colored with entire 8 bit range
1908 * @author heinrichs weikamp gmbh
1909 * @version V0.0.1
1910 * @date 22-April-2014
1911 ******************************************************************************
1912 *
1913 * @param hgfx: check gfx_engine.h.
1914 * @param Ydelta: input
1915 * @param character: character
1916 * @param *Font: pointer to font to be used for this char
1917 * @retval Ydelta: 0x0000FFFF if not successful or char_truncated
1918 */
1919
1920 static uint32_t GFX_write_char_doubleSize(GFX_DrawCfgWindow* hgfx, GFX_CfgWriteString* cfg, uint8_t character, tFont *Font)
1921 {
1922 uint32_t i, j;
1923 uint32_t width, height;
1924 uint32_t found;
1925 uint16_t* pDestination;
1926 uint32_t pSource;
1927 uint32_t OffsetDestination;
1928 uint32_t width_left;
1929 uint32_t height_left;
1930 uint32_t char_truncated_WidthFlag;
1931 uint32_t char_truncated_Height;
1932 uint8_t fill;
1933 uint32_t widthFont, heightFont;
1934 uint32_t nextLine;
1935 int32_t stepdir;
1936
1937 stepdir = 1;
1938
1939 if(hgfx->Image->ImageWidth <= (hgfx->WindowX0 + cfg->Xdelta))
1940 return 0x0000FFFF;
1941
1942 // -----------------------------
1943 found = 0;
1944 for(i=0;i<Font->length;i++)
1945 {
1946 if(Font->chars[i].code == character)
1947 {
1948 found = 1;
1949 break;
1950 }
1951 }
1952 if(!found)
1953 return cfg->Xdelta;
1954
1955 pSource = ((uint32_t)Font->chars[i].image->data);
1956 pDestination = (uint16_t*)(hgfx->Image->FBStartAdress);
1957
1958 heightFont = Font->chars[i].image->height;
1959 widthFont = Font->chars[i].image->width;
1960
1961 height = heightFont*2;
1962 width = widthFont*2;
1963
1964
1965 pDestination += (uint32_t)(hgfx->WindowX0 + cfg->Xdelta) * hgfx->Image->ImageHeight; /* set pointer to delta row */
1966 pDestination += (hgfx->WindowY0 + cfg->Ydelta); /* set pointer to delta colum */
1967
1968 OffsetDestination = (hgfx->Image->ImageHeight - height);
1969 nextLine = hgfx->Image->ImageHeight;
1970
1971 // -----------------------------
1972 char_truncated_WidthFlag = 0;
1973 width_left = hgfx->Image->ImageWidth - (hgfx->WindowX0 + cfg->Xdelta);
1974 if(width_left < width)
1975 {
1976 char_truncated_WidthFlag = 1;
1977 width = width_left;
1978 widthFont = width/2;
1979 }
1980 // -----------------------------
1981
1982 char_truncated_Height = 0;
1983 height_left = hgfx->Image->ImageHeight - (hgfx->WindowY0 + cfg->Ydelta);
1984 if(height_left < height)
1985 {
1986 char_truncated_Height = height - height_left;
1987 if((char_truncated_Height & 1) != 0)
1988 {
1989 height_left -= 1;
1990 char_truncated_Height += 1;
1991 }
1992 height = height_left;
1993 heightFont = height/2;
1994 }
1995
1996 OffsetDestination += char_truncated_Height;
1997 // -----------------------------
1998 if(height == 0)
1999 return 0x0000FFFF;
2000 // -----------------------------
2001
2002 if(cfg->singleSpaceWithSizeOfNextChar)
2003 {
2004 cfg->singleSpaceWithSizeOfNextChar = 0;
2005
2006 if(cfg->invert)
2007 fill = 0xFF;
2008 else
2009 fill = 0;
2010
2011 height /= 2;
2012 for(i = width; i > 0; i--)
2013 {
2014 for (j = height; j > 0; j--)
2015 {
2016 *(__IO uint16_t*)pDestination = fill << 8 | cfg->color;
2017 pDestination += stepdir;
2018 *(__IO uint16_t*)pDestination = fill << 8 | cfg->color;
2019 pDestination += stepdir;
2020 }
2021 pDestination += stepdir * OffsetDestination;
2022 }
2023 }
2024 else
2025 if(cfg->invert)
2026 {
2027 if((heightFont & 3) == 0) /* unroll for perfomance, by 4 if possible, by 2 (16bit) otherwise */
2028 {
2029 heightFont /= 4;
2030 for(i = widthFont; i > 0; i--)
2031 {
2032 if(*(uint8_t*)pSource != 0x01)
2033 {
2034 for (j = heightFont; j > 0; j--)
2035 {
2036 *(__IO uint16_t*)pDestination = (0xFF - *(uint8_t*)pSource) << 8 | cfg->color;
2037 *(__IO uint16_t*)(pDestination + nextLine) = (0xFF - *(uint8_t*)pSource) << 8 | cfg->color;
2038 pDestination += stepdir;
2039 *(__IO uint16_t*)pDestination = (0xFF - *(uint8_t*)pSource) << 8 | cfg->color;
2040 *(__IO uint16_t*)(pDestination + nextLine) = (0xFF - *(uint8_t*)pSource) << 8 | cfg->color;
2041 pDestination += stepdir;
2042 pSource++;
2043
2044 *(__IO uint16_t*)pDestination = (0xFF - *(uint8_t*)pSource) << 8 | cfg->color;
2045 *(__IO uint16_t*)(pDestination + nextLine) = (0xFF - *(uint8_t*)pSource) << 8 | cfg->color;
2046 pDestination += stepdir;
2047 *(__IO uint16_t*)pDestination = (0xFF - *(uint8_t*)pSource) << 8 | cfg->color;
2048 *(__IO uint16_t*)(pDestination + nextLine) = (0xFF - *(uint8_t*)pSource) << 8 | cfg->color;
2049 pDestination += stepdir;
2050 pSource++;
2051
2052 *(__IO uint16_t*)pDestination = (0xFF - *(uint8_t*)pSource) << 8 | cfg->color;
2053 *(__IO uint16_t*)(pDestination + nextLine) = (0xFF - *(uint8_t*)pSource) << 8 | cfg->color;
2054 pDestination += stepdir;
2055 *(__IO uint16_t*)pDestination = (0xFF - *(uint8_t*)pSource) << 8 | cfg->color;
2056 *(__IO uint16_t*)(pDestination + nextLine) = (0xFF - *(uint8_t*)pSource) << 8 | cfg->color;
2057 pDestination += stepdir;
2058 pSource++;
2059
2060 *(__IO uint16_t*)pDestination = (0xFF - *(uint8_t*)pSource) << 8 | cfg->color;
2061 *(__IO uint16_t*)(pDestination + nextLine) = (0xFF - *(uint8_t*)pSource) << 8 | cfg->color;
2062 pDestination += stepdir;
2063 *(__IO uint16_t*)pDestination = (0xFF - *(uint8_t*)pSource) << 8 | cfg->color;
2064 *(__IO uint16_t*)(pDestination + nextLine) = (0xFF - *(uint8_t*)pSource) << 8 | cfg->color;
2065 pDestination += stepdir;
2066 pSource++;
2067 }
2068 pSource += char_truncated_Height;
2069 }
2070 else
2071 {
2072 pSource++;
2073 for (j = heightFont; j > 0; j--)
2074 {
2075 *(__IO uint16_t*)pDestination = 0xFF << 8 | cfg->color;
2076 *(__IO uint16_t*)(pDestination + nextLine) = 0xFF << 8 | cfg->color;
2077 pDestination += stepdir;
2078 *(__IO uint16_t*)pDestination = 0xFF << 8 | cfg->color;
2079 *(__IO uint16_t*)(pDestination + nextLine) = 0xFF << 8 | cfg->color;
2080 pDestination += stepdir;
2081 *(__IO uint16_t*)pDestination = 0xFF << 8 | cfg->color;
2082 *(__IO uint16_t*)(pDestination + nextLine) = 0xFF << 8 | cfg->color;
2083 pDestination += stepdir;
2084 *(__IO uint16_t*)pDestination = 0xFF << 8 | cfg->color;
2085 *(__IO uint16_t*)(pDestination + nextLine) = 0xFF << 8 | cfg->color;
2086 pDestination += stepdir;
2087 *(__IO uint16_t*)pDestination = 0xFF << 8 | cfg->color;
2088 *(__IO uint16_t*)(pDestination + nextLine) = 0xFF << 8 | cfg->color;
2089 pDestination += stepdir;
2090 *(__IO uint16_t*)pDestination = 0xFF << 8 | cfg->color;
2091 *(__IO uint16_t*)(pDestination + nextLine) = 0xFF << 8 | cfg->color;
2092 pDestination += stepdir;
2093 *(__IO uint16_t*)pDestination = 0xFF << 8 | cfg->color;
2094 *(__IO uint16_t*)(pDestination + nextLine) = 0xFF << 8 | cfg->color;
2095 pDestination += stepdir;
2096 *(__IO uint16_t*)pDestination = 0xFF << 8 | cfg->color;
2097 *(__IO uint16_t*)(pDestination + nextLine) = 0xFF << 8 | cfg->color;
2098 pDestination += stepdir;
2099 }
2100 }
2101 pDestination += (OffsetDestination + nextLine) * stepdir;
2102 }
2103 }
2104 else
2105 {
2106 heightFont /= 2;
2107 for(i = widthFont; i > 0; i--)
2108 {
2109 if(*(uint8_t*)pSource != 0x01)
2110 {
2111 for (j = heightFont; j > 0; j--)
2112 {
2113 *(__IO uint16_t*)pDestination = (0xFF - *(uint8_t*)pSource) << 8 | cfg->color;
2114 *(__IO uint16_t*)(pDestination + nextLine) = (0xFF - *(uint8_t*)pSource) << 8 | cfg->color;
2115 pDestination += stepdir;
2116 *(__IO uint16_t*)pDestination = (0xFF - *(uint8_t*)pSource) << 8 | cfg->color;
2117 *(__IO uint16_t*)(pDestination + nextLine) = (0xFF - *(uint8_t*)pSource) << 8 | cfg->color;
2118 pDestination += stepdir;
2119 pSource++;
2120
2121 *(__IO uint16_t*)pDestination = (0xFF - *(uint8_t*)pSource) << 8 | cfg->color;
2122 *(__IO uint16_t*)(pDestination + nextLine) = (0xFF - *(uint8_t*)pSource) << 8 | cfg->color;
2123 pDestination += stepdir;
2124 *(__IO uint16_t*)pDestination = (0xFF - *(uint8_t*)pSource) << 8 | cfg->color;
2125 *(__IO uint16_t*)(pDestination + nextLine) = (0xFF - *(uint8_t*)pSource) << 8 | cfg->color;
2126 pDestination += stepdir;
2127 pSource++;
2128 }
2129 pSource += char_truncated_Height;
2130 }
2131 else
2132 {
2133 pSource++;
2134 for (j = heightFont; j > 0; j--)
2135 {
2136 *(__IO uint16_t*)pDestination = 0xFF << 8 | cfg->color;
2137 *(__IO uint16_t*)(pDestination + nextLine) = 0xFF << 8 | cfg->color;
2138 pDestination += stepdir;
2139 *(__IO uint16_t*)pDestination = 0xFF << 8 | cfg->color;
2140 *(__IO uint16_t*)(pDestination + nextLine) = 0xFF << 8 | cfg->color;
2141 pDestination += stepdir;
2142 *(__IO uint16_t*)pDestination = 0xFF << 8 | cfg->color;
2143 *(__IO uint16_t*)(pDestination + nextLine) = 0xFF << 8 | cfg->color;
2144 pDestination += stepdir;
2145 *(__IO uint16_t*)pDestination = 0xFF << 8 | cfg->color;
2146 *(__IO uint16_t*)(pDestination + nextLine) = 0xFF << 8 | cfg->color;
2147 pDestination += stepdir;
2148 }
2149 }
2150 pDestination += (OffsetDestination + nextLine) * stepdir;
2151 }
2152 }
2153 } /* inverted */
2154 else
2155 {
2156 if((heightFont & 3) == 0) /* unroll for perfomance, by 4 if possible, by 2 (16bit) otherwise */
2157 {
2158 heightFont /= 4;
2159 for(i = widthFont; i > 0; i--)
2160 {
2161 if(*(uint8_t*)pSource != 0x01)
2162 {
2163 for (j = heightFont; j > 0; j--)
2164 {
2165 *(__IO uint16_t*)pDestination = *(uint8_t*)pSource << 8 | cfg->color;
2166 *(__IO uint16_t*)(pDestination + (stepdir * nextLine)) = *(uint8_t*)pSource << 8 | cfg->color;
2167 pDestination += stepdir;
2168 *(__IO uint16_t*)pDestination = *(uint8_t*)pSource << 8 | cfg->color;
2169 *(__IO uint16_t*)(pDestination + (stepdir * nextLine)) = *(uint8_t*)pSource << 8 | cfg->color;
2170 pDestination += stepdir;
2171 pSource++;
2172
2173 *(__IO uint16_t*)pDestination = *(uint8_t*)pSource << 8 | cfg->color;
2174 *(__IO uint16_t*)(pDestination + (stepdir * nextLine)) = *(uint8_t*)pSource << 8 | cfg->color;
2175 pDestination += stepdir;
2176 *(__IO uint16_t*)pDestination = *(uint8_t*)pSource << 8 | cfg->color;
2177 *(__IO uint16_t*)(pDestination + (stepdir * nextLine)) = *(uint8_t*)pSource << 8 | cfg->color;
2178 pDestination += stepdir;
2179 pSource++;
2180
2181 *(__IO uint16_t*)pDestination = *(uint8_t*)pSource << 8 | cfg->color;
2182 *(__IO uint16_t*)(pDestination + (stepdir * nextLine)) = *(uint8_t*)pSource << 8 | cfg->color;
2183 pDestination += stepdir;
2184 *(__IO uint16_t*)pDestination = *(uint8_t*)pSource << 8 | cfg->color;
2185 *(__IO uint16_t*)(pDestination + (stepdir * nextLine)) = *(uint8_t*)pSource << 8 | cfg->color;
2186 pDestination += stepdir;
2187 pSource++;
2188
2189 *(__IO uint16_t*)pDestination = *(uint8_t*)pSource << 8 | cfg->color;
2190 *(__IO uint16_t*)(pDestination + (stepdir * nextLine)) = *(uint8_t*)pSource << 8 | cfg->color;
2191 pDestination += stepdir;
2192 *(__IO uint16_t*)pDestination = *(uint8_t*)pSource << 8 | cfg->color;
2193 *(__IO uint16_t*)(pDestination + (stepdir * nextLine)) = *(uint8_t*)pSource << 8 | cfg->color;
2194 pDestination += stepdir;
2195 pSource++;
2196 }
2197 pSource += char_truncated_Height;
2198 }
2199 else
2200 {
2201 pSource++;
2202 pDestination += stepdir * height;
2203 }
2204 pDestination += stepdir * (OffsetDestination + nextLine);
2205 }
2206 }
2207 else
2208 {
2209 heightFont /= 2;
2210 for(i = widthFont; i > 0; i--)
2211 {
2212 if(*(uint8_t*)pSource != 0x01)
2213 {
2214 for (j = heightFont; j > 0; j--)
2215 {
2216 *(__IO uint16_t*)pDestination = *(uint8_t*)pSource << 8 | cfg->color;
2217 *(__IO uint16_t*)(pDestination + (stepdir * nextLine)) = *(uint8_t*)pSource << 8 | cfg->color;
2218 pDestination += stepdir;
2219 *(__IO uint16_t*)pDestination = *(uint8_t*)pSource << 8 | cfg->color;
2220 *(__IO uint16_t*)(pDestination + (stepdir * nextLine)) = *(uint8_t*)pSource << 8 | cfg->color;
2221 pDestination += stepdir;
2222 pSource++;
2223
2224 *(__IO uint16_t*)pDestination = *(uint8_t*)pSource << 8 | cfg->color;
2225 *(__IO uint16_t*)(pDestination + (stepdir * nextLine)) = *(uint8_t*)pSource << 8 | cfg->color;
2226 pDestination += stepdir;
2227 *(__IO uint16_t*)pDestination = *(uint8_t*)pSource << 8 | cfg->color;
2228 *(__IO uint16_t*)(pDestination + (stepdir * nextLine)) = *(uint8_t*)pSource << 8 | cfg->color;
2229 pDestination += stepdir;
2230 pSource++;
2231 }
2232 pSource += char_truncated_Height;
2233 }
2234 else
2235 {
2236 pSource++;
2237 pDestination += stepdir * height;
2238 }
2239 pDestination += stepdir * (OffsetDestination + nextLine);
2240 }
2241 }
2242 }
2243
2244 // -----------------------------
2245
2246 if(Font == &FontT144)
2247 width += 6;
2248 else
2249 if(Font == &FontT105)
2250 width += 4;
2251
2252 // -----------------------------
2253
2254 if(char_truncated_WidthFlag)
2255 return 0x0000FFFF;
2256 else
2257 return cfg->Xdelta + width;
2258
2259 }
2260
2261
2262 /**
2263 ******************************************************************************
2264 * @brief GFX write char. / Write non-inverted, non-colored with entire 8 bit range
2265 * @author heinrichs weikamp gmbh
2266 * @version V0.0.1
2267 * @date 22-April-2014
2268 ******************************************************************************
2269 *
2270 * @param hgfx: check gfx_engine.h.
2271 * @param Ydelta: input
2272 * @param character: character
2273 * @param *Font: pointer to font to be used for this char
2274 * @retval Ydelta: 0x0000FFFF if not successful or char_truncated
2275 */
2276
2277 static uint32_t GFX_write_char(GFX_DrawCfgWindow* hgfx, GFX_CfgWriteString* cfg, uint8_t character, tFont *Font)
2278 {
2279 if(cfg->doubleSize)
2280 {
2281 return GFX_write_char_doubleSize(hgfx, cfg, character, Font);
2282 }
2283
2284 uint32_t i, j;
2285 uint32_t width, height;
2286 uint32_t found;
2287 uint16_t* pDestination;
2288 uint32_t pSource;
2289 uint32_t OffsetDestination;
2290 uint32_t width_left;
2291 uint32_t height_left;
2292 uint32_t char_truncated_WidthFlag;
2293 uint32_t char_truncated_Height;
2294 uint8_t fill;
2295 uint32_t fillpattern;
2296 int16_t stepdir;
2297
2298 stepdir = 1;
2299
2300 if(hgfx->Image->ImageWidth <= (hgfx->WindowX0 + cfg->Xdelta))
2301 return 0x0000FFFF;
2302
2303 // -----------------------------
2304 found = 0;
2305 for(i=0;i<Font->length;i++)
2306 {
2307 if(Font->chars[i].code == character)
2308 {
2309 found = 1;
2310 break;
2311 }
2312 }
2313 if(!found)
2314 return cfg->Xdelta;
2315 // -----------------------------
2316 /*
2317 if(Font == &Font144)
2318 cfg->Xdelta += 3;
2319 else
2320 if(Font == &Font84)
2321 cfg->Xdelta += 2;
2322 */
2323 // -----------------------------
2324
2325
2326 pSource = ((uint32_t)Font->chars[i].image->data);
2327 pDestination = (uint16_t*)(hgfx->Image->FBStartAdress);
2328
2329
2330 height = Font->chars[i].image->height;
2331 width = Font->chars[i].image->width;
2332
2333 OffsetDestination = hgfx->Image->ImageHeight - height;
2334
2335
2336 /* Xyyyyy y= height */
2337 /* Xyyyyy x= width */
2338 /* Xyyyyy */
2339
2340 pDestination += (hgfx->WindowX0 + cfg->Xdelta) * hgfx->Image->ImageHeight; /* set pointer to delta row */
2341 pDestination += (hgfx->WindowY0 + cfg->Ydelta); /* set pointer to delta colum */
2342
2343 // -----------------------------
2344 char_truncated_WidthFlag = 0;
2345 width_left = hgfx->Image->ImageWidth - (hgfx->WindowX0 + cfg->Xdelta);
2346 if(width_left < width)
2347 {
2348 char_truncated_WidthFlag = 1;
2349 width = width_left;
2350 }
2351 // -----------------------------
2352 char_truncated_Height = 0;
2353 height_left = hgfx->Image->ImageHeight - (hgfx->WindowY0 + cfg->Ydelta);
2354 if(height_left < height)
2355 {
2356 char_truncated_Height = height - height_left;
2357 if((char_truncated_Height & 1) != 0)
2358 {
2359 height_left -= 1;
2360 char_truncated_Height += 1;
2361 }
2362 height = height_left;
2363 }
2364 OffsetDestination += char_truncated_Height;
2365 // -----------------------------
2366 if(height == 0)
2367 return 0x0000FFFF;
2368 // -----------------------------
2369
2370 if(cfg->singleSpaceWithSizeOfNextChar)
2371 {
2372 cfg->singleSpaceWithSizeOfNextChar = 0;
2373
2374 if(cfg->invert)
2375 fill = 0xFF;
2376 else
2377 fill = 0;
2378
2379 height /= 2;
2380 for(i = width; i > 0; i--)
2381 {
2382 for (j = height; j > 0; j--)
2383 {
2384 *(__IO uint16_t*)pDestination = fill << 8 | cfg->color;
2385 pDestination += stepdir;
2386 *(__IO uint16_t*)pDestination = fill << 8 | cfg->color;
2387 pDestination += stepdir;
2388 }
2389 pDestination += stepdir * OffsetDestination;
2390 }
2391 }
2392 else
2393 if(cfg->invert)
2394 {
2395 if((height & 3) == 0) /* unroll for perfomance, by 4 if possible, by 2 (16bit) otherwise */
2396 {
2397 height /= 4;
2398 for(i = width; i > 0; i--)
2399 {
2400 if(*(uint8_t*)pSource != 0x01)
2401 {
2402
2403 for (j = height; j > 0; j--)
2404 {
2405 *(__IO uint16_t*)pDestination = (0xFF - *(uint8_t*)pSource++) << 8 | cfg->color;
2406 pDestination += stepdir;
2407 *(__IO uint16_t*)pDestination = (0xFF - *(uint8_t*)pSource++) << 8 | cfg->color;
2408 pDestination += stepdir;
2409 *(__IO uint16_t*)pDestination = (0xFF - *(uint8_t*)pSource++) << 8 | cfg->color;
2410 pDestination += stepdir;
2411 *(__IO uint16_t*)pDestination = (0xFF - *(uint8_t*)pSource++) << 8 | cfg->color;
2412 pDestination += stepdir;
2413 }
2414 pSource += char_truncated_Height;
2415 }
2416 else /* empty line => fast fill */
2417 {
2418 pSource++;
2419 fillpattern = (( 0xFF << 8 | cfg->color) << 16) | ( 0xFF << 8 | cfg->color);
2420 for (j = height; j > 0; j--)
2421 {
2422 *(__IO uint32_t*)pDestination = fillpattern;
2423 pDestination += stepdir;
2424 pDestination += stepdir;
2425 *(__IO uint32_t*)pDestination = fillpattern;
2426 pDestination += stepdir;
2427 pDestination += stepdir;
2428 }
2429 }
2430 pDestination += stepdir * OffsetDestination;
2431 }
2432 }
2433 else
2434 {
2435 height /= 2;
2436 for(i = width; i > 0; i--)
2437 {
2438 if(*(uint8_t*)pSource != 0x01)
2439 {
2440 for (j = height; j > 0; j--)
2441 {
2442 *(__IO uint16_t*)pDestination = (0xFF - *(uint8_t*)pSource++) << 8 | cfg->color;
2443 pDestination += stepdir;
2444 *(__IO uint16_t*)pDestination = (0xFF - *(uint8_t*)pSource++) << 8 | cfg->color;
2445 pDestination += stepdir;
2446 }
2447 pSource += char_truncated_Height;
2448 }
2449 else
2450 {
2451 pSource++;
2452 for (j = height; j > 0; j--)
2453 {
2454 *(__IO uint16_t*)pDestination = 0xFF << 8 | cfg->color;
2455 pDestination += stepdir;
2456 *(__IO uint16_t*)pDestination = 0xFF << 8 | cfg->color;
2457 pDestination += stepdir;
2458 }
2459 }
2460 pDestination += stepdir * OffsetDestination;
2461 }
2462 }
2463 }
2464 else /* not inverted */
2465 {
2466 if((height & 3) == 0) /* unroll for perfomance, by 4 if possible, by 2 (16bit) otherwise */
2467 {
2468
2469 height /= 4;
2470
2471 for(i = width; i > 0; i--)
2472 {
2473 if(*(uint8_t*)pSource != 0x01)
2474 {
2475 for (j = height; j > 0; j--)
2476 {
2477 *(__IO uint16_t*)pDestination = ( *(uint8_t*)pSource++ << 8) | (cfg->color);
2478 pDestination += stepdir;
2479 *(__IO uint16_t*)pDestination = ( *(uint8_t*)pSource++ << 8) | (cfg->color);
2480 pDestination += stepdir;
2481 *(__IO uint16_t*)pDestination = ( *(uint8_t*)pSource++ << 8) | (cfg->color);
2482 pDestination += stepdir;
2483 *(__IO uint16_t*)pDestination = ( *(uint8_t*)pSource++ << 8) | (cfg->color);
2484 pDestination += stepdir;
2485 }
2486
2487 pSource += char_truncated_Height;
2488 }
2489 else /* clear line */
2490 {
2491 pSource++;
2492 fillpattern = (cfg->color << 16) | cfg->color;
2493
2494 for (j = height; j > 0; j--)
2495 {
2496 *(__IO uint32_t*)pDestination = fillpattern;
2497 pDestination += stepdir;
2498 pDestination += stepdir;
2499 *(__IO uint32_t*)pDestination = fillpattern;
2500 pDestination += stepdir;
2501 pDestination += stepdir;
2502 }
2503 }
2504 pDestination += stepdir * OffsetDestination;
2505 }
2506 }
2507 else
2508 {
2509 height /= 2;
2510 for(i = width; i > 0; i--)
2511 {
2512 if(*(uint8_t*)pSource != 0x01)
2513 {
2514 for (j = height; j > 0; j--)
2515 {
2516 *(__IO uint16_t*)pDestination = ( *(uint8_t*)pSource++ << 8) | (cfg->color);
2517 pDestination += stepdir;
2518 *(__IO uint16_t*)pDestination = ( *(uint8_t*)pSource++ << 8) | (cfg->color);
2519 pDestination += stepdir;
2520 }
2521 pSource += char_truncated_Height;
2522 }
2523 else /* clear line */
2524 {
2525 pSource++;
2526 for (j = height; j > 0; j--)
2527 {
2528 *(__IO uint16_t*)pDestination = cfg->color;
2529 pDestination += stepdir;
2530 *(__IO uint16_t*)pDestination = cfg->color;
2531 pDestination += stepdir;
2532 }
2533 }
2534 pDestination += stepdir * OffsetDestination;
2535 }
2536 }
2537 }
2538
2539 // -----------------------------
2540
2541 if(Font == &FontT144)
2542 width += 3;
2543 else
2544 if(Font == &FontT105)
2545 width += 2;
2546 /*
2547 else
2548 if(Font == &Font144)
2549 width += 3;
2550 else
2551 if(Font == &Font84)
2552 width += 1;
2553 */
2554 // -----------------------------
2555
2556 if(char_truncated_WidthFlag)
2557 return 0x0000FFFF;
2558 else
2559 return cfg->Xdelta + width;
2560 }
2561
2562 /**
2563 ******************************************************************************
2564 * @brief GFX write Modify Ydelta for align. / calc Ydelta for start
2565 * @author heinrichs weikamp gmbh
2566 * @version V0.0.1
2567 * @date 22-April-2014
2568 ******************************************************************************
2569 *
2570 * @param *hgfx: check gfx_engine.h.
2571 * @param *cfg: Ydelta, Font
2572 * @param *pText: character
2573 * @retval Ydelta: 0 if text has to start left ( and probably does not fit)
2574 */
2575
2576 static uint32_t GFX_write__Modify_Xdelta__Centered(GFX_CfgWriteString* cfg, GFX_DrawCfgWindow* hgfx, const char *pTextInput)
2577 {
2578 char cText[101];
2579 uint32_t result;
2580 uint32_t Xsum;
2581 uint32_t j;
2582 uint32_t pText;
2583 uint16_t decodeUTF8;
2584 uint8_t tinyState = 0; /* used to identify the usage of tiny font */
2585 tFont* ptargetFont;
2586
2587 pText = (uint32_t)&cText[0];
2588 Xsum = 0;
2589 j = 0;
2590 ptargetFont = (tFont *)cfg->font;
2591 while (*(char*)pText != 0)// und fehlend: Abfrage window / image size
2592 {
2593 if(*(char*)pText == '\016') /* request font change */
2594 {
2595 tinyState++;
2596 }
2597 if(*(char*)pText == '\017') /* request font reset */
2598 {
2599 tinyState = 0;
2600 }
2601
2602 if((ptargetFont == &FontT105) && ((*(char*)pText == '.') || (*(char*)pText == ':')))
2603 {
2604 tinyState++;
2605 }
2606
2607 if(tinyState > 1)
2608 {
2609 ptargetFont = (tFont *)cfg->TinyFont;
2610 }
2611 else
2612 {
2613 ptargetFont = (tFont *)cfg->font;
2614 }
2615
2616 decodeUTF8 = *(char*)pText; /* place ASCII char */
2617 if((*(char*)pText == '\005') || (*(char*)pText == '\006'))
2618 {
2619 Xsum += 45;
2620 }
2621 else
2622 {
2623 if((*(char*)pText) & 0x80) /* Identify a UNICODE character other than standard ASCII using the highest bit */
2624 {
2625 decodeUTF8 = ((*(char*)pText) & 0x1F) << 6; /* use 5bits of first byte for upper part of unicode */
2626 pText++;
2627 decodeUTF8 |= (*(char*)pText) & 0x3F; /* add lower 6bits as second part of the unicode */
2628 }
2629 else
2630 {
2631 decodeUTF8 = *(char*)pText; /* place ASCII char */
2632 }
2633 Xsum += GFX_Character_Width(decodeUTF8, ptargetFont);
2634 }
2635
2636 pText++;
2637 j++;
2638 if((ptargetFont == &FontT144) && (*(char*)pText != 0))
2639 Xsum += 3;
2640 else
2641 if((ptargetFont == &FontT105) && (*(char*)pText != 0))
2642 Xsum += 2;
2643 }
2644 pText -= j;
2645
2646 if(cfg->doubleSize)
2647 Xsum *= 2;
2648
2649 result = hgfx->WindowX1 - hgfx->WindowX0;
2650 if(Xsum < result)
2651 {
2652 result -= Xsum;
2653 result /= 2;
2654 }
2655 else
2656 result = 0;
2657 return result;
2658 }
2659
2660
2661 static uint32_t GFX_write__Modify_Xdelta__RightAlign(GFX_CfgWriteString* cfg, GFX_DrawCfgWindow* hgfx, const char *pTextInput)
2662 {
2663 uint32_t result;
2664 uint32_t Xsum;
2665 uint32_t j;
2666 tFont *font;
2667 char cText[101];
2668 uint32_t pText;
2669 uint16_t decodeUTF8;
2670 uint8_t tinyState = 0; /* used to identify the usage of tiny font */
2671
2672 cText[0] = 0;
2673
2674 // -----------------------------
2675 pText = (uint32_t)&cText[0];
2676 // -----------------------------
2677
2678 font = (tFont *)cfg->font;
2679 Xsum = 0;
2680 j = 0;
2681
2682 while (*(char*)pText != 0)// und fehlend: Abfrage window / image size
2683 {
2684 if(*(char*)pText == '\016') /* request font change */
2685 {
2686 tinyState++;
2687 }
2688 if(*(char*)pText == '\017') /* request font reset */
2689 {
2690 tinyState = 0;
2691 }
2692
2693 if((font == &FontT144) && (*(char*)pText == '.'))
2694 {
2695 tinyState++;
2696 }
2697 if((font == &FontT105) && ((*(char*)pText == '.') || (*(char*)pText == ':')))
2698 {
2699 tinyState++;
2700 }
2701
2702 if(tinyState > 1)
2703 {
2704 font = (tFont *)cfg->TinyFont;
2705 }
2706 else
2707 {
2708 font = (tFont *)cfg->font;
2709 }
2710
2711 if(*(char*)pText == ' ')
2712 {
2713 Xsum += font->spacesize;
2714 }
2715 else
2716 if((*(char*)pText == '\005') || (*(char*)pText == '\006'))
2717 {
2718 Xsum += 45;
2719 }
2720 else
2721 {
2722 if((*(char*)pText) & 0x80) /* Identify a UNICODE character other than standard ASCII using the highest bit */
2723 {
2724 decodeUTF8 = ((*(char*)pText) & 0x1F) << 6; /* use 5bits of first byte for upper part of unicode */
2725 pText++;
2726 decodeUTF8 |= (*(char*)pText) & 0x3F; /* add lower 6bits as second part of the unicode */
2727 }
2728 else
2729 {
2730 decodeUTF8 = *(char*)pText;
2731 }
2732 Xsum += GFX_Character_Width(decodeUTF8, font); /* lookup character and add width */
2733 }
2734 pText++;
2735 j++;
2736 if((font == &FontT144) && (*(char*)pText != 0))
2737 Xsum += 3;
2738 else
2739 if((font == &FontT105) && (*(char*)pText != 0))
2740 Xsum += 2;
2741 }
2742 pText -= j;
2743
2744 if(cfg->doubleSize)
2745 Xsum *= 2;
2746
2747 result = hgfx->WindowX1 - hgfx->WindowX0 - 1;
2748 if(Xsum < result)
2749 result -= Xsum;
2750 else
2751 result = 0;
2752
2753 return result;
2754 }
2755
2756 void GFX_LTDC_Init(void)
2757 {
2758 GFX_LTDC_Init_display1();
2759 }
2760
2761 void GFX_LTDC_Init_display1(void)
2762 {
2763 /* Timing configuration */
2764 #define ActiveH_d1 800
2765 #define ActiveW_d1 480
2766
2767 #define Hsync_d1 2
2768 #define HFP_d1 8
2769 #define HBP_d1 8
2770
2771 #define Vsync_d1 2
2772 #define VFP_d1 4 // make sure this value * VSYNC is also set in display.c for OLED_VFP_SET
2773 #define VBP_d1 4 // make sure this value * VSYNC is also set in display.c for OLED_VBP_SET
2774
2775 /* Horizontal synchronization width = Hsync - 1 */
2776 LtdcHandle.Init.HorizontalSync = Hsync_d1 - 1;
2777 /* Vertical synchronization height = Vsync - 1 */
2778 LtdcHandle.Init.VerticalSync = Vsync_d1 -1;
2779 /* Accumulated horizontal back porch = Hsync + HBP - 1 */
2780 LtdcHandle.Init.AccumulatedHBP = Hsync_d1 + HBP_d1 - 1;
2781 /* Accumulated vertical back porch = Vsync + VBP - 1 */
2782 LtdcHandle.Init.AccumulatedVBP = Vsync_d1 + VBP_d1 - 1;
2783 /* Accumulated active width = Hsync + HBP + Active Width - 1 */
2784 LtdcHandle.Init.AccumulatedActiveW = Hsync_d1 + HBP_d1 + ActiveW_d1 - 1;
2785 /* Accumulated active height = Vsync + VBP + Active Heigh - 1 */
2786 LtdcHandle.Init.AccumulatedActiveH = Vsync_d1 + VBP_d1 + ActiveH_d1 - 1;
2787 /* Total width = Hsync + HBP + Active Width + HFP - 1 */
2788 LtdcHandle.Init.TotalWidth = Hsync_d1 + HBP_d1 + ActiveW_d1 + HFP_d1 - 1;
2789 /* Total height = Vsync + VBP + Active Heigh + VFP - 1 */
2790 LtdcHandle.Init.TotalHeigh = Vsync_d1 + VBP_d1 + ActiveH_d1 + VFP_d1 - 1;
2791
2792 /* Configure R,G,B component values for LCD background color */
2793 LtdcHandle.Init.Backcolor.Red= 0;
2794 LtdcHandle.Init.Backcolor.Blue= 0;
2795 LtdcHandle.Init.Backcolor.Green= 0;
2796
2797 /* LCD clock configuration */
2798 /* PLLSAI_VCO Input = HSE_VALUE/PLL_M = 1 Mhz */
2799 /* PLLSAI_VCO Output = PLLSAI_VCO Input * PLLSAIN = 192 Mhz */
2800 /* PLLLCDCLK = PLLSAI_VCO Output/PLLSAIR = 192/4 = 48 Mhz */
2801 /* LTDC clock frequency = PLLLCDCLK / LTDC_PLLSAI_DIVR_8 = 48/4 = 6Mhz */
2802
2803 /* done in base.c SystemClockConfig
2804
2805 PeriphClkInitStruct.PeriphClockSelection = RCC_PERIPHCLK_LTDC;
2806 PeriphClkInitStruct.PLLSAI.PLLSAIN = 192;
2807 PeriphClkInitStruct.PLLSAI.PLLSAIR = 4;
2808 PeriphClkInitStruct.PLLSAIDivR = RCC_PLLSAIDIVR_8;
2809 HAL_RCCEx_PeriphCLKConfig(&PeriphClkInitStruct);
2810 */
2811 /* Polarity */
2812 LtdcHandle.Init.HSPolarity = LTDC_HSPOLARITY_AL;
2813 LtdcHandle.Init.VSPolarity = LTDC_VSPOLARITY_AL;
2814 LtdcHandle.Init.DEPolarity = LTDC_DEPOLARITY_AL;
2815 LtdcHandle.Init.PCPolarity = LTDC_PCPOLARITY_IIPC;//LTDC_PCPOLARITY_IPC;
2816
2817 LtdcHandle.Instance = LTDC;
2818
2819 /* Configure the LTDC */
2820 if(HAL_LTDC_Init(&LtdcHandle) != HAL_OK) // initialize GPIO Pins, too
2821 {
2822 /* Initialization Error */
2823 GFX_Error_Handler();
2824 }
2825 }
2826
2827 void GFX_LTDC_LayerDefaultInit(uint16_t LayerIndex, uint32_t FB_Address)
2828 {
2829 LTDC_LayerCfgTypeDef Layercfg;
2830
2831 /* Layer Init */
2832 Layercfg.WindowX0 = 0;
2833 Layercfg.WindowX1 = 480;
2834 Layercfg.WindowY0 = 0;
2835 Layercfg.WindowY1 = 800;
2836 Layercfg.PixelFormat = LTDC_PIXEL_FORMAT_AL88;//LTDC_PIXEL_FORMAT_ARGB8888;
2837 Layercfg.FBStartAdress = FB_Address;
2838 Layercfg.Alpha = 255;
2839 Layercfg.Alpha0 = 0;
2840 Layercfg.Backcolor.Blue = 0;
2841 Layercfg.Backcolor.Green = 0;
2842 Layercfg.Backcolor.Red = 0;
2843 Layercfg.BlendingFactor1 = LTDC_BLENDING_FACTOR1_PAxCA;
2844 Layercfg.BlendingFactor2 = LTDC_BLENDING_FACTOR2_PAxCA;
2845 Layercfg.ImageWidth = 480;
2846 Layercfg.ImageHeight = 800;
2847
2848 HAL_LTDC_ConfigCLUT(&LtdcHandle, ColorLUT, CLUT_END, LayerIndex);
2849 HAL_LTDC_ConfigLayer(&LtdcHandle, &Layercfg, LayerIndex);
2850 HAL_LTDC_EnableCLUT(&LtdcHandle, LayerIndex);
2851 }
2852
2853 static uint32_t GFX_doubleBufferOne(void)
2854 {
2855 return SDRAM_DOUBLE_BUFFER_ONE;
2856 }
2857
2858
2859 static uint32_t GFX_doubleBufferTwo(void)
2860 {
2861 return SDRAM_DOUBLE_BUFFER_TWO;
2862 }
2863
2864 uint32_t getFrame(uint8_t callerId)
2865 {
2866 static uint8_t lastFrameProvided = 0;
2867 uint8_t i;
2868
2869 /* first iteration: look for a clear frame */
2870 i = lastFrameProvided;
2871 do
2872 {
2873 i++;
2874 if(i == MAXFRAMES)
2875 {
2876 i = 0;
2877 }
2878 } while((i != lastFrameProvided) && (frame[i].status != CLEAR));
2879
2880 if((i < MAXFRAMES) && (frame[i].status == CLEAR))
2881 {
2882 frame[i].status = BLOCKED;
2883 frame[i].caller = callerId;
2884 lastFrameProvided = i;
2885 return frame[i].StartAddress;
2886 }
2887
2888 /* second iteration: look for a frame which may be reused after clearing */
2889 i = lastFrameProvided;
2890 do
2891 {
2892 i++;
2893 if(i == MAXFRAMES)
2894 {
2895 i = 0;
2896 }
2897 }while((i != lastFrameProvided) && (frame[i].status != RELEASED));
2898
2899
2900 if((i < MAXFRAMES) && (frame[i].status == RELEASED))
2901 {
2902 GFX_clear_frame_immediately(frame[i].StartAddress);
2903 frame[i].status = BLOCKED;
2904 lastFrameProvided = i;
2905 return frame[i].StartAddress;
2906 }
2907 return 0;
2908 }
2909
2910
2911 void GFX_forceReleaseFramesWithId(uint8_t callerId)
2912 {
2913 for(int i=0; i<MAXFRAMES; i++)
2914 if((frame[i].caller == callerId) && (frame[i].status == BLOCKED))
2915 frame[i].status = RELEASED;
2916 }
2917
2918
2919 void releaseAllFramesExcept(uint8_t callerId, uint32_t frameStartAddress)
2920 {
2921 for(int i=0; i<MAXFRAMES; i++)
2922 if((frame[i].caller == callerId) && (frame[i].status == BLOCKED) && (frame[i].StartAddress != frameStartAddress))
2923 frame[i].status = RELEASED;
2924 }
2925
2926
2927 uint8_t releaseFrame(uint8_t callerId, uint32_t frameStartAddress)
2928 {
2929 static uint8_t countErrorCalls = 0;
2930
2931 if(frameStartAddress < FBGlobalStart)
2932 return 2;
2933
2934
2935 uint8_t i;
2936
2937 i = 0;
2938 while((i < MAXFRAMES) && (frame[i].StartAddress != frameStartAddress))
2939 i++;
2940
2941 if((i < MAXFRAMES) && (frame[i].StartAddress == frameStartAddress))
2942 {
2943 if(frame[i].caller == callerId)
2944 {
2945 frame[i].status = RELEASED;
2946 return 1;
2947 }
2948 else
2949 countErrorCalls++;
2950 }
2951 return 0;
2952 }
2953
2954
2955 uint16_t blockedFramesCount(void)
2956 {
2957 uint16_t count = MAXFRAMES;
2958
2959 for(int i = 0;i<MAXFRAMES;i++)
2960 if(frame[i].status == BLOCKED)
2961 count--;
2962
2963 return count;
2964 }
2965
2966
2967 uint8_t housekeepingFrame(void)
2968 {
2969 static uint8_t countLogClear = 0;
2970 uint8_t i;
2971 uint8_t retVal = 1;
2972
2973 if(DMA2D_at_work == 255)
2974 {
2975 i = 0;
2976 /* skip frame cleaning for actual frames which have not yet been replaced by new top/bottom frames */
2977 while((i < MAXFRAMES) && ((frame[i].status != RELEASED) || (frame[i].StartAddress == GFX_get_pActualFrameTop()) || (frame[i].StartAddress == GFX_get_pActualFrameBottom())))
2978 i++;
2979
2980 if((i < MAXFRAMES) && (frame[i].status == RELEASED))
2981 {
2982 if(frame[i].caller == 15)
2983 countLogClear++;
2984 GFX_clear_frame_dma2d(i);
2985 }
2986 else
2987 {
2988 retVal = 0; /* no more frame to be cleaned found */
2989 }
2990 }
2991 return retVal;
2992 }
2993
2994
2995 static void GFX_Dma2d_TransferComplete(DMA2D_HandleTypeDef* Dma2dHandle)
2996 {
2997 if(DMA2D_at_work < MAXFRAMES)
2998 frame[DMA2D_at_work].status = CLEAR;
2999
3000 DMA2D_at_work = 255;
3001 }
3002
3003
3004 static void GFX_Dma2d_TransferError(DMA2D_HandleTypeDef* Dma2dHandle)
3005 {
3006
3007 }
3008
3009 static void GFX_Error_Handler(void)
3010 {
3011 /* Turn LED3 on */
3012 // BSP_LED_On(LED3);
3013 while(1)
3014 {
3015 }
3016 }
3017
3018 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)
3019 {
3020 GFX_DrawCfgWindow hgfx;
3021
3022
3023 if(XrightGimpStyle > 799)
3024 XrightGimpStyle = 799;
3025 if(XleftGimpStyle >= XrightGimpStyle)
3026 XleftGimpStyle = 0;
3027 if(YtopGimpStyle > 479)
3028 YtopGimpStyle = 479;
3029
3030 hgfx.Image = tMscreen;
3031 hgfx.WindowNumberOfTextLines = 1;
3032 hgfx.WindowLineSpacing = 0;
3033 hgfx.WindowTab = 0;
3034
3035 hgfx.WindowX0 = XleftGimpStyle;
3036 hgfx.WindowX1 = XrightGimpStyle;
3037 hgfx.WindowY1 = 479 - YtopGimpStyle;
3038 if(hgfx.WindowY1 < Font->height)
3039 hgfx.WindowY0 = 0;
3040 else
3041 hgfx.WindowY0 = hgfx.WindowY1 - Font->height;
3042 GFX_write_string_color(Font, &hgfx, text, 0, color);
3043 }
3044
3045
3046 void gfx_write_topline_simple(GFX_DrawCfgScreen *tMscreen, const char *text, uint8_t color)
3047 {
3048 GFX_DrawCfgWindow hgfx;
3049 const tFont *Font = &FontT48;
3050
3051 hgfx.Image = tMscreen;
3052 hgfx.WindowNumberOfTextLines = 1;
3053 hgfx.WindowLineSpacing = 0;
3054
3055 hgfx.WindowTab = 0;
3056 hgfx.WindowX0 = 20;
3057 hgfx.WindowX1 = 779;
3058
3059 hgfx.WindowY1 = 479;
3060 hgfx.WindowY0 = hgfx.WindowY1 - Font->height;
3061 GFX_write_label(Font, &hgfx, text, color);
3062 }
3063
3064
3065 void gfx_write_page_number(GFX_DrawCfgScreen *tMscreen, uint8_t page, uint8_t total, uint8_t color)
3066 {
3067 GFX_DrawCfgWindow hgfx;
3068 const tFont *Font = &FontT48;
3069 char text[7];
3070 uint8_t i, secondDigitPage, secondDigitTotal;
3071
3072 if(total > 8)
3073 {
3074 Font = &FontT24;
3075 }
3076
3077 hgfx.Image = tMscreen;
3078 hgfx.WindowNumberOfTextLines = 1;
3079 hgfx.WindowLineSpacing = 0;
3080 hgfx.WindowTab = 0;
3081
3082 hgfx.WindowX1 = 779;
3083 if(Font == &FontT24)
3084 {
3085 hgfx.WindowX0 = hgfx.WindowX1 - (Font->spacesize*3);
3086 }
3087 else
3088 {
3089 hgfx.WindowX0 = hgfx.WindowX1 - (Font->spacesize2Monospaced*3);
3090 }
3091 hgfx.WindowY1 = 479;
3092 hgfx.WindowY0 = hgfx.WindowY1 - Font->height;
3093 if(page > 99)
3094 page = 99;
3095 if(total > 99)
3096 total = 99;
3097
3098 i = 0;
3099 text[i++] = '\002';
3100
3101 secondDigitPage = page / 10;
3102 page -= secondDigitPage * 10;
3103
3104 secondDigitTotal = total / 10;
3105 total -= secondDigitTotal * 10;
3106
3107 if(secondDigitPage)
3108 text[i++] = '0' + secondDigitPage;
3109 text[i++] = '0' + page;
3110
3111 text[i++] = '/';
3112
3113 if(secondDigitTotal)
3114 text[i++] = '0' + secondDigitTotal;
3115 text[i++] = '0' + total;
3116
3117 text[i] = 0;
3118
3119 GFX_clear_window_immediately(&hgfx);
3120 GFX_write_label(Font, &hgfx, text, color);
3121 }
3122
3123
3124 uint8_t gfx_number_to_string(uint8_t max_digits, _Bool fill, char *pText, uint32_t input)
3125 {
3126 uint8_t digits[10];
3127 uint32_t number, divider;
3128 int first;
3129 uint8_t out;
3130
3131 number = input;
3132 first = 0;
3133 divider = 1000000000;
3134 for(int i=9;i>=0;i--)
3135 {
3136 digits[i] = (uint8_t)(number / divider);
3137 number -= digits[i] * divider;
3138 divider /= 10;
3139 if((first == 0) && (digits[i] != 0))
3140 first = i;
3141 }
3142
3143 if((first + 1) > max_digits)
3144 {
3145 for(int i = 0; i<max_digits; i++)
3146 pText[i] = '9';
3147 out = max_digits;
3148 }
3149 else if(fill)
3150 {
3151 int i = 0;
3152 for(int k = max_digits; k>0; k--)
3153 pText[i++] = digits[k -1] + '0';
3154 out = max_digits;
3155 }
3156 else
3157 {
3158 int i = 0;
3159 for(int k = first; k>=0; k--)
3160 pText[i++] = digits[k] + '0';
3161 out = i;
3162 }
3163
3164 return out;
3165 }
3166
3167
3168 /* output is
3169 * 0->
3170 * |
3171 * v
3172 *
3173 * input is
3174 *
3175 * ->
3176 * A
3177 * |
3178 * 0
3179 */
3180 void GFX_screenshot(void)
3181 {
3182 uint32_t pSource = GFX_get_pActualFrameTop();
3183 uint32_t pSourceBottom =GFX_get_pActualFrameBottom();
3184 uint32_t pBottomNew = getFrame(99);
3185 uint32_t pDestination = GFX_doubleBufferOne();
3186 uint32_t sourceNow;
3187
3188
3189 uint32_t bot_leftStart = FrameHandler.actualBottom.leftStart; // x0 z.B. 0
3190 uint32_t bot_bottomStart = FrameHandler.actualBottom.bottomStart; // y0 z.B. 25
3191 uint32_t bot_width = FrameHandler.actualBottom.width; // 800
3192 uint32_t bot_height = FrameHandler.actualBottom.height; // 390
3193
3194 struct split
3195 {
3196 uint8_t blue;
3197 uint8_t green;
3198 uint8_t red;
3199 uint8_t alpha;
3200 };
3201
3202 union inout_u
3203 {
3204 uint32_t in;
3205 struct split out;
3206 };
3207
3208 union inout_u value;
3209
3210 /* test
3211 uint32_t pSourceTemp = pSource + (2*479);
3212 for (int j = 0xFFFF; j > 0x00FF; j -= 0x0100)
3213 {
3214 *(__IO uint16_t*)pSourceTemp = j;
3215 pSourceTemp += 480*2;
3216 }
3217 */
3218 // Top Layer
3219 const unsigned width = 800, height = 480;
3220 const uint32_t heightX2 = height*2;
3221
3222 for(unsigned y = 0; y < height; y++)
3223 {
3224 sourceNow = pSource + 2 * ((height - 1) - y);
3225 for(unsigned x = 0; x < width; x++)
3226 {
3227 // sourceNow += 2 * height * x + 2 * (height - 1 - y);
3228 value.in = ColorLUT[*(__IO uint8_t*)(sourceNow)];
3229 value.out.alpha = *(__IO uint8_t*)(sourceNow + 1);
3230
3231 *(__IO uint8_t*)(pDestination++) = value.out.red;
3232 *(__IO uint8_t*)(pDestination++) = value.out.green;
3233 *(__IO uint8_t*)(pDestination++) = value.out.blue;
3234 *(__IO uint8_t*)(pDestination++) = value.out.alpha;
3235 sourceNow += heightX2;
3236 }
3237 }
3238
3239 // Bottom Layer
3240 // build newBottom
3241 pSource = pSourceBottom;
3242 for(unsigned x = bot_leftStart; x < bot_leftStart+bot_width; x++)
3243 {
3244 for(unsigned y = bot_bottomStart; y < bot_bottomStart+bot_height; y++)
3245 {
3246 pDestination = pBottomNew + (2 * y);
3247 pDestination += heightX2 * x;
3248 *(__IO uint16_t*)(pDestination) = *(__IO uint16_t*)(pSource);
3249 pSource += 2;
3250 }
3251 }
3252
3253 // output Bottom Layer
3254 pSource = pBottomNew;
3255 pDestination = GFX_doubleBufferTwo();
3256
3257 for(unsigned y = 0; y < height; y++)
3258 {
3259 sourceNow = pSource + 2 * ((height - 1) - y);
3260 for(unsigned x = 0; x < width; x++)
3261 {
3262 // sourceNow = pSource + 2 * height * x + 2 * (height - 1 - y);
3263 value.in = ColorLUT[*(__IO uint8_t*)(sourceNow)];
3264 value.out.alpha = *(__IO uint8_t*)(sourceNow + 1);
3265
3266 *(__IO uint8_t*)(pDestination++) = value.out.red;
3267 *(__IO uint8_t*)(pDestination++) = value.out.green;
3268 *(__IO uint8_t*)(pDestination++) = value.out.blue;
3269 *(__IO uint8_t*)(pDestination++) = value.out.alpha;
3270 sourceNow += heightX2;
3271 }
3272 }
3273 releaseFrame(99,pBottomNew);
3274 /*
3275 // das kommt dazu!
3276 unsigned yEnd = 480 - FrameHandler.actualBottom.bottomStart;
3277 unsigned yStart = yEnd - FrameHandler.actualBottom.height;
3278
3279 if(yStart > 0)
3280 {
3281 for(unsigned y = 0; y < yStart; y++)
3282 for(unsigned x = 0; x < width; x++)
3283 {
3284 *(__IO uint8_t*)(pDestination++) = 0;
3285 *(__IO uint8_t*)(pDestination++) = 0;
3286 *(__IO uint8_t*)(pDestination++) = 0;
3287 *(__IO uint8_t*)(pDestination++) = 0;
3288 }
3289 }
3290 for(unsigned y = yStart; y < yEnd; y++)
3291 for(unsigned x = 0; x < width; x++)
3292 {
3293 sourceNow = pSource + 2 * height * x + 2 * (height - 1 - y);
3294 value.in = ColorLUT[*(__IO uint8_t*)(sourceNow)];
3295 value.out.alpha = *(__IO uint8_t*)(sourceNow + 1);
3296
3297 *(__IO uint8_t*)(pDestination++) = value.out.red;
3298 *(__IO uint8_t*)(pDestination++) = value.out.green;
3299 *(__IO uint8_t*)(pDestination++) = value.out.blue;
3300 *(__IO uint8_t*)(pDestination++) = value.out.alpha;
3301 }
3302 if(yEnd < 480)
3303 {
3304 for(unsigned y = yEnd; y < 480; y++)
3305 for(unsigned x = 0; x < width; x++)
3306 {
3307 *(__IO uint8_t*)(pDestination++) = 0;
3308 *(__IO uint8_t*)(pDestination++) = 0;
3309 *(__IO uint8_t*)(pDestination++) = 0;
3310 *(__IO uint8_t*)(pDestination++) = 0;
3311 }
3312 }
3313 */
3314 }
3315
3316 uint32_t GFX_Character_Width(uint8_t character, tFont *Font)
3317 {
3318 uint32_t i;
3319 for(i=0;i<Font->length;i++)
3320 {
3321 if(Font->chars[i].code == character)
3322 {
3323 return Font->chars[i].image->width;
3324 }
3325 }
3326
3327 return 0;
3328 }
3329
3330 void Gfx_colorsscheme_mod(char *text, uint8_t alternativeColor)
3331 {
3332 char *p = text;
3333 uint8_t index = 0;
3334
3335 while ((*p) && (index < MAX_COLOR_STRING_LENGTH))
3336 {
3337 if (*p == '\020')
3338 {
3339 if(!GFX_is_colorschemeDiveStandard())
3340 {
3341 *p = '\027';
3342 }
3343 else if(alternativeColor != 0)
3344 {
3345 *p += alternativeColor;
3346 }
3347 }
3348 p++;
3349 index++;
3350 }
3351 }
3352