-
Hi,
I have spun a custom PCB (attached) based around the SSD1963, for use with an off the shelf display (datasheet attached).
The issue:
- I can't get the display to initialize, I think I may be misunderstanding some of the SSD19963 init sequence. Specifically the timing values.
Things I know:
- I got my MCU to talk to a SSD1963 Display board successfully in 8bit mode (mcu works ok).
- All my parts are new, and assumed to be working.
Things I Don't Know:
- If my custom board is working (I can't test it without getting the display to work first).
- If one of my parts got nuked during assembly.
- if my code is the problem (attached).
I'm really at a loss, any info that anyone can provide would be very helpful, thank you.
-
What time units used in HAL_Delay? Datasheet for SSD1963 says:
When the PLL frequency is configured and the PLL was enabled with the
bit 0 of “set_pll” command 0xE0, the user should still wait for 100us for the PLL to lock.
You have HAL_Delay(10) after PLL enabling. If 10 is 10us, then it is not enough.
-
Hi, the time unit is milliseconds.
-
Ok, than it shouldn't be a problem.
Is your SSD1963 works at all? Try to read/write some registers on it.
-
Hi, I was able to read and write to the regs, ...AFTER... I replaced a faulty voltage regulator (thank goodness for multi meters) (see attached).
Now that I'm able to read and write I will retest the init code and post my results.
I'm still pretty confident the init code is wrong for my display. I'm not sure how to calculate the values for the horizontal and vertical period.
Thank you for helping btw, I'm glad the community is alive and well on this forum.
-
I'm still not getting anything, not even junk on screen (see attached).
-
I'm still pretty confident the init code is wrong for my display.
Could be. try another initialization sequence. Here is small collection - https://arm-stm.blogspot.com/2016/12/ssd1963-init-collection.html
-
Hi,
I just found this doc from the manufacturer (attached), but its still incorrect *pulls out hair*.
Should I contact them about the error? in the hopes they will provide working code.
Last time they were nice, but I don't want to keep bugging the FE.
Things I've done:
- I tried the broken init code from the doc, result was still nothing, not even garbage.
-
Hi all,
I have made progress, as it turns out I had a short on the 1.2v rail, this was realized after replacing the voltage regulator and checking the output (it was like 400mV).
I now officially have garbage on the screen! yay! (see attached mp4)
My init code is as follows, any help would be greatly appreciated.
void LCD_Init(void)
{
//1. Power up the system platform and assert the RESET# signal (‘L’ state) for a minimum of 100us to reset the controller.
LCD_RST_SET
HAL_Delay (100);
LCD_RST_RESET
HAL_Delay (120);
LCD_RST_SET
HAL_Delay(150);
// Software reset
LCD_Send_Cmd(0x01); // Trigger software reset
HAL_Delay(50); // Wait for reset to complete
// PLL configuration
LCD_Send_Cmd(0xE2); // PLL multiplier, set PLL clock
LCD_Send_Dat(0x1E); // N=0x23 for 10M crystal (adjust as needed)
LCD_Send_Dat(0x02); // Set divider (adjust as needed)
LCD_Send_Dat(0x54); // Additional PLL settings
LCD_Send_Cmd(0xE0); // PLL enable
LCD_Send_Dat(0x01); // Enable PLL
HAL_Delay(10); // Wait for PLL to stabilize
// Set pixel clock (DCLK)
LCD_Send_Cmd(0xE6);
LCD_Send_Dat(0x03); // Set DCLK frequency (adjust based on requirements)
LCD_Send_Dat(0xFF); // Additional settings for DCLK
LCD_Send_Dat(0xF5); // Additional settings for DCLK
// Set display configuration
LCD_Send_Cmd(0xB0); // Set display mode
LCD_Send_Dat(0x24); // 24-bit color depth
LCD_Send_Dat(0x00); // Additional settings
LCD_Send_Dat(0x03); // 1024 pixels horizontal
LCD_Send_Dat(0xFF); // Additional settings for horizontal pixels
LCD_Send_Dat(0x00);
LCD_Send_Dat(0x63); // 100 pixels vertical
LCD_Send_Dat(0x00);
LCD_Send_Dat(0x00);
// Horizontal timings
LCD_Send_Cmd(0xB4);
LCD_Send_Dat(0x04); // Horizontal total line (1344 lines)
LCD_Send_Dat(0x09);
LCD_Send_Dat(0x00); // Horizontal back porch
LCD_Send_Dat(0x00);
LCD_Send_Dat(0x0A); // Horizontal pulse width
LCD_Send_Dat(0x00);
LCD_Send_Dat(0x00); // Horizontal front porch
LCD_Send_Dat(0x00);
/*
// Vertical timings
LCD_Send_Cmd(0xB6);
LCD_Send_Dat(0x04); // Vertical total time (258 lines)
LCD_Send_Dat(0x09);
LCD_Send_Dat(0x15); // Vertical back porch (21 lines)
LCD_Send_Dat(0x00);
LCD_Send_Dat(0x02); // Vertical pulse width (2 lines)
LCD_Send_Dat(0x00); // Vertical front porch (105 lines)
*/
LCD_Send_Cmd(0xBA); // GPIO output configuration if needed
LCD_Send_Dat(0x0F);
LCD_Send_Cmd(0xB8);
LCD_Send_Dat(0x0F);
LCD_Send_Dat(0x01);
// Memory Access Control (MADCTL)
LCD_Send_Cmd(0x36);
LCD_Send_Dat(0x01);
// Pixel data format configuration
LCD_Send_Cmd(0xF0);
LCD_Send_Dat(0x00);
// Set column address range
LCD_Send_Cmd(0x2A);
LCD_Send_Dat(0x00);
LCD_Send_Dat(0x00);
LCD_Send_Dat(0x03);
LCD_Send_Dat(0xff);
// Set page address range
LCD_Send_Cmd(0x2B);
LCD_Send_Dat(0x00);
LCD_Send_Dat(0x00);
LCD_Send_Dat(0x00);
LCD_Send_Dat(0x63);
// Turn on display
LCD_Send_Cmd(0x29); // Display on command
LCD_Send_Cmd(0xBE); //set PWM for B/L
LCD_Send_Dat(0x06);
LCD_Send_Dat(0x80);
LCD_Send_Dat(0x01);
LCD_Send_Dat(0xF0);
LCD_Send_Dat(0x00);
LCD_Send_Dat(0x00);
LCD_Send_Cmd(0xD0);
LCD_Send_Dat(0x0D);
HAL_Delay(100); // Wait for the display to stabilize before use
}
-
Hi all, more progress (see attached).
So I found the app notes for the SSD1963, this really cleared things up for me, sort of.
I'm also waiting to hear back from the display place about the funky code in the app note, I'm hoping they have a good solution to my problem.
I still have this chunk of dead space to the right, and this strange flicker (which gets worse if I forget to switch to the internal PLL, so it might be a clock thing). I expected the display to be rock solid, so I'm not sure if it's the code.. or hardware, both, neither?
I'll keep chugging along, if anyone has any input, I'm all ears, and a foot. (I prefer the metric system).
(setting the Horizontal Display Period Start Position, shifts the display the wrong way, so I'm at a loss about the white chunk)
init code is below
void LCD_Init(void)
{
/* #1 */
LCD_RST_SET
HAL_Delay(100);
LCD_RST_RESET
HAL_Delay(120);
LCD_RST_SET
HAL_Delay(150);
// Software reset
LCD_Send_Cmd(0x01); // Trigger software reset
HAL_Delay(50); // Wait for reset to complete
/* #2 */
// PLL configuration
LCD_Send_Cmd(0xE2); // PLL multiplier, set PLL clock
//LCD_Send_Dat(0x1D); // M = 29
//LCD_Send_Dat(0x02); // n = 2
//LCD_Send_Dat(0x54); // dummy byte
LCD_Send_Dat(0x1E);
LCD_Send_Dat(0x02);
LCD_Send_Dat(0x54);
/* #3 */
LCD_Send_Cmd(0xE0); //
LCD_Send_Dat(0x01); // Enable PLL
HAL_Delay(10); // Wait for PLL to stabilize
/* #4 */
/* #5 */
LCD_Send_Cmd(0xE0); //
LCD_Send_Dat(0x03); // Switch to PLL
/* #6 */
LCD_Send_Cmd(0x01);
/* #7 */
// Set pixel clock (DCLK)
LCD_Send_Cmd(0xE6);
//LCD_Send_Dat(0x03); // Set DCLK frequency to 21MHz
//LCD_Send_Dat(0x5C); //
//LCD_Send_Dat(0x28); //
LCD_Send_Dat(0x03);
LCD_Send_Dat(0xFF);
LCD_Send_Dat(0xF5);
/* #8 A */
// Set display configuration
LCD_Send_Cmd(0xB0); // Set display mode
LCD_Send_Dat(0x24); // 24-bit color depth
LCD_Send_Dat(0x00); // TFT type
LCD_Send_Dat(0x03); // 1024 pixels horizontal
LCD_Send_Dat(0xFF); //
LCD_Send_Dat(0x00); // 100 pixels vertical
LCD_Send_Dat(0x63); //
LCD_Send_Dat(0x00); // dummy byte
/* #8 B */
// Horizontal timings
LCD_Send_Cmd(0xB4);
LCD_Send_Dat(0x05); // HT: horizontal total period (display + non-display) – 1
LCD_Send_Dat(0x3F); // 1344 - 1 - 1343
LCD_Send_Dat(0x00); // HPS: Horizontal Sync Pulse Start Position = Horizontal Pulse Width + Horizontal Back Porch
LCD_Send_Dat(0x9F); // 1 + 158 = 159
LCD_Send_Dat(0x00); // HPW: Horizontal Sync Pulse Width - 1
// 1 - 1
LCD_Send_Dat(0x00); // LPS: Horizontal Display Period Start Position = 0x0000
LCD_Send_Dat(0x00);
LCD_Send_Dat(0x00); // LPSPP: Horizontal Sync Pulse Subpixel Start Position(for serial TFT interface). Dummy value for TFT interface.
/* #8 C */
// Vertical timings
LCD_Send_Cmd(0xB6);
LCD_Send_Dat(0x00); // VT: Vertical Total (display + non-display) Period – 1
LCD_Send_Dat(0x81); // 130 - 1 = 129
LCD_Send_Dat(0x00); // VPS: Vertical Sync Pulse Start Position = Vertical Pulse Width + Vertical Back Porch
LCD_Send_Dat(0x17); // 2 + 21 = 23
LCD_Send_Dat(0x01); // VPW: Vertical Sync Pulse Width – 1, 2 - 1 = 1
LCD_Send_Dat(0x00); // FPS: Vertical Display Period Start Position = 0x0000
LCD_Send_Dat(0x00);
/* #9 */
LCD_Send_Cmd(0xBE); //set PWM for B/L
LCD_Send_Dat(0x08);
LCD_Send_Dat(0x80);
LCD_Send_Dat(0x01);
/* #10 */
// Turn on display
LCD_Send_Cmd(0x29); // Display on command
/* #11 A */
// Set column address range
LCD_Send_Cmd(0x2A);
LCD_Send_Dat(0x00);
LCD_Send_Dat(0x00);
LCD_Send_Dat(0x00); //100 - 1
LCD_Send_Dat(0x63);
/* #11 B */
// Set page address range
LCD_Send_Cmd(0x2B);
LCD_Send_Dat(0x00);
LCD_Send_Dat(0x00);
LCD_Send_Dat(0x03); //1024 - 1
LCD_Send_Dat(0xFF);
/* #12 */
LCD_Send_Cmd(0x36); // set address mode
LCD_Send_Dat(0x08); //
//LCD_Send_Dat(0x02); //
/* #13 */
// Pixel data format configuration
LCD_Send_Cmd(0xF0);
LCD_Send_Dat(0x00); // 8bit interface
//HAL_Delay(100); // Wait for the display to stabilize before use
}
-
Good news all, I got the display working great, see photo.
But assumption bit me in the butt again.
the SSD1963 datasheet states on page 8
1 GENERAL DESCRIPTION
SSD1963 is a display controller of 1215K byte frame buffer to support up to 864 x 480 x 24bit graphics
content. It also equips parallel MCU interfaces in different bus width to receive graphics data and command
from MCU. Its display interface supports common RAM-less LCD driver of color depth up to 24 bit-per-
pixel
so despite the app notes saying I can use the SSD1963 for driving a E104RB-FW450-N, I don't think ya actually can....
Final init code below
void LCD_Init(void)
{
/* #1 */
LCD_RST_SET
HAL_Delay(100);
LCD_RST_RESET
HAL_Delay(120);
LCD_RST_SET
HAL_Delay(150);
// Software reset
LCD_Send_Cmd(LCD_RESET); // Trigger software reset
HAL_Delay(50); // Wait for reset to complete
/* #2 */
// PLL configuration
LCD_Send_Cmd(0xE2); // PLL multiplier, set PLL clock 100MHz
LCD_Send_Dat(0x1D); // M = 29
LCD_Send_Dat(0x02); // n = 2
LCD_Send_Dat(0x54); // dummy byte
/* #3 */
LCD_Send_Cmd(0xE0); //
LCD_Send_Dat(0x01); // Enable PLL
HAL_Delay(10); // Wait for PLL to stabilize
/* #4 */
/* #5 */
LCD_Send_Cmd(0xE0); //
LCD_Send_Dat(0x03); // Switch to PLL
/* #6 */
LCD_Send_Cmd(LCD_RESET); //Soft Reset
HAL_Delay(50); // Wait for reset to complete
/* #7 */
// Set pixel clock (DCLK)
LCD_Send_Cmd(0xE6);
LCD_Send_Dat(0x03); // Set DCLK frequency to 21MHz
LCD_Send_Dat(0x5C); //
LCD_Send_Dat(0x28); //
/* #8 A */
// Set display configuration
LCD_Send_Cmd(0xB0); // Set display mode
LCD_Send_Dat(0x20); // 24-bit color depth
LCD_Send_Dat(0x00); // TFT type
LCD_Send_Dat(((LCD_WIDTH - 1) >> 8) & 0xFF); // nth pixels horizontal
LCD_Send_Dat((LCD_WIDTH - 1) & 0xFF); //
LCD_Send_Dat(((LCD_HEIGHT - 1) >> 8) & 0xFF); // nth pixels vertical
LCD_Send_Dat((LCD_HEIGHT - 1) & 0xFF); //
LCD_Send_Dat(0x00); // dummy byte
/* #8 B */
// Horizontal timings
LCD_Send_Cmd(0xB4);
LCD_Send_Dat(((LCD_FULL_WIDTH - 1) >> 8) & 0xFF); // nth pixels horizontal
LCD_Send_Dat((LCD_FULL_WIDTH - 1) & 0xFF); //
LCD_Send_Dat(0x00); // HPS: Horizontal Sync Pulse Start Position = Horizontal Pulse Width + Horizontal Back Porch
LCD_Send_Dat(0x9F); // 1 + 158 = 159
LCD_Send_Dat(0x00); // HPW: Horizontal Sync Pulse Width - 1
// 1 - 1
LCD_Send_Dat(0x00); // LPS: Horizontal Display Period Start Position = 0x0000
LCD_Send_Dat(0x00);
LCD_Send_Dat(0x00); // LPSPP: Horizontal Sync Pulse Sub Pixel Start Position(for serial TFT interface). Dummy value for TFT interface.
/* #8 C */
// Vertical timings
LCD_Send_Cmd(0xB6);
LCD_Send_Dat(0x00); // VT: Vertical Total (display + non-display) Period – 1
LCD_Send_Dat(0x81); // 130 - 1 = 129
LCD_Send_Dat(0x00); // VPS: Vertical Sync Pulse Start Position = Vertical Pulse Width + Vertical Back Porch
LCD_Send_Dat(0x17); // 2 + 21 = 23
LCD_Send_Dat(0x01); // VPW: Vertical Sync Pulse Width – 1
LCD_Send_Dat(0x00); // FPS: Vertical Display Period Start Position = 0x0000
LCD_Send_Dat(0x00);
/* #9 */
LCD_Send_Cmd(0xBE); //set PWM for B/L
LCD_Send_Dat(0x08);
LCD_Send_Dat(0x64);
LCD_Send_Dat(0x01);
/* #10 */
// Turn on display
LCD_Send_Cmd(LCD_DISPLAY_ON); // Display on command
/* #11 A */
// Set column address range
LCD_Send_Cmd(LCD_COLUMN_ADDR);
LCD_Send_Dat(0x00); //SC: 0x0000
LCD_Send_Dat(0x00);
LCD_Send_Dat(((LCD_HEIGHT - 1) >> 8) & 0xFF); // nth pixels vertical
LCD_Send_Dat((LCD_HEIGHT - 1) & 0xFF); //
/* #11 B */
// Set page address range
LCD_Send_Cmd(LCD_PAGE_ADDR);
LCD_Send_Dat(0x00); //SP: 0x0000
LCD_Send_Dat(0x00);
LCD_Send_Dat(((LCD_WIDTH - 1) >> 8) & 0xFF); // nth pixels horizontal
LCD_Send_Dat((LCD_WIDTH - 1) & 0xFF); //
/* #12 */
LCD_Send_Cmd(0x36); // set address mode
LCD_Send_Dat(0x08); //
/* #13 */
// Pixel data format configuration
LCD_Send_Cmd(0xF0);
LCD_Send_Dat(0x00); // 8bit interface
}