Arducam_UTFT_SPI_Library

Dependents:   DigitalCamera_OV5642_WIZwiki-W7500 Prelude_OV5642_dev

UTFT_SPI.cpp

Committer:
justinkim
Date:
2015-10-29
Revision:
0:53f8d6b23687

File content as of revision 0:53f8d6b23687:

/*
  UTFT.cpp - Arduino library support for Color TFT LCD Boards
  This is special porting for ArduCAM shield LCD screen. 
  Use SPI bus interface and SSD1289 controller. Only work on 
  ArduCAM shield Rev.C.
  For more information about ArduCAM shield please visit
  www.arducam.com
  Copyright (C)2010-2014 Henning Karlsen. All right reserved
  
  This library is the continuation of my ITDB02_Graph, ITDB02_Graph16
  and RGB_GLCD libraries for Arduino and chipKit. As the number of 
  supported display modules and controllers started to increase I felt 
  it was time to make a single, universal library as it will be much 
  easier to maintain in the future.

  Basic functionality of this library was origianlly based on the 
  demo-code provided by ITead studio (for the ITDB02 modules) and 
  NKC Electronics (for the RGB GLCD module/shield).

  This library supports a number of 8bit, 16bit and serial graphic 
  displays, and will work with both Arduino and chipKit boards. For a 
  full list of tested display modules and controllers, see the 
  document UTFT_Supported_display_modules_&_controllers.pdf.

  When using 8bit and 16bit display modules there are some 
  requirements you must adhere to. These requirements can be found 
  in the document UTFT_Requirements.pdf.
  There are no special requirements when using serial displays.

  You can always find the latest version of the library at 
  http://electronics.henningkarlsen.com/

  If you make any modifications or improvements to the code, I would 
  appreciate that you share the code with me so that I might include 
  it in the next release. I can be contacted through 
  http://electronics.henningkarlsen.com/contact.php.

  This library is free software; you can redistribute it and/or
  modify it under the terms of the GNU Lesser General Public
  License as published by the Free Software Foundation; either
  version 2.1 of the License, or (at your option) any later version.

  This library is distributed in the hope that it will be useful,
  but WITHOUT ANY WARRANTY; without even the implied warranty of
  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
  Lesser General Public License for more details.

  You should have received a copy of the GNU Lesser General Public
  License along with this library; if not, write to the Free Software
  Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA  02110-1301  USA
*/

#include "mbed.h"
#include "UTFT_SPI.h"

ArduLCD::ArduLCD(PinName mosi, PinName miso, PinName sck, PinName cs)
        : spi(mosi,miso,sck), _cs(cs)
{   
    //Must initialize the Bus default status
    _cs = 1;
    model = SSD1289;
    disp_x_size=239;
    disp_y_size=319;
    display_transfer_mode=8;

    display_model=model;

    //_set_direction_registers(display_transfer_mode);
    //P_CS  = portOutputRegister(digitalPinToPort(CS));
    //B_CS  = digitalPinToBitMask(CS);
    //pinMode(CS,OUTPUT);
}

int ArduLCD::bus_write(int address, int value) 
{
  _cs = 0;
  spi.write(address);
  spi.write(value);
  _cs = 1;
  return value;
}

uint8_t ArduLCD::bus_read(int address) 
{
  uint8_t value = 0;
  _cs = 0;
  spi.write(address);
  value = spi.write(0x00);
  _cs = 1;
  return value;
}

void ArduLCD::LCD_Write_COM(char VL)  
{   
    bus_write(0xBE, VL);
}

void ArduLCD::LCD_Write_DATA(char VH,char VL)
{
    bus_write(0xBF, VH);
    bus_write(0xBF, VL);
}

void ArduLCD::LCD_Write_COM_DATA(char com1,int dat1)
{
     LCD_Write_COM(com1);
     LCD_Write_DATA(dat1>>8,dat1);
     
}

void ArduLCD::LCD_Writ_Bus(char VH,char VL)
{
    LCD_Write_DATA(VH,VL);
}

void ArduLCD::InitLCD(uint8_t orientation)
{
    orient=orientation;

    LCD_Write_COM_DATA(0x00,0x0001);
    LCD_Write_COM_DATA(0x03,0xA8A4);
    LCD_Write_COM_DATA(0x0C,0x0000);
    LCD_Write_COM_DATA(0x0D,0x080C);
    LCD_Write_COM_DATA(0x0E,0x2B00);
    LCD_Write_COM_DATA(0x1E,0x00B7);
    LCD_Write_COM_DATA(0x01,0x693F);
    LCD_Write_COM_DATA(0x02,0x0600);
    LCD_Write_COM_DATA(0x10,0x0000);
    LCD_Write_COM_DATA(0x11,0x6078);
    LCD_Write_COM_DATA(0x05,0x0000);
    LCD_Write_COM_DATA(0x06,0x0000);
    LCD_Write_COM_DATA(0x16,0xEF1C);
    LCD_Write_COM_DATA(0x17,0x0003);
    LCD_Write_COM_DATA(0x07,0x0233);
    LCD_Write_COM_DATA(0x0B,0x0000);
    LCD_Write_COM_DATA(0x0F,0x0000);
    LCD_Write_COM_DATA(0x41,0x0000);
    LCD_Write_COM_DATA(0x42,0x0000);
    LCD_Write_COM_DATA(0x48,0x0000);
    LCD_Write_COM_DATA(0x49,0x013F);
    LCD_Write_COM_DATA(0x4A,0x0000);
    LCD_Write_COM_DATA(0x4B,0x0000);
    LCD_Write_COM_DATA(0x44,0xEF00);
    LCD_Write_COM_DATA(0x45,0x0000);
    LCD_Write_COM_DATA(0x46,0x013F);
    LCD_Write_COM_DATA(0x30,0x0707);
    LCD_Write_COM_DATA(0x31,0x0204);
    LCD_Write_COM_DATA(0x32,0x0204);
    LCD_Write_COM_DATA(0x33,0x0502);
    LCD_Write_COM_DATA(0x34,0x0507);
    LCD_Write_COM_DATA(0x35,0x0204);
    LCD_Write_COM_DATA(0x36,0x0204);
    LCD_Write_COM_DATA(0x37,0x0502);
    LCD_Write_COM_DATA(0x3A,0x0302);
    LCD_Write_COM_DATA(0x3B,0x0302);
    LCD_Write_COM_DATA(0x23,0x0000);
    LCD_Write_COM_DATA(0x24,0x0000);
    LCD_Write_COM_DATA(0x25,0x8000);
    LCD_Write_COM_DATA(0x4f,0x0000);
    LCD_Write_COM_DATA(0x4e,0x0000);
    LCD_Write_COM(0x22);

    //setColor(255, 255, 255);
    //setBackColor(0, 0, 0);
    cfont.font=0;
    clrScr();
}

void ArduLCD::setXY(uint16_t x1, uint16_t y1, uint16_t x2, uint16_t y2)
{
    if (orient==LANDSCAPE)
    {
        swap(uint16_t, x1, y1);
        swap(uint16_t, x2, y2)
        y1=disp_y_size-y1;
        y2=disp_y_size-y2;
        swap(uint16_t, y1, y2)
    }
    
    LCD_Write_COM_DATA(0x44,(x2<<8)+x1);
    LCD_Write_COM_DATA(0x45,y1);
    LCD_Write_COM_DATA(0x46,y2);
    LCD_Write_COM_DATA(0x4e,x1);
    LCD_Write_COM_DATA(0x4f,y1);
    LCD_Write_COM(0x22);
}

void ArduLCD::clrXY()
{
    if (orient==PORTRAIT)
        setXY(0,0,disp_x_size,disp_y_size);
    else
        setXY(0,0,disp_y_size,disp_x_size);
}

void ArduLCD::resetXY()
{
    clrXY();
}

void ArduLCD::drawRect(int x1, int y1, int x2, int y2)
{
    if (x1>x2)
    {
        swap(int, x1, x2);
    }
    if (y1>y2)
    {
        swap(int, y1, y2);
    }

    drawHLine(x1, y1, x2-x1);
    drawHLine(x1, y2, x2-x1);
    drawVLine(x1, y1, y2-y1);
    drawVLine(x2, y1, y2-y1);
}

void ArduLCD::drawRoundRect(int x1, int y1, int x2, int y2)
{
    if (x1>x2)
    {
        swap(int, x1, x2);
    }
    if (y1>y2)
    {
        swap(int, y1, y2);
    }
    if ((x2-x1)>4 && (y2-y1)>4)
    {
        drawPixel(x1+1,y1+1);
        drawPixel(x2-1,y1+1);
        drawPixel(x1+1,y2-1);
        drawPixel(x2-1,y2-1);
        drawHLine(x1+2, y1, x2-x1-4);
        drawHLine(x1+2, y2, x2-x1-4);
        drawVLine(x1, y1+2, y2-y1-4);
        drawVLine(x2, y1+2, y2-y1-4);
    }
}

void ArduLCD::fillRect(int x1, int y1, int x2, int y2)
{
    if (x1>x2)
    {
        swap(int, x1, x2);
    }
    if (y1>y2)
    {
        swap(int, y1, y2);
    }
    
    if (orient==PORTRAIT)
    {
        for (int i=0; i<((y2-y1)/2)+1; i++)
        {
            drawHLine(x1, y1+i, x2-x1);
            drawHLine(x1, y2-i, x2-x1);
        }
    }
    else
    {
        for (int i=0; i<((x2-x1)/2)+1; i++)
        {
            drawVLine(x1+i, y1, y2-y1);
            drawVLine(x2-i, y1, y2-y1);
        }
    }
}

void ArduLCD::fillRoundRect(int x1, int y1, int x2, int y2)
{
    if (x1>x2)
    {
        swap(int, x1, x2);
    }
    if (y1>y2)
    {
        swap(int, y1, y2);
    }

    if ((x2-x1)>4 && (y2-y1)>4)
    {
        for (int i=0; i<((y2-y1)/2)+1; i++)
        {
            switch(i)
            {
            case 0:
                drawHLine(x1+2, y1+i, x2-x1-4);
                drawHLine(x1+2, y2-i, x2-x1-4);
                break;
            case 1:
                drawHLine(x1+1, y1+i, x2-x1-2);
                drawHLine(x1+1, y2-i, x2-x1-2);
                break;
            default:
                drawHLine(x1, y1+i, x2-x1);
                drawHLine(x1, y2-i, x2-x1);
            }
        }
    }
}

void ArduLCD::drawCircle(int x, int y, int radius)
{
    int f = 1 - radius;
    int ddF_x = 1;
    int ddF_y = -2 * radius;
    int x1 = 0;
    int y1 = radius;
 
    _cs = 0;
    setXY(x, y + radius, x, y + radius);
    LCD_Write_DATA(fch,fcl);
    setXY(x, y - radius, x, y - radius);
    LCD_Write_DATA(fch,fcl);
    setXY(x + radius, y, x + radius, y);
    LCD_Write_DATA(fch,fcl);
    setXY(x - radius, y, x - radius, y);
    LCD_Write_DATA(fch,fcl);
 
    while(x1 < y1)
    {
        if(f >= 0) 
        {
            y1--;
            ddF_y += 2;
            f += ddF_y;
        }
        x1++;
        ddF_x += 2;
        f += ddF_x;    
        setXY(x + x1, y + y1, x + x1, y + y1);
        LCD_Write_DATA(fch,fcl);
        setXY(x - x1, y + y1, x - x1, y + y1);
        LCD_Write_DATA(fch,fcl);
        setXY(x + x1, y - y1, x + x1, y - y1);
        LCD_Write_DATA(fch,fcl);
        setXY(x - x1, y - y1, x - x1, y - y1);
        LCD_Write_DATA(fch,fcl);
        setXY(x + y1, y + x1, x + y1, y + x1);
        LCD_Write_DATA(fch,fcl);
        setXY(x - y1, y + x1, x - y1, y + x1);
        LCD_Write_DATA(fch,fcl);
        setXY(x + y1, y - x1, x + y1, y - x1);
        LCD_Write_DATA(fch,fcl);
        setXY(x - y1, y - x1, x - y1, y - x1);
        LCD_Write_DATA(fch,fcl);
    }
    _cs = 1;
    clrXY();
}

void ArduLCD::fillCircle(int x, int y, int radius)
{
    for(int y1=-radius; y1<=0; y1++) 
        for(int x1=-radius; x1<=0; x1++)
            if(x1*x1+y1*y1 <= radius*radius) 
            {
                drawHLine(x+x1, y+y1, 2*(-x1));
                drawHLine(x+x1, y-y1, 2*(-x1));
                break;
            }
}

void ArduLCD::clrScr()
{
    long i;
    
    clrXY();

    for (i=0; i<((disp_x_size+1)*(disp_y_size+1)); i++)
    {
        if (display_transfer_mode!=1)
            LCD_Writ_Bus(0x00,0x00);
        else
        {
            LCD_Writ_Bus(1,0);
            LCD_Writ_Bus(1,0);
            
            //LCD_Writ_Bus(00,0x55);
        }
        //delay(1);
#if defined(ESP8266)    
      yield();  
#endif    
    }
}

void ArduLCD::fillScr(uint8_t r, uint8_t g, uint8_t b)
{
    uint16_t color = ((r&248)<<8 | (g&252)<<3 | (b&248)>>3);
    fillScr(color);
}

void ArduLCD::fillScr(uint16_t color)
{
    long i;
    char ch, cl;
    
    ch=uint8_t(color>>8);
    cl=uint8_t(color & 0xFF);

    clrXY();
    
    for (i=0; i<((disp_x_size+1)*(disp_y_size+1)); i++)
    {
        if (display_transfer_mode!=1)
            LCD_Writ_Bus(ch,cl);
        else
        {
            LCD_Writ_Bus(1,ch);
            LCD_Writ_Bus(1,cl);
        }
#if defined(ESP8266)    
      yield();  
#endif          
    }

}

void ArduLCD::setColor(uint8_t r, uint8_t g, uint8_t b)
{
    fch=((r&248)|g>>5);
    fcl=((g&28)<<3|b>>3);
}

void ArduLCD::setColor(uint16_t color)
{
    fch=uint8_t(color>>8);
    fcl=uint8_t(color & 0xFF);
}

uint16_t ArduLCD::getColor()
{
    return (fch<<8) | fcl;
}

void ArduLCD::setBackColor(uint8_t r, uint8_t g, uint8_t b)
{
    bch=((r&248)|g>>5);
    bcl=((g&28)<<3|b>>3);
    _transparent=false;
}

void ArduLCD::setBackColor(uint32_t color)
{
    if (color==VGA_TRANSPARENT)
        _transparent=true;
    else
    {
        bch=uint8_t(color>>8);
        bcl=uint8_t(color & 0xFF);
        _transparent=false;
    }
}

uint16_t ArduLCD::getBackColor()
{
    return (bch<<8) | bcl;
}

void ArduLCD::setPixel(uint16_t color)
{
    LCD_Write_DATA((color>>8),(color&0xFF));    // rrrrrggggggbbbbb
}

void ArduLCD::drawPixel(int x, int y)
{
    setXY(x, y, x, y);
    setPixel((fch<<8)|fcl);
    clrXY();
}

void ArduLCD::drawLine(int x1, int y1, int x2, int y2)
{
    if (y1==y2)
        drawHLine(x1, y1, x2-x1);
    else if (x1==x2)
        drawVLine(x1, y1, y2-y1);
    else
    {
        unsigned int    dx = (x2 > x1 ? x2 - x1 : x1 - x2);
        short           xstep =  x2 > x1 ? 1 : -1;
        unsigned int    dy = (y2 > y1 ? y2 - y1 : y1 - y2);
        short           ystep =  y2 > y1 ? 1 : -1;
        int             col = x1, row = y1;

        if (dx < dy)
        {
            int t = - (dy >> 1);
            while (true)
            {
                setXY (col, row, col, row);
                LCD_Write_DATA (fch, fcl);
                if (row == y2)
                    return;
                row += ystep;
                t += dx;
                if (t >= 0)
                {
                    col += xstep;
                    t   -= dy;
                }
            } 
        }
        else
        {
            int t = - (dx >> 1);
            while (true)
            {
                setXY (col, row, col, row);
                LCD_Write_DATA (fch, fcl);
                if (col == x2)
                    return;
                col += xstep;
                t += dy;
                if (t >= 0)
                {
                    row += ystep;
                    t   -= dx;
                }
            } 
        }
    }
    clrXY();
}

void ArduLCD::drawHLine(int x, int y, int l)
{
    if (l<0)
    {
        l = -l;
        x -= l;
    }
    setXY(x, y, x+l, y);
    if (display_transfer_mode == 16)
    {
        _fast_fill_16(fch,fcl,l);
    }
    else if ((display_transfer_mode==8) and (fch==fcl))
    {
        _fast_fill_8(fch,l);
    }
    else
    {
        for (int i=0; i<l+1; i++)
        {
            LCD_Write_DATA(fch, fcl);
        }
    }
    clrXY();
}

void ArduLCD::drawVLine(int x, int y, int l)
{
    if (l<0)
    {
        l = -l;
        y -= l;
    }
    setXY(x, y, x, y+l);
    if (display_transfer_mode == 16)
    {
        _fast_fill_16(fch,fcl,l);
    }
    else if ((display_transfer_mode==8) and (fch==fcl))
    {
        _fast_fill_8(fch,l);
    }
    else
    {
        for (int i=0; i<l+1; i++)
        {
            LCD_Write_DATA(fch, fcl);
        }
    }
    clrXY();
}
/*
void ArduLCD::printChar(uint8_t c, int x, int y)
{
    uint8_t i,ch;
    uint16_t j;
    uint16_t temp; 
  
    if (!_transparent)
    {
        if (orient==PORTRAIT)
        {
            setXY(x,y,x+cfont.x_size-1,y+cfont.y_size-1);
      
            temp=((c-cfont.offset)*((cfont.x_size/8)*cfont.y_size))+4;
            for(j=0;j<((cfont.x_size/8)*cfont.y_size);j++)
            {
                ch=pgm_read_byte(&cfont.font[temp]);
                for(i=0;i<8;i++)
                {   
                    if((ch&(1<<(7-i)))!=0)   
                    {
                        setPixel((fch<<8)|fcl);
                    } 
                    else
                    {
                        setPixel((bch<<8)|bcl);
                    }   
                }
                temp++;
            }
        }
        else
        {
            temp=((c-cfont.offset)*((cfont.x_size/8)*cfont.y_size))+4;

            for(j=0;j<((cfont.x_size/8)*cfont.y_size);j+=(cfont.x_size/8))
            {
                setXY(x,y+(j/(cfont.x_size/8)),x+cfont.x_size-1,y+(j/(cfont.x_size/8)));
                for (int zz=(cfont.x_size/8)-1; zz>=0; zz--)
                {
                    ch=pgm_read_byte(&cfont.font[temp+zz]);
                    for(i=0;i<8;i++)
                    {   
                        if((ch&(1<<i))!=0)   
                        {
                            setPixel((fch<<8)|fcl);
                        } 
                        else
                        {
                            setPixel((bch<<8)|bcl);
                        }   
                    }
                }
                temp+=(cfont.x_size/8);
            }
        }
    }
    else
    {
        temp=((c-cfont.offset)*((cfont.x_size/8)*cfont.y_size))+4;
        for(j=0;j<cfont.y_size;j++) 
        {
            for (int zz=0; zz<(cfont.x_size/8); zz++)
            {
                ch=pgm_read_byte(&cfont.font[temp+zz]); 
                for(i=0;i<8;i++)
                {   
                    setXY(x+i+(zz*8),y+j,x+i+(zz*8)+1,y+j+1);
                
                    if((ch&(1<<(7-i)))!=0)   
                    {
                        setPixel((fch<<8)|fcl);
                    } 
                }
            }
            temp+=(cfont.x_size/8);
        }
    }
    clrXY();
}

void ArduLCD::rotateChar(uint8_t c, int x, int y, int pos, int deg)
{
    uint8_t i,j,ch;
    uint16_t temp; 
    int newx,newy;
    double radian;
    radian=deg*0.0175;  

    temp=((c-cfont.offset)*((cfont.x_size/8)*cfont.y_size))+4;
    for(j=0;j<cfont.y_size;j++) 
    {
        for (int zz=0; zz<(cfont.x_size/8); zz++)
        {
            ch=pgm_read_byte(&cfont.font[temp+zz]); 
            for(i=0;i<8;i++)
            {   
                newx=x+(((i+(zz*8)+(pos*cfont.x_size))*cos(radian))-((j)*sin(radian)));
                newy=y+(((j)*cos(radian))+((i+(zz*8)+(pos*cfont.x_size))*sin(radian)));

                setXY(newx,newy,newx+1,newy+1);
                
                if((ch&(1<<(7-i)))!=0)   
                {
                    setPixel((fch<<8)|fcl);
                } 
                else  
                {
                    if (!_transparent)
                        setPixel((bch<<8)|bcl);
                }   
            }
        }
        temp+=(cfont.x_size/8);
    }
    clrXY();
}

void ArduLCD::print(char *st, int x, int y, int deg)
{
    int stl, i;

    stl = strlen(st);

    if (orient==PORTRAIT)
    {
    if (x==RIGHT)
        x=(disp_x_size+1)-(stl*cfont.x_size);
    if (x==CENTER)
        x=((disp_x_size+1)-(stl*cfont.x_size))/2;
    }
    else
    {
    if (x==RIGHT)
        x=(disp_y_size+1)-(stl*cfont.x_size);
    if (x==CENTER)
        x=((disp_y_size+1)-(stl*cfont.x_size))/2;
    }

    for (i=0; i<stl; i++)
        if (deg==0)
            printChar(*st++, x + (i*(cfont.x_size)), y);
        else
            rotateChar(*st++, x, y, i, deg);
}

void ArduLCD::print(string st, int x, int y, int deg)
{
    char buf[st.length()+1];

    st.toCharArray(buf, st.length()+1);
    print(buf, x, y, deg);
}

void ArduLCD::printNumI(long num, int x, int y, int length, char filler)
{
    char buf[25];
    char st[27];
    bool neg=false;
    int c=0, f=0;
  
    if (num==0)
    {
        if (length!=0)
        {
            for (c=0; c<(length-1); c++)
                st[c]=filler;
            st[c]=48;
            st[c+1]=0;
        }
        else
        {
            st[0]=48;
            st[1]=0;
        }
    }
    else
    {
        if (num<0)
        {
            neg=true;
            num=-num;
        }
      
        while (num>0)
        {
            buf[c]=48+(num % 10);
            c++;
            num=(num-(num % 10))/10;
        }
        buf[c]=0;
      
        if (neg)
        {
            st[0]=45;
        }
      
        if (length>(c+neg))
        {
            for (int i=0; i<(length-c-neg); i++)
            {
                st[i+neg]=filler;
                f++;
            }
        }

        for (int i=0; i<c; i++)
        {
            st[i+neg+f]=buf[c-i-1];
        }
        st[c+neg+f]=0;

    }

    print(st,x,y);
}

void ArduLCD::printNumF(double num, uint8_t dec, int x, int y, char divider, int length, char filler)
{
    char st[27];
    bool neg=false;

    if (dec<1)
        dec=1;
    else if (dec>5)
        dec=5;

    if (num<0)
        neg = true;

    _convert_float(st, num, length, dec);

    if (divider != '.')
    {
        for (int i=0; i<sizeof(st); i++)
            if (st[i]=='.')
                st[i]=divider;
    }

    if (filler != ' ')
    {
        if (neg)
        {
            st[0]='-';
            for (int i=1; i<sizeof(st); i++)
                if ((st[i]==' ') || (st[i]=='-'))
                    st[i]=filler;
        }
        else
        {
            for (int i=0; i<sizeof(st); i++)
                if (st[i]==' ')
                    st[i]=filler;
        }
    }

    print(st,x,y);
}

void ArduLCD::setFont(uint8_t* font)
{
    cfont.font=font;
    cfont.x_size=fontbyte(0);
    cfont.y_size=fontbyte(1);
    cfont.offset=fontbyte(2);
    cfont.numchars=fontbyte(3);
}

uint8_t* ArduLCD::getFont()
{
    return cfont.font;
}

uint8_t ArduLCD::getFontXsize()
{
    return cfont.x_size;
}

uint8_t ArduLCD::getFontYsize()
{
    return cfont.y_size;
}*/

void ArduLCD::drawBitmap(int x, int y, int sx, int sy, bitmapdatatype data, int scale)
{
    unsigned int col;
    int tx, ty, tc, tsx, tsy;

    if (scale==1)
    {
        if (orient==PORTRAIT)
        {
            setXY(x, y, x+sx-1, y+sy-1);
            for (tc=0; tc<(sx*sy); tc++)
            {
                col=pgm_read_word(&data[tc]);
                LCD_Write_DATA(col>>8,col & 0xff);
            }
        }
        else
        {
            for (ty=0; ty<sy; ty++)
            {
                setXY(x, y+ty, x+sx-1, y+ty);
                for (tx=sx-1; tx>=0; tx--)
                {
                    col=pgm_read_word(&data[(ty*sx)+tx]);
                    LCD_Write_DATA(col>>8,col & 0xff);
                }
            }
        }
    }
    else
    {
        if (orient==PORTRAIT)
        {
            for (ty=0; ty<sy; ty++)
            {
                setXY(x, y+(ty*scale), x+((sx*scale)-1), y+(ty*scale)+scale);
                for (tsy=0; tsy<scale; tsy++)
                    for (tx=0; tx<sx; tx++)
                    {
                        col=pgm_read_word(&data[(ty*sx)+tx]);
                        for (tsx=0; tsx<scale; tsx++)
                            LCD_Write_DATA(col>>8,col & 0xff);
                    }
            }
        }
        else
        {
            for (ty=0; ty<sy; ty++)
            {
                for (tsy=0; tsy<scale; tsy++)
                {
                    setXY(x, y+(ty*scale)+tsy, x+((sx*scale)-1), y+(ty*scale)+tsy);
                    for (tx=sx-1; tx>=0; tx--)
                    {
                        col=pgm_read_word(&data[(ty*sx)+tx]);
                        for (tsx=0; tsx<scale; tsx++)
                            LCD_Write_DATA(col>>8,col & 0xff);
                    }
                }
            }
        }
    }
    clrXY();
}

void ArduLCD::drawBitmap(int x, int y, int sx, int sy, bitmapdatatype data, int deg, int rox, int roy)
{
    unsigned int col;
    int tx, ty, newx, newy;
    double radian;
    radian=deg*0.0175;  

    if (deg==0)
        drawBitmap(x, y, sx, sy, data);
    else
    {
        for (ty=0; ty<sy; ty++)
            for (tx=0; tx<sx; tx++)
            {
                col=pgm_read_word(&data[(ty*sx)+tx]);

                newx=x+rox+(((tx-rox)*cos(radian))-((ty-roy)*sin(radian)));
                newy=y+roy+(((ty-roy)*cos(radian))+((tx-rox)*sin(radian)));

                setXY(newx, newy, newx, newy);
                LCD_Write_DATA(col>>8,col & 0xff);
            }
    }
    clrXY();
}

void ArduLCD::lcdOff()
{

}

void ArduLCD::lcdOn()
{

}

void ArduLCD::setContrast(char c)
{

}

int ArduLCD::getDisplayXSize()
{
    if (orient==PORTRAIT)
        return disp_x_size+1;
    else
        return disp_y_size+1;
}

int ArduLCD::getDisplayYSize()
{
    if (orient==PORTRAIT)
        return disp_y_size+1;
    else
        return disp_x_size+1;
}

void ArduLCD::_fast_fill_16(int ch, int cl, long pix)
{

}

void ArduLCD::_fast_fill_8(int ch, long pix)
{

}

void ArduLCD::setBrightness(uint8_t br)
{

}

void ArduLCD::setDisplayPage(uint8_t page)
{

}

void ArduLCD::setWritePage(uint8_t page)
{

}

void ArduLCD::_convert_float(char *buf, double num, int width, uint8_t prec)
{
    
}