/******************************************************************* File: display.c Date: 30-September-2020 Author: Peter Spindler Description: Display driver Based on display driver from STMicroelectronics: stm32f723e_discovery_lcd.c STM32Cube Firmware F7 Version 1.16.0, STM32F723E Discovery board License from STMicroelectronics: Redistribution and use in source and binary forms, with or without modification, are permitted provided that the following conditions are met: 1. Redistributions of source code must retain the above copyright notice, this list of conditions and the following disclaimer. 2. Redistributions in binary form must reproduce the above copyright notice, this list of conditions and the following disclaimer in the documentation and/or other materials provided with the distribution. 3. Neither the name of STMicroelectronics nor the names of its contributors may be used to endorse or promote products derived from this software without specific prior written permission. THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. ********************************************************************/ #include "stm32f7xx_hal.h" #include "main.h" #include "display.h" #include #include #include /* ToDo: Include headers for RTOS/mutex, declare mutex */ extern SRAM_HandleTypeDef hsram2; #define DISPLAY_WIDTH 240 #define DISPLAY_HEIGHT 240 #define DISPLAY_ABS(X) ((x) > 0 ? (x) : -(x)) #define DISPLAY_LIMIT( x, min, max ) {if( x < min ) x = min; else if( x > max ) x = max; } static char Display_LineBuffer[64]; // Buffer for printf // Display_Select: Called before any access to the display. // Return: 0: Error, do not access the display // 1: OK, access the display uint8_t Display_Select( void ) { /* ToDo: Take mutex */ return 1; // OK } // Display_Deselect: Called after any access to the display. void Display_Deselect( void ) { /* ToDo: Give mutex */ } /************************************************************************************************************* Display: LowLevel **************************************************************************************************************/ typedef struct { __IO uint16_t REG; __IO uint16_t RAM; } LCD_CONTROLLER_TypeDef; #define FMC_BANK2_BASE ((uint32_t)(0x60000000 | 0x04000000)) #define FMC_BANK2 ((LCD_CONTROLLER_TypeDef *) FMC_BANK2_BASE) void Display_WriteCommand( uint8_t Reg) { FMC_BANK2->REG = Reg; __DSB(); } void Display_WriteData( uint16_t Value ) { FMC_BANK2->RAM = Value; __DSB(); } static uint16_t Display_ReadData(void) { return FMC_BANK2->RAM; } uint8_t Display_ReadReg(uint8_t Command) { Display_WriteCommand(Command); Display_ReadData(); return (Display_ReadData()); } // Command list format: // Per command: // Byte 0: Command. 0xff: End of list // Byte 1: Number of arguments (N). Bit 7 set: delay, time in last argument // Byte 2,...,1+N: Arguments static const uint8_t InitCmd[] = { 0x10, 0x80, 10, // Sleep in, wait 10 ms 0x01, 0x80, 200, // Reset, wait 100 ms 0x11, 0x80, 120, // Sleep out, wait 120 ms 0x36, 0, // Normal Display 0x3a, 1, 0x05, // Color mode 0x21, 0, // Display inversion 0x2a, 4, 0, 0, 0, 239, // Column address 0x2b, 4, 0, 0, 0, 239, // Row address 0xb2, 5, 0x0c, 0x0c, 0x00, 0x33, 0x33, // Porch 0xb7, 1, 0x35, // Gate 0xbb, 1, 0x1f, // Vcom 0xc0, 1, 0x2c, // LCM 0xc2, 2, 0x01, 0xc3, // VDV CRH EN 0xc4, 1, 0x20, // VDV set 0xc6, 1, 0x0f, // Frame rate control 0xd0, 2, 0xa4, 0xa1, // Power control 0xe0, 14, 0xd0, 0x08, 0x11, 0x08, 0x0c, 0x15, 0x39, 0x33, 0x50, 0x36, 0x13, 0x14, 0x29, 0x2d, // Positive Voltage Gamma Control 0xe1, 14, 0xd0, 0x08, 0x10, 0x08, 0x06, 0x06, 0x39, 0x44, 0x51, 0x0b, 0x16, 0x14, 0x2f, 0x31, // Negative Voltage Gamma Control 0x29, 0, // Display on 0x11, 0, // Sleep out 0x35, 1, 0x00, // Tearing Effect 0xff }; static void Display_WriteCommandList(const uint8_t *addr) { uint8_t NumArgs; uint16_t Delay; while(*addr != 0xff) { //printf("Cmd %x, ", *addr); Display_WriteCommand(*addr++); // Command NumArgs = *addr++; // Number of arguments Delay = NumArgs & 0x80; // Bit 7: Delay flag NumArgs &= ~0x80; //printf("Num: %d: ", NumArgs); while(NumArgs--) { //printf("%x ", *addr ); Display_WriteData(*addr++); } //printf("\n"); // Delay after command if(Delay) { // If delay flag set Delay = *addr++; // Delay time if( Delay == 255) { Delay = 500; } //printf("Delay: %d\n", Delay ); HAL_Delay(Delay); } } } static void Display_InitFmc( void ) { FMC_NORSRAM_TimingTypeDef sram_timing={0}; // PSRAM device configuration // Timing configuration derived from system clock (up to 216Mhz) for 108Mhz as PSRAM clock frequency sram_timing.AddressSetupTime = 9; sram_timing.AddressHoldTime = 2; sram_timing.DataSetupTime = 6; sram_timing.BusTurnAroundDuration = 1; sram_timing.CLKDivision = 2; sram_timing.DataLatency = 2; sram_timing.AccessMode = FMC_ACCESS_MODE_A; // Initialize the FMC controller for LCD (FMC_NORSRAM_BANK2) HAL_SRAM_Init(&hsram2, &sram_timing, &sram_timing); } static void Display_SetOrientation(uint32_t orientation) { uint8_t NormalDisplayParam; if( orientation == LCD_ORIENTATION_LANDSCAPE ) { NormalDisplayParam = 0x00; } else if( orientation == LCD_ORIENTATION_LANDSCAPE_ROT180 ) { // Vertical Scrolling Definition Display_WriteCommand(0x33); // TFA describes the Top Fixed Area Display_WriteData(0x00); Display_WriteData(0x00); // VSA describes the height of the Vertical Scrolling Area Display_WriteData(0x01); Display_WriteData(0xf0); // BFA describes the Bottom Fixed Area Display_WriteData(0x00); Display_WriteData(0x00); // Vertical Scroll Start Address of RAM: // GRAM row nbr (320) - Display row nbr (240) = 80 = 0x50 Display_WriteCommand(0x37); Display_WriteData(0x00); Display_WriteData(0x50); NormalDisplayParam = 0xC0; } else { NormalDisplayParam = 0x60; } Display_WriteCommand(0x36); Display_WriteData(NormalDisplayParam); } /************************************************************************************************************* Display: Primitives WITHOUT Select/Deselect **************************************************************************************************************/ static void Display_SetCursor_( uint16_t x, uint16_t y ) { DISPLAY_LIMIT( x, 0, DISPLAY_WIDTH-1 ); DISPLAY_LIMIT( y, 0, DISPLAY_HEIGHT-1 ); Display_WriteCommand( 0x2a ); Display_WriteData( 0 ); Display_WriteData( x ); Display_WriteData( 0 ); Display_WriteData( x+1 ); Display_WriteCommand( 0x2b ); Display_WriteData( 0 ); Display_WriteData( y ); Display_WriteData( 0 ); Display_WriteData( y+1 ); Display_WriteCommand( 0x2c ); } static void Display_SetWindow_( uint16_t x, uint16_t y, uint16_t Width, uint16_t Height ) { DISPLAY_LIMIT( x, 0, DISPLAY_WIDTH-1 ); DISPLAY_LIMIT( y, 0, DISPLAY_HEIGHT-1 ); Display_WriteCommand( 0x2a ); Display_WriteData( 0 ); Display_WriteData( x ); Display_WriteData( 0 ); Display_WriteData( x+Width ); Display_WriteCommand( 0x2b ); Display_WriteData( 0 ); Display_WriteData( y ); Display_WriteData( 0 ); Display_WriteData( y+Height ); Display_WriteCommand( 0x2c ); } static void Display_DrawHLine_( uint16_t x, uint16_t y, uint16_t Length, uint16_t Color ) { uint16_t counter = 0; Display_SetWindow_( x, y, DISPLAY_WIDTH-1, 0 ); for(counter = 0; counter < Length; counter++) { Display_WriteData( Color ); } } static void Display_DrawVLine_( uint16_t x, uint16_t y, uint16_t Length, uint16_t Color ) { uint16_t counter = 0; Display_SetWindow_( x, y, 0, DISPLAY_HEIGHT-1 ); for(counter = 0; counter < Length; counter++) { Display_WriteData( Color ); } } uint16_t Display_GetHeight( void ) { return DISPLAY_HEIGHT; } uint16_t Display_GetWidth( void ) { return DISPLAY_WIDTH; } static void Display_DrawPixel_( uint16_t x, uint16_t y, uint16_t Color ) { Display_SetCursor_( x, y ); Display_WriteData( Color ); } static void Display_DrawChar_( uint16_t x, uint16_t y, uint16_t ColorFront, uint16_t ColorBack, FONT_TypeDef *Font, char Char ) { uint32_t i = 0, j = 0; uint16_t Height, Width; uint8_t Offset; const uint8_t *CharData; const uint8_t *LinePtr; uint32_t Line; Height = Font->Height; Width = Font->Width; Offset = 8 *((Width + 7)/8) - Width; CharData = &Font->table[(Char-' ')*Height * ((Width + 7) / 8)]; Display_SetWindow_( x, y, Width-1, Height-1 ); for( i = 0; i < Height; i++ ) { LinePtr = ((const uint8_t *)CharData + (Width + 7)/8 * i); switch(((Width + 7)/8)) { case 1: Line = LinePtr[0]; break; case 2: Line = (LinePtr[0]<< 8) | LinePtr[1]; break; case 3: default: Line = (LinePtr[0]<< 16) | (LinePtr[1]<< 8) | LinePtr[2]; break; } for( j = 0; j < Width; j++ ) { if( Line & (1 << (Width- j + Offset- 1))) { Display_WriteData( ColorFront ); } else { Display_WriteData( ColorBack ); } } y++; } } static void Display_PrintString_( uint16_t x, uint16_t y, uint16_t ColorFront, uint16_t ColorBack, FONT_TypeDef *Font, char *String ) { DISPLAY_ALIGN_TypeDef Mode = ALIGN_LEFT; if( Mode != ALIGN_LEFT ) { size_t StrLen = strlen(String); if( Mode == ALIGN_CENTER ) { x -= StrLen*Font->Width/2; } else if( Mode == ALIGN_RIGHT ) { x -= StrLen*Font->Width; } if( x < 0 ) { x = 0; } } while( *String ) { if( x >= Display_GetWidth() ) { break; } Display_DrawChar_( x, y, ColorFront, ColorBack, Font, *String ); x += Font->Width; String ++; } } static void Display_DrawLine_( uint16_t x1, uint16_t y1, uint16_t x2, uint16_t y2, uint16_t Color ) { int16_t deltax = 0, deltay = 0, x = 0, y = 0, xinc1 = 0, xinc2 = 0, yinc1 = 0, yinc2 = 0, den = 0, num = 0, numadd = 0, numpixels = 0, curpixel = 0; deltax = DISPLAY_ABS(x2 - x1); deltay = DISPLAY_ABS(y2 - y1); x = x1; y = y1; if (x2 >= x1) { xinc1 = 1; xinc2 = 1; } else { xinc1 = -1; xinc2 = -1; } if( y2 >= y1 ) { yinc1 = 1; yinc2 = 1; } else { yinc1 = -1; yinc2 = -1; } if( deltax >= deltay ) { // There is at least one x-value for every y-value xinc1 = 0; // Don't change the x when numerator >= denominator yinc2 = 0; // Don't change the y for every iteration den = deltax; num = deltax / 2; numadd = deltay; numpixels = deltax; // There are more x-values than y-values } else { // There is at least one y-value for every x-value xinc2 = 0; // Don't change the x for every iteration yinc1 = 0; // Don't change the y when numerator >= denominator den = deltay; num = deltay / 2; numadd = deltax; numpixels = deltay; // There are more y-values than x-values } for( curpixel = 0; curpixel <= numpixels; curpixel++ ) { Display_DrawPixel_( x, y, Color ); num += numadd; // Increase the numerator by the top of the fraction if (num >= den) { // Check if numerator >= denominator num -= den; // Calculate the new numerator value x += xinc1; // Change the x as appropriate y += yinc1; // Change the y as appropriate } x += xinc2; // Change the x as appropriate y += yinc2; // Change the y as appropriate } } static void Display_Clear_( uint16_t Color ) { uint16_t y = 0; uint16_t Height = 0; uint16_t Width = Display_GetWidth(); Height = Display_GetHeight(); for( y = 0; y < Height ; y ++ ) { Display_DrawHLine_( 0, y, Width, Color ); } } static void Display_FillTriangle_( uint16_t x1, uint16_t x2, uint16_t x3, uint16_t y1, uint16_t y2, uint16_t y3, uint16_t Color ) { int16_t deltax = 0, deltay = 0, x = 0, y = 0, xinc1 = 0, xinc2 = 0, yinc1 = 0, yinc2 = 0, den = 0, num = 0, numadd = 0, numpixels = 0, curpixel = 0; deltax = DISPLAY_ABS(x2 - x1); deltay = DISPLAY_ABS(y2 - y1); x = x1; y = y1; if (x2 >= x1) { xinc1 = 1; xinc2 = 1; } else { xinc1 = -1; xinc2 = -1; } if (y2 >= y1) { yinc1 = 1; yinc2 = 1; } else { yinc1 = -1; yinc2 = -1; } if (deltax >= deltay) { // There is at least one x-value for every y-value xinc1 = 0; // Don't change the x when numerator >= denominator yinc2 = 0; // Don't change the y for every iteration den = deltax; num = deltax / 2; numadd = deltay; numpixels = deltax; // There are more x-values than y-values } else { // There is at least one y-value for every x-value xinc2 = 0; // Don't change the x for every iteration yinc1 = 0; // Don't change the y when numerator >= denominator den = deltay; num = deltay / 2; numadd = deltax; numpixels = deltay; // There are more y-values than x-values } for( curpixel = 0; curpixel <= numpixels; curpixel++ ) { Display_DrawLine_( x, y, x3, y3, Color ); num += numadd; // Increase the numerator by the top of the fraction if( num >= den ) { // Check if numerator >= denominator num -= den; // Calculate the new numerator value x += xinc1; // Change the x as appropriate y += yinc1; // Change the y as appropriate } x += xinc2; // Change the x as appropriate y += yinc2; // Change the y as appropriate } } /************************************************************************************************************* Display: High level with Select/Deselect **************************************************************************************************************/ void Display_On( void ) { if( !Display_Select() ) return; Display_WriteCommand( 0x29 ); Display_WriteCommand( 0x11 ); Display_Deselect(); } void Display_Off( void ) { if( !Display_Select() ) return; Display_WriteCommand( 0xbd ); Display_WriteData( 0xfe ); Display_WriteCommand( 0x10 ); Display_Deselect(); } void Display_Clear( uint16_t Color ) { if( !Display_Select() ) return; Display_Clear_( Color ); Display_Deselect(); } void Display_DrawPixel( uint16_t x, uint16_t y, uint16_t Color ) { if( !Display_Select() ) return; Display_DrawPixel_( x, y, Color ); Display_Deselect(); } uint16_t Display_ReadPixel( uint16_t x, uint16_t y ) { uint16_t Color; if( !Display_Select() ) return 0; Display_SetCursor_( x, y ); Display_WriteCommand( 0x2e ); Color = Display_ReadData(); Display_Deselect(); return Color; } uint16_t Display_GetStringWidth( FONT_TypeDef *Font, char *String ) { return (uint16_t) strlen(String)*Font->Width; } uint16_t Display_GetFontCharHeight( FONT_TypeDef *Font ) { return Font->Height; } void Display_PrintString( uint16_t x, uint16_t y, uint16_t ColorFront, uint16_t ColorBack, FONT_TypeDef *Font, char *String ) { if( !Display_Select() ) return; Display_PrintString_( x, y, ColorFront, ColorBack, Font, String ); Display_Deselect(); } void Display_Printf( uint16_t x, uint16_t y, uint16_t ColorFront, uint16_t ColorBack, FONT_TypeDef *Font, char *Format, ... ) { va_list Args; va_start( Args, Format ); if( !Display_Select() ) return; vsnprintf( Display_LineBuffer, sizeof(Display_LineBuffer), Format, Args ); va_end( Args ); Display_PrintString_( x, y, ColorFront, ColorBack, Font, Display_LineBuffer ); Display_Deselect(); } void Display_DrawLine( uint16_t x1, uint16_t y1, uint16_t x2, uint16_t y2, uint16_t Color ) { if( !Display_Select() ) return; Display_DrawLine_( x1, y1, x2, y2, Color ); Display_Deselect(); } void Display_DrawRect( uint16_t x, uint16_t y, uint16_t Width, uint16_t Height, uint16_t Color ) { if( !Display_Select() ) return; Display_DrawHLine_( x, y, Width, Color ); Display_DrawHLine_( x, (y+ Height), Width, Color ); Display_DrawVLine_( x, y, Height, Color ); Display_DrawVLine_( (x + Width), y, Height, Color ); Display_Deselect(); } void Display_FillRect( uint16_t x, uint16_t y, uint16_t Width, uint16_t Height, uint16_t Color ) { uint16_t i; if( !Display_Select() ) return; for( i = 0; i < Height ; i ++ ) { Display_DrawHLine_( x, y+i, Width, Color ); } Display_Deselect(); } void Display_DrawCircle( uint16_t x, uint16_t y, uint16_t Radius, uint16_t Color ) { int32_t decision; uint32_t current_x; uint32_t current_y; if( !Display_Select() ) return; decision = 3 - (Radius << 1); current_x = 0; current_y = Radius; while (current_x <= current_y) { Display_DrawPixel_((x + current_x), (y - current_y), Color); Display_DrawPixel_((x - current_x), (y - current_y), Color); Display_DrawPixel_((x + current_y), (y - current_x), Color); Display_DrawPixel_((x - current_y), (y - current_x), Color); Display_DrawPixel_((x + current_x), (y + current_y), Color); Display_DrawPixel_((x - current_x), (y + current_y), Color); Display_DrawPixel_((x + current_y), (y + current_x), Color); Display_DrawPixel_((x - current_y), (y + current_x), Color); if (decision < 0) { decision += (current_x << 2) + 6; } else { decision += ((current_x - current_y) << 2) + 10; current_y--; } current_x++; } Display_Deselect(); } void Display_FillCircle( uint16_t x, uint16_t y, uint16_t Radius, uint16_t Color ) { int32_t decision; uint32_t current_x; uint32_t current_y; decision = 3 - (Radius << 1); current_x = 0; current_y = Radius; if( !Display_Select() ) return; while (current_x <= current_y) { if(current_y > 0) { Display_DrawHLine_( x - current_y, y + current_x, 2*current_y, Color ); Display_DrawHLine_( x - current_y, y - current_x, 2*current_y, Color ); } if(current_x > 0) { Display_DrawHLine_( x - current_x, y - current_y, 2*current_x, Color ); Display_DrawHLine_( x - current_x, y + current_y, 2*current_x, Color ); } if (decision < 0) { decision += (current_x << 2) + 6; } else { decision += ((current_x - current_y) << 2) + 10; current_y--; } current_x++; } Display_Deselect(); Display_DrawCircle( x, y, Radius, Color ); } void Display_DrawEllipse( uint16_t x, uint16_t y, uint16_t xRadius, uint16_t yRadius, uint16_t Color ) { int16_t xCur = 0, yCur = -yRadius, err = 2-2*xRadius, e2; float k = 0, rad1 = 0, rad2 = 0; rad1 = xRadius; rad2 = yRadius; k = (float)(rad2/rad1); if( !Display_Select() ) return; while (yCur <= 0) { Display_DrawPixel_((x-(uint16_t)(xCur/k)), (y+yCur), Color); Display_DrawPixel_((x+(uint16_t)(xCur/k)), (y+yCur), Color); Display_DrawPixel_((x+(uint16_t)(xCur/k)), (y-yCur), Color); Display_DrawPixel_((x-(uint16_t)(xCur/k)), (y-yCur), Color); e2 = err; if (e2 <= xCur) { err += ++xCur*2+1; if (-yCur == xCur && e2 <= yCur) e2 = 0; } if (e2 > yCur) err += ++yCur*2+1; } Display_Deselect(); } void Display_FillEllipse( uint16_t x, uint16_t y, uint16_t xRadius, uint16_t yRadius, uint16_t Color ) { int16_t xCur = 0, yCur = -yRadius, err = 2-2*xRadius, e2; float k = 0, rad1 = 0, rad2 = 0; rad1 = xRadius; rad2 = yRadius; k = (float)(rad2/rad1); if( !Display_Select() ) return; while (yCur <= 0) { Display_DrawHLine_((x-(uint16_t)(xCur/k)), (y+yCur), (2*(uint16_t)(xCur/k) + 1), Color ); Display_DrawHLine_((x-(uint16_t)(xCur/k)), (y-yCur), (2*(uint16_t)(xCur/k) + 1), Color ); e2 = err; if (e2 <= xCur) { err += ++xCur*2+1; if (-yCur == xCur && e2 <= yCur) e2 = 0; } if (e2 > yCur) err += ++yCur*2+1; } Display_Deselect(); } void Display_DrawPolygon( DISPLAY_POINT_TypeDef *Points, uint16_t PointCount, uint16_t Color ) { int16_t x = 0, y = 0; if(PointCount < 2) { return; } if( !Display_Select() ) return; Display_DrawLine_( Points->x, Points->y, (Points+PointCount-1)->x, (Points+PointCount-1)->y, Color ); while(--PointCount) { x = Points->x; y = Points->y; Points++; Display_DrawLine_( x, y, Points->x, Points->y, Color ); } Display_Deselect(); } void Display_FillTriangle( uint16_t x1, uint16_t x2, uint16_t x3, uint16_t y1, uint16_t y2, uint16_t y3, uint16_t Color ) { if( !Display_Select() ) return; Display_FillTriangle_( x1, x2, x3, y1, y2, y3, Color ); Display_Deselect(); } void Display_FillPolygon( DISPLAY_POINT_TypeDef *Points, uint16_t PointCount, uint16_t Color ) { int16_t X = 0, Y = 0, X2 = 0, Y2 = 0, X_center = 0, Y_center = 0, X_first = 0, Y_first = 0, pixelX = 0, pixelY = 0, counter = 0; uint16_t IMAGE_LEFT = 0, IMAGE_RIGHT = 0, IMAGE_TOP = 0, IMAGE_BOTTOM = 0; IMAGE_LEFT = IMAGE_RIGHT = Points->x; IMAGE_TOP= IMAGE_BOTTOM = Points->y; for(counter = 1; counter < PointCount; counter++) { pixelX = Points[counter].x; if(pixelX < IMAGE_LEFT) { IMAGE_LEFT = pixelX; } if(pixelX > IMAGE_RIGHT) { IMAGE_RIGHT = pixelX; } pixelY = Points[counter].y; if(pixelY < IMAGE_TOP) { IMAGE_TOP = pixelY; } if(pixelY > IMAGE_BOTTOM) { IMAGE_BOTTOM = pixelY; } } if(PointCount < 2) { return; } X_center = (IMAGE_LEFT + IMAGE_RIGHT)/2; Y_center = (IMAGE_BOTTOM + IMAGE_TOP)/2; X_first = Points->x; Y_first = Points->y; if( !Display_Select() ) return; while( --PointCount ) { X = Points->x; Y = Points->y; Points++; X2 = Points->x; Y2 = Points->y; Display_FillTriangle_( X, X2, X_center, Y, Y2, Y_center, Color ); Display_FillTriangle_( X, X_center, X2, Y, Y_center, Y2, Color ); Display_FillTriangle_( X_center, X2, X, Y_center, Y2, Y, Color); } Display_FillTriangle_( X_first, X2, X_center, Y_first, Y2, Y_center, Color ); Display_FillTriangle_( X_first, X_center, X2, Y_first, Y_center, Y2, Color ); Display_FillTriangle_( X_center, X2, X_first, Y_center, Y2, Y_first, Color ); Display_Deselect(); } void Display_Test( void ) { Display_Clear( LCD_COLOR_BLACK ); Display_PrintString(0,0,LCD_COLOR_WHITE,LCD_COLOR_BLACK,&FontBig,"Hallo"); Display_DrawLine( 0, 0, Display_GetWidth()-1, Display_GetHeight()-1, LCD_COLOR_BLUE ); Display_DrawLine( 0, Display_GetHeight()-1, Display_GetWidth()-1, 0, LCD_COLOR_BLUE ); Display_DrawLine( 0, 0, Display_GetWidth()-1, 0, LCD_COLOR_GREEN ); Display_DrawLine( 0, 0, 0, Display_GetHeight()-1, LCD_COLOR_GREEN ); Display_DrawLine( 0, 10, Display_GetWidth()-1, 20, LCD_COLOR_RED ); Display_DrawRect( 50, 50, 40, 20, LCD_COLOR_YELLOW ); Display_FillRect( 150, 50, 40, 20, LCD_COLOR_YELLOW ); Display_DrawCircle( 80, 120, 30, LCD_COLOR_MAGENTA ); Display_FillCircle( 180, 120, 30, LCD_COLOR_MAGENTA ); Display_DrawEllipse( 80, 180, 20, 30, LCD_COLOR_CYAN ); Display_FillEllipse( 180, 180, 30, 20, LCD_COLOR_CYAN ); DISPLAY_POINT_TypeDef Points[4] = { {20,20}, {50,10}, {40,40}, {30,50} }; Display_DrawPolygon( Points, 4, LCD_COLOR_LIGHTBLUE ); uint8_t i; for( i=0; i<4; i++ ) { Points[i].x += 100; } Display_FillPolygon( Points, 4, LCD_COLOR_LIGHTBLUE ); } void Display_Init( void ) { // Backlight control signal assertion: HAL_GPIO_WritePin(GPIOH, GPIO_PIN_11, GPIO_PIN_SET); // Apply hardware reset according to procedure indicated in FRD154BP2901 documentation: HAL_GPIO_WritePin(LCD_RST_GPIO_Port, LCD_RST_Pin, GPIO_PIN_RESET); HAL_Delay(5); HAL_GPIO_WritePin(LCD_RST_GPIO_Port, LCD_RST_Pin, GPIO_PIN_SET); HAL_Delay(10); HAL_GPIO_WritePin(LCD_RST_GPIO_Port, LCD_RST_Pin, GPIO_PIN_RESET); HAL_Delay(20); HAL_GPIO_WritePin(LCD_RST_GPIO_Port, LCD_RST_Pin, GPIO_PIN_SET); HAL_Delay(10); Display_InitFmc(); uint8_t DisplayId = Display_ReadReg(0x04); if( DisplayId == 0x85 ) { Display_WriteCommandList( InitCmd ); Display_SetOrientation( LCD_ORIENTATION_LANDSCAPE_ROT180 ); Display_Clear_( LCD_COLOR_BLACK ); // Use variant without select/deselect to ignore OS and Mutex here! } /* ToDo: Create Mutex */ }