UniGraphic-Fork for ST7920-LCD-controller and SH1106. Tested with 128x64 LCD with SPI and 128x64-OLED with IIC
Dependents: UniGraphic-St7920-Test AfficheurUTILECO
Fork of UniGraphic by
Fork of the UniGraphic-Library for monochrome LCDs with ST7920 controller and 128x64-IIC-OLED-Display with SH1106-Controller

Had to adapt LCD for following reasons:
- Give access to screenbuffer buffer[] to parent class
- pixel() and pixel_read() as they are hardware-dependent
- added reset-pin to IIC-Interface
GraphicDisplay:: sends buffer to LCD when auto_update is set to true.
Testprogram for ST7920 can be found here:
https://developer.mbed.org/users/charly/code/UniGraphic-St7920-Test/
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();
