Add sgpanel driver: a generic TFT LCD graphics panel with SPI interface.

Currently only ILI8341 chip is supported.
This commit is contained in:
Serge Vakulenko
2015-11-28 00:17:01 -08:00
parent e073fcbd64
commit ac9ef0eee9
8 changed files with 952 additions and 3 deletions

View File

@@ -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.

View File

@@ -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

View File

@@ -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,

View File

@@ -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

View File

@@ -0,0 +1,371 @@
/*
* Display driver for ILI9341 LCD controller.
*
* Copyright (C) 2015 Serge Vakulenko <serge@vak.ru>
*
* 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 <sys/param.h>
#include <sys/gpanel.h>
/*
* 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; 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_send_data(c >> 8);
gpanel_send_data(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)
ili9341_set_pixel(x + w, y + h, color);
}
}
}
}
/*
* Initialize the LCD controller.
* Fill the gpanel_hw descriptor.
*/
void ili9341_init_display(struct gpanel_hw *h)
{
/* Use a few NOPs to synchronize after the hard Reset. */
gpanel_cs_active();
gpanel_send_command(ILI9341_No_Operation);
gpanel_send_command(ILI9341_No_Operation);
gpanel_send_command(ILI9341_No_Operation);
gpanel_send_command(ILI9341_No_Operation);
gpanel_send_command(ILI9341_Sleep_OUT);
udelay(150000);
gpanel_send_command(ILI9341_Display_OFF);
gpanel_send_command(ILI9341_Power_Control_1);
gpanel_send_data(0x23);
gpanel_send_command(ILI9341_Power_Control_2);
gpanel_send_data(0x10);
gpanel_send_command(ILI9341_VCOM_Control_1);
gpanel_send_data(0x2B);
gpanel_send_data(0x2B);
gpanel_send_command(ILI9341_VCOM_Control_2);
gpanel_send_data(0xC0);
gpanel_send_command(ILI9341_Pixel_Format_Set);
gpanel_send_data(0x55);
gpanel_send_command(ILI9341_Frame_Control_In_Normal_Mode);
gpanel_send_data(0x00);
gpanel_send_data(0x1B);
gpanel_send_command(ILI9341_Entry_Mode_Set);
gpanel_send_data(0x07);
gpanel_send_command(ILI9341_Display_ON);
set_rotation(1); /* Landscape */
gpanel_cs_idle();
/*
* Fill the gpanel_hw descriptor.
*/
h->name = "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;
}

499
sys/pic32/gpanel-spi.c Normal file
View File

@@ -0,0 +1,499 @@
/*
* Generic TFT LCD driver with SPI interface.
* Supported chips: ILI9341.
*
* Copyright (C) 2015 Serge Vakulenko <serge@vak.ru>
*
* 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 <sys/param.h>
#include <sys/conf.h>
#include <sys/user.h>
#include <sys/ioctl.h>
#include <sys/systm.h>
#include <sys/uio.h>
#include <sys/tty.h>
#include <sys/kconfig.h>
#include <sys/spi.h>
#include <sys/gpanel.h>
#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,
};

View File

@@ -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

View File

@@ -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