/* * Copyright (c) 2006-2021, RT-Thread Development Team * * SPDX-License-Identifier: Apache-2.0 * * Change Logs: * Date Author Notes * 2011-03-05 lgnq ZYMG12864C3 LCD driver */ #include #include #include "lcd.h" #include "font.h" static struct rt_device_graphic_info _lcd_info; static rt_uint8_t gui_disp_buf[GUI_LCM_YMAX/8][GUI_LCM_XMAX]; const unsigned char BIT_MASK[8] = {0x80, 0x40, 0x20, 0x10, 0x08, 0x04, 0x02, 0x01}; /* simple font: ' ', '0'~'9','a'~'z','A'~'Z' */ extern const unsigned char FONTTYPE8_8[][8]; rt_uint32_t x; rt_uint32_t y; void power_delay(void) { rt_uint32_t i = 0x4ffff; while(i--) ; } void delay(void) { rt_uint8_t i = 0x8; while(i--) ; } void reset_delay(void) { rt_uint8_t i = 0xff; while(i--) ; } void lcd_write_cmd(unsigned char command) { rt_uint8_t i; LCD_PS_LOW(); LCD_CS_LOW(); LCD_CD_LOW(); for (i=0; i<8; i++) { if (command & (0x80 >> i)) LCD_DATA_HIGH(); else LCD_DATA_LOW(); LCD_CLK_LOW(); delay(); LCD_CLK_HIGH(); delay(); } LCD_CS_HIGH(); } void lcd_write_data(unsigned char data) { rt_uint8_t i; LCD_PS_LOW(); LCD_CS_LOW(); LCD_CD_HIGH(); for (i=0; i<8; i++) { if (data & (0x80 >> i)) LCD_DATA_HIGH(); else LCD_DATA_LOW(); LCD_CLK_LOW(); delay(); LCD_CLK_HIGH(); delay(); } LCD_CS_HIGH(); } #ifdef RT_USING_RTGUI #include #include static void rt_hw_lcd_update(struct rt_device_rect_info *rect_info) { rt_uint8_t i,j = GUI_LCM_XMAX; rt_uint8_t* p = (rt_uint8_t*)gui_disp_buf; for (i=0; i> 4; lcd_write_cmd(SET_PAGE_ADDR_0 | page); lcd_write_cmd(SET_COLH_ADDR_0 | colh); lcd_write_cmd(SET_COLL_ADDR_0 | coll); lcd_write_data(gui_disp_buf[page][i]); } } const struct rtgui_graphic_driver_ops _lcd_ops = { rt_hw_lcd_set_pixel, rt_hw_lcd_get_pixel, rt_hw_lcd_draw_hline, rt_hw_lcd_draw_vline, rt_hw_lcd_draw_raw_hline }; #endif void lcd_io_init() { /* Release the analog input function*/ FM3_GPIO->ADE =0x03; /*Select CPIO function*/ LCD_CS_PFR &= ~LCD_CS; /*Make pin output*/ LCD_CS_DDR |= LCD_CS; /*Select CPIO function*/ LCD_CD_PFR &= ~LCD_CD; /*Make pin output*/ LCD_CD_DDR |= LCD_CD; /*Select CPIO function*/ LCD_PS_PFR &= ~LCD_PS; /*Make pin output*/ LCD_PS_DDR |= LCD_PS; /*Select CPIO function*/ LCD_CLK_PFR &= ~LCD_CLK; /*Make pin output*/ LCD_CLK_DDR |= LCD_CLK; /*Select CPIO function*/ LCD_DATA_PFR &= ~LCD_DATA; /*Make pin output*/ LCD_DATA_DDR |= LCD_DATA; } /* RT-Thread Device Interface */ static rt_err_t rt_lcd_init (rt_device_t dev) { lcd_io_init(); power_delay(); lcd_write_cmd(DISPLAY_OFF); reset_delay(); // Resetting circuit lcd_write_cmd(RESET_LCD); reset_delay(); // LCD bias setting lcd_write_cmd(SET_LCD_BIAS_9); reset_delay(); // ADC selection: display from left to right lcd_write_cmd(SET_ADC_NORMAL); reset_delay(); // Common output state selection: display from up to down lcd_write_cmd(COM_SCAN_DIR_REVERSE); reset_delay(); lcd_write_cmd(POWER_BOOSTER_ON); power_delay(); // 50ms requried lcd_write_cmd(POWER_REGULATOR_ON); power_delay(); // 50ms lcd_write_cmd(POWER_FOLLOWER_ON); power_delay(); // 50ms // Setting the built-in resistance radio for regulation of the V0 voltage // Electronic volume control // Power control setting lcd_write_cmd(SET_ELECVOL_REG|0x05); delay(); lcd_write_cmd(SET_ELECVOL_MODE); delay(); lcd_write_cmd(SET_ELECVOL_REG); delay(); // LCD_Clear(); delay(); lcd_write_cmd(SET_PAGE_ADDR_0); delay(); lcd_write_cmd(SET_COLH_ADDR_0); delay(); lcd_write_cmd(SET_COLL_ADDR_0); delay(); lcd_write_cmd(DISPLAY_ON); delay(); lcd_write_cmd(DISPLAY_ALL_ON); delay(); lcd_write_cmd(DISPLAY_OFF); delay(); lcd_write_cmd(DISPLAY_ON); delay(); lcd_write_cmd(DISPLAY_ALL_NORMAL); delay(); return RT_EOK; } /******************************************************************************* * Function Name : LCD_FillAll * Description : Fill the whole LCD. * Input : None * Output : None * Return : None *******************************************************************************/ void LCD_FillAll(unsigned char* buffer) { unsigned char i,j = GUI_LCM_XMAX; unsigned char* p = buffer; for (i=0; i> 4; lcd_write_cmd(SET_PAGE_ADDR_0 | page); // page no. lcd_write_cmd(SET_COLH_ADDR_0 | colh); // fixed col first addr lcd_write_cmd(SET_COLL_ADDR_0 | coll); lcd_write_data(gui_disp_buf[page][x]); } /**************************************************************************** * Function Name : LCD_PutChar * Description : output a char to screen (the char only can be ' ','0'~'9','A'~'Z','a'~'z') * Input : x X-coordinate y Y-coordinate ch character * Output : None * Return : 1 Success 0 Fail ****************************************************************************/ unsigned char LCD_PutChar(unsigned long x, unsigned long y, unsigned char ch) { unsigned char data; unsigned char i, j; if( x >=(GUI_LCM_XMAX-8) ) return(0); if( y >=(GUI_LCM_YMAX-8) ) return(0); if(ch == 0x20) ch -= 0x20; else if((ch >= 0x30)&&(ch <= 0x39)) ch -= 0x2f; else if((ch >= 0x41)&&(ch <= 0x5a)) ch -= 0x36; else if((ch >= 0x61)&&(ch <= 0x7a)) ch -= 0x3C; else return(0); for(i = 0; i < 8; i++) { data = FONTTYPE8_8[ch][i]; for(j = 0; j < 8; j++) { if( (data&BIT_MASK[j]) == 0) gui_disp_buf[y / 8][x] &= (~(0x01 << ( y % 8))); else gui_disp_buf[y / 8][x] |= (0x01 <<( y % 8)); LCD_UpdatePoint(x, y); x ++; } x -= 8; y++; } return(1); } /**************************************************************************** * Function Name : LCD_PutString * Description : output string to screen * Input : x X-coordinate y Y-coordinate str pointer to string * Output : None * Return : None ****************************************************************************/ void LCD_PutString(unsigned long x, unsigned long y, char *str) { while(1) { if( (*str)=='\0' ) break; if( LCD_PutChar(x, y, *str++) == 0 ) break; x += 6; } } static rt_err_t rt_lcd_control (rt_device_t dev, int cmd, void *args) { switch (cmd) { #ifdef RT_USING_RTGUI case RTGRAPHIC_CTRL_RECT_UPDATE: rt_hw_lcd_update(args); break; case RTGRAPHIC_CTRL_POWERON: break; case RTGRAPHIC_CTRL_POWEROFF: break; case RTGRAPHIC_CTRL_GET_INFO: rt_memcpy(args, &_lcd_info, sizeof(_lcd_info)); break; case RTGRAPHIC_CTRL_SET_MODE: break; #else case RT_DEVICE_CTRL_LCD_DISPLAY_ON: lcd_write_cmd(DISPLAY_ON); break; case RT_DEVICE_CTRL_LCD_DISPLAY_OFF: lcd_write_cmd(DISPLAY_OFF); break; case RT_DEVICE_CTRL_LCD_PUT_STRING: LCD_PutString(x, y, (char*)args); break; case RT_DEVICE_CTRL_LCD_CLEAR_SCR: LCD_ClearSCR(); break; #endif } return RT_EOK; } void rt_hw_lcd_init(void) { rt_device_t lcd = rt_malloc(sizeof(struct rt_device)); if (lcd == RT_NULL) return; /* no memory yet */ _lcd_info.bits_per_pixel = 16; _lcd_info.pixel_format = RTGRAPHIC_PIXEL_FORMAT_RGB565; _lcd_info.framebuffer = RT_NULL; _lcd_info.width = LCD_WIDTH; _lcd_info.height = LCD_HEIGHT; /* init device structure */ lcd->type = RT_Device_Class_Unknown; lcd->init = rt_lcd_init; lcd->open = RT_NULL; lcd->close = RT_NULL; lcd->control = rt_lcd_control; #ifdef RT_USING_RTGUI lcd->user_data = (void*)&_lcd_ops; #endif /* register lcd device to RT-Thread */ rt_device_register(lcd, "lcd", RT_DEVICE_FLAG_RDWR); }