Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
92 changes: 47 additions & 45 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -22,25 +22,25 @@ This library was originally created to be able to test out SPI on the newer Teen
also adapted to allow this on the Teensy LC as well.


Constructor and begin
Constructor and begin()
----
This library was developed to allow you to use any of the SPI busses on a Teensy 3.x or 4.x processor.
It detects this by looking at which pins were specified on the constructor.

```
ILI9341_t3n(uint8_t _CS, uint8_t _DC, uint8_t _RST = 255, uint8_t _MOSI = 11,
uint8_t _SCLK = 13, uint8_t _MISO = 12);
```c++
ILI9341_t3n(uint8_t _CS, uint8_t _DC, uint8_t _RST = 255, uint8_t _MOSI = 11,
uint8_t _SCLK = 13, uint8_t _MISO = 12);
```

When the begin method is called. The parameters passed in for MISO/MOSI/SCK are checked to see if they are valid
for the SPI object. If so SPI is used. If not and the board type has SPI1, it will check to
see if those pins are valid for SPI1 and if so use SPI1, if not if there is an SPI2, it will check...
```
void begin(uint32_t spi_clock = ILI9341_SPICLOCK,
uint32_t spi_clock_read = ILI9341_SPICLOCK_READ);
When the begin method is called the parameters passed in for MISO/MOSI/SCK are checked to see if they are valid
for the SPI object. If so SPI is used; if not, and the board type has SPI1, it will check to
see if those pins are valid for SPI1 and if so use SPI1; if not and there is an SPI2, it will check...
```c++
void begin(uint32_t spi_clock = ILI9341_SPICLOCK,
uint32_t spi_clock_read = ILI9341_SPICLOCK_READ);
```

In addition, On Teensy 3.x boards, this code allows the ILI9341 code to work with only
In addition, on Teensy 3.x boards, this code allows the ILI9341 code to work with only
one hardware CS pin available, which in this case must be used for the DC pin.
This is very useful to support SPI1 on the T3.5 and T3.6 boards which only
have one CS pin unless you use some form of adapter to use the SPI pins that are on the SDCARD.
Expand All @@ -51,62 +51,64 @@ get a modest speed increase if hardware CS pin is used for the DC signal.

Frame Buffer
------------
The teensy 3.6 and now 3.5 and now the T4.x have a lot more memory than previous Teensy processors, so on these boards,
The Teensy 3.5, 3.6 and now the T4.x have a lot more memory than previous Teensy processors, so on these boards,
I borrowed some ideas from the ILI9341_t3DMA library and added code to be able to use a logical Frame Buffer.
To enable this I added a couple of API's
To enable this I added some APIs:
```c++
uint8_t useFrameBuffer(boolean b) - if b non-zero it will allocate memory and start using
void freeFrameBuffer(void) - Will free up the memory that was used.
void updateScreen(void); - Will update the screen with all of your updates...
void setFrameBuffer(uint16_t *frame_buffer); - Now have the ability allocate the frame buffer and pass it in, to avoid use of malloc
uint8_t useFrameBuffer(boolean b) // if b true it will allocate memory and start using it
void freeFrameBuffer(void) // Frees up the memory that was used.
void updateScreen(void); // Will update the screen with all of your changes...
void setFrameBuffer(uint16_t *frame_buffer); // Now have the ability to allocate the frame buffer and pass it in, to avoid use of malloc()
```
Asynchronous Update support (Frame buffer)
------------------------

The code now has support to use DMA for Asynchronous updates of the screen. You can choose to do the updates once or in continuous mode. Note: I mainly use the
oneshot as I prefer more control on when the screen updates which helps to minimize things like flashing and tearing.
Some of the New methods for this include:
one-shot as I prefer more control on when the screen updates which helps to minimize things like flashing and tearing.
Some of the new methods for this include:

```c++
bool updateScreenAsync(bool update_cont = false); - Starts an update either one shot or continuous
void waitUpdateAsyncComplete(void); - Wait for any active update to complete
void endUpdateAsync(); - Turn of the continuous mode.
boolean asyncUpdateActive(void) - Lets you know if an async operation is still active
bool updateScreenAsync(bool update_cont = false); // Starts an update, either one-shot or continuous
void waitUpdateAsyncComplete(void); // Wait for any active update to complete
void endUpdateAsync(); // Turn off the continuous mode.
bool asyncUpdateActive(void) // Lets you know if an async operation is still active
```

Additional APIs
---------------
In addition, this library now has some of the API's and functionality that has been requested in a pull request. In particular it now supports, the ability to set a clipping rectangle as well as setting an origin that is used with the drawing primitives. These new API's include:
In addition, this library now has some of the APIs and functionality that has been requested in a pull request. In particular it now supports, the ability to set a clipping rectangle as well as setting an origin that is used with the drawing primitives. These new API's include:
```c++
void setOrigin(int16_t x = 0, int16_t y = 0);
void getOrigin(int16_t* x, int16_t* y);
void setClipRect(int16_t x1, int16_t y1, int16_t w, int16_t h);
void setClipRect();
void setOrigin(int16_t x = 0, int16_t y = 0);
void getOrigin(int16_t* x, int16_t* y);
void setClipRect(int16_t x1, int16_t y1, int16_t w, int16_t h);
void setClipRect();
```

This library borrows some concepts and functionality from other libraries as well, such as: from the TFT_ILI9341_ESP, https://github.com/Bodmer/TFT_ILI9341_ESP, for additional functions:
```c++
int16_t drawNumber(long long_num,int poX, int poY);
int16_t drawFloat(float floatNumber,int decimal,int poX, int poY);
int16_t drawString(const String& string, int poX, int poY);
int16_t drawString(char string[], int16_t len, int poX, int poY);
void setTextDatum(uint8_t datum);
int16_t drawNumber(long long_num,int poX, int poY);
int16_t drawFloat(float floatNumber,int decimal,int poX, int poY);
int16_t drawString(const String& string, int poX, int poY);
int16_t drawString(char string[], int16_t len, int poX, int poY);
void setTextDatum(uint8_t datum);
```

In addition, scrolling text has been added using appropriate function from, https://github.com/vitormhenrique/ILI9341_t3:
In addition, scrolling text has been added using appropriate function from, https://github.com/vitormhenrique/ILI9341_t3.
These functions _require_ the ability to read screen data, so the MISO pin must be connected and functional.
```c++
void enableScroll(void);
void resetScrollBackgroundColor(uint16_t color);
void setScrollTextArea(int16_t x, int16_t y, int16_t w, int16_t h);
void setScrollBackgroundColor(uint16_t color);
void scrollTextArea(uint8_t scrollSize);
void resetScrollBackgroundColor(uint16_t color);
void enableScroll(void);
void resetScrollBackgroundColor(uint16_t color);
void setScrollTextArea(int16_t x, int16_t y, int16_t w, int16_t h);
void setScrollBackgroundColor(uint16_t color); // area is filled
void scrollTextArea(int16_t scrollSize);
void resetScrollBackgroundColor(uint16_t color); // just sets colour
```
A negative parameter for `scrollTextArea` scrolls the area down the screen (i.e. in the opposite direction to normal text scrolling).

Some other member functions have been added by request, that have not been fully tested, nor will they work with the
frame buffer.
```c++
void setScrollMargins(uint16_t top, uint16_t bottom); // Note this is now also member of Adafruit library
void setScrollMargins(uint16_t top, uint16_t bottom); // Note this is now also member of Adafruit library
```

Font Support
Expand All @@ -120,7 +122,7 @@ The text output support also has been exteneded in a way similar to the RA8875 l

The member function setCursor has been extended in a couple of ways:
```c++
void setCursor(int16_t x, int16_t y, bool autoCenter=false);
void setCursor(int16_t x, int16_t y, bool autoCenter=false);
```
if the autoCenter is true, the next text output will be centered at the given x, y location. Note: this is only true for the NEXT output.

Expand Down Expand Up @@ -153,16 +155,16 @@ Discussion regarding this optimized version:
http://forum.pjrc.com/threads/26305-Highly-optimized-ILI9341-%28320x240-TFT-color-display%29-library

This version of the library supports the Adafruit displays that use the ILI9341 displays, but in
addition are setup to support the displays that are sold by PJRC, which include:
addition are set up to support the displays that are sold by PJRC, which include:
http://pjrc.com/store/display_ili9341.html
http://pjrc.com/store/display_ili9341_touch.html

Note: this library like the ILI9341_t3 library which it is derived from no longer require any of the Adafruit libraries, such as their Adafruit_ILI9341 and Adafruit_GFX libraries APIS are based on, but...
Note: this library, like the ILI9341_t3 library which it is derived from, no longer requires any of the Adafruit libraries, such as their Adafruit_ILI9341 and Adafruit_GFX libraries APIS are based on, but...

Adafruit library info
=======================

...as this code is based of of their work, their original information is included below:
...as this code is based on their work, their original information is included below:

------------------------------------------

Expand Down
139 changes: 114 additions & 25 deletions examples/scrollTest/scrollTest.ino
Original file line number Diff line number Diff line change
Expand Up @@ -29,57 +29,146 @@ ILI9341_t3n tft = ILI9341_t3n(ILI9341_CS, ILI9341_DC, ILI9341_RST);
// If using the breakout, change pins as desired
//Adafruit_ILI9341 tft = Adafruit_ILI9341(TFT_CS, TFT_DC, TFT_MOSI, TFT_CLK, TFT_RST, TFT_MISO);

void setup() {

Serial.begin(9600);
/*********************************************************************************
* MISO needs to be connected and working for this example
* to work properly, so provide a way to check that and tell the user
* the result. Implemented as a template class, so it should be easy
* to transfer to any display which provides writeRect() and readRect()
*/
template <class TFTdrv>
class checkMISO
{
TFTdrv& tft;
bool miso_ok{false};
public:
checkMISO(TFTdrv& _tft)
: tft(_tft)
{}

bool isOK(uint16_t x=0, uint16_t y=0)
{
uint16_t ref[]{ILI9341_RED, ILI9341_GREEN, ILI9341_BLUE, ILI9341_WHITE};
uint16_t chk[4]{0,0,0,0};
tft.writeRect(x,y,2,2,ref);
tft.readRect(x,y,2,2,chk);

return 0 == memcmp(ref,chk,sizeof ref);
}
};


// One way of reporting to the user - use the Serial port
void printMISOcheck(void)
{
checkMISO<ILI9341_t3n> checker(tft);
Serial.printf("Screen %s functional MISO\n",checker.isOK()?"has":"does NOT have");
}
//********************************************************************************


void setup() {

Serial.begin(9600);

tft.begin();
tft.setRotation(3);
tft.enableScroll();

tft.fillScreen(ILI9341_NAVY);
tft.setTextSize(2);
tft.setTextColor(ILI9341_WHITE);
tft.setCursor(20,120-8);
tft.print("Waiting for");
tft.setCursor(20,120+8);
tft.print("serial connection...");
while (!Serial) // wait for Serial connection
;
printMISOcheck();
}


void scrollCS1(const ILI9341_t3_font_t& font, bool reverse=false)
{
tft.fillScreen(ILI9341_BLACK);
while (!Serial) ;
tft.setTextColor(ILI9341_WHITE); tft.setTextSize(1);
tft.enableScroll();
tft.setScrollTextArea(0,0,120,240);
tft.setScrollBackgroundColor(ILI9341_GREEN);

tft.setCursor(180, 100);

tft.setFont(ComicSansMS_12);
tft.setFont(font);
tft.print("Fixed text");

tft.setCursor(0, 0);

tft.setTextColor(ILI9341_BLACK);

for(int i=0;i<20;i++){
tft.print(" this is line ");
tft.println(i);
delay(100);
if (reverse)
{
unsigned char line_space = font.line_space;
int ypos = 240-line_space+4;
for(int i=20;i>=0;i--){
tft.setCursor(0, ypos);
tft.print(" this is line ");
tft.print(i);
delay(100);
if (ypos >= line_space)
ypos -= line_space;
else
tft.scrollTextArea(-line_space);
}
}
else
{
tft.setCursor(0, 2);
for(int i=0;i<=20;i++){
tft.print(" this is line ");
tft.println(i);
delay(100);
}
}
}


void scrollCS2(const ILI9341_t3_font_t& font, bool reverse=false)
{
tft.fillScreen(ILI9341_BLACK);
tft.setScrollTextArea(40,50,120,120);
tft.setScrollBackgroundColor(ILI9341_GREEN);
tft.setFont(ComicSansMS_10);
tft.setFont(font);

tft.setTextSize(1);
tft.setCursor(40, 50);

for(int i=0;i<20;i++){
tft.print(" this is line ");
tft.println(i);
delay(500);

if (reverse)
{
unsigned char line_space = font.line_space;
int ypos = 50+120-line_space-2;
for(int i=20;i>=0;i--){
tft.setCursor(40, ypos);
tft.print(" this is line ");
tft.print(i);
delay(500);
if (ypos-50 >= line_space)
ypos -= line_space;
else
tft.scrollTextArea(-line_space);
}
}
else
{
tft.setCursor(40, 52);
for(int i=0;i<=20;i++){
tft.print(" this is line ");
tft.println(i);
delay(500);
}
}
}


}



void loop(void) {


void loop(void)
{
scrollCS1(ComicSansMS_12);
scrollCS1(ComicSansMS_12, true);
scrollCS2(ComicSansMS_10);
scrollCS2(ComicSansMS_10, true);
}
2 changes: 1 addition & 1 deletion library.properties
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
name=ILI9341_t3n
version=1.2.0
version=1.2.1
author=Limor Fried, Adafruit, Paul Stoffregen, Kurt Eckhardt
maintainer=Kurt Eckhardt
sentence=Optimized ILI9341 (320x240 Color TFT) Display
Expand Down
34 changes: 28 additions & 6 deletions src/ILI9341_t3n.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -5186,14 +5186,36 @@ int16_t ILI9341_t3n::drawString(const char string[], int16_t len, int poX, int p
return sumX;
}

void ILI9341_t3n::scrollTextArea(uint8_t scrollSize) {
void ILI9341_t3n::scrollTextArea(int16_t scrollSize) {
uint16_t awColors[scroll_width];
for (int y = scroll_y + scrollSize; y < (scroll_y + scroll_height); y++) {
readRect(scroll_x, y, scroll_width, 1, awColors);
writeRect(scroll_x, y - scrollSize, scroll_width, 1, awColors);
if (scrollSize >= 0)
{
int y = scroll_y + scrollSize;
int16_t ssz = scroll_height-scrollSize;
while (ssz > 0) {
readRect(scroll_x, y, scroll_width, 1, awColors);
writeRect(scroll_x, y - scrollSize, scroll_width, 1, awColors);
y++;
ssz--;
}
fillRect(scroll_x, (scroll_y + scroll_height) - scrollSize,
scroll_width, scrollSize,
scrollbgcolor);
}
else
{
int y = scroll_y+scroll_height+scrollSize;
int16_t ssz = scroll_height+scrollSize;
while (ssz > 0) {
readRect(scroll_x, y, scroll_width, 1, awColors);
writeRect(scroll_x, y - scrollSize, scroll_width, 1, awColors);
y--;
ssz--;
}
fillRect(scroll_x, scroll_y,
scroll_width, -scrollSize,
scrollbgcolor);
}
fillRect(scroll_x, (scroll_y + scroll_height) - scrollSize, scroll_width,
scrollSize, scrollbgcolor);
}

void ILI9341_t3n::setScrollTextArea(int16_t x, int16_t y, int16_t w,
Expand Down
2 changes: 1 addition & 1 deletion src/ILI9341_t3n.h
Original file line number Diff line number Diff line change
Expand Up @@ -501,7 +501,7 @@ class ILI9341_t3n : public Print {
void setScrollBackgroundColor(uint16_t color);
void enableScroll(void);
void disableScroll(void);
void scrollTextArea(uint8_t scrollSize);
void scrollTextArea(int16_t scrollSize);
void resetScrollBackgroundColor(uint16_t color);

// added support to use optional Frame buffer
Expand Down
Loading