NXP Rapid IoT prototyping kit verified port of the LCD library.
ColorMemLCD.cpp
- Committer:
- batman52
- Date:
- 2019-12-26
- Revision:
- 2:6dc3f280499f
- Parent:
- 1:b035a997ec3f
File content as of revision 2:6dc3f280499f:
/* * mbed library for the JDI color memory LCD LPM013M126A * derived from C12832_lcd * Copyright (c) 2016 Tadayuki Okamoto * Released under the MIT License: http://mbed.org/license/mit * * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN * THE SOFTWARE. */ #include "ColorMemLCD.h" #include "mbed.h" /** @def * LCD_Color SPI commands */ #define LCD_COLOR_CMD_UPDATE (0x90) //!< Update Mode (4bit Data Mode) #define LCD_COLOR_CMD_ALL_CLEAR (0x20) //!< All Clear Mode #define LCD_COLOR_CMD_NO_UPDATE (0x00) //!< No Update Mode #define LCD_COLOR_CMD_BLINKING_WHITE (0x18) //!< Display Blinking Color Mode (White) #define LCD_COLOR_CMD_BLINKING_BLACK (0x10) //!< Display Blinking Color Mode (Black) #define LCD_COLOR_CMD_INVERSION (0x14) //!< Display Inversion Mode /** Create a SPI_LCD object connected to SPI */ ColorMemLCD::ColorMemLCD( PinName mosi, PinName miso, PinName sclk, PinName cs, PinName disp, PinName power, const char *name ) : GraphicsDisplay( name ), _spi( mosi, miso, sclk ), _cs( cs ), _disp( disp ), _power( power ) { /* initialize signal level */ _power = 0; _disp = 0; _cs = 0; wait_us( 100 ); /* initialize lcd module */ _power = 1; _spi.format( 8,0 ); // 8bit mode3 _spi.frequency( 2000000 ); // 2 Mhz SPI clock _spi.write( 0x00 ); // dummy polarity = 0; blink_cmd = 0x00; /* initialize variables */ char_x = 0; char_y = 0; trans_mode = LCD_TRANSMODE_OPAQUE; window_x = 0; window_y = 0; window_w = LCD_DISP_WIDTH; window_h = LCD_DISP_HEIGHT_MAX_BUF; /* set default color */ foreground( LCD_COLOR_WHITE ); background( LCD_COLOR_BLACK ); /* initialize temporary buffer */ memset( &cmd_buf[0], 0, sizeof(cmd_buf) ); memset( &disp_buf[0], (char)( (_background & 0x0F ) | ( (_background & 0x0F ) << 4 ) ), sizeof(disp_buf) ); memset( &file_buf[0], 0, sizeof(file_buf) ); /* display turn ON */ command_AllClear(); _disp = 1; } /** Get the width of the screen in pixel */ int ColorMemLCD::width() { return LCD_DISP_WIDTH; } /** Get the height of the screen in pixel */ int ColorMemLCD::height() { return LCD_DISP_HEIGHT; } /** Set window region */ void ColorMemLCD::window( int x, int y, int w, int h ) { #if ( LCD_DEVICE_HEIGHT != LCD_DISP_HEIGHT_MAX_BUF ) if( ( ( x & 0x01 ) == 0x01 )|| ( ( w & 0x01 ) == 0x01 ) ) { /* Parameter Error */ GraphicsDisplay::window( x, y, w, h ); return; } /* adjust region */ if( x + w > LCD_DISP_WIDTH ) { w = LCD_DISP_WIDTH - x; } if( h > ( ( LCD_DISP_WIDTH / 2 ) * LCD_DISP_HEIGHT_MAX_BUF ) / ( w / 2 ) ) { h = ( ( LCD_DISP_WIDTH / 2 ) * LCD_DISP_HEIGHT_MAX_BUF ) / ( w / 2 ); } if( ( window_x == x )&& ( window_y == y )&& ( window_w == w )&& ( window_h == h ) ) { /* Same Area */ return; } window_x = x; window_y = y; window_w = w; window_h = h; /* Initialize Buffer */ memset( &disp_buf[0], (char)( (_background & 0x0F ) | ( (_background & 0x0F ) << 4 ) ), sizeof(disp_buf) ); #endif /* ( LCD_DEVICE_HEIGHT != LCD_DISP_HEIGHT_MAX_BUF ) */ GraphicsDisplay::window( x, y, w, h ); } /** Set a pixel on the window memory */ void ColorMemLCD::pixel( int x, int y, int color ) { if( ( window_x > x )|| ( ( window_x + window_w ) <= x )|| ( window_y > y )|| ( ( window_y + window_h ) <= y ) ) { /* out of display buffer */ return; } if( ( x % 2 ) == 0 ) { disp_buf[ ( (window_w / 2) * ( y - window_y ) ) + ( ( x - window_x ) / 2 ) ] &= 0x0F; disp_buf[ ( (window_w / 2) * ( y - window_y ) ) + ( ( x - window_x ) / 2 ) ] |= ( ( color & 0x0F ) << 4 ); } else { disp_buf[ ( (window_w / 2) * ( y - window_y ) ) + ( ( x - window_x ) / 2 ) ] &= 0xF0; disp_buf[ ( (window_w / 2) * ( y - window_y ) ) + ( ( x - window_x ) / 2 ) ] |= ( ( color & 0x0F ) ); } } /** Set a pixel - for transrucent mode */ void ColorMemLCD::pixel_alpha( int x, int y, int color ) { if( ( window_x > x )|| ( ( window_x + window_w ) <= x )|| ( window_y > y )|| ( ( window_y + window_h ) <= y ) ) { /* out of display buffer */ return; } if( ( x % 2 ) == 0 ) { disp_buf[ ( (window_w / 2) * ( y - window_y ) ) + ( ( x - window_x ) / 2 ) ] &= ( ( ( color & 0x0F ) << 4 ) | 0x0F ); } else { disp_buf[ ( (window_w / 2) * ( y - window_y ) ) + ( ( x - window_x ) / 2 ) ] &= ( ( ( color & 0x0F ) ) | 0xF0 ); } } /** Fill the window memory with background color */ void ColorMemLCD::cls( void ) { memset( &disp_buf[0], (char)( (_background & 0x0F ) | ( (_background & 0x0F ) << 4 ) ), sizeof(disp_buf) ); } /** draw a circle */ void ColorMemLCD::circle( int x0, int y0, int r, int color ) { int x = -r; int y = 0; int err = 2 - (2*r); int e2 = err; 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); } /** draw a filled circle */ void ColorMemLCD::fillcircle( int x0, int y0, int r, int color ) { int x = -r; int y = 0; int err = 2 - (2*r); int e2 = err; 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); } /** draw a horizontal line */ void ColorMemLCD::hline( int x0, int x1, int y, int color ) { int x; int direction; if( x0 == x1 ) { pixel( x0, y, color ); return; } else if( x0 > x1 ) { direction = -1; } else { direction = 1; } for( x = x0 ; x <= x1 ; x += direction ) { pixel( x, y, color ); } } /** draw a vertical line */ void ColorMemLCD::vline( int x, int y0, int y1, int color ) { int y; int direction; if( y0 == y1 ) { pixel( x, y0, color ); return; } else if( y0 > y1 ) { direction = -1; } else { direction = 1; } for( y = y0 ; y <= y1 ; y += direction ) { pixel( x, y, color ); } } /** draw a 1 pixel line */ void ColorMemLCD::line( int x0, int y0, int x1, int y1, int color ) { int dx = 0; int dy = 0; int dx_sym = 0; int dy_sym = 0; int dx_x2 = 0; int dy_x2 = 0; int di = 0; dx = x1 - x0; dy = y1 - y0; if( dx == 0 ) { /* vertical line */ vline( x0, y0, y1, color ); return; } else if( dx > 0 ) { dx_sym = 1; } else { dx_sym = -1; } if( dy == 0 ) { /* horizontal line */ hline( x0, x1, y0, color ); return; } else 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; } /** draw a rect */ void ColorMemLCD::rect( int x0, int y0, int x1, int y1, int color ) { hline( x0, x1, y0, color ); vline( x0, y0, y1, color ); hline( x0, x1, y1, color ); vline( x1, y0, y1, color ); } /** draw a filled rect */ void ColorMemLCD::fillrect(int x0, int y0, int x1, int y1, int color) { int y; int direction; if( y0 == y1 ) { hline( x0, x1, y0, color ); return; } else if( y0 > y1 ) { direction = -1; } else { direction = 1; } for( y = y0 ; y <= y1 ; y += direction ) { hline( x0, x1, y, color ); } } /** setup cursor position */ void ColorMemLCD::locate( int x, int y ) { char_x = x; char_y = y; } /** calculate the max number of char in a line */ int ColorMemLCD::columns() { return width() / font[1]; } /** calculate the max number of columns */ int ColorMemLCD::rows() { return height() / font[2]; } /** put a char on the screen */ int ColorMemLCD::_putc( int value ) { if( value == '\n' ) { // new line char_x = 0; char_y = char_y + font[2]; if( char_y >= ( height() - font[2] ) ) { char_y = 0; } } else { character( char_x, char_y, value ); } return value; } /** draw a character of selected font */ void ColorMemLCD::character( int x, int y, int c ) { int hor, vert, offset, bpl, j, i, b; unsigned char* zeichen; unsigned char z,w; if( (c < 31) || (c > 127) ) { return; // test char range } // read font parameter from start of array offset = font[0]; // bytes / char hor = font[1]; // get hor size of font vert = font[2]; // get vert size of font bpl = font[3]; // bytes per line 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 ) * offset ) + 4 ]; // start of char bitmap w = zeichen[0]; // width of actual 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 ) { if( trans_mode == LCD_TRANSMODE_OPAQUE ) { pixel( x + i, y + j, _background ); } else if( trans_mode == LCD_TRANSMODE_TRANSLUCENT ) { pixel_alpha( x + i, y + j, _background ); } } else { pixel( x + i, y + j, _foreground ); } } } if( ( w + 2 ) < hor ) { // x offset to next char char_x += w + 2; } else { char_x += hor; } } /** draw a symbol of same format as "character" */ void ColorMemLCD::symbol(unsigned int x, unsigned int y, unsigned char *symbol) { unsigned int hor,vert,bpl,j,i,b; unsigned char z; 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() - vert ) { char_y = 0; } } for( j = 0; j < vert ; j++ ) { // vert line for( i = 0 ; i < hor ; i++ ) { // horz line z = symbol[ bpl * i + ( ( j & 0xF8 ) >> 3 ) + 1 + 3 ]; b = 1 << ( j & 0x07 ); if( ( z & b ) == 0x00 ) { if( trans_mode == LCD_TRANSMODE_OPAQUE ) { pixel( x + i, y + j, _background ); } else if( trans_mode == LCD_TRANSMODE_TRANSLUCENT ) { pixel_alpha( x + i, y + j, _background ); } } else { pixel( x + i, y + j, _foreground ); } } } } /** select the font */ void ColorMemLCD::set_font( unsigned char* f ) { font = f; } /** set transpalent effect */ void ColorMemLCD::setTransMode( char mode ) { trans_mode = mode; } /** set a bitmap on the window buffer */ void ColorMemLCD::Bitmap4bit( int x, int y, int w, int h, unsigned char *bitmap ) { Bitmap4bit( x, y, w, h, bitmap, 0, 0, w, h ); } /** set a bitmap on the window buffer */ void ColorMemLCD::Bitmap4bit( int x, int y, int w, int h, unsigned char *bitmap, int bmp_x, int bmp_y, int bmp_w, int bmp_h ) { int i, j; if( ( x < 0 )|| ( y < 0 )|| ( w <= 0 )|| ( h <= 0 )|| ( bitmap == NULL )|| ( bmp_x < 0 )|| ( bmp_y < 0 )|| ( bmp_w <= 0 )|| ( bmp_h <= 0 )|| ( ( x & 0x01 ) == 0x01 )|| ( ( w & 0x01 ) == 0x01 )|| ( ( bmp_x & 0x01 ) == 0x01 )|| ( ( bmp_w & 0x01 ) == 0x01 ) ) { /* Parameter Error */ return; } for( i = 0 ; i < h ; i++ ) { if( ( window_y > i + y )|| ( ( window_y + window_h ) <= i + y )|| ( ( bmp_h ) <= i + bmp_y ) ) { /* out of display buffer */ continue; } for( j = 0 ; j < w ; j += 2 ) { if( ( window_x > j + x )|| ( ( window_x + window_w ) <= j + x )|| ( ( bmp_w ) <= j + bmp_x ) ) { /* out of display buffer */ continue; } /* copy to display bufffer */ disp_buf[ ( ( window_w / 2 ) * ( i + y - window_y ) ) + ( ( j + x - window_x ) / 2 ) ] = bitmap[ ( ( bmp_w / 2 ) * ( i + bmp_y ) ) + ( ( j + bmp_x ) / 2 ) ]; } } } /** set a bitmap on the window buffer */ void ColorMemLCD::Bitmap1bit( int x, int y, int w, int h, unsigned char *bitmap ) { Bitmap1bit( x, y, w, h, bitmap, 0, 0, w, h ); } /** set a bitmap on the window buffer */ void ColorMemLCD::Bitmap1bit( int x, int y, int w, int h, unsigned char *bitmap, int bmp_x, int bmp_y, int bmp_w, int bmp_h ) { int i, j; int byte, offset; if( ( x < 0 )|| ( y < 0 )|| ( w <= 0 )|| ( h <= 0 )|| ( bitmap == NULL )|| ( bmp_x < 0 )|| ( bmp_y < 0 )|| ( bmp_w <= 0 )|| ( bmp_h <= 0 ) ) { /* Parameter Error */ return; } for( i = 0 ; i < h ; i++ ) { if( ( window_y > i + y )|| ( ( window_y + window_h ) <= i + y )|| ( ( bmp_h ) <= i + bmp_y ) ) { /* out of display buffer */ continue; } for( j = 0 ; j < w ; j ++ ) { if( ( window_x > j + x )|| ( ( window_x + window_w ) <= j + x )|| ( ( bmp_w ) <= j + bmp_x ) ) { /* out of display buffer */ continue; } byte = ( ( bmp_w * ( i + bmp_y ) ) + ( ( j + bmp_x ) ) ) / 8; offset = ( ( bmp_w * ( i + bmp_y ) ) + ( ( j + bmp_x ) ) ) % 8; /* set to display bufffer */ if( ( bitmap[ byte ] & ( 0x80 >> offset ) ) != 0x00 ) { /* Foregroud */ pixel( ( j + x - window_x ), ( i + y - window_y ), _foreground ); } else { /* Backgroud */ if( trans_mode == LCD_TRANSMODE_OPAQUE ) { pixel( ( j + x - window_x ), ( i + y - window_y ), _background ); } else if( trans_mode == LCD_TRANSMODE_TRANSLUCENT ) { pixel_alpha( ( j + x - window_x ), ( i + y - window_y ), _background ); } } } } } /** Transfer to the LCD from diaply buffer */ void ColorMemLCD::update() { int32_t i; int copy_width; if( window_x + window_w < LCD_DISP_WIDTH ) { copy_width = (window_w / 2); } else { copy_width = ( ( LCD_DISP_WIDTH - window_x ) / 2 ); } for( i = 0 ; i < window_h ; i++ ) { if( window_y + i > LCD_DISP_HEIGHT ){ /* out of window system */ break; } /* initialize command buffer */ memset( &cmd_buf[0], (char)( (_background & 0x0F ) | ( (_background & 0x0F ) << 4 ) ), sizeof(cmd_buf) ); /* copy to command bufffer */ memcpy( &cmd_buf[(window_x/2)], &disp_buf[ (window_w / 2) * i ], copy_width ); /* send cmaoond request */ sendLineCommand( &cmd_buf[0], window_y + i ); } } /** Transfer a 24 bit BMP to the LCD from filesytem */ int ColorMemLCD::BMP_24( int x, int y, const char *filenameBMP ) { FILE* fp; int32_t width; int32_t height; int16_t data_bit_size; bool data_direction = false; // uint32_t filesize; uint32_t data_offset; int32_t i = 0; int32_t j = 0; int32_t line = 0; memset( &file_buf[0], 0, sizeof(file_buf) ); fp = fopen( filenameBMP, "rb" ); if( fp != NULL ) { /* read file header */ fread( &file_buf[0], sizeof(char), 14, fp ); // filesize = file_buf[ 2] + ( file_buf[ 3] << 8 ) + ( file_buf[ 4] << 16 ) + ( file_buf[ 5] << 24 ); data_offset = file_buf[10] + ( file_buf[11] << 8 ) + ( file_buf[12] << 16 ) + ( file_buf[13] << 24 ); if( data_offset <= 14 ) { /* error */ fclose(fp); return(0); } memset( &file_buf[0], 0, sizeof(file_buf) ); /* read file header */ fread( &file_buf[0], sizeof(char), (data_offset - 14), fp ); if( data_offset == 0x0C ) { /* OS/2 format */ width = file_buf[ 4] + ( file_buf[ 5] << 8 ); height = file_buf[ 6] + ( file_buf[ 7] << 8 ); data_bit_size = file_buf[10] + ( file_buf[11] << 8 ); } else if( data_offset == 0x36 ){ /* Windows format */ width = file_buf[ 4] + ( file_buf[ 5] << 8 ) + ( file_buf[ 6] << 16 ) + ( file_buf[ 7] << 24 ); height = file_buf[ 8] + ( file_buf[ 9] << 8 ) + ( file_buf[10] << 16 ) + ( file_buf[11] << 24 ); data_bit_size = file_buf[14] + ( file_buf[15] << 8 ); } else{ /* Unknown format */ fclose(fp); return(0); } if( data_bit_size != 24 ) { /* Not 24bit format */ fclose(fp); return(0); } if( height < 0 ) { height *= -1; data_direction = true; } if( data_direction == true ) { line = i; } else { line = height - i - 1; } for( i = 0; i < height; i++ ) { if( data_direction == true ) { line = i + y; } else { line = height - i - 1 + y; } if( line >= LCD_DISP_HEIGHT ) { /* out of window system */ continue; } /* initialize line display data with backgroud color */ memset( &cmd_buf[0], (char)( (_background & 0x0F ) | ( (_background & 0x0F ) << 4 ) ), sizeof(cmd_buf) ); if( ( line > window_y )&& ( line < window_y + window_h ) ) { /* inside display_buffer */ memcpy( &cmd_buf[ ( window_x / 2 ) ], &disp_buf[ ( window_w / 2 ) * ( line - window_y ) ], ( window_w / 2 ) ); } for( j = 0 ; j < width / 2 ; j++ ) { /* Read pixel */ memset( &file_buf[0], 0, 6 ); if( ( ( j * 2 ) + 1 ) < width ) { fread( &file_buf[0], sizeof(char), 6, fp ); } else if( ( ( j * 2 ) + 1 ) == width ){ fread( &file_buf[0], sizeof(char), 3, fp ); } else { break; } if( j + ( x / 2 ) >= (LCD_DISP_WIDTH/2) ) { /* out of window system */ continue; } cmd_buf[ j + ( x / 2 ) ] = ( ( file_buf[0] & 0x80 ) >> 2 ); /* B */ cmd_buf[ j + ( x / 2 ) ] |= ( ( file_buf[1] & 0x80 ) >> 1 ); /* G */ cmd_buf[ j + ( x / 2 ) ] |= ( file_buf[2] & 0x80 ); /* R */ if( ( ( j * 2 ) + 1 ) < width ) { cmd_buf[ j + ( x / 2 ) ] |= ( ( file_buf[3] & 0x80 ) >> 6 ); /* B */ cmd_buf[ j + ( x / 2 ) ] |= ( ( file_buf[4] & 0x80 ) >> 5 ); /* G */ cmd_buf[ j + ( x / 2 ) ] |= ( ( file_buf[5] & 0x80 ) >> 4 ); /* R */ } } /* send cmaoond request */ sendLineCommand( &cmd_buf[0], line ); /* copy to display buffer */ if( ( line > window_y )&& ( line < window_y + window_h ) ) { /* inside display_buffer */ memcpy( &disp_buf[ ( window_w / 2 ) * ( line - window_y ) ], &cmd_buf[ ( window_x / 2 ) ], ( window_w / 2 ) ); } } fclose(fp); } return(1); } /** send data packet */ void ColorMemLCD::sendLineCommand( char* line_cmd, int line ) { int32_t j; if( ( line < 0 )|| ( line >= LCD_DEVICE_HEIGHT ) ) { /* out of device size */ return; } wait_us(6); _cs = 1; wait_us(6); _spi.write( LCD_COLOR_CMD_UPDATE | ( polarity << 6 ) ); // Command _spi.write( line + 1 ); // line for( j = 0 ; j < (LCD_DISP_WIDTH/2) ; j++ ) { if( j >= (LCD_DEVICE_WIDTH/2) ) { /* out of device size */ break; } _spi.write(line_cmd[j]); // data } for( ; j < (LCD_DEVICE_WIDTH/2) ; j++ ) { /* padding to device size */ _spi.write( 0x00 ); } _spi.write( 0x00 ); _spi.write( 0x00 ); wait_us(6); _cs = 0; } /** Toggle the polarity at evry scecond */ void ColorMemLCD::polling() { if( polarity == 0 ) { polarity = 1; } else { polarity = 0; } if( _cs == 1 ) { return; } command_SetState(); } /** Command for setting the state of LCD */ void ColorMemLCD::command_SetState() { wait_us( 6 ); _cs = 1; wait_us( 6 ); _spi.write( blink_cmd | ( polarity << 6 )); _spi.write( 0x00 ); wait_us(6); _cs = 0; } /** Command to clear whole the LCD */ void ColorMemLCD::command_AllClear() { wait_us( 6 ); _cs = 1; wait_us( 6 ); _spi.write( LCD_COLOR_CMD_ALL_CLEAR | ( polarity << 6 )); _spi.write( 0x00 ); wait_us(6); _cs = 0; } /** Command to blink */ void ColorMemLCD::setBlinkMode( char mode ) { switch( mode ) { case LCD_BLINKMODE_NONE: /* Blinking None */ blink_cmd = LCD_COLOR_CMD_NO_UPDATE; break; case LCD_BLINKMODE_WHITE: /* Blinking White */ blink_cmd = LCD_COLOR_CMD_BLINKING_WHITE; break; case LCD_BLINKMODE_BLACK: /* Blinking Black */ blink_cmd = LCD_COLOR_CMD_BLINKING_BLACK; break; case LCD_BLINKMODE_INVERSE: /* Inversion Mode */ blink_cmd = LCD_COLOR_CMD_INVERSION; break; default: /* No Update */ blink_cmd = LCD_COLOR_CMD_NO_UPDATE; break; } _cs = 1; wait_us( 6 ); _spi.write( blink_cmd | ( polarity << 6 )); _spi.write( 0x00 ); wait_us(6); _cs = 0; }