comparison lcd.c @ 8:58d76cf522ff

Split out code into separate files.
author Daniel O'Connor <darius@dons.net.au>
date Sat, 04 Feb 2012 13:29:31 +1030
parents 9404b9869c27
children be0a1ac64d97
comparison
equal deleted inserted replaced
7:9404b9869c27 8:58d76cf522ff
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 <stdio.h>
59 #include <stdint.h>
59 #include "stm32f10x.h" 60 #include "stm32f10x.h"
60 #include "lcd.h" 61 #include "lcd.h"
61 62 #include "delay.h"
62 static void LCD_Doinit(void);
63 63
64 #define Bank1_LCD_C ((uint32_t)0x60000000) /* Register Address */ 64 #define Bank1_LCD_C ((uint32_t)0x60000000) /* Register Address */
65 #define Bank1_LCD_D ((uint32_t)0x60020000) /* Data Address */ 65 #define Bank1_LCD_D ((uint32_t)0x60020000) /* Data Address */
66 66
67 void 67 void
68 LCD_WR_Reg(uint16_t index, uint16_t val) { 68 lcd_wr_reg(uint16_t index, uint16_t val) {
69 *(__IO uint16_t *)(Bank1_LCD_C) = index; 69 *(__IO uint16_t *)(Bank1_LCD_C) = index;
70 *(__IO uint16_t *)(Bank1_LCD_D) = val; 70 *(__IO uint16_t *)(Bank1_LCD_D) = val;
71 } 71 }
72 72
73 uint16_t 73 uint16_t
74 LCD_RD_Reg(uint16_t index) { 74 lcd_rd_reg(uint16_t index) {
75 *(__IO uint16_t *)(Bank1_LCD_C) = index; 75 *(__IO uint16_t *)(Bank1_LCD_C) = index;
76 return(*(__IO uint16_t *)(Bank1_LCD_D)); 76 return(*(__IO uint16_t *)(Bank1_LCD_D));
77 } 77 }
78 78
79 uint16_t 79 uint16_t
80 LCD_RD_Data(int first) { 80 lcd_rd_data(int first) {
81 uint16_t a = 0; 81 uint16_t a = 0;
82 if (first) 82 if (first)
83 a = *(__IO uint16_t *) (Bank1_LCD_D); /* Dummy */ 83 a = *(__IO uint16_t *) (Bank1_LCD_D); /* Dummy */
84 a = *(__IO uint16_t *) (Bank1_LCD_D); /* Read */ 84 a = *(__IO uint16_t *) (Bank1_LCD_D); /* Read */
85 85
86 return (a); 86 return (a);
87 } 87 }
88 88
89 void 89 void
90 LCD_WR_StartData(uint16_t x, uint16_t y) { 90 lcd_wr_startdata(uint16_t x, uint16_t y) {
91 LCD_WR_Reg(0x20, x); 91 lcd_wr_reg(0x20, x);
92 LCD_WR_Reg(0x21, y); 92 lcd_wr_reg(0x21, y);
93 *(__IO uint16_t *)(Bank1_LCD_C) = 0x22; /* Start GRAM write */ 93 *(__IO uint16_t *)(Bank1_LCD_C) = 0x22; /* Start GRAM write */
94 } 94 }
95 95
96 void 96 void
97 LCD_WR_Data(uint16_t val) { 97 lcd_wr_data(uint16_t val) {
98 *(__IO uint16_t *)(Bank1_LCD_D) = val; 98 *(__IO uint16_t *)(Bank1_LCD_D) = val;
99 }
100
101 /* This is a bit rough and ready */
102 void
103 Delay(__IO uint32_t nCount) {
104 __IO uint32_t i;
105
106 for(; nCount != 0; nCount--)
107 for (i = 0; i < 3900; i++)
108 ;
109 }
110
111 uint8_t
112 SPI_WriteByte(uint8_t out) {
113 uint8_t in = 0;
114
115 /* Wait until the transmit buffer is empty */
116 while (SPI_I2S_GetFlagStatus(SPI1,SPI_I2S_FLAG_TXE) == RESET)
117 ;
118
119 /* Send the byte */
120 SPI_I2S_SendData(SPI1, out);
121
122 /* Wait until a data is received */
123 while (SPI_I2S_GetFlagStatus(SPI1,SPI_I2S_FLAG_RXNE) == RESET)
124 ;
125
126 /* Get the received data */
127 in = SPI_I2S_ReceiveData(SPI1);
128
129 /* Return the shifted data */
130 return (in);
131 }
132
133 #define TP_SELECT() GPIO_ResetBits(GPIOB, GPIO_Pin_7)
134 #define TP_DESELECT() GPIO_SetBits(GPIOB, GPIO_Pin_7)
135 uint16_t
136 TPRead(uint8_t type) {
137 uint16_t x = 0;
138
139 /* Select device */
140 TP_SELECT();
141
142 /* Do conversion */
143 Delay(10);
144 SPI_WriteByte(type);
145
146 /* Read result */
147 Delay(10);
148 x = SPI_WriteByte(0x00);
149 x <<= 8;
150 x |= SPI_WriteByte(0x00);
151 Delay(10);
152
153 /* De-select device */
154 TP_DESELECT();
155
156 /* Right justify 12 bit result */
157 x = x >> 3;
158 return (x);
159 }
160
161 #define FL_SELECT() GPIO_ResetBits(GPIOA, GPIO_Pin_4)
162 #define FL_DESELECT() GPIO_SetBits(GPIOA, GPIO_Pin_4)
163
164 #define FL_READ 0x03
165 #define FL_HSREAD 0x0b
166 #define FL_32KERASE 0x52
167 #define FL_64KERASE 0xd8
168 #define FL_CHIPERASE 0x60
169 #define FL_BYTEPROG 0x02
170 #define FL_AAIWP 0xad
171 #define FL_RDSR 0x05
172 #define FL_EWSR 0x50
173 #define FL_WRSR 0x01
174 #define FL_WREN 0x06
175 #define FL_WRDI 0x04
176 #define FL_RDID 0x90
177 #define FL_JEDECID 0x9f
178 #define FL_EBSY 0x70
179 #define FL_DBSY 0x80
180
181 uint16_t
182 FlashReadID(void) {
183 uint8_t fac, dev;
184
185 FL_SELECT(); /* Select device */
186
187 SPI_WriteByte(FL_RDID); /* Send command */
188 SPI_WriteByte(0x00); /* Send address cycles (ID data starts at 0) */
189 SPI_WriteByte(0x00);
190 SPI_WriteByte(0x00);
191 fac = SPI_WriteByte(0x00); /* Read ID */
192 dev = SPI_WriteByte(0x00);
193
194 FL_DESELECT(); /* De-select device */
195
196 return fac << 8 | dev;
197 }
198
199 uint8_t
200 FlashReadStatus(void) {
201 uint8_t status;
202
203 FL_SELECT(); /* Select device */
204
205 SPI_WriteByte(FL_RDSR); /* Send command */
206 SPI_WriteByte(0x00); /* Send dummy byte for address cycle */
207 status = SPI_WriteByte(0x00); /* Read status */
208
209 FL_DESELECT(); /* De-select device */
210
211 return status;
212 }
213
214 void
215 FlashWriteStatus(uint8_t status) {
216 /* Enable status write */
217 FL_SELECT(); /* Select device */
218 SPI_WriteByte(FL_EWSR); /* Send command */
219 SPI_WriteByte(0x00); /* Send data byte */
220 FL_DESELECT();
221
222 /* Actually write status */
223 FL_SELECT(); /* Re-select device for new command */
224 SPI_WriteByte(FL_WRSR); /* Send command */
225 SPI_WriteByte(status); /* Send data byte */
226 FL_DESELECT(); /* De-select device */
227 }
228
229 void
230 LCD_init(void) {
231 GPIO_InitTypeDef GPIO_InitStructure;
232 SPI_InitTypeDef SPI_InitStructure;
233 FSMC_NORSRAMInitTypeDef FSMC_NORSRAMInitStructure;
234 FSMC_NORSRAMTimingInitTypeDef p;
235 TIM_TimeBaseInitTypeDef TIM_TimeBaseStructure;
236
237 /* Enable FSMC clock */
238 RCC_AHBPeriphClockCmd(RCC_AHBPeriph_FSMC, ENABLE);
239
240 /* Enable alternate function IO clock */
241 RCC_APB2PeriphClockCmd(RCC_APB2Periph_AFIO, ENABLE);
242
243 /* Enable GPIOD clock */
244 RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOD, ENABLE);
245
246 /* Enable GPIOD clock */
247 RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOE, ENABLE);
248
249 /* Configures LCD Control lines (FSMC Pins) in alternate function Push-Pull mode.
250 *
251 * PD0(D2), PD1(D3), PD4(NOE), PD5(NWE), PD7(NE1/CS), PD8(D13), PD9(D14),
252 * PD10(D15), PD11(A16/RS) PD14(D0), PD15(D1)
253 */
254 GPIO_InitStructure.GPIO_Pin = (GPIO_Pin_0 | GPIO_Pin_1 | GPIO_Pin_4 | GPIO_Pin_5 | GPIO_Pin_7 |
255 GPIO_Pin_8 | GPIO_Pin_9 | GPIO_Pin_10 | GPIO_Pin_11 |
256 GPIO_Pin_14 | GPIO_Pin_15);
257 GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz;
258 GPIO_InitStructure.GPIO_Mode = GPIO_Mode_AF_PP;
259 GPIO_Init(GPIOD, &GPIO_InitStructure);
260
261 /* PE7(D4), PE8(D5), PE9(D6), PE10(D7), PE11(D8), PE12(D9), PE13(D10),
262 * PE14(D11), PE15(D12)
263 */
264 GPIO_InitStructure.GPIO_Pin = (GPIO_Pin_7 | GPIO_Pin_8 | GPIO_Pin_9 | GPIO_Pin_10 |
265 GPIO_Pin_11 | GPIO_Pin_12 | GPIO_Pin_13 | GPIO_Pin_14 |
266 GPIO_Pin_15);
267 GPIO_Init(GPIOE, &GPIO_InitStructure);
268
269 /* Configure backlight control (PD13/FSMC_A18 remapped to TIM4_CH2) */
270 /* Enable TIM4 clock */
271 RCC_APB1PeriphClockCmd(RCC_APB1Periph_TIM4, ENABLE);
272
273 /* Enable timer function
274 * Note source clock is SYSCLK / 2 = 36MHz
275 */
276 GPIO_InitStructure.GPIO_Pin = GPIO_Pin_13;
277 GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz;
278 GPIO_InitStructure.GPIO_Mode = GPIO_Mode_AF_PP;
279 GPIO_Init(GPIOD, &GPIO_InitStructure);
280
281 /* Remap TIM4_CH2 to PD13 */
282 GPIO_PinRemapConfig(GPIO_Remap_TIM4, ENABLE);
283
284 /* Reset TIM4 */
285 TIM_DeInit(TIM4);
286
287 /* Time Base configuration */
288 TIM_TimeBaseStructure.TIM_Period = 999;
289 TIM_TimeBaseStructure.TIM_Prescaler = 0;
290 TIM_TimeBaseStructure.TIM_ClockDivision = 0;
291 TIM_TimeBaseStructure.TIM_CounterMode = TIM_CounterMode_Down;
292
293 TIM_TimeBaseInit(TIM4, &TIM_TimeBaseStructure);
294
295 /* Init to full brightness */
296 lcd_setpwm(1000);
297
298 /* Enable timer */
299 TIM_OC2PreloadConfig(TIM4, TIM_OCPreload_Enable);
300 TIM_ARRPreloadConfig(TIM4, ENABLE);
301 TIM_Cmd(TIM4, ENABLE);
302
303 /* Configure reset pin (PE1) as GPIO out PP */
304 GPIO_InitStructure.GPIO_Pin = GPIO_Pin_1;
305 GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz;
306 GPIO_InitStructure.GPIO_Mode = GPIO_Mode_Out_PP;
307 GPIO_Init(GPIOE, &GPIO_InitStructure);
308
309 /* Configures the Parallel interface (FSMC) for LCD (Parallel mode) */
310 /* Timing configuration */
311 p.FSMC_AddressSetupTime = 5;
312 p.FSMC_AddressHoldTime = 5;
313 p.FSMC_DataSetupTime = 5;
314 p.FSMC_BusTurnAroundDuration = 0;
315 p.FSMC_CLKDivision = 0;
316 p.FSMC_DataLatency = 0;
317 p.FSMC_AccessMode = FSMC_AccessMode_A;
318
319 /* FSMC_Bank1_NORSRAM1 configured as follows:
320 - Data/Address MUX = Disable
321 - Memory Type = SRAM
322 - Data Width = 16bit
323 - Write Operation = Enable
324 - Extended Mode = Disable
325 - Asynchronous Wait = Disable */
326 FSMC_NORSRAMInitStructure.FSMC_Bank = FSMC_Bank1_NORSRAM1;
327 FSMC_NORSRAMInitStructure.FSMC_DataAddressMux = FSMC_DataAddressMux_Disable;
328 FSMC_NORSRAMInitStructure.FSMC_MemoryType = FSMC_MemoryType_SRAM;
329 FSMC_NORSRAMInitStructure.FSMC_MemoryDataWidth = FSMC_MemoryDataWidth_16b;
330 FSMC_NORSRAMInitStructure.FSMC_BurstAccessMode = FSMC_BurstAccessMode_Disable;
331 FSMC_NORSRAMInitStructure.FSMC_AsynchronousWait = FSMC_AsynchronousWait_Disable;
332 FSMC_NORSRAMInitStructure.FSMC_WaitSignalPolarity = FSMC_WaitSignalPolarity_Low;
333 FSMC_NORSRAMInitStructure.FSMC_WrapMode = FSMC_WrapMode_Disable;
334 FSMC_NORSRAMInitStructure.FSMC_WaitSignalActive = FSMC_WaitSignalActive_BeforeWaitState;
335 FSMC_NORSRAMInitStructure.FSMC_WriteOperation = FSMC_WriteOperation_Enable;
336 FSMC_NORSRAMInitStructure.FSMC_WaitSignal = FSMC_WaitSignal_Disable;
337 FSMC_NORSRAMInitStructure.FSMC_ExtendedMode = FSMC_ExtendedMode_Disable;
338 FSMC_NORSRAMInitStructure.FSMC_WriteBurst = FSMC_WriteBurst_Disable;
339 FSMC_NORSRAMInitStructure.FSMC_ReadWriteTimingStruct = &p;
340 FSMC_NORSRAMInitStructure.FSMC_WriteTimingStruct = &p;
341 FSMC_NORSRAMInit(&FSMC_NORSRAMInitStructure);
342
343 /* Enable FSMC_Bank1_NORSRAM1 */
344 FSMC_NORSRAMCmd(FSMC_Bank1_NORSRAM1, ENABLE);
345
346 /* Configure touch screen controller
347 *
348 * Connected to SPI1 which is shared with the AT45DB161D.
349 *
350 * The touch screen is selected with PB7.
351 * The flash chip is selected with PA4.
352 */
353
354 /* Enable SPI1 clock */
355 RCC_APB2PeriphClockCmd(RCC_APB2Periph_SPI1, ENABLE);
356
357 /* Configure MOSI, MISO and SCLK as alternate function PP */
358 GPIO_InitStructure.GPIO_Pin = GPIO_Pin_5 | GPIO_Pin_6 | GPIO_Pin_7;
359 GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz;
360 GPIO_InitStructure.GPIO_Mode = GPIO_Mode_AF_PP;
361 GPIO_Init(GPIOA, &GPIO_InitStructure);
362
363 /* Configure flash chip select pin (PA4) as GPIO out PP */
364 GPIO_InitStructure.GPIO_Pin = GPIO_Pin_4;
365 GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz;
366 GPIO_InitStructure.GPIO_Mode = GPIO_Mode_Out_PP;
367 GPIO_Init(GPIOA, &GPIO_InitStructure);
368
369 /* Configure touch chip select pin (PB7) as GPIO out PP */
370 GPIO_InitStructure.GPIO_Pin = GPIO_Pin_7;
371 GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz;
372 GPIO_InitStructure.GPIO_Mode = GPIO_Mode_Out_PP;
373 GPIO_Init(GPIOB, &GPIO_InitStructure);
374
375 /* De-select touch & flash */
376 GPIO_SetBits(GPIOA, GPIO_Pin_4);
377 GPIO_SetBits(GPIOB, GPIO_Pin_7);
378
379 /* SPI1 Config */
380 SPI_InitStructure.SPI_Direction = SPI_Direction_2Lines_FullDuplex;
381 SPI_InitStructure.SPI_Mode = SPI_Mode_Master;
382 SPI_InitStructure.SPI_DataSize = SPI_DataSize_8b;
383 SPI_InitStructure.SPI_CPOL = SPI_CPOL_Low;
384 SPI_InitStructure.SPI_CPHA = SPI_CPHA_1Edge;
385 SPI_InitStructure.SPI_NSS = SPI_NSS_Soft;
386 SPI_InitStructure.SPI_BaudRatePrescaler = SPI_BaudRatePrescaler_64;
387 SPI_InitStructure.SPI_FirstBit = SPI_FirstBit_MSB;
388 SPI_InitStructure.SPI_CRCPolynomial = 7;
389 SPI_Init(SPI1, &SPI_InitStructure);
390
391 /* SPI1 enable */
392 SPI_Cmd(SPI1, ENABLE);
393
394 LCD_Doinit();
395 } 99 }
396 100
397 void 101 void
398 lcd_setpwm(uint16_t val) { 102 lcd_setpwm(uint16_t val) {
399 TIM_OCInitTypeDef TIM_OCInitStructure; 103 TIM_OCInitTypeDef TIM_OCInitStructure;
406 110
407 TIM_OC2Init(TIM4, &TIM_OCInitStructure); 111 TIM_OC2Init(TIM4, &TIM_OCInitStructure);
408 112
409 } 113 }
410 114
411 static void 115 void
412 LCD_Doinit(void) { 116 lcd_init(void) {
413 uint16_t id; 117 uint16_t id;
414 118
415 /* Initialise LCD panel */ 119 /* Initialise LCD panel */
416 120
417 /* Pull reset pin low */ 121 /* Pull reset pin low */
418 Delay(1); 122 delay(1);
419 GPIO_ResetBits(GPIOE, GPIO_Pin_1); 123 GPIO_ResetBits(GPIOE, GPIO_Pin_1);
420 Delay(10); 124 delay(10);
421 GPIO_SetBits(GPIOE, GPIO_Pin_1); 125 GPIO_SetBits(GPIOE, GPIO_Pin_1);
422 Delay(50); 126 delay(50);
423 127
424 id = LCD_RD_Reg(0x00); 128 id = lcd_rd_reg(0x00);
425 if (id != 0x9325) { 129 if (id != 0x9325) {
426 printf("LCD ID doesn't match, expected 0x9325 got 0x%x\r\n", id); 130 printf("LCD ID doesn't match, expected 0x9325 got 0x%x\r\n", id);
427 return; 131 return;
428 } 132 }
429 printf("LCD ID matches\r\n"); 133 printf("LCD ID matches\r\n");
430 134
431 LCD_WR_Reg(0x00e3, 0x3008); /* Set internal timing (not documented) */ 135 lcd_wr_reg(0x00e3, 0x3008); /* Set internal timing (not documented) */
432 LCD_WR_Reg(0x00e7, 0x0012); /* Set internal timing (not documented) */ 136 lcd_wr_reg(0x00e7, 0x0012); /* Set internal timing (not documented) */
433 LCD_WR_Reg(0x00ef, 0x1231); /* Set internal timing (not documented) */ 137 lcd_wr_reg(0x00ef, 0x1231); /* Set internal timing (not documented) */
434 LCD_WR_Reg(0x0000, 0x0001); /* Start Oscillation */ 138 lcd_wr_reg(0x0000, 0x0001); /* Start Oscillation */
435 Delay(50); 139 delay(50);
436 LCD_WR_Reg(0x0001, 0x0100); /* set SS (S720 -> S1) */ 140 lcd_wr_reg(0x0001, 0x0100); /* set SS (S720 -> S1) */
437 LCD_WR_Reg(0x0002, 0x0700); /* set line inversion (B/C + EOR) */ 141 lcd_wr_reg(0x0002, 0x0700); /* set line inversion (B/C + EOR) */
438 LCD_WR_Reg(0x0004, 0x0000); /* no resizing */ 142 lcd_wr_reg(0x0004, 0x0000); /* no resizing */
439 LCD_WR_Reg(0x0008, 0x0202); /* set the back porch and front porch (2 lines each) */ 143 lcd_wr_reg(0x0008, 0x0202); /* set the back porch and front porch (2 lines each) */
440 LCD_WR_Reg(0x0009, 0x0000); /* set non-display area refresh cycle ISC[3:0] */ 144 lcd_wr_reg(0x0009, 0x0000); /* set non-display area refresh cycle ISC[3:0] */
441 LCD_WR_Reg(0x000a, 0x0000); /* FMARK function */ 145 lcd_wr_reg(0x000a, 0x0000); /* FMARK function */
442 146
443 LCD_WR_Reg(0x000c, 0x0000); /* RGB ctl - Internal clock, 18bit interface */ 147 lcd_wr_reg(0x000c, 0x0000); /* RGB ctl - Internal clock, 18bit interface */
444 LCD_WR_Reg(0x000d, 0x0000); /* Frame marker Position */ 148 lcd_wr_reg(0x000d, 0x0000); /* Frame marker Position */
445 LCD_WR_Reg(0x000f, 0x0000); /* RGB interface polarity */ 149 lcd_wr_reg(0x000f, 0x0000); /* RGB interface polarity */
446 150
447 /* Power On sequence */ 151 /* Power On sequence */
448 LCD_WR_Reg(0x0010, 0x0000); /* SAP, BT[3:0], AP, DSTB, SLP, STB */ 152 lcd_wr_reg(0x0010, 0x0000); /* SAP, BT[3:0], AP, DSTB, SLP, STB */
449 LCD_WR_Reg(0x0011, 0x0007); /* DC1[2:0], DC0[2:0], VC[2:0] */ 153 lcd_wr_reg(0x0011, 0x0007); /* DC1[2:0], DC0[2:0], VC[2:0] */
450 LCD_WR_Reg(0x0012, 0x0000); /* VREG1OUT voltage */ 154 lcd_wr_reg(0x0012, 0x0000); /* VREG1OUT voltage */
451 LCD_WR_Reg(0x0013, 0x0000); /* VDV[4:0] for VCOM amplitude */ 155 lcd_wr_reg(0x0013, 0x0000); /* VDV[4:0] for VCOM amplitude */
452 Delay(200); /* Dis-charge capacitor power voltage */ 156 delay(200); /* Dis-charge capacitor power voltage */
453 LCD_WR_Reg(0x0010, 0x1690); /* SAP, BT[3:0], AP, DSTB, SLP, STB */ 157 lcd_wr_reg(0x0010, 0x1690); /* SAP, BT[3:0], AP, DSTB, SLP, STB */
454 LCD_WR_Reg(0x0011, 0x0227); /* R11h = 0x0221 at VCI = 3.3V, DC1[2:0], DC0[2:0], VC[2:0] */ 158 lcd_wr_reg(0x0011, 0x0227); /* R11h = 0x0221 at VCI = 3.3V, DC1[2:0], DC0[2:0], VC[2:0] */
455 Delay(50); /* Delay 50ms */ 159 delay(50); /* delay 50ms */
456 LCD_WR_Reg(0x0012, 0x001c); /* External reference voltage= Vci; */ 160 lcd_wr_reg(0x0012, 0x001c); /* External reference voltage= Vci; */
457 Delay(50); /* Delay 50ms */ 161 delay(50); /* delay 50ms */
458 LCD_WR_Reg(0x0013, 0x1800); /* R13 = 1200 when R12 = 009D; VDV[4:0] for VCOM amplitude */ 162 lcd_wr_reg(0x0013, 0x1800); /* R13 = 1200 when R12 = 009D; VDV[4:0] for VCOM amplitude */
459 LCD_WR_Reg(0x0029, 0x001c); /* R29 = 000C when R12 = 009D; VCM[5:0] for VCOMH */ 163 lcd_wr_reg(0x0029, 0x001c); /* R29 = 000C when R12 = 009D; VCM[5:0] for VCOMH */
460 LCD_WR_Reg(0x002b, 0x000d); /* Frame Rate = 91Hz */ 164 lcd_wr_reg(0x002b, 0x000d); /* Frame Rate = 91Hz */
461 Delay(50); /* Delay 50ms */ 165 delay(50); /* delay 50ms */
462 166
463 /* Set GRAM area */ 167 /* Set GRAM area */
464 LCD_WR_Reg(0x0050, 0x0000); /* Horizontal GRAM Start Address */ 168 lcd_wr_reg(0x0050, 0x0000); /* Horizontal GRAM Start Address */
465 LCD_WR_Reg(0x0051, 0x00ef); /* Horizontal GRAM End Address */ 169 lcd_wr_reg(0x0051, 0x00ef); /* Horizontal GRAM End Address */
466 LCD_WR_Reg(0x0052, 0x0000); /* Vertical GRAM Start Address */ 170 lcd_wr_reg(0x0052, 0x0000); /* Vertical GRAM Start Address */
467 LCD_WR_Reg(0x0053, 0x013f); /* Vertical GRAM Start Address */ 171 lcd_wr_reg(0x0053, 0x013f); /* Vertical GRAM Start Address */
468 172
469 LCD_WR_Reg(0x0060, 0xa700); /* Gate Scan Line, drive G320 -> G1 */ 173 lcd_wr_reg(0x0060, 0xa700); /* Gate Scan Line, drive G320 -> G1 */
470 LCD_WR_Reg(0x0061, 0x0003); /* VLE & REV */ 174 lcd_wr_reg(0x0061, 0x0003); /* VLE & REV */
471 LCD_WR_Reg(0x006a, 0x0000); /* set scrolling line */ 175 lcd_wr_reg(0x006a, 0x0000); /* set scrolling line */
472 176
473 /* Partial Display Control */ 177 /* Partial Display Control */
474 LCD_WR_Reg(0x0080, 0x0000); /* Image 1 */ 178 lcd_wr_reg(0x0080, 0x0000); /* Image 1 */
475 LCD_WR_Reg(0x0081, 0x0000); 179 lcd_wr_reg(0x0081, 0x0000);
476 LCD_WR_Reg(0x0082, 0x0000); 180 lcd_wr_reg(0x0082, 0x0000);
477 LCD_WR_Reg(0x0083, 0x0000); /* Image 2 */ 181 lcd_wr_reg(0x0083, 0x0000); /* Image 2 */
478 LCD_WR_Reg(0x0084, 0x0000); 182 lcd_wr_reg(0x0084, 0x0000);
479 LCD_WR_Reg(0x0085, 0x0000); 183 lcd_wr_reg(0x0085, 0x0000);
480 184
481 /* Panel Control */ 185 /* Panel Control */
482 LCD_WR_Reg(0x0090, 0x0010); 186 lcd_wr_reg(0x0090, 0x0010);
483 LCD_WR_Reg(0x0092, 0x0000); 187 lcd_wr_reg(0x0092, 0x0000);
484 LCD_WR_Reg(0x0093, 0x0003); 188 lcd_wr_reg(0x0093, 0x0003);
485 LCD_WR_Reg(0x0095, 0x0110); 189 lcd_wr_reg(0x0095, 0x0110);
486 LCD_WR_Reg(0x0097, 0x0000); /* Undocumented */ 190 lcd_wr_reg(0x0097, 0x0000); /* Undocumented */
487 LCD_WR_Reg(0x0098, 0x0000); /* Undocumented */ 191 lcd_wr_reg(0x0098, 0x0000); /* Undocumented */
488 192
489 LCD_WR_Reg(0x0007, 0x0133); /* Display on, 262k colour mode (vs 8) */ 193 lcd_wr_reg(0x0007, 0x0133); /* Display on, 262k colour mode (vs 8) */
490 194
491 LCD_WR_Reg(0x0003, 0x1030); /* set GRAM write direction and enable BGR, 64K colours, 1 transfers/pixel. */ 195 lcd_wr_reg(0x0003, 0x1030); /* set GRAM write direction and enable BGR, 64K colours, 1 transfers/pixel. */
492 196
493 /* Adjust the Gamma Curve */ 197 /* Adjust the Gamma Curve */
494 LCD_WR_Reg(0x0030, 0x0006); 198 lcd_wr_reg(0x0030, 0x0006);
495 LCD_WR_Reg(0x0031, 0x0101); 199 lcd_wr_reg(0x0031, 0x0101);
496 LCD_WR_Reg(0x0032, 0x0003); 200 lcd_wr_reg(0x0032, 0x0003);
497 LCD_WR_Reg(0x0035, 0x0106); 201 lcd_wr_reg(0x0035, 0x0106);
498 LCD_WR_Reg(0x0036, 0x0b02); 202 lcd_wr_reg(0x0036, 0x0b02);
499 LCD_WR_Reg(0x0037, 0x0302); 203 lcd_wr_reg(0x0037, 0x0302);
500 LCD_WR_Reg(0x0038, 0x0707); 204 lcd_wr_reg(0x0038, 0x0707);
501 LCD_WR_Reg(0x0039, 0x0007); 205 lcd_wr_reg(0x0039, 0x0007);
502 LCD_WR_Reg(0x003c, 0x0600); 206 lcd_wr_reg(0x003c, 0x0600);
503 LCD_WR_Reg(0x003d, 0x020b); 207 lcd_wr_reg(0x003d, 0x020b);
504 208
505 fputs("Testing\r\n", stdout); 209 fputs("Testing\r\n", stdout);
506 LCD_WR_StartData(0, 0); 210 lcd_wr_startdata(0, 0);
507 LCD_WR_Data(0xa5a5); 211 lcd_wr_data(0xa5a5);
508 LCD_WR_Data(0x5a5a); 212 lcd_wr_data(0x5a5a);
509 LCD_WR_StartData(0, 0); 213 lcd_wr_startdata(0, 0);
510 if ((id = LCD_RD_Data(1)) != 0xa5a5) 214 if ((id = lcd_rd_data(1)) != 0xa5a5)
511 printf("Expected 0xa5a5 got 0x%04x\r\n", id); 215 printf("Expected 0xa5a5 got 0x%04x\r\n", id);
512 216
513 if ((id = LCD_RD_Data(0)) != 0x5a5a) 217 if ((id = lcd_rd_data(0)) != 0x5a5a)
514 printf("Expected 0x5a5a got 0x%04x\r\n", id); 218 printf("Expected 0x5a5a got 0x%04x\r\n", id);
515 219
516 fputs("Filling\r\n", stdout); 220 fputs("Filling\r\n", stdout);
517 /* Fill panel */ 221 /* Fill panel */
518 LCD_WR_StartData(0, 0); 222 lcd_wr_startdata(0, 0);
519
520 #define RGB24_565(R, G, B) (((((R) >> 3) & 0x1f) << 11) | ((((G) >> 2) & 0x3f) << 5) | (((B) >> 3) & 0x1f))
521 223
522 for (int x = 0; x < 320; x++) { 224 for (int x = 0; x < 320; x++) {
523 for (int y = 0; y < 240; y++) { 225 for (int y = 0; y < 240; y++) {
524 if (((x / 5) % 3) == 0) 226 if (((x / 5) % 3) == 0)
525 LCD_WR_Data(RGB24_565(255, 0, 0)); 227 lcd_wr_data(LCD_RED);
526 else if (((x / 5) % 3) == 1) 228 else if (((x / 5) % 3) == 1)
527 LCD_WR_Data(RGB24_565(0, 255, 0)); 229 lcd_wr_data(LCD_GREEN);
528 else 230 else
529 LCD_WR_Data(RGB24_565(0, 0, 255)); 231 lcd_wr_data(LCD_BLUE);
530 } 232 }
531 } 233 }
532 234
533 } 235 lcd_circle(50, 50, 20, LCD_BLACK);
534 236
237 }
238
239 void
240 lcd_pixel(uint16_t x, uint16_t y, uint16_t colour) {
241 if (x > LCD_HEIGHT || y > LCD_WIDTH)
242 return;
243
244 lcd_wr_startdata(x, y);
245 lcd_wr_data(colour);
246 }
247
248 /*
249 * Draw a circle
250 * From http://en.wikipedia.org/wiki/Midpoint_circle_algorithm
251 */
252 void
253 lcd_circle(uint16_t x0, uint16_t y0, uint16_t radius, uint16_t colour) {
254 int16_t f;
255 uint16_t ddF_x, ddF_y, x, y;
256
257 f = 1 - radius;
258 ddF_x = 1;
259 ddF_y = -2 * radius;
260 x = 0;
261 y = radius;
262
263 lcd_pixel(x0, y0 + radius, colour);
264 lcd_pixel(x0, y0 - radius, colour);
265 lcd_pixel(x0 + radius, y0, colour);
266 lcd_pixel(x0 - radius, y0, colour);
267
268 while(x < y) {
269 // ddF_x == 2 * x + 1;
270 // ddF_y == -2 * y;
271 // f == x*x + y*y - radius*radius + 2*x - y + 1;
272 if(f >= 0) {
273 y--;
274 ddF_y += 2;
275 f += ddF_y;
276 }
277 x++;
278 ddF_x += 2;
279 f += ddF_x;
280 lcd_pixel(x0 + x, y0 + y, colour);
281 lcd_pixel(x0 - x, y0 + y, colour);
282 lcd_pixel(x0 + x, y0 - y, colour);
283 lcd_pixel(x0 - x, y0 - y, colour);
284 lcd_pixel(x0 + y, y0 + x, colour);
285 lcd_pixel(x0 - y, y0 + x, colour);
286 lcd_pixel(x0 + y, y0 - x, colour);
287 lcd_pixel(x0 - y, y0 - x, colour);
288 }
289 }
290
291
292 /*
293 * Draw a line
294 * From http://en.wikipedia.org/wiki/Bresenham%27s_line_algorithm
295 */
296 void
297 lcd_line(uint16_t x0, uint16_t y0, uint16_t x1, uint16_t y1, uint16_t colour) {
298 uint16_t dx, dy, d, x, y;
299
300 dx = x1 - x0;
301 dy = y1 - y0;
302
303 d = 2 * dy - dx;
304 lcd_pixel(x0, y0, colour);
305 y = y0;
306
307 for (x = x0 + 1; x <= x1; x++) {
308 if (d > 0) {
309 y++;
310 lcd_pixel(x, y, colour);
311 d += 2 * dy - 2 * dx;
312 } else {
313 lcd_pixel(x, y, colour);
314 d += 2 * dy;
315 }
316 }
317 }