changeset 7:9404b9869c27

Make the LCD panel work (timings, GPIOE clock needs to be on, etc) Factor out LCD init (needs more work)
author Daniel O'Connor <darius@dons.net.au>
date Sun, 22 Jan 2012 17:10:51 +1030
parents 2b92d9632999
children 58d76cf522ff
files BSDmakefile README.txt lcd.c lcd.h main.c
diffstat 5 files changed, 182 insertions(+), 127 deletions(-) [+]
line wrap: on
line diff
--- a/BSDmakefile	Sat Jan 14 11:42:24 2012 +1030
+++ b/BSDmakefile	Sun Jan 22 17:10:51 2012 +1030
@@ -7,7 +7,7 @@
 		misc.c \
 		startup_stm32f10x_md_mthomas.c \
 		syscalls.c \
-		system_stm32f10x.c \
+		system_stm32f10x.c
 
 STM32LIBS=	usart gpio rcc rtc pwr bkp fsmc spi tim
 
@@ -24,9 +24,9 @@
 # Enable thumb code (since the Cortex M3 only does thumb)
 COMMONFLAGS+=	-mthumb
 # Debugging & optimisation
-COMMONFLAGS+= -g -O2
+COMMONFLAGS+= -g -O0
 # Put functions & data in individual sections to allow the linker to optimise (breaks debugging apparently)
-#COMMONFLAGS+=	-ffunction-sections -fdata-sections
+COMMONFLAGS+=	-ffunction-sections -fdata-sections
 # We aren't using exceptions
 COMMONFLAGS+=	-fno-exceptions
 
@@ -68,4 +68,7 @@
 load:
 	${GDB} --eval-command="target remote 127.0.0.1:61234" --eval-command "load" ${PROG}.elf
 
+png2bin:	png2bin.c
+	gcc ${.CURDIR}/png2bin.c -o ${.OBJDIR}/png2bin -O2 -Wall -I/opt/local/include -L/opt/local/lib -lpng
+
 .include "${.CURDIR}/BSDmakefile.arm"
--- a/README.txt	Sat Jan 14 11:42:24 2012 +1030
+++ b/README.txt	Sun Jan 22 17:10:51 2012 +1030
@@ -12,7 +12,7 @@
 SDIO.
 
 The LCD is driven by an ILI9325 connected in parallel 16 bit mode via
-the FSMC controller.
+the FSMC controller with a TSC2046N on the SPI bus for touch.
 
 Toolchain
 =========
--- a/lcd.c	Sat Jan 14 11:42:24 2012 +1030
+++ b/lcd.c	Sun Jan 22 17:10:51 2012 +1030
@@ -3,13 +3,13 @@
  * ~/projects/STM32Strive/奋斗STM32开发板例程/奋斗STM32开发板例程/奋斗STM32开发板MINI/STM32奋斗版ucOS II V2.86 uCGUI 3.9 DEMO-V2/STM32奋斗版ucOS II V2.86 uCGUI 3.9 DEMO
  *
  * Schematics
- * Main board ~/Downloads/Strive\ Mini\ STM32\ Schematic.pdf 
- * LCD board ~/Downloads/Strive Mini LCD STM32 Schematic.pdf
- * MCU reference manual
- * ~/Downloads/CD00171190.pdf
- * MCU Data sheet (pinout)
- * ~/Downloads/CD00191185.pdf
- * LCD data sheet
+ * Main board docs/Strive\ Mini\ STM32\ Schematic.pdf 
+ * LCD board docs/Strive Mini LCD STM32 Schematic.pdf
+ * MCU reference manual docs/CD00171190.pdf
+ * MCU Data sheet (pinout) docs/CD00191185.pdf
+ * LCD controller data sheet docs/ili9325-v0.35.pdf
+ * LCD controller app notes docs/ILI9325AN_V0.22.pdf
+ * XXX: not sure what panel is connected
  * 
  */
 /*	LCD board	MCU
@@ -44,7 +44,7 @@
   29	D1		PD15/FSMC_D1
   30	D9		PE12/FSMC_D9
   31	D0		PD14/FSMC_D0
-  32	D14		PD9/FSMC_D9
+  32	D14		PD9/FSMC_D14
   33	NC		
   34	D8		PE11/FSMC_D8
   35	NC		
@@ -59,6 +59,8 @@
 #include "stm32f10x.h"
 #include "lcd.h"
 
+static void	LCD_Doinit(void);
+
 #define Bank1_LCD_C	((uint32_t)0x60000000)    /* Register Address */
 #define Bank1_LCD_D	((uint32_t)0x60020000)    /* Data Address */
 
@@ -85,15 +87,25 @@
 }
 
 void
+LCD_WR_StartData(uint16_t x, uint16_t y) {
+    LCD_WR_Reg(0x20, x);
+    LCD_WR_Reg(0x21, y);
+    *(__IO uint16_t *)(Bank1_LCD_C) = 0x22;	/* Start GRAM write */
+}
+
+void
 LCD_WR_Data(uint16_t val) {
     *(__IO uint16_t *)(Bank1_LCD_D) = val;
 }
 
-/* Callers imply this is in milliseconds but that seems unlikely */
+/* This is a bit rough and ready */
 void
 Delay(__IO uint32_t nCount) {
+    __IO uint32_t i;
+    
     for(; nCount != 0; nCount--)
-	;
+	for (i = 0; i < 3900; i++)
+	    ;
 }
 
 uint8_t
@@ -221,16 +233,18 @@
     FSMC_NORSRAMInitTypeDef		FSMC_NORSRAMInitStructure;
     FSMC_NORSRAMTimingInitTypeDef	p;
     TIM_TimeBaseInitTypeDef		TIM_TimeBaseStructure;
-    uint16_t				id;
     
     /* Enable FSMC clock */
     RCC_AHBPeriphClockCmd(RCC_AHBPeriph_FSMC, ENABLE);
 
+    /* Enable alternate function IO clock */
+    RCC_APB2PeriphClockCmd(RCC_APB2Periph_AFIO, ENABLE);
+
     /* Enable GPIOD clock */
     RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOD, ENABLE);
 
-    /* Enable alternate function IO clock */
-    RCC_APB2PeriphClockCmd(RCC_APB2Periph_AFIO, ENABLE);
+    /* Enable GPIOD clock */
+    RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOE, ENABLE);
 
     /* Configures LCD Control lines (FSMC Pins) in alternate function Push-Pull mode.
      *
@@ -238,7 +252,8 @@
      * PD10(D15), PD11(A16/RS) PD14(D0), PD15(D1)
      */
     GPIO_InitStructure.GPIO_Pin = (GPIO_Pin_0 | GPIO_Pin_1 | GPIO_Pin_4 | GPIO_Pin_5 | GPIO_Pin_7 |
-				   GPIO_Pin_8 | GPIO_Pin_9 | GPIO_Pin_10 | GPIO_Pin_11 | GPIO_Pin_14 | GPIO_Pin_15);
+				   GPIO_Pin_8 | GPIO_Pin_9 | GPIO_Pin_10 | GPIO_Pin_11 | 
+				   GPIO_Pin_14 | GPIO_Pin_15);
     GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz;
     GPIO_InitStructure.GPIO_Mode = GPIO_Mode_AF_PP;
     GPIO_Init(GPIOD, &GPIO_InitStructure);
@@ -246,8 +261,9 @@
     /* PE7(D4), PE8(D5), PE9(D6), PE10(D7), PE11(D8), PE12(D9), PE13(D10),
      * PE14(D11), PE15(D12)
      */
-    GPIO_InitStructure.GPIO_Pin = GPIO_Pin_7 | GPIO_Pin_8 | GPIO_Pin_9 | GPIO_Pin_10 | 
-    GPIO_Pin_11 | GPIO_Pin_12 | GPIO_Pin_13 | GPIO_Pin_14 | GPIO_Pin_15;
+    GPIO_InitStructure.GPIO_Pin = (GPIO_Pin_7 | GPIO_Pin_8 | GPIO_Pin_9 | GPIO_Pin_10 | 
+				   GPIO_Pin_11 | GPIO_Pin_12 | GPIO_Pin_13 | GPIO_Pin_14 |
+				   GPIO_Pin_15);
     GPIO_Init(GPIOE, &GPIO_InitStructure);
 
     /* Configure backlight control (PD13/FSMC_A18 remapped to TIM4_CH2) */
@@ -291,23 +307,23 @@
     GPIO_Init(GPIOE, &GPIO_InitStructure);
 
     /* Configures the Parallel interface (FSMC) for LCD (Parallel mode) */
-    /* FSMC_Bank1_NORSRAM4 timing configuration */
-    p.FSMC_AddressSetupTime = 1;
-    p.FSMC_AddressHoldTime = 0;
-    p.FSMC_DataSetupTime = 2;
+    /* Timing configuration */
+    p.FSMC_AddressSetupTime = 5;
+    p.FSMC_AddressHoldTime = 5;
+    p.FSMC_DataSetupTime = 5;
     p.FSMC_BusTurnAroundDuration = 0;
     p.FSMC_CLKDivision = 0;
     p.FSMC_DataLatency = 0;
     p.FSMC_AccessMode = FSMC_AccessMode_A;
 
-    /* FSMC_Bank1_NORSRAM4 configured as follows:
+    /* FSMC_Bank1_NORSRAM1 configured as follows:
        - Data/Address MUX = Disable
        - Memory Type = SRAM
        - Data Width = 16bit
        - Write Operation = Enable
        - Extended Mode = Disable
        - Asynchronous Wait = Disable */
-    FSMC_NORSRAMInitStructure.FSMC_Bank = FSMC_Bank1_NORSRAM4;
+    FSMC_NORSRAMInitStructure.FSMC_Bank = FSMC_Bank1_NORSRAM1;
     FSMC_NORSRAMInitStructure.FSMC_DataAddressMux = FSMC_DataAddressMux_Disable;
     FSMC_NORSRAMInitStructure.FSMC_MemoryType = FSMC_MemoryType_SRAM;
     FSMC_NORSRAMInitStructure.FSMC_MemoryDataWidth = FSMC_MemoryDataWidth_16b;
@@ -322,105 +338,10 @@
     FSMC_NORSRAMInitStructure.FSMC_WriteBurst = FSMC_WriteBurst_Disable;
     FSMC_NORSRAMInitStructure.FSMC_ReadWriteTimingStruct = &p;
     FSMC_NORSRAMInitStructure.FSMC_WriteTimingStruct = &p;
-
     FSMC_NORSRAMInit(&FSMC_NORSRAMInitStructure);  
 
-    /* Enable FSMC_Bank1_NORSRAM4 */
-    FSMC_NORSRAMCmd(FSMC_Bank1_NORSRAM4, ENABLE);
-
-    /* Initialise LCD panel */
-
-    /* Pull reset pin low */
-    GPIO_ResetBits(GPIOE, GPIO_Pin_1);
-    Delay(0xafff);					   
-    GPIO_SetBits(GPIOE, GPIO_Pin_1);
-    Delay(0xafff);	
-
-    id = LCD_RD_Reg(0x00);
-    if (id != 0x9325) {
-	printf("LCD ID doesn't match, expected 0x9325 got 0x%x\r\n", id);
-	return;
-    }
-    
-    LCD_WR_Reg(0x00e3, 0x3008); /* Set internal timing */
-    LCD_WR_Reg(0x00e7, 0x0012); /* Set internal timing */
-    LCD_WR_Reg(0x00ef, 0x1231); /* Set internal timing */
-    LCD_WR_Reg(0x0000, 0x0001); /* Start Oscillation */
-    LCD_WR_Reg(0x0001, 0x0100); /* set SS and SM bit */
-    LCD_WR_Reg(0x0002, 0x0700); /* set 1 line inversion */
-
-    LCD_WR_Reg(0x0003, 0x1030); /* set GRAM write direction and BGR = 0, 262K colours, 1 transfers/pixel. */
-    LCD_WR_Reg(0x0004, 0x0000); /* Resize register */
-    LCD_WR_Reg(0x0008, 0x0202); /* set the back porch and front porch */
-    LCD_WR_Reg(0x0009, 0x0000); /* set non-display area refresh cycle ISC[3:0] */
-    LCD_WR_Reg(0x000a, 0x0000); /* FMARK function */
-    LCD_WR_Reg(0x000c, 0x0000); /* RGB interface setting */
-    LCD_WR_Reg(0x000d, 0x0000); /* Frame marker Position */
-    LCD_WR_Reg(0x000f, 0x0000); /* RGB interface polarity */
-
-    /* Power On sequence  */
-    LCD_WR_Reg(0x0010, 0x0000); /* SAP, BT[3:0], AP, DSTB, SLP, STB */
-    LCD_WR_Reg(0x0011, 0x0007); /* DC1[2:0], DC0[2:0], VC[2:0] */
-    LCD_WR_Reg(0x0012, 0x0000); /* VREG1OUT voltage */
-    LCD_WR_Reg(0x0013, 0x0000); /* VDV[4:0] for VCOM amplitude */
-    Delay(200);			/* Dis-charge capacitor power voltage */
-    LCD_WR_Reg(0x0010, 0x1690); /* SAP, BT[3:0], AP, DSTB, SLP, STB */
-    LCD_WR_Reg(0x0011, 0x0227); /* R11h = 0x0221 at VCI = 3.3V, DC1[2:0], DC0[2:0], VC[2:0] */
-    Delay(50); 			/* Delay 50ms */
-    LCD_WR_Reg(0x0012, 0x001c); /* External reference voltage= Vci; */
-    Delay(50); 			/* Delay 50ms */
-    LCD_WR_Reg(0x0013, 0x1800); /* R13 = 1200 when R12 = 009D; VDV[4:0] for VCOM amplitude */
-    LCD_WR_Reg(0x0029, 0x001c); /* R29 = 000C when R12 = 009D; VCM[5:0] for VCOMH */
-    LCD_WR_Reg(0x002b, 0x000d); /* Frame Rate = 91Hz */
-    Delay(50); 			/* Delay 50ms */
-    LCD_WR_Reg(0x0020, 0x0000); /* GRAM horizontal Address */
-    LCD_WR_Reg(0x0021, 0x0000); /* GRAM Vertical Address */
-
-    /* Adjust the Gamma Curve */
-    LCD_WR_Reg(0x0030, 0x0007);
-    LCD_WR_Reg(0x0031, 0x0302);
-    LCD_WR_Reg(0x0032, 0x0105);
-    LCD_WR_Reg(0x0035, 0x0206);
-    LCD_WR_Reg(0x0036, 0x0808);
-    LCD_WR_Reg(0x0037, 0x0206);
-    LCD_WR_Reg(0x0038, 0x0504);
-    LCD_WR_Reg(0x0039, 0x0007);
-    LCD_WR_Reg(0x003c, 0x0105);
-    LCD_WR_Reg(0x003d, 0x0808);
-
-    /* Set GRAM area */
-    LCD_WR_Reg(0x0050, 0x0000); /* Horizontal GRAM Start Address */
-    LCD_WR_Reg(0x0051, 0x00ef); /* Horizontal GRAM End Address */
-    LCD_WR_Reg(0x0052, 0x0000); /* Vertical GRAM Start Address */
-    LCD_WR_Reg(0x0053, 0x013f); /* Vertical GRAM Start Address */
-    LCD_WR_Reg(0x0060, 0xa700); /* Gate Scan Line */
-    LCD_WR_Reg(0x0061, 0x0001); /* NDL,VLE, REV */
-    LCD_WR_Reg(0x006a, 0x0000); /* set scrolling line */
-
-    /* Partial Display Control */
-    LCD_WR_Reg(0x0080, 0x0000);
-    LCD_WR_Reg(0x0081, 0x0000);
-    LCD_WR_Reg(0x0082, 0x0000);
-    LCD_WR_Reg(0x0083, 0x0000);
-    LCD_WR_Reg(0x0084, 0x0000);
-    LCD_WR_Reg(0x0085, 0x0000);
-
-    /* Panel Control */
-    LCD_WR_Reg(0x0090, 0x0010);
-    LCD_WR_Reg(0x0092, 0x0000);
-    LCD_WR_Reg(0x0093, 0x0003);
-    LCD_WR_Reg(0x0095, 0x0110);
-    LCD_WR_Reg(0x0097, 0x0000);
-    LCD_WR_Reg(0x0098, 0x0000);
-    LCD_WR_Reg(0x0007, 0x0133); /* 262K colour and display ON */
-  	
-    /* Fill panel with white */
-    LCD_WR_Reg(0x20, 0);
-    LCD_WR_Reg(0x21, 0x013f);
-    *(__IO uint16_t *)(Bank1_LCD_C) = 34;
-    for (uint32_t i = 0; i < 320 * 240; i++) {
-	LCD_WR_Data(0xffff);
-    }
+    /* Enable FSMC_Bank1_NORSRAM1 */
+    FSMC_NORSRAMCmd(FSMC_Bank1_NORSRAM1, ENABLE);
 
     /* Configure touch screen controller
      *
@@ -470,6 +391,7 @@
     /* SPI1 enable */
     SPI_Cmd(SPI1, ENABLE);  
 
+    LCD_Doinit();
 }
 
 void
@@ -485,3 +407,128 @@
     TIM_OC2Init(TIM4, &TIM_OCInitStructure);
 
 }
+
+static void
+LCD_Doinit(void) {
+    uint16_t				id;
+
+    /* Initialise LCD panel */
+
+    /* Pull reset pin low */
+    Delay(1);
+    GPIO_ResetBits(GPIOE, GPIO_Pin_1);
+    Delay(10);
+    GPIO_SetBits(GPIOE, GPIO_Pin_1);
+    Delay(50);
+
+    id = LCD_RD_Reg(0x00);
+    if (id != 0x9325) {
+	printf("LCD ID doesn't match, expected 0x9325 got 0x%x\r\n", id);
+	return;
+    }
+    printf("LCD ID matches\r\n");
+    
+    LCD_WR_Reg(0x00e3, 0x3008); /* Set internal timing (not documented) */
+    LCD_WR_Reg(0x00e7, 0x0012); /* Set internal timing (not documented) */
+    LCD_WR_Reg(0x00ef, 0x1231); /* Set internal timing (not documented) */
+    LCD_WR_Reg(0x0000, 0x0001); /* Start Oscillation */
+    Delay(50);
+    LCD_WR_Reg(0x0001, 0x0100); /* set SS (S720 -> S1) */
+    LCD_WR_Reg(0x0002, 0x0700); /* set line inversion (B/C + EOR) */
+    LCD_WR_Reg(0x0004, 0x0000); /* no resizing */
+    LCD_WR_Reg(0x0008, 0x0202); /* set the back porch and front porch (2 lines each) */
+    LCD_WR_Reg(0x0009, 0x0000); /* set non-display area refresh cycle ISC[3:0] */
+    LCD_WR_Reg(0x000a, 0x0000); /* FMARK function */
+
+    LCD_WR_Reg(0x000c, 0x0000); /* RGB ctl - Internal clock, 18bit interface */
+    LCD_WR_Reg(0x000d, 0x0000); /* Frame marker Position */
+    LCD_WR_Reg(0x000f, 0x0000); /* RGB interface polarity */
+
+    /* Power On sequence  */
+    LCD_WR_Reg(0x0010, 0x0000); /* SAP, BT[3:0], AP, DSTB, SLP, STB */
+    LCD_WR_Reg(0x0011, 0x0007); /* DC1[2:0], DC0[2:0], VC[2:0] */
+    LCD_WR_Reg(0x0012, 0x0000); /* VREG1OUT voltage */
+    LCD_WR_Reg(0x0013, 0x0000); /* VDV[4:0] for VCOM amplitude */
+    Delay(200);                 /* Dis-charge capacitor power voltage */
+    LCD_WR_Reg(0x0010, 0x1690); /* SAP, BT[3:0], AP, DSTB, SLP, STB */
+    LCD_WR_Reg(0x0011, 0x0227); /* R11h = 0x0221 at VCI = 3.3V, DC1[2:0], DC0[2:0], VC[2:0] */
+    Delay(50);                  /* Delay 50ms */
+    LCD_WR_Reg(0x0012, 0x001c); /* External reference voltage= Vci; */
+    Delay(50);                  /* Delay 50ms */
+    LCD_WR_Reg(0x0013, 0x1800); /* R13 = 1200 when R12 = 009D; VDV[4:0] for VCOM amplitude */
+    LCD_WR_Reg(0x0029, 0x001c); /* R29 = 000C when R12 = 009D; VCM[5:0] for VCOMH */
+    LCD_WR_Reg(0x002b, 0x000d); /* Frame Rate = 91Hz */
+    Delay(50);                  /* Delay 50ms */
+
+    /* Set GRAM area */
+    LCD_WR_Reg(0x0050, 0x0000); /* Horizontal GRAM Start Address */
+    LCD_WR_Reg(0x0051, 0x00ef); /* Horizontal GRAM End Address */
+    LCD_WR_Reg(0x0052, 0x0000); /* Vertical GRAM Start Address */
+    LCD_WR_Reg(0x0053, 0x013f); /* Vertical GRAM Start Address */
+
+    LCD_WR_Reg(0x0060, 0xa700); /* Gate Scan Line, drive G320 -> G1 */
+    LCD_WR_Reg(0x0061, 0x0003); /* VLE & REV */
+    LCD_WR_Reg(0x006a, 0x0000); /* set scrolling line */
+
+    /* Partial Display Control */
+    LCD_WR_Reg(0x0080, 0x0000); /* Image 1 */
+    LCD_WR_Reg(0x0081, 0x0000);
+    LCD_WR_Reg(0x0082, 0x0000);
+    LCD_WR_Reg(0x0083, 0x0000); /* Image 2 */
+    LCD_WR_Reg(0x0084, 0x0000);
+    LCD_WR_Reg(0x0085, 0x0000);
+
+    /* Panel Control */
+    LCD_WR_Reg(0x0090, 0x0010);
+    LCD_WR_Reg(0x0092, 0x0000);
+    LCD_WR_Reg(0x0093, 0x0003);
+    LCD_WR_Reg(0x0095, 0x0110);
+    LCD_WR_Reg(0x0097, 0x0000); /* Undocumented */
+    LCD_WR_Reg(0x0098, 0x0000); /* Undocumented */
+
+    LCD_WR_Reg(0x0007, 0x0133); /* Display on, 262k colour mode (vs 8) */
+
+    LCD_WR_Reg(0x0003, 0x1030); /* set GRAM write direction and enable BGR, 64K colours, 1 transfers/pixel. */
+
+    /* Adjust the Gamma Curve */
+    LCD_WR_Reg(0x0030, 0x0006);
+    LCD_WR_Reg(0x0031, 0x0101);
+    LCD_WR_Reg(0x0032, 0x0003);
+    LCD_WR_Reg(0x0035, 0x0106);
+    LCD_WR_Reg(0x0036, 0x0b02);
+    LCD_WR_Reg(0x0037, 0x0302);
+    LCD_WR_Reg(0x0038, 0x0707);
+    LCD_WR_Reg(0x0039, 0x0007);
+    LCD_WR_Reg(0x003c, 0x0600);
+    LCD_WR_Reg(0x003d, 0x020b);
+
+    fputs("Testing\r\n", stdout);
+    LCD_WR_StartData(0, 0);
+    LCD_WR_Data(0xa5a5);
+    LCD_WR_Data(0x5a5a);
+    LCD_WR_StartData(0, 0);
+    if ((id = LCD_RD_Data(1)) != 0xa5a5)
+	printf("Expected 0xa5a5 got 0x%04x\r\n", id);
+    
+    if ((id = LCD_RD_Data(0)) != 0x5a5a)
+	printf("Expected 0x5a5a got 0x%04x\r\n", id);
+
+    fputs("Filling\r\n", stdout);
+    /* Fill panel */
+    LCD_WR_StartData(0, 0);
+
+#define RGB24_565(R, G, B) (((((R) >> 3) & 0x1f) << 11) | ((((G) >> 2) & 0x3f) << 5) | (((B) >> 3) & 0x1f))
+
+    for (int x = 0; x < 320; x++) {
+	for (int y = 0; y < 240; y++) {
+	    if (((x / 5) % 3) == 0)
+		LCD_WR_Data(RGB24_565(255, 0, 0));
+	    else if (((x / 5) % 3) == 1)
+		LCD_WR_Data(RGB24_565(0, 255, 0));
+	    else
+		LCD_WR_Data(RGB24_565(0, 0, 255));
+	}
+    }
+
+}
+
--- a/lcd.h	Sat Jan 14 11:42:24 2012 +1030
+++ b/lcd.h	Sun Jan 22 17:10:51 2012 +1030
@@ -6,7 +6,10 @@
 uint16_t	LCD_RD_Reg(uint16_t index);
 uint16_t	LCD_RD_Data(int first);
 void		LCD_WR_Data(uint16_t val);
+void		LCD_WR_StartData(uint16_t x, uint16_t y);
+void		Delay(__IO uint32_t nCount);
 
+/* Touch controller (TSC2046N) defines */
 /* Mode/channel select defines */
 #define TP_READ_SEL(chan, mode, ref, pd) (0x80 | (((chan) & 0x07) << 4) | (((mode) & 0x01) << 3) | (((ref) & 0x01) << 2) | ((pd) & 0x03))
 
--- a/main.c	Sat Jan 14 11:42:24 2012 +1030
+++ b/main.c	Sun Jan 22 17:10:51 2012 +1030
@@ -119,14 +119,14 @@
 	    ;
     }
 
-    /* Init LCD interface */
+    /* Init LCD panel */
     LCD_init();
 
     /* Set stdout to unbuffered */
     setvbuf(stdout, NULL, _IONBF, 0);
     
     /* Say hello */
-    fputs("\r\nHello world\r\n", stdout);
+    fputs("\r\n\r\n\r\nHello world\r\n", stdout);
     
     while (1) {
 	fputs("> ", stdout);
@@ -145,8 +145,6 @@
 		tv.tv_sec = atoi(cmd.buf + 3);
 		tv.tv_usec = 0;
 		settimeofday(&tv, NULL);
-	    } else if (!strncmp("lcd", cmd.buf, 3)) {
-		printf("LCD ID = %hx\r\n", LCD_RD_Reg(0x00));
 	    } else if (!strncmp("read", cmd.buf, 4)) {
 		printf("PB5 = %d\r\n", GPIO_ReadInputDataBit(GPIOB, GPIO_Pin_15));
 	    } else if (!strncmp("touch", cmd.buf, 5)) {
@@ -199,6 +197,10 @@
 		printf("(0x%02x)\r\n", status);
 	    } else if (!strncmp("pwm ", cmd.buf, 4)) {
 		lcd_setpwm(atoi(cmd.buf + 4));
+	    } else if (!strncmp("timing", cmd.buf, 6)) {
+		fputs("Timing..\r\n", stdout);
+		Delay(10000);
+		fputs("Done\r\n", stdout);
 	    } else if (!strncmp("zz", cmd.buf, 2)) {
 		NVIC_SystemReset();
 	    } else {