Add sgpanel driver: a generic TFT LCD graphics panel with SPI interface.
Currently only ILI8341 chip is supported.
This commit is contained in:
@@ -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.
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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,
|
||||
|
||||
@@ -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
|
||||
|
||||
371
sys/pic32/gpanel-spi-ili9341.c
Normal file
371
sys/pic32/gpanel-spi-ili9341.c
Normal 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
499
sys/pic32/gpanel-spi.c
Normal 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,
|
||||
};
|
||||
@@ -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
|
||||
|
||||
72
sys/pic32/wf32/Config-adafruit
Normal file
72
sys/pic32/wf32/Config-adafruit
Normal 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
|
||||
Reference in New Issue
Block a user