comparison lcd.c @ 4:2c87e30c982d

Add LCD init, touch screen writing etc.. PWM of LCD backlight doesn't work yet though..
author Daniel O'Connor <darius@dons.net.au>
date Tue, 03 Jan 2012 22:37:18 +1030
parents 74e9b3baac1e
children efa2c22266e3
comparison
equal deleted inserted replaced
3:74e9b3baac1e 4:2c87e30c982d
53 38 LCD_PWM PD13/TIM4_CH2 53 38 LCD_PWM PD13/TIM4_CH2
54 39 NC 54 39 NC
55 40 D15 PD10/FSMC_D15 55 40 D15 PD10/FSMC_D15
56 */ 56 */
57 57
58 #include <stdio.h>
58 #include "stm32f10x.h" 59 #include "stm32f10x.h"
59 #include "lcd.h" 60 #include "lcd.h"
61
62 #define Bank1_LCD_C ((uint32_t)0x60000000) /* Register Address */
63 #define Bank1_LCD_D ((uint32_t)0x60020000) /* Data Address */
64
65 unsigned long colour1 = 0;
66
67 void
68 LCD_WR_Reg(uint16_t index, uint16_t val) {
69 *(__IO uint16_t *)(Bank1_LCD_C) = index;
70 *(__IO uint16_t *)(Bank1_LCD_D) = val;
71 }
72
73 uint16_t
74 LCD_RD_Reg(uint16_t index) {
75 *(__IO uint16_t *)(Bank1_LCD_C) = index;
76 return(*(__IO uint16_t *)(Bank1_LCD_D));
77 }
78
79 uint16_t
80 LCD_RD_Data(int first) {
81 uint16_t a = 0;
82 if (first)
83 a = *(__IO uint16_t *) (Bank1_LCD_D); /* Dummy */
84 a = *(__IO uint16_t *) (Bank1_LCD_D); /* Read */
85
86 return (a);
87 }
88
89 void
90 LCD_WR_Data(uint16_t val) {
91 *(__IO uint16_t *)(Bank1_LCD_D) = val;
92 }
93
94 /* Callers imply this is in milliseconds but that seems unlikely */
95 void
96 Delay(__IO uint32_t nCount) {
97 for(; nCount != 0; nCount--)
98 ;
99 }
100
101 uint8_t
102 SPI_WriteByte(uint8_t out) {
103 uint8_t in = 0;
104
105 /* Wait until the transmit buffer is empty */
106 while (SPI_I2S_GetFlagStatus(SPI1,SPI_I2S_FLAG_TXE) == RESET)
107 ;
108
109 /* Send the byte */
110 SPI_I2S_SendData(SPI1, out);
111
112 /* Wait until a data is received */
113 while (SPI_I2S_GetFlagStatus(SPI1,SPI_I2S_FLAG_RXNE) == RESET)
114 ;
115
116 /* Get the received data */
117 in = SPI_I2S_ReceiveData(SPI1);
118
119 /* Return the shifted data */
120 return (in);
121 }
122
123 #define TP_SELECT() GPIO_ResetBits(GPIOB, GPIO_Pin_7)
124 #define TP_DESELECT() GPIO_SetBits(GPIOB, GPIO_Pin_7)
125 uint16_t
126 TPRead(uint8_t type) {
127 uint16_t x = 0;
128
129 /* Select device */
130 TP_SELECT();
131
132 /* Do conversion */
133 Delay(10);
134 SPI_WriteByte(type);
135
136 /* Read result */
137 Delay(10);
138 x = SPI_WriteByte(0x00);
139 x <<= 8;
140 x |= SPI_WriteByte(0x00);
141 Delay(10);
142
143 /* De-select device */
144 TP_DESELECT();
145
146 /* Right justify 12 bit result */
147 x = x >> 3;
148 return (x);
149 }
150
151 #define FL_SELECT() GPIO_ResetBits(GPIOA, GPIO_Pin_4)
152 #define FL_DESELECT() GPIO_SetBits(GPIOA, GPIO_Pin_4)
153
154 #define FL_READ 0x03
155 #define FL_HSREAD 0x0b
156 #define FL_32KERASE 0x52
157 #define FL_64KERASE 0xd8
158 #define FL_CHIPERASE 0x60
159 #define FL_BYTEPROG 0x02
160 #define FL_AAIWP 0xad
161 #define FL_RDSR 0x05
162 #define FL_EWSR 0x50
163 #define FL_WRSR 0x01
164 #define FL_WREN 0x06
165 #define FL_WRDI 0x04
166 #define FL_RDID 0x90
167 #define FL_JEDECID 0x9f
168 #define FL_EBSY 0x70
169 #define FL_DBSY 0x80
170
171 uint16_t
172 FlashReadID(void) {
173 uint8_t fac, dev;
174
175 FL_SELECT(); /* Select device */
176
177 SPI_WriteByte(FL_RDID); /* Send command */
178 SPI_WriteByte(0x00); /* Send address cycles (ID data starts at 0) */
179 SPI_WriteByte(0x00);
180 SPI_WriteByte(0x00);
181 fac = SPI_WriteByte(0x00); /* Read ID */
182 dev = SPI_WriteByte(0x00);
183
184 FL_DESELECT(); /* De-select device */
185
186 return fac << 8 | dev;
187 }
188
189 uint8_t
190 FlashReadStatus(void) {
191 uint8_t status;
192
193 FL_SELECT(); /* Select device */
194
195 SPI_WriteByte(FL_RDSR); /* Send command */
196 SPI_WriteByte(0x00); /* Send dummy byte for address cycle */
197 status = SPI_WriteByte(0x00); /* Read status */
198
199 FL_DESELECT(); /* De-select device */
200
201 return status;
202 }
203
204 void
205 FlashWriteStatus(uint8_t status) {
206 /* Enable status write */
207 FL_SELECT(); /* Select device */
208 SPI_WriteByte(FL_EWSR); /* Send command */
209 SPI_WriteByte(0x00); /* Send data byte */
210 FL_DESELECT();
211
212 /* Actually write status */
213 FL_SELECT(); /* Re-select device for new command */
214 SPI_WriteByte(FL_WRSR); /* Send command */
215 SPI_WriteByte(status); /* Send data byte */
216 FL_DESELECT(); /* De-select device */
217 }
60 218
61 void 219 void
62 LCD_init(void) { 220 LCD_init(void) {
63 GPIO_InitTypeDef GPIO_InitStructure; 221 GPIO_InitTypeDef GPIO_InitStructure;
222 SPI_InitTypeDef SPI_InitStructure;
64 FSMC_NORSRAMInitTypeDef FSMC_NORSRAMInitStructure; 223 FSMC_NORSRAMInitTypeDef FSMC_NORSRAMInitStructure;
65 FSMC_NORSRAMTimingInitTypeDef p; 224 FSMC_NORSRAMTimingInitTypeDef p;
225 #if 0
226 TIM_TimeBaseInitTypeDef TIM_TimeBaseStructure;
227 TIM_OCInitTypeDef TIM_OCInitStructure;
228 TIM_BDTRInitTypeDef TIM_BDTRInitStructure;
229 #endif
230 uint16_t id;
231
232 /* Enable FSMC clock */
233 RCC_AHBPeriphClockCmd(RCC_AHBPeriph_FSMC, ENABLE);
234
235 /* Enable GPIOD clock */
236 RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOD, ENABLE);
66 237
67 /* Configures LCD Control lines (FSMC Pins) in alternate function Push-Pull mode. 238 /* Configures LCD Control lines (FSMC Pins) in alternate function Push-Pull mode.
68 * 239 *
69 * PD0(D2), PD1(D3), PD4(NOE), PD5(NWE), PD7(NE1/CS), PD8(D13), PD9(D14), 240 * PD0(D2), PD1(D3), PD4(NOE), PD5(NWE), PD7(NE1/CS), PD8(D13), PD9(D14),
70 * PD10(D15), PD11(A16/RS) PD14(D0), PD15(D1) 241 * PD10(D15), PD11(A16/RS) PD14(D0), PD15(D1)
78 /* PE7(D4), PE8(D5), PE9(D6), PE10(D7), PE11(D8), PE12(D9), PE13(D10), 249 /* PE7(D4), PE8(D5), PE9(D6), PE10(D7), PE11(D8), PE12(D9), PE13(D10),
79 * PE14(D11), PE15(D12) 250 * PE14(D11), PE15(D12)
80 */ 251 */
81 GPIO_InitStructure.GPIO_Pin = GPIO_Pin_7 | GPIO_Pin_8 | GPIO_Pin_9 | GPIO_Pin_10 | 252 GPIO_InitStructure.GPIO_Pin = GPIO_Pin_7 | GPIO_Pin_8 | GPIO_Pin_9 | GPIO_Pin_10 |
82 GPIO_Pin_11 | GPIO_Pin_12 | GPIO_Pin_13 | GPIO_Pin_14 | GPIO_Pin_15; 253 GPIO_Pin_11 | GPIO_Pin_12 | GPIO_Pin_13 | GPIO_Pin_14 | GPIO_Pin_15;
254 GPIO_Init(GPIOE, &GPIO_InitStructure);
255
256 /* Configure backlight control (PD13/FSMC_A18 remapped to TIM4_CH2) */
257 #if 0
258 /* Enable TIM4 clock */
259 RCC_APB1PeriphClockCmd(RCC_APB1Periph_TIM4, ENABLE);
260
261 /* Enable timer function */
262 GPIO_InitStructure.GPIO_Pin = GPIO_Pin_13;
263 GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz;
264 GPIO_InitStructure.GPIO_Mode = GPIO_Mode_AF_PP;
265 GPIO_Init(GPIOD, &GPIO_InitStructure);
266
267 /* Remap TIM4_CH2 to PD13 */
268 GPIO_PinRemapConfig(GPIO_Remap_TIM4, ENABLE);
269
270 /* Reset TIM4 */
271 TIM_DeInit(TIM4);
272
273 /* Time Base configuration */
274 TIM_TimeBaseStructure.TIM_Prescaler = 0x00;
275 TIM_TimeBaseStructure.TIM_CounterMode = TIM_CounterMode_Up;
276 TIM_TimeBaseStructure.TIM_Period = 0x8000;
277 TIM_TimeBaseStructure.TIM_ClockDivision = 0x0;
278 TIM_TimeBaseStructure.TIM_RepetitionCounter = 0x0;
279 TIM_TimeBaseInit(TIM4 ,&TIM_TimeBaseStructure);
280
281 /* Channel 1, 2, 3 and 4 Configuration in PWM mode */
282 TIM_OCInitStructure.TIM_OCMode = TIM_OCMode_PWM2;
283 TIM_OCInitStructure.TIM_OutputState = TIM_OutputState_Enable;
284 TIM_OCInitStructure.TIM_Pulse = 0;
285 TIM_OCInitStructure.TIM_OCPolarity = TIM_OCPolarity_Low;
286 TIM_OCInitStructure.TIM_OCNPolarity = TIM_OCNPolarity_Low;
287 TIM_OCInitStructure.TIM_OCIdleState = TIM_OCIdleState_Set;
288 TIM_OCInitStructure.TIM_OCNIdleState = TIM_OCIdleState_Reset;
289 TIM_OC2Init(TIM4, &TIM_OCInitStructure);
290
291 /* Automatic Output enable, Break, dead time and lock configuration*/
292 TIM_BDTRInitStructure.TIM_OSSRState = TIM_OSSRState_Enable;
293 TIM_BDTRInitStructure.TIM_OSSIState = TIM_OSSIState_Enable;
294 TIM_BDTRInitStructure.TIM_LOCKLevel = TIM_LOCKLevel_1;
295 TIM_BDTRInitStructure.TIM_DeadTime = 0x75;
296 TIM_BDTRInitStructure.TIM_Break = TIM_Break_Enable;
297 TIM_BDTRInitStructure.TIM_BreakPolarity = TIM_BreakPolarity_High;
298 TIM_BDTRInitStructure.TIM_AutomaticOutput = TIM_AutomaticOutput_Enable;
299
300 TIM_BDTRConfig(TIM4, &TIM_BDTRInitStructure);
301
302 /* TIM1 counter enable */
303 TIM_Cmd(TIM4,ENABLE);
304 #else
305 GPIO_InitStructure.GPIO_Pin = GPIO_Pin_13;
306 GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz;
307 GPIO_InitStructure.GPIO_Mode = GPIO_Mode_Out_PP;
308 GPIO_Init(GPIOD, &GPIO_InitStructure);
309
310 GPIO_SetBits(GPIOD, GPIO_Pin_13);
311 #endif
312
313 /* Configure reset pin (PE1) as GPIO out PP */
314 GPIO_InitStructure.GPIO_Pin = GPIO_Pin_1;
315 GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz;
316 GPIO_InitStructure.GPIO_Mode = GPIO_Mode_Out_PP;
83 GPIO_Init(GPIOE, &GPIO_InitStructure); 317 GPIO_Init(GPIOE, &GPIO_InitStructure);
84 318
85 /* Configures the Parallel interface (FSMC) for LCD (Parallel mode) */ 319 /* Configures the Parallel interface (FSMC) for LCD (Parallel mode) */
86 /* FSMC_Bank1_NORSRAM4 timing configuration */ 320 /* FSMC_Bank1_NORSRAM4 timing configuration */
87 p.FSMC_AddressSetupTime = 1; 321 p.FSMC_AddressSetupTime = 1;
117 351
118 FSMC_NORSRAMInit(&FSMC_NORSRAMInitStructure); 352 FSMC_NORSRAMInit(&FSMC_NORSRAMInitStructure);
119 353
120 /* Enable FSMC_Bank1_NORSRAM4 */ 354 /* Enable FSMC_Bank1_NORSRAM4 */
121 FSMC_NORSRAMCmd(FSMC_Bank1_NORSRAM4, ENABLE); 355 FSMC_NORSRAMCmd(FSMC_Bank1_NORSRAM4, ENABLE);
122 } 356
357 /* Initialise LCD panel */
358
359 /* Pull reset pin low */
360 GPIO_ResetBits(GPIOE, GPIO_Pin_1);
361 Delay(0xafff);
362 GPIO_SetBits(GPIOE, GPIO_Pin_1);
363 Delay(0xafff);
364
365 id = LCD_RD_Reg(0x00);
366 if (id != 0x9325) {
367 printf("LCD ID doesn't match, expected 0x9325 got 0x%x\r\n", id);
368 return;
369 }
370
371 LCD_WR_Reg(0x00e3, 0x3008); /* Set internal timing */
372 LCD_WR_Reg(0x00e7, 0x0012); /* Set internal timing */
373 LCD_WR_Reg(0x00ef, 0x1231); /* Set internal timing */
374 LCD_WR_Reg(0x0000, 0x0001); /* Start Oscillation */
375 LCD_WR_Reg(0x0001, 0x0100); /* set SS and SM bit */
376 LCD_WR_Reg(0x0002, 0x0700); /* set 1 line inversion */
377
378 LCD_WR_Reg(0x0003, 0x1030); /* set GRAM write direction and BGR = 0, 262K colours, 1 transfers/pixel. */
379 LCD_WR_Reg(0x0004, 0x0000); /* Resize register */
380 LCD_WR_Reg(0x0008, 0x0202); /* set the back porch and front porch */
381 LCD_WR_Reg(0x0009, 0x0000); /* set non-display area refresh cycle ISC[3:0] */
382 LCD_WR_Reg(0x000a, 0x0000); /* FMARK function */
383 LCD_WR_Reg(0x000c, 0x0000); /* RGB interface setting */
384 LCD_WR_Reg(0x000d, 0x0000); /* Frame marker Position */
385 LCD_WR_Reg(0x000f, 0x0000); /* RGB interface polarity */
386
387 /* Power On sequence */
388 LCD_WR_Reg(0x0010, 0x0000); /* SAP, BT[3:0], AP, DSTB, SLP, STB */
389 LCD_WR_Reg(0x0011, 0x0007); /* DC1[2:0], DC0[2:0], VC[2:0] */
390 LCD_WR_Reg(0x0012, 0x0000); /* VREG1OUT voltage */
391 LCD_WR_Reg(0x0013, 0x0000); /* VDV[4:0] for VCOM amplitude */
392 Delay(200); /* Dis-charge capacitor power voltage */
393 LCD_WR_Reg(0x0010, 0x1690); /* SAP, BT[3:0], AP, DSTB, SLP, STB */
394 LCD_WR_Reg(0x0011, 0x0227); /* R11h = 0x0221 at VCI = 3.3V, DC1[2:0], DC0[2:0], VC[2:0] */
395 Delay(50); /* Delay 50ms */
396 LCD_WR_Reg(0x0012, 0x001c); /* External reference voltage= Vci; */
397 Delay(50); /* Delay 50ms */
398 LCD_WR_Reg(0x0013, 0x1800); /* R13 = 1200 when R12 = 009D; VDV[4:0] for VCOM amplitude */
399 LCD_WR_Reg(0x0029, 0x001c); /* R29 = 000C when R12 = 009D; VCM[5:0] for VCOMH */
400 LCD_WR_Reg(0x002b, 0x000d); /* Frame Rate = 91Hz */
401 Delay(50); /* Delay 50ms */
402 LCD_WR_Reg(0x0020, 0x0000); /* GRAM horizontal Address */
403 LCD_WR_Reg(0x0021, 0x0000); /* GRAM Vertical Address */
404
405 /* Adjust the Gamma Curve */
406 LCD_WR_Reg(0x0030, 0x0007);
407 LCD_WR_Reg(0x0031, 0x0302);
408 LCD_WR_Reg(0x0032, 0x0105);
409 LCD_WR_Reg(0x0035, 0x0206);
410 LCD_WR_Reg(0x0036, 0x0808);
411 LCD_WR_Reg(0x0037, 0x0206);
412 LCD_WR_Reg(0x0038, 0x0504);
413 LCD_WR_Reg(0x0039, 0x0007);
414 LCD_WR_Reg(0x003c, 0x0105);
415 LCD_WR_Reg(0x003d, 0x0808);
416
417 /* Set GRAM area */
418 LCD_WR_Reg(0x0050, 0x0000); /* Horizontal GRAM Start Address */
419 LCD_WR_Reg(0x0051, 0x00ef); /* Horizontal GRAM End Address */
420 LCD_WR_Reg(0x0052, 0x0000); /* Vertical GRAM Start Address */
421 LCD_WR_Reg(0x0053, 0x013f); /* Vertical GRAM Start Address */
422 LCD_WR_Reg(0x0060, 0xa700); /* Gate Scan Line */
423 LCD_WR_Reg(0x0061, 0x0001); /* NDL,VLE, REV */
424 LCD_WR_Reg(0x006a, 0x0000); /* set scrolling line */
425
426 /* Partial Display Control */
427 LCD_WR_Reg(0x0080, 0x0000);
428 LCD_WR_Reg(0x0081, 0x0000);
429 LCD_WR_Reg(0x0082, 0x0000);
430 LCD_WR_Reg(0x0083, 0x0000);
431 LCD_WR_Reg(0x0084, 0x0000);
432 LCD_WR_Reg(0x0085, 0x0000);
433
434 /* Panel Control */
435 LCD_WR_Reg(0x0090, 0x0010);
436 LCD_WR_Reg(0x0092, 0x0000);
437 LCD_WR_Reg(0x0093, 0x0003);
438 LCD_WR_Reg(0x0095, 0x0110);
439 LCD_WR_Reg(0x0097, 0x0000);
440 LCD_WR_Reg(0x0098, 0x0000);
441 LCD_WR_Reg(0x0007, 0x0133); /* 262K colour and display ON */
442
443 /* Fill panel with white */
444 LCD_WR_Reg(0x20, 0);
445 LCD_WR_Reg(0x21, 0x013f);
446 *(__IO uint16_t *)(Bank1_LCD_C) = 34;
447 for (colour1 = 0; colour1 < 76800; colour1++) {
448 LCD_WR_Data(0xffff);
449 }
450 colour1 = 0;
451
452 /* Configure touch screen controller
453 *
454 * Connected to SPI1 which is shared with the AT45DB161D.
455 *
456 * The touch screen is selected with PB7.
457 * The flash chip is selected with PA4.
458 */
459
460 /* Enable SPI1 clock */
461 RCC_APB2PeriphClockCmd(RCC_APB2Periph_SPI1, ENABLE);
462
463 /* Configure MOSI, MISO and SCLK as alternate function PP */
464 GPIO_InitStructure.GPIO_Pin = GPIO_Pin_5 | GPIO_Pin_6 | GPIO_Pin_7;
465 GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz;
466 GPIO_InitStructure.GPIO_Mode = GPIO_Mode_AF_PP;
467 GPIO_Init(GPIOA, &GPIO_InitStructure);
468
469 /* Configure flash chip select pin (PA4) as GPIO out PP */
470 GPIO_InitStructure.GPIO_Pin = GPIO_Pin_4;
471 GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz;
472 GPIO_InitStructure.GPIO_Mode = GPIO_Mode_Out_PP;
473 GPIO_Init(GPIOA, &GPIO_InitStructure);
474
475 /* Configure touch chip select pin (PB7) as GPIO out PP */
476 GPIO_InitStructure.GPIO_Pin = GPIO_Pin_7;
477 GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz;
478 GPIO_InitStructure.GPIO_Mode = GPIO_Mode_Out_PP;
479 GPIO_Init(GPIOB, &GPIO_InitStructure);
480
481 /* De-select touch & flash */
482 GPIO_SetBits(GPIOA, GPIO_Pin_4);
483 GPIO_SetBits(GPIOB, GPIO_Pin_7);
484
485 /* SPI1 Config */
486 SPI_InitStructure.SPI_Direction = SPI_Direction_2Lines_FullDuplex;
487 SPI_InitStructure.SPI_Mode = SPI_Mode_Master;
488 SPI_InitStructure.SPI_DataSize = SPI_DataSize_8b;
489 SPI_InitStructure.SPI_CPOL = SPI_CPOL_Low;
490 SPI_InitStructure.SPI_CPHA = SPI_CPHA_1Edge;
491 SPI_InitStructure.SPI_NSS = SPI_NSS_Soft;
492 SPI_InitStructure.SPI_BaudRatePrescaler = SPI_BaudRatePrescaler_64;
493 SPI_InitStructure.SPI_FirstBit = SPI_FirstBit_MSB;
494 SPI_InitStructure.SPI_CRCPolynomial = 7;
495 SPI_Init(SPI1, &SPI_InitStructure);
496
497 /* SPI1 enable */
498 SPI_Cmd(SPI1, ENABLE);
499
500 }