Important changes to repositories hosted on mbed.com
Mbed hosted mercurial repositories are deprecated and are due to be permanently deleted in July 2026.
To keep a copy of this software download the repository Zip archive or clone locally using Mercurial.
It is also possible to export all your personal repositories from the account settings page.
Dependents: TFTLCDSCREEN Pong_ILI9163C
Fork of TFT_ILI9163C by
Diff: TFT_ILI9163C.cpp
- 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); +}