marco valli / TFT_ILI9163C

Dependents:   TFTLCDSCREEN Pong_ILI9163C

Fork of TFT_ILI9163C by _ peu605

Revision:
0:f90a4405ef98
Child:
1:c271e7e2e330
diff -r 000000000000 -r f90a4405ef98 TFT_ILI9163C.cpp
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/TFT_ILI9163C.cpp	Wed Jan 21 14:32:07 2015 +0000
@@ -0,0 +1,495 @@
+#include "TFT_ILI9163C.h"
+#include "mbed.h"
+
+/**
+ * TFT_ILI9163C library for ST Nucleo F411RE
+ * 
+ * @author Copyright (c) 2014, .S.U.M.O.T.O.Y., coded by Max MC Costa
+ * https://github.com/sumotoy/TFT_ILI9163C
+ *
+ * @author modified by masuda, Masuda Naika
+ */
+
+//constructors
+TFT_ILI9163C::TFT_ILI9163C(PinName mosi, PinName miso, PinName sclk, PinName cs, PinName dc, PinName reset) 
+	: Adafruit_GFX(_TFTWIDTH,_TFTHEIGHT) , SPI(mosi,miso,sclk,NC), _cs(cs), _dc(dc) {
+		
+		_resetPinName = reset;
+}
+
+TFT_ILI9163C::TFT_ILI9163C(PinName mosi, PinName miso, PinName sclk, PinName cs, PinName dc) 
+	: Adafruit_GFX(_TFTWIDTH,_TFTHEIGHT) , SPI(mosi,miso,sclk,NC), _cs(cs), _dc(dc) {
+		
+		_resetPinName = NC;
+}
+
+
+//Serial pc(SERIAL_TX, SERIAL_RX);
+
+
+inline void TFT_ILI9163C::waitSpiFree() {
+	
+	while ((spi_ptr->SR & SPI_SR_TXE) == 0);
+	while ((spi_ptr->SR & SPI_SR_BSY) != 0);
+}
+
+
+inline void TFT_ILI9163C::writecommand(uint8_t c){
+	
+	spi_ptr->CR1 &= ~SPI_CR1_DFF;
+	
+	_dc = 0;
+	_cs = 0;
+	
+	spi_ptr->DR = c;
+	
+	waitSpiFree();
+	_cs = 1;
+}
+
+
+inline void TFT_ILI9163C::writedata(uint8_t c){
+	
+	spi_ptr->CR1 &= ~SPI_CR1_DFF;
+	
+	_dc = 1;
+	_cs = 0;
+	
+	spi_ptr->DR = c;
+	
+	waitSpiFree();
+	_cs = 1;
+} 
+
+
+inline void TFT_ILI9163C::writedata16(uint16_t d){
+	
+	spi_ptr->CR1 |= SPI_CR1_DFF;
+	
+	_dc = 1;
+	_cs = 0;
+	
+	spi_ptr->DR = d;
+	
+	waitSpiFree();
+	_cs = 1;
+}
+
+
+inline void TFT_ILI9163C::writedata32(uint16_t d1, uint16_t d2){
+	
+	spi_ptr->CR1 |= SPI_CR1_DFF;
+	
+	_dc = 1;
+	_cs = 0;
+	
+	spi_ptr->DR = d1;
+	while ((spi_ptr->SR & SPI_SR_TXE) == 0);
+	spi_ptr->DR = d2;
+	
+	waitSpiFree();
+	_cs = 1;
+}
+
+
+inline void TFT_ILI9163C::writedata16burst(uint16_t d, int32_t len) {
+	
+	if (len < 0) {
+		len = -len;
+	}
+
+	spi_ptr->CR1 |= SPI_CR1_DFF;
+	
+	_dc = 1;
+	_cs = 0;
+	
+#if defined(__F411RE_DMA__)
+	// use DMA, but polling... :-(
+
+	// clear DMA flags
+//	__HAL_DMA_CLEAR_FLAG(&hdma, __HAL_DMA_GET_TE_FLAG_INDEX(&hdma));
+	__HAL_DMA_CLEAR_FLAG(&hdma, __HAL_DMA_GET_TC_FLAG_INDEX(&hdma));
+	
+	hdma.Instance->M0AR = (uint32_t) &d;
+	hdma.Instance->NDTR = len;
+	// enable DMA
+	hdma.Instance->CR |= DMA_SxCR_EN;
+
+	// enable DMA request from SPI
+	spi_ptr->CR2 |= SPI_CR2_TXDMAEN;
+	// wait DMA complete
+	while (hdma.Instance->NDTR);
+	// disable SPI-DMA
+	spi_ptr->CR2 &= ~SPI_CR2_TXDMAEN;
+	
+	// disable DMA
+	hdma.Instance->CR &= ~DMA_SxCR_EN;
+	while (hdma.Instance->CR & DMA_SxCR_EN);
+		
+#else
+	// use software loop, fast enough :-)
+	while (len--) {
+		while ((spi_ptr->SR & SPI_SR_TXE) == 0);
+		spi_ptr->DR = d;
+	}
+#endif
+	
+	waitSpiFree();
+	_cs = 1;
+}
+
+
+void TFT_ILI9163C::setBitrate(uint32_t n){
+	SPI::frequency(n);
+}
+
+
+void TFT_ILI9163C::begin(void) {
+	
+	SPI::format(8,0);			// 8 bit spi mode 0
+	SPI::frequency(5000000L);	// 5MHz
+	
+	spi_ptr = (SPI_TypeDef*) _spi.spi;
+	
+#if defined(__F411RE_DMA__)
+	hdma.Init.Direction = DMA_MEMORY_TO_PERIPH;
+	hdma.Init.PeriphInc = DMA_PINC_DISABLE;
+	hdma.Init.MemInc = DMA_MINC_DISABLE;
+	hdma.Init.PeriphDataAlignment = DMA_PDATAALIGN_HALFWORD;
+	hdma.Init.MemDataAlignment = DMA_MDATAALIGN_HALFWORD;
+	hdma.Init.Mode = DMA_NORMAL;
+	hdma.Init.Priority = DMA_PRIORITY_MEDIUM;
+	hdma.Init.FIFOMode = DMA_FIFOMODE_DISABLE;
+	hdma.Init.FIFOThreshold = DMA_FIFO_THRESHOLD_HALFFULL;
+	hdma.Init.MemBurst = DMA_MBURST_SINGLE;
+	hdma.Init.PeriphBurst = DMA_PBURST_SINGLE;
+	
+    if(_spi.spi == SPI_1){
+        hdma.Instance = DMA2_Stream3;		// DMA2_Stream2
+		hdma.Init.Channel = DMA_CHANNEL_3;	// DMA_CHANNEL_2
+        __DMA2_CLK_ENABLE();
+    } else if(_spi.spi == SPI_2){
+        hdma.Instance = DMA1_Stream4;
+		hdma.Init.Channel = DMA_CHANNEL_0;
+        __DMA1_CLK_ENABLE();
+    } else if(_spi.spi == SPI_3){
+        hdma.Instance = DMA1_Stream5;		// DMA1_Stream7
+		hdma.Init.Channel = DMA_CHANNEL_0;	// DMA_CHANNEL0
+        __DMA1_CLK_ENABLE();
+    } else if(_spi.spi == SPI_4){
+        hdma.Instance = DMA2_Stream1;		// DMA2_Stream4
+		hdma.Init.Channel = DMA_CHANNEL_4;	// DMA_CHANNEL_5
+        __DMA2_CLK_ENABLE();
+    } else if(_spi.spi == SPI_5){
+        hdma.Instance = DMA2_Stream4;		// DMA2_Stream5, DMA2_Stream6
+		hdma.Init.Channel = DMA_CHANNEL_2;	// DMA_CHANNEL5, DMA_CHANNEL7
+        __DMA2_CLK_ENABLE();
+    }
+    
+    HAL_DMA_Init(&hdma);
+
+	// set SPI DR ss Peripheral address
+	hdma.Instance->PAR = (uint32_t) &spi_ptr->DR;
+#endif
+	
+	if (_resetPinName != NC) {
+		DigitalOut _reset(_resetPinName);
+		_reset = 1;
+	    wait_ms(1);
+	    _reset = 0;
+	    wait_ms(2);
+	    _reset = 1;
+	    wait_ms(120);
+    }
+
+/*
+7) MY:  1(bottom to top), 0(top to bottom) 	Row Address Order
+6) MX:  1(R to L),        0(L to R)        	Column Address Order
+5) MV:  1(Exchanged),     0(normal)        	Row/Column exchange
+4) ML:  1(bottom to top), 0(top to bottom) 	Vertical Refresh Order
+3) RGB: 1(BGR), 		   0(RGB)           	Color Space
+2) MH:  1(R to L),        0(L to R)        	Horizontal Refresh Order
+1)
+0)
+
+     MY, MX, MV, ML,RGB, MH, D1, D0
+	 0 | 0 | 0 | 0 | 1 | 0 | 0 | 0	//normal
+	 1 | 0 | 0 | 0 | 1 | 0 | 0 | 0	//Y-Mirror
+	 0 | 1 | 0 | 0 | 1 | 0 | 0 | 0	//X-Mirror
+	 1 | 1 | 0 | 0 | 1 | 0 | 0 | 0	//X-Y-Mirror
+	 0 | 0 | 1 | 0 | 1 | 0 | 0 | 0	//X-Y Exchange
+	 1 | 0 | 1 | 0 | 1 | 0 | 0 | 0	//X-Y Exchange, Y-Mirror
+	 0 | 1 | 1 | 0 | 1 | 0 | 0 | 0	//XY exchange
+	 1 | 1 | 1 | 0 | 1 | 0 | 0 | 0
+*/
+	_Mactrl_Data = 0;	// 0b00000000;
+	_colorspaceData = __COLORSPC;//start with default data;
+	chipInit();
+}
+
+
+void TFT_ILI9163C::chipInit() {
+	writecommand(CMD_SWRESET);//software reset
+	wait_ms(120);
+	writecommand(CMD_SLPOUT);//exit sleep
+	wait_ms(5);
+	writecommand(CMD_PIXFMT);//Set Color Format 16bit   
+	writedata(0x05);
+	wait_ms(5);
+	writecommand(CMD_GAMMASET);//default gamma curve 3
+	writedata(0x04);//0x04
+	wait_ms(1);
+	writecommand(CMD_GAMRSEL);//Enable Gamma adj    
+	writedata(0x01); 
+	wait_ms(1);
+	writecommand(CMD_NORML);
+	
+	writecommand(CMD_DFUNCTR);
+	writedata(0xff);	// writedata(0b11111111);//
+	writedata(0x06);	// writedata(0b00000110);//
+
+	writecommand(CMD_PGAMMAC);//Positive Gamma Correction Setting
+	#if defined(__GAMMASET1)
+		writedata(0x36);//p1
+		writedata(0x29);//p2
+		writedata(0x12);//p3
+		writedata(0x22);//p4
+		writedata(0x1C);//p5
+		writedata(0x15);//p6
+		writedata(0x42);//p7
+		writedata(0xB7);//p8
+		writedata(0x2F);//p9
+		writedata(0x13);//p10
+		writedata(0x12);//p11
+		writedata(0x0A);//p12
+		writedata(0x11);//p13
+		writedata(0x0B);//p14
+		writedata(0x06);//p15
+	#else
+		writedata(0x3F);//p1
+		writedata(0x25);//p2
+		writedata(0x1C);//p3
+		writedata(0x1E);//p4
+		writedata(0x20);//p5
+		writedata(0x12);//p6
+		writedata(0x2A);//p7
+		writedata(0x90);//p8
+		writedata(0x24);//p9
+		writedata(0x11);//p10
+		writedata(0x00);//p11
+		writedata(0x00);//p12
+		writedata(0x00);//p13
+		writedata(0x00);//p14
+		writedata(0x00);//p15
+	#endif
+
+	writecommand(CMD_NGAMMAC);//Negative Gamma Correction Setting
+	#if defined(__GAMMASET1)
+		writedata(0x09);//p1
+		writedata(0x16);//p2
+		writedata(0x2D);//p3
+		writedata(0x0D);//p4
+		writedata(0x13);//p5
+		writedata(0x15);//p6
+		writedata(0x40);//p7
+		writedata(0x48);//p8
+		writedata(0x53);//p9
+		writedata(0x0C);//p10
+		writedata(0x1D);//p11
+		writedata(0x25);//p12
+		writedata(0x2E);//p13
+		writedata(0x34);//p14
+		writedata(0x39);//p15
+	#else
+		writedata(0x20);//p1
+		writedata(0x20);//p2
+		writedata(0x20);//p3
+		writedata(0x20);//p4
+		writedata(0x05);//p5
+		writedata(0x15);//p6
+		writedata(0x00);//p7
+		writedata(0xA7);//p8
+		writedata(0x3D);//p9
+		writedata(0x18);//p10
+		writedata(0x25);//p11
+		writedata(0x2A);//p12
+		writedata(0x2B);//p13
+		writedata(0x2B);//p14
+		writedata(0x3A);//p15
+	#endif
+
+	writecommand(CMD_FRMCTR1);//Frame Rate Control (In normal mode/Full colors)
+	writedata(0x08);//0x0C//0x08
+	writedata(0x02);//0x14//0x08
+	wait_ms(1);
+	writecommand(CMD_DINVCTR);//display inversion 
+	writedata(0x07);
+    wait_ms(1);
+	writecommand(CMD_PWCTR1);//Set VRH1[4:0] & VC[2:0] for VCI1 & GVDD   
+	writedata(0x0A);//4.30 - 0x0A
+	writedata(0x02);//0x05
+	wait_ms(1);
+	writecommand(CMD_PWCTR2);//Set BT[2:0] for AVDD & VCL & VGH & VGL   
+	writedata(0x02);
+	wait_ms(1);
+	writecommand(CMD_VCOMCTR1);//Set VMH[6:0] & VML[6:0] for VOMH & VCOML   
+	writedata(0x50);//0x50
+	writedata(99);//0x5b
+	wait_ms(1);
+	writecommand(CMD_VCOMOFFS);
+	writedata(0);//0x40
+	wait_ms(1);
+  
+	colorSpace(_colorspaceData);
+	setRotation(0);
+	wait_ms(1);
+
+	fillScreen(BLACK);
+	writecommand(CMD_DISPON);//display ON 
+}
+
+/*
+Colorspace selection:
+0: RGB
+1: GBR
+*/
+void TFT_ILI9163C::colorSpace(uint8_t cspace) {
+	if (cspace < 1){
+		_Mactrl_Data &= ~(1 << 3);	// bitClear(_Mactrl_Data,3);
+	} else {
+		_Mactrl_Data |= 1 << 3;		// bitSet(_Mactrl_Data,3);
+	}
+}
+
+
+void TFT_ILI9163C::clearScreen(uint16_t color) {
+	homeAddress();
+	writedata16burst(color, _GRAMSIZE);
+}
+
+void TFT_ILI9163C::homeAddress() {
+	setAddrWindow(0x00,0x00,_GRAMWIDTH-1,_GRAMHEIGH-1);
+}
+
+
+void TFT_ILI9163C::setCursor(int16_t x, int16_t y) {
+	if (boundaryCheck(x,y)) return;
+	setAddrWindow(0x00,0x00,x,y);
+	cursor_x = x;
+	cursor_y = y;
+}
+
+
+void TFT_ILI9163C::pushColor(uint16_t color) {
+	 writedata16(color);
+}
+
+
+void TFT_ILI9163C::drawPixel(int16_t x, int16_t y, uint16_t color) {
+	if (boundaryCheck(x,y)) return;
+	if ((x < 0) || (y < 0)) return;
+	setAddrWindow(x,y,x+1,y+1);
+	writedata16(color);
+}
+
+
+void TFT_ILI9163C::drawFastVLine(int16_t x, int16_t y, int16_t h, uint16_t color) {
+	// Rudimentary clipping
+	if (boundaryCheck(x,y)) return;
+	if (((y + h) - 1) >= _height) h = _height-y;
+	
+	setAddrWindow(x,y,x,(y+h)-1);
+	writedata16burst(color, h);
+}
+
+inline bool TFT_ILI9163C::boundaryCheck(int16_t x,int16_t y){
+	if ((x >= _width) || (y >= _height)) return true;
+	return false;
+}
+
+void TFT_ILI9163C::drawFastHLine(int16_t x, int16_t y, int16_t w, uint16_t color) {
+	// Rudimentary clipping
+	if (boundaryCheck(x,y)) return;
+	if (((x+w) - 1) >= _width)  w = _width-x;
+	
+	setAddrWindow(x,y,(x+w)-1,y);
+	writedata16burst(color, w);
+}
+
+void TFT_ILI9163C::fillScreen(uint16_t color) {
+	clearScreen(color);
+}
+
+// fill a rectangle
+void TFT_ILI9163C::fillRect(int16_t x, int16_t y, int16_t w, int16_t h, uint16_t color) {
+	
+	if (boundaryCheck(x,y)) return;
+	if (((x + w) - 1) >= _width)  w = _width  - x;
+	if (((y + h) - 1) >= _height) h = _height - y;
+	
+	setAddrWindow(x,y,(x+w)-1,(y+h)-1);
+	writedata16burst(color, w * h);
+}
+
+
+// Pass 8-bit (each) R,G,B, get back 16-bit packed color
+
+uint16_t TFT_ILI9163C::Color565(uint8_t r, uint8_t g, uint8_t b) {
+	return ((r & 0xF8) << 8) | ((g & 0xFC) << 3) | (b >> 3);
+}
+
+
+void TFT_ILI9163C::setAddrWindow(uint16_t x0, uint16_t y0, uint16_t x1, uint16_t y1) {
+	
+	writecommand(CMD_CLMADRS); // Column
+	
+	if (rotation == 1) {
+		writedata32(x0 + __OFFSET, x1 + __OFFSET);
+	} else {
+		writedata32(x0, x1);
+	}
+
+	writecommand(CMD_PGEADRS); // Page
+	if (rotation == 0){
+		writedata32(y0 + __OFFSET, y1 + __OFFSET);
+	} else {
+		writedata32(y0, y1);
+	}
+
+	writecommand(CMD_RAMWR); //Into RAM
+}
+
+
+void TFT_ILI9163C::setRotation(uint8_t m) {
+	rotation = m &3; // can't be higher than 3
+	switch (rotation) {
+	case 0:
+		_Mactrl_Data = 0x08;	// 0b00001000;
+		_width  = _TFTWIDTH;
+		_height = _TFTHEIGHT;//-__OFFSET;
+		break;
+	case 1:
+		_Mactrl_Data = 0x68;	// 0b01101000;
+		_width  = _TFTHEIGHT;//-__OFFSET;
+		_height = _TFTWIDTH;
+		break;
+	case 2:
+		_Mactrl_Data = 0xC8;	// 0b11001000;
+		_width  = _TFTWIDTH;
+		_height = _TFTHEIGHT;//-__OFFSET;
+		break;
+	case 3:
+		_Mactrl_Data = 0xA8;	// 0b10101000;
+		_width  = _TFTWIDTH;
+		_height = _TFTHEIGHT;//-__OFFSET;
+		break;
+	}
+	colorSpace(_colorspaceData);
+	writecommand(CMD_MADCTL);
+	writedata(_Mactrl_Data);
+}
+
+
+void TFT_ILI9163C::invertDisplay(bool i) {
+	writecommand(i ? CMD_DINVON : CMD_DINVOF);
+}