xiuos/Ubiquitous/RT_Thread/bsp/k210/base-drivers/drv_lcd.c

332 lines
8.8 KiB
C

/* Copyright 2018 Canaan Inc.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
#include <rtthread.h>
#ifdef BSP_USING_LCD
#include <drv_lcd.h>
#include <gpiohs.h>
#include <spi.h>
#include <unistd.h>
#include <string.h>
#include <fpioa.h>
#define DBG_TAG "LCD"
#define DBG_LVL DBG_LOG
#include <rtdbg.h>
static lcd_ctl_t lcd_ctl;
static void init_dcx(void)
{
gpiohs_set_drive_mode(DCX_GPIONUM, GPIO_DM_OUTPUT);
gpiohs_set_pin(DCX_GPIONUM, GPIO_PV_HIGH);
}
static void set_dcx_control(void)
{
gpiohs_set_pin(DCX_GPIONUM, GPIO_PV_LOW);
}
static void set_dcx_data(void)
{
gpiohs_set_pin(DCX_GPIONUM, GPIO_PV_HIGH);
}
static void init_rst(void)
{
gpiohs_set_drive_mode(RST_GPIONUM, GPIO_DM_OUTPUT);
gpiohs_set_pin(RST_GPIONUM, GPIO_PV_LOW);
rt_thread_mdelay(10);
gpiohs_set_pin(RST_GPIONUM, GPIO_PV_HIGH);
rt_thread_mdelay(10);
}
void tft_hard_init(void)
{
init_dcx();
spi_init(SPI_CHANNEL, SPI_WORK_MODE_0, SPI_FF_OCTAL, 8, 0);
init_rst();
spi_set_clk_rate(SPI_CHANNEL, 20000000);
}
void tft_write_command(uint8_t cmd)
{
set_dcx_control();
spi_init(SPI_CHANNEL, SPI_WORK_MODE_0, SPI_FF_OCTAL, 8, 0);
spi_init_non_standard(SPI_CHANNEL, 8/*instrction length*/, 0/*address length*/, 0/*wait cycles*/,
SPI_AITM_AS_FRAME_FORMAT/*spi address trans mode*/);
spi_send_data_normal_dma(DMAC_CHANNEL0, SPI_CHANNEL, SPI_SLAVE_SELECT, (uint8_t *)(&cmd), 1,SPI_TRANS_CHAR);
}
void tft_write_byte(uint8_t *data_buf, uint32_t length)
{
set_dcx_data();
spi_init(SPI_CHANNEL, SPI_WORK_MODE_0, SPI_FF_OCTAL, 8, 0);
spi_init_non_standard(SPI_CHANNEL, 8/*instrction length*/, 0/*address length*/, 0/*wait cycles*/,
SPI_AITM_AS_FRAME_FORMAT/*spi address trans mode*/);
spi_send_data_normal_dma(DMAC_CHANNEL0, SPI_CHANNEL, SPI_SLAVE_SELECT, data_buf, length, SPI_TRANS_CHAR);
}
void tft_write_half(uint16_t *data_buf, uint32_t length)
{
set_dcx_data();
spi_init(SPI_CHANNEL, SPI_WORK_MODE_0, SPI_FF_OCTAL, 16, 0);
spi_init_non_standard(SPI_CHANNEL, 16/*instrction length*/, 0/*address length*/, 0/*wait cycles*/,
SPI_AITM_AS_FRAME_FORMAT/*spi address trans mode*/);
spi_send_data_normal_dma(DMAC_CHANNEL0, SPI_CHANNEL, SPI_SLAVE_SELECT,data_buf, length, SPI_TRANS_SHORT);
}
void tft_write_word(uint32_t *data_buf, uint32_t length, uint32_t flag)
{
set_dcx_data();
spi_init(SPI_CHANNEL, SPI_WORK_MODE_0, SPI_FF_OCTAL, 32, 0);
spi_init_non_standard(SPI_CHANNEL, 0/*instrction length*/, 32/*address length*/, 0/*wait cycles*/,
SPI_AITM_AS_FRAME_FORMAT/*spi address trans mode*/);
spi_send_data_normal_dma(DMAC_CHANNEL0, SPI_CHANNEL, SPI_SLAVE_SELECT,data_buf, length, SPI_TRANS_INT);
}
void tft_fill_data(uint32_t *data_buf, uint32_t length)
{
set_dcx_data();
spi_init(SPI_CHANNEL, SPI_WORK_MODE_0, SPI_FF_OCTAL, 32, 0);
spi_init_non_standard(SPI_CHANNEL, 0/*instrction length*/, 32/*address length*/, 0/*wait cycles*/,
SPI_AITM_AS_FRAME_FORMAT/*spi address trans mode*/);
spi_fill_data_dma(DMAC_CHANNEL0, SPI_CHANNEL, SPI_SLAVE_SELECT,data_buf, length);
}
void lcd_polling_enable(void)
{
lcd_ctl.mode = 0;
}
void lcd_interrupt_enable(void)
{
lcd_ctl.mode = 1;
}
void lcd_pre()
{
fpioa_set_function(37, FUNC_GPIOHS0 + RST_GPIONUM);
fpioa_set_function(38, FUNC_GPIOHS0 + DCX_GPIONUM);
fpioa_set_function(36, FUNC_SPI0_SS0 + LCD_SPI_SLAVE_SELECT);
fpioa_set_function(39, FUNC_SPI0_SCLK);
}
int lcd_init(void)
{
uint8_t data = 0;
lcd_pre();
tft_hard_init();
/*soft reset*/
tft_write_command(SOFTWARE_RESET);
rt_thread_mdelay(10);
/*exit sleep*/
tft_write_command(SLEEP_OFF);
rt_thread_mdelay(10);
/*pixel format*/
tft_write_command(PIXEL_FORMAT_SET);
data = 0x55;
tft_write_byte(&data, 1);
/*display on*/
tft_write_command(DISPALY_ON);
lcd_polling_enable();
lcd_clear(PINK);
lcd_set_direction(DIR_YX_RLDU);
LOG_I("LCD initialization successfully");
}
INIT_APP_EXPORT(lcd_init);
void lcd_set_direction(lcd_dir_t dir)
{
lcd_ctl.dir = dir;
if (dir & DIR_XY_MASK)
{
lcd_ctl.width = LCD_Y_MAX - 1;
lcd_ctl.height = LCD_X_MAX - 1;
}
else
{
lcd_ctl.width = LCD_X_MAX - 1;
lcd_ctl.height = LCD_Y_MAX - 1;
}
tft_write_command(MEMORY_ACCESS_CTL);
tft_write_byte((uint8_t *)&dir, 1);
}
void lcd_set_area(uint16_t x1, uint16_t y1, uint16_t x2, uint16_t y2)
{
uint8_t data[4] = {0};
data[0] = (uint8_t)(x1 >> 8);
data[1] = (uint8_t)(x1);
data[2] = (uint8_t)(x2 >> 8);
data[3] = (uint8_t)(x2);
tft_write_command(HORIZONTAL_ADDRESS_SET);
tft_write_byte(data, 4);
data[0] = (uint8_t)(y1 >> 8);
data[1] = (uint8_t)(y1);
data[2] = (uint8_t)(y2 >> 8);
data[3] = (uint8_t)(y2);
tft_write_command(VERTICAL_ADDRESS_SET);
tft_write_byte(data, 4);
tft_write_command(MEMORY_WRITE);
}
void lcd_draw_point(uint16_t x, uint16_t y, uint16_t color)
{
lcd_set_area(x, y, x, y);
tft_write_half(&color, 1);
}
void lcd_draw_char(uint16_t x, uint16_t y, char c, uint16_t color)
{
uint8_t i = 0;
uint8_t j = 0;
uint8_t data = 0;
for (i = 0; i < 16; i++)
{
data = ascii0816[c * 16 + i];
for (j = 0; j < 8; j++)
{
if (data & 0x80)
lcd_draw_point(x + j, y, color);
data <<= 1;
}
y++;
}
}
void lcd_draw_string(uint16_t x, uint16_t y, char *str, uint16_t color)
{
while (*str)
{
lcd_draw_char(x, y, *str, color);
str++;
x += 8;
}
}
void lcd_ram_draw_string(char *str, uint32_t *ptr, uint16_t font_color, uint16_t bg_color)
{
uint8_t i = 0;
uint8_t j = 0;
uint8_t data = 0;
uint8_t *pdata = NULL;
uint16_t width = 0;
uint32_t *pixel = NULL;
width = 4 * strlen(str);
while (*str)
{
pdata = (uint8_t *)&ascii0816[(*str) * 16];
for (i = 0; i < 16; i++)
{
data = *pdata++;
pixel = ptr + i * width;
for (j = 0; j < 4; j++)
{
switch (data >> 6)
{
case 0:
*pixel = ((uint32_t)bg_color << 16) | bg_color;
break;
case 1:
*pixel = ((uint32_t)bg_color << 16) | font_color;
break;
case 2:
*pixel = ((uint32_t)font_color << 16) | bg_color;
break;
case 3:
*pixel = ((uint32_t)font_color << 16) | font_color;
break;
default:
*pixel = 0;
break;
}
data <<= 2;
pixel++;
}
}
str++;
ptr += 4;
}
}
void lcd_clear(uint16_t color)
{
uint32_t data = ((uint32_t)color << 16) | (uint32_t)color;
lcd_set_area(0, 0, lcd_ctl.width, lcd_ctl.height);
tft_fill_data(&data, LCD_X_MAX * LCD_Y_MAX / 2);
}
void lcd_draw_rectangle(uint16_t x1, uint16_t y1, uint16_t x2, uint16_t y2, uint16_t width, uint16_t color)
{
uint32_t data_buf[640] = {0};
uint32_t *p = data_buf;
uint32_t data = color;
uint32_t index = 0;
data = (data << 16) | data;
for (index = 0; index < 160 * width; index++)
*p++ = data;
lcd_set_area(x1, y1, x2, y1 + width - 1);
tft_write_word(data_buf, ((x2 - x1 + 1) * width + 1) / 2, 0);
lcd_set_area(x1, y2 - width + 1, x2, y2);
tft_write_word(data_buf, ((x2 - x1 + 1) * width + 1) / 2, 0);
lcd_set_area(x1, y1, x1 + width - 1, y2);
tft_write_word(data_buf, ((y2 - y1 + 1) * width + 1) / 2, 0);
lcd_set_area(x2 - width + 1, y1, x2, y2);
tft_write_word(data_buf, ((y2 - y1 + 1) * width + 1) / 2, 0);
}
void lcd_draw_picture(uint16_t x1, uint16_t y1, uint16_t width, uint16_t height, uint32_t *ptr)
{
lcd_set_area(x1, y1, x1 + width - 1, y1 + height - 1);
tft_write_word(ptr, width * height / 2, lcd_ctl.mode ? 2 : 0);
}
void lcd_test0()
{
char test[]={"xuos-intelligence framwork"};
lcd_draw_string(0,0,test,BLUE);
}
MSH_CMD_EXPORT(lcd_test0,lcd show string);
void lcd_test1()
{
lcd_clear(YELLOW);
}
MSH_CMD_EXPORT(lcd_test1,lcd show string);
#endif