SPI based library for the ST7735 LCD controller.
Dependents: RayCastingEngine RETRO_LCD_PerformanceTest RETRO_loop_test RETRO_RickGame ... more
Diff: LCD_ST7735.cpp
- Revision:
- 0:7b3fb3085867
- Child:
- 1:33ff5fad4320
diff -r 000000000000 -r 7b3fb3085867 LCD_ST7735.cpp --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/LCD_ST7735.cpp Fri Sep 19 02:43:29 2014 +0000 @@ -0,0 +1,423 @@ +#include "mbed.h" +#include "LCD_ST7735.h" + +LCD_ST7735::LCD_ST7735( + PinName backlightPin, + PinName resetPin, + PinName dsPin, + PinName mosiPin, + PinName misoPin, + PinName clkPin, + PinName csPin) : + _backlight(backlightPin, 0), + _reset(resetPin, 1), + _ds(dsPin, 0), + _cs(csPin, 1), + _spi(mosiPin, misoPin, clkPin) +{ + _spi.format(8, 3); + _spi.frequency(12000000); + + initDisplay(); + clearScreen(); + setForegroundColor(0xffff); + setBackgroundColor(0x0000); +} + +void LCD_ST7735::setBacklight(bool state) +{ + _backlight = state ? 1 : 0; +} + +void LCD_ST7735::clearScreen(uint16_t color) +{ + clipRect(0, 0, 127, 159); + beginBatchCommand(CMD_RAMWR); + for(int i = 0; i < 128 * 160 * 2; ++i) + { + writeBatchData(color); + } + endBatchCommand(); +} + +void LCD_ST7735::setPixel(int x, int y, uint16_t color) +{ + write(CMD_CASET, (uint8_t[]){0, x, 0, x}, 4); + write(CMD_RASET, (uint8_t[]){0, y, 0, y}, 4); + write(CMD_RAMWR, color); +} + +void LCD_ST7735::drawLine(int x1, int y1, int x2, int y2, uint16_t color) +{ + int dx = abs(x2 - x1); + int dy = abs(y2 - y1); + + if (dx == 0) + { + drawVertLine(x1, y1, y2, color); + return; + } + else if(dy == 0) + { + drawHorizLine(x1, y1, x2, color); + return; + } + + int sx = (x1 < x2) ? 1 : -1; + int sy = (y1 < y2) ? 1 : -1; + int err = dx - dy; + while(x1 != x2 || y1 != y2) + { + setPixel(x1, y1, color); + int e2 = err << 1; + if (e2 > -dy) + { + err -= dy; + x1 += sx; + } + if (e2 < dx) + { + err += dx; + y1 += sy; + } + } + setPixel(x2, y2, color); +} + +void LCD_ST7735::swap(int &a, int &b) +{ + int t = a; + a = b; + b = t; +} + +void LCD_ST7735::drawRect(int x1, int y1, int x2, int y2, uint16_t color) +{ + if (x1 > x2) swap(x1, x2); + if (y1 > y2) swap(y1, y2); + + drawHorizLine(x1, y1, x2, color); + drawHorizLine(x1, y2, x2, color); + drawVertLine(x1, y1, y2, color); + drawVertLine(x2, y1, y2, color); +} + +void LCD_ST7735::drawCircle(int x, int y, int r, uint16_t color) +{ + int ix = r; + int iy = 0; + int err = 1 - r; + + while(ix >= iy) + { + setPixel(x + ix, y + iy, color); + setPixel(x + iy, y + ix, color); + setPixel(x - ix, y + iy, color); + setPixel(x - iy, y + ix, color); + setPixel(x - ix, y - iy, color); + setPixel(x - iy, y - ix, color); + setPixel(x + ix, y - iy, color); + setPixel(x + iy, y - ix, color); + iy++; + if (err < 0) + { + err += 2 * iy + 1; + } + else + { + ix--; + err += 2 * (iy - ix + 1); + } + } +} + +void LCD_ST7735::fillRect(int x1, int y1, int x2, int y2, uint16_t borderColor, uint16_t fillColor) +{ + if (x1 > x2) swap(x1, x2); + if (y1 > y2) swap(y1, y2); + + drawRect(x1, y1, x2, y2, borderColor); + clipRect(x1 + 1, y1 + 1, x2 - 1, y2 - 1); + int c = ((x2-x1-2) * (y2-y1-2)) << 1; + beginBatchCommand(CMD_RAMWR); + while(c--) + { + writeBatchData(fillColor); + } + endBatchCommand(); +} + +void LCD_ST7735::fillCircle(int x, int y, int r, uint16_t borderColor, uint16_t fillColor) +{ + int ix = r; + int iy = 0; + int err = 1 - r; + + while(ix >= iy) + { + setPixel(x - ix, y + iy, borderColor); + setPixel(x + ix, y + iy, borderColor); + drawHorizLine(x - ix + 1, y + iy, x + ix - 1, fillColor); + + setPixel(x - iy, y + ix, borderColor); + setPixel(x + iy, y + ix, borderColor); + drawHorizLine(x - iy + 1, y + ix, x + iy - 1, fillColor); + + setPixel(x - ix, y - iy, borderColor); + setPixel(x + ix, y - iy, borderColor); + drawHorizLine(x - ix + 1, y - iy, x + ix - 1, fillColor); + + setPixel(x - iy, y - ix, borderColor); + setPixel(x + iy, y - ix, borderColor); + drawHorizLine(x - iy + 1, y - ix, x + iy - 1, fillColor); + iy++; + if (err < 0) + { + err += 2 * iy + 1; + } + else + { + ix--; + err += 2 * (iy - ix + 1); + } + } +} + +void LCD_ST7735::drawBitmap(int x, int y, const uint16_t *pbmp) +{ + int w = *pbmp++; + int h = *pbmp++; + + clip(x, y, w, h); + int c = w * h; + beginBatchCommand(CMD_RAMWR); + while(c--) + { + writeBatchData(*pbmp++); + } + endBatchCommand(); +} + +void LCD_ST7735::setForegroundColor(uint16_t color) +{ + _foregroundColor = color; +} + +void LCD_ST7735::setBackgroundColor(uint16_t color) +{ + _backgroundColor = color; +} + +void LCD_ST7735::drawString(const uint8_t *pFont, int x, int y, const char *pString) +{ + char *p = (char*)pString; + while(*p != 0) + { + drawChar(pFont, x, y, *p++); + x += 8; + } +} + +void LCD_ST7735::drawVertLine(int x1, int y1, int y2, uint16_t color) +{ + clipRect(x1, y1, x1, y2); + beginBatchCommand(CMD_RAMWR); + for (int i = 0; i < (y2 - y1) * 2; ++i) + { + writeBatchData(color); + } + endBatchCommand(); +} + +void LCD_ST7735::drawHorizLine(int x1, int y1, int x2, uint16_t color) +{ + clipRect(x1, y1, x2, y1); + beginBatchCommand(CMD_RAMWR); + for (int i = 0; i < (x2 - x1) * 2; ++i) + { + writeBatchData(color); + } + endBatchCommand(); +} + +void LCD_ST7735::drawChar(const uint8_t *pFont, int x, int y, char c) +{ + const uint8_t *pChar = pFont + (c * 8); + + clip(x, y, 8, 8); + beginBatchCommand(CMD_RAMWR); + for(int r = 0; r < 8; ++r) + { + uint8_t b = pChar[r]; + for(int c = 0; c < 8; ++c) + { + if (b & 0x80) + writeBatchData(_foregroundColor); + else + writeBatchData(_backgroundColor); + + b <<= 1; + } + } + endBatchCommand(); +} + +void LCD_ST7735::initDisplay() +{ + reset(); + + write(CMD_SLPOUT); + + write(CMD_FRMCTR1, (uint8_t[]){0x01, 0x2c, 0x2d}, 3); + write(CMD_FRMCTR1, (uint8_t[]){0x01, 0x2c, 0x2d}, 3); + write(CMD_FRMCTR1, (uint8_t[]){0x01, 0x2c, 0x2d, 0x01, 0x2c, 0x2d}, 6); + + write(CMD_INVCTR, (uint8_t[]){0x07}, 1); + + write(CMD_PWCTR1, (uint8_t[]){0xa2, 0x02, 0x84}, 3); + write(CMD_PWCTR2, (uint8_t[]){0xc5}, 1); + write(CMD_PWCTR3, (uint8_t[]){0x0a, 0x00}, 2); + write(CMD_PWCTR4, (uint8_t[]){0x8a, 0x2a}, 2); + write(CMD_PWCTR5, (uint8_t[]){0x8a, 0xee}, 2); + + write(CMD_VMCTR1, (uint8_t[]){0x0e}, 1); + + write(CMD_MADCTL, (uint8_t[]){0xc8}, 1); + + // Gama sequence + write(CMD_GAMCTRP1, (uint8_t[]) + { + 0x0f, 0x1a, + 0x0f, 0x18, + 0x2f, 0x28, + 0x20, 0x22, + 0x1f, 0x1b, + 0x23, 0x37, + 0x00, 0x07, + 0x02, 0x10 + }, 16); + + write(CMD_GAMCTRN1, (uint8_t[]) + { + 0x0f, 0x1b, + 0x0f, 0x17, + 0x33, 0x2c, + 0x29, 0x2e, + 0x30, 0x30, + 0x39, 0x3f, + 0x00, 0x07, + 0x03, 0x10 + }, 16); + + write(CMD_CASET, (uint8_t[]){0x00, 0x00, 0x00, 0x7f}, 4); + write(CMD_RASET, (uint8_t[]){0x00, 0x00, 0x00, 0x9f}, 4); + + write(CMD_EXTCTRL, (uint8_t[]){0x01}, 1); + + // Disable RAM power save + write(0xf6, (uint8_t[]){0x00}, 1); + + // 65k color mode + write(CMD_COLMOD, (uint8_t[]){0x05}, 1); + + // Enable display + write(CMD_DISPON); + + setBacklight(true); +} + +void LCD_ST7735::reset() +{ + _reset = 0; + wait_us(100); + _reset = 1; + wait_us(100); +} + +void LCD_ST7735::clip(int x, int y, int w, int h) +{ + clipRect(x, y, (x + w) - 1, (y + h) - 1); +} + +void LCD_ST7735::clipRect(int x1, int y1, int x2, int y2) +{ + uint8_t x1l = (uint8_t)(x1 & 0xff); + uint8_t x1h = (uint8_t)((x1 >> 8) & 0xff); + uint8_t x2l = (uint8_t)(x2 & 0xff); + uint8_t x2h = (uint8_t)((x2 >> 8) & 0xff); + write(CMD_CASET, (uint8_t[]){x1h, x1l, x2h, x2l}, 4); + + uint8_t y1l = (uint8_t)(y1 & 0xff); + uint8_t y1h = (uint8_t)((y1 >> 8) & 0xff); + uint8_t y2l = (uint8_t)(y2 & 0xff); + uint8_t y2h = (uint8_t)((y2 >> 8) & 0xff); + write(CMD_RASET, (uint8_t[]){y1h, y1l, y2h, y2l}, 4); +} + +void LCD_ST7735::write(uint8_t cmd) +{ + write(cmd, NULL, 0); +} + +void LCD_ST7735::write(uint8_t cmd, uint8_t data[], int dataLen) +{ + _ds = 0; + _cs = 0; + _spi.write(cmd); + if (data != NULL & dataLen > 0) + { + _ds = 1; + for(int i = 0; i < dataLen; ++i) + { + _spi.write(data[i]); + } + _ds = 0; + } + _cs = 1; +} + +void LCD_ST7735::write(uint8_t cmd, uint16_t data) +{ + _ds = 0; + _cs = 0; + _spi.write(cmd); + _ds = 1; + _spi.write((data >> 8) & 0xff); + _spi.write(data & 0xff); + _ds = 0; + _cs = 1; +} + +void LCD_ST7735::writeData(uint8_t data) +{ + _ds = 1; + _cs = 0; + _spi.write(data); + _ds = 0; + _cs = 1; +} + +void LCD_ST7735::beginBatchCommand(uint8_t cmd) +{ + _ds = 0; + _cs = 0; + _spi.write(cmd); + _ds = 1; +} + +void LCD_ST7735::writeBatchData(uint8_t data) +{ + _spi.write(data); +} + +void LCD_ST7735::writeBatchData(uint16_t data) +{ + _spi.write((data >> 8) & 0xff); + _spi.write(data & 0xff); +} + +void LCD_ST7735::endBatchCommand() +{ + _ds = 0; + _cs = 1; +} \ No newline at end of file