SPI based library for the ST7735 LCD controller.

Dependents:   RayCastingEngine RETRO_LCD_PerformanceTest RETRO_loop_test RETRO_RickGame ... more

Revision:
0:7b3fb3085867
Child:
1:33ff5fad4320
--- /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