Race around the city collecting the flags while avoiding those that stand in the way of your mission. Make no mistake you will need to be quick to outwit your opponents, they are smart and will try to box you in. I wrote this game to prove that writing a game with scrolling scenery is possible even with the limited 6kB of RAM available. I had to compromise sound effects for features, I wanted multiple opponents, I wanted to be able to drop smoke bombs to trap the opponents but all this required memory so the sound effects had to take a back seat.

Dependencies:   mbed

LCD_ST7735/LCD_ST7735.cpp

Committer:
taylorza
Date:
2015-02-01
Revision:
1:1b8125937f28
Parent:
0:d85c449aca6d

File content as of revision 1:1b8125937f28:

#include "mbed.h"
#include "LCD_ST7735.h"

const uint16_t LCD_ST7735::DefaultPalette[] = {
    0x0000, // 0  - Black
    0x0019, // 1  - Blue
    0xc800, // 2  - Red
    0xc819, // 3  - Magenta
    0x0660, // 4  - Green
    0x0679, // 5  - Cyan
    0xce60, // 6  - Yellow
    0xce79, // 7  - White        
    0x001f, // 8  - Bright Blue
    0xf800, // 9  - Bright Red
    0xf81f, // 10 - Bright Magenta
    0x07e0, // 11 - Bright Green
    0x07ff, // 12 - Bright Cyan
    0xffe0, // 13 - Bright Yellow
    0xffff, // 14 - Bright White
};

LCD_ST7735::LCD_ST7735(
    PinName backlightPin,
    PinName resetPin,
    PinName dsPin,
    PinName mosiPin,
    PinName misoPin,
    PinName clkPin,
    PinName csPin,
    PanelColorFilter colorFilter
    ) :
        _colorFilter(colorFilter),
        _backlight(backlightPin, 0),
        _reset(resetPin, 1),
        _ds(dsPin, 0),
        _cs(csPin, 1),
        _spi(mosiPin, misoPin, clkPin)        
{        
    _spi.format(8, 3);
    _spi.frequency(18000000);
    
    initDisplay();
    clearScreen();
    setForegroundColor(0xffff);
    setBackgroundColor(0x0000);    
    
    _palette = (uint16_t*)DefaultPalette;    
}

void LCD_ST7735::setOrientation(Orientation orientation, bool flip)
{
    const static uint8_t my = 0x80; 
    const static uint8_t mx = 0x40;
    const static uint8_t mv = 0x20;
    
    uint8_t madctlData = _colorFilter;
    switch(orientation)
    {
        case Rotate0:
            _width = 128;
            _height = 160;
            madctlData |= flip ? mx : 0;
            break;
            
        case Rotate90:
            _width = 160;
            _height = 128;
            madctlData |= flip ? my | mv | mx : mv | mx;
            break;
            
        case Rotate180:
            _width = 128;
            _height = 160;
            madctlData |= flip ? my : mx | my;
            break;
            
        case Rotate270:
            _width = 160;
            _height = 128;
            madctlData |= flip ? mv : mv | my;
            break;
    }
    write(CMD_MADCTL, (uint8_t[]){madctlData}, 1);
}

int LCD_ST7735::getWidth()
{
    return _width;
}
        
int LCD_ST7735::getHeight()
{
    return _height;
}

void LCD_ST7735::setBacklight(bool state)
{
    _backlight = state ? 1 : 0;
}

void LCD_ST7735::setPalette(uint16_t *palette)
{
    _palette = palette;
}

void LCD_ST7735::clearScreen(uint16_t color)
{
    clipRect(0, 0, _width - 1, _height - 1);
    beginBatchCommand(CMD_RAMWR);
    uint8_t colorHigh = color >> 8;
    uint8_t colorLow = color;
    for(int i = 0; i < 128 * 160 * 2; ++i)
    {
        writeBatchData(colorHigh, colorLow);
    }
    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) 
    {
        if (y1 > y2) swap(y1, y2);
        drawVertLine(x1, y1, y2, color);
        return;
    }
    else if(dy == 0)
    {
        if (x1 > x2) swap(x1, x2);
        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::drawEllipse(int x, int y, int rx, int ry, uint16_t color)
{
    int a2 = rx * rx;
    int b2 = ry * ry;
    int fa2 = 4 * a2;
    int fb2 = 4 * b2;
    
    int ix, iy, sigma;    
    for (ix = 0, iy = ry, sigma = 2 * b2 + a2 * (1 - 2 * ry); b2 * ix <= a2 * iy; ix++)
    {
        setPixel(x + ix, y + iy, color);
        setPixel(x - ix, y + iy, color);
        setPixel(x + ix, y - iy, color);
        setPixel(x - ix, y - iy, color);
        if (sigma >= 0)
        {
            sigma+= fa2 * (1 - iy);
            iy--;
        }
        sigma += b2 * ((4 * ix) + 6);
    }
    
    for (ix = rx, iy = 0, sigma = 2 * a2 + b2 * (1 - 2 * rx); a2 * iy <= b2 * ix; iy++)
    {
        setPixel(x + ix, y + iy, color);
        setPixel(x - ix, y + iy, color);
        setPixel(x + ix, y - iy, color);
        setPixel(x - ix, y - iy, color);
        if (sigma >= 0)
        {
            sigma+= fb2 * (1 - ix);
            ix--;
        }
        sigma += a2 * ((4 * iy) + 6);
    }
}
void LCD_ST7735::fillRect(int x1, int y1, int x2, int y2, uint16_t fillColor)
{
    clipRect(x1, y1, x2, y2);
    int c = ((x2-x1) * (y2-y1)) << 1;
    uint8_t colorHigh = fillColor >> 8;
    uint8_t colorLow = fillColor;
    beginBatchCommand(CMD_RAMWR);
    while(c--)
    {
        writeBatchData(colorHigh, colorLow);
    }
    endBatchCommand();
}

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);
    ++x1; ++y1; --x2; --y2;
    if (x2 >= x1 && y2 >= y1)
    {
        clipRect(x1, y1, x2, y2);
        int c = ((x2-x1-2) * (y2-y1-2)) << 1;
        uint8_t colorHigh = fillColor >> 8;
        uint8_t colorLow = fillColor;
        beginBatchCommand(CMD_RAMWR);
        while(c--)
        {
            writeBatchData(colorHigh, colorLow);
        }
        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::fillEllipse(int x, int y, int rx, int ry, uint16_t borderColor, uint16_t fillColor)
{
    int a2 = rx * rx;
    int b2 = ry * ry;
    int fa2 = 4 * a2;
    int fb2 = 4 * b2;
    
    int ix, iy, sigma;    
    for (ix = 0, iy = ry, sigma = 2 * b2 + a2 * (1 - 2 * ry); b2 * ix <= a2 * iy; ix++)
    {
        setPixel(x + ix, y + iy, borderColor);
        setPixel(x - ix, y + iy, borderColor);
        drawHorizLine(x - ix + 1, y + iy, x + ix - 1, fillColor);
        
        setPixel(x + ix, y - iy, borderColor);
        setPixel(x - ix, y - iy, borderColor);
        drawHorizLine(x - ix + 1, y - iy, x + ix - 1, fillColor);
        
        if (sigma >= 0)
        {
            sigma+= fa2 * (1 - iy);
            iy--;
        }
        sigma += b2 * ((4 * ix) + 6);
    }
    
    for (ix = rx, iy = 0, sigma = 2 * a2 + b2 * (1 - 2 * rx); a2 * iy <= b2 * 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 + ix, y - iy, borderColor);
        setPixel(x - ix, y - iy, borderColor);
        drawHorizLine(x - ix + 1, y - iy, x + ix - 1, fillColor);
        if (sigma >= 0)
        {
            sigma+= fb2 * (1 - ix);
            ix--;
        }
        sigma += a2 * ((4 * iy) + 6);
    }
}

void LCD_ST7735::drawBitmap(int x, int y, const uint16_t *pbmp)
{
    int w = *pbmp++;
    int h = *pbmp++;
    
    drawBitmap(x, y, pbmp, 0, 0, w, h);
}

void LCD_ST7735::drawBitmap(int x, int y, const uint16_t *pbmp, int srcX, int srcY, int srcWidth, int srcHeight)
{
    // Clip if out of screen    
    if ((x >= _width) || (x + srcWidth < 0) || 
        (y >= _height) || (y + srcHeight < 0))
    {
        return;
    }
    
    // Clip X
    if (x < 0) { srcX += -x; srcWidth += x; x = 0; }
    if (x + srcWidth >= _width) { srcWidth += _width - (x + srcWidth); }
    
    // Clip Y
    if (y  < 0) {srcY += -y; srcHeight += y; y = 0; }  
    if (y + srcHeight >= _height) { srcHeight += _height - (y + srcHeight); }
    
    int w = *pbmp++;
    int h = *pbmp++;
    
    clip(x, y, srcWidth, srcHeight);
    beginBatchCommand(CMD_RAMWR);    
    const uint16_t *p = pbmp + srcX + (srcY * w);
    for(int iy = 0; iy < srcHeight; ++iy)
    {
        for(int ix = 0; ix < srcWidth; ++ix)
        {
            writeBatchData(*(p + ix));
        }
        p += w;
    } 
    endBatchCommand();
}

void LCD_ST7735::drawBitmap(int x, int y, Bitmap2bpp &bmp, int srcX, int srcY, int srcWidth, int srcHeight)
{
    // Clip if out of screen    
    if ((x >= _width) || (x + srcWidth < 0) || 
        (y >= _height) || (y + srcHeight < 0))
    {
        return;
    }
    
    // Clip X
    if (x < 0) { srcX += -x; srcWidth += x; x = 0; }
    if (x + srcWidth >= _width) { srcWidth += _width - (x + srcWidth); }
    
    // Clip Y
    if (y  < 0) {srcY += -y; srcHeight += y; y = 0; }  
    if (y + srcHeight >= _height) { srcHeight += _height - (y + srcHeight); }
    
    int offset = (bmp.getStride() * srcY) + (srcX / 4);
    int startbits = 6 - ((srcX % 4) << 1);
    
    clip(x, y, srcWidth, srcHeight);
    beginBatchCommand(CMD_RAMWR);
    for(int r = 0; r < srcHeight; ++r)
    {
        const uint8_t *p = bmp.getBitmapData() + offset;
        
        uint8_t b = *p;
        for (int c = 0, shift = startbits; c < srcWidth; ++c, shift -= 2)
        {
            if (shift < 0) 
            {
                shift = 6;
                b = *++p;
            }
            
            uint8_t colorIndex = (b >> shift) & 0x03;
            writeBatchData(_palette[colorIndex]);            
        }   
        offset += bmp.getStride();             
    }
    endBatchCommand();
}


void LCD_ST7735::drawBitmap(int x, int y, Bitmap4bpp &bmp, int srcX, int srcY, int srcWidth, int srcHeight)
{
    // Clip if out of screen    
    if ((x >= _width) || (x + srcWidth < 0) || 
        (y >= _height) || (y + srcHeight < 0))
    {
        return;
    }
    
    // Clip X
    if (x < 0) { srcX += -x; srcWidth += x; x = 0; }
    if (x + srcWidth >= _width) { srcWidth += _width - (x + srcWidth); }
    
    // Clip Y
    if (y  < 0) {srcY += -y; srcHeight += y; y = 0; }  
    if (y + srcHeight >= _height) { srcHeight += _height - (y + srcHeight); }
    
    int stride = bmp.getStride();
    
    bool oddStart = srcX & 0x01;
    bool oddWidth = srcWidth & 0x01;    
    bool oddEnd = oddStart ^ oddWidth;
    
    int startX = oddStart ? 1 : 0;
    int endX = (oddEnd ? srcWidth : srcWidth + 1) >> 1;    
    
    const uint8_t *p = bmp.getBitmapData() + (srcX >> 1) + (srcY * stride);    

    clip(x, y, srcWidth, srcHeight);
    beginBatchCommand(CMD_RAMWR);        
    for(int iy = 0; iy < srcHeight; ++iy, p += stride)
    {
        if (oddStart) writeBatchData(_palette[*p & 0x0f]);
        for(int ix = startX; ix < endX; ++ix)
        {
            uint8_t c = *(p + ix);
            writeBatchData(_palette[(c >> 4) & 0x0f]);
            writeBatchData(_palette[c & 0x0f]);
        }        
        if (oddEnd) writeBatchData(_palette[(*(p + endX) >> 4) & 0x0f]);
    } 
    endBatchCommand();
}

void LCD_ST7735::drawBitmap(int x, int y, Bitmap1bpp &bmp, int srcX, int srcY, int srcWidth, int srcHeight, uint16_t foregroundColor, uint16_t backgroundColor)
{
    // Clip if out of screen    
    if ((x >= _width) || (x + srcWidth < 0) || 
        (y >= _height) || (y + srcHeight < 0))
    {
        return;
    }
    
    // Clip X
    if (x < 0) { srcX += -x; srcWidth += x; x = 0; }
    if (x + srcWidth >= _width) { srcWidth += _width - (x + srcWidth); }
    
    // Clip Y
    if (y  < 0) {srcY += -y; srcHeight += y; y = 0; }  
    if (y + srcHeight >= _height) { srcHeight += _height - (y + srcHeight); }
    
    uint8_t fch = foregroundColor >> 8;
    uint8_t fcl = foregroundColor;
    uint8_t bch = backgroundColor >> 8;
    uint8_t bcl = backgroundColor;
    
    clip(x, y, srcWidth, srcHeight);
    
    int offset = (bmp.getStride() * srcY) + (srcX / 8);
    int startbits = srcX % 8;
    
    beginBatchCommand(CMD_RAMWR);
    for(int r = 0; r < srcHeight; ++r)
    {
        const uint8_t *p = bmp.getBitmapData() + offset;
        
        uint8_t b = *p;
        for (int c = 0, shift = startbits; c < srcWidth; ++c, ++shift)
        {
            if (shift == 8) 
            {
                shift = 0;
                b = *++p;
            }
            
            if ((b << shift) & 0x80)                            
            {
                writeBatchData(fch, fcl);                
            }
            else
            {
                writeBatchData(bch, bcl);                
            }
        }   
        offset += bmp.getStride();             
    }
    endBatchCommand();
}

void LCD_ST7735::drawBitmap(int x, int y, const uint8_t *pbmp, int srcX, int srcY, int srcWidth, int srcHeight, uint16_t foregroundColor, uint16_t backgroundColor)
{
    // Clip if out of screen    
    if ((x >= _width) || (x + srcWidth < 0) || 
        (y >= _height) || (y + srcHeight < 0))
    {
        return;
    }
    
    // Clip X
    if (x < 0) { srcX += -x; srcWidth += x; x = 0; }
    if (x + srcWidth >= _width) { srcWidth += _width - (x + srcWidth); }
    
    // Clip Y
    if (y  < 0) {srcY += -y; srcHeight += y; y = 0; }  
    if (y + srcHeight >= _height) { srcHeight += _height - (y + srcHeight); }
    
    uint8_t fch = foregroundColor >> 8;
    uint8_t fcl = foregroundColor;
    uint8_t bch = backgroundColor >> 8;
    uint8_t bcl = backgroundColor;
    
    uint16_t w = (*(pbmp + 1) << 8) | (*(pbmp + 0));    
    pbmp += 4;
    
    int stride = w / 8;
    clip(x, y, srcWidth, srcHeight);
    
    int offset = (stride * srcY) + (srcX / 8);
    int startbits = srcX % 8;
    
    beginBatchCommand(CMD_RAMWR);
    for(int r = 0; r < srcHeight; ++r)
    {
        const uint8_t *p = pbmp + offset;
        
        uint8_t b = *p;
        for (int c = 0, shift = startbits; c < srcWidth; ++c, ++shift)
        {
            if (shift == 8) 
            {
                shift = 0;
                b = *++p;
            }
            
            if ((b << shift) & 0x80)                            
            {
                writeBatchData(fch, fcl);                
            }
            else
            {
                writeBatchData(bch, bcl);                
            }
        }   
        offset += stride;             
    }
    endBatchCommand();
}

void LCD_ST7735::setForegroundColor(uint16_t color)
{
    _foregroundColorHigh = color >> 8;
    _foregroundColorLow = color;
}

void LCD_ST7735::setBackgroundColor(uint16_t color)
{
    _backgroundColorHigh = color >> 8;
    _backgroundColorLow = 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::selectDevice()
{
    _spi.prepareFastSPI();
}

void LCD_ST7735::drawVertLine(int x1, int y1, int y2, uint16_t color)
{
    clipRect(x1, y1, x1, y2);
    beginBatchCommand(CMD_RAMWR);
    int c = (y2 - y1) << 1;
    uint8_t colorHigh = color >> 8;
    uint8_t colorLow = color;
    for (int i = 0; i < c; ++i)
    {
        writeBatchData(colorHigh, colorLow);        
    }
    endBatchCommand();
}

void LCD_ST7735::drawHorizLine(int x1, int y1, int x2, uint16_t color)
{    
    clipRect(x1, y1, x2, y1);
    beginBatchCommand(CMD_RAMWR);
    int c = (x2 - x1) << 1;
    uint8_t colorHigh = color >> 8;
    uint8_t colorLow = color;
    for (int i = 0; i < c; ++i)
    {
        writeBatchData(colorHigh, colorLow);
    }
    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(_foregroundColorHigh);
                writeBatchData(_foregroundColorLow);
            }
            else
            {
                writeBatchData(_backgroundColorHigh);
                writeBatchData(_backgroundColorLow);
            }
                
            b <<= 1;
        }
    }
    endBatchCommand();
}

void LCD_ST7735::initDisplay()
{
    selectDevice();
    reset();
    
    writeCommand(CMD_SLPOUT);
    
    write(CMD_FRMCTR1, (uint8_t[]){0x01, 0x2c, 0x2d}, 3);
    write(CMD_FRMCTR2, (uint8_t[]){0x01, 0x2c, 0x2d}, 3);
    write(CMD_FRMCTR3, (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[]){0xc0 | _colorFilter}, 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
    writeCommand(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;
    //uint8_t x1h = (uint8_t)(x1 >> 8);
    uint8_t x2l = (uint8_t)x2;
    //uint8_t x2h = (uint8_t)(x2 >> 8);
    write(CMD_CASET, (uint8_t[]){0, x1l, 0, x2l}, 4);    
    
    uint8_t y1l = (uint8_t)y1;
    //uint8_t y1h = (uint8_t)(y1 >> 8);
    uint8_t y2l = (uint8_t)y2;
    //uint8_t y2h = (uint8_t)(y2 >> 8);
    write(CMD_RASET, (uint8_t[]){0, y1l, 0, y2l}, 4);    
}
        
void LCD_ST7735::writeCommand(uint8_t cmd)
{
    _cs = 0;
    _ds = 0;    
    _spi.fastWrite(cmd);
    _spi.waitWhileBusy();
    _spi.clearRx();
    _cs = 1;
}

void LCD_ST7735::write(uint8_t cmd, uint8_t data[], int dataLen)
{
    _cs = 0;
    _ds = 0;    
    _spi.fastWrite(cmd);
    _spi.waitWhileBusy();
    if (data != NULL & dataLen > 0)
    {
        _ds = 1;        
        for(int i = 0; i < dataLen; ++i)
        {            
            _spi.fastWrite(data[i]); 
        }        
        _spi.waitWhileBusy();
        _ds = 0; 
    }    
    _spi.clearRx();
    _cs = 1;
}

void LCD_ST7735::write(uint8_t cmd, uint16_t data)
{
    _cs = 0; 
    _ds = 0;    
    _spi.fastWrite(cmd);       
    _spi.waitWhileBusy();
    _ds = 1;            
    _spi.fastWrite(data >> 8);
    _spi.fastWrite(data);
    _spi.waitWhileBusy();
    _spi.clearRx();
    _ds = 0;     
    _cs = 1;
}

void LCD_ST7735::beginBatchCommand(uint8_t cmd)
{
    _cs = 0;
    _ds = 0;        
    _spi.fastWrite(cmd);   
    _spi.waitWhileBusy();
    _ds = 1;
}

void LCD_ST7735::writeBatchData(uint8_t data)
{
    _spi.fastWrite(data);
}

void LCD_ST7735::writeBatchData(uint8_t dataHigh, uint8_t dataLow)
{
    _spi.fastWrite(dataHigh);
    _spi.fastWrite(dataLow);
}


void LCD_ST7735::writeBatchData(uint16_t data)
{
    _spi.fastWrite(data >> 8);
    _spi.fastWrite(data); 
}

void LCD_ST7735::endBatchCommand()
{
    _spi.waitWhileBusy();
    _spi.clearRx();
    _ds = 0; 
    _cs = 1; 
}