Reuse ili9341 routines for nt35702 display.
This commit is contained in:
@@ -146,9 +146,7 @@ extern void gpanel_write_dir(void);
|
||||
*/
|
||||
struct gpanel_hw {
|
||||
const char *name;
|
||||
int width;
|
||||
int height;
|
||||
void (*clear)(struct gpanel_hw *hw, int color, int width, int height);
|
||||
void (*resize)(struct gpanel_hw *hw, int width, int height);
|
||||
void (*set_pixel)(int x, int y, int color);
|
||||
void (*fill_rectangle)(int x0, int y0, int x1, int y1, int color);
|
||||
void (*draw_image)(int x, int y, int width, int height,
|
||||
@@ -157,6 +155,8 @@ struct gpanel_hw {
|
||||
int color, int background, int x, int y, int width,
|
||||
const unsigned short *bits);
|
||||
};
|
||||
extern int gpanel_width;
|
||||
extern int gpanel_height;
|
||||
extern void st7781_init_display(struct gpanel_hw *hw);
|
||||
extern void nt35702_init_display(struct gpanel_hw *hw);
|
||||
extern void ili9341_init_display(struct gpanel_hw *hw);
|
||||
|
||||
@@ -24,11 +24,6 @@
|
||||
#include <sys/param.h>
|
||||
#include <sys/gpanel.h>
|
||||
|
||||
/*
|
||||
* Display size.
|
||||
*/
|
||||
static int _width, _height;
|
||||
|
||||
/*
|
||||
* ILI9341 registers.
|
||||
*/
|
||||
@@ -160,9 +155,9 @@ static void set_window(int x0, int y0, int x1, int y1)
|
||||
/*
|
||||
* Draw a pixel.
|
||||
*/
|
||||
static void ili9341_set_pixel(int x, int y, int color)
|
||||
void ili9341_set_pixel(int x, int y, int color)
|
||||
{
|
||||
if (x < 0 || x >= _width || y < 0 || y >= _height)
|
||||
if (x < 0 || x >= gpanel_width || y < 0 || y >= gpanel_height)
|
||||
return;
|
||||
gpanel_cs_active();
|
||||
set_window(x, y, x, y);
|
||||
@@ -239,28 +234,28 @@ static void set_rotation(int rotation)
|
||||
switch (rotation & 3) {
|
||||
case 0: /* Portrait */
|
||||
write_data(MADCTL_MX | MADCTL_BGR);
|
||||
_width = 240;
|
||||
_height = 320;
|
||||
gpanel_width = 240;
|
||||
gpanel_height = 320;
|
||||
break;
|
||||
case 1: /* Landscape */
|
||||
write_data(MADCTL_MV | MADCTL_BGR);
|
||||
_width = 320;
|
||||
_height = 240;
|
||||
gpanel_width = 320;
|
||||
gpanel_height = 240;
|
||||
break;
|
||||
case 2: /* Upside down portrait */
|
||||
write_data(MADCTL_MY | MADCTL_BGR);
|
||||
_width = 240;
|
||||
_height = 320;
|
||||
gpanel_width = 240;
|
||||
gpanel_height = 320;
|
||||
break;
|
||||
case 3: /* Upside down landscape */
|
||||
write_data(MADCTL_MX | MADCTL_MY | MADCTL_MV | MADCTL_BGR);
|
||||
_width = 320;
|
||||
_height = 240;
|
||||
gpanel_width = 320;
|
||||
gpanel_height = 240;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
static void ili9341_clear(struct gpanel_hw *h, int color, int width, int height)
|
||||
static void ili9341_resize(struct gpanel_hw *h, int width, int height)
|
||||
{
|
||||
gpanel_cs_active();
|
||||
|
||||
@@ -270,25 +265,22 @@ static void ili9341_clear(struct gpanel_hw *h, int color, int width, int height)
|
||||
else if (width < height)
|
||||
set_rotation(0); /* Portrait */
|
||||
|
||||
/* Fill the screen with a color. */
|
||||
set_window(0, 0, _width-1, _height-1);
|
||||
flood(color, _width * _height);
|
||||
gpanel_cs_idle();
|
||||
}
|
||||
|
||||
/*
|
||||
* Fill a rectangle with specified color.
|
||||
*/
|
||||
static void ili9341_fill_rectangle(int x0, int y0, int x1, int y1, int color)
|
||||
void ili9341_fill_rectangle(int x0, int y0, int x1, int y1, int color)
|
||||
{
|
||||
if (x0 < 0) x0 = 0;
|
||||
if (y0 < 0) x0 = 0;
|
||||
if (x1 < 0) x1 = 0;
|
||||
if (y1 < 0) x1 = 0;
|
||||
if (x0 >= _width) x0 = _width-1;
|
||||
if (x1 >= _width) x1 = _width-1;
|
||||
if (y0 >= _height) y0 = _height-1;
|
||||
if (y1 >= _height) y1 = _height-1;
|
||||
if (x0 >= gpanel_width) x0 = gpanel_width-1;
|
||||
if (x1 >= gpanel_width) x1 = gpanel_width-1;
|
||||
if (y0 >= gpanel_height) y0 = gpanel_height-1;
|
||||
if (y1 >= gpanel_height) y1 = gpanel_height-1;
|
||||
|
||||
if (x1 < x0) {
|
||||
int t = x0;
|
||||
@@ -309,7 +301,7 @@ static void ili9341_fill_rectangle(int x0, int y0, int x1, int y1, int color)
|
||||
/*
|
||||
* Fill a rectangle with user data.
|
||||
*/
|
||||
static void ili9341_draw_image(int x, int y, int width, int height,
|
||||
void ili9341_draw_image(int x, int y, int width, int height,
|
||||
const unsigned short *data)
|
||||
{
|
||||
unsigned cnt = width * height;
|
||||
@@ -329,14 +321,14 @@ static void ili9341_draw_image(int x, int y, int width, int height,
|
||||
/*
|
||||
* Draw a glyph of one symbol.
|
||||
*/
|
||||
static void ili9341_draw_glyph(const struct gpanel_font_t *font,
|
||||
void ili9341_draw_glyph(const struct gpanel_font_t *font,
|
||||
int color, int background, int x, int y, int width,
|
||||
const unsigned short *bits)
|
||||
{
|
||||
int h, w, c;
|
||||
unsigned bitmask = 0;
|
||||
|
||||
if (x + width > _width || y + font->height > _height)
|
||||
if (x + width > gpanel_width || y + font->height > gpanel_height)
|
||||
return;
|
||||
|
||||
if (background >= 0) {
|
||||
@@ -426,16 +418,14 @@ void ili9341_init_display(struct gpanel_hw *h)
|
||||
write_command(ILI9341_Display_ON);
|
||||
|
||||
set_rotation(1); /* Landscape */
|
||||
set_window(0, 0, _width-1, _height-1);
|
||||
set_window(0, 0, gpanel_width-1, gpanel_height-1);
|
||||
gpanel_cs_idle();
|
||||
|
||||
/*
|
||||
* Fill the gpanel_hw descriptor.
|
||||
*/
|
||||
h->name = "Ilitek ILI9341";
|
||||
h->width = _width;
|
||||
h->height = _height;
|
||||
h->clear = ili9341_clear;
|
||||
h->resize = ili9341_resize;
|
||||
h->set_pixel = ili9341_set_pixel;
|
||||
h->fill_rectangle = ili9341_fill_rectangle;
|
||||
h->draw_image = ili9341_draw_image;
|
||||
|
||||
@@ -1,5 +1,7 @@
|
||||
/*
|
||||
* Display driver for NT35702 LCD controller.
|
||||
* This controller is partially compatible with ILI9341 chip,
|
||||
* so we can reuse most of ili9341_xxx() routines.
|
||||
*
|
||||
* Copyright (C) 2015 Serge Vakulenko <serge@vak.ru>
|
||||
*
|
||||
@@ -24,11 +26,6 @@
|
||||
#include <sys/param.h>
|
||||
#include <sys/gpanel.h>
|
||||
|
||||
/*
|
||||
* Display size.
|
||||
*/
|
||||
static int _width, _height;
|
||||
|
||||
/*
|
||||
* NT35702 registers.
|
||||
*/
|
||||
@@ -120,6 +117,17 @@ static int _width, _height;
|
||||
#define MADCTL_BGR 0x08 /* Color filter selector: 0=RGB, 1=BGR */
|
||||
#define MADCTL_MH 0x04 /* Horisontal refresh direction: 1=left-to-right */
|
||||
|
||||
/*
|
||||
* Reuse ILI9341 routines.
|
||||
*/
|
||||
extern void ili9341_set_pixel(int x, int y, int color);
|
||||
extern void ili9341_fill_rectangle(int x0, int y0, int x1, int y1, int color);
|
||||
extern void ili9341_draw_image(int x, int y, int width, int height,
|
||||
const unsigned short *data);
|
||||
extern void ili9341_draw_glyph(const struct gpanel_font_t *font,
|
||||
int color, int background, int x, int y, int width,
|
||||
const unsigned short *bits);
|
||||
|
||||
/*
|
||||
* Write a 8-bit value to the NT35702 Command register.
|
||||
*/
|
||||
@@ -138,99 +146,6 @@ static void write_data(int cmd)
|
||||
gpanel_write_byte(cmd);
|
||||
}
|
||||
|
||||
/*
|
||||
* Set address window.
|
||||
*/
|
||||
static void set_window(int x0, int y0, int x1, int y1)
|
||||
{
|
||||
write_command(NT35702_CASET);
|
||||
write_data(x0 >> 8);
|
||||
gpanel_write_byte(x0);
|
||||
gpanel_write_byte(x1 >> 8);
|
||||
gpanel_write_byte(x1);
|
||||
|
||||
write_command(NT35702_RASET);
|
||||
write_data(y0 >> 8);
|
||||
gpanel_write_byte(y0);
|
||||
gpanel_write_byte(y1 >> 8);
|
||||
gpanel_write_byte(y1);
|
||||
|
||||
write_command(NT35702_RAMWR);
|
||||
}
|
||||
|
||||
/*
|
||||
* Draw a pixel.
|
||||
*/
|
||||
static void nt35702_set_pixel(int x, int y, int color)
|
||||
{
|
||||
if (x < 0 || x >= _width || y < 0 || y >= _height)
|
||||
return;
|
||||
gpanel_cs_active();
|
||||
set_window(x, y, x, y);
|
||||
write_data(color >> 8);
|
||||
write_data(color);
|
||||
gpanel_cs_idle();
|
||||
}
|
||||
|
||||
/*
|
||||
* Fast block fill operation.
|
||||
* Requires set_window() has previously been called to set
|
||||
* the fill bounds.
|
||||
* 'npixels' is inclusive, MUST be >= 1.
|
||||
*/
|
||||
static void flood(int color, int npixels)
|
||||
{
|
||||
unsigned blocks, i;
|
||||
unsigned hi = color >> 8,
|
||||
lo = color;
|
||||
|
||||
/* Write first pixel normally, decrement counter by 1. */
|
||||
gpanel_rs_data();
|
||||
gpanel_write_byte(hi);
|
||||
gpanel_write_byte(lo);
|
||||
npixels--;
|
||||
|
||||
/* 64 pixels/block. */
|
||||
blocks = npixels >> 6;
|
||||
if (hi == lo) {
|
||||
/* High and low bytes are identical. Leave prior data
|
||||
* on the port(s) and just toggle the write strobe. */
|
||||
while (blocks--) {
|
||||
/* 64 pixels/block / 4 pixels/pass. */
|
||||
for (i = 16; i > 0; i--) {
|
||||
/* 2 bytes/pixel x 4 pixels. */
|
||||
gpanel_wr_strobe();
|
||||
gpanel_wr_strobe();
|
||||
gpanel_wr_strobe();
|
||||
gpanel_wr_strobe();
|
||||
gpanel_wr_strobe();
|
||||
gpanel_wr_strobe();
|
||||
gpanel_wr_strobe();
|
||||
gpanel_wr_strobe();
|
||||
}
|
||||
}
|
||||
/* Fill any remaining pixels (1 to 64). */
|
||||
for (i = npixels & 63; i > 0; i--) {
|
||||
gpanel_wr_strobe();
|
||||
gpanel_wr_strobe();
|
||||
}
|
||||
} else {
|
||||
while (blocks--) {
|
||||
/* 64 pixels/block / 4 pixels/pass. */
|
||||
for (i = 16; i > 0; i--) {
|
||||
gpanel_write_byte(hi); gpanel_write_byte(lo);
|
||||
gpanel_write_byte(hi); gpanel_write_byte(lo);
|
||||
gpanel_write_byte(hi); gpanel_write_byte(lo);
|
||||
gpanel_write_byte(hi); gpanel_write_byte(lo);
|
||||
}
|
||||
}
|
||||
for (i = npixels & 63; i > 0; i--) {
|
||||
gpanel_write_byte(hi);
|
||||
gpanel_write_byte(lo);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
* Switch the screen orientation.
|
||||
*/
|
||||
@@ -240,28 +155,28 @@ static void set_rotation(int rotation)
|
||||
switch (rotation & 3) {
|
||||
case 0: /* Portrait */
|
||||
write_data(MADCTL_MX | MADCTL_MY | MADCTL_BGR);
|
||||
_width = 240;
|
||||
_height = 320;
|
||||
gpanel_width = 240;
|
||||
gpanel_height = 320;
|
||||
break;
|
||||
case 1: /* Landscape */
|
||||
write_data(MADCTL_MY | MADCTL_MV | MADCTL_BGR);
|
||||
_width = 320;
|
||||
_height = 240;
|
||||
gpanel_width = 320;
|
||||
gpanel_height = 240;
|
||||
break;
|
||||
case 2: /* Upside down portrait */
|
||||
write_data(MADCTL_BGR);
|
||||
_width = 240;
|
||||
_height = 320;
|
||||
gpanel_width = 240;
|
||||
gpanel_height = 320;
|
||||
break;
|
||||
case 3: /* Upside down landscape */
|
||||
write_data(MADCTL_MX | MADCTL_MV | MADCTL_BGR);
|
||||
_width = 320;
|
||||
_height = 240;
|
||||
gpanel_width = 320;
|
||||
gpanel_height = 240;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
static void nt35702_clear(struct gpanel_hw *h, int color, int width, int height)
|
||||
static void nt35702_resize(struct gpanel_hw *h, int width, int height)
|
||||
{
|
||||
gpanel_cs_active();
|
||||
|
||||
@@ -271,118 +186,9 @@ static void nt35702_clear(struct gpanel_hw *h, int color, int width, int height)
|
||||
else if (width < height)
|
||||
set_rotation(0); /* Portrait */
|
||||
|
||||
/* Fill the screen with a color. */
|
||||
set_window(0, 0, _width-1, _height-1);
|
||||
flood(color, _width * _height);
|
||||
gpanel_cs_idle();
|
||||
}
|
||||
|
||||
/*
|
||||
* Fill a rectangle with specified color.
|
||||
*/
|
||||
static void nt35702_fill_rectangle(int x0, int y0, int x1, int y1, int color)
|
||||
{
|
||||
if (x0 < 0) x0 = 0;
|
||||
if (y0 < 0) x0 = 0;
|
||||
if (x1 < 0) x1 = 0;
|
||||
if (y1 < 0) x1 = 0;
|
||||
if (x0 >= _width) x0 = _width-1;
|
||||
if (x1 >= _width) x1 = _width-1;
|
||||
if (y0 >= _height) y0 = _height-1;
|
||||
if (y1 >= _height) y1 = _height-1;
|
||||
|
||||
if (x1 < x0) {
|
||||
int t = x0;
|
||||
x0 = x1;
|
||||
x1 = t;
|
||||
}
|
||||
if (y1 < y0) {
|
||||
int t = y0;
|
||||
y0 = y1;
|
||||
y1 = t;
|
||||
}
|
||||
gpanel_cs_active();
|
||||
set_window(x0, y0, x1, y1);
|
||||
flood(color, (x1 - x0 + 1) * (y1 - y0 + 1));
|
||||
gpanel_cs_idle();
|
||||
}
|
||||
|
||||
/*
|
||||
* Fill a rectangle with user data.
|
||||
*/
|
||||
static void nt35702_draw_image(int x, int y, int width, int height,
|
||||
const unsigned short *data)
|
||||
{
|
||||
unsigned cnt = width * height;
|
||||
int color;
|
||||
|
||||
gpanel_cs_active();
|
||||
set_window(x, y, x + width - 1, y + height - 1);
|
||||
gpanel_rs_data();
|
||||
while (cnt--) {
|
||||
color = *data++;
|
||||
gpanel_write_byte(color >> 8);
|
||||
gpanel_write_byte(color);
|
||||
}
|
||||
gpanel_cs_idle();
|
||||
}
|
||||
|
||||
/*
|
||||
* Draw a glyph of one symbol.
|
||||
*/
|
||||
static void nt35702_draw_glyph(const struct gpanel_font_t *font,
|
||||
int color, int background, int x, int y, int width,
|
||||
const unsigned short *bits)
|
||||
{
|
||||
int h, w, c;
|
||||
unsigned bitmask = 0;
|
||||
|
||||
if (x + width > _width || y + font->height > _height)
|
||||
return;
|
||||
|
||||
if (background >= 0) {
|
||||
/*
|
||||
* Clear background.
|
||||
*/
|
||||
gpanel_cs_active();
|
||||
set_window(x, y, x + width - 1, y + font->height - 1);
|
||||
gpanel_rs_data();
|
||||
|
||||
/* Loop on each glyph row. */
|
||||
for (h=0; h<font->height; h++) {
|
||||
/* Loop on every pixel in the row (left to right). */
|
||||
for (w=0; w<width; w++) {
|
||||
if ((w & 15) == 0)
|
||||
bitmask = *bits++;
|
||||
else
|
||||
bitmask <<= 1;
|
||||
|
||||
c = (bitmask & 0x8000) ? color : background;
|
||||
gpanel_write_byte(c >> 8);
|
||||
gpanel_write_byte(c);
|
||||
}
|
||||
}
|
||||
gpanel_cs_idle();
|
||||
} else {
|
||||
/*
|
||||
* Transparent background.
|
||||
*/
|
||||
/* Loop on each glyph row. */
|
||||
for (h=0; h<font->height; h++) {
|
||||
/* Loop on every pixel in the row (left to right). */
|
||||
for (w=0; w<width; w++) {
|
||||
if ((w & 15) == 0)
|
||||
bitmask = *bits++;
|
||||
else
|
||||
bitmask <<= 1;
|
||||
|
||||
if (bitmask & 0x8000)
|
||||
nt35702_set_pixel(x + w, y + h, color);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
* Initialize the LCD controller.
|
||||
* Fill the gpanel_hw descriptor.
|
||||
@@ -484,11 +290,9 @@ void nt35702_init_display(struct gpanel_hw *h)
|
||||
* Fill the gpanel_hw descriptor.
|
||||
*/
|
||||
h->name = "Novatek NT35702";
|
||||
h->width = _width;
|
||||
h->height = _height;
|
||||
h->clear = nt35702_clear;
|
||||
h->set_pixel = nt35702_set_pixel;
|
||||
h->fill_rectangle = nt35702_fill_rectangle;
|
||||
h->draw_image = nt35702_draw_image;
|
||||
h->draw_glyph = nt35702_draw_glyph;
|
||||
h->resize = nt35702_resize;
|
||||
h->set_pixel = ili9341_set_pixel;
|
||||
h->fill_rectangle = ili9341_fill_rectangle;
|
||||
h->draw_image = ili9341_draw_image;
|
||||
h->draw_glyph = ili9341_draw_glyph;
|
||||
}
|
||||
|
||||
@@ -194,14 +194,6 @@ static void flood(int color, int npixels)
|
||||
gpanel_cs_idle();
|
||||
}
|
||||
|
||||
static void st7781_clear(struct gpanel_hw *h, int color, int width, int height)
|
||||
{
|
||||
gpanel_cs_active();
|
||||
write_reg(ST7781_DRAM_Horizontal_Address_Set, 0);
|
||||
write_reg(ST7781_DRAM_Vertical_Address_Set, 0);
|
||||
flood(color, WIDTH * HEIGHT);
|
||||
}
|
||||
|
||||
/*
|
||||
* Fill a rectangle with specified color.
|
||||
*/
|
||||
@@ -370,11 +362,10 @@ void st7781_init_display(struct gpanel_hw *h)
|
||||
|
||||
/* Fill the gpanel_hw descriptor. */
|
||||
h->name = "Sitronix ST7781";
|
||||
h->width = WIDTH;
|
||||
h->height = HEIGHT;
|
||||
h->clear = st7781_clear;
|
||||
h->set_pixel = st7781_set_pixel;
|
||||
h->fill_rectangle = st7781_fill_rectangle;
|
||||
h->draw_image = st7781_draw_image;
|
||||
h->draw_glyph = st7781_draw_glyph;
|
||||
gpanel_width = WIDTH;
|
||||
gpanel_height = HEIGHT;
|
||||
}
|
||||
|
||||
@@ -47,6 +47,11 @@ static int _col, _row;
|
||||
*/
|
||||
static int _chip_id;
|
||||
|
||||
/*
|
||||
* Display size.
|
||||
*/
|
||||
int gpanel_width, gpanel_height;
|
||||
|
||||
/*
|
||||
* Delay for 100 nanoseconds.
|
||||
* Needed to match the /WR and /RD timing requirements.
|
||||
@@ -372,7 +377,7 @@ static void gpanel_draw_char(const struct gpanel_font_t *font,
|
||||
case '\n': /* goto next line */
|
||||
_row += font->height;
|
||||
_col = 0;
|
||||
if (_row > hw.height - font->height)
|
||||
if (_row > gpanel_height - font->height)
|
||||
_row = 0;
|
||||
return;
|
||||
case '\r': /* carriage return - go to begin of line */
|
||||
@@ -460,9 +465,11 @@ int gpanel_ioctl(dev_t dev, register u_int cmd, caddr_t addr, int flag)
|
||||
case GPANEL_CLEAR: {
|
||||
struct gpanel_clear_t *param = (struct gpanel_clear_t*) addr;
|
||||
|
||||
hw.clear(&hw, param->color, param->xsize, param->ysize);
|
||||
param->xsize = hw.width;
|
||||
param->ysize = hw.height;
|
||||
if (hw.resize != 0)
|
||||
hw.resize(&hw, param->xsize, param->ysize);
|
||||
hw.fill_rectangle(0, 0, gpanel_width - 1, gpanel_height - 1, param->color);
|
||||
param->xsize = gpanel_width;
|
||||
param->ysize = gpanel_height;
|
||||
break;
|
||||
}
|
||||
|
||||
@@ -563,10 +570,10 @@ static void draw_logo()
|
||||
#define COLOR_S 0x07ff
|
||||
#define COLOR_D 0xffe0
|
||||
|
||||
int x = hw.width/2 - 17*K;
|
||||
int y = hw.height/2 + 11*K;
|
||||
int x = gpanel_width/2 - 17*K;
|
||||
int y = gpanel_height/2 + 11*K;
|
||||
|
||||
hw.clear(&hw, 0, 0, 0);
|
||||
hw.fill_rectangle(0, 0, gpanel_width - 1, gpanel_height - 1, 0);
|
||||
|
||||
/* B */
|
||||
gpanel_draw_line( 0*K+x, y- 0*K, 0*K+x, y-11*K, COLOR_B);
|
||||
@@ -673,7 +680,7 @@ static int probe(config)
|
||||
nt35702_init_display(&hw);
|
||||
break;
|
||||
}
|
||||
printf("gpanel0: <%s> display %ux%u\n", hw.name, hw.width, hw.height);
|
||||
printf("gpanel0: <%s> display %ux%u\n", hw.name, gpanel_width, gpanel_height);
|
||||
draw_logo();
|
||||
return 1;
|
||||
|
||||
|
||||
Reference in New Issue
Block a user