Library for MI0283QT-2 LCD
Diff: MI0283QTlib.cpp
- Revision:
- 0:7ad454fed160
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/MI0283QTlib.cpp Wed May 23 06:25:31 2012 +0000 @@ -0,0 +1,1332 @@ +/* mbed Graphics LCD library. Library for MI0283QT-2 screen. + + Copyright (c) 2011 NXP 3803 + + Permission is hereby granted, free of charge, to any person obtaining a copy + of this software and associated documentation files (the "Software"), to deal + in the Software without restriction, including without limitation the rights + to use, copy, modify, merge, publish, distribute, sublicense, and/or sell + copies of the Software, and to permit persons to whom the Software is + furnished to do so, subject to the following conditions: + + The above copyright notice and this permission notice shall be included in + all copies or substantial portions of the Software. + + 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 "MI0283QTlib.h" +#include "mbed.h" +#include "Terminal24x12.h" +#include "Terminal12x6.h" + +#ifdef _USE_FILE +#include "SDFileSystem.h" +#endif + +/* GLCD definition and functions. */ +#define LCD_MODE_262K 5 // 5=65K, 6=262K colors. + +/* */ +#define LCD_FAST_SPEED 40000000 +#define LCD_SLOW_SPEED 3000000 +// +#define LCD_ID (0) +#define LCD_DATA ((0x72)|(LCD_ID<<2)) +#define LCD_REGISTER ((0x70)|(LCD_ID<<2)) +// +#define LCD_WIDTH (320) +#define LCD_HEIGHT (240) + +#if ( LCD_MODE_262K==6 ) + #define RGB(r,g,b) (((r&0xFC)<<16)|((g&0xFC)<<8)|((b&0xFC))) //6 red | 6 green | 6 blue +#else + #define RGB(r,g,b) (((r&0xF8)<<8)|((g&0xFC)<<3)|((b&0xF8)>>3)) //5 red | 6 green | 5 blue + #endif + +#define LCD_RST_DISABLE() _rst = 1; +#define LCD_RST_ENABLE() _rst = 0; +#define LCD_CS_DISABLE() _cs = 1; +#define LCD_CS_ENABLE() _cs = 0; + +//MODDMA dma; + +GLCD::GLCD( PinName mosi, PinName miso, PinName sclk, PinName cs, PinName rst, PinName bklgh) : _spi( mosi, miso, sclk), _cs( cs), _rst( rst), _bklgh( bklgh) { + // deselect the device + LCD_CS_DISABLE(); + LCD_RST_ENABLE(); + // defaults params + SPIClkSpeed=LCD_FAST_SPEED; + SPISlowClkSpeed=LCD_SLOW_SPEED; + SPIMode=3; + LCDBkLight=0.5; + // + BackGroundColor=LCD_BLACK; + // +#if 0 +struct _FONTINFO { + unsigned char *pText; + unsigned int h_size; + unsigned int v_size; + unsigned int h_line; +}; +#endif + + FontInfo[0].pText=(unsigned char*)&Text12x6[0]; + FontInfo[0].h_size=6; + FontInfo[0].v_size=12; + FontInfo[0].h_line=1; + + FontInfo[1].pText=(unsigned char*)&Text24x12[0]; + FontInfo[1].h_size=12; + FontInfo[1].v_size=24; + FontInfo[1].h_line=2; + + FontIdx=0; +} + +void GLCD::backlighton( void) +{ + backlightset( 1); +} + +void GLCD::backlightoff( void) +{ + backlightset( 0); +} + +void GLCD::backlightset( double val) +{ + LCDBkLight=val; + _bklgh = LCDBkLight; +} + +void GLCD::lcd_init( void) +{ + _spi.format(8,SPIMode); + _spi.frequency( SPIClkSpeed); + _bklgh = LCDBkLight; + + lcd_reset(); + +} + +void GLCD::lcd_init( unsigned int speedf) +{ + _spi.format(8,SPIMode); + _spi.frequency( speedf); + SPIClkSpeed=speedf; + _bklgh = LCDBkLight; + + lcd_reset(); + +} + +void GLCD::lcd_init( unsigned int speedf, unsigned int speeds) +{ + _spi.format(8,SPIMode); + _spi.frequency( speedf); + SPIClkSpeed=speedf; + SPISlowClkSpeed=speeds; + _bklgh = LCDBkLight; + + lcd_reset(); + +} + +void GLCD::lcd_setfontsmall( void) +{ + FontIdx=0; +} + +void GLCD::lcd_setfontbig( void) +{ + FontIdx=1; +} + +void GLCD::lcd_setbackgroundcolor( unsigned int color) { + BackGroundColor=color; +} + +void GLCD::lcd_drawstr(char *__putstr, unsigned int xpos, unsigned int ypos, unsigned int color) +{ + char __ps; + unsigned int xp,yp; + + /* Set the fast SPI speed. */ + _spi.frequency( SPIClkSpeed); + + xp=xpos; yp=ypos; + + while((__ps = *__putstr)) + { + __putstr++; + if (__ps== 0) break; + lcd_drawch(__ps,xp,yp, color); + xp+=FontInfo[FontIdx].h_size; // la dimensione del font per adesso è impostata manualmente. + } + /* Reset to slow speed. */ + _spi.frequency( SPISlowClkSpeed); +} + +void GLCD::lcd_drawch( unsigned ch, unsigned int xpos, unsigned int ypos, unsigned int color) +{ + unsigned int H_Line, H_Size, V_Size, SrcInc; + unsigned char *pSrc; + unsigned int i, j, txtcolor; + + /* Set the fast SPI speed. */ + _spi.frequency( SPIClkSpeed); + + // per adesso imposto i valori di queste grandezze manualmente + H_Line=FontInfo[FontIdx].h_line; + H_Size=FontInfo[FontIdx].h_size; + V_Size=FontInfo[FontIdx].v_size; + + // + lcd_area(xpos, ypos, (H_Size-1)+xpos, (V_Size-1)+ypos); + // printf("Programmo area: xpos=%d, ypos=%d, Hs=%d, Vs=%d\r\n", xpos,ypos,(H_Size-1)+xpos, (V_Size-1)+ypos); + // wait( 1); + // + pSrc=(unsigned char*)&FontInfo[FontIdx].pText[0]+(H_Line*V_Size*ch); + // printf("Carico il puntatore @ Text[%d]\r\n", (H_Line*V_Size*ch)); + // wait( 1); + + lcd_drawstart(); + +#if ( LCD_MODE_262K==6 ) + _spi.format(6,SPIMode); +#endif + + // + for ( i=0; i<V_Size; i++) { + SrcInc=H_Line; + for ( j=0; j<H_Size; j++) { + txtcolor=(*pSrc & (1UL<<(j&0x07)))?color:BackGroundColor; +#if (LCD_MODE_262K==6 ) + _spi.write( (txtcolor&0x00FC0000)>>18 ); + _spi.write( (txtcolor&0x0000FC00)>>10 ); + _spi.write( (txtcolor&0x000000FC)>>2); +#else + lcd_draw( txtcolor); +#endif // + if ((j&0x07) == 7) { + ++pSrc; + --SrcInc; + } + } + pSrc += SrcInc; + } + // +#if ( LCD_MODE_262K==6 ) + _spi.format(8,SPIMode); +#endif + lcd_drawstop(); + /* Reset to the slow SPI speed. */ + _spi.frequency( SPISlowClkSpeed); +} + +void GLCD::lcd_draw(unsigned int color) +{ + _spi.write(color>>8); + _spi.write(color); + + return; +} + + +void GLCD::lcd_drawstop(void) +{ + LCD_CS_DISABLE(); + + return; +} + + +void GLCD::lcd_drawstart(void) +{ + LCD_CS_ENABLE(); + _spi.write(LCD_REGISTER); + _spi.write(0x22); + LCD_CS_DISABLE(); + + LCD_CS_ENABLE(); + _spi.write(LCD_DATA); + + return; +} + +inline void GLCD::lcd_cmd(unsigned int reg, unsigned int param) +{ + LCD_CS_ENABLE(); + _spi.write( LCD_REGISTER); + _spi.write( reg); + LCD_CS_DISABLE(); + + LCD_CS_ENABLE(); + _spi.write( LCD_DATA); + _spi.write( param); + LCD_CS_DISABLE(); + + return; +} + + +void GLCD::lcd_data(unsigned int c) +{ + LCD_CS_ENABLE(); + _spi.write(LCD_DATA); + _spi.write(c>>8); + _spi.write(c); + LCD_CS_DISABLE(); + + return; +} + +void GLCD::lcd_area(unsigned int x0, unsigned int y0, unsigned int x1, unsigned int y1) +{ + lcd_cmd(0x03, (x0>>0)); //set x0 + lcd_cmd(0x02, (x0>>8)); //set x0 + lcd_cmd(0x05, (x1>>0)); //set x1 + lcd_cmd(0x04, (x1>>8)); //set x1 + lcd_cmd(0x07, (y0>>0)); //set y0 + lcd_cmd(0x06, (y0>>8)); //set y0 + lcd_cmd(0x09, (y1>>0)); //set y1 + lcd_cmd(0x08, (y1>>8)); //set y1 + + return; +} + +void GLCD::lcd_setverticalarea( unsigned int topf, unsigned int height, unsigned int butf) +{ + if ( (topf+height+butf) > 320) + return; + + lcd_cmd( 0x0F, (topf>>0)); + lcd_cmd( 0x0E, (topf>>8)); + lcd_cmd( 0x11, (height>>0)); + lcd_cmd( 0x10, (height>>8)); + lcd_cmd( 0x13, (butf>>0)); + lcd_cmd( 0x12, (butf>>8)); +} + +void GLCD::lcd_scrollstartadd( unsigned int ssa) +{ + lcd_cmd( 0x15, (ssa>>0)); + lcd_cmd( 0x14, (ssa>>8)); +} + +void GLCD::lcd_scrollstart( void) +{ + lcd_cmd( 0x01, 0x0008); +} + +void GLCD::lcd_scrollstop( void) +{ + lcd_cmd( 0x01, 0x0000); +} + +unsigned int GLCD::lcd_RGB( unsigned int color) +{ + + return ( RGB( (( color&0x00FF0000)>>16), ( ( color&0x0000FF00)>>8), ( color&0x000000FF)) ); + +} + +unsigned int GLCD::lcd_RGB( unsigned int r, unsigned int g, unsigned int b) +{ + return ( RGB( r, g, b)); +} + + +void GLCD::lcd_clear(unsigned int color) +{ + unsigned int i; + + /* Set the fast SPI speed. */ + _spi.frequency( SPIClkSpeed); + + lcd_area(0, 0, (LCD_WIDTH-1), (LCD_HEIGHT-1)); + + lcd_drawstart(); + +#if ( LCD_MODE_262K==6 ) + _spi.format(6,SPIMode); + _spi.frequency( SPIClkSpeed); +#endif + + for(i=(LCD_WIDTH*LCD_HEIGHT); i!=0; i--) + { +#if (LCD_MODE_262K==6 ) + _spi.write( (color&0x00FC0000)>>18 ); + _spi.write( (color&0x0000FC00)>>10 ); + _spi.write( (color&0x000000FC)>>2); +#else + lcd_draw( color); +#endif + } + // +#if ( LCD_MODE_262K==6 ) + _spi.format(8,SPIMode); + _spi.frequency( SPIClkSpeed); +#endif + lcd_drawstop(); + + /* Reset to the slow SPI speed. */ + _spi.frequency( SPISlowClkSpeed); + return; +} + +void GLCD::lcd_clear(unsigned int x0, unsigned int y0, unsigned int w, unsigned int h, unsigned int color) +{ + unsigned int i; + + /* Set the fast SPI speed. */ + _spi.frequency( SPIClkSpeed); + + lcd_area(x0, y0, (w-1)+x0, (h-1)+y0); + + lcd_drawstart(); + +#if ( LCD_MODE_262K==6 ) + _spi.format(6,SPIMode); + _spi.frequency( SPIClkSpeed); +#endif + + for(i=(w*h); i!=0; i--) + { +#if (LCD_MODE_262K==6 ) + _spi.write( (color&0x00FC0000)>>18 ); + _spi.write( (color&0x0000FC00)>>10 ); + _spi.write( (color&0x000000FC)>>2); +#else + lcd_draw( color); +#endif + } + // +#if ( LCD_MODE_262K==6 ) + _spi.format(8,SPIMode); + _spi.frequency( SPIClkSpeed); +#endif + lcd_drawstop(); + + /* Reset to the slow SPI speed. */ + _spi.frequency( SPISlowClkSpeed); + return; +} + + +#ifdef _USE_FILE +unsigned int GLCD::lcd_drawimage(char *fname) +{ + unsigned int i; + unsigned char r, g, b; + + FILE *fp; + + if ( (fp=fopen( fname, "r")) == NULL ) { + return 0; + } + + lcd_area(0, 0, (LCD_WIDTH-1), (LCD_HEIGHT-1)); + + lcd_drawstart(); + +#if ( LCD_MODE_262K==6 ) + _spi.format(6,3); +#endif + + for(i=(LCD_WIDTH*LCD_HEIGHT); i!=0; i--) + { + // + r=fgetc( fp); + g=fgetc( fp); + b=fgetc( fp); + // +#if ( LCD_MODE_262K==6 ) + _spi.write( (r&0xFC)>>2 ); + _spi.write( (g&0xFC)>>2 ); + _spi.write( (b&0xFC)>>2 ); +#else + lcd_draw( RGB( r, g, b)); +#endif + // + if ( feof( fp)) { + fclose( fp); + break; + } + } + // + if ( fp) + fclose( fp); + // +#if ( LCD_MODE_262K==6 ) + _spi.format(8,3); +#endif + lcd_drawstop(); + + return 1; +} +#endif + + +#ifdef _USE_FILE + +unsigned int GLCD::lcd_drawimagebuff(char *fname) +{ + unsigned int i; + unsigned char r, g, b; + unsigned char buffer[320*BUFFER_LINE*3]; + unsigned int size, idx, y=0; + + FILE *fp; + + if ( (fp=fopen( fname, "r")) == NULL ) { + return 0; + } + + size=fread( &buffer[0], sizeof(buffer[0]), sizeof(buffer)/sizeof(buffer[0]), fp); + + /* Set the fast SPI speed. */ + _spi.frequency( SPIClkSpeed); + + lcd_area(0, 0, (LCD_WIDTH-1), (LCD_HEIGHT-1)); + + lcd_drawstart(); + +#if ( LCD_MODE_262K==6 ) + _spi.format(6,SPIMode); +#endif + + idx=0; + for(i=(LCD_WIDTH*LCD_HEIGHT); i!=0; i--) + { + // + r=buffer[idx++]; + g=buffer[idx++]; + b=buffer[idx++]; + // +#if ( LCD_MODE_262K==6 ) + _spi.write( (r&0xFC)>>2 ); + _spi.write( (g&0xFC)>>2 ); + _spi.write( (b&0xFC)>>2 ); +#else + lcd_draw( RGB( r, g, b)); +#endif + // + if ( idx>=size){ +#if ( LCD_MODE_262K==6 ) + _spi.format(8,SPIMode); +#endif + lcd_drawstop(); + // + if ( feof( fp)) { + fclose( fp); + break; + } + // + size=fread( &buffer[0], sizeof(buffer[0]), sizeof(buffer)/sizeof(buffer[0]), fp); + idx=0; + y+=BUFFER_LINE; + lcd_area(0, y, (LCD_WIDTH-1), (LCD_HEIGHT-1)); + lcd_drawstart(); +#if ( LCD_MODE_262K==6 ) + _spi.format(6,SPIMode); +#endif + } + } + // +#if ( LCD_MODE_262K==6 ) + _spi.format(8,SPIMode); +#endif + // + lcd_drawstop(); + /* Reset to the slow SPI speed. */ + _spi.frequency( SPISlowClkSpeed); + // + if ( fp) + fclose( fp); + + return 1; +} +#endif + +#ifdef _USE_FILE +unsigned int GLCD::lcd_drawimagebyline(unsigned char *buffer, unsigned int lnum, unsigned int xstart, unsigned int ystart, unsigned int scale) +{ + unsigned int i, idx; + unsigned char r, g, b; + + /* Set the fast SPI speed. */ + _spi.frequency( SPIClkSpeed); + + lcd_area(xstart, lnum+ystart, ((LCD_WIDTH/scale)-1)+xstart, lnum+ystart); + + lcd_drawstart(); + +#if ( LCD_MODE_262K==6 ) + _spi.format(6,SPIMode); +#endif + + idx=0; + for(i=LCD_WIDTH/scale; i!=0; i--) + { + // + r=buffer[idx]; + g=buffer[idx+1]; + b=buffer[idx+2]; + // + idx+=(scale*3); + // +#if ( LCD_MODE_262K==6 ) + _spi.write( (r&0xFC)>>2 ); + _spi.write( (g&0xFC)>>2 ); + _spi.write( (b&0xFC)>>2 ); +#else + lcd_draw( RGB( r, g, b)); +#endif + } + // +#if ( LCD_MODE_262K==6 ) + _spi.format(8,SPIMode); +#endif + // + lcd_drawstop(); + /* Reset to the slow SPI speed. */ + _spi.frequency( SPISlowClkSpeed); + + return 1; +} +#endif + +#ifdef _USE_FILE +unsigned int GLCD::lcd_drawimagebyline(unsigned char *buffer, unsigned int lnum) +{ + unsigned int i, idx; + unsigned char r, g, b; + + /* Set the fast SPI speed. */ + _spi.frequency( SPIClkSpeed); + + lcd_area(0, lnum, (LCD_WIDTH-1), lnum); + + lcd_drawstart(); + +#if ( LCD_MODE_262K==6 ) + _spi.format(6,SPIMode); +#endif + + idx=0; + for(i=LCD_WIDTH; i!=0; i--) + { + // + r=buffer[idx++]; + g=buffer[idx++]; + b=buffer[idx++]; + // +#if ( LCD_MODE_262K==6 ) + _spi.write( (r&0xFC)>>2 ); + _spi.write( (g&0xFC)>>2 ); + _spi.write( (b&0xFC)>>2 ); +#else + lcd_draw( RGB( r, g, b)); +#endif + } + // +#if ( LCD_MODE_262K==6 ) + _spi.format(8,SPIMode); +#endif + // + lcd_drawstop(); + /* Reset to the slow SPI speed. */ + _spi.frequency( SPISlowClkSpeed); + + return 1; +} +#endif + +#ifdef _USE_FILE + +unsigned int GLCD::lcd_drawmovie(char *fname, unsigned int x_start, unsigned int y_start) +{ + unsigned int i; + unsigned char r, g, b; + + FILE *fp; + + if ( (fp=fopen( fname, "r")) == NULL ) { + return 0; + } + + /* Set the fast SPI speed. */ + _spi.frequency( SPIClkSpeed); + + lcd_drawstop(); + // lcd_area(0, 0, (LCD_WIDTH-1), (LCD_HEIGHT-1)); + lcd_area(x_start, y_start, (80-1)+x_start, (60-1)+y_start); + + lcd_drawstart(); + +#if ( LCD_MODE_262K==6 ) + _spi.format(6,SPIMode); +#endif + + while( 1) + { + // + r=fgetc( fp); + g=fgetc( fp); + b=fgetc( fp); + // +#if ( LCD_MODE_262K==6 ) + _spi.write( (r&0xFC)>>2 ); + _spi.write( (g&0xFC)>>2 ); + _spi.write( (b&0xFC)>>2 ); +#else + lcd_draw( RGB( r, g, b)); +#endif + // + if ( feof( fp)) { + fclose( fp); + break; + } + } + // + if ( fp) + fclose( fp); + // +#if ( LCD_MODE_262K==6 ) + _spi.format(8,SPIMode); +#endif + lcd_drawstop(); + + /* Reset to the slow SPI speed. */ + _spi.frequency( SPISlowClkSpeed); + + return 1; +} +#endif + +#ifdef _USE_FILE +#if ( LCD_MODE_262K==5 ) + +// I will use a portion of memory proportional to a defined number of rows. +#define cLINE_NUMBER 40 + +// Ping-pong buffer. The buffer are proportional to the number of pixel per row (160), to the +// numeber of line I want to read and to the number of byte for each pixel. In this case I have +// a ready-made file with each pixel defined with 16bit (RGB==565bit) +unsigned char buffer[160*cLINE_NUMBER*2] __attribute((section("AHBSRAM1"),aligned)); +unsigned char buffer1[160*cLINE_NUMBER*2] __attribute((section("AHBSRAM0"),aligned)); + +/** DMA_IRQHandler Called by DMA. + * Please to learn more read: http://mbed.org/users/AjK/programs/SOWB/lg489e/docs/flash__read_8c_source.html + */ +volatile int DMA_flag; +extern "C" void DMA_IRQHandler(void) __irq { + if (LPC_GPDMA->DMACIntStat & 1) { + if (LPC_GPDMA->DMACIntTCStat & 1) { + DMA_flag=1; + LPC_GPDMA->DMACIntTCClear = 1; + } + if (LPC_GPDMA->DMACIntErrStat & 1) { + LPC_GPDMA->DMACIntErrClr = 1; + } + } +} + +/** Linked List structure. I use this structure to send with one shot 3x3200 byte to the GLCD. + */ +typedef struct { + uint32_t SrcAddr; /* Source Address */ + uint32_t DstAddr; /* Destination address */ + uint32_t NextLLI; /* Next LLI address, otherwise set to '0' */ + uint32_t Control; /* GPDMA Control Register of this LLI. Reflect the content of LPC_GPDMACH0->DMACCControl */ +} GPDMA_LLI; + +/* Let declare the 3 linked list. The first LLI address will be programmed inside the DMA registers. */ +GPDMA_LLI LLI0, LLI1, LLI2; + +#define DMA_CHANNEL_ENABLE 1 +#define DMA_TRANSFER_TYPE_M2P (1UL << 11) +#define DMA_CHANNEL_TCIE (1UL << 31) +#define DMA_CHANNEL_SRC_INC (1UL << 26) +#define DMA_MASK_IE (1UL << 14) +#define DMA_MASK_ITC (1UL << 15) +#define DMA_CHANNEL_SRC_PERIPHERAL_SSP0_RX (1UL << 1) +#define DMA_CHANNEL_SRC_PERIPHERAL_SSP0_TX (0UL << 1) +#define DMA_CHANNEL_DST_PERIPHERAL_SSP0_RX (1UL << 6) +#define DMA_CHANNEL_DST_PERIPHERAL_SSP0_TX (0UL << 6) + +/** Display a movie file. The file is ready made to speed up the entire process. + * + * @param the name file. + * + */ +unsigned int GLCD::lcd_drawmoviebuff(char *fname, unsigned int x_start, unsigned int y_start) +{ + unsigned int i; + unsigned char r, g, b; + unsigned int size, idx, y=0; + unsigned char *pframe; + FILE *fp; + + LPC_SSP0->DMACR=2; + + /* Load the content to the LLI */ + /* The LLI are chained, so I load the address to the corrispondent LLI*/ + LLI0.NextLLI=(uint32_t)&LLI1; + LLI1.NextLLI=(uint32_t)&LLI2; + LLI2.NextLLI=0; // The last is NULL to stop the chain. + + /* The dimension of the buffer are fixed. So each LLI have a fixed pointer to the owned block of memory */ + /* Each buffer is 16KB long but I use fixed chunk following this rule: */ + /* The image is 160x120x2 = 38400 byte big. I have divided this amount by three so that it can */ + /* use the two memory buffer. Each chunk is now 12800 byte. But the DMA can only transfer 4KB of RAM, */ + /* so I divided this amount of memory by four, 3200 byte, and use three LLI to let the DMA to send the entire buffer all at once. */ + /* The LLI are three because the DMA is programmed with the first chund of buffer. At the end of this operation, the DMA load the LLI */ + /* and sends the remaining buffers. */ + LLI0.SrcAddr=(uint32_t)&buffer[3200]; + LLI1.SrcAddr=(uint32_t)&buffer[3200+3200]; + LLI2.SrcAddr=(uint32_t)&buffer[3200+3200+3200]; + /* OK, the destination address is the same for all LLI. Please change if you use a different SPI. */ + LLI0.DstAddr=(uint32_t)&LPC_SSP0->DR; + LLI1.DstAddr=(uint32_t)&LPC_SSP0->DR; + LLI2.DstAddr=(uint32_t)&LPC_SSP0->DR; + /* This is the control register. */ + LLI0.Control= DMA_CHANNEL_TCIE | DMA_CHANNEL_SRC_INC | 3200; + LLI1.Control= DMA_CHANNEL_TCIE | DMA_CHANNEL_SRC_INC | 3200; + LLI2.Control= DMA_CHANNEL_TCIE | DMA_CHANNEL_SRC_INC | 3200; + /* ****************************************************** */ + + /* Power up the GPDMA. */ + LPC_SC->PCONP |= (1UL << 29); + LPC_GPDMA->DMACConfig = 1; + LPC_GPDMA->DMACIntTCClear = 0x1; + // LPC_GPDMA->DMACSoftSReq = 0xC; + LPC_GPDMA->DMACSoftSReq = 0x3; + + /* Enable the IRQ */ + NVIC_EnableIRQ(DMA_IRQn); + + /* Open the file */ + if ( (fp=fopen( fname, "rb")) == NULL ) { + return 0; + } + + /* Set the fast SPI speed. */ + _spi.frequency( SPIClkSpeed); + _spi.format(8,SPIMode); + /* Define a fixed area to display the movie. */ + lcd_area(x_start, y_start, (160-1)+x_start, (120-1)+y_start); + lcd_drawstart(); + + /* read the first buffer... */ + size=fread( &buffer[0], sizeof(buffer[0]), sizeof(buffer)/sizeof(buffer[0]), fp); + + /* Loop untile the whole file is read. */ + while( 1) { + pframe=&buffer[0]; + /* set the source buffer... */ + LLI0.SrcAddr=(uint32_t)&pframe[3200]; + LLI1.SrcAddr=(uint32_t)&pframe[3200+3200]; + LLI2.SrcAddr=(uint32_t)&pframe[3200+3200+3200]; + + /* configure the DMA channell... */ + LPC_GPDMACH0->DMACCSrcAddr = (uint32_t)pframe; + LPC_GPDMACH0->DMACCDestAddr = (uint32_t)&LPC_SSP0->DR; + LPC_GPDMACH0->DMACCLLI = (uint32_t)&LLI0; + LPC_GPDMACH0->DMACCControl = DMA_CHANNEL_TCIE | DMA_CHANNEL_SRC_INC | 3200; + + DMA_flag=0; + /* Fire GPDMA Channel0 */ + LPC_GPDMACH0->DMACCConfig = DMA_CHANNEL_ENABLE | + DMA_CHANNEL_DST_PERIPHERAL_SSP0_TX | + DMA_TRANSFER_TYPE_M2P | + DMA_MASK_IE | + DMA_MASK_ITC; + + if ( feof( fp)) { + fclose( fp); + break; + } + /* Read the second chunk of the frame... */ + size=fread( &buffer1[0], sizeof(buffer1[0]), sizeof(buffer1)/sizeof(buffer1[0]), fp); + /* OK, the buffer from the SDCar is read but now we must check if the DMA it's work... */ + while( !DMA_flag); + DMA_flag=0; + /* At this point I check if I'm at end of the file. */ + if ( feof( fp) || size != sizeof(buffer1)/sizeof(buffer1[0]) ) { + // + LPC_SSP0->IMSC = (1UL << 3); + + LPC_GPDMACH0->DMACCConfig = 0; + LPC_GPDMA->DMACIntTCClear = 1; + + fclose( fp); + while(LPC_SSP0->SR & (1UL << 2)) { + /* This loop ensures we read the last byte in the + RX FIFO and test that. */ + int sr = LPC_SSP0->DR; + } + + // lcd_drawstop(); + NVIC_DisableIRQ(DMA_IRQn); + LPC_GPDMA->DMACIntTCClear = 1; + LPC_SSP0->DMACR=0; + LPC_GPDMA->DMACConfig = 0; + LPC_GPDMA->DMACIntTCClear = 0x1; + LPC_GPDMA->DMACSoftSReq = 0; + LPC_SC->PCONP &= ~(1UL << 29); + LPC_GPDMA->DMACIntTCClear = 1; + // + lcd_drawstop(); + break; + } + /* Now I have a buffer full with new data and the DMA stopped. I can start it again. */ + pframe=&buffer1[0]; + /* I set the new buffer inside the LLI... */ + LLI0.SrcAddr=(uint32_t)&pframe[3200]; + LLI1.SrcAddr=(uint32_t)&pframe[3200+3200]; + LLI2.SrcAddr=(uint32_t)&pframe[3200+3200+3200]; + /* DMA configuration. */ + LPC_GPDMACH0->DMACCSrcAddr = (uint32_t)pframe; + LPC_GPDMACH0->DMACCDestAddr = (uint32_t)&LPC_SSP0->DR; + LPC_GPDMACH0->DMACCLLI = (uint32_t)&LLI0; + LPC_GPDMACH0->DMACCControl = DMA_CHANNEL_TCIE | DMA_CHANNEL_SRC_INC | 3200; + /* Fire GPDMA Channel0 */ + LPC_GPDMACH0->DMACCConfig = DMA_CHANNEL_ENABLE | + DMA_CHANNEL_DST_PERIPHERAL_SSP0_TX | + DMA_TRANSFER_TYPE_M2P | + DMA_MASK_IE | + DMA_MASK_ITC; + + if ( feof( fp)) { + fclose( fp); + break; + } + /* A new read from the SDCad... */ + size=fread( &buffer[0], sizeof(buffer[0]), sizeof(buffer)/sizeof(buffer[0]), fp); + /* just wait is the DMA it's working... */ + while( !DMA_flag); + DMA_flag=0; + /* At this point I check if I'm at end of the file. */ + if ( feof( fp) || size != sizeof(buffer)/sizeof(buffer[0]) ) { + fclose( fp); + break; + } + /* */ + pframe=&buffer[0]; + /* programmo nella LLI il nvuovo buffer... */ + LLI0.SrcAddr=(uint32_t)&pframe[3200]; + LLI1.SrcAddr=(uint32_t)&pframe[3200+3200]; + LLI2.SrcAddr=(uint32_t)&pframe[3200+3200+3200]; + /* programmo il DMA */ + LPC_GPDMACH0->DMACCSrcAddr = (uint32_t)pframe; + LPC_GPDMACH0->DMACCDestAddr = (uint32_t)&LPC_SSP0->DR; + LPC_GPDMACH0->DMACCLLI = (uint32_t)&LLI0; + LPC_GPDMACH0->DMACCControl = DMA_CHANNEL_TCIE | DMA_CHANNEL_SRC_INC | 3200; + /* Fire GPDMA Channel0 */ + LPC_GPDMACH0->DMACCConfig = DMA_CHANNEL_ENABLE | + DMA_CHANNEL_DST_PERIPHERAL_SSP0_TX | + DMA_TRANSFER_TYPE_M2P | + DMA_MASK_IE | + DMA_MASK_ITC; + if ( feof( fp)) { + fclose( fp); + break; + } + /* */ + size=fread( &buffer1[0], sizeof(buffer1[0]), sizeof(buffer1)/sizeof(buffer1[0]), fp); + /* Aspetto che il DMA completi l'ultimo transfer... */ + while( !DMA_flag); + DMA_flag=0; + /* At this point I check if I'm at end of the file. */ + if ( feof( fp) || size != sizeof(buffer1)/sizeof(buffer1[0]) ) { + fclose( fp); + break; + } + /* */ + pframe=&buffer1[0]; + /* At this point I reset the display area resending the xy value*/ + lcd_drawstop(); + LPC_SSP0->DMACR=0; + /* Invio un nuovo comando di lcd_area */ + lcd_area(x_start, y_start, (160-1)+x_start, (120-1)+y_start); + lcd_drawstart(); + /* */ + LPC_SSP0->DMACR=2; + + /* programmo nella LLI il nvuovo buffer... */ + LLI0.SrcAddr=(uint32_t)&pframe[3200]; + LLI1.SrcAddr=(uint32_t)&pframe[3200+3200]; + LLI2.SrcAddr=(uint32_t)&pframe[3200+3200+3200]; + /* programmo il DMA */ + LPC_GPDMACH0->DMACCSrcAddr = (uint32_t)pframe; + LPC_GPDMACH0->DMACCDestAddr = (uint32_t)&LPC_SSP0->DR; + LPC_GPDMACH0->DMACCLLI = (uint32_t)&LLI0; + LPC_GPDMACH0->DMACCControl = DMA_CHANNEL_TCIE | DMA_CHANNEL_SRC_INC | 3200; + /* Fire GPDMA Channel0 */ + LPC_GPDMACH0->DMACCConfig = DMA_CHANNEL_ENABLE | + DMA_CHANNEL_DST_PERIPHERAL_SSP0_TX | + DMA_TRANSFER_TYPE_M2P | + DMA_MASK_IE | + DMA_MASK_ITC; + + if ( feof( fp)) { + fclose( fp); + break; + } + /* Ultima lettura del buffer da SDCard... */ + size=fread( &buffer[0], sizeof(buffer[0]), sizeof(buffer)/sizeof(buffer[0]), fp); + /* Aspetto che il DMA completi il transfer... */ + while( !DMA_flag); + DMA_flag=0; + /* At this point I check if I'm at end of the file. */ + if ( feof( fp) || size != sizeof(buffer)/sizeof(buffer[0]) ) { + fclose( fp); + break; + } + } + // + LPC_SSP0->IMSC = (1UL << 3); + while(LPC_SSP0->SR & (1UL << 2)) { + /* This loop ensures we read the last byte in the + RX FIFO and test that. */ + int sr = LPC_SSP0->DR; + } + + LPC_GPDMACH0->DMACCConfig = 0; + LPC_SSP0->DMACR=0; + LPC_GPDMA->DMACConfig = 0; + LPC_GPDMA->DMACIntTCClear = 0x1; + LPC_GPDMA->DMACSoftSReq = 0; + LPC_SC->PCONP &= ~(1UL << 29); + // + lcd_drawstop(); + // + LPC_SSP0->DMACR=0; + LPC_GPDMA->DMACConfig = 0; + LPC_GPDMA->DMACIntTCClear = 0x1; + LPC_GPDMA->DMACSoftSReq = 0; + LPC_SC->PCONP &= ~(1UL << 29); + // + /* Reset to the slow SPI speed. */ + _spi.frequency( SPISlowClkSpeed); + _spi.format(8,SPIMode); + // + lcd_drawstop(); + + lcd_area(0, 0, (320-1), (240-1)); + + /* Disable the IRQ */ + NVIC_DisableIRQ(DMA_IRQn); + return 1; +} +#endif // #if ( LCD_MODE_262K==5 ) +#endif // #ifdef _USE_FILE + +void GLCD::lcd_drawicon( const unsigned char *icon, unsigned int x, unsigned int y, unsigned int size) +{ + unsigned int i; + unsigned char r, g, b; + + /* Set the fast SPI speed. */ + _spi.frequency( SPIClkSpeed); + + lcd_area(x, y, ((size-1)+x), ((size-1)+y)); + + lcd_drawstart(); + +#if ( LCD_MODE_262K==6 ) + _spi.format(6,SPIMode); +#endif + + for(i=(size*size); i!=0; i--) + { + r=*icon++; + g=*icon++; + b=*icon++; + +#if ( LCD_MODE_262K==6 ) + _spi.write( (r&0xFC)>>2 ); + _spi.write( (g&0xFC)>>2 ); + _spi.write( (b&0xFC)>>2); +#else + lcd_draw( RGB( r, g, b ) ); +#endif + } +#if ( LCD_MODE_262K==6 ) + _spi.format(8,SPIMode); +#endif + lcd_drawstop(); + /* Reset to the slow SPI speed. */ + _spi.frequency( SPISlowClkSpeed); + return; +} + +void GLCD::lcd_drawicon( const unsigned char *icon, unsigned int x, unsigned int y, unsigned int xsize, unsigned int ysize) +{ + unsigned int i; + unsigned char r, g, b; + + /* Set the fast SPI speed. */ + _spi.frequency( SPIClkSpeed); + + lcd_area(x, y, ((xsize-1)+x), ((ysize-1)+y)); + + lcd_drawstart(); + +#if ( LCD_MODE_262K==6 ) + _spi.format(6,SPIMode); +#endif + + for(i=(xsize*ysize); i!=0; i--) + { + r=*icon++; + g=*icon++; + b=*icon++; + +#if ( LCD_MODE_262K==6 ) + _spi.write( (r&0xFC)>>2 ); + _spi.write( (g&0xFC)>>2 ); + _spi.write( (b&0xFC)>>2); +#else + lcd_draw( RGB( r, g, b ) ); +#endif + } +#if ( LCD_MODE_262K==6 ) + _spi.format(8,SPIMode); +#endif + lcd_drawstop(); + /* Reset to the slow SPI speed. */ + _spi.frequency( SPISlowClkSpeed); + return; +} + + +void GLCD::lcd_drawicon( const unsigned int *icon, unsigned int x, unsigned int y, unsigned int size) +{ + unsigned int i, tmp; + + /* Set the fast SPI speed. */ + _spi.frequency( SPIClkSpeed); + + lcd_area(x, y, ((size-1)+x), ((size-1)+y)); + + lcd_drawstart(); + +#if ( LCD_MODE_262K==6 ) + _spi.format(6,SPIMode); +#endif + + for(i=(size*size); i!=0; i--) + { + tmp = *icon++; +#if ( LCD_MODE_262K==6 ) + _spi.write( (tmp&0x00FC0000)>>18 ); + _spi.write( (tmp&0x0000FC00)>>10 ); + _spi.write( (tmp&0x000000FC)>>2); +#else + lcd_draw( RGB( (( tmp&0x00FF0000)>>16), ( ( tmp&0x0000FF00)>>8), ( tmp&0x000000FF)) ); +#endif + } +#if ( LCD_MODE_262K==6 ) + _spi.format(8,SPIMode); +#endif + lcd_drawstop(); + /* Reset to the slow SPI speed. */ + _spi.frequency( SPISlowClkSpeed); + return; +} + +void GLCD::lcd_drawpixel(unsigned int x0, unsigned int y0, unsigned int color) { + + /* Set the fast SPI speed. */ + _spi.frequency( SPIClkSpeed); + + lcd_area( x0, y0, x0, y0); + lcd_drawstart(); + +#if ( LCD_MODE_262K==6 ) + _spi.format(6,SPIMode); + _spi.write( (color&0x00FC0000)>>18 ); + _spi.write( (color&0x0000FC00)>>10 ); + _spi.write( (color&0x000000FC)>>2); + _spi.format(8,SPIMode); +#else + lcd_draw(color); +#endif + + lcd_drawstop(); + /* Reset to the slow SPI speed. */ + _spi.frequency( SPISlowClkSpeed); + +} + +void GLCD::lcd_drawline(unsigned int x0, unsigned int y0, unsigned int x1, unsigned int y1, unsigned int color) { + // + // pInt32U pData = ((pInt32U) LCD_VRAM_BASE_ADDR) + x0 + (y0 * LCD_HEIGHT); + // pInt32U pData = ((pInt32U) pCurrFrmBuff) + x0 + (y0 * LCD_HEIGHT); + + int dy = y1 - y0; + int dx = x1 - x0; + int stepx, stepy; + + if (dy < 0) { dy = -dy; stepy = -1; } else { stepy = 1; } + if (dx < 0) { dx = -dx; stepx = -1; } else { stepx = 1; } + + dy <<= 1; // dy is now 2*dy + dx <<= 1; // dx is now 2*dx + + /* Set the fast SPI speed. */ + _spi.frequency( SPIClkSpeed); + + lcd_area( x0, y0, x0, y0); + lcd_drawstart(); + +#if ( LCD_MODE_262K==6 ) + _spi.format(6,SPIMode); + _spi.write( (color&0x00FC0000)>>18 ); + _spi.write( (color&0x0000FC00)>>10 ); + _spi.write( (color&0x000000FC)>>2); + _spi.format(8,SPIMode); +#else + lcd_draw(color); +#endif + + lcd_drawstop(); + + // *(pData)= color; + + if (dx > dy) { + int fraction = dy - (dx >> 1); // same as 2*dy - dx + while (x0 != x1) { + if (fraction >= 0) { + y0 += stepy; + fraction -= dx; // same as fraction -= 2*dx + } + x0 += stepx; + fraction += dy; // same as fraction -= 2*dy + // pData = ((pInt32U) LCD_VRAM_BASE_ADDR) + x0 + (y0 * C_GLCD_H_SIZE); + // pData = ((pInt32U) pCurrFrmBuff) + x0 + (y0 * C_GLCD_H_SIZE); + // *(pData)= color; + lcd_area( x0, y0, x0, y0); + lcd_drawstart(); + +#if ( LCD_MODE_262K==6 ) + _spi.format(6,SPIMode); + _spi.write( (color&0x00FC0000)>>18 ); + _spi.write( (color&0x0000FC00)>>10 ); + _spi.write( (color&0x000000FC)>>2); + _spi.format(8,SPIMode); +#else + lcd_draw(color); +#endif + + lcd_drawstop(); + + } + } else { + int fraction = dx - (dy >> 1); + while (y0 != y1) { + if (fraction >= 0) { + x0 += stepx; + fraction -= dy; + } + y0 += stepy; + fraction += dx; + // pData = ((pInt32U) LCD_VRAM_BASE_ADDR) + x0 + (y0 * C_GLCD_H_SIZE); + // pData = ((pInt32U) pCurrFrmBuff) + x0 + (y0 * C_GLCD_H_SIZE); + // *(pData)= color; + lcd_area( x0, y0, x0, y0); + lcd_drawstart(); + +#if ( LCD_MODE_262K==6 ) + _spi.format(6,SPIMode); + _spi.write( (color&0x00FC0000)>>18 ); + _spi.write( (color&0x0000FC00)>>10 ); + _spi.write( (color&0x000000FC)>>2); + _spi.format(8,SPIMode); +#else + lcd_draw(color); +#endif + + lcd_drawstop(); + } + } + /* Reset to the slow SPI speed. */ + _spi.frequency( SPISlowClkSpeed); +} + +void GLCD::lcd_reset(void) +{ + //reset + LCD_CS_DISABLE(); + LCD_RST_ENABLE(); + wait_ms(50); + LCD_RST_DISABLE(); + wait_ms(50); + + //driving ability + lcd_cmd(0xEA, 0x0000); + lcd_cmd(0xEB, 0x0020); + lcd_cmd(0xEC, 0x000C); + lcd_cmd(0xED, 0x00C4); + lcd_cmd(0xE8, 0x0040); + lcd_cmd(0xE9, 0x0038); + lcd_cmd(0xF1, 0x0001); + lcd_cmd(0xF2, 0x0010); + lcd_cmd(0x27, 0x00A3); + + //power voltage + lcd_cmd(0x1B, 0x001B); + lcd_cmd(0x1A, 0x0001); + lcd_cmd(0x24, 0x002F); + lcd_cmd(0x25, 0x0057); + + //VCOM offset + lcd_cmd(0x23, 0x008D); //for flicker adjust + + //power on + lcd_cmd(0x18, 0x0036); + lcd_cmd(0x19, 0x0001); //start osc + lcd_cmd(0x01, 0x0000); //wakeup + lcd_cmd(0x1F, 0x0088); + wait_ms(5); + lcd_cmd(0x1F, 0x0080); + wait_ms(5); + lcd_cmd(0x1F, 0x0090); + wait_ms(5); + lcd_cmd(0x1F, 0x00D0); + wait_ms(5); + + //color selection + lcd_cmd(0x17, LCD_MODE_262K); //0x0005=65k, 0x0006=262k + + //panel characteristic + lcd_cmd(0x36, 0x0000); + + //display on + lcd_cmd(0x28, 0x0038); + wait_ms(40); + lcd_cmd(0x28, 0x003C); + + //display options +#ifdef LCD_MIRROR + lcd_cmd(0x16, 0x0068); //MY=0 MX=1 MV=1 ML=0 BGR=1 +#else + lcd_cmd(0x16, 0x00A8); //MY=1 MX=0 MV=1 ML=0 BGR=1 +#endif + + lcd_area(0, 0, (LCD_WIDTH-1), (LCD_HEIGHT-1)); + + return; +} +