Version 6.0. Animaiton demo.

Dependents:   MIP8f_FRDM_Animation_sample

MIP8F_SPI_Ver6.0

Ver6.0 Addtional function is animation code sample.

MIP8F_SPI.cpp

Committer:
JDI_Mbed_Team
Date:
5 months ago
Revision:
6:4bfbc7e50577
Parent:
5:8cc8e00fed46

File content as of revision 6:4bfbc7e50577:

/**
* @file MIP8F_SPI.cpp
* @brief ver5.0 Library source code file: Class for JDI MIP8 display
* @details
* Ver5.0 Addtional function is checking the refresh display speed between 4bit,3bit and 1bit transfer mode 
* Ver4.0 Addtional function is Line buffer version
* Ver3.0 Addtional function is font display
* ver2.0 Addtional function is Monochome display by 1bit mode of SPI transfer.
*
* spi-transfer to Display has 3 mode. 
* 4bit mode is color display, this bit arrange is  R,G,B,x.   R,G,B = R,G,B subpixel bit. x bit is Dummy.
* 3bit mode is color display, this bit arrange is  R,G,B.   R,G,B = R,G,B subpixel bit.  No bit is Dummy.
* 1bit mode is monocrome display,high speed refresh mode. a only Green subpixel of bitmap data is transfered.
*
* <license>
* Copyright 2018 Japan Display Inc.
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*     http://www.apache.org/licenses/LICENSE-2.0
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/

#include "mbed.h"
#include "MIP8F_SPI.h"

// for debug
Serial pc2(USBTX, USBRX); // tx, rx

memLCD8::memLCD8(PinName mosi,PinName miso,PinName sclk,PinName cs,PinName disp,PinName power)
    : _spi(mosi, miso, sclk),_cs(cs),_disp(disp),_power(power)
{

    _power= 0;
    _disp=  0;
    _cs  =  0;
    wait_us(100);

    _power= 1;
    _spi.format(8,0);                // 8bit mode3
    _spi.frequency(2000000);         // 2 Mhz SPI clock
    _spi.write(0x00);                // mbed dummy

    /*
        _cs  = 1;
        command(0x02);   // All crear mode
        _cs  = 0;
    */
    _FixedFontWidth=0;//setting:actual font width display  if _FixedFontWidth !=1: font fixed witdh
#if MOVIEBUFF_MODE    
    //movie_height = 80;
    //movie_width = 80;
    _height = 240;
    _width = 400;
#endif
}

/**
* @brief  set font name
*/
void memLCD8::set_font(unsigned char* f)
{
    font = f;
}

/**
* @brief  set allocation for font display
*/
void memLCD8::locate(int x, int y)
{
    char_x = x;
    char_y = y;
}

/**
* @brief  setting fixed width between charactor and charctor  for font display
*/
void memLCD8::set_FixedFontWidth( unsigned char width )
{
    _FixedFontWidth = width;
}
/**
* @brief  setting Actual width between charactor and charctor  for font display
*/
void memLCD8::set_ActualFontWidth(void)
{
    _FixedFontWidth = 0;
}

/**
* @brief  set Configuration for transfer mode
* @param[in] int transfermode : instruction the transfer data size ,4bit,3bit,1bit and some parameter
*/
void memLCD8::SetTransfermode(int transfermode)
{
    switch(transfermode)
    {
    case TrBIT4:
        TrModeCommand = 0x90;
        TrAdd = 1;
        TrValNum = 1;
        break;
    case TrBIT3:
        TrModeCommand = 0x80;
        TrAdd = 4;
        TrValNum = 3;
        break;
    case TrBIT1:
        TrModeCommand = 0x88;
        TrAdd = 4;
        TrValNum = 1;
        break;
    }
}

/**
* @brief  set a display size ,width ,height
*/
void memLCD8::setWH(int width, int height)
{
    _width  = width;
    _height = height;
}

/**
* @brief  set color data of foreground
*/
void memLCD8::foreground(uint8_t colour)
{
    _foreground = colour;
}

/**
* @brief  set color data of background
*/
void memLCD8::background(uint8_t colour)
{
    _background = colour;
}

/**
* @brief  set the Diaplay On/Off data
*/
void memLCD8::SwDisp(bool ONorOFF)
{
    _disp= ONorOFF;
}

/**
* @brief  transfer a command code to the display by SPI
*/
void memLCD8::command(char command)
{
    wait_us(6);
    _cs  = 1;
    wait_us(6);
    _spi.write(command);//
    _spi.write(0x00);// dummy
    wait_us(6);
    _cs  = 0;
}

/**
* @brief  putc
*/
int memLCD8::_putc(int value)
{
    if (value == '\n') {    // new line
        char_x = 0;
        char_y = char_y + font[3];
        if (char_y >= _height - font[3]) {
            char_y = 0;
        }
    }
#if FRAMEBUFF_MODE
     else {
        character(char_x, char_y, value);
    }
#endif
    return value;
}

/**
* @brief  getc
*/
int memLCD8::_getc()
{
    return -1;
}
/**
* @brief  get color data of background
*/
unsigned char memLCD8::get_Background(void)
{
    return _background;
}
/*
void memLCD8::setmarge(bool ifMarge)
{
    _ifMarge = ifMarge;
}
*/
//////////////////////////////////////////////////////////////////////////////
// line buffer mode
//////////////////////////////////////////////////////////////////////////////
#if LINEBUFF_MODE
/**
* @brief  Transfer One Pixel Data with x,y allocation Line buffer mode
* @param[in] int x : horizontal allocation left to right
* @param[in] uint8_t color : the color data for Drawing  0x0X  x is color data(RGBC) C is not used
*/
void memLCD8::pixel(int x, uint8_t color)
{
    if(!(x % 2)) _dispLINEBUF[x/2] =  _dispLINEBUF[x/2]&0x0F  |  (color << 4)&0xF0 ;   //MASK 0000 1111
    else         _dispLINEBUF[x/2] =  _dispLINEBUF[x/2]&0xF0  |  (color     )&0x0F ;   //MASK 1111 0000
}

/**
* @brief  Transfer Pixel Data from same Line buffer to Display
*/
void memLCD8::writeDISPLinebuffer(void)    // refresh whole display
{

    char pol = 0;
    char command = 0x90; // 8b 1*0xNNNN *=POL x=AutoW  A  1010

    // frame
    for (int i=0; i<_height; i++) {
        // line
        wait_us(6);
        _cs  = 1;
        wait_us(6);
        _spi.write(command | (pol << 6) | (i+1)>>8 ); // COMMAND
        _spi.write((i+1)& 0x00FF ); // V ADDR
        for(int j=0; j<_width/2; j++) _spi.write(_dispLINEBUF[j]);
        _spi.write(0x00); // DUMMY transfer
        _spi.write(0x00); // DUMMY transfer
        wait_us(6);
        _cs  = 0;
        if(pol) pol=0x00;
        else    pol=0x01;
    }
}

/**
* @brief  Transfer Pixel Data from line buffer to Display
* @param[in] int line : set line number for display.
* @param[in] int transfermode : instruction the transfer data size ,4bit,3bit,1bit
*/
void memLCD8::writeDISP(int line,int transfermode)    // refresh gate line display
{

    char pol = 0;
    //char command = 0x90; // 8b 1*0xNNNN *=POL x=AutoW  A  1010
    SetTransfermode(transfermode);
    
    // frame
        // line
        wait_us(6);
        _cs  = 1;
        wait_us(6);
        _spi.write(TrModeCommand | (pol << 6) | (line+1)>>8 ); // COMMAND
        //pc2.printf("com 0x%x\n",TrModeCommand | (pol << 6) | (i+1)>>8);
        
        _spi.write((line+1)& 0x00FF ); // V ADDR
        //pc2.printf("v adr 0x%x\n",(i+1)& 0x00FF);
        
        for(int j=0; j<_width; j+=TrAdd)
        {
            GetPixelValueFromLineBuffer(j,_dispLINEBUF);
            //pc2.printf("data=[%d]{%d][%d]/[%d]\n",j*TrAdd,i,TrValue[0],TrAdd);
            for(int k=0;k<TrValNum;k++)
                _spi.write(TrValue[k]);
        }
        _spi.write(0x00); // DUMMY transfer
        _spi.write(0x00); // DUMMY transfer
//        wait_ms(1);      //1.8Hz simulation
//        wait_ms(2);      //1.35Hz simulation
        wait_us(6);
        _cs  = 0;
        if(pol) pol=0x00;
        else    pol=0x01;

}

/**
* @brief  Get Edited data for SPI transfer from line buffer
* @param[in] int x : horizontal allocation left to right
* @param[in] uint8_t* buff : buffer data for Display
*/
int* memLCD8::GetPixelValueFromLineBuffer(int _x,uint8_t* buff)
{
    //bitmap data = 4bit data => modify transfer data bit size;
    switch(TrModeCommand)
    {
    case 0x90: //TrBIT4:
        // buffer 2pixel/1byte => 2pixel/1byte  buffe 2byte毎進める。
        TrValue[0] = _dispLINEBUF[_x];
        break;
    case 0x80://TrBIT3:
        // buffer 2pixel/1byte => 3pixel-1subpixel/1bye (24 pixel/3byte) buffer 3byte毎進める。
        for(int j=0;j<3;j++) TrValue[j] = 0;
        //for( int i = 0 ; i<12 ; i--)
        {
            //4 bit RGBN(Nは予備) => 3bit RGB
            if( _width/2 > _x )
            {
                TrValue[0] = TrValue[0] | ( ( (_dispLINEBUF[_x    ]&0xE0) ) );
                TrValue[0] = TrValue[0] | ( ( (_dispLINEBUF[_x    ]&0x0E) ) << 1);
            }
            if( _width/2 > _x + 1 )
            {
                TrValue[0] = TrValue[0] | ( ( (_dispLINEBUF[_x + 1]&0xC0) ) >> 6);

                TrValue[1] = TrValue[1] | ( ( (_dispLINEBUF[_x + 1]&0x20) ) << 2);
                TrValue[1] = TrValue[1] | ( ( (_dispLINEBUF[_x + 1]&0x0E) ) << 3);
            }
            if( _width/2 > _x + 2 )
            {
                TrValue[1] = TrValue[1] | ( ( (_dispLINEBUF[ _x + 2]&0xE0) ) >> 4);
                TrValue[1] = TrValue[1] | ( ( (_dispLINEBUF[ _x + 2]&0x08) ) >> 3);

                TrValue[2] = TrValue[2] | ( ( (_dispLINEBUF[_x + 2]&0x06) ) << 5);
            }
            if( _width/2 > _x + 3 )
            {
                TrValue[2] = TrValue[2] | ( ( (_dispLINEBUF[ _x + 3]&0xE0) ) >> 2);
                TrValue[2] = TrValue[2] | ( ( (_dispLINEBUF[_x + 3]&0x0E) ) >> 1);
            }    
        }
        break;
    case 0x88://TrBIT1:
        // buffer 2pixel/1byte => 8 pixel/1byte  buffe 4byte毎進める。
        for(int j=0;j<3;j++) TrValue[j] = 0;
        for(int i = 0 ; i<4 ; i++)
        {
            //Green bit => monochrome bit
            if( _width/2 > _x + i )
            {
                TrValue[0] = TrValue[0] | ( ( (_dispLINEBUF[_x + i]&0x40) == 0 ? 0 : 1 ) << (7-i*2)   );
                TrValue[0] = TrValue[0] | ( ( (_dispLINEBUF[_x + i]&0x04) == 0 ? 0 : 1 ) << (7-i*2)-1 );
                //pc2.printf("[%d+%d][%d]<0x%x>\n",_x,i,_y,_dispBUF[_y* _width/2 + _x + i]);
            }
        }
        break;
    }
    return TrValue;   
}

/**
* @brief  clear line buffer data by background color data
*/
void memLCD8::clsLINEBUF(void)
{

    for (int j=0; j<_width; j++) {
        pixel(j,_background);
    }
}
#endif
//////////////////////////////////////////////////////////////////////////////
// Frame buffer mode
//////////////////////////////////////////////////////////////////////////////
#if FRAMEBUFF_MODE

/**
* @brief  display the text.
* @param[in] int x : horizontal allocation , up-left of text
* @param[in] int y : vertical allocation , bottom-right of text
* @param[in] char* text : strings
*/
int memLCD8::textout(int x,int y,char* text)
{
    int i=0;
    char_x = x;
    char_y = y;

    while(text[i] != 0x00 )
    {
       character(char_x, char_y, text[i]);
       i++;
    }
    return text[i];
}

/**
* @brief  display the oblique text.
* @param[in] int x : horizontal allocation , up-left of text
* @param[in] int y : vertical allocation , bottom-right of text
* @param[in] char* text : strings
*/
int memLCD8::obliqueout(int x,int y,char* text)
{
    int i=0;
    char_x = x;
    char_y = y;

    while(text[i] != 0x00 )
    {
       oblique(char_x, char_y, text[i]);
       i++;
    }
    return text[i];
}

/**
* @brief  dispay a character by bog font. big font is that "char data" byte size is over 0xff.
* @param[in] int x : horizontal allocation , up-left of text
* @param[in] int y : vertical allocation , bottom-right of text
* @param[in] char c : a charactor.
* 
*/
void memLCD8::character(int x, int y, int c)
{
    unsigned int hor,vert,offset0,offset1,bpl,j,i,b; // T.Okamoto modified, for big font
    unsigned int headroffset;// 2018-10-26 added by Y.Saruhashi
    unsigned char* zeichen;
    unsigned char z,w;

    if ((c < 32) || (c > 127)) return;   // test char range

    //for big font
    offset0 = font[0];  // bytes / char uppser adress
    offset1 = font[1];  // bytes / char lower adress
    hor = font[2];      // get hor size of font
    vert = font[3];     // get vert size of font
    bpl = font[4];      // bytes per line
    headroffset = 5;

    if (char_x + hor > _width) {
        char_x = 0;
        char_y = char_y + vert;
        if (char_y >= _height - vert) char_y = 0; // original =  font[2]  T.Okamoto modified, for big font
    }

    zeichen = &font[(c -32) * (offset0 *256 + offset1) + headroffset]; // start of char bitmap // original =  +4  T.Okamoto modified, for big font
    
    if( _FixedFontWidth == 0 ) w = zeichen[0];                          // width of actual char
    else                       w = _FixedFontWidth;                     // fixed width of char

    for (j=0; j<vert; j++) {  //  vert line
        for (i=0; i<hor; i++) {   //  horz line
            z =  zeichen[bpl * i + ((j & 0xF8) >> 3)+1];
            b = 1 << (j & 0x07);
            if (( z & b ) != 0x00)  pixel(x+i,y+j,_foreground);
            else if (_ifMarge == 0) pixel(x+i,y+j,_background);//  _background  -> _LayerBUF[index];

        }
    }
    if ((w + 2) < hor) char_x += w + 2;                  // x offset to next char
    else               char_x += hor;
}

/**
* @brief  dispay a oblique typte character by big font. 
* @param[in] int x : horizontal allocation , up-left of text
* @param[in] int y : vertical allocation , bottom-right of text
* @param[in] char c : a charactor.
*/
void memLCD8::oblique(int x, int y, int c)
{
    unsigned int hor,vert,offset0,offset1,bpl,j,i,b; // T.Okamoto modified, for big font
    unsigned int headroffset;// 2018-10-26 added by Y.Saruhashi
    unsigned char* zeichen;
    unsigned char z,w;
    if ((c < 32) || (c > 127)) return;   // test char range

    //for big font
    offset0 = font[0];  // bytes / char uppser adress
    offset1 = font[1];  // bytes / char lower adress
    hor = font[2];      // get hor size of font
    vert = font[3];     // get vert size of font
    bpl = font[4];      // bytes per line
    headroffset = 5;

    int oblique_raio=3;    // 3 = 30(%percentage) /  10
    int shift_x = (hor*oblique_raio)/10; //oblique pixel x size, top of char;
    int shift_y = vert / shift_x;        //oblique ratio for vertical.  

    if (char_x + hor > _width) {
        char_x = 0;
        char_y = char_y + vert;
        if (char_y >= _height - vert) char_y = 0;
    }
    
    zeichen = &font[(c -32) * (offset0 *256 + offset1) + headroffset];
    if( _FixedFontWidth == 0 ) w = zeichen[0];                          // actual width of char
    else                       w = _FixedFontWidth;                     // fixed width of char

    for (j=0; j<vert; j++) {  //  vert line
        for (i=0; i<hor; i++) {   //  horz line
            z =  zeichen[bpl * i + ((j & 0xF8) >> 3)+1];
            b = 1 << (j & 0x07);
            if (( z & b ) != 0x00)  pixel(x+i+shift_x-(j/shift_y),y+j,_foreground);
            else if (_ifMarge == 0) pixel(x+i+shift_x-(j/shift_y),y+j,_background);//  _background  -> _LayerBUF[index];

        }
    }
    if ((w + 2) < hor) char_x += w + 2;                  // x offset to next char
    else               char_x += hor;
}

/**
* @brief  dispay the image from symbol data
*/
void memLCD8::Symbol(unsigned int x, unsigned int y, unsigned char *symbol)
{
    unsigned int hor,vert,bpl,j,i,b;
    unsigned char* zeichen;
    unsigned char z,w;
    hor = symbol[0];                       // get hor size of font
    vert = symbol[1];                      // get vert size of font
    bpl = symbol[2];                       // bytes per line

    if (char_x + hor > _width) {
        char_x = 0;
        char_y = char_y + vert;
        if (char_y >= _height - symbol[1]) char_y = 0;
    }

    zeichen = &symbol[3];
    w = zeichen[0];                          // actual width of char
    for (j=0; j<vert; j++) {  //  vert line
        for (i=0; i<hor; i++) {   //  horz line
            z =  zeichen[bpl * i + ((j & 0xF8) >> 3)+1];
            b = 1 << (j & 0x07);
            if (( z & b ) != 0x00)  pixel(x+i,y+j,_foreground);
            else if (_ifMarge == 0) pixel(x+i,y+j,_background);//  _background  -> _LayerBUF[index];
        }
    }
    if ((w + 2) < hor) char_x += w + 2;                  // x offset to next char
    else               char_x += hor;
}

/**
* @brief  dispay a circle line by color data
*/
void memLCD8::circle(int x0, int y0, int r, uint8_t color)
{
    int x = -r, y = 0, err = 2-2*r, e2;
    do {
        pixel(x0-x, y0+y,color);
        pixel(x0+x, y0+y,color);
        pixel(x0+x, y0-y,color);
        pixel(x0-x, y0-y,color);
        e2 = err;
        if (e2 <= y) {
            err += ++y*2+1;
            if (-x == y && e2 <= x) e2 = 0;
        }
        if (e2 > x) err += ++x*2+1;
    } while (x <= 0);

}

/**
* @brief  dispay a filled circle by color data
*/
void memLCD8::fillcircle(int x0, int y0, int r, uint8_t color)
{
    int x = -r, y = 0, err = 2-2*r, e2;
    do {
        vline(x0-x, y0-y, y0+y, color);
        vline(x0+x, y0-y, y0+y, color);
        e2 = err;
        if (e2 <= y) {
            err += ++y*2+1;
            if (-x == y && e2 <= x) e2 = 0;
        }
        if (e2 > x) err += ++x*2+1;
    } while (x <= 0);
}

/**
* @brief  dispay a horizontal line by color data
*/
void memLCD8::hline(int x0, int x1, int y, uint8_t color)
{
    int w;
    w = x1 - x0 + 1;
    for (int j=0; j<w; j++) pixel(x0+j, y,color);
}
/**
* @brief  dispay a vertical line by color data
*/
void memLCD8::vline(int x, int y0, int y1, uint8_t color)
{
    int h;
    h = y1 - y0 + 1;
    for (int j=0; j<h; j++) pixel(x, y0+j,color);
}

/**
* @brief  dispay a line by color data
*/
void memLCD8::line(int x0, int y0, int x1, int y1, uint8_t color)
{
    int   dx = 0, dy = 0;
    int   dx_sym = 0, dy_sym = 0;
    int   dx_x2 = 0, dy_x2 = 0;
    int   di = 0;

    dx = x1-x0;
    dy = y1-y0;

    if (dx == 0) {        // vertical line
        if (y1 > y0) vline(x0,y0,y1,color);
        else vline(x0,y1,y0,color);
        return;
    }

    if (dx > 0) {
        dx_sym = 1;
    } else {
        dx_sym = -1;
    }
    if (dy == 0) {        // horizontal line
        if (x1 > x0) hline(x0,x1,y0,color);
        else  hline(x1,x0,y0,color);
        return;
    }

    if (dy > 0) {
        dy_sym = 1;
    } else {
        dy_sym = -1;
    }

    dx = dx_sym*dx;
    dy = dy_sym*dy;

    dx_x2 = dx*2;
    dy_x2 = dy*2;

    if (dx >= dy) {
        di = dy_x2 - dx;
        while (x0 != x1) {

            pixel(x0, y0, color);
            x0 += dx_sym;
            if (di<0) {
                di += dy_x2;
            } else {
                di += dy_x2 - dx_x2;
                y0 += dy_sym;
            }
        }
        pixel(x0, y0, color);
    } else {
        di = dx_x2 - dy;
        while (y0 != y1) {
            pixel(x0, y0, color);
            y0 += dy_sym;
            if (di < 0) {
                di += dx_x2;
            } else {
                di += dx_x2 - dy_x2;
                x0 += dx_sym;
            }
        }
        pixel(x0, y0, color);
    }
    return;
}
/**
* @brief  dispay a rectangle line by color data
*/
void memLCD8::rect(int x0, int y0, int x1, int y1, uint8_t color)
{

    if (x1 > x0) hline(x0,x1,y0,color);
    else  hline(x1,x0,y0,color);

    if (y1 > y0) vline(x0,y0,y1,color);
    else vline(x0,y1,y0,color);

    if (x1 > x0) hline(x0,x1,y1,color);
    else  hline(x1,x0,y1,color);

    if (y1 > y0) vline(x1,y0,y1,color);
    else vline(x1,y1,y0,color);

    return;
}
/**
* @brief  dispay a filled rectangle by color data
*/
void memLCD8::fillrect(int x0, int y0, int x1, int y1, uint8_t color)
{
    int h = y1 - y0 + 1;
    for (int i=0; i<h; i++) hline(x0, x1, y0+i, color);
}
/**
* @brief  Transfer One Pixel Data with x,y allocation
* @param[in] int x : horizontal allocation left to right
* @param[in] int y : vertival allocation top to bottom
* @param[in] uint8_t color : the color data for Drawing  0x0X  x is color data(RGBC) C is not used
*/
void memLCD8::pixel(int x, int y, uint8_t color)
{
    if(!(x % 2)) _dispBUF[y*_width/2+x/2] =  _dispBUF[y*_width/2+x/2]&0x0F  |  (color << 4)&0xF0 ;   //MASK 0000 1111
    else         _dispBUF[y*_width/2+x/2] =  _dispBUF[y*_width/2+x/2]&0xF0  |  (color     )&0x0F ;   //MASK 1111 0000
}

/**
* @brief  Get Edited data for SPI transfer
* @param[in] int x : horizontal allocation left to right
* @param[in] int y : vertival allocation top to bottom
* @param[in] uint8_t* buff : buffer data for Display
*/
int* memLCD8::GetPixelValue(int _x, int _y ,uint8_t* buff)
{
    //bitmap data = 4bit data => modify transfer data bit size;
    switch(TrModeCommand)
    {
    case 0x90: //TrBIT4:
        // buffer 2pixel/1byte => 2pixel/1byte  buffe 2byte毎進める。
        TrValue[0] = buff[_y* _width/2 + _x];
        break;
    case 0x80://TrBIT3:
        // buffer 2pixel/1byte => 3pixel-1subpixel/1bye (24 pixel/3byte) buffer 3byte毎進める。
        for(int j=0;j<3;j++) TrValue[j] = 0;
        //for( int i = 0 ; i<12 ; i--)
        {
            //4 bit RGBN(Nは予備) => 3bit RGB
            if( _width/2 > _x )
            {
                TrValue[0] = TrValue[0] | ( ( (buff[_y* _width/2 + _x    ]&0xE0) ) );
                TrValue[0] = TrValue[0] | ( ( (buff[_y* _width/2 + _x    ]&0x0E) ) << 1);
            }
            if( _width/2 > _x + 1 )
            {
                TrValue[0] = TrValue[0] | ( ( (buff[_y* _width/2 + _x + 1]&0xC0) ) >> 6);

                TrValue[1] = TrValue[1] | ( ( (buff[_y* _width/2 + _x + 1]&0x20) ) << 2);
                TrValue[1] = TrValue[1] | ( ( (buff[_y* _width/2 + _x + 1]&0x0E) ) << 3);
            }
            if( _width/2 > _x + 2 )
            {
                TrValue[1] = TrValue[1] | ( ( (buff[_y* _width/2 + _x + 2]&0xE0) ) >> 4);
                TrValue[1] = TrValue[1] | ( ( (buff[_y* _width/2 + _x + 2]&0x08) ) >> 3);

                TrValue[2] = TrValue[2] | ( ( (buff[_y* _width/2 + _x + 2]&0x06) ) << 5);
            }
            if( _width/2 > _x + 3 )
            {
                TrValue[2] = TrValue[2] | ( ( (buff[_y* _width/2 + _x + 3]&0xE0) ) >> 2);
                TrValue[2] = TrValue[2] | ( ( (buff[_y* _width/2 + _x + 3]&0x0E) ) >> 1);
            }    
        }
        break;
    case 0x88://TrBIT1:
        // buffer 2pixel/1byte => 8 pixel/1byte  buffe 4byte毎進める。
        for(int j=0;j<3;j++) TrValue[j] = 0;
        for(int i = 0 ; i<4 ; i++)
        {
            //Green bit => monochrome bit
            if( _width/2 > _x + i )
            {
                TrValue[0] = TrValue[0] | ( ( (buff[_y* _width/2 + _x + i]&0x40) == 0 ? 0 : 1 ) << (7-i*2)   );
                TrValue[0] = TrValue[0] | ( ( (buff[_y* _width/2 + _x + i]&0x04) == 0 ? 0 : 1 ) << (7-i*2)-1 );
                //pc2.printf("[%d+%d][%d]<0x%x>\n",_x,i,_y,_dispBUF[_y* _width/2 + _x + i]);
            }
        }
        break;
    }
    return TrValue;   
}

/**
* @brief  Transfer Pixel Data from buffer to Display
* @param[in] int transfermode : instruction the transfer data size ,4bit,3bit,1bit
*/
void memLCD8::writeDISP(int transfermode)    // refresh whole display
{
    char pol = 0;
    //char command = 0x90; // 8b 1*0xNNNN *=POL x=AutoW  A  1010
    SetTransfermode(transfermode);
    
    // frame
    for (int i=0; i<_height; i++) {
        // line
        wait_us(6);
        _cs  = 1;
        wait_us(6);
        _spi.write(TrModeCommand | (pol << 6) | (i+1)>>8 ); // COMMAND
        //pc2.printf("com 0x%x\n",TrModeCommand | (pol << 6) | (i+1)>>8);
        
        _spi.write((i+1)& 0x00FF ); // V ADDR
        //pc2.printf("v adr 0x%x\n",(i+1)& 0x00FF);
        
        for(int j=0; j<_width; j+=TrAdd)
        {
            GetPixelValue(j,i,_dispBUF);
            //pc2.printf("data=[%d]{%d][%d]/[%d]\n",j*TrAdd,i,TrValue[0],TrAdd);
            for(int k=0;k<TrValNum;k++)
                _spi.write(TrValue[k]);
        }
        _spi.write(0x00); // DUMMY transfer
        _spi.write(0x00); // DUMMY transfer
//        wait_ms(1);      //1.8Hz simulation
//        wait_ms(2);      //1.35Hz simulation
        wait_us(6);
        _cs  = 0;
        if(pol) pol=0x00;
        else    pol=0x01;
    }
}

/**
* @brief  Transfer Pixel Data  : from Start line number to Display of frame buffer
* @param[in] int startline : Start line number to Display
* @param[in] int endline : end line number to Display
* @param[in] int transfermode : instruction the transfer data size ,4bit,3bit,1bit
*/
void memLCD8::writeDISP(int startline , int endline , int transfermode)    // refresh display selected line
{
    char pol = 0;
    //char command = 0x90; // 8b 1*0xNNNN *=POL x=AutoW  A  1010
    SetTransfermode(transfermode);
    
    // frame
    for (int i=startline; i<=endline; i++) {
        if( i >= _height ) continue;
        if( i <0   ) continue;
        
        // line
        wait_us(6);
        _cs  = 1;
        wait_us(6);
        _spi.write(TrModeCommand | (pol << 6) | (i+1)>>8 ); // COMMAND
        //pc2.printf("com 0x%x\n",TrModeCommand | (pol << 6) | (i+1)>>8);
        
        _spi.write((i+1)& 0x00FF ); // V ADDR
        //pc2.printf("v adr 0x%x\n",(i+1)& 0x00FF);
        
        for(int j=0; j<_width; j+=TrAdd)
        //for(int j=0; j<100; j+=TrAdd)
        {
            GetPixelValue(j,i,_dispBUF);
            //pc2.printf("data=[%d]{%d][%d]/[%d]\n",j*TrAdd,i,TrValue[0],TrAdd);
            for(int k=0;k<TrValNum;k++)
                _spi.write(TrValue[k]);
        }
        _spi.write(0x00); // DUMMY transfer
        _spi.write(0x00); // DUMMY transfer
//        wait_ms(1);      //1.8Hz simulation
//        wait_ms(2);      //1.35Hz simulation
        wait_us(6);
        _cs  = 0;
        if(pol) pol=0x00;
        else    pol=0x01;
    }
}

/**
* @brief  Transfer Pixel Data from frame buffer to Display
*/
void memLCD8::writeDISP(void)    // refresh whole display
{

    char pol = 0;
    char command = 0x90; // 8b 1*0xNNNN *=POL x=AutoW  A  1010

    // frame
    for (int i=0; i<_height; i++) {
        // line
        wait_us(6);
        _cs  = 1;
        wait_us(6);
        _spi.write(command | (pol << 6) | (i+1)>>8 ); // COMMAND
        _spi.write((i+1)& 0x00FF ); // V ADDR
        for(int j=0; j<_width/2; j++) _spi.write(_dispBUF[i*_width/2 + j]);
        _spi.write(0x00); // DUMMY transfer
        _spi.write(0x00); // DUMMY transfer
        wait_us(6);
        _cs  = 0;
        if(pol) pol=0x00;
        else    pol=0x01;
    }
}

/**
* @brief  clear buffer data by background color data
*/
void memLCD8::clsBUF(void)
{

    for (int i=0; i<_height; i++) {
        for (int j=0; j<_width; j++) {
            pixel(j,i,_background);
        }
    }
}
#if MOVIEBUFF_MODE
/**
* @brief  Transfer One Pixel Data with x,y allocation to Animation buffer
* @param[in] int x : horizontal allocation left to right
* @param[in] int y : vertival allocation top to bottom
* @param[in] uint8_t color : the color data for Drawing  0x0X  x is color data(RGBC) C is not used
* @param[in] int memnu : animation buffer number.
*/
void memLCD8::movie_pixel(int x, int y, uint8_t color,int memnum)
{
    //pc2.printf("movie_pixel[%d][%d]col[%d]\n",x,y,color);
    if(!(x % 2)) _dispMOVIEBUF[memnum][y*MOVIE_HORI_SIZE/2+x/2] =  _dispMOVIEBUF[memnum][y*MOVIE_HORI_SIZE/2+x/2]&0x0F  |  (color << 4)&0xF0 ;   //MASK 0000 1111
    else         _dispMOVIEBUF[memnum][y*MOVIE_HORI_SIZE/2+x/2] =  _dispMOVIEBUF[memnum][y*MOVIE_HORI_SIZE/2+x/2]&0xF0  |  (color     )&0x0F ;   //MASK 1111 0000
}

/**
* @brief  Transfer Pixel Data of Animation buffer with x,y allocation to frame buffer.
* @param[in] int sx : horizontal start allocation left to right
* @param[in] int sy : vertival start allocation top to bottom
* @param[in] int memnu : animation buffer number.
*/
void memLCD8::makeMovieFrame(int sx , int sy, int memnum)
{
    int x,y;
    //pc2.printf("1<%d,%d>\n",_width,_height);
    for(y = 0; y < MOVIE_VERT_SIZE;y++)
    {
        for(x = 0; x < MOVIE_HORI_SIZE ;x+=2)
        {
                if( (sx + x) >= _width ) continue;
                if( (sx + x) < 0 ) continue;
                if( (sy + y) >= _height ) continue;
                if( (sy + y) < 0 ) continue;
                
                _dispBACKUPBUF[y*MOVIE_HORI_SIZE/2+x/2] = _dispBUF[(sy+y)*(_width)/2+(sx+x)/2];

                if( (_dispMOVIEBUF[memnum][y*MOVIE_HORI_SIZE/2+x/2]&0xF0) != 0 )
                    _dispBUF[(sy+y)*(_width)/2+(sx+x)/2] = _dispBUF[(sy+y)*(_width)/2+(sx+x)/2]&0x0F | _dispMOVIEBUF[memnum][y*MOVIE_HORI_SIZE/2+x/2]&0xF0;   //MASK 0000 1111

                if( (_dispMOVIEBUF[memnum][y*MOVIE_HORI_SIZE/2+x/2]&0x0F) != 0 )
                    _dispBUF[(sy+y)*(_width)/2+(sx+x)/2] =  _dispBUF[(sy+y)*(_width)/2+(sx+x)/2]&0xF0 | _dispMOVIEBUF[memnum][y*MOVIE_HORI_SIZE/2+x/2]&0x0F;   //MASK 0000 1111
        
            //pc2.printf("dispMOVIEBUF[%d][%d] = %d\n",x,y,_dispMOVIEBUF[memnum][y*MOVIE_HORI_SIZE/2+x/2]);
           //_dispBUF[(sy+y)*(_width)/2+(sx+x)/2] = _dispMOVIEBUF[memnum][y*MOVIE_HORI_SIZE/2+x/2];
        }
    }
    //pc2.printf("memnum=%d,x=%d,y=%d>sx=%d,sy=%d\n",memnum,sx,sy,(sx+x)-1,(sy+y)-1);

}
/**
* @brief  Transfer Pixel Data of Animation buffer with x,y allocation to frame buffer.  animation data read right to left.
* @param[in] int sx : horizontal start allocation left to right
* @param[in] int sy : vertival start allocation top to bottom
* @param[in] int memnu : animation buffer number.
*/
void memLCD8::makeMovieFrame_Reverse(int sx , int sy, int memnum)
{
    int x,y;
    //pc2.printf("1<%d,%d>\n",_width,_height);
    for(y = 0; y < MOVIE_VERT_SIZE ;y++)
    {
        for(x = 0; x < MOVIE_HORI_SIZE  ;x+=2)
        {
                if( (sx + x) >= _width ) continue;
                if( (sx + x) < 0 ) continue;
                if( (sy + y) >= _height ) continue;
                if( (sy + y) < 0 ) continue;
                
                _dispBACKUPBUF[y*MOVIE_HORI_SIZE/2+x/2] = _dispBUF[(sy+y)*(_width)/2+(sx+x)/2];

                if( (_dispMOVIEBUF[memnum][y*MOVIE_HORI_SIZE/2+(MOVIE_HORI_SIZE-2-x)/2]&0xF0) != 0 )
                    _dispBUF[(sy+y)*(_width)/2+(sx+x)/2] = _dispBUF[(sy+y)*(_width)/2+(sx+x)/2]&0x0F | _dispMOVIEBUF[memnum][y*MOVIE_HORI_SIZE/2+(MOVIE_HORI_SIZE-2-x)/2]&0xF0;   //MASK 0000 1111

                if( (_dispMOVIEBUF[memnum][y*MOVIE_HORI_SIZE/2+(MOVIE_HORI_SIZE-2-x)/2]&0x0F) != 0 )
                    _dispBUF[(sy+y)*(_width)/2+(sx+x)/2] = _dispBUF[(sy+y)*(_width)/2+(sx+x)/2]&0xF0 | _dispMOVIEBUF[memnum][y*MOVIE_HORI_SIZE/2+(MOVIE_HORI_SIZE-2-x)/2]&0x0F;   //MASK 0000 1111
        
            //pc2.printf("dispMOVIEBUF[%d][%d] = %d\n",x,y,_dispMOVIEBUF[memnum][y*MOVIE_HORI_SIZE/2+x/2]);
           //_dispBUF[(sy+y)*(_width)/2+(sx+x)/2] = _dispMOVIEBUF[memnum][y*MOVIE_HORI_SIZE/2+x/2];
        }
    }
    //pc2.printf("memnum=%d,x=%d,y=%d>sx=%d,sy=%d\n",memnum,sx,sy,(sx+x)-1,(sy+y)-1);

}
/**
* @brief  Transfer Pixel Data of Animation buffer with x,y allocation to frame buffer.  animation data bottom to top.
* @param[in] int sx : horizontal start allocation left to right
* @param[in] int sy : vertival start allocation top to bottom
* @param[in] int memnu : animation buffer number.
*/
void memLCD8::makeMovieFrame_Updown(int sx , int sy, int memnum)
{
    int x,y;
    //pc2.printf("1<%d,%d>\n",_width,_height);
    for(y = 0; y < MOVIE_VERT_SIZE ;y++)
    {
        for(x = 0; x < MOVIE_HORI_SIZE  ;x+=2)
        {
                if( (sx + x) >= _width ) continue;
                if( (sx + x) < 0 ) continue;
                if( (sy + y) >= _height ) continue;
                if( (sy + y) < 0 ) continue;
                
                _dispBACKUPBUF[y*MOVIE_HORI_SIZE/2+x/2] = _dispBUF[(sy+y)*(_width)/2+(sx+x)/2];

                if( (_dispMOVIEBUF[memnum][(MOVIE_VERT_SIZE-1-y)*MOVIE_HORI_SIZE/2+x/2]&0xF0) != 0 )
                    _dispBUF[(sy+y)*(_width)/2+(sx+x)/2] = _dispBUF[(sy+y)*(_width)/2+(sx+x)/2]&0x0F | _dispMOVIEBUF[memnum][(MOVIE_VERT_SIZE-1-y)*MOVIE_HORI_SIZE/2+x/2]&0xF0;   //MASK 0000 1111

                if( (_dispMOVIEBUF[memnum][(MOVIE_VERT_SIZE-1-y)*MOVIE_HORI_SIZE/2+x/2]&0x0F) != 0 )
                    _dispBUF[(sy+y)*(_width)/2+(sx+x)/2] = _dispBUF[(sy+y)*(_width)/2+(sx+x)/2]&0xF0 | _dispMOVIEBUF[memnum][(MOVIE_VERT_SIZE-1-y)*MOVIE_HORI_SIZE/2+x/2]&0x0F;   //MASK 0000 1111
        
            //pc2.printf("dispMOVIEBUF[%d][%d] = %d\n",x,y,_dispMOVIEBUF[memnum][y*MOVIE_HORI_SIZE/2+x/2]);
           //_dispBUF[(sy+y)*(_width)/2+(sx+x)/2] = _dispMOVIEBUF[memnum][y*MOVIE_HORI_SIZE/2+x/2];
        }
    }
    //pc2.printf("memnum=%d,x=%d,y=%d>sx=%d,sy=%d\n",memnum,sx,sy,(sx+x)-1,(sy+y)-1);

}
/**
* @brief  Transfer  Pixel Data of backuped original frame buffer with x,y allocation to frame buffer.
* @param[in] int sx : horizontal start allocation left to right
* @param[in] int sy : vertival start allocation top to bottom
* @param[in] int memnu : animation buffer number.
*/
void memLCD8::RestoreMovieFrame(int sx , int sy, int memnum)
{
    int x,y;
    //pc2.printf("1<%d,%d>\n",_width,_height);
    for(y = 0; y < MOVIE_VERT_SIZE;y++)
    {
        for(x = 0; x < MOVIE_HORI_SIZE ;x++)
        {
           if( (sx + x) >= _width ) continue;
           if( (sx + x) < 0 ) continue;
           if( (sy + y) >= _height ) continue;
           if( (sy + y) < 0 ) continue;
           _dispBUF[(sy+y)*(_width)/2+(sx+x)/2]=_dispBACKUPBUF[y*MOVIE_HORI_SIZE/2+x/2];
        }
    }
    //pc2.printf("memnum=%d,x=%d,y=%d>sx=%d,sy=%d\n",memnum,sx,sy,(sx+x)-1,(sy+y)-1);

}
//end MOVIEBUFF_MODE
#endif
//end FRAMEBUFF_MODE
#endif