2022-03-10 11:04:14 +03:00

434 lines
12 KiB
C

/*
* lcd.c
*
* Copyright 2016 Edward V. Emelianov <eddy@sao.ru, edward.emelianoff@gmail.com>
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation; either version 2 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program; if not, write to the Free Software
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston,
* MA 02110-1301, USA.
*/
#include "main.h"
#include "lcd.h"
#include "hardware_ini.h"
#include "dmagpio.h"
#include "registers.h"
static uint16_t LCD_id = 0;
#define nop() __asm__("nop")
uint8_t readbyte(){
RD_clear;
nop();
uint8_t byte = LCD_rdbyte();
RD_set;
nop();
return byte;
}
void writebyte(uint8_t b){
LCD_wrbyte(b);
WR_clear;
nop();
WR_set;
nop();
}
void writereg(uint16_t r){
LCD_wrbyte(r >> 8);
RS_clear;
WR_clear;
nop();
WR_set;
LCD_wrbyte(r & 0xff);
nop();
WR_clear;
nop();
WR_set;
RS_set;
}
uint16_t read_reg(uint16_t reg){
uint32_t dat = 0;
CS_clear; // active
writereg(reg);
LCD_read();
dat = readbyte() << 8;
dat |= readbyte();
CS_set;
LCD_write(); // restore dir to out
return dat;
}
void write_reg(uint16_t reg, uint16_t dat){
CS_clear; // active
writereg(reg);
RS_set; // data
writebyte(dat >> 8);
writebyte(dat && 0xff);
CS_set;
}
/*
typedef union{
uint8_t bytes[4];
uint32_t word;
}word32;
void write16_16(uint16_t reg, uint16_t dat){
CS_clear; // active
RS_clear; // register
LCD_write(); // dir: out
writebyte(reg >> 8);
writebyte(reg && 0xff);
RS_set; // data
writebyte(dat >> 8);
writebyte(dat && 0xff);
CS_set;
}
void write_reg16_var(uint16_t reg, uint32_t dat, uint8_t len){
int i;
CS_clear; // active
RS_clear; // register
LCD_write(); // dir: out
writebyte(reg >> 8);
writebyte(reg && 0xff);
RS_set; // data
word32 w;
w.word = dat;
--len;
for(i = len; i > -1; --i){
writebyte(w.bytes[i]);
}
CS_set;
}
void write_reg_var(uint8_t reg, uint32_t dat, uint8_t len){
int i;
CS_clear; // active
RS_clear; // register
LCD_write(); // dir: out
writebyte(reg);
RS_set; // data
word32 w;
w.word = dat;
--len;
for(i = len; i > -1; --i){
writebyte(w.bytes[i]);
}
CS_set;
}
uint32_t read_reg_var(uint8_t reg, uint8_t len){
uint32_t dat = 0;
int i;
CS_clear; // active
RS_clear; // register
LCD_write(); // dir: out
writebyte(reg);
LCD_read();
RS_set; // data
for(i = 0; i < len; ++i){
dat <<= 8;
dat = dat | readbyte();
}
CS_set;
return dat;
}
uint32_t read16_reg_var(uint16_t reg, uint8_t len){
uint32_t dat = 0;
int i;
CS_clear; // active
RS_clear; // register
LCD_write(); // dir: out
writebyte(reg >> 8);
writebyte(reg & 0xff);
LCD_read();
RS_set; // data
for(i = 0; i < len; ++i){
dat <<= 8;
dat = dat | readbyte();
}
CS_set;
return dat;
}
*/
uint16_t LCD_status_read(){
uint16_t dat;
LCD_read();
CS_clear;
RS_clear;
dat = readbyte() << 8;
dat |= readbyte();
RS_set;
CS_set;
LCD_write();
return dat;
}
void LCD_reset(){
CS_set; RS_set; WR_set; RD_set;
LCD_write();
LCD_wrbyte(0xff);
RST_clear;
Delay(300);
RST_set;
Delay(100);
write_reg(0,1);
Delay(100);
/* CS_clear; RS_clear;
int i;
for(i = 0; i < 4; ++i) writebyte(0);
RS_set; CS_set;
*/
}
/**
* read LCD identification
*/
uint16_t LCD_read_id(){
write_reg(0,0);
LCD_id = read_reg(0);
write_reg(0,1);
/*if(read8_32(0x04) == 0x8000){
write8_24(HX8357D_SETC, 0xFF8357);
Delay(10);
if(read8_32(0xD0) == 0x990000){
LCD_id = 0x8357;
return 0x8357;
}
}
if(read8_32(0xD3) == 0x9341){
LCD_id = 0x9341;
return 0x9341;
}*/
return LCD_id;
}
#define TFTLCD_DELAY 0xfff
static const uint16_t ILI932x_regValues[] = {
ILI932X_START_OSC , 0x0001, // 0x00
TFTLCD_DELAY , 100,
ILI932X_DISP_CTRL1 , 0x0121, // 0x07
ILI932X_DRIV_OUT_CTRL , 0x0100, // 0x01
ILI932X_DRIV_WAV_CTRL , 0x0700, // 0x02
ILI932X_ENTRY_MOD , 0x0030, // 0x03
ILI932X_RESIZE_CTRL , 0x0000, // 0x04
ILI932X_DISP_CTRL2 , 0x0202, // 0x08
ILI932X_DISP_CTRL3 , 0x0000, // 0x09
ILI932X_DISP_CTRL4 , 0x0000, // 0x0A
ILI932X_RGB_DISP_IF_CTRL1, 0x0001, // 0x0C
ILI932X_FRM_MARKER_POS , 0x0000, // 0x0D
ILI932X_RGB_DISP_IF_CTRL2, 0x0000, // 0x0F
/*
ILI932X_POW_CTRL1 , 0x0000, // 0x10
ILI932X_POW_CTRL2 , 0x0007, // 0x11
ILI932X_POW_CTRL3 , 0x0000, // 0x12
ILI932X_POW_CTRL4 , 0x0000, // 0x13
TFTLCD_DELAY , 200,
ILI932X_POW_CTRL1 , 0x1690, // 0x10
ILI932X_POW_CTRL2 , 0x0227, // 0x11
TFTLCD_DELAY , 50,
//ILI932X_POW_CTRL3 , 0x001A, // 0x12
ILI932X_POW_CTRL3 , 0x001D, // 0x12
TFTLCD_DELAY , 50,
//ILI932X_POW_CTRL4 , 0x1800, // 0x13
ILI932X_POW_CTRL4 , 0x0800, // 0x13
//ILI932X_POW_CTRL7 , 0x002A, // 0x29
ILI932X_POW_CTRL7 , 0x0012, // 0x29
*/
ILI932X_POW_CTRL1 , 0x16b0, // 0x10
ILI932X_POW_CTRL2 , 0x0007, // 0x11
ILI932X_POW_CTRL3 , 0x0138, // 0x12
ILI932X_POW_CTRL4 , 0x0b00, // 0x13
ILI932X_POW_CTRL7 , 0x0000, // 0x29
TFTLCD_DELAY , 200,
ILI932X_FRM_RATE_COL_CTRL, 0x0000, // 0x2B (100Hz)
TFTLCD_DELAY , 50,
ILI932X_GAMMA_CTRL1 , 0x0000, // 0x30
ILI932X_GAMMA_CTRL2 , 0x0000, // 0x31
ILI932X_GAMMA_CTRL3 , 0x0000, // 0x32
ILI932X_GAMMA_CTRL4 , 0x0206, // 0x35
ILI932X_GAMMA_CTRL5 , 0x0808, // 0x36
ILI932X_GAMMA_CTRL6 , 0x0007, // 0x37
ILI932X_GAMMA_CTRL7 , 0x0201, // 0x38
ILI932X_GAMMA_CTRL8 , 0x0000, // 0x39
ILI932X_GAMMA_CTRL9 , 0x0000, // 0x3C
ILI932X_GAMMA_CTRL10 , 0x0000, // 0x3D
ILI932X_GRAM_HOR_AD , 0x0000, // 0x20
ILI932X_GRAM_VER_AD , 0x0000, // 0x21
ILI932X_HOR_START_AD , 0x0000, // 0x50
ILI932X_HOR_END_AD , TFTWIDTH-1, // 0x51
ILI932X_VER_START_AD , 0x0000, // 0x52
ILI932X_VER_END_AD , TFTHEIGHT-1, // 0x53
//ILI932X_GATE_SCAN_CTRL1 , 0xA700, // 0x60
ILI932X_GATE_SCAN_CTRL1 , 0x2700, // 0x60
//ILI932X_GATE_SCAN_CTRL2 , 0x0003, // 0x61
ILI932X_GATE_SCAN_CTRL2 , 0x0001, // 0x61
ILI932X_GATE_SCAN_CTRL3 , 0x0000, // 0x6A
ILI932X_PANEL_IF_CTRL1 , 0x0010, // 0x90
ILI932X_PANEL_IF_CTRL2 , 0x0000, // 0x92
ILI932X_PANEL_IF_CTRL3 , 0x0003, // 0x93
ILI932X_PANEL_IF_CTRL4 , 0x0110, // 0x95
ILI932X_PANEL_IF_CTRL5 , 0x0000, // 0x97
ILI932X_PANEL_IF_CTRL6 , 0x0000, // 0x98
TFTLCD_DELAY , 50,
//ILI932X_DISP_CTRL1 , 0x013b, // 0x07 - 8bit color
ILI932X_DISP_CTRL1 , 0x0133, // 0x07
};
/*
static const uint16_t ILI932x_regValues[] = {
ILI932X_START_OSC , 0x0001, // 0x00
TFTLCD_DELAY , 100,
ILI932X_DRIV_OUT_CTRL , 0x0000, // 0x01
ILI932X_DRIV_WAV_CTRL , 0x0700, // 0x02
ILI932X_ENTRY_MOD , 0x1030, // 0x03
ILI932X_RESIZE_CTRL , 0x0000, // 0x04
ILI932X_DISP_CTRL2 , 0x0202, // 0x08
ILI932X_DISP_CTRL3 , 0x0000, // 0x09
ILI932X_DISP_CTRL4 , 0x0000, // 0x0A
ILI932X_RGB_DISP_IF_CTRL1, 0x0003, // 0x0C
ILI932X_FRM_MARKER_POS , 0x0000, // 0x0D
ILI932X_RGB_DISP_IF_CTRL2, 0x0000, // 0x0F
ILI932X_DISP_CTRL1 , 0x0021, // 0x07
TFTLCD_DELAY , 10,
ILI932X_POW_CTRL1 , 0x0000, // 0x10
ILI932X_POW_CTRL2 , 0x0007, // 0x11
ILI932X_POW_CTRL3 , 0x0000, // 0x12
ILI932X_POW_CTRL4 , 0x0000, // 0x13
TFTLCD_DELAY , 100,
ILI932X_POW_CTRL1 , 0x1690, // 0x10
ILI932X_POW_CTRL2 , 0x0007, // 0x11
TFTLCD_DELAY , 100,
ILI932X_POW_CTRL3 , 0x0118, // 0x12
TFTLCD_DELAY , 100,
ILI932X_POW_CTRL4 , 0x0b00, // 0x13
TFTLCD_DELAY , 100,
ILI932X_POW_CTRL7 , 0x0012, // 0x29
ILI932X_FRM_RATE_COL_CTRL, 0x000B, // 0x2B
ILI932X_GRAM_HOR_AD , 0x0000, // 0x20
ILI932X_GRAM_VER_AD , 0x0000, // 0x21
ILI932X_HOR_START_AD , 0x0000, // 0x50
ILI932X_HOR_END_AD , TFTWIDTH-1, // 0x51
ILI932X_VER_START_AD , 0x0000, // 0x52
ILI932X_VER_END_AD , TFTHEIGHT-1, // 0x53
ILI932X_GATE_SCAN_CTRL1 , 0x2700, // 0x60
ILI932X_GATE_SCAN_CTRL2 , 0x0001, // 0x61
ILI932X_GATE_SCAN_CTRL3 , 0x0000, // 0x6A
ILI932X_PANEL_IF_CTRL1 , 0x0010, // 0x90
ILI932X_PANEL_IF_CTRL2 , 0x0000, // 0x92
ILI932X_PANEL_IF_CTRL3 , 0x0001, // 0x93
ILI932X_PANEL_IF_CTRL4 , 0x0110, // 0x95
ILI932X_PANEL_IF_CTRL5 , 0x0000, // 0x97
ILI932X_PANEL_IF_CTRL6 , 0x0000, // 0x98
ILI932X_DISP_CTRL1 , 0x0133, // 0x07
};*/
/*
static const uint16_t ILI932x_regValues[] = {
ILI932X_START_OSC , 0x0001, // 0x00
TFTLCD_DELAY , 100,
ILI932X_DRIV_OUT_CTRL , 0x0000, // 0x01
ILI932X_DRIV_WAV_CTRL , 0x0700, // 0x02
ILI932X_ENTRY_MOD , 0x1030, // 0x03
ILI932X_RESIZE_CTRL , 0x0000, // 0x04
ILI932X_DISP_CTRL2 , 0x0202, // 0x08
ILI932X_DISP_CTRL3 , 0x0000, // 0x09
ILI932X_DISP_CTRL4 , 0x0000, // 0x0A
ILI932X_RGB_DISP_IF_CTRL1, 0x0003, // 0x0C
ILI932X_FRM_MARKER_POS , 0x0000, // 0x0D
ILI932X_RGB_DISP_IF_CTRL2, 0x0000, // 0x0F
ILI932X_DISP_CTRL1 , 0x0011, // 0x07
TFTLCD_DELAY , 10,
ILI932X_POW_CTRL1 , 0x0000, // 0x10
ILI932X_POW_CTRL2 , 0x0007, // 0x11
ILI932X_POW_CTRL3 , 0x0000, // 0x12
ILI932X_POW_CTRL4 , 0x0000, // 0x13
TFTLCD_DELAY , 100,
ILI932X_POW_CTRL1 , 0x1690, // 0x10
ILI932X_POW_CTRL2 , 0x0007, // 0x11
TFTLCD_DELAY , 100,
ILI932X_POW_CTRL3 , 0x0118, // 0x12
TFTLCD_DELAY , 100,
ILI932X_POW_CTRL4 , 0x0b00, // 0x13
TFTLCD_DELAY , 100,
ILI932X_POW_CTRL7 , 0x0012, // 0x29
ILI932X_FRM_RATE_COL_CTRL, 0x000B, // 0x2B
ILI932X_GRAM_HOR_AD , 0x0000, // 0x20
ILI932X_GRAM_VER_AD , 0x0000, // 0x21
ILI932X_HOR_START_AD , 0x0000, // 0x50
ILI932X_HOR_END_AD , TFTWIDTH-1, // 0x51
ILI932X_VER_START_AD , 0x0000, // 0x52
ILI932X_VER_END_AD , TFTHEIGHT-1, // 0x53
ILI932X_GATE_SCAN_CTRL1 , 0x2700, // 0x60
ILI932X_GATE_SCAN_CTRL2 , 0x0001, // 0x61
ILI932X_GATE_SCAN_CTRL3 , 0x0000, // 0x6A
ILI932X_PANEL_IF_CTRL1 , 0x0010, // 0x90
ILI932X_PANEL_IF_CTRL2 , 0x0000, // 0x92
ILI932X_PANEL_IF_CTRL3 , 0x0001, // 0x93
ILI932X_PANEL_IF_CTRL4 , 0x0110, // 0x95
ILI932X_PANEL_IF_CTRL5 , 0x0000, // 0x97
ILI932X_PANEL_IF_CTRL6 , 0x0000, // 0x98
ILI932X_DISP_CTRL1 , 0x0133, // 0x07
};
*/
/**
* try to init display
* return 0 if failed
*/
uint16_t LCD_init(){
//if(LCD_id == 0)
LCD_read_id();
if(LCD_id > 0x931f && LCD_id < 0x932a){ // 932x
// LCD_id = 0x9320; // make it simple!
int i, s = sizeof(ILI932x_regValues)/sizeof(uint16_t);
for(i = 0; i < s;){
uint16_t a = ILI932x_regValues[i++];
uint16_t b = ILI932x_regValues[i++];
if(a == TFTLCD_DELAY) Delay(b);
else write_reg(a, b);
}
uint16_t addr;
for(addr = 0x80; addr < 0x86; ++addr)
write_reg(addr, 0);
Delay(300);
return LCD_id;
}
//LCD_reset();
return LCD_id;
}
/**
* put point to current position incrementing coordinates
*/
void putpoint(uint16_t colr){
int i;
if(LCD_id == 0) return;
LCD_write(); // dir: out
CS_clear; // active
writereg(ILI932X_RW_GRAM);
for(i = 0; i < 500; ++i){
writebyte(colr >> 8);
writebyte(colr && 0xff);
}
CS_set;
//if(LCD_id == 0x9320){
//}
}
void setpix(uint16_t x, uint16_t y, uint16_t colr){
write_reg(ILI932X_GRAM_HOR_AD, x);
write_reg(ILI932X_GRAM_VER_AD, y);
write_reg(ILI932X_RW_GRAM, colr);
}