/*! * @file Adafruit_HX8357.cpp * * @mainpage Adafruit HX8357 TFT Displays * * @section intro_sec Introduction * * This is the documentation for Adafruit's HX8357 driver for the Arduino * platform. * * This library works with the Adafruit 3.5" TFT 320x480 + Touchscreen Breakout * http://www.adafruit.com/products/2050 * * Adafruit TFT FeatherWing - 3.5" 480x320 Touchscreen for Feathers * https://www.adafruit.com/product/3651 * * These displays use SPI to communicate. This requires 4 pins (MOSI, * SCK, select, data/command) and optionally a reset pin. Hardware SPI * or 'bitbang' software SPI are both supported. * * Adafruit invests time and resources providing this open source code, * please support Adafruit and open-source hardware by purchasing * products from Adafruit! * * @section dependencies Dependencies * * This library depends on * Adafruit_GFX being present on your system. Please make sure you have * installed the latest version before using this library. * * @section author Author * * Written by Limor Fried/Ladyada for Adafruit Industries, with * contributions from the open source community. * * @section license License * * BSD license, all text here must be included in any redistribution. */ #include "Adafruit_HX8357.h" #include #include #define MADCTL_MY 0x80 ///< Bottom to top #define MADCTL_MX 0x40 ///< Right to left #define MADCTL_MV 0x20 ///< Reverse Mode #define MADCTL_ML 0x10 ///< LCD refresh Bottom to top #define MADCTL_RGB 0x00 ///< Red-Green-Blue pixel order #define MADCTL_BGR 0x08 ///< Blue-Green-Red pixel order #define MADCTL_MH 0x04 ///< LCD refresh right to left // THIS REALLY SHOULD GO IN SPITFT (PART OF ADAFRUIT_GFX), // AND CAN BE FURTHER EXPANDED (e.g. add 12 MHz for M0, 24 for M4), // BUT TEMPORARILY FOR NOW IT'S HERE: #if defined(ARDUINO_ARCH_ARC32) #define SPI_DEFAULT_FREQ 16000000 #elif defined(__AVR__) || defined(TEENSYDUINO) #define SPI_DEFAULT_FREQ 8000000 #elif defined(ESP8266) || defined(ARDUINO_MAXIM) #define SPI_DEFAULT_FREQ 16000000 #elif defined(ESP32) #define SPI_DEFAULT_FREQ 24000000 #elif defined(RASPI) #define SPI_DEFAULT_FREQ 24000000 #else #define SPI_DEFAULT_FREQ 24000000 ///< The default SPI frequency #endif // CONSTRUCTORS, DESTRUCTOR ------------------------------------------------ /*! @brief Constructor for Adafruit_HX8357 displays, using software (bitbang) SPI. @param cs Chip select pin (using Arduino pin numbering). @param dc Data/Command pin (using Arduino pin numbering). @param mosi SPI MOSI pin (using Arduino pin numbering). @param sclk SPI Clock pin (using Arduino pin numbering). @param rst Reset pin (Arduino pin numbering, optional, pass -1 if unused). @param miso SPI MISO pin (Arduino pin #, optional, pass -1 if unused). @param type Display type, HX8357D (default if unspecified) or HX8357B. @return Adafruit_HX8357 object. @note Call the object's begin() function before use. */ Adafruit_HX8357::Adafruit_HX8357(int8_t cs, int8_t dc, int8_t mosi, int8_t sclk, int8_t rst, int8_t miso, uint8_t type) : Adafruit_SPITFT(HX8357_TFTWIDTH, HX8357_TFTHEIGHT, cs, dc, mosi, sclk, rst, miso), displayType(type) {} /*! @brief Constructor for Adafruit_HX8357 displays, using the default hardware SPI interface. @param cs Chip select pin (using Arduino pin numbering). @param dc Data/Command pin (using Arduino pin numbering). @param rst Reset pin (Arduino pin numbering, optional, pass -1 if unused). @param type Display type, HX8357D (default if unspecified) or HX8357B. @return Adafruit_HX8357 object. @note Call the object's begin() function before use. */ Adafruit_HX8357::Adafruit_HX8357(int8_t cs, int8_t dc, int8_t rst, uint8_t type) : Adafruit_SPITFT(HX8357_TFTWIDTH, HX8357_TFTHEIGHT, cs, dc, rst), displayType(type) {} #if !defined(ESP8266) /*! @brief Constructor for Adafruit_HX8357 displays, using an arbitrary SPI interface. @param spi SPI peripheral to use. @param cs Chip select pin (using Arduino pin numbering). @param dc Data/Command pin (using Arduino pin numbering). @param rst Reset pin (Arduino pin numbering, optional, pass -1 if unused). @param type Display type, HX8357D (default if unspecified) or HX8357B. @return Adafruit_HX8357 object. @note Call the object's begin() function before use. */ Adafruit_HX8357::Adafruit_HX8357(SPIClass *spi, int8_t cs, int8_t dc, int8_t rst, uint8_t type) : Adafruit_SPITFT(HX8357_TFTWIDTH, HX8357_TFTHEIGHT, spi, cs, dc, rst), displayType(type) {} #endif // end !ESP8266 /**************************************************************************/ /*! @brief Constructor for Adafruit_HX8357 displays, using parallel interface. @param busWidth If tft16 (enumeration in Adafruit_SPITFT.h), is a 16-bit interface, else 8-bit. @param d0 Data pin 0 (MUST be a byte- or word-aligned LSB of a PORT register -- pins 1-n are extrapolated from this). @param wr Write strobe pin # (required). @param dc Data/Command pin # (required). @param cs Chip select pin # (optional, pass -1 if unused and CS is tied to GND). @param rst Reset pin # (optional, pass -1 if unused). @param rd Read strobe pin # (optional, pass -1 if unused). */ /**************************************************************************/ Adafruit_HX8357::Adafruit_HX8357(tftBusWidth busWidth, int8_t d0, int8_t wr, int8_t dc, int8_t cs, int8_t rst, int8_t rd) : Adafruit_SPITFT(HX8357_TFTWIDTH, HX8357_TFTHEIGHT, busWidth, d0, wr, dc, cs, rst, rd) {} /*! @brief Destructor for Adafruit_HX8357 object. @return None (void). */ Adafruit_HX8357::~Adafruit_HX8357(void) {} // INIT DISPLAY ------------------------------------------------------------ static const uint8_t PROGMEM initb[] = { HX8357B_SETPOWER, 3, 0x44, 0x41, 0x06, HX8357B_SETVCOM, 2, 0x40, 0x10, HX8357B_SETPWRNORMAL, 2, 0x05, 0x12, HX8357B_SET_PANEL_DRIVING, 5, 0x14, 0x3b, 0x00, 0x02, 0x11, HX8357B_SETDISPLAYFRAME, 1, 0x0c, // 6.8mhz HX8357B_SETPANELRELATED, 1, 0x01, // BGR 0xEA, 3, // seq_undefined1, 3 args 0x03, 0x00, 0x00, 0xEB, 4, // undef2, 4 args 0x40, 0x54, 0x26, 0xdb, HX8357B_SETGAMMA, 12, 0x00, 0x15, 0x00, 0x22, 0x00, 0x08, 0x77, 0x26, 0x66, 0x22, 0x04, 0x00, HX8357_MADCTL, 1, 0xC0, HX8357_COLMOD, 1, 0x55, HX8357_PASET, 4, 0x00, 0x00, 0x01, 0xDF, HX8357_CASET, 4, 0x00, 0x00, 0x01, 0x3F, HX8357B_SETDISPMODE, 1, 0x00, // CPU (DBI) and internal oscillation ?? HX8357_SLPOUT, 0x80 + 120 / 5, // Exit sleep, then delay 120 ms HX8357_DISPON, 0x80 + 10 / 5, // Main screen turn on, delay 10 ms 0 // END OF COMMAND LIST }, initd[] = { HX8357_SWRESET, 0x80 + 100 / 5, // Soft reset, then delay 10 ms HX8357D_SETC, 3, 0xFF, 0x83, 0x57, 0xFF, 0x80 + 500 / 5, // No command, just delay 300 ms HX8357_SETRGB, 4, 0x80, 0x00, 0x06, 0x06, // 0x80 enables SDO pin (0x00 disables) HX8357D_SETCOM, 1, 0x25, // -1.52V HX8357_SETOSC, 1, 0x68, // Normal mode 70Hz, Idle mode 55 Hz HX8357_SETPANEL, 1, 0x05, // BGR, Gate direction swapped HX8357_SETPWR1, 6, 0x00, // Not deep standby 0x15, // BT 0x1C, // VSPR 0x1C, // VSNR 0x83, // AP 0xAA, // FS HX8357D_SETSTBA, 6, 0x50, // OPON normal 0x50, // OPON idle 0x01, // STBA 0x3C, // STBA 0x1E, // STBA 0x08, // GEN HX8357D_SETCYC, 7, 0x02, // NW 0x02 0x40, // RTN 0x00, // DIV 0x2A, // DUM 0x2A, // DUM 0x0D, // GDON 0x78, // GDOFF HX8357D_SETGAMMA, 34, 0x02, 0x0A, 0x11, 0x1d, 0x23, 0x35, 0x41, 0x4b, 0x4b, 0x42, 0x3A, 0x27, 0x1B, 0x08, 0x09, 0x03, 0x02, 0x0A, 0x11, 0x1d, 0x23, 0x35, 0x41, 0x4b, 0x4b, 0x42, 0x3A, 0x27, 0x1B, 0x08, 0x09, 0x03, 0x00, 0x01, HX8357_COLMOD, 1, 0x55, // 16 bit HX8357_MADCTL, 1, 0xC0, HX8357_TEON, 1, 0x00, // TW off HX8357_TEARLINE, 2, 0x00, 0x02, HX8357_SLPOUT, 0x80 + 150 / 5, // Exit Sleep, then delay 150 ms HX8357_DISPON, 0x80 + 50 / 5, // Main screen turn on, delay 50 ms 0, // END OF COMMAND LIST }; /*! @brief Initialize HX8357 chip. Connects to the HX8357 over SPI and sends initialization commands. @param freq SPI bitrate -- default of 0 will use a (usually) platform- optimized value, e.g. 8 MHz on AVR, 12 MHz on M0. @return None (void). */ void Adafruit_HX8357::begin(uint32_t freq) { // Older version of this library accepted a display type as the only // argument (HX8357D or HX8357B), but SPITFT (part of GFX lib) REQUIRES // the begin() function instead accept an SPI bitrate (or 0 for default), // so display type was moved to the constructor. Examples will be // updated, but just in case there's old code around, we pull shenanigans // here...the values for HX8357D and HX8357B (0xD and 0xB, respectively) // would make for absurd SPI bitrates...so if we receive one of those // values, assume it's old code intending to pass the display type. // Override the displayType value that was set in the constructor with // the value passed here, and use the default SPI bitrate for platform. if (freq == HX8357D) { displayType = freq; freq = 0; // Use default SPI frequency } else if (freq == HX8357B) { displayType = freq; freq = 0; // Use default SPI frequency } if (!freq) freq = SPI_DEFAULT_FREQ; initSPI(freq); const uint8_t *addr = (displayType == HX8357B) ? initb : initd; uint8_t cmd, x, numArgs; while ((cmd = pgm_read_byte(addr++)) > 0) { // '0' command ends list x = pgm_read_byte(addr++); numArgs = x & 0x7F; if (cmd != 0xFF) { // '255' is ignored if (x & 0x80) { // If high bit set, numArgs is a delay time sendCommand(cmd); } else { sendCommand(cmd, addr, numArgs); addr += numArgs; } } if (x & 0x80) { // If high bit set... delay(numArgs * 5); // numArgs is actually a delay time (5ms units) } } _width = HX8357_TFTWIDTH; // Screen dimensions for default rotation 0 _height = HX8357_TFTHEIGHT; } // GFX FUNCTIONS ----------------------------------------------------------- /*! @brief Set origin of (0,0) and orientation of TFT display @param m The index for rotation, from 0-3 inclusive @return None (void). */ void Adafruit_HX8357::setRotation(uint8_t m) { rotation = m & 3; // can't be higher than 3 switch (rotation) { case 0: m = MADCTL_MX | MADCTL_MY | MADCTL_RGB; _width = HX8357_TFTWIDTH; _height = HX8357_TFTHEIGHT; break; case 1: m = MADCTL_MV | MADCTL_MY | MADCTL_RGB; _width = HX8357_TFTHEIGHT; _height = HX8357_TFTWIDTH; break; case 2: m = MADCTL_RGB; _width = HX8357_TFTWIDTH; _height = HX8357_TFTHEIGHT; break; case 3: m = MADCTL_MX | MADCTL_MV | MADCTL_RGB; _width = HX8357_TFTHEIGHT; _height = HX8357_TFTWIDTH; break; } sendCommand(HX8357_MADCTL, &m, 1); } /*! @brief Enable/Disable display color inversion @param invert True to invert display, False for normal color. @return None (void). */ void Adafruit_HX8357::invertDisplay(boolean invert) { sendCommand(invert ? HX8357_INVON : HX8357_INVOFF); } /*! @brief Set the "address window" - the rectangle we will write to graphics RAM with the next chunk of SPI data writes. The HX8357 will automatically wrap the data as each row is filled. @param x1 Leftmost column of rectangle (screen pixel coordinates). @param y1 Topmost row of rectangle (screen pixel coordinates). @param w Width of rectangle. @param h Height of rectangle. @return None (void). */ void Adafruit_HX8357::setAddrWindow(uint16_t x1, uint16_t y1, uint16_t w, uint16_t h) { uint16_t x2 = (x1 + w - 1), y2 = (y1 + h - 1); writeCommand(HX8357_CASET); // Column address set SPI_WRITE16(x1); SPI_WRITE16(x2); writeCommand(HX8357_PASET); // Row address set SPI_WRITE16(y1); SPI_WRITE16(y2); writeCommand(HX8357_RAMWR); // Write to RAM }