mirror of
https://github.com/adafruit/Adafruit-GFX-Library.git
synced 2024-10-03 18:18:46 -04:00
WIP do not use yet!
This commit is contained in:
parent
7855b62aae
commit
6b5e177fb1
1778
Adafruit_SPITFT.cpp
1778
Adafruit_SPITFT.cpp
File diff suppressed because it is too large
Load Diff
@ -1,143 +1,431 @@
|
|||||||
#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 <SPI.h>
|
||||||
#include "Adafruit_GFX.h"
|
#include "Adafruit_GFX.h"
|
||||||
|
|
||||||
#define USE_FAST_PINIO ///< If set, use PORT access instead of digitalWrite()
|
// 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
|
//#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>
|
// If DMA is enabled, Arduino sketch MUST #include <Adafruit_ZeroDMA.h>
|
||||||
// Estimated RAM usage:
|
// Estimated RAM usage:
|
||||||
// 4 bytes/pixel on display major axis + 8 bytes/pixel on minor axis,
|
// 4 bytes/pixel on display major axis + 8 bytes/pixel on minor axis,
|
||||||
// e.g. 320x240 pixels = 320 * 4 + 240 * 8 = 3,200 bytes.
|
// e.g. 320x240 pixels = 320 * 4 + 240 * 8 = 3,200 bytes.
|
||||||
|
|
||||||
#if !defined(ARDUINO_ARCH_SAMD)
|
#if !defined(ARDUINO_ARCH_SAMD)
|
||||||
#undef USE_SPI_DMA ///< Only for SAMD chips
|
#undef USE_SPI_DMA ///< DMA currently for SAMD chips only
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
#ifdef USE_SPI_DMA
|
#if defined(USE_SPI_DMA)
|
||||||
#pragma message ("SPI DMA IS ENABLED. HIGHLY EXPERIMENTAL.")
|
#pragma message ("GFX DMA IS ENABLED. HIGHLY EXPERIMENTAL.")
|
||||||
#include <Adafruit_ZeroDMA.h>
|
#include <Adafruit_ZeroDMA.h>
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
#if defined(__AVR__)
|
// CLASS DEFINITION --------------------------------------------------------
|
||||||
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"
|
/*!
|
||||||
|
@brief Adafruit_SPITFT is an intermediary class between Adafruit_GFX
|
||||||
/// 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.
|
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 {
|
class Adafruit_SPITFT : public Adafruit_GFX {
|
||||||
|
|
||||||
public:
|
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);
|
// CONSTRUCTORS --------------------------------------------------------
|
||||||
|
|
||||||
// Required Non-Transaction
|
// Software SPI constructor: expects width & height (at default rotation
|
||||||
void drawPixel(int16_t x, int16_t y, uint16_t color);
|
// 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);
|
||||||
|
|
||||||
// Transaction API
|
// 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:
|
||||||
|
|
||||||
|
/*!
|
||||||
|
@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);
|
void startWrite(void);
|
||||||
|
// Chip deselect and/or hardware SPI transaction end as needed:
|
||||||
void endWrite(void);
|
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 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 writePixels(uint16_t *colors, uint32_t len);
|
||||||
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 writeColor(uint16_t color, uint32_t len);
|
||||||
void pushColor(uint16_t color);
|
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);
|
||||||
|
|
||||||
// Recommended Non-Transaction
|
// These functions are similar to the 'write' functions above, but with
|
||||||
void drawFastVLine(int16_t x, int16_t y, int16_t h, uint16_t color);
|
// a chip-select and/or SPI transaction built-in. They're typically used
|
||||||
void drawFastHLine(int16_t x, int16_t y, int16_t w, uint16_t color);
|
// solo -- that is, as graphics primitives in themselves, not invoked by
|
||||||
void fillRect(int16_t x, int16_t y, int16_t w, int16_t h, uint16_t color);
|
// 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
|
using Adafruit_GFX::drawRGBBitmap; // Check base class first
|
||||||
void drawRGBBitmap(int16_t x, int16_t y,
|
void drawRGBBitmap(int16_t x, int16_t y,
|
||||||
uint16_t *pcolors, int16_t w, int16_t h);
|
uint16_t *pcolors, int16_t w, int16_t h);
|
||||||
void invertDisplay(boolean i);
|
|
||||||
|
|
||||||
|
void invertDisplay(bool i);
|
||||||
uint16_t color565(uint8_t r, uint8_t g, uint8_t b);
|
uint16_t color565(uint8_t r, uint8_t g, uint8_t b);
|
||||||
void writeCommand(uint8_t cmd);
|
|
||||||
void spiWrite(uint8_t v);
|
// Despite parallel additions, function names kept for compatibility:
|
||||||
uint8_t spiRead(void);
|
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:
|
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
|
|
||||||
|
|
||||||
#ifdef USE_FAST_PINIO
|
// A few more low-level member functions -- some may have previously
|
||||||
volatile RwReg *mosiport, ///< Direct chip register for toggling MOSI with fast bitbang IO
|
// been macros. Shouldn't have a need to access these externally, so
|
||||||
*misoport, ///< Direct chip register for toggling MISO with fast bitbang IO
|
// they've been moved to the protected section. Additionally, they're
|
||||||
*clkport, ///< Direct chip register for toggling CLK with fast bitbang IO
|
// declared inline here and the code is in the .cpp file, since outside
|
||||||
*dcport, ///< Direct chip register for toggling DC with fast bitbang IO
|
// code doesn't need to see these.
|
||||||
*csport; ///< Direct chip register for toggling CS with fast bitbang IO
|
inline void SPI_MOSI_HIGH(void);
|
||||||
RwReg mosipinmask, ///< bitmask for turning on/off MOSI with fast register bitbang IO
|
inline void SPI_MOSI_LOW(void);
|
||||||
misopinmask, ///< bitmask for turning on/off MISO with fast register bitbang IO
|
inline void SPI_SCK_HIGH(void);
|
||||||
clkpinmask, ///< bitmask for turning on/off CLK with fast register bitbang IO
|
inline void SPI_SCK_LOW(void);
|
||||||
cspinmask, ///< bitmask for turning on/off CS with fast register bitbang IO
|
inline bool SPI_MISO_READ(void);
|
||||||
dcpinmask; ///< bitmask for turning on/off DC with fast register bitbang IO
|
inline void SPI_BEGIN_TRANSACTION(void);
|
||||||
#endif
|
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
|
||||||
|
|
||||||
uint8_t invertOnCommand = 0, ///< SPI command byte to turn on invert
|
// CLASS INSTANCE VARIABLES --------------------------------------------
|
||||||
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
|
// 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
|
Adafruit_ZeroDMA dma; ///< DMA instance
|
||||||
DmacDescriptor *dptr = NULL; ///< 1st descriptor
|
DmacDescriptor *dptr = NULL; ///< 1st descriptor
|
||||||
DmacDescriptor *descriptor = NULL; ///< Allocated descriptor list
|
DmacDescriptor *descriptor = NULL; ///< Allocated descriptor list
|
||||||
@ -147,8 +435,31 @@ class Adafruit_SPITFT : public Adafruit_GFX {
|
|||||||
uint32_t lastFillLen = 0; ///< # of pixels w/last fill
|
uint32_t lastFillLen = 0; ///< # of pixels w/last fill
|
||||||
uint8_t onePixelBuf; ///< For hi==lo fill
|
uint8_t onePixelBuf; ///< For hi==lo fill
|
||||||
#endif
|
#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 #
|
||||||
|
|
||||||
|
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 // !__AVR_ATtiny85__
|
#endif // end __AVR_ATtiny85__
|
||||||
|
#endif // end _ADAFRUIT_SPITFT_H_
|
||||||
#endif // !_ADAFRUIT_SPITFT_
|
|
||||||
|
@ -1,116 +1,6 @@
|
|||||||
#ifndef _ADAFRUIT_SPITFT_MACROS
|
// THIS FILE INTENTIONALLY LEFT BLANK.
|
||||||
#define _ADAFRUIT_SPITFT_MACROS
|
|
||||||
|
|
||||||
/*
|
// Macros previously #defined here have been made into (mostly) inline
|
||||||
* Control Pins
|
// functions in the Adafruit_SPITFT class. Other libraries might still
|
||||||
* */
|
// contain code trying to #include this header file, so until everything's
|
||||||
|
// updated this file still exists (but doing nothing) to avoid trouble.
|
||||||
#ifdef USE_FAST_PINIO
|
|
||||||
#define SPI_DC_HIGH() *dcport |= dcpinmask
|
|
||||||
#define SPI_DC_LOW() *dcport &= ~dcpinmask
|
|
||||||
#define SPI_CS_HIGH() *csport |= cspinmask
|
|
||||||
#define SPI_CS_LOW() *csport &= ~cspinmask
|
|
||||||
#else
|
|
||||||
#define SPI_DC_HIGH() digitalWrite(_dc, HIGH)
|
|
||||||
#define SPI_DC_LOW() digitalWrite(_dc, LOW)
|
|
||||||
#define SPI_CS_HIGH() { if(_cs >= 0) digitalWrite(_cs, HIGH); }
|
|
||||||
#define SPI_CS_LOW() { if(_cs >= 0) digitalWrite(_cs, LOW); }
|
|
||||||
#endif
|
|
||||||
|
|
||||||
/*
|
|
||||||
* Software SPI Macros
|
|
||||||
* */
|
|
||||||
|
|
||||||
#ifdef USE_FAST_PINIO
|
|
||||||
#define SSPI_MOSI_HIGH() *mosiport |= mosipinmask
|
|
||||||
#define SSPI_MOSI_LOW() *mosiport &= ~mosipinmask
|
|
||||||
#define SSPI_SCK_HIGH() *clkport |= clkpinmask
|
|
||||||
#define SSPI_SCK_LOW() *clkport &= ~clkpinmask
|
|
||||||
#define SSPI_MISO_READ() ((*misoport & misopinmask) != 0)
|
|
||||||
#else
|
|
||||||
#define SSPI_MOSI_HIGH() digitalWrite(_mosi, HIGH)
|
|
||||||
#define SSPI_MOSI_LOW() digitalWrite(_mosi, LOW)
|
|
||||||
#define SSPI_SCK_HIGH() digitalWrite(_sclk, HIGH)
|
|
||||||
#define SSPI_SCK_LOW() digitalWrite(_sclk, LOW)
|
|
||||||
#define SSPI_MISO_READ() digitalRead(_miso)
|
|
||||||
#endif
|
|
||||||
|
|
||||||
#define SSPI_BEGIN_TRANSACTION()
|
|
||||||
#define SSPI_END_TRANSACTION()
|
|
||||||
#define SSPI_WRITE(v) spiWrite(v)
|
|
||||||
#define SSPI_WRITE16(s) SSPI_WRITE((s) >> 8); SSPI_WRITE(s)
|
|
||||||
#define SSPI_WRITE32(l) SSPI_WRITE((l) >> 24); SSPI_WRITE((l) >> 16); SSPI_WRITE((l) >> 8); SSPI_WRITE(l)
|
|
||||||
#define SSPI_WRITE_PIXELS(c,l) for(uint32_t i=0; i<(l); i+=2){ SSPI_WRITE(((uint8_t*)(c))[i+1]); SSPI_WRITE(((uint8_t*)(c))[i]); }
|
|
||||||
|
|
||||||
/*
|
|
||||||
* Hardware SPI Macros
|
|
||||||
* */
|
|
||||||
|
|
||||||
#if defined (__AVR__) || defined(TEENSYDUINO) || defined(ARDUINO_ARCH_STM32F1)
|
|
||||||
#define HSPI_SET_CLOCK() _spi->setClockDivider(SPI_CLOCK_DIV2);
|
|
||||||
#elif defined (__arm__)
|
|
||||||
#define HSPI_SET_CLOCK() _spi->setClockDivider(11);
|
|
||||||
#elif defined(ESP8266) || defined(ESP32)
|
|
||||||
#define HSPI_SET_CLOCK() _spi->setFrequency(_freq);
|
|
||||||
#elif defined(RASPI)
|
|
||||||
#define HSPI_SET_CLOCK() _spi->setClock(_freq);
|
|
||||||
#elif defined(ARDUINO_ARCH_STM32F1)
|
|
||||||
#define HSPI_SET_CLOCK() _spi->setClock(_freq);
|
|
||||||
#else
|
|
||||||
#define HSPI_SET_CLOCK()
|
|
||||||
#endif
|
|
||||||
|
|
||||||
#ifdef SPI_HAS_TRANSACTION
|
|
||||||
#define HSPI_BEGIN_TRANSACTION() _spi->beginTransaction(SPISettings(_freq, MSBFIRST, SPI_MODE0))
|
|
||||||
#define HSPI_END_TRANSACTION() _spi->endTransaction()
|
|
||||||
#else
|
|
||||||
#define HSPI_BEGIN_TRANSACTION() HSPI_SET_CLOCK(); _spi->setBitOrder(MSBFIRST); _spi->setDataMode(SPI_MODE0)
|
|
||||||
#define HSPI_END_TRANSACTION()
|
|
||||||
#endif
|
|
||||||
|
|
||||||
#ifdef ESP32
|
|
||||||
#define SPI_HAS_WRITE_PIXELS
|
|
||||||
#endif
|
|
||||||
#if defined(ESP8266) || defined(ESP32)
|
|
||||||
// Optimized SPI (ESP8266 and ESP32)
|
|
||||||
#define HSPI_READ() _spi->transfer(0)
|
|
||||||
#define HSPI_WRITE(b) _spi->write(b)
|
|
||||||
#define HSPI_WRITE16(s) _spi->write16(s)
|
|
||||||
#define HSPI_WRITE32(l) _spi->write32(l)
|
|
||||||
#ifdef SPI_HAS_WRITE_PIXELS
|
|
||||||
#define SPI_MAX_PIXELS_AT_ONCE 32
|
|
||||||
#define HSPI_WRITE_PIXELS(c,l) _spi->writePixels(c,l)
|
|
||||||
#else
|
|
||||||
#define HSPI_WRITE_PIXELS(c,l) for(uint32_t i=0; i<((l)/2); i++){ SPI_WRITE16(((uint16_t*)(c))[i]); }
|
|
||||||
#endif
|
|
||||||
#else
|
|
||||||
// Standard Byte-by-Byte SPI
|
|
||||||
|
|
||||||
#if defined (__AVR__) || defined(TEENSYDUINO)
|
|
||||||
static inline uint8_t _avr_spi_read(void) __attribute__((always_inline));
|
|
||||||
static inline uint8_t _avr_spi_read(void) {
|
|
||||||
uint8_t r = 0;
|
|
||||||
SPDR = r;
|
|
||||||
while(!(SPSR & _BV(SPIF)));
|
|
||||||
r = SPDR;
|
|
||||||
return r;
|
|
||||||
}
|
|
||||||
#define HSPI_WRITE(b) {SPDR = (b); while(!(SPSR & _BV(SPIF)));}
|
|
||||||
#define HSPI_READ() _avr_spi_read()
|
|
||||||
#else
|
|
||||||
#define HSPI_WRITE(b) _spi->transfer((uint8_t)(b))
|
|
||||||
#define HSPI_READ() HSPI_WRITE(0)
|
|
||||||
#endif
|
|
||||||
#define HSPI_WRITE16(s) HSPI_WRITE((s) >> 8); HSPI_WRITE(s)
|
|
||||||
#define HSPI_WRITE32(l) HSPI_WRITE((l) >> 24); HSPI_WRITE((l) >> 16); HSPI_WRITE((l) >> 8); HSPI_WRITE(l)
|
|
||||||
#define HSPI_WRITE_PIXELS(c,l) for(uint32_t i=0; i<(l); i+=2){ HSPI_WRITE(((uint8_t*)(c))[i+1]); HSPI_WRITE(((uint8_t*)(c))[i]); }
|
|
||||||
#endif
|
|
||||||
|
|
||||||
#define SPI_BEGIN() if(_sclk < 0){_spi->begin();}
|
|
||||||
#define SPI_BEGIN_TRANSACTION() if(_sclk < 0){HSPI_BEGIN_TRANSACTION();}
|
|
||||||
#define SPI_END_TRANSACTION() if(_sclk < 0){HSPI_END_TRANSACTION();}
|
|
||||||
#define SPI_WRITE16(s) if(_sclk < 0){HSPI_WRITE16(s);}else{SSPI_WRITE16(s);}
|
|
||||||
#define SPI_WRITE32(l) if(_sclk < 0){HSPI_WRITE32(l);}else{SSPI_WRITE32(l);}
|
|
||||||
#define SPI_WRITE_PIXELS(c,l) if(_sclk < 0){HSPI_WRITE_PIXELS(c,l);}else{SSPI_WRITE_PIXELS(c,l);}
|
|
||||||
|
|
||||||
#endif // _ADAFRUIT_SPITFT_MACROS
|
|
||||||
|
@ -1,608 +0,0 @@
|
|||||||
/*!
|
|
||||||
* @file Adafruit_TFT8.cpp
|
|
||||||
*
|
|
||||||
* @mainpage Adafruit 8-bit Parallel TFT Displays
|
|
||||||
*
|
|
||||||
* @section intro_sec Introduction
|
|
||||||
* This is our library for TFT Displays using an 8-bit parallel interface
|
|
||||||
* with address windows and 16 bit color.
|
|
||||||
*
|
|
||||||
* These displays use ip to 13 pins to communicate:
|
|
||||||
* - 8 data lines (required)
|
|
||||||
* - Write strobe (required)
|
|
||||||
* - Command/data (required)
|
|
||||||
* - Chip select (optional, can be tied LOW)
|
|
||||||
* - Read strobe (optional)
|
|
||||||
* - Reset (optional, can connect to MCU reset)
|
|
||||||
*
|
|
||||||
* Adafruit invests time and resources providing this open source code,
|
|
||||||
* please support Adafruit and open-source hardware by purchasing
|
|
||||||
* products from Adafruit!
|
|
||||||
*
|
|
||||||
* Written by Limor Fried/Ladyada for Adafruit Industries.
|
|
||||||
* MIT license, all text above must be included in any redistribution
|
|
||||||
* @section dependencies Dependencies
|
|
||||||
*
|
|
||||||
* This library depends on <a href="https://github.com/adafruit/Adafruit_GFX">
|
|
||||||
* Adafruit_GFX</a> being present on your system. Please make sure you have
|
|
||||||
* installed the latest version before using this library.
|
|
||||||
*
|
|
||||||
* @section author Author
|
|
||||||
*
|
|
||||||
* Written by Limor "ladyada" Fried for Adafruit Industries.
|
|
||||||
*
|
|
||||||
* @section license License
|
|
||||||
*
|
|
||||||
* BSD license, all text here must be included in any redistribution.
|
|
||||||
*
|
|
||||||
*/
|
|
||||||
|
|
||||||
#if !defined(__AVR_ATtiny85__) // Not for ATtiny, at all
|
|
||||||
|
|
||||||
#include "Adafruit_TFT8.h"
|
|
||||||
|
|
||||||
#ifdef PORT_IOBUS
|
|
||||||
// On SAMD21, redefine digitalPinToPort() to use the slightly-faster
|
|
||||||
// PORT_IOBUS rather than PORT (not needed on SAMD51).
|
|
||||||
#undef digitalPinToPort
|
|
||||||
#define digitalPinToPort(P) (&(PORT_IOBUS->Group[g_APinDescription[P].ulPort]))
|
|
||||||
#endif
|
|
||||||
|
|
||||||
#ifdef USE_PORT_DMA
|
|
||||||
#include <Adafruit_ZeroDMA.h>
|
|
||||||
#include <malloc.h> // memalign() function
|
|
||||||
|
|
||||||
// DMA transfer-in-progress indicator and callback
|
|
||||||
static volatile boolean dma_busy = false;
|
|
||||||
static void dma_callback(Adafruit_ZeroDMA *dma) {
|
|
||||||
dma_busy = false;
|
|
||||||
}
|
|
||||||
#endif // USE_PORT_DMA
|
|
||||||
|
|
||||||
#if defined(__AVR__)
|
|
||||||
#define WR_LOW() *wrPort &= wrPinMaskClr;
|
|
||||||
#define WR_HIGH() *wrPort |= wrPinMaskSet;
|
|
||||||
#define DC_LOW() *dcPort &= dcPinMaskClr;
|
|
||||||
#define DC_HIGH() *dcPort |= dcPinMaskSet;
|
|
||||||
#define CS_LOW() if(_cs >= 0) *csPort &= csPinMaskClr;
|
|
||||||
#define CS_HIGH() if(_cs >= 0) *csPort |= csPinMaskSet;
|
|
||||||
#define RD_LOW() *rdPort &= rdPinMaskClr;
|
|
||||||
#define RD_HIGH() *rdPort |= rdPinMaskSet;
|
|
||||||
#define PORT_OUTPUT() *portDir = 0xFF;
|
|
||||||
#define PORT_INPUT() *portDir = 0x00;
|
|
||||||
#else
|
|
||||||
#define WR_LOW() *wrPortClr = wrPinMask;
|
|
||||||
#define WR_HIGH() *wrPortSet = wrPinMask;
|
|
||||||
#define DC_LOW() *dcPortClr = dcPinMask;
|
|
||||||
#define DC_HIGH() *dcPortSet = dcPinMask;
|
|
||||||
#define CS_LOW() if(_cs >= 0) *csPortClr = csPinMask;
|
|
||||||
#define CS_HIGH() if(_cs >= 0) *csPortSet = csPinMask;
|
|
||||||
#define RD_LOW() *rdPortClr = rdPinMask;
|
|
||||||
#define RD_HIGH() *rdPortSet = rdPinMask;
|
|
||||||
#define PORT_OUTPUT() *dirSet = 0xFF;
|
|
||||||
#define PORT_INPUT() *dirClr = 0xFF;
|
|
||||||
#define PORT_OUTPUT16() *(volatile uint16_t *)dirSet = 0xFFFF;
|
|
||||||
#define PORT_INPUT16() *(volatile uint16_t *)dirClr = 0xFFFF;
|
|
||||||
#endif
|
|
||||||
#define WR_STROBE() { WR_LOW(); WR_HIGH(); }
|
|
||||||
|
|
||||||
/*!
|
|
||||||
@brief Instantiate Adafruit TFT8 display driver.
|
|
||||||
@param w Display width in pixels.
|
|
||||||
@param h Display height in pixels.
|
|
||||||
@param D0 Arduino pin # for data bit 0 (1+ are extrapolated).
|
|
||||||
The 8 data bits MUST be contiguous and byte-aligned
|
|
||||||
(word-aligned for 'wide' interface) within the same
|
|
||||||
PORT register (may not correspond to Arduino pin sequence).
|
|
||||||
@param WR Arduino pin # for write strobe.
|
|
||||||
@param DC Arduino pin # for data/command.
|
|
||||||
@param CS Arduino pin # for chip select (-1 if unused, tie CS low).
|
|
||||||
@param RST Arduino pin # for reset (-1 if unused, tie to MCU reset).
|
|
||||||
@param RD Arduino pin # for read strobe (-1 if unused).
|
|
||||||
@param wide If true, use 16-bit wide interface (not on AVR).
|
|
||||||
*/
|
|
||||||
Adafruit_TFT8::Adafruit_TFT8(uint16_t w, uint16_t h,
|
|
||||||
int8_t D0, int8_t WR, int8_t DC, int8_t CS, int8_t RST, int8_t RD,
|
|
||||||
bool wide) : Adafruit_GFX(w, h),
|
|
||||||
_d0(D0), _wr(WR), _dc(DC), _cs(CS), _rst(RST), _rd(RD)
|
|
||||||
{
|
|
||||||
#if defined(__AVR__)
|
|
||||||
if(digitalPinToBitMask(D0) != 1) return; // D0 MUST be port bit 0
|
|
||||||
_d0 = D0; // Save D0 pin to indicate valid alignment
|
|
||||||
wrPort = (PORTreg_t)portOutputRegister(digitalPinToPort(WR));
|
|
||||||
wrPinMaskSet = digitalPinToBitMask(WR);
|
|
||||||
dcPort = (PORTreg_t)portOutputRegister(digitalPinToPort(DC));
|
|
||||||
dcPinMaskSet = digitalPinToBitMask(DC);
|
|
||||||
if(CS >= 0) {
|
|
||||||
csPort = (PORTreg_t)portOutputRegister(digitalPinToPort(CS));
|
|
||||||
csPinMaskSet = digitalPinToBitMask(CS);
|
|
||||||
} else {
|
|
||||||
// No chip-select line defined; might be permanently tied to GND.
|
|
||||||
// Assign a valid GPIO register (though not used for CS), and an
|
|
||||||
// empty pin bitmask...the nonsense bit-twiddling might be faster
|
|
||||||
// than checking _cs and possibly branching.
|
|
||||||
csPort = dcPort;
|
|
||||||
csPinMaskSet = 0;
|
|
||||||
}
|
|
||||||
if(RD >= 0) {
|
|
||||||
rdPort = (PORTreg_t)portOutputRegister(digitalPinToPort(RD));
|
|
||||||
rdPinMaskSet = digitalPinToBitMask(RD);
|
|
||||||
} else {
|
|
||||||
// No read-strobe line defined; similar to CS case above
|
|
||||||
rdPort = dcPort;
|
|
||||||
rdPinMaskSet = 0;
|
|
||||||
}
|
|
||||||
wrPinMaskClr = ~wrPinMaskSet;
|
|
||||||
dcPinMaskClr = ~dcPinMaskSet;
|
|
||||||
csPinMaskClr = ~csPinMaskSet;
|
|
||||||
rdPinMaskClr = ~rdPinMaskSet;
|
|
||||||
writePort = (PORTreg_t)portOutputRegister(digitalPinToPort(D0));
|
|
||||||
readPort = (PORTreg_t)portInputRegister(digitalPinToPort(D0));
|
|
||||||
portDir = (PORTreg_t)portModeRegister(digitalPinToPort(D0));
|
|
||||||
#else
|
|
||||||
// Confirm D0 bit is byte- or word-aligned in PORT...
|
|
||||||
if(g_APinDescription[D0].ulPin & (wide ? 15 : 7)) return;
|
|
||||||
_d0 = D0; // Save D0 pin to indicate valid alignment
|
|
||||||
_wide = wide;
|
|
||||||
wrPinMask = digitalPinToBitMask(WR);
|
|
||||||
wrPortSet = &(PORT->Group[g_APinDescription[WR].ulPort].OUTSET.reg);
|
|
||||||
wrPortClr = &(PORT->Group[g_APinDescription[WR].ulPort].OUTCLR.reg);
|
|
||||||
dcPinMask = digitalPinToBitMask(DC);
|
|
||||||
dcPortSet = &(PORT->Group[g_APinDescription[DC].ulPort].OUTSET.reg);
|
|
||||||
dcPortClr = &(PORT->Group[g_APinDescription[DC].ulPort].OUTCLR.reg);
|
|
||||||
if(CS >= 0) { // If chip-select pin is specified...
|
|
||||||
csPinMask = digitalPinToBitMask(CS);
|
|
||||||
csPortSet = &(PORT->Group[g_APinDescription[CS].ulPort].OUTSET.reg);
|
|
||||||
csPortClr = &(PORT->Group[g_APinDescription[CS].ulPort].OUTCLR.reg);
|
|
||||||
} else {
|
|
||||||
// No chip-select line defined; might be permanently tied to GND.
|
|
||||||
// Assign a valid GPIO register (though not used for CS), and an
|
|
||||||
// empty pin bitmask...the nonsense bit-twiddling might be faster
|
|
||||||
// than checking _cs and possibly branching.
|
|
||||||
csPinMask = 0;
|
|
||||||
csPortSet = dcPortSet;
|
|
||||||
csPortClr = dcPortClr;
|
|
||||||
}
|
|
||||||
if(RD >= 0) { // If read-strobe pin is specified...
|
|
||||||
rdPinMask = digitalPinToBitMask(RD);
|
|
||||||
rdPortSet = &(PORT->Group[g_APinDescription[RD].ulPort].OUTSET.reg);
|
|
||||||
rdPortClr = &(PORT->Group[g_APinDescription[RD].ulPort].OUTCLR.reg);
|
|
||||||
} else {
|
|
||||||
rdPinMask = 0;
|
|
||||||
rdPortSet = dcPortSet;
|
|
||||||
rdPortClr = dcPortClr;
|
|
||||||
}
|
|
||||||
|
|
||||||
// Get pointers to PORT write/read/dir bytes within 32-bit PORT
|
|
||||||
uint8_t dBit = g_APinDescription[_d0].ulPin; // d0 bit # in PORT
|
|
||||||
PortGroup *p = (&(PORT->Group[g_APinDescription[_d0].ulPort]));
|
|
||||||
uint8_t offset = dBit / 8; // d[7:0] byte # within PORT
|
|
||||||
if(wide) offset &= ~1; // d[15:8] byte # within PORT
|
|
||||||
// These are all uint8_t* pointers -- elsewhere they're recast
|
|
||||||
// as necessary if a 'wide' 16-bit interface is in use.
|
|
||||||
writePort = (volatile uint8_t *)&(p->OUT.reg) + offset;
|
|
||||||
readPort = (volatile uint8_t *)&(p->IN.reg) + offset;
|
|
||||||
dirSet = (volatile uint8_t *)&(p->DIRSET.reg) + offset;
|
|
||||||
dirClr = (volatile uint8_t *)&(p->DIRCLR.reg) + offset;
|
|
||||||
#endif
|
|
||||||
}
|
|
||||||
|
|
||||||
/*!
|
|
||||||
@brief Initialiaze hardware interface.
|
|
||||||
*/
|
|
||||||
bool Adafruit_TFT8::init(void) {
|
|
||||||
|
|
||||||
if(_d0 < 0) return false; // Bad alignment in constructor
|
|
||||||
|
|
||||||
// Initialize data pins. We were only passed d0, so scan
|
|
||||||
// the pin description list looking for the other pins.
|
|
||||||
// They'll be on the same PORT, and within the next 7 (or 15) bits
|
|
||||||
// (because we need to write to a contiguous PORT byte or word).
|
|
||||||
#if defined(__AVR__)
|
|
||||||
// PORT registers are 8 bits wide, so just need a register match...
|
|
||||||
for(uint8_t i=0; i<NUM_DIGITAL_PINS; i++) {
|
|
||||||
if((PORTreg_t)portOutputRegister(digitalPinToPort(i)) == writePort) {
|
|
||||||
pinMode(i, OUTPUT);
|
|
||||||
digitalWrite(i, LOW);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
#else
|
|
||||||
uint8_t portNum = g_APinDescription[_d0].ulPort, // d0 PORT #
|
|
||||||
dBit = g_APinDescription[_d0].ulPin, // d0 bit # in PORT
|
|
||||||
lastBit = dBit + (_wide ? 15 : 7);
|
|
||||||
for(uint8_t i=0; i<PINS_COUNT; i++) {
|
|
||||||
if((g_APinDescription[i].ulPort == portNum ) &&
|
|
||||||
(g_APinDescription[i].ulPin >= dBit ) &&
|
|
||||||
(g_APinDescription[i].ulPin <= (uint32_t)lastBit)) {
|
|
||||||
pinMode(i, OUTPUT);
|
|
||||||
digitalWrite(i, LOW);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
#endif
|
|
||||||
|
|
||||||
// Initialize control signal pins, all active LOW
|
|
||||||
pinMode(_wr, OUTPUT);
|
|
||||||
digitalWrite(_wr, HIGH);
|
|
||||||
pinMode(_dc, OUTPUT);
|
|
||||||
digitalWrite(_dc, HIGH);
|
|
||||||
if(_cs >= 0) {
|
|
||||||
pinMode(_cs, OUTPUT);
|
|
||||||
digitalWrite(_cs, HIGH); // Deselect
|
|
||||||
}
|
|
||||||
if(_rd >= 0) {
|
|
||||||
pinMode(_rd, OUTPUT);
|
|
||||||
digitalWrite(_rd, HIGH);
|
|
||||||
}
|
|
||||||
if(_rst >= 0) {
|
|
||||||
pinMode(_rst, OUTPUT);
|
|
||||||
digitalWrite(_rst, HIGH);
|
|
||||||
delay(100);
|
|
||||||
digitalWrite(_rst, LOW); // Toggle RST low to reset
|
|
||||||
delay(100);
|
|
||||||
digitalWrite(_rst, HIGH);
|
|
||||||
delay(200);
|
|
||||||
}
|
|
||||||
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
|
|
||||||
/*!
|
|
||||||
@brief Initiate write (or read!) operation.
|
|
||||||
*/
|
|
||||||
inline void Adafruit_TFT8::startWrite(void) {
|
|
||||||
CS_LOW(); // Chip select LOW
|
|
||||||
}
|
|
||||||
|
|
||||||
/*!
|
|
||||||
@brief End write (or read!) operation.
|
|
||||||
*/
|
|
||||||
inline void Adafruit_TFT8::endWrite(void) {
|
|
||||||
CS_HIGH(); // Chip select HIGH
|
|
||||||
}
|
|
||||||
|
|
||||||
/*!
|
|
||||||
@brief Write one byte to hardware interface.
|
|
||||||
@param b One byte to send, MSB order
|
|
||||||
*/
|
|
||||||
void Adafruit_TFT8::write8(uint8_t b) {
|
|
||||||
#if defined(__AVR__)
|
|
||||||
*writePort = b;
|
|
||||||
#else
|
|
||||||
if(!_wide) {
|
|
||||||
*writePort = b;
|
|
||||||
} else {
|
|
||||||
*(volatile uint16_t *)writePort = b;
|
|
||||||
}
|
|
||||||
#endif
|
|
||||||
WR_STROBE(); // Write strobe LOW, HIGH
|
|
||||||
}
|
|
||||||
|
|
||||||
/*!
|
|
||||||
@brief Write one word to hardware interface.
|
|
||||||
@param w One word to send, MSB order
|
|
||||||
*/
|
|
||||||
void Adafruit_TFT8::write16(uint16_t w) {
|
|
||||||
#if defined(__AVR__)
|
|
||||||
*writePort = w >> 8; // MSB
|
|
||||||
WR_STROBE(); // Write strobe LOW, HIGH
|
|
||||||
*writePort = w; // LSB
|
|
||||||
WR_STROBE(); // Write strobe LOW, HIGH
|
|
||||||
#else
|
|
||||||
if(!_wide) {
|
|
||||||
*writePort = w >> 8; // MSB
|
|
||||||
WR_STROBE(); // Write strobe LOW, HIGH
|
|
||||||
*writePort = w; // LSB
|
|
||||||
} else {
|
|
||||||
*(volatile uint16_t *)writePort = w;
|
|
||||||
}
|
|
||||||
WR_STROBE(); // Write strobe LOW, HIGH
|
|
||||||
#endif
|
|
||||||
}
|
|
||||||
|
|
||||||
/*!
|
|
||||||
@brief Write a command byte.
|
|
||||||
@param cmd The 8-bit command to send.
|
|
||||||
*/
|
|
||||||
void Adafruit_TFT8::writeCommand(uint8_t cmd) {
|
|
||||||
DC_LOW(); // Data/Command LOW (command mode)
|
|
||||||
write8(cmd); // Issue value
|
|
||||||
DC_HIGH(); // Data/Command HIGH (data mode)
|
|
||||||
}
|
|
||||||
|
|
||||||
/*!
|
|
||||||
@brief Read one byte or word from TFT interface.
|
|
||||||
@returns One byte or word, native order.
|
|
||||||
*/
|
|
||||||
uint16_t Adafruit_TFT8::read(void) {
|
|
||||||
uint16_t r = 0;
|
|
||||||
if(_rd >= 0) {
|
|
||||||
#if defined(__AVR__)
|
|
||||||
PORT_INPUT(); // Set port to INPUT
|
|
||||||
RD_LOW(); // Read strobe LOW
|
|
||||||
r = *readPort; // Read value from port
|
|
||||||
RD_HIGH(); // Read strobe HIGH
|
|
||||||
PORT_OUTPUT(); // Set port back to OUTPUT
|
|
||||||
#else
|
|
||||||
if(!_wide) {
|
|
||||||
PORT_INPUT(); // Set port to INPUT
|
|
||||||
RD_LOW(); // Read strobe LOW
|
|
||||||
r = *readPort; // Read value from port
|
|
||||||
RD_HIGH(); // Read strobe HIGH
|
|
||||||
PORT_OUTPUT(); // Set port back to OUTPUT
|
|
||||||
} else {
|
|
||||||
PORT_INPUT16(); // Set port to INPUT (16-bit)
|
|
||||||
RD_LOW(); // Read strobe LOW
|
|
||||||
r = *(volatile uint16_t *)readPort; // Read value from port
|
|
||||||
RD_HIGH(); // Read strobe HIGH
|
|
||||||
PORT_OUTPUT16(); // Set port back to OUTPUT (16-bit)
|
|
||||||
}
|
|
||||||
#endif
|
|
||||||
}
|
|
||||||
return r;
|
|
||||||
}
|
|
||||||
|
|
||||||
/*!
|
|
||||||
@brief Draw a single pixel.
|
|
||||||
@param x X coordinate.
|
|
||||||
@param y Y coordinate.
|
|
||||||
@param color 16-bit 5-6-5 pixel color.
|
|
||||||
*/
|
|
||||||
void Adafruit_TFT8::drawPixel(int16_t x, int16_t y, uint16_t color) {
|
|
||||||
// Clip first...
|
|
||||||
if((x >= 0) && (x < _width) && (y >= 0) && (y < _height)) {
|
|
||||||
// THEN device-select and draw...
|
|
||||||
startWrite();
|
|
||||||
setAddrWindow(x, y, 1, 1);
|
|
||||||
writePixel(color);
|
|
||||||
endWrite();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
/*!
|
|
||||||
@brief Converts 8-bit (each) R,G,B color to 16-bit packed 5-6-5 value.
|
|
||||||
@param red Red level, 0 to 255
|
|
||||||
@param green Green level, 0 to 255
|
|
||||||
@param blue Blue level, 0 to 255
|
|
||||||
@return Unsigned 16-bit decimated color in "5-6-5" format
|
|
||||||
*/
|
|
||||||
uint16_t Adafruit_TFT8::color565(uint8_t red, uint8_t green, uint8_t blue) {
|
|
||||||
return ((red & 0xF8) << 8) | ((green & 0xFC) << 3) | (blue >> 3);
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
#if 0
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
/*!
|
|
||||||
@brief Issue multiple 2-byte colors.
|
|
||||||
@param colors Array of 16-bit 5-6-5 Colors to draw.
|
|
||||||
@param len How many pixels to draw.
|
|
||||||
*/
|
|
||||||
void Adafruit_TFT8::writePixels(uint16_t *colors, uint32_t len) {
|
|
||||||
SPI_WRITE_PIXELS((uint8_t*)colors , len * 2);
|
|
||||||
}
|
|
||||||
|
|
||||||
/*!
|
|
||||||
@brief Issue a 2-byte color many times.
|
|
||||||
@param color The 16-bit 5-6-5 Color to draw.
|
|
||||||
@param len How many pixels to draw.
|
|
||||||
*/
|
|
||||||
void Adafruit_TFT8::writeColor(uint16_t color, uint32_t len) {
|
|
||||||
|
|
||||||
if(!len) return; // Avoid 0-byte transfers
|
|
||||||
|
|
||||||
uint8_t hi = color >> 8, lo = color;
|
|
||||||
|
|
||||||
if(hi != lo) {
|
|
||||||
} else {
|
|
||||||
len *= 2;
|
|
||||||
// Issue as bytes
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
/**************************************************************************/
|
|
||||||
/*!
|
|
||||||
@brief Write a pixel (must have a transaction in progress)
|
|
||||||
@param x x coordinate
|
|
||||||
@param y y coordinate
|
|
||||||
@param color 16-bit 5-6-5 Color to draw with
|
|
||||||
*/
|
|
||||||
/**************************************************************************/
|
|
||||||
void Adafruit_SPITFT::writePixel(int16_t x, int16_t y, uint16_t color) {
|
|
||||||
if((x < 0) ||(x >= _width) || (y < 0) || (y >= _height)) return;
|
|
||||||
setAddrWindow(x,y,1,1);
|
|
||||||
writePixel(color);
|
|
||||||
}
|
|
||||||
|
|
||||||
/**************************************************************************/
|
|
||||||
/*!
|
|
||||||
@brief Write a filled rectangle (must have a transaction in progress)
|
|
||||||
@param x Top left corner x coordinate
|
|
||||||
@param y Top left corner y coordinate
|
|
||||||
@param w Width in pixels
|
|
||||||
@param h Height in pixels
|
|
||||||
@param color 16-bit 5-6-5 Color to fill with
|
|
||||||
*/
|
|
||||||
/**************************************************************************/
|
|
||||||
void Adafruit_SPITFT::writeFillRect(int16_t x, int16_t y, int16_t w, int16_t h, uint16_t color){
|
|
||||||
if((x >= _width) || (y >= _height)) return;
|
|
||||||
int16_t x2 = x + w - 1, y2 = y + h - 1;
|
|
||||||
if((x2 < 0) || (y2 < 0)) return;
|
|
||||||
|
|
||||||
// Clip left/top
|
|
||||||
if(x < 0) {
|
|
||||||
x = 0;
|
|
||||||
w = x2 + 1;
|
|
||||||
}
|
|
||||||
if(y < 0) {
|
|
||||||
y = 0;
|
|
||||||
h = y2 + 1;
|
|
||||||
}
|
|
||||||
|
|
||||||
// Clip right/bottom
|
|
||||||
if(x2 >= _width) w = _width - x;
|
|
||||||
if(y2 >= _height) h = _height - y;
|
|
||||||
|
|
||||||
setAddrWindow(x, y, w, h);
|
|
||||||
writeColor(color, (int32_t)w * h);
|
|
||||||
}
|
|
||||||
|
|
||||||
/**************************************************************************/
|
|
||||||
/*!
|
|
||||||
@brief Write a perfectly vertical line (must have a transaction in progress)
|
|
||||||
@param x Top-most x coordinate
|
|
||||||
@param y Top-most y coordinate
|
|
||||||
@param h Height in pixels
|
|
||||||
@param color 16-bit 5-6-5 Color to fill with
|
|
||||||
*/
|
|
||||||
/**************************************************************************/
|
|
||||||
void inline Adafruit_SPITFT::writeFastVLine(int16_t x, int16_t y, int16_t h, uint16_t color){
|
|
||||||
writeFillRect(x, y, 1, h, color);
|
|
||||||
}
|
|
||||||
|
|
||||||
/**************************************************************************/
|
|
||||||
/*!
|
|
||||||
@brief Write a perfectly horizontal line (must have a transaction in progress)
|
|
||||||
@param x Left-most x coordinate
|
|
||||||
@param y Left-most y coordinate
|
|
||||||
@param w Width in pixels
|
|
||||||
@param color 16-bit 5-6-5 Color to fill with
|
|
||||||
*/
|
|
||||||
/**************************************************************************/
|
|
||||||
void inline Adafruit_SPITFT::writeFastHLine(int16_t x, int16_t y, int16_t w, uint16_t color){
|
|
||||||
writeFillRect(x, y, w, 1, color);
|
|
||||||
}
|
|
||||||
|
|
||||||
/**************************************************************************/
|
|
||||||
/*!
|
|
||||||
@brief Write a perfectly vertical line - sets up transaction
|
|
||||||
@param x Top-most x coordinate
|
|
||||||
@param y Top-most y coordinate
|
|
||||||
@param h Height in pixels
|
|
||||||
@param color 16-bit 5-6-5 Color to fill with
|
|
||||||
*/
|
|
||||||
/**************************************************************************/
|
|
||||||
void Adafruit_SPITFT::drawFastVLine(int16_t x, int16_t y,
|
|
||||||
int16_t h, uint16_t color) {
|
|
||||||
startWrite();
|
|
||||||
writeFastVLine(x, y, h, color);
|
|
||||||
endWrite();
|
|
||||||
}
|
|
||||||
|
|
||||||
/**************************************************************************/
|
|
||||||
/*!
|
|
||||||
@brief Write a perfectly horizontal line - sets up transaction
|
|
||||||
@param x Left-most x coordinate
|
|
||||||
@param y Left-most y coordinate
|
|
||||||
@param w Width in pixels
|
|
||||||
@param color 16-bit 5-6-5 Color to fill with
|
|
||||||
*/
|
|
||||||
/**************************************************************************/
|
|
||||||
void Adafruit_SPITFT::drawFastHLine(int16_t x, int16_t y,
|
|
||||||
int16_t w, uint16_t color) {
|
|
||||||
startWrite();
|
|
||||||
writeFastHLine(x, y, w, color);
|
|
||||||
endWrite();
|
|
||||||
}
|
|
||||||
|
|
||||||
/**************************************************************************/
|
|
||||||
/*!
|
|
||||||
@brief Fill a rectangle completely with one color.
|
|
||||||
@param x Top left corner x coordinate
|
|
||||||
@param y Top left corner y coordinate
|
|
||||||
@param w Width in pixels
|
|
||||||
@param h Height in pixels
|
|
||||||
@param color 16-bit 5-6-5 Color to fill with
|
|
||||||
*/
|
|
||||||
/**************************************************************************/
|
|
||||||
void Adafruit_SPITFT::fillRect(int16_t x, int16_t y, int16_t w, int16_t h,
|
|
||||||
uint16_t color) {
|
|
||||||
startWrite();
|
|
||||||
writeFillRect(x,y,w,h,color);
|
|
||||||
endWrite();
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
/**************************************************************************/
|
|
||||||
/*!
|
|
||||||
@brief Invert the display using built-in hardware command
|
|
||||||
@param i True if you want to invert, false to make 'normal'
|
|
||||||
*/
|
|
||||||
/**************************************************************************/
|
|
||||||
void Adafruit_SPITFT::invertDisplay(boolean i) {
|
|
||||||
startWrite();
|
|
||||||
writeCommand(i ? invertOnCommand : invertOffCommand);
|
|
||||||
endWrite();
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
/**************************************************************************/
|
|
||||||
/*!
|
|
||||||
@brief Draw a 16-bit image (RGB 5/6/5) at the specified (x,y) position.
|
|
||||||
For 16-bit display devices; no color reduction performed.
|
|
||||||
Adapted from https://github.com/PaulStoffregen/ILI9341_t3
|
|
||||||
by Marc MERLIN. See examples/pictureEmbed to use this.
|
|
||||||
5/6/2017: function name and arguments have changed for compatibility
|
|
||||||
with current GFX library and to avoid naming problems in prior
|
|
||||||
implementation. Formerly drawBitmap() with arguments in different order.
|
|
||||||
|
|
||||||
@param x Top left corner x coordinate
|
|
||||||
@param y Top left corner y coordinate
|
|
||||||
@param pcolors 16-bit array with 16-bit color bitmap
|
|
||||||
@param w Width of bitmap in pixels
|
|
||||||
@param h Height of bitmap in pixels
|
|
||||||
*/
|
|
||||||
/**************************************************************************/
|
|
||||||
void Adafruit_SPITFT::drawRGBBitmap(int16_t x, int16_t y,
|
|
||||||
uint16_t *pcolors, int16_t w, int16_t h) {
|
|
||||||
|
|
||||||
int16_t x2, y2; // Lower-right coord
|
|
||||||
if(( x >= _width ) || // Off-edge right
|
|
||||||
( y >= _height) || // " top
|
|
||||||
((x2 = (x+w-1)) < 0 ) || // " left
|
|
||||||
((y2 = (y+h-1)) < 0) ) return; // " bottom
|
|
||||||
|
|
||||||
int16_t bx1=0, by1=0, // Clipped top-left within bitmap
|
|
||||||
saveW=w; // Save original bitmap width value
|
|
||||||
if(x < 0) { // Clip left
|
|
||||||
w += x;
|
|
||||||
bx1 = -x;
|
|
||||||
x = 0;
|
|
||||||
}
|
|
||||||
if(y < 0) { // Clip top
|
|
||||||
h += y;
|
|
||||||
by1 = -y;
|
|
||||||
y = 0;
|
|
||||||
}
|
|
||||||
if(x2 >= _width ) w = _width - x; // Clip right
|
|
||||||
if(y2 >= _height) h = _height - y; // Clip bottom
|
|
||||||
|
|
||||||
pcolors += by1 * saveW + bx1; // Offset bitmap ptr to clipped top-left
|
|
||||||
startWrite();
|
|
||||||
setAddrWindow(x, y, w, h); // Clipped area
|
|
||||||
while(h--) { // For each (clipped) scanline...
|
|
||||||
writePixels(pcolors, w); // Push one (clipped) row
|
|
||||||
pcolors += saveW; // Advance pointer by one full (unclipped) line
|
|
||||||
}
|
|
||||||
endWrite();
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
#endif // 0
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
#endif // !__AVR_ATtiny85__
|
|
||||||
|
|
60
olde/ttt.ttt
Normal file
60
olde/ttt.ttt
Normal file
@ -0,0 +1,60 @@
|
|||||||
|
#define TFT_HARD_SPI 0
|
||||||
|
#define TFT_SOFT_SPI 1
|
||||||
|
#define TFT_PARALLEL 2
|
||||||
|
|
||||||
|
#if defined(USE_FAST_PINIO)
|
||||||
|
#if defined(HAS_PORT_SET_CLR)
|
||||||
|
#define TFT_CS_HIGH() { *csPortSet = csPinMask; }
|
||||||
|
#define TFT_CS_LOW() { *csPortClr = csPinMask; }
|
||||||
|
#define TFT_DC_HIGH() { *dcPortSet = dcPinMask; }
|
||||||
|
#define TFT_DC_LOW() { *dcPortClr = dcPinMask; }
|
||||||
|
#define TFT_MOSI_HIGH() { *mosiPortSet = mosiPinMask; }
|
||||||
|
#define TFT_MOSI_LOW() { *mosiPortClr = mosiPinMask; }
|
||||||
|
#define TFT_SCK_HIGH() { *sckPortSet = sckPinMask; }
|
||||||
|
#define TFT_SCK_LOW() { *sckPortClr = sckPinMask; }
|
||||||
|
#define TFT_WR_HIGH() { *wrPortSet = wrPinMask; }
|
||||||
|
#define TFT_WR_LOW() { *wrPortClr = wrPinMask; }
|
||||||
|
#define TFT_RD_HIGH() { *rdPortSet = rdPinMask; }
|
||||||
|
#define TFT_RD_LOW() { *rdPortClr = rdPinMask; }
|
||||||
|
#define TFT_PORT_OUTPUT() { *dirSet = 0xFF; }
|
||||||
|
#define TFT_PORT_INPUT() { *dirClr = 0xFF; }
|
||||||
|
#define TFT_PORT_OUTPUT16() { *(volatile uint16_t *)dirSet = 0xFFFF; }
|
||||||
|
#define TFT_PORT_INPUT16() { *(volatile uint16_t *)dirClr = 0xFFFF; }
|
||||||
|
#else // !HAS_PORT_SET_CLR
|
||||||
|
#define TFT_CS_HIGH() { *csPort |= csPinMaskSet; }
|
||||||
|
#define TFT_CS_LOW() { *csPort &= csPinMaskClr; }
|
||||||
|
#define TFT_DC_HIGH() { *dcPort |= dcPinMaskSet; }
|
||||||
|
#define TFT_DC_LOW() { *dcPort &= dcPinMaskClr; }
|
||||||
|
#define TFT_MOSI_HIGH() { *mosiPort |= mosiPinMaskSet; }
|
||||||
|
#define TFT_MOSI_LOW() { *mosiPort &= mosiPinMaskClr; }
|
||||||
|
#define TFT_SCK_HIGH() { *sckPort |= sckPinMaskSet; }
|
||||||
|
#define TFT_SCK_LOW() { *sckPort &= sckPinMaskClr; }
|
||||||
|
#define TFT_WR_HIGH() { *wrPort |= wrPinMaskSet; }
|
||||||
|
#define TFT_WR_LOW() { *wrPort &= wrPinMaskClr; }
|
||||||
|
#define TFT_RD_HIGH() { *rdPort |= rdPinMaskSet; }
|
||||||
|
#define TFT_RD_LOW() { *rdPort &= rdPinMaskClr; }
|
||||||
|
#define TFT_PORT_OUTPUT() { *portDir = 0xFF; }
|
||||||
|
#define TFT_PORT_INPUT() { *portDir = 0x00; }
|
||||||
|
#define TFT_PORT_OUTPUT16() { *(volatile uint16_t *)portDir = 0xFFFF; }
|
||||||
|
#define TFT_PORT_INPUT16() { *(volatile uint16_t *)portDir = 0x0000; }
|
||||||
|
#endif // end HAS_PORT_SET_CLR
|
||||||
|
#define TFT_SPI_READ() (*misoPort & misoPinMask)
|
||||||
|
#else // !USE_FAST_PINIO
|
||||||
|
#define TFT_CS_HIGH() digitalWrite(_cs , HIGH)
|
||||||
|
#define TFT_CS_LOW() digitalWrite(_cs , LOW )
|
||||||
|
#define TFT_DC_HIGH() digitalWrite(_dc , HIGH)
|
||||||
|
#define TFT_DC_LOW() digitalWrite(_dc , LOW )
|
||||||
|
#define TFT_MOSI_HIGH() digitalWrite(_mosi, HIGH)
|
||||||
|
#define TFT_MOSI_LOW() digitalWrite(_mosi, LOW )
|
||||||
|
#define TFT_SCK_HIGH() digitalWrite(_sck , HIGH)
|
||||||
|
#define TFT_SCK_LOW() digitalWrite(_sck , LOW )
|
||||||
|
#define TFT_WR_HIGH() digitalWrite(_wr , HIGH)
|
||||||
|
#define TFT_WR_LOW() digitalWrite(_wr , LOW )
|
||||||
|
#define TFT_RD_HIGH() digitalWrite(_rd , HIGH)
|
||||||
|
#define TFT_RD_LOW() digitalWrite(_rd , LOW )
|
||||||
|
#define TFT_PORT_OUTPUT() { } // 8-bit parallel is not supported
|
||||||
|
#define TFT_PORT_INPUT() { } // if USE_FAST_PINIO is unavailable.
|
||||||
|
#define TFT_PORT_OUTPUT16() { } // No plans to implement this. If no
|
||||||
|
#define TFT_PORT_INPUT16() { } // PORT access, use an SPI display!
|
||||||
|
#define TFT_SPI_READ() digitalRead(_miso)
|
||||||
|
#endif // end USE_FAST_PINIO
|
Loading…
Reference in New Issue
Block a user