123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477 |
- /*
- * 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 <rtthread.h>
- #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 <rtgui/driver.h>
- #include <rtgui/color.h>
- 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<GUI_LCM_PAGE; i++)
- {
- lcd_write_cmd(SET_PAGE_ADDR_0|i);
- lcd_write_cmd(SET_COLH_ADDR_0);
- lcd_write_cmd(SET_COLL_ADDR_0);
- j = GUI_LCM_XMAX;
- while (j--)
- {
- lcd_write_data(*p++);
- delay();
- }
- }
- }
- static rt_uint8_t * rt_hw_lcd_get_framebuffer(void)
- {
- return(rt_uint8_t *)gui_disp_buf;
- }
- static void rt_hw_lcd_set_pixel(rtgui_color_t *c, int x, int y)
- {
- rt_uint8_t page;
- page = y/8;
- if (*c == rtgui_color_to_565(black))
- gui_disp_buf[page][x] |= 1<<(y%8);
- else
- if (*c == rtgui_color_to_565(white))
- gui_disp_buf[page][x] &= ~(1<<(y%8));
- }
- static void rt_hw_lcd_get_pixel(rtgui_color_t *c, int x, int y)
- {
- rt_uint8_t page;
- page = y/8;
- if (gui_disp_buf[page][x] & (1<<(y%8)))
- *c = black;
- else
- *c = white;
- }
- static void rt_hw_lcd_draw_hline(rtgui_color_t *c, int x1, int x2, int y)
- {
- rt_uint8_t page;
- rt_uint8_t i;
- page = y/8;
- for (i=x1; i<x2; i++)
- {
- if (*c == rtgui_color_to_565(black))
- gui_disp_buf[page][i] |= 1<<(y%8);
- else
- if (*c == rtgui_color_to_565(white))
- gui_disp_buf[page][i] &= ~(1<<(y%8));
- }
- }
- static void rt_hw_lcd_draw_vline(rtgui_color_t *c, int x, int y1, int y2)
- {
- rt_uint8_t y;
- for (y = y1; y < y2; y ++)
- {
- rt_hw_lcd_set_pixel(c, x, y);
- }
- }
- static void rt_hw_lcd_draw_raw_hline(rt_uint8_t *pixels, int x1, int x2, int y)
- {
- rt_uint8_t coll;
- rt_uint8_t colh;
- rt_uint8_t page;
- rt_uint8_t i;
- page = y/8;
- for (i=x1; i<x2; i++)
- {
- gui_disp_buf[page][i] |= 1<<(y%8);
- coll = i & 0x0f;
- colh = 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<GUI_LCM_PAGE; i++)
- {
- lcd_write_cmd(SET_PAGE_ADDR_0|i);
- lcd_write_cmd(SET_COLH_ADDR_0);
- lcd_write_cmd(SET_COLL_ADDR_0);
- j = GUI_LCM_XMAX;
- while (j--)
- {
- lcd_write_data(*p++);
- delay();
- }
- }
- }
- /*******************************************************************************
- * Function Name : LCD_ClearSCR
- * Description : clean screen
- * Input : None
- * Output : None
- * Return : None
- *******************************************************************************/
- void LCD_ClearSCR(void)
- {
- unsigned char i, j;
- for(i=0; i<GUI_LCM_PAGE; i++)
- {
- for(j = 0; j < GUI_LCM_XMAX; j++)
- gui_disp_buf[i][j] = 0;
- }
- LCD_FillAll((unsigned char*)gui_disp_buf);
- }
- /****************************************************************************
- * Function Name : LCD_UpdatePoint
- * Description : refresh the point in screen
- * Input : x X-coordinate
- y Y-coordinate
- * Output : None
- * Return : None
- ****************************************************************************/
- void LCD_UpdatePoint(unsigned int x, unsigned int y)
- {
- unsigned char coll, colh, page;
- page = y / 8;
- coll = x & 0x0f;
- colh = x >> 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);
- }
|