blob: 7517c5c3d2fb6ce961a64b0d1ecdb50ab2b2ddbf [file] [log] [blame]
#include "lcd.h"
#include "st7735.c"
#include "font.c"
#include "hal.h"
#define NULL 0
#define printf obm_printf
#define mdelay(x) Delay((x) * 1000)
#ifdef CONFIG_SPI_LCD_3WIRE
#define FB_SIZE (CONFIG_SPI_LCD_XRES * CONFIG_SPI_LCD_YRES * 2 * 2)
#else
#define FB_SIZE (CONFIG_SPI_LCD_XRES * CONFIG_SPI_LCD_YRES * 2)
#endif
static unsigned char *gFramebuffer = NULL;
static inline void LCD_SELECT_DATA_OR_CMD(int a)
{
#ifndef CONFIG_SPI_LCD_3WIRE
gpio_direction_output(CONFIG_SPI_LCD_RS_PIN, a);
#endif
}
void LCD_SEND_DATA(void)
{
LCD_SELECT_DATA_OR_CMD(1);
}
void LCD_SEND_CMD(void)
{
LCD_SELECT_DATA_OR_CMD(0);
}
void lcd_power(int on)
{
#ifdef CONFIG_SPI_LCD_POWER_PIN
gpio_direction_output(CONFIG_SPI_LCD_POWER_PIN, on);
#endif
}
void lcd_reset(void)
{
gpio_direction_output(CONFIG_SPI_LCD_RST_PIN, 1);
mdelay(50);
gpio_direction_output(CONFIG_SPI_LCD_RST_PIN, 0);
mdelay(50);
gpio_direction_output(CONFIG_SPI_LCD_RST_PIN, 1);
mdelay(150);
}
static void lcd_set_backlight(int on)
{
gpio_direction_output(CONFIG_SPI_LCD_BL_PIN, on);
}
static void lcd_spi_write(unsigned int data)
{
Assert_CS();
SPI_FireUp();
SPI_WriteData(data);
SPI_WaitSSPComplete();
SPI_DisableSSP();
Deassert_CS();
}
static int lcd_write_cmd(unsigned char cmd)
{
int ret = 0;
unsigned short bits, _data;
#ifdef CONFIG_SPI_LCD_3WIRE
bits = 9;
_data = cmd;
#else
bits = 8;
_data = cmd;
LCD_SEND_CMD();
#endif
SPI_ConfigDSS(bits);
lcd_spi_write(_data);
return ret;
}
static int lcd_write_data(unsigned char data)
{
int ret = 0;
unsigned short bits, _data;
#ifdef CONFIG_SPI_LCD_3WIRE
bits = 9;
_data = 0x100 | data;
#else
bits = 8;
_data = data;
LCD_SEND_DATA();
#endif
SPI_ConfigDSS(bits);
lcd_spi_write(_data);
return ret;
}
static int lcd_write_data16(unsigned short data)
{
int ret = 0;
unsigned int bits, _data;
#ifdef CONFIG_SPI_LCD_3WIRE
unsigned char h, l;
bits = 18;
h = (data >> 8) & 0xff;
l = data & 0xff;
_data = ((0x100 | h) << 9) | (0x100 | l);
#else
bits = 16;
_data = data;
LCD_SEND_DATA();
#endif
SPI_ConfigDSS(bits);
lcd_spi_write(_data);
return ret;
}
static int lcd_set_window(unsigned char xs, unsigned char ys, unsigned char xe, unsigned char ye)
{
lcd_write_cmd(0x2a); // column addr set
lcd_write_data(0x00);
lcd_write_data(xs + 2);
lcd_write_data(0x00);
lcd_write_data(xe + 2);
lcd_write_cmd(0x2b); // row addr set
lcd_write_data(0x00);
lcd_write_data(ys + 3);
lcd_write_data(0x00);
lcd_write_data(ye + 3);
return 0;
}
static int lcd_write_memory(unsigned char *buf, int cnt)
{
int i;
lcd_write_cmd(0x2c); // memory write command
for (i = 0; i < cnt; i++)
lcd_write_data(buf[i]);
return 0;
}
static int lcd_fill(unsigned short color)
{
unsigned char x, y, low, high;
unsigned short *buf = (unsigned short *)gFramebuffer;
memset(buf, 0, FB_SIZE);
lcd_set_window(0, 0, CONFIG_SPI_LCD_XRES - 1, CONFIG_SPI_LCD_YRES - 1);
for (x=0; x < CONFIG_SPI_LCD_XRES; x++)
for (y=0; y < CONFIG_SPI_LCD_YRES; y++) {
low = color & 0xff;
high = (color & 0xff00) >> 8;
#ifdef CONFIG_SPI_LCD_3WIRE
*(buf++) = low;
*(buf++) = high;
#else
*(buf++) = (low << 8) | high;
#endif
}
return lcd_write_memory(gFramebuffer, FB_SIZE);
}
static int lcd_draw_logo(
unsigned char p_x, unsigned char line,
unsigned char W, unsigned char H,
unsigned char *buf, unsigned short txt_color, unsigned short bg_color)
{
int i, j, k;
unsigned char c;
int index, size;
unsigned short *buff = (unsigned short *)gFramebuffer;
lcd_set_window(line, p_x, (line + H - 1), (p_x + W - 1));
index = 0;
for(i = 0; i < W; i++) {
for(k = (H / 8 -1); k >= 0; k--) {
c = *buf++;
for(j = (8 - 1); j >= 0; j--) {
if((1 << (7 - j)) & c)
*(buff++) = txt_color;
else
*(buff++) = bg_color;
index++;
}
}
}
size = index;
return lcd_write_memory(gFramebuffer, size * 2);
}
static void panel_init(void *sequence)
{
struct lcd_cmd *array = (struct lcd_cmd *)sequence;
if (!array) {
printf("Warning: null init sequence.\n");
return;
}
while (array->type != CMD_TYPE_END) {
switch (array->type) {
case CMD_TYPE_START:
break;
case CMD_TYPE_CMD:
lcd_write_cmd(array->data);
break;
case CMD_TYPE_DATA:
lcd_write_data(array->data);
break;
case CMD_TYPE_DELAY:
mdelay(array->data);
break;
}
array++;
}
printf("Panel: init done.\r\n");
}
int spi_lcd_init(void)
{
int ret;
gFramebuffer = malloc(FB_SIZE);
lcd_reset();
panel_init(st7735_init_sequence);
lcd_fill(0); // 0: Black, 0xF800: Red, 0x7E0: Green, 0x1F: Blue
lcd_set_backlight(1);
return 0;
}
void lcd_display_char(unsigned char x, unsigned char y, const char c)
{
int i, j, len;
unsigned short pos;
unsigned char *font;
pos = c - ' ';
/* font length */
len = (LCD_Currentfonts->width * LCD_Currentfonts->height) / 8;
font = (unsigned char *)&LCD_Currentfonts->table[pos * len];
lcd_set_window (x, y, x + LCD_Currentfonts->width - 1, y + LCD_Currentfonts->height - 1);
lcd_write_cmd(0x2c);
for (i = 0; i < len; i++) {
for (j = 0; j < 8; j++) {
if (font[i] & (0x80 >> j))
lcd_write_data16(0xffff);
else
lcd_write_data16(0);
}
}
}
void lcd_display_string(unsigned short x, unsigned short y, char *str)
{
unsigned short x0, y0;
x0 = x;
y0 = y;
while (*str) {
if (x > CONFIG_SPI_LCD_XRES) {
x = x0;
y += LCD_Currentfonts->height;
}
if (y > CONFIG_SPI_LCD_YRES) {
x = x0;
y = y0;
}
lcd_display_char(x, y, *str);
str++;
x += LCD_Currentfonts->width;
}
}