Mercurial > ~darius > hgwebdir.cgi > stm32temp
view lcd.c @ 62:bb52e6dad784
The LCD works better when the GPIO clocks are enabled before frobbing them.
PWM doesn't work for some reason, just hard on for now.
author | Daniel O'Connor <darius@dons.net.au> |
---|---|
date | Tue, 09 Apr 2013 00:28:29 +0930 |
parents | be0a1ac64d97 |
children | ff29436c0224 |
line wrap: on
line source
/* * Example code (I think) * ~/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 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 1 VCC 2 TC_SCK PA5/SPI1_SCK 3 GND 4 TC_CS PB7/SPI1_CS3 5 RST PE1 FSMC_NBL1? (unlikely) 6 TC_DIN PA7/SPI1_MOSI 7 nOE PD4/FSMC_nOE 8 TC_DOUT PA6/SPI1_MISO 9 nWR PD5/FSMC_nWE 10 TC_INT PB6 11 CS PD7/FSMC_NE1/FSMC_NCE2 12 NC 13 RS PD11/FSMC_A16 14 NC 15 D7 PE10/FSMC_D7 16 NC 17 D6 PE9/FSMC_D6 18 NC 19 D3 PD1/FSMC_D3 20 D13 PD8/FSMC_D13 21 D5 PE8/FSMC_D5 22 D12 PE15/FSMC_D12 23 D4 PE7/FSMC_D4 24 GND 25 NC 26 D11 PE14/FSMC_D11 27 D2 PD0/FSMC_D2 28 D10 PE13/FSMC_D10 29 D1 PD15/FSMC_D1 30 D9 PE12/FSMC_D9 31 D0 PD14/FSMC_D0 32 D14 PD9/FSMC_D14 33 NC 34 D8 PE11/FSMC_D8 35 NC 36 NC 37 NC 38 LCD_PWM PD13/TIM4_CH2 39 NC 40 D15 PD10/FSMC_D15 */ #include <stdio.h> #include <stdint.h> #include <stdlib.h> #include <ctype.h> #include "stm32f10x.h" #include "lcd.h" #include "delay.h" #define Bank1_LCD_C ((uint32_t)0x60000000) /* Register Address */ #define Bank1_LCD_D ((uint32_t)0x60020000) /* Data Address */ #define COLINCVAL 7968 /* 255.0 / 320.0 * 10000 */ void colinc(uint16_t *mag, uint16_t *err, uint16_t amt, uint16_t max) { *err += amt; if (*err > max) { (*mag) = (*mag) + 1; (*err) = (*err) - max; } } void lcd_writereg(uint16_t index, uint16_t val) { *(__IO uint16_t *)(Bank1_LCD_C) = index; *(__IO uint16_t *)(Bank1_LCD_D) = val; } uint16_t lcd_readreg(uint16_t index) { *(__IO uint16_t *)(Bank1_LCD_C) = index; return(*(__IO uint16_t *)(Bank1_LCD_D)); } uint16_t lcd_readdata(int first) { uint16_t a = 0; if (first) a = *(__IO uint16_t *) (Bank1_LCD_D); /* Dummy */ a = *(__IO uint16_t *) (Bank1_LCD_D); /* Read */ return (a); } void lcd_startgram(uint16_t x, uint16_t y) { lcd_writereg(0x20, x); lcd_writereg(0x21, y); *(__IO uint16_t *)(Bank1_LCD_C) = 0x22; /* Start GRAM write */ } void lcd_writedata(uint16_t val) { *(__IO uint16_t *)(Bank1_LCD_D) = val; } void lcd_setpwm(uint16_t val) { TIM_OCInitTypeDef TIM_OCInitStructure; /* Channel 2 configuration in PWM mode */ TIM_OCInitStructure.TIM_OCMode = TIM_OCMode_PWM1; TIM_OCInitStructure.TIM_OutputState = TIM_OutputState_Enable; TIM_OCInitStructure.TIM_Pulse = val; TIM_OCInitStructure.TIM_OCPolarity = TIM_OCPolarity_High; TIM_OC2Init(TIM4, &TIM_OCInitStructure); } void lcd_init(void) { uint16_t id, x, y; /* Initialise LCD panel */ /* Pull reset pin low */ delay(10); GPIO_ResetBits(GPIOE, GPIO_Pin_1); delay(500); GPIO_SetBits(GPIOE, GPIO_Pin_1); delay(500); id = lcd_readreg(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_writereg(0x00e3, 0x3008); /* Set internal timing (not documented) */ lcd_writereg(0x00e7, 0x0012); /* Set internal timing (not documented) */ lcd_writereg(0x00ef, 0x1231); /* Set internal timing (not documented) */ lcd_writereg(0x0000, 0x0001); /* Start Oscillation */ delay(50); lcd_writereg(0x0001, 0x0100); /* set SS (S720 -> S1) */ lcd_writereg(0x0002, 0x0700); /* set line inversion (B/C + EOR) */ lcd_writereg(0x0004, 0x0000); /* no resizing */ lcd_writereg(0x0008, 0x0202); /* set the back porch and front porch (2 lines each) */ lcd_writereg(0x0009, 0x0000); /* set non-display area refresh cycle ISC[3:0] */ lcd_writereg(0x000a, 0x0000); /* FMARK function */ lcd_writereg(0x000c, 0x0000); /* RGB ctl - Internal clock, 18bit interface */ lcd_writereg(0x000d, 0x0000); /* Frame marker Position */ lcd_writereg(0x000f, 0x0000); /* RGB interface polarity */ /* Power On sequence */ lcd_writereg(0x0010, 0x0000); /* SAP, BT[3:0], AP, DSTB, SLP, STB */ lcd_writereg(0x0011, 0x0007); /* DC1[2:0], DC0[2:0], VC[2:0] */ lcd_writereg(0x0012, 0x0000); /* VREG1OUT voltage */ lcd_writereg(0x0013, 0x0000); /* VDV[4:0] for VCOM amplitude */ delay(200); /* Dis-charge capacitor power voltage */ lcd_writereg(0x0010, 0x1690); /* SAP, BT[3:0], AP, DSTB, SLP, STB */ lcd_writereg(0x0011, 0x0227); /* R11h = 0x0221 at VCI = 3.3V, DC1[2:0], DC0[2:0], VC[2:0] */ delay(50); /* delay 50ms */ lcd_writereg(0x0012, 0x001c); /* External reference voltage= Vci; */ delay(50); /* delay 50ms */ lcd_writereg(0x0013, 0x1800); /* R13 = 1200 when R12 = 009D; VDV[4:0] for VCOM amplitude */ lcd_writereg(0x0029, 0x001c); /* R29 = 000C when R12 = 009D; VCM[5:0] for VCOMH */ lcd_writereg(0x002b, 0x000d); /* Frame Rate = 91Hz */ delay(50); /* delay 50ms */ /* Set GRAM area */ lcd_writereg(0x0050, 0x0000); /* Horizontal GRAM Start Address */ lcd_writereg(0x0051, 0x00ef); /* Horizontal GRAM End Address */ lcd_writereg(0x0052, 0x0000); /* Vertical GRAM Start Address */ lcd_writereg(0x0053, 0x013f); /* Vertical GRAM Start Address */ lcd_writereg(0x0060, 0xa700); /* Gate Scan Line, drive G320 -> G1 */ lcd_writereg(0x0061, 0x0003); /* VLE & REV */ lcd_writereg(0x006a, 0x0000); /* set scrolling line */ /* Partial Display Control */ lcd_writereg(0x0080, 0x0000); /* Image 1 */ lcd_writereg(0x0081, 0x0000); lcd_writereg(0x0082, 0x0000); lcd_writereg(0x0083, 0x0000); /* Image 2 */ lcd_writereg(0x0084, 0x0000); lcd_writereg(0x0085, 0x0000); /* Panel Control */ lcd_writereg(0x0090, 0x0010); lcd_writereg(0x0092, 0x0000); lcd_writereg(0x0093, 0x0003); lcd_writereg(0x0095, 0x0110); lcd_writereg(0x0097, 0x0000); /* Undocumented */ lcd_writereg(0x0098, 0x0000); /* Undocumented */ lcd_writereg(0x0007, 0x0133); /* Display on, 262k colour mode (vs 8) */ lcd_writereg(0x0003, 0x1030); /* set GRAM write direction and enable BGR, 64K colours, 1 transfers/pixel. */ /* Adjust the Gamma Curve */ lcd_writereg(0x0030, 0x0006); lcd_writereg(0x0031, 0x0101); lcd_writereg(0x0032, 0x0003); lcd_writereg(0x0035, 0x0106); lcd_writereg(0x0036, 0x0b02); lcd_writereg(0x0037, 0x0302); lcd_writereg(0x0038, 0x0707); lcd_writereg(0x0039, 0x0007); lcd_writereg(0x003c, 0x0600); lcd_writereg(0x003d, 0x020b); fputs("Testing\r\n", stdout); lcd_startgram(0, 0); lcd_writedata(0xa5a5); lcd_writedata(0x5a5a); lcd_startgram(0, 0); if ((id = lcd_readdata(1)) != 0xa5a5) printf("Expected 0xa5a5 got 0x%04x\r\n", id); if ((id = lcd_readdata(0)) != 0x5a5a) printf("Expected 0x5a5a got 0x%04x\r\n", id); fputs("Filling\r\n", stdout); /* Fill panel */ lcd_startgram(0, 0); for (y = 0; y < 320; y++) for (x = 0; x < 240; x++) lcd_writedata(LCD_BLACK); } void lcd_pixel(uint16_t x, uint16_t y, uint16_t colour) { if (x > LCD_WIDTH || y > LCD_HEIGHT) return; /* Rotate for landscape */ lcd_startgram(y, x); lcd_writedata(colour); } /* * Draw a circle * From http://en.wikipedia.org/wiki/Midpoint_circle_algorithm */ void lcd_circle(uint16_t x0, uint16_t y0, uint16_t radius, uint8_t fill, uint16_t colour) { int16_t f; uint16_t ddF_x, ddF_y, x, y; f = 1 - radius; ddF_x = 1; ddF_y = -2 * radius; x = 0; y = radius; if (fill) { lcd_line(x0, y0 + radius, x0, y0 - radius, colour); lcd_line(x0 + radius, y0, x0 - radius, y0, colour); } else { lcd_pixel(x0, y0 + radius, colour); lcd_pixel(x0, y0 - radius, colour); lcd_pixel(x0 + radius, y0, colour); lcd_pixel(x0 - radius, y0, colour); } while(x < y) { if(f >= 0) { y--; ddF_y += 2; f += ddF_y; } x++; ddF_x += 2; f += ddF_x; if (fill) { lcd_line(x0 + x, y0 + y, x0 - x, y0 + y, colour); lcd_line(x0 + x, y0 - y, x0 - x, y0 - y, colour); lcd_line(x0 + y, y0 + x, x0 - y, y0 + x, colour); lcd_line(x0 + y, y0 - x, x0 - y, y0 - x, colour); } else { lcd_pixel(x0 + x, y0 + y, colour); lcd_pixel(x0 - x, y0 + y, colour); lcd_pixel(x0 + x, y0 - y, colour); lcd_pixel(x0 - x, y0 - y, colour); lcd_pixel(x0 + y, y0 + x, colour); lcd_pixel(x0 - y, y0 + x, colour); lcd_pixel(x0 + y, y0 - x, colour); lcd_pixel(x0 - y, y0 - x, colour); } } } /* * Draw a line * From http://en.wikipedia.org/wiki/Bresenham%27s_line_algorithm */ void lcd_line(uint16_t x0, uint16_t y0, uint16_t x1, uint16_t y1, uint16_t colour) { uint16_t dx, dy; int16_t sx, sy, err, e2; dx = abs(x1 - x0); dy = abs(y1 - y0); if (x0 < x1) sx = 1; else sx = -1; if (y0 < y1) sy = 1; else sy = -1; err = dx - dy; while (1) { lcd_pixel(x0, y0, colour); if (x0 == x1 && y0 == y1) break; e2 = 2 * err; if (e2 > -dy) { err = err - dy; x0 = x0 + sx; } if (e2 < dx) { err = err + dx; y0 = y0 + sy; } } } static void _lcd_ellipsedraw(uint16_t xc, uint16_t yc, uint16_t x, uint16_t y, uint8_t fill, uint16_t colour) { if (fill) { lcd_line(xc + x, yc + y, xc - x, yc + y, colour); lcd_line(xc - x, yc - y, xc + x, yc - y, colour); } else { lcd_pixel(xc + x, yc + y, colour); /* 1st quadrant */ lcd_pixel(xc - x, yc + y, colour); /* 2nd quadrant */ lcd_pixel(xc - x, yc - y, colour); /* 3rd quadrant */ lcd_pixel(xc + x, yc - y, colour); /* 4th quadrant */ } } /* Draw an ellipse, from * http://rooparam.blogspot.com.au/2009/09/midpoint-ellipse-algorithm.html */ void lcd_ellipse(int xc, int yc, int rx, int ry, uint8_t fill, uint16_t colour) { long long int rx_2 = rx * rx, ry_2 = ry * ry; long long int p = ry_2 - rx_2 * ry + (ry_2 >> 2); int x = 0, y = ry; long long int two_ry_2_x = 0, two_rx_2_y = (rx_2 << 1) * y; _lcd_ellipsedraw(xc, yc, x, y, fill, colour); while (two_rx_2_y >= two_ry_2_x) { x++; two_ry_2_x += ry_2 << 1; p += two_ry_2_x + ry_2; if (p >= 0){ y--; two_rx_2_y -= rx_2 << 1; p -= two_rx_2_y; } _lcd_ellipsedraw(xc, yc, x, y, fill, colour); } p = (long long int)(ry_2 * (x + 1 / 2.0) * (x + 1 / 2.0) + rx_2 * (y - 1) * (y - 1) - rx_2 * ry_2); while (y >= 0) { p += rx_2; y--; two_rx_2_y -= rx_2 << 1; p -= two_rx_2_y; if (p <= 0) { x++; two_ry_2_x += ry_2 << 1; p += two_ry_2_x; } _lcd_ellipsedraw(xc, yc, x, y, fill, colour); } } void lcd_stripes(void) { uint16_t x, y, mag, err; lcd_startgram(0, 0); mag = err = 0; for (y = 0; y < 320; y++) { for (x = 0; x < 240; x++) { if (((x / 80) % 3) == 0) { lcd_writedata(RGB24_565(mag, 0, 0)); } else if (((x / 80) % 3) == 1) { lcd_writedata(RGB24_565(0, mag, 0)); } else { lcd_writedata(RGB24_565(0, 0, mag)); } } colinc(&mag, &err, COLINCVAL, 10000); } } uint16_t lcd_parsecol(char c) { c = toupper(c); if (c == 'R') return(LCD_RED); else if (c == 'G') return(LCD_GREEN); else if (c == 'B') return(LCD_BLUE); else if (c == 'L') return(LCD_BLACK); else return(LCD_WHITE); }