diff --git a/sys/include/gpanel.h b/sys/include/gpanel.h index 405642a..e0a9a18 100644 --- a/sys/include/gpanel.h +++ b/sys/include/gpanel.h @@ -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); diff --git a/sys/pic32/gpanel-ili9341.c b/sys/pic32/gpanel-ili9341.c index ebaf2fd..979f39d 100644 --- a/sys/pic32/gpanel-ili9341.c +++ b/sys/pic32/gpanel-ili9341.c @@ -24,11 +24,6 @@ #include #include -/* - * 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; diff --git a/sys/pic32/gpanel-nt35702.c b/sys/pic32/gpanel-nt35702.c index 2dc5744..92663e3 100644 --- a/sys/pic32/gpanel-nt35702.c +++ b/sys/pic32/gpanel-nt35702.c @@ -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 * @@ -24,11 +26,6 @@ #include #include -/* - * 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; hheight; h++) { - /* Loop on every pixel in the row (left to right). */ - for (w=0; w> 8); - gpanel_write_byte(c); - } - } - gpanel_cs_idle(); - } else { - /* - * Transparent background. - */ - /* Loop on each glyph row. */ - for (h=0; hheight; h++) { - /* Loop on every pixel in the row (left to right). */ - for (w=0; wname = "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; } diff --git a/sys/pic32/gpanel-st7781.c b/sys/pic32/gpanel-st7781.c index 8104d1c..e148b10 100644 --- a/sys/pic32/gpanel-st7781.c +++ b/sys/pic32/gpanel-st7781.c @@ -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; } diff --git a/sys/pic32/gpanel.c b/sys/pic32/gpanel.c index d9a9ba9..55f7121 100644 --- a/sys/pic32/gpanel.c +++ b/sys/pic32/gpanel.c @@ -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;