STM32 and 7" Display
A couple of weeks ago I recieved an SSD1963 evaluation board and a 7″ display.
The SSD1963 chip makes it possible to control a 7″ display with a regular microcontroller or microprocessor, which haven’t got enough memory and power to control it itself, as it’s a normal display with vSync and hSync and so on.
So after a couple of hours I got it running with my STM32 board and a touch screen controller.
Please take a look at the video below to see some of the things I can show/do.
Edit, 11. October 2014:
Another updated version of the SSD1963 library, with transparent fonts, support for larger fonts and drawing routines for Bitmap images from SD card, was used in the IOT Football Table Project whose code is published here: https://github.com/TKJElectronics/IoT_Football/tree/master/LCD/src
Edit, 21. February 2011:
I’ve now uploaded the source code for the driver of SSD1963, using the STM32.
You can download the “library” here: SSD1963_STM32_Driver.zip
Where have you bought both SSD1963 board + TFT Display? Are you running on STM32F103B? Thanks.
I’ve bought the SSD1963 evaluation board from TechToys.com.hk – http://www.techtoys.com.hk/Displays/SSD1963EvalRev2A/SSD1963%20Eval%20Board%20Rev2A.htm
About the display I got it for free as a sample, but it can be bought at TechToys.com.hk too – http://www.techtoys.com.hk/Displays/TY700TFT800480/TY700TFT800480Rev02.htm
Hi ! Very nice project !
So, i’m very interesting by this project. I purchase the SSD1963 borad and the 7″ TFT from techtoys, but it’s very difficult to me to port the “techtoys sample” to my lpc2138 board… do you publish your source code ?
Thanx for reply
Regards
Alek
Hi,
how did you interface the 1963 from the STM32? I’m thinking about doing something very similiar.
Best
Tom
@Tom Bennett
I connected the SSD1963 different lines for simple 8080 communication, this includes:
CS, RS, WR, RD, Reset and of course the 16-bit data line.
Thomas
I recently used the SSD1963 with a Stellaris Cortex microcontroller. (using Newhaven Display 5.7″ w/ controller board)
I had issues with the SSD1963 not updating single-pixel writes correctly. There was an odd problem where every other pixel would not appear until the next write was done.
I.e., I could write a pixel, but it only every other would would appear.
This was resolved by writing another command after writing pixel data to the SSD163 current buffer location.
For example, when you want to do a single-pixel write:
1. Write new x, y addresses
2. Write memory start command ” WriteCommandByte(WRITE_MEMORY_START);”
3. Write consecutive pixel color data.
-> 4. TERMINATE using another command of some type, instead of nothing.
I used WriteCommandByte(WRITE_MEMORY_START); for consistency.
@Marty McLeod (micro_engineer)
Hi Marty.
I can do single pixel writes without any problems. I’m doing exactly as you do, by first setting area, then entering Memory-mode, but then I CLEAR the CS line, write the color data, and SETs the CS line to put the pixel!
Would you mind trying to do this, and tell me if it solves your problem?
Hi Thomas. Actually, I recall trying just about everything exaustively to figure out what was going on.
I never noticed it until I was stepping through single-pixel operations, in which (I believe it was) odd-numbered pixel writes did not result in a visible pixel until the next pixel write completed. Until I used the other method…
I’ll have to drag my Stellaris ARM board out of storage (I’ve relocated) and give it a shot, not too long from now I hope.
Thanks.
Hi
So your project are quite terrefic. Pretty great. So about the Techtoy.. basically i gab 2 of these and since 1 month around i can’t have them working properly. I’m running the SSD1963 with an arduino mega. I can initialize the display and all signal and clock seem fine. It’s also in 8bit mode. So when the code boot, i just can have a kind of snow picture. I can’t put a black picture or anything.. So if you can help me a little about this one.. Thanks
@Jeff
Dear Jeff.
Are you using the proper initialization commands, and do you remember to set the correct startup registers? I used the Microchip SSD1963 example as a reference, when making the code for the STM32 processor, as you can see the correct Startup commands and register setups in the Microchip example.
You also have to take care of the specific display registers, where you have to enter the properties of the connected display (the setup commands isn’t the same whether you use a 3.5″ or 7″ display)
Btw. It took me quite a while to get it working too!
Best Regards
Thomas Jespersen
Hi,
I have to use the SSD1963 on an STM32 (F207), dou you distribut you coude source of you SSD1963 driver? This could help me a lot.
Thanks
@Axel
I have now uploaded the driver/library for the control of the SSD1963 chip!
Best Regards
Thomas Jespersen
Hi Thomas,
I have use Atmel AVR32 (EVK1105 development kit) to drive a 3.2″ TFT LCD (16 bit data bus). It works well and we can display any image loaded in an USB memory stick on-board.
Now I consider to use the same board to drive a 4.3″ TFT LCD (24 bit RGB). It seems SSD1963 is the most suitable.
I have searched and see New Heaven Display provide a DEV kits to start with:
http://www.newhavendisplay.com/index.php?main_page=index&cPath=372
http://www.newhavendisplay.com/index.php?main_page=product_info&cPath=372&products_id=2657
http://www.newhavendisplay.com/index.php?main_page=product_info&cPath=372&products_id=2093
But unfortunately, they use only 8 bit data bus to interface and control a 4.3″ TFT LCD.
I have followed your post on SparkFun and in your blog. It’s quite impressive. I would be able to get the kit from “techtoy”.
Could you please give me some advice for that? I could send you the datasheet of the 3.2″ TFT LCD I use and a propose 4.3″ TFT LCD.
Thanks a lot in advance, Thomas.
Best regards,
Ralf
@Ralf
Dear Ralf.
Sorry for the late response.
The SSD1963 is a great chip for a big variety of displays, fx 4.3″ TFT’s.
I can recommend the TechToys evaluation board, as this board makes it possible to test different displays together with the SSD1963 without having to buy multiple display boards. Though you have to make sure the LCD connections are correct, and matches the FPC-connector.
The library I’ve made will be easily portable for you to use it with the AVR32, so no problem there. If you are interested I could also do some of the development and testing for you.
Best Regards
Thomas Jespersen
Hi Thomas,
I am sorry to get back to this post lately.
Yes, I did buy the following parts from Techtoys:
;—————————————————————-
1. SSD1963 demo kit:
http://techtoys.com.hk/Displays/SSD1963EvalRev3B/SSD1963%20Eval%20Board%20Rev3B.htm
2. PIC2432 EVK RD4 kit (PIC32MX360F512L):
http://techtoys.com.hk/PIC_boards/PIC2432EVK-RD4/PIC2432%20EVK%20RD4.htm
3. 4.3″ TFT LCDs
;—————————————————————-
Thanks a lot for your advice.
I have also downloaded SSD1963 – microchip driver + demo firmware from the website as well.
I do run a simplified example of AVR32 on EVK1105 kit (3.2″ TFT LCD, AVR studio compiler) as well as a basic firmware to show some displays on PIC2432 EVK RD4 kit (4.3″ TFT LCD, microchip, MPLAB IDE V8.7). Both of the kits work well and I have been able to make any change on each kit’s TFT LCD.
However, I have still not been able to modified the code of the AVR32 to drive the SD1963 and 4.3″ TFT LCD.
I wonder if you can give me some helps. Please send your contact to my email, I’ll email you the wiring details in between AVR32 board & SSD1963 as well as the firmware works with 3.2″” TFT LCD.
Thanks a lot for your support and I am looking forward to hear from you soon.
Best regards,
Ralf
@Ralf
Dear Ralf.
Great that you got it working and that you are able to modify the examples – this is also how I make progress most of the times, when playing with new development boards.
I used the Microchip Graphics Library as the base for my SSD1963 library for the STM32. And with enough time it will also be easily ported to the AVR32!
Please use the “Contact Us” link on our main page so we can get in touch.
Best Regards
Thomas Jespersen
Hi, i looked at your example for the SSD1963 and it is very good, thank you very much!
The font that you have in your example, where can I get more fonts? I can not get the standard fonts of the STM32 working with your PutChar function…
@Justus
Hi Justus.
The fonts I am using have been generated using the free font creator by MikroElektronika: http://www.mikroe.com/eng/products/view/683/glcd-font-creator/
Then I made my own displaying routine for decoding these fonts and putting the right pixels to the display.
You can do the same by finding the pattern in the generated font C-files, which is actually just the pixel bits putted together in bytes.
Best Regards
Thomas Jespersen
Hi,
i looked at your library too.
But it doesn’t work. I use the STM32F103, the SSD1963 and a 4,3″ display with 480*272 and 16 Bit.
The GPIO signals work perfect (controlled with the scope). Are there any timinigs i have to consider? It is possible to check, that the display receive my send commands and data?
Best regards
Kim Petersen
@Kim Petersen
Dear Kim.
The library I have posted was made for my specific 7″ display with it’s timing parameters etc.
You should change the SSD1963_Configuration.h file appropriately to your display configuration.
Here is the test configuration I have been using for my 4.3″ display, also with a resolution of 480×272 pixels. Maybe it will fit your display too.
You should add this code below the /* End of definition for DISPLAY_PANEL == TY700TFT800480 */ line but before the #else in the SSD1963_Configuration.h file.
To enable the display you should remember to define its’ use in the top of the file too, by adding “#define DISPLAY_PANEL TY430TFT480272” and uncommenting the other (TY700TFT800480)
/*********************************************************************
* Overview: Horizontal and vertical display resolution
* (from the glass datasheet).
*********************************************************************/
#define DISP_HOR_RESOLUTION 480
#define DISP_VER_RESOLUTION 272
/*********************************************************************
* Overview: Image orientation (can be 0, 90, 180, 270 degrees).
*********************************************************************/
#define DISP_ORIENTATION 0
/*********************************************************************
* Overview: Panel Data Width
*********************************************************************/
#define DISP_DATA_WIDTH 24
/*********************************************************************
* Overview: LSHIFT Polarity Swap
* If defined LSHIFT is a falling trigger
*********************************************************************/
//#define DISP_INV_LSHIFT
/*********************************************************************
* Overview: Horizontal synchronization timing in pixels
* (from the glass datasheet).
*********************************************************************/
#define DISP_HOR_PULSE_WIDTH 41
#define DISP_HOR_BACK_PORCH 2
#define DISP_HOR_FRONT_PORCH 2
/*********************************************************************
* Overview: Vertical synchronization timing in lines
* (from the glass datasheet).
*********************************************************************/
#define DISP_VER_PULSE_WIDTH 10
#define DISP_VER_BACK_PORCH 2
#define DISP_VER_FRONT_PORCH 2
/*********************************************************************
* Definition for SPI interface for SSD1963
* Hardware dependent!
*********************************************************************/
#define GPIO3 3
#define GPIO2 2
#define GPIO1 1
#define GPIO0 0
#define LCD_RESET (1<<GPIO0) //LCD Reset signal (Reset for display panel, NOT ssd1963)
#define LCD_SPENA 0
#define LCD_SPCLK 0
#define LCD_SPDAT 0
/* End of definition for DISPLAY_PANEL == TY430TFT480272 */
Hi. Your project looks great.
Just wondering what sort of refresh rate you are getting now?
Since you are using a modified version of the Microchip Graphics Library, do you think using a PIC32 of similar specs will give you similar results? (Am concerned about the latency for the transfer between the microcontroller and the SSD1963.)
@Shem
In the demonstration video I’ve currently uploaded the SSD1963 is simply connected to some of the GPIOs on the STM32-STAMP board. As the STM32-STAMP board does only contain the STM32F103RET6 it doesn’t have any FSMC port.
With this setup I am only able to get around 6FPS of full resolution images (800×480, 16BPP).
I have also been connecting this 7″ display with the SSD1963 to the STM3210E-EVAL board which contains the STM32F103ZGT6 (1MB flash, 144-pins) which has a full FSMC port.
With that setup I am able to get much faster clock rates giving me up to 20FPS – so that’s a good increase.
I decided to use the Microchip Graphics Library as inspiration to the making of the display library for the STM32 device as Microchip had already interfaced with the SSD1963 and made the low level driver commands.
So instead of having to look in the SSD1963 datasheet a lot more these example codes saved me a lot of time.
I have worked with the PIC32 and I like it for sure. Though I like the ARM family more and I think I will continue them rather than the PIC32s.
Best Regards
Thomas Jespersen
Hi Thomas,
i just played a bit with GPIO functions on STM32 and found that e.g. GPIO_SetBits is far slower (close to 10x) than writing to register directly. e.g.
GPIO_SetBits(GPIOD, GPIO_Pin_15); vs GPIOD->BSRRL=GPIO_Pin_15;
So for your lcd driver using direct registry access instead of stdperiph lib(in your case e.g. Clr_Cs; Clr_nWr; Set_nWr; Set_Cs) would make lcd access even faster.
I am using same lcd with fsmc interface for which is this not matter.
regards
Brano
Brano
@brano
Dear Brano.
Yes you are definitely right. We have also been proving that the built in bits writing functions are very slow due to some extra checking (if the IO exists and the parameters are correct).
In the case where FSMC isn’t supported or not used setting and clearing the IOs would be much faster with direct register writes – that is for sure.
Thank you for the reminder – it is always good to see other smart brains out there 🙂
Best Regards
Thomas Jespersen
Does sommebody code and experience with FSMC and direct register writing on STM32F207? Beacause of the fire up i failed. With GPIO works SSD perfect with Pic24, 32 dsPIC33EP (both GPIO and PMP) and STM32 (only GPIO). But now my brain is smoking… 😛
@Simon
Dear Simon.
We have experience in the FSMC bus interfacing and succeeded in using it for together with the SSD1963 controller.
Please see my reply to your mail.
Regards Thomas
Hi Thomas !
I have a 5″ TFT with SSD1963 up and running through FSMC on a STM32F4Discovery board.
Thank you for your code, it helped me through as well as http://en.radzio.dxp.pl/ssd1963/
Still having some bugs, for example some color and artifact issues due to timing.
I’d like to point out that in your very helpful driver code is hidden a very nasty typo that can cause a lot of headache, and maybe you’d want to fix it for other poor souls before they spend a day looking for it.
SSD1963.c line 427:
LCD_WriteData(0x04);
This should be 0x03 because the value were trying to set for LCDC_FPR is 0x3FFFF !
As this throws timing completely off I wanted to alert others to the bug.
Thanks ! Jonne from Finland
The SSD1963 datasheet shows 8080 mode CS# signal activating WITHIN the WE# or RD# signal activation period. STM32 FSMC signals have CS# asserted first and then then WE or RD are toggled. Is this an issue in interfacing/bus control?
@Andrew Spencer
No, there doesn’t seem to be any problems with the FSMC interface on the STM32 when using it with a SSD1963.
The most correct 8080 way is also to set the Chip select first and then toggle the write or read signals.
@Jonne Valola
Dear Jonne.
Thanks for pointing it out – odd that the project has been working at our end then.
Maybe the 7″ display we have been using hasn’t been that time critical.
Btw. Nice page you are having with the different GLCD libraries.
Regards Thomas
@Jonne Valola
Hi all,
since I am also fiddling around some nights now with the FSMC interface, is there anybody who provides the FSMC Code also? Until now I have only seen GPIO solutions so far.
Thanks a lot.
@Thomas
When you first get a good feeling of the memory environment and the Flexible Static Memory Controller of the STM32, these are actually quite easy to get running.
In the LVDS video we have uploaded we are using FSMC too.
You can find the LCD driver used to control our own LVDS display board but with both GPIO and FSMC options here: TKJ_STM32_LCD_FSMC_Driver.zip
You should definitely be able to use that as a ground level for adding the initialization register writes etc. for the SSD1963, which you already have within your current GPIO driver.
We do also have these drivers with FSMC but these are under an NDA so I can’t share them.
Regards Thomas
Hello Thomas,
I am working on STM32F103ZT6 and with SSD1963. I have connected 480X272 and 320X240 LCD’s. I am initializing SSD1963 with the Init Commands on same pins as you use, but in GPIO mode & not in FSMC mode. The Clock Freq from Crystal is 8MHz and in STM32 acitvating PLL is made to 72MHz. So, Clk Freq for SSD1963 is 8MHz. Hope we should configure the PLL in SSD1963. So below is my Initialisation Sequence details.
Please check it and let me know whether everything is proper.
//Hardware Reset
GPIOD->BSRR = GPIO_Pin_6;
millisecond_delay(1);
GPIOD->BRR = GPIO_Pin_6;
millisecond_delay(5);
GPIOD->BSRR = GPIO_Pin_6;
millisecond_delay(1);
// Software Reset
LCD_Cmd(0x01);
millisecond_delay(5);
LCD_Cmd(0x01);
millisecond_delay(5);
// Set PLL
LCD_Cmd(0xE0);
// Before the start, the system was operated with the crystal oscillator or clock input.
// A[1] : Lock PLL. After PLL enabled for 100us, can start to lock PLL
// 0 Use reference clock as system clock, 1 Use PLL output as system clock
// A[0] : 0 Disable PLL, 1 Enable PLL
LCD_Data(0x01);
millisecond_delay(10);
LCD_Data(0x03);
// Set LCD Mode
LCD_Cmd(0xB0);
// Bits settings
// 5 : TFT panel data width, 0 18-bit, 1 24-bit
// 4 : TFT color depth enhancement, 0 Disable FRC or dithering, 1 Enable FRC or dithering
// 3 : TFT FRC enable, 0 TFT dithering enable, 1 TFT FRC enable
// 2 : LSHIFT (dot clock) polarity, 0 Rising edge, 1 Falling edge
// 1 : LLINE (horizontal sync pulse) polarity, 0 Active low, 1 Active high
// 0 : LFRAME (vertical sync pulse) polarity, 0 Active low, 1 Active high
LCD_Data(0x23);
// Bits settings
// 7 : LCD panel mode, 0 Hsync+Vsync+DE mode, 1 TTL mode
// 6:5 : TFT type, 00, 01 TFT mode, 10 Serial RGB mode, 11 Serial RGB+dummy mode
LCD_Data(0x00);
// Horizontal panel size = (HPS + 1) pixels
// HPS[10:8] : Set the horizontal panel size
LCD_Data((GuiConst_DISPLAY_WIDTH – 1)>>8);
// HPS[7:0] : Set the horizontal panel size
LCD_Data((GuiConst_INT8U)(GuiConst_DISPLAY_WIDTH – 1));
// Vertical panel size = (VPS + 1) lines
// VPS[10:8] : Set the vertical panel size
LCD_Data((GuiConst_BYTE_LINES – 1)>>8);
// VPS[7:0] : Set the vertical panel size
LCD_Data((GuiConst_INT8U)(GuiConst_BYTE_LINES – 1));
// Bits settings
// 5:3 : Even line RGB sequence, 000 RGB, 001 RBG, 010 GRB, 011 GBR, 100 BRG, 101 BGR
// 2:1 : Odd line RGB sequence, 000 RGB, 001 RBG, 010 GRB, 011 GBR, 100 BRG, 101 BGR
LCD_Data(0x00);
// Set Pixel Data Interface
LCD_Cmd(0xF0);
// A[2:0] : 0: 8-bit, 1: 12-bit, 2: 16-bit packed, 3: 16-bit (565 format),
// 4: 18-bit, 5: 24-bit, 6: 9-bit
#ifdef 8BIT_BUS
LCD_Data(0x00);
#else
LCD_Data(0x03);
#endif
// Set Pixel Format
LCD_Cmd(0x3A);
// A[6:4] : 001: 3-bit/pixel, 010: 8-bit/pixel, 011: 12-bit/pixel,
// 101: 16-bit/pixel,110: 18-bit/pixel,111: 24-bit/pixel
LCD_Data(0x20);
// Set PLL MN
// N[7:0] : Multiplier (N) of PLL.
// M[3:0] : Divider (M) of PLL.
// C[2] : Effectuate MN value,
// 0 Ignore the multiplier (N) and divider (M) values in A[7:0] and B[7:0]
// 1 Effectuate the multiplier and divider value
// Example For a 10MHz reference clock to obtain 115MHz PLL frequency
//Sha – To acheive 120Mhz, Considering 119MHz, 119*6/8 (8.0MHz) = 89.25.. Rounding to 89*8/6 = 118.66MHz
LCD_Cmd(0xE2);
LCD_Data(0x59); // (N=34)
LCD_Data(0x06); // (M=3)
LCD_Data(0x04); // (Dummy Byte)
// Set LSHIFT Frequency
LCD_Cmd(0xE6);
// Configure the pixel clock to PLL freq x ((LCDC_FPR + 1) / 2 on 20)
// Example to obtain PCLK = 5.3MHz with PLL Frequency = 120MHz,
//Sha – 4.0 Mhz with PLL Freq = 72MHz
//LCDC_FPR[19:16]
LCD_Data(0x00);
// LCDC_FPR[15:8]
LCD_Data(0xE3);
// LCDC_FPR[7:0]
LCD_Data(0x8E);
// Set Horizontal Period
LCD_Cmd(0xB4);
// Horizontal total period = (HT + 1) pixels
// HT[10:8]
LCD_Data((GuiConst_DISPLAY_WIDTH + 0x30)>>8);
// HT[7:0]
LCD_Data((GuiConst_INT8U)(GuiConst_DISPLAY_WIDTH + 0x30));
// Horizontal Sync Pulse Start Position = (HPS + 1) pixels
// HPS[10:8]
LCD_Data(0x00);
// HPS[7:0]
LCD_Data(0x10);
// (LLINE) Horizontal Sync Pulse Width = (HPW + 1) pixels
// HPW[6:0]
LCD_Data(0x20);
// Horizontal Display Period Start Position = LPS pixels
// LPS[10:8]
LCD_Data(0x00);
// LPS[7:0]
LCD_Data(0x20);
// LPSPP[1:0] : Set the horizontal sync pulse subpixel start position
LCD_Data(0x00);
// Set Vertical Period
LCD_Cmd(0xB6);
// Vertical Total = (VT + 1) lines
// VT[10:8]
LCD_Data((GuiConst_BYTE_LINES + 0x10)>>8);
// VT[7:0]
LCD_Data((GuiConst_INT8U)(GuiConst_BYTE_LINES + 0x10));
// Vertical Sync Pulse Start Position = VPS lines
// VPS[10:8]
LCD_Data(0x00);
// VPS[7:0]
LCD_Data(0x04);
// (LFRAME)Vertical Sync Pulse Width = (VPW + 1) lines
// VPW[6:0]
LCD_Data(0x01);
// Vertical Display Period Start Position = FPS lines
// FPS[10:8]
LCD_Data(0x00);
// FPS[7:0]
LCD_Data(0x06);
/***************************************/
// Set Address Mode
LCD_Cmd(0x36);
// A[7] : Page address order, 0 Top to bottom, 1 Bottom to top
// A[6] : Column address order, 0 Left to right, 1 Right to left
// A[5] : Page / Column order, 0 Normal mode, 1 Reverse mode
// A[4] : Refresh line address order, 0 from top to bottom, 1 from bottom to top
// A[3] : RGB / BGR order, 0 RGB, 1 BGR
// A[2] : Display data refresh, 0 from left to right side, 1 from right to left side
// A[1] : Flip Horizontal, 0 Normal, 1 Flipped
// A[0] : Flip Vertical, 0 Normal, 1 Flipped
LCD_Data(0x00);
// Set GPIO Configuration
LCD_Cmd(0xB8);
// A[7] – A[4] : GPIO3 configuration, 0 GPIO is controlled by host, 1 GPIO is controlled by LCDC
LCD_Data(0xF0);
// B[0] : GPIO0 direction
// 0 GPIO0 is used to control the panel power with Enter or Exit Sleep Mode
// 1 GPIO0 is used as normal GPIO
LCD_Data(0x00);
// Set Post Proc
LCD_Cmd(0xBC);
// A[7:0] : Set the contrast value
// B[7:0] : Set the brightness value
// C[7:0] : Set the saturation value
// D[0] : 0 Disable the postprocessor, 1 Enable the postprocessor
LCD_Data(0x40);
LCD_Data(0x40);
LCD_Data(0x40);
LCD_Data(0x00);
// Set Gamma Curve
LCD_Cmd(0x26);
// 0 – No gamma curve, 1 – Gamma curve 0, 2 – Gamma curve 1, 4 – Gamma Curve 2, 8 – Gamma curve 3
LCD_Data(0x08);
// Set Column Address
LCD_Cmd(0x2A);
// Start column
LCD_Data(0x00);
LCD_Data(0x00);
// End column
LCD_Data(GuiConst_DISPLAY_WIDTH>>8);
LCD_Data((GuiConst_INT8U)GuiConst_DISPLAY_WIDTH);
// Set Page Address
LCD_Cmd(0x2B);
// Start row
LCD_Data(0x00);
LCD_Data(0x00);
// End row
LCD_Data(GuiConst_BYTE_LINES>>8);
LCD_Data((GuiConst_INT8U)GuiConst_BYTE_LINES);
// Enter Normal Mode
LCD_Cmd(0x13);
// Set display on
LCD_Cmd(0x29);
// Clear display memory
LCD_Cmd(0x2C);
for (i = 0; i < (GuiConst_DISPLAY_BYTES/2); i++);
LCD_Data(0x0000);
//Transfer some color codes.
while(1)
{
k++;
SSD1963_FillArea(k);
millisecond_delay(1);
}
I am not able to get any kind of Signals at LFRAME, LLINE, LSHIFT, LDEN. I dont know how to use GAMAS0 pin and where. If required I will send you the Schematic also later.
Thanks
Shankar
@Thomas Jespersen
Hello Thomas,
I am able to get something on LCD now.. But when I send the color code in Fill Color Function, I am always getting Grey Code Colors only. Not any color like Red, Blue , Green..
I am also not getting how does SSD1396 will convert it to 24bit Color Code to LCD, with 16Bit Color code from MicroController as Input.
Thanks in advance..
Rgds
Shankar
@Shankar
Hi Shankar.
I have just briefly checked your code, and I’m not sure that you are doing the same initializations as me – but yet again they can and also needs to vary a bit from display to display.
Here is my register initialization for a 480×272 LCD:
LCD_WriteData(0x01); // enable PLL
LCD_Delay(10000); // wait stablize
LCD_WriteCommand(0xE0); // Start PLL command again
LCD_WriteData(0x03); // now, use PLL output as system clock
LCD_WriteCommand(0x01); // Soft reset
LCD_Delay(50000);
//Set LSHIFT freq, i.e. the DCLK with PLL freq 120MHz set previously
//Typical DCLK for display is between 9MHz and 15MHz
//10MHz = 120MHz*(LCDC_FPR+1)/2^20
//LCDC_FPR = 87380 (0x15554)
LCD_WriteCommand(0xE6);
LCD_WriteData(0x03);
LCD_WriteData(0x33);
LCD_WriteData(0x33);
//Set panel mode, varies from individual manufacturer
LCD_WriteCommand(0xB0);
LCD_WriteData(0x00);
LCD_WriteData(0x00); // set TTL mode
LCD_WriteData((HDP>>8)&0X00FF); //Set HDP
LCD_WriteData(HDP&0X00FF);
LCD_WriteData((VDP>>8)&0X00FF); //Set VDP
LCD_WriteData(VDP&0X00FF);
LCD_WriteData(0x0000); //RGB sequence
//Set horizontal period
LCD_WriteCommand(0xB4); //HSYNC -> Set HT
LCD_WriteData((HT>>8)&0X00FF);
LCD_WriteData(HT&0X00FF);
LCD_WriteData((HPS>>8)&0X00FF); //Set HPS
LCD_WriteData(HPS&0X00FF);
LCD_WriteData(HPW); //Set HPW
LCD_WriteData((LPS>>8)&0X00FF); //Set HPS
LCD_WriteData(LPS&0X00FF);
LCD_WriteData(0x0000);
//Set vertical period
LCD_WriteCommand(0xB6); //VSYNC -> //Set VT
LCD_WriteData((VT>>8)&0X00FF);
LCD_WriteData(VT&0X00FF);
LCD_WriteData((VPS>>8)&0X00FF); //Set VPS
LCD_WriteData(VPS&0X00FF);
LCD_WriteData(VPW); //Set VPW
LCD_WriteData((FPS>>8)&0X00FF); //Set FPS
LCD_WriteData(FPS&0X00FF);
LCD_WriteCommand(0x0036);
LCD_WriteData(ORIENTATION_REGISTER);
//Set pixel data interface
LCD_WriteCommand(0xF0);
LCD_WriteData(0x03); //16-bit(565 format) data for 16bpp PIC32MX only
//LCD_WriteData(0x00); //8-bit data for 16bpp, PIC24 series
LCD_WriteCommand(0x29); // Turn on display; show the image on display
Here are my display settings variables:
#define DISP_VER_RESOLUTION 272
#define HDP 479
#define HT 531
#define HPS 43
#define LPS 8
#define HPW 1
#define VDP 271
#define VT 288
#define VPS 12
#define FPS 4
#define VPW 10
Please be aware that I’m using an 10MHz crystal connected to the SSD1963 chip, instead of the 8MHz in your case.
You would have to change the PLL settings accordingly.
Though in your code you have made a mistake with the for loop, writing the 0x0000 color data.
You have made a semicolor after the for loop, which means that it will simply execute itself, and no code – so the following LCD_Data line will only be executed once!
Instead it should say:
Regarding the color conversion you can decide which mode to use: 8-bit, 16-bit, 18-bit or 24-bit.
Whatever mode you decide to use you will simply have to clock in the color data, either by a single cycle clock operation or by multiple.
For 24-bit displays used in 16-bit mode, the lower bits is simply not used.
Good luck.
Kind regards
Thomas Jespersen
Hi everybody,
I am trying the same like most of you: Connecting the SSD1963 with a STM32 (F4-Discovery Board). I am very very new with microcontrollers.
I think it is clear how to connect the SSD1963 to the STM32. All but the clock.
The clock speed of STM32 is set up by “GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz”, isnt it? Ok good so far.
If I understood right, the SSD1963 can either generate its own clock signal or use an external clock. What is better? Should (can) I use any clock signal from STM?
Which timings should I setup with the SSD 0xE2 command? The higher the better? Or must it match somehow the display or STM or anything else?
Thanks & Kind regards,
Steffen Strueber
@Steffen Strueber
Hi Steffen.
I would definitely recommend to have a crystal or oscillator on the SSD1963 board and drive the display controller in that way.
The GPIO_Speed you set within the code is simply to tell the processor which rise and fall times to expect – it has nothing to do with clock generation on the GPIO outputs.
You could of course also decide to get the main processor oscillator output (probably 8MHz) on one of the GPIO pins, but this would require some very short shielded cables to avoid emission and noise on the other cables.
The 0xE2 command is used to set the Multiplier and Divider of the internal PLL of the SSD1963 to generate an internal frequency between 250MHz and 800MHz.
You would have to set this setting accordingly to the input clock frequency used (the crystal on the SSD1963 board).
Regards Thomas
@Thomas Jespersen
Hello Thomas,
Thanks a lot, Now I am able to display colors and whatever I want on TFT (480X272).
Now I am facing some problem with the display buffer initialization in STM32.
In STM32F103ZGT6, SRAM size is 96K, and I need Display Buffer size of ((480X272) X 2) = 261120 bytes. I am using 16 bit Color Coding.
The fact is, 261120 bytes cant fit in STM32 SRAM now. So I want to configure the FSMC bank location 0x60000000 location for storing this Display Buffer data. F.Y.I
typedef union
{
GuiConst_INT8U Bytes[GuiConst_BYTE_LINES][GuiConst_BYTES_PR_LINE];
GuiConst_INT16U Words[GuiConst_BYTE_LINES][GuiConst_BYTES_PR_LINE / 2];
}DisplayBufUnion;
extern DisplayBufUnion GuiLib_DisplayBuf __attribute__((at(0x60020000)));
At present, I am not able to write into this buffer. It has 0x002C as data into all the locations of Buffer. If I cahnge the content of this location or buffer using Debugger or in software, it is writing anything into this buffer, always it has data 0x002C.
Can you please tell me, how to take control of this FSMC Bank location by doing the required configurations. I went through the examples mentioned by you before my first comment. “TKJ_DISP.c” & “TKJ_DISP.h”, but didnt get how can we send the commands to SSD1963 of X1, Y1, X2 & Y2 positions to write the data into that location.
The function “LCD_WriteReg(reg,data)” is sending only one byte of data, but actually SSD1963 Command “0x2B” needs four bytes of data to be sent (Start Row and End Row), and it is same for Command “0x2A”. Can you tell me, how is this FSMC taking care regarding this.
Thanks
Shankar
@Shankar
Hello Thomas,
I can see in File “TKJ_DISP.c” line 1263, that you are writing the Command and Data,
LCD_REG = LCD_Reg;
/* Write 16-bit Reg */
LCD_RAM = LCD_RegValue;
I dont know abt how FSMC works, but please clarify, whether just by writing on location 0x60000000, the command will be sent?..and Just by writing on location 0x60020000, the data is written to SSD1963.. ?..
I know that, SSD1963 works with only 16Bit of Command and Data. No addressing required. So when I write on any Location between, 0x60000000 & 0x6FFFFFFF (Not considering Banks at present), I can be sure that, Command or Data is written on Data lines of SSD1963 (or on STM32 FSMC data lines)..
I am quite confused..
Rgds
Shankar
@Shankar
Hi Shankar.
Your discoveries in the TKJ_DISP.c is completely right and I will try to explain what is going on with the FSMC interface.
As you say too, the SSD1963 doesn’t have any address lines for control, though the FSMC interface does.
Instead the SSD1963 has a Register Select pin, which the FSMC interface unfortunately doesn’t have.
So to fix this issue we are simply just using one of the Address pins and connect that to the RS pin on the SSD1963.
In the TKJ_DISP project we have connected A16 (GPIOD.11) to the RS pin.
Whenever we need to write some 16-bit data to the command register of the SSD1963 the RS pin has to be low (0). This is done by writing to the currently configured NOR/SRAM FSMC memory area at adress 0x60000000, as the address is then 0x00000.
Finally when we need to write to some data to the SSD1963 the RS pin has to be high (1). This is then done by setting this appropriate address (writing to this address) which sets that bit high.
In this case it is 0x6002000 as this turns into an address of 0x10000 which is equal to bit 16 set (1 << 16). So whenever you write to the FSMC address 0x60000000 you will be writing to the command register of the SSD1963 - in the code named LCD_REG. And whenever you write to the FSMC address 0x60020000 you will be writing to the data memory of the SSD1963 - in the code named LCD_RAM. I hope this gave you some basic understanding of how the FSMC periphiral is implemented and used to control 16-bit LCDs. Kind regards Thomas Jespersen
Hello Thoma
@Thomas Jespersen
Hello Thomas,
I was wondering, this could be the reason, before seeing your comment.. Even in my Hardware PD11 is connected to RS pin of SSD1963.
But have small confusion now..
0x60020000, when I take only 0x20000, in binary it will be 0010 0000 0000 0000 0000.. How can this become address 0x10000, on address lines of FSMC.. Where did one “0” miss in Binary.
Please explain me
“In this case it is 0x60020000 as this turns into an address of 0x10000 which is equal to bit 16 set (1 << 16)."
Thanks
Shankar
@Shankar
Considering 0x20000 (0x60020000)
A19A18A17A16 A15A14A13A12 A11A10A9A8 A7A6A5A4 A3A2A1A0
0 0 1 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0
(1 is coming at A17 and not at A16)
How can this value become 0x10000
0001 0000 0000 0000 0000
So that I can get 1 at A16, Please explain.
Thanks
Shankar
@Thomas Jespersen
Hello Thomas,
Thanks a lot for your support.. I am able to get the TFT working with FSMC settings.
But still, please clarify my above doubt..
Please let me also know, how safe it is with “Donate” button above to the right. I know Paypal process, but my currency is INR (India), I will check with my bank of how much service charge do they take for Currency conversion after Donation..
Thanks a lot..
Shankar
Hi Thomas,
I am interfacing 5″ Kentec display (800×480) driver SSD1963. But the screen shows only blueish color, not even any other color changing as i am trying to fill it with other colors. I also download code from techtoys. Please suggest some solution. already checked all signals & timing.
Source Code for SSD1963
void delay(uint32_t delay_counts_val){
uint32_t delay_counts;
delay_counts_val *= 1000;
for(delay_counts = 0; delay_counts < delay_counts_val; delay_counts++);
}
/************************************************************************//**
* void glcd_data_write(void)
*
* @brief Graphical LCD Write.
****************************************************************************/
void command_data_write_gpio(uint16_t command){
uint8_t data_val, val = 0;
uint16_t temp_command;
temp_command = command;
for(data_val = 0; data_val > data_val);
val = temp_command & 0x0001;
temp_command = command;
switch(data_val){
case 0:
if(val == LCD_TRUE)
DATA_L0_HIGH;
else
DATA_L0_LOW;
break;
case 1:
if(val == LCD_TRUE)
DATA_L1_HIGH;
else
DATA_L1_LOW;
break;
case 2:
if(val == LCD_TRUE)
DATA_L2_HIGH;
else
DATA_L2_LOW;
break;
case 3:
if(val == LCD_TRUE)
DATA_L3_HIGH;
else
DATA_L3_LOW;
break;
case 4:
if(val == LCD_TRUE)
DATA_L4_HIGH;
else
DATA_L4_LOW;
break;
case 5:
if(val == LCD_TRUE)
DATA_L5_HIGH;
else
DATA_L5_LOW;
break;
case 6:
if(val == LCD_TRUE)
DATA_L6_HIGH;
else
DATA_L6_LOW;
break;
case 7:
if(val == LCD_TRUE)
DATA_L7_HIGH;
else
DATA_L7_LOW;
break;
case 8:
if(val == LCD_TRUE)
DATA_L8_HIGH;
else
DATA_L8_LOW;
break;
case 9:
if(val == LCD_TRUE)
DATA_L9_HIGH;
else
DATA_L9_LOW;
break;
case 10:
if(val == LCD_TRUE)
DATA_L10_HIGH;
else
DATA_L10_LOW;
break;
case 11:
if(val == LCD_TRUE)
DATA_L11_HIGH;
else
DATA_L11_LOW;
break;
case 12:
if(val == LCD_TRUE)
DATA_L12_HIGH;
else
DATA_L12_LOW;
break;
case 13:
if(val == LCD_TRUE)
DATA_L13_HIGH;
else
DATA_L13_LOW;
break;
case 14:
if(val == LCD_TRUE)
DATA_L14_HIGH;
else
DATA_L14_LOW;
break;
case 15:
if(val == LCD_TRUE)
DATA_L15_HIGH;
else
DATA_L15_LOW;
break;
}
}
}
/************************************************************************//**
* void glcd_data_write(uint16_t)
*
* @brief Graphical LCD Data Write.
****************************************************************************/
void glcd_command_write(uint16_t command){
uint16_t x_cordinates = 0, color = 0, temp_loop = 0;
LCD_CS_LOW;
LCD_RS_LOW; //for Command RS = 0
command_data_write_gpio(command); //Write command
DATA_WR_LOW;
DATA_WR_HIGH; //To Write Operation L - H Transition
LCD_CS_HIGH; // Latched into the system on Rising Edge of CS
}
/************************************************************************//**
* void glcd_data_write(uint16_t)
*
* @brief Graphical LCD command Write.
****************************************************************************/
void glcd_data_write(uint16_t data){
LCD_RS_HIGH; //for Command RS = 1
DATA_WR_LOW;
command_data_write_gpio(data); //Write command
DATA_WR_HIGH; //To Write Operation L - H Transition
}
WindowSet(unsigned int s_x,unsigned int e_x,unsigned int s_y,unsigned int e_y)
{
glcd_command_write(0x2a); //SET page address
LCD_CS_LOW;
glcd_data_write((s_x)>>8); //SET start page address=0
glcd_data_write((e_x)); //SET end page address=320
LCD_CS_HIGH;
glcd_command_write(0x2b); //SET column address
LCD_CS_LOW;
glcd_data_write((s_y)>>8); //SET start column address=0
glcd_data_write((e_y)); //SET end column address=240
LCD_CS_HIGH;
}
void SendData(int color)
{
glcd_data_write((color)); // color is red
}
void FULL_ON(int dat){
unsigned int x,y;
WindowSet(0,DISP_HOR_RESOLUTION-1, 0, DISP_VER_RESOLUTION-1);
glcd_command_write(0x2c);
LCD_CS_LOW;
for (x=0;x<480;x++)
{
for (y= 0;y>8); //HT - Horizontal Total Period
glcd_data_write(HT-1);
glcd_data_write((HPS-1)>>8); //HPS - HSYNC (Non_Display Area) to Start Pixel
glcd_data_write(HPS-1); //HPS: non-display period between the start of the horizontal sync (LLINE) signal and the first display data
glcd_data_write((DISP_HOR_PULSE_WIDTH-1)); //HSYNC Pulse Width
glcd_data_write(0x00); //LPS: horizontal sync pulse (LLINE) start location in pixel clocks
glcd_data_write(0x00);
glcd_data_write(0x00);
LCD_CS_HIGH;
//Set Vertical Period (VSYNC + V Front Porch + V Back Porch)
glcd_command_write(LCD_SET_VERT_PERIOD); //0xB6
LCD_CS_LOW;
glcd_data_write((VT-1)>>8); //VT - Horizontal Total Period
glcd_data_write(VT-1);
glcd_data_write((VSP-1)>>8); //VPS - VSYNC (Non_Display Area) to Start Pixel
glcd_data_write(VSP-1); //VPS: non-display period between the start of the Vertical sync (LLINE) signal and the first display data
glcd_data_write(DISP_VER_PULSE_WIDTH-1); //VSYNC Pulse Width
glcd_data_write(0x00); //VPS: Vertical sync pulse (LLINE) start location in pixel clocks
glcd_data_write(0x00);
LCD_CS_HIGH;
//Set Column Address
glcd_command_write(LCD_SET_COLUMN_ADDRESS);
LCD_CS_LOW;
glcd_data_write(0x00); //Start of Column
glcd_data_write(0x00);
glcd_data_write(0x03); //End of Column 0x01DF - 480 Pixels
glcd_data_write(0x1F);
LCD_CS_HIGH;
//Set Page Address
glcd_command_write(LCD_SET_PAGE_ADDRESS);
LCD_CS_LOW;
glcd_data_write(0x00); //Start of Page Number
glcd_data_write(0x00);
glcd_data_write(0x01); //End of Page Number 0x010F - 272 Pixels
glcd_data_write(0xDF);
LCD_CS_HIGH;
glcd_command_write(LCD_ENTER_NORMAL_MODE); //Enter Normal Mode
delay(10);
glcd_command_write(0x36); //Set Address Mode
LCD_CS_LOW;
glcd_data_write(0x00);
LCD_CS_HIGH;
delay(10);
glcd_command_write(0x3A);
LCD_CS_LOW;
glcd_data_write(0x55); //Pixel Data Interface - 16-bit 565
LCD_CS_HIGH;
glcd_command_write(LCD_SET_INTERFACE);
LCD_CS_LOW;
glcd_data_write(PIXEL_DATA_16B_565); //Pixel Data Interface - 16-bit 565
LCD_CS_HIGH;
glcd_command_write(0xB8);
LCD_CS_LOW;
glcd_data_write(0x0F);
glcd_data_write(0x01);
LCD_CS_HIGH;
glcd_command_write(LCD_SET_DISPLAY_ON); //Set Display On
}
@Aman
Dear Aman.
Have you confirmed that the 16-bit interface is working properly – like trying and probing all 16 lines when writing a specific data-byte?
I have one question about your “for”-loop in “command_data_write_gpio”: why do you have a semicolon afterwards? This makes the loop not execute anything, which means in your case the code below, is only executed ONCE!
Best regards
Thomas Jespersen
Hi Thomas
It was the mistake when i posted, but it not in the code. There is no semicolon after for loop.Yes i had tested all data lines status, every line is responding as i sent data.
for(data_val = 0; data_val > data_val);
val = temp_command & 0x0001;
temp_command = command;
Hi Thomas,
Please can you make sure one thing about the LCD module data for DB0 & DB9. In hardware schematic i had seen so many schematics in which DB0 & DB9 is connected to GND to make it as 18-bit mode.
Is it required to connect DB0 & DB9 to GND?
Hey Thomas,
LCD is running now, found one issue in the hardware. RST & CS both sorted due to loose connector. Now fixed.
Thanks
@Aman
Perfect. I am glad that you found the issue.
For me it is very difficult to debug these kind of issues without having the hardware 😉
Dear Thomas,
I found your source code very helpful. With the actual displaying routine for decoding fonts, it is not possible to display font bigger than the 16×16 (width and height) one. Do you have a displaying routine for decoding until 32×32 fonts ?
Best regards,
Julien
@Julien
Hi Julien.
I am aware that this released version of my SSD1963 graphics drivers doesn’t support larger fonts than 16×16.
It was a relatively easy fix to implement, which only included changing the font width algorithm within the char printing function.
Furthermore I’ve also implemented the capability of individual varying character widths to make the text flow look a bit better.
Unfortunately I can’t release this update as I’ve been using this for commercial purposes within TKJ Electronics. Though I hope with the above mentioned changes that you are able to implement it yourself.
Thank you for your understanding.
Best regards
Thomas Jespersen
Hi Thomas,
Thanks a lot for your help. The font generated by sotware is as follows:
const unsigned char const MyFont[] = {
109, // Size of one char (number of bytes)
27, // Font Width
31, // Font Height
……
i tried fixing your algorithm for that kind of font:
void LCD_PutChar(uint16_t x, uint16_t y, uint8_t Character, uint16_t ForeColor, uint16_t BackColor)
{
int row = 0;
int column = 0;
int offset = Character * MyFont[0];
GLCD_SetArea(x, y, x+MyFont[1]-1, y+MyFont[2]-1);
GLCD_WriteCommand(CMD_WR_MEM_START);
for (row = 0; row < MyFont[2]; row++)
{
for (column = 0; column 0)
{
GLCD_WriteData(ForeColor);
} else {
GLCD_WriteData(BackColor);
}
}
if (row > 0 && row 0) // Math.Pow = ^ (opløftet i)
{
GLCD_WriteData(ForeColor);
} else {
GLCD_WriteData(BackColor);
}
}
if (row == 8)
{
if ((MyFont[2 * column + 2 + 3+offset] & 1) > 0)
{
GLCD_WriteData(ForeColor);
} else {
GLCD_WriteData(BackColor);
}
}
if (row > 8 && row 0) // Math.Pow = ^ (opløftet i)
{
GLCD_WriteData(ForeColor);
} else {
GLCD_WriteData(BackColor);
}
}
if (row == 16)
{
if ((MyFont[2 * column + 3 + 3+offset] & 1) > 0)
{
GLCD_WriteData(ForeColor);
} else {
GLCD_WriteData(BackColor);
}
}
if ( row > 16 && row 0) // Math.Pow = ^ (opløftet i)
{
GLCD_WriteData(ForeColor);
} else {
GLCD_WriteData(BackColor);
}
}
if (row == 24)
{
if ((MyFont[2 * column + 4 + 3+offset] & 1) > 0)
{
GLCD_WriteData(ForeColor);
} else {
GLCD_WriteData(BackColor);
}
}
if ( row > 24 && row 0) // Math.Pow = ^ (opløftet i)
{
GLCD_WriteData(ForeColor);
} else {
GLCD_WriteData(BackColor);
}
}
}
}
}
However, that does not work. Can you just give me a piece of advice please ?
Best regards,
Julien
Sorry for that indentation. Correct code is the following:
void LCD_PutChar(uint16_t x, uint16_t y, uint8_t Character, uint16_t ForeColor, uint16_t BackColor)
{
int row = 0;
int column = 0;
int offset = Character * MyFont[0];
GLCD_SetArea(x, y, x+MyFont[1]-1, y+MyFont[2]-1);
GLCD_WriteCommand(CMD_WR_MEM_START);
for (row = 0; row < MyFont[2]; row++)
{
for (column = 0; column 0)
{
GLCD_WriteData(ForeColor);
} else {
GLCD_WriteData(BackColor);
}
}
if (row > 0 && row 0)
{
GLCD_WriteData(ForeColor);
} else {
GLCD_WriteData(BackColor);
}
}
if (row == 8)
{
if ((MyFont[2 * column + 2 + 3+offset] & 1) > 0)
{
GLCD_WriteData(ForeColor);
} else {
GLCD_WriteData(BackColor);
}
}
if (row > 8 && row 0)
{
GLCD_WriteData(ForeColor);
} else {
GLCD_WriteData(BackColor);
}
}
if (row == 16)
{
if ((MyFont[2 * column + 3 + 3+offset] & 1) > 0)
{
GLCD_WriteData(ForeColor);
} else {
GLCD_WriteData(BackColor);
}
}
if ( row > 16 && row 0)
{
GLCD_WriteData(ForeColor);
} else {
GLCD_WriteData(BackColor);
}
}
if (row == 24)
{
if ((MyFont[2 * column + 4 + 3+offset] & 1) > 0)
{
GLCD_WriteData(ForeColor);
} else {
GLCD_WriteData(BackColor);
}
}
if ( row > 24 && row 0)
{
GLCD_WriteData(ForeColor);
} else {
GLCD_WriteData(BackColor);
}
}
}
}
}
@Julien
Hi Julien.
I have just realised that I used a minimized but still very functional version of the SSD1963 library in our IOT Football table project, which has been published on both our Blog and Github.
So to help you out with the specific Font size problem, I would refer to the updated PutChar function: https://github.com/TKJElectronics/IoT_Football/blob/master/LCD/src/SSD1963_api.c#L313
I hope this help you.
hi thanx for your website
could you pleas send me a schematic of interfasing STM32F4xx to SSD1963?
thanx