#include "otm8009a.h"
#include "delay.h"
void otm8009_init(display_t *display, otm8009a_mode_t mode,
otm8009a_frame_rates_t frame_rate,
otm8009a_colormap_t colormap,
uint16_t width, uint16_t height) {
display_dsi_short_write(display, OTM8009A_CMD_SWRESET, 0x00, 0x15);
delay_ms(100);
display_dsi_short_write(display, OTM8009A_CMD_NOP, 0x00, 0x15);
{
uint8_t data[] = { 0x80, 0x09, 0x01 };
display_dsi_long_write(display, 0xFF, data, 3, 0x39);
}
display_dsi_short_write(display, OTM8009A_CMD_NOP, 0x80, 0x15);
{
uint8_t data[] = { 0x80, 0x09 };
display_dsi_long_write(display, 0xFF, data, 2, 0x39);
}
display_dsi_short_write(display, OTM8009A_CMD_NOP, 0x80, 0x15);
display_dsi_short_write(display, 0xC4, 0x30, 0x15);
delay_ms(10);
display_dsi_short_write(display, OTM8009A_CMD_NOP, 0x8A, 0x15);
display_dsi_short_write(display, 0xC4, 0x40, 0x15);
delay_ms(10);
display_dsi_short_write(display, OTM8009A_CMD_NOP, 0xB1, 0x15);
display_dsi_short_write(display, 0xC5, 0xA9, 0x15);
display_dsi_short_write(display, OTM8009A_CMD_NOP, 0x91, 0x15);
display_dsi_short_write(display, 0xC5, 0x34, 0x15);
display_dsi_short_write(display, OTM8009A_CMD_NOP, 0xB4, 0x15);
display_dsi_short_write(display, 0xC0, 0x50, 0x15);
display_dsi_short_write(display, OTM8009A_CMD_NOP, 0x00, 0x15);
display_dsi_short_write(display, 0xD9, 0x4E, 0x15);
display_dsi_short_write(display, OTM8009A_CMD_NOP, 0x81, 0x15);
display_dsi_short_write(display, 0xC1, frame_rate | (frame_rate << 4), 0x15);
display_dsi_short_write(display, OTM8009A_CMD_NOP, 0xA1, 0x15);
display_dsi_short_write(display, 0xC1, 0x08, 0x15);
display_dsi_short_write(display, OTM8009A_CMD_NOP, 0x92, 0x15);
display_dsi_short_write(display, 0xC5, 0x01, 0x15);
display_dsi_short_write(display, OTM8009A_CMD_NOP, 0x95, 0x15);
display_dsi_short_write(display, 0xC5, 0x34, 0x15);
display_dsi_short_write(display, OTM8009A_CMD_NOP, 0x00, 0x15);
{
uint8_t data[] = { 0x79, 0x79 };
display_dsi_long_write(display, 0xD8, data, 2, 0x39);
}
display_dsi_short_write(display, OTM8009A_CMD_NOP, 0x94, 0x15);
display_dsi_short_write(display, 0xC5, 0x33, 0x15);
display_dsi_short_write(display, OTM8009A_CMD_NOP, 0xA3, 0x15);
display_dsi_short_write(display, 0xC0, 0x1B, 0x15);
display_dsi_short_write(display, OTM8009A_CMD_NOP, 0x82, 0x15);
display_dsi_short_write(display, 0xC5, 0x83, 0x15);
display_dsi_short_write(display, OTM8009A_CMD_NOP, 0x81, 0x15);
display_dsi_short_write(display, 0xC4, 0x83, 0x15);
display_dsi_short_write(display, OTM8009A_CMD_NOP, 0xA1, 0x15);
display_dsi_short_write(display, 0xC1, 0x0E, 0x15);
display_dsi_short_write(display, OTM8009A_CMD_NOP, 0xA6, 0x15);
{
uint8_t data[] = { 0x00, 0x01 };
display_dsi_long_write(display, 0xB3, data, 2, 0x39);
}
display_dsi_short_write(display, OTM8009A_CMD_NOP, 0x80, 0x15);
{
uint8_t data[] = { 0x85, 0x01, 0x00, 0x84, 0x01, 0x00 };
display_dsi_long_write(display, 0xCE, data, 6, 0x39);
}
display_dsi_short_write(display, OTM8009A_CMD_NOP, 0x80, 0x15);
{
uint8_t data[] = { 0x18, 0x04, 0x03, 0x39, 0x00, 0x00, 0x00, 0x18, 0x03, 0x03, 0x3A, 0x00, 0x00, 0x00 };
display_dsi_long_write(display, 0xCE, data, 14, 0x39);
}
display_dsi_short_write(display, OTM8009A_CMD_NOP, 0xB0, 0x15);
{
uint8_t data[] = { 0x18, 0x04, 0x03, 0x39, 0x00, 0x00, 0x00, 0x18, 0x03, 0x03, 0x3A, 0x00, 0x00, 0x00 };
display_dsi_long_write(display, 0xCE, data, 14, 0x39);
}
display_dsi_short_write(display, OTM8009A_CMD_NOP, 0xC0, 0x15);
{
uint8_t data[] = { 0x01, 0x01, 0x20, 0x20, 0x00, 0x00, 0x01, 0x02, 0x00, 0x00 };
display_dsi_long_write(display, 0xCF, data, 10, 0x39);
}
display_dsi_short_write(display, OTM8009A_CMD_NOP, 0x80, 0x15);
{
uint8_t data[] = { 0, 10 };
display_dsi_long_write(display, 0xCB, data, 2, 0x39);
}
display_dsi_short_write(display, OTM8009A_CMD_NOP, 0x90, 0x15);
{
uint8_t data[] = { 0, 15 };
display_dsi_long_write(display, 0xCB, data, 2, 0x39);
}
display_dsi_short_write(display, OTM8009A_CMD_NOP, 0xa0, 0x15);
{
uint8_t data[] = { 0, 15 };
display_dsi_long_write(display, 0xCB, data, 2, 0x39);
}
display_dsi_short_write(display, OTM8009A_CMD_NOP, 0xb0, 0x15);
{
uint8_t data[] = { 0, 10 };
display_dsi_long_write(display, 0xCB, data, 2, 0x39);
}
display_dsi_short_write(display, OTM8009A_CMD_NOP, 0xc0, 0x15);
{
uint8_t data[] = {
0x00, 0x04, 0x04, 0x04, 0x04, 0x04, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00,
};
display_dsi_long_write(display, 0xCB, data, 15, 0x39);
}
display_dsi_short_write(display, OTM8009A_CMD_NOP, 0xd0, 0x15);
{
uint8_t data[] = {
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x04, 0x04, 0x04, 0x04, 0x04, 0x00, 0x00, 0x00,
0x00,
};
display_dsi_long_write(display, 0xCB, data, 15, 0x39);
}
display_dsi_short_write(display, OTM8009A_CMD_NOP, 0xe0, 0x15);
{
uint8_t data[] = { 0, 10 };
display_dsi_long_write(display, 0xCB, data, 2, 0x39);
}
display_dsi_short_write(display, OTM8009A_CMD_NOP, 0xf0, 0x15);
{
uint8_t data[] = { 255, 10 };
display_dsi_long_write(display, 0xCB, data, 2, 0x39);
}
display_dsi_short_write(display, OTM8009A_CMD_NOP, 0x80, 0x15);
{
uint8_t data[] = { 0x00, 0x26, 0x09, 0x0B, 0x01, 0x25, 0x00, 0x00, 0x00, 0x00 };
display_dsi_long_write(display, 0xCC, data, 10, 0x39);
}
display_dsi_short_write(display, OTM8009A_CMD_NOP, 0x90, 0x15);
{
uint8_t data[] = {
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x26, 0x0A, 0x0C,
0x02,
};
display_dsi_long_write(display, 0xCC, data, 15, 0x39);
}
display_dsi_short_write(display, OTM8009A_CMD_NOP, 0xa0, 0x15);
{
uint8_t data[] = {
0x25, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00,
};
display_dsi_long_write(display, 0xCC, data, 15, 0x39);
}
display_dsi_short_write(display, OTM8009A_CMD_NOP, 0xb0, 0x15);
{
uint8_t data[] = {
0x00, 0x25, 0x0C, 0x0A, 0x02, 0x26, 0x00, 0x00, 0x00, 0x00
};
display_dsi_long_write(display, 0xCC, data, 10, 0x39);
}
display_dsi_short_write(display, OTM8009A_CMD_NOP, 0xc0, 0x15);
display_dsi_short_write(display, OTM8009A_CMD_NOP, 0xb0, 0x15);
{
uint8_t data[] = {
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x25, 0x0B, 0x09,
0x01,
};
display_dsi_long_write(display, 0xCC, data, 15, 0x39);
}
display_dsi_short_write(display, OTM8009A_CMD_NOP, 0xd0, 0x15);
{
uint8_t data[] = {
0x26, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00,
};
display_dsi_long_write(display, 0xCC, data, 15, 0x39);
}
// PWR_CTRL1 - 0xc580h - 130th parameter - default
// Pump 1 min and max DM
display_dsi_short_write(display, OTM8009A_CMD_NOP, 0x81, 0x15);
display_dsi_short_write(display, 0xc5, 0x66, 0x15);
display_dsi_short_write(display, OTM8009A_CMD_NOP, 0xb6, 0x15);
display_dsi_short_write(display, 0xf5, 0x06, 0x15);
// CABC LEDPWM frequency adjusted to 19,5kHz
display_dsi_short_write(display, OTM8009A_CMD_NOP, 0xb1, 0x15);
display_dsi_short_write(display, 0xc6, 0x06, 0x15);
// Exit CMD2 mode
display_dsi_short_write(display, OTM8009A_CMD_NOP, 0, 0x15);
{
uint8_t data[] = {
0xFF, 0xFF, 0xFF
};
display_dsi_long_write(display, 0xFF, data, 3, 0x39);
}
// Standard DCS Initialization TO KEEP CAN BE DONE IN HSDT
// NOP - goes back to DCS std command ?
display_dsi_short_write(display, OTM8009A_CMD_NOP, 0, 0x15);
// Gamma correction 2.2+ table (HSDT possible)
display_dsi_short_write(display, OTM8009A_CMD_NOP, 0, 0x15);
{
uint8_t data[] = {
0x00, 0x09, 0x0F, 0x0E, 0x07, 0x10, 0x0B, 0x0A, 0x04, 0x07, 0x0B, 0x08, 0x0F, 0x10,
0x0A, 0x01,
};
display_dsi_long_write(display, 0xE1, data, 16, 0x39);
}
// Gamma correction 2.2- table (HSDT possible)
display_dsi_short_write(display, OTM8009A_CMD_NOP, 0x00, 0x15);
{
uint8_t data[] = {
0x00, 0x09, 0x0F, 0x0E, 0x07, 0x10, 0x0B, 0x0A, 0x04, 0x07, 0x0B, 0x08, 0x0F, 0x10,
0x0A, 0x01,
};
display_dsi_long_write(display, 0xE2, data, 16, 0x39);
}
// Send Sleep Out command to display : no parameter
display_dsi_short_write(display, OTM8009A_CMD_SLPOUT, 0x00, 0x15);
// Wait for sleep out exit
delay_ms(120);
display_dsi_short_write(display, OTM8009A_CMD_COLMOD, OTM8009A_COLMOD_RGB888, 0x15);
// Send command to configure display in landscape orientation mode. By default
// the orientation mode is portrait
// CASET value (Column Address Set) : X direction LCD GRAM boundaries
// depending on LCD orientation mode and PASET value (Page Address Set) : Y direction
// LCD GRAM boundaries depending on LCD orientation mode
// XS[15:0] = 0x000 = 0, XE[15:0] = 0x31F = 799 for landscape mode : apply to CASET
// YS[15:0] = 0x000 = 0, YE[15:0] = 0x31F = 799 for portrait mode : apply to PASET
//static const uint8_t LcdRegData27[] = {0x00, 0x00, 0x03, 0x1F};
//
// XS[15:0] = 0x000 = 0, XE[15:0] = 0x1DF = 479 for portrait mode : apply to CASET
// YS[15:0] = 0x000 = 0, YE[15:0] = 0x1DF = 479 for landscape mode : apply to PASET
//static const uint8_t lcdregdata28[] = {0x00, 0x00, 0x01, 0xdf};
uint16_t madctr;
if (mode == OTM8009A_MODE_PORTRAIT) {
madctr = 0;
} else {
madctr = OTM8009A_MADCTR_MODE_LANDSCAPE;
}
if (colormap == OTM8009A_COLORMAP_BGR) {
madctr |= (1 << 3);
}
display_dsi_short_write(display, OTM8009A_CMD_MADCTR, madctr, 0x15);
uint16_t last_col = (width - 1);
uint16_t last_row = (height - 1);
uint8_t caset[] = {0, 0, last_col >> 8, last_col & 0xFF };
uint8_t paset[] = {0, 0, last_row >> 8, last_row & 0xFF};
display_dsi_long_write(display, OTM8009A_CMD_CASET, caset, 4, 0x39);
display_dsi_long_write(display, OTM8009A_CMD_PASET, paset, 4, 0x39);
//* CABC : Content Adaptive Backlight Control section start
// Note : defaut is 0 (lowest Brightness], 0xFF is highest Brightness, try 0x7F : intermediate value
display_dsi_short_write(display, OTM8009A_CMD_WRDISBV, 0x7f, 0x15);
// defaut is 0, try 0x2C - Brightness Control Block, Display Dimming & BackLight on
display_dsi_short_write(display, OTM8009A_CMD_WRCTRLD, 0x2c, 0x15);
// /* defaut is 0, try 0x02 - image Content based Adaptive Brightness [Still Picture] */
display_dsi_short_write(display, OTM8009A_CMD_WRCABC, 0x02, 0x15);
// /* defaut is 0 (lowest Brightness], 0xFF is highest Brightness */
display_dsi_short_write(display, OTM8009A_CMD_WRCABCMB, 0xff, 0x15);
//* CABC : Content Adaptive Backlight Control section end <<
// Send Command Display On
display_dsi_short_write(display, OTM8009A_CMD_DISPON, 0, 0x15);
// NOP command
display_dsi_short_write(display, OTM8009A_CMD_NOP, 0, 0x15);
// Send Command GRAM memory write (no parameters) : this initiates frame write via other DSI commands sent by
// DSI host from LTDC incoming pixels in video mode
display_dsi_short_write(display, OTM8009A_CMD_RAMWR, 0, 0x15);
{
uint8_t data[] = { (533 >> 8) & 0xFF, 533 & 0xFF };
display_dsi_long_write(display, OTM8009A_CMD_WRTESCN, data, 2, 0x39);
}
display_dsi_short_write(display, OTM8009A_CMD_TEEON, OTM8009A_TEEON_TELOM_VBLANKING_INFO_ONLY, 0x15);
}