aboutsummaryrefslogtreecommitdiff
#include <tft.h>
#include <hardware.h>
#include <zeta.h>

void
_delay_ms(u8 ms);

/*
 * Driver for the ILI9341 TFT Chip
 */

static inline void
tft_soft_reset(void)
{
	tft_ctrl = SWRESET;
}

static inline void
tft_enable_ext_cmd(void)
{
	tft_ctrl = SETEXTC;
	tft_data = 0xFF;
	tft_data = 0x83;
	tft_data = 0x57;
}

static inline void
tft_memory_access_ctrl(u8 bits)
{
	tft_ctrl = MADCTL;
	tft_data = bits;
}

static inline void
tft_sleep_out(void) {
	tft_ctrl = SLPOUT;
}

static inline void
tft_display_on(void)
{
	tft_ctrl = DISPON;
}

static inline void
tft_pixel_format(u8 dbi, u8 dpi)
{
	tft_ctrl = COLMOD;
	tft_data = (dpi << 4) | dbi;
}

static inline void
tft_set_rgb_interface(void)
{
	tft_ctrl = SETRGB;
	tft_data = 0x00;
	tft_data = 0x00;
	tft_data = 0x06;
	tft_data = 0x06;
}

static inline void
tft_set_col_addr(u16 start, u16 end)
{
	tft_ctrl = CASET;
	tft_data = start >> 8;
	tft_data = start & 0xFF;
	tft_data = end >> 8;
	tft_data = end & 0xFF;
}

static inline void
tft_set_page_addr(u16 start, u16 end)
{
	tft_ctrl = PASET;
	tft_data = start >> 8;
	tft_data = start & 0xFF;
	tft_data = end >> 8;
	tft_data = end & 0xFF;
}

void
tft_set_area(u16 x, u16 y, u16 w, u16 h)
{
	tft_set_col_addr(x, x + w - 1);
	tft_set_page_addr(y, y + h - 1);
}

enum memory_access {
	// MY MX MV ML |  BGR SS X X
	MV = 0x20, // 1: landscape 0 <= x < 480; 0 <= y < 320
	MX = 0x40, // MV = 0: Invert X; MV = 1: Invert Y
	MY = 0x80, // MV = 0: Invert Y; MV = 1: Invert X
	ML = 0x10
};

extern u8 blink;

void
clear_screen(void)
{
	DI;
	u8 tmp = blink;
	blink = 0;
	EI;

	tft_set_col_addr(0, TFT_WIDTH - 1);
	tft_set_page_addr(0, TFT_HEIGHT - 1);

	tft_ctrl = RAMWR;
	for (u16 i = 0; i < TFT_HEIGHT; ++i) {
		for (u16 j = 0; j < TFT_WIDTH; ++j) {
			tft_data = 0x00;
			tft_data = 0x00;
		}
	}

	DI;
	blink = tmp;
	EI;
}

void
tft_init(void)
{
	_delay_ms(200);

	tft_soft_reset();
	tft_enable_ext_cmd();

	_delay_ms(250);

	tft_set_rgb_interface();

	tft_pixel_format(BIT16, BIT16);

	tft_memory_access_ctrl(MV | 0x0C);
	tft_sleep_out();

	_delay_ms(150);

	tft_display_on();

	_delay_ms(50);
	clear_screen();
}