Important changes to repositories hosted on mbed.com
Mbed hosted mercurial repositories are deprecated and are due to be permanently deleted in July 2026.
To keep a copy of this software download the repository Zip archive or clone locally using Mercurial.
It is also possible to export all your personal repositories from the account settings page.
Fork of UniGraphic by
Revision 20:14daa48ffd4c, committed 2015-03-23
- Comitter:
- Geremia
- Date:
- Mon Mar 23 14:08:04 2015 +0000
- Parent:
- 19:1bdfb971b2c1
- Child:
- 21:ae0a4eedfc90
- Commit message:
- Add ILI 9320/9325/9328 custom TFT932x class, parallel/spi 8/16bit, with orientation, scroll, pixelread, fastwindow.; Par8 and 16 tested, SPI not at all, needs checking if the CS toggle is necessary (see SPI8.cpp SPI16.cpp).
Changed in this revision
--- a/Display/LCD.cpp Mon Mar 02 10:52:26 2015 +0000
+++ b/Display/LCD.cpp Mon Mar 23 14:08:04 2015 +0000
@@ -243,15 +243,17 @@
// first check parameter
if((x >= screensize_X) || (y >= screensize_Y)) return;
-// if(draw_mode == NORMAL)
-// {
- 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) * screensize_X)] ^= (1 << (y&7)); // xor 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
+}
+unsigned short LCD::pixelread(int x, int y)
+{
+ if(!(orientation&1)) SWAP(x,y);
+ // first check parameter
+ if((x >= screensize_X) || (y >= screensize_Y)) return 0;
+
+ if((buffer[(x + ((y>>3)*screensize_X))^1] & (1 << (y&7)))==0) return 0xFFFF ; // pixel not set, White
+ else return 0; // pixel set, Black
}
void LCD::copy_to_lcd(void)
{
--- a/Display/LCD.h Mon Mar 02 10:52:26 2015 +0000
+++ b/Display/LCD.h Mon Mar 23 14:08:04 2015 +0000
@@ -68,7 +68,12 @@
*/
virtual void window(int x, int y, int w, int h);
-
+ /** Read pixel color at location
+ * @param x is the horizontal offset to this pixel.
+ * @param y is the vertical offset to this pixel.
+ * @returns 16bit color, 0000=Black(pixel set), FFFF=White(pixel clear).
+ */
+ virtual unsigned short pixelread(int x, int y);
/** Push a single pixel into the window and increment position.
* You must first call window() then push pixels in loop.
@@ -139,15 +144,15 @@
*/
int sizeX();
- /** get display X size in pixels (native, orientation independent)
- * @returns screen height in pixels.
+ /** get display Y size in pixels (native, orientation independent)
+ * @returns Y size in pixels
*/
int sizeY();
////////////////////////////////////////////////////////////////////////////////
// not implemented yet
//////////////////////////////////////////////////////////////////
- virtual unsigned short pixelread(int x, int y){return 0;};
+ // 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){};
--- a/Display/TFT.cpp Mon Mar 02 10:52:26 2015 +0000
+++ b/Display/TFT.cpp Mon Mar 23 14:08:04 2015 +0000
@@ -123,6 +123,7 @@
void TFT::hw_reset()
{
proto->hw_reset();
+ BusEnable(true);
}
void TFT::BusEnable(bool enable)
{
@@ -291,7 +292,7 @@
{
if(BGR2RGB(rback)==px) isBGR=true;
}
- // else debug("\r\nfail to identify gram read color format,\r\nsent %.4X read16 %.4X read18 %.4X", px, rback, rback18);
+ // debug("\r\nIdentify gram read color format,\r\nsent %.4X read16 %.4X(bgr%.4X) read18 %.4X(bgr%.4X)", px, rback, BGR2RGB(rback), rback18, BGR2RGB(rback18));
}
// try to identify display controller
void TFT::identify()
--- a/Display/TFT.h Mon Mar 02 10:52:26 2015 +0000
+++ b/Display/TFT.h Mon Mar 23 14:08:04 2015 +0000
@@ -146,8 +146,8 @@
*/
int sizeX();
- /** get display X size in pixels (native, orientation independent)
- * @returns screen height in pixels.
+ /** get display Y size in pixels (native, orientation independent)
+ * @returns Y size in pixels
*/
int sizeY();
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/Display/TFT932x.cpp Mon Mar 23 14:08:04 2015 +0000
@@ -0,0 +1,309 @@
+ /* mbed UniGraphic library - custom TFT driver class, ILI932x specific
+ * Copyright (c) 2015 Giuliano Dianda
+ * Released under the MIT License: http://mbed.org/license/mit
+ */
+
+#include "TFT932x.h"
+
+//#include "mbed_debug.h"
+
+#define SWAP(a, b) { a ^= b; b ^= a; a ^= b; }
+
+TFT932x::TFT932x(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), screensize_X(lcdsize_x), screensize_Y(lcdsize_y)
+{
+ if(displayproto==PAR_8)
+ {
+ proto = new PAR8(port, CS, reset, DC, WR, RD);
+ dummycycles=1;
+ }
+ else if(displayproto==PAR_16)
+ {
+ proto = new PAR16(port, CS, reset, DC, WR, RD);
+ dummycycles=0;
+ }
+ // set_orientation(0);
+ foreground(White);
+ background(Black);
+ set_auto_up(false); //we don't have framebuffer
+ usefastwindow=false;
+ fastwindowready=false;
+ is18bit=false;
+ isBGR=false;
+ // cls();
+ // locate(0,0);
+}
+TFT932x::TFT932x(proto_t displayproto, int Hz, PinName mosi, PinName miso, PinName sclk, PinName CS, PinName reset, const int lcdsize_x, const int lcdsize_y, const char *name)
+ : GraphicsDisplay(name), screensize_X(lcdsize_x), screensize_Y(lcdsize_y)
+{
+ if(displayproto==SPI_8)
+ {
+ proto = new SPI8(Hz, mosi, miso, sclk, CS, reset);
+ dummycycles=4;
+ }
+ else if(displayproto==SPI_16)
+ {
+ proto = new SPI16(Hz, mosi, miso, sclk, CS, reset);
+ dummycycles=2;
+ }
+ // set_orientation(0);
+ foreground(White);
+ background(Black);
+ set_auto_up(false);
+ usefastwindow=false;
+ fastwindowready=false;
+ is18bit=false;
+ isBGR=false;
+ // locate(0,0);
+}
+// dummy read needed before read gram
+// read gram protocol function does 1 dymmy read as for MIPI standard, but ILI932x needs more and protocol specific number of cycles
+// for example in spi mode, 5 dummy byte read needed, so for SPI16 2x16bit clocks done here and the 5th dummy will be handled by read gram function
+void TFT932x::dummyread()
+ {
+ for(unsigned int i=0; i<dummycycles; i++) proto->dummyread();
+ }
+void TFT932x::reg_select(unsigned char reg, bool forread)
+ {
+ proto->reg_select(reg, forread);
+ }
+void TFT932x::reg_write(unsigned char reg, unsigned short data)
+ {
+ proto->reg_write(reg, data);
+ }
+unsigned short TFT932x::reg_read(unsigned char reg)
+ {
+ return proto->reg_read(reg);
+ }
+void TFT932x::wr_gram(unsigned short data)
+ {
+ proto->wr_gram(data);
+ }
+void TFT932x::wr_gram(unsigned short data, unsigned int count)
+ {
+ proto->wr_gram(data, count);
+ }
+void TFT932x::wr_grambuf(unsigned short* data, unsigned int lenght)
+ {
+ proto->wr_grambuf(data, lenght);
+ }
+unsigned short TFT932x::rd_gram()
+ {
+ return proto->rd_gram(is18bit); // protocol will handle 18to16 bit conversion
+
+ }
+//for TFT, just send data, position counters are in hw
+void TFT932x::window_pushpixel(unsigned short color)
+{
+ proto->wr_gram(color);
+}
+void TFT932x::window_pushpixel(unsigned short color, unsigned int count)
+{
+ proto->wr_gram(color, count);
+}
+void TFT932x::window_pushpixelbuf(unsigned short* color, unsigned int lenght)
+ {
+ proto->wr_grambuf(color, lenght);
+ }
+void TFT932x::hw_reset()
+ {
+ proto->hw_reset();
+ BusEnable(true);
+ }
+void TFT932x::BusEnable(bool enable)
+ {
+ proto->BusEnable(enable);
+ }
+// ILI932x can't rotate in hw (swap raw<->columns) for landscape views,
+// but can change the way address counter is auto incremented/decremented
+void TFT932x::set_orientation(int o)
+{
+ // if(orientation == o) return;
+ orientation = o;
+ switch (orientation)
+ // BGR bit set for all modes, seems most TFT are like that, in case override set_orientation() in init
+ // ORG bit set for all modes
+ {
+ case 0:// default, portrait view 0°
+ reg_write(0x0001,0x0100); // S720 to S1
+ reg_write(0x0060,0xA700); // G320 to G1
+ reg_write(0x03, 0x10B0);
+ set_width(screensize_X);
+ set_height(screensize_Y);
+ break;
+ case 1:// landscape view +90°
+ reg_write(0x0001,0x0000); // S1 to S720
+ reg_write(0x0060,0xA700); // G320 to G1
+ reg_write(0x03, 0x10B8); // AM=1 increase addr ctr first vertically then horizontally
+ set_width(screensize_Y);
+ set_height(screensize_X);
+ break;
+ case 2:// portrait view +180°
+ reg_write(0x0001,0x0000); // S1 to S720
+ reg_write(0x0060,0x2700); // G1 to G320
+ reg_write(0x03, 0x10B0);
+ set_width(screensize_X);
+ set_height(screensize_Y);
+ break;
+ case 3:// landscape view -90°
+ reg_write(0x0001,0x0100); // S720 to S1
+ reg_write(0x0060,0x2700); // G1 to G320
+ reg_write(0x03, 0x10B8); // AM=1 increase addr ctr first vertically then horizontally
+ set_width(screensize_Y);
+ set_height(screensize_X);
+ break;
+ }
+}
+void TFT932x::invert(unsigned char o)
+{
+ unsigned short oldreg = reg_read(0x61);
+ if(o == 0) reg_write(0x61, oldreg|1); // seems most TFT have REV bit enabled for normal display
+ else reg_write(0x61, oldreg&0xFFFE);
+}
+void TFT932x::FastWindow(bool enable)
+ {
+ usefastwindow=enable;
+ }
+// TFT have both column and raw autoincrement inside a window, with internal counters
+void TFT932x::window(int x, int y, int w, int h)
+{
+ if(orientation==1 || orientation==3)
+ {
+ SWAP(x,y);
+ SWAP(w,h);
+ }
+ fastwindowready=false; // end raw/column going to be set to lower value than bottom-right corner
+ reg_write(0x50, x);//start column
+ reg_write(0x51, x+w-1);//end column
+ reg_write(0x52, y);//start page
+ reg_write(0x53, y+h-1);//end page
+
+ reg_write(0x20, 0); // since ORG bit is set, address is windows relative, so should be set always to 0000
+ reg_write(0x21, 0);
+
+ reg_select(0x22, false); //write mem, just write gram next
+}
+void TFT932x::window4read(int x, int y, int w, int h)
+{
+ if(orientation==1 || orientation==3)
+ {
+ SWAP(x,y);
+ SWAP(w,h);
+ }
+ fastwindowready=false; // end raw/column going to be set to lower value than bottom-right corner
+ reg_write(0x50, x);//start column
+ reg_write(0x51, x+w-1);//end column
+ reg_write(0x52, y);//start page
+ reg_write(0x53, y+h-1);//end page
+
+ reg_write(0x20, 0); // since ORG bit is set, address is windows relative, so should be set always to 0000
+ reg_write(0x21, 0);
+
+ reg_select(0x22, true); //read mem, just read gram next
+ dummyread();
+}
+void TFT932x::pixel(int x, int y, unsigned short color)
+{
+ if(usefastwindow)
+ {
+ if(fastwindowready) //setting only start column/page does speedup, but needs end raw/column previously set to bottom-right corner
+ {
+ if(orientation==1 || orientation==3) SWAP(x,y);
+ reg_write(0x50, x);//start column only
+ reg_write(0x52, y);//start page only
+ reg_write(0x20, 0); // since ORG bit is set, address is window relative, so should be set always to 0000
+ reg_write(0x21, 0);
+ reg_select(0x22, false); //write mem, just write gram next
+ }
+ else
+ {
+ window(x,y,width()-x,height()-y); // set also end raw/column to bottom-right corner
+ fastwindowready=true;
+ }
+ }
+ else window(x,y,1,1);
+ wr_gram(color);
+}
+unsigned short TFT932x::pixelread(int x, int y)
+{
+ /* if(usefastwindow) // for ILI9325 fastwindows for reading works only in PAR16
+ {
+ if(fastwindowready) //setting only start column/page does speedup, but needs end raw/column previously set to bottom-right corner
+ {
+ if(orientation==1 || orientation==3) SWAP(x,y);
+ reg_write(0x50, x);//start column only
+ reg_write(0x52, y);//start page only
+ reg_write(0x20, 0); // since ORG bit is set, address is window relative, so should be set always to 0000
+ reg_write(0x21, 0);
+ reg_select(0x22, true); //read mem, just read gram next
+ }
+ else
+ {
+ window4read(x,y,width()-x,height()-y); // set also end raw/column to bottom-right corner
+ fastwindowready=true;
+ }
+ }
+ else*/
+ window4read(x,y,1,1);
+
+ unsigned short color;
+ color = rd_gram();
+ if(isBGR) color = BGR2RGB(color); // in case, convert BGR to RGB
+ return color;
+}
+void TFT932x::setscrollarea (int startY, int areasize) // ie 0,480 for whole screen
+{
+ // ILI932x allows only ful lscreen scrolling
+ unsigned short oldreg = reg_read(0x61);
+ reg_write(0x61, oldreg|2); // enable scroll
+}
+void TFT932x::scroll (int lines) // ie 1= scrollup 1, 479= scrolldown 1
+{
+ reg_write(0x6A, lines%screensize_Y); // select the (absolute)line which will be displayed as first line
+}
+void TFT932x::scrollreset()
+{
+ unsigned short oldreg = reg_read(0x61);
+ // reg_write(0x61, oldreg&0xFFFD); // disable scroll
+ reg_write(0x6A, 0);
+}
+void TFT932x::cls (void)
+{
+ WindowMax();
+ wr_gram(_background,screensize_X*screensize_Y);
+}
+// try to get read gram pixel format, could be 16bit or 18bit, RGB or BGR
+void TFT932x::auto_gram_read_format()
+{
+ unsigned short px=0xCDB1;
+ unsigned short rback, rback18;
+ pixel(0,0,px);
+ window4read(0,0,1,1);
+ rback=proto->rd_gram(0); // try 16bit
+ window4read(0,0,1,1);
+ rback18=proto->rd_gram(1); // try 18bit converted to 16
+ if((rback18==px) || (BGR2RGB(rback18)==px))
+ {
+ is18bit=true;
+ if(BGR2RGB(rback18)==px) isBGR=true;
+ }
+ else if((rback==px) || (BGR2RGB(rback)==px))
+ {
+ if(BGR2RGB(rback)==px) isBGR=true;
+ }
+ // debug("\r\nIdentify gram read color format,\r\nsent %.4X read16 %.4X(bgr%.4X) read18 %.4X(bgr%.4X)", px, rback, BGR2RGB(rback), rback18, BGR2RGB(rback18));
+}
+// try to identify display controller
+void TFT932x::identify()
+{
+ tftID = reg_read(0x00);
+ hw_reset(); // in case wrong cmd messed up important settings
+}
+int TFT932x::sizeX()
+{
+ return screensize_X;
+}
+int TFT932x::sizeY()
+{
+ return screensize_Y;
+}
\ No newline at end of file
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/Display/TFT932x.h Mon Mar 23 14:08:04 2015 +0000
@@ -0,0 +1,266 @@
+#ifndef MBED_TFT932x_H
+#define MBED_TFT932x_H
+
+#include "GraphicsDisplay.h"
+#include "PAR8.h"
+#include "PAR16.h"
+#include "SPI8.h"
+#include "SPI16.h"
+#include "Protocols.h"
+
+
+/** A custom base class for ILI932x color TFT Display (except ILI9327 which is MIPI standard)
+*/
+class TFT932x : public GraphicsDisplay
+{
+
+public:
+
+ /** Create a monochrome LCD Parallel interface
+ * @param name The name used by the parent class to access the interface
+ */
+ TFT932x(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);
+
+ /** Create a monochrome LCD SPI interface
+ * @note ILI9325D has different SPI protocol, not supported here
+ * @param name The name used by the parent class to access the interface
+ */
+ TFT932x(proto_t displayproto, int Hz, PinName mosi, PinName miso, PinName sclk, PinName CS, PinName reset, const int lcdsize_x, const int lcdsize_y, const char* name);
+
+ /////// functions that come for free, but can be overwritten///////////////////////////////////////////////////
+/////// ----------------------------------------------------///////////////////////////////////////////////////
+
+ /** Draw a pixel in the specified color.
+ * @param x is the horizontal offset to this pixel.
+ * @param y is the vertical offset to this pixel.
+ * @param color defines the color for the pixel.
+ */
+ 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
+ * be captured into the window when it crosses a boundary.
+ * @param x is the left edge in pixels.
+ * @param y is the top edge in pixels.
+ * @param w is the window width in pixels.
+ * @param h is the window height in pixels.
+ */
+ virtual void window(int x, int y, int w, int h);
+
+ /** Read pixel color at location
+ * @param x is the horizontal offset to this pixel.
+ * @param y is the vertical offset to this pixel.
+ * @returns 16bit color.
+ */
+ virtual unsigned short pixelread(int x, int y);
+
+ /** Set the window from which gram is read from. Autoincrements row/column
+ * @param x is the left edge in pixels.
+ * @param y is the top edge in pixels.
+ * @param w is the window width in pixels.
+ * @param h is the window height in pixels.
+ */
+ virtual void window4read(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.
+ * @param color is the pixel color.
+ */
+ virtual void window_pushpixel(unsigned short color);
+
+ /** Push some pixels of the same color into the window and increment position.
+ * You must first call window() then push pixels.
+ * @param color is the pixel color.
+ * @param count: how many
+ */
+ virtual void window_pushpixel(unsigned short color, unsigned int count);
+
+ /** Push array of pixel colors into the window and increment position.
+ * You must first call window() then push pixels.
+ * @param color is the pixel color.
+ */
+ virtual void window_pushpixelbuf(unsigned short* color, unsigned int lenght);
+
+ /** Framebuffer is not used for TFT
+ */
+ virtual void copy_to_lcd(){ };
+
+ /** display inverted colors
+ *
+ * @param o = 0 normal, 1 invert
+ */
+ void invert(unsigned char o);
+
+ /** clear the entire screen
+ * The inherited one sets windomax then fill with background color
+ * We override it to speedup
+ */
+ virtual void cls();
+
+ /** Set the orientation of the screen
+ * x,y: 0,0 is always top left
+ *
+ * @param o direction to use the screen (0-3)
+ * 0 = default 0° portrait view
+ * 1 = +90° landscape view
+ * 2 = +180° portrait view
+ * 3 = -90° landscape view
+ *
+ */
+ virtual void set_orientation(int o);
+
+ /** Set ChipSelect high or low
+ * @param enable true/false
+ */
+ virtual void BusEnable(bool enable);
+
+ /** Enable fast window (default disabled)
+ * used to speedup functions that plots single pixels, like circle, oblique lines or just sparse pixels
+ * @param enable true/false
+ * @note most but not all controllers support this, even if datasheet tells they should
+ */
+ void FastWindow(bool enable);
+
+ /** Enable scroll
+ * 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
+ * @note ILI932x does not allow partial screen scrolling, only full screen is selectable
+ * @param startY unused, always 0 for ILI932x
+ * @param areasize unused, always screensize_Y for ILI932x
+ */
+ void setscrollarea (int startY=0, int areasize=0);
+
+ /** Scroll up(or left) the scrollarea
+ *
+ * @param lines number of lines to scroll, 1= scrollup 1, areasize-1= scrolldown 1
+ */
+ void scroll (int lines);
+
+ /** Disable scroll 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 Y size in pixels (native, orientation independent)
+ * @returns Y size in pixels
+ */
+ int sizeY();
+
+ unsigned int tftID;
+
+
+
+
+protected:
+
+
+////// functions needed by parent class ///////////////////////////////////////
+////// -------------------------------- ///////////////////////////////////////
+
+ /** ILI932x specific, does a dummy read cycle, number of bits is protocol dependent
+ * for PAR protocols: a signle RD bit toggle
+ * for SPI8: 8clocks
+ * for SPI16: 16 clocks
+ */
+ virtual void dummyread ();
+
+ /** ILI932x specific, select register for a successive write or read
+ *
+ * @param reg register to be selected
+ * @param forread false = a write next (default), true = a read next
+ * @note forread only used by SPI protocols
+ */
+ virtual void reg_select(unsigned char reg, bool forread =false);
+
+ /** ILI932x specific, write register with data
+ *
+ * @param reg register to write
+ * @param data 16bit data
+ */
+ virtual void reg_write(unsigned char reg, unsigned short data);
+
+ /** ILI932x specific, read register
+ *
+ * @param reg register to be read
+ * @returns 16bit register value
+ */
+ virtual unsigned short reg_read(unsigned char reg);
+
+ /** Send 16bit pixeldata to display controller
+ *
+ * @param data: halfword to send
+ *
+ */
+ virtual void wr_gram(unsigned short data);
+
+ /** Send same 16bit pixeldata to display controller multiple times
+ *
+ * @param data: halfword to send
+ * @param count: how many
+ *
+ */
+ virtual void wr_gram(unsigned short data, unsigned int count);
+
+ /** Send array of pixeldata shorts to display controller
+ *
+ * @param data: unsigned short pixeldata array
+ * @param lenght: lenght (in shorts)
+ *
+ */
+ virtual void wr_grambuf(unsigned short* data, unsigned int lenght);
+
+ /** Read 16bit pixeldata from display controller (with dummy cycle)
+ *
+ * @note autoconverts 18to16bit based on display identify info
+ * @returns 16bit color
+ */
+ virtual unsigned short rd_gram();
+
+ /** HW reset sequence (without display init commands)
+ */
+ void hw_reset();
+
+ /** Try to get read gram pixel format, could be 16bit or 18bit, RGB or BGR
+ * autoset internal flags so pixelread() will always return correct value.
+ */
+ virtual void auto_gram_read_format();
+
+ /** 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;
+
+
+
+private:
+
+ Protocols* proto;
+ const int screensize_X;
+ const int screensize_Y;
+ // pixel location
+ int cur_x;
+ int cur_y;
+ // window location
+ int win_x1;
+ int win_x2;
+ int win_y1;
+ int win_y2;
+ int orientation;
+ bool dummycycles;
+ bool usefastwindow;
+ bool fastwindowready;
+ bool fastwindowready4read;
+ bool is18bit;
+ bool isBGR;
+
+};
+
+#endif
\ No newline at end of file
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/Inits/ILI932x.cpp Mon Mar 23 14:08:04 2015 +0000
@@ -0,0 +1,113 @@
+ /* mbed UniGraphic library - Device specific class
+ * Copyright (c) 2015 Giuliano Dianda
+ * Released under the MIT License: http://mbed.org/license/mit
+ */
+
+#include "Protocols.h"
+#include "ILI932x.h"
+
+//////////////////////////////////////////////////////////////////////////////////
+// display settings ///////////////////////////////////////////////////////
+/////////////////////////////////////////////////////////////////////////
+
+
+ILI932x::ILI932x(proto_t displayproto, PortName port, PinName CS, PinName reset, PinName DC, PinName WR, PinName RD, const char *name , unsigned int LCDSIZE_X, unsigned int LCDSIZE_Y)
+ : TFT932x(displayproto, port, CS, reset, DC, WR, RD, LCDSIZE_X, LCDSIZE_Y, name)
+{
+ hw_reset();
+ BusEnable(true); //set CS low, will stay low untill manually set high with BusEnable(false);
+ identify(); // will collect tftID
+ if(tftID==0x9325) init9325();
+ auto_gram_read_format();// try to get read gram pixel format, could be 16bit or 18bit, RGB or BGR. Will set flags accordingly
+ set_orientation(0);
+ FastWindow(true); // most but not all controllers support this, even if datasheet tells they should.
+ cls();
+ locate(0,0);
+}
+ILI932x::ILI932x(proto_t displayproto, int Hz, PinName mosi, PinName miso, PinName sclk, PinName CS, PinName reset, const char *name, unsigned int LCDSIZE_X, unsigned int LCDSIZE_Y)
+ : TFT932x(displayproto, Hz, mosi, miso, sclk, CS, reset, LCDSIZE_X, LCDSIZE_Y, name)
+{
+ hw_reset(); //TFT class forwards to Protocol class
+ BusEnable(true); //set CS low, TFT932x class will toggle CS every transfer
+ identify(); // will collect tftID
+ if(tftID==0x9325) init9325();
+ auto_gram_read_format();// try to get read gram pixel format, could be 16bit or 18bit, RGB or BGR. Will set flags accordingly
+ set_orientation(0);
+ FastWindow(true); // most but not all controllers support this, even if datasheet tells they should.
+ cls();
+ locate(0,0);
+}
+// reset and init the lcd controller
+
+void ILI932x::init9325()
+{
+ /* Example for ILI9325 ----------------------------------------------------*/
+
+ reg_write(0x0001,0x0100);
+ reg_write(0x0002,0x0700);
+ reg_write(0x0003,0x1030);
+ reg_write(0x0004,0x0000);
+ reg_write(0x0008,0x0207);
+ reg_write(0x0009,0x0000);
+ reg_write(0x000A,0x0000);
+ reg_write(0x000C,0x0000);
+ reg_write(0x000D,0x0000);
+ reg_write(0x000F,0x0000);
+//power on sequence VGHVGL
+ reg_write(0x0010,0x0000);
+ reg_write(0x0011,0x0007);
+ reg_write(0x0012,0x0000);
+ reg_write(0x0013,0x0000);
+ reg_write(0x0007,0x0001);
+wait_ms(200);
+//vgh
+ reg_write(0x0010,0x1290);
+ reg_write(0x0011,0x0227);
+wait_ms(50);
+ //vregiout
+ reg_write(0x0012,0x001d); //0x001b
+ wait_ms(50);
+ //vom amplitude
+ reg_write(0x0013,0x1500);
+ wait_ms(50);
+ //vom H
+ reg_write(0x0029,0x0018);
+ reg_write(0x002B,0x000D);
+wait_ms(50);
+//gamma
+ reg_write(0x0030,0x0004);
+ reg_write(0x0031,0x0307);
+ reg_write(0x0032,0x0002);// 0006
+ reg_write(0x0035,0x0206);
+ reg_write(0x0036,0x0408);
+ reg_write(0x0037,0x0507);
+ reg_write(0x0038,0x0204);//0200
+ reg_write(0x0039,0x0707);
+ reg_write(0x003C,0x0405);// 0504
+ reg_write(0x003D,0x0F02);
+ //ram
+ reg_write(0x0050,0x0000);
+ reg_write(0x0051,0x00EF);
+ reg_write(0x0052,0x0000);
+ reg_write(0x0053,0x013F);
+ reg_write(0x0060,0xA700);
+ reg_write(0x0061,0x0001);
+ reg_write(0x006A,0x0000);
+ //
+ reg_write(0x0080,0x0000);
+ reg_write(0x0081,0x0000);
+ reg_write(0x0082,0x0000);
+ reg_write(0x0083,0x0000);
+ reg_write(0x0084,0x0000);
+ reg_write(0x0085,0x0000);
+ //
+ reg_write(0x0090,0x0010);
+ reg_write(0x0092,0x0600);
+ reg_write(0x0093,0x0003);
+ reg_write(0x0095,0x0110);
+ reg_write(0x0097,0x0000);
+ reg_write(0x0098,0x0000);
+
+ reg_write(0x0007,0x0133); // display on
+
+}
\ No newline at end of file
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/Inits/ILI932x.h Mon Mar 23 14:08:04 2015 +0000
@@ -0,0 +1,57 @@
+#ifndef MBED_ILI932x_H
+#define MBED_ILI932x_H
+
+
+
+#include "mbed.h"
+#include "TFT932x.h"
+
+/** Class for ILI932x tft display controller
+* to be copypasted and adapted for other controllers
+*/
+class ILI932x : public TFT932x
+{
+
+ public:
+
+ /** Create a PAR display interface
+ * @param displayproto PAR_8 or PAR_16
+ * @param port GPIO port name to use
+ * @param CS pin connected to CS of display
+ * @param reset pin connected to RESET of display
+ * @param DC pin connected to data/command of display
+ * @param WR pin connected to SDI of display
+ * @param RD pin connected to RS of display
+ * @param name The name used by the parent class to access the interface
+ * @param LCDSIZE_X x size in pixel - optional
+ * @param LCDSIZE_Y y size in pixel - optional
+ */
+ ILI932x(proto_t displayproto, PortName port, PinName CS, PinName reset, PinName DC, PinName WR, PinName RD, const char* name, unsigned int LCDSIZE_X = 240, unsigned int LCDSIZE_Y = 320);
+
+ /** Create an SPI display interface
+ * @param displayproto SPI_8 or SPI_16
+ * @param Hz SPI speed in Hz
+ * @param mosi SPI pin
+ * @param miso SPI pin
+ * @param sclk SPI pin
+ * @param CS pin connected to CS of display
+ * @param reset pin connected to RESET of display
+ * @param name The name used by the parent class to access the interface
+ * @param LCDSIZE_X x size in pixel - optional
+ * @param LCDSIZE_Y y size in pixel - optional
+ */
+ ILI932x(proto_t displayproto, int Hz, PinName mosi, PinName miso, PinName sclk, PinName CS, PinName reset, const char* name, unsigned int LCDSIZE_X = 240, unsigned int LCDSIZE_Y= 320);
+
+
+
+protected:
+
+
+ /** Init command sequence
+ */
+ void init9325();
+
+
+
+};
+#endif
\ No newline at end of file
--- a/Protocols/PAR16.cpp Mon Mar 02 10:52:26 2015 +0000
+++ b/Protocols/PAR16.cpp Mon Mar 23 14:08:04 2015 +0000
@@ -25,56 +25,27 @@
_WR=1;
_RD=1;
_CS=1;
-#ifdef STMPORTDEBUG
- findport(port); //on return, GPIO get disabled
-#endif
_port.mode(PullNone);
_port.output(); // will re-enable our GPIO port
hw_reset();
}
-#ifdef STMPORTDEBUG
-// create a port obj with STM HAL drivers, just to collect memorymapped regs
-void PAR16::findport(PortName port)
-{
- port_t tempport;
- port_init(&tempport, port, 0xFF, PIN_INPUT);
- outreg = tempport.reg_out;
- inreg = tempport.reg_in;
- // debug("out 0x%.8X in 0x%.8X\r\n", outreg, inreg);
-}
-#endif
void PAR16::wr_cmd8(unsigned char cmd)
-{
-#ifdef USE_CS
- _CS = 0;
-#endif
+{
_DC = 0; // 0=cmd
_port.write(cmd); // write 8bit
_WR=0;
_WR=1;
-#ifdef USE_CS
- _CS = 1;
-#endif
+ _DC = 1; // 1=data next
}
void PAR16::wr_data8(unsigned char data)
{
-#ifdef USE_CS
- _CS = 0;
-#endif
- _DC = 1; // 1=data
_port.write(data); // write 8bit
_WR=0;
_WR=1;
-#ifdef USE_CS
- _CS = 1;
-#endif
}
void PAR16::wr_cmd16(unsigned short cmd)
-{
-#ifdef USE_CS
- _CS = 0;
-#endif
+{
_DC = 0; // 0=cmd
_port.write(cmd>>8); // write 8bit
_WR=0;
@@ -82,62 +53,35 @@
_port.write(cmd&0xFF); // write 8bit
_WR=0;
_WR=1;
-#ifdef USE_CS
- _CS = 1;
-#endif
+ _DC = 1; // 1=data next
}
void PAR16::wr_data16(unsigned short data)
{
-#ifdef USE_CS
- _CS = 0;
-#endif
- _DC = 1; // 1=data
_port.write(data>>8); // write 8bit
_WR=0;
_WR=1;
_port.write(data&0xFF); // write 8bit
_WR=0;
_WR=1;
-#ifdef USE_CS
- _CS = 1;
-#endif
}
void PAR16::wr_gram(unsigned short data)
{
-#ifdef USE_CS
- _CS = 0;
-#endif
- _DC = 1; // 1=data
_port.write(data); // write 16bit
_WR=0;
_WR=1;
-#ifdef USE_CS
- _CS = 1;
-#endif
}
void PAR16::wr_gram(unsigned short data, unsigned int count)
{
-#ifdef USE_CS
- _CS = 0;
-#endif
- _DC = 1; // 1=data
while(count)
{
- _port.write(data); // write 16bit
+ _port.write(data); // rewrite even if same data, otherwise too much fast
_WR=0;
_WR=1;
count--;
}
-#ifdef USE_CS
- _CS = 1;
-#endif
}
void PAR16::wr_grambuf(unsigned short* data, unsigned int lenght)
{
-#ifdef USE_CS
- _CS = 0;
-#endif
- _DC = 1; // 1=data
while(lenght)
{
_port.write(*data); // write 16bit
@@ -146,17 +90,10 @@
data++;
lenght--;
}
-#ifdef USE_CS
- _CS = 1;
-#endif
}
unsigned short PAR16::rd_gram(bool convert)
{
-#ifdef USE_CS
- _CS = 0;
-#endif
unsigned int r=0;
- _DC = 1; // 1=data
_port.input();
_RD = 0;
@@ -164,7 +101,7 @@
_RD = 1;
_RD = 0;
-// _RD = 0; // add wait
+ // _RD = 0; // add wait
r |= _port.read();
_RD = 1;
if(convert)
@@ -178,20 +115,14 @@
// during reading, you read the raw 18bit gram
r = RGB24to16((r&0xFF0000)>>16, (r&0xFF00)>>8, r&0xFF);// 18bit pixel padded to 24bits, rrrrrr00_gggggg00_bbbbbb00, converted to 16bit
}
-#ifdef USE_CS
- _CS = 1;
-#endif
_port.output();
return (unsigned short)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
+ // _DC = 1; // 1=data
_port.input();
_RD = 0;
@@ -221,10 +152,9 @@
r |= (_port.read()&0xFF);
_RD = 1;
- _CS = 1; // force CS HIG to interupt the cmd in case was not supported
-#ifndef USE_CS //if CS is not used, force fixed LOW again
+ _CS = 1; // toggle CS to interupt the cmd in case was not supported
_CS = 0;
-#endif
+
_port.output();
return r;
}
@@ -233,6 +163,52 @@
{
return rd_reg_data32(reg);
}
+// ILI932x specific
+void PAR16::dummyread()
+{
+ _port.input();
+ _RD = 0;
+ _port.read(); // dummy read
+ _RD=1;
+ // _port.output();
+}
+// ILI932x specific
+void PAR16::reg_select(unsigned char reg, bool forread)
+{
+ _DC = 0;
+ _port.write(reg); // write 16bit
+ _WR=0;
+ _WR=1;
+ _DC = 1; // 1=data next
+}
+// ILI932x specific
+void PAR16::reg_write(unsigned char reg, unsigned short data)
+{
+ _DC = 0;
+ _port.write(reg); // write 16bit
+ _WR=0;
+ _WR=1;
+ _DC = 1;
+ _port.write(data); // write 16bit
+ _WR=0;
+ _WR=1;
+}
+// ILI932x specific
+unsigned short PAR16::reg_read(unsigned char reg)
+{
+ unsigned short r=0;
+ _DC = 0;
+ _port.write(reg); // write 16bit
+ _WR=0;
+ _WR=1;
+ _DC = 1;
+ _port.input();
+ _RD=0;
+ r |= _port.read(); // read 16bit
+ _RD=1;
+ _port.output();
+ return r;
+}
void PAR16::hw_reset()
{
wait_ms(15);
@@ -241,12 +217,9 @@
_WR = 1;
_RD = 1;
_reset = 0; // display reset
- wait_us(50);
+ wait_ms(2);
_reset = 1; // end reset
- wait_ms(15);
-#ifndef USE_CS
- _CS=0; // put CS low now and forever
-#endif
+ wait_ms(100);
}
void PAR16::BusEnable(bool enable)
{
--- a/Protocols/PAR16.h Mon Mar 02 10:52:26 2015 +0000
+++ b/Protocols/PAR16.h Mon Mar 23 14:08:04 2015 +0000
@@ -96,6 +96,35 @@
*/
virtual unsigned int rd_extcreg_data32(unsigned char reg, unsigned char SPIreadenablecmd);
+ /** ILI932x specific, does a dummy read cycle, number of bits is protocol dependent
+ * for PAR protocols: a signle RD bit toggle
+ * for SPI8: 8clocks
+ * for SPI16: 16 clocks
+ */
+ virtual void dummyread ();
+
+ /** ILI932x specific, select register for a successive write or read
+ *
+ * @param reg register to be selected
+ * @param forread false = a write next (default), true = a read next
+ * @note forread only used by SPI protocols
+ */
+ virtual void reg_select(unsigned char reg, bool forread =false);
+
+ /** ILI932x specific, write register with data
+ *
+ * @param reg register to write
+ * @param data 16bit data
+ */
+ virtual void reg_write(unsigned char reg, unsigned short data);
+
+ /** ILI932x specific, read register
+ *
+ * @param reg register to be read
+ * @returns 16bit register value
+ */
+ virtual unsigned short reg_read(unsigned char reg);
+
/** HW reset sequence (without display init commands)
*/
virtual void hw_reset();
--- a/Protocols/PAR8.cpp Mon Mar 02 10:52:26 2015 +0000
+++ b/Protocols/PAR8.cpp Mon Mar 23 14:08:04 2015 +0000
@@ -26,111 +26,63 @@
_WR=1;
_RD=1;
_CS=1;
-#ifdef STMPORTDEBUG
- findport(port); //on return, GPIO get disabled
-#endif
_port.mode(PullNone);
_port.output(); // will re-enable our GPIO port
hw_reset();
}
-#ifdef STMPORTDEBUG
-// create a port obj with STM HAL drivers, just to collect memorymapped regs
-void PAR8::findport(PortName port)
-{
- port_t tempport;
- port_init(&tempport, port, 0xFF, PIN_INPUT);
- outreg = tempport.reg_out;
- inreg = tempport.reg_in;
- // debug("out 0x%.8X in 0x%.8X\r\n", outreg, inreg);
-}
-#endif
void PAR8::wr_cmd8(unsigned char cmd)
-{
-#ifdef USE_CS
- _CS = 0;
-#endif
+{
_DC = 0; // 0=cmd
+ _port.write(cmd); // write 8bit
_WR=0;
- _port.write(cmd); // write 8bit
_WR=1;
-#ifdef USE_CS
- _CS = 1;
-#endif
+ _DC = 1; // 1=data next
}
void PAR8::wr_data8(unsigned char data)
{
-#ifdef USE_CS
- _CS = 0;
-#endif
- _DC = 1; // 1=data
+ _port.write(data); // write 8bit
_WR=0;
- _port.write(data); // write 8bit
_WR=1;
-#ifdef USE_CS
- _CS = 1;
-#endif
}
void PAR8::wr_cmd16(unsigned short cmd)
-{
-#ifdef USE_CS
- _CS = 0;
-#endif
+{
_DC = 0; // 0=cmd
- _WR=0;
_port.write(cmd>>8); // write 8bit
- _WR=1;
_WR=0;
- _port.write(cmd&0xFF); // write 8bit
_WR=1;
-#ifdef USE_CS
- _CS = 1;
-#endif
+ _port.write(cmd&0xFF); // write 8bit
+ _WR=0;
+ _WR=1;
+ _DC = 1; // 1=data next
}
void PAR8::wr_data16(unsigned short data)
{
-#ifdef USE_CS
- _CS = 0;
-#endif
- _DC = 1; // 1=data
+ _port.write(data>>8); // write 8bit
_WR=0;
- _port.write(data>>8); // write 8bit
_WR=1;
+ _port.write(data&0xFF); // write 8bit
_WR=0;
- _port.write(data&0xFF); // write 8bit
_WR=1;
-#ifdef USE_CS
- _CS = 1;
-#endif
}
void PAR8::wr_gram(unsigned short data)
{
-#ifdef USE_CS
- _CS = 0;
-#endif
- _DC = 1; // 1=data
+ _port.write(data>>8); // write 8bit
_WR=0;
- _port.write(data>>8); // write 8bit
_WR=1;
+ _port.write(data&0xFF); // write 8bit
_WR=0;
- _port.write(data&0xFF); // write 8bit
_WR=1;
-#ifdef USE_CS
- _CS = 1;
-#endif
}
void PAR8::wr_gram(unsigned short data, unsigned int count)
{
-#ifdef USE_CS
- _CS = 0;
-#endif
- _DC = 1; // 1=data
if((data>>8)==(data&0xFF))
{
count<<=1;
- _port.write(data); // write 8bit
+ // _port.write(data); // write 8bit
while(count)
{
+ _port.write(data); // rewrite even if same data, otherwise too much fast
_WR=0;
_WR=1;
count--;
@@ -140,62 +92,49 @@
{
while(count)
{
+ _port.write(data>>8); // write 8bit
_WR=0;
- _port.write(data>>8); // write 8bit
_WR=1;
+ _port.write(data&0xFF); // write 8bit
_WR=0;
- _port.write(data&0xFF); // write 8bit
_WR=1;
count--;
}
}
-#ifdef USE_CS
- _CS = 1;
-#endif
}
void PAR8::wr_grambuf(unsigned short* data, unsigned int lenght)
{
-#ifdef USE_CS
- _CS = 0;
-#endif
- _DC = 1; // 1=data
while(lenght)
{
+ _port.write((*data)>>8); // write 8bit
_WR=0;
- _port.write((*data)>>8); // write 8bit
_WR=1;
+ _port.write((*data)&0xFF); // write 8bit
_WR=0;
- _port.write((*data)&0xFF); // write 8bit
_WR=1;
data++;
lenght--;
}
-#ifdef USE_CS
- _CS = 1;
-#endif
}
unsigned short PAR8::rd_gram(bool convert)
{
-#ifdef USE_CS
- _CS = 0;
-#endif
unsigned int r=0;
- _DC = 1; // 1=data
_port.input();
_RD = 0;
+ _RD = 0; // add wait
_port.read(); //dummy read
_RD = 1;
_RD = 0;
-// _RD = 0; // add wait
- r |= (_port.read()&0xFF);
+ _RD = 0; // add wait
+ r |= _port.read();
+ _RD = 1;
r <<= 8;
- _RD = 1;
_RD = 0;
-// _RD = 0; // add wait
- r |= (_port.read()&0xFF);
+ _RD = 0; // add wait
+ r |= _port.read();
_RD = 1;
if(convert)
{
@@ -208,20 +147,13 @@
// during reading, you read the raw 18bit gram
r = RGB24to16((r&0xFF0000)>>16, (r&0xFF00)>>8, r&0xFF);// 18bit pixel padded to 24bits, rrrrrr00_gggggg00_bbbbbb00, converted to 16bit
}
-#ifdef USE_CS
- _CS = 1;
-#endif
_port.output();
return (unsigned short)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();
_RD = 0;
@@ -252,9 +184,7 @@
_RD = 1;
_CS = 1; // force CS HIG to interupt the cmd in case was not supported
-#ifndef USE_CS //if CS is not used, force fixed LOW again
_CS = 0;
-#endif
_port.output();
return r;
}
@@ -263,6 +193,70 @@
{
return rd_reg_data32(reg);
}
+// ILI932x specific
+void PAR8::dummyread()
+{
+ _port.input();
+ _RD=0;
+ _RD=0; // add wait
+ _port.read(); // dummy read
+ _RD=1;
+ // _port.output();
+}
+// ILI932x specific
+void PAR8::reg_select(unsigned char reg, bool forread)
+{
+ _DC = 0;
+ _port.write(0); // write MSB
+ _WR=0;
+ _WR=1;
+ _port.write(reg); // write LSB
+ _WR=0;
+ _WR=1;
+ _DC = 1; // 1=data next
+}
+// ILI932x specific
+void PAR8::reg_write(unsigned char reg, unsigned short data)
+{
+ _DC = 0;
+ _port.write(0); // write MSB
+ _WR=0;
+ _WR=1;
+ _port.write(reg); // write MSB
+ _WR=0;
+ _WR=1;
+ _DC = 1;
+ _port.write(data>>8);
+ _WR=0;
+ _WR=1;
+ _port.write(data&0xFF);
+ _WR=0;
+ _WR=1;
+}
+// ILI932x specific
+unsigned short PAR8::reg_read(unsigned char reg)
+{
+ unsigned short r=0;
+ _DC = 0;
+ _port.write(0);
+ _WR=0;
+ _WR=1;
+ _port.write(reg);
+ _WR=0;
+ _WR=1;
+ _DC = 1;
+ _port.input();
+ _RD=0;
+ r |= _port.read(); // read 8bit
+ _RD=1;
+ r <<= 8;
+ _RD=0;
+ r |= _port.read(); // read 8bit
+ _RD=1;
+ _port.output();
+
+ return r;
+}
void PAR8::hw_reset()
{
wait_ms(15);
@@ -271,12 +265,9 @@
_WR = 1;
_RD = 1;
_reset = 0; // display reset
- wait_us(50);
+ wait_ms(2);
_reset = 1; // end reset
- wait_ms(15);
-#ifndef USE_CS
- _CS=0; // put CS low now and forever
-#endif
+ wait_ms(100);
}
void PAR8::BusEnable(bool enable)
{
--- a/Protocols/PAR8.h Mon Mar 02 10:52:26 2015 +0000
+++ b/Protocols/PAR8.h Mon Mar 23 14:08:04 2015 +0000
@@ -96,6 +96,35 @@
*/
virtual unsigned int rd_extcreg_data32(unsigned char reg, unsigned char SPIreadenablecmd);
+ /** ILI932x specific, does a dummy read cycle, number of bits is protocol dependent
+ * for PAR protocols: a signle RD bit toggle
+ * for SPI8: 8clocks
+ * for SPI16: 16 clocks
+ */
+ virtual void dummyread ();
+
+ /** ILI932x specific, select register for a successive write or read
+ *
+ * @param reg register to be selected
+ * @param forread false = a write next (default), true = a read next
+ * @note forread only used by SPI protocols
+ */
+ virtual void reg_select(unsigned char reg, bool forread =false);
+
+ /** ILI932x specific, write register with data
+ *
+ * @param reg register to write
+ * @param data 16bit data
+ */
+ virtual void reg_write(unsigned char reg, unsigned short data);
+
+ /** ILI932x specific, read register
+ *
+ * @param reg register to be read
+ * @returns 16bit register value
+ */
+ virtual unsigned short reg_read(unsigned char reg);
+
/** HW reset sequence (without display init commands)
*/
virtual void hw_reset();
--- a/Protocols/Protocols.h Mon Mar 02 10:52:26 2015 +0000
+++ b/Protocols/Protocols.h Mon Mar 23 14:08:04 2015 +0000
@@ -104,6 +104,35 @@
*/
virtual unsigned int rd_extcreg_data32(unsigned char reg, unsigned char SPIreadenablecmd) = 0;
+ /** ILI932x specific, does a dummy read cycle, number of bits is protocol dependent
+ * for PAR protocols: a signle RD bit toggle
+ * for SPI8: 8clocks
+ * for SPI16: 16 clocks
+ */
+ virtual void dummyread () = 0;
+
+ /** ILI932x specific, select register for a successive write or read
+ *
+ * @param reg register to be selected
+ * @param forread false = a write next (default), true = a read next
+ * @note forread only used by SPI protocols
+ */
+ virtual void reg_select(unsigned char reg, bool forread =false) = 0;
+
+ /** ILI932x specific, write register with data
+ *
+ * @param reg register to write
+ * @param data 16bit data
+ */
+ virtual void reg_write(unsigned char reg, unsigned short data) = 0;
+
+ /** ILI932x specific, read register
+ *
+ * @param reg register to be read
+ * @returns 16bit register value
+ */
+ virtual unsigned short reg_read(unsigned char reg) = 0;
+
/** HW reset sequence (without display init commands)
*/
virtual void hw_reset() = 0;
--- a/Protocols/SPI16.cpp Mon Mar 02 10:52:26 2015 +0000
+++ b/Protocols/SPI16.cpp Mon Mar 23 14:08:04 2015 +0000
@@ -17,7 +17,6 @@
*/
#include "SPI16.h"
-//#define USE_CS
SPI16::SPI16(int Hz, PinName mosi, PinName miso, PinName sclk, PinName CS, PinName reset, PinName DC)
: _CS(CS), _spi(mosi, miso, sclk), _reset(reset), _DC(DC)
@@ -33,101 +32,52 @@
void SPI16::wr_cmd8(unsigned char cmd)
{
-#ifdef USE_CS
- _CS = 0;
-#endif
_spi.format(8,0); // it takes time, better use wr_cmd16 with NOP cmd
_DC.write(0); // 0=cmd
_spi.write(cmd); // write 8bit
_spi.format(16,0);
-#ifdef USE_CS
- _CS = 1;
-#endif
+ _DC.write(1); // 1=data next
}
void SPI16::wr_data8(unsigned char data)
{
-#ifdef USE_CS
- _CS = 0;
-#endif
_spi.format(8,0); // it takes time, check prev cmd parameter, in case use wr_data16 with repeated byte
- _DC.write(1); // 1=data
_spi.write(data); // write 8bit
_spi.format(16,0);
-#ifdef USE_CS
- _CS = 1;
-#endif
}
void SPI16::wr_cmd16(unsigned short cmd)
-{
-#ifdef USE_CS
- _CS = 0;
-#endif
+{
_DC.write(0); // 0=cmd
_spi.write(cmd); // write 16bit
-#ifdef USE_CS
- _CS = 1;
-#endif
+ _DC.write(1); // 1=data next
}
void SPI16::wr_data16(unsigned short data)
{
-#ifdef USE_CS
- _CS = 0;
-#endif
- _DC.write(1); // 1=data
_spi.write(data); // write 16bit
-#ifdef USE_CS
- _CS = 1;
-#endif
}
void SPI16::wr_gram(unsigned short data)
{
-#ifdef USE_CS
- _CS = 0;
-#endif
- _DC.write(1); // 1=data
_spi.write(data); // write 16bit
-#ifdef USE_CS
- _CS = 1;
-#endif
}
void SPI16::wr_gram(unsigned short data, unsigned int count)
{
-#ifdef USE_CS
- _CS = 0;
-#endif
- _DC.write(1); // 1=data
while(count)
{
_spi.write(data);
count--;
}
-#ifdef USE_CS
- _CS = 1;
-#endif
}
void SPI16::wr_grambuf(unsigned short* data, unsigned int lenght)
{
-#ifdef USE_CS
- _CS = 0;
-#endif
- _DC.write(1); // 1=data
while(lenght)
{
_spi.write(*data);
data++;
lenght--;
}
-#ifdef USE_CS
- _CS = 1;
-#endif
}
unsigned short SPI16::rd_gram(bool convert)
{
-#ifdef USE_CS
- _CS = 0;
-#endif
unsigned int r=0;
- _DC.write(1); // 1=data
r |= _spi.write(0); // 16bit, whole first byte is dummy, second is red
r <<= 16;
r |= _spi.write(0);
@@ -138,20 +88,15 @@
r = RGB24to16((r&0xFF0000)>>16, (r&0xFF00)>>8, r&0xFF);// 18bit pixel padded to 24bits, rrrrrr00_gggggg00_bbbbbb00, converted to 16bit
}
else r >>= 8;
-_CS = 1; // force CS HIG to interupt the "read state"
-#ifndef USE_CS //if CS is not used, force fixed LOW again
+ _CS = 1; // force CS HIG to interupt the "read state"
_CS = 0;
-#endif
+
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;
@@ -160,9 +105,7 @@
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)
@@ -173,29 +116,71 @@
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 = 1; // force CS HIG to interupt the cmd
_CS = 0;
-#endif
+
return r;
}
+// ILI932x specific
+void SPI16::dummyread()
+{
+ _spi.write(0); // dummy read
+}
+// ILI932x specific
+void SPI16::reg_select(unsigned char reg, bool forread)
+{
+ _CS = 1; //fixme: really needed?
+ _CS = 0; //fixme: really needed?
+ _spi.write(0x70); // write 0070
+ _spi.write(reg); // write 16bit
+ _CS = 1; //fixme: really needed?
+ _CS = 0; //fixme: really needed?
+ if(forread) _spi.write(0x73);
+ else _spi.write(0x72);
+}
+// ILI932x specific
+void SPI16::reg_write(unsigned char reg, unsigned short data)
+{
+ _CS = 1; //fixme: really needed?
+ _CS = 0; //fixme: really needed?
+ _spi.write(0x70); // write 0070
+ _spi.write(reg); // write 16bit
+ _CS = 1; //fixme: really needed?
+ _CS = 0; //fixme: really needed?
+ _spi.write(0x72); // write 0072
+ _spi.write(data); // write 16bit
+}
+// ILI932x specific
+unsigned short SPI16::reg_read(unsigned char reg)
+{
+ unsigned int r=0;
+ _CS = 1; //fixme: really needed?
+ _CS = 0; //fixme: really needed?
+ _spi.write(0x70); // write 0070
+ _spi.write(reg); // write 16bit
+ _CS = 1; //fixme: really needed?
+ _CS = 0; //fixme: really needed?
+ _spi.write(0x73); // write 0073
+ r |= _spi.write(0); // read 16bit, 8bit dummy + 8bit valid
+ r <<= 16;
+ r |= _spi.write(0); // read 16bit
+
+ _CS = 1; //fixme: to resync, maybe really needed
+ _CS = 0; //fixme: to resync, maybe really needed
+ return (r>>8);
+}
void SPI16::hw_reset()
{
wait_ms(15);
_DC = 1;
- // _CS = 1;
- _CS = 0;
+ _CS = 1;
_reset = 0; // display reset
- wait_us(50);
+ wait_ms(2);
_reset = 1; // end reset
- wait_ms(15);
-#ifndef USE_CS
- _CS=0; // put CS low now and forever
-#endif
+ wait_ms(100);
}
void SPI16::BusEnable(bool enable)
{
--- a/Protocols/SPI16.h Mon Mar 02 10:52:26 2015 +0000
+++ b/Protocols/SPI16.h Mon Mar 23 14:08:04 2015 +0000
@@ -20,7 +20,7 @@
* @param reset pin connected to RESET of display
* @param DC pin connected to data/command of display
*/
- SPI16(int Hz, PinName mosi, PinName miso, PinName sclk, PinName CS, PinName reset, PinName DC);
+ SPI16(int Hz, PinName mosi, PinName miso, PinName sclk, PinName CS, PinName reset, PinName DC=NC);
protected:
@@ -99,6 +99,35 @@
*/
virtual unsigned int rd_extcreg_data32(unsigned char reg, unsigned char SPIreadenablecmd);
+ /** ILI932x specific, does a dummy read cycle, number of bits is protocol dependent
+ * for PAR protocols: a signle RD bit toggle
+ * for SPI8: 8clocks
+ * for SPI16: 16 clocks
+ */
+ virtual void dummyread ();
+
+ /** ILI932x specific, select register for a successive write or read
+ *
+ * @param reg register to be selected
+ * @param forread false = a write next (default), true = a read next
+ * @note forread only used by SPI protocols
+ */
+ virtual void reg_select(unsigned char reg, bool forread =false);
+
+ /** ILI932x specific, write register with data
+ *
+ * @param reg register to write
+ * @param data 16bit data
+ */
+ virtual void reg_write(unsigned char reg, unsigned short data);
+
+ /** ILI932x specific, read register
+ *
+ * @param reg register to be read
+ * @returns 16bit register value
+ */
+ virtual unsigned short reg_read(unsigned char reg);
+
/** HW reset sequence (without display init commands)
*/
virtual void hw_reset();
--- a/Protocols/SPI8.cpp Mon Mar 02 10:52:26 2015 +0000
+++ b/Protocols/SPI8.cpp Mon Mar 23 14:08:04 2015 +0000
@@ -18,7 +18,6 @@
#include "SPI8.h"
-//#define USE_CS
SPI8::SPI8(int Hz, PinName mosi, PinName miso, PinName sclk, PinName CS, PinName reset, PinName DC)
: _CS(CS), _spi(mosi, miso, sclk), _reset(reset), _DC(DC)
@@ -27,75 +26,39 @@
_DC=1;
_CS=1;
_spi.format(8,0); // 8 bit spi mode 0
- // _spi.frequency(12000000); // 10 Mhz SPI clock, 12mhz for F411
_spi.frequency(Hz);
hw_reset();
}
void SPI8::wr_cmd8(unsigned char cmd)
-{
-#ifdef USE_CS
- _CS = 0;
-#endif
+{
_DC.write(0); // 0=cmd
_spi.write(cmd); // write 8bit
-#ifdef USE_CS
- _CS = 1;
-#endif
+ _DC.write(1); // 1=data next
}
void SPI8::wr_data8(unsigned char data)
{
-#ifdef USE_CS
- _CS = 0;
-#endif
- _DC.write(1); // 1=data
_spi.write(data); // write 8bit
-#ifdef USE_CS
- _CS = 1;
-#endif
}
void SPI8::wr_cmd16(unsigned short cmd)
-{
-#ifdef USE_CS
- _CS = 0;
-#endif
+{
_DC.write(0); // 0=cmd
_spi.write(cmd>>8); // write 8bit
_spi.write(cmd&0xFF); // write 8bit
-#ifdef USE_CS
- _CS = 1;
-#endif
+ _DC.write(1); // 1=data next
}
void SPI8::wr_data16(unsigned short data)
{
-#ifdef USE_CS
- _CS = 0;
-#endif
- _DC.write(1); // 1=data
_spi.write(data>>8); // write 8bit
_spi.write(data&0xFF); // write 8bit
-#ifdef USE_CS
- _CS = 1;
-#endif
}
void SPI8::wr_gram(unsigned short data)
{
-#ifdef USE_CS
- _CS = 0;
-#endif
- _DC.write(1); // 1=data
_spi.write(data>>8); // write 8bit
_spi.write(data&0xFF); // write 8bit
-#ifdef USE_CS
- _CS = 1;
-#endif
}
void SPI8::wr_gram(unsigned short data, unsigned int count)
{
-#ifdef USE_CS
- _CS = 0;
-#endif
- _DC.write(1); // 1=data
if((data>>8)==(data&0xFF))
{
count<<=1;
@@ -114,16 +77,9 @@
count--;
}
}
-#ifdef USE_CS
- _CS = 1;
-#endif
}
void SPI8::wr_grambuf(unsigned short* data, unsigned int lenght)
{
-#ifdef USE_CS
- _CS = 0;
-#endif
- _DC.write(1); // 1=data
while(lenght)
{
_spi.write((*data)>>8); // write 8bit
@@ -131,17 +87,10 @@
data++;
lenght--;
}
-#ifdef USE_CS
- _CS = 1;
-#endif
}
unsigned short SPI8::rd_gram(bool convert)
{
-#ifdef USE_CS
- _CS = 0;
-#endif
unsigned int r=0;
- _DC.write(1); // 1=data
_spi.write(0); // whole first byte is dummy
r |= _spi.write(0);
r <<= 8;
@@ -155,19 +104,13 @@
r = RGB24to16((r&0xFF0000)>>16, (r&0xFF00)>>8, r&0xFF);// 18bit pixel padded to 24bits, rrrrrr00_gggggg00_bbbbbb00, converted to 16bit
}
_CS = 1; // force CS HIG to interupt the "read state"
-#ifndef USE_CS //if CS is not used, force fixed LOW again
_CS = 0;
-#endif
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;
@@ -180,9 +123,7 @@
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)
@@ -193,30 +134,73 @@
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 = 1; // force CS HIG to interupt the cmd
_CS = 0;
-#endif
+ return r;
+}
+// ILI932x specific
+void SPI8::dummyread()
+{
+ _spi.write(0); // dummy read
+}
+// ILI932x specific
+void SPI8::reg_select(unsigned char reg, bool forread)
+{
+ _CS = 1; //fixme: really needed?
+ _CS = 0; //fixme: really needed?
+ _spi.write(0x70);
+ _spi.write(0); // write MSB
+ _spi.write(reg); // write LSB
+ _CS = 1; //fixme: really needed?
+ _CS = 0; //fixme: really needed?
+ if(forread) _spi.write(0x73);
+ else _spi.write(0x72);
+}
+// ILI932x specific
+void SPI8::reg_write(unsigned char reg, unsigned short data)
+{
+ _CS = 1; //fixme: really needed?
+ _CS = 0; //fixme: really needed?
+ _spi.write(0x70);
+ _spi.write(0); // write MSB
+ _spi.write(reg); // write LSB
+ _CS = 1; //fixme: really needed?
+ _CS = 0; //fixme: really needed?
+ _spi.write(0x72);
+ _spi.write(data>>8);
+ _spi.write(data&0xFF);
+}
+// ILI932x specific
+unsigned short SPI8::reg_read(unsigned char reg)
+{
+ unsigned short r=0;
+ _CS = 1; //fixme: really needed?
+ _CS = 0; //fixme: really needed?
+ _spi.write(0x70);
+ _spi.write(0); // write MSB
+ _spi.write(reg); // write LSB
+ _CS = 1; //fixme: really needed?
+ _CS = 0; //fixme: really needed?
+ _spi.write(0x73);
+ _spi.write(0); // dummy read
+ r = _spi.write(0); // read 8bit
+ r <<= 8;
+ r |= _spi.write(0); // read 8bit
return r;
}
void SPI8::hw_reset()
{
wait_ms(15);
_DC = 1;
- // _CS = 1;
- _CS = 0;
+ _CS = 1;
_reset = 0; // display reset
- wait_us(50);
+ wait_ms(2);
_reset = 1; // end reset
- wait_ms(15);
-#ifndef USE_CS
- _CS=0; // put CS low now and forever
-#endif
+ wait_ms(100);
}
void SPI8::BusEnable(bool enable)
{
--- a/Protocols/SPI8.h Mon Mar 02 10:52:26 2015 +0000
+++ b/Protocols/SPI8.h Mon Mar 23 14:08:04 2015 +0000
@@ -20,7 +20,7 @@
* @param reset pin connected to RESET of display
* @param DC pin connected to data/command of display
*/
- SPI8(int Hz, PinName mosi, PinName miso, PinName sclk, PinName CS, PinName reset, PinName DC);
+ SPI8(int Hz, PinName mosi, PinName miso, PinName sclk, PinName CS, PinName reset, PinName DC=NC);
protected:
@@ -96,6 +96,35 @@
*/
virtual unsigned int rd_extcreg_data32(unsigned char reg, unsigned char SPIreadenablecmd);
+ /** ILI932x specific, does a dummy read cycle, number of bits is protocol dependent
+ * for PAR protocols: a signle RD bit toggle
+ * for SPI8: 8clocks
+ * for SPI16: 16 clocks
+ */
+ virtual void dummyread ();
+
+ /** ILI932x specific, select register for a successive write or read
+ *
+ * @param reg register to be selected
+ * @param forread false = a write next (default), true = a read next
+ * @note forread only used by SPI protocols
+ */
+ virtual void reg_select(unsigned char reg, bool forread =false);
+
+ /** ILI932x specific, write register with data
+ *
+ * @param reg register to write
+ * @param data 16bit data
+ */
+ virtual void reg_write(unsigned char reg, unsigned short data);
+
+ /** ILI932x specific, read register
+ *
+ * @param reg register to be read
+ * @returns 16bit register value
+ */
+ virtual unsigned short reg_read(unsigned char reg);
+
/** HW reset sequence (without display init commands)
*/
virtual void hw_reset();
