diff --git a/sys/include/gpanel.h b/sys/include/gpanel.h index 144338e..b848879 100644 --- a/sys/include/gpanel.h +++ b/sys/include/gpanel.h @@ -141,6 +141,8 @@ extern void gpanel_rs_data(void); extern void gpanel_wr_strobe(void); extern void gpanel_read_dir(void); extern void gpanel_write_dir(void); +extern int gpanel_send_command(int value); +extern int gpanel_send_data(int value); /* * Descriptor for access to the hardware-level driver. diff --git a/sys/pic32/Config.generic b/sys/pic32/Config.generic index 654a7ad..5cf9b9c 100644 --- a/sys/pic32/Config.generic +++ b/sys/pic32/Config.generic @@ -130,7 +130,8 @@ device picga0 at spi1 pin RA4 # chip select signal options "PICGA_BUS=SPI1CON" # TODO: delete this option signal "PICGA_CS" pin RA4 # TODO: delete -# TFT display driver: ST7781 +# TFT display driver with 8-bit parallel interface. +# Supported controllers: ST7781, ILI9341, NT35702 device gpanel signal "LCD_RST" pin RB10 signal "LCD_CS" pin RB0 diff --git a/sys/pic32/devsw.c b/sys/pic32/devsw.c index eacd8d2..eb60c87 100644 --- a/sys/pic32/devsw.c +++ b/sys/pic32/devsw.c @@ -317,7 +317,8 @@ const struct cdevsw cdevsw[] = { #if GPANEL_MAJOR != 16 # error Wrong GPANEL_MAJOR value! #endif -#if defined(HXTFT_ENABLED) || defined(GPANEL_ENABLED) +#if defined(HXTFT_ENABLED) || defined(GPANEL_ENABLED) || \ + defined(SGPANEL_ENABLED) gpanel_open, gpanel_close, gpanel_read, gpanel_write, gpanel_ioctl, nulldev, 0, seltrue, nostrategy, 0, 0, diff --git a/sys/pic32/files.kconf b/sys/pic32/files.kconf index 5c0a909..0c05df7 100644 --- a/sys/pic32/files.kconf +++ b/sys/pic32/files.kconf @@ -75,6 +75,8 @@ pic32/gpanel-ili9341.c optional gpanel pic32/gpanel-nt35702.c optional gpanel #pic32/gpanel-s6d04h0.c optional gpanel pic32/gpanel-st7781.c optional gpanel +pic32/gpanel-spi.c optional sgpanel +pic32/gpanel-spi-ili9341.c optional sgpanel pic32/gpio.c optional gpio pic32/hx8357.c optional hxtft pic32/picga.c optional picga diff --git a/sys/pic32/gpanel-spi-ili9341.c b/sys/pic32/gpanel-spi-ili9341.c new file mode 100644 index 0000000..4e05a7e --- /dev/null +++ b/sys/pic32/gpanel-spi-ili9341.c @@ -0,0 +1,371 @@ +/* + * Display driver for ILI9341 LCD controller. + * + * Copyright (C) 2015 Serge Vakulenko + * + * Permission to use, copy, modify, and distribute this software + * and its documentation for any purpose and without fee is hereby + * granted, provided that the above copyright notice appear in all + * copies and that both that the copyright notice and this + * permission notice and warranty disclaimer appear in supporting + * documentation, and that the name of the author not be used in + * advertising or publicity pertaining to distribution of the + * software without specific, written prior permission. + * + * The author disclaim all warranties with regard to this + * software, including all implied warranties of merchantability + * and fitness. In no event shall the author be liable for any + * special, indirect or consequential damages or any damages + * whatsoever resulting from loss of use, data or profits, whether + * in an action of contract, negligence or other tortious action, + * arising out of or in connection with the use or performance of + * this software. + */ +#include +#include + +/* + * ILI9341 registers. + */ +#define ILI9341_No_Operation 0x00 +#define ILI9341_Software_Reset 0x01 +#define ILI9341_Read_Display_Identification_Information 0x04 +#define ILI9341_Read_Display_Status 0x09 +#define ILI9341_Read_Display_Power_Mode 0x0A +#define ILI9341_Read_Display_MADCTL 0x0B +#define ILI9341_Read_Display_Pixel_Format 0x0C +#define ILI9341_Read_Display_Image_Format 0x0D +#define ILI9341_Read_Display_Signal_Mode 0x0E +#define ILI9341_Read_Display_Self_Diagnostic_Result 0x0F +#define ILI9341_Enter_Sleep_Mode 0x10 +#define ILI9341_Sleep_OUT 0x11 +#define ILI9341_Partial_Mode_ON 0x12 +#define ILI9341_Normal_Display_Mode_ON 0x13 +#define ILI9341_Display_Inversion_OFF 0x20 +#define ILI9341_Display_Inversion_ON 0x21 +#define ILI9341_Gamma_Set 0x26 +#define ILI9341_Display_OFF 0x28 +#define ILI9341_Display_ON 0x29 +#define ILI9341_Column_Address_Set 0x2A +#define ILI9341_Page_Address_Set 0x2B +#define ILI9341_Memory_Write 0x2C +#define ILI9341_Color_SET 0x2D +#define ILI9341_Memory_Read 0x2E +#define ILI9341_Partial_Area 0x30 +#define ILI9341_Vertical_Scrolling_Definition 0x33 +#define ILI9341_Tearing_Effect_Line_OFF 0x34 +#define ILI9341_Tearing_Effect_Line_ON 0x35 +#define ILI9341_Memory_Access_Control 0x36 +#define ILI9341_Vertical_Scrolling_Start_Address 0x37 +#define ILI9341_Idle_Mode_OFF 0x38 +#define ILI9341_Idle_Mode_ON 0x39 +#define ILI9341_Pixel_Format_Set 0x3A +#define ILI9341_Write_Memory_Continue 0x3C +#define ILI9341_Read_Memory_Continue 0x3E +#define ILI9341_Set_Tear_Scanline 0x44 +#define ILI9341_Get_Scanline 0x45 +#define ILI9341_Write_Display_Brightness 0x51 +#define ILI9341_Read_Display_Brightness 0x52 +#define ILI9341_Write_CTRL_Display 0x53 +#define ILI9341_Read_CTRL_Display 0x54 +#define ILI9341_Write_Content_Adaptive_Brightness_Control 0x55 +#define ILI9341_Read_Content_Adaptive_Brightness_Control 0x56 +#define ILI9341_Write_CABC_Minimum_Brightness 0x5E +#define ILI9341_Read_CABC_Minimum_Brightness 0x5F +#define ILI9341_Read_ID1 0xDA +#define ILI9341_Read_ID2 0xDB +#define ILI9341_Read_ID3 0xDC +#define ILI9341_RGB_Interface_Signal_Control 0xB0 +#define ILI9341_Frame_Control_In_Normal_Mode 0xB1 +#define ILI9341_Frame_Control_In_Idle_Mode 0xB2 +#define ILI9341_Frame_Control_In_Partial_Mode 0xB3 +#define ILI9341_Display_Inversion_Control 0xB4 +#define ILI9341_Blanking_Porch_Control 0xB5 +#define ILI9341_Display_Function_Control 0xB6 +#define ILI9341_Entry_Mode_Set 0xB7 +#define ILI9341_Backlight_Control_1 0xB8 +#define ILI9341_Backlight_Control_2 0xB9 +#define ILI9341_Backlight_Control_3 0xBA +#define ILI9341_Backlight_Control_4 0xBB +#define ILI9341_Backlight_Control_5 0xBC +#define ILI9341_Backlight_Control_7 0xBE +#define ILI9341_Backlight_Control_8 0xBF +#define ILI9341_Power_Control_1 0xC0 +#define ILI9341_Power_Control_2 0xC1 +#define ILI9341_VCOM_Control_1 0xC5 +#define ILI9341_VCOM_Control_2 0xC7 +#define ILI9341_NV_Memory_Write 0xD0 +#define ILI9341_NV_Memory_Protection Key 0xD1 +#define ILI9341_NV_Memory_Status Read 0xD2 +#define ILI9341_Read_ID4 0xD3 +#define ILI9341_Positive_Gamma_Correction 0xE0 +#define ILI9341_Negative_Gamma_Correction 0xE1 +#define ILI9341_Digital_Gamma_Control_1 0xE2 +#define ILI9341_Digital_Gamma_Control_2 0xE3 +#define ILI9341_Interface_Control 0xF6 + +/* + * Memory Access Control register + */ +#define MADCTL_MY 0x80 /* Row address order */ +#define MADCTL_MX 0x40 /* Column address order */ +#define MADCTL_MV 0x20 /* Row/column exchange */ +#define MADCTL_ML 0x10 /* Vertical refresh order */ +#define MADCTL_BGR 0x08 /* Color filter selector: 0=RGB, 1=BGR */ +#define MADCTL_MH 0x04 /* Horisontal refresh direction: 1=left-to-right */ + +/* + * Set address window. + */ +static void set_window(int x0, int y0, int x1, int y1) +{ + gpanel_send_command(ILI9341_Column_Address_Set); + gpanel_send_data(x0 >> 8); + gpanel_send_data(x0); + gpanel_send_data(x1 >> 8); + gpanel_send_data(x1); + + gpanel_send_command(ILI9341_Page_Address_Set); + gpanel_send_data(y0 >> 8); + gpanel_send_data(y0); + gpanel_send_data(y1 >> 8); + gpanel_send_data(y1); + + gpanel_send_command(ILI9341_Memory_Write); +} + +/* + * Draw a pixel. + */ +void ili9341_set_pixel(int x, int y, int color) +{ + if (x < 0 || x >= gpanel_width || y < 0 || y >= gpanel_height) + return; + gpanel_cs_active(); + set_window(x, y, x, y); + gpanel_send_data(color >> 8); + gpanel_send_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 i; + unsigned hi = color >> 8, + lo = color; + + for (i = npixels; i > 0; i--) { + gpanel_send_data(hi); + gpanel_send_data(lo); + } +} + +/* + * Switch the screen orientation. + */ +static void set_rotation(int rotation) +{ + gpanel_send_command(ILI9341_Memory_Access_Control); + switch (rotation & 3) { + case 0: /* Portrait */ + gpanel_send_data(MADCTL_MX | MADCTL_BGR); + gpanel_width = 240; + gpanel_height = 320; + break; + case 1: /* Landscape */ + gpanel_send_data(MADCTL_MV | MADCTL_BGR); + gpanel_width = 320; + gpanel_height = 240; + break; + case 2: /* Upside down portrait */ + gpanel_send_data(MADCTL_MY | MADCTL_BGR); + gpanel_width = 240; + gpanel_height = 320; + break; + case 3: /* Upside down landscape */ + gpanel_send_data(MADCTL_MX | MADCTL_MY | MADCTL_MV | MADCTL_BGR); + gpanel_width = 320; + gpanel_height = 240; + break; + } +} + +static void ili9341_resize(struct gpanel_hw *h, int width, int height) +{ + gpanel_cs_active(); + + /* Switch screen orientaation. */ + if (width > height) + set_rotation(1); /* Landscape */ + else if (width < height) + set_rotation(0); /* Portrait */ + + gpanel_cs_idle(); +} + +/* + * Fill a rectangle with specified 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 >= 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; + 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. + */ +void ili9341_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); + while (cnt--) { + color = *data++; + gpanel_send_data(color >> 8); + gpanel_send_data(color); + } + gpanel_cs_idle(); +} + +/* + * Draw a glyph of one symbol. + */ +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 > gpanel_width || y + font->height > gpanel_height) + return; + + if (background >= 0) { + /* + * Clear background. + */ + gpanel_cs_active(); + set_window(x, y, x + width - 1, y + font->height - 1); + + /* 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_send_data(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 = "Ilitek ILI9341"; + h->resize = ili9341_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-spi.c b/sys/pic32/gpanel-spi.c new file mode 100644 index 0000000..d02960a --- /dev/null +++ b/sys/pic32/gpanel-spi.c @@ -0,0 +1,499 @@ +/* + * Generic TFT LCD driver with SPI interface. + * Supported chips: ILI9341. + * + * Copyright (C) 2015 Serge Vakulenko + * + * Permission to use, copy, modify, and distribute this software + * and its documentation for any purpose and without fee is hereby + * granted, provided that the above copyright notice appear in all + * copies and that both that the copyright notice and this + * permission notice and warranty disclaimer appear in supporting + * documentation, and that the name of the author not be used in + * advertising or publicity pertaining to distribution of the + * software without specific, written prior permission. + * + * The author disclaim all warranties with regard to this + * software, including all implied warranties of merchantability + * and fitness. In no event shall the author be liable for any + * special, indirect or consequential damages or any damages + * whatsoever resulting from loss of use, data or profits, whether + * in an action of contract, negligence or other tortious action, + * arising out of or in connection with the use or performance of + * this software. + */ +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#define SGPANEL_KHZ 10000 /* clock 10 MHz */ + +/* + * Descriptor for access to the hardware-level driver. + */ +static struct gpanel_hw hw; + +/* + * Cursor position for text output. + */ +static int _col, _row; + +/* + * ID of the LCD controller chip. + */ +static int _chip_id; + +/* + * Data/command signal pin. + */ +static int _dc; +static int _last_dc = -1; /* last DC value */ + +static struct spiio _spiio; + +/* + * Display size. + */ +int gpanel_width, gpanel_height; + +/* + * Control /CS signal. + */ +void gpanel_cs_active() { spi_select(&_spiio); } +void gpanel_cs_idle() { spi_deselect(&_spiio); } + +/* + * Send a command to the SPI bus. + */ +int gpanel_send_command(int value) +{ + if (_last_dc != 0) { + gpio_clr(_dc); + _last_dc = 0; + } + return spi_transfer(&_spiio, value); +} + +/* + * Send data to the SPI bus. + */ +int gpanel_send_data(int value) +{ + if (_last_dc != 1) { + gpio_set(_dc); + _last_dc = 1; + } + return spi_transfer(&_spiio, value); +} + +/* + * Read a 32-bit value from the specified chip register. + */ +static int read_reg32(int reg) +{ + unsigned value; + + spi_select(&_spiio); + gpanel_send_command(reg); + value = gpanel_send_data(0) << 24; + value |= gpanel_send_data(0) << 16; + value |= gpanel_send_data(0) << 8; + value |= gpanel_send_data(0); + spi_deselect(&_spiio); + return value; +} + +/* + * Draw a line. + */ +static void gpanel_draw_line(int x0, int y0, int x1, int y1, int color) +{ + int dx, dy, stepx, stepy, fraction; + + if (x0 == x1 || y0 == y1) { + hw.fill_rectangle(x0, y0, x1, y1, color); + return; + } + + /* Use Bresenham's line algorithm. */ + dy = y1 - y0; + if (dy < 0) { + dy = -dy; + stepy = -1; + } else { + stepy = 1; + } + dx = x1 - x0; + if (dx < 0) { + dx = -dx; + stepx = -1; + } else { + stepx = 1; + } + dy <<= 1; /* dy is now 2*dy */ + dx <<= 1; /* dx is now 2*dx */ + hw.set_pixel(x0, y0, color); + if (dx > dy) { + fraction = dy - (dx >> 1); /* same as 2*dy - dx */ + while (x0 != x1) { + if (fraction >= 0) { + y0 += stepy; + fraction -= dx; /* same as fraction -= 2*dx */ + } + x0 += stepx; + fraction += dy; /* same as fraction -= 2*dy */ + hw.set_pixel(x0, y0, color); + } + } else { + fraction = dx - (dy >> 1); + while (y0 != y1) { + if (fraction >= 0) { + x0 += stepx; + fraction -= dy; + } + y0 += stepy; + fraction += dx; + hw.set_pixel(x0, y0, color); + } + } +} + +/* + * Draw a rectangular frame. + */ +static void gpanel_draw_frame(int x0, int y0, int x1, int y1, int color) +{ + hw.fill_rectangle(x0, y0, x1, y0, color); + hw.fill_rectangle(x0, y1, x1, y1, color); + hw.fill_rectangle(x0, y0, x0, y1, color); + hw.fill_rectangle(x1, y0, x1, y1, color); +} + +/* + * Draw a circle. + */ +static void gpanel_draw_circle(int x0, int y0, int radius, int color) +{ + int f = 1 - radius; + int ddF_x = 0; + int ddF_y = -2 * radius; + int x = 0; + int y = radius; + + hw.set_pixel(x0, y0 + radius, color); + hw.set_pixel(x0, y0 - radius, color); + hw.set_pixel(x0 + radius, y0, color); + hw.set_pixel(x0 - radius, y0, color); + while (x < y) { + if (f >= 0) { + y--; + ddF_y += 2; + f += ddF_y; + } + x++; + ddF_x += 2; + f += ddF_x + 1; + hw.set_pixel(x0 + x, y0 + y, color); + hw.set_pixel(x0 - x, y0 + y, color); + hw.set_pixel(x0 + x, y0 - y, color); + hw.set_pixel(x0 - x, y0 - y, color); + hw.set_pixel(x0 + y, y0 + x, color); + hw.set_pixel(x0 - y, y0 + x, color); + hw.set_pixel(x0 + y, y0 - x, color); + hw.set_pixel(x0 - y, y0 - x, color); + } +} + +/* + * Draw a character from a specified font. + */ +static void gpanel_draw_char(const struct gpanel_font_t *font, + int color, int background, int sym) +{ + unsigned cindex, width; + const unsigned short *bits; + + switch (sym) { + case '\n': /* goto next line */ + _row += font->height; + _col = 0; + if (_row > gpanel_height - font->height) + _row = 0; + return; + case '\r': /* carriage return - go to begin of line */ + _col = 0; + return; + case '\t': /* tab replaced by space */ + sym = ' '; + break; + } + + if (sym < font->firstchar || sym >= font->firstchar + font->size) + sym = font->defaultchar; + cindex = sym - font->firstchar; + + /* Get font bitmap depending on fixed pitch or not. */ + if (font->width) { + /* Proportional font. */ + width = font->width[cindex]; + } else { + /* Fixed width font. */ + width = font->maxwidth; + } + if (font->offset) { + bits = font->bits + font->offset[cindex]; + } else { + bits = font->bits + cindex * font->height; + } + + /* Draw a character. */ + hw.draw_glyph(font, color, background, _col, _row, width, bits); + _col += width; +} + +/* + * Draw a string of characters. + * TODO: Decode UTF-8. + */ +static void gpanel_draw_text(const struct gpanel_font_t *font, + int color, int background, int x, int y, const char *text) +{ + int sym; + + _col = x; + _row = y; + for (;;) { + sym = *text++; + if (! sym) + break; + + gpanel_draw_char(font, color, background, sym); + } +} + +int gpanel_open(dev_t dev, int flag, int mode) +{ + if (minor(dev) != 0) + return ENODEV; + return 0; +} + +int gpanel_close(dev_t dev, int flag, int mode) +{ + return 0; +} + +int gpanel_read(dev_t dev, struct uio *uio, int flag) +{ + return ENODEV; +} + +int gpanel_write(dev_t dev, struct uio *uio, int flag) +{ + return ENODEV; +} + +/* + * TODO: check whether user pointers are valid. + */ +int gpanel_ioctl(dev_t dev, register u_int cmd, caddr_t addr, int flag) +{ + switch (cmd) { + /* + * Clear the whole screen with a given color. + */ + case GPANEL_CLEAR: { + struct gpanel_clear_t *param = (struct gpanel_clear_t*) addr; + + 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; + } + + /* + * Draw a single pixel. + */ + case GPANEL_PIXEL: { + struct gpanel_pixel_t *param = (struct gpanel_pixel_t*) addr; + + hw.set_pixel(param->x, param->y, param->color); + break; + } + + /* + * Draw a line. + */ + case GPANEL_LINE: { + struct gpanel_line_t *param = (struct gpanel_line_t*) addr; + + gpanel_draw_line(param->x0, param->y0, param->x1, param->y1, param->color); + break; + } + + /* + * Draw a rectangle frame. + */ + case GPANEL_RECT: { + struct gpanel_rect_t *param = (struct gpanel_rect_t*) addr; + + gpanel_draw_frame(param->x0, param->y0, param->x1, param->y1, param->color); + break; + } + + /* + * Fill a rectangle with color. + */ + case GPANEL_FILL: { + struct gpanel_rect_t *param = (struct gpanel_rect_t*) addr; + + hw.fill_rectangle(param->x0, param->y0, param->x1, param->y1, param->color); + break; + } + + /* + * Draw a circle. + */ + case GPANEL_CIRCLE: { + struct gpanel_circle_t *param = (struct gpanel_circle_t*) addr; + + gpanel_draw_circle(param->x, param->y, param->radius, param->color); + break; + } + + /* + * Fill a rectangular area with the user-supplied data. + */ + case GPANEL_IMAGE: { + struct gpanel_image_t *param = (struct gpanel_image_t*) addr; + + hw.draw_image(param->x, param->y, param->width, param->height, + param->image); + break; + } + + /* + * Draw a character. + */ + case GPANEL_CHAR: { + struct gpanel_char_t *param = (struct gpanel_char_t*) addr; + + _col = param->x; + _row = param->y; + gpanel_draw_char(param->font, param->color, param->background, param->sym); + break; + } + + /* + * Draw a string of characters. + */ + case GPANEL_TEXT: { + struct gpanel_text_t *param = (struct gpanel_text_t*) addr; + + gpanel_draw_text(param->font, param->color, param->background, + param->x, param->y, param->text); + break; + } + } + return 0; +} + +/* + * Draw a BSD logo on the screen. + */ +static void draw_logo() +{ +#define K 7 +#define COLOR_B 0xf81f +#define COLOR_S 0x07ff +#define COLOR_D 0xffe0 + + int x = gpanel_width/2 - 17*K; + int y = gpanel_height/2 + 11*K; + + 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); + gpanel_draw_line( 0*K+x, y-11*K, 0*K+x, y-22*K, COLOR_B); + gpanel_draw_line( 0*K+x, y-22*K, 10*K+x, y-19*K, COLOR_B); + gpanel_draw_line(10*K+x, y-19*K, 0*K+x, y-11*K, COLOR_B); + gpanel_draw_line( 0*K+x, y-11*K, 10*K+x, y- 8*K, COLOR_B); + gpanel_draw_line(10*K+x, y- 8*K, 0*K+x, y- 0*K, COLOR_B); + + /* S */ + gpanel_draw_line(22*K+x, y-22*K, 12*K+x, y-19*K, COLOR_S); + gpanel_draw_line(12*K+x, y-19*K, 22*K+x, y- 8*K, COLOR_S); + gpanel_draw_line(22*K+x, y- 8*K, 12*K+x, y- 0*K, COLOR_S); + + /* D */ + gpanel_draw_line(24*K+x, y-22*K, 24*K+x, y- 0*K, COLOR_D); + gpanel_draw_line(24*K+x, y-22*K, 34*K+x, y-19*K, COLOR_D); + gpanel_draw_line(34*K+x, y-19*K, 34*K+x, y- 8*K, COLOR_D); + gpanel_draw_line(34*K+x, y- 8*K, 24*K+x, y- 0*K, COLOR_D); +} + +/* + * Detect the type of the LCD controller, and initialize it. + * Return true if found and initialized ok. + */ +static int probe(config) + struct conf_device *config; +{ + int cs; + struct spiio *io = &_spiio; + + /* Only one device is allowed. */ + if (config->dev_unit > 0) + return 0; + cs = config->dev_pins[0]; + _dc = config->dev_pins[1]; + printf("sgpanel: port SPI%d, pins cs=R%c%d/dc=R%c%d\n", + config->dev_ctlr, gpio_portname(cs), gpio_pinno(cs), + gpio_portname(_dc), gpio_pinno(_dc)); + + if (spi_setup(io, config->dev_ctlr, cs) != 0) { + printf("sgpanel: cannot open SPI%u port\n", config->dev_ctlr); + return 0; + } + spi_brg(io, SGPANEL_KHZ); + spi_set(io, PIC32_SPICON_CKE); + + /* Enable outputs. */ + gpio_set_output(_dc); + + /* Read the the chip ID register. */ + _chip_id = read_reg32(0xD3) & 0xffffff; + switch (_chip_id) { + default: + printf("sgpanel0: Unknown chip ID = 0x%04x\n", _chip_id); + goto failed; + + case 0x009341: + /* Ilitek ILI9341. */ + ili9341_init_display(&hw); + break; + } + printf("gpanel0: <%s> display %ux%u\n", hw.name, gpanel_width, gpanel_height); + draw_logo(); + return 1; + +failed: + /* Disable outputs. */ + gpio_set_input(_dc); + gpio_set_input(cs); + return 0; +} + +struct driver sgpaneldriver = { + "sgpanel", probe, +}; diff --git a/sys/pic32/wf32/Config b/sys/pic32/wf32/Config index 4c07a8b..e40aab5 100644 --- a/sys/pic32/wf32/Config +++ b/sys/pic32/wf32/Config @@ -65,7 +65,8 @@ device adc # PWM driver device pwm -# TFT display driver: ST7781 +# TFT display driver with 8-bit parallel interface. +# Supported controllers: ST7781, ILI9341, NT35702 device gpanel signal "LCD_RST" pin RB10 signal "LCD_CS" pin RB0 diff --git a/sys/pic32/wf32/Config-adafruit b/sys/pic32/wf32/Config-adafruit new file mode 100644 index 0000000..be7428a --- /dev/null +++ b/sys/pic32/wf32/Config-adafruit @@ -0,0 +1,72 @@ +# +# chipKIT WF32 board with microSD card on Adafruit 2.8" TFT Touch Shield +# +# To build the kernel, use: +# cd sys/pic32/wf32 +# kconfig Config +# make clean +# make +# +# Format of this file is described on page: +# http://retrobsd.org/wiki/doku.php/doc/kconfig +# +architecture "pic32" +cpu "PIC32MX7" # Processor variant +board "WF32" # Board type +ldscript "max32/bootloader.ld" # Linker script + +# Standard system options +options "CPU_KHZ=80000" # Oscillator frequency of CPU core +options "BUS_KHZ=80000" # Frequency of peripheral bus +options "BUS_DIV=1" # Bus clock divisor 1/2/4/8 + +# LEDs +signal "LED_KERNEL" pin RA0 # kernel activity indicator +signal "LED_DISK" pin RA1 # disk activity indicator + +# Root filesystem at /dev/sd0a, swap at /dev/sd0b +config unix root on sd0a + swap on sd0b + +# Serial UART ports +device uart1 # Serial-to-USB converter + +# Console options +options "CONS_MAJOR=UART_MAJOR" # UART device +options "CONS_MINOR=0" # /dev/tty0 + +# SPI ports +controller spi2 # SD card + +# microSD card +device sd0 at spi2 pin RF1 # select pin RF1 (Digital #4) +options "SD_MHZ=10" # speed 10 MHz + +# General purpose I/O ports +# Flags define a mask of available pins +# The following pins excluded: +# RF2, RF8 - uart1 +# RG6, RG7, RG8, RD4 - spi2, SD card +# RA14, RB0, RB2, RB4, +# RB8, RB10, RD0, RD1, +# RD2, RD3, RE8, RE9, RF1 - LCD display +# +device gpio0 flags 0x86ff # port A +device gpio1 flags 0xfaea # port B +device gpio2 flags 0xf01e # port C +device gpio3 flags 0xffe0 # port D +device gpio4 flags 0x00ff # port E +device gpio5 flags 0x3039 # port F +device gpio6 flags 0xf20f # port G + +# ADC driver +device adc + +# PWM driver +device pwm + +# TFT display driver with SPI interface. +# Supported controllers: ILI9341. +device sgpanel at spi2 + pins RD4, # CS - Digital #10 + RD3 # DC - Digital #9