|
|
@@ -1,154 +1,465 @@
|
|
|
-#ifndef _ADAFRUIT_SPITFT_
|
|
|
-#define _ADAFRUIT_SPITFT_
|
|
|
+/*!
|
|
|
+ * @file Adafruit_SPITFT.h
|
|
|
+ *
|
|
|
+ * Part of Adafruit's GFX graphics library. Originally this class was
|
|
|
+ * written to handle a range of color TFT displays connected via SPI,
|
|
|
+ * but over time this library and some display-specific subclasses have
|
|
|
+ * mutated to include some color OLEDs as well as parallel-interfaced
|
|
|
+ * displays. The name's been kept for the sake of older code.
|
|
|
+ *
|
|
|
+ * Adafruit invests time and resources providing this open source code,
|
|
|
+ * please support Adafruit and open-source hardware by purchasing
|
|
|
+ * products from Adafruit!
|
|
|
+ *
|
|
|
+ * @section author Author
|
|
|
+ *
|
|
|
+ * Written by Limor "ladyada" Fried for Adafruit Industries,
|
|
|
+ * with contributions from the open source community.
|
|
|
+ *
|
|
|
+ * @section license License
|
|
|
+ *
|
|
|
+ * BSD license, all text here must be included in any redistribution.
|
|
|
+ */
|
|
|
|
|
|
-#if !defined(__AVR_ATtiny85__) // NOT A CHANCE of this stuff working on ATtiny
|
|
|
+#ifndef _ADAFRUIT_SPITFT_H_
|
|
|
+#define _ADAFRUIT_SPITFT_H_
|
|
|
+
|
|
|
+#if !defined(__AVR_ATtiny85__) // Not for ATtiny, at all
|
|
|
|
|
|
-#if ARDUINO >= 100
|
|
|
- #include "Arduino.h"
|
|
|
- #include "Print.h"
|
|
|
-#else
|
|
|
- #include "WProgram.h"
|
|
|
-#endif
|
|
|
#include <SPI.h>
|
|
|
#include "Adafruit_GFX.h"
|
|
|
|
|
|
-#define USE_FAST_PINIO ///< If set, use PORT access instead of digitalWrite()
|
|
|
-//#define USE_SPI_DMA ///< If set, use SPI DMA if available
|
|
|
+// HARDWARE CONFIG ---------------------------------------------------------
|
|
|
+
|
|
|
+#if defined(__AVR__)
|
|
|
+ typedef uint8_t PORT_t; ///< PORT values are 8-bit
|
|
|
+ #define USE_FAST_PINIO ///< Use direct PORT register access
|
|
|
+#elif defined(__arm__)
|
|
|
+ #if defined(SAM)
|
|
|
+ // Arduino Due
|
|
|
+ typedef uint32_t PORT_t; ///< PORT values are 32-bit
|
|
|
+ // USE_FAST_PINIO not available here (yet)...Due has a totally different
|
|
|
+ // GPIO register set and will require some changes elsewhere (e.g. in
|
|
|
+ // constructors especially).
|
|
|
+ #elif defined(CORE_TEENSY)
|
|
|
+ // PJRC Teensy 3.x
|
|
|
+ typedef uint8_t PORT_t; ///< PORT values are 8-bit
|
|
|
+ #define USE_FAST_PINIO ///< Use direct PORT register access
|
|
|
+ #define HAS_PORT_SET_CLR ///< PORTs have set & clear registers
|
|
|
+ #else
|
|
|
+ // Adafruit M0, M4
|
|
|
+ typedef uint32_t PORT_t; ///< PORT values are 32-bit
|
|
|
+ #define USE_FAST_PINIO ///< Use direct PORT register access
|
|
|
+ #define HAS_PORT_SET_CLR ///< PORTs have set & clear registers
|
|
|
+ #endif
|
|
|
+#else // !ARM
|
|
|
+ // Probably ESP8266 or ESP32. USE_FAST_PINIO is not available here (yet)
|
|
|
+ // but don't worry about it too much...the digitalWrite() implementation
|
|
|
+ // on these platforms is reasonably efficient and already RAM-resident,
|
|
|
+ // only gotcha then is no parallel connection support for now.
|
|
|
+ typedef uint32_t PORT_t; ///< PORT values are 32-bit
|
|
|
+#endif // end !ARM
|
|
|
+typedef volatile PORT_t* PORTreg_t; ///< PORT register type
|
|
|
+
|
|
|
+#if defined(__AVR__)
|
|
|
+ #define DEFAULT_SPI_FREQ 8000000L ///< Hardware SPI default speed
|
|
|
+#else
|
|
|
+ #define DEFAULT_SPI_FREQ 16000000L ///< Hardware SPI default speed
|
|
|
+#endif
|
|
|
+
|
|
|
+//#define USE_SPI_DMA ///< If set, use SPI DMA if available
|
|
|
+// Another "oops" name -- in the future parallel DMA will also be handled.
|
|
|
// If DMA is enabled, Arduino sketch MUST #include <Adafruit_ZeroDMA.h>
|
|
|
// Estimated RAM usage:
|
|
|
// 4 bytes/pixel on display major axis + 8 bytes/pixel on minor axis,
|
|
|
// e.g. 320x240 pixels = 320 * 4 + 240 * 8 = 3,200 bytes.
|
|
|
|
|
|
#if !defined(ARDUINO_ARCH_SAMD)
|
|
|
- #undef USE_SPI_DMA ///< Only for SAMD chips
|
|
|
+ #undef USE_SPI_DMA ///< DMA currently for SAMD chips only
|
|
|
#endif
|
|
|
|
|
|
-#ifdef USE_SPI_DMA
|
|
|
- #pragma message ("SPI DMA IS ENABLED. HIGHLY EXPERIMENTAL.")
|
|
|
+#if defined(USE_SPI_DMA)
|
|
|
+ #pragma message ("GFX DMA IS ENABLED. HIGHLY EXPERIMENTAL.")
|
|
|
#include <Adafruit_ZeroDMA.h>
|
|
|
#endif
|
|
|
|
|
|
-#if defined(__AVR__)
|
|
|
- typedef volatile uint8_t RwReg;
|
|
|
-#elif defined(ARDUINO_STM32_FEATHER)
|
|
|
- typedef volatile uint32_t RwReg;
|
|
|
- #undef USE_FAST_PINIO
|
|
|
- typedef class HardwareSPI SPIClass;
|
|
|
-#elif defined(__OPENCR__) || defined (__OPENCM904__)
|
|
|
- #undef USE_FAST_PINIO
|
|
|
-#elif defined(ARDUINO_FEATHER52) || defined(__arm__)
|
|
|
- typedef volatile uint32_t RwReg;
|
|
|
-#elif defined(ESP32) || defined(ESP8266)
|
|
|
- typedef volatile uint32_t RwReg;
|
|
|
- #undef USE_FAST_PINIO
|
|
|
-#else
|
|
|
- #undef USE_FAST_PINIO
|
|
|
-#endif
|
|
|
-
|
|
|
-#include "Adafruit_SPITFT_Macros.h"
|
|
|
+// CLASS DEFINITION --------------------------------------------------------
|
|
|
|
|
|
-/// A heavily optimized SPI display subclass of GFX. Manages SPI bitbanging, transactions, DMA, etc! Despite being called SPITFT, the classic SPI data/command interface is also used by OLEDs.
|
|
|
+/*!
|
|
|
+ @brief Adafruit_SPITFT is an intermediary class between Adafruit_GFX
|
|
|
+ and various hardware-specific subclasses for different displays.
|
|
|
+ It handles certain operations that are common to a range of
|
|
|
+ displays (address window, area fills, etc.). Originally these were
|
|
|
+ all color TFT displays interfaced via SPI, but it's since expanded
|
|
|
+ to include color OLEDs and parallel-interfaced TFTs. THE NAME HAS
|
|
|
+ BEEN KEPT TO AVOID BREAKING A LOT OF SUBCLASSES AND EXAMPLE CODE.
|
|
|
+ Many of the class member functions similarly live on with names
|
|
|
+ that don't necessarily accurately describe what they're doing,
|
|
|
+ again to avoid breaking a lot of other code. If in doubt, read
|
|
|
+ the comments.
|
|
|
+*/
|
|
|
class Adafruit_SPITFT : public Adafruit_GFX {
|
|
|
|
|
|
- public:
|
|
|
- Adafruit_SPITFT(uint16_t w, uint16_t h, int8_t _CS, int8_t _DC, int8_t _MOSI, int8_t _SCLK, int8_t _RST = -1, int8_t _MISO = -1);
|
|
|
- Adafruit_SPITFT(uint16_t w, uint16_t h, int8_t _CS, int8_t _DC, int8_t _RST = -1);
|
|
|
- Adafruit_SPITFT(uint16_t w, uint16_t h, SPIClass *spiClass, int8_t _CS, int8_t _DC, int8_t _RST = -1);
|
|
|
- virtual void begin(uint32_t freq) = 0; ///< Virtual begin() function to set SPI frequency, must be overridden in subclass. @param freq Maximum SPI hardware clock speed
|
|
|
-
|
|
|
- void initSPI(uint32_t freq);
|
|
|
-
|
|
|
- // Required Non-Transaction
|
|
|
- void drawPixel(int16_t x, int16_t y, uint16_t color);
|
|
|
-
|
|
|
- // Transaction API
|
|
|
- void startWrite(void);
|
|
|
- void endWrite(void);
|
|
|
-
|
|
|
- void writePixel(int16_t x, int16_t y, uint16_t color);
|
|
|
- void writeFillRect(int16_t x, int16_t y, int16_t w, int16_t h, uint16_t color);
|
|
|
- void writeFastVLine(int16_t x, int16_t y, int16_t h, uint16_t color);
|
|
|
- void writeFastHLine(int16_t x, int16_t y, int16_t w, uint16_t color);
|
|
|
-
|
|
|
- // Transaction API not used by GFX
|
|
|
-
|
|
|
- /*!
|
|
|
- @brief SPI displays set an address window rectangle for blitting pixels
|
|
|
- @param x Top left corner x coordinate
|
|
|
- @param y Top left corner x coordinate
|
|
|
- @param w Width of window
|
|
|
- @param h Height of window
|
|
|
- */
|
|
|
- virtual void setAddrWindow(uint16_t x, uint16_t y, uint16_t w, uint16_t h) = 0;
|
|
|
-
|
|
|
- /*!
|
|
|
- @brief Write a 2-byte color (must have a transaction in progress)
|
|
|
- @param color 16-bit 5-6-5 Color to draw
|
|
|
- */
|
|
|
- void inline writePixel(uint16_t color) { SPI_WRITE16(color); }
|
|
|
- void writePixels(uint16_t * colors, uint32_t len);
|
|
|
- void writeColor(uint16_t color, uint32_t len);
|
|
|
- void pushColor(uint16_t color);
|
|
|
-
|
|
|
- // Recommended Non-Transaction
|
|
|
- void drawFastVLine(int16_t x, int16_t y, int16_t h, uint16_t color);
|
|
|
- void drawFastHLine(int16_t x, int16_t y, int16_t w, uint16_t color);
|
|
|
- void fillRect(int16_t x, int16_t y, int16_t w, int16_t h, uint16_t color);
|
|
|
-
|
|
|
- using Adafruit_GFX::drawRGBBitmap; // Check base class first
|
|
|
- void drawRGBBitmap(int16_t x, int16_t y,
|
|
|
- uint16_t *pcolors, int16_t w, int16_t h);
|
|
|
- void invertDisplay(boolean i);
|
|
|
-
|
|
|
- uint16_t color565(uint8_t r, uint8_t g, uint8_t b);
|
|
|
- void writeCommand(uint8_t cmd);
|
|
|
- void spiWrite(uint8_t v);
|
|
|
- uint8_t spiRead(void);
|
|
|
-
|
|
|
- protected:
|
|
|
- SPIClass *_spi; ///< The SPI device we want to use (set in constructor)
|
|
|
- uint32_t _freq; ///< SPI clock frequency (for hardware SPI)
|
|
|
-#if defined (__AVR__) || defined(TEENSYDUINO) || defined (ESP8266) || defined (ESP32)
|
|
|
- int8_t _cs, _dc, _rst, _sclk, _mosi, _miso;
|
|
|
-#else
|
|
|
- int32_t _cs, ///< Arduino pin # for chip-select pin
|
|
|
- _dc, ///< Arduino pin # for data-command pin
|
|
|
- _rst, ///< Arduino pin # for reset pin
|
|
|
- _sclk, ///< Arduino pin # for SPI clock pin
|
|
|
- _mosi, ///< Arduino pin # for SPI MOSI pin
|
|
|
- _miso; ///< Arduino pin # for SPI MISO pin
|
|
|
-#endif
|
|
|
+ public:
|
|
|
|
|
|
-#ifdef USE_FAST_PINIO
|
|
|
- volatile RwReg *mosiport, ///< Direct chip register for toggling MOSI with fast bitbang IO
|
|
|
- *misoport, ///< Direct chip register for toggling MISO with fast bitbang IO
|
|
|
- *clkport, ///< Direct chip register for toggling CLK with fast bitbang IO
|
|
|
- *dcport, ///< Direct chip register for toggling DC with fast bitbang IO
|
|
|
- *csport; ///< Direct chip register for toggling CS with fast bitbang IO
|
|
|
- RwReg mosipinmask, ///< bitmask for turning on/off MOSI with fast register bitbang IO
|
|
|
- misopinmask, ///< bitmask for turning on/off MISO with fast register bitbang IO
|
|
|
- clkpinmask, ///< bitmask for turning on/off CLK with fast register bitbang IO
|
|
|
- cspinmask, ///< bitmask for turning on/off CS with fast register bitbang IO
|
|
|
- dcpinmask; ///< bitmask for turning on/off DC with fast register bitbang IO
|
|
|
-#endif
|
|
|
+ // CONSTRUCTORS --------------------------------------------------------
|
|
|
+
|
|
|
+ // Software SPI constructor: expects width & height (at default rotation
|
|
|
+ // setting 0), 4 signal pins (cs, dc, mosi, sclk), 2 optional pins
|
|
|
+ // (reset, miso). cs argument is required but can be -1 if unused --
|
|
|
+ // rather than moving it to the optional arguments, it was done this way
|
|
|
+ // to avoid breaking existing code (-1 option was a later addition).
|
|
|
+ Adafruit_SPITFT(uint16_t w, uint16_t h,
|
|
|
+ int8_t cs, int8_t dc, int8_t mosi, int8_t sck,
|
|
|
+ int8_t rst = -1, int8_t miso = -1);
|
|
|
+
|
|
|
+ // Hardware SPI constructor using the default SPI port: expects width &
|
|
|
+ // height (at default rotation setting 0), 2 signal pins (cs, dc),
|
|
|
+ // optional reset pin. cs is required but can be -1 if unused -- rather
|
|
|
+ // than moving it to the optional arguments, it was done this way to
|
|
|
+ // avoid breaking existing code (-1 option was a later addition).
|
|
|
+ Adafruit_SPITFT(uint16_t w, uint16_t h,
|
|
|
+ int8_t cs, int8_t dc, int8_t rst = -1);
|
|
|
+
|
|
|
+ // Hardware SPI constructor using an arbitrary SPI peripheral: expects
|
|
|
+ // width & height (rotation 0), SPIClass pointer, 2 signal pins (cs, dc)
|
|
|
+ // and optional reset pin. cs is required but can be -1 if unused.
|
|
|
+ Adafruit_SPITFT(uint16_t w, uint16_t h, SPIClass *spiClass,
|
|
|
+ int8_t cs, int8_t dc, int8_t rst = -1);
|
|
|
+
|
|
|
+ // Parallel constructor: expects width & height (rotation 0), flag
|
|
|
+ // indicating whether 16-bit (true) or 8-bit (false) interface, 3 signal
|
|
|
+ // pins (d0, wr, dc), 3 optional pins (cs, rst, rd). 16-bit parallel
|
|
|
+ // isn't even fully implemented but the 'wide' flag was added as a
|
|
|
+ // required argument to avoid ambiguity with other constructors.
|
|
|
+ Adafruit_SPITFT(uint16_t w, uint16_t h, bool wide,
|
|
|
+ int8_t d0, int8_t wr, int8_t dc,
|
|
|
+ int8_t cs = -1, int8_t rst = -1, int8_t rd = -1);
|
|
|
+
|
|
|
+ // CLASS MEMBER FUNCTIONS ----------------------------------------------
|
|
|
+
|
|
|
+ // These first two functions MUST be declared by subclasses:
|
|
|
|
|
|
- uint8_t invertOnCommand = 0, ///< SPI command byte to turn on invert
|
|
|
- invertOffCommand = 0; ///< SPI command byte to turn off invert
|
|
|
- int16_t _xstart = 0; ///< Many displays don't have pixels starting at (0,0) of the internal framebuffer, this is the x offset from 0 to align
|
|
|
- int16_t _ystart = 0; ///< Many displays don't have pixels starting at (0,0) of the internal framebuffer, this is the y offset from 0 to align
|
|
|
-
|
|
|
-#ifdef USE_SPI_DMA
|
|
|
- Adafruit_ZeroDMA dma; ///< DMA instance
|
|
|
- DmacDescriptor *dptr = NULL; ///< 1st descriptor
|
|
|
- DmacDescriptor *descriptor = NULL; ///< Allocated descriptor list
|
|
|
- uint16_t *pixelBuf[2]; ///< Working buffers
|
|
|
- uint16_t maxFillLen; ///< Max pixels per DMA xfer
|
|
|
- uint16_t lastFillColor = 0; ///< Last color used w/fill
|
|
|
- uint32_t lastFillLen = 0; ///< # of pixels w/last fill
|
|
|
- uint8_t onePixelBuf; ///< For hi==lo fill
|
|
|
+ /*!
|
|
|
+ @brief Display-specific initialization function.
|
|
|
+ @param freq SPI frequency, in hz (or 0 for default or unused).
|
|
|
+ */
|
|
|
+ virtual void begin(uint32_t freq) = 0;
|
|
|
+
|
|
|
+ /*!
|
|
|
+ @brief Set up the specific display hardware's "address window"
|
|
|
+ for subsequent pixel-pushing operations.
|
|
|
+ @param x Leftmost pixel of area to be drawn (MUST be within
|
|
|
+ display bounds at current rotation setting).
|
|
|
+ @param y Topmost pixel of area to be drawn (MUST be within
|
|
|
+ display bounds at current rotation setting).
|
|
|
+ @param w Width of area to be drawn, in pixels (MUST be >0 and,
|
|
|
+ added to x, within display bounds at current rotation).
|
|
|
+ @param h Height of area to be drawn, in pixels (MUST be >0 and,
|
|
|
+ added to x, within display bounds at current rotation).
|
|
|
+ */
|
|
|
+ virtual void setAddrWindow(
|
|
|
+ uint16_t x, uint16_t y, uint16_t w, uint16_t h) = 0;
|
|
|
+
|
|
|
+ // Remaining functions do not need to be declared in subclasses
|
|
|
+ // unless they wish to provide hardware-specific optimizations.
|
|
|
+ // Brief comments here...documented more thoroughly in .cpp file.
|
|
|
+
|
|
|
+ // Subclass' begin() function invokes this to initialize hardware.
|
|
|
+ // Name is outdated (interface may be parallel) but for compatibility:
|
|
|
+ void initSPI(uint32_t freq = 0); // 0 = use default SPI speed
|
|
|
+ // Chip select and/or hardware SPI transaction start as needed:
|
|
|
+ void startWrite(void);
|
|
|
+ // Chip deselect and/or hardware SPI transaction end as needed:
|
|
|
+ void endWrite(void);
|
|
|
+
|
|
|
+ // These functions require a chip-select and/or SPI transaction
|
|
|
+ // around them. Higher-level graphics primitives might start a
|
|
|
+ // single transaction and then make multiple calls to these functions
|
|
|
+ // (e.g. circle or text rendering might make repeated lines or rects)
|
|
|
+ // before ending the transaction. It's more efficient than starting a
|
|
|
+ // transaction every time.
|
|
|
+ void writePixel(int16_t x, int16_t y, uint16_t color);
|
|
|
+ void writePixels(uint16_t *colors, uint32_t len);
|
|
|
+ void writeColor(uint16_t color, uint32_t len);
|
|
|
+ void writeFillRect(int16_t x, int16_t y, int16_t w, int16_t h,
|
|
|
+ uint16_t color);
|
|
|
+ void writeFastHLine(int16_t x, int16_t y, int16_t w,
|
|
|
+ uint16_t color);
|
|
|
+ void writeFastVLine(int16_t x, int16_t y, int16_t h,
|
|
|
+ uint16_t color);
|
|
|
+ // This is a new function, similar to writeFillRect() except that
|
|
|
+ // all arguments MUST be onscreen, sorted and clipped. If higher-level
|
|
|
+ // primitives can handle their own sorting/clipping, it avoids repeating
|
|
|
+ // such operations in the low-level code, making it potentially faster.
|
|
|
+ // CALLING THIS WITH UNCLIPPED OR NEGATIVE VALUES COULD BE DISASTROUS.
|
|
|
+ inline void writeFillRectPreclipped(int16_t x, int16_t y,
|
|
|
+ int16_t w, int16_t h, uint16_t color);
|
|
|
+ // This variant of writePixel() just calls SPI_WRITE16()...new code
|
|
|
+ // should probably just do the latter, consider this deprecated:
|
|
|
+ inline void writePixel(uint16_t color);
|
|
|
+
|
|
|
+ // These functions are similar to the 'write' functions above, but with
|
|
|
+ // a chip-select and/or SPI transaction built-in. They're typically used
|
|
|
+ // solo -- that is, as graphics primitives in themselves, not invoked by
|
|
|
+ // higher-level primitives (which should use the functions above).
|
|
|
+ void drawPixel(int16_t x, int16_t y, uint16_t color);
|
|
|
+ void fillRect(int16_t x, int16_t y, int16_t w, int16_t h,
|
|
|
+ uint16_t color);
|
|
|
+ void drawFastHLine(int16_t x, int16_t y, int16_t w,
|
|
|
+ uint16_t color);
|
|
|
+ void drawFastVLine(int16_t x, int16_t y, int16_t h,
|
|
|
+ uint16_t color);
|
|
|
+ // A single-pixel push encapsulated in a transaction. I don't think
|
|
|
+ // this is used anymore (BMP demos might've used it?) but is provided
|
|
|
+ // for backward compatibility, consider it deprecated:
|
|
|
+ void pushColor(uint16_t color);
|
|
|
+
|
|
|
+ using Adafruit_GFX::drawRGBBitmap; // Check base class first
|
|
|
+ void drawRGBBitmap(int16_t x, int16_t y,
|
|
|
+ uint16_t *pcolors, int16_t w, int16_t h);
|
|
|
+
|
|
|
+ void invertDisplay(bool i);
|
|
|
+ uint16_t color565(uint8_t r, uint8_t g, uint8_t b);
|
|
|
+
|
|
|
+ // Despite parallel additions, function names kept for compatibility:
|
|
|
+ void spiWrite(uint8_t b); // Write single byte as DATA
|
|
|
+ void writeCommand(uint8_t cmd); // Write single byte as COMMAND
|
|
|
+ uint8_t spiRead(void); // Read single byte of data
|
|
|
+
|
|
|
+ // Most of these low-level functions were formerly macros in
|
|
|
+ // Adafruit_SPITFT_Macros.h. Some have been made into inline functions
|
|
|
+ // to avoid macro mishaps. Despite the addition of code for a parallel
|
|
|
+ // display interface, the names have been kept for backward
|
|
|
+ // compatibility (some subclasses may be invoking these):
|
|
|
+ void SPI_WRITE16(uint16_t w); // Not inline
|
|
|
+ void SPI_WRITE32(uint32_t l); // Not inline
|
|
|
+ void SPI_WRITE_PIXELS(uint16_t *data, uint32_t bytes); // ditto
|
|
|
+ // Old code had both a spiWrite16() function and SPI_WRITE16 macro
|
|
|
+ // in addition to the SPI_WRITE32 macro. The latter two have been
|
|
|
+ // made into functions here, and spiWrite16() removed (use SPI_WRITE16()
|
|
|
+ // instead). It looks like most subclasses had gotten comfortable with
|
|
|
+ // SPI_WRITE16 and SPI_WRITE32 anyway so those names were kept rather
|
|
|
+ // than the less-obnoxious camelcase variants, oh well.
|
|
|
+
|
|
|
+ // Placing these functions entirely in the class definition inlines
|
|
|
+ // them implicitly them while allowing their use in other code:
|
|
|
+
|
|
|
+ /*!
|
|
|
+ @brief Set the chip-select line HIGH. Does NOT check whether CS pin
|
|
|
+ is set (>=0), that should be handled in calling function.
|
|
|
+ Despite function name, this is used even if the display
|
|
|
+ connection is parallel.
|
|
|
+ */
|
|
|
+ void SPI_CS_HIGH(void) {
|
|
|
+ #if defined(USE_FAST_PINIO)
|
|
|
+ #if defined(HAS_PORT_SET_CLR)
|
|
|
+ *csPortSet = csPinMask;
|
|
|
+ #else // !HAS_PORT_SET_CLR
|
|
|
+ *csPort |= csPinMaskSet;
|
|
|
+ #endif // end !HAS_PORT_SET_CLR
|
|
|
+ #else // !USE_FAST_PINIO
|
|
|
+ digitalWrite(_cs, HIGH);
|
|
|
+ #endif // end !USE_FAST_PINIO
|
|
|
+ }
|
|
|
+
|
|
|
+ /*!
|
|
|
+ @brief Set the chip-select line LOW. Does NOT check whether CS pin
|
|
|
+ is set (>=0), that should be handled in calling function.
|
|
|
+ Despite function name, this is used even if the display
|
|
|
+ connection is parallel.
|
|
|
+ */
|
|
|
+ void SPI_CS_LOW(void) {
|
|
|
+ #if defined(USE_FAST_PINIO)
|
|
|
+ #if defined(HAS_PORT_SET_CLR)
|
|
|
+ *csPortClr = csPinMask;
|
|
|
+ #else // !HAS_PORT_SET_CLR
|
|
|
+ *csPort &= csPinMaskClr;
|
|
|
+ #endif // end !HAS_PORT_SET_CLR
|
|
|
+ #else // !USE_FAST_PINIO
|
|
|
+ digitalWrite(_cs, LOW);
|
|
|
+ #endif // end !USE_FAST_PINIO
|
|
|
+ }
|
|
|
+
|
|
|
+ /*!
|
|
|
+ @brief Set the data/command line HIGH (data mode).
|
|
|
+ */
|
|
|
+ void SPI_DC_HIGH(void) {
|
|
|
+ #if defined(USE_FAST_PINIO)
|
|
|
+ #if defined(HAS_PORT_SET_CLR)
|
|
|
+ #if defined(KINETISK)
|
|
|
+ *dcPortSet = 1;
|
|
|
+ #else // !KINETISK
|
|
|
+ *dcPortSet = dcPinMask;
|
|
|
+ #endif // end !KINETISK
|
|
|
+ #else // !HAS_PORT_SET_CLR
|
|
|
+ *dcPort |= dcPinMaskSet;
|
|
|
+ #endif // end !HAS_PORT_SET_CLR
|
|
|
+ #else // !USE_FAST_PINIO
|
|
|
+ digitalWrite(_dc, HIGH);
|
|
|
+ #endif // end !USE_FAST_PINIO
|
|
|
+ }
|
|
|
+
|
|
|
+ /*!
|
|
|
+ @brief Set the data/command line LOW (command mode).
|
|
|
+ */
|
|
|
+ void SPI_DC_LOW(void) {
|
|
|
+ #if defined(USE_FAST_PINIO)
|
|
|
+ #if defined(HAS_PORT_SET_CLR)
|
|
|
+ #if defined(KINETISK)
|
|
|
+ *dcPortClr = 1;
|
|
|
+ #else // !KINETISK
|
|
|
+ *dcPortClr = dcPinMask;
|
|
|
+ #endif // end !KINETISK
|
|
|
+ #else // !HAS_PORT_SET_CLR
|
|
|
+ *dcPort &= dcPinMaskClr;
|
|
|
+ #endif // end !HAS_PORT_SET_CLR
|
|
|
+ #else // !USE_FAST_PINIO
|
|
|
+ digitalWrite(_dc, LOW);
|
|
|
+ #endif // end !USE_FAST_PINIO
|
|
|
+ }
|
|
|
+
|
|
|
+ protected:
|
|
|
+
|
|
|
+ // A few more low-level member functions -- some may have previously
|
|
|
+ // been macros. Shouldn't have a need to access these externally, so
|
|
|
+ // they've been moved to the protected section. Additionally, they're
|
|
|
+ // declared inline here and the code is in the .cpp file, since outside
|
|
|
+ // code doesn't need to see these.
|
|
|
+ inline void SPI_MOSI_HIGH(void);
|
|
|
+ inline void SPI_MOSI_LOW(void);
|
|
|
+ inline void SPI_SCK_HIGH(void);
|
|
|
+ inline void SPI_SCK_LOW(void);
|
|
|
+ inline bool SPI_MISO_READ(void);
|
|
|
+ inline void SPI_BEGIN_TRANSACTION(void);
|
|
|
+ inline void SPI_END_TRANSACTION(void);
|
|
|
+ inline void TFT_WR_STROBE(void); // Parallel interface write strobe
|
|
|
+ inline void TFT_RD_HIGH(void); // Parallel interface read high
|
|
|
+ inline void TFT_RD_LOW(void); // Parallel interface read low
|
|
|
+
|
|
|
+ // CLASS INSTANCE VARIABLES --------------------------------------------
|
|
|
+
|
|
|
+ // Here be dragons! There's a big union of three structures here --
|
|
|
+ // one each for hardware SPI, software (bitbang) SPI, and parallel
|
|
|
+ // interfaces. This is to save some memory, since a display's connection
|
|
|
+ // will be only one of these. The order of some things is a little weird
|
|
|
+ // in an attempt to get values to align and pack better in RAM.
|
|
|
+
|
|
|
+#if defined(USE_FAST_PINIO)
|
|
|
+#if defined(HAS_PORT_SET_CLR)
|
|
|
+ PORTreg_t csPortSet; ///< PORT register for chip select SET
|
|
|
+ PORTreg_t csPortClr; ///< PORT register for chip select CLEAR
|
|
|
+ PORTreg_t dcPortSet; ///< PORT register for data/command SET
|
|
|
+ PORTreg_t dcPortClr; ///< PORT register for data/command CLEAR
|
|
|
+#else // !HAS_PORT_SET_CLR
|
|
|
+ PORTreg_t csPort; ///< PORT register for chip select
|
|
|
+ PORTreg_t dcPort; ///< PORT register for data/command
|
|
|
+#endif // end HAS_PORT_SET_CLR
|
|
|
+#endif // end USE_FAST_PINIO
|
|
|
+ union {
|
|
|
+ struct { // Values specific to HARDWARE SPI:
|
|
|
+ SPIClass *_spi; ///< SPI class pointer
|
|
|
+ uint32_t _freq;
|
|
|
+ SPISettings settings;
|
|
|
+ } hwspi;
|
|
|
+ struct { // Values specific to SOFTWARE SPI:
|
|
|
+#if defined(USE_FAST_PINIO)
|
|
|
+ PORTreg_t misoPort; ///< PORT (PIN) register for MISO
|
|
|
+#if defined(HAS_PORT_SET_CLR)
|
|
|
+ PORTreg_t mosiPortSet; ///< PORT register for MOSI SET
|
|
|
+ PORTreg_t mosiPortClr; ///< PORT register for MOSI CLEAR
|
|
|
+ PORTreg_t sckPortSet; ///< PORT register for SCK SET
|
|
|
+ PORTreg_t sckPortClr; ///< PORT register for SCK CLEAR
|
|
|
+ #if !defined(KINETISK)
|
|
|
+ PORT_t mosiPinMask; ///< Bitmask for MOSI
|
|
|
+ PORT_t sckPinMask; ///< Bitmask for SCK
|
|
|
+ #endif // end !KINETISK
|
|
|
+#else // !HAS_PORT_SET_CLR
|
|
|
+ PORTreg_t mosiPort; ///< PORT register for MOSI
|
|
|
+ PORTreg_t sckPort; ///< PORT register for SCK
|
|
|
+ PORT_t mosiPinMaskSet; ///< Bitmask for MOSI SET (OR)
|
|
|
+ PORT_t mosiPinMaskClr; ///< Bitmask for MOSI CLEAR (AND)
|
|
|
+ PORT_t sckPinMaskSet; ///< Bitmask for SCK SET (OR bitmask)
|
|
|
+ PORT_t sckPinMaskClr; ///< Bitmask for SCK CLEAR (AND)
|
|
|
+#endif // end HAS_PORT_SET_CLR
|
|
|
+ #if !defined(KINETISK)
|
|
|
+ PORT_t misoPinMask; ///< Bitmask for MISO
|
|
|
+ #endif // end !KINETISK
|
|
|
+#endif // end USE_FAST_PINIO
|
|
|
+ int8_t _mosi; ///< MOSI pin #
|
|
|
+ int8_t _miso; ///< MISO pin #
|
|
|
+ int8_t _sck; ///< SCK pin #
|
|
|
+ } swspi;
|
|
|
+ struct { // Values specific to 8-bit parallel:
|
|
|
+#if defined(USE_FAST_PINIO)
|
|
|
+ volatile uint8_t *writePort; ///< PORT register for DATA WRITE
|
|
|
+ volatile uint8_t *readPort; ///< PORT (PIN) register for DATA READ
|
|
|
+#if defined(HAS_PORT_SET_CLR)
|
|
|
+ // Port direction register pointers are always 8-bit regardless of
|
|
|
+ // PORTreg_t -- even if 32-bit port, we modify a byte-aligned 8 bits.
|
|
|
+ volatile uint8_t *dirSet; ///< PORT byte data direction SET
|
|
|
+ volatile uint8_t *dirClr; ///< PORT byte data direction CLEAR
|
|
|
+ PORTreg_t wrPortSet; ///< PORT register for write strobe SET
|
|
|
+ PORTreg_t wrPortClr; ///< PORT register for write strobe CLEAR
|
|
|
+ PORTreg_t rdPortSet; ///< PORT register for read strobe SET
|
|
|
+ PORTreg_t rdPortClr; ///< PORT register for read strobe CLEAR
|
|
|
+ #if !defined(KINETISK)
|
|
|
+ PORT_t wrPinMask; ///< Bitmask for write strobe
|
|
|
+ #endif // end !KINETISK
|
|
|
+ PORT_t rdPinMask; ///< Bitmask for read strobe
|
|
|
+#else // !HAS_PORT_SET_CLR
|
|
|
+ // Port direction register pointer is always 8-bit regardless of
|
|
|
+ // PORTreg_t -- even if 32-bit port, we modify a byte-aligned 8 bits.
|
|
|
+ volatile uint8_t *portDir; ///< PORT direction register
|
|
|
+ PORTreg_t wrPort; ///< PORT register for write strobe
|
|
|
+ PORTreg_t rdPort; ///< PORT register for read strobe
|
|
|
+ PORT_t wrPinMaskSet; ///< Bitmask for write strobe SET (OR)
|
|
|
+ PORT_t wrPinMaskClr; ///< Bitmask for write strobe CLEAR (AND)
|
|
|
+ PORT_t rdPinMaskSet; ///< Bitmask for read strobe SET (OR)
|
|
|
+ PORT_t rdPinMaskClr; ///< Bitmask for read strobe CLEAR (AND)
|
|
|
+#endif // end HAS_PORT_SET_CLR
|
|
|
+#endif // end USE_FAST_PINIO
|
|
|
+ int8_t _d0; ///< Data pin 0 #
|
|
|
+ int8_t _wr; ///< Write strobe pin #
|
|
|
+ int8_t _rd; ///< Read strobe pin # (or -1)
|
|
|
+ bool wide = 0; ///< If true, is 16-bit interface
|
|
|
+ } tft8;
|
|
|
+ };
|
|
|
+#if defined(USE_SPI_DMA) // Used by hardware SPI and tft8
|
|
|
+ Adafruit_ZeroDMA dma; ///< DMA instance
|
|
|
+ DmacDescriptor *dptr = NULL; ///< 1st descriptor
|
|
|
+ DmacDescriptor *descriptor = NULL; ///< Allocated descriptor list
|
|
|
+ uint16_t *pixelBuf[2]; ///< Working buffers
|
|
|
+ uint16_t maxFillLen; ///< Max pixels per DMA xfer
|
|
|
+ uint16_t lastFillColor = 0; ///< Last color used w/fill
|
|
|
+ uint32_t lastFillLen = 0; ///< # of pixels w/last fill
|
|
|
+ uint8_t onePixelBuf; ///< For hi==lo fill
|
|
|
#endif
|
|
|
-};
|
|
|
+#if defined(USE_FAST_PINIO)
|
|
|
+#if defined(HAS_PORT_SET_CLR)
|
|
|
+ PORT_t csPinMask; ///< Bitmask for chip select
|
|
|
+ #if !defined(KINETISK)
|
|
|
+ PORT_t dcPinMask; ///< Bitmask for data/command
|
|
|
+ #endif // end !KINETISK
|
|
|
+#else // !HAS_PORT_SET_CLR
|
|
|
+ PORT_t csPinMaskSet; ///< Bitmask for chip select SET (OR)
|
|
|
+ PORT_t csPinMaskClr; ///< Bitmask for chip select CLEAR (AND)
|
|
|
+ PORT_t dcPinMaskSet; ///< Bitmask for data/command SET (OR)
|
|
|
+ PORT_t dcPinMaskClr; ///< Bitmask for data/command CLEAR (AND)
|
|
|
+#endif // end HAS_PORT_SET_CLR
|
|
|
+#endif // end USE_FAST_PINIO
|
|
|
+ uint8_t connection; ///< TFT_HARD_SPI, TFT_SOFT_SPI, etc.
|
|
|
+ int8_t _rst; ///< Reset pin # (or -1)
|
|
|
+ int8_t _cs; ///< Chip select pin # (or -1)
|
|
|
+ int8_t _dc; ///< Data/command pin #
|
|
|
|
|
|
-#endif // !__AVR_ATtiny85__
|
|
|
+ int16_t _xstart = 0; ///< Internal framebuffer X offset
|
|
|
+ int16_t _ystart = 0; ///< Internal framebuffer Y offset
|
|
|
+ uint8_t invertOnCommand = 0; ///< Command to enable invert mode
|
|
|
+ uint8_t invertOffCommand = 0; ///< Command to disable invert mode
|
|
|
+
|
|
|
+ uint32_t _freq = 0; ///< Dummy var to keep subclasses happy
|
|
|
+};
|
|
|
|
|
|
-#endif // !_ADAFRUIT_SPITFT_
|
|
|
+#endif // end __AVR_ATtiny85__
|
|
|
+#endif // end _ADAFRUIT_SPITFT_H_
|