2025-12-02 12:18:48 +01:00

823 lines
25 KiB
C

/*******************************************************************
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 <string.h>
#include <stdarg.h>
#include <stdio.h>
#include "FreeRTOS.h"
#include "semphr.h"
/* 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; }
SemaphoreHandle_t Mutex_Display = NULL;
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 ) {
xSemaphoreTake(Mutex_Display, portMAX_DELAY);
return 1; // OK
}
// Display_Deselect: Called after any access to the display.
void Display_Deselect( void ) {
xSemaphoreGive(Mutex_Display);
}
/*************************************************************************************************************
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!
}
Mutex_Display = xSemaphoreCreateMutex();
}