view 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
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 "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 */

void
lcd_wr_reg(uint16_t index, uint16_t val) {
    *(__IO uint16_t *)(Bank1_LCD_C) = index;
    *(__IO uint16_t *)(Bank1_LCD_D) = val;
}

uint16_t
lcd_rd_reg(uint16_t index) {
    *(__IO uint16_t *)(Bank1_LCD_C) = index;
    return(*(__IO uint16_t *)(Bank1_LCD_D));
}

uint16_t
lcd_rd_data(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_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;
}

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;

    /* 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);

    for (int x = 0; x < 320; x++) {
	for (int y = 0; y < 240; y++) {
	    if (((x / 5) % 3) == 0)
		lcd_wr_data(LCD_RED);
	    else if (((x / 5) % 3) == 1)
		lcd_wr_data(LCD_GREEN);
	    else
		lcd_wr_data(LCD_BLUE);
	}
    }

    lcd_circle(50, 50, 20, LCD_BLACK);

}

void
lcd_pixel(uint16_t x, uint16_t y, uint16_t colour) {
    if (x > LCD_HEIGHT || y > LCD_WIDTH)
	return;

    lcd_wr_startdata(x, y);
    lcd_wr_data(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, 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;
 
    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) {
	// ddF_x == 2 * x + 1;
	// ddF_y == -2 * y;
	// f == x*x + y*y - radius*radius + 2*x - y + 1;
	if(f >= 0) {
	    y--;
	    ddF_y += 2;
	    f += ddF_y;
	}
	x++;
	ddF_x += 2;
	f += ddF_x;    
	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, d, x, y;

    dx = x1 - x0;
    dy = y1 - y0;
    
    d = 2 * dy - dx;
    lcd_pixel(x0, y0, colour);
    y = y0;
    
    for (x = x0 + 1; x <= x1; x++) {
	if (d > 0) {
	    y++;
	    lcd_pixel(x, y, colour);
	    d += 2 * dy - 2 * dx;
	} else {
	    lcd_pixel(x, y, colour);
	    d += 2 * dy;
	}
    }
}