#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); }