/*
* File: tft.c
* Author: torsten.roemer@luniks.net
*
* Created on 6. November 2023, 18:45
*/
#include "tft.h"
/**
* Does a hardware reset.
*/
static void hwReset(void) {
PORT_DISP &= ~(1 << PIN_DRST);
_delay_ms(10);
PORT_DISP |= (1 << PIN_DRST);
}
static void displaySel(void) {
PORT_DISP &= ~(1 << PIN_DCS);
}
static void displayDes(void) {
PORT_DISP |= (1 << PIN_DCS);
}
/**
* Sets display to send a command.
*/
static void displaySetCmd(void) {
PORT_DISP &= ~(1 << PIN_DDC);
}
/**
* Sets display to send data.
*/
static void displaySetData(void) {
PORT_DISP |= (1 << PIN_DDC);
}
/**
* Sends the given command to the display.
*
* @param cmd
*/
static void displayCmd(uint8_t cmd) {
displaySetCmd();
transmit(cmd);
}
/**
* Sends the given data to the display.
*
* @param data
*/
static void displayData(uint8_t data) {
displaySetData();
transmit(data);
}
/**
* Sets horizontal and/or vertical flip.
*
* @param hflip
* @param vflip
*/
static void madctl(bool hflip, bool vflip) {
// Memory data access control
uint8_t madctl = 0b00110110;
madctl |= (HFLIP << 7);
madctl |= (VFLIP << 6);
madctl |= (BGR << 3);
if (hflip) {
// Row Address Order (MY)
madctl ^= (1 << 7);
}
if (vflip) {
// Column Address Order (MX)
madctl ^= (1 << 6);
}
displaySel();
displayCmd(MADCTL);
displayData(madctl);
displayDes();
}
/**
* Sets the given column start and end address.
*
* @param xs start address
* @param xe end address
*/
static void caset(x_t xs, x_t xe) {
displaySel();
displayCmd(CASET);
displayData(xs >> 8);
displayData(xs);
displayData(xe >> 8);
displayData(xe);
displayDes();
}
/**
* Sets the given row start and end address.
*
* @param ys start address
* @param ye end address
*/
static void raset(y_t ys, y_t ye) {
displaySel();
displayCmd(RASET);
displayData(ys >> 8);
displayData(ys);
displayData(ye >> 8);
displayData(ye);
displayDes();
}
void initDisplay(void) {
_delay_ms(10);
// Hardware reset
hwReset();
// TODO necessary?
_delay_ms(10);
// Software reset
displaySel();
displayCmd(SWRESET);
displayDes();
// TODO necessary?
_delay_ms(10);
// Sleep out & booster on
displaySel();
displayCmd(SLPOUT);
displayDes();
// Partial off (Normal)
displaySel();
displayCmd(NORON);
displayDes();
// Display Inversion on/off
displaySel();
displayCmd(INVOFF + INVERT); // INVOFF + 1 = INVON
displayDes();
// Interface pixel format
displaySel();
displayCmd(COLMOD);
displayData(0b00111101);
displayDes();
// Display on
displaySel();
displayCmd(DISPON);
displayDes();
// Sleep in & booster off
// displaySel();
// displayCmd(SLPIN);
// displayDes();
printString("Display init done\r\n");
}
void demoDisplay(void) {
// TODO
}
void drawPixel(x_t x, y_t y, uint16_t color) {
// TODO
}
void drawCircle(x_t x, y_t y, uint16_t radius, uint16_t color) {
// TODO
}
void drawRectangle(x_t x, y_t y, width_t width, height_t height,
uint16_t color) {
// TODO
}
void writeStart(void) {
// Memory write
displaySel();
displayCmd(RAMWR);
displaySetData();
}
void writeRestart(void) {
displaySel();
}
void writeByte(uint8_t byte) {
// Memory write
transmit(byte);
}
void writeEnd(void) {
// Memory write
displayDes();
}
void fillArea(x_t x, x_t y,
width_t width, height_t height,
uint16_t color) {
madctl(false, false);
// X address start/end
uint16_t xs = x;
uint16_t xe = x + width - 1;
caset(xs, xe);
// Y address start/end
uint16_t ys = y;
uint16_t ye = y + height - 1;
raset(ys, ye);
writeStart();
bytes_t pixels = (bytes_t)width * (bytes_t)height;
for (bytes_t i = 0; i < pixels; i++) {
transmit(color >> 8);
transmit(color);
}
writeEnd();
}
void setArea(x_t x, y_t y,
width_t width, height_t height,
bool hflip, bool vflip) {
madctl(hflip, vflip);
// X address start/end
uint16_t xs = x;
uint16_t xe = x + width - 1;
if (hflip) {
xs = DISPLAY_WIDTH - x - width;
xe = DISPLAY_WIDTH - x - 1;
}
caset(xs, xe);
// Y address start/end
uint16_t ys = y;
uint16_t ye = y + height - 1;
if (vflip) {
ys = DISPLAY_HEIGHT - y - height;
ye = DISPLAY_HEIGHT - y - 1;
}
raset(ys, ye);
}
void writeData(const __flash uint8_t *bitmap,
width_t width, height_t height,
space_t space, uint16_t bg, uint16_t fg) {
writeStart();
writeSpace(bitmap, width, height, space, bg, fg);
writeEnd();
}