Basically i glued Peter Drescher and Simon Ford libs in a GraphicsDisplay class, then derived TFT or LCD class (which inherits Protocols class), then the most derived ones (Inits), which are per-display and are the only part needed to be adapted to diff hw.
Revision 7:bb0383b91104, committed 2015-02-17
- Comitter:
- Geremia
- Date:
- Tue Feb 17 11:02:06 2015 +0000
- Parent:
- 6:8356d48a07db
- Child:
- 8:26757296c79d
- Commit message:
- TFT: added get deviceID, scroll functions
Changed in this revision
--- a/Display/LCD.cpp Mon Feb 16 01:18:29 2015 +0000 +++ b/Display/LCD.cpp Tue Feb 17 11:02:06 2015 +0000 @@ -21,40 +21,29 @@ #include "LCD.h" //#include "mbed_debug.h" -//#define LCDPAGES (LCDSIZE_Y>>3) // 8raws per page -//#define IC_PAGES (IC_Y_COMS>>3) // max pages in IC ddram, 8raws per page + #define SWAP(a, b) { a ^= b; b ^= a; a ^= b; } -//#define USEFRAMEBUFFER - -//#define FRAMEBUFSIZE (LCDSIZE_X*LCDPAGES) LCD::LCD(proto_t displayproto, PortName port, PinName CS, PinName reset, PinName DC, PinName WR, PinName RD, const int lcdsize_x, const int lcdsize_y, const int ic_x_segs, const int ic_y_coms, const char *name) - : /*PAR8(port, CS, reset, DC, WR, RD),*/ GraphicsDisplay(name), LCDSIZE_X(lcdsize_x), LCDSIZE_Y(lcdsize_y), LCDPAGES(lcdsize_y>>3), IC_X_SEGS(ic_x_segs), IC_Y_COMS(ic_y_coms), IC_PAGES(ic_y_coms>>3) + : GraphicsDisplay(name), screensize_X(lcdsize_x), screensize_Y(lcdsize_y), _LCDPAGES(lcdsize_y>>3), _IC_X_SEGS(ic_x_segs), _IC_Y_COMS(ic_y_coms), _IC_PAGES(ic_y_coms>>3) { - // LCDPAGES = LCDSIZE_Y>>3; - // IC_PAGES = IC_Y_COMS>>3; - // buffer = new unsigned char [LCDSIZE_X*LCDPAGES]; - // PAR8 par8proto(port, CS, reset, DC, WR, RD); if(displayproto==PAR_8) proto = new PAR8(port, CS, reset, DC, WR, RD); useNOP=false; - buffer = (unsigned char*) malloc (LCDSIZE_X*LCDPAGES); + buffer = (unsigned char*) malloc (screensize_X*_LCDPAGES); buffer16 = (unsigned short*)buffer; draw_mode = NORMAL; set_orientation(1); foreground(White); background(Black); set_auto_up(true); + tftID=0; // cls(); // locate(0,0); } LCD::LCD(proto_t displayproto, int Hz, PinName mosi, PinName miso, PinName sclk, PinName CS, PinName reset, PinName DC, const int lcdsize_x, const int lcdsize_y, const int ic_x_segs, const int ic_y_coms, const char *name) - : GraphicsDisplay(name), LCDSIZE_X(lcdsize_x), LCDSIZE_Y(lcdsize_y), LCDPAGES(lcdsize_y>>3), IC_X_SEGS(ic_x_segs), IC_Y_COMS(ic_y_coms), IC_PAGES(ic_y_coms>>3) + : GraphicsDisplay(name), screensize_X(lcdsize_x), screensize_Y(lcdsize_y), _LCDPAGES(lcdsize_y>>3), _IC_X_SEGS(ic_x_segs), _IC_Y_COMS(ic_y_coms), _IC_PAGES(ic_y_coms>>3) { - // LCDPAGES = LCDSIZE_Y>>3; - // IC_PAGES = IC_Y_COMS>>3; - // buffer = new unsigned char [LCDSIZE_X*LCDPAGES]; - // PAR8 par8proto(port, CS, reset, DC, WR, RD); if(displayproto==SPI_8) { proto = new SPI8(Hz, mosi, miso, sclk, CS, reset, DC); @@ -65,7 +54,7 @@ proto = new SPI16(Hz, mosi, miso, sclk, CS, reset, DC); useNOP=true; } - buffer = (unsigned char*) malloc (LCDSIZE_X*LCDPAGES); + buffer = (unsigned char*) malloc (screensize_X*_LCDPAGES); buffer16 = (unsigned short*)buffer; draw_mode = NORMAL; // cls(); @@ -73,6 +62,7 @@ foreground(White); background(Black); set_auto_up(true); + tftID=0; // locate(0,0); } @@ -122,33 +112,33 @@ case (0):// portrait view -90° mirrorXY(Y); col_offset = 0; - page_offset = IC_PAGES-LCDPAGES; - set_width(LCDSIZE_Y); - set_height(LCDSIZE_X); + page_offset = _IC_PAGES-_LCDPAGES; + set_width(screensize_Y); + set_height(screensize_X); // portrait = true; break; case (1): // default, landscape view 0° mirrorXY(NONE); col_offset = 0; page_offset = 0; - set_width(LCDSIZE_X); - set_height(LCDSIZE_Y); + set_width(screensize_X); + set_height(screensize_Y); // portrait = false; break; case (2):// portrait view +90° mirrorXY(X); - col_offset = IC_X_SEGS-LCDSIZE_X; // some displays have less pixels than IC ram + col_offset = _IC_X_SEGS-screensize_X; // some displays have less pixels than IC ram page_offset = 0; - set_width(LCDSIZE_Y); - set_height(LCDSIZE_X); + set_width(screensize_Y); + set_height(screensize_X); // portrait = true; break; case (3):// landscape view +180° mirrorXY(XY); - col_offset = IC_X_SEGS-LCDSIZE_X; - page_offset = IC_PAGES-LCDPAGES; - set_width(LCDSIZE_X); - set_height(LCDSIZE_Y); + col_offset = _IC_X_SEGS-screensize_X; + page_offset = _IC_PAGES-_LCDPAGES; + set_width(screensize_X); + set_height(screensize_Y); // portrait = false; break; } @@ -251,43 +241,51 @@ { if(!(orientation&1)) SWAP(x,y); // first check parameter - if((x >= LCDSIZE_X) || (y >= LCDSIZE_Y)) return; + if((x >= screensize_X) || (y >= screensize_Y)) return; // if(draw_mode == NORMAL) // { - if(color) buffer[(x + ((y>>3)*LCDSIZE_X))^1] &= ~(1 << (y&7)); // erase pixel - else buffer[(x + ((y>>3)*LCDSIZE_X))^1] |= (1 << (y&7)); //Black=0000, set pixel + if(color) buffer[(x + ((y>>3)*screensize_X))^1] &= ~(1 << (y&7)); // erase pixel + else buffer[(x + ((y>>3)*screensize_X))^1] |= (1 << (y&7)); //Black=0000, set pixel // } // else // { // XOR mode -// if(color == 1) buffer[x + ((y>>3) * LCDSIZE_X)] ^= (1 << (y&7)); // xor pixel +// if(color == 1) buffer[x + ((y>>3) * screensize_X)] ^= (1 << (y&7)); // xor pixel // } } void LCD::copy_to_lcd(void) { unsigned short i=0; unsigned short setcolcmd = 0x0010 | ((col_offset&0xF)<<8) | (col_offset>>4); - for(int page=0; page<LCDPAGES; page++) + for(int page=0; page<_LCDPAGES; page++) { // wr_cmd8(col_offset&0xF); // set column low nibble // wr_cmd8(0x10|(col_offset>>4)); // set column hi nibble wr_cmd16(setcolcmd); wr_cmd8(0xB0|(page+page_offset)); // set page - wr_grambuf(buffer16+i, LCDSIZE_X>>1); // send whole page pixels - i+=LCDSIZE_X>>1; + wr_grambuf(buffer16+i, screensize_X>>1); // send whole page pixels + i+=screensize_X>>1; } } void LCD::cls(void) { unsigned short tmp = _background^0xFFFF; - memset(buffer,tmp,LCDSIZE_X*LCDPAGES); // clear display buffer + memset(buffer,tmp,screensize_X*_LCDPAGES); // clear display buffer unsigned short setcolcmd = 0x0010 | ((col_offset&0xF)<<8) | (col_offset>>4); - for(int page=0; page<LCDPAGES; page++) + for(int page=0; page<_LCDPAGES; page++) { // wr_cmd8((unsigned char)col_offset&0xF); // set column low nibble // wr_cmd8(0x10|(col_offset>>4)); // set column hi nibble wr_cmd16(setcolcmd); wr_cmd8(0xB0|(page+page_offset)); // set page - wr_gram(tmp, LCDSIZE_X>>1); // send whole page pixels =0 + wr_gram(tmp, screensize_X>>1); // send whole page pixels =0 } +} +int LCD::sizeX() +{ + return screensize_X; +} +int LCD::sizeY() +{ + return screensize_Y; } \ No newline at end of file
--- a/Display/LCD.h Mon Feb 16 01:18:29 2015 +0000 +++ b/Display/LCD.h Tue Feb 17 11:02:06 2015 +0000 @@ -53,9 +53,6 @@ */ virtual void pixel(int x, int y, unsigned short color); - - - /** Set the window, which controls where items are written to the screen. * When something hits the window width, it wraps back to the left side * and down a row. If the initial write is outside the window, it will @@ -66,6 +63,8 @@ * @param h is the window height in pixels. */ virtual void window(int x, int y, int w, int h); + + /** Push a single pixel into the window and increment position. * You must first call window() then push pixels in loop. @@ -102,7 +101,7 @@ */ int get_contrast(void); - /** invert the screen + /** display inverted colors * * @param o = 0 normal, 1 invert */ @@ -114,10 +113,6 @@ */ virtual void cls(); - - - - /** Set the orientation of the screen * x,y: 0,0 is always top left * @@ -135,6 +130,29 @@ */ virtual void BusEnable(bool enable); + /** get display X size in pixels (native, orientation independent) + * @returns X size in pixels + */ + int sizeX(); + + /** get display X size in pixels (native, orientation independent) + * @returns screen height in pixels. + */ + int sizeY(); + +//////////////////////////////////////////////////////////////////////////////// + // not implemented yet +////////////////////////////////////////////////////////////////// + virtual unsigned short pixelread(int x, int y){return 0;}; + virtual void window4read(int x, int y, int w, int h){}; + void setscrollarea (int startY, int areasize){}; + void scroll (int lines){}; + void scrollreset(){}; + + unsigned int tftID; + + + protected: @@ -196,12 +214,12 @@ Protocols* proto; unsigned char *buffer; unsigned short *buffer16; - const int LCDSIZE_X; - const int LCDSIZE_Y; - const int LCDPAGES; - const int IC_X_SEGS; - const int IC_Y_COMS; - const int IC_PAGES; + const int screensize_X; + const int screensize_Y; + const int _LCDPAGES; + const int _IC_X_SEGS; + const int _IC_Y_COMS; + const int _IC_PAGES; int page_offset; int col_offset;
--- a/Display/TFT.cpp Mon Feb 16 01:18:29 2015 +0000 +++ b/Display/TFT.cpp Tue Feb 17 11:02:06 2015 +0000 @@ -23,7 +23,7 @@ #define SWAP(a, b) { a ^= b; b ^= a; a ^= b; } TFT::TFT(proto_t displayproto, PortName port, PinName CS, PinName reset, PinName DC, PinName WR, PinName RD, const int lcdsize_x, const int lcdsize_y, const char *name) - : GraphicsDisplay(name), LCDSIZE_X(lcdsize_x), LCDSIZE_Y(lcdsize_y) + : GraphicsDisplay(name), screensize_X(lcdsize_x), screensize_Y(lcdsize_y) { if(displayproto==PAR_8) proto = new PAR8(port, CS, reset, DC, WR, RD); else if(displayproto==PAR_16) proto = new PAR16(port, CS, reset, DC, WR, RD); @@ -34,11 +34,13 @@ foreground(White); background(Black); set_auto_up(false); //we don't have framebuffer + topfixedareasize=0; + scrollareasize=0; // cls(); // locate(0,0); } TFT::TFT(proto_t displayproto, int Hz, PinName mosi, PinName miso, PinName sclk, PinName CS, PinName reset, PinName DC, const int lcdsize_x, const int lcdsize_y, const char *name) - : GraphicsDisplay(name), LCDSIZE_X(lcdsize_x), LCDSIZE_Y(lcdsize_y) + : GraphicsDisplay(name), screensize_X(lcdsize_x), screensize_Y(lcdsize_y) { if(displayproto==SPI_8) { @@ -56,6 +58,8 @@ foreground(White); background(Black); set_auto_up(false); + topfixedareasize=0; + scrollareasize=0; // locate(0,0); } void TFT::wr_cmd8(unsigned char cmd) @@ -83,13 +87,17 @@ { proto->wr_grambuf(data, lenght); } -unsigned int TFT::rd_data32_wdummy() - { - return proto->rd_data32_wdummy(); - } unsigned short TFT::rd_gram() { - return (proto->rd_gram()); + return proto->rd_gram(); + } +unsigned int TFT::rd_reg_data32(unsigned char reg) + { + return proto->rd_reg_data32(reg); + } +unsigned int TFT::rd_extcreg_data32(unsigned char reg, unsigned char SPIreadenablecmd) + { + return proto->rd_extcreg_data32(reg, SPIreadenablecmd); } //for TFT, just send data, position counters are in hw void TFT::window_pushpixel(unsigned short color) @@ -121,29 +129,34 @@ case 0:// default, portrait view 0° if(mipistd) wr_data8(0x0A); // this is in real a vertical flip enabled, seems most displays are vertical flipped else wr_data8(0x48); //for some other ILIxxxx - set_width(LCDSIZE_X); - set_height(LCDSIZE_Y); + set_width(screensize_X); + set_height(screensize_Y); break; case 1:// landscape view +90° if(mipistd) wr_data8(0x28); else wr_data8(0x29);//for some other ILIxxxx - set_width(LCDSIZE_Y); - set_height(LCDSIZE_X); + set_width(screensize_Y); + set_height(screensize_X); break; case 2:// portrait view +180° if(mipistd) wr_data8(0x09); else wr_data8(0x99);//for some other ILIxxxx - set_width(LCDSIZE_X); - set_height(LCDSIZE_Y); + set_width(screensize_X); + set_height(screensize_Y); break; case 3:// landscape view -90° if(mipistd) wr_data8(0x2B); else wr_data8(0xF8);//for some other ILIxxxx - set_width(LCDSIZE_Y); - set_height(LCDSIZE_X); + set_width(screensize_Y); + set_height(screensize_X); break; } } +void TFT::invert(unsigned char o) +{ + if(o == 0) wr_cmd8(0x20); + else wr_cmd8(0x21); +} // TFT have both column and raw autoincrement inside a window, with internal counters void TFT::window(int x, int y, int w, int h) { @@ -186,10 +199,70 @@ if(mipistd) color = BGR2RGB(color); // in case, convert BGR to RGB (should depend on cmd36 bit3) but maybe is device specific return color; } +void TFT::setscrollarea (int startY, int areasize) // ie 0,480 for whole screen +{ + unsigned int bfa; + topfixedareasize=startY; + scrollareasize=areasize; + wr_cmd8(0x33); + wr_data16(topfixedareasize); //num lines of top fixed area + wr_data16(scrollareasize+scrollbugfix); //num lines of vertical scroll area, +1 for ILI9481 fix + if((areasize+startY)>height()) bfa=0; + else bfa = height()-(areasize+startY); + wr_data16(bfa); //num lines of bottom fixed area +} +void TFT::scroll (int lines) // ie 1= scrollup 1, 479= scrolldown 1 +{ + wr_cmd8(0x37); + wr_data16((topfixedareasize+lines)%scrollareasize); //num lines of top fixed area +} +void TFT::scrollreset() +{ + wr_cmd8(0x13); //normal display mode +} void TFT::cls (void) { WindowMax(); - // proto->wr_gram(_background,LCDSIZE_X*LCDSIZE_Y); - // proto->wr_gram(0,LCDSIZE_X*LCDSIZE_Y); - wr_gram(_background,LCDSIZE_X*LCDSIZE_Y); + // proto->wr_gram(_background,screensize_X*screensize_Y); + // proto->wr_gram(0,screensize_X*screensize_Y); + wr_gram(_background,screensize_X*screensize_Y); +} +// try to identify display controller +void TFT::identify() +{ + // MIPI std read ID cmd + tftID=rd_reg_data32(0xBF); + mipistd=true; + // debug("ID MIPI : 0x%8X\r\n",tftID); + if(((tftID&0xFF)==((tftID>>8)&0xFF)) && ((tftID&0xFF)==((tftID>>16)&0xFF))) + { + mipistd=false; + // ILI specfic read ID cmd + tftID=rd_reg_data32(0xD3)>>8; + // debug("ID ILI : 0x%8X\r\n",tftID); + } + if(((tftID&0xFF)==((tftID>>8)&0xFF)) && ((tftID&0xFF)==((tftID>>16)&0xFF))) + { + // ILI specfic read ID cmd with ili9341 specific spi read-in enable 0xD9 cmd + tftID=rd_extcreg_data32(0xD3, 0xD9); + // debug("ID D9 extc ILI : 0x%8X\r\n",tftID); + } + if(((tftID&0xFF)==((tftID>>8)&0xFF)) && ((tftID&0xFF)==((tftID>>16)&0xFF))) + { + // ILI specfic read ID cmd with ili9486/88 specific spi read-in enable 0xFB cmd + tftID=rd_extcreg_data32(0xD3, 0xFB); + // debug("ID D9 extc ILI : 0x%8X\r\n",tftID); + } + if(((tftID&0xFF)==((tftID>>8)&0xFF)) && ((tftID&0xFF)==((tftID>>16)&0xFF))) tftID=0xDEAD; + if ((tftID&0xFFFF)==0x9481) scrollbugfix=1; + else scrollbugfix=0; + hw_reset(); // in case wrong cmds messed up important settings +} +int TFT::sizeX() +{ + return screensize_X; +} +int TFT::sizeY() +{ + return screensize_Y; } \ No newline at end of file
--- a/Display/TFT.h Mon Feb 16 01:18:29 2015 +0000 +++ b/Display/TFT.h Tue Feb 17 11:02:06 2015 +0000 @@ -85,7 +85,7 @@ */ virtual void copy_to_lcd(){ }; - /** invert the screen + /** display inverted colors * * @param o = 0 normal, 1 invert */ @@ -114,6 +114,40 @@ */ virtual void BusEnable(bool enable); + /** Set scroll area boundaries + * scroll is done in hw but only on the native vertical axis + * TFTs are mainly native protrait view, so horizontal scroll if rotated in landscape view + * + * @param startY boundary offset from top (or left if rotated), 0 for fullscreen scroll + * @param areasize size of the scroll area, 480 for fullscreen scroll of a 320x480 display + */ + void setscrollarea (int startY, int areasize); + + /** Scroll up(or left) the scrollarea + * + * @param lines number of lines to scroll, 1= scrollup 1, areasize-1= scrolldown 1 + */ + void scroll (int lines); + + /** Reset the scrollarea and display un-scrolled screen + * + */ + void scrollreset(); + + /** get display X size in pixels (native, orientation independent) + * @returns X size in pixels + */ + int sizeX(); + + /** get display X size in pixels (native, orientation independent) + * @returns screen height in pixels. + */ + int sizeY(); + + unsigned int tftID; + + + protected: @@ -165,38 +199,44 @@ */ virtual void wr_grambuf(unsigned short* data, unsigned int lenght); - /** Read 4x8bit data from display controller (with dummy cycle) - * - * @returns data as uint - * - */ - virtual unsigned int rd_data32_wdummy(); - /** Read 16bit pixeldata from display controller (with dummy cycle) * * @returns 16bit color */ virtual unsigned short rd_gram(); + /** Read 4x8bit register data (with dummy cycle) + * @param reg the register to read + * @returns data as uint + * + */ + virtual unsigned int rd_reg_data32(unsigned char reg); + + /** Read 3x8bit ExtendedCommands register data + * @param reg the register to read + * @param SPIreadenablecmd vendor/device specific cmd to read EXTC registers + * @returns data as uint + * @note EXTC regs (0xB0 to 0xFF) are read/write registers but needs special cmd to be read in SPI mode + */ + virtual unsigned int rd_extcreg_data32(unsigned char reg, unsigned char SPIreadenablecmd); + /** HW reset sequence (without display init commands) */ void hw_reset(); + /** Try to identify display ID + * @note support ILI9341,94xx, MIPI standard. May be be overridden in Init class for other specific IC + */ + virtual void identify(); + unsigned int scrollbugfix; bool mipistd; private: Protocols* proto; - const int LCDSIZE_X; - const int LCDSIZE_Y; - // const int LCDPAGES; - // const int IC_X_SEGS; - // const int IC_Y_COMS; - // const int IC_PAGES; - - // int page_offset; - // int col_offset; + const int screensize_X; + const int screensize_Y; // pixel location int cur_x; int cur_y; @@ -206,7 +246,8 @@ int win_y1; int win_y2; int orientation; - unsigned int tftID; + int topfixedareasize; + int scrollareasize; bool useNOP; };
--- a/Inits/ILI9341.cpp Mon Feb 16 01:18:29 2015 +0000 +++ b/Inits/ILI9341.cpp Tue Feb 17 11:02:06 2015 +0000 @@ -20,8 +20,8 @@ { hw_reset(); BusEnable(true); + identify(); // will collect tftID and set mipistd flag init(); - mipistd=false; set_orientation(0); cls(); locate(0,0); @@ -31,8 +31,8 @@ { hw_reset(); //TFT class forwards to Protocol class BusEnable(true); //TFT class forwards to Protocol class + identify(); // will collect tftID and set mipistd flag init(); // per display custom init cmd sequence, implemented here - mipistd=false; set_orientation(0); //TFT class does for MIPI standard and some ILIxxx cls(); locate(0,0);
--- a/Inits/ILI9486.cpp Mon Feb 16 01:18:29 2015 +0000 +++ b/Inits/ILI9486.cpp Tue Feb 17 11:02:06 2015 +0000 @@ -19,9 +19,8 @@ { hw_reset(); BusEnable(true); + identify(); // will collect tftID and set mipistd flag init(); - mipistd=false; - scrollbugfix=1; // when scrolling 1 line, the last line disappears, set to 1 to fix it set_orientation(0); cls(); locate(0,0); @@ -31,9 +30,8 @@ { hw_reset(); //TFT class forwards to Protocol class BusEnable(true); //TFT class forwards to Protocol class + identify(); // will collect tftID and set mipistd flag init(); // per display custom init cmd sequence, implemented here - mipistd=false; - scrollbugfix=1; // when scrolling 1 line, the last line disappears, set to 1 to fix it set_orientation(0); //TFT class does for MIPI standard and some ILIxxx cls(); locate(0,0);
--- a/Inits/TFT_MIPI.cpp Mon Feb 16 01:18:29 2015 +0000 +++ b/Inits/TFT_MIPI.cpp Tue Feb 17 11:02:06 2015 +0000 @@ -19,8 +19,9 @@ { hw_reset(); BusEnable(true); + identify(); // will collect tftID, set mipistd flag init(); - mipistd=true; +// scrollbugfix=1; // when scrolling 1 line, the last line disappears, set to 1 to fix it, for ili9481 is set automatically in identify() set_orientation(0); cls(); locate(0,0); @@ -30,8 +31,9 @@ { hw_reset(); //TFT class forwards to Protocol class BusEnable(true); //TFT class forwards to Protocol class + identify(); // will collect tftID and set mipistd flag init(); // per display custom init cmd sequence, implemented here - mipistd=true; + // scrollbugfix=1; // when scrolling 1 line, the last line disappears, set to 1 to fix it, for ili9481 is set automatically in identify() set_orientation(0); //TFT class does for MIPI standard and some ILIxxx cls(); locate(0,0);
--- a/Protocols/PAR16.cpp Mon Feb 16 01:18:29 2015 +0000 +++ b/Protocols/PAR16.cpp Tue Feb 17 11:02:06 2015 +0000 @@ -150,11 +150,36 @@ _CS = 1; #endif } -unsigned int PAR16::rd_data32_wdummy() +unsigned short PAR16::rd_gram() { #ifdef USE_CS _CS = 0; #endif + unsigned short r=0; + _DC = 1; // 1=data + _port.input(); + + _RD = 0; + _port.read(); //dummy read + _RD = 1; + + _RD = 0; +// _RD = 0; // add wait + r |= _port.read(); + _RD = 1; + +#ifdef USE_CS + _CS = 1; +#endif + _port.output(); + return r; +} +unsigned int PAR16::rd_reg_data32(unsigned char reg) +{ +#ifdef USE_CS + _CS = 0; +#endif + wr_cmd8(reg); unsigned int r=0; _DC = 1; // 1=data _port.input(); @@ -193,29 +218,10 @@ _port.output(); return r; } -unsigned short PAR16::rd_gram() +// in Par mode EXTC regs (0xB0-0xFF) can be directly read +unsigned int PAR16::rd_extcreg_data32(unsigned char reg, unsigned char SPIreadenablecmd) { -#ifdef USE_CS - _CS = 0; -#endif - unsigned short r=0; - _DC = 1; // 1=data - _port.input(); - - _RD = 0; - _port.read(); //dummy read - _RD = 1; - - _RD = 0; -// _RD = 0; // add wait - r |= _port.read(); - _RD = 1; - -#ifdef USE_CS - _CS = 1; -#endif - _port.output(); - return r; + return rd_reg_data32(reg); } void PAR16::hw_reset() {
--- a/Protocols/PAR16.h Mon Feb 16 01:18:29 2015 +0000 +++ b/Protocols/PAR16.h Tue Feb 17 11:02:06 2015 +0000 @@ -75,19 +75,26 @@ */ virtual void wr_grambuf(unsigned short* data, unsigned int lenght); - /** Read 4x8bit data from display controller (with dummy cycle) - * - * @returns data as uint - * - */ - virtual unsigned int rd_data32_wdummy(); - /** Read 16bit pixeldata from display controller (with dummy cycle) * * @returns 16bit color */ virtual unsigned short rd_gram(); + /** Read 4x8bit register data (with dummy cycle) + * @param reg the register to read + * @returns data as uint + * + */ + virtual unsigned int rd_reg_data32(unsigned char reg); + + /** Read 3x8bit ExtendedCommands register data + * @param reg the register to read + * @returns data as uint + * @note EXTC regs (0xB0 to 0xFF) are read/write registers, for Parallel mode directly accessible in both directions + */ + virtual unsigned int rd_extcreg_data32(unsigned char reg, unsigned char SPIreadenablecmd); + /** HW reset sequence (without display init commands) */ virtual void hw_reset();
--- a/Protocols/PAR8.cpp Mon Feb 16 01:18:29 2015 +0000 +++ b/Protocols/PAR8.cpp Tue Feb 17 11:02:06 2015 +0000 @@ -174,11 +174,42 @@ _CS = 1; #endif } -unsigned int PAR8::rd_data32_wdummy() +unsigned short PAR8::rd_gram() { #ifdef USE_CS _CS = 0; #endif + unsigned short r=0; + _DC = 1; // 1=data + _port.input(); + + _RD = 0; + _port.read(); //dummy read + _RD = 1; + + _RD = 0; +// _RD = 0; // add wait + r |= (_port.read()&0xFF); + r <<= 8; + _RD = 1; + + _RD = 0; +// _RD = 0; // add wait + r |= (_port.read()&0xFF); + _RD = 1; + +#ifdef USE_CS + _CS = 1; +#endif + _port.output(); + return r; +} +unsigned int PAR8::rd_reg_data32(unsigned char reg) +{ +#ifdef USE_CS + _CS = 0; +#endif + wr_cmd8(reg); unsigned int r=0; _DC = 1; // 1=data _port.input(); @@ -217,35 +248,10 @@ _port.output(); return r; } -unsigned short PAR8::rd_gram() +// in Par mode EXTC regs (0xB0-0xFF) can be directly read +unsigned int PAR8::rd_extcreg_data32(unsigned char reg, unsigned char SPIreadenablecmd) { -#ifdef USE_CS - _CS = 0; -#endif - unsigned short r=0; - _DC = 1; // 1=data - _port.input(); - - _RD = 0; - _port.read(); //dummy read - _RD = 1; - - _RD = 0; -// _RD = 0; // add wait - r |= (_port.read()&0xFF); - r <<= 8; - _RD = 1; - - _RD = 0; -// _RD = 0; // add wait - r |= (_port.read()&0xFF); - _RD = 1; - -#ifdef USE_CS - _CS = 1; -#endif - _port.output(); - return r; + return rd_reg_data32(reg); } void PAR8::hw_reset() {
--- a/Protocols/PAR8.h Mon Feb 16 01:18:29 2015 +0000 +++ b/Protocols/PAR8.h Tue Feb 17 11:02:06 2015 +0000 @@ -75,19 +75,26 @@ */ virtual void wr_grambuf(unsigned short* data, unsigned int lenght); - /** Read 4x8bit data from display controller (with dummy cycle) - * - * @returns data as uint - * - */ - virtual unsigned int rd_data32_wdummy(); - /** Read 16bit pixeldata from display controller (with dummy cycle) * * @returns 16bit color */ virtual unsigned short rd_gram(); + /** Read 4x8bit register data (with dummy cycle) + * @param reg the register to read + * @returns data as uint + * + */ + virtual unsigned int rd_reg_data32(unsigned char reg); + + /** Read 3x8bit ExtendedCommands register data + * @param reg the register to read + * @returns data as uint + * @note EXTC regs (0xB0 to 0xFF) are read/write registers, for Parallel mode directly accessible in both directions + */ + virtual unsigned int rd_extcreg_data32(unsigned char reg, unsigned char SPIreadenablecmd); + /** HW reset sequence (without display init commands) */ virtual void hw_reset();
--- a/Protocols/Protocols.h Mon Feb 16 01:18:29 2015 +0000 +++ b/Protocols/Protocols.h Tue Feb 17 11:02:06 2015 +0000 @@ -82,19 +82,27 @@ */ virtual void wr_grambuf(unsigned short* data, unsigned int lenght) = 0; - /** Read 4x8bit data from display controller (with dummy cycle) - * - * @returns data as uint - * - */ - virtual unsigned int rd_data32_wdummy() = 0; - /** Read 16bit pixeldata from display controller (with dummy cycle) * * @returns 16bit color */ virtual unsigned short rd_gram() = 0; + /** Read 4x8bit register data (with dummy cycle) + * @param reg the register to read + * @returns data as uint + * + */ + virtual unsigned int rd_reg_data32(unsigned char reg) = 0; + + /** Read 3x8bit ExtendedCommands register data + * @param reg the register to read + * @param SPIreadenablecmd vendor/device specific cmd to read EXTC registers + * @returns data as uint + * @note EXTC regs (0xB0 to 0xFF) are read/write registers but needs special cmd to be read in SPI mode + */ + virtual unsigned int rd_extcreg_data32(unsigned char reg, unsigned char SPIreadenablecmd) = 0; + /** HW reset sequence (without display init commands) */ virtual void hw_reset() = 0;
--- a/Protocols/SPI16.cpp Mon Feb 16 01:18:29 2015 +0000 +++ b/Protocols/SPI16.cpp Tue Feb 17 11:02:06 2015 +0000 @@ -121,26 +121,6 @@ _CS = 1; #endif } -unsigned int SPI16::rd_data32_wdummy() -{ -#ifdef USE_CS - _CS = 0; -#endif - unsigned int r=0; - _DC.write(1);; // 1=data - - r |= _spi.write(0); // we get only 15bit valid, first bit was the dummy cycle - r <<= 16; - r |= _spi.write(0); - r <<= 1; // 32bits are aligned, now collecting bit_0 - r |= (_spi.write(0) >> 15); - // we clocked 15 more bit so ILI waiting for 16th, we need to reset spi bus - _CS = 1; // force CS HIG to interupt the cmd -#ifndef USE_CS //if CS is not used, force fixed LOW again - _CS = 0; -#endif - return r; -} unsigned short SPI16::rd_gram() { #ifdef USE_CS @@ -160,6 +140,45 @@ r = RGB18to16((r&0xFC0000)>>16, (r&0xFC00)>>8, r&0xFC);// 18bit pixel, rrrrrr00_gggggg00_bbbbbb00, converted to 16bit return (unsigned short)r; } +unsigned int SPI16::rd_reg_data32(unsigned char reg) +{ +#ifdef USE_CS + _CS = 0; +#endif + wr_cmd8(reg); + unsigned int r=0; + _DC.write(1);; // 1=data + + r |= _spi.write(0); // we get only 15bit valid, first bit was the dummy cycle + r <<= 16; + r |= _spi.write(0); + r <<= 1; // 32bits are aligned, now collecting bit_0 + r |= (_spi.write(0) >> 15); + // we clocked 15 more bit so ILI waiting for 16th, we need to reset spi bus + _CS = 1; // force CS HIG to interupt the cmd +#ifndef USE_CS //if CS is not used, force fixed LOW again + _CS = 0; +#endif + return r; +} +unsigned int SPI16::rd_extcreg_data32(unsigned char reg, unsigned char SPIreadenablecmd) +{ + unsigned int r=0; + for(int regparam=1; regparam<4; regparam++) // when reading EXTC regs, first parameter is always dummy, so start with 1 + { + wr_cmd8(SPIreadenablecmd); // spi-in enable cmd, 0xD9 (ili9341) or 0xFB (ili9488) or don't know + wr_data8(0xF0|regparam); // in low nibble specify which reg parameter we want + wr_cmd8(reg); // now send cmd (select register we want to read) + _DC.write(1); // 1=data + r <<= 8; + r |= (_spi.write(0) >> 8); + } +_CS = 1; // force CS HIG to interupt the cmd +#ifndef USE_CS //if CS is not used, force fixed LOW again + _CS = 0; +#endif + return r; +} void SPI16::hw_reset() { wait_ms(15);
--- a/Protocols/SPI16.h Mon Feb 16 01:18:29 2015 +0000 +++ b/Protocols/SPI16.h Tue Feb 17 11:02:06 2015 +0000 @@ -77,19 +77,27 @@ */ virtual void wr_grambuf(unsigned short* data, unsigned int lenght); - /** Read 4x8bit data from display controller (with dummy cycle) - * - * @returns data as uint - * - */ - virtual unsigned int rd_data32_wdummy(); - /** Read 16bit pixeldata from display controller (with dummy cycle) * * @returns 16bit color */ virtual unsigned short rd_gram(); + /** Read 4x8bit register data (with dummy cycle) + * @param reg the register to read + * @returns data as uint + * + */ + virtual unsigned int rd_reg_data32(unsigned char reg); + + /** Read 3x8bit ExtendedCommands register data + * @param reg the register to read + * @param SPIreadenablecmd vendor/device specific cmd to read EXTC registers + * @returns data as uint + * @note EXTC regs (0xB0 to 0xFF) are read/write registers but needs special cmd to be read in SPI mode + */ + virtual unsigned int rd_extcreg_data32(unsigned char reg, unsigned char SPIreadenablecmd); + /** HW reset sequence (without display init commands) */ virtual void hw_reset();
--- a/Protocols/SPI8.cpp Mon Feb 16 01:18:29 2015 +0000 +++ b/Protocols/SPI8.cpp Tue Feb 17 11:02:06 2015 +0000 @@ -135,30 +135,6 @@ _CS = 1; #endif } -unsigned int SPI8::rd_data32_wdummy() -{ -#ifdef USE_CS - _CS = 0; -#endif - unsigned int r=0; - _DC.write(1); // 1=data - - r |= _spi.write(0); // we get only 7bit valid, first bit was the dummy cycle - r <<= 8; - r |= _spi.write(0); - r <<= 8; - r |= _spi.write(0); - r <<= 8; - r |= _spi.write(0); - r <<= 1; // 32bits are aligned, now collecting bit_0 - r |= (_spi.write(0) >> 7); - // we clocked 7 more bit so ILI waiting for 8th, we need to reset spi bus - _CS = 1; // force CS HIG to interupt the cmd -#ifndef USE_CS //if CS is not used, force fixed LOW again - _CS = 0; -#endif - return r; -} unsigned short SPI8::rd_gram() { #ifdef USE_CS @@ -181,6 +157,50 @@ r = RGB18to16((r&0xFC0000)>>16, (r&0xFC00)>>8, r&0xFC);// 18bit pixel, rrrrrr00_gggggg00_bbbbbb00, converted to 16bit return (unsigned short)r; } +unsigned int SPI8::rd_reg_data32(unsigned char reg) +{ +#ifdef USE_CS + _CS = 0; +#endif + wr_cmd8(reg); + unsigned int r=0; + _DC.write(1); // 1=data + + r |= _spi.write(0); // we get only 7bit valid, first bit was the dummy cycle + r <<= 8; + r |= _spi.write(0); + r <<= 8; + r |= _spi.write(0); + r <<= 8; + r |= _spi.write(0); + r <<= 1; // 32bits are aligned, now collecting bit_0 + r |= (_spi.write(0) >> 7); + // we clocked 7 more bit so ILI waiting for 8th, we need to reset spi bus + _CS = 1; // force CS HIG to interupt the cmd +#ifndef USE_CS //if CS is not used, force fixed LOW again + _CS = 0; +#endif + return r; +} +unsigned int SPI8::rd_extcreg_data32(unsigned char reg, unsigned char SPIreadenablecmd) +{ + unsigned int r=0; + for(int regparam=1; regparam<4; regparam++) // when reading EXTC regs, first parameter is always dummy, so start with 1 + { + wr_cmd8(SPIreadenablecmd); // spi-in enable cmd, 0xD9 (ili9341) or 0xFB (ili9488) or don't know + wr_data8(0xF0|regparam); // in low nibble specify which reg parameter we want + wr_cmd8(reg); // now send cmd (select register we want to read) + _DC.write(1); // 1=data + r <<= 8; + r |= _spi.write(0); + // r = _spi.write(0) >> 8; for 16bit + } +_CS = 1; // force CS HIG to interupt the cmd +#ifndef USE_CS //if CS is not used, force fixed LOW again + _CS = 0; +#endif + return r; +} void SPI8::hw_reset() { wait_ms(15);
--- a/Protocols/SPI8.h Mon Feb 16 01:18:29 2015 +0000 +++ b/Protocols/SPI8.h Tue Feb 17 11:02:06 2015 +0000 @@ -74,19 +74,27 @@ */ virtual void wr_grambuf(unsigned short* data, unsigned int lenght); - /** Read 4x8bit data from display controller (with dummy cycle) - * - * @returns data as uint - * - */ - virtual unsigned int rd_data32_wdummy(); - /** Read 16bit pixeldata from display controller (with dummy cycle) * * @returns 16bit color */ virtual unsigned short rd_gram(); + /** Read 4x8bit register data (with dummy cycle) + * @param reg the register to read + * @returns data as uint + * + */ + virtual unsigned int rd_reg_data32(unsigned char reg); + + /** Read 3x8bit ExtendedCommands register data + * @param reg the register to read + * @param SPIreadenablecmd vendor/device specific cmd to read EXTC registers + * @returns data as uint + * @note EXTC regs (0xB0 to 0xFF) are read/write registers but needs special cmd to be read in SPI mode + */ + virtual unsigned int rd_extcreg_data32(unsigned char reg, unsigned char SPIreadenablecmd); + /** HW reset sequence (without display init commands) */ virtual void hw_reset();