diff --git a/Adafruit_ST7735.cpp b/Adafruit_ST7735.cpp index bfab90a..8b9fb2f 100644 --- a/Adafruit_ST7735.cpp +++ b/Adafruit_ST7735.cpp @@ -181,6 +181,16 @@ static const uint8_t PROGMEM 0x00, 0x00, // XSTART = 0 0x00, 0x9F }, // XEND = 159 + Rcmd2green160x80bgr[] = { // 7735S init, part 2 (mini 160x80 bgr) + 3, // 3 commands in list: + ST77XX_CASET, 4, // 1: Column addr set, 4 args, no delay: + 0x00, 0x00, // XSTART = 0 + 0x00, 0x4F, // XEND = 79 + ST77XX_RASET, 4, // 2: Row addr set, 4 args, no delay: + 0x00, 0x00, // XSTART = 0 + 0x00, 0x9F, // XEND = 159 + ST77XX_INVON, 0 }, // 3: Invert display, no args + Rcmd3[] = { // 7735R init, part 3 (red or green tab) 4, // 4 commands in list: ST7735_GMCTRP1, 16 , // 1: Gamma Adjustments (pos. polarity), 16 args + delay: @@ -234,6 +244,12 @@ void Adafruit_ST7735::initR(uint8_t options) { displayInit(Rcmd2green160x80); _colstart = 24; _rowstart = 0; + } else if (options == INITR_MINI160x80BGR) { + _height = ST7735_TFTHEIGHT_160; + _width = ST7735_TFTWIDTH_80; + displayInit(Rcmd2green160x80bgr); + _colstart = 26; + _rowstart = 1; } else { // colstart, rowstart left at default '0' values displayInit(Rcmd2red); @@ -242,10 +258,16 @@ void Adafruit_ST7735::initR(uint8_t options) { // Black tab, change MADCTL color filter if ((options == INITR_BLACKTAB) || (options == INITR_MINI160x80)) { - uint8_t data = 0xC0; - sendCommand(ST77XX_MADCTL, &data, 1); + madctl = 0xC0; + sendCommand(ST77XX_MADCTL, &madctl, 1); } + if (options == INITR_MINI160x80BGR) + { + invertOnCommand = ST77XX_INVOFF; + invertOffCommand = ST77XX_INVON; + } + if (options == INITR_HALLOWING) { // Hallowing is simply a 1.44" green tab upside-down: tabcolor = INITR_144GREENTAB; @@ -265,7 +287,6 @@ void Adafruit_ST7735::initR(uint8_t options) { */ /**************************************************************************/ void Adafruit_ST7735::setRotation(uint8_t m) { - uint8_t madctl = 0; rotation = m & 3; // can't be higher than 3 @@ -286,7 +307,7 @@ void Adafruit_ST7735::setRotation(uint8_t m) { if (tabcolor == INITR_144GREENTAB) { _height = ST7735_TFTHEIGHT_128; _width = ST7735_TFTWIDTH_128; - } else if (tabcolor == INITR_MINI160x80) { + } else if (tabcolor == INITR_MINI160x80 || tabcolor == INITR_MINI160x80BGR) { _height = ST7735_TFTHEIGHT_160; _width = ST7735_TFTWIDTH_80; } else { @@ -306,7 +327,7 @@ void Adafruit_ST7735::setRotation(uint8_t m) { if (tabcolor == INITR_144GREENTAB) { _width = ST7735_TFTHEIGHT_128; _height = ST7735_TFTWIDTH_128; - } else if (tabcolor == INITR_MINI160x80) { + } else if (tabcolor == INITR_MINI160x80 || tabcolor == INITR_MINI160x80BGR) { _width = ST7735_TFTHEIGHT_160; _height = ST7735_TFTWIDTH_80; } else { @@ -326,7 +347,7 @@ void Adafruit_ST7735::setRotation(uint8_t m) { if (tabcolor == INITR_144GREENTAB) { _height = ST7735_TFTHEIGHT_128; _width = ST7735_TFTWIDTH_128; - } else if (tabcolor == INITR_MINI160x80) { + } else if (tabcolor == INITR_MINI160x80 || tabcolor == INITR_MINI160x80BGR) { _height = ST7735_TFTHEIGHT_160; _width = ST7735_TFTWIDTH_80; } else { @@ -346,7 +367,7 @@ void Adafruit_ST7735::setRotation(uint8_t m) { if (tabcolor == INITR_144GREENTAB) { _width = ST7735_TFTHEIGHT_128; _height = ST7735_TFTWIDTH_128; - } else if (tabcolor == INITR_MINI160x80) { + } else if (tabcolor == INITR_MINI160x80 || tabcolor == INITR_MINI160x80BGR) { _width = ST7735_TFTHEIGHT_160; _height = ST7735_TFTWIDTH_80; } else { @@ -360,3 +381,40 @@ void Adafruit_ST7735::setRotation(uint8_t m) { sendCommand(ST77XX_MADCTL, &madctl, 1); } + + +/**************************************************************************/ +/*! + @brief Only for ST7735S. Sets Vertical Scrolling Area basic config, VSA must be within TFA and BFA. + @param top_fix_height TFA Top Fixed Area in pixels, >= 1 + @param bottom_fix_height BFA Bottom Fixed Area in pixels, >=1 + @param bottom_to_top Scroll direction +*/ +/**************************************************************************/ +void Adafruit_ST7735::setVerticalScrollConfig(uint8_t top_fix_height, uint8_t bottom_fix_height, bool bottom_to_top) { + uint8_t scroll_height; + scroll_height = _height - top_fix_height - bottom_fix_height; // TFA + VSA + BFA = 162 + + uint8_t args [6] = {0x00, top_fix_height, 0x00, scroll_height, 0x00, bottom_fix_height}; + sendCommand(ST7735_SCRLAR, args, 6); + + if(bottom_to_top) + madctl |= ST77XX_MADCTL_ML; // sets ML bit = 1 + else + madctl &= ~ST77XX_MADCTL_ML; // sets ML bit = 0 + + sendCommand(ST77XX_MADCTL, &madctl, 1); +} + + +/**************************************************************************/ +/*! + @brief Only for ST7735S. Sets Vertical Scroll Pointer, vsp must be within TFA and BFA. + @param vsp Vertical Scroll Pointer +*/ +/**************************************************************************/ +void Adafruit_ST7735::setVerticalScrollPointer(uint8_t vsp) { + uint8_t args[2] = {0x00, vsp}; + sendCommand(ST7735_VSCSAD, args, 2); +} + diff --git a/Adafruit_ST7735.h b/Adafruit_ST7735.h index da1320a..b509737 100755 --- a/Adafruit_ST7735.h +++ b/Adafruit_ST7735.h @@ -13,6 +13,7 @@ #define INITR_144GREENTAB 0x01 #define INITR_MINI160x80 0x04 #define INITR_HALLOWING 0x05 +#define INITR_MINI160x80BGR 0x06 // ST7735S // Some register settings #define ST7735_MADCTL_BGR 0x08 @@ -36,6 +37,10 @@ #define ST7735_GMCTRP1 0xE0 #define ST7735_GMCTRN1 0xE1 +// Vertical Scrolling +#define ST7735_SCRLAR 0x33 +#define ST7735_VSCSAD 0x37 + // Some ready-made 16-bit ('565') color settings: #define ST7735_BLACK ST77XX_BLACK #define ST7735_WHITE ST77XX_WHITE @@ -63,8 +68,12 @@ class Adafruit_ST7735 : public Adafruit_ST77xx { void setRotation(uint8_t m); + void setVerticalScrollConfig(uint8_t top_fix_height = 1, uint8_t bottom_fix_height = 1, bool bottom_to_top = true); + void setVerticalScrollPointer(uint8_t vsp); + private: uint8_t tabcolor; + uint8_t madctl; }; #endif // _ADAFRUIT_ST7735H_ diff --git a/examples/st7735s_vscrolltest/.cpb.test.skip b/examples/st7735s_vscrolltest/.cpb.test.skip new file mode 100644 index 0000000..e69de29 diff --git a/examples/st7735s_vscrolltest/st7735s_vscrolltest.ino b/examples/st7735s_vscrolltest/st7735s_vscrolltest.ino new file mode 100644 index 0000000..6e4bdf7 --- /dev/null +++ b/examples/st7735s_vscrolltest/st7735s_vscrolltest.ino @@ -0,0 +1,384 @@ +/************************************************************************** + This is a library for displays based on ST775S driver. + + These displays use SPI to communicate, 4 or 5 pins are required to + interface (RST is optional). + + Adafruit invests time and resources providing this open source code, + please support Adafruit and open-source hardware by purchasing + products from Adafruit! + + Written by NeKuNeKo, based on Limor Fried/Ladyada graphictest script for Adafruit Industries. + MIT license, all text above must be included in any redistribution + **************************************************************************/ + +#include // Core graphics library +#include // Hardware-specific library for ST7735 +#include + +#if defined(ARDUINO_FEATHER_ESP32) // Feather Huzzah32 + #define TFT_CS 14 + #define TFT_RST 15 + #define TFT_DC 32 + +#elif defined(ESP8266) + #define TFT_CS 4 + #define TFT_RST 16 + #define TFT_DC 5 + +#else + // For the breakout board, you can use any 2 or 3 pins. + // These pins will also work for the 1.8" TFT shield. + #define TFT_CS 10 + #define TFT_RST 9 // Or set to -1 and connect to Arduino RESET pin + #define TFT_DC 8 +#endif + +// #define TFT_LITE A0 // Uncomment if needed, and check the propper pin + +// OPTION 1 (recommended) is to use the HARDWARE SPI pins, which are unique +// to each board and not reassignable. For Arduino Uno: MOSI = pin 11 and +// SCLK = pin 13. This is the fastest mode of operation and is required if +// using the breakout board's microSD card. + +// For 1.44" and 1.8" TFT with ST7735 use: +Adafruit_ST7735 tft = Adafruit_ST7735(TFT_CS, TFT_DC, TFT_RST); + +// OPTION 2 lets you interface the display using ANY TWO or THREE PINS, +// tradeoff being that performance is not as fast as hardware SPI above. +//#define TFT_MOSI 11 // Data out +//#define TFT_SCLK 13 // Clock out + +// For ST7735-based displays, we will use this call +//Adafruit_ST7735 tft = Adafruit_ST7735(TFT_CS, TFT_DC, TFT_MOSI, TFT_SCLK, TFT_RST); + + +void setup(void) +{ + Serial.begin(9600); + //while(!Serial); + Serial.print(F("Hello! ST77xx TFT Test")); + + // Use this initializer if using a 1.8" TFT screen: + //tft.initR(INITR_BLACKTAB); // Init ST7735S chip, black tab + + // OR use this initializer if using a 1.8" TFT screen with offset such as WaveShare: + // tft.initR(INITR_GREENTAB); // Init ST7735S chip, green tab + + // OR use this initializer (uncomment) if using a 0.96" 160x80 TFT: + //tft.initR(INITR_MINI160x80); // Init ST7735S mini display + + // OR use this initializer (uncomment) if using a 0.96" 160x80 BGR TFT: + tft.initR(INITR_MINI160x80BGR); // Init ST7735S BGR mini display + + // SPI speed defaults to SPI_DEFAULT_FREQ defined in the library, you can override it here + // Note that speed allowable depends on chip and quality of wiring, if you go too fast, you + // may end up with a black screen some times, or all the time. + //tft.setSPISpeed(40000000); + + Serial.println(F("Initialized")); + +#ifdef TFT_LITE + pinMode(TFT_LITE, OUTPUT); + digitalWrite(TFT_LITE, LOW); // Set LOW / HIGH depends on your config. + //analogWrite(TFT_LITE, 1023); // Use this if using PWM pin. +#endif + + // - Color Scheme config - + tft.invertDisplay(false); + tft.fillScreen(ST77XX_BLACK); // Color Background +} + +void loop() +{ + testBounds(); + testRotation(); + testColor(); + //testColorVscroll(); // infinite Loop + vscrolltest(); // infinite Loop + //hscrolltest(); // infinite Loop +} + + +void testBounds () +{ + tft.setTextSize(1); + tft.setTextWrap(true); + + tft.setRotation(0); + tft.fillScreen(ST77XX_BLACK); + tft.drawPixel(0, 0, ST77XX_WHITE); + tft.setRotation(0); + tft.setTextColor(ST77XX_WHITE); + tft.setCursor(0+20, 0+20); + tft.print("(0,0)"); + delay(2000); + + tft.setRotation(0); + tft.fillScreen(ST77XX_BLACK); + tft.drawPixel(tft.width()-1, 0, ST77XX_BLUE); + tft.setRotation(1); + tft.setTextColor(ST77XX_BLUE); + tft.setCursor(0+20, 0+20); + tft.print("(width,0)"); + delay(2000); + + tft.setRotation(0); + tft.fillScreen(ST77XX_BLACK); + tft.drawPixel(tft.width()-1, tft.height()-1, ST77XX_YELLOW); + tft.setRotation(2); + tft.setTextColor(ST77XX_YELLOW); + tft.setCursor(0+20, 0+20); + tft.print("(width,height)"); + delay(2000); + + tft.setRotation(0); + tft.fillScreen(ST77XX_BLACK); + tft.drawPixel(0, tft.height()-1, ST77XX_RED); + tft.setRotation(3); + tft.setTextColor(ST77XX_RED); + tft.setCursor(0+20, 0+20); + tft.print("(0,height)"); + delay(2000); +} + + +void testRotation () +{ + tft.setTextSize(1); + tft.setTextWrap(false); + + tft.setRotation(0); // 0 - Vertical + tft.fillScreen(ST77XX_BLACK); + tft.drawFastHLine(0, 0, tft.width(), ST77XX_RED); + tft.drawFastVLine(0, 0, tft.height(), ST77XX_CYAN); + tft.setCursor(10, 10); + tft.setTextColor(ST77XX_WHITE); + tft.print("Rotation 0"); + tft.setCursor(10, 30); + tft.setTextColor(ST77XX_RED); + tft.print("width"); + tft.setCursor(10, 50); + tft.setTextColor(ST77XX_CYAN); + tft.print("height"); + delay(2000); + + tft.setRotation(1); // 1 - Horizontal + tft.fillScreen(ST77XX_BLACK); + tft.drawFastHLine(0, 0, tft.width(), ST77XX_RED); + tft.drawFastVLine(0, 0, tft.height(), ST77XX_CYAN); + tft.setCursor(10, 10); + tft.setTextColor(ST77XX_WHITE); + tft.print("Rotation 1"); + tft.setCursor(10, 30); + tft.setTextColor(ST77XX_RED); + tft.print("width"); + tft.setCursor(10, 50); + tft.setTextColor(ST77XX_CYAN); + tft.print("height"); + delay(2000); + + tft.setRotation(2); // 2 - Inverse Vertical + tft.fillScreen(ST77XX_BLACK); + tft.drawFastHLine(0, 0, tft.width(), ST77XX_RED); + tft.drawFastVLine(0, 0, tft.height(), ST77XX_CYAN); + tft.setCursor(10, 10); + tft.setTextColor(ST77XX_WHITE); + tft.print("Rotation 2"); + tft.setCursor(10, 30); + tft.setTextColor(ST77XX_RED); + tft.print("width"); + tft.setCursor(10, 50); + tft.setTextColor(ST77XX_CYAN); + tft.print("height"); + delay(2000); + + tft.setRotation(3); // 3- Inverse Horizontal + tft.fillScreen(ST77XX_BLACK); + tft.drawFastHLine(0, 0, tft.width(), ST77XX_RED); + tft.drawFastVLine(0, 0, tft.height(), ST77XX_CYAN); + tft.setCursor(10, 10); + tft.setTextColor(ST77XX_WHITE); + tft.print("Rotation 3"); + tft.setCursor(10, 30); + tft.setTextColor(ST77XX_RED); + tft.print("width"); + tft.setCursor(10, 50); + tft.setTextColor(ST77XX_CYAN); + tft.print("height"); + delay(2000); +} + + +void testColor() +{ + tft.setRotation(0); + tft.fillScreen(ST77XX_BLACK); + tft.setTextSize(1); + tft.setTextWrap(false); + + tft.setCursor(0, 15); + tft.setTextColor(ST77XX_BLACK); + tft.print("BLACK"); + + tft.setCursor(0, 30); + tft.setTextColor(ST77XX_WHITE); + tft.print("WHITE"); + + tft.setCursor(0, 45); + tft.setTextColor(ST77XX_YELLOW); + tft.print("YELLOW"); + + tft.setCursor(0, 60); + tft.setTextColor(ST77XX_GREEN); + tft.print("GREEN"); + + tft.setCursor(0, 75); + tft.setTextColor(ST77XX_BLUE); + tft.print("BLUE"); + + tft.setCursor(0, 90); + tft.setTextColor(ST77XX_MAGENTA); + tft.print("MAGENTA"); + + tft.setCursor(0, 105); + tft.setTextColor(ST77XX_ORANGE); + tft.print("ORANGE"); + + tft.setCursor(0, 120); + tft.setTextColor(ST77XX_CYAN); + tft.print("CYAN"); + + tft.setCursor(0, 135); + tft.setTextColor(ST7735_RED); + tft.print("RED"); + + delay(2000); +} + + +void testColorVscroll () +{ + uint8_t TFA = 1; // Top Fixed Area. Minimum 1 pixel + uint8_t BFA = 1; // Bottom Fixed Area. Minimum 1 pixel + bool bottom_to_top = true; // Scroll direction + + testColor(); + tft.setVerticalScrollConfig(TFA, BFA, bottom_to_top); + + uint8_t scroll = 0; + while(true){ + tft.setVerticalScrollPointer(scroll + TFA); + scroll++; + if(scroll > (tft.height() - TFA - BFA)) + scroll = 0; + delay(25); + } +} + + +void vscrolltest () +{ + char txt[] = "ST7735 TFT vertical scrolling"; + char nbr[5]; // Number can be up to five digits + uint8_t scroll; // Vertical Scroll Area pointer + uint16_t number; + + tft.setRotation(0); // only valid 0 + tft.fillScreen(ST77XX_BLACK); + tft.setTextWrap(true); + + tft.setCursor(0, 0); + tft.setTextColor(ST77XX_WHITE); + tft.print(txt); + + strcpy (txt, "Line:"); + tft.setTextWrap(false); + + uint8_t TFA = 30; // Top Fixed Area. Minimum 1 pixel + uint8_t BFA = 1; // Bottom Fixed Area. Minimum 1 pixel + bool bottom_to_top = true; // Scroll direction + tft.setVerticalScrollConfig(TFA, BFA, bottom_to_top); + + scroll = 0; + number = 0; + while(true) + { + for(int i=0; i < 10; i++) + { + tft.setVerticalScrollPointer(scroll + TFA); + tft.drawFastHLine(0, scroll + TFA, tft.width(), ST7735_BLACK); // Delete lines which may appear in bottom of TFT + scroll++; + delay(25); // scroll speed + if(scroll >= (tft.height() - TFA)) + scroll = 0; + } + + sprintf(nbr,"%Lu",number); + + if(scroll == 0) + { + tft.setCursor(0, 150); + tft.setTextColor(ST7735_YELLOW); + tft.print(txt); + + tft.setCursor(40, 150); + tft.setTextColor(ST7735_GREEN); + tft.print(nbr); + } + else + { + tft.setCursor(0, 20 + scroll); + tft.setTextColor(ST7735_YELLOW); + tft.print(txt); + + tft.setCursor(40, 20 + scroll); + tft.setTextColor(ST7735_GREEN); + tft.print(nbr); + } + number++; + } +} + + +void hscrolltest() +{ + char message [] = "In a village of La Mancha, the name of which I have no desire\ + to call to mind, there lived not long since one of those gentlemen that keep a lance\ + in the lance-rack, an old buckler, a lean hack, and a greyhound for coursing."; + int x, minX; + + tft.setRotation(1); + tft.setTextWrap(false); + tft.setTextColor(ST77XX_WHITE); + tft.fillScreen(ST77XX_BLACK); + + tft.setTextSize(1); + tft.setCursor(0, 7); + tft.print("TEST SCROLLING TEXT"); + + tft.setTextSize(3); + tft.setCursor(0, 40); + tft.print("Hello world!"); + + tft.setTextSize(2); + x = tft.width(); + minX = -12 * strlen(message); // 12 = 6 pixels /character * textSize + while(true) + { + // Option 1: fastHLines + //for (int i = 0; i<= 20; ++i) + // tft.writeFastHLine(0, 20+i, tft.width(), ST77XX_BLACK); + + // Option 2: fastVLines + for (int i = 0; i< tft.width(); ++i) + tft.writeFastVLine(0+i, 20, 16, ST77XX_BLACK); + + tft.setCursor(x, 20); + tft.print(message); + + x = x-2; // scroll speed + if (x < minX) + x = tft.width(); + } +}