/*! \file gd32f20x_lcd_eval.c \brief LCD driver functions \version 2015-07-15, V1.0.0, firmware for GD32F20x \version 2017-06-05, V2.0.0, firmware for GD32F20x \version 2018-10-31, V2.1.0, firmware for GD32F20x */ /* Copyright (c) 2018, GigaDevice Semiconductor Inc. All rights reserved. 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 the copyright holder 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 "gd32f20x_lcd_eval.h" #include "gd32f20x_sdram_eval.h" #include "gd32f20x_tli.h" #include #define LCD_FRAME_BUFFER ((uint32_t)0xC0000000) #define BUFFER_OFFSET ((uint32_t)0x7F800) #define LCD_DEFAULT_FONT Font16x24 static sFONT *current_font; static uint16_t current_textcolor = 0x0000; static uint16_t current_backcolor = 0xFFFF; static uint32_t current_framebuffer = LCD_FRAME_BUFFER; static uint32_t current_layer = LCD_LAYER_BACKGROUND; static void pixel_set(int16_t x, int16_t y); #define HORIZONTAL_SYNCHRONOUS_PULSE 41 #define HORIZONTAL_BACK_PORCH 2 #define ACTIVE_WIDTH 480 #define HORIZONTAL_FRONT_PORCH 2 #define VERTICAL_SYNCHRONOUS_PULSE 10 #define VERTICAL_BACK_PORCH 2 #define ACTIVE_HEIGHT 272 #define VERTICAL_FRONT_PORCH 2 /*! \brief initialize the LCD GPIO and TLI \param[in] none \param[out] none \retval none */ void lcd_init(void) { tli_parameter_struct tli_init_struct; /* GPIO clock enable */ rcu_periph_clock_enable(RCU_GPIOE); rcu_periph_clock_enable(RCU_GPIOF); rcu_periph_clock_enable(RCU_GPIOG); rcu_periph_clock_enable(RCU_GPIOH); rcu_periph_clock_enable(RCU_GPIOI); rcu_periph_clock_enable(RCU_AF); /* TLI GPIO pin remap configuration */ gpio_pin_remap1_config(GPIO_PCF3, GPIO_PCF3_TLI_B3_PG11_REMAP | GPIO_PCF3_TLI_B2_PG10_REMAP | GPIO_PCF3_TLI_CLK_PG7_REMAP | GPIO_PCF3_TLI_R7_PG6_REMAP | GPIO_PCF3_TLI_DE_PF10_REMAP | GPIO_PCF3_TLI_B0_PE4_REMAP | GPIO_PCF3_TLI_G0_PE5_REMAP | GPIO_PCF3_TLI_G1_PE6_REMAP | GPIO_PCF3_TLI_R2_PC10_REMAP, ENABLE); gpio_pin_remap1_config(GPIO_PCF4, GPIO_PCF4_TLI_HSYNC_PI10_REMAP | GPIO_PCF4_TLI_VSYNC_PI9_REMAP | GPIO_PCF4_TLI_B7_PI7_REMAP | GPIO_PCF4_TLI_B6_PI6_REMAP | GPIO_PCF4_TLI_B5_PI5_REMAP | GPIO_PCF4_TLI_B4_PI4_REMAP | GPIO_PCF4_TLI_G7_PI2_REMAP | GPIO_PCF4_TLI_R1_PI3_REMAP | GPIO_PCF4_TLI_G6_PI1_REMAP | GPIO_PCF4_TLI_G5_PI0_REMAP | GPIO_PCF4_TLI_G4_PH15_REMAP | GPIO_PCF4_TLI_G3_PH14_REMAP | GPIO_PCF4_TLI_G2_PH13_REMAP | GPIO_PCF4_TLI_R6_PH12_REMAP | GPIO_PCF4_TLI_R5_PH11_REMAP | GPIO_PCF4_TLI_R4_PH10_REMAP | GPIO_PCF4_TLI_R3_PH9_REMAP | GPIO_PCF4_TLI_R0_PH4_REMAP | GPIO_PCF4_TLI_B1_PG12_REMAP, ENABLE); /* configure HSYNC(PI10), VSYNC(PI9), PCLK(PG7) */ /* configure LCD_R7(PG6), LCD_R6(PH12), LCD_R5(PH11), LCD_R4(PH10), LCD_R3(PH9),LCD_R2(PC10), LCD_R1(PI3), LCD_R0(PH4), LCD_G7(PI2), LCD_G6(PI1), LCD_G5(PI0), LCD_G4(PH15), LCD_G3(PH14), LCD_G2(PH13),LCD_G1(PE6), LCD_G0(PE5),LCD_B7(PI7), LCD_B6(PI6), LCD_B5(PI5), LCD_B4(PI4), LCD_B3(PG11),LCD_B2(PG10), LCD_B1(PG12), LCD_B0(PE4), LCD_CLK(PG7), LCD_HSYNC(PI10), LCD_VSYNC(PI9), LCD_DE(PF10) */ gpio_init(GPIOE,GPIO_MODE_AF_PP,GPIO_OSPEED_50MHZ,GPIO_PIN_4 | GPIO_PIN_5 | GPIO_PIN_6); gpio_init(GPIOH,GPIO_MODE_AF_PP,GPIO_OSPEED_50MHZ,GPIO_PIN_4 | GPIO_PIN_8 |GPIO_PIN_9 | GPIO_PIN_10 | GPIO_PIN_11 | GPIO_PIN_12| GPIO_PIN_13 | GPIO_PIN_14 | GPIO_PIN_15); gpio_init(GPIOI,GPIO_MODE_AF_PP,GPIO_OSPEED_50MHZ,GPIO_PIN_0 | GPIO_PIN_1 | GPIO_PIN_2 | GPIO_PIN_3 | GPIO_PIN_4 | GPIO_PIN_5 | GPIO_PIN_6 | GPIO_PIN_7 | GPIO_PIN_9 | GPIO_PIN_10); gpio_init(GPIOG,GPIO_MODE_AF_PP,GPIO_OSPEED_50MHZ,GPIO_PIN_6 | GPIO_PIN_7 | GPIO_PIN_10 | GPIO_PIN_11 | GPIO_PIN_12); gpio_init(GPIOF,GPIO_MODE_AF_PP,GPIO_OSPEED_50MHZ,GPIO_PIN_10); gpio_init(GPIOC,GPIO_MODE_AF_PP,GPIO_OSPEED_50MHZ,GPIO_PIN_10); /* back light */ gpio_init(GPIOH, GPIO_MODE_OUT_PP,GPIO_OSPEED_50MHZ,GPIO_PIN_6); gpio_bit_set(GPIOH,GPIO_PIN_6); rcu_periph_clock_enable(RCU_TLI); /* configure the TLI clock to generate lcd clock */ rcu_pllt_config(RCU_PLLTSRC_HXTAL); #ifdef __CC_ARM if(ERROR == rcu_pllt_vco_config(25, 192, 3)){ while(1); } #endif /* __CC_ARM */ #ifdef __IAR_SYSTEMS_ICC__ if(ERROR == rcu_pllt_vco_config(25, 192, 6)){ while(1); } #endif /* __IAR_SYSTEMS_ICC__ */ rcu_tli_clock_config(RCU_CKTLI_CKPLLTR_DIV8); rcu_osci_on(RCU_PLLT_CK); if(ERROR == rcu_osci_stab_wait(RCU_PLLT_CK)){ while(1); } /* config the EXMC access mode */ exmc_synchronous_dynamic_ram_init(EXMC_SDRAM_DEVICE0); /* TLI initialization */ tli_init_struct.signalpolarity_hs = TLI_HSYN_ACTLIVE_LOW; tli_init_struct.signalpolarity_vs = TLI_VSYN_ACTLIVE_LOW; tli_init_struct.signalpolarity_de = TLI_DE_ACTLIVE_LOW; tli_init_struct.signalpolarity_pixelck = TLI_PIXEL_CLOCK_TLI; /* LCD display timing configuration */ tli_init_struct.synpsz_hpsz = HORIZONTAL_SYNCHRONOUS_PULSE - 1; tli_init_struct.synpsz_vpsz = VERTICAL_SYNCHRONOUS_PULSE - 1; tli_init_struct.backpsz_hbpsz = HORIZONTAL_SYNCHRONOUS_PULSE + HORIZONTAL_BACK_PORCH - 1; tli_init_struct.backpsz_vbpsz = VERTICAL_SYNCHRONOUS_PULSE + VERTICAL_BACK_PORCH - 1; tli_init_struct.activesz_hasz = HORIZONTAL_SYNCHRONOUS_PULSE + HORIZONTAL_BACK_PORCH + ACTIVE_WIDTH - 1; tli_init_struct.activesz_vasz = VERTICAL_SYNCHRONOUS_PULSE + VERTICAL_BACK_PORCH + ACTIVE_HEIGHT - 1; tli_init_struct.totalsz_htsz = HORIZONTAL_SYNCHRONOUS_PULSE + HORIZONTAL_BACK_PORCH + ACTIVE_WIDTH + HORIZONTAL_FRONT_PORCH - 1; tli_init_struct.totalsz_vtsz = VERTICAL_SYNCHRONOUS_PULSE + VERTICAL_BACK_PORCH + ACTIVE_HEIGHT + VERTICAL_FRONT_PORCH - 1; /* LCD background color configure*/ tli_init_struct.backcolor_red = 0xFF; tli_init_struct.backcolor_green = 0xFF; tli_init_struct.backcolor_blue = 0xFF; tli_init(&tli_init_struct); } /*! \brief initialize TLI layer0 or layer1 \param[in] layer: LCD layer \arg LCD_LAYER_BACKGROUND \arg LCD_LAYER_FOREGROUND \param[in] width: width of the window \param[in] height: height of the window \param[out] none \retval none */ void lcd_layer_init(uint32_t layer, uint32_t width, uint32_t height) { tli_layer_parameter_struct tli_layer_init_struct; if(LCD_LAYER_BACKGROUND == layer){ /* TLI layer0 configuration */ tli_layer_init_struct.layer_window_leftpos = (HORIZONTAL_SYNCHRONOUS_PULSE + HORIZONTAL_BACK_PORCH); tli_layer_init_struct.layer_window_rightpos = (width + HORIZONTAL_SYNCHRONOUS_PULSE + HORIZONTAL_BACK_PORCH - 1); tli_layer_init_struct.layer_window_toppos = (VERTICAL_SYNCHRONOUS_PULSE + VERTICAL_BACK_PORCH); tli_layer_init_struct.layer_window_bottompos = (height + VERTICAL_SYNCHRONOUS_PULSE + VERTICAL_BACK_PORCH - 1); tli_layer_init_struct.layer_ppf = LAYER_PPF_RGB565; tli_layer_init_struct.layer_sa = 0xFF; tli_layer_init_struct.layer_default_blue = 0xFF; tli_layer_init_struct.layer_default_green = 0xFF; tli_layer_init_struct.layer_default_red = 0xFF; tli_layer_init_struct.layer_default_alpha = 0xFF; tli_layer_init_struct.layer_acf1 = LAYER_ACF1_PASA; tli_layer_init_struct.layer_acf2 = LAYER_ACF2_PASA; tli_layer_init_struct.layer_frame_bufaddr = LCD_FRAME_BUFFER; tli_layer_init_struct.layer_frame_line_length = ((width * 2) + 3); tli_layer_init_struct.layer_frame_buf_stride_offset = (width * 2); tli_layer_init_struct.layer_frame_total_line_number = height; tli_layer_init(LAYER0, &tli_layer_init_struct); }else if(LCD_LAYER_FOREGROUND == layer){ /* TLI layer1 configuration */ tli_layer_init_struct.layer_window_leftpos = (HORIZONTAL_SYNCHRONOUS_PULSE + HORIZONTAL_BACK_PORCH); tli_layer_init_struct.layer_window_rightpos = (width + HORIZONTAL_SYNCHRONOUS_PULSE + HORIZONTAL_BACK_PORCH - 1); tli_layer_init_struct.layer_window_toppos = (VERTICAL_SYNCHRONOUS_PULSE + VERTICAL_BACK_PORCH); tli_layer_init_struct.layer_window_bottompos = (height + VERTICAL_SYNCHRONOUS_PULSE + VERTICAL_BACK_PORCH - 1); tli_layer_init_struct.layer_ppf = LAYER_PPF_RGB565; tli_layer_init_struct.layer_sa = 0xFF; tli_layer_init_struct.layer_default_blue = 0xFF; tli_layer_init_struct.layer_default_green = 0xFF; tli_layer_init_struct.layer_default_red = 0xFF; tli_layer_init_struct.layer_default_alpha = 0x0; tli_layer_init_struct.layer_acf1 = LAYER_ACF1_PASA; tli_layer_init_struct.layer_acf2 = LAYER_ACF2_PASA; tli_layer_init_struct.layer_frame_bufaddr = LCD_FRAME_BUFFER + BUFFER_OFFSET; tli_layer_init_struct.layer_frame_line_length = ((width * 2) + 3); tli_layer_init_struct.layer_frame_buf_stride_offset = (width * 2); tli_layer_init_struct.layer_frame_total_line_number = height; tli_layer_init(LAYER1, &tli_layer_init_struct); } tli_reload_config(TLI_REQUEST_RELOAD_EN); lcd_font_set(&LCD_DEFAULT_FONT); } /*! \brief enable the LCD layer0 or layer1 \param[in] layer: LCD layer \arg LCD_LAYER_BACKGROUND \arg LCD_LAYER_FOREGROUND \param[out] none \retval none */ void lcd_layer_enable(uint32_t layer) { if(LCD_LAYER_BACKGROUND == layer){ tli_layer_enable(LAYER0); }else if(LCD_LAYER_FOREGROUND == layer){ tli_layer_enable(LAYER1); } tli_enable(); } /*! \brief set the LCD layer \param[in] layer: LCD layer \arg LCD_LAYER_BACKGROUND \arg LCD_LAYER_FOREGROUND \param[out] none \retval none */ void lcd_layer_set(uint32_t layer) { if (LCD_LAYER_BACKGROUND == layer){ current_framebuffer = LCD_FRAME_BUFFER; current_layer = LCD_LAYER_BACKGROUND; }else{ current_framebuffer = LCD_FRAME_BUFFER + BUFFER_OFFSET; current_layer = LCD_LAYER_FOREGROUND; } } /*! \brief set the transparency of LCD \param[in] trans: transparency of LCD, from 0 to 255 \param[out] none \retval none */ void lcd_transparency_set(uint8_t trans) { if (LCD_LAYER_BACKGROUND == current_layer){ TLI_LxSA(LAYER0) &= ~(TLI_LxSA_SA); TLI_LxSA(LAYER0) = trans; }else{ TLI_LxSA(LAYER1) &= ~(TLI_LxSA_SA); TLI_LxSA(LAYER1) = trans; } tli_reload_config(TLI_REQUEST_RELOAD_EN); } /*! \brief configure the packeted pixel format \param[in] pixel_format: pixel format \arg LAYER_PPF_ARGB8888 \arg LAYER_PPF_RGB888 \arg LAYER_PPF_RGB565 \arg LAYER_PPF_ARGB1555 \arg LAYER_PPF_ARGB4444 \arg LAYER_PPF_L8 \arg LAYER_PPF_AL44 \arg LAYER_PPF_AL88 \param[out] none \retval none */ void lcd_pixel_format_config(uint32_t pixel_format) { if(LCD_LAYER_BACKGROUND == current_layer){ TLI_LxPPF(LAYER0) &= ~(TLI_LxPPF_PPF); TLI_LxPPF(LAYER0) = pixel_format; }else{ TLI_LxPPF(LAYER1) &= ~(TLI_LxPPF_PPF); TLI_LxPPF(LAYER1) = pixel_format; } } /*! \brief configure the frame buffer base address \param[in] address: frame buffer base address \param[out] none \retval none */ void lcd_address_config(uint32_t address) { if (LCD_LAYER_BACKGROUND == current_layer){ TLI_LxFBADDR(LAYER0) &= ~(TLI_LxFBADDR_FBADD); TLI_LxFBADDR(LAYER0) = address; }else{ TLI_LxFBADDR(LAYER1) &= ~(TLI_LxFBADDR_FBADD); TLI_LxFBADDR(LAYER1) = address; } tli_reload_config(TLI_REQUEST_RELOAD_EN); } /*! \brief clear the LCD with specified color \param[in] color: LCD color \arg LCD_COLOR_WHITE \arg LCD_COLOR_BLACK \arg LCD_COLOR_GREY \arg LCD_COLOR_BLUE \arg LCD_COLOR_BLUE2 \arg LCD_COLOR_RED \arg LCD_COLOR_MAGENTA \arg LCD_COLOR_GREEN \arg LCD_COLOR_CYAN \arg LCD_COLOR_YELLOW \param[out] none \retval none */ void lcd_clear(uint16_t color) { uint32_t index = 0; for (index = 0x00; index < BUFFER_OFFSET; index++){ *(__IO uint16_t*)(current_framebuffer + (2*index)) = color; } } /*! \brief set the text font \param[in] font: the text font \param[out] none \retval none */ void lcd_font_set(sFONT *font) { current_font = font; } /*! \brief get the text font \param[in] none \param[out] none \retval the text font */ sFONT* lcd_font_get(void) { return current_font; } /*! \brief set the text color \param[in] color: LCD color \arg LCD_COLOR_WHITE \arg LCD_COLOR_BLACK \arg LCD_COLOR_GREY \arg LCD_COLOR_BLUE \arg LCD_COLOR_BLUE2 \arg LCD_COLOR_RED \arg LCD_COLOR_MAGENTA \arg LCD_COLOR_GREEN \arg LCD_COLOR_CYAN \arg LCD_COLOR_YELLOW \param[out] none \retval none */ void lcd_text_color_set(uint16_t color) { current_textcolor = color; } /*! \brief get the current text color \param[in] none \param[out] none \retval LCD color \arg LCD_COLOR_WHITE \arg LCD_COLOR_BLACK \arg LCD_COLOR_GREY \arg LCD_COLOR_BLUE \arg LCD_COLOR_BLUE2 \arg LCD_COLOR_RED \arg LCD_COLOR_MAGENTA \arg LCD_COLOR_GREEN \arg LCD_COLOR_CYAN \arg LCD_COLOR_YELLOW */ uint16_t lcd_text_color_get(void) { return current_textcolor; } /*! \brief set the background color \param[in] color: LCD color \arg LCD_COLOR_WHITE \arg LCD_COLOR_BLACK \arg LCD_COLOR_GREY \arg LCD_COLOR_BLUE \arg LCD_COLOR_BLUE2 \arg LCD_COLOR_RED \arg LCD_COLOR_MAGENTA \arg LCD_COLOR_GREEN \arg LCD_COLOR_CYAN \arg LCD_COLOR_YELLOW \param[out] none \retval none */ void lcd_background_color_set(uint16_t color) { current_backcolor = color; } /*! \brief get the current background color \param[in] none \param[out] none \retval LCD color \arg LCD_COLOR_WHITE \arg LCD_COLOR_BLACK \arg LCD_COLOR_GREY \arg LCD_COLOR_BLUE \arg LCD_COLOR_BLUE2 \arg LCD_COLOR_RED \arg LCD_COLOR_MAGENTA \arg LCD_COLOR_GREEN \arg LCD_COLOR_CYAN \arg LCD_COLOR_YELLOW */ uint16_t lcd_background_color_get(void) { return current_backcolor; } /*! \brief set point with the specified position and color \param[in] xpos: position of x \param[in] ypos: position of y \param[in] color: LCD color \arg LCD_COLOR_WHITE \arg LCD_COLOR_BLACK \arg LCD_COLOR_GREY \arg LCD_COLOR_BLUE \arg LCD_COLOR_BLUE2 \arg LCD_COLOR_RED \arg LCD_COLOR_MAGENTA \arg LCD_COLOR_GREEN \arg LCD_COLOR_CYAN \arg LCD_COLOR_YELLOW \param[out] none \retval none */ void lcd_point_set(uint16_t xpos, uint16_t ypos, uint16_t color) { *(__IO uint16_t*)(current_framebuffer + 2*((LCD_PIXEL_WIDTH*ypos) + xpos)) = color; } /*! \brief get the color of point with the specified position \param[in] xpos: position of x \param[in] ypos: position of y \param[out] none \retval value of point(x, y) */ uint16_t lcd_point_get(uint16_t xpos, uint16_t ypos) { return *(__IO uint16_t*)(current_framebuffer + 2*((LCD_PIXEL_WIDTH*ypos) + xpos)); } /*! \brief draw a line on LCD \param[in] xpos: position of x \param[in] ypos: position of y \param[in] length: length of line \param[in] line_direction: direction of line \arg LCD_LINEDIR_HORIZONTAL \arg LCD_LINEDIR_VERTICAL \param[out] none \retval none */ void lcd_line_draw(uint16_t xpos, uint16_t ypos, uint16_t length, uint8_t line_direction) { if(LCD_LINEDIR_HORIZONTAL == line_direction){ uint16_t x; for(x = xpos; x < xpos + length; x++){ pixel_set(x, ypos); } }else{ uint16_t y; for(y = ypos; y < ypos + length; y++){ pixel_set(xpos, y); } } } /*! \brief draw a rectangle on LCD \param[in] xpos: position of x \param[in] ypos: position of y \param[in] width: width of rectangle \param[in] height: height of rectangle \param[out] none \retval none */ void lcd_rectangle_draw(uint16_t xpos, uint16_t ypos, uint16_t width, uint16_t height) { /* draw horizontal lines */ lcd_line_draw(xpos, ypos, width, LCD_LINEDIR_HORIZONTAL); lcd_line_draw(xpos, (ypos+ height), width + 1, LCD_LINEDIR_HORIZONTAL); /* draw vertical lines */ lcd_line_draw(xpos, ypos, height, LCD_LINEDIR_VERTICAL); lcd_line_draw((xpos + width), ypos, height, LCD_LINEDIR_VERTICAL); } /*! \brief draw a circle on LCD using Bresenham algorithm \param[in] xpos: position of x \param[in] ypos: position of y \param[in] radius: radius of the circle \param[out] none \retval none */ void lcd_circle_draw(uint16_t xpos, uint16_t ypos, uint16_t radius) { int x, y, e; e = 3-2*radius; x = 0; y = radius; /* set four pixel (x-r, y), (x+r, y), (x, y-r), (x, y-r) */ pixel_set(-radius+xpos, ypos); pixel_set(radius+xpos, ypos); pixel_set(xpos, -radius+ypos); pixel_set(xpos, radius+ypos); while(x <= y){ if(e < 0){ /* choose the right of the current pixel as the next pixel */ e = e+4*x+6; x++; }else{ /* choose the right bottom of the current pixel as the next pixel */ e = e+4*(x-y)+10; x++; y--; } pixel_set(x+xpos, y+ypos); pixel_set(-x+xpos, y+ypos); pixel_set(-x+xpos, -y+ypos); pixel_set(x+xpos, -y+ypos); pixel_set(y+xpos, x+ypos); pixel_set(-y+xpos, x+ypos); pixel_set(-y+xpos, -x+ypos); pixel_set(y+xpos, -x+ypos); } } /*! \brief set plot point of ellipse \param[in] center_x: x position of ellipse center \param[in] center_y: y position of ellipse center \param[in] x: x value \param[in] y: y value \param[out] none \retval none */ static void plotpoint_set(int center_x,int center_y,int x,int y) { pixel_set(center_x+x, center_y+y); pixel_set(center_x-x, center_y+y); pixel_set(center_x+x, center_y-y); pixel_set(center_x-x, center_y-y); } /*! \brief draw a ellipse on LCD using the midpoint ellipse algorithm \param[in] xpos: x position of ellipse center \param[in] ypos: y position of ellipse center \param[in] axis1: major axis \param[in] axis2: minor axis \param[out] none \retval none */ void lcd_ellipse_draw(uint16_t xpos, uint16_t ypos, uint16_t axis1, uint16_t axis2) { int sq_axis1 = axis1*axis1, sq_axis2 = axis2*axis2; int p; int x = 0, y = axis2; int px = 0, py = 2*sq_axis1*y; /* draw four points on the long and short axis of the ellipse */ plotpoint_set(xpos, ypos, x, y); /* calculate the initial value in area 1 */ p = (int)((sq_axis2-(sq_axis1*axis2)+(0.25*sq_axis1))); while(px < py){ ++x; px += 2*sq_axis2; if(p<0){ p += sq_axis2+px; }else{ --y; py -= 2*sq_axis1; p += sq_axis2+px-py; } plotpoint_set(xpos, ypos, x, y); } /* calculate the initial value with the last point calculated in the area 1 */ p = (int)((sq_axis2*(x+0.5)*(x+0.5)+sq_axis1*(y-1)*(y-1)-sq_axis1*sq_axis2)); while(y > 0){ --y; py -= 2*sq_axis1; if(p > 0){ p += sq_axis1-py; }else{ ++x; px += 2*sq_axis2; p += sq_axis1-py+px; } plotpoint_set(xpos, ypos, x, y); } } /*! \brief draw a triangle on LCD \param[in] point: \param[in] point_count: \param[out] none \retval none */ void lcd_triangle_draw(ptr_point point, uint16_t point_count) { } /*! \brief fill the whole rectangle \param[in] xpos: position of x \param[in] ypos: position of y \param[in] width: width of the rectangle \param[in] height: height of the rectangle \param[out] none \retval none */ void lcd_rectangle_fill(uint16_t xpos, uint16_t ypos, uint16_t width, uint16_t height) { uint16_t x, y; for(x = xpos; x < xpos + width; x++){ for(y = ypos; y < ypos + height; y++){ pixel_set(x, y); } } } /*! \brief display the string on LCD \param[in] stringline: line to display the character \arg LCD_LINE_x(x=0..39 for 480*272) \param[in] ptr: a pointer to the string \param[out] none \retval none */ void lcd_string_display(uint16_t stringline, uint8_t *ptr) { uint16_t column = 0; while ((column < LCD_PIXEL_WIDTH) && (*ptr != 0)){ /* display character on LCD */ lcd_char_display(stringline, column, *ptr); column += current_font->Width; ptr++; } } /*! \brief display the vertical string on LCD \param[in] stringline: line to display the character \arg LCD_LINE_x(x=0..39 for 480*272) \param[in] offset: offset value \param[in] ptr: a pointer to the string \param[out] none \retval none */ void lcd_vertical_string_display(uint16_t stringline, uint16_t offset, uint8_t *ptr) { uint16_t column = LCD_PIXEL_HEIGHT - (current_font->Width + offset + 2); while ((column > 0) && (*ptr != 0)){ /* display character on LCD */ lcd_vertical_char_display(stringline, column, *ptr); column -= current_font->Width; ptr++; } } /*! \brief display the character on LCD \param[in] line: line to display the character \arg LCD_LINE_x(x=0..39 for 480*272) \param[in] column: column address \param[in] ascii: character ascii code(from 0x20 to 0x7E) \param[out] none \retval none */ void lcd_char_display(uint16_t line, uint16_t column, uint8_t ascii) { ascii -= 32; lcd_char_draw(line, column, ¤t_font->table[ascii * current_font->Height]); } /*! \brief display the vertical character on LCD \param[in] line: line to display the character \arg LCD_LINE_x(x=0..39 for 480*272) \param[in] column: column address \param[in] ascii: character ascii code(from 0x20 to 0x7E) \param[out] none \retval none */ void lcd_vertical_char_display(uint16_t line, uint16_t column, uint8_t ascii) { ascii -= 32; lcd_vertical_char_draw(line, column, ¤t_font->table[ascii * current_font->Height]); } /*! \brief draw the character on LCD \param[in] xpos: position of x \param[in] ypos: position of y \param[in] c: a pointer to the character \param[out] none \retval none */ void lcd_char_draw(uint16_t xpos, uint16_t ypos, const uint16_t *c) { uint32_t index = 0, counter = 0, x = 0; uint32_t xaddress = 0; x = xpos * LCD_PIXEL_WIDTH * 2; xaddress += ypos; for(index = 0; index < current_font->Height; index++){ for(counter = 0; counter < current_font->Width; counter++){ if((((c[index] & ((0x80 << ((current_font->Width / 12) * 8)) >> counter)) == 0x00) && (current_font->Width <= 12))|| (((c[index] & (0x1 << counter)) == 0x00) && (current_font->Width > 12))){ /* write the background color */ *(__IO uint16_t*) (current_framebuffer + (2*xaddress) + x) = current_backcolor; }else{ /* write the text color */ *(__IO uint16_t*) (current_framebuffer + (2*xaddress) + x) = current_textcolor; } xaddress++; } xaddress += (LCD_PIXEL_WIDTH - current_font->Width); } } /*! \brief draw the vertical character on LCD \param[in] xpos: position of x \param[in] ypos: position of y \param[in] c: a pointer to the character \param[out] none \retval none */ void lcd_vertical_char_draw(uint16_t xpos, uint16_t ypos, const uint16_t *c) { uint32_t index = 0, counter = 0; for(index = 0; index < current_font->Height; index++){ for(counter = 0; counter < current_font->Width; counter++){ if((((c[index] & ((0x80 << ((current_font->Width / 12) * 8)) >> counter)) == 0x00) && (current_font->Width <= 12))|| (((c[index] & (0x1 << counter)) == 0x00) && (current_font->Width > 12))){ }else{ pixel_set(xpos + index, ypos + current_font->Width - counter); } } } } /*! \brief set a pixel \param[in] x: x position \param[in] y: y position \param[out] none \retval none */ static void pixel_set(int16_t x, int16_t y) { if(x < 0 || x > (LCD_PIXEL_WIDTH - 1) || y < 0 || y > (LCD_PIXEL_HEIGHT - 1)){ return; } /* draw pixel with current text color */ *(__IO uint16_t*)(current_framebuffer + 2*((LCD_PIXEL_WIDTH*y) + x)) = current_textcolor; }