mirror of https://github.com/arendst/Tasmota.git
Add initial display support
Add initial display support for Lcd, Oled, Matrix, Tft and e-paper - Need more docs
This commit is contained in:
parent
4cde6bb463
commit
b12c8d39d5
|
@ -0,0 +1,46 @@
|
||||||
|
Thank you for opening an issue on an Adafruit Arduino library repository. To
|
||||||
|
improve the speed of resolution please review the following guidelines and
|
||||||
|
common troubleshooting steps below before creating the issue:
|
||||||
|
|
||||||
|
- **Do not use GitHub issues for troubleshooting projects and issues.** Instead use
|
||||||
|
the forums at http://forums.adafruit.com to ask questions and troubleshoot why
|
||||||
|
something isn't working as expected. In many cases the problem is a common issue
|
||||||
|
that you will more quickly receive help from the forum community. GitHub issues
|
||||||
|
are meant for known defects in the code. If you don't know if there is a defect
|
||||||
|
in the code then start with troubleshooting on the forum first.
|
||||||
|
|
||||||
|
- **If following a tutorial or guide be sure you didn't miss a step.** Carefully
|
||||||
|
check all of the steps and commands to run have been followed. Consult the
|
||||||
|
forum if you're unsure or have questions about steps in a guide/tutorial.
|
||||||
|
|
||||||
|
- **For Arduino projects check these very common issues to ensure they don't apply**:
|
||||||
|
|
||||||
|
- For uploading sketches or communicating with the board make sure you're using
|
||||||
|
a **USB data cable** and **not** a **USB charge-only cable**. It is sometimes
|
||||||
|
very hard to tell the difference between a data and charge cable! Try using the
|
||||||
|
cable with other devices or swapping to another cable to confirm it is not
|
||||||
|
the problem.
|
||||||
|
|
||||||
|
- **Be sure you are supplying adequate power to the board.** Check the specs of
|
||||||
|
your board and plug in an external power supply. In many cases just
|
||||||
|
plugging a board into your computer is not enough to power it and other
|
||||||
|
peripherals.
|
||||||
|
|
||||||
|
- **Double check all soldering joints and connections.** Flakey connections
|
||||||
|
cause many mysterious problems. See the [guide to excellent soldering](https://learn.adafruit.com/adafruit-guide-excellent-soldering/tools) for examples of good solder joints.
|
||||||
|
|
||||||
|
- **Ensure you are using an official Arduino or Adafruit board.** We can't
|
||||||
|
guarantee a clone board will have the same functionality and work as expected
|
||||||
|
with this code and don't support them.
|
||||||
|
|
||||||
|
If you're sure this issue is a defect in the code and checked the steps above
|
||||||
|
please fill in the following fields to provide enough troubleshooting information.
|
||||||
|
You may delete the guideline and text above to just leave the following details:
|
||||||
|
|
||||||
|
- Arduino board: **INSERT ARDUINO BOARD NAME/TYPE HERE**
|
||||||
|
|
||||||
|
- Arduino IDE version (found in Arduino -> About Arduino menu): **INSERT ARDUINO
|
||||||
|
VERSION HERE**
|
||||||
|
|
||||||
|
- List the steps to reproduce the problem below (if possible attach a sketch or
|
||||||
|
copy the sketch code in too): **LIST REPRO STEPS BELOW**
|
|
@ -0,0 +1,26 @@
|
||||||
|
Thank you for creating a pull request to contribute to Adafruit's GitHub code!
|
||||||
|
Before you open the request please review the following guidelines and tips to
|
||||||
|
help it be more easily integrated:
|
||||||
|
|
||||||
|
- **Describe the scope of your change--i.e. what the change does and what parts
|
||||||
|
of the code were modified.** This will help us understand any risks of integrating
|
||||||
|
the code.
|
||||||
|
|
||||||
|
- **Describe any known limitations with your change.** For example if the change
|
||||||
|
doesn't apply to a supported platform of the library please mention it.
|
||||||
|
|
||||||
|
- **Please run any tests or examples that can exercise your modified code.** We
|
||||||
|
strive to not break users of the code and running tests/examples helps with this
|
||||||
|
process.
|
||||||
|
|
||||||
|
Thank you again for contributing! We will try to test and integrate the change
|
||||||
|
as soon as we can, but be aware we have many GitHub repositories to manage and
|
||||||
|
can't immediately respond to every request. There is no need to bump or check in
|
||||||
|
on a pull request (it will clutter the discussion of the request).
|
||||||
|
|
||||||
|
Also don't be worried if the request is closed or not integrated--sometimes the
|
||||||
|
priorities of Adafruit's GitHub code (education, ease of use) might not match the
|
||||||
|
priorities of the pull request. Don't fret, the open source community thrives on
|
||||||
|
forks and GitHub makes it easy to keep your changes in a forked repo.
|
||||||
|
|
||||||
|
After reviewing the guidelines above you can delete this text from the pull request.
|
|
@ -0,0 +1,695 @@
|
||||||
|
/***************************************************
|
||||||
|
This is our library for the Adafruit ILI9341 Breakout and Shield
|
||||||
|
----> http://www.adafruit.com/products/1651
|
||||||
|
|
||||||
|
Check out the links above for our tutorials and wiring diagrams
|
||||||
|
These displays use SPI to communicate, 4 or 5 pins are required to
|
||||||
|
interface (RST is optional)
|
||||||
|
Adafruit invests time and resources providing this open source code,
|
||||||
|
please support Adafruit and open-source hardware by purchasing
|
||||||
|
products from Adafruit!
|
||||||
|
|
||||||
|
Written by Limor Fried/Ladyada for Adafruit Industries.
|
||||||
|
MIT license, all text above must be included in any redistribution
|
||||||
|
****************************************************/
|
||||||
|
|
||||||
|
#include "Adafruit_ILI9341.h"
|
||||||
|
#ifndef ARDUINO_STM32_FEATHER
|
||||||
|
#include "pins_arduino.h"
|
||||||
|
#ifndef RASPI
|
||||||
|
#include "wiring_private.h"
|
||||||
|
#endif
|
||||||
|
#endif
|
||||||
|
#include <limits.h>
|
||||||
|
|
||||||
|
|
||||||
|
#define MADCTL_MY 0x80
|
||||||
|
#define MADCTL_MX 0x40
|
||||||
|
#define MADCTL_MV 0x20
|
||||||
|
#define MADCTL_ML 0x10
|
||||||
|
#define MADCTL_RGB 0x00
|
||||||
|
#define MADCTL_BGR 0x08
|
||||||
|
#define MADCTL_MH 0x04
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Control Pins
|
||||||
|
* */
|
||||||
|
|
||||||
|
#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() digitalWrite(_cs, HIGH)
|
||||||
|
#define SPI_CS_LOW() 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
|
||||||
|
* */
|
||||||
|
|
||||||
|
#ifndef ESP32
|
||||||
|
#define SPI_OBJECT SPI
|
||||||
|
#else
|
||||||
|
#define SPI_OBJECT _spi
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#if defined (__AVR__) || defined(TEENSYDUINO) || defined(ARDUINO_ARCH_STM32F1)
|
||||||
|
#define HSPI_SET_CLOCK() SPI_OBJECT.setClockDivider(SPI_CLOCK_DIV2);
|
||||||
|
#elif defined (__arm__)
|
||||||
|
#define HSPI_SET_CLOCK() SPI_OBJECT.setClockDivider(11);
|
||||||
|
#elif defined(ESP8266) || defined(ESP32)
|
||||||
|
#define HSPI_SET_CLOCK() SPI_OBJECT.setFrequency(_freq);
|
||||||
|
#elif defined(RASPI)
|
||||||
|
#define HSPI_SET_CLOCK() SPI_OBJECT.setClock(_freq);
|
||||||
|
#elif defined(ARDUINO_ARCH_STM32F1)
|
||||||
|
#define HSPI_SET_CLOCK() SPI_OBJECT.setClock(_freq);
|
||||||
|
#else
|
||||||
|
#define HSPI_SET_CLOCK()
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#ifdef SPI_HAS_TRANSACTION
|
||||||
|
#define HSPI_BEGIN_TRANSACTION() SPI_OBJECT.beginTransaction(SPISettings(_freq, MSBFIRST, SPI_MODE0))
|
||||||
|
#define HSPI_END_TRANSACTION() SPI_OBJECT.endTransaction()
|
||||||
|
#else
|
||||||
|
#define HSPI_BEGIN_TRANSACTION() HSPI_SET_CLOCK(); SPI_OBJECT.setBitOrder(MSBFIRST); SPI_OBJECT.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_OBJECT.transfer(0)
|
||||||
|
#define HSPI_WRITE(b) SPI_OBJECT.write(b)
|
||||||
|
#define HSPI_WRITE16(s) SPI_OBJECT.write16(s)
|
||||||
|
#define HSPI_WRITE32(l) SPI_OBJECT.write32(l)
|
||||||
|
#ifdef SPI_HAS_WRITE_PIXELS
|
||||||
|
#define SPI_MAX_PIXELS_AT_ONCE 32
|
||||||
|
#define HSPI_WRITE_PIXELS(c,l) SPI_OBJECT.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_OBJECT.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
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Final SPI Macros
|
||||||
|
* */
|
||||||
|
#if defined (ARDUINO_ARCH_ARC32)
|
||||||
|
#define SPI_DEFAULT_FREQ 16000000
|
||||||
|
#elif defined (__AVR__) || defined(TEENSYDUINO)
|
||||||
|
#define SPI_DEFAULT_FREQ 8000000
|
||||||
|
#elif defined(ESP8266) || defined(ESP32)
|
||||||
|
#define SPI_DEFAULT_FREQ 40000000
|
||||||
|
#elif defined(RASPI)
|
||||||
|
#define SPI_DEFAULT_FREQ 80000000
|
||||||
|
#elif defined(ARDUINO_ARCH_STM32F1)
|
||||||
|
#define SPI_DEFAULT_FREQ 36000000
|
||||||
|
#else
|
||||||
|
#define SPI_DEFAULT_FREQ 24000000
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#define SPI_BEGIN() if(_sclk < 0){SPI_OBJECT.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);}
|
||||||
|
|
||||||
|
// Pass 8-bit (each) R,G,B, get back 16-bit packed color
|
||||||
|
uint16_t Adafruit_ILI9341::color565(uint8_t r, uint8_t g, uint8_t b) {
|
||||||
|
return ((r & 0xF8) << 8) | ((g & 0xFC) << 3) | ((b & 0xF8) >> 3);
|
||||||
|
}
|
||||||
|
|
||||||
|
Adafruit_ILI9341::Adafruit_ILI9341(int8_t cs, int8_t dc, int8_t mosi,
|
||||||
|
int8_t sclk, int8_t rst, int8_t miso) : Adafruit_GFX(ILI9341_TFTWIDTH, ILI9341_TFTHEIGHT) {
|
||||||
|
_cs = cs;
|
||||||
|
_dc = dc;
|
||||||
|
_rst = rst;
|
||||||
|
_sclk = sclk;
|
||||||
|
_mosi = mosi;
|
||||||
|
_miso = miso;
|
||||||
|
_freq = 0;
|
||||||
|
#ifdef USE_FAST_PINIO
|
||||||
|
csport = portOutputRegister(digitalPinToPort(_cs));
|
||||||
|
cspinmask = digitalPinToBitMask(_cs);
|
||||||
|
dcport = portOutputRegister(digitalPinToPort(_dc));
|
||||||
|
dcpinmask = digitalPinToBitMask(_dc);
|
||||||
|
clkport = portOutputRegister(digitalPinToPort(_sclk));
|
||||||
|
clkpinmask = digitalPinToBitMask(_sclk);
|
||||||
|
mosiport = portOutputRegister(digitalPinToPort(_mosi));
|
||||||
|
mosipinmask = digitalPinToBitMask(_mosi);
|
||||||
|
if(miso >= 0){
|
||||||
|
misoport = portInputRegister(digitalPinToPort(_miso));
|
||||||
|
misopinmask = digitalPinToBitMask(_miso);
|
||||||
|
} else {
|
||||||
|
misoport = 0;
|
||||||
|
misopinmask = 0;
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
}
|
||||||
|
|
||||||
|
Adafruit_ILI9341::Adafruit_ILI9341(int8_t cs, int8_t dc, int8_t rst) : Adafruit_GFX(ILI9341_TFTWIDTH, ILI9341_TFTHEIGHT) {
|
||||||
|
_cs = cs;
|
||||||
|
_dc = dc;
|
||||||
|
_rst = rst;
|
||||||
|
_sclk = -1;
|
||||||
|
_mosi = -1;
|
||||||
|
_miso = -1;
|
||||||
|
_freq = 0;
|
||||||
|
#ifdef USE_FAST_PINIO
|
||||||
|
csport = portOutputRegister(digitalPinToPort(_cs));
|
||||||
|
cspinmask = digitalPinToBitMask(_cs);
|
||||||
|
dcport = portOutputRegister(digitalPinToPort(_dc));
|
||||||
|
dcpinmask = digitalPinToBitMask(_dc);
|
||||||
|
clkport = 0;
|
||||||
|
clkpinmask = 0;
|
||||||
|
mosiport = 0;
|
||||||
|
mosipinmask = 0;
|
||||||
|
misoport = 0;
|
||||||
|
misopinmask = 0;
|
||||||
|
#endif
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
#ifdef ESP32
|
||||||
|
void Adafruit_ILI9341::begin(uint32_t freq, SPIClass &spi)
|
||||||
|
#else
|
||||||
|
void Adafruit_ILI9341::begin(uint32_t freq)
|
||||||
|
#endif
|
||||||
|
{
|
||||||
|
#ifdef ESP32
|
||||||
|
_spi = spi;
|
||||||
|
#endif
|
||||||
|
if(!freq){
|
||||||
|
freq = SPI_DEFAULT_FREQ;
|
||||||
|
}
|
||||||
|
_freq = freq;
|
||||||
|
|
||||||
|
// Control Pins
|
||||||
|
pinMode(_dc, OUTPUT);
|
||||||
|
digitalWrite(_dc, LOW);
|
||||||
|
pinMode(_cs, OUTPUT);
|
||||||
|
digitalWrite(_cs, HIGH);
|
||||||
|
|
||||||
|
// Software SPI
|
||||||
|
if(_sclk >= 0){
|
||||||
|
pinMode(_mosi, OUTPUT);
|
||||||
|
digitalWrite(_mosi, LOW);
|
||||||
|
pinMode(_sclk, OUTPUT);
|
||||||
|
digitalWrite(_sclk, HIGH);
|
||||||
|
if(_miso >= 0){
|
||||||
|
pinMode(_miso, INPUT);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// Hardware SPI
|
||||||
|
SPI_BEGIN();
|
||||||
|
|
||||||
|
// toggle RST low to reset
|
||||||
|
if (_rst >= 0) {
|
||||||
|
pinMode(_rst, OUTPUT);
|
||||||
|
digitalWrite(_rst, HIGH);
|
||||||
|
delay(100);
|
||||||
|
digitalWrite(_rst, LOW);
|
||||||
|
delay(100);
|
||||||
|
digitalWrite(_rst, HIGH);
|
||||||
|
delay(200);
|
||||||
|
}
|
||||||
|
|
||||||
|
startWrite();
|
||||||
|
|
||||||
|
writeCommand(0xEF);
|
||||||
|
spiWrite(0x03);
|
||||||
|
spiWrite(0x80);
|
||||||
|
spiWrite(0x02);
|
||||||
|
|
||||||
|
writeCommand(0xCF);
|
||||||
|
spiWrite(0x00);
|
||||||
|
spiWrite(0XC1);
|
||||||
|
spiWrite(0X30);
|
||||||
|
|
||||||
|
writeCommand(0xED);
|
||||||
|
spiWrite(0x64);
|
||||||
|
spiWrite(0x03);
|
||||||
|
spiWrite(0X12);
|
||||||
|
spiWrite(0X81);
|
||||||
|
|
||||||
|
writeCommand(0xE8);
|
||||||
|
spiWrite(0x85);
|
||||||
|
spiWrite(0x00);
|
||||||
|
spiWrite(0x78);
|
||||||
|
|
||||||
|
writeCommand(0xCB);
|
||||||
|
spiWrite(0x39);
|
||||||
|
spiWrite(0x2C);
|
||||||
|
spiWrite(0x00);
|
||||||
|
spiWrite(0x34);
|
||||||
|
spiWrite(0x02);
|
||||||
|
|
||||||
|
writeCommand(0xF7);
|
||||||
|
spiWrite(0x20);
|
||||||
|
|
||||||
|
writeCommand(0xEA);
|
||||||
|
spiWrite(0x00);
|
||||||
|
spiWrite(0x00);
|
||||||
|
|
||||||
|
writeCommand(ILI9341_PWCTR1); //Power control
|
||||||
|
spiWrite(0x23); //VRH[5:0]
|
||||||
|
|
||||||
|
writeCommand(ILI9341_PWCTR2); //Power control
|
||||||
|
spiWrite(0x10); //SAP[2:0];BT[3:0]
|
||||||
|
|
||||||
|
writeCommand(ILI9341_VMCTR1); //VCM control
|
||||||
|
spiWrite(0x3e);
|
||||||
|
spiWrite(0x28);
|
||||||
|
|
||||||
|
writeCommand(ILI9341_VMCTR2); //VCM control2
|
||||||
|
spiWrite(0x86); //--
|
||||||
|
|
||||||
|
writeCommand(ILI9341_MADCTL); // Memory Access Control
|
||||||
|
spiWrite(0x48);
|
||||||
|
|
||||||
|
writeCommand(ILI9341_VSCRSADD); // Vertical scroll
|
||||||
|
SPI_WRITE16(0); // Zero
|
||||||
|
|
||||||
|
writeCommand(ILI9341_PIXFMT);
|
||||||
|
spiWrite(0x55);
|
||||||
|
|
||||||
|
writeCommand(ILI9341_FRMCTR1);
|
||||||
|
spiWrite(0x00);
|
||||||
|
spiWrite(0x18);
|
||||||
|
|
||||||
|
writeCommand(ILI9341_DFUNCTR); // Display Function Control
|
||||||
|
spiWrite(0x08);
|
||||||
|
spiWrite(0x82);
|
||||||
|
spiWrite(0x27);
|
||||||
|
|
||||||
|
writeCommand(0xF2); // 3Gamma Function Disable
|
||||||
|
spiWrite(0x00);
|
||||||
|
|
||||||
|
writeCommand(ILI9341_GAMMASET); //Gamma curve selected
|
||||||
|
spiWrite(0x01);
|
||||||
|
|
||||||
|
writeCommand(ILI9341_GMCTRP1); //Set Gamma
|
||||||
|
spiWrite(0x0F);
|
||||||
|
spiWrite(0x31);
|
||||||
|
spiWrite(0x2B);
|
||||||
|
spiWrite(0x0C);
|
||||||
|
spiWrite(0x0E);
|
||||||
|
spiWrite(0x08);
|
||||||
|
spiWrite(0x4E);
|
||||||
|
spiWrite(0xF1);
|
||||||
|
spiWrite(0x37);
|
||||||
|
spiWrite(0x07);
|
||||||
|
spiWrite(0x10);
|
||||||
|
spiWrite(0x03);
|
||||||
|
spiWrite(0x0E);
|
||||||
|
spiWrite(0x09);
|
||||||
|
spiWrite(0x00);
|
||||||
|
|
||||||
|
writeCommand(ILI9341_GMCTRN1); //Set Gamma
|
||||||
|
spiWrite(0x00);
|
||||||
|
spiWrite(0x0E);
|
||||||
|
spiWrite(0x14);
|
||||||
|
spiWrite(0x03);
|
||||||
|
spiWrite(0x11);
|
||||||
|
spiWrite(0x07);
|
||||||
|
spiWrite(0x31);
|
||||||
|
spiWrite(0xC1);
|
||||||
|
spiWrite(0x48);
|
||||||
|
spiWrite(0x08);
|
||||||
|
spiWrite(0x0F);
|
||||||
|
spiWrite(0x0C);
|
||||||
|
spiWrite(0x31);
|
||||||
|
spiWrite(0x36);
|
||||||
|
spiWrite(0x0F);
|
||||||
|
|
||||||
|
writeCommand(ILI9341_SLPOUT); //Exit Sleep
|
||||||
|
delay(120);
|
||||||
|
writeCommand(ILI9341_DISPON); //Display on
|
||||||
|
delay(120);
|
||||||
|
endWrite();
|
||||||
|
|
||||||
|
_width = ILI9341_TFTWIDTH;
|
||||||
|
_height = ILI9341_TFTHEIGHT;
|
||||||
|
}
|
||||||
|
|
||||||
|
/*********************************************************************************************/
|
||||||
|
|
||||||
|
void Adafruit_ILI9341::setScrollStart(uint16_t start)
|
||||||
|
{
|
||||||
|
startWrite();
|
||||||
|
writeCommand(0x37);
|
||||||
|
spiWrite(start>>8);
|
||||||
|
spiWrite(start);
|
||||||
|
endWrite();
|
||||||
|
}
|
||||||
|
|
||||||
|
void Adafruit_ILI9341::setScrollMargins(uint16_t top, uint16_t bottom)
|
||||||
|
{
|
||||||
|
uint16_t height = _height - (top + bottom);
|
||||||
|
|
||||||
|
startWrite();
|
||||||
|
writeCommand(0x33);
|
||||||
|
spiWrite(top>>8);
|
||||||
|
spiWrite(top);
|
||||||
|
spiWrite(height>>8);
|
||||||
|
spiWrite(height);
|
||||||
|
spiWrite(bottom>>8);
|
||||||
|
spiWrite(bottom);
|
||||||
|
endWrite();
|
||||||
|
}
|
||||||
|
|
||||||
|
/*********************************************************************************************/
|
||||||
|
|
||||||
|
void Adafruit_ILI9341::setRotation(uint8_t m) {
|
||||||
|
rotation = m % 4; // can't be higher than 3
|
||||||
|
switch (rotation) {
|
||||||
|
case 0:
|
||||||
|
m = (MADCTL_MX | MADCTL_BGR);
|
||||||
|
_width = ILI9341_TFTWIDTH;
|
||||||
|
_height = ILI9341_TFTHEIGHT;
|
||||||
|
break;
|
||||||
|
case 1:
|
||||||
|
m = (MADCTL_MV | MADCTL_BGR);
|
||||||
|
_width = ILI9341_TFTHEIGHT;
|
||||||
|
_height = ILI9341_TFTWIDTH;
|
||||||
|
break;
|
||||||
|
case 2:
|
||||||
|
m = (MADCTL_MY | MADCTL_BGR);
|
||||||
|
_width = ILI9341_TFTWIDTH;
|
||||||
|
_height = ILI9341_TFTHEIGHT;
|
||||||
|
break;
|
||||||
|
case 3:
|
||||||
|
m = (MADCTL_MX | MADCTL_MY | MADCTL_MV | MADCTL_BGR);
|
||||||
|
_width = ILI9341_TFTHEIGHT;
|
||||||
|
_height = ILI9341_TFTWIDTH;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
startWrite();
|
||||||
|
writeCommand(ILI9341_MADCTL);
|
||||||
|
spiWrite(m);
|
||||||
|
endWrite();
|
||||||
|
}
|
||||||
|
|
||||||
|
void Adafruit_ILI9341::invertDisplay(boolean i) {
|
||||||
|
startWrite();
|
||||||
|
writeCommand(i ? ILI9341_INVON : ILI9341_INVOFF);
|
||||||
|
endWrite();
|
||||||
|
}
|
||||||
|
|
||||||
|
void Adafruit_ILI9341::scrollTo(uint16_t y) {
|
||||||
|
startWrite();
|
||||||
|
writeCommand(ILI9341_VSCRSADD);
|
||||||
|
SPI_WRITE16(y);
|
||||||
|
endWrite();
|
||||||
|
}
|
||||||
|
|
||||||
|
uint8_t Adafruit_ILI9341::spiRead() {
|
||||||
|
if(_sclk < 0){
|
||||||
|
return HSPI_READ();
|
||||||
|
}
|
||||||
|
if(_miso < 0){
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
uint8_t r = 0;
|
||||||
|
for (uint8_t i=0; i<8; i++) {
|
||||||
|
SSPI_SCK_LOW();
|
||||||
|
SSPI_SCK_HIGH();
|
||||||
|
r <<= 1;
|
||||||
|
if (SSPI_MISO_READ()){
|
||||||
|
r |= 0x1;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return r;
|
||||||
|
}
|
||||||
|
|
||||||
|
void Adafruit_ILI9341::spiWrite(uint8_t b) {
|
||||||
|
if(_sclk < 0){
|
||||||
|
HSPI_WRITE(b);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
for(uint8_t bit = 0x80; bit; bit >>= 1){
|
||||||
|
if((b) & bit){
|
||||||
|
SSPI_MOSI_HIGH();
|
||||||
|
} else {
|
||||||
|
SSPI_MOSI_LOW();
|
||||||
|
}
|
||||||
|
SSPI_SCK_LOW();
|
||||||
|
SSPI_SCK_HIGH();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Transaction API
|
||||||
|
* */
|
||||||
|
|
||||||
|
void Adafruit_ILI9341::startWrite(void){
|
||||||
|
SPI_BEGIN_TRANSACTION();
|
||||||
|
SPI_CS_LOW();
|
||||||
|
}
|
||||||
|
|
||||||
|
void Adafruit_ILI9341::endWrite(void){
|
||||||
|
SPI_CS_HIGH();
|
||||||
|
SPI_END_TRANSACTION();
|
||||||
|
}
|
||||||
|
|
||||||
|
void Adafruit_ILI9341::writeCommand(uint8_t cmd){
|
||||||
|
SPI_DC_LOW();
|
||||||
|
spiWrite(cmd);
|
||||||
|
SPI_DC_HIGH();
|
||||||
|
}
|
||||||
|
|
||||||
|
void Adafruit_ILI9341::setAddrWindow(uint16_t x, uint16_t y, uint16_t w, uint16_t h) {
|
||||||
|
uint32_t xa = ((uint32_t)x << 16) | (x+w-1);
|
||||||
|
uint32_t ya = ((uint32_t)y << 16) | (y+h-1);
|
||||||
|
writeCommand(ILI9341_CASET); // Column addr set
|
||||||
|
SPI_WRITE32(xa);
|
||||||
|
writeCommand(ILI9341_PASET); // Row addr set
|
||||||
|
SPI_WRITE32(ya);
|
||||||
|
writeCommand(ILI9341_RAMWR); // write to RAM
|
||||||
|
}
|
||||||
|
|
||||||
|
void Adafruit_ILI9341::pushColor(uint16_t color) {
|
||||||
|
startWrite();
|
||||||
|
SPI_WRITE16(color);
|
||||||
|
endWrite();
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
void Adafruit_ILI9341::writePixel(uint16_t color){
|
||||||
|
SPI_WRITE16(color);
|
||||||
|
}
|
||||||
|
|
||||||
|
void Adafruit_ILI9341::writePixels(uint16_t * colors, uint32_t len){
|
||||||
|
SPI_WRITE_PIXELS((uint8_t*)colors , len * 2);
|
||||||
|
}
|
||||||
|
|
||||||
|
void Adafruit_ILI9341::writeColor(uint16_t color, uint32_t len){
|
||||||
|
#ifdef SPI_HAS_WRITE_PIXELS
|
||||||
|
if(_sclk >= 0){
|
||||||
|
for (uint32_t t=0; t<len; t++){
|
||||||
|
writePixel(color);
|
||||||
|
}
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
static uint16_t temp[SPI_MAX_PIXELS_AT_ONCE];
|
||||||
|
size_t blen = (len > SPI_MAX_PIXELS_AT_ONCE)?SPI_MAX_PIXELS_AT_ONCE:len;
|
||||||
|
uint16_t tlen = 0;
|
||||||
|
|
||||||
|
for (uint32_t t=0; t<blen; t++){
|
||||||
|
temp[t] = color;
|
||||||
|
}
|
||||||
|
|
||||||
|
while(len){
|
||||||
|
tlen = (len>blen)?blen:len;
|
||||||
|
writePixels(temp, tlen);
|
||||||
|
len -= tlen;
|
||||||
|
}
|
||||||
|
#else
|
||||||
|
uint8_t hi = color >> 8, lo = color;
|
||||||
|
if(_sclk < 0){ //AVR Optimization
|
||||||
|
for (uint32_t t=len; t; t--){
|
||||||
|
HSPI_WRITE(hi);
|
||||||
|
HSPI_WRITE(lo);
|
||||||
|
}
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
for (uint32_t t=len; t; t--){
|
||||||
|
spiWrite(hi);
|
||||||
|
spiWrite(lo);
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
}
|
||||||
|
|
||||||
|
void Adafruit_ILI9341::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);
|
||||||
|
}
|
||||||
|
|
||||||
|
void Adafruit_ILI9341::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;
|
||||||
|
|
||||||
|
int32_t len = (int32_t)w * h;
|
||||||
|
setAddrWindow(x, y, w, h);
|
||||||
|
writeColor(color, len);
|
||||||
|
}
|
||||||
|
|
||||||
|
void Adafruit_ILI9341::writeFastVLine(int16_t x, int16_t y, int16_t h, uint16_t color){
|
||||||
|
writeFillRect(x, y, 1, h, color);
|
||||||
|
}
|
||||||
|
|
||||||
|
void Adafruit_ILI9341::writeFastHLine(int16_t x, int16_t y, int16_t w, uint16_t color){
|
||||||
|
writeFillRect(x, y, w, 1, color);
|
||||||
|
}
|
||||||
|
|
||||||
|
uint8_t Adafruit_ILI9341::readcommand8(uint8_t c, uint8_t index) {
|
||||||
|
uint32_t freq = _freq;
|
||||||
|
if(_freq > 24000000){
|
||||||
|
_freq = 24000000;
|
||||||
|
}
|
||||||
|
startWrite();
|
||||||
|
writeCommand(0xD9); // woo sekret command?
|
||||||
|
spiWrite(0x10 + index);
|
||||||
|
writeCommand(c);
|
||||||
|
uint8_t r = spiRead();
|
||||||
|
endWrite();
|
||||||
|
_freq = freq;
|
||||||
|
return r;
|
||||||
|
}
|
||||||
|
|
||||||
|
void Adafruit_ILI9341::drawPixel(int16_t x, int16_t y, uint16_t color){
|
||||||
|
startWrite();
|
||||||
|
writePixel(x, y, color);
|
||||||
|
endWrite();
|
||||||
|
}
|
||||||
|
|
||||||
|
void Adafruit_ILI9341::drawFastVLine(int16_t x, int16_t y,
|
||||||
|
int16_t h, uint16_t color) {
|
||||||
|
startWrite();
|
||||||
|
writeFastVLine(x, y, h, color);
|
||||||
|
endWrite();
|
||||||
|
}
|
||||||
|
|
||||||
|
void Adafruit_ILI9341::drawFastHLine(int16_t x, int16_t y,
|
||||||
|
int16_t w, uint16_t color) {
|
||||||
|
startWrite();
|
||||||
|
writeFastHLine(x, y, w, color);
|
||||||
|
endWrite();
|
||||||
|
}
|
||||||
|
|
||||||
|
void Adafruit_ILI9341::fillRect(int16_t x, int16_t y, int16_t w, int16_t h,
|
||||||
|
uint16_t color) {
|
||||||
|
startWrite();
|
||||||
|
writeFillRect(x,y,w,h,color);
|
||||||
|
endWrite();
|
||||||
|
}
|
||||||
|
|
||||||
|
// 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.
|
||||||
|
void Adafruit_ILI9341::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();
|
||||||
|
}
|
|
@ -0,0 +1,206 @@
|
||||||
|
/******************************************************************
|
||||||
|
This is our library for the Adafruit ILI9341 Breakout and Shield
|
||||||
|
----> http://www.adafruit.com/products/1651
|
||||||
|
|
||||||
|
Check out the links above for our tutorials and wiring diagrams
|
||||||
|
These displays use SPI to communicate, 4 or 5 pins are required
|
||||||
|
to interface (RST is optional)
|
||||||
|
Adafruit invests time and resources providing this open source
|
||||||
|
code, please support Adafruit and open-source hardware by
|
||||||
|
purchasing products from Adafruit!
|
||||||
|
|
||||||
|
Written by Limor Fried/Ladyada for Adafruit Industries.
|
||||||
|
MIT license, all text above must be included in any redistribution
|
||||||
|
*******************************************************************/
|
||||||
|
|
||||||
|
#ifndef _ADAFRUIT_ILI9341H_
|
||||||
|
#define _ADAFRUIT_ILI9341H_
|
||||||
|
|
||||||
|
#if ARDUINO >= 100
|
||||||
|
#include "Arduino.h"
|
||||||
|
#include "Print.h"
|
||||||
|
#else
|
||||||
|
#include "WProgram.h"
|
||||||
|
#endif
|
||||||
|
#include <SPI.h>
|
||||||
|
#include "Adafruit_GFX.h"
|
||||||
|
|
||||||
|
#if defined(ARDUINO_STM32_FEATHER)
|
||||||
|
typedef volatile uint32 RwReg;
|
||||||
|
#endif
|
||||||
|
#if defined(ARDUINO_FEATHER52)
|
||||||
|
typedef volatile uint32_t RwReg;
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#define ILI9341_TFTWIDTH 240
|
||||||
|
#define ILI9341_TFTHEIGHT 320
|
||||||
|
|
||||||
|
#define ILI9341_NOP 0x00
|
||||||
|
#define ILI9341_SWRESET 0x01
|
||||||
|
#define ILI9341_RDDID 0x04
|
||||||
|
#define ILI9341_RDDST 0x09
|
||||||
|
|
||||||
|
#define ILI9341_SLPIN 0x10
|
||||||
|
#define ILI9341_SLPOUT 0x11
|
||||||
|
#define ILI9341_PTLON 0x12
|
||||||
|
#define ILI9341_NORON 0x13
|
||||||
|
|
||||||
|
#define ILI9341_RDMODE 0x0A
|
||||||
|
#define ILI9341_RDMADCTL 0x0B
|
||||||
|
#define ILI9341_RDPIXFMT 0x0C
|
||||||
|
#define ILI9341_RDIMGFMT 0x0D
|
||||||
|
#define ILI9341_RDSELFDIAG 0x0F
|
||||||
|
|
||||||
|
#define ILI9341_INVOFF 0x20
|
||||||
|
#define ILI9341_INVON 0x21
|
||||||
|
#define ILI9341_GAMMASET 0x26
|
||||||
|
#define ILI9341_DISPOFF 0x28
|
||||||
|
#define ILI9341_DISPON 0x29
|
||||||
|
|
||||||
|
#define ILI9341_CASET 0x2A
|
||||||
|
#define ILI9341_PASET 0x2B
|
||||||
|
#define ILI9341_RAMWR 0x2C
|
||||||
|
#define ILI9341_RAMRD 0x2E
|
||||||
|
|
||||||
|
#define ILI9341_PTLAR 0x30
|
||||||
|
#define ILI9341_MADCTL 0x36
|
||||||
|
#define ILI9341_VSCRSADD 0x37
|
||||||
|
#define ILI9341_PIXFMT 0x3A
|
||||||
|
|
||||||
|
#define ILI9341_FRMCTR1 0xB1
|
||||||
|
#define ILI9341_FRMCTR2 0xB2
|
||||||
|
#define ILI9341_FRMCTR3 0xB3
|
||||||
|
#define ILI9341_INVCTR 0xB4
|
||||||
|
#define ILI9341_DFUNCTR 0xB6
|
||||||
|
|
||||||
|
#define ILI9341_PWCTR1 0xC0
|
||||||
|
#define ILI9341_PWCTR2 0xC1
|
||||||
|
#define ILI9341_PWCTR3 0xC2
|
||||||
|
#define ILI9341_PWCTR4 0xC3
|
||||||
|
#define ILI9341_PWCTR5 0xC4
|
||||||
|
#define ILI9341_VMCTR1 0xC5
|
||||||
|
#define ILI9341_VMCTR2 0xC7
|
||||||
|
|
||||||
|
#define ILI9341_RDID1 0xDA
|
||||||
|
#define ILI9341_RDID2 0xDB
|
||||||
|
#define ILI9341_RDID3 0xDC
|
||||||
|
#define ILI9341_RDID4 0xDD
|
||||||
|
|
||||||
|
#define ILI9341_GMCTRP1 0xE0
|
||||||
|
#define ILI9341_GMCTRN1 0xE1
|
||||||
|
/*
|
||||||
|
#define ILI9341_PWCTR6 0xFC
|
||||||
|
|
||||||
|
*/
|
||||||
|
|
||||||
|
// Color definitions
|
||||||
|
#define ILI9341_BLACK 0x0000 /* 0, 0, 0 */
|
||||||
|
#define ILI9341_NAVY 0x000F /* 0, 0, 128 */
|
||||||
|
#define ILI9341_DARKGREEN 0x03E0 /* 0, 128, 0 */
|
||||||
|
#define ILI9341_DARKCYAN 0x03EF /* 0, 128, 128 */
|
||||||
|
#define ILI9341_MAROON 0x7800 /* 128, 0, 0 */
|
||||||
|
#define ILI9341_PURPLE 0x780F /* 128, 0, 128 */
|
||||||
|
#define ILI9341_OLIVE 0x7BE0 /* 128, 128, 0 */
|
||||||
|
#define ILI9341_LIGHTGREY 0xC618 /* 192, 192, 192 */
|
||||||
|
#define ILI9341_DARKGREY 0x7BEF /* 128, 128, 128 */
|
||||||
|
#define ILI9341_BLUE 0x001F /* 0, 0, 255 */
|
||||||
|
#define ILI9341_GREEN 0x07E0 /* 0, 255, 0 */
|
||||||
|
#define ILI9341_CYAN 0x07FF /* 0, 255, 255 */
|
||||||
|
#define ILI9341_RED 0xF800 /* 255, 0, 0 */
|
||||||
|
#define ILI9341_MAGENTA 0xF81F /* 255, 0, 255 */
|
||||||
|
#define ILI9341_YELLOW 0xFFE0 /* 255, 255, 0 */
|
||||||
|
#define ILI9341_WHITE 0xFFFF /* 255, 255, 255 */
|
||||||
|
#define ILI9341_ORANGE 0xFD20 /* 255, 165, 0 */
|
||||||
|
#define ILI9341_GREENYELLOW 0xAFE5 /* 173, 255, 47 */
|
||||||
|
#define ILI9341_PINK 0xF81F
|
||||||
|
|
||||||
|
#if defined (ARDUINO_STM32_FEATHER) // doesnt work on wiced feather
|
||||||
|
#undef USE_FAST_PINIO
|
||||||
|
#elif defined (__AVR__) || defined(TEENSYDUINO) || defined(ESP8266) || defined (ESP32) || defined(__arm__)
|
||||||
|
#define USE_FAST_PINIO
|
||||||
|
#endif
|
||||||
|
|
||||||
|
class Adafruit_ILI9341 : public Adafruit_GFX {
|
||||||
|
protected:
|
||||||
|
|
||||||
|
public:
|
||||||
|
Adafruit_ILI9341(int8_t _CS, int8_t _DC, int8_t _MOSI, int8_t _SCLK, int8_t _RST = -1, int8_t _MISO = -1);
|
||||||
|
Adafruit_ILI9341(int8_t _CS, int8_t _DC, int8_t _RST = -1);
|
||||||
|
|
||||||
|
#ifndef ESP32
|
||||||
|
void begin(uint32_t freq = 0);
|
||||||
|
#else
|
||||||
|
void begin(uint32_t freq = 0, SPIClass &spi=SPI);
|
||||||
|
#endif
|
||||||
|
|
||||||
|
void setScrollStart(uint16_t start);
|
||||||
|
void setScrollMargins(uint16_t top, uint16_t bottom);
|
||||||
|
|
||||||
|
void setRotation(uint8_t r);
|
||||||
|
void invertDisplay(boolean i);
|
||||||
|
void scrollTo(uint16_t y);
|
||||||
|
|
||||||
|
// 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
|
||||||
|
void setAddrWindow(uint16_t x, uint16_t y, uint16_t w, uint16_t h);
|
||||||
|
void writePixel(uint16_t 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);
|
||||||
|
|
||||||
|
uint8_t readcommand8(uint8_t reg, uint8_t index = 0);
|
||||||
|
|
||||||
|
uint16_t color565(uint8_t r, uint8_t g, uint8_t b);
|
||||||
|
|
||||||
|
private:
|
||||||
|
#ifdef ESP32
|
||||||
|
SPIClass _spi;
|
||||||
|
#endif
|
||||||
|
uint32_t _freq;
|
||||||
|
#if defined (__AVR__) || defined(TEENSYDUINO)
|
||||||
|
int8_t _cs, _dc, _rst, _sclk, _mosi, _miso;
|
||||||
|
#ifdef USE_FAST_PINIO
|
||||||
|
volatile uint8_t *mosiport, *misoport, *clkport, *dcport, *csport;
|
||||||
|
uint8_t mosipinmask, misopinmask, clkpinmask, cspinmask, dcpinmask;
|
||||||
|
#endif
|
||||||
|
#elif defined (__arm__)
|
||||||
|
int32_t _cs, _dc, _rst, _sclk, _mosi, _miso;
|
||||||
|
#ifdef USE_FAST_PINIO
|
||||||
|
volatile RwReg *mosiport, *misoport, *clkport, *dcport, *csport;
|
||||||
|
uint32_t mosipinmask, misopinmask, clkpinmask, cspinmask, dcpinmask;
|
||||||
|
#endif
|
||||||
|
#elif defined (ESP8266) || defined (ESP32)
|
||||||
|
int8_t _cs, _dc, _rst, _sclk, _mosi, _miso;
|
||||||
|
#ifdef USE_FAST_PINIO
|
||||||
|
volatile uint32_t *mosiport, *misoport, *clkport, *dcport, *csport;
|
||||||
|
uint32_t mosipinmask, misopinmask, clkpinmask, cspinmask, dcpinmask;
|
||||||
|
#endif
|
||||||
|
#else
|
||||||
|
int8_t _cs, _dc, _rst, _sclk, _mosi, _miso;
|
||||||
|
#endif
|
||||||
|
|
||||||
|
void writeCommand(uint8_t cmd);
|
||||||
|
void spiWrite(uint8_t v);
|
||||||
|
uint8_t spiRead(void);
|
||||||
|
};
|
||||||
|
|
||||||
|
#endif
|
|
@ -0,0 +1,145 @@
|
||||||
|
/***************************************************
|
||||||
|
This is our touchscreen painting example for the Adafruit ILI9341 Breakout
|
||||||
|
----> http://www.adafruit.com/products/1770
|
||||||
|
|
||||||
|
Check out the links above for our tutorials and wiring diagrams
|
||||||
|
These displays use SPI to communicate, 4 or 5 pins are required to
|
||||||
|
interface (RST is optional)
|
||||||
|
Adafruit invests time and resources providing this open source code,
|
||||||
|
please support Adafruit and open-source hardware by purchasing
|
||||||
|
products from Adafruit!
|
||||||
|
|
||||||
|
Written by Limor Fried/Ladyada for Adafruit Industries.
|
||||||
|
MIT license, all text above must be included in any redistribution
|
||||||
|
****************************************************/
|
||||||
|
|
||||||
|
/** NOT FOR USE WITH THE TOUCH SHIELD, ONLY FOR THE BREAKOUT! **/
|
||||||
|
|
||||||
|
#include <Adafruit_GFX.h> // Core graphics library
|
||||||
|
#include <SPI.h>
|
||||||
|
#include <Adafruit_ILI9341.h>
|
||||||
|
#include "TouchScreen.h"
|
||||||
|
|
||||||
|
// These are the four touchscreen analog pins
|
||||||
|
#define YP A2 // must be an analog pin, use "An" notation!
|
||||||
|
#define XM A3 // must be an analog pin, use "An" notation!
|
||||||
|
#define YM 5 // can be a digital pin
|
||||||
|
#define XP 4 // can be a digital pin
|
||||||
|
|
||||||
|
// This is calibration data for the raw touch data to the screen coordinates
|
||||||
|
#define TS_MINX 150
|
||||||
|
#define TS_MINY 120
|
||||||
|
#define TS_MAXX 920
|
||||||
|
#define TS_MAXY 940
|
||||||
|
|
||||||
|
#define MINPRESSURE 10
|
||||||
|
#define MAXPRESSURE 1000
|
||||||
|
|
||||||
|
// The display uses hardware SPI, plus #9 & #10
|
||||||
|
#define TFT_CS 10
|
||||||
|
#define TFT_DC 9
|
||||||
|
Adafruit_ILI9341 tft = Adafruit_ILI9341(TFT_CS, TFT_DC);
|
||||||
|
|
||||||
|
// For better pressure precision, we need to know the resistance
|
||||||
|
// between X+ and X- Use any multimeter to read it
|
||||||
|
// For the one we're using, its 300 ohms across the X plate
|
||||||
|
TouchScreen ts = TouchScreen(XP, YP, XM, YM, 300);
|
||||||
|
|
||||||
|
// Size of the color selection boxes and the paintbrush size
|
||||||
|
#define BOXSIZE 40
|
||||||
|
#define PENRADIUS 3
|
||||||
|
int oldcolor, currentcolor;
|
||||||
|
|
||||||
|
void setup(void) {
|
||||||
|
// while (!Serial); // used for leonardo debugging
|
||||||
|
|
||||||
|
Serial.begin(9600);
|
||||||
|
Serial.println(F("Touch Paint!"));
|
||||||
|
|
||||||
|
tft.begin();
|
||||||
|
tft.fillScreen(ILI9341_BLACK);
|
||||||
|
|
||||||
|
// make the color selection boxes
|
||||||
|
tft.fillRect(0, 0, BOXSIZE, BOXSIZE, ILI9341_RED);
|
||||||
|
tft.fillRect(BOXSIZE, 0, BOXSIZE, BOXSIZE, ILI9341_YELLOW);
|
||||||
|
tft.fillRect(BOXSIZE*2, 0, BOXSIZE, BOXSIZE, ILI9341_GREEN);
|
||||||
|
tft.fillRect(BOXSIZE*3, 0, BOXSIZE, BOXSIZE, ILI9341_CYAN);
|
||||||
|
tft.fillRect(BOXSIZE*4, 0, BOXSIZE, BOXSIZE, ILI9341_BLUE);
|
||||||
|
tft.fillRect(BOXSIZE*5, 0, BOXSIZE, BOXSIZE, ILI9341_MAGENTA);
|
||||||
|
|
||||||
|
// select the current color 'red'
|
||||||
|
tft.drawRect(0, 0, BOXSIZE, BOXSIZE, ILI9341_WHITE);
|
||||||
|
currentcolor = ILI9341_RED;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
void loop()
|
||||||
|
{
|
||||||
|
// Retrieve a point
|
||||||
|
TSPoint p = ts.getPoint();
|
||||||
|
|
||||||
|
/*
|
||||||
|
Serial.print("X = "); Serial.print(p.x);
|
||||||
|
Serial.print("\tY = "); Serial.print(p.y);
|
||||||
|
Serial.print("\tPressure = "); Serial.println(p.z);
|
||||||
|
*/
|
||||||
|
|
||||||
|
// we have some minimum pressure we consider 'valid'
|
||||||
|
// pressure of 0 means no pressing!
|
||||||
|
if (p.z < MINPRESSURE || p.z > MAXPRESSURE) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Scale from ~0->1000 to tft.width using the calibration #'s
|
||||||
|
p.x = map(p.x, TS_MINX, TS_MAXX, 0, tft.width());
|
||||||
|
p.y = map(p.y, TS_MINY, TS_MAXY, 0, tft.height());
|
||||||
|
|
||||||
|
/*
|
||||||
|
Serial.print("("); Serial.print(p.x);
|
||||||
|
Serial.print(", "); Serial.print(p.y);
|
||||||
|
Serial.println(")");
|
||||||
|
*/
|
||||||
|
|
||||||
|
|
||||||
|
if (p.y < BOXSIZE) {
|
||||||
|
oldcolor = currentcolor;
|
||||||
|
|
||||||
|
if (p.x < BOXSIZE) {
|
||||||
|
currentcolor = ILI9341_RED;
|
||||||
|
tft.drawRect(0, 0, BOXSIZE, BOXSIZE, ILI9341_WHITE);
|
||||||
|
} else if (p.x < BOXSIZE*2) {
|
||||||
|
currentcolor = ILI9341_YELLOW;
|
||||||
|
tft.drawRect(BOXSIZE, 0, BOXSIZE, BOXSIZE, ILI9341_WHITE);
|
||||||
|
} else if (p.x < BOXSIZE*3) {
|
||||||
|
currentcolor = ILI9341_GREEN;
|
||||||
|
tft.drawRect(BOXSIZE*2, 0, BOXSIZE, BOXSIZE, ILI9341_WHITE);
|
||||||
|
} else if (p.x < BOXSIZE*4) {
|
||||||
|
currentcolor = ILI9341_CYAN;
|
||||||
|
tft.drawRect(BOXSIZE*3, 0, BOXSIZE, BOXSIZE, ILI9341_WHITE);
|
||||||
|
} else if (p.x < BOXSIZE*5) {
|
||||||
|
currentcolor = ILI9341_BLUE;
|
||||||
|
tft.drawRect(BOXSIZE*4, 0, BOXSIZE, BOXSIZE, ILI9341_WHITE);
|
||||||
|
} else if (p.x < BOXSIZE*6) {
|
||||||
|
currentcolor = ILI9341_MAGENTA;
|
||||||
|
tft.drawRect(BOXSIZE*5, 0, BOXSIZE, BOXSIZE, ILI9341_WHITE);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (oldcolor != currentcolor) {
|
||||||
|
if (oldcolor == ILI9341_RED)
|
||||||
|
tft.fillRect(0, 0, BOXSIZE, BOXSIZE, ILI9341_RED);
|
||||||
|
if (oldcolor == ILI9341_YELLOW)
|
||||||
|
tft.fillRect(BOXSIZE, 0, BOXSIZE, BOXSIZE, ILI9341_YELLOW);
|
||||||
|
if (oldcolor == ILI9341_GREEN)
|
||||||
|
tft.fillRect(BOXSIZE*2, 0, BOXSIZE, BOXSIZE, ILI9341_GREEN);
|
||||||
|
if (oldcolor == ILI9341_CYAN)
|
||||||
|
tft.fillRect(BOXSIZE*3, 0, BOXSIZE, BOXSIZE, ILI9341_CYAN);
|
||||||
|
if (oldcolor == ILI9341_BLUE)
|
||||||
|
tft.fillRect(BOXSIZE*4, 0, BOXSIZE, BOXSIZE, ILI9341_BLUE);
|
||||||
|
if (oldcolor == ILI9341_MAGENTA)
|
||||||
|
tft.fillRect(BOXSIZE*5, 0, BOXSIZE, BOXSIZE, ILI9341_MAGENTA);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if (((p.y-PENRADIUS) > BOXSIZE) && ((p.y+PENRADIUS) < tft.height())) {
|
||||||
|
tft.fillCircle(p.x, p.y, PENRADIUS, currentcolor);
|
||||||
|
}
|
||||||
|
}
|
|
@ -0,0 +1,253 @@
|
||||||
|
/***************************************************
|
||||||
|
This is our touchscreen painting example for the Adafruit TFT FeatherWing
|
||||||
|
----> http://www.adafruit.com/products/3315
|
||||||
|
|
||||||
|
Check out the links above for our tutorials and wiring diagrams
|
||||||
|
|
||||||
|
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
|
||||||
|
****************************************************/
|
||||||
|
|
||||||
|
#include <SPI.h>
|
||||||
|
#include <Wire.h> // this is needed even tho we aren't using it
|
||||||
|
|
||||||
|
#include <Adafruit_GFX.h> // Core graphics library
|
||||||
|
#include <Adafruit_ILI9341.h> // Hardware-specific library
|
||||||
|
#include <SD.h>
|
||||||
|
#include <Adafruit_STMPE610.h>
|
||||||
|
|
||||||
|
#ifdef ESP8266
|
||||||
|
#define STMPE_CS 16
|
||||||
|
#define TFT_CS 0
|
||||||
|
#define TFT_DC 15
|
||||||
|
#define SD_CS 2
|
||||||
|
#endif
|
||||||
|
#ifdef ESP32
|
||||||
|
#define STMPE_CS 32
|
||||||
|
#define TFT_CS 15
|
||||||
|
#define TFT_DC 33
|
||||||
|
#define SD_CS 14
|
||||||
|
#endif
|
||||||
|
#if defined (__AVR_ATmega32U4__) || defined(ARDUINO_SAMD_FEATHER_M0) || defined (__AVR_ATmega328P__)
|
||||||
|
#define STMPE_CS 6
|
||||||
|
#define TFT_CS 9
|
||||||
|
#define TFT_DC 10
|
||||||
|
#define SD_CS 5
|
||||||
|
#endif
|
||||||
|
#ifdef TEENSYDUINO
|
||||||
|
#define TFT_DC 10
|
||||||
|
#define TFT_CS 4
|
||||||
|
#define STMPE_CS 3
|
||||||
|
#define SD_CS 8
|
||||||
|
#endif
|
||||||
|
#ifdef ARDUINO_STM32_FEATHER
|
||||||
|
#define TFT_DC PB4
|
||||||
|
#define TFT_CS PA15
|
||||||
|
#define STMPE_CS PC7
|
||||||
|
#define SD_CS PC5
|
||||||
|
#endif
|
||||||
|
#ifdef ARDUINO_NRF52_FEATHER /* BSP 0.6.5 and higher! */
|
||||||
|
#define TFT_DC 11
|
||||||
|
#define TFT_CS 31
|
||||||
|
#define STMPE_CS 30
|
||||||
|
#define SD_CS 27
|
||||||
|
#endif
|
||||||
|
|
||||||
|
Adafruit_ILI9341 tft = Adafruit_ILI9341(TFT_CS, TFT_DC);
|
||||||
|
Adafruit_STMPE610 ts = Adafruit_STMPE610(STMPE_CS);
|
||||||
|
|
||||||
|
|
||||||
|
// This is calibration data for the raw touch data to the screen coordinates
|
||||||
|
#define TS_MINX 3800
|
||||||
|
#define TS_MAXX 100
|
||||||
|
#define TS_MINY 100
|
||||||
|
#define TS_MAXY 3750
|
||||||
|
|
||||||
|
#define PENRADIUS 3
|
||||||
|
|
||||||
|
void setup(void) {
|
||||||
|
Serial.begin(115200);
|
||||||
|
|
||||||
|
delay(10);
|
||||||
|
Serial.println("FeatherWing TFT");
|
||||||
|
if (!ts.begin()) {
|
||||||
|
Serial.println("Couldn't start touchscreen controller");
|
||||||
|
while (1);
|
||||||
|
}
|
||||||
|
Serial.println("Touchscreen started");
|
||||||
|
|
||||||
|
tft.begin();
|
||||||
|
tft.fillScreen(ILI9341_BLUE);
|
||||||
|
|
||||||
|
yield();
|
||||||
|
|
||||||
|
Serial.print("Initializing SD card...");
|
||||||
|
if (!SD.begin(SD_CS)) {
|
||||||
|
Serial.println("failed!");
|
||||||
|
}
|
||||||
|
Serial.println("OK!");
|
||||||
|
|
||||||
|
bmpDraw("purple.bmp", 0, 0);
|
||||||
|
}
|
||||||
|
|
||||||
|
void loop() {
|
||||||
|
// Retrieve a point
|
||||||
|
TS_Point p = ts.getPoint();
|
||||||
|
|
||||||
|
Serial.print("X = "); Serial.print(p.x);
|
||||||
|
Serial.print("\tY = "); Serial.print(p.y);
|
||||||
|
Serial.print("\tPressure = "); Serial.println(p.z);
|
||||||
|
|
||||||
|
|
||||||
|
// Scale from ~0->4000 to tft.width using the calibration #'s
|
||||||
|
p.x = map(p.x, TS_MINX, TS_MAXX, 0, tft.width());
|
||||||
|
p.y = map(p.y, TS_MINY, TS_MAXY, 0, tft.height());
|
||||||
|
|
||||||
|
if (((p.y-PENRADIUS) > 0) && ((p.y+PENRADIUS) < tft.height())) {
|
||||||
|
tft.fillCircle(p.x, p.y, PENRADIUS, ILI9341_RED);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// This function opens a Windows Bitmap (BMP) file and
|
||||||
|
// displays it at the given coordinates. It's sped up
|
||||||
|
// by reading many pixels worth of data at a time
|
||||||
|
// (rather than pixel by pixel). Increasing the buffer
|
||||||
|
// size takes more of the Arduino's precious RAM but
|
||||||
|
// makes loading a little faster. 20 pixels seems a
|
||||||
|
// good balance.
|
||||||
|
|
||||||
|
#define BUFFPIXEL 20
|
||||||
|
|
||||||
|
void bmpDraw(char *filename, uint8_t x, uint16_t y) {
|
||||||
|
|
||||||
|
File bmpFile;
|
||||||
|
int bmpWidth, bmpHeight; // W+H in pixels
|
||||||
|
uint8_t bmpDepth; // Bit depth (currently must be 24)
|
||||||
|
uint32_t bmpImageoffset; // Start of image data in file
|
||||||
|
uint32_t rowSize; // Not always = bmpWidth; may have padding
|
||||||
|
uint8_t sdbuffer[3*BUFFPIXEL]; // pixel buffer (R+G+B per pixel)
|
||||||
|
uint8_t buffidx = sizeof(sdbuffer); // Current position in sdbuffer
|
||||||
|
boolean goodBmp = false; // Set to true on valid header parse
|
||||||
|
boolean flip = true; // BMP is stored bottom-to-top
|
||||||
|
int w, h, row, col;
|
||||||
|
uint8_t r, g, b;
|
||||||
|
uint32_t pos = 0, startTime = millis();
|
||||||
|
|
||||||
|
if((x >= tft.width()) || (y >= tft.height())) return;
|
||||||
|
|
||||||
|
Serial.println();
|
||||||
|
Serial.print(F("Loading image '"));
|
||||||
|
Serial.print(filename);
|
||||||
|
Serial.println('\'');
|
||||||
|
|
||||||
|
// Open requested file on SD card
|
||||||
|
if ((bmpFile = SD.open(filename)) == NULL) {
|
||||||
|
Serial.print(F("File not found"));
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Parse BMP header
|
||||||
|
if(read16(bmpFile) == 0x4D42) { // BMP signature
|
||||||
|
Serial.print(F("File size: ")); Serial.println(read32(bmpFile));
|
||||||
|
(void)read32(bmpFile); // Read & ignore creator bytes
|
||||||
|
bmpImageoffset = read32(bmpFile); // Start of image data
|
||||||
|
Serial.print(F("Image Offset: ")); Serial.println(bmpImageoffset, DEC);
|
||||||
|
// Read DIB header
|
||||||
|
Serial.print(F("Header size: ")); Serial.println(read32(bmpFile));
|
||||||
|
bmpWidth = read32(bmpFile);
|
||||||
|
bmpHeight = read32(bmpFile);
|
||||||
|
if(read16(bmpFile) == 1) { // # planes -- must be '1'
|
||||||
|
bmpDepth = read16(bmpFile); // bits per pixel
|
||||||
|
Serial.print(F("Bit Depth: ")); Serial.println(bmpDepth);
|
||||||
|
if((bmpDepth == 24) && (read32(bmpFile) == 0)) { // 0 = uncompressed
|
||||||
|
|
||||||
|
goodBmp = true; // Supported BMP format -- proceed!
|
||||||
|
Serial.print(F("Image size: "));
|
||||||
|
Serial.print(bmpWidth);
|
||||||
|
Serial.print('x');
|
||||||
|
Serial.println(bmpHeight);
|
||||||
|
|
||||||
|
// BMP rows are padded (if needed) to 4-byte boundary
|
||||||
|
rowSize = (bmpWidth * 3 + 3) & ~3;
|
||||||
|
|
||||||
|
// If bmpHeight is negative, image is in top-down order.
|
||||||
|
// This is not canon but has been observed in the wild.
|
||||||
|
if(bmpHeight < 0) {
|
||||||
|
bmpHeight = -bmpHeight;
|
||||||
|
flip = false;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Crop area to be loaded
|
||||||
|
w = bmpWidth;
|
||||||
|
h = bmpHeight;
|
||||||
|
if((x+w-1) >= tft.width()) w = tft.width() - x;
|
||||||
|
if((y+h-1) >= tft.height()) h = tft.height() - y;
|
||||||
|
|
||||||
|
// Set TFT address window to clipped image bounds
|
||||||
|
tft.setAddrWindow(x, y, x+w-1, y+h-1);
|
||||||
|
|
||||||
|
for (row=0; row<h; row++) { // For each scanline...
|
||||||
|
|
||||||
|
// Seek to start of scan line. It might seem labor-
|
||||||
|
// intensive to be doing this on every line, but this
|
||||||
|
// method covers a lot of gritty details like cropping
|
||||||
|
// and scanline padding. Also, the seek only takes
|
||||||
|
// place if the file position actually needs to change
|
||||||
|
// (avoids a lot of cluster math in SD library).
|
||||||
|
if(flip) // Bitmap is stored bottom-to-top order (normal BMP)
|
||||||
|
pos = bmpImageoffset + (bmpHeight - 1 - row) * rowSize;
|
||||||
|
else // Bitmap is stored top-to-bottom
|
||||||
|
pos = bmpImageoffset + row * rowSize;
|
||||||
|
if(bmpFile.position() != pos) { // Need seek?
|
||||||
|
bmpFile.seek(pos);
|
||||||
|
buffidx = sizeof(sdbuffer); // Force buffer reload
|
||||||
|
}
|
||||||
|
|
||||||
|
for (col=0; col<w; col++) { // For each pixel...
|
||||||
|
// Time to read more pixel data?
|
||||||
|
if (buffidx >= sizeof(sdbuffer)) { // Indeed
|
||||||
|
bmpFile.read(sdbuffer, sizeof(sdbuffer));
|
||||||
|
buffidx = 0; // Set index to beginning
|
||||||
|
}
|
||||||
|
|
||||||
|
// Convert pixel from BMP to TFT format, push to display
|
||||||
|
b = sdbuffer[buffidx++];
|
||||||
|
g = sdbuffer[buffidx++];
|
||||||
|
r = sdbuffer[buffidx++];
|
||||||
|
tft.pushColor(tft.color565(r,g,b));
|
||||||
|
} // end pixel
|
||||||
|
} // end scanline
|
||||||
|
Serial.print(F("Loaded in "));
|
||||||
|
Serial.print(millis() - startTime);
|
||||||
|
Serial.println(" ms");
|
||||||
|
} // end goodBmp
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
bmpFile.close();
|
||||||
|
if(!goodBmp) Serial.println(F("BMP format not recognized."));
|
||||||
|
}
|
||||||
|
|
||||||
|
// These read 16- and 32-bit types from the SD card file.
|
||||||
|
// BMP data is stored little-endian, Arduino is little-endian too.
|
||||||
|
// May need to reverse subscript order if porting elsewhere.
|
||||||
|
|
||||||
|
uint16_t read16(File &f) {
|
||||||
|
uint16_t result;
|
||||||
|
((uint8_t *)&result)[0] = f.read(); // LSB
|
||||||
|
((uint8_t *)&result)[1] = f.read(); // MSB
|
||||||
|
return result;
|
||||||
|
}
|
||||||
|
|
||||||
|
uint32_t read32(File &f) {
|
||||||
|
uint32_t result;
|
||||||
|
((uint8_t *)&result)[0] = f.read(); // LSB
|
||||||
|
((uint8_t *)&result)[1] = f.read();
|
||||||
|
((uint8_t *)&result)[2] = f.read();
|
||||||
|
((uint8_t *)&result)[3] = f.read(); // MSB
|
||||||
|
return result;
|
||||||
|
}
|
|
@ -13,31 +13,36 @@
|
||||||
MIT license, all text above must be included in any redistribution
|
MIT license, all text above must be included in any redistribution
|
||||||
****************************************************/
|
****************************************************/
|
||||||
|
|
||||||
|
|
||||||
#include "SPI.h"
|
#include "SPI.h"
|
||||||
#include "Adafruit_GFX.h"
|
#include "Adafruit_GFX.h"
|
||||||
#include "TasmotaTFT.h"
|
#include "Adafruit_ILI9341.h"
|
||||||
|
|
||||||
#define TFT_DC 16
|
// For the Adafruit shield, these are the default.
|
||||||
#define TFT_CS 15
|
#define TFT_DC 9
|
||||||
|
#define TFT_CS 10
|
||||||
|
|
||||||
TasmotaTFT tft = TasmotaTFT(ILI9341, TFT_CS, TFT_DC);
|
// Use hardware SPI (on Uno, #13, #12, #11) and the above for CS/DC
|
||||||
|
Adafruit_ILI9341 tft = Adafruit_ILI9341(TFT_CS, TFT_DC);
|
||||||
|
// If using the breakout, change pins as desired
|
||||||
|
//Adafruit_ILI9341 tft = Adafruit_ILI9341(TFT_CS, TFT_DC, TFT_MOSI, TFT_CLK, TFT_RST, TFT_MISO);
|
||||||
|
|
||||||
void setup() {
|
void setup() {
|
||||||
Serial.begin(115200);
|
Serial.begin(9600);
|
||||||
Serial.println("ILI9341 Test!");
|
Serial.println("ILI9341 Test!");
|
||||||
|
|
||||||
tft.begin();
|
tft.begin();
|
||||||
|
|
||||||
// read diagnostics (optional but can help debug problems)
|
// read diagnostics (optional but can help debug problems)
|
||||||
uint8_t x = tft.readcommand8(TFT_RDMODE);
|
uint8_t x = tft.readcommand8(ILI9341_RDMODE);
|
||||||
Serial.print("Display Power Mode: 0x"); Serial.println(x, HEX);
|
Serial.print("Display Power Mode: 0x"); Serial.println(x, HEX);
|
||||||
x = tft.readcommand8(TFT_RDMADCTL);
|
x = tft.readcommand8(ILI9341_RDMADCTL);
|
||||||
Serial.print("MADCTL Mode: 0x"); Serial.println(x, HEX);
|
Serial.print("MADCTL Mode: 0x"); Serial.println(x, HEX);
|
||||||
x = tft.readcommand8(TFT_RDPIXFMT);
|
x = tft.readcommand8(ILI9341_RDPIXFMT);
|
||||||
Serial.print("Pixel Format: 0x"); Serial.println(x, HEX);
|
Serial.print("Pixel Format: 0x"); Serial.println(x, HEX);
|
||||||
x = tft.readcommand8(TFT_RDIMGFMT);
|
x = tft.readcommand8(ILI9341_RDIMGFMT);
|
||||||
Serial.print("Image Format: 0x"); Serial.println(x, HEX);
|
Serial.print("Image Format: 0x"); Serial.println(x, HEX);
|
||||||
x = tft.readcommand8(TFT_RDSELFDIAG);
|
x = tft.readcommand8(ILI9341_RDSELFDIAG);
|
||||||
Serial.print("Self Diagnostic: 0x"); Serial.println(x, HEX);
|
Serial.print("Self Diagnostic: 0x"); Serial.println(x, HEX);
|
||||||
|
|
||||||
Serial.println(F("Benchmark Time (microseconds)"));
|
Serial.println(F("Benchmark Time (microseconds)"));
|
||||||
|
@ -51,26 +56,26 @@ void setup() {
|
||||||
delay(3000);
|
delay(3000);
|
||||||
|
|
||||||
Serial.print(F("Lines "));
|
Serial.print(F("Lines "));
|
||||||
Serial.println(testLines(TFT_CYAN));
|
Serial.println(testLines(ILI9341_CYAN));
|
||||||
delay(500);
|
delay(500);
|
||||||
|
|
||||||
Serial.print(F("Horiz/Vert Lines "));
|
Serial.print(F("Horiz/Vert Lines "));
|
||||||
Serial.println(testFastLines(TFT_RED, TFT_BLUE));
|
Serial.println(testFastLines(ILI9341_RED, ILI9341_BLUE));
|
||||||
delay(500);
|
delay(500);
|
||||||
|
|
||||||
Serial.print(F("Rectangles (outline) "));
|
Serial.print(F("Rectangles (outline) "));
|
||||||
Serial.println(testRects(TFT_GREEN));
|
Serial.println(testRects(ILI9341_GREEN));
|
||||||
delay(500);
|
delay(500);
|
||||||
|
|
||||||
Serial.print(F("Rectangles (filled) "));
|
Serial.print(F("Rectangles (filled) "));
|
||||||
Serial.println(testFilledRects(TFT_YELLOW, TFT_MAGENTA));
|
Serial.println(testFilledRects(ILI9341_YELLOW, ILI9341_MAGENTA));
|
||||||
delay(500);
|
delay(500);
|
||||||
|
|
||||||
Serial.print(F("Circles (filled) "));
|
Serial.print(F("Circles (filled) "));
|
||||||
Serial.println(testFilledCircles(10, TFT_MAGENTA));
|
Serial.println(testFilledCircles(10, ILI9341_MAGENTA));
|
||||||
|
|
||||||
Serial.print(F("Circles (outline) "));
|
Serial.print(F("Circles (outline) "));
|
||||||
Serial.println(testCircles(10, TFT_WHITE));
|
Serial.println(testCircles(10, ILI9341_WHITE));
|
||||||
delay(500);
|
delay(500);
|
||||||
|
|
||||||
Serial.print(F("Triangles (outline) "));
|
Serial.print(F("Triangles (outline) "));
|
||||||
|
@ -104,31 +109,31 @@ void loop(void) {
|
||||||
|
|
||||||
unsigned long testFillScreen() {
|
unsigned long testFillScreen() {
|
||||||
unsigned long start = micros();
|
unsigned long start = micros();
|
||||||
tft.fillScreen(TFT_BLACK);
|
tft.fillScreen(ILI9341_BLACK);
|
||||||
yield();
|
yield();
|
||||||
tft.fillScreen(TFT_RED);
|
tft.fillScreen(ILI9341_RED);
|
||||||
yield();
|
yield();
|
||||||
tft.fillScreen(TFT_GREEN);
|
tft.fillScreen(ILI9341_GREEN);
|
||||||
yield();
|
yield();
|
||||||
tft.fillScreen(TFT_BLUE);
|
tft.fillScreen(ILI9341_BLUE);
|
||||||
yield();
|
yield();
|
||||||
tft.fillScreen(TFT_BLACK);
|
tft.fillScreen(ILI9341_BLACK);
|
||||||
yield();
|
yield();
|
||||||
return micros() - start;
|
return micros() - start;
|
||||||
}
|
}
|
||||||
|
|
||||||
unsigned long testText() {
|
unsigned long testText() {
|
||||||
tft.fillScreen(TFT_BLACK);
|
tft.fillScreen(ILI9341_BLACK);
|
||||||
unsigned long start = micros();
|
unsigned long start = micros();
|
||||||
tft.setCursor(0, 0);
|
tft.setCursor(0, 0);
|
||||||
tft.setTextColor(TFT_WHITE); tft.setTextSize(1);
|
tft.setTextColor(ILI9341_WHITE); tft.setTextSize(1);
|
||||||
tft.println("Hello World!");
|
tft.println("Hello World!");
|
||||||
tft.setTextColor(TFT_YELLOW); tft.setTextSize(2);
|
tft.setTextColor(ILI9341_YELLOW); tft.setTextSize(2);
|
||||||
tft.println(1234.56);
|
tft.println(1234.56);
|
||||||
tft.setTextColor(TFT_RED); tft.setTextSize(3);
|
tft.setTextColor(ILI9341_RED); tft.setTextSize(3);
|
||||||
tft.println(0xDEADBEEF, HEX);
|
tft.println(0xDEADBEEF, HEX);
|
||||||
tft.println();
|
tft.println();
|
||||||
tft.setTextColor(TFT_GREEN);
|
tft.setTextColor(ILI9341_GREEN);
|
||||||
tft.setTextSize(5);
|
tft.setTextSize(5);
|
||||||
tft.println("Groop");
|
tft.println("Groop");
|
||||||
tft.setTextSize(2);
|
tft.setTextSize(2);
|
||||||
|
@ -150,7 +155,7 @@ unsigned long testLines(uint16_t color) {
|
||||||
w = tft.width(),
|
w = tft.width(),
|
||||||
h = tft.height();
|
h = tft.height();
|
||||||
|
|
||||||
tft.fillScreen(TFT_BLACK);
|
tft.fillScreen(ILI9341_BLACK);
|
||||||
yield();
|
yield();
|
||||||
|
|
||||||
x1 = y1 = 0;
|
x1 = y1 = 0;
|
||||||
|
@ -162,7 +167,7 @@ unsigned long testLines(uint16_t color) {
|
||||||
t = micros() - start; // fillScreen doesn't count against timing
|
t = micros() - start; // fillScreen doesn't count against timing
|
||||||
|
|
||||||
yield();
|
yield();
|
||||||
tft.fillScreen(TFT_BLACK);
|
tft.fillScreen(ILI9341_BLACK);
|
||||||
yield();
|
yield();
|
||||||
|
|
||||||
x1 = w - 1;
|
x1 = w - 1;
|
||||||
|
@ -175,7 +180,7 @@ unsigned long testLines(uint16_t color) {
|
||||||
t += micros() - start;
|
t += micros() - start;
|
||||||
|
|
||||||
yield();
|
yield();
|
||||||
tft.fillScreen(TFT_BLACK);
|
tft.fillScreen(ILI9341_BLACK);
|
||||||
yield();
|
yield();
|
||||||
|
|
||||||
x1 = 0;
|
x1 = 0;
|
||||||
|
@ -188,7 +193,7 @@ unsigned long testLines(uint16_t color) {
|
||||||
t += micros() - start;
|
t += micros() - start;
|
||||||
|
|
||||||
yield();
|
yield();
|
||||||
tft.fillScreen(TFT_BLACK);
|
tft.fillScreen(ILI9341_BLACK);
|
||||||
yield();
|
yield();
|
||||||
|
|
||||||
x1 = w - 1;
|
x1 = w - 1;
|
||||||
|
@ -207,7 +212,7 @@ unsigned long testFastLines(uint16_t color1, uint16_t color2) {
|
||||||
unsigned long start;
|
unsigned long start;
|
||||||
int x, y, w = tft.width(), h = tft.height();
|
int x, y, w = tft.width(), h = tft.height();
|
||||||
|
|
||||||
tft.fillScreen(TFT_BLACK);
|
tft.fillScreen(ILI9341_BLACK);
|
||||||
start = micros();
|
start = micros();
|
||||||
for(y=0; y<h; y+=5) tft.drawFastHLine(0, y, w, color1);
|
for(y=0; y<h; y+=5) tft.drawFastHLine(0, y, w, color1);
|
||||||
for(x=0; x<w; x+=5) tft.drawFastVLine(x, 0, h, color2);
|
for(x=0; x<w; x+=5) tft.drawFastVLine(x, 0, h, color2);
|
||||||
|
@ -221,7 +226,7 @@ unsigned long testRects(uint16_t color) {
|
||||||
cx = tft.width() / 2,
|
cx = tft.width() / 2,
|
||||||
cy = tft.height() / 2;
|
cy = tft.height() / 2;
|
||||||
|
|
||||||
tft.fillScreen(TFT_BLACK);
|
tft.fillScreen(ILI9341_BLACK);
|
||||||
n = min(tft.width(), tft.height());
|
n = min(tft.width(), tft.height());
|
||||||
start = micros();
|
start = micros();
|
||||||
for(i=2; i<n; i+=6) {
|
for(i=2; i<n; i+=6) {
|
||||||
|
@ -238,7 +243,7 @@ unsigned long testFilledRects(uint16_t color1, uint16_t color2) {
|
||||||
cx = tft.width() / 2 - 1,
|
cx = tft.width() / 2 - 1,
|
||||||
cy = tft.height() / 2 - 1;
|
cy = tft.height() / 2 - 1;
|
||||||
|
|
||||||
tft.fillScreen(TFT_BLACK);
|
tft.fillScreen(ILI9341_BLACK);
|
||||||
n = min(tft.width(), tft.height());
|
n = min(tft.width(), tft.height());
|
||||||
for(i=n; i>0; i-=6) {
|
for(i=n; i>0; i-=6) {
|
||||||
i2 = i / 2;
|
i2 = i / 2;
|
||||||
|
@ -257,7 +262,7 @@ unsigned long testFilledCircles(uint8_t radius, uint16_t color) {
|
||||||
unsigned long start;
|
unsigned long start;
|
||||||
int x, y, w = tft.width(), h = tft.height(), r2 = radius * 2;
|
int x, y, w = tft.width(), h = tft.height(), r2 = radius * 2;
|
||||||
|
|
||||||
tft.fillScreen(TFT_BLACK);
|
tft.fillScreen(ILI9341_BLACK);
|
||||||
start = micros();
|
start = micros();
|
||||||
for(x=radius; x<w; x+=r2) {
|
for(x=radius; x<w; x+=r2) {
|
||||||
for(y=radius; y<h; y+=r2) {
|
for(y=radius; y<h; y+=r2) {
|
||||||
|
@ -291,7 +296,7 @@ unsigned long testTriangles() {
|
||||||
int n, i, cx = tft.width() / 2 - 1,
|
int n, i, cx = tft.width() / 2 - 1,
|
||||||
cy = tft.height() / 2 - 1;
|
cy = tft.height() / 2 - 1;
|
||||||
|
|
||||||
tft.fillScreen(TFT_BLACK);
|
tft.fillScreen(ILI9341_BLACK);
|
||||||
n = min(cx, cy);
|
n = min(cx, cy);
|
||||||
start = micros();
|
start = micros();
|
||||||
for(i=0; i<n; i+=5) {
|
for(i=0; i<n; i+=5) {
|
||||||
|
@ -310,7 +315,7 @@ unsigned long testFilledTriangles() {
|
||||||
int i, cx = tft.width() / 2 - 1,
|
int i, cx = tft.width() / 2 - 1,
|
||||||
cy = tft.height() / 2 - 1;
|
cy = tft.height() / 2 - 1;
|
||||||
|
|
||||||
tft.fillScreen(TFT_BLACK);
|
tft.fillScreen(ILI9341_BLACK);
|
||||||
start = micros();
|
start = micros();
|
||||||
for(i=min(cx,cy); i>10; i-=5) {
|
for(i=min(cx,cy); i>10; i-=5) {
|
||||||
start = micros();
|
start = micros();
|
||||||
|
@ -331,7 +336,7 @@ unsigned long testRoundRects() {
|
||||||
cx = tft.width() / 2 - 1,
|
cx = tft.width() / 2 - 1,
|
||||||
cy = tft.height() / 2 - 1;
|
cy = tft.height() / 2 - 1;
|
||||||
|
|
||||||
tft.fillScreen(TFT_BLACK);
|
tft.fillScreen(ILI9341_BLACK);
|
||||||
w = min(tft.width(), tft.height());
|
w = min(tft.width(), tft.height());
|
||||||
start = micros();
|
start = micros();
|
||||||
for(i=0; i<w; i+=6) {
|
for(i=0; i<w; i+=6) {
|
||||||
|
@ -348,7 +353,7 @@ unsigned long testFilledRoundRects() {
|
||||||
cx = tft.width() / 2 - 1,
|
cx = tft.width() / 2 - 1,
|
||||||
cy = tft.height() / 2 - 1;
|
cy = tft.height() / 2 - 1;
|
||||||
|
|
||||||
tft.fillScreen(TFT_BLACK);
|
tft.fillScreen(ILI9341_BLACK);
|
||||||
start = micros();
|
start = micros();
|
||||||
for(i=min(tft.width(), tft.height()); i>20; i-=6) {
|
for(i=min(tft.width(), tft.height()); i>20; i-=6) {
|
||||||
i2 = i / 2;
|
i2 = i / 2;
|
|
@ -0,0 +1,395 @@
|
||||||
|
/***************************************************
|
||||||
|
This is our GFX example for the Adafruit ILI9341 TFT FeatherWing
|
||||||
|
----> http://www.adafruit.com/products/3315
|
||||||
|
|
||||||
|
Check out the links above for our tutorials and wiring diagrams
|
||||||
|
|
||||||
|
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
|
||||||
|
****************************************************/
|
||||||
|
|
||||||
|
#include <SPI.h>
|
||||||
|
#include <Adafruit_GFX.h>
|
||||||
|
#include <Adafruit_ILI9341.h>
|
||||||
|
|
||||||
|
#ifdef ESP8266
|
||||||
|
#define STMPE_CS 16
|
||||||
|
#define TFT_CS 0
|
||||||
|
#define TFT_DC 15
|
||||||
|
#define SD_CS 2
|
||||||
|
#endif
|
||||||
|
#ifdef ESP32
|
||||||
|
#define STMPE_CS 32
|
||||||
|
#define TFT_CS 15
|
||||||
|
#define TFT_DC 33
|
||||||
|
#define SD_CS 14
|
||||||
|
#endif
|
||||||
|
#if defined (__AVR_ATmega32U4__) || defined(ARDUINO_SAMD_FEATHER_M0) || defined (__AVR_ATmega328P__)
|
||||||
|
#define STMPE_CS 6
|
||||||
|
#define TFT_CS 9
|
||||||
|
#define TFT_DC 10
|
||||||
|
#define SD_CS 5
|
||||||
|
#endif
|
||||||
|
#ifdef TEENSYDUINO
|
||||||
|
#define TFT_DC 10
|
||||||
|
#define TFT_CS 4
|
||||||
|
#define STMPE_CS 3
|
||||||
|
#define SD_CS 8
|
||||||
|
#endif
|
||||||
|
#ifdef ARDUINO_STM32_FEATHER
|
||||||
|
#define TFT_DC PB4
|
||||||
|
#define TFT_CS PA15
|
||||||
|
#define STMPE_CS PC7
|
||||||
|
#define SD_CS PC5
|
||||||
|
#endif
|
||||||
|
#ifdef ARDUINO_NRF52_FEATHER /* BSP 0.6.5 and higher! */
|
||||||
|
#define TFT_DC 11
|
||||||
|
#define TFT_CS 31
|
||||||
|
#define STMPE_CS 30
|
||||||
|
#define SD_CS 27
|
||||||
|
#endif
|
||||||
|
|
||||||
|
Adafruit_ILI9341 tft = Adafruit_ILI9341(TFT_CS, TFT_DC);
|
||||||
|
|
||||||
|
void setup() {
|
||||||
|
Serial.begin(115200);
|
||||||
|
|
||||||
|
delay(10);
|
||||||
|
Serial.println("FeatherWing TFT Test!");
|
||||||
|
|
||||||
|
tft.begin();
|
||||||
|
|
||||||
|
// read diagnostics (optional but can help debug problems)
|
||||||
|
uint8_t x = tft.readcommand8(ILI9341_RDMODE);
|
||||||
|
Serial.print("Display Power Mode: 0x"); Serial.println(x, HEX);
|
||||||
|
x = tft.readcommand8(ILI9341_RDMADCTL);
|
||||||
|
Serial.print("MADCTL Mode: 0x"); Serial.println(x, HEX);
|
||||||
|
x = tft.readcommand8(ILI9341_RDPIXFMT);
|
||||||
|
Serial.print("Pixel Format: 0x"); Serial.println(x, HEX);
|
||||||
|
x = tft.readcommand8(ILI9341_RDIMGFMT);
|
||||||
|
Serial.print("Image Format: 0x"); Serial.println(x, HEX);
|
||||||
|
x = tft.readcommand8(ILI9341_RDSELFDIAG);
|
||||||
|
Serial.print("Self Diagnostic: 0x"); Serial.println(x, HEX);
|
||||||
|
|
||||||
|
Serial.println(F("Benchmark Time (microseconds)"));
|
||||||
|
delay(10);
|
||||||
|
Serial.print(F("Screen fill "));
|
||||||
|
Serial.println(testFillScreen());
|
||||||
|
delay(500);
|
||||||
|
|
||||||
|
Serial.print(F("Text "));
|
||||||
|
Serial.println(testText());
|
||||||
|
delay(3000);
|
||||||
|
|
||||||
|
Serial.print(F("Lines "));
|
||||||
|
Serial.println(testLines(ILI9341_CYAN));
|
||||||
|
delay(500);
|
||||||
|
|
||||||
|
Serial.print(F("Horiz/Vert Lines "));
|
||||||
|
Serial.println(testFastLines(ILI9341_RED, ILI9341_BLUE));
|
||||||
|
delay(500);
|
||||||
|
|
||||||
|
Serial.print(F("Rectangles (outline) "));
|
||||||
|
Serial.println(testRects(ILI9341_GREEN));
|
||||||
|
delay(500);
|
||||||
|
|
||||||
|
Serial.print(F("Rectangles (filled) "));
|
||||||
|
Serial.println(testFilledRects(ILI9341_YELLOW, ILI9341_MAGENTA));
|
||||||
|
delay(500);
|
||||||
|
|
||||||
|
Serial.print(F("Circles (filled) "));
|
||||||
|
Serial.println(testFilledCircles(10, ILI9341_MAGENTA));
|
||||||
|
|
||||||
|
Serial.print(F("Circles (outline) "));
|
||||||
|
Serial.println(testCircles(10, ILI9341_WHITE));
|
||||||
|
delay(500);
|
||||||
|
|
||||||
|
Serial.print(F("Triangles (outline) "));
|
||||||
|
Serial.println(testTriangles());
|
||||||
|
delay(500);
|
||||||
|
|
||||||
|
Serial.print(F("Triangles (filled) "));
|
||||||
|
Serial.println(testFilledTriangles());
|
||||||
|
delay(500);
|
||||||
|
|
||||||
|
Serial.print(F("Rounded rects (outline) "));
|
||||||
|
Serial.println(testRoundRects());
|
||||||
|
delay(500);
|
||||||
|
|
||||||
|
Serial.print(F("Rounded rects (filled) "));
|
||||||
|
Serial.println(testFilledRoundRects());
|
||||||
|
delay(500);
|
||||||
|
|
||||||
|
Serial.println(F("Done!"));
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
void loop(void) {
|
||||||
|
for(uint8_t rotation=0; rotation<4; rotation++) {
|
||||||
|
tft.setRotation(rotation);
|
||||||
|
testText();
|
||||||
|
delay(1000);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
unsigned long testFillScreen() {
|
||||||
|
unsigned long start = micros();
|
||||||
|
tft.fillScreen(ILI9341_BLACK);
|
||||||
|
yield();
|
||||||
|
tft.fillScreen(ILI9341_RED);
|
||||||
|
yield();
|
||||||
|
tft.fillScreen(ILI9341_GREEN);
|
||||||
|
yield();
|
||||||
|
tft.fillScreen(ILI9341_BLUE);
|
||||||
|
yield();
|
||||||
|
tft.fillScreen(ILI9341_BLACK);
|
||||||
|
yield();
|
||||||
|
return micros() - start;
|
||||||
|
}
|
||||||
|
|
||||||
|
unsigned long testText() {
|
||||||
|
tft.fillScreen(ILI9341_BLACK);
|
||||||
|
unsigned long start = micros();
|
||||||
|
tft.setCursor(0, 0);
|
||||||
|
tft.setTextColor(ILI9341_WHITE); tft.setTextSize(1);
|
||||||
|
tft.println("Hello World!");
|
||||||
|
tft.setTextColor(ILI9341_YELLOW); tft.setTextSize(2);
|
||||||
|
tft.println(1234.56);
|
||||||
|
tft.setTextColor(ILI9341_RED); tft.setTextSize(3);
|
||||||
|
tft.println(0xDEADBEEF, HEX);
|
||||||
|
tft.println();
|
||||||
|
tft.setTextColor(ILI9341_GREEN);
|
||||||
|
tft.setTextSize(5);
|
||||||
|
tft.println("Groop");
|
||||||
|
tft.setTextSize(2);
|
||||||
|
tft.println("I implore thee,");
|
||||||
|
tft.setTextSize(1);
|
||||||
|
tft.println("my foonting turlingdromes.");
|
||||||
|
tft.println("And hooptiously drangle me");
|
||||||
|
tft.println("with crinkly bindlewurdles,");
|
||||||
|
tft.println("Or I will rend thee");
|
||||||
|
tft.println("in the gobberwarts");
|
||||||
|
tft.println("with my blurglecruncheon,");
|
||||||
|
tft.println("see if I don't!");
|
||||||
|
return micros() - start;
|
||||||
|
}
|
||||||
|
|
||||||
|
unsigned long testLines(uint16_t color) {
|
||||||
|
unsigned long start, t;
|
||||||
|
int x1, y1, x2, y2,
|
||||||
|
w = tft.width(),
|
||||||
|
h = tft.height();
|
||||||
|
|
||||||
|
tft.fillScreen(ILI9341_BLACK);
|
||||||
|
yield();
|
||||||
|
|
||||||
|
x1 = y1 = 0;
|
||||||
|
y2 = h - 1;
|
||||||
|
start = micros();
|
||||||
|
for(x2=0; x2<w; x2+=6) tft.drawLine(x1, y1, x2, y2, color);
|
||||||
|
x2 = w - 1;
|
||||||
|
for(y2=0; y2<h; y2+=6) tft.drawLine(x1, y1, x2, y2, color);
|
||||||
|
t = micros() - start; // fillScreen doesn't count against timing
|
||||||
|
|
||||||
|
yield();
|
||||||
|
tft.fillScreen(ILI9341_BLACK);
|
||||||
|
yield();
|
||||||
|
|
||||||
|
x1 = w - 1;
|
||||||
|
y1 = 0;
|
||||||
|
y2 = h - 1;
|
||||||
|
start = micros();
|
||||||
|
for(x2=0; x2<w; x2+=6) tft.drawLine(x1, y1, x2, y2, color);
|
||||||
|
x2 = 0;
|
||||||
|
for(y2=0; y2<h; y2+=6) tft.drawLine(x1, y1, x2, y2, color);
|
||||||
|
t += micros() - start;
|
||||||
|
|
||||||
|
yield();
|
||||||
|
tft.fillScreen(ILI9341_BLACK);
|
||||||
|
yield();
|
||||||
|
|
||||||
|
x1 = 0;
|
||||||
|
y1 = h - 1;
|
||||||
|
y2 = 0;
|
||||||
|
start = micros();
|
||||||
|
for(x2=0; x2<w; x2+=6) tft.drawLine(x1, y1, x2, y2, color);
|
||||||
|
x2 = w - 1;
|
||||||
|
for(y2=0; y2<h; y2+=6) tft.drawLine(x1, y1, x2, y2, color);
|
||||||
|
t += micros() - start;
|
||||||
|
|
||||||
|
yield();
|
||||||
|
tft.fillScreen(ILI9341_BLACK);
|
||||||
|
yield();
|
||||||
|
|
||||||
|
x1 = w - 1;
|
||||||
|
y1 = h - 1;
|
||||||
|
y2 = 0;
|
||||||
|
start = micros();
|
||||||
|
for(x2=0; x2<w; x2+=6) tft.drawLine(x1, y1, x2, y2, color);
|
||||||
|
x2 = 0;
|
||||||
|
for(y2=0; y2<h; y2+=6) tft.drawLine(x1, y1, x2, y2, color);
|
||||||
|
|
||||||
|
yield();
|
||||||
|
return micros() - start;
|
||||||
|
}
|
||||||
|
|
||||||
|
unsigned long testFastLines(uint16_t color1, uint16_t color2) {
|
||||||
|
unsigned long start;
|
||||||
|
int x, y, w = tft.width(), h = tft.height();
|
||||||
|
|
||||||
|
tft.fillScreen(ILI9341_BLACK);
|
||||||
|
start = micros();
|
||||||
|
for(y=0; y<h; y+=5) tft.drawFastHLine(0, y, w, color1);
|
||||||
|
for(x=0; x<w; x+=5) tft.drawFastVLine(x, 0, h, color2);
|
||||||
|
|
||||||
|
return micros() - start;
|
||||||
|
}
|
||||||
|
|
||||||
|
unsigned long testRects(uint16_t color) {
|
||||||
|
unsigned long start;
|
||||||
|
int n, i, i2,
|
||||||
|
cx = tft.width() / 2,
|
||||||
|
cy = tft.height() / 2;
|
||||||
|
|
||||||
|
tft.fillScreen(ILI9341_BLACK);
|
||||||
|
n = min(tft.width(), tft.height());
|
||||||
|
start = micros();
|
||||||
|
for(i=2; i<n; i+=6) {
|
||||||
|
i2 = i / 2;
|
||||||
|
tft.drawRect(cx-i2, cy-i2, i, i, color);
|
||||||
|
}
|
||||||
|
|
||||||
|
return micros() - start;
|
||||||
|
}
|
||||||
|
|
||||||
|
unsigned long testFilledRects(uint16_t color1, uint16_t color2) {
|
||||||
|
unsigned long start, t = 0;
|
||||||
|
int n, i, i2,
|
||||||
|
cx = tft.width() / 2 - 1,
|
||||||
|
cy = tft.height() / 2 - 1;
|
||||||
|
|
||||||
|
tft.fillScreen(ILI9341_BLACK);
|
||||||
|
n = min(tft.width(), tft.height());
|
||||||
|
for(i=n; i>0; i-=6) {
|
||||||
|
i2 = i / 2;
|
||||||
|
start = micros();
|
||||||
|
tft.fillRect(cx-i2, cy-i2, i, i, color1);
|
||||||
|
t += micros() - start;
|
||||||
|
// Outlines are not included in timing results
|
||||||
|
tft.drawRect(cx-i2, cy-i2, i, i, color2);
|
||||||
|
yield();
|
||||||
|
}
|
||||||
|
|
||||||
|
return t;
|
||||||
|
}
|
||||||
|
|
||||||
|
unsigned long testFilledCircles(uint8_t radius, uint16_t color) {
|
||||||
|
unsigned long start;
|
||||||
|
int x, y, w = tft.width(), h = tft.height(), r2 = radius * 2;
|
||||||
|
|
||||||
|
tft.fillScreen(ILI9341_BLACK);
|
||||||
|
start = micros();
|
||||||
|
for(x=radius; x<w; x+=r2) {
|
||||||
|
for(y=radius; y<h; y+=r2) {
|
||||||
|
tft.fillCircle(x, y, radius, color);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return micros() - start;
|
||||||
|
}
|
||||||
|
|
||||||
|
unsigned long testCircles(uint8_t radius, uint16_t color) {
|
||||||
|
unsigned long start;
|
||||||
|
int x, y, r2 = radius * 2,
|
||||||
|
w = tft.width() + radius,
|
||||||
|
h = tft.height() + radius;
|
||||||
|
|
||||||
|
// Screen is not cleared for this one -- this is
|
||||||
|
// intentional and does not affect the reported time.
|
||||||
|
start = micros();
|
||||||
|
for(x=0; x<w; x+=r2) {
|
||||||
|
for(y=0; y<h; y+=r2) {
|
||||||
|
tft.drawCircle(x, y, radius, color);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return micros() - start;
|
||||||
|
}
|
||||||
|
|
||||||
|
unsigned long testTriangles() {
|
||||||
|
unsigned long start;
|
||||||
|
int n, i, cx = tft.width() / 2 - 1,
|
||||||
|
cy = tft.height() / 2 - 1;
|
||||||
|
|
||||||
|
tft.fillScreen(ILI9341_BLACK);
|
||||||
|
n = min(cx, cy);
|
||||||
|
start = micros();
|
||||||
|
for(i=0; i<n; i+=5) {
|
||||||
|
tft.drawTriangle(
|
||||||
|
cx , cy - i, // peak
|
||||||
|
cx - i, cy + i, // bottom left
|
||||||
|
cx + i, cy + i, // bottom right
|
||||||
|
tft.color565(i, i, i));
|
||||||
|
}
|
||||||
|
|
||||||
|
return micros() - start;
|
||||||
|
}
|
||||||
|
|
||||||
|
unsigned long testFilledTriangles() {
|
||||||
|
unsigned long start, t = 0;
|
||||||
|
int i, cx = tft.width() / 2 - 1,
|
||||||
|
cy = tft.height() / 2 - 1;
|
||||||
|
|
||||||
|
tft.fillScreen(ILI9341_BLACK);
|
||||||
|
start = micros();
|
||||||
|
for(i=min(cx,cy); i>10; i-=5) {
|
||||||
|
start = micros();
|
||||||
|
tft.fillTriangle(cx, cy - i, cx - i, cy + i, cx + i, cy + i,
|
||||||
|
tft.color565(0, i*10, i*10));
|
||||||
|
t += micros() - start;
|
||||||
|
tft.drawTriangle(cx, cy - i, cx - i, cy + i, cx + i, cy + i,
|
||||||
|
tft.color565(i*10, i*10, 0));
|
||||||
|
yield();
|
||||||
|
}
|
||||||
|
|
||||||
|
return t;
|
||||||
|
}
|
||||||
|
|
||||||
|
unsigned long testRoundRects() {
|
||||||
|
unsigned long start;
|
||||||
|
int w, i, i2,
|
||||||
|
cx = tft.width() / 2 - 1,
|
||||||
|
cy = tft.height() / 2 - 1;
|
||||||
|
|
||||||
|
tft.fillScreen(ILI9341_BLACK);
|
||||||
|
w = min(tft.width(), tft.height());
|
||||||
|
start = micros();
|
||||||
|
for(i=0; i<w; i+=6) {
|
||||||
|
i2 = i / 2;
|
||||||
|
tft.drawRoundRect(cx-i2, cy-i2, i, i, i/8, tft.color565(i, 0, 0));
|
||||||
|
}
|
||||||
|
|
||||||
|
return micros() - start;
|
||||||
|
}
|
||||||
|
|
||||||
|
unsigned long testFilledRoundRects() {
|
||||||
|
unsigned long start;
|
||||||
|
int i, i2,
|
||||||
|
cx = tft.width() / 2 - 1,
|
||||||
|
cy = tft.height() / 2 - 1;
|
||||||
|
|
||||||
|
tft.fillScreen(ILI9341_BLACK);
|
||||||
|
start = micros();
|
||||||
|
for(i=min(tft.width(), tft.height()); i>20; i-=6) {
|
||||||
|
i2 = i / 2;
|
||||||
|
tft.fillRoundRect(cx-i2, cy-i2, i, i, i/8, tft.color565(0, i, 0));
|
||||||
|
yield();
|
||||||
|
}
|
||||||
|
|
||||||
|
return micros() - start;
|
||||||
|
}
|
|
@ -0,0 +1,125 @@
|
||||||
|
//This example implements a simple sliding On/Off button. The example
|
||||||
|
// demonstrates drawing and touch operations.
|
||||||
|
//
|
||||||
|
//Thanks to Adafruit forums member Asteroid for the original sketch!
|
||||||
|
//
|
||||||
|
#include <Adafruit_GFX.h>
|
||||||
|
#include <SPI.h>
|
||||||
|
#include <Wire.h>
|
||||||
|
#include <Adafruit_ILI9341.h>
|
||||||
|
#include <Adafruit_STMPE610.h>
|
||||||
|
|
||||||
|
// This is calibration data for the raw touch data to the screen coordinates
|
||||||
|
#define TS_MINX 150
|
||||||
|
#define TS_MINY 130
|
||||||
|
#define TS_MAXX 3800
|
||||||
|
#define TS_MAXY 4000
|
||||||
|
|
||||||
|
#define STMPE_CS 8
|
||||||
|
Adafruit_STMPE610 ts = Adafruit_STMPE610(STMPE_CS);
|
||||||
|
#define TFT_CS 10
|
||||||
|
#define TFT_DC 9
|
||||||
|
Adafruit_ILI9341 tft = Adafruit_ILI9341(TFT_CS, TFT_DC);
|
||||||
|
|
||||||
|
boolean RecordOn = false;
|
||||||
|
|
||||||
|
#define FRAME_X 210
|
||||||
|
#define FRAME_Y 180
|
||||||
|
#define FRAME_W 100
|
||||||
|
#define FRAME_H 50
|
||||||
|
|
||||||
|
#define REDBUTTON_X FRAME_X
|
||||||
|
#define REDBUTTON_Y FRAME_Y
|
||||||
|
#define REDBUTTON_W (FRAME_W/2)
|
||||||
|
#define REDBUTTON_H FRAME_H
|
||||||
|
|
||||||
|
#define GREENBUTTON_X (REDBUTTON_X + REDBUTTON_W)
|
||||||
|
#define GREENBUTTON_Y FRAME_Y
|
||||||
|
#define GREENBUTTON_W (FRAME_W/2)
|
||||||
|
#define GREENBUTTON_H FRAME_H
|
||||||
|
|
||||||
|
void drawFrame()
|
||||||
|
{
|
||||||
|
tft.drawRect(FRAME_X, FRAME_Y, FRAME_W, FRAME_H, ILI9341_BLACK);
|
||||||
|
}
|
||||||
|
|
||||||
|
void redBtn()
|
||||||
|
{
|
||||||
|
tft.fillRect(REDBUTTON_X, REDBUTTON_Y, REDBUTTON_W, REDBUTTON_H, ILI9341_RED);
|
||||||
|
tft.fillRect(GREENBUTTON_X, GREENBUTTON_Y, GREENBUTTON_W, GREENBUTTON_H, ILI9341_BLUE);
|
||||||
|
drawFrame();
|
||||||
|
tft.setCursor(GREENBUTTON_X + 6 , GREENBUTTON_Y + (GREENBUTTON_H/2));
|
||||||
|
tft.setTextColor(ILI9341_WHITE);
|
||||||
|
tft.setTextSize(2);
|
||||||
|
tft.println("ON");
|
||||||
|
RecordOn = false;
|
||||||
|
}
|
||||||
|
|
||||||
|
void greenBtn()
|
||||||
|
{
|
||||||
|
tft.fillRect(GREENBUTTON_X, GREENBUTTON_Y, GREENBUTTON_W, GREENBUTTON_H, ILI9341_GREEN);
|
||||||
|
tft.fillRect(REDBUTTON_X, REDBUTTON_Y, REDBUTTON_W, REDBUTTON_H, ILI9341_BLUE);
|
||||||
|
drawFrame();
|
||||||
|
tft.setCursor(REDBUTTON_X + 6 , REDBUTTON_Y + (REDBUTTON_H/2));
|
||||||
|
tft.setTextColor(ILI9341_WHITE);
|
||||||
|
tft.setTextSize(2);
|
||||||
|
tft.println("OFF");
|
||||||
|
RecordOn = true;
|
||||||
|
}
|
||||||
|
|
||||||
|
void setup(void)
|
||||||
|
{
|
||||||
|
Serial.begin(9600);
|
||||||
|
tft.begin();
|
||||||
|
if (!ts.begin()) {
|
||||||
|
Serial.println("Unable to start touchscreen.");
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
Serial.println("Touchscreen started.");
|
||||||
|
}
|
||||||
|
|
||||||
|
tft.fillScreen(ILI9341_BLUE);
|
||||||
|
// origin = left,top landscape (USB left upper)
|
||||||
|
tft.setRotation(1);
|
||||||
|
redBtn();
|
||||||
|
}
|
||||||
|
|
||||||
|
void loop()
|
||||||
|
{
|
||||||
|
// See if there's any touch data for us
|
||||||
|
if (!ts.bufferEmpty())
|
||||||
|
{
|
||||||
|
// Retrieve a point
|
||||||
|
TS_Point p = ts.getPoint();
|
||||||
|
// Scale using the calibration #'s
|
||||||
|
// and rotate coordinate system
|
||||||
|
p.x = map(p.x, TS_MINY, TS_MAXY, 0, tft.height());
|
||||||
|
p.y = map(p.y, TS_MINX, TS_MAXX, 0, tft.width());
|
||||||
|
int y = tft.height() - p.x;
|
||||||
|
int x = p.y;
|
||||||
|
|
||||||
|
if (RecordOn)
|
||||||
|
{
|
||||||
|
if((x > REDBUTTON_X) && (x < (REDBUTTON_X + REDBUTTON_W))) {
|
||||||
|
if ((y > REDBUTTON_Y) && (y <= (REDBUTTON_Y + REDBUTTON_H))) {
|
||||||
|
Serial.println("Red btn hit");
|
||||||
|
redBtn();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else //Record is off (RecordOn == false)
|
||||||
|
{
|
||||||
|
if((x > GREENBUTTON_X) && (x < (GREENBUTTON_X + GREENBUTTON_W))) {
|
||||||
|
if ((y > GREENBUTTON_Y) && (y <= (GREENBUTTON_Y + GREENBUTTON_H))) {
|
||||||
|
Serial.println("Green btn hit");
|
||||||
|
greenBtn();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
Serial.println(RecordOn);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
|
@ -0,0 +1,133 @@
|
||||||
|
//This example implements a simple sliding On/Off button. The example
|
||||||
|
// demonstrates drawing and touch operations.
|
||||||
|
//
|
||||||
|
//Thanks to Adafruit forums member Asteroid for the original sketch!
|
||||||
|
//
|
||||||
|
#include <Adafruit_GFX.h>
|
||||||
|
#include <SPI.h>
|
||||||
|
#include <Wire.h>
|
||||||
|
#include <Adafruit_ILI9341.h>
|
||||||
|
#include <TouchScreen.h>
|
||||||
|
|
||||||
|
//Touchscreen X+ X- Y+ Y- pins
|
||||||
|
#define YP A3 // must be an analog pin, use "An" notation!
|
||||||
|
#define XM A2 // must be an analog pin, use "An" notation!
|
||||||
|
#define YM 5 // can be a digital pin
|
||||||
|
#define XP 4 // can be a digital pin
|
||||||
|
|
||||||
|
// This is calibration data for the raw touch data to the screen coordinates
|
||||||
|
#define TS_MINX 150
|
||||||
|
#define TS_MINY 120
|
||||||
|
#define TS_MAXX 920
|
||||||
|
#define TS_MAXY 940
|
||||||
|
|
||||||
|
#define MINPRESSURE 10
|
||||||
|
#define MAXPRESSURE 1000
|
||||||
|
|
||||||
|
// For better pressure precision, we need to know the resistance
|
||||||
|
// between X+ and X- Use any multimeter to read it
|
||||||
|
// For the one we're using, its 300 ohms across the X plate
|
||||||
|
TouchScreen ts = TouchScreen(XP, YP, XM, YM, 300);
|
||||||
|
|
||||||
|
|
||||||
|
#define TFT_CS 10
|
||||||
|
#define TFT_DC 9
|
||||||
|
Adafruit_ILI9341 tft = Adafruit_ILI9341(TFT_CS, TFT_DC);
|
||||||
|
|
||||||
|
boolean RecordOn = false;
|
||||||
|
|
||||||
|
#define FRAME_X 210
|
||||||
|
#define FRAME_Y 180
|
||||||
|
#define FRAME_W 100
|
||||||
|
#define FRAME_H 50
|
||||||
|
|
||||||
|
#define REDBUTTON_X FRAME_X
|
||||||
|
#define REDBUTTON_Y FRAME_Y
|
||||||
|
#define REDBUTTON_W (FRAME_W/2)
|
||||||
|
#define REDBUTTON_H FRAME_H
|
||||||
|
|
||||||
|
#define GREENBUTTON_X (REDBUTTON_X + REDBUTTON_W)
|
||||||
|
#define GREENBUTTON_Y FRAME_Y
|
||||||
|
#define GREENBUTTON_W (FRAME_W/2)
|
||||||
|
#define GREENBUTTON_H FRAME_H
|
||||||
|
|
||||||
|
void drawFrame()
|
||||||
|
{
|
||||||
|
tft.drawRect(FRAME_X, FRAME_Y, FRAME_W, FRAME_H, ILI9341_BLACK);
|
||||||
|
}
|
||||||
|
|
||||||
|
void redBtn()
|
||||||
|
{
|
||||||
|
tft.fillRect(REDBUTTON_X, REDBUTTON_Y, REDBUTTON_W, REDBUTTON_H, ILI9341_RED);
|
||||||
|
tft.fillRect(GREENBUTTON_X, GREENBUTTON_Y, GREENBUTTON_W, GREENBUTTON_H, ILI9341_BLUE);
|
||||||
|
drawFrame();
|
||||||
|
tft.setCursor(GREENBUTTON_X + 6 , GREENBUTTON_Y + (GREENBUTTON_H/2));
|
||||||
|
tft.setTextColor(ILI9341_WHITE);
|
||||||
|
tft.setTextSize(2);
|
||||||
|
tft.println("ON");
|
||||||
|
RecordOn = false;
|
||||||
|
}
|
||||||
|
|
||||||
|
void greenBtn()
|
||||||
|
{
|
||||||
|
tft.fillRect(GREENBUTTON_X, GREENBUTTON_Y, GREENBUTTON_W, GREENBUTTON_H, ILI9341_GREEN);
|
||||||
|
tft.fillRect(REDBUTTON_X, REDBUTTON_Y, REDBUTTON_W, REDBUTTON_H, ILI9341_BLUE);
|
||||||
|
drawFrame();
|
||||||
|
tft.setCursor(REDBUTTON_X + 6 , REDBUTTON_Y + (REDBUTTON_H/2));
|
||||||
|
tft.setTextColor(ILI9341_WHITE);
|
||||||
|
tft.setTextSize(2);
|
||||||
|
tft.println("OFF");
|
||||||
|
RecordOn = true;
|
||||||
|
}
|
||||||
|
|
||||||
|
void setup(void)
|
||||||
|
{
|
||||||
|
Serial.begin(9600);
|
||||||
|
tft.begin();
|
||||||
|
|
||||||
|
tft.fillScreen(ILI9341_BLUE);
|
||||||
|
// origin = left,top landscape (USB left upper)
|
||||||
|
tft.setRotation(1);
|
||||||
|
redBtn();
|
||||||
|
}
|
||||||
|
|
||||||
|
void loop()
|
||||||
|
{
|
||||||
|
// Retrieve a point
|
||||||
|
TSPoint p = ts.getPoint();
|
||||||
|
|
||||||
|
// See if there's any touch data for us
|
||||||
|
if (p.z > MINPRESSURE && p.z < MAXPRESSURE)
|
||||||
|
{
|
||||||
|
// Scale using the calibration #'s
|
||||||
|
// and rotate coordinate system
|
||||||
|
p.x = map(p.x, TS_MINY, TS_MAXY, 0, tft.height());
|
||||||
|
p.y = map(p.y, TS_MINX, TS_MAXX, 0, tft.width());
|
||||||
|
int y = tft.height() - p.x;
|
||||||
|
int x = p.y;
|
||||||
|
|
||||||
|
if (RecordOn)
|
||||||
|
{
|
||||||
|
if((x > REDBUTTON_X) && (x < (REDBUTTON_X + REDBUTTON_W))) {
|
||||||
|
if ((y > REDBUTTON_Y) && (y <= (REDBUTTON_Y + REDBUTTON_H))) {
|
||||||
|
Serial.println("Red btn hit");
|
||||||
|
redBtn();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else //Record is off (RecordOn == false)
|
||||||
|
{
|
||||||
|
if((x > GREENBUTTON_X) && (x < (GREENBUTTON_X + GREENBUTTON_W))) {
|
||||||
|
if ((y > GREENBUTTON_Y) && (y <= (GREENBUTTON_Y + GREENBUTTON_H))) {
|
||||||
|
Serial.println("Green btn hit");
|
||||||
|
greenBtn();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
Serial.println(RecordOn);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
|
@ -0,0 +1,861 @@
|
||||||
|
#define DRAGON_WIDTH 110
|
||||||
|
#define DRAGON_HEIGHT 70
|
||||||
|
|
||||||
|
const PROGMEM uint16_t dragonBitmap[DRAGON_WIDTH * DRAGON_HEIGHT] = {
|
||||||
|
0XFFFF, 0XFFFF, 0XFFFF, 0XFFFF, 0XFFFF, 0XFFFF, 0XFFFF, 0XFFFF, 0XFFFF,
|
||||||
|
0XFFFF, 0XFFFF, 0XFFFF, 0XFFFF, 0XFFFF, 0XFFFF, 0XFFFF, 0XFFFF, 0XFFFF,
|
||||||
|
0XFFFF, 0XFFFF, 0XFFFF, 0XFFFF, 0XFFFF, 0XFFFF, 0XFFFF, 0XFFFF, 0XFFFF,
|
||||||
|
0XFFFF, 0XFFFF, 0XFFFF, 0XFFFF, 0XFFFF, 0XFFFF, 0XFFFF, 0XFFFF, 0XFFFF,
|
||||||
|
0XFFFF, 0XFFFF, 0XFFFF, 0XFFFF, 0XFFFF, 0XFFFF, 0XFFFF, 0XFFFF, 0XFFFF,
|
||||||
|
0XFFFF, 0XFFFF, 0XFFFF, 0XFFFF, 0XFFFF, 0XFFFF, 0XFFFF, 0XFFFF, 0XFFFF,
|
||||||
|
0XFFFF, 0XFFFF, 0XFFFF, 0XFFFF, 0XFFFF, 0XFFFF, 0XFFFF, 0XFFFF, 0XFFFF,
|
||||||
|
0XFFFF, 0XFFFF, 0XFFFF, 0XFFFF, 0XFFFF, 0XFFFF, 0XFFFF, 0XFFFF, 0XFFFF,
|
||||||
|
0XFFFF, 0XFFFF, 0XFFFF, 0XFFFF, 0XFFFF, 0XFFFF, 0XFFFF, 0XFFFF, 0XFFFF,
|
||||||
|
0XFFFF, 0XFFFF, 0XFFFF, 0XFFFF, 0XFFFF, 0XFFFF, 0XFFFF, 0XFFFF, 0XFFFF,
|
||||||
|
0XFFFF, 0XFFFF, 0XFFFF, 0XFFFF, 0XFFFF, 0XFFFF, 0XFFFF, 0XFFFF, 0XFFFF,
|
||||||
|
0XFFFF, 0XFFFF, 0XFFFF, 0XFFFF, 0XFFFF, 0XFFFF, 0XFFFF, 0XFFFF, 0XFFFF,
|
||||||
|
0XFFFF, 0XFFFF, 0XFFFF, 0XFFFF, 0XFFFF, 0XFFFF, 0XFFFF, 0XFFFF, 0XFFFF,
|
||||||
|
0XFFFF, 0XFFFF, 0XFFFF, 0XFFFF, 0XFFFF, 0XFFFF, 0XFFFF, 0XFFFF, 0XFFFF,
|
||||||
|
0XFFFF, 0XFFFF, 0XFFFF, 0XFFFF, 0XFFFF, 0XFFFF, 0XFFFF, 0XFFFF, 0XFFFF,
|
||||||
|
0XFFFF, 0XFFFF, 0XFFFF, 0XFFFF, 0XFFFF, 0XFFFF, 0XFFFF, 0XFFFF, 0XFFFF,
|
||||||
|
0XFFFF, 0XFFFF, 0XFFFF, 0XFFFF, 0XFFFF, 0XFFFF, 0XFFFF, 0XFFFF, 0XFFFF,
|
||||||
|
0XFFFF, 0XFFFF, 0XFFFF, 0XFFFF, 0XFFFF, 0XFFFF, 0XFFFF, 0XFFFF, 0XFFFF,
|
||||||
|
0XFFFF, 0XFFFF, 0XFFFF, 0XFFFF, 0XFFFF, 0XFFFF, 0XFFFF, 0XFFFF, 0XFFFF,
|
||||||
|
0XFFFF, 0XFFFF, 0XFFFF, 0XFFFF, 0XFFFF, 0XFFFF, 0XFFFF, 0XFFFF, 0XFFFF,
|
||||||
|
0XFFFF, 0XFFFF, 0XFFFF, 0XFFFF, 0XFFFF, 0XFFFF, 0XFFFF, 0XFFFF, 0XFFFF,
|
||||||
|
0XFFFF, 0XFFFF, 0XFFFF, 0XFFFF, 0XFFFF, 0XFFFF, 0XFFFF, 0XFFFF, 0XFFFF,
|
||||||
|
0XFFFF, 0XFFFF, 0XFFFF, 0XFFFF, 0XFFFF, 0XFFFF, 0XFFFF, 0XFFFF, 0XFFFF,
|
||||||
|
0XFFFF, 0XFFFF, 0XFFFF, 0XFFFF, 0XFFFF, 0XFFFF, 0XFFFF, 0XFFFF, 0XFFFF,
|
||||||
|
0XFFFF, 0XFFFF, 0XFFFF, 0XFFFF, 0XFFFF, 0XFFFF, 0XFFFF, 0XFFFF, 0XFFFF,
|
||||||
|
0XFFFF, 0XFFFF, 0XFFFF, 0XFFFF, 0XFFFF, 0XFFFF, 0XFFFF, 0XFFFF, 0XFFFF,
|
||||||
|
0XFFFF, 0XFFFF, 0XFFFF, 0XFFFF, 0XFFFF, 0XFFFF, 0XFFFF, 0XFFFF, 0XFFFF,
|
||||||
|
0XFFFF, 0XFFFF, 0XFFFF, 0XFFFF, 0XFFFF, 0XFFFF, 0XFFFF, 0XFFFF, 0XFFFF,
|
||||||
|
0XFFFF, 0XFFFF, 0XFFFF, 0XFFFF, 0XFFFF, 0XFFFF, 0XFFFF, 0XFFFF, 0XFFFF,
|
||||||
|
0XFFFF, 0XFFFF, 0XFFFF, 0XFFFF, 0XFFFF, 0XFFFF, 0XFFFF, 0XFFFF, 0XFFFF,
|
||||||
|
0XFFFF, 0XFFFF, 0XFFFF, 0XFFFF, 0XFFFF, 0XFFFF, 0XFFFF, 0XFFFF, 0XFFFF,
|
||||||
|
0XFFFF, 0XFFFF, 0XFFFF, 0XFFFF, 0XFFFF, 0XFFFF, 0XFFFF, 0XFFFF, 0XFFFF,
|
||||||
|
0XFFFF, 0XFFFF, 0XFFFF, 0XFFFF, 0XFFFF, 0XFFFF, 0XFFFF, 0XFFFF, 0XFFFF,
|
||||||
|
0XFFFF, 0XFFFF, 0XFFFF, 0XFFFF, 0XFFFF, 0XFFFF, 0XFFFF, 0XFFFF, 0XFFFF,
|
||||||
|
0XFFFF, 0XFFFF, 0XFFFF, 0XFFFF, 0XFFFF, 0XFFFF, 0XFFFF, 0XFFFF, 0XFFFF,
|
||||||
|
0XFFFF, 0XFFFF, 0XFFFF, 0XFFFF, 0XFFFF, 0XFFFF, 0XFFFF, 0XFFFF, 0XFFFF,
|
||||||
|
0XFFFF, 0XFFFF, 0XFFFF, 0XFFFF, 0XFFFF, 0XFFFF, 0XFFFF, 0XFFFF, 0XFFFF,
|
||||||
|
0XFFFF, 0XFFFF, 0XFFFF, 0XFFFF, 0XFFFF, 0XFFFF, 0XFFFF, 0XFFFF, 0XFFFF,
|
||||||
|
0XFFFF, 0XFFFF, 0XFFFF, 0XFFFF, 0XFFFF, 0XFFFF, 0XFFFF, 0XFFFF, 0XFFFF,
|
||||||
|
0XFFFF, 0XFFFF, 0XFFFF, 0XFFFF, 0XFFFF, 0XFFFF, 0XFFFF, 0XFFFF, 0XFFFF,
|
||||||
|
0XFFFF, 0XFFFF, 0XFFFF, 0XFFFF, 0XFFFF, 0XFFFF, 0XFFFF, 0XFFFF, 0XFFFF,
|
||||||
|
0XFFFF, 0XFFFF, 0XFFFF, 0XFFFF, 0X8C10, 0XFFFF, 0XFFFF, 0XFFFF, 0XFFFF,
|
||||||
|
0XFFFF, 0XFFFF, 0XFFFF, 0XFFFF, 0XFFFF, 0XFFFF, 0XFFFF, 0XFFFF, 0XFFFF,
|
||||||
|
0XFFFF, 0XFFFF, 0XFFFF, 0XFFFF, 0XFFFF, 0XFFFF, 0XFFFF, 0XFFFF, 0XFFFF,
|
||||||
|
0XFFFF, 0XFFFF, 0XFFFF, 0XFFFF, 0XFFFF, 0XFFFF, 0XBD14, 0XAC92, 0XFFFF,
|
||||||
|
0XFFFF, 0XFFFF, 0XFFFF, 0XFFFF, 0XFFFF, 0XFFFF, 0XFFFF, 0XFFFF, 0XFFFF,
|
||||||
|
0XFFFF, 0XFFFF, 0XFFFF, 0XFFFF, 0XFFFF, 0XFFFF, 0XFFFF, 0XFFFF, 0XFFFF,
|
||||||
|
0XFFFF, 0XFFFF, 0XFFFF, 0XFFFF, 0XFFFF, 0XFFFF, 0XFFFF, 0XFFFF, 0XFFFF,
|
||||||
|
0XFFFF, 0XFFFF, 0XFFFF, 0XFFFF, 0XFFFF, 0XFFFF, 0XFFFF, 0XFFFF, 0XFFFF,
|
||||||
|
0XFFFF, 0XFFFF, 0XFFFF, 0XFFFF, 0XFFFF, 0XFFFF, 0XFFFF, 0XFFFF, 0XFFFF,
|
||||||
|
0XFFFF, 0XFFFF, 0XFFFF, 0XFFFF, 0XFFFF, 0XFFFF, 0XFFFF, 0XFFFF, 0XFFFF,
|
||||||
|
0XFFFF, 0XFFFF, 0XFFFF, 0XFFFF, 0XFFFF, 0XFFFF, 0XFFFF, 0XFFFF, 0XFFFF,
|
||||||
|
0XFFFF, 0XFFFF, 0XFFFF, 0XFFFF, 0XFFFF, 0XFFFF, 0XFFFF, 0XFFFF, 0XFFFF,
|
||||||
|
0XFFFF, 0XFFFF, 0XFFFF, 0XDEFB, 0XB431, 0XA1C9, 0XAA4B, 0XFFFF, 0XFFFF,
|
||||||
|
0XFFFF, 0XFFFF, 0XFFFF, 0XFFFF, 0XFFFF, 0XFFFF, 0XFFFF, 0XFFFF, 0XFFFF,
|
||||||
|
0XFFFF, 0XFFFF, 0XFFFF, 0XFFFF, 0XFFFF, 0XFFFF, 0XFFFF, 0XFFFF, 0XFFFF,
|
||||||
|
0XFFFF, 0XFFFF, 0XFFFF, 0XFFFF, 0XFFFF, 0XFFFF, 0XCE18, 0X9A2A, 0X9044,
|
||||||
|
0XDEFB, 0XFFFF, 0XFFFF, 0XFFFF, 0XFFFF, 0XFFFF, 0XFFFF, 0XFFFF, 0XFFFF,
|
||||||
|
0XFFFF, 0XFFFF, 0XFFFF, 0XFFFF, 0XFFFF, 0XFFFF, 0XFFFF, 0XFFFF, 0XEF7D,
|
||||||
|
0XFFFF, 0XFFFF, 0XFFFF, 0XFFFF, 0XFFFF, 0XFFFF, 0XFFFF, 0XFFFF, 0XFFFF,
|
||||||
|
0XFFFF, 0XFFFF, 0XFFFF, 0XFFFF, 0XFFFF, 0XFFFF, 0XFFFF, 0XFFFF, 0XFFFF,
|
||||||
|
0XFFFF, 0XFFFF, 0XFFFF, 0XFFFF, 0XFFFF, 0XFFFF, 0XFFFF, 0XFFFF, 0XFFFF,
|
||||||
|
0XFFFF, 0XFFFF, 0XFFFF, 0XFFFF, 0XFFFF, 0XFFFF, 0XFFFF, 0XFFFF, 0XFFFF,
|
||||||
|
0XFFFF, 0XFFFF, 0XFFFF, 0XFFFF, 0XFFFF, 0XFFFF, 0XFFFF, 0XFFFF, 0XFFFF,
|
||||||
|
0XFFFF, 0XFFFF, 0XFFFF, 0XFFFF, 0XFFFF, 0XFFFF, 0XFFFF, 0XFFFF, 0XFFFF,
|
||||||
|
0XFFFF, 0XFFFF, 0XDEFB, 0XB3B0, 0XA148, 0XB865, 0XC066, 0XC066, 0XAA4B,
|
||||||
|
0XFFFF, 0XFFFF, 0XFFFF, 0XFFFF, 0XFFFF, 0XFFFF, 0XFFFF, 0XFFFF, 0XFFFF,
|
||||||
|
0XFFFF, 0XFFFF, 0XFFFF, 0XFFFF, 0XFFFF, 0XFFFF, 0XFFFF, 0XFFFF, 0XFFFF,
|
||||||
|
0XFFFF, 0XFFFF, 0XFFFF, 0XFFFF, 0XFFFF, 0XFFFF, 0XEF7D, 0XAB2E, 0X9864,
|
||||||
|
0XA865, 0XAAAC, 0XFFFF, 0XFFFF, 0XFFFF, 0XFFFF, 0XFFFF, 0XFFFF, 0XFFFF,
|
||||||
|
0XFFFF, 0XFFFF, 0XFFFF, 0XFFFF, 0XFFFF, 0XFFFF, 0XFFFF, 0XEF7D, 0XAC92,
|
||||||
|
0X728B, 0XDEFB, 0XFFFF, 0XFFFF, 0XFFFF, 0XFFFF, 0XFFFF, 0XFFFF, 0XFFFF,
|
||||||
|
0XFFFF, 0XFFFF, 0XFFFF, 0XFFFF, 0XFFFF, 0XFFFF, 0XFFFF, 0XFFFF, 0XFFFF,
|
||||||
|
0XFFFF, 0XFFFF, 0XFFFF, 0XFFFF, 0XFFFF, 0XFFFF, 0XFFFF, 0XFFFF, 0XFFFF,
|
||||||
|
0XFFFF, 0XFFFF, 0XFFFF, 0XFFFF, 0XFFFF, 0XFFFF, 0XFFFF, 0XFFFF, 0XFFFF,
|
||||||
|
0XFFFF, 0XFFFF, 0XFFFF, 0XFFFF, 0XFFFF, 0XFFFF, 0XFFFF, 0XFFFF, 0XFFFF,
|
||||||
|
0XFFFF, 0XFFFF, 0XFFFF, 0XCE18, 0XAB2E, 0XAA4B, 0XAA4B, 0XAA4B, 0XA3AF,
|
||||||
|
0XB431, 0XB431, 0XB431, 0XA411, 0XA8E6, 0XD086, 0XB865, 0X7043, 0XA865,
|
||||||
|
0XD086, 0XAA4B, 0XCE79, 0XFFFF, 0XFFFF, 0XFFFF, 0XFFFF, 0XFFFF, 0XFFFF,
|
||||||
|
0XFFFF, 0XFFFF, 0XFFFF, 0XFFFF, 0XFFFF, 0XFFFF, 0XFFFF, 0XFFFF, 0XFFFF,
|
||||||
|
0XFFFF, 0XFFFF, 0XFFFF, 0XFFFF, 0XFFFF, 0XFFFF, 0XFFFF, 0XB493, 0XA8E6,
|
||||||
|
0X9864, 0XC066, 0XD086, 0XB493, 0XFFFF, 0XFFFF, 0XFFFF, 0XFFFF, 0XFFFF,
|
||||||
|
0XFFFF, 0XFFFF, 0XFFFF, 0XFFFF, 0XFFFF, 0XFFFF, 0XFFFF, 0XCE79, 0X830D,
|
||||||
|
0X80C5, 0XAB2E, 0XFFFF, 0XFFFF, 0XFFFF, 0XFFFF, 0XFFFF, 0XFFFF, 0XFFFF,
|
||||||
|
0XFFFF, 0XFFFF, 0XFFFF, 0XFFFF, 0XFFFF, 0XFFFF, 0XFFFF, 0XFFFF, 0XFFFF,
|
||||||
|
0XFFFF, 0XFFFF, 0XFFFF, 0XFFFF, 0XFFFF, 0XFFFF, 0XFFFF, 0XFFFF, 0XFFFF,
|
||||||
|
0XFFFF, 0XFFFF, 0XFFFF, 0XFFFF, 0XFFFF, 0XFFFF, 0XFFFF, 0XFFFF, 0XFFFF,
|
||||||
|
0XFFFF, 0XFFFF, 0XFFFF, 0XFFFF, 0XFFFF, 0XFFFF, 0XFFFF, 0XFFFF, 0XFFFF,
|
||||||
|
0XFFFF, 0XFFFF, 0XFFFF, 0XFFFF, 0XB431, 0XC066, 0XD086, 0XD086, 0XD086,
|
||||||
|
0XD086, 0XD086, 0XD086, 0XD086, 0XD086, 0X9864, 0XD086, 0XB865, 0X9864,
|
||||||
|
0XC066, 0XD086, 0XB8E7, 0XB493, 0XFFFF, 0XFFFF, 0XFFFF, 0XFFFF, 0XFFFF,
|
||||||
|
0XFFFF, 0XFFFF, 0XFFFF, 0XFFFF, 0XFFFF, 0XFFFF, 0XFFFF, 0XFFFF, 0XFFFF,
|
||||||
|
0XFFFF, 0XFFFF, 0XFFFF, 0XFFFF, 0XFFFF, 0XFFFF, 0XFFFF, 0XDE9A, 0XA1C9,
|
||||||
|
0XB865, 0X9864, 0XD086, 0XD086, 0XD086, 0XBDF7, 0XFFFF, 0XFFFF, 0XFFFF,
|
||||||
|
0XFFFF, 0XFFFF, 0XFFFF, 0XFFFF, 0XFFFF, 0XFFFF, 0XEF7D, 0XAD14, 0X71A8,
|
||||||
|
0X9864, 0XC066, 0XC515, 0XFFFF, 0XFFFF, 0XFFFF, 0XFFFF, 0XFFFF, 0XFFFF,
|
||||||
|
0XFFFF, 0XFFFF, 0XFFFF, 0XFFFF, 0XFFFF, 0XFFFF, 0XFFFF, 0XFFFF, 0XFFFF,
|
||||||
|
0XFFFF, 0XFFFF, 0XFFFF, 0XFFFF, 0XFFFF, 0XFFFF, 0XFFFF, 0XFFFF, 0XFFFF,
|
||||||
|
0XFFFF, 0XFFFF, 0XFFFF, 0XFFFF, 0XFFFF, 0XFFFF, 0XFFFF, 0XFFFF, 0XFFFF,
|
||||||
|
0XFFFF, 0XFFFF, 0XFFFF, 0XFFFF, 0XFFFF, 0XFFFF, 0XFFFF, 0XFFFF, 0XFFFF,
|
||||||
|
0XFFFF, 0XDEFB, 0XBDF7, 0XBD14, 0XA411, 0XB431, 0XB148, 0XD086, 0XC066,
|
||||||
|
0X9864, 0XD086, 0XD086, 0XD086, 0XD086, 0XD086, 0XC066, 0XD086, 0XA865,
|
||||||
|
0XB865, 0XD086, 0XD086, 0XB1CA, 0XDEFB, 0XFFFF, 0XFFFF, 0XFFFF, 0XFFFF,
|
||||||
|
0XFFFF, 0XFFFF, 0XFFFF, 0XFFFF, 0XFFFF, 0XFFFF, 0XFFFF, 0XFFFF, 0XFFFF,
|
||||||
|
0XFFFF, 0XFFFF, 0XFFFF, 0XFFFF, 0XFFFF, 0XFFFF, 0XFFFF, 0XEF7D, 0XB3B0,
|
||||||
|
0XB865, 0XA865, 0XB865, 0XD086, 0XD086, 0XD086, 0XD086, 0XBD14, 0XFFFF,
|
||||||
|
0XFFFF, 0XFFFF, 0XFFFF, 0XFFFF, 0XFFFF, 0XFFFF, 0XCE79, 0X932D, 0X78C5,
|
||||||
|
0XA865, 0XD086, 0XC066, 0XC515, 0XFFFF, 0XFFFF, 0XFFFF, 0XFFFF, 0XFFFF,
|
||||||
|
0XFFFF, 0XFFFF, 0XFFFF, 0XFFFF, 0XFFFF, 0XFFFF, 0XFFFF, 0XFFFF, 0XFFFF,
|
||||||
|
0XFFFF, 0XFFFF, 0XFFFF, 0XFFFF, 0XFFFF, 0XFFFF, 0XFFFF, 0XFFFF, 0XFFFF,
|
||||||
|
0XFFFF, 0XFFFF, 0XFFFF, 0XFFFF, 0XFFFF, 0XFFFF, 0XFFFF, 0XFFFF, 0XFFFF,
|
||||||
|
0XFFFF, 0XFFFF, 0XFFFF, 0XFFFF, 0XFFFF, 0XFFFF, 0XFFFF, 0XFFFF, 0XFFFF,
|
||||||
|
0XDEFB, 0XAB2E, 0XA0C6, 0XB865, 0XD086, 0XD086, 0XD086, 0X9864, 0XD086,
|
||||||
|
0XB865, 0X78C5, 0X4208, 0X2104, 0X8947, 0X9864, 0X9864, 0X9864, 0XD086,
|
||||||
|
0XD086, 0XA865, 0X9864, 0XD086, 0XB865, 0XDEFB, 0XFFFF, 0XFFFF, 0XFFFF,
|
||||||
|
0XFFFF, 0XFFFF, 0XFFFF, 0XFFFF, 0XFFFF, 0XFFFF, 0XFFFF, 0XFFFF, 0XFFFF,
|
||||||
|
0XFFFF, 0XFFFF, 0XFFFF, 0XFFFF, 0XFFFF, 0XFFFF, 0XFFFF, 0XFFFF, 0XCE18,
|
||||||
|
0XB148, 0XC066, 0XA865, 0XB865, 0XD086, 0XD086, 0XD086, 0XD086, 0XD086,
|
||||||
|
0XAA4B, 0XFFFF, 0XFFFF, 0XFFFF, 0XFFFF, 0XEF7D, 0XB493, 0X89A8, 0X9044,
|
||||||
|
0XB865, 0XD086, 0XD086, 0XC066, 0XC515, 0XFFFF, 0XFFFF, 0XFFFF, 0XFFFF,
|
||||||
|
0XFFFF, 0XFFFF, 0XFFFF, 0XFFFF, 0XFFFF, 0XFFFF, 0XFFFF, 0XFFFF, 0XFFFF,
|
||||||
|
0XFFFF, 0X7B8E, 0XFFFF, 0XFFFF, 0XFFFF, 0XFFFF, 0XFFFF, 0XFFFF, 0XFFFF,
|
||||||
|
0XFFFF, 0XFFFF, 0XFFFF, 0XFFFF, 0XFFFF, 0XFFFF, 0XFFFF, 0XFFFF, 0XFFFF,
|
||||||
|
0XFFFF, 0XFFFF, 0XAD14, 0XDEFB, 0XFFFF, 0XFFFF, 0XFFFF, 0XFFFF, 0XFFFF,
|
||||||
|
0XFFFF, 0XB431, 0XB865, 0XD086, 0XD086, 0XD086, 0XD086, 0XC066, 0XA865,
|
||||||
|
0X9864, 0XD086, 0XD086, 0XD086, 0XAA4B, 0X9A2A, 0XC066, 0XD086, 0XD086,
|
||||||
|
0XD086, 0XD086, 0XC066, 0X9044, 0X9864, 0X9864, 0X9044, 0XCE18, 0XFFFF,
|
||||||
|
0XFFFF, 0XFFFF, 0XFFFF, 0XFFFF, 0XFFFF, 0XFFFF, 0XFFFF, 0XFFFF, 0XFFFF,
|
||||||
|
0XFFFF, 0XFFFF, 0XFFFF, 0XFFFF, 0XFFFF, 0XFFFF, 0XFFFF, 0XFFFF, 0XEF7D,
|
||||||
|
0XB3B0, 0XC066, 0XB865, 0XA865, 0XD086, 0XD086, 0XD086, 0XD086, 0XD086,
|
||||||
|
0XD086, 0XD086, 0XD086, 0XAAAC, 0XBD96, 0XAD14, 0XAAAC, 0X8044, 0X9864,
|
||||||
|
0XB865, 0XD086, 0XD086, 0XD086, 0XD086, 0XB431, 0XFFFF, 0XFFFF, 0XFFFF,
|
||||||
|
0XFFFF, 0XFFFF, 0XFFFF, 0XFFFF, 0XFFFF, 0XFFFF, 0XFFFF, 0XFFFF, 0XFFFF,
|
||||||
|
0XFFFF, 0XFFFF, 0XB3B0, 0XAA4B, 0XFFFF, 0XFFFF, 0XFFFF, 0XFFFF, 0XFFFF,
|
||||||
|
0XFFFF, 0XFFFF, 0XFFFF, 0XFFFF, 0XFFFF, 0XFFFF, 0XFFFF, 0XFFFF, 0XFFFF,
|
||||||
|
0XFFFF, 0XFFFF, 0XFFFF, 0XFFFF, 0XBD96, 0XB8E7, 0XB431, 0XEF7D, 0XFFFF,
|
||||||
|
0XFFFF, 0XFFFF, 0XA32E, 0X9864, 0X9864, 0XAA4B, 0XAA4B, 0X9147, 0XB865,
|
||||||
|
0X9044, 0XD086, 0XA865, 0XD086, 0XC066, 0XC066, 0XD086, 0XD086, 0XD086,
|
||||||
|
0XD086, 0XD086, 0XD086, 0XD086, 0XD086, 0X9864, 0XD086, 0XD086, 0XD086,
|
||||||
|
0XAA4B, 0XFFFF, 0XFFFF, 0XFFFF, 0XFFFF, 0XFFFF, 0XFFFF, 0XFFFF, 0XFFFF,
|
||||||
|
0XFFFF, 0XFFFF, 0XFFFF, 0XFFFF, 0XFFFF, 0XFFFF, 0XFFFF, 0XFFFF, 0XFFFF,
|
||||||
|
0XDE9A, 0XB148, 0XD086, 0XA865, 0XB865, 0XD086, 0XD086, 0XD086, 0XD086,
|
||||||
|
0XD086, 0XD086, 0XD086, 0XD086, 0XA865, 0X9864, 0X9864, 0XA865, 0X9864,
|
||||||
|
0XC066, 0XD086, 0XD086, 0XD086, 0XD086, 0XD086, 0XA148, 0XFFFF, 0XFFFF,
|
||||||
|
0XFFFF, 0XFFFF, 0XFFFF, 0XFFFF, 0XFFFF, 0XFFFF, 0XFFFF, 0XFFFF, 0XFFFF,
|
||||||
|
0XFFFF, 0XFFFF, 0XFFFF, 0XC515, 0XC066, 0XAA4B, 0XFFFF, 0XFFFF, 0XFFFF,
|
||||||
|
0XFFFF, 0XFFFF, 0XFFFF, 0XFFFF, 0XFFFF, 0XFFFF, 0XFFFF, 0XFFFF, 0XFFFF,
|
||||||
|
0XFFFF, 0XFFFF, 0XFFFF, 0XFFFF, 0XFFFF, 0XFFFF, 0XFFFF, 0XAA4B, 0XD086,
|
||||||
|
0XA865, 0XAB2E, 0XBD96, 0XEF7D, 0XCE79, 0XFFFF, 0XFFFF, 0XFFFF, 0XFFFF,
|
||||||
|
0XFFFF, 0XDEFB, 0XB1CA, 0XD086, 0XD086, 0X9864, 0X822A, 0XBDF7, 0XB493,
|
||||||
|
0XB148, 0XD086, 0XD086, 0XD086, 0XD086, 0XD086, 0XD086, 0XA865, 0X9864,
|
||||||
|
0XD086, 0XD086, 0XD086, 0XAA4B, 0XBD14, 0XFFFF, 0XFFFF, 0XFFFF, 0XFFFF,
|
||||||
|
0XFFFF, 0XFFFF, 0XFFFF, 0XFFFF, 0XFFFF, 0XFFFF, 0XFFFF, 0XFFFF, 0XFFFF,
|
||||||
|
0XFFFF, 0XB431, 0XB865, 0XD086, 0X9864, 0XC066, 0XD086, 0XD086, 0XD086,
|
||||||
|
0XD086, 0XD086, 0XD086, 0XC066, 0X9864, 0X9864, 0XC066, 0XA865, 0X9864,
|
||||||
|
0XC066, 0XD086, 0XD086, 0XD086, 0XD086, 0XD086, 0XD086, 0XD086, 0XB3B0,
|
||||||
|
0XFFFF, 0XFFFF, 0XFFFF, 0XFFFF, 0XFFFF, 0XFFFF, 0XFFFF, 0XFFFF, 0XFFFF,
|
||||||
|
0XFFFF, 0XFFFF, 0XFFFF, 0XFFFF, 0XCD96, 0XC066, 0XD086, 0XAA4B, 0XFFFF,
|
||||||
|
0XFFFF, 0XFFFF, 0XFFFF, 0XFFFF, 0XFFFF, 0XFFFF, 0XFFFF, 0XFFFF, 0XFFFF,
|
||||||
|
0XFFFF, 0XFFFF, 0XFFFF, 0XFFFF, 0XFFFF, 0XFFFF, 0XFFFF, 0XFFFF, 0XFFFF,
|
||||||
|
0XDE9A, 0XB865, 0XD086, 0XD086, 0XD086, 0XA865, 0X9147, 0X9C92, 0XFFFF,
|
||||||
|
0XFFFF, 0XFFFF, 0XFFFF, 0XFFFF, 0XCE18, 0X80C5, 0X5822, 0X5A08, 0XDEFB,
|
||||||
|
0XFFFF, 0XFFFF, 0XCE79, 0XA0C6, 0XD086, 0XD086, 0XD086, 0XD086, 0XD086,
|
||||||
|
0X9044, 0XB865, 0XD086, 0XD086, 0XD086, 0XD086, 0XD086, 0XAB2E, 0XFFFF,
|
||||||
|
0XFFFF, 0XFFFF, 0XFFFF, 0XFFFF, 0XFFFF, 0XFFFF, 0XFFFF, 0XFFFF, 0XFFFF,
|
||||||
|
0XFFFF, 0XEF7D, 0XAA4B, 0XD086, 0XC066, 0X9864, 0XD086, 0XD086, 0XD086,
|
||||||
|
0XD086, 0XD086, 0XD086, 0XA865, 0X9864, 0XA865, 0XD086, 0X9864, 0X9864,
|
||||||
|
0XC066, 0XD086, 0XD086, 0XD086, 0XD086, 0XD086, 0XD086, 0XD086, 0XD086,
|
||||||
|
0XD086, 0XAB2E, 0XFFFF, 0XFFFF, 0XFFFF, 0XFFFF, 0XFFFF, 0XFFFF, 0XFFFF,
|
||||||
|
0XFFFF, 0XFFFF, 0XFFFF, 0XFFFF, 0XFFFF, 0XDE9A, 0XB8E7, 0XD086, 0XD086,
|
||||||
|
0XAA4B, 0XFFFF, 0XFFFF, 0XFFFF, 0XFFFF, 0XFFFF, 0XFFFF, 0XFFFF, 0XFFFF,
|
||||||
|
0XFFFF, 0XFFFF, 0XFFFF, 0XFFFF, 0XFFFF, 0XFFFF, 0XFFFF, 0XFFFF, 0XFFFF,
|
||||||
|
0XFFFF, 0XFFFF, 0XFFFF, 0XC515, 0XC066, 0XD086, 0XB865, 0X8044, 0X82AB,
|
||||||
|
0XBDF7, 0XBDF7, 0XBDF7, 0XBDF7, 0XBDF7, 0XBDF7, 0XAC92, 0XA3AF, 0X92AC,
|
||||||
|
0XAB2E, 0XAA4B, 0XA1C9, 0X9864, 0XB865, 0XA865, 0XC066, 0XD086, 0XD086,
|
||||||
|
0XD086, 0XD086, 0XD086, 0X9864, 0XD086, 0XD086, 0XD086, 0XB1CA, 0XBD14,
|
||||||
|
0X9CF3, 0XFFFF, 0XFFFF, 0XFFFF, 0XFFFF, 0XFFFF, 0XFFFF, 0XFFFF, 0XFFFF,
|
||||||
|
0XFFFF, 0XFFFF, 0XCE18, 0XA8E6, 0XD086, 0XC066, 0XA865, 0XD086, 0XD086,
|
||||||
|
0XD086, 0XD086, 0XC066, 0X9864, 0X9864, 0XC066, 0XD086, 0X9864, 0X9864,
|
||||||
|
0XD086, 0XD086, 0XD086, 0XD086, 0XD086, 0XD086, 0XD086, 0XD086, 0XD086,
|
||||||
|
0XD086, 0XD086, 0XD086, 0XC066, 0XC515, 0XFFFF, 0XFFFF, 0XFFFF, 0XFFFF,
|
||||||
|
0XFFFF, 0XFFFF, 0XFFFF, 0XFFFF, 0XFFFF, 0XFFFF, 0XDE9A, 0XB8E7, 0XD086,
|
||||||
|
0XD086, 0XD086, 0XAA4B, 0XFFFF, 0XFFFF, 0XFFFF, 0XFFFF, 0XFFFF, 0XFFFF,
|
||||||
|
0XFFFF, 0XFFFF, 0XFFFF, 0XFFFF, 0XFFFF, 0XFFFF, 0XFFFF, 0XFFFF, 0XFFFF,
|
||||||
|
0XFFFF, 0XFFFF, 0XFFFF, 0XFFFF, 0XFFFF, 0XFFFF, 0XB3B0, 0XD086, 0XA865,
|
||||||
|
0XC066, 0XD086, 0XD086, 0XD086, 0XD086, 0XD086, 0XD086, 0XD086, 0XD086,
|
||||||
|
0XD086, 0XD086, 0XD086, 0XC066, 0XA865, 0X8044, 0X4822, 0X9044, 0X9044,
|
||||||
|
0XD086, 0XD086, 0XD086, 0XD086, 0X8044, 0X9864, 0XD086, 0XD086, 0XD086,
|
||||||
|
0XAA4B, 0XCE18, 0XFFFF, 0XFFFF, 0XFFFF, 0XFFFF, 0XFFFF, 0XFFFF, 0XFFFF,
|
||||||
|
0XFFFF, 0XFFFF, 0XFFFF, 0XB493, 0XC066, 0XD086, 0XC066, 0XA865, 0XD086,
|
||||||
|
0XD086, 0XD086, 0XA865, 0X9864, 0XA865, 0XD086, 0XC066, 0X9864, 0X9864,
|
||||||
|
0XD086, 0XD086, 0XD086, 0XD086, 0XD086, 0XD086, 0XD086, 0XD086, 0XD086,
|
||||||
|
0XD086, 0XD086, 0XD086, 0XD086, 0XD086, 0X9864, 0X9044, 0X3986, 0XCE79,
|
||||||
|
0XFFFF, 0XFFFF, 0XFFFF, 0XFFFF, 0XFFFF, 0XFFFF, 0XFFFF, 0XDE9A, 0XB8E7,
|
||||||
|
0XD086, 0XD086, 0XC066, 0XD086, 0XAA4B, 0XFFFF, 0XFFFF, 0XFFFF, 0XFFFF,
|
||||||
|
0XFFFF, 0XFFFF, 0XFFFF, 0XFFFF, 0XFFFF, 0XFFFF, 0XFFFF, 0XFFFF, 0XFFFF,
|
||||||
|
0XFFFF, 0XFFFF, 0XFFFF, 0XFFFF, 0XFFFF, 0XFFFF, 0XFFFF, 0XFFFF, 0XFFFF,
|
||||||
|
0XB431, 0XC066, 0X90C6, 0XAA4B, 0XAA4B, 0XAA4B, 0XAA4B, 0X99C9, 0X9864,
|
||||||
|
0X9864, 0X9864, 0X6843, 0X6843, 0X5822, 0X4822, 0X7043, 0X9044, 0XC066,
|
||||||
|
0X9864, 0X7043, 0XC066, 0XB865, 0XD086, 0X7043, 0X8044, 0XC066, 0XD086,
|
||||||
|
0XD086, 0XD086, 0XD086, 0XC066, 0XB431, 0XFFFF, 0XFFFF, 0XFFFF, 0XFFFF,
|
||||||
|
0XFFFF, 0XFFFF, 0XFFFF, 0XEF7D, 0XAB2E, 0XD086, 0XD086, 0XC066, 0XA865,
|
||||||
|
0XD086, 0XD086, 0X9864, 0X9044, 0XC066, 0XD086, 0XC066, 0X9864, 0XA865,
|
||||||
|
0XD086, 0XD086, 0XD086, 0XD086, 0XD086, 0XD086, 0XD086, 0XD086, 0XD086,
|
||||||
|
0XB865, 0X9864, 0X9864, 0X9864, 0X9044, 0X6843, 0X6843, 0X8044, 0X7B0C,
|
||||||
|
0XCE79, 0XFFFF, 0XFFFF, 0XFFFF, 0XFFFF, 0XFFFF, 0XFFFF, 0XFFFF, 0XDE9A,
|
||||||
|
0XB8E7, 0XD086, 0X9864, 0XC066, 0X9864, 0XD086, 0XAA4B, 0XFFFF, 0XFFFF,
|
||||||
|
0XFFFF, 0XFFFF, 0XFFFF, 0XFFFF, 0XFFFF, 0XFFFF, 0XFFFF, 0XFFFF, 0XFFFF,
|
||||||
|
0XFFFF, 0XFFFF, 0XFFFF, 0XFFFF, 0XFFFF, 0XFFFF, 0XFFFF, 0XFFFF, 0XFFFF,
|
||||||
|
0XFFFF, 0XFFFF, 0XFFFF, 0XC515, 0XA8E6, 0XCE18, 0XFFFF, 0XFFFF, 0XFFFF,
|
||||||
|
0XFFFF, 0XFFFF, 0XFFFF, 0XFFFF, 0XA148, 0XD086, 0XD086, 0XD086, 0XD086,
|
||||||
|
0XB148, 0XBD14, 0X9A2A, 0XD086, 0X9864, 0X9864, 0X6843, 0XD086, 0XC066,
|
||||||
|
0XC066, 0XD086, 0XD086, 0XD086, 0XA865, 0XC066, 0XA865, 0XEF7D, 0XFFFF,
|
||||||
|
0XFFFF, 0XFFFF, 0XFFFF, 0XFFFF, 0XEF7D, 0XB1CA, 0XD086, 0XD086, 0XD086,
|
||||||
|
0X9864, 0XC066, 0X9864, 0X9864, 0XD086, 0XD086, 0XC066, 0X9864, 0XA865,
|
||||||
|
0XD086, 0XD086, 0XD086, 0XD086, 0XD086, 0XC066, 0X9864, 0X9864, 0X9864,
|
||||||
|
0X9864, 0X9864, 0X9864, 0X9864, 0X9864, 0X9864, 0XA865, 0XD086, 0XA1C9,
|
||||||
|
0XDE9A, 0XFFFF, 0XFFFF, 0XFFFF, 0XFFFF, 0XFFFF, 0XFFFF, 0XFFFF, 0XFFFF,
|
||||||
|
0XDE9A, 0XB8E7, 0XD086, 0XD086, 0X9864, 0XD086, 0X9864, 0XD086, 0XAA4B,
|
||||||
|
0XFFFF, 0XFFFF, 0XFFFF, 0XFFFF, 0XFFFF, 0XFFFF, 0XFFFF, 0XFFFF, 0XFFFF,
|
||||||
|
0XFFFF, 0XFFFF, 0XFFFF, 0XFFFF, 0XFFFF, 0XFFFF, 0XFFFF, 0XFFFF, 0XFFFF,
|
||||||
|
0XFFFF, 0XFFFF, 0XFFFF, 0XFFFF, 0XFFFF, 0XFFFF, 0XDEFB, 0XCE18, 0XFFFF,
|
||||||
|
0XFFFF, 0XFFFF, 0XFFFF, 0XFFFF, 0XFFFF, 0XFFFF, 0XAA4B, 0XD086, 0XC066,
|
||||||
|
0XD086, 0XAAAC, 0XEF7D, 0XFFFF, 0X932D, 0XB865, 0XB865, 0XC066, 0X7043,
|
||||||
|
0XD086, 0XD086, 0XD086, 0XD086, 0XD086, 0XB148, 0XEF7D, 0XBD14, 0XA148,
|
||||||
|
0XBDF7, 0XFFFF, 0XFFFF, 0XFFFF, 0XFFFF, 0XFFFF, 0XAA4B, 0XD086, 0XD086,
|
||||||
|
0XD086, 0X8044, 0X9864, 0XA865, 0XD086, 0XD086, 0XC066, 0X9864, 0XA865,
|
||||||
|
0XD086, 0XD086, 0XA865, 0X9864, 0X9864, 0X9864, 0X9864, 0XA865, 0XD086,
|
||||||
|
0XB865, 0X9864, 0X9864, 0X9864, 0XB865, 0XD086, 0XD086, 0XD086, 0XD086,
|
||||||
|
0XAB2E, 0XFFFF, 0XFFFF, 0XFFFF, 0XFFFF, 0XFFFF, 0XFFFF, 0XFFFF, 0XFFFF,
|
||||||
|
0XFFFF, 0XDE9A, 0XB8E7, 0XD086, 0XD086, 0XC066, 0XA865, 0XD086, 0X9864,
|
||||||
|
0XD086, 0XA0C6, 0XFFFF, 0XFFFF, 0XFFFF, 0XFFFF, 0XFFFF, 0XFFFF, 0XFFFF,
|
||||||
|
0XFFFF, 0XFFFF, 0XFFFF, 0XFFFF, 0XFFFF, 0XFFFF, 0XFFFF, 0XFFFF, 0XFFFF,
|
||||||
|
0XFFFF, 0XFFFF, 0XFFFF, 0XFFFF, 0XFFFF, 0X8C10, 0XB431, 0XEF7D, 0XFFFF,
|
||||||
|
0XFFFF, 0XFFFF, 0XFFFF, 0XFFFF, 0XFFFF, 0XFFFF, 0XFFFF, 0XFFFF, 0XBD14,
|
||||||
|
0XD086, 0XA1C9, 0X80C5, 0XEF7D, 0XFFFF, 0XB431, 0XD086, 0XB865, 0X9864,
|
||||||
|
0X8044, 0X9864, 0XD086, 0XD086, 0XD086, 0XD086, 0XD086, 0XAA4B, 0XFFFF,
|
||||||
|
0XFFFF, 0XFFFF, 0XFFFF, 0XFFFF, 0XFFFF, 0XFFFF, 0XFFFF, 0XBD14, 0XD086,
|
||||||
|
0XD086, 0XD086, 0XA865, 0XB865, 0XD086, 0XD086, 0XC066, 0X9864, 0X9864,
|
||||||
|
0X9864, 0X9044, 0X9864, 0X9864, 0XC066, 0XD086, 0XD086, 0XB865, 0X9864,
|
||||||
|
0X9864, 0X9864, 0XB865, 0XD086, 0XD086, 0XD086, 0XD086, 0XD086, 0XD086,
|
||||||
|
0XD086, 0XAB2E, 0XFFFF, 0XFFFF, 0XFFFF, 0XFFFF, 0XFFFF, 0XFFFF, 0XFFFF,
|
||||||
|
0XFFFF, 0XFFFF, 0XDE9A, 0XB8E7, 0XD086, 0XD086, 0XD086, 0X9864, 0XD086,
|
||||||
|
0XD086, 0X9864, 0XD086, 0X9864, 0XFFFF, 0XFFFF, 0XFFFF, 0XFFFF, 0XFFFF,
|
||||||
|
0XFFFF, 0XFFFF, 0XFFFF, 0XFFFF, 0XFFFF, 0XFFFF, 0XFFFF, 0XFFFF, 0XFFFF,
|
||||||
|
0XFFFF, 0XFFFF, 0XFFFF, 0XFFFF, 0XFFFF, 0XFFFF, 0XFFFF, 0XEF7D, 0XB148,
|
||||||
|
0XA1C9, 0XFFFF, 0XFFFF, 0XFFFF, 0XFFFF, 0XFFFF, 0XFFFF, 0XFFFF, 0XFFFF,
|
||||||
|
0XFFFF, 0XBDF7, 0XD086, 0XBD14, 0XEF7D, 0XFFFF, 0XFFFF, 0XA148, 0XD086,
|
||||||
|
0XD086, 0XD086, 0X9864, 0X9864, 0XD086, 0XD086, 0XD086, 0XD086, 0XD086,
|
||||||
|
0XC066, 0XB431, 0XEF7D, 0XFFFF, 0XFFFF, 0XFFFF, 0XFFFF, 0XFFFF, 0XFFFF,
|
||||||
|
0XAA4B, 0XD086, 0XD086, 0XD086, 0X9864, 0XD086, 0XD086, 0XC066, 0X7043,
|
||||||
|
0X9864, 0XA865, 0XD086, 0XD086, 0XD086, 0XC066, 0X9864, 0X9864, 0X9864,
|
||||||
|
0XB865, 0XD086, 0XD086, 0XD086, 0XD086, 0XD086, 0XD086, 0XD086, 0XD086,
|
||||||
|
0XD086, 0XD086, 0XAAAC, 0XFFFF, 0XFFFF, 0XFFFF, 0XFFFF, 0XFFFF, 0XFFFF,
|
||||||
|
0XFFFF, 0XFFFF, 0XFFFF, 0XFFFF, 0XA32E, 0XAA4B, 0XAA4B, 0XAA4B, 0XAB2E,
|
||||||
|
0X9044, 0XD086, 0XA865, 0X9864, 0XD086, 0XD086, 0XBDF7, 0XFFFF, 0XFFFF,
|
||||||
|
0XFFFF, 0XFFFF, 0XFFFF, 0XFFFF, 0XFFFF, 0XFFFF, 0XFFFF, 0XFFFF, 0XFFFF,
|
||||||
|
0XFFFF, 0XFFFF, 0XFFFF, 0XFFFF, 0XEF7D, 0XBDF7, 0XDEFB, 0XFFFF, 0XFFFF,
|
||||||
|
0XFFFF, 0XB431, 0XB865, 0XAC92, 0XFFFF, 0XEF7D, 0XFFFF, 0XFFFF, 0XFFFF,
|
||||||
|
0XFFFF, 0XFFFF, 0XFFFF, 0XEF7D, 0X8947, 0XEF7D, 0XFFFF, 0XFFFF, 0XEF7D,
|
||||||
|
0X9044, 0XD086, 0XD086, 0XB865, 0XB865, 0X9864, 0XD086, 0XD086, 0XD086,
|
||||||
|
0XD086, 0XD086, 0XD086, 0XD086, 0XA0C6, 0XEF7D, 0XFFFF, 0XFFFF, 0XFFFF,
|
||||||
|
0XFFFF, 0XFFFF, 0X9864, 0XD086, 0XD086, 0X9864, 0XD086, 0XD086, 0XD086,
|
||||||
|
0XD086, 0XD086, 0XD086, 0XD086, 0X9864, 0X9864, 0X9864, 0XA865, 0XD086,
|
||||||
|
0XD086, 0XD086, 0XD086, 0XD086, 0XD086, 0XD086, 0XD086, 0XD086, 0XD086,
|
||||||
|
0XD086, 0XD086, 0XD086, 0XA8E6, 0XEF7D, 0XFFFF, 0XFFFF, 0XFFFF, 0XFFFF,
|
||||||
|
0XFFFF, 0XFFFF, 0XFFFF, 0XFFFF, 0XFFFF, 0XFFFF, 0XFFFF, 0XFFFF, 0XFFFF,
|
||||||
|
0XFFFF, 0XCE18, 0XC066, 0XD086, 0XA1C9, 0XB431, 0XD086, 0XD086, 0XB493,
|
||||||
|
0XFFFF, 0XFFFF, 0XFFFF, 0XFFFF, 0XFFFF, 0XFFFF, 0XFFFF, 0XFFFF, 0XFFFF,
|
||||||
|
0XFFFF, 0XFFFF, 0XFFFF, 0XFFFF, 0XFFFF, 0XFFFF, 0XEF7D, 0XAB2E, 0XB865,
|
||||||
|
0XB3B0, 0XFFFF, 0XFFFF, 0X9AAC, 0XB865, 0XA148, 0XFFFF, 0X9AAC, 0XCD96,
|
||||||
|
0XFFFF, 0XFFFF, 0XFFFF, 0XFFFF, 0XFFFF, 0XFFFF, 0XFFFF, 0XFFFF, 0XFFFF,
|
||||||
|
0XFFFF, 0XAA4B, 0XB865, 0X9864, 0X9864, 0X8044, 0X9044, 0X8044, 0XD086,
|
||||||
|
0XD086, 0XD086, 0XD086, 0XD086, 0XA1C9, 0X90C6, 0XD086, 0XB3B0, 0XFFFF,
|
||||||
|
0XFFFF, 0XFFFF, 0XFFFF, 0XFFFF, 0X9864, 0XD086, 0XD086, 0X9864, 0XD086,
|
||||||
|
0XD086, 0XD086, 0XD086, 0X9864, 0X9864, 0X9864, 0XD086, 0XD086, 0XD086,
|
||||||
|
0XD086, 0XD086, 0XD086, 0XD086, 0XD086, 0XD086, 0XD086, 0XD086, 0XD086,
|
||||||
|
0XD086, 0XD086, 0XD086, 0XD086, 0XD086, 0XAB2E, 0XFFFF, 0XFFFF, 0XFFFF,
|
||||||
|
0XFFFF, 0XFFFF, 0XFFFF, 0XDEFB, 0XB3B0, 0XAA4B, 0X9864, 0X9864, 0XA1C9,
|
||||||
|
0XAB2E, 0XBD96, 0XFFFF, 0XAA4B, 0XD086, 0XD086, 0XB493, 0XFFFF, 0XAB2E,
|
||||||
|
0XC066, 0XAAAC, 0XFFFF, 0XFFFF, 0XFFFF, 0XFFFF, 0XFFFF, 0XFFFF, 0XFFFF,
|
||||||
|
0XFFFF, 0XFFFF, 0XFFFF, 0XFFFF, 0XFFFF, 0XFFFF, 0XFFFF, 0XFFFF, 0XFFFF,
|
||||||
|
0XFFFF, 0X8947, 0X9864, 0X9A2A, 0XFFFF, 0X9864, 0XD086, 0XA148, 0XEF7D,
|
||||||
|
0XA8E6, 0XB431, 0XFFFF, 0XFFFF, 0XFFFF, 0XFFFF, 0XFFFF, 0XFFFF, 0XFFFF,
|
||||||
|
0XFFFF, 0XFFFF, 0XCE79, 0XC066, 0XD086, 0XD086, 0XD086, 0X9044, 0X7043,
|
||||||
|
0X8044, 0XD086, 0XD086, 0XD086, 0XD086, 0X9864, 0XFFFF, 0XFFFF, 0XBD14,
|
||||||
|
0X92AC, 0XFFFF, 0XFFFF, 0XFFFF, 0XFFFF, 0XFFFF, 0X9864, 0XD086, 0XB865,
|
||||||
|
0XB865, 0XD086, 0XD086, 0X8044, 0X6843, 0X9864, 0X9864, 0X9864, 0X9864,
|
||||||
|
0XD086, 0XD086, 0XD086, 0XD086, 0XD086, 0XD086, 0XD086, 0XD086, 0XD086,
|
||||||
|
0XD086, 0XD086, 0XD086, 0XD086, 0XD086, 0XD086, 0XD086, 0XBD96, 0XFFFF,
|
||||||
|
0XFFFF, 0XFFFF, 0XFFFF, 0XFFFF, 0XB431, 0XB865, 0XD086, 0XD086, 0XD086,
|
||||||
|
0XD086, 0XD086, 0XD086, 0XD086, 0X9147, 0XA865, 0XD086, 0XC066, 0XCE79,
|
||||||
|
0XFFFF, 0XFFFF, 0XCD96, 0X7926, 0XEF7D, 0XFFFF, 0XFFFF, 0XFFFF, 0XFFFF,
|
||||||
|
0XFFFF, 0XFFFF, 0XFFFF, 0XFFFF, 0XFFFF, 0XFFFF, 0XFFFF, 0XFFFF, 0XFFFF,
|
||||||
|
0XFFFF, 0XFFFF, 0XFFFF, 0X9864, 0XD086, 0XC066, 0X9CF3, 0XC066, 0XD086,
|
||||||
|
0X8A2A, 0X8947, 0XD086, 0XBD14, 0XFFFF, 0XFFFF, 0XFFFF, 0XFFFF, 0XFFFF,
|
||||||
|
0XFFFF, 0XFFFF, 0XFFFF, 0XFFFF, 0XAD14, 0XC066, 0XD086, 0XD086, 0XD086,
|
||||||
|
0X9864, 0X9864, 0X8044, 0XD086, 0XD086, 0XD086, 0XD086, 0XB865, 0XDEFB,
|
||||||
|
0XFFFF, 0XFFFF, 0XFFFF, 0XFFFF, 0XFFFF, 0XFFFF, 0XFFFF, 0XFFFF, 0X9864,
|
||||||
|
0XD086, 0X9864, 0XD086, 0XD086, 0XD086, 0XD086, 0XD086, 0XD086, 0XD086,
|
||||||
|
0XD086, 0XD086, 0X9864, 0X9864, 0X9864, 0X9864, 0X9864, 0X9864, 0X9864,
|
||||||
|
0XC066, 0XD086, 0XD086, 0XD086, 0XD086, 0XD086, 0XD086, 0XD086, 0XD086,
|
||||||
|
0XBDF7, 0XFFFF, 0XFFFF, 0XFFFF, 0XFFFF, 0XB493, 0XD086, 0XD086, 0XD086,
|
||||||
|
0XD086, 0XD086, 0XD086, 0XD086, 0XD086, 0XD086, 0XD086, 0XC066, 0XA865,
|
||||||
|
0XA148, 0XFFFF, 0XFFFF, 0XFFFF, 0XFFFF, 0XFFFF, 0XFFFF, 0XFFFF, 0XFFFF,
|
||||||
|
0XFFFF, 0XFFFF, 0XFFFF, 0XFFFF, 0XFFFF, 0XFFFF, 0XFFFF, 0XFFFF, 0XFFFF,
|
||||||
|
0XFFFF, 0XFFFF, 0XFFFF, 0XFFFF, 0XFFFF, 0XAA4B, 0XD086, 0XD086, 0X71A8,
|
||||||
|
0XD086, 0XD086, 0X9044, 0XD086, 0X9864, 0XBDF7, 0XFFFF, 0XFFFF, 0XFFFF,
|
||||||
|
0XFFFF, 0XFFFF, 0XFFFF, 0XFFFF, 0XFFFF, 0XDE9A, 0XB865, 0XA865, 0XA865,
|
||||||
|
0XD086, 0XD086, 0X7043, 0X9864, 0X9044, 0XA865, 0XD086, 0XD086, 0XD086,
|
||||||
|
0XD086, 0XA8E6, 0XB493, 0XFFFF, 0XFFFF, 0XFFFF, 0XFFFF, 0XFFFF, 0XFFFF,
|
||||||
|
0XFFFF, 0X9864, 0XB865, 0XB865, 0XD086, 0XD086, 0XD086, 0X9864, 0X9864,
|
||||||
|
0X9864, 0X9864, 0X9864, 0X9864, 0X9864, 0X9864, 0XD086, 0XD086, 0XD086,
|
||||||
|
0XD086, 0XD086, 0XA865, 0X9864, 0X9864, 0X9864, 0X9864, 0XD086, 0XD086,
|
||||||
|
0XD086, 0XD086, 0XBDF7, 0XFFFF, 0XFFFF, 0XFFFF, 0XFFFF, 0XA0C6, 0XD086,
|
||||||
|
0XD086, 0XD086, 0XA865, 0X80C5, 0X9864, 0XC066, 0XD086, 0XD086, 0XD086,
|
||||||
|
0XD086, 0XC066, 0X8B8E, 0XFFFF, 0XFFFF, 0XFFFF, 0XFFFF, 0XFFFF, 0XFFFF,
|
||||||
|
0XFFFF, 0XFFFF, 0XFFFF, 0XFFFF, 0XFFFF, 0XFFFF, 0XFFFF, 0XFFFF, 0XFFFF,
|
||||||
|
0XFFFF, 0XFFFF, 0XFFFF, 0XFFFF, 0XFFFF, 0XFFFF, 0XFFFF, 0XB493, 0XD086,
|
||||||
|
0XD086, 0X9864, 0XA865, 0XA865, 0XC066, 0XD086, 0XA8E6, 0XEF7D, 0XFFFF,
|
||||||
|
0XFFFF, 0XFFFF, 0XFFFF, 0XFFFF, 0XFFFF, 0XFFFF, 0XFFFF, 0XAAAC, 0XD086,
|
||||||
|
0XD086, 0XC066, 0X9864, 0X8044, 0XA865, 0X9044, 0XC066, 0X8044, 0XD086,
|
||||||
|
0XD086, 0XD086, 0XD086, 0XD086, 0XD086, 0X9A2A, 0XFFFF, 0XFFFF, 0XFFFF,
|
||||||
|
0XFFFF, 0XFFFF, 0XEF7D, 0XA865, 0X9864, 0XD086, 0XD086, 0XD086, 0XD086,
|
||||||
|
0X9864, 0X9864, 0XC066, 0XD086, 0XD086, 0XD086, 0XD086, 0XC066, 0X9864,
|
||||||
|
0X9864, 0X9864, 0X9864, 0X9864, 0X9864, 0X9864, 0X9864, 0XD086, 0XD086,
|
||||||
|
0X9864, 0X9864, 0X9864, 0XC066, 0XAB2E, 0XFFFF, 0XFFFF, 0XFFFF, 0XFFFF,
|
||||||
|
0X9864, 0XD086, 0XD086, 0X90C6, 0XCE79, 0XFFFF, 0XFFFF, 0X9C92, 0X9864,
|
||||||
|
0XD086, 0XD086, 0XD086, 0XD086, 0XAB2E, 0XFFFF, 0XFFFF, 0XFFFF, 0XFFFF,
|
||||||
|
0XFFFF, 0XFFFF, 0XFFFF, 0XFFFF, 0XFFFF, 0XFFFF, 0XFFFF, 0XFFFF, 0XFFFF,
|
||||||
|
0XFFFF, 0XFFFF, 0XFFFF, 0XFFFF, 0XFFFF, 0XFFFF, 0XFFFF, 0XFFFF, 0XFFFF,
|
||||||
|
0XEF7D, 0XA0C6, 0XD086, 0XD086, 0XB865, 0X9864, 0XD086, 0XB1CA, 0XDE9A,
|
||||||
|
0XFFFF, 0XFFFF, 0XFFFF, 0XFFFF, 0XFFFF, 0XFFFF, 0XFFFF, 0XFFFF, 0XFFFF,
|
||||||
|
0XAA4B, 0XD086, 0XD086, 0XD086, 0XD086, 0X9864, 0X7043, 0XA865, 0X9044,
|
||||||
|
0X9044, 0XD086, 0XD086, 0XD086, 0XD086, 0XB1CA, 0XB431, 0X82AB, 0XFFFF,
|
||||||
|
0XFFFF, 0XFFFF, 0XFFFF, 0XFFFF, 0XBD14, 0XA865, 0XC066, 0XD086, 0XD086,
|
||||||
|
0XD086, 0XD086, 0XD086, 0XD086, 0XA865, 0X9864, 0XC066, 0XD086, 0XD086,
|
||||||
|
0XD086, 0XD086, 0XD086, 0XD086, 0XD086, 0XD086, 0XD086, 0XD086, 0XD086,
|
||||||
|
0X9864, 0X9864, 0X9864, 0X9864, 0X9864, 0X7043, 0X8044, 0XDEFB, 0XFFFF,
|
||||||
|
0XFFFF, 0XFFFF, 0X9864, 0XD086, 0XD086, 0XA32E, 0XFFFF, 0XFFFF, 0XFFFF,
|
||||||
|
0XFFFF, 0X728B, 0XB865, 0XD086, 0XD086, 0XD086, 0X9864, 0XFFFF, 0XFFFF,
|
||||||
|
0XFFFF, 0XFFFF, 0XFFFF, 0XFFFF, 0XFFFF, 0XFFFF, 0XFFFF, 0XFFFF, 0XFFFF,
|
||||||
|
0XFFFF, 0XFFFF, 0XFFFF, 0XFFFF, 0XFFFF, 0XFFFF, 0XFFFF, 0XFFFF, 0XFFFF,
|
||||||
|
0XFFFF, 0XFFFF, 0XFFFF, 0XEF7D, 0XAA4B, 0XD086, 0XD086, 0XB865, 0X90C6,
|
||||||
|
0XEF7D, 0XFFFF, 0XFFFF, 0XFFFF, 0XFFFF, 0XFFFF, 0XFFFF, 0XFFFF, 0XFFFF,
|
||||||
|
0XFFFF, 0XC515, 0X9044, 0XC066, 0XD086, 0XD086, 0XD086, 0X9864, 0X8044,
|
||||||
|
0XC066, 0X8044, 0X9044, 0XC066, 0XD086, 0XD086, 0XD086, 0XBDF7, 0XFFFF,
|
||||||
|
0XFFFF, 0XFFFF, 0XFFFF, 0XFFFF, 0XFFFF, 0XEF7D, 0X6926, 0XC066, 0XD086,
|
||||||
|
0XD086, 0XD086, 0X9044, 0XB865, 0XD086, 0XD086, 0XD086, 0XD086, 0XA865,
|
||||||
|
0X9864, 0XD086, 0XD086, 0XD086, 0XD086, 0XD086, 0XD086, 0XD086, 0XD086,
|
||||||
|
0XD086, 0XD086, 0XD086, 0XD086, 0XD086, 0XA8E6, 0XAAAC, 0XB431, 0X8410,
|
||||||
|
0X8C71, 0XFFFF, 0XFFFF, 0XFFFF, 0XAAAC, 0XD086, 0XD086, 0XA865, 0XA32E,
|
||||||
|
0XB431, 0XB431, 0X8947, 0XC066, 0X9864, 0XD086, 0XD086, 0XD086, 0XC066,
|
||||||
|
0XCE79, 0XFFFF, 0XFFFF, 0XFFFF, 0XFFFF, 0XFFFF, 0XFFFF, 0XFFFF, 0XFFFF,
|
||||||
|
0XFFFF, 0XFFFF, 0XFFFF, 0XFFFF, 0XFFFF, 0XFFFF, 0XFFFF, 0XFFFF, 0XFFFF,
|
||||||
|
0XFFFF, 0XFFFF, 0XFFFF, 0XFFFF, 0XFFFF, 0XFFFF, 0XB431, 0XD086, 0XD086,
|
||||||
|
0XD086, 0XB8E7, 0XDEFB, 0XFFFF, 0XFFFF, 0XFFFF, 0XFFFF, 0XFFFF, 0XFFFF,
|
||||||
|
0XFFFF, 0XFFFF, 0XFFFF, 0XA0C6, 0XD086, 0XA865, 0X9864, 0X9864, 0X9864,
|
||||||
|
0X9044, 0X9044, 0XA865, 0X9864, 0XA865, 0X9864, 0XD086, 0XD086, 0XD086,
|
||||||
|
0XB3B0, 0XFFFF, 0XEF7D, 0XBDF7, 0XB431, 0XAAAC, 0XA148, 0XA865, 0XD086,
|
||||||
|
0XD086, 0XD086, 0XC066, 0XD086, 0XB865, 0X9044, 0X9864, 0X9864, 0XC066,
|
||||||
|
0XD086, 0XD086, 0XD086, 0X9864, 0XB865, 0XD086, 0XD086, 0XD086, 0XD086,
|
||||||
|
0XD086, 0XD086, 0XD086, 0XD086, 0XD086, 0XB8E7, 0XB493, 0XEF7D, 0XFFFF,
|
||||||
|
0XFFFF, 0XFFFF, 0XFFFF, 0XFFFF, 0XFFFF, 0XFFFF, 0XDE9A, 0XB8E7, 0XD086,
|
||||||
|
0XD086, 0XD086, 0XD086, 0XD086, 0XD086, 0XD086, 0X9864, 0XD086, 0XD086,
|
||||||
|
0XD086, 0XD086, 0XBDF7, 0XFFFF, 0XFFFF, 0XFFFF, 0XFFFF, 0XFFFF, 0XFFFF,
|
||||||
|
0XFFFF, 0XFFFF, 0XFFFF, 0XFFFF, 0XFFFF, 0XFFFF, 0XFFFF, 0XFFFF, 0XFFFF,
|
||||||
|
0XFFFF, 0XFFFF, 0XFFFF, 0XFFFF, 0XFFFF, 0XFFFF, 0XFFFF, 0XFFFF, 0XAAAC,
|
||||||
|
0XD086, 0XD086, 0XD086, 0XD086, 0XB3B0, 0XFFFF, 0XFFFF, 0XFFFF, 0XFFFF,
|
||||||
|
0XFFFF, 0XFFFF, 0XFFFF, 0XFFFF, 0XDEFB, 0XB865, 0XD086, 0XD086, 0XD086,
|
||||||
|
0XD086, 0XD086, 0X8044, 0X9864, 0XB865, 0X8044, 0XC066, 0X6843, 0XD086,
|
||||||
|
0XD086, 0X9864, 0XA0C6, 0X99C9, 0XA865, 0XD086, 0XD086, 0XD086, 0XD086,
|
||||||
|
0XD086, 0XD086, 0XD086, 0XD086, 0X8044, 0XB865, 0XD086, 0XC066, 0XA865,
|
||||||
|
0XD086, 0XA865, 0X9864, 0X9864, 0XD086, 0XD086, 0XB865, 0X9864, 0XC066,
|
||||||
|
0XD086, 0XD086, 0XD086, 0XD086, 0XD086, 0XD086, 0XB1CA, 0XDEFB, 0XFFFF,
|
||||||
|
0XFFFF, 0XFFFF, 0XFFFF, 0XFFFF, 0XFFFF, 0XFFFF, 0XFFFF, 0XFFFF, 0XFFFF,
|
||||||
|
0XDEFB, 0XAB2E, 0X9864, 0XC066, 0XD086, 0XC066, 0X9864, 0X89A8, 0XA865,
|
||||||
|
0XD086, 0XD086, 0XD086, 0XA865, 0XEF7D, 0XFFFF, 0XFFFF, 0XFFFF, 0XFFFF,
|
||||||
|
0XFFFF, 0XFFFF, 0XFFFF, 0XFFFF, 0XFFFF, 0XFFFF, 0XFFFF, 0XFFFF, 0XFFFF,
|
||||||
|
0XFFFF, 0XFFFF, 0XFFFF, 0XFFFF, 0XFFFF, 0XFFFF, 0XFFFF, 0XFFFF, 0XFFFF,
|
||||||
|
0XFFFF, 0XAA4B, 0XD086, 0XD086, 0XD086, 0XD086, 0XA148, 0XFFFF, 0XFFFF,
|
||||||
|
0XFFFF, 0XFFFF, 0XFFFF, 0XFFFF, 0XFFFF, 0XFFFF, 0XBDF7, 0XD086, 0XD086,
|
||||||
|
0XD086, 0XD086, 0XD086, 0XD086, 0X7043, 0XC066, 0X6843, 0XD086, 0X7043,
|
||||||
|
0XC066, 0X9044, 0X9864, 0XD086, 0XD086, 0XD086, 0XD086, 0XD086, 0XD086,
|
||||||
|
0XD086, 0XD086, 0XD086, 0XD086, 0XA865, 0XD086, 0X9864, 0XB865, 0XB865,
|
||||||
|
0XD086, 0XC066, 0XA865, 0XD086, 0XD086, 0XD086, 0X9864, 0X9864, 0XC066,
|
||||||
|
0XD086, 0XA865, 0XA865, 0XD086, 0XD086, 0XD086, 0XD086, 0XA865, 0X9C92,
|
||||||
|
0XBDF7, 0XBDF7, 0XBDF7, 0XBDF7, 0XFFFF, 0XFFFF, 0XFFFF, 0XFFFF, 0XFFFF,
|
||||||
|
0XFFFF, 0XFFFF, 0XFFFF, 0XFFFF, 0XFFFF, 0XCE79, 0XBDF7, 0XCE79, 0XEF7D,
|
||||||
|
0XAAAC, 0XD086, 0XD086, 0XD086, 0XD086, 0XA1C9, 0XFFFF, 0XFFFF, 0XFFFF,
|
||||||
|
0XFFFF, 0XFFFF, 0XFFFF, 0XFFFF, 0XFFFF, 0XFFFF, 0XFFFF, 0XFFFF, 0XFFFF,
|
||||||
|
0XFFFF, 0XFFFF, 0XFFFF, 0XFFFF, 0XFFFF, 0XFFFF, 0XFFFF, 0XFFFF, 0XFFFF,
|
||||||
|
0XFFFF, 0XFFFF, 0XFFFF, 0XA148, 0XD086, 0XD086, 0XD086, 0XD086, 0XB865,
|
||||||
|
0XDEFB, 0XFFFF, 0XFFFF, 0XFFFF, 0XFFFF, 0XFFFF, 0XFFFF, 0XFFFF, 0XCD96,
|
||||||
|
0X8044, 0XD086, 0XD086, 0XD086, 0XD086, 0XD086, 0X6843, 0X9044, 0X9864,
|
||||||
|
0XA865, 0XA865, 0X9044, 0XB865, 0XD086, 0XD086, 0XB865, 0X9864, 0X8044,
|
||||||
|
0XC066, 0XD086, 0XD086, 0XB865, 0XD086, 0XA865, 0X9044, 0XD086, 0XB865,
|
||||||
|
0XB865, 0XB865, 0XA865, 0XD086, 0XB865, 0XB865, 0XD086, 0XD086, 0XD086,
|
||||||
|
0XD086, 0XA865, 0X9864, 0XB865, 0XC066, 0X9864, 0XD086, 0XD086, 0XD086,
|
||||||
|
0X9864, 0XD086, 0XD086, 0XD086, 0XD086, 0XD086, 0X9864, 0X9864, 0XA1C9,
|
||||||
|
0XAB2E, 0XBD14, 0XCE79, 0XFFFF, 0XFFFF, 0XFFFF, 0XFFFF, 0XFFFF, 0XCE79,
|
||||||
|
0XB493, 0XB148, 0XD086, 0XD086, 0XD086, 0XD086, 0XD086, 0XBD14, 0XFFFF,
|
||||||
|
0XFFFF, 0XFFFF, 0XFFFF, 0XFFFF, 0XFFFF, 0XFFFF, 0XFFFF, 0XFFFF, 0XFFFF,
|
||||||
|
0XFFFF, 0XFFFF, 0XFFFF, 0XFFFF, 0XFFFF, 0XFFFF, 0XFFFF, 0XFFFF, 0XFFFF,
|
||||||
|
0XFFFF, 0XFFFF, 0XFFFF, 0XFFFF, 0XFFFF, 0X9864, 0XD086, 0XD086, 0XD086,
|
||||||
|
0XD086, 0XD086, 0XBDF7, 0XFFFF, 0XFFFF, 0XFFFF, 0XFFFF, 0XFFFF, 0XFFFF,
|
||||||
|
0XFFFF, 0XA148, 0XD086, 0X9864, 0X9864, 0X9864, 0X9864, 0X9864, 0X9864,
|
||||||
|
0X9864, 0X9864, 0X7043, 0X9864, 0XD086, 0XD086, 0XA865, 0X9864, 0XB865,
|
||||||
|
0XD086, 0X9864, 0XD086, 0XC066, 0X7043, 0XD086, 0XD086, 0X9864, 0XC066,
|
||||||
|
0XA865, 0XD086, 0X9864, 0XD086, 0XC066, 0XA865, 0XD086, 0XA865, 0XC066,
|
||||||
|
0XD086, 0XD086, 0XD086, 0XD086, 0XD086, 0XC066, 0X9864, 0X9044, 0X9864,
|
||||||
|
0XC066, 0X9864, 0XD086, 0XD086, 0XD086, 0XD086, 0XD086, 0XD086, 0XD086,
|
||||||
|
0XD086, 0XD086, 0XD086, 0XD086, 0XC066, 0X9864, 0X9864, 0X9864, 0X9864,
|
||||||
|
0X9864, 0XB865, 0XD086, 0XD086, 0XD086, 0XD086, 0XD086, 0XD086, 0XA1C9,
|
||||||
|
0XFFFF, 0XFFFF, 0XFFFF, 0XFFFF, 0XFFFF, 0XFFFF, 0XFFFF, 0XFFFF, 0XFFFF,
|
||||||
|
0XFFFF, 0XFFFF, 0XFFFF, 0XFFFF, 0XFFFF, 0XFFFF, 0XFFFF, 0XFFFF, 0XFFFF,
|
||||||
|
0XFFFF, 0XFFFF, 0XFFFF, 0XFFFF, 0XFFFF, 0XFFFF, 0XC515, 0XC066, 0XA865,
|
||||||
|
0XD086, 0XD086, 0XD086, 0XD086, 0XAD14, 0XFFFF, 0XFFFF, 0XFFFF, 0XFFFF,
|
||||||
|
0XFFFF, 0XFFFF, 0XFFFF, 0X9864, 0XD086, 0XD086, 0XD086, 0XD086, 0XD086,
|
||||||
|
0XD086, 0X9044, 0X8044, 0X9864, 0XA865, 0XD086, 0XA865, 0X9864, 0XC066,
|
||||||
|
0XD086, 0XD086, 0XA865, 0XC066, 0XC066, 0XA865, 0X9864, 0XD086, 0XA865,
|
||||||
|
0XC066, 0XD086, 0X9864, 0XD086, 0X9864, 0XD086, 0XD086, 0XB865, 0XB865,
|
||||||
|
0XD086, 0X9864, 0XD086, 0XD086, 0XD086, 0XD086, 0XD086, 0XD086, 0XD086,
|
||||||
|
0XD086, 0X9864, 0X8044, 0X8044, 0XD086, 0XD086, 0XD086, 0XD086, 0X9864,
|
||||||
|
0XA865, 0XD086, 0XD086, 0XD086, 0XD086, 0XD086, 0XD086, 0XD086, 0XD086,
|
||||||
|
0XD086, 0XD086, 0XD086, 0XD086, 0XD086, 0XD086, 0XD086, 0XD086, 0XD086,
|
||||||
|
0XB8E7, 0XDEFB, 0XFFFF, 0XFFFF, 0XFFFF, 0XFFFF, 0XFFFF, 0XFFFF, 0XFFFF,
|
||||||
|
0XFFFF, 0XFFFF, 0XFFFF, 0XFFFF, 0XFFFF, 0XFFFF, 0XFFFF, 0X0547, 0X0547,
|
||||||
|
0X0547, 0X0547, 0X0547, 0X0547, 0X0547, 0X0547, 0X0547, 0X04A6, 0XB865,
|
||||||
|
0XD086, 0X31C3, 0XC066, 0XD086, 0XD086, 0X9864, 0XB865, 0X2305, 0X0547,
|
||||||
|
0X0547, 0X0547, 0X0547, 0X0547, 0X0547, 0X9864, 0XD086, 0XD086, 0XD086,
|
||||||
|
0XD086, 0XD086, 0XD086, 0X6843, 0X9864, 0XA865, 0XB865, 0X9864, 0XC066,
|
||||||
|
0XD086, 0XD086, 0XD086, 0XD086, 0X9864, 0XC066, 0XA865, 0XD086, 0X9864,
|
||||||
|
0XD086, 0X9864, 0XD086, 0XD086, 0XA865, 0XC066, 0X9864, 0XD086, 0XD086,
|
||||||
|
0XD086, 0XC066, 0XA865, 0XB865, 0XB865, 0XD086, 0XD086, 0XD086, 0XD086,
|
||||||
|
0XD086, 0XD086, 0XD086, 0XD086, 0XC066, 0X8044, 0X8044, 0XD086, 0XD086,
|
||||||
|
0XD086, 0XD086, 0XD086, 0X9864, 0XC066, 0XD086, 0XD086, 0XD086, 0XD086,
|
||||||
|
0XD086, 0XD086, 0XD086, 0XD086, 0XD086, 0XD086, 0XD086, 0XD086, 0XD086,
|
||||||
|
0XD086, 0X8145, 0X0C66, 0X0547, 0X0547, 0X0547, 0X0547, 0X0547, 0X0547,
|
||||||
|
0X0547, 0X0547, 0X0547, 0X0547, 0X0547, 0X0547, 0X0547, 0X0547, 0X0547,
|
||||||
|
0X0547, 0X0547, 0X0547, 0X0547, 0X0547, 0X0547, 0X0547, 0X0547, 0X0506,
|
||||||
|
0X8145, 0XD086, 0X9105, 0X0506, 0X80E5, 0XD086, 0XD086, 0X9864, 0XD086,
|
||||||
|
0X9864, 0X0547, 0X0547, 0X0547, 0X0547, 0X0547, 0X0547, 0X80E5, 0XD086,
|
||||||
|
0XD086, 0XD086, 0XD086, 0XD086, 0XD086, 0X8044, 0XB865, 0X9864, 0XB865,
|
||||||
|
0XD086, 0XD086, 0XD086, 0XD086, 0XD086, 0XA865, 0XC066, 0X9864, 0XD086,
|
||||||
|
0XD086, 0X9864, 0XC066, 0XA865, 0XD086, 0XD086, 0XD086, 0X9864, 0X9864,
|
||||||
|
0XD086, 0XD086, 0XD086, 0XD086, 0XC066, 0XA865, 0X9864, 0XD086, 0XD086,
|
||||||
|
0XD086, 0XD086, 0XD086, 0XA865, 0X9864, 0X9864, 0X7043, 0X9864, 0XA865,
|
||||||
|
0XD086, 0XD086, 0XD086, 0XD086, 0XD086, 0XD086, 0XA865, 0XC066, 0XD086,
|
||||||
|
0XD086, 0XD086, 0XD086, 0XD086, 0XD086, 0XD086, 0XD086, 0XD086, 0XD086,
|
||||||
|
0XD086, 0XC066, 0X59E5, 0X0506, 0X0547, 0X0547, 0X0547, 0X0547, 0X0547,
|
||||||
|
0X0547, 0X0547, 0X0547, 0X0547, 0X0547, 0X0547, 0X0547, 0X0547, 0X0547,
|
||||||
|
0X0547, 0X0547, 0X0547, 0X0547, 0X0547, 0X0547, 0X0547, 0X0547, 0X0547,
|
||||||
|
0X0547, 0X2305, 0XB865, 0XD086, 0X2305, 0X0547, 0X1B65, 0XD086, 0XD086,
|
||||||
|
0XB865, 0XB865, 0X9864, 0X6985, 0X1B65, 0X0547, 0X0547, 0X0547, 0X0547,
|
||||||
|
0X0C05, 0X9864, 0XD086, 0XD086, 0XD086, 0XD086, 0X9044, 0X8044, 0X9864,
|
||||||
|
0XD086, 0XD086, 0XD086, 0XD086, 0XD086, 0XD086, 0XD086, 0X9864, 0X9864,
|
||||||
|
0XD086, 0XD086, 0XD086, 0X9864, 0X9864, 0XD086, 0XD086, 0XD086, 0XD086,
|
||||||
|
0X9864, 0X9864, 0XD086, 0XD086, 0XD086, 0XD086, 0XD086, 0XB865, 0XA865,
|
||||||
|
0XA865, 0XD086, 0XD086, 0XA865, 0X9864, 0XC066, 0XD086, 0XD086, 0X9864,
|
||||||
|
0XD086, 0XD086, 0XD086, 0XD086, 0XD086, 0XD086, 0XD086, 0XD086, 0XD086,
|
||||||
|
0XA865, 0XC066, 0XD086, 0XD086, 0XD086, 0XD086, 0XD086, 0XD086, 0XD086,
|
||||||
|
0XD086, 0XD086, 0X80E5, 0X0C05, 0X0547, 0X0547, 0X0547, 0X0547, 0X0547,
|
||||||
|
0X0547, 0X0547, 0X0547, 0X0547, 0X0547, 0X0547, 0X0547, 0X0547, 0X0547,
|
||||||
|
0X0547, 0X0547, 0X0547, 0X0547, 0X0547, 0X0547, 0X0547, 0X0547, 0X0547,
|
||||||
|
0X0547, 0X0547, 0X0547, 0X1B65, 0XC066, 0X8044, 0X04A6, 0X0547, 0X0547,
|
||||||
|
0X80E5, 0XD086, 0XD086, 0X9864, 0XA865, 0XD086, 0XD086, 0X1AC4, 0X0405,
|
||||||
|
0X0547, 0X0547, 0X4285, 0XC066, 0X9864, 0X9864, 0X9864, 0X9864, 0X8044,
|
||||||
|
0XA865, 0XD086, 0XD086, 0XC066, 0XA865, 0XD086, 0XD086, 0XD086, 0XD086,
|
||||||
|
0X7043, 0XC066, 0XD086, 0XD086, 0XD086, 0X9864, 0X9864, 0XD086, 0XD086,
|
||||||
|
0XD086, 0XD086, 0XA865, 0XA865, 0XB865, 0XD086, 0XD086, 0XD086, 0XD086,
|
||||||
|
0XD086, 0XB865, 0X8044, 0XD086, 0XA865, 0XC066, 0XD086, 0XD086, 0XD086,
|
||||||
|
0XD086, 0XC066, 0XA865, 0XD086, 0XD086, 0XD086, 0XD086, 0XD086, 0XD086,
|
||||||
|
0XD086, 0XD086, 0XD086, 0X9864, 0XD086, 0XD086, 0XD086, 0XD086, 0XD086,
|
||||||
|
0XD086, 0XA865, 0X59E5, 0X0BA5, 0X0547, 0X0547, 0X0547, 0X0547, 0X0547,
|
||||||
|
0X0547, 0X0547, 0X0547, 0X0547, 0X0547, 0X0547, 0X0547, 0X0547, 0X0547,
|
||||||
|
0X0547, 0X0547, 0X0547, 0X0547, 0X0547, 0X0547, 0X0547, 0X0547, 0X0547,
|
||||||
|
0X0547, 0X0547, 0X0547, 0X0506, 0X3264, 0X98A5, 0X7145, 0X04A6, 0X0547,
|
||||||
|
0X0547, 0X0547, 0X1BC5, 0XC066, 0XD086, 0XD086, 0X9864, 0XD086, 0XD086,
|
||||||
|
0X9864, 0XD086, 0X7145, 0X4984, 0X80A4, 0XD086, 0XD086, 0XD086, 0XD086,
|
||||||
|
0XD086, 0X9864, 0X7043, 0X9864, 0X9864, 0XB865, 0X9864, 0XD086, 0XD086,
|
||||||
|
0XD086, 0X8044, 0XA865, 0XD086, 0XD086, 0XD086, 0XD086, 0X9044, 0XA865,
|
||||||
|
0XD086, 0XD086, 0XD086, 0XD086, 0XD086, 0X9864, 0X9864, 0XD086, 0XD086,
|
||||||
|
0XD086, 0XD086, 0XD086, 0XD086, 0X9864, 0X8044, 0XC066, 0XD086, 0XD086,
|
||||||
|
0XD086, 0XD086, 0XD086, 0XD086, 0XA865, 0XC066, 0XD086, 0XD086, 0XD086,
|
||||||
|
0XD086, 0XD086, 0XD086, 0XD086, 0XD086, 0XD086, 0X9044, 0XA865, 0X9864,
|
||||||
|
0X6985, 0X4285, 0X1B65, 0X0506, 0X0547, 0X0547, 0X0547, 0X0547, 0X0547,
|
||||||
|
0X0547, 0X0547, 0X0547, 0X0547, 0X0547, 0X0547, 0X0547, 0X0547, 0X0547,
|
||||||
|
0X0547, 0X0547, 0X0547, 0X0547, 0X0547, 0X0547, 0X0547, 0X0547, 0X0547,
|
||||||
|
0X0547, 0X0547, 0X0547, 0X0547, 0X0547, 0X0547, 0X0445, 0X0445, 0X0547,
|
||||||
|
0X0547, 0X0547, 0X0547, 0X0547, 0X0547, 0X4A25, 0XD086, 0XD086, 0XD086,
|
||||||
|
0X9864, 0X9864, 0XC066, 0XD086, 0XD086, 0X9864, 0X9864, 0XD086, 0XD086,
|
||||||
|
0XD086, 0XD086, 0XD086, 0XD086, 0X9864, 0XD086, 0XD086, 0XD086, 0X9864,
|
||||||
|
0XD086, 0XB865, 0X9864, 0X4822, 0XD086, 0XD086, 0XD086, 0XD086, 0XD086,
|
||||||
|
0X6843, 0XD086, 0XD086, 0XD086, 0XD086, 0XD086, 0XD086, 0X9864, 0X9864,
|
||||||
|
0XD086, 0XC066, 0X9864, 0X8044, 0X9864, 0X9864, 0X9864, 0X8044, 0XD086,
|
||||||
|
0XD086, 0XD086, 0XD086, 0XD086, 0XD086, 0XD086, 0XD086, 0XA865, 0X9864,
|
||||||
|
0XD086, 0XD086, 0XD086, 0XD086, 0XD086, 0XD086, 0XD086, 0XD086, 0XD086,
|
||||||
|
0XA8C5, 0X32C5, 0X0506, 0X0547, 0X0547, 0X0547, 0X0547, 0X0547, 0X0547,
|
||||||
|
0X0547, 0X0547, 0X0547, 0X0547, 0X0547, 0X0547, 0X0547, 0X0547, 0X0547,
|
||||||
|
0X0547, 0X0547, 0X0547, 0X0547, 0X0547, 0X0547, 0X0547, 0X0547, 0X0547,
|
||||||
|
0X0547, 0X0547, 0X0547, 0X0547, 0X0547, 0X0547, 0X0547, 0X0547, 0X0547,
|
||||||
|
0X0547, 0X0547, 0X0547, 0X0547, 0X0547, 0X0547, 0X0547, 0X0547, 0X4A25,
|
||||||
|
0XD086, 0XD086, 0XD086, 0XA865, 0X9864, 0XB865, 0XD086, 0X9864, 0X9864,
|
||||||
|
0XD086, 0XD086, 0XD086, 0XD086, 0XD086, 0X9864, 0XD086, 0XD086, 0XD086,
|
||||||
|
0XD086, 0X9864, 0XA865, 0XB865, 0XD086, 0X8044, 0XD086, 0XD086, 0XD086,
|
||||||
|
0XD086, 0XD086, 0X6843, 0XD086, 0X9044, 0X9864, 0X9044, 0X9864, 0XB865,
|
||||||
|
0X9864, 0X9864, 0XB865, 0XA865, 0XD086, 0X9864, 0XD086, 0XD086, 0XD086,
|
||||||
|
0XA865, 0XB865, 0XD086, 0XD086, 0XD086, 0XD086, 0XD086, 0XD086, 0XD086,
|
||||||
|
0XC066, 0X9864, 0XA865, 0X9864, 0X9044, 0XA865, 0XD086, 0XD086, 0XD086,
|
||||||
|
0XD086, 0XD086, 0XD086, 0XD086, 0X98A5, 0X32C5, 0X0547, 0X0547, 0X0547,
|
||||||
|
0X0547, 0X0547, 0X0547, 0X0547, 0X0547, 0X0547, 0X0547, 0X0547, 0X0547,
|
||||||
|
0X0547, 0X0547, 0X0547, 0X0547, 0X0547, 0X0547, 0X0547, 0X0547, 0X0547,
|
||||||
|
0X0547, 0X0547, 0X0547, 0X0547, 0X0547, 0X0547, 0X0547, 0X0547, 0X0547,
|
||||||
|
0X0547, 0X0547, 0X0547, 0X0547, 0X0547, 0X0547, 0X0547, 0X0547, 0X0547,
|
||||||
|
0X0547, 0X0547, 0X32C5, 0XC066, 0XD086, 0XD086, 0XD086, 0XB865, 0X9864,
|
||||||
|
0X8044, 0X9864, 0X8044, 0XD086, 0XD086, 0XD086, 0XD086, 0X9864, 0XD086,
|
||||||
|
0XD086, 0XD086, 0XD086, 0X9864, 0XC066, 0XA865, 0X9864, 0X9864, 0XA865,
|
||||||
|
0X9864, 0X9044, 0X9864, 0XD086, 0X6843, 0X9864, 0XC066, 0XA865, 0XD086,
|
||||||
|
0XD086, 0XB865, 0X8044, 0X7043, 0XB865, 0XD086, 0X9864, 0X9864, 0X9864,
|
||||||
|
0X9864, 0X9864, 0XA865, 0XB865, 0X9864, 0X9864, 0X9864, 0XA865, 0XD086,
|
||||||
|
0XD086, 0XD086, 0X9044, 0XD086, 0XD086, 0XC066, 0XA865, 0XC066, 0X9864,
|
||||||
|
0X9864, 0X9044, 0X9864, 0XD086, 0XD086, 0XD086, 0XD086, 0XD086, 0X80E5,
|
||||||
|
0X1BC5, 0X0547, 0X0547, 0X0547, 0X0547, 0X0547, 0X0547, 0X0547, 0X0547,
|
||||||
|
0X0547, 0X0547, 0X0547, 0X0547, 0X0547, 0X0547, 0X0547, 0X0547, 0X0547,
|
||||||
|
0X0547, 0X0547, 0X0547, 0X0547, 0X0547, 0X0547, 0X0547, 0X0547, 0X0547,
|
||||||
|
0X0547, 0X0547, 0X0547, 0X0547, 0X0547, 0X0547, 0X0547, 0X0547, 0X0547,
|
||||||
|
0X0547, 0X0547, 0X0547, 0X0547, 0X0547, 0X4285, 0XD086, 0XD086, 0XD086,
|
||||||
|
0XD086, 0XD086, 0XD086, 0XD086, 0X9864, 0XD086, 0XD086, 0XD086, 0XD086,
|
||||||
|
0XB865, 0XB865, 0XD086, 0XD086, 0XD086, 0XD086, 0X9044, 0X7043, 0XD086,
|
||||||
|
0X8044, 0X9044, 0XD086, 0XD086, 0X9044, 0X9864, 0X6843, 0XD086, 0XD086,
|
||||||
|
0X9864, 0XD086, 0XD086, 0XD086, 0X9864, 0XD086, 0XD086, 0XB865, 0XA865,
|
||||||
|
0X9864, 0XD086, 0XD086, 0XD086, 0XD086, 0XD086, 0XD086, 0XD086, 0X6985,
|
||||||
|
0X04A6, 0X4A25, 0X80A4, 0XA865, 0XD086, 0XD086, 0XD086, 0X9864, 0XD086,
|
||||||
|
0XD086, 0XD086, 0X9864, 0XD086, 0XD086, 0X9864, 0X8044, 0X9864, 0XC066,
|
||||||
|
0XD086, 0XD086, 0XC066, 0X6985, 0X0C66, 0X0547, 0X0547, 0X0547, 0X0547,
|
||||||
|
0X0547, 0X0547, 0X0547, 0X0547, 0X0547, 0X0547, 0X0547, 0X0547, 0X0547,
|
||||||
|
0X0547, 0X0547, 0X0547, 0X0547, 0X0547, 0X0547, 0X0547, 0X0547, 0X0547,
|
||||||
|
0X0547, 0X0547, 0X0547, 0X0547, 0X0547, 0X0547, 0X0547, 0X0547, 0X0547,
|
||||||
|
0X0547, 0X0547, 0X0547, 0X0547, 0X0547, 0X0547, 0X0547, 0X0547, 0X4A25,
|
||||||
|
0XD086, 0XD086, 0XD086, 0XD086, 0XD086, 0XD086, 0X9864, 0XD086, 0XD086,
|
||||||
|
0XD086, 0XD086, 0XA865, 0X9044, 0XB865, 0XA865, 0X9864, 0X9044, 0X9864,
|
||||||
|
0XB865, 0X9044, 0XC066, 0X9864, 0XD086, 0XD086, 0X9864, 0XD086, 0XA865,
|
||||||
|
0XD086, 0XD086, 0X9864, 0XD086, 0XD086, 0XD086, 0X9864, 0XC066, 0X9864,
|
||||||
|
0XB865, 0XD086, 0X9864, 0XD086, 0XD086, 0XD086, 0XD086, 0XD086, 0XD086,
|
||||||
|
0X4A25, 0X0506, 0X0547, 0X0547, 0X1BC5, 0XA8C5, 0XD086, 0XD086, 0XB865,
|
||||||
|
0XB865, 0XD086, 0XD086, 0XD086, 0X9864, 0XD086, 0XD086, 0XD086, 0X9864,
|
||||||
|
0XD086, 0X9864, 0XB865, 0XD086, 0XD086, 0XD086, 0XB865, 0X32C5, 0X0547,
|
||||||
|
0X0547, 0X0547, 0X0547, 0X0547, 0X0547, 0X0547, 0X0547, 0X0547, 0X0547,
|
||||||
|
0X0547, 0X0547, 0X0547, 0X0547, 0X0547, 0X0547, 0X0547, 0X0547, 0X0547,
|
||||||
|
0X0547, 0X0547, 0X0547, 0X0547, 0X0547, 0X0547, 0X0547, 0X0547, 0X0547,
|
||||||
|
0X0547, 0X0547, 0X0547, 0X0547, 0X0547, 0X0547, 0X0547, 0X0547, 0X0547,
|
||||||
|
0X0547, 0X0506, 0X8145, 0XD086, 0XD086, 0XD086, 0XD086, 0XD086, 0XC066,
|
||||||
|
0XA865, 0XD086, 0XD086, 0XB865, 0XB865, 0XD086, 0XB865, 0X8044, 0XB865,
|
||||||
|
0XA865, 0X8044, 0XA865, 0XD086, 0XD086, 0X9864, 0XD086, 0XD086, 0X9864,
|
||||||
|
0XD086, 0XD086, 0XD086, 0XD086, 0X9864, 0XD086, 0XD086, 0X8044, 0X7043,
|
||||||
|
0X7043, 0XC066, 0XD086, 0XC066, 0XA865, 0XD086, 0XD086, 0XD086, 0XD086,
|
||||||
|
0XD086, 0X6985, 0X0547, 0X0547, 0X0547, 0X0547, 0X0547, 0X04A6, 0X2305,
|
||||||
|
0X32C5, 0X6944, 0XD086, 0XD086, 0XD086, 0X9864, 0XC066, 0XD086, 0XD086,
|
||||||
|
0X9864, 0XD086, 0XD086, 0X9864, 0XB865, 0XB865, 0XD086, 0XC066, 0XB865,
|
||||||
|
0XD086, 0X7145, 0X0C66, 0X0547, 0X0547, 0X0547, 0X0547, 0X0547, 0X0547,
|
||||||
|
0X0547, 0X0547, 0X0547, 0X0547, 0X0547, 0X0547, 0X0547, 0X0547, 0X0547,
|
||||||
|
0X0547, 0X0547, 0X0547, 0X0547, 0X0547, 0X0547, 0X0547, 0X0547, 0X0547,
|
||||||
|
0X0547, 0X0547, 0X0547, 0X0547, 0X0547, 0X0547, 0X0547, 0X0547, 0X0547,
|
||||||
|
0X0547, 0X0547, 0X0547, 0X0547, 0X0C66, 0XB865, 0XD086, 0XD086, 0XD086,
|
||||||
|
0XD086, 0XD086, 0XA865, 0XC066, 0XD086, 0X9864, 0XD086, 0XD086, 0XD086,
|
||||||
|
0X9044, 0XB865, 0X9044, 0XD086, 0XD086, 0XD086, 0XC066, 0XA865, 0XD086,
|
||||||
|
0XD086, 0X9864, 0XD086, 0XD086, 0XD086, 0XB865, 0XA865, 0XD086, 0XB865,
|
||||||
|
0XB865, 0XD086, 0XD086, 0XB865, 0X9864, 0X7043, 0XD086, 0XD086, 0XD086,
|
||||||
|
0XD086, 0XD086, 0XD086, 0X32C5, 0X0547, 0X0547, 0X0547, 0X0547, 0X0547,
|
||||||
|
0X0547, 0X0547, 0X0547, 0X0547, 0X0405, 0X2305, 0X0BA5, 0X0BA5, 0X7145,
|
||||||
|
0X9864, 0X90A4, 0X58E3, 0XD086, 0XB865, 0XB865, 0XD086, 0X9864, 0XD086,
|
||||||
|
0XD086, 0X1A63, 0XA8C5, 0XD086, 0XA8C5, 0X0C66, 0X0547, 0X0547, 0X0547,
|
||||||
|
0X0547, 0X0547, 0X0547, 0X0547, 0X0547, 0X0547, 0X0547, 0X0547, 0X0547,
|
||||||
|
0X0547, 0X0547, 0X0547, 0X0547, 0X0547, 0X0547, 0X0547, 0X0547, 0X0547,
|
||||||
|
0X0547, 0X0547, 0X0547, 0X0547, 0X0547, 0X0547, 0X0547, 0X0547, 0X0547,
|
||||||
|
0X0547, 0X0547, 0X0547, 0X0547, 0X0547, 0X0547, 0X0547, 0X32C5, 0XD086,
|
||||||
|
0XD086, 0XD086, 0XD086, 0XA865, 0X90A4, 0X4183, 0X6985, 0X5924, 0X9044,
|
||||||
|
0XD086, 0XB865, 0XB865, 0X9044, 0X9864, 0XD086, 0XD086, 0XD086, 0X9864,
|
||||||
|
0XD086, 0XD086, 0X9864, 0XD086, 0XD086, 0XD086, 0XA8C5, 0X1B65, 0X0405,
|
||||||
|
0X0405, 0X9044, 0XD086, 0XD086, 0XD086, 0XD086, 0XD086, 0X9864, 0XD086,
|
||||||
|
0XD086, 0XD086, 0XD086, 0XD086, 0XD086, 0X4A25, 0X0547, 0X0547, 0X0547,
|
||||||
|
0X0547, 0X0547, 0X0547, 0X0547, 0X0547, 0X0547, 0X0547, 0X0547, 0X0547,
|
||||||
|
0X0547, 0X0547, 0X0547, 0X0547, 0X0547, 0X0405, 0X1AC4, 0XD086, 0XD086,
|
||||||
|
0X9864, 0XD086, 0XD086, 0X4285, 0X04A6, 0X59E5, 0X9864, 0X4224, 0X0547,
|
||||||
|
0X0547, 0X0547, 0X0547, 0X0547, 0X0547, 0X0547, 0X0547, 0X0547, 0X0547,
|
||||||
|
0X0547, 0X0547, 0X0547, 0X0547, 0X0547, 0X0547, 0X0547, 0X0547, 0X0547,
|
||||||
|
0X0547, 0X0547, 0X0547, 0X0547, 0X0547, 0X0547, 0X0547, 0X0547, 0X0547,
|
||||||
|
0X0547, 0X0547, 0X0547, 0X0547, 0X0547, 0X0547, 0X0547, 0X0547, 0X0547,
|
||||||
|
0X0506, 0X98A5, 0XD086, 0XD086, 0X22C4, 0X0506, 0X0547, 0X0547, 0X0547,
|
||||||
|
0X2305, 0XD086, 0XA865, 0X8044, 0XD086, 0XD086, 0XD086, 0XD086, 0XD086,
|
||||||
|
0XD086, 0X9864, 0XD086, 0XD086, 0X9044, 0XD086, 0XB865, 0X6985, 0X04A6,
|
||||||
|
0X0547, 0X0547, 0X0547, 0X90A4, 0XD086, 0XD086, 0XD086, 0XD086, 0XD086,
|
||||||
|
0XA865, 0XC066, 0XD086, 0XD086, 0XD086, 0XD086, 0XD086, 0XB865, 0X0BA5,
|
||||||
|
0X0547, 0X0547, 0X0547, 0X0547, 0X0547, 0X0547, 0X0547, 0X0547, 0X0547,
|
||||||
|
0X0547, 0X0547, 0X0547, 0X0547, 0X0547, 0X0547, 0X0547, 0X0547, 0X0547,
|
||||||
|
0X22C4, 0XA865, 0X9044, 0X9864, 0XD086, 0X6985, 0X0547, 0X0547, 0X0547,
|
||||||
|
0X0547, 0X0547, 0X0547, 0X0547, 0X0547, 0X0547, 0X0547, 0X0547, 0X0547,
|
||||||
|
0X0547, 0X0547, 0X0547, 0X0547, 0X0547, 0X0547, 0X0547, 0X0547, 0X0547,
|
||||||
|
0X0547, 0X0547, 0X0547, 0X0547, 0X0547, 0X0547, 0X0547, 0X0547, 0X0547,
|
||||||
|
0X0547, 0X0547, 0X0547, 0X0547, 0X0547, 0X0547, 0X0547, 0X0547, 0X0547,
|
||||||
|
0X0547, 0X0547, 0X0547, 0X4A25, 0XD086, 0X98A5, 0X0506, 0X0547, 0X0547,
|
||||||
|
0X0547, 0X0506, 0X4183, 0X9864, 0X9044, 0XB865, 0XD086, 0XD086, 0XD086,
|
||||||
|
0X9864, 0XD086, 0XD086, 0X9864, 0XD086, 0X7145, 0X0BA5, 0X0405, 0X04A6,
|
||||||
|
0X0547, 0X0547, 0X0547, 0X0547, 0X0547, 0X32C5, 0XD086, 0XD086, 0XD086,
|
||||||
|
0XD086, 0XD086, 0XD086, 0X9044, 0XD086, 0XD086, 0XD086, 0XD086, 0XD086,
|
||||||
|
0XD086, 0XD086, 0X90A4, 0X4285, 0X04A6, 0X0547, 0X0547, 0X0547, 0X0547,
|
||||||
|
0X0547, 0X0547, 0X0547, 0X0547, 0X0547, 0X0547, 0X0547, 0X0547, 0X0547,
|
||||||
|
0X0547, 0X0547, 0X0405, 0XD086, 0XD086, 0X9864, 0XD086, 0X6985, 0X0547,
|
||||||
|
0X0547, 0X0547, 0X0547, 0X0547, 0X0547, 0X0547, 0X0547, 0X0547, 0X0547,
|
||||||
|
0X0547, 0X0547, 0X0547, 0X0547, 0X0547, 0X0547, 0X0547, 0X0547, 0X0547,
|
||||||
|
0X0547, 0X0547, 0X0547, 0X0547, 0X0547, 0X0547, 0X0547, 0X0547, 0X0547,
|
||||||
|
0X0547, 0X0547, 0X0547, 0X0547, 0X0547, 0X0547, 0X0547, 0X0547, 0X0547,
|
||||||
|
0X0547, 0X0547, 0X0547, 0X0547, 0X0547, 0X1B65, 0XD086, 0X4A25, 0X0547,
|
||||||
|
0X0547, 0X0547, 0X0547, 0X4A25, 0XD086, 0XD086, 0X9864, 0XD086, 0XD086,
|
||||||
|
0XD086, 0X8145, 0X0B64, 0XD086, 0XD086, 0XA865, 0X32C5, 0X0547, 0X0547,
|
||||||
|
0X0547, 0X0547, 0X0547, 0X0547, 0X0547, 0X0547, 0X0547, 0X0547, 0X2305,
|
||||||
|
0X98A5, 0XC066, 0X9864, 0X9864, 0X9864, 0XC066, 0X9864, 0XA865, 0XD086,
|
||||||
|
0XD086, 0XD086, 0XD086, 0XD086, 0XD086, 0XD086, 0XA865, 0X80E5, 0X59E5,
|
||||||
|
0X0C05, 0X0547, 0X0547, 0X0547, 0X0547, 0X0547, 0X0547, 0X0547, 0X0547,
|
||||||
|
0X0547, 0X0547, 0X0547, 0X0547, 0X0445, 0XC066, 0XD086, 0X9044, 0XD086,
|
||||||
|
0X6985, 0X0547, 0X0547, 0X0547, 0X0547, 0X0547, 0X0547, 0X0547, 0X0547,
|
||||||
|
0X0547, 0X0547, 0X0547, 0X0547, 0X0547, 0X0547, 0X0547, 0X0547, 0X0547,
|
||||||
|
0X0547, 0X0547, 0X0547, 0X0547, 0X0547, 0X0547, 0X0547, 0X0547, 0X0547,
|
||||||
|
0X0547, 0X0547, 0X0547, 0X0547, 0X0547, 0X0547, 0X0547, 0X0547, 0X0547,
|
||||||
|
0X0547, 0X0547, 0X0547, 0X0547, 0X0547, 0X0547, 0X0547, 0X0405, 0X98A5,
|
||||||
|
0X0506, 0X0547, 0X0547, 0X0547, 0X0547, 0X59E5, 0XD086, 0XB865, 0XB865,
|
||||||
|
0XD086, 0XD086, 0XA8C5, 0X0C66, 0X0506, 0X98A5, 0XD086, 0X90A4, 0X0547,
|
||||||
|
0X0547, 0X0547, 0X0547, 0X0547, 0X0547, 0X0547, 0X0547, 0X0547, 0X0547,
|
||||||
|
0X0547, 0X0547, 0X0506, 0X70E4, 0XD086, 0XD086, 0XD086, 0XD086, 0XC066,
|
||||||
|
0X9864, 0X9864, 0X9864, 0X9044, 0X9864, 0XC066, 0XD086, 0XD086, 0XD086,
|
||||||
|
0XD086, 0XD086, 0XC066, 0X1BC5, 0X0547, 0X0547, 0X0547, 0X0547, 0X0547,
|
||||||
|
0X0547, 0X0547, 0X0547, 0X0547, 0X0547, 0X0547, 0X0547, 0X68E4, 0X9044,
|
||||||
|
0X9864, 0XD086, 0X6985, 0X0547, 0X0547, 0X0547, 0X0547, 0X0547, 0X0547,
|
||||||
|
0X0547, 0X0547, 0X0547, 0X0547, 0X0547, 0X0547, 0X0547, 0X0547, 0X0547,
|
||||||
|
0X0547, 0X0547, 0X0547, 0X0547, 0X0547, 0X0547, 0X0547, 0X0547, 0X0547,
|
||||||
|
0X0547, 0X0547, 0X0547, 0X0547, 0X0547, 0X0547, 0X0547, 0X0547, 0X0547,
|
||||||
|
0X0547, 0X0547, 0X0547, 0X0547, 0X0547, 0X0547, 0X0547, 0X0547, 0X0547,
|
||||||
|
0X0445, 0X1BC5, 0X0547, 0X0547, 0X0547, 0X0547, 0X0C66, 0X90A4, 0XA865,
|
||||||
|
0X9044, 0XD086, 0XD086, 0XA8C5, 0X0C66, 0X0547, 0X0547, 0X32C5, 0XD086,
|
||||||
|
0X4A25, 0X0547, 0X0547, 0X0547, 0X0547, 0X0547, 0X0547, 0X0547, 0X0547,
|
||||||
|
0X0547, 0X0547, 0X0547, 0X0547, 0X0547, 0X0C66, 0X7145, 0X9864, 0X9864,
|
||||||
|
0XA865, 0XA865, 0XD086, 0XD086, 0X9864, 0XD086, 0XD086, 0X9864, 0XD086,
|
||||||
|
0XD086, 0X90A4, 0X80E5, 0XC066, 0XD086, 0X7145, 0X0547, 0X0547, 0X0547,
|
||||||
|
0X0547, 0X0547, 0X0547, 0X0547, 0X0547, 0X0547, 0X0547, 0X0547, 0X0547,
|
||||||
|
0X9864, 0XD086, 0X9864, 0XD086, 0X6985, 0X0547, 0X0547, 0X0547, 0X0547,
|
||||||
|
0X0547, 0X0547, 0X0547, 0X0547, 0X0547, 0X0547, 0X0547, 0X0547, 0X0547,
|
||||||
|
0X0547, 0X0547, 0X0547, 0X0547, 0X0547, 0X0547, 0X0547, 0X0547, 0X0547,
|
||||||
|
0X0547, 0X0547, 0X0547, 0X0547, 0X0547, 0X0547, 0X0547, 0X0547, 0X0547,
|
||||||
|
0X0547, 0X0547, 0X0547, 0X0547, 0X0547, 0X0547, 0X0547, 0X0547, 0X0547,
|
||||||
|
0X0547, 0X0547, 0X0547, 0X0547, 0X0547, 0X0547, 0X0547, 0X0547, 0X80E5,
|
||||||
|
0XD086, 0XB865, 0XB865, 0XD086, 0XA8C5, 0X0C66, 0X0547, 0X0547, 0X0547,
|
||||||
|
0X0506, 0X9044, 0X04A6, 0X0547, 0X0547, 0X0547, 0X0547, 0X0547, 0X0547,
|
||||||
|
0X0547, 0X0547, 0X0547, 0X0547, 0X0547, 0X0547, 0X0547, 0X0547, 0X0547,
|
||||||
|
0X0547, 0X0547, 0X4285, 0XB865, 0XA865, 0X9864, 0XC066, 0XD086, 0XA865,
|
||||||
|
0XC066, 0XD086, 0XC066, 0X0C05, 0X0547, 0X0445, 0X4285, 0X58E3, 0X0547,
|
||||||
|
0X0547, 0X0547, 0X0547, 0X0547, 0X0547, 0X0547, 0X0547, 0X0547, 0X0547,
|
||||||
|
0X0547, 0X0547, 0X9864, 0XD086, 0X9864, 0XD086, 0X4285, 0X0547, 0X0547,
|
||||||
|
0X0547, 0X0547, 0X0547, 0X0547, 0X0547, 0X0547, 0X0547, 0X0547, 0X0547,
|
||||||
|
0X0547, 0X0547, 0X0547, 0X0547, 0X0547, 0X0547, 0X0547, 0X0547, 0X0547,
|
||||||
|
0X0547, 0X0547, 0X0547, 0X0547, 0X0547, 0X0547, 0X0547, 0X0547, 0X0547,
|
||||||
|
0X0547, 0X0547, 0X0547, 0X0547, 0X0547, 0X0547, 0X0547, 0X0547, 0X0547,
|
||||||
|
0X0547, 0X0547, 0X0547, 0X0547, 0X0547, 0X0547, 0X0547, 0X0547, 0X0547,
|
||||||
|
0X0547, 0X9864, 0XD086, 0X9864, 0XD086, 0XA8C5, 0X0C66, 0X0547, 0X0547,
|
||||||
|
0X0547, 0X0547, 0X0547, 0X0405, 0X0547, 0X0547, 0X0547, 0X0547, 0X0547,
|
||||||
|
0X0405, 0X04A6, 0X2305, 0X0547, 0X0547, 0X0547, 0X0547, 0X0547, 0X0547,
|
||||||
|
0X0547, 0X0547, 0X0547, 0X0547, 0X0C66, 0X80E5, 0X9864, 0X9864, 0X9864,
|
||||||
|
0X8044, 0XB865, 0XD086, 0XD086, 0X32C5, 0X0547, 0X0547, 0X0547, 0X0547,
|
||||||
|
0X0547, 0X0547, 0X0547, 0X0547, 0X0547, 0X0547, 0X0547, 0X0547, 0X0547,
|
||||||
|
0X0547, 0X0547, 0X0547, 0X4285, 0XA865, 0X7043, 0XB865, 0XD086, 0X2305,
|
||||||
|
0X0547, 0X0547, 0X0547, 0X0547, 0X0547, 0X0547, 0X0547, 0X0547, 0X0547,
|
||||||
|
0X0547, 0X0547, 0X0547, 0X0547, 0X0547, 0X0547, 0X0547, 0X0547, 0X0547,
|
||||||
|
0X0547, 0X0547, 0X0547, 0X0547, 0X0547, 0X0547, 0X0547, 0X0547, 0X0547,
|
||||||
|
0X0547, 0X0547, 0X0547, 0X0547, 0X0547, 0X0547, 0X0547, 0X0547, 0X0547,
|
||||||
|
0X0547, 0X0547, 0X0547, 0X0547, 0X0547, 0X0547, 0X0547, 0X0547, 0X0547,
|
||||||
|
0X0547, 0X0547, 0X2365, 0X9864, 0XB865, 0XB865, 0XA8C5, 0X0C66, 0X0547,
|
||||||
|
0X0547, 0X0547, 0X0547, 0X0547, 0X0547, 0X0547, 0X0547, 0X0547, 0X0547,
|
||||||
|
0X0506, 0X70A4, 0XA865, 0X8044, 0XD086, 0X7145, 0X0506, 0X0547, 0X0547,
|
||||||
|
0X0547, 0X0547, 0X0547, 0X0547, 0X0547, 0X04A6, 0X3224, 0XD086, 0XD086,
|
||||||
|
0XC066, 0X9864, 0XC066, 0XD086, 0XD086, 0X4A25, 0X0547, 0X0547, 0X0547,
|
||||||
|
0X0547, 0X0547, 0X0547, 0X1B65, 0X32C5, 0X68E4, 0X2365, 0X0547, 0X0547,
|
||||||
|
0X0547, 0X0547, 0X0547, 0X0547, 0X0547, 0X9864, 0XD086, 0X9864, 0XD086,
|
||||||
|
0XC066, 0X0445, 0X0547, 0X0547, 0X0547, 0X0547, 0X0547, 0X0547, 0X0547,
|
||||||
|
0X0547, 0X0547, 0X0547, 0X0547, 0X0547, 0X0547, 0X0547, 0X0547, 0X0547,
|
||||||
|
0X0547, 0X0547, 0X0547, 0X0547, 0X0547, 0X0547, 0X0547, 0X0547, 0X0547,
|
||||||
|
0X0547, 0X0547, 0X0547, 0X0547, 0X0547, 0X0547, 0X0547, 0X0547, 0X0547,
|
||||||
|
0X0547, 0X2305, 0X6985, 0X59E5, 0X22C4, 0X0445, 0X0547, 0X0547, 0X0547,
|
||||||
|
0X0547, 0X0547, 0X0547, 0X0C66, 0XA8C5, 0XA865, 0XA865, 0XD086, 0X2305,
|
||||||
|
0X0547, 0X0547, 0X0547, 0X0547, 0X0547, 0X0547, 0X0547, 0X0547, 0X0547,
|
||||||
|
0X0547, 0X0547, 0X0BA5, 0X0C05, 0X0C66, 0X9044, 0XD086, 0XD086, 0X8145,
|
||||||
|
0X04A6, 0X0547, 0X0547, 0X0547, 0X0547, 0X0547, 0X0C05, 0XB865, 0XC066,
|
||||||
|
0X9864, 0X9044, 0XA865, 0XD086, 0XD086, 0XD086, 0X4A25, 0X0547, 0X0547,
|
||||||
|
0X0547, 0X0547, 0X0547, 0X0547, 0X22C4, 0X70E4, 0XB865, 0X9864, 0XC066,
|
||||||
|
0X2365, 0X0547, 0X0547, 0X0547, 0X0547, 0X0547, 0X0547, 0X5924, 0X9864,
|
||||||
|
0XA865, 0XD086, 0X9864, 0X0547, 0X0547, 0X0547, 0X0547, 0X0547, 0X0547,
|
||||||
|
0X0547, 0X0547, 0X0547, 0X0547, 0X0547, 0X0547, 0X0547, 0X0547, 0X0547,
|
||||||
|
0X0547, 0X0547, 0X0547, 0X0547, 0X0547, 0X0547, 0X0547, 0X0547, 0X0547,
|
||||||
|
0X0547, 0X0547, 0X0547, 0X0547, 0X0547, 0X0547, 0X0547, 0X0547, 0X0547,
|
||||||
|
0X0547, 0X0547, 0X0547, 0X3224, 0X22C4, 0X9864, 0XA865, 0XC066, 0X6985,
|
||||||
|
0X0BA5, 0X0506, 0X0547, 0X0506, 0X32C5, 0XB865, 0XD086, 0XD086, 0XD086,
|
||||||
|
0X80E5, 0X0547, 0X0547, 0X0547, 0X0547, 0X0547, 0X0547, 0X0547, 0X0547,
|
||||||
|
0X0547, 0X0547, 0X0547, 0X0547, 0X0547, 0X0547, 0X0547, 0X0C05, 0X4A25,
|
||||||
|
0X80E5, 0XD086, 0XB865, 0X4A25, 0X0BA5, 0X22C4, 0X6985, 0X90A4, 0X9864,
|
||||||
|
0X9864, 0X9864, 0X9044, 0XD086, 0XD086, 0XD086, 0XB865, 0X2305, 0X0547,
|
||||||
|
0X0547, 0X0547, 0X0547, 0X0547, 0X0547, 0X0547, 0X04A6, 0X0547, 0X1B04,
|
||||||
|
0XC066, 0XD086, 0XC066, 0X4285, 0X0506, 0X0547, 0X0547, 0X0547, 0X4A25,
|
||||||
|
0XD086, 0XD086, 0XD086, 0XD086, 0X59E5, 0X0547, 0X0547, 0X0547, 0X0547,
|
||||||
|
0X0547, 0X0547, 0X0547, 0X0547, 0X0547, 0X0547, 0X0547, 0X0547, 0X0547,
|
||||||
|
0X0547, 0X0547, 0X0547, 0X0547, 0X0547, 0X0547, 0X0547, 0X0547, 0X0547,
|
||||||
|
0X0547, 0X0547, 0X0547, 0X0547, 0X0547, 0X0547, 0X0547, 0X0547, 0X0547,
|
||||||
|
0X0547, 0X0547, 0X0547, 0X0547, 0X0547, 0X0547, 0X0547, 0X7043, 0XA865,
|
||||||
|
0XD086, 0XD086, 0XB865, 0X7043, 0X6843, 0X9864, 0XD086, 0XD086, 0XD086,
|
||||||
|
0XD086, 0XD086, 0X1B65, 0X0547, 0X0547, 0X0547, 0X0547, 0X0547, 0X0547,
|
||||||
|
0X0547, 0X0547, 0X0547, 0X0547, 0X0547, 0X0506, 0X32C5, 0X3264, 0X6985,
|
||||||
|
0X59E5, 0X04A6, 0X0547, 0X4A25, 0XC066, 0X9864, 0XA865, 0XD086, 0XD086,
|
||||||
|
0XD086, 0XD086, 0XD086, 0XD086, 0XD086, 0XD086, 0XC066, 0X6985, 0X04A6,
|
||||||
|
0X0547, 0X0547, 0X0547, 0X0547, 0X0547, 0X0547, 0X0547, 0X0547, 0X0547,
|
||||||
|
0X0C66, 0X59E5, 0X6883, 0X9864, 0X9864, 0XD086, 0X98A5, 0X4285, 0X32C5,
|
||||||
|
0X6944, 0XD086, 0XD086, 0XD086, 0XD086, 0XD086, 0X2305, 0X0547, 0X0547,
|
||||||
|
0X0547, 0X0547, 0X0547, 0X0547, 0X0547, 0X0547, 0X0547, 0X0547, 0X0547,
|
||||||
|
0X0547, 0X0547, 0X0547, 0X0547, 0X0547, 0X0547, 0X0547, 0X0547, 0X0547,
|
||||||
|
0X0547, 0X0547, 0X0547, 0X0547, 0X0547, 0X0547, 0X0547, 0X0547, 0X0547,
|
||||||
|
0X0547, 0X0547, 0X0547, 0X0547, 0X0547, 0X0506, 0X32C5, 0X6985, 0X6944,
|
||||||
|
0XC066, 0XC066, 0X9864, 0X9864, 0XB865, 0XD086, 0XD086, 0XD086, 0XD086,
|
||||||
|
0XD086, 0XD086, 0XD086, 0XA865, 0X0506, 0X0547, 0X0547, 0X0547, 0X0547,
|
||||||
|
0X0547, 0X0547, 0X0547, 0X0547, 0X0547, 0X0547, 0X0506, 0X80E5, 0X9864,
|
||||||
|
0X9864, 0XD086, 0XD086, 0XB865, 0X6985, 0X6985, 0X9044, 0XD086, 0XD086,
|
||||||
|
0XD086, 0XD086, 0XD086, 0XD086, 0XD086, 0XD086, 0XA865, 0X59E5, 0X0C05,
|
||||||
|
0X0547, 0X0547, 0X0547, 0X0547, 0X0547, 0X0547, 0X0547, 0X0547, 0X0547,
|
||||||
|
0X0506, 0X6985, 0XA865, 0XA865, 0XD086, 0XD086, 0XD086, 0X9864, 0XB865,
|
||||||
|
0XD086, 0XD086, 0XD086, 0XD086, 0XD086, 0XD086, 0XD086, 0XD086, 0X6985,
|
||||||
|
0X0547, 0X0547, 0X0547, 0X0547, 0X0547, 0X0547, 0X0547, 0X0547, 0X0547,
|
||||||
|
0X0547, 0X0547, 0X0547, 0X0547, 0X0547, 0X0547, 0X0547, 0X0547, 0X0547,
|
||||||
|
0X0547, 0X0547, 0X0547, 0X0547, 0X0547, 0X0547, 0X0547, 0X0547, 0X0547,
|
||||||
|
0X0547, 0X0547, 0X0547, 0X0547, 0X0547, 0X0547, 0X0547, 0X3264, 0X7145,
|
||||||
|
0X6985, 0X9864, 0X9044, 0X9864, 0X9864, 0X9864, 0XA865, 0XD086, 0XD086,
|
||||||
|
0XD086, 0XD086, 0XD086, 0XD086, 0XD086, 0XD086, 0X90A4, 0X6985, 0X4285,
|
||||||
|
0X1BC5, 0X0547, 0X0547, 0X0547, 0X0547, 0X0547, 0X0547, 0X0547, 0X0445,
|
||||||
|
0X2305, 0X04A6, 0X90A4, 0XC066, 0X9864, 0X9044, 0X9864, 0X9864, 0X9864,
|
||||||
|
0X9864, 0XD086, 0XD086, 0XD086, 0XD086, 0XD086, 0XD086, 0X58E3, 0X3264,
|
||||||
|
0X1B65, 0X0506, 0X0547, 0X0547, 0X0547, 0X0547, 0X0547, 0X0547, 0X0547,
|
||||||
|
0X0547, 0X0547, 0X4224, 0X4224, 0X3264, 0X7043, 0X4A25, 0X32C5, 0X49C4,
|
||||||
|
0X9864, 0XD086, 0XD086, 0XD086, 0XD086, 0XD086, 0XD086, 0XD086, 0XD086,
|
||||||
|
0XD086, 0XD086, 0X7145, 0X1B65, 0X0506, 0X0547, 0X0547, 0X0547, 0X0547,
|
||||||
|
0X0547, 0X0547, 0X0547, 0X0547, 0X0547, 0X0547, 0X0547, 0X0547, 0X0547,
|
||||||
|
0X0547, 0X0547, 0X0547, 0X0547, 0X0547, 0X0547, 0X0547, 0X0547, 0X0547,
|
||||||
|
0X0547, 0X0547, 0X0547, 0X0547, 0X0547, 0X0547, 0X0547, 0X0547, 0X0547,
|
||||||
|
0X04A6, 0X0547, 0X0547, 0X04A6, 0X80E5, 0XD086, 0XD086, 0XD086, 0XD086,
|
||||||
|
0XD086, 0XD086, 0XD086, 0XD086, 0XC066, 0X7145, 0X49C4, 0XB865, 0XD086,
|
||||||
|
0XD086, 0XD086, 0X9044, 0X9864, 0X32C5, 0X0547, 0X0547, 0X0547, 0X0547,
|
||||||
|
0X0547, 0X0547, 0X0547, 0X0547, 0X0445, 0X5883, 0XA865, 0XD086, 0XD086,
|
||||||
|
0XC066, 0X9864, 0X7145, 0X6985, 0X3264, 0X80E5, 0X7145, 0X32C5, 0X70E4,
|
||||||
|
0XD086, 0XD086, 0XD086, 0X68E4, 0X4285, 0X04A6, 0X0547, 0X0547, 0X0547,
|
||||||
|
0X0547, 0X0547, 0X0547, 0X0547, 0X0405, 0X0547, 0X0547, 0X0547, 0X0506,
|
||||||
|
0X6985, 0X9864, 0XD086, 0XD086, 0XA865, 0X9864, 0XD086, 0XD086, 0XD086,
|
||||||
|
0XB865, 0X80E5, 0X80A4, 0XC066, 0XD086, 0XD086, 0X58E3, 0X32C5, 0X0547,
|
||||||
|
0X0547, 0X0547, 0X0547, 0X0547, 0X0547, 0X0547, 0X0547, 0X0547, 0X0547,
|
||||||
|
0X0547, 0X0547, 0X0547, 0X0547, 0X0547, 0X0547, 0X0547, 0X0547, 0X0547,
|
||||||
|
0X0547, 0X0547, 0X0547, 0X0547, 0X0547, 0X0547, 0X0547, 0X0547, 0X0547,
|
||||||
|
0X0547, 0X0547, 0X0547, 0X0547, 0X0C66, 0X90A4, 0XA865, 0XA865, 0XD086,
|
||||||
|
0XD086, 0XD086, 0X6985, 0X0BA5, 0X0405, 0X22C4, 0X0C05, 0X0547, 0X0547,
|
||||||
|
0X0C66, 0X7145, 0XC066, 0XD086, 0X70A4, 0X4285, 0X58E3, 0X0506, 0X0547,
|
||||||
|
0X0547, 0X0547, 0X0547, 0X0547, 0X0547, 0X0547, 0X59E5, 0XA865, 0X9044,
|
||||||
|
0X9864, 0X4A25, 0X0445, 0X0547, 0X0547, 0X0547, 0X0547, 0X0547, 0X0547,
|
||||||
|
0X0547, 0X0547, 0X1B65, 0X98A5, 0XD086, 0X9044, 0X7145, 0X8044, 0X04A6,
|
||||||
|
0X0547, 0X0547, 0X0547, 0X0547, 0X0547, 0X0547, 0X0547, 0X0547, 0X0547,
|
||||||
|
0X1BC5, 0X7145, 0X9864, 0XD086, 0X98A5, 0X2305, 0X0506, 0X0506, 0X32C5,
|
||||||
|
0X6985, 0X32C5, 0X04A6, 0X0547, 0X0547, 0X0C05, 0X5984, 0XA865, 0X9864,
|
||||||
|
0X9864, 0X32C5, 0X0547, 0X0547, 0X0547, 0X0547, 0X0547, 0X0547, 0X0547,
|
||||||
|
0X0547, 0X0547, 0X0547, 0X0547, 0X0547, 0X0547, 0X0547, 0X0547, 0X0547,
|
||||||
|
0X0547, 0X0547, 0X0547, 0X0547, 0X0547, 0X0547, 0X0547, 0X0547, 0X0547,
|
||||||
|
0X0547, 0X0547, 0X0547, 0X0547, 0X0547, 0X0547, 0X49C4, 0X59E5, 0X22C4,
|
||||||
|
0X70E4, 0X9864, 0X7145, 0X1B65, 0X0547, 0X0547, 0X0547, 0X0547, 0X0547,
|
||||||
|
0X0547, 0X0547, 0X0547, 0X0547, 0X0445, 0X0405, 0X0506, 0X0547, 0X0506,
|
||||||
|
0X0506, 0X0547, 0X0547, 0X0547, 0X0547, 0X0547, 0X0547, 0X0547, 0X2264,
|
||||||
|
0X0506, 0X0506, 0X0445, 0X0547, 0X0547, 0X0547, 0X0547, 0X0547, 0X0547,
|
||||||
|
0X0547, 0X0547, 0X0547, 0X0547, 0X0547, 0X0506, 0X0405, 0X0445, 0X0547,
|
||||||
|
0X0C66, 0X0445, 0X0547, 0X0547, 0X0547, 0X0547, 0X0547, 0X0547, 0X0547,
|
||||||
|
0X0547, 0X0506, 0X90A4, 0X80E5, 0X4224, 0X3224, 0X0506, 0X0547, 0X0547,
|
||||||
|
0X0547, 0X0547, 0X0547, 0X0547, 0X0547, 0X0547, 0X0547, 0X0547, 0X0547,
|
||||||
|
0X0405, 0X0547, 0X0506, 0X1A03, 0X0547, 0X0547, 0X0547, 0X0547, 0X0547,
|
||||||
|
0X0547, 0X0547, 0X0547, 0X0547, 0X0547, 0X0547, 0X0547, 0X0547, 0X0547,
|
||||||
|
0X0547, 0X0547, 0X0547, 0X0547, 0X0547, 0X0547, 0X0547, 0X0547, 0X0547,
|
||||||
|
0X0547, 0X0547, 0X0547, 0X0547, 0X0547, 0X0547, 0X0547, 0X0547, 0X0B64,
|
||||||
|
0X0547, 0X0547, 0X0547, 0X0547, 0X0547, 0X0547, 0X0547, 0X0547, 0X0547,
|
||||||
|
0X0547, 0X0547, 0X0547, 0X0547, 0X0547, 0X0547, 0X0547, 0X0547, 0X0547,
|
||||||
|
0X0547, 0X0547, 0X0547, 0X0547, 0X0547, 0X0547, 0X0547, 0X0547, 0X0547,
|
||||||
|
0X0547, 0X0547, 0X0547, 0X0547, 0X0547, 0X0547, 0X0547, 0X0547, 0X0547,
|
||||||
|
0X0547, 0X0547, 0X0547, 0X0547, 0X0547, 0X0547, 0X0547, 0X0547, 0X0547,
|
||||||
|
0X0547, 0X0547, 0X0547, 0X0547, 0X0547, 0X0547, 0X0547, 0X0547, 0X0547,
|
||||||
|
0X0547, 0X0547, 0X0547, 0X04A6, 0X1BC5, 0X0547, 0X0547, 0X0547, 0X0547,
|
||||||
|
0X0547, 0X0547, 0X0547, 0X0547, 0X0547, 0X0547, 0X0547, 0X0547, 0X0547,
|
||||||
|
0X0547, 0X0547, 0X0547, 0X0547, 0X0547, 0X0547, 0X0547, 0X0547, 0X0547,
|
||||||
|
0X0547, 0X0547, 0X0547, 0X0547, 0X0547, 0X0547, 0X0547, 0X0547, 0X0547,
|
||||||
|
0X0547, 0X0547, 0X0547, 0X0547, 0X0547, 0X0547, 0X0547, 0X0547, 0X0547,
|
||||||
|
0X0547, 0X0547, 0X0547, 0X0547, 0X0547, 0X0547, 0X0547, 0X0547, 0X0547,
|
||||||
|
0X0547, 0X0547, 0X0547, 0X0547, 0X0547, 0X0547, 0X0547, 0X0547, 0X0547,
|
||||||
|
0X0547, 0X0547, 0X0547, 0X0547, 0X0547, 0X0547, 0X0547, 0X0547, 0X0547,
|
||||||
|
0X0547, 0X0547, 0X0547, 0X0547, 0X0547, 0X0547, 0X0547, 0X0547, 0X0547,
|
||||||
|
0X0547, 0X0547, 0X0547, 0X0547, 0X0547, 0X0547, 0X0547, 0X0547, 0X0547,
|
||||||
|
0X0547, 0X0547, 0X0547, 0X0547, 0X0547, 0X0547, 0X0547, 0X0547, 0X0547,
|
||||||
|
0X0547, 0X0547, 0X0547, 0X0547, 0X0547, 0X0547, 0X0547, 0X0547, 0X0547,
|
||||||
|
0X0547, 0X0547, 0X0547, 0X0547, 0X0547, 0X0547, 0X0547, 0X0547, 0X0547,
|
||||||
|
0X0547, 0X0547, 0X0547, 0X0547, 0X0547, 0X0547, 0X0547, 0X0547, 0X0547,
|
||||||
|
0X0547, 0X0547, 0X0547, 0X0547, 0X0547, 0X0547, 0X0547, 0X0547, 0X0547,
|
||||||
|
0X0547, 0X0547, 0X0547, 0X0547, 0X0547, 0X0547, 0X0547, 0X0547, 0X0547,
|
||||||
|
0X0547, 0X0547, 0X0547, 0X0547, 0X0547, 0X0547, 0X0547, 0X0547, 0X0547,
|
||||||
|
0X0547, 0X0547, 0X0547, 0X0547, 0X0547, 0X0547, 0X0547, 0X0547, 0X0547,
|
||||||
|
0X0547, 0X0547, 0X0547, 0X0547, 0X0547, 0X0547, 0X0547, 0X0547, 0X0547,
|
||||||
|
0X0547, 0X0547, 0X0547, 0X0547, 0X0547, 0X0547, 0X0547, 0X0547, 0X0547,
|
||||||
|
0X0547, 0X0547, 0X0547, 0X0547, 0X0547, 0X0547, 0X0547, 0X0547, 0X0547,
|
||||||
|
0X0547, 0X0547, 0X0547, 0X0547, 0X0547, 0X0547, 0X0547, 0X0547, 0X0547,
|
||||||
|
0X0547, 0X0547, 0X0547, 0X0547, 0X0547, 0X0547, 0X0547, 0X0547, 0X0547,
|
||||||
|
0X0547, 0X0547, 0X0547, 0X0547, 0X0547, 0X0547, 0X0547, 0X0547, 0X0547,
|
||||||
|
0X0547, 0X0547, 0X0547, 0X0547, 0X0547, 0X0547, 0X0547, 0X0547, 0X0547,
|
||||||
|
0X0547, 0X0547, 0X0547, 0X0547, 0X0547, 0X0547, 0X0547, 0X0547, 0X0547,
|
||||||
|
0X0547, 0X0547, 0X0547, 0X0547, 0X0547, 0X0547, 0X0547, 0X0547, 0X0547,
|
||||||
|
0X0547, 0X0547, 0X0547, 0X0547, 0X0547, 0X0547, 0X0547, 0X0547, 0X0547,
|
||||||
|
0X0547, 0X0547, 0X0547, 0X0547, 0X0547, 0X0547, 0X0547, 0X0547, 0X0547,
|
||||||
|
0X0547, 0X0547, 0X0547, 0X0547, 0X0547, 0X0547, 0X0547, 0X0547, 0X0547,
|
||||||
|
0X0547, 0X0547, 0X0547, 0X0547, 0X0547, 0X0547, 0X0547, 0X0547, 0X0547,
|
||||||
|
0X0547, 0X0547, 0X0547, 0X0547, 0X0547, 0X0547, 0X0547, 0X0547, 0X0547,
|
||||||
|
0X0547, 0X0547, 0X0547, 0X0547, 0X0547, 0X0547, 0X0547, 0X0547, 0X0547,
|
||||||
|
0X0547, 0X0547, 0X0547, 0X0547, 0X0547, 0X0547, 0X0547, 0X0547, 0X0547,
|
||||||
|
0X0547, 0X0547, 0X0547, 0X0547, 0X0547, 0X0547, 0X0547, 0X0547, 0X0547,
|
||||||
|
0X0547, 0X0547, 0X0547, 0X0547, 0X0547, 0X0547, 0X0547, 0X0547, 0X0547,
|
||||||
|
0X0547, 0X0547, 0X0547, 0X0547, 0X0547, 0X0547, 0X0547, 0X0547, 0X0547,
|
||||||
|
0X0547, 0X0547, 0X0547, 0X0547, 0X0547, 0X0547, 0X0547, 0X0547, 0X0547,
|
||||||
|
0X0547, 0X0547, 0X0547, 0X0547, 0X0547, 0X0547, 0X0547, 0X0547, 0X0547,
|
||||||
|
0X0547, 0X0547, 0X0547, 0X0547, 0X0547, 0X0547, 0X0547, 0X0547, 0X0547,
|
||||||
|
0X0547, 0X0547, 0X0547, 0X0547, 0X0547, 0X0547, 0X0547, 0X0547, 0X0547,
|
||||||
|
0X0547, 0X0547, 0X0547, 0X0547, 0X0547, 0X0547, 0X0547, 0X0547, 0X0547,
|
||||||
|
0X0547, 0X0547, 0X0547, 0X0547, 0X0547, 0X0547, 0X0547, 0X0547, 0X0547,
|
||||||
|
0X0547, 0X0547, 0X0547, 0X0547, 0X0547, 0X0547, 0X0547, 0X0547, 0X0547,
|
||||||
|
0X0547, 0X0547, 0X0547, 0X0547, 0X0547, 0X0547, 0X0547, 0X0547, 0X0547,
|
||||||
|
0X0547, 0X0547, 0X0547, 0X0547, 0X0547, 0X0547, 0X0547, 0X0547, 0X0547,
|
||||||
|
0X0547, 0X0547, 0X0547, 0X0547, 0X0547, 0X0547, 0X0547, 0X0547, 0X0547,
|
||||||
|
0X0547, 0X0547, 0X0547, 0X0547, 0X0547, 0X0547, 0X0547, 0X0547, 0X0547,
|
||||||
|
0X0547, 0X0547, 0X0547, 0X0547, 0X0547, 0X0547, 0X0547, 0X0547, 0X0547,
|
||||||
|
0X0547, 0X0547, 0X0547, 0X0547, 0X0547, 0X0547, 0X0547, 0X0547, 0X0547,
|
||||||
|
0X0547, 0X0547, 0X0547, 0X0547, 0X0547, 0X0547, 0X0547, 0X0547, 0X0547,
|
||||||
|
0X0547, 0X0547, 0X0547, 0X0547, 0X0547, 0X0547, 0X0547, 0X0547, 0X0547,
|
||||||
|
0X0547, 0X0547, 0X0547, 0X0547, 0X0547, 0X0547, 0X0547, 0X0547, 0X0547,
|
||||||
|
0X0547, 0X0547, 0X0547, 0X0547, 0X0547, 0X0547, 0X0547, 0X0547, 0X0547,
|
||||||
|
0X0547, 0X0547, 0X0547, 0X0547, 0X0547, 0X0547, 0X0547, 0X0547, 0X0547,
|
||||||
|
0X0547, 0X0547, 0X0547, 0X0547, 0X0547, 0X0547, 0X0547, 0X0547, 0X0547,
|
||||||
|
0X0547, 0X0547, 0X0547, 0X0547, 0X0547, 0X0547, 0X0547, 0X0547, 0X0547,
|
||||||
|
0X0547, 0X0547, 0X0547, 0X0547, 0X0547, 0X0547, 0X0547, 0X0547, 0X0547,
|
||||||
|
0X0547, 0X0547, 0X0547, 0X0547, 0X0547, 0X0547, 0X0547, 0X0547, 0X0547,
|
||||||
|
0X0547, 0X0547, 0X0547, 0X0547, 0X0547, 0X0547, 0X0547, 0X0547, 0X0547,
|
||||||
|
0X0547, 0X0547, 0X0547, 0X0547, 0X0547, 0X0547, 0X0547, 0X0547, 0X0547,
|
||||||
|
0X0547, 0X0547, 0X0547, 0X0547, 0X0547, 0X0547, 0X0547, 0X0547, 0X0547,
|
||||||
|
0X0547, 0X0547, 0X0547, 0X0547, 0X0547, 0X0547, 0X0547, 0X0547, 0X0547,
|
||||||
|
0X0547, 0X0547, 0X0547, 0X0547, 0X0547, 0X0547, 0X0547, 0X0547, 0X0547,
|
||||||
|
0X0547, 0X0547, 0X0547, 0X0547, 0X0547, 0X0547, 0X0547, 0X0547, 0X0547,
|
||||||
|
0X0547, 0X0547, 0X0547, 0X0547, 0X0547 };
|
||||||
|
|
|
@ -0,0 +1,69 @@
|
||||||
|
// ILI9341 example with embedded color bitmaps in sketch.
|
||||||
|
// WILL NOT FIT ON ARDUINO UNO OR OTHER AVR BOARDS;
|
||||||
|
// uses large bitmap image stored in array!
|
||||||
|
|
||||||
|
// Options for converting images to the format used here include:
|
||||||
|
// http://www.rinkydinkelectronics.com/t_imageconverter565.php
|
||||||
|
// or
|
||||||
|
// GIMP (https://www.gimp.org/) as follows:
|
||||||
|
// 1. File -> Export As
|
||||||
|
// 2. In Export Image dialog, use 'C source code (*.c)' as filetype.
|
||||||
|
// 3. Press export to get the export options dialog.
|
||||||
|
// 4. Type the desired variable name into the 'prefixed name' box.
|
||||||
|
// 5. Uncheck 'GLIB types (guint8*)'
|
||||||
|
// 6. Check 'Save as RGB565 (16-bit)'
|
||||||
|
// 7. Press export to save your image.
|
||||||
|
// Assuming 'image_name' was typed in the 'prefixed name' box of step 4,
|
||||||
|
// you can have to include the c file, then using the image can be done with:
|
||||||
|
// tft.drawRGBBitmap(0, 0, image_name.pixel_data, image_name.width, image_name.height);
|
||||||
|
// See also https://forum.pjrc.com/threads/35575-Export-for-ILI9341_t3-with-GIMP
|
||||||
|
|
||||||
|
#include "SPI.h"
|
||||||
|
#include <Adafruit_ILI9341.h>
|
||||||
|
#include "dragon.h"
|
||||||
|
|
||||||
|
// For the Adafruit shield, these are the default.
|
||||||
|
//#define TFT_DC 9
|
||||||
|
//#define TFT_CS 10
|
||||||
|
|
||||||
|
// Feather 32u4 or M0 with TFT FeatherWing:
|
||||||
|
#define TFT_DC 10
|
||||||
|
#define TFT_CS 9
|
||||||
|
// ESP8266:
|
||||||
|
//#define TFT_DC 15
|
||||||
|
//#define TFT_CS 0
|
||||||
|
// Other boards (including Feather boards) may have other pinouts;
|
||||||
|
// see learn.adafruit.com/adafruit-2-4-tft-touch-screen-featherwing/pinouts
|
||||||
|
|
||||||
|
Adafruit_ILI9341 tft = Adafruit_ILI9341(TFT_CS, TFT_DC);
|
||||||
|
// If using the breakout, change pins as desired
|
||||||
|
//Adafruit_ILI9341 tft = Adafruit_ILI9341(TFT_CS, TFT_DC, TFT_MOSI, TFT_CLK, TFT_RST, TFT_MISO);
|
||||||
|
|
||||||
|
void setup() {
|
||||||
|
tft.begin();
|
||||||
|
}
|
||||||
|
|
||||||
|
void loop(void) {
|
||||||
|
for(uint8_t r=0; r<4; r++) {
|
||||||
|
tft.setRotation(r);
|
||||||
|
tft.fillScreen(ILI9341_BLACK);
|
||||||
|
for(uint8_t j=0; j<20; j++) {
|
||||||
|
tft.drawRGBBitmap(
|
||||||
|
random(-DRAGON_WIDTH , tft.width()),
|
||||||
|
random(-DRAGON_HEIGHT, tft.height()),
|
||||||
|
#if defined(__AVR__) || defined(ESP8266)
|
||||||
|
dragonBitmap,
|
||||||
|
#else
|
||||||
|
// Some non-AVR MCU's have a "flat" memory model and don't
|
||||||
|
// distinguish between flash and RAM addresses. In this case,
|
||||||
|
// the RAM-resident-optimized drawRGBBitmap in the ILI9341
|
||||||
|
// library can be invoked by forcibly type-converting the
|
||||||
|
// PROGMEM bitmap pointer to a non-const uint16_t *.
|
||||||
|
(uint16_t *)dragonBitmap,
|
||||||
|
#endif
|
||||||
|
DRAGON_WIDTH, DRAGON_HEIGHT);
|
||||||
|
delay(1); // Allow ESP8266 to handle watchdog & WiFi stuff
|
||||||
|
}
|
||||||
|
delay(3000);
|
||||||
|
}
|
||||||
|
}
|
|
@ -0,0 +1,218 @@
|
||||||
|
/***************************************************
|
||||||
|
This is our Bitmap drawing example for the Adafruit ILI9341 Breakout and Shield
|
||||||
|
----> http://www.adafruit.com/products/1651
|
||||||
|
|
||||||
|
Check out the links above for our tutorials and wiring diagrams
|
||||||
|
These displays use SPI to communicate, 4 or 5 pins are required to
|
||||||
|
interface (RST is optional)
|
||||||
|
Adafruit invests time and resources providing this open source code,
|
||||||
|
please support Adafruit and open-source hardware by purchasing
|
||||||
|
products from Adafruit!
|
||||||
|
|
||||||
|
Written by Limor Fried/Ladyada for Adafruit Industries.
|
||||||
|
MIT license, all text above must be included in any redistribution
|
||||||
|
****************************************************/
|
||||||
|
|
||||||
|
|
||||||
|
#include <Adafruit_GFX.h> // Core graphics library
|
||||||
|
#include "Adafruit_ILI9341.h" // Hardware-specific library
|
||||||
|
#include <SPI.h>
|
||||||
|
#include <SD.h>
|
||||||
|
|
||||||
|
// TFT display and SD card will share the hardware SPI interface.
|
||||||
|
// Hardware SPI pins are specific to the Arduino board type and
|
||||||
|
// cannot be remapped to alternate pins. For Arduino Uno,
|
||||||
|
// Duemilanove, etc., pin 11 = MOSI, pin 12 = MISO, pin 13 = SCK.
|
||||||
|
|
||||||
|
#define TFT_DC 9
|
||||||
|
#define TFT_CS 10
|
||||||
|
Adafruit_ILI9341 tft = Adafruit_ILI9341(TFT_CS, TFT_DC);
|
||||||
|
|
||||||
|
#define SD_CS 4
|
||||||
|
|
||||||
|
void setup(void) {
|
||||||
|
Serial.begin(9600);
|
||||||
|
|
||||||
|
tft.begin();
|
||||||
|
|
||||||
|
yield();
|
||||||
|
|
||||||
|
Serial.print("Initializing SD card...");
|
||||||
|
if (!SD.begin(SD_CS)) {
|
||||||
|
Serial.println("failed!");
|
||||||
|
}
|
||||||
|
Serial.println("OK!");
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
void loop() {
|
||||||
|
for(uint8_t r=0; r<4; r++) {
|
||||||
|
tft.setRotation(r);
|
||||||
|
tft.fillScreen(ILI9341_BLUE);
|
||||||
|
for(int8_t i=-2; i<1; i++) {
|
||||||
|
bmpDraw("purple.bmp",
|
||||||
|
(tft.width() / 2) + (i * 120),
|
||||||
|
(tft.height() / 2) + (i * 160));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// This function opens a Windows Bitmap (BMP) file and
|
||||||
|
// displays it at the given coordinates. It's sped up
|
||||||
|
// by reading many pixels worth of data at a time
|
||||||
|
// (rather than pixel by pixel). Increasing the buffer
|
||||||
|
// size takes more of the Arduino's precious RAM but
|
||||||
|
// makes loading a little faster. 20 pixels seems a
|
||||||
|
// good balance.
|
||||||
|
|
||||||
|
#define BUFFPIXEL 20
|
||||||
|
|
||||||
|
void bmpDraw(char *filename, int16_t x, int16_t y) {
|
||||||
|
|
||||||
|
File bmpFile;
|
||||||
|
int bmpWidth, bmpHeight; // W+H in pixels
|
||||||
|
uint8_t bmpDepth; // Bit depth (currently must be 24)
|
||||||
|
uint32_t bmpImageoffset; // Start of image data in file
|
||||||
|
uint32_t rowSize; // Not always = bmpWidth; may have padding
|
||||||
|
uint8_t sdbuffer[3*BUFFPIXEL]; // pixel buffer (R+G+B per pixel)
|
||||||
|
uint8_t buffidx = sizeof(sdbuffer); // Current position in sdbuffer
|
||||||
|
boolean goodBmp = false; // Set to true on valid header parse
|
||||||
|
boolean flip = true; // BMP is stored bottom-to-top
|
||||||
|
int w, h, row, col, x2, y2, bx1, by1;
|
||||||
|
uint8_t r, g, b;
|
||||||
|
uint32_t pos = 0, startTime = millis();
|
||||||
|
|
||||||
|
if((x >= tft.width()) || (y >= tft.height())) return;
|
||||||
|
|
||||||
|
Serial.println();
|
||||||
|
Serial.print(F("Loading image '"));
|
||||||
|
Serial.print(filename);
|
||||||
|
Serial.println('\'');
|
||||||
|
|
||||||
|
// Open requested file on SD card
|
||||||
|
if ((bmpFile = SD.open(filename)) == NULL) {
|
||||||
|
Serial.print(F("File not found"));
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Parse BMP header
|
||||||
|
if(read16(bmpFile) == 0x4D42) { // BMP signature
|
||||||
|
Serial.print(F("File size: ")); Serial.println(read32(bmpFile));
|
||||||
|
(void)read32(bmpFile); // Read & ignore creator bytes
|
||||||
|
bmpImageoffset = read32(bmpFile); // Start of image data
|
||||||
|
Serial.print(F("Image Offset: ")); Serial.println(bmpImageoffset, DEC);
|
||||||
|
// Read DIB header
|
||||||
|
Serial.print(F("Header size: ")); Serial.println(read32(bmpFile));
|
||||||
|
bmpWidth = read32(bmpFile);
|
||||||
|
bmpHeight = read32(bmpFile);
|
||||||
|
if(read16(bmpFile) == 1) { // # planes -- must be '1'
|
||||||
|
bmpDepth = read16(bmpFile); // bits per pixel
|
||||||
|
Serial.print(F("Bit Depth: ")); Serial.println(bmpDepth);
|
||||||
|
if((bmpDepth == 24) && (read32(bmpFile) == 0)) { // 0 = uncompressed
|
||||||
|
|
||||||
|
goodBmp = true; // Supported BMP format -- proceed!
|
||||||
|
Serial.print(F("Image size: "));
|
||||||
|
Serial.print(bmpWidth);
|
||||||
|
Serial.print('x');
|
||||||
|
Serial.println(bmpHeight);
|
||||||
|
|
||||||
|
// BMP rows are padded (if needed) to 4-byte boundary
|
||||||
|
rowSize = (bmpWidth * 3 + 3) & ~3;
|
||||||
|
|
||||||
|
// If bmpHeight is negative, image is in top-down order.
|
||||||
|
// This is not canon but has been observed in the wild.
|
||||||
|
if(bmpHeight < 0) {
|
||||||
|
bmpHeight = -bmpHeight;
|
||||||
|
flip = false;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Crop area to be loaded
|
||||||
|
x2 = x + bmpWidth - 1; // Lower-right corner
|
||||||
|
y2 = y + bmpHeight - 1;
|
||||||
|
if((x2 >= 0) && (y2 >= 0)) { // On screen?
|
||||||
|
w = bmpWidth; // Width/height of section to load/display
|
||||||
|
h = bmpHeight;
|
||||||
|
bx1 = by1 = 0; // UL coordinate in BMP file
|
||||||
|
if(x < 0) { // Clip left
|
||||||
|
bx1 = -x;
|
||||||
|
x = 0;
|
||||||
|
w = x2 + 1;
|
||||||
|
}
|
||||||
|
if(y < 0) { // Clip top
|
||||||
|
by1 = -y;
|
||||||
|
y = 0;
|
||||||
|
h = y2 + 1;
|
||||||
|
}
|
||||||
|
if(x2 >= tft.width()) w = tft.width() - x; // Clip right
|
||||||
|
if(y2 >= tft.height()) h = tft.height() - y; // Clip bottom
|
||||||
|
|
||||||
|
// Set TFT address window to clipped image bounds
|
||||||
|
tft.startWrite(); // Requires start/end transaction now
|
||||||
|
tft.setAddrWindow(x, y, w, h);
|
||||||
|
|
||||||
|
for (row=0; row<h; row++) { // For each scanline...
|
||||||
|
|
||||||
|
// Seek to start of scan line. It might seem labor-
|
||||||
|
// intensive to be doing this on every line, but this
|
||||||
|
// method covers a lot of gritty details like cropping
|
||||||
|
// and scanline padding. Also, the seek only takes
|
||||||
|
// place if the file position actually needs to change
|
||||||
|
// (avoids a lot of cluster math in SD library).
|
||||||
|
if(flip) // Bitmap is stored bottom-to-top order (normal BMP)
|
||||||
|
pos = bmpImageoffset + (bmpHeight - 1 - (row + by1)) * rowSize;
|
||||||
|
else // Bitmap is stored top-to-bottom
|
||||||
|
pos = bmpImageoffset + (row + by1) * rowSize;
|
||||||
|
pos += bx1 * 3; // Factor in starting column (bx1)
|
||||||
|
if(bmpFile.position() != pos) { // Need seek?
|
||||||
|
tft.endWrite(); // End TFT transaction
|
||||||
|
bmpFile.seek(pos);
|
||||||
|
buffidx = sizeof(sdbuffer); // Force buffer reload
|
||||||
|
tft.startWrite(); // Start new TFT transaction
|
||||||
|
}
|
||||||
|
for (col=0; col<w; col++) { // For each pixel...
|
||||||
|
// Time to read more pixel data?
|
||||||
|
if (buffidx >= sizeof(sdbuffer)) { // Indeed
|
||||||
|
tft.endWrite(); // End TFT transaction
|
||||||
|
bmpFile.read(sdbuffer, sizeof(sdbuffer));
|
||||||
|
buffidx = 0; // Set index to beginning
|
||||||
|
tft.startWrite(); // Start new TFT transaction
|
||||||
|
}
|
||||||
|
// Convert pixel from BMP to TFT format, push to display
|
||||||
|
b = sdbuffer[buffidx++];
|
||||||
|
g = sdbuffer[buffidx++];
|
||||||
|
r = sdbuffer[buffidx++];
|
||||||
|
tft.writePixel(tft.color565(r,g,b));
|
||||||
|
} // end pixel
|
||||||
|
} // end scanline
|
||||||
|
tft.endWrite(); // End last TFT transaction
|
||||||
|
} // end onscreen
|
||||||
|
Serial.print(F("Loaded in "));
|
||||||
|
Serial.print(millis() - startTime);
|
||||||
|
Serial.println(" ms");
|
||||||
|
} // end goodBmp
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
bmpFile.close();
|
||||||
|
if(!goodBmp) Serial.println(F("BMP format not recognized."));
|
||||||
|
}
|
||||||
|
|
||||||
|
// These read 16- and 32-bit types from the SD card file.
|
||||||
|
// BMP data is stored little-endian, Arduino is little-endian too.
|
||||||
|
// May need to reverse subscript order if porting elsewhere.
|
||||||
|
|
||||||
|
uint16_t read16(File &f) {
|
||||||
|
uint16_t result;
|
||||||
|
((uint8_t *)&result)[0] = f.read(); // LSB
|
||||||
|
((uint8_t *)&result)[1] = f.read(); // MSB
|
||||||
|
return result;
|
||||||
|
}
|
||||||
|
|
||||||
|
uint32_t read32(File &f) {
|
||||||
|
uint32_t result;
|
||||||
|
((uint8_t *)&result)[0] = f.read(); // LSB
|
||||||
|
((uint8_t *)&result)[1] = f.read();
|
||||||
|
((uint8_t *)&result)[2] = f.read();
|
||||||
|
((uint8_t *)&result)[3] = f.read(); // MSB
|
||||||
|
return result;
|
||||||
|
}
|
|
@ -0,0 +1,146 @@
|
||||||
|
/***************************************************
|
||||||
|
This is our touchscreen painting example for the Adafruit ILI9341 Shield
|
||||||
|
----> http://www.adafruit.com/products/1651
|
||||||
|
|
||||||
|
Check out the links above for our tutorials and wiring diagrams
|
||||||
|
These displays use SPI to communicate, 4 or 5 pins are required to
|
||||||
|
interface (RST is optional)
|
||||||
|
Adafruit invests time and resources providing this open source code,
|
||||||
|
please support Adafruit and open-source hardware by purchasing
|
||||||
|
products from Adafruit!
|
||||||
|
|
||||||
|
Written by Limor Fried/Ladyada for Adafruit Industries.
|
||||||
|
MIT license, all text above must be included in any redistribution
|
||||||
|
****************************************************/
|
||||||
|
|
||||||
|
|
||||||
|
#include <Adafruit_GFX.h> // Core graphics library
|
||||||
|
#include <SPI.h>
|
||||||
|
#include <Wire.h> // this is needed even tho we aren't using it
|
||||||
|
#include <Adafruit_ILI9341.h>
|
||||||
|
#include <Adafruit_STMPE610.h>
|
||||||
|
|
||||||
|
// This is calibration data for the raw touch data to the screen coordinates
|
||||||
|
#define TS_MINX 150
|
||||||
|
#define TS_MINY 130
|
||||||
|
#define TS_MAXX 3800
|
||||||
|
#define TS_MAXY 4000
|
||||||
|
|
||||||
|
// The STMPE610 uses hardware SPI on the shield, and #8
|
||||||
|
#define STMPE_CS 8
|
||||||
|
Adafruit_STMPE610 ts = Adafruit_STMPE610(STMPE_CS);
|
||||||
|
|
||||||
|
// The display also uses hardware SPI, plus #9 & #10
|
||||||
|
#define TFT_CS 10
|
||||||
|
#define TFT_DC 9
|
||||||
|
Adafruit_ILI9341 tft = Adafruit_ILI9341(TFT_CS, TFT_DC);
|
||||||
|
|
||||||
|
// Size of the color selection boxes and the paintbrush size
|
||||||
|
#define BOXSIZE 40
|
||||||
|
#define PENRADIUS 3
|
||||||
|
int oldcolor, currentcolor;
|
||||||
|
|
||||||
|
void setup(void) {
|
||||||
|
// while (!Serial); // used for leonardo debugging
|
||||||
|
|
||||||
|
Serial.begin(9600);
|
||||||
|
Serial.println(F("Touch Paint!"));
|
||||||
|
|
||||||
|
tft.begin();
|
||||||
|
|
||||||
|
if (!ts.begin()) {
|
||||||
|
Serial.println("Couldn't start touchscreen controller");
|
||||||
|
while (1);
|
||||||
|
}
|
||||||
|
Serial.println("Touchscreen started");
|
||||||
|
|
||||||
|
tft.fillScreen(ILI9341_BLACK);
|
||||||
|
|
||||||
|
// make the color selection boxes
|
||||||
|
tft.fillRect(0, 0, BOXSIZE, BOXSIZE, ILI9341_RED);
|
||||||
|
tft.fillRect(BOXSIZE, 0, BOXSIZE, BOXSIZE, ILI9341_YELLOW);
|
||||||
|
tft.fillRect(BOXSIZE*2, 0, BOXSIZE, BOXSIZE, ILI9341_GREEN);
|
||||||
|
tft.fillRect(BOXSIZE*3, 0, BOXSIZE, BOXSIZE, ILI9341_CYAN);
|
||||||
|
tft.fillRect(BOXSIZE*4, 0, BOXSIZE, BOXSIZE, ILI9341_BLUE);
|
||||||
|
tft.fillRect(BOXSIZE*5, 0, BOXSIZE, BOXSIZE, ILI9341_MAGENTA);
|
||||||
|
|
||||||
|
// select the current color 'red'
|
||||||
|
tft.drawRect(0, 0, BOXSIZE, BOXSIZE, ILI9341_WHITE);
|
||||||
|
currentcolor = ILI9341_RED;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
void loop()
|
||||||
|
{
|
||||||
|
// See if there's any touch data for us
|
||||||
|
if (ts.bufferEmpty()) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
/*
|
||||||
|
// You can also wait for a touch
|
||||||
|
if (! ts.touched()) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
*/
|
||||||
|
|
||||||
|
// Retrieve a point
|
||||||
|
TS_Point p = ts.getPoint();
|
||||||
|
|
||||||
|
/*
|
||||||
|
Serial.print("X = "); Serial.print(p.x);
|
||||||
|
Serial.print("\tY = "); Serial.print(p.y);
|
||||||
|
Serial.print("\tPressure = "); Serial.println(p.z);
|
||||||
|
*/
|
||||||
|
|
||||||
|
// Scale from ~0->4000 to tft.width using the calibration #'s
|
||||||
|
p.x = map(p.x, TS_MINX, TS_MAXX, 0, tft.width());
|
||||||
|
p.y = map(p.y, TS_MINY, TS_MAXY, 0, tft.height());
|
||||||
|
|
||||||
|
/*
|
||||||
|
Serial.print("("); Serial.print(p.x);
|
||||||
|
Serial.print(", "); Serial.print(p.y);
|
||||||
|
Serial.println(")");
|
||||||
|
*/
|
||||||
|
|
||||||
|
if (p.y < BOXSIZE) {
|
||||||
|
oldcolor = currentcolor;
|
||||||
|
|
||||||
|
if (p.x < BOXSIZE) {
|
||||||
|
currentcolor = ILI9341_RED;
|
||||||
|
tft.drawRect(0, 0, BOXSIZE, BOXSIZE, ILI9341_WHITE);
|
||||||
|
} else if (p.x < BOXSIZE*2) {
|
||||||
|
currentcolor = ILI9341_YELLOW;
|
||||||
|
tft.drawRect(BOXSIZE, 0, BOXSIZE, BOXSIZE, ILI9341_WHITE);
|
||||||
|
} else if (p.x < BOXSIZE*3) {
|
||||||
|
currentcolor = ILI9341_GREEN;
|
||||||
|
tft.drawRect(BOXSIZE*2, 0, BOXSIZE, BOXSIZE, ILI9341_WHITE);
|
||||||
|
} else if (p.x < BOXSIZE*4) {
|
||||||
|
currentcolor = ILI9341_CYAN;
|
||||||
|
tft.drawRect(BOXSIZE*3, 0, BOXSIZE, BOXSIZE, ILI9341_WHITE);
|
||||||
|
} else if (p.x < BOXSIZE*5) {
|
||||||
|
currentcolor = ILI9341_BLUE;
|
||||||
|
tft.drawRect(BOXSIZE*4, 0, BOXSIZE, BOXSIZE, ILI9341_WHITE);
|
||||||
|
} else if (p.x < BOXSIZE*6) {
|
||||||
|
currentcolor = ILI9341_MAGENTA;
|
||||||
|
tft.drawRect(BOXSIZE*5, 0, BOXSIZE, BOXSIZE, ILI9341_WHITE);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (oldcolor != currentcolor) {
|
||||||
|
if (oldcolor == ILI9341_RED)
|
||||||
|
tft.fillRect(0, 0, BOXSIZE, BOXSIZE, ILI9341_RED);
|
||||||
|
if (oldcolor == ILI9341_YELLOW)
|
||||||
|
tft.fillRect(BOXSIZE, 0, BOXSIZE, BOXSIZE, ILI9341_YELLOW);
|
||||||
|
if (oldcolor == ILI9341_GREEN)
|
||||||
|
tft.fillRect(BOXSIZE*2, 0, BOXSIZE, BOXSIZE, ILI9341_GREEN);
|
||||||
|
if (oldcolor == ILI9341_CYAN)
|
||||||
|
tft.fillRect(BOXSIZE*3, 0, BOXSIZE, BOXSIZE, ILI9341_CYAN);
|
||||||
|
if (oldcolor == ILI9341_BLUE)
|
||||||
|
tft.fillRect(BOXSIZE*4, 0, BOXSIZE, BOXSIZE, ILI9341_BLUE);
|
||||||
|
if (oldcolor == ILI9341_MAGENTA)
|
||||||
|
tft.fillRect(BOXSIZE*5, 0, BOXSIZE, BOXSIZE, ILI9341_MAGENTA);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if (((p.y-PENRADIUS) > BOXSIZE) && ((p.y+PENRADIUS) < tft.height())) {
|
||||||
|
tft.fillCircle(p.x, p.y, PENRADIUS, currentcolor);
|
||||||
|
}
|
||||||
|
}
|
|
@ -0,0 +1,156 @@
|
||||||
|
/***************************************************
|
||||||
|
This is our touchscreen painting example for the Adafruit TFT FeatherWing
|
||||||
|
----> http://www.adafruit.com/products/3315
|
||||||
|
|
||||||
|
Check out the links above for our tutorials and wiring diagrams
|
||||||
|
|
||||||
|
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
|
||||||
|
****************************************************/
|
||||||
|
|
||||||
|
#include <SPI.h>
|
||||||
|
#include <Wire.h> // this is needed even tho we aren't using it
|
||||||
|
|
||||||
|
#include <Adafruit_GFX.h> // Core graphics library
|
||||||
|
#include <Adafruit_ILI9341.h> // Hardware-specific library
|
||||||
|
#include <Adafruit_STMPE610.h>
|
||||||
|
|
||||||
|
#ifdef ESP8266
|
||||||
|
#define STMPE_CS 16
|
||||||
|
#define TFT_CS 0
|
||||||
|
#define TFT_DC 15
|
||||||
|
#define SD_CS 2
|
||||||
|
#endif
|
||||||
|
#ifdef ESP32
|
||||||
|
#define STMPE_CS 32
|
||||||
|
#define TFT_CS 15
|
||||||
|
#define TFT_DC 33
|
||||||
|
#define SD_CS 14
|
||||||
|
#endif
|
||||||
|
#if defined (__AVR_ATmega32U4__) || defined(ARDUINO_SAMD_FEATHER_M0) || defined (__AVR_ATmega328P__)
|
||||||
|
#define STMPE_CS 6
|
||||||
|
#define TFT_CS 9
|
||||||
|
#define TFT_DC 10
|
||||||
|
#define SD_CS 5
|
||||||
|
#endif
|
||||||
|
#ifdef TEENSYDUINO
|
||||||
|
#define TFT_DC 10
|
||||||
|
#define TFT_CS 4
|
||||||
|
#define STMPE_CS 3
|
||||||
|
#define SD_CS 8
|
||||||
|
#endif
|
||||||
|
#ifdef ARDUINO_STM32_FEATHER
|
||||||
|
#define TFT_DC PB4
|
||||||
|
#define TFT_CS PA15
|
||||||
|
#define STMPE_CS PC7
|
||||||
|
#define SD_CS PC5
|
||||||
|
#endif
|
||||||
|
#ifdef ARDUINO_NRF52_FEATHER /* BSP 0.6.5 and higher! */
|
||||||
|
#define TFT_DC 11
|
||||||
|
#define TFT_CS 31
|
||||||
|
#define STMPE_CS 30
|
||||||
|
#define SD_CS 27
|
||||||
|
#endif
|
||||||
|
|
||||||
|
Adafruit_ILI9341 tft = Adafruit_ILI9341(TFT_CS, TFT_DC);
|
||||||
|
Adafruit_STMPE610 ts = Adafruit_STMPE610(STMPE_CS);
|
||||||
|
|
||||||
|
|
||||||
|
// This is calibration data for the raw touch data to the screen coordinates
|
||||||
|
#define TS_MINX 3800
|
||||||
|
#define TS_MAXX 100
|
||||||
|
#define TS_MINY 100
|
||||||
|
#define TS_MAXY 3750
|
||||||
|
|
||||||
|
// Size of the color selection boxes and the paintbrush size
|
||||||
|
#define BOXSIZE 40
|
||||||
|
#define PENRADIUS 3
|
||||||
|
int oldcolor, currentcolor;
|
||||||
|
|
||||||
|
void setup(void) {
|
||||||
|
Serial.begin(115200);
|
||||||
|
|
||||||
|
delay(10);
|
||||||
|
Serial.println("FeatherWing TFT");
|
||||||
|
if (!ts.begin()) {
|
||||||
|
Serial.println("Couldn't start touchscreen controller");
|
||||||
|
while (1);
|
||||||
|
}
|
||||||
|
Serial.println("Touchscreen started");
|
||||||
|
|
||||||
|
tft.begin();
|
||||||
|
tft.fillScreen(ILI9341_BLACK);
|
||||||
|
|
||||||
|
// make the color selection boxes
|
||||||
|
tft.fillRect(0, 0, BOXSIZE, BOXSIZE, ILI9341_RED);
|
||||||
|
tft.fillRect(BOXSIZE, 0, BOXSIZE, BOXSIZE, ILI9341_YELLOW);
|
||||||
|
tft.fillRect(BOXSIZE*2, 0, BOXSIZE, BOXSIZE, ILI9341_GREEN);
|
||||||
|
tft.fillRect(BOXSIZE*3, 0, BOXSIZE, BOXSIZE, ILI9341_CYAN);
|
||||||
|
tft.fillRect(BOXSIZE*4, 0, BOXSIZE, BOXSIZE, ILI9341_BLUE);
|
||||||
|
tft.fillRect(BOXSIZE*5, 0, BOXSIZE, BOXSIZE, ILI9341_MAGENTA);
|
||||||
|
|
||||||
|
// select the current color 'red'
|
||||||
|
tft.drawRect(0, 0, BOXSIZE, BOXSIZE, ILI9341_WHITE);
|
||||||
|
currentcolor = ILI9341_RED;
|
||||||
|
}
|
||||||
|
|
||||||
|
void loop() {
|
||||||
|
// Retrieve a point
|
||||||
|
TS_Point p = ts.getPoint();
|
||||||
|
|
||||||
|
Serial.print("X = "); Serial.print(p.x);
|
||||||
|
Serial.print("\tY = "); Serial.print(p.y);
|
||||||
|
Serial.print("\tPressure = "); Serial.println(p.z);
|
||||||
|
|
||||||
|
|
||||||
|
// Scale from ~0->4000 to tft.width using the calibration #'s
|
||||||
|
p.x = map(p.x, TS_MINX, TS_MAXX, 0, tft.width());
|
||||||
|
p.y = map(p.y, TS_MINY, TS_MAXY, 0, tft.height());
|
||||||
|
|
||||||
|
if (p.y < BOXSIZE) {
|
||||||
|
oldcolor = currentcolor;
|
||||||
|
|
||||||
|
if (p.x < BOXSIZE) {
|
||||||
|
currentcolor = ILI9341_RED;
|
||||||
|
tft.drawRect(0, 0, BOXSIZE, BOXSIZE, ILI9341_WHITE);
|
||||||
|
} else if (p.x < BOXSIZE*2) {
|
||||||
|
currentcolor = ILI9341_YELLOW;
|
||||||
|
tft.drawRect(BOXSIZE, 0, BOXSIZE, BOXSIZE, ILI9341_WHITE);
|
||||||
|
} else if (p.x < BOXSIZE*3) {
|
||||||
|
currentcolor = ILI9341_GREEN;
|
||||||
|
tft.drawRect(BOXSIZE*2, 0, BOXSIZE, BOXSIZE, ILI9341_WHITE);
|
||||||
|
} else if (p.x < BOXSIZE*4) {
|
||||||
|
currentcolor = ILI9341_CYAN;
|
||||||
|
tft.drawRect(BOXSIZE*3, 0, BOXSIZE, BOXSIZE, ILI9341_WHITE);
|
||||||
|
} else if (p.x < BOXSIZE*5) {
|
||||||
|
currentcolor = ILI9341_BLUE;
|
||||||
|
tft.drawRect(BOXSIZE*4, 0, BOXSIZE, BOXSIZE, ILI9341_WHITE);
|
||||||
|
} else if (p.x < BOXSIZE*6) {
|
||||||
|
currentcolor = ILI9341_MAGENTA;
|
||||||
|
tft.drawRect(BOXSIZE*5, 0, BOXSIZE, BOXSIZE, ILI9341_WHITE);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (oldcolor != currentcolor) {
|
||||||
|
if (oldcolor == ILI9341_RED)
|
||||||
|
tft.fillRect(0, 0, BOXSIZE, BOXSIZE, ILI9341_RED);
|
||||||
|
if (oldcolor == ILI9341_YELLOW)
|
||||||
|
tft.fillRect(BOXSIZE, 0, BOXSIZE, BOXSIZE, ILI9341_YELLOW);
|
||||||
|
if (oldcolor == ILI9341_GREEN)
|
||||||
|
tft.fillRect(BOXSIZE*2, 0, BOXSIZE, BOXSIZE, ILI9341_GREEN);
|
||||||
|
if (oldcolor == ILI9341_CYAN)
|
||||||
|
tft.fillRect(BOXSIZE*3, 0, BOXSIZE, BOXSIZE, ILI9341_CYAN);
|
||||||
|
if (oldcolor == ILI9341_BLUE)
|
||||||
|
tft.fillRect(BOXSIZE*4, 0, BOXSIZE, BOXSIZE, ILI9341_BLUE);
|
||||||
|
if (oldcolor == ILI9341_MAGENTA)
|
||||||
|
tft.fillRect(BOXSIZE*5, 0, BOXSIZE, BOXSIZE, ILI9341_MAGENTA);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if (((p.y-PENRADIUS) > 0) && ((p.y+PENRADIUS) < tft.height())) {
|
||||||
|
tft.fillCircle(p.x, p.y, PENRADIUS, currentcolor);
|
||||||
|
}
|
||||||
|
}
|
|
@ -0,0 +1,9 @@
|
||||||
|
name=Adafruit ILI9341
|
||||||
|
version=1.0.11
|
||||||
|
author=Adafruit
|
||||||
|
maintainer=Adafruit <info@adafruit.com>
|
||||||
|
sentence=Library for Adafruit ILI9341 displays
|
||||||
|
paragraph=Library for Adafruit ILI9341 displays
|
||||||
|
category=Display
|
||||||
|
url=https://github.com/adafruit/Adafruit_ILI9341
|
||||||
|
architectures=*
|
|
@ -1,41 +0,0 @@
|
||||||
#######################################
|
|
||||||
# Syntax Coloring Map for TasmotaTFT
|
|
||||||
# (esp8266)
|
|
||||||
#######################################
|
|
||||||
|
|
||||||
#######################################
|
|
||||||
# Datatypes (KEYWORD1)
|
|
||||||
#######################################
|
|
||||||
|
|
||||||
TasmotaTFT KEYWORD1
|
|
||||||
|
|
||||||
#######################################
|
|
||||||
# Methods and Functions (KEYWORD2)
|
|
||||||
#######################################
|
|
||||||
|
|
||||||
begin KEYWORD2
|
|
||||||
setScrollStart KEYWORD2
|
|
||||||
setScrollMargins KEYWORD2
|
|
||||||
setAddrWindow KEYWORD2
|
|
||||||
pushColor KEYWORD2
|
|
||||||
fillScreen KEYWORD2
|
|
||||||
drawPixel KEYWORD2
|
|
||||||
drawFastVLine KEYWORD2
|
|
||||||
drawFastHLine KEYWORD2
|
|
||||||
fillRect KEYWORD2
|
|
||||||
setRotation KEYWORD2
|
|
||||||
invertDisplay KEYWORD2
|
|
||||||
showDisplay KEYWORD2
|
|
||||||
color565 KEYWORD2
|
|
||||||
readdata KEYWORD2
|
|
||||||
readcommand8 KEYWORD2
|
|
||||||
spiwrite KEYWORD2
|
|
||||||
writecommand KEYWORD2
|
|
||||||
writedata KEYWORD2
|
|
||||||
commandList KEYWORD2
|
|
||||||
spiread KEYWORD2
|
|
||||||
|
|
||||||
#######################################
|
|
||||||
# Constants (LITERAL1)
|
|
||||||
#######################################
|
|
||||||
|
|
|
@ -1,15 +0,0 @@
|
||||||
{
|
|
||||||
"name": "TasmotaTFT",
|
|
||||||
"version": "1.0.1",
|
|
||||||
"keywords": [
|
|
||||||
"spi", "io", "tft", "TasmotaTFT"
|
|
||||||
],
|
|
||||||
"description": "Library for ILI9341, ILI9481 and ILI9486 displays",
|
|
||||||
"repository":
|
|
||||||
{
|
|
||||||
"type": "git",
|
|
||||||
"url": "https://github.com/arendst/Sonoff-Tasmota/lib/TasmotaTFT"
|
|
||||||
},
|
|
||||||
"frameworks": "arduino",
|
|
||||||
"platforms": "espressif8266"
|
|
||||||
}
|
|
|
@ -1,9 +0,0 @@
|
||||||
name=TasmotaTFT
|
|
||||||
version=1.0.1
|
|
||||||
author=Theo Arends
|
|
||||||
maintainer=Theo Arends <theo@arends.com>
|
|
||||||
sentence=Library for ILI9341, ILI9481 and ILI9486 displays
|
|
||||||
paragraph=
|
|
||||||
category=Display
|
|
||||||
url=
|
|
||||||
architectures=esp8266
|
|
|
@ -1,616 +0,0 @@
|
||||||
/*
|
|
||||||
TasmotaTFT.cpp - Adapted implementation of Adafruit ILI9341 for Tasmota
|
|
||||||
|
|
||||||
Copyright (C) 2018 Adafruit and Theo Arends
|
|
||||||
|
|
||||||
This library is free software: you can redistribute it and/or modify
|
|
||||||
it under the terms of the GNU General Public License as published by
|
|
||||||
the Free Software Foundation, either version 3 of the License, or
|
|
||||||
(at your option) any later version.
|
|
||||||
|
|
||||||
This program is distributed in the hope that it will be useful,
|
|
||||||
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
|
||||||
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
|
||||||
GNU General Public License for more details.
|
|
||||||
|
|
||||||
You should have received a copy of the GNU General Public License
|
|
||||||
along with this program. If not, see <http://www.gnu.org/licenses/>.
|
|
||||||
*/
|
|
||||||
|
|
||||||
/*********************************************************************************************\
|
|
||||||
* See original Adafruit ILI9341 license text below
|
|
||||||
*
|
|
||||||
* Based in Adafruit_ILI9341 v1.0.11
|
|
||||||
* This is a library for the ILI9341, ILI9481 and ILI9486 TFT LCD using hardware SPI only
|
|
||||||
*
|
|
||||||
* These displays use hardware SPI to communicate, 4 or 5 pins are required to interface (RST is optional)
|
|
||||||
\*********************************************************************************************/
|
|
||||||
|
|
||||||
#include "TasmotaTFT.h"
|
|
||||||
#include <limits.h>
|
|
||||||
#include "pins_arduino.h"
|
|
||||||
#include "wiring_private.h"
|
|
||||||
#include <SPI.h>
|
|
||||||
|
|
||||||
static inline void spi_begin(void) __attribute__((always_inline));
|
|
||||||
static inline void spi_begin(void) {
|
|
||||||
SPI.beginTransaction(SPISettings(24000000, MSBFIRST, SPI_MODE0));
|
|
||||||
}
|
|
||||||
static inline void spi_end(void) __attribute__((always_inline));
|
|
||||||
static inline void spi_end(void) {
|
|
||||||
SPI.endTransaction();
|
|
||||||
}
|
|
||||||
|
|
||||||
struct _sSize
|
|
||||||
{
|
|
||||||
int16_t width;
|
|
||||||
int16_t height;
|
|
||||||
};
|
|
||||||
_sSize _size[TFT_MAX] = {
|
|
||||||
{240, 320}, // ILI9340 / ILI9341
|
|
||||||
{320, 480}, // ILI9481 / HX8357B
|
|
||||||
{320, 480} // ILI9486
|
|
||||||
};
|
|
||||||
|
|
||||||
TasmotaTFT::TasmotaTFT(int8_t m, int8_t cs, int8_t dc, int8_t rst) : Adafruit_GFX(_size[m].width, _size[m].height) {
|
|
||||||
_mod = m;
|
|
||||||
_w = _size[m].width;
|
|
||||||
_h = _size[m].height;
|
|
||||||
_cs = cs;
|
|
||||||
_dc = dc;
|
|
||||||
_rst = rst;
|
|
||||||
_mosi = _sclk = 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
void TasmotaTFT::writecommand(uint8_t c)
|
|
||||||
{
|
|
||||||
digitalWrite(_dc, LOW);
|
|
||||||
digitalWrite(_sclk, LOW);
|
|
||||||
digitalWrite(_cs, LOW);
|
|
||||||
SPI.transfer(c);
|
|
||||||
digitalWrite(_cs, HIGH);
|
|
||||||
}
|
|
||||||
|
|
||||||
void TasmotaTFT::writedata(uint8_t c)
|
|
||||||
{
|
|
||||||
digitalWrite(_dc, HIGH);
|
|
||||||
digitalWrite(_cs, LOW);
|
|
||||||
SPI.transfer(c);
|
|
||||||
digitalWrite(_cs, HIGH);
|
|
||||||
}
|
|
||||||
|
|
||||||
void TasmotaTFT::begin(void)
|
|
||||||
{
|
|
||||||
pinMode(_dc, OUTPUT);
|
|
||||||
digitalWrite(_dc, LOW);
|
|
||||||
pinMode(_cs, OUTPUT);
|
|
||||||
digitalWrite(_cs, HIGH);
|
|
||||||
|
|
||||||
SPI.begin();
|
|
||||||
|
|
||||||
// toggle RST low to reset
|
|
||||||
if (_rst > 0) {
|
|
||||||
pinMode(_rst, OUTPUT);
|
|
||||||
digitalWrite(_rst, HIGH);
|
|
||||||
delay(100);
|
|
||||||
digitalWrite(_rst, LOW);
|
|
||||||
delay(100);
|
|
||||||
digitalWrite(_rst, HIGH);
|
|
||||||
delay(200);
|
|
||||||
}
|
|
||||||
|
|
||||||
spi_begin();
|
|
||||||
|
|
||||||
if (_mod == ILI9341) { // 320 x 240
|
|
||||||
writecommand(0xEF); // Display Supplier dependant
|
|
||||||
writedata(0x03);
|
|
||||||
writedata(0x80);
|
|
||||||
writedata(0x02);
|
|
||||||
|
|
||||||
writecommand(0xCF); // Display Supplier dependant
|
|
||||||
writedata(0x00);
|
|
||||||
writedata(0XC1);
|
|
||||||
writedata(0X30);
|
|
||||||
|
|
||||||
writecommand(0xED); // Display Supplier dependant
|
|
||||||
writedata(0x64);
|
|
||||||
writedata(0x03);
|
|
||||||
writedata(0X12);
|
|
||||||
writedata(0X81);
|
|
||||||
|
|
||||||
writecommand(0xE8); // Display Supplier dependant
|
|
||||||
writedata(0x85);
|
|
||||||
writedata(0x00);
|
|
||||||
writedata(0x78);
|
|
||||||
|
|
||||||
writecommand(0xCB); // Display Supplier dependant
|
|
||||||
writedata(0x39);
|
|
||||||
writedata(0x2C);
|
|
||||||
writedata(0x00);
|
|
||||||
writedata(0x34);
|
|
||||||
writedata(0x02);
|
|
||||||
|
|
||||||
writecommand(0xF7); // Display Supplier dependant
|
|
||||||
writedata(0x20);
|
|
||||||
|
|
||||||
writecommand(0xEA); // Display Supplier dependant
|
|
||||||
writedata(0x00);
|
|
||||||
writedata(0x00);
|
|
||||||
|
|
||||||
writecommand(0xC0); // Power control 1
|
|
||||||
writedata(0x23); // VRH[5:0]
|
|
||||||
|
|
||||||
writecommand(0xC1); // Power control 2
|
|
||||||
writedata(0x10); // SAP[2:0];BT[3:0]
|
|
||||||
|
|
||||||
writecommand(0xC5); // VCM control 1
|
|
||||||
writedata(0x3e); // Contrast
|
|
||||||
writedata(0x28);
|
|
||||||
|
|
||||||
writecommand(0xC7); // VCM control 2
|
|
||||||
writedata(0x86); // --
|
|
||||||
|
|
||||||
writecommand(0x36); // Memory Access Control
|
|
||||||
writedata(0x48);
|
|
||||||
|
|
||||||
writecommand(0x3A); // Pixel Format
|
|
||||||
writedata(0x55);
|
|
||||||
|
|
||||||
writecommand(0xB1); // Frame Control in Normal Mode
|
|
||||||
writedata(0x00);
|
|
||||||
writedata(0x18);
|
|
||||||
|
|
||||||
writecommand(0xB6); // Display Function Control
|
|
||||||
writedata(0x08);
|
|
||||||
writedata(0x82);
|
|
||||||
writedata(0x27);
|
|
||||||
|
|
||||||
writecommand(0xF2); // 3Gamma Function Disable
|
|
||||||
writedata(0x00);
|
|
||||||
|
|
||||||
writecommand(0x26); // Gamma curve selected
|
|
||||||
writedata(0x01);
|
|
||||||
|
|
||||||
writecommand(0xE0); // Positive Gamma
|
|
||||||
writedata(0x0F);
|
|
||||||
writedata(0x31);
|
|
||||||
writedata(0x2B);
|
|
||||||
writedata(0x0C);
|
|
||||||
writedata(0x0E);
|
|
||||||
writedata(0x08);
|
|
||||||
writedata(0x4E);
|
|
||||||
writedata(0xF1);
|
|
||||||
writedata(0x37);
|
|
||||||
writedata(0x07);
|
|
||||||
writedata(0x10);
|
|
||||||
writedata(0x03);
|
|
||||||
writedata(0x0E);
|
|
||||||
writedata(0x09);
|
|
||||||
writedata(0x00);
|
|
||||||
|
|
||||||
writecommand(0xE1); // Negative Gamma
|
|
||||||
writedata(0x00);
|
|
||||||
writedata(0x0E);
|
|
||||||
writedata(0x14);
|
|
||||||
writedata(0x03);
|
|
||||||
writedata(0x11);
|
|
||||||
writedata(0x07);
|
|
||||||
writedata(0x31);
|
|
||||||
writedata(0xC1);
|
|
||||||
writedata(0x48);
|
|
||||||
writedata(0x08);
|
|
||||||
writedata(0x0F);
|
|
||||||
writedata(0x0C);
|
|
||||||
writedata(0x31);
|
|
||||||
writedata(0x36);
|
|
||||||
writedata(0x0F);
|
|
||||||
|
|
||||||
writecommand(0x11); // Exit Sleep
|
|
||||||
spi_end();
|
|
||||||
delay(120);
|
|
||||||
spi_begin();
|
|
||||||
writecommand(0x29); // Display on
|
|
||||||
}
|
|
||||||
|
|
||||||
else if (_mod == ILI9481) { // 480 x 320
|
|
||||||
writecommand(0x11); // Exit Sleep
|
|
||||||
|
|
||||||
spi_end();
|
|
||||||
delay(20);
|
|
||||||
spi_begin();
|
|
||||||
|
|
||||||
writecommand(0xD0); // Power Setting
|
|
||||||
writedata(0x07);
|
|
||||||
writedata(0x42);
|
|
||||||
writedata(0x18);
|
|
||||||
|
|
||||||
writecommand(0xD1); // VCOM Control
|
|
||||||
writedata(0x00);
|
|
||||||
writedata(0x07);
|
|
||||||
writedata(0x10);
|
|
||||||
|
|
||||||
writecommand(0xD2); // Power Setting for Normal Mode
|
|
||||||
writedata(0x01);
|
|
||||||
writedata(0x02);
|
|
||||||
|
|
||||||
writecommand(0xC0); // Panel Driving Setting
|
|
||||||
writedata(0x10);
|
|
||||||
writedata(0x3B);
|
|
||||||
writedata(0x00);
|
|
||||||
writedata(0x02);
|
|
||||||
writedata(0x11);
|
|
||||||
|
|
||||||
writecommand(0xC5); // Frame Rate and Inversion Control
|
|
||||||
writedata(0x08); // 0x03
|
|
||||||
|
|
||||||
writecommand(0xC8); // Gamma Setting
|
|
||||||
writedata(0x00);
|
|
||||||
writedata(0x32);
|
|
||||||
writedata(0x36);
|
|
||||||
writedata(0x45);
|
|
||||||
writedata(0x06);
|
|
||||||
writedata(0x16);
|
|
||||||
writedata(0x37);
|
|
||||||
writedata(0x75);
|
|
||||||
writedata(0x77);
|
|
||||||
writedata(0x54);
|
|
||||||
writedata(0x0C);
|
|
||||||
writedata(0x00);
|
|
||||||
|
|
||||||
writecommand(0x36); // Address Mode
|
|
||||||
writedata(0x0A);
|
|
||||||
|
|
||||||
writecommand(0x3A); // Pixel Format
|
|
||||||
writedata(0x55);
|
|
||||||
|
|
||||||
writecommand(0x2A); // Column Address
|
|
||||||
writedata(0x00);
|
|
||||||
writedata(0x00);
|
|
||||||
writedata(0x01);
|
|
||||||
writedata(0x3F);
|
|
||||||
|
|
||||||
writecommand(0x2B); // Page Address
|
|
||||||
writedata(0x00);
|
|
||||||
writedata(0x00);
|
|
||||||
writedata(0x01);
|
|
||||||
writedata(0xDF); // 0xE0
|
|
||||||
|
|
||||||
spi_end();
|
|
||||||
delay(120);
|
|
||||||
spi_begin();
|
|
||||||
writecommand(0x29); // Display on
|
|
||||||
}
|
|
||||||
|
|
||||||
else if (_mod == ILI9486) { // 480 x 320
|
|
||||||
writecommand(0x01); // Soft reset
|
|
||||||
// writedata(0x00);
|
|
||||||
|
|
||||||
spi_end();
|
|
||||||
delay(50);
|
|
||||||
spi_begin();
|
|
||||||
|
|
||||||
writecommand(0x28); // Display off
|
|
||||||
// writedata(0x00);
|
|
||||||
|
|
||||||
writecommand(0xC0); // Power Control 1
|
|
||||||
writedata(0x0d);
|
|
||||||
writedata(0x0d);
|
|
||||||
|
|
||||||
writecommand(0xC1); // Power Control 2
|
|
||||||
writedata(0x43);
|
|
||||||
writedata(0x00);
|
|
||||||
|
|
||||||
writecommand(0xC2); // Power Control 3
|
|
||||||
writedata(0x00);
|
|
||||||
|
|
||||||
writecommand(0xC5); // VCOM Control
|
|
||||||
writedata(0x00);
|
|
||||||
writedata(0x48);
|
|
||||||
|
|
||||||
writecommand(0xB6); // Display Function Control
|
|
||||||
writedata(0x00);
|
|
||||||
writedata(0x22); // 0x42 = Rotate display 180 deg.
|
|
||||||
writedata(0x3B);
|
|
||||||
|
|
||||||
writecommand(0xE0); // PGAMCTRL (Positive Gamma Control)
|
|
||||||
writedata(0x0f);
|
|
||||||
writedata(0x24);
|
|
||||||
writedata(0x1c);
|
|
||||||
writedata(0x0a);
|
|
||||||
writedata(0x0f);
|
|
||||||
writedata(0x08);
|
|
||||||
writedata(0x43);
|
|
||||||
writedata(0x88);
|
|
||||||
writedata(0x32);
|
|
||||||
writedata(0x0f);
|
|
||||||
writedata(0x10);
|
|
||||||
writedata(0x06);
|
|
||||||
writedata(0x0f);
|
|
||||||
writedata(0x07);
|
|
||||||
writedata(0x00);
|
|
||||||
|
|
||||||
writecommand(0xE1); // NGAMCTRL (Negative Gamma Control)
|
|
||||||
writedata(0x0F);
|
|
||||||
writedata(0x38);
|
|
||||||
writedata(0x30);
|
|
||||||
writedata(0x09);
|
|
||||||
writedata(0x0f);
|
|
||||||
writedata(0x0f);
|
|
||||||
writedata(0x4e);
|
|
||||||
writedata(0x77);
|
|
||||||
writedata(0x3c);
|
|
||||||
writedata(0x07);
|
|
||||||
writedata(0x10);
|
|
||||||
writedata(0x05);
|
|
||||||
writedata(0x23);
|
|
||||||
writedata(0x1b);
|
|
||||||
writedata(0x00);
|
|
||||||
|
|
||||||
writecommand(0x20); // Display Inversion OFF, 0x21 = ON
|
|
||||||
|
|
||||||
writecommand(0x36); // Memory Access Control
|
|
||||||
writedata(0x0A);
|
|
||||||
|
|
||||||
writecommand(0x3A); // Interface Pixel Format
|
|
||||||
writedata(0x55);
|
|
||||||
|
|
||||||
writecommand(0x11); // Exit Sleep
|
|
||||||
spi_end();
|
|
||||||
delay(150);
|
|
||||||
spi_begin();
|
|
||||||
writecommand(0x29); // Display on
|
|
||||||
}
|
|
||||||
|
|
||||||
spi_end();
|
|
||||||
}
|
|
||||||
|
|
||||||
void TasmotaTFT::setScrollStart(uint16_t start)
|
|
||||||
{
|
|
||||||
spi_begin();
|
|
||||||
writecommand(0x37);
|
|
||||||
writedata(start>>8);
|
|
||||||
writedata(start);
|
|
||||||
spi_end();
|
|
||||||
}
|
|
||||||
|
|
||||||
void TasmotaTFT::setScrollMargins(uint16_t top, uint16_t bottom)
|
|
||||||
{
|
|
||||||
uint16_t height = _height - (top + bottom);
|
|
||||||
|
|
||||||
spi_begin();
|
|
||||||
writecommand(0x33);
|
|
||||||
writedata(top>>8);
|
|
||||||
writedata(top);
|
|
||||||
writedata(height>>8);
|
|
||||||
writedata(height);
|
|
||||||
writedata(bottom>>8);
|
|
||||||
writedata(bottom);
|
|
||||||
spi_end();
|
|
||||||
}
|
|
||||||
|
|
||||||
void TasmotaTFT::setAddrWindow(uint16_t x0, uint16_t y0, uint16_t x1, uint16_t y1)
|
|
||||||
{
|
|
||||||
writecommand(TFT_CASET); // Column addr set
|
|
||||||
writedata(x0 >> 8);
|
|
||||||
writedata(x0 & 0xFF); // XSTART
|
|
||||||
writedata(x1 >> 8);
|
|
||||||
writedata(x1 & 0xFF); // XEND
|
|
||||||
|
|
||||||
writecommand(TFT_PASET); // Row addr set
|
|
||||||
writedata(y0>>8);
|
|
||||||
writedata(y0); // YSTART
|
|
||||||
writedata(y1>>8);
|
|
||||||
writedata(y1); // YEND
|
|
||||||
|
|
||||||
writecommand(TFT_RAMWR); // write to RAM
|
|
||||||
}
|
|
||||||
|
|
||||||
void TasmotaTFT::pushColor(uint16_t color)
|
|
||||||
{
|
|
||||||
spi_begin();
|
|
||||||
|
|
||||||
digitalWrite(_dc, HIGH);
|
|
||||||
digitalWrite(_cs, LOW);
|
|
||||||
SPI.transfer(color >> 8);
|
|
||||||
SPI.transfer(color);
|
|
||||||
digitalWrite(_cs, HIGH);
|
|
||||||
|
|
||||||
spi_end();
|
|
||||||
}
|
|
||||||
|
|
||||||
void TasmotaTFT::drawPixel(int16_t x, int16_t y, uint16_t color)
|
|
||||||
{
|
|
||||||
if((x < 0) ||(x >= _width) || (y < 0) || (y >= _height)) return;
|
|
||||||
|
|
||||||
spi_begin();
|
|
||||||
|
|
||||||
setAddrWindow(x,y,x+1,y+1);
|
|
||||||
digitalWrite(_dc, HIGH);
|
|
||||||
digitalWrite(_cs, LOW);
|
|
||||||
SPI.transfer(color >> 8);
|
|
||||||
SPI.transfer(color);
|
|
||||||
digitalWrite(_cs, HIGH);
|
|
||||||
|
|
||||||
spi_end();
|
|
||||||
}
|
|
||||||
|
|
||||||
void TasmotaTFT::drawFastVLine(int16_t x, int16_t y, int16_t h, uint16_t color)
|
|
||||||
{
|
|
||||||
// Rudimentary clipping
|
|
||||||
if((x >= _width) || (y >= _height)) return;
|
|
||||||
if((y+h-1) >= _height) h = _height-y;
|
|
||||||
|
|
||||||
spi_begin();
|
|
||||||
|
|
||||||
setAddrWindow(x, y, x, y+h-1);
|
|
||||||
uint8_t hi = color >> 8, lo = color;
|
|
||||||
digitalWrite(_dc, HIGH);
|
|
||||||
digitalWrite(_cs, LOW);
|
|
||||||
while (h--) {
|
|
||||||
SPI.transfer(hi);
|
|
||||||
SPI.transfer(lo);
|
|
||||||
}
|
|
||||||
digitalWrite(_cs, HIGH);
|
|
||||||
|
|
||||||
spi_end();
|
|
||||||
}
|
|
||||||
|
|
||||||
void TasmotaTFT::drawFastHLine(int16_t x, int16_t y, int16_t w, uint16_t color)
|
|
||||||
{
|
|
||||||
// Rudimentary clipping
|
|
||||||
if((x >= _width) || (y >= _height)) return;
|
|
||||||
if((x+w-1) >= _width) w = _width-x;
|
|
||||||
|
|
||||||
spi_begin();
|
|
||||||
|
|
||||||
setAddrWindow(x, y, x+w-1, y);
|
|
||||||
uint8_t hi = color >> 8, lo = color;
|
|
||||||
digitalWrite(_dc, HIGH);
|
|
||||||
digitalWrite(_cs, LOW);
|
|
||||||
while (w--) {
|
|
||||||
SPI.transfer(hi);
|
|
||||||
SPI.transfer(lo);
|
|
||||||
}
|
|
||||||
digitalWrite(_cs, HIGH);
|
|
||||||
|
|
||||||
spi_end();
|
|
||||||
}
|
|
||||||
|
|
||||||
void TasmotaTFT::fillScreen(uint16_t color)
|
|
||||||
{
|
|
||||||
fillRect(0, 0, _width, _height, color);
|
|
||||||
}
|
|
||||||
|
|
||||||
// fill a rectangle
|
|
||||||
void TasmotaTFT::fillRect(int16_t x, int16_t y, int16_t w, int16_t h, uint16_t color)
|
|
||||||
{
|
|
||||||
// rudimentary clipping (drawChar w/big text requires this)
|
|
||||||
if((x >= _width) || (y >= _height)) return;
|
|
||||||
if((x + w - 1) >= _width) w = _width - x;
|
|
||||||
if((y + h - 1) >= _height) h = _height - y;
|
|
||||||
|
|
||||||
spi_begin();
|
|
||||||
|
|
||||||
setAddrWindow(x, y, x+w-1, y+h-1);
|
|
||||||
uint8_t hi = color >> 8, lo = color;
|
|
||||||
digitalWrite(_dc, HIGH);
|
|
||||||
digitalWrite(_cs, LOW);
|
|
||||||
for(y=h; y>0; y--) {
|
|
||||||
for(x=w; x>0; x--) {
|
|
||||||
SPI.transfer(hi);
|
|
||||||
SPI.transfer(lo);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
digitalWrite(_cs, HIGH);
|
|
||||||
|
|
||||||
spi_end();
|
|
||||||
}
|
|
||||||
|
|
||||||
// Pass 8-bit (each) R,G,B, get back 16-bit packed color
|
|
||||||
uint16_t TasmotaTFT::color565(uint8_t r, uint8_t g, uint8_t b)
|
|
||||||
{
|
|
||||||
return ((r & 0xF8) << 8) | ((g & 0xFC) << 3) | (b >> 3);
|
|
||||||
}
|
|
||||||
|
|
||||||
#define MADCTL_MY 0x80
|
|
||||||
#define MADCTL_MX 0x40
|
|
||||||
#define MADCTL_MV 0x20
|
|
||||||
#define MADCTL_ML 0x10
|
|
||||||
#define MADCTL_RGB 0x00
|
|
||||||
#define MADCTL_BGR 0x08
|
|
||||||
#define MADCTL_MH 0x04
|
|
||||||
|
|
||||||
void TasmotaTFT::setRotation(uint8_t m)
|
|
||||||
{
|
|
||||||
rotation = m % 4; // can't be higher than 3
|
|
||||||
switch (rotation) {
|
|
||||||
case 0:
|
|
||||||
m = (MADCTL_MX | MADCTL_BGR);
|
|
||||||
_width = _w;
|
|
||||||
_height = _h;
|
|
||||||
break;
|
|
||||||
case 1:
|
|
||||||
m = (MADCTL_MV | MADCTL_BGR);
|
|
||||||
_width = _h;
|
|
||||||
_height = _w;
|
|
||||||
break;
|
|
||||||
case 2:
|
|
||||||
m = (MADCTL_MY | MADCTL_BGR);
|
|
||||||
_width = _w;
|
|
||||||
_height = _h;
|
|
||||||
break;
|
|
||||||
case 3:
|
|
||||||
m = (MADCTL_MX | MADCTL_MY | MADCTL_MV | MADCTL_BGR);
|
|
||||||
_width = _h;
|
|
||||||
_height = _w;
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
|
|
||||||
spi_begin();
|
|
||||||
writecommand(TFT_MADCTL);
|
|
||||||
writedata(m);
|
|
||||||
spi_end();
|
|
||||||
}
|
|
||||||
|
|
||||||
void TasmotaTFT::invertDisplay(boolean i)
|
|
||||||
{
|
|
||||||
spi_begin();
|
|
||||||
writecommand(i ? TFT_INVON : TFT_INVOFF);
|
|
||||||
spi_end();
|
|
||||||
}
|
|
||||||
|
|
||||||
void TasmotaTFT::showDisplay(boolean i)
|
|
||||||
{
|
|
||||||
spi_begin();
|
|
||||||
writecommand(i ? TFT_DISPON : TFT_DISPOFF);
|
|
||||||
spi_end();
|
|
||||||
}
|
|
||||||
|
|
||||||
uint8_t TasmotaTFT::readdata(void)
|
|
||||||
{
|
|
||||||
digitalWrite(_dc, HIGH);
|
|
||||||
digitalWrite(_cs, LOW);
|
|
||||||
uint8_t r = SPI.transfer(0x00);
|
|
||||||
digitalWrite(_cs, HIGH);
|
|
||||||
|
|
||||||
return r;
|
|
||||||
}
|
|
||||||
|
|
||||||
uint8_t TasmotaTFT::readcommand8(uint8_t c, uint8_t index)
|
|
||||||
{
|
|
||||||
spi_begin();
|
|
||||||
|
|
||||||
digitalWrite(_dc, LOW); // command
|
|
||||||
digitalWrite(_cs, LOW);
|
|
||||||
SPI.transfer(0xD9); // woo sekret command?
|
|
||||||
digitalWrite(_dc, HIGH); // data
|
|
||||||
SPI.transfer(0x10 + index);
|
|
||||||
digitalWrite(_cs, HIGH);
|
|
||||||
|
|
||||||
digitalWrite(_dc, LOW); // command
|
|
||||||
digitalWrite(_sclk, LOW);
|
|
||||||
digitalWrite(_cs, LOW);
|
|
||||||
SPI.transfer(c);
|
|
||||||
|
|
||||||
digitalWrite(_dc, HIGH); // data
|
|
||||||
uint8_t r = SPI.transfer(0x00);
|
|
||||||
digitalWrite(_cs, HIGH);
|
|
||||||
|
|
||||||
spi_end();
|
|
||||||
return r;
|
|
||||||
}
|
|
||||||
|
|
||||||
/***************************************************
|
|
||||||
This is our library for the Adafruit ILI9341 Breakout and Shield
|
|
||||||
----> http://www.adafruit.com/products/1651
|
|
||||||
|
|
||||||
Check out the links above for our tutorials and wiring diagrams
|
|
||||||
These displays use SPI to communicate, 4 or 5 pins are required to
|
|
||||||
interface (RST is optional)
|
|
||||||
Adafruit invests time and resources providing this open source code,
|
|
||||||
please support Adafruit and open-source hardware by purchasing
|
|
||||||
products from Adafruit!
|
|
||||||
|
|
||||||
Written by Limor Fried/Ladyada for Adafruit Industries.
|
|
||||||
MIT license, all text above must be included in any redistribution
|
|
||||||
****************************************************/
|
|
|
@ -1,137 +0,0 @@
|
||||||
/*
|
|
||||||
TasmotaTFT.cpp - Adapted implementation of Adafruit ILI9341 for Tasmota
|
|
||||||
|
|
||||||
Copyright (C) 2018 Adafruit and Theo Arends
|
|
||||||
|
|
||||||
This library is free software: you can redistribute it and/or modify
|
|
||||||
it under the terms of the GNU General Public License as published by
|
|
||||||
the Free Software Foundation, either version 3 of the License, or
|
|
||||||
(at your option) any later version.
|
|
||||||
|
|
||||||
This program is distributed in the hope that it will be useful,
|
|
||||||
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
|
||||||
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
|
||||||
GNU General Public License for more details.
|
|
||||||
|
|
||||||
You should have received a copy of the GNU General Public License
|
|
||||||
along with this program. If not, see <http://www.gnu.org/licenses/>.
|
|
||||||
*/
|
|
||||||
|
|
||||||
#ifndef _TasmotaTFT_h
|
|
||||||
#define _TasmotaTFT_h
|
|
||||||
/*********************************************************************************************\
|
|
||||||
* See original Adafruit ILI9341 license text below
|
|
||||||
*
|
|
||||||
* This is a library for the ILI9341, ILI9481 and ILI9486 TFT LCD
|
|
||||||
*
|
|
||||||
* These displays use SPI to communicate, 4 or 5 pins are required to interface (RST is optional)
|
|
||||||
\*********************************************************************************************/
|
|
||||||
|
|
||||||
#include "Arduino.h"
|
|
||||||
#include "Print.h"
|
|
||||||
#include <Adafruit_GFX.h>
|
|
||||||
|
|
||||||
// Supported TFT LCD drivers
|
|
||||||
#define ILI9340 0 // 320 x 240
|
|
||||||
#define ILI9341 0 // 320 x 240
|
|
||||||
#define ILI9481 1 // 480 x 320
|
|
||||||
#define HX8357B 1 // 480 x 320
|
|
||||||
#define ILI9486 2 // 480 x 320
|
|
||||||
#define TFT_MAX 3
|
|
||||||
|
|
||||||
// Common driver registers
|
|
||||||
#define TFT_RDMODE 0x0A // Get Power Mode
|
|
||||||
#define TFT_RDMADCTL 0x0B // Get Address Mode
|
|
||||||
#define TFT_RDPIXFMT 0x0C // Get Pixel Format
|
|
||||||
#define TFT_RDIMGFMT 0x0D // Get Display Mode
|
|
||||||
#define TFT_RDSELFDIAG 0x0F // Get Diagnostic Result
|
|
||||||
|
|
||||||
#define TFT_INVOFF 0x20 // Exit Invert Mode
|
|
||||||
#define TFT_INVON 0x21 // Enter Invert Mode
|
|
||||||
#define TFT_DISPOFF 0x28 // Set Display Off
|
|
||||||
#define TFT_DISPON 0x29 // Set Display on
|
|
||||||
|
|
||||||
#define TFT_CASET 0x2A // Set Column Address
|
|
||||||
#define TFT_PASET 0x2B // Set Page Address
|
|
||||||
#define TFT_RAMWR 0x2C // Write Memory Start
|
|
||||||
|
|
||||||
#define TFT_MADCTL 0x36 // Set Address Mode
|
|
||||||
|
|
||||||
// Color definitions
|
|
||||||
#define TFT_BLACK 0x0000 /* 0, 0, 0 */
|
|
||||||
#define TFT_NAVY 0x000F /* 0, 0, 128 */
|
|
||||||
#define TFT_DARKGREEN 0x03E0 /* 0, 128, 0 */
|
|
||||||
#define TFT_DARKCYAN 0x03EF /* 0, 128, 128 */
|
|
||||||
#define TFT_MAROON 0x7800 /* 128, 0, 0 */
|
|
||||||
#define TFT_PURPLE 0x780F /* 128, 0, 128 */
|
|
||||||
#define TFT_OLIVE 0x7BE0 /* 128, 128, 0 */
|
|
||||||
#define TFT_LIGHTGREY 0xC618 /* 192, 192, 192 */
|
|
||||||
#define TFT_DARKGREY 0x7BEF /* 128, 128, 128 */
|
|
||||||
#define TFT_BLUE 0x001F /* 0, 0, 255 */
|
|
||||||
#define TFT_GREEN 0x07E0 /* 0, 255, 0 */
|
|
||||||
#define TFT_CYAN 0x07FF /* 0, 255, 255 */
|
|
||||||
#define TFT_RED 0xF800 /* 255, 0, 0 */
|
|
||||||
#define TFT_MAGENTA 0xF81F /* 255, 0, 255 */
|
|
||||||
#define TFT_YELLOW 0xFFE0 /* 255, 255, 0 */
|
|
||||||
#define TFT_WHITE 0xFFFF /* 255, 255, 255 */
|
|
||||||
#define TFT_ORANGE 0xFD20 /* 255, 165, 0 */
|
|
||||||
#define TFT_GREENYELLOW 0xAFE5 /* 173, 255, 47 */
|
|
||||||
#define TFT_PINK 0xF81F
|
|
||||||
|
|
||||||
class TasmotaTFT : public Adafruit_GFX {
|
|
||||||
public:
|
|
||||||
TasmotaTFT(int8_t _MODEL, int8_t _CS, int8_t _DC, int8_t _RST = -1);
|
|
||||||
void begin(void);
|
|
||||||
void setScrollStart(uint16_t start);
|
|
||||||
void setScrollMargins(uint16_t top, uint16_t bottom);
|
|
||||||
void setAddrWindow(uint16_t x0, uint16_t y0, uint16_t x1, uint16_t y1);
|
|
||||||
void pushColor(uint16_t color);
|
|
||||||
void fillScreen(uint16_t color);
|
|
||||||
void drawPixel(int16_t x, int16_t y, uint16_t color);
|
|
||||||
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);
|
|
||||||
void setRotation(uint8_t r);
|
|
||||||
void invertDisplay(boolean i);
|
|
||||||
void showDisplay(boolean i);
|
|
||||||
uint16_t color565(uint8_t r, uint8_t g, uint8_t b);
|
|
||||||
|
|
||||||
/* These are not for current use, 8-bit protocol only! */
|
|
||||||
uint8_t readdata(void);
|
|
||||||
uint8_t readcommand8(uint8_t reg, uint8_t index = 0);
|
|
||||||
|
|
||||||
void spiwrite(uint8_t);
|
|
||||||
void writecommand(uint8_t c);
|
|
||||||
void writedata(uint8_t d);
|
|
||||||
void commandList(uint8_t *addr);
|
|
||||||
uint8_t spiread(void);
|
|
||||||
|
|
||||||
private:
|
|
||||||
uint8_t tabcolor;
|
|
||||||
uint8_t _mod;
|
|
||||||
int16_t _w;
|
|
||||||
int16_t _h;
|
|
||||||
int32_t _cs;
|
|
||||||
int32_t _dc;
|
|
||||||
int32_t _rst;
|
|
||||||
int32_t _mosi;
|
|
||||||
int32_t _miso;
|
|
||||||
int32_t _sclk;
|
|
||||||
};
|
|
||||||
|
|
||||||
#endif // _TasmotaTFT_h
|
|
||||||
|
|
||||||
/***************************************************
|
|
||||||
This is our library for the Adafruit ILI9341 Breakout and Shield
|
|
||||||
----> http://www.adafruit.com/products/1651
|
|
||||||
|
|
||||||
Check out the links above for our tutorials and wiring diagrams
|
|
||||||
These displays use SPI to communicate, 4 or 5 pins are required to
|
|
||||||
interface (RST is optional)
|
|
||||||
Adafruit invests time and resources providing this open source code,
|
|
||||||
please support Adafruit and open-source hardware by purchasing
|
|
||||||
products from Adafruit!
|
|
||||||
|
|
||||||
Written by Limor Fried/Ladyada for Adafruit Industries.
|
|
||||||
MIT license, all text above must be included in any redistribution
|
|
||||||
****************************************************/
|
|
|
@ -1,4 +1,7 @@
|
||||||
/* 6.1.1.6
|
/* 6.1.1.7
|
||||||
|
* Add initial display support for Lcd, Oled, Matrix, Tft and e-paper - Need more docs
|
||||||
|
*
|
||||||
|
* 6.1.1.6
|
||||||
* Add modulo option to rules like rule1 on Time#Minute|5 do backlog power on;delay 200;power off endon (#3466)
|
* Add modulo option to rules like rule1 on Time#Minute|5 do backlog power on;delay 200;power off endon (#3466)
|
||||||
*
|
*
|
||||||
* 6.1.1.5
|
* 6.1.1.5
|
||||||
|
|
|
@ -377,18 +377,6 @@
|
||||||
#define D_CMND_LATITUDE "Latitude"
|
#define D_CMND_LATITUDE "Latitude"
|
||||||
#define D_CMND_LONGITUDE "Longitude"
|
#define D_CMND_LONGITUDE "Longitude"
|
||||||
|
|
||||||
// Commands xdrv_98_display.ino
|
|
||||||
#define D_CMND_DISPLAY "Display"
|
|
||||||
#define D_CMND_DISP_ADDRESS "Address"
|
|
||||||
#define D_CMND_DISP_COLS "Cols"
|
|
||||||
#define D_CMND_DISP_DIMMER "Dimmer"
|
|
||||||
#define D_CMND_DISP_MODE "Mode"
|
|
||||||
#define D_CMND_DISP_MODEL "Model"
|
|
||||||
#define D_CMND_DISP_REFRESH "Refresh"
|
|
||||||
#define D_CMND_DISP_ROWS "Rows"
|
|
||||||
#define D_CMND_DISP_SIZE "Size"
|
|
||||||
#define D_CMND_DISP_TEXT "Text"
|
|
||||||
|
|
||||||
/********************************************************************************************/
|
/********************************************************************************************/
|
||||||
|
|
||||||
#define D_ASTERIX "********"
|
#define D_ASTERIX "********"
|
||||||
|
|
|
@ -196,9 +196,7 @@ enum LichtSubtypes {LST_NONE, LST_SINGLE, LST_COLDWARM, LST_RGB, LST_RGBW, LST_R
|
||||||
enum LichtSchemes {LS_POWER, LS_WAKEUP, LS_CYCLEUP, LS_CYCLEDN, LS_RANDOM, LS_MAX};
|
enum LichtSchemes {LS_POWER, LS_WAKEUP, LS_CYCLEUP, LS_CYCLEDN, LS_RANDOM, LS_MAX};
|
||||||
|
|
||||||
enum XsnsFunctions {FUNC_PRE_INIT, FUNC_INIT, FUNC_LOOP, FUNC_EVERY_50_MSECOND, FUNC_EVERY_SECOND, FUNC_PREP_BEFORE_TELEPERIOD, FUNC_JSON_APPEND, FUNC_WEB_APPEND, FUNC_SAVE_BEFORE_RESTART,
|
enum XsnsFunctions {FUNC_PRE_INIT, FUNC_INIT, FUNC_LOOP, FUNC_EVERY_50_MSECOND, FUNC_EVERY_SECOND, FUNC_PREP_BEFORE_TELEPERIOD, FUNC_JSON_APPEND, FUNC_WEB_APPEND, FUNC_SAVE_BEFORE_RESTART,
|
||||||
FUNC_COMMAND, FUNC_MQTT_SUBSCRIBE, FUNC_MQTT_INIT, FUNC_MQTT_DATA, FUNC_SET_POWER, FUNC_SHOW_SENSOR, FUNC_RULES_PROCESS, FUNC_FREE_MEM,
|
FUNC_COMMAND, FUNC_MQTT_SUBSCRIBE, FUNC_MQTT_INIT, FUNC_MQTT_DATA, FUNC_SET_POWER, FUNC_SHOW_SENSOR, FUNC_RULES_PROCESS, FUNC_FREE_MEM};
|
||||||
FUNC_DISPLAY_POWER, FUNC_DISPLAY_CLEAR, FUNC_DISPLAY_INIT_PARTIAL, FUNC_DISPLAY_INIT_FULL, FUNC_DISPLAY_DRAW_HLINE, FUNC_DISPLAY_DRAW_VLINE, FUNC_DISPLAY_DRAW_CIRCLE,
|
|
||||||
FUNC_DISPLAY_FILL_CIRCLE, FUNC_DISPLAY_DRAW_RECTANGLE, FUNC_DISPLAY_FILL_RECTANGLE, FUNC_DISPLAY_DRAW_FRAME, FUNC_DISPLAY_FONT_SIZE, FUNC_DISPLAY_DRAW_STRING, FUNC_DISPLAY_ONOFF };
|
|
||||||
|
|
||||||
const uint8_t kDefaultRfCode[9] PROGMEM = { 0x21, 0x16, 0x01, 0x0E, 0x03, 0x48, 0x2E, 0x1A, 0x00 };
|
const uint8_t kDefaultRfCode[9] PROGMEM = { 0x21, 0x16, 0x01, 0x0E, 0x03, 0x48, 0x2E, 0x1A, 0x00 };
|
||||||
|
|
||||||
|
|
|
@ -20,7 +20,7 @@
|
||||||
#ifndef _SONOFF_VERSION_H_
|
#ifndef _SONOFF_VERSION_H_
|
||||||
#define _SONOFF_VERSION_H_
|
#define _SONOFF_VERSION_H_
|
||||||
|
|
||||||
#define VERSION 0x06010106
|
#define VERSION 0x06010107
|
||||||
|
|
||||||
#define D_PROGRAMNAME "Sonoff-Tasmota"
|
#define D_PROGRAMNAME "Sonoff-Tasmota"
|
||||||
#define D_AUTHOR "Theo Arends"
|
#define D_AUTHOR "Theo Arends"
|
||||||
|
|
|
@ -271,6 +271,7 @@
|
||||||
|
|
||||||
// -- I2C sensors ---------------------------------
|
// -- I2C sensors ---------------------------------
|
||||||
#define USE_I2C // I2C using library wire (+10k code, 0k2 mem, 124 iram)
|
#define USE_I2C // I2C using library wire (+10k code, 0k2 mem, 124 iram)
|
||||||
|
|
||||||
#ifdef USE_I2C
|
#ifdef USE_I2C
|
||||||
#define USE_SHT // Enable SHT1X sensor (+1k4 code)
|
#define USE_SHT // Enable SHT1X sensor (+1k4 code)
|
||||||
#define USE_HTU // Enable HTU21/SI7013/SI7020/SI7021 sensor (I2C address 0x40) (+1k5 code)
|
#define USE_HTU // Enable HTU21/SI7013/SI7020/SI7021 sensor (I2C address 0x40) (+1k5 code)
|
||||||
|
@ -295,11 +296,31 @@
|
||||||
// #define USE_MPR121 // Enable MPR121 controller (I2C addresses 0x5A, 0x5B, 0x5C and 0x5D) in input mode for touch buttons (+1k3 code)
|
// #define USE_MPR121 // Enable MPR121 controller (I2C addresses 0x5A, 0x5B, 0x5C and 0x5D) in input mode for touch buttons (+1k3 code)
|
||||||
// #define USE_CCS811 // Enable CCS811 sensor (I2C address 0x5A) (+2k2 code)
|
// #define USE_CCS811 // Enable CCS811 sensor (I2C address 0x5A) (+2k2 code)
|
||||||
// #define USE_MPU6050 // Enable MPU6050 sensor (I2C address 0x68 AD0 low or 0x69 AD0 high) (+2k6 code)
|
// #define USE_MPU6050 // Enable MPU6050 sensor (I2C address 0x68 AD0 low or 0x69 AD0 high) (+2k6 code)
|
||||||
|
|
||||||
|
// #define USE_DISPLAY // Add I2C Display Support for LCD, Oled and up to eigth Matrices (+19k code)
|
||||||
|
#define USE_DISPLAY_LCD // Enable Lcd display (I2C addresses 0x27 and 0x3F)
|
||||||
|
#define USE_DISPLAY_SSD1306 // Enable Oled 128x64 display (I2C addresses 0x3C and 0x3D)
|
||||||
|
// #define USE_DISPLAY_MATRIX // Enable 8x8 Matrix display (I2C adresses below)
|
||||||
|
#define MTX_ADDRESS1 0x71 // [DisplayAddress[1]] I2C address of first 8x8 matrix module
|
||||||
|
#define MTX_ADDRESS2 0x74 // [DisplayAddress[2]] I2C address of second 8x8 matrix module
|
||||||
|
#define MTX_ADDRESS3 0x75 // [DisplayAddress[3]] I2C address of third 8x8 matrix module
|
||||||
|
#define MTX_ADDRESS4 0x72 // [DisplayAddress[4]] I2C address of fourth 8x8 matrix module
|
||||||
|
#define MTX_ADDRESS5 0x73 // [DisplayAddress[5]] I2C address of fifth 8x8 matrix module
|
||||||
|
#define MTX_ADDRESS6 0x76 // [DisplayAddress[6]] I2C address of sixth 8x8 matrix module
|
||||||
|
#define MTX_ADDRESS7 0x00 // [DisplayAddress[7]] I2C address of seventh 8x8 matrix module
|
||||||
|
#define MTX_ADDRESS8 0x00 // [DisplayAddress[8]] I2C address of eigth 8x8 matrix module
|
||||||
|
|
||||||
#endif // USE_I2C
|
#endif // USE_I2C
|
||||||
|
|
||||||
// -- SPI sensors ---------------------------------
|
// -- SPI sensors ---------------------------------
|
||||||
//#define USE_SPI // SPI using default library
|
//#define USE_SPI // SPI using library TasmotaTFT
|
||||||
|
|
||||||
#ifdef USE_SPI
|
#ifdef USE_SPI
|
||||||
|
#ifndef USE_DISPLAY
|
||||||
|
#define USE_DISPLAY // Add SPI Display support for 320x240 and 480x320 TFT
|
||||||
|
#endif
|
||||||
|
#define USE_DISPLAY_ILI9341 // Enable Tft 480x320 display
|
||||||
|
// #define USE_DISPLAY_EPAPER // Enable e-paper display
|
||||||
|
|
||||||
#endif // USE_SPI
|
#endif // USE_SPI
|
||||||
|
|
||||||
|
@ -312,9 +333,9 @@
|
||||||
#define USE_NOVA_SDS // Add support for SDS011 and SDS021 particle concentration sensor (+0k7 code)
|
#define USE_NOVA_SDS // Add support for SDS011 and SDS021 particle concentration sensor (+0k7 code)
|
||||||
#define USE_PZEM004T // Add support for PZEM004T Energy monitor (+2k code)
|
#define USE_PZEM004T // Add support for PZEM004T Energy monitor (+2k code)
|
||||||
#define USE_SERIAL_BRIDGE // Add support for software Serial Bridge (+0k8 code)
|
#define USE_SERIAL_BRIDGE // Add support for software Serial Bridge (+0k8 code)
|
||||||
#define USE_SDM120 // Add support for Eastron SDM120-Modbus energy meter (+1k7 code)
|
//#define USE_SDM120 // Add support for Eastron SDM120-Modbus energy meter (+1k7 code)
|
||||||
#define SDM120_SPEED 9600 // SDM120-Modbus RS485 serial speed (default: 2400 baud)
|
#define SDM120_SPEED 9600 // SDM120-Modbus RS485 serial speed (default: 2400 baud)
|
||||||
#define USE_SDM630 // Add support for Eastron SDM630-Modbus energy meter (+2k code)
|
//#define USE_SDM630 // Add support for Eastron SDM630-Modbus energy meter (+2k code)
|
||||||
#define SDM630_SPEED 9600 // SDM630-Modbus RS485 serial speed (default: 9600 baud)
|
#define SDM630_SPEED 9600 // SDM630-Modbus RS485 serial speed (default: 9600 baud)
|
||||||
|
|
||||||
// -- Low level interface devices -----------------
|
// -- Low level interface devices -----------------
|
||||||
|
@ -330,7 +351,7 @@
|
||||||
|
|
||||||
#define USE_SR04 // Add support for HC-SR04 ultrasonic devices (+1k code)
|
#define USE_SR04 // Add support for HC-SR04 ultrasonic devices (+1k code)
|
||||||
|
|
||||||
#define USE_TM1638 // Add support for TM1638 switches copying Switch1 .. Switch8 (+1k code)
|
//#define USE_TM1638 // Add support for TM1638 switches copying Switch1 .. Switch8 (+1k code)
|
||||||
|
|
||||||
#define USE_RF_FLASH // Add support for flashing the EFM8BB1 chip on the Sonoff RF Bridge. C2CK must be connected to GPIO4, C2D to GPIO5 on the PCB (+3k code)
|
#define USE_RF_FLASH // Add support for flashing the EFM8BB1 chip on the Sonoff RF Bridge. C2CK must be connected to GPIO4, C2D to GPIO5 on the PCB (+3k code)
|
||||||
|
|
||||||
|
|
|
@ -0,0 +1,891 @@
|
||||||
|
/*
|
||||||
|
xdrv_13_display.ino - Display support for Sonoff-Tasmota
|
||||||
|
|
||||||
|
Copyright (C) 2018 Theo Arends
|
||||||
|
|
||||||
|
This program is free software: you can redistribute it and/or modify
|
||||||
|
it under the terms of the GNU General Public License as published by
|
||||||
|
the Free Software Foundation, either version 3 of the License, or
|
||||||
|
(at your option) any later version.
|
||||||
|
|
||||||
|
This program is distributed in the hope that it will be useful,
|
||||||
|
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||||
|
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||||
|
GNU General Public License for more details.
|
||||||
|
|
||||||
|
You should have received a copy of the GNU General Public License
|
||||||
|
along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||||
|
*/
|
||||||
|
|
||||||
|
#if defined(USE_I2C) || defined(USE_SPI)
|
||||||
|
#ifdef USE_DISPLAY
|
||||||
|
|
||||||
|
#define DISPLAY_MAX_DRIVERS 16 // Max number of display drivers/models supported by xdsp_interface.ino
|
||||||
|
|
||||||
|
#define DISPLAY_SCREEN_COLS 40 // Max number of columns to display
|
||||||
|
#define DISPLAY_SCREEN_ROWS 8 // Max number of lines to display for LCD and Oled using local screen buffer
|
||||||
|
|
||||||
|
#define DISPLAY_LOG_COLS DISPLAY_SCREEN_COLS +1 // Number of characters in display log buffer line +1
|
||||||
|
#define DISPLAY_LOG_ROWS 32 // Number of lines in display log buffer
|
||||||
|
|
||||||
|
#define D_CMND_DISPLAY "Display"
|
||||||
|
#define D_CMND_DISP_ADDRESS "Address"
|
||||||
|
#define D_CMND_DISP_COLS "Cols"
|
||||||
|
#define D_CMND_DISP_DIMMER "Dimmer"
|
||||||
|
#define D_CMND_DISP_MODE "Mode"
|
||||||
|
#define D_CMND_DISP_MODEL "Model"
|
||||||
|
#define D_CMND_DISP_REFRESH "Refresh"
|
||||||
|
#define D_CMND_DISP_ROWS "Rows"
|
||||||
|
#define D_CMND_DISP_SIZE "Size"
|
||||||
|
#define D_CMND_DISP_TEXT "Text"
|
||||||
|
|
||||||
|
enum XdspFunctions { FUNC_DISPLAY_INIT_DRIVER, FUNC_DISPLAY_INIT, FUNC_DISPLAY_EVERY_50_MSECOND, FUNC_DISPLAY_EVERY_SECOND,
|
||||||
|
FUNC_DISPLAY_MODEL, FUNC_DISPLAY_MODE, FUNC_DISPLAY_POWER,
|
||||||
|
FUNC_DISPLAY_CLEAR, FUNC_DISPLAY_DRAW_FRAME,
|
||||||
|
FUNC_DISPLAY_DRAW_HLINE, FUNC_DISPLAY_DRAW_VLINE, FUNC_DISPLAY_DRAW_LINE,
|
||||||
|
FUNC_DISPLAY_DRAW_CIRCLE, FUNC_DISPLAY_FILL_CIRCLE,
|
||||||
|
FUNC_DISPLAY_DRAW_RECTANGLE, FUNC_DISPLAY_FILL_RECTANGLE,
|
||||||
|
FUNC_DISPLAY_FONT_SIZE, FUNC_DISPLAY_ROTATION, FUNC_DISPLAY_DRAW_STRING, FUNC_DISPLAY_ONOFF };
|
||||||
|
|
||||||
|
enum DisplayInitModes { DISPLAY_INIT_MODE, DISPLAY_INIT_PARTIAL, DISPLAY_INIT_FULL };
|
||||||
|
|
||||||
|
enum DisplayCommands { CMND_DISP_MODEL, CMND_DISP_MODE, CMND_DISP_REFRESH, CMND_DISP_DIMMER, CMND_DISP_COLS, CMND_DISP_ROWS,
|
||||||
|
CMND_DISP_SIZE, CMND_DISP_TEXT, CMND_DISP_ADDRESS };
|
||||||
|
const char kDisplayCommands[] PROGMEM =
|
||||||
|
D_CMND_DISP_MODEL "|" D_CMND_DISP_MODE "|" D_CMND_DISP_REFRESH "|" D_CMND_DISP_DIMMER "|" D_CMND_DISP_COLS "|" D_CMND_DISP_ROWS "|"
|
||||||
|
D_CMND_DISP_SIZE "|" D_CMND_DISP_TEXT "|" D_CMND_DISP_ADDRESS ;
|
||||||
|
|
||||||
|
const char S_JSON_DISPLAY_COMMAND_VALUE[] PROGMEM = "{\"" D_CMND_DISPLAY "%s\":\"%s\"}";
|
||||||
|
const char S_JSON_DISPLAY_COMMAND_NVALUE[] PROGMEM = "{\"" D_CMND_DISPLAY "%s\":%d}";
|
||||||
|
const char S_JSON_DISPLAY_COMMAND_INDEX_NVALUE[] PROGMEM = "{\"" D_CMND_DISPLAY "%s%d\":%d}";
|
||||||
|
|
||||||
|
char disp_log_buffer[DISPLAY_LOG_ROWS][DISPLAY_LOG_COLS];
|
||||||
|
char disp_temp[2]; // C or F
|
||||||
|
uint8_t disp_log_buffer_idx = 0;
|
||||||
|
uint8_t disp_log_buffer_ptr = 0;
|
||||||
|
bool disp_log_buffer_active = false;
|
||||||
|
uint8_t disp_refresh = 1;
|
||||||
|
uint8_t disp_power = 0;
|
||||||
|
uint8_t disp_device = 0;
|
||||||
|
uint8_t disp_subscribed = 0;
|
||||||
|
|
||||||
|
int16_t disp_xpos = 0;
|
||||||
|
int16_t disp_ypos = 0;
|
||||||
|
|
||||||
|
uint8_t dsp_init;
|
||||||
|
uint8_t dsp_font;
|
||||||
|
uint8_t dsp_flag;
|
||||||
|
uint8_t dsp_on;
|
||||||
|
uint8_t dsp_rotation;
|
||||||
|
uint16_t dsp_x;
|
||||||
|
uint16_t dsp_y;
|
||||||
|
uint16_t dsp_x2;
|
||||||
|
uint16_t dsp_y2;
|
||||||
|
uint16_t dsp_rad;
|
||||||
|
uint16_t dsp_color;
|
||||||
|
int16_t dsp_len;
|
||||||
|
char *dsp_str;
|
||||||
|
|
||||||
|
void DisplayInit(uint8_t mode)
|
||||||
|
{
|
||||||
|
dsp_init = mode;
|
||||||
|
XdspCall(FUNC_DISPLAY_INIT);
|
||||||
|
}
|
||||||
|
|
||||||
|
void DisplayClear()
|
||||||
|
{
|
||||||
|
XdspCall(FUNC_DISPLAY_CLEAR);
|
||||||
|
}
|
||||||
|
|
||||||
|
void DisplayDrawHLine(uint16_t x, uint16_t y, int16_t len, uint16_t color)
|
||||||
|
{
|
||||||
|
dsp_x = x;
|
||||||
|
dsp_y = y;
|
||||||
|
dsp_len = len;
|
||||||
|
dsp_color = color;
|
||||||
|
XdspCall(FUNC_DISPLAY_DRAW_HLINE);
|
||||||
|
}
|
||||||
|
|
||||||
|
void DisplayDrawVLine(uint16_t x, uint16_t y, int16_t len, uint16_t color)
|
||||||
|
{
|
||||||
|
dsp_x = x;
|
||||||
|
dsp_y = y;
|
||||||
|
dsp_len = len;
|
||||||
|
dsp_color = color;
|
||||||
|
XdspCall(FUNC_DISPLAY_DRAW_VLINE);
|
||||||
|
}
|
||||||
|
|
||||||
|
void DisplayDrawLine(uint16_t x, uint16_t y, uint16_t x2, uint16_t y2, uint16_t color)
|
||||||
|
{
|
||||||
|
dsp_x = x;
|
||||||
|
dsp_y = y;
|
||||||
|
dsp_x2 = x2;
|
||||||
|
dsp_y2 = y2;
|
||||||
|
dsp_color = color;
|
||||||
|
XdspCall(FUNC_DISPLAY_DRAW_LINE);
|
||||||
|
}
|
||||||
|
|
||||||
|
void DisplayDrawCircle(uint16_t x, uint16_t y, uint16_t rad, uint16_t color)
|
||||||
|
{
|
||||||
|
dsp_x = x;
|
||||||
|
dsp_y = y;
|
||||||
|
dsp_rad = rad;
|
||||||
|
dsp_color = color;
|
||||||
|
XdspCall(FUNC_DISPLAY_DRAW_CIRCLE);
|
||||||
|
}
|
||||||
|
|
||||||
|
void DisplayDrawFilledCircle(uint16_t x, uint16_t y, uint16_t rad, uint16_t color)
|
||||||
|
{
|
||||||
|
dsp_x = x;
|
||||||
|
dsp_y = y;
|
||||||
|
dsp_rad = rad;
|
||||||
|
dsp_color = color;
|
||||||
|
XdspCall(FUNC_DISPLAY_FILL_CIRCLE);
|
||||||
|
}
|
||||||
|
|
||||||
|
void DisplayDrawRectangle(uint16_t x, uint16_t y, uint16_t x2, uint16_t y2, uint16_t color)
|
||||||
|
{
|
||||||
|
dsp_x = x;
|
||||||
|
dsp_y = y;
|
||||||
|
dsp_x2 = x2;
|
||||||
|
dsp_y2 = y2;
|
||||||
|
dsp_color = color;
|
||||||
|
XdspCall(FUNC_DISPLAY_DRAW_RECTANGLE);
|
||||||
|
}
|
||||||
|
|
||||||
|
void DisplayDrawFilledRectangle(uint16_t x, uint16_t y, uint16_t x2, uint16_t y2, uint16_t color)
|
||||||
|
{
|
||||||
|
dsp_x = x;
|
||||||
|
dsp_y = y;
|
||||||
|
dsp_x2 = x2;
|
||||||
|
dsp_y2 = y2;
|
||||||
|
dsp_color = color;
|
||||||
|
XdspCall(FUNC_DISPLAY_FILL_RECTANGLE);
|
||||||
|
}
|
||||||
|
|
||||||
|
void DisplayDrawFrame()
|
||||||
|
{
|
||||||
|
XdspCall(FUNC_DISPLAY_DRAW_FRAME);
|
||||||
|
}
|
||||||
|
|
||||||
|
void DisplaySetFontorSize(uint8_t font)
|
||||||
|
{
|
||||||
|
Settings.display_size = font;
|
||||||
|
XdspCall(FUNC_DISPLAY_FONT_SIZE);
|
||||||
|
}
|
||||||
|
|
||||||
|
void DisplaySetRotation(uint8_t rotation)
|
||||||
|
{
|
||||||
|
dsp_rotation = rotation;
|
||||||
|
XdspCall(FUNC_DISPLAY_ROTATION);
|
||||||
|
}
|
||||||
|
|
||||||
|
void DisplayDrawStringAt(uint16_t x, uint16_t y, char *str, uint16_t color, uint8_t flag)
|
||||||
|
{
|
||||||
|
dsp_x = x;
|
||||||
|
dsp_y = y;
|
||||||
|
dsp_str = str;
|
||||||
|
dsp_color = color;
|
||||||
|
dsp_flag = flag;
|
||||||
|
XdspCall(FUNC_DISPLAY_DRAW_STRING);
|
||||||
|
}
|
||||||
|
|
||||||
|
void DisplayOnOff(uint8_t on)
|
||||||
|
{
|
||||||
|
dsp_on = on;
|
||||||
|
XdspCall(FUNC_DISPLAY_ONOFF);
|
||||||
|
}
|
||||||
|
|
||||||
|
// get asci number until delimiter and return asci number lenght and value
|
||||||
|
uint8_t atoiv(char *cp, int16_t *res)
|
||||||
|
{
|
||||||
|
uint8_t index = 0;
|
||||||
|
*res = atoi(cp);
|
||||||
|
while (*cp) {
|
||||||
|
if ((*cp>='0' && *cp<='9') || (*cp=='-')) {
|
||||||
|
cp++;
|
||||||
|
index++;
|
||||||
|
} else {
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return index;
|
||||||
|
}
|
||||||
|
|
||||||
|
// get asci number until delimiter and return asci number lenght and value
|
||||||
|
uint8_t atoiV(char *cp, uint16_t *res)
|
||||||
|
{
|
||||||
|
uint8_t index = 0;
|
||||||
|
*res = atoi(cp);
|
||||||
|
while (*cp) {
|
||||||
|
if (*cp>='0' && *cp<='9') {
|
||||||
|
cp++;
|
||||||
|
index++;
|
||||||
|
} else {
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return index;
|
||||||
|
}
|
||||||
|
|
||||||
|
/*********************************************************************************************/
|
||||||
|
|
||||||
|
#define DISPLAY_BUFFER_COLS 128 // Max number of characters in linebuf
|
||||||
|
|
||||||
|
void DisplayText()
|
||||||
|
{
|
||||||
|
uint8_t lpos;
|
||||||
|
uint8_t escape = 0;
|
||||||
|
uint8_t var;
|
||||||
|
uint8_t font_x = 6;
|
||||||
|
uint8_t font_y = 8;
|
||||||
|
uint8_t fontnumber = 1;
|
||||||
|
int16_t lin = 0;
|
||||||
|
int16_t col = 0;
|
||||||
|
int16_t fill = 0;
|
||||||
|
int16_t temp;
|
||||||
|
int16_t temp1;
|
||||||
|
uint16_t color = 0;
|
||||||
|
|
||||||
|
char linebuf[DISPLAY_BUFFER_COLS];
|
||||||
|
char *dp = linebuf;
|
||||||
|
char *cp = XdrvMailbox.data;
|
||||||
|
|
||||||
|
memset(linebuf, ' ', sizeof(linebuf));
|
||||||
|
linebuf[sizeof(linebuf)-1] = 0;
|
||||||
|
*dp = 0;
|
||||||
|
|
||||||
|
while (*cp) {
|
||||||
|
if (!escape) {
|
||||||
|
// check for escape
|
||||||
|
if (*cp == '[') {
|
||||||
|
escape = 1;
|
||||||
|
cp++;
|
||||||
|
// if string in buffer print it
|
||||||
|
if ((uint32_t)dp - (uint32_t)linebuf) {
|
||||||
|
if (!fill) { *dp = 0; }
|
||||||
|
if (col > 0 && lin > 0) {
|
||||||
|
// use col and lin
|
||||||
|
DisplayDrawStringAt(col, lin, linebuf, color, 1);
|
||||||
|
} else {
|
||||||
|
// use disp_xpos, disp_ypos
|
||||||
|
DisplayDrawStringAt(disp_xpos, disp_ypos, linebuf, color, 0);
|
||||||
|
}
|
||||||
|
memset(linebuf, ' ', sizeof(linebuf));
|
||||||
|
linebuf[sizeof(linebuf)-1] = 0;
|
||||||
|
dp = linebuf;
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
// copy chars
|
||||||
|
if (dp < (linebuf + DISPLAY_BUFFER_COLS)) { *dp++ = *cp++; }
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
// check escapes
|
||||||
|
if (*cp == ']') {
|
||||||
|
escape = 0;
|
||||||
|
cp++;
|
||||||
|
} else {
|
||||||
|
// analyze escapes
|
||||||
|
switch (*cp++) {
|
||||||
|
case 'z':
|
||||||
|
// clear display
|
||||||
|
DisplayClear();
|
||||||
|
disp_xpos = 0;
|
||||||
|
disp_ypos = 0;
|
||||||
|
col = 0;
|
||||||
|
lin = 0;
|
||||||
|
break;
|
||||||
|
case 'i':
|
||||||
|
// init display with partial update
|
||||||
|
DisplayInit(DISPLAY_INIT_PARTIAL);
|
||||||
|
break;
|
||||||
|
case 'I':
|
||||||
|
// init display with full refresh
|
||||||
|
DisplayInit(DISPLAY_INIT_FULL);
|
||||||
|
break;
|
||||||
|
case 'o':
|
||||||
|
DisplayOnOff(0);
|
||||||
|
break;
|
||||||
|
case 'O':
|
||||||
|
DisplayOnOff(1);
|
||||||
|
break;
|
||||||
|
case 'x':
|
||||||
|
// set disp_xpos
|
||||||
|
var = atoiv(cp, &disp_xpos);
|
||||||
|
cp += var;
|
||||||
|
break;
|
||||||
|
case 'y':
|
||||||
|
// set disp_ypos
|
||||||
|
var = atoiv(cp, &disp_ypos);
|
||||||
|
cp += var;
|
||||||
|
break;
|
||||||
|
case 'l':
|
||||||
|
// text line lxx
|
||||||
|
var = atoiv(cp, &lin);
|
||||||
|
cp += var;
|
||||||
|
//display.setCursor(display.getCursorX(),(lin-1)*font_y*txtsize);
|
||||||
|
break;
|
||||||
|
case 'c':
|
||||||
|
// text column cxx
|
||||||
|
var = atoiv(cp, &col);
|
||||||
|
cp += var;
|
||||||
|
//display.setCursor((col-1)*font_x*txtsize,display.getCursorY());
|
||||||
|
break;
|
||||||
|
case 'C':
|
||||||
|
// text color cxx
|
||||||
|
var = atoiV(cp, &color);
|
||||||
|
cp += var;
|
||||||
|
break;
|
||||||
|
case 'p':
|
||||||
|
// pad field with spaces fxx
|
||||||
|
var = atoiv(cp, &fill);
|
||||||
|
cp += var;
|
||||||
|
linebuf[fill] = 0;
|
||||||
|
break;
|
||||||
|
case 'h':
|
||||||
|
// hor line to
|
||||||
|
var = atoiv(cp, &temp);
|
||||||
|
cp += var;
|
||||||
|
if (temp < 0) {
|
||||||
|
DisplayDrawHLine(disp_xpos + temp, disp_ypos, -temp, color);
|
||||||
|
} else {
|
||||||
|
DisplayDrawHLine(disp_xpos, disp_ypos, temp, color);
|
||||||
|
}
|
||||||
|
disp_xpos += temp;
|
||||||
|
break;
|
||||||
|
case 'v':
|
||||||
|
// vert line to
|
||||||
|
var = atoiv(cp, &temp);
|
||||||
|
cp += var;
|
||||||
|
if (temp < 0) {
|
||||||
|
DisplayDrawVLine(disp_xpos, disp_ypos + temp, -temp, color);
|
||||||
|
} else {
|
||||||
|
DisplayDrawVLine(disp_xpos, disp_ypos, temp, color);
|
||||||
|
}
|
||||||
|
disp_ypos += temp;
|
||||||
|
break;
|
||||||
|
case 'L':
|
||||||
|
// any line to
|
||||||
|
var = atoiv(cp, &temp);
|
||||||
|
cp += var;
|
||||||
|
cp++;
|
||||||
|
var = atoiv(cp, &temp1);
|
||||||
|
cp += var;
|
||||||
|
DisplayDrawLine(disp_xpos, disp_ypos, temp, temp1, color);
|
||||||
|
disp_xpos += temp;
|
||||||
|
break;
|
||||||
|
case 'k':
|
||||||
|
// circle
|
||||||
|
var = atoiv(cp, &temp);
|
||||||
|
cp += var;
|
||||||
|
DisplayDrawCircle(disp_xpos, disp_ypos, temp, color);
|
||||||
|
break;
|
||||||
|
case 'K':
|
||||||
|
// filled circle
|
||||||
|
var = atoiv(cp, &temp);
|
||||||
|
cp += var;
|
||||||
|
DisplayDrawFilledCircle(disp_xpos, disp_ypos, temp, color);
|
||||||
|
break;
|
||||||
|
case 'r':
|
||||||
|
// rectangle
|
||||||
|
var = atoiv(cp, &temp);
|
||||||
|
cp += var;
|
||||||
|
cp++;
|
||||||
|
var = atoiv(cp, &temp1);
|
||||||
|
cp += var;
|
||||||
|
DisplayDrawRectangle(disp_xpos, disp_ypos, temp, temp1, color);
|
||||||
|
break;
|
||||||
|
case 'R':
|
||||||
|
// filled rectangle
|
||||||
|
var = atoiv(cp, &temp);
|
||||||
|
cp += var;
|
||||||
|
cp++;
|
||||||
|
var = atoiv(cp, &temp1);
|
||||||
|
cp += var;
|
||||||
|
DisplayDrawFilledRectangle(disp_xpos, disp_ypos, temp, temp1, color);
|
||||||
|
break;
|
||||||
|
case 't': {
|
||||||
|
if (dp < (linebuf + DISPLAY_BUFFER_COLS) -5) {
|
||||||
|
snprintf_P(dp, 5, PSTR("%02d" D_HOUR_MINUTE_SEPARATOR "%02d"), RtcTime.hour, RtcTime.minute);
|
||||||
|
dp += 5;
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
case 'd':
|
||||||
|
// force draw grafics buffer
|
||||||
|
DisplayDrawFrame();
|
||||||
|
break;
|
||||||
|
case 's':
|
||||||
|
case 'f':
|
||||||
|
// size or font sx
|
||||||
|
DisplaySetFontorSize(*cp&3);
|
||||||
|
cp += 1;
|
||||||
|
break;
|
||||||
|
case 'a':
|
||||||
|
// rotation angle
|
||||||
|
DisplaySetRotation(*cp&3);
|
||||||
|
cp+=1;
|
||||||
|
break;
|
||||||
|
default:
|
||||||
|
// unknown escape
|
||||||
|
snprintf_P(mqtt_data, sizeof(mqtt_data), PSTR("Unknown Escape"));
|
||||||
|
goto exit;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
exit:
|
||||||
|
// now draw buffer
|
||||||
|
if ((uint32_t)dp - (uint32_t)linebuf) {
|
||||||
|
if (!fill) { *dp = 0; }
|
||||||
|
if (col > 0 && lin > 0) {
|
||||||
|
// use col and lin
|
||||||
|
DisplayDrawStringAt(col, lin, linebuf, color, 1);
|
||||||
|
} else {
|
||||||
|
// use disp_xpos, disp_ypos
|
||||||
|
DisplayDrawStringAt(disp_xpos, disp_ypos, linebuf, color, 0);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
// draw buffer
|
||||||
|
DisplayDrawFrame();
|
||||||
|
}
|
||||||
|
|
||||||
|
void DisplayLogBufferIdxInc()
|
||||||
|
{
|
||||||
|
disp_log_buffer_idx++;
|
||||||
|
if (DISPLAY_LOG_ROWS == disp_log_buffer_idx) {
|
||||||
|
disp_log_buffer_idx = 0;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void DisplayLogBufferPtrInc()
|
||||||
|
{
|
||||||
|
disp_log_buffer_ptr++;
|
||||||
|
if (DISPLAY_LOG_ROWS == disp_log_buffer_ptr) {
|
||||||
|
disp_log_buffer_ptr = 0;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
void DisplayPrintLog()
|
||||||
|
{
|
||||||
|
disp_refresh--;
|
||||||
|
if (!disp_refresh) {
|
||||||
|
disp_refresh = Settings.display_refresh;
|
||||||
|
disp_log_buffer_active = (disp_log_buffer_idx != disp_log_buffer_ptr);
|
||||||
|
if (disp_log_buffer_active) {
|
||||||
|
XdspPrintLog(disp_log_buffer[disp_log_buffer_ptr]);
|
||||||
|
DisplayLogBufferPtrInc();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
*/
|
||||||
|
|
||||||
|
void DisplayLogBufferInit()
|
||||||
|
{
|
||||||
|
disp_log_buffer_idx = 0;
|
||||||
|
disp_log_buffer_ptr = 0;
|
||||||
|
disp_log_buffer_active = false;
|
||||||
|
disp_refresh = Settings.display_refresh;
|
||||||
|
|
||||||
|
snprintf_P(disp_log_buffer[disp_log_buffer_idx], sizeof(disp_log_buffer[disp_log_buffer_idx]), PSTR(D_VERSION " %s"), my_version);
|
||||||
|
DisplayLogBufferIdxInc();
|
||||||
|
snprintf_P(disp_log_buffer[disp_log_buffer_idx], sizeof(disp_log_buffer[disp_log_buffer_idx]), PSTR("Display mode %d"), Settings.display_mode);
|
||||||
|
DisplayLogBufferIdxInc();
|
||||||
|
}
|
||||||
|
|
||||||
|
/*********************************************************************************************\
|
||||||
|
* Sensors
|
||||||
|
\*********************************************************************************************/
|
||||||
|
|
||||||
|
enum SensorQuantity {
|
||||||
|
JSON_TEMPERATURE,
|
||||||
|
JSON_HUMIDITY, JSON_LIGHT, JSON_NOISE, JSON_AIRQUALITY,
|
||||||
|
JSON_PRESSURE, JSON_PRESSUREATSEALEVEL,
|
||||||
|
JSON_ILLUMINANCE,
|
||||||
|
JSON_GAS,
|
||||||
|
JSON_YESTERDAY, JSON_TOTAL, JSON_TODAY,
|
||||||
|
JSON_PERIOD,
|
||||||
|
JSON_POWERFACTOR, JSON_COUNTER, JSON_ANALOG_INPUT, JSON_UV_LEVEL,
|
||||||
|
JSON_CURRENT,
|
||||||
|
JSON_VOLTAGE,
|
||||||
|
JSON_POWERUSAGE,
|
||||||
|
JSON_CO2 };
|
||||||
|
const char kSensorQuantity[] PROGMEM =
|
||||||
|
D_JSON_TEMPERATURE "|" // degrees
|
||||||
|
D_JSON_HUMIDITY "|" D_JSON_LIGHT "|" D_JSON_NOISE "|" D_JSON_AIRQUALITY "|" // percentage
|
||||||
|
D_JSON_PRESSURE "|" D_JSON_PRESSUREATSEALEVEL "|" // hPa
|
||||||
|
D_JSON_ILLUMINANCE "|" // lx
|
||||||
|
D_JSON_GAS "|" // kOhm
|
||||||
|
D_JSON_YESTERDAY "|" D_JSON_TOTAL "|" D_JSON_TODAY "|" // kWh
|
||||||
|
D_JSON_PERIOD "|" // Wh
|
||||||
|
D_JSON_POWERFACTOR "|" D_JSON_COUNTER "|" D_JSON_ANALOG_INPUT "|" D_JSON_UV_LEVEL "|" // No unit
|
||||||
|
D_JSON_CURRENT "|" // Ampere
|
||||||
|
D_JSON_VOLTAGE "|" // Volt
|
||||||
|
D_JSON_POWERUSAGE "|" // Watt
|
||||||
|
D_JSON_CO2 ; // ppm
|
||||||
|
|
||||||
|
void DisplayJsonValue(const char *topic, const char* device, const char* mkey, const char* value)
|
||||||
|
{
|
||||||
|
char quantity[TOPSZ];
|
||||||
|
char spaces[Settings.display_cols[0]];
|
||||||
|
char source[Settings.display_cols[0] - Settings.display_cols[1]];
|
||||||
|
char svalue[Settings.display_cols[1] +1];
|
||||||
|
|
||||||
|
ShowFreeMem(PSTR("DisplayJsonValue"));
|
||||||
|
|
||||||
|
memset(spaces, 0x20, sizeof(spaces));
|
||||||
|
spaces[sizeof(spaces) -1] = '\0';
|
||||||
|
// snprintf_P(source, sizeof(source), PSTR("%s/%s%s"), topic, mkey, (DISP_MATRIX == Settings.display_model) ? "" : spaces); // pow1/Voltage
|
||||||
|
snprintf_P(source, sizeof(source), PSTR("%s/%s%s"), topic, mkey, spaces); // pow1/Voltage
|
||||||
|
|
||||||
|
int quantity_code = GetCommandCode(quantity, sizeof(quantity), mkey, kSensorQuantity);
|
||||||
|
if ((-1 == quantity_code) || !strcmp_P(mkey, S_RSLT_POWER)) { // Ok: Power, Not ok: POWER
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
if (JSON_TEMPERATURE == quantity_code) {
|
||||||
|
snprintf_P(svalue, sizeof(svalue), PSTR("%s~%s"), value, disp_temp);
|
||||||
|
}
|
||||||
|
else if ((quantity_code >= JSON_HUMIDITY) && (quantity_code <= JSON_AIRQUALITY)) {
|
||||||
|
snprintf_P(svalue, sizeof(svalue), PSTR("%s%%"), value);
|
||||||
|
}
|
||||||
|
else if ((quantity_code >= JSON_PRESSURE) && (quantity_code <= JSON_PRESSUREATSEALEVEL)) {
|
||||||
|
snprintf_P(svalue, sizeof(svalue), PSTR("%s" D_UNIT_PRESSURE), value);
|
||||||
|
}
|
||||||
|
else if (JSON_ILLUMINANCE == quantity_code) {
|
||||||
|
snprintf_P(svalue, sizeof(svalue), PSTR("%s" D_UNIT_LUX), value);
|
||||||
|
}
|
||||||
|
else if (JSON_GAS == quantity_code) {
|
||||||
|
snprintf_P(svalue, sizeof(svalue), PSTR("%s" D_UNIT_KILOOHM), value);
|
||||||
|
}
|
||||||
|
else if ((quantity_code >= JSON_YESTERDAY) && (quantity_code <= JSON_TODAY)) {
|
||||||
|
snprintf_P(svalue, sizeof(svalue), PSTR("%s" D_UNIT_KILOWATTHOUR), value);
|
||||||
|
}
|
||||||
|
else if (JSON_PERIOD == quantity_code) {
|
||||||
|
snprintf_P(svalue, sizeof(svalue), PSTR("%s" D_UNIT_WATTHOUR), value);
|
||||||
|
}
|
||||||
|
else if ((quantity_code >= JSON_POWERFACTOR) && (quantity_code <= JSON_UV_LEVEL)) {
|
||||||
|
snprintf_P(svalue, sizeof(svalue), PSTR("%s"), value);
|
||||||
|
}
|
||||||
|
else if (JSON_CURRENT == quantity_code) {
|
||||||
|
snprintf_P(svalue, sizeof(svalue), PSTR("%s" D_UNIT_AMPERE), value);
|
||||||
|
}
|
||||||
|
else if (JSON_VOLTAGE == quantity_code) {
|
||||||
|
snprintf_P(svalue, sizeof(svalue), PSTR("%s" D_UNIT_VOLT), value);
|
||||||
|
}
|
||||||
|
else if (JSON_POWERUSAGE == quantity_code) {
|
||||||
|
snprintf_P(svalue, sizeof(svalue), PSTR("%s" D_UNIT_WATT), value);
|
||||||
|
}
|
||||||
|
else if (JSON_CO2 == quantity_code) {
|
||||||
|
snprintf_P(svalue, sizeof(svalue), PSTR("%s" D_UNIT_PARTS_PER_MILLION), value);
|
||||||
|
}
|
||||||
|
snprintf_P(disp_log_buffer[disp_log_buffer_idx], sizeof(disp_log_buffer[disp_log_buffer_idx]), PSTR("%s %s"), source, svalue);
|
||||||
|
|
||||||
|
// snprintf_P(log_data, sizeof(log_data), PSTR(D_LOG_DEBUG "mkey [%s], source [%s], value [%s], quantity_code %d, log_buffer [%s]"), mkey, source, value, quantity_code, disp_log_buffer[disp_log_buffer_idx]);
|
||||||
|
// AddLog(LOG_LEVEL_DEBUG);
|
||||||
|
|
||||||
|
DisplayLogBufferIdxInc();
|
||||||
|
}
|
||||||
|
|
||||||
|
void DisplayAnalyzeJson(char *topic, char *json)
|
||||||
|
{
|
||||||
|
// //tele/pow2/STATE {"Time":"2017-09-20T11:53:03", "Uptime":10, "Vcc":3.123, "POWER":"ON", "Wifi":{"AP":2, "SSId":"indebuurt2", "RSSI":68, "APMac":"00:22:6B:FE:8E:20"}}
|
||||||
|
// //tele/pow2/ENERGY {"Time":"2017-09-20T11:53:03", "Total":6.522, "Yesterday":0.150, "Today":0.073, "Period":0.5, "Power":12.1, "Factor":0.56, "Voltage":210.1, "Current":0.102}
|
||||||
|
|
||||||
|
// tele/pow1/SENSOR = {"Time":"2018-01-02T17:13:17","ENERGY":{"Total":13.091,"Yesterday":0.060,"Today":0.046,"Period":0.2,"Power":9.8,"Factor":0.49,"Voltage":206.8,"Current":0.096}}
|
||||||
|
// tele/dual/STATE {"Time":"2017-09-20T11:53:03","Uptime":25,"Vcc":3.178,"POWER1":"OFF","POWER2":"OFF","Wifi":{"AP":2,"SSId":"indebuurt2","RSSI":100,"APMac":"00:22:6B:FE:8E:20"}}
|
||||||
|
// tele/sc/SENSOR {"Time":"2017-09-20T11:53:09","Temperature":24.0,"Humidity":16.0,"Light":30,"Noise":20,"AirQuality":100,"TempUnit":"C"}
|
||||||
|
// tele/rf1/SENSOR {"Time":"2017-09-20T11:53:23","BH1750":{"Illuminance":57}}
|
||||||
|
// tele/wemos5/SENSOR {"Time":"2017-09-20T11:53:53","SHT1X":{"Temperature":20.1,"Humidity":58.9},"HTU21":{"Temperature":20.7,"Humidity":58.5},"BMP280":{"Temperature":21.6,"Pressure":1020.3},"TempUnit":"C"}
|
||||||
|
// tele/th1/SENSOR {"Time":"2017-09-20T11:54:48","DS18B20":{"Temperature":49.7},"TempUnit":"C"}
|
||||||
|
|
||||||
|
const char *tempunit;
|
||||||
|
|
||||||
|
// char jsonStr[MESSZ];
|
||||||
|
// strlcpy(jsonStr, json, sizeof(jsonStr)); // Save original before destruction by JsonObject
|
||||||
|
String jsonStr = json; // Move from stack to heap to fix watchdogs (20180626)
|
||||||
|
|
||||||
|
StaticJsonBuffer<1024> jsonBuf;
|
||||||
|
JsonObject &root = jsonBuf.parseObject(jsonStr);
|
||||||
|
if (root.success()) {
|
||||||
|
|
||||||
|
tempunit = root[D_JSON_TEMPERATURE_UNIT];
|
||||||
|
if (tempunit) {
|
||||||
|
snprintf_P(disp_temp, sizeof(disp_temp), PSTR("%s"), tempunit);
|
||||||
|
// snprintf_P(log_data, sizeof(log_data), disp_temp);
|
||||||
|
// AddLog(LOG_LEVEL_DEBUG);
|
||||||
|
}
|
||||||
|
|
||||||
|
for (JsonObject::iterator it = root.begin(); it != root.end(); ++it) {
|
||||||
|
JsonVariant value = it->value;
|
||||||
|
if (value.is<JsonObject>()) {
|
||||||
|
JsonObject& Object2 = value;
|
||||||
|
for (JsonObject::iterator it2 = Object2.begin(); it2 != Object2.end(); ++it2) {
|
||||||
|
JsonVariant value2 = it2->value;
|
||||||
|
if (value2.is<JsonObject>()) {
|
||||||
|
JsonObject& Object3 = value2;
|
||||||
|
for (JsonObject::iterator it3 = Object3.begin(); it3 != Object3.end(); ++it3) {
|
||||||
|
DisplayJsonValue(topic, it->key, it3->key, it3->value.as<const char*>()); // Sensor 56%
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
DisplayJsonValue(topic, it->key, it2->key, it2->value.as<const char*>()); // Sensor 56%
|
||||||
|
}
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
DisplayJsonValue(topic, it->key, it->key, it->value.as<const char*>()); // Topic 56%
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/*********************************************************************************************\
|
||||||
|
* Public
|
||||||
|
\*********************************************************************************************/
|
||||||
|
|
||||||
|
void DisplayInitDriver()
|
||||||
|
{
|
||||||
|
XdspCall(FUNC_DISPLAY_INIT_DRIVER);
|
||||||
|
|
||||||
|
// snprintf_P(log_data, sizeof(log_data), PSTR(D_LOG_DEBUG "Display model %d"), Settings.display_model);
|
||||||
|
// AddLog(LOG_LEVEL_DEBUG);
|
||||||
|
|
||||||
|
if (Settings.display_model) {
|
||||||
|
devices_present++;
|
||||||
|
disp_device = devices_present;
|
||||||
|
snprintf_P(disp_temp, sizeof(disp_temp), PSTR("%c"), TempUnit());
|
||||||
|
|
||||||
|
DisplayLogBufferInit();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void DisplaySetPower()
|
||||||
|
{
|
||||||
|
disp_power = bitRead(XdrvMailbox.index, disp_device -1);
|
||||||
|
if (Settings.display_model) {
|
||||||
|
XdspCall(FUNC_DISPLAY_POWER);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void DisplayMqttSubscribe()
|
||||||
|
{
|
||||||
|
/* Subscribe to tele messages only
|
||||||
|
* Supports the following FullTopic formats
|
||||||
|
* - %prefix%/%topic%
|
||||||
|
* - home/%prefix%/%topic%
|
||||||
|
* - home/level2/%prefix%/%topic% etc.
|
||||||
|
*/
|
||||||
|
// if (Settings.display_mode &0x04) {
|
||||||
|
if (Settings.display_model) {
|
||||||
|
|
||||||
|
char stopic[TOPSZ];
|
||||||
|
char ntopic[TOPSZ];
|
||||||
|
|
||||||
|
ntopic[0] = '\0';
|
||||||
|
strlcpy(stopic, Settings.mqtt_fulltopic, sizeof(stopic));
|
||||||
|
char *tp = strtok(stopic, "/");
|
||||||
|
while (tp != NULL) {
|
||||||
|
if (!strcmp_P(tp, PSTR(MQTT_TOKEN_PREFIX))) {
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
strncat_P(ntopic, PSTR("+/"), sizeof(ntopic)); // Add single-level wildcards
|
||||||
|
tp = strtok(NULL, "/");
|
||||||
|
}
|
||||||
|
strncat(ntopic, Settings.mqtt_prefix[2], sizeof(ntopic)); // Subscribe to tele messages
|
||||||
|
strncat_P(ntopic, PSTR("/#"), sizeof(ntopic)); // Add multi-level wildcard
|
||||||
|
MqttSubscribe(ntopic);
|
||||||
|
disp_subscribed = 1;
|
||||||
|
} else {
|
||||||
|
disp_subscribed = 0;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
boolean DisplayMqttData()
|
||||||
|
{
|
||||||
|
if (disp_subscribed) {
|
||||||
|
char stopic[TOPSZ];
|
||||||
|
|
||||||
|
snprintf_P(stopic, sizeof(stopic) , PSTR("%s/"), Settings.mqtt_prefix[2]); // tele/
|
||||||
|
char *tp = strstr(XdrvMailbox.topic, stopic);
|
||||||
|
if (tp) { // tele/sonoff/SENSOR
|
||||||
|
if (Settings.display_mode &0x04) {
|
||||||
|
tp = tp + strlen(stopic); // sonoff/SENSOR
|
||||||
|
char *topic = strtok(tp, "/"); // sonoff
|
||||||
|
DisplayAnalyzeJson(topic, XdrvMailbox.data);
|
||||||
|
}
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
void DisplayLocalSensor()
|
||||||
|
{
|
||||||
|
if ((Settings.display_mode &0x02) && (0 == tele_period)) {
|
||||||
|
DisplayAnalyzeJson(mqtt_topic, mqtt_data);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/*********************************************************************************************\
|
||||||
|
* Commands
|
||||||
|
\*********************************************************************************************/
|
||||||
|
|
||||||
|
boolean DisplayCommand()
|
||||||
|
{
|
||||||
|
char command [CMDSZ];
|
||||||
|
boolean serviced = true;
|
||||||
|
uint8_t disp_len = strlen(D_CMND_DISPLAY); // Prep for string length change
|
||||||
|
|
||||||
|
if (!strncasecmp_P(XdrvMailbox.topic, PSTR(D_CMND_DISPLAY), disp_len)) { // Prefix
|
||||||
|
int command_code = GetCommandCode(command, sizeof(command), XdrvMailbox.topic +disp_len, kDisplayCommands);
|
||||||
|
if (-1 == command_code) {
|
||||||
|
serviced = false; // Unknown command
|
||||||
|
}
|
||||||
|
else if (CMND_DISP_MODEL == command_code) {
|
||||||
|
if ((XdrvMailbox.payload >= 0) && (XdrvMailbox.payload < DISPLAY_MAX_DRIVERS)) {
|
||||||
|
uint8_t last_display_model = Settings.display_model;
|
||||||
|
Settings.display_model = XdrvMailbox.payload;
|
||||||
|
if (XdspCall(FUNC_DISPLAY_MODEL)) {
|
||||||
|
restart_flag = 2; // Restart to re-init interface and add/Remove MQTT subscribe
|
||||||
|
} else {
|
||||||
|
Settings.display_model = last_display_model;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
snprintf_P(mqtt_data, sizeof(mqtt_data), S_JSON_DISPLAY_COMMAND_NVALUE, command, Settings.display_model);
|
||||||
|
}
|
||||||
|
else if (CMND_DISP_MODE == command_code) {
|
||||||
|
/*
|
||||||
|
* Matrix LCD / Oled TFT
|
||||||
|
* 0 = Text Text Text
|
||||||
|
* 1 = Text up and time Time
|
||||||
|
* 2 = Date Local sensors Local sensors
|
||||||
|
* 3 = Day Local sensors and time Local sensors and time
|
||||||
|
* 4 = Mqtt left and time Mqtt (incl local) sensors Mqtt (incl local) sensors
|
||||||
|
* 5 = Mqtt up and time Mqtt (incl local) sensors and time Mqtt (incl local) sensors and time
|
||||||
|
*/
|
||||||
|
if ((XdrvMailbox.payload >= 0) && (XdrvMailbox.payload <= 5)) {
|
||||||
|
uint8_t last_display_mode = Settings.display_mode;
|
||||||
|
Settings.display_mode = XdrvMailbox.payload;
|
||||||
|
if (!disp_subscribed) {
|
||||||
|
restart_flag = 2; // Restart to Add/Remove MQTT subscribe
|
||||||
|
} else {
|
||||||
|
if (last_display_mode && !Settings.display_mode) { // Switch to mode 0
|
||||||
|
DisplayInit(DISPLAY_INIT_MODE);
|
||||||
|
DisplayClear();
|
||||||
|
}
|
||||||
|
if (!last_display_mode && Settings.display_mode) { // Switch to non mode 0
|
||||||
|
DisplayInit(DISPLAY_INIT_MODE);
|
||||||
|
DisplayLogBufferInit();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
snprintf_P(mqtt_data, sizeof(mqtt_data), S_JSON_DISPLAY_COMMAND_NVALUE, command, Settings.display_mode);
|
||||||
|
}
|
||||||
|
else if (CMND_DISP_REFRESH == command_code) {
|
||||||
|
if ((XdrvMailbox.payload >= 1) && (XdrvMailbox.payload <= 7)) {
|
||||||
|
Settings.display_refresh = XdrvMailbox.payload;
|
||||||
|
}
|
||||||
|
snprintf_P(mqtt_data, sizeof(mqtt_data), S_JSON_DISPLAY_COMMAND_NVALUE, command, Settings.display_refresh);
|
||||||
|
}
|
||||||
|
else if ((CMND_DISP_COLS == command_code) && (XdrvMailbox.index > 0) && (XdrvMailbox.index <= 2)) {
|
||||||
|
if ((XdrvMailbox.payload > 0) && (XdrvMailbox.payload <= DISPLAY_SCREEN_COLS)) {
|
||||||
|
Settings.display_cols[XdrvMailbox.index -1] = XdrvMailbox.payload;
|
||||||
|
}
|
||||||
|
snprintf_P(mqtt_data, sizeof(mqtt_data), S_JSON_DISPLAY_COMMAND_INDEX_NVALUE, command, XdrvMailbox.index, Settings.display_cols[XdrvMailbox.index -1]);
|
||||||
|
}
|
||||||
|
else if (CMND_DISP_DIMMER == command_code) {
|
||||||
|
if ((XdrvMailbox.payload >= 0) && (XdrvMailbox.payload <= 100)) {
|
||||||
|
Settings.display_dimmer = ((XdrvMailbox.payload +1) * 100) / 666; // Correction for Domoticz (0 - 15)
|
||||||
|
if (Settings.display_dimmer && !(disp_power)) {
|
||||||
|
ExecuteCommandPower(disp_device, POWER_ON, SRC_DISPLAY);
|
||||||
|
}
|
||||||
|
else if (!Settings.display_dimmer && disp_power) {
|
||||||
|
ExecuteCommandPower(disp_device, POWER_OFF, SRC_DISPLAY);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
snprintf_P(mqtt_data, sizeof(mqtt_data), S_JSON_DISPLAY_COMMAND_NVALUE, command, Settings.display_dimmer);
|
||||||
|
}
|
||||||
|
else if (CMND_DISP_ROWS == command_code) {
|
||||||
|
if ((XdrvMailbox.payload > 0) && (XdrvMailbox.payload <= DISPLAY_SCREEN_ROWS)) {
|
||||||
|
Settings.display_rows = XdrvMailbox.payload;
|
||||||
|
}
|
||||||
|
snprintf_P(mqtt_data, sizeof(mqtt_data), S_JSON_DISPLAY_COMMAND_NVALUE, command, Settings.display_rows);
|
||||||
|
}
|
||||||
|
else if (CMND_DISP_SIZE == command_code) {
|
||||||
|
if ((XdrvMailbox.payload > 0) && (XdrvMailbox.payload <= 4)) {
|
||||||
|
Settings.display_size = XdrvMailbox.payload;
|
||||||
|
}
|
||||||
|
snprintf_P(mqtt_data, sizeof(mqtt_data), S_JSON_DISPLAY_COMMAND_NVALUE, command, Settings.display_size);
|
||||||
|
}
|
||||||
|
else if (CMND_DISP_TEXT == command_code) {
|
||||||
|
mqtt_data[0] = '\0';
|
||||||
|
if (disp_device && XdrvMailbox.data_len > 0) {
|
||||||
|
if (!Settings.display_mode) {
|
||||||
|
DisplayText();
|
||||||
|
} else {
|
||||||
|
strlcpy(disp_log_buffer[disp_log_buffer_idx], XdrvMailbox.data, sizeof(disp_log_buffer[disp_log_buffer_idx]));
|
||||||
|
DisplayLogBufferIdxInc();
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
snprintf_P(mqtt_data, sizeof(mqtt_data), PSTR("No Text"));
|
||||||
|
}
|
||||||
|
if (mqtt_data[0] == '\0') {
|
||||||
|
snprintf_P(mqtt_data, sizeof(mqtt_data), S_JSON_DISPLAY_COMMAND_VALUE, command, XdrvMailbox.data);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else if ((CMND_DISP_ADDRESS == command_code) && (XdrvMailbox.index > 0) && (XdrvMailbox.index <= 8)) {
|
||||||
|
if ((XdrvMailbox.payload >= 0) && (XdrvMailbox.payload <= 255)) {
|
||||||
|
Settings.display_address[XdrvMailbox.index -1] = XdrvMailbox.payload;
|
||||||
|
}
|
||||||
|
snprintf_P(mqtt_data, sizeof(mqtt_data), S_JSON_DISPLAY_COMMAND_INDEX_NVALUE, command, XdrvMailbox.index, Settings.display_address[XdrvMailbox.index -1]);
|
||||||
|
}
|
||||||
|
else serviced = false; // Unknown command
|
||||||
|
}
|
||||||
|
else serviced = false; // Unknown command
|
||||||
|
|
||||||
|
return serviced;
|
||||||
|
}
|
||||||
|
|
||||||
|
/*********************************************************************************************\
|
||||||
|
* Interface
|
||||||
|
\*********************************************************************************************/
|
||||||
|
|
||||||
|
#define XDRV_98
|
||||||
|
|
||||||
|
boolean Xdrv98(byte function)
|
||||||
|
{
|
||||||
|
boolean result = false;
|
||||||
|
|
||||||
|
if ((i2c_flg || spi_flg) && XdspPresent()) {
|
||||||
|
switch (function) {
|
||||||
|
case FUNC_PRE_INIT:
|
||||||
|
DisplayInitDriver();
|
||||||
|
break;
|
||||||
|
case FUNC_EVERY_50_MSECOND:
|
||||||
|
if (Settings.display_model && Settings.display_mode) { XdspCall(FUNC_DISPLAY_EVERY_50_MSECOND); }
|
||||||
|
break;
|
||||||
|
case FUNC_EVERY_SECOND:
|
||||||
|
if (Settings.display_model && Settings.display_mode) { XdspCall(FUNC_DISPLAY_EVERY_SECOND); }
|
||||||
|
break;
|
||||||
|
case FUNC_COMMAND:
|
||||||
|
result = DisplayCommand();
|
||||||
|
break;
|
||||||
|
case FUNC_MQTT_SUBSCRIBE:
|
||||||
|
DisplayMqttSubscribe();
|
||||||
|
break;
|
||||||
|
case FUNC_MQTT_DATA:
|
||||||
|
result = DisplayMqttData();
|
||||||
|
break;
|
||||||
|
case FUNC_SET_POWER:
|
||||||
|
DisplaySetPower();
|
||||||
|
break;
|
||||||
|
case FUNC_SHOW_SENSOR:
|
||||||
|
DisplayLocalSensor();
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return result;
|
||||||
|
}
|
||||||
|
|
||||||
|
#endif // USE_DISPLAY
|
||||||
|
#endif // USE_I2C or USE_SPI
|
|
@ -0,0 +1,259 @@
|
||||||
|
/*
|
||||||
|
xdsp_01_lcd.ino - Display LCD support for Sonoff-Tasmota
|
||||||
|
|
||||||
|
Copyright (C) 2018 Theo Arends and Adafruit
|
||||||
|
|
||||||
|
This program is free software: you can redistribute it and/or modify
|
||||||
|
it under the terms of the GNU General Public License as published by
|
||||||
|
the Free Software Foundation, either version 3 of the License, or
|
||||||
|
(at your option) any later version.
|
||||||
|
|
||||||
|
This program is distributed in the hope that it will be useful,
|
||||||
|
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||||
|
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||||
|
GNU General Public License for more details.
|
||||||
|
|
||||||
|
You should have received a copy of the GNU General Public License
|
||||||
|
along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||||
|
*/
|
||||||
|
|
||||||
|
#ifdef USE_I2C
|
||||||
|
#ifdef USE_DISPLAY
|
||||||
|
#ifdef USE_DISPLAY_LCD
|
||||||
|
|
||||||
|
#define XDSP_01 1
|
||||||
|
|
||||||
|
#define LCD_ADDRESS1 0x27 // LCD I2C address option 1
|
||||||
|
#define LCD_ADDRESS2 0x3F // LCD I2C address option 2
|
||||||
|
|
||||||
|
#define LCD_BUFFER_COLS 40 // Max number of columns in display shadow buffer
|
||||||
|
#define LCD_BUFFER_ROWS 8 // Max number of lines in display shadow buffer
|
||||||
|
|
||||||
|
#include <Wire.h>
|
||||||
|
#include <LiquidCrystal_I2C.h>
|
||||||
|
|
||||||
|
LiquidCrystal_I2C *lcd;
|
||||||
|
|
||||||
|
char lcd_screen_buffer[LCD_BUFFER_ROWS][LCD_BUFFER_COLS +1];
|
||||||
|
|
||||||
|
void LcdInitFull()
|
||||||
|
{
|
||||||
|
lcd->init();
|
||||||
|
lcd->clear();
|
||||||
|
memset(lcd_screen_buffer[Settings.display_rows -1], 0x20, Settings.display_cols[0]);
|
||||||
|
lcd_screen_buffer[Settings.display_rows -1][Settings.display_cols[0]] = 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
void LcdDrawStringAt()
|
||||||
|
{
|
||||||
|
lcd->setCursor(dsp_x, dsp_y);
|
||||||
|
lcd->print(dsp_str);
|
||||||
|
}
|
||||||
|
|
||||||
|
void LcdDisplayOnOff(uint8_t on)
|
||||||
|
{
|
||||||
|
if (on) {
|
||||||
|
lcd->backlight();
|
||||||
|
} else {
|
||||||
|
lcd->noBacklight();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/*********************************************************************************************/
|
||||||
|
|
||||||
|
void LcdCenter(byte row, char* txt)
|
||||||
|
{
|
||||||
|
int offset;
|
||||||
|
int len;
|
||||||
|
char line[Settings.display_cols[0] +2];
|
||||||
|
|
||||||
|
memset(line, 0x20, Settings.display_cols[0]);
|
||||||
|
line[Settings.display_cols[0]] = 0;
|
||||||
|
len = strlen(txt);
|
||||||
|
offset = (len < Settings.display_cols[0]) ? offset = (Settings.display_cols[0] - len) / 2 : 0;
|
||||||
|
strncpy(line +offset, txt, len);
|
||||||
|
lcd->setCursor(0, row);
|
||||||
|
lcd->print(line);
|
||||||
|
}
|
||||||
|
|
||||||
|
/*********************************************************************************************/
|
||||||
|
|
||||||
|
void LcdInitMode()
|
||||||
|
{
|
||||||
|
lcd->init();
|
||||||
|
lcd->clear();
|
||||||
|
memset(lcd_screen_buffer[Settings.display_rows -1], 0x20, Settings.display_cols[0]);
|
||||||
|
lcd_screen_buffer[Settings.display_rows -1][Settings.display_cols[0]] = 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
void LcdInit(uint8_t mode)
|
||||||
|
{
|
||||||
|
switch(mode) {
|
||||||
|
case DISPLAY_INIT_MODE:
|
||||||
|
LcdInitMode();
|
||||||
|
break;
|
||||||
|
case DISPLAY_INIT_PARTIAL:
|
||||||
|
case DISPLAY_INIT_FULL:
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void LcdInitDriver()
|
||||||
|
{
|
||||||
|
if (!Settings.display_model) {
|
||||||
|
if (I2cDevice(LCD_ADDRESS1)) {
|
||||||
|
Settings.display_address[0] = LCD_ADDRESS1;
|
||||||
|
Settings.display_model = XDSP_01;
|
||||||
|
}
|
||||||
|
else if (I2cDevice(LCD_ADDRESS2)) {
|
||||||
|
Settings.display_address[0] = LCD_ADDRESS2;
|
||||||
|
Settings.display_model = XDSP_01;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if (XDSP_01 == Settings.display_model) {
|
||||||
|
lcd = new LiquidCrystal_I2C(Settings.display_address[0], Settings.display_cols[0], Settings.display_rows);
|
||||||
|
|
||||||
|
LcdInitMode();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void LcdPrintLogLine()
|
||||||
|
{
|
||||||
|
uint8_t last_row = Settings.display_rows -1;
|
||||||
|
|
||||||
|
for (byte i = 0; i < last_row; i++) {
|
||||||
|
strlcpy(lcd_screen_buffer[i], lcd_screen_buffer[i +1], sizeof(lcd_screen_buffer[i]));
|
||||||
|
lcd->setCursor(0, i); // Col 0, Row i
|
||||||
|
lcd->print(lcd_screen_buffer[i +1]);
|
||||||
|
}
|
||||||
|
|
||||||
|
char *pch = strchr(disp_log_buffer[disp_log_buffer_ptr],'~'); // = 0x7E (~) Replace degrees character (276 octal)
|
||||||
|
if (pch != NULL) {
|
||||||
|
disp_log_buffer[disp_log_buffer_ptr][pch - disp_log_buffer[disp_log_buffer_ptr]] = '\337'; // = 0xDF
|
||||||
|
}
|
||||||
|
strlcpy(lcd_screen_buffer[last_row], disp_log_buffer[disp_log_buffer_ptr], sizeof(lcd_screen_buffer[last_row]));
|
||||||
|
|
||||||
|
// Fill with spaces
|
||||||
|
byte len = sizeof(lcd_screen_buffer[last_row]) - strlen(lcd_screen_buffer[last_row]);
|
||||||
|
if (len) {
|
||||||
|
memset(lcd_screen_buffer[last_row] + strlen(lcd_screen_buffer[last_row]), 0x20, len);
|
||||||
|
lcd_screen_buffer[last_row][sizeof(lcd_screen_buffer[last_row])-1] = 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
snprintf_P(log_data, sizeof(log_data), PSTR(D_LOG_DEBUG "[%s]"), lcd_screen_buffer[last_row]);
|
||||||
|
AddLog(LOG_LEVEL_DEBUG);
|
||||||
|
|
||||||
|
lcd->setCursor(0, last_row);
|
||||||
|
lcd->print(lcd_screen_buffer[last_row]);
|
||||||
|
}
|
||||||
|
|
||||||
|
void LcdPrintLog()
|
||||||
|
{
|
||||||
|
disp_refresh--;
|
||||||
|
if (!disp_refresh) {
|
||||||
|
disp_refresh = Settings.display_refresh;
|
||||||
|
disp_log_buffer_active = (disp_log_buffer_idx != disp_log_buffer_ptr);
|
||||||
|
if (disp_log_buffer_active) {
|
||||||
|
LcdPrintLogLine();
|
||||||
|
DisplayLogBufferPtrInc();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void LcdTime()
|
||||||
|
{
|
||||||
|
char line[Settings.display_cols[0] +1];
|
||||||
|
|
||||||
|
snprintf_P(line, sizeof(line), PSTR("%02d" D_HOUR_MINUTE_SEPARATOR "%02d" D_MINUTE_SECOND_SEPARATOR "%02d"), RtcTime.hour, RtcTime.minute, RtcTime.second);
|
||||||
|
LcdCenter(0, line);
|
||||||
|
snprintf_P(line, sizeof(line), PSTR("%02d" D_MONTH_DAY_SEPARATOR "%02d" D_YEAR_MONTH_SEPARATOR "%04d"), RtcTime.day_of_month, RtcTime.month, RtcTime.year);
|
||||||
|
LcdCenter(1, line);
|
||||||
|
}
|
||||||
|
|
||||||
|
void LcdRefresh() // Every second
|
||||||
|
{
|
||||||
|
if (Settings.display_mode) { // Mode 0 is User text
|
||||||
|
switch (Settings.display_mode) {
|
||||||
|
case 1: // Time
|
||||||
|
LcdTime();
|
||||||
|
break;
|
||||||
|
case 2: // Local
|
||||||
|
case 4: // Mqtt
|
||||||
|
LcdPrintLog();
|
||||||
|
break;
|
||||||
|
case 3: // Local
|
||||||
|
case 5: { // Mqtt
|
||||||
|
LcdPrintLog();
|
||||||
|
if (!disp_log_buffer_active) {
|
||||||
|
LcdTime();
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/*********************************************************************************************\
|
||||||
|
* Interface
|
||||||
|
\*********************************************************************************************/
|
||||||
|
|
||||||
|
boolean Xdsp01(byte function)
|
||||||
|
{
|
||||||
|
boolean result = false;
|
||||||
|
|
||||||
|
if (i2c_flg) {
|
||||||
|
if (FUNC_DISPLAY_INIT_DRIVER == function) {
|
||||||
|
LcdInitDriver();
|
||||||
|
}
|
||||||
|
else if (XDSP_01 == Settings.display_model) {
|
||||||
|
switch (function) {
|
||||||
|
case FUNC_DISPLAY_MODEL:
|
||||||
|
result = true;
|
||||||
|
break;
|
||||||
|
case FUNC_DISPLAY_INIT:
|
||||||
|
LcdInit(dsp_init);
|
||||||
|
break;
|
||||||
|
case FUNC_DISPLAY_EVERY_SECOND:
|
||||||
|
LcdRefresh();
|
||||||
|
break;
|
||||||
|
case FUNC_DISPLAY_POWER:
|
||||||
|
LcdDisplayOnOff(disp_power);
|
||||||
|
break;
|
||||||
|
|
||||||
|
case FUNC_DISPLAY_CLEAR:
|
||||||
|
lcd->clear();
|
||||||
|
break;
|
||||||
|
// case FUNC_DISPLAY_DRAW_HLINE:
|
||||||
|
// break;
|
||||||
|
// case FUNC_DISPLAY_DRAW_VLINE:
|
||||||
|
// break;
|
||||||
|
// case FUNC_DISPLAY_DRAW_CIRCLE:
|
||||||
|
// break;
|
||||||
|
// case FUNC_DISPLAY_FILL_CIRCLE:
|
||||||
|
// break;
|
||||||
|
// case FUNC_DISPLAY_DRAW_RECTANGLE:
|
||||||
|
// break;
|
||||||
|
// case FUNC_DISPLAY_FILL_RECTANGLE:
|
||||||
|
// break;
|
||||||
|
// case FUNC_DISPLAY_DRAW_FRAME:
|
||||||
|
// break;
|
||||||
|
// case FUNC_DISPLAY_FONT_SIZE:
|
||||||
|
// break;
|
||||||
|
case FUNC_DISPLAY_DRAW_STRING:
|
||||||
|
LcdDrawStringAt();
|
||||||
|
break;
|
||||||
|
case FUNC_DISPLAY_ONOFF:
|
||||||
|
LcdDisplayOnOff(dsp_on);
|
||||||
|
break;
|
||||||
|
// case FUNC_DISPLAY_ROTATION:
|
||||||
|
// break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return result;
|
||||||
|
}
|
||||||
|
|
||||||
|
#endif // USE_DISPLAY_LCD
|
||||||
|
#endif // USE_DISPLAY
|
||||||
|
#endif // USE_I2C
|
|
@ -0,0 +1,291 @@
|
||||||
|
/*
|
||||||
|
xdsp_02_ssd1306.ino - Display Oled ssd1306 support for Sonoff-Tasmota
|
||||||
|
|
||||||
|
Copyright (C) 2018 Theo Arends and Adafruit
|
||||||
|
|
||||||
|
This program is free software: you can redistribute it and/or modify
|
||||||
|
it under the terms of the GNU General Public License as published by
|
||||||
|
the Free Software Foundation, either version 3 of the License, or
|
||||||
|
(at your option) any later version.
|
||||||
|
|
||||||
|
This program is distributed in the hope that it will be useful,
|
||||||
|
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||||
|
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||||
|
GNU General Public License for more details.
|
||||||
|
|
||||||
|
You should have received a copy of the GNU General Public License
|
||||||
|
along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||||
|
*/
|
||||||
|
|
||||||
|
#ifdef USE_I2C
|
||||||
|
#ifdef USE_DISPLAY
|
||||||
|
#ifdef USE_DISPLAY_SSD1306
|
||||||
|
|
||||||
|
#define XDSP_02 2
|
||||||
|
|
||||||
|
#define OLED_ADDRESS1 0x3C // Oled 128x32 I2C address
|
||||||
|
#define OLED_ADDRESS2 0x3D // Oled 128x64 I2C address
|
||||||
|
|
||||||
|
#define OLED_BUFFER_COLS 40 // Max number of columns in display shadow buffer
|
||||||
|
#define OLED_BUFFER_ROWS 8 // Max number of lines in display shadow buffer
|
||||||
|
|
||||||
|
#define OLED_FONT_WIDTH 6
|
||||||
|
#define OLED_FONT_HEIGTH 8
|
||||||
|
|
||||||
|
#include <Wire.h>
|
||||||
|
#include <Adafruit_GFX.h>
|
||||||
|
#include <Adafruit_SSD1306.h>
|
||||||
|
|
||||||
|
Adafruit_SSD1306 *oled;
|
||||||
|
|
||||||
|
char oled_screen_buffer[OLED_BUFFER_ROWS][OLED_BUFFER_COLS +1];
|
||||||
|
|
||||||
|
uint8_t ssd1306_font_x = OLED_FONT_WIDTH;
|
||||||
|
uint8_t ssd1306_font_y = OLED_FONT_HEIGTH;
|
||||||
|
|
||||||
|
void Ssd1306InitFull()
|
||||||
|
{
|
||||||
|
oled->invertDisplay(false);
|
||||||
|
oled->clearDisplay();
|
||||||
|
oled->setTextWrap(false); // Allow text to run off edges
|
||||||
|
oled->cp437(true);
|
||||||
|
|
||||||
|
oled->setTextSize(Settings.display_size);
|
||||||
|
oled->setTextColor(WHITE);
|
||||||
|
oled->setCursor(0,0);
|
||||||
|
oled->display();
|
||||||
|
}
|
||||||
|
|
||||||
|
void Ssd1306Clear()
|
||||||
|
{
|
||||||
|
oled->clearDisplay();
|
||||||
|
oled->setCursor(0, 0);
|
||||||
|
oled->display();
|
||||||
|
}
|
||||||
|
|
||||||
|
void Ssd1306DrawStringAt(uint16_t x, uint16_t y, char *str, uint16_t color, uint8_t flag)
|
||||||
|
{
|
||||||
|
if (!flag) {
|
||||||
|
oled->setCursor(x, y);
|
||||||
|
} else {
|
||||||
|
oled->setCursor((x-1) * ssd1306_font_x * Settings.display_size, (y-1) * ssd1306_font_y * Settings.display_size);
|
||||||
|
}
|
||||||
|
oled->println(str);
|
||||||
|
}
|
||||||
|
|
||||||
|
void Ssd1306DisplayOnOff(uint8_t on)
|
||||||
|
{
|
||||||
|
if (on) {
|
||||||
|
oled->ssd1306_command(SSD1306_DISPLAYON);
|
||||||
|
} else {
|
||||||
|
oled->ssd1306_command(SSD1306_DISPLAYOFF);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/*********************************************************************************************/
|
||||||
|
|
||||||
|
void Ssd1306InitMode()
|
||||||
|
{
|
||||||
|
oled->invertDisplay(false);
|
||||||
|
oled->clearDisplay();
|
||||||
|
oled->setTextWrap(false); // Allow text to run off edges
|
||||||
|
oled->cp437(true);
|
||||||
|
|
||||||
|
oled->setTextSize(Settings.display_size);
|
||||||
|
oled->setTextColor(WHITE);
|
||||||
|
oled->setCursor(0,0);
|
||||||
|
oled->display();
|
||||||
|
}
|
||||||
|
|
||||||
|
void Ssd1306Init(uint8_t mode)
|
||||||
|
{
|
||||||
|
switch(mode) {
|
||||||
|
case DISPLAY_INIT_MODE:
|
||||||
|
Ssd1306InitMode();
|
||||||
|
break;
|
||||||
|
case DISPLAY_INIT_PARTIAL:
|
||||||
|
case DISPLAY_INIT_FULL:
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void Ssd1306InitDriver()
|
||||||
|
{
|
||||||
|
if (!Settings.display_model) {
|
||||||
|
if (I2cDevice(OLED_ADDRESS1)) {
|
||||||
|
Settings.display_address[0] = OLED_ADDRESS1;
|
||||||
|
Settings.display_model = XDSP_02;
|
||||||
|
}
|
||||||
|
else if (I2cDevice(OLED_ADDRESS2)) {
|
||||||
|
Settings.display_address[0] = OLED_ADDRESS2;
|
||||||
|
Settings.display_model = XDSP_02;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if (XDSP_02 == Settings.display_model) {
|
||||||
|
oled = new Adafruit_SSD1306();
|
||||||
|
oled->begin(SSD1306_SWITCHCAPVCC, Settings.display_address[0]);
|
||||||
|
|
||||||
|
Ssd1306InitMode();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void Ssd1306PrintLogLine()
|
||||||
|
{
|
||||||
|
uint8_t last_row = Settings.display_rows -1;
|
||||||
|
|
||||||
|
oled->clearDisplay();
|
||||||
|
oled->setTextSize(Settings.display_size);
|
||||||
|
oled->setCursor(0,0);
|
||||||
|
for (byte i = 0; i < last_row; i++) {
|
||||||
|
strlcpy(oled_screen_buffer[i], oled_screen_buffer[i +1], sizeof(oled_screen_buffer[i]));
|
||||||
|
oled->println(oled_screen_buffer[i]);
|
||||||
|
}
|
||||||
|
|
||||||
|
char *pch = strchr(disp_log_buffer[disp_log_buffer_ptr],'~'); // = 0x7E (~) Replace degrees character (276 octal)
|
||||||
|
if (pch != NULL) {
|
||||||
|
disp_log_buffer[disp_log_buffer_ptr][pch - disp_log_buffer[disp_log_buffer_ptr]] = '\370'; // = 0xF8
|
||||||
|
}
|
||||||
|
strlcpy(oled_screen_buffer[last_row], disp_log_buffer[disp_log_buffer_ptr], sizeof(oled_screen_buffer[last_row]));
|
||||||
|
|
||||||
|
// Fill with spaces
|
||||||
|
byte len = sizeof(oled_screen_buffer[last_row]) - strlen(oled_screen_buffer[last_row]);
|
||||||
|
if (len) {
|
||||||
|
memset(oled_screen_buffer[last_row] + strlen(oled_screen_buffer[last_row]), 0x20, len);
|
||||||
|
oled_screen_buffer[last_row][sizeof(oled_screen_buffer[last_row])-1] = 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
snprintf_P(log_data, sizeof(log_data), PSTR(D_LOG_DEBUG "[%s]"), oled_screen_buffer[last_row]);
|
||||||
|
AddLog(LOG_LEVEL_DEBUG);
|
||||||
|
|
||||||
|
oled->println(oled_screen_buffer[last_row]);
|
||||||
|
oled->display();
|
||||||
|
}
|
||||||
|
|
||||||
|
void Ssd1306PrintLog()
|
||||||
|
{
|
||||||
|
disp_refresh--;
|
||||||
|
if (!disp_refresh) {
|
||||||
|
disp_refresh = Settings.display_refresh;
|
||||||
|
disp_log_buffer_active = (disp_log_buffer_idx != disp_log_buffer_ptr);
|
||||||
|
if (disp_log_buffer_active) {
|
||||||
|
Ssd1306PrintLogLine();
|
||||||
|
DisplayLogBufferPtrInc();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void Ssd1306OnOff()
|
||||||
|
{
|
||||||
|
Ssd1306DisplayOnOff(disp_power);
|
||||||
|
oled->display();
|
||||||
|
}
|
||||||
|
|
||||||
|
void Ssd1306Time()
|
||||||
|
{
|
||||||
|
char line[12];
|
||||||
|
|
||||||
|
oled->clearDisplay();
|
||||||
|
oled->setTextSize(2);
|
||||||
|
oled->setCursor(0, 0);
|
||||||
|
snprintf_P(line, sizeof(line), PSTR(" %02d" D_HOUR_MINUTE_SEPARATOR "%02d" D_MINUTE_SECOND_SEPARATOR "%02d"), RtcTime.hour, RtcTime.minute, RtcTime.second); // [ 12:34:56 ]
|
||||||
|
oled->println(line);
|
||||||
|
snprintf_P(line, sizeof(line), PSTR("%02d" D_MONTH_DAY_SEPARATOR "%02d" D_YEAR_MONTH_SEPARATOR "%04d"), RtcTime.day_of_month, RtcTime.month, RtcTime.year); // [01-02-2018]
|
||||||
|
oled->println(line);
|
||||||
|
oled->display();
|
||||||
|
}
|
||||||
|
|
||||||
|
void Ssd1306Refresh() // Every second
|
||||||
|
{
|
||||||
|
if (Settings.display_mode) { // Mode 0 is User text
|
||||||
|
switch (Settings.display_mode) {
|
||||||
|
case 1: // Time
|
||||||
|
Ssd1306Time();
|
||||||
|
break;
|
||||||
|
case 2: // Local
|
||||||
|
case 3: // Local
|
||||||
|
case 4: // Mqtt
|
||||||
|
case 5: // Mqtt
|
||||||
|
Ssd1306PrintLog();
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/*********************************************************************************************\
|
||||||
|
* Interface
|
||||||
|
\*********************************************************************************************/
|
||||||
|
|
||||||
|
boolean Xdsp02(byte function)
|
||||||
|
{
|
||||||
|
boolean result = false;
|
||||||
|
|
||||||
|
if (i2c_flg) {
|
||||||
|
if (FUNC_DISPLAY_INIT_DRIVER == function) {
|
||||||
|
Ssd1306InitDriver();
|
||||||
|
}
|
||||||
|
else if (XDSP_02 == Settings.display_model) {
|
||||||
|
|
||||||
|
if (!dsp_color) { dsp_color = WHITE; }
|
||||||
|
|
||||||
|
switch (function) {
|
||||||
|
case FUNC_DISPLAY_MODEL:
|
||||||
|
result = true;
|
||||||
|
break;
|
||||||
|
case FUNC_DISPLAY_INIT:
|
||||||
|
Ssd1306Init(dsp_init);
|
||||||
|
break;
|
||||||
|
case FUNC_DISPLAY_EVERY_SECOND:
|
||||||
|
Ssd1306Refresh();
|
||||||
|
break;
|
||||||
|
case FUNC_DISPLAY_POWER:
|
||||||
|
Ssd1306OnOff();
|
||||||
|
break;
|
||||||
|
case FUNC_DISPLAY_CLEAR:
|
||||||
|
Ssd1306Clear();
|
||||||
|
break;
|
||||||
|
case FUNC_DISPLAY_DRAW_HLINE:
|
||||||
|
oled->writeFastHLine(dsp_x, dsp_y, dsp_len, dsp_color);
|
||||||
|
break;
|
||||||
|
case FUNC_DISPLAY_DRAW_VLINE:
|
||||||
|
oled->writeFastVLine(dsp_x, dsp_y, dsp_len, dsp_color);
|
||||||
|
break;
|
||||||
|
case FUNC_DISPLAY_DRAW_LINE:
|
||||||
|
oled->writeLine(dsp_x, dsp_y, dsp_x2, dsp_y2, dsp_color);
|
||||||
|
break;
|
||||||
|
case FUNC_DISPLAY_DRAW_CIRCLE:
|
||||||
|
oled->drawCircle(dsp_x, dsp_y, dsp_rad, dsp_color);
|
||||||
|
break;
|
||||||
|
case FUNC_DISPLAY_FILL_CIRCLE:
|
||||||
|
oled->fillCircle(dsp_x, dsp_y, dsp_rad, dsp_color);
|
||||||
|
break;
|
||||||
|
case FUNC_DISPLAY_DRAW_RECTANGLE:
|
||||||
|
oled->drawRect(dsp_x, dsp_y, dsp_x2, dsp_y2, dsp_color);
|
||||||
|
break;
|
||||||
|
case FUNC_DISPLAY_FILL_RECTANGLE:
|
||||||
|
oled->fillRect(dsp_x, dsp_y, dsp_x2, dsp_y2, dsp_color);
|
||||||
|
break;
|
||||||
|
case FUNC_DISPLAY_DRAW_FRAME:
|
||||||
|
oled->display();
|
||||||
|
break;
|
||||||
|
case FUNC_DISPLAY_FONT_SIZE:
|
||||||
|
oled->setTextSize(Settings.display_size);
|
||||||
|
break;
|
||||||
|
case FUNC_DISPLAY_DRAW_STRING:
|
||||||
|
Ssd1306DrawStringAt(dsp_x, dsp_y, dsp_str, dsp_color, dsp_flag);
|
||||||
|
break;
|
||||||
|
case FUNC_DISPLAY_ONOFF:
|
||||||
|
Ssd1306DisplayOnOff(dsp_on);
|
||||||
|
break;
|
||||||
|
case FUNC_DISPLAY_ROTATION:
|
||||||
|
oled->setRotation(dsp_rotation);
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return result;
|
||||||
|
}
|
||||||
|
|
||||||
|
#endif // USE_DISPLAY_SSD1306
|
||||||
|
#endif // USE_DISPLAY
|
||||||
|
#endif // USE_I2C
|
|
@ -0,0 +1,344 @@
|
||||||
|
/*
|
||||||
|
xdsp_03_matrix.ino - Display 8x8 matrix support for Sonoff-Tasmota
|
||||||
|
|
||||||
|
Copyright (C) 2018 Theo Arends and Adafruit
|
||||||
|
|
||||||
|
This program is free software: you can redistribute it and/or modify
|
||||||
|
it under the terms of the GNU General Public License as published by
|
||||||
|
the Free Software Foundation, either version 3 of the License, or
|
||||||
|
(at your option) any later version.
|
||||||
|
|
||||||
|
This program is distributed in the hope that it will be useful,
|
||||||
|
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||||
|
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||||
|
GNU General Public License for more details.
|
||||||
|
|
||||||
|
You should have received a copy of the GNU General Public License
|
||||||
|
along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||||
|
*/
|
||||||
|
|
||||||
|
#ifdef USE_I2C
|
||||||
|
#ifdef USE_DISPLAY
|
||||||
|
#ifdef USE_DISPLAY_MATRIX
|
||||||
|
|
||||||
|
#define XDSP_03 3
|
||||||
|
|
||||||
|
#include <Wire.h>
|
||||||
|
#include <Adafruit_GFX.h>
|
||||||
|
#include <Adafruit_LEDBackpack.h> // 8x8 Matrix
|
||||||
|
|
||||||
|
Adafruit_8x8matrix *matrix[8];
|
||||||
|
uint8_t mtx_matrices = 0;
|
||||||
|
uint8_t mtx_state = 0;
|
||||||
|
uint8_t mtx_counter = 0;
|
||||||
|
int16_t mtx_x = 0;
|
||||||
|
int16_t mtx_y = 0;
|
||||||
|
|
||||||
|
/*********************************************************************************************/
|
||||||
|
|
||||||
|
void MatrixWrite()
|
||||||
|
{
|
||||||
|
for (byte i = 0; i < mtx_matrices; i++) {
|
||||||
|
matrix[i]->writeDisplay();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void MatrixClear()
|
||||||
|
{
|
||||||
|
for (byte i = 0; i < mtx_matrices; i++) {
|
||||||
|
matrix[i]->clear();
|
||||||
|
}
|
||||||
|
MatrixWrite();
|
||||||
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
void MatrixAll() // On based on Text value (1 - 6)
|
||||||
|
{
|
||||||
|
int value = atoi(Settings.text);
|
||||||
|
for (byte i = 0; i < mtx_matrices; i++) {
|
||||||
|
matrix[i]->clear();
|
||||||
|
if (i < value) {
|
||||||
|
matrix[i]->fillRect(0,0, 8,8, LED_ON);
|
||||||
|
}
|
||||||
|
matrix[i]->setBrightness(Settings.display_dimmer);
|
||||||
|
}
|
||||||
|
MatrixWrite();
|
||||||
|
}
|
||||||
|
|
||||||
|
void MatrixAllOn()
|
||||||
|
{
|
||||||
|
for (byte i = 0; i < mtx_matrices; i++) {
|
||||||
|
matrix[i]->clear();
|
||||||
|
matrix[i]->fillRect(0,0, 8,8, LED_ON);
|
||||||
|
matrix[i]->setBrightness(Settings.display_dimmer);
|
||||||
|
}
|
||||||
|
MatrixWrite();
|
||||||
|
}
|
||||||
|
*/
|
||||||
|
|
||||||
|
void MatrixFixed(char* txt)
|
||||||
|
{
|
||||||
|
for (byte i = 0; i < mtx_matrices; i++) {
|
||||||
|
matrix[i]->clear();
|
||||||
|
matrix[i]->setCursor(-i *8, 0);
|
||||||
|
matrix[i]->print(txt);
|
||||||
|
matrix[i]->setBrightness(Settings.display_dimmer);
|
||||||
|
}
|
||||||
|
MatrixWrite();
|
||||||
|
}
|
||||||
|
|
||||||
|
void MatrixCenter(char* txt)
|
||||||
|
{
|
||||||
|
int offset;
|
||||||
|
|
||||||
|
int len = strlen(txt);
|
||||||
|
offset = (len < 8) ? offset = ((mtx_matrices *8) - (len *6)) / 2 : 0;
|
||||||
|
for (byte i = 0; i < mtx_matrices; i++) {
|
||||||
|
matrix[i]->clear();
|
||||||
|
matrix[i]->setCursor(-(i *8)+offset, 0);
|
||||||
|
matrix[i]->print(txt);
|
||||||
|
matrix[i]->setBrightness(Settings.display_dimmer);
|
||||||
|
}
|
||||||
|
MatrixWrite();
|
||||||
|
}
|
||||||
|
|
||||||
|
void MatrixScrollLeft(char* txt, int loop)
|
||||||
|
{
|
||||||
|
switch (mtx_state) {
|
||||||
|
case 1:
|
||||||
|
mtx_state = 2;
|
||||||
|
// Horiz. position of text -- starts off right edge
|
||||||
|
mtx_x = 8 * mtx_matrices;
|
||||||
|
|
||||||
|
snprintf_P(log_data, sizeof(log_data), PSTR(D_LOG_DEBUG "[%s]"), txt);
|
||||||
|
AddLog(LOG_LEVEL_DEBUG);
|
||||||
|
|
||||||
|
disp_refresh = Settings.display_refresh;
|
||||||
|
case 2:
|
||||||
|
disp_refresh--;
|
||||||
|
if (!disp_refresh) {
|
||||||
|
disp_refresh = Settings.display_refresh;
|
||||||
|
for (byte i = 0; i < mtx_matrices; i++) {
|
||||||
|
matrix[i]->clear();
|
||||||
|
matrix[i]->setCursor(mtx_x - i *8, 0);
|
||||||
|
matrix[i]->print(txt);
|
||||||
|
matrix[i]->setBrightness(Settings.display_dimmer);
|
||||||
|
}
|
||||||
|
MatrixWrite();
|
||||||
|
// Move text position left by 1 pixel.
|
||||||
|
mtx_x--;
|
||||||
|
int16_t len = strlen(txt);
|
||||||
|
if (mtx_x < -(len *6)) {
|
||||||
|
mtx_state = loop;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void MatrixScrollUp(char* txt, int loop)
|
||||||
|
{
|
||||||
|
int wordcounter = 0;
|
||||||
|
char tmpbuf[200];
|
||||||
|
char *words[100];
|
||||||
|
// char separators[] = " ,.;:!?";
|
||||||
|
// char separators[] = " ";
|
||||||
|
// char separators[] = " /|";
|
||||||
|
char separators[] = " /";
|
||||||
|
|
||||||
|
switch (mtx_state) {
|
||||||
|
case 1:
|
||||||
|
mtx_state = 2;
|
||||||
|
// Vertical position of text -- starts off left bottom edge
|
||||||
|
mtx_y = 8;
|
||||||
|
mtx_counter = 0;
|
||||||
|
disp_refresh = Settings.display_refresh;
|
||||||
|
case 2:
|
||||||
|
disp_refresh--;
|
||||||
|
if (!disp_refresh) {
|
||||||
|
disp_refresh = Settings.display_refresh;
|
||||||
|
strlcpy(tmpbuf, txt, sizeof(tmpbuf));
|
||||||
|
char *p = strtok(tmpbuf, separators);
|
||||||
|
while (p != NULL && wordcounter < 40) {
|
||||||
|
words[wordcounter++] = p;
|
||||||
|
p = strtok(NULL, separators);
|
||||||
|
}
|
||||||
|
for (byte i = 0; i < mtx_matrices; i++) {
|
||||||
|
matrix[i]->clear();
|
||||||
|
for (byte j = 0; j < wordcounter; j++) {
|
||||||
|
matrix[i]->setCursor(-i *8, mtx_y + (j *8));
|
||||||
|
matrix[i]->println(words[j]);
|
||||||
|
}
|
||||||
|
matrix[i]->setBrightness(Settings.display_dimmer);
|
||||||
|
}
|
||||||
|
MatrixWrite();
|
||||||
|
if (((mtx_y %8) == 0) && mtx_counter) {
|
||||||
|
mtx_counter--;
|
||||||
|
} else {
|
||||||
|
mtx_y--; // Move text position up by 1 pixel.
|
||||||
|
mtx_counter = STATES * 1; // Hold text for 1 seconds
|
||||||
|
}
|
||||||
|
if (mtx_y < -(wordcounter *8)) {
|
||||||
|
mtx_state = loop;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void MatrixBufferScroll(uint8_t direction)
|
||||||
|
{
|
||||||
|
if (disp_log_buffer_idx != disp_log_buffer_ptr) {
|
||||||
|
if (!mtx_state) {
|
||||||
|
mtx_state = 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
char *pch = strchr(disp_log_buffer[disp_log_buffer_ptr],'~'); // = 0x7E (~) Replace degrees character (276 octal)
|
||||||
|
if (pch != NULL) {
|
||||||
|
disp_log_buffer[disp_log_buffer_ptr][pch - disp_log_buffer[disp_log_buffer_ptr]] = '\370'; // = 0xF8
|
||||||
|
}
|
||||||
|
|
||||||
|
if (direction) {
|
||||||
|
MatrixScrollUp(disp_log_buffer[disp_log_buffer_ptr], 0);
|
||||||
|
} else {
|
||||||
|
MatrixScrollLeft(disp_log_buffer[disp_log_buffer_ptr], 0);
|
||||||
|
}
|
||||||
|
if (!mtx_state) {
|
||||||
|
DisplayLogBufferPtrInc();
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
char disp_time[9]; // 13:45:43
|
||||||
|
|
||||||
|
snprintf_P(disp_time, sizeof(disp_time), PSTR("%02d" D_HOUR_MINUTE_SEPARATOR "%02d" D_MINUTE_SECOND_SEPARATOR "%02d"), RtcTime.hour, RtcTime.minute, RtcTime.second);
|
||||||
|
MatrixFixed(disp_time);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/*********************************************************************************************/
|
||||||
|
|
||||||
|
void MatrixInitMode()
|
||||||
|
{
|
||||||
|
for (byte i = 0; i < mtx_matrices; i++) {
|
||||||
|
matrix[i]->setRotation(1);
|
||||||
|
matrix[i]->setBrightness(Settings.display_dimmer);
|
||||||
|
matrix[i]->blinkRate(0); // 0 - 3
|
||||||
|
matrix[i]->setTextWrap(false); // Allow text to run off edges
|
||||||
|
// matrix[i]->setTextSize(Settings.display_size);
|
||||||
|
// matrix[i]->setTextColor(LED_RED);
|
||||||
|
matrix[i]->cp437(true);
|
||||||
|
}
|
||||||
|
MatrixClear();
|
||||||
|
}
|
||||||
|
|
||||||
|
void MatrixInit(uint8_t mode)
|
||||||
|
{
|
||||||
|
switch(mode) {
|
||||||
|
case DISPLAY_INIT_MODE:
|
||||||
|
MatrixInitMode();
|
||||||
|
break;
|
||||||
|
case DISPLAY_INIT_PARTIAL:
|
||||||
|
case DISPLAY_INIT_FULL:
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void MatrixInitDriver()
|
||||||
|
{
|
||||||
|
if (!Settings.display_model) {
|
||||||
|
if (I2cDevice(Settings.display_address[1])) {
|
||||||
|
Settings.display_model = XDSP_03;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if (XDSP_03 == Settings.display_model) {
|
||||||
|
mtx_state = 1;
|
||||||
|
for (mtx_matrices = 0; mtx_matrices < 8; mtx_matrices++) {
|
||||||
|
if (Settings.display_address[mtx_matrices]) {
|
||||||
|
matrix[mtx_matrices] = new Adafruit_8x8matrix();
|
||||||
|
matrix[mtx_matrices]->begin(Settings.display_address[mtx_matrices]);
|
||||||
|
} else {
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
MatrixInitMode();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void MatrixOnOff()
|
||||||
|
{
|
||||||
|
if (!disp_power) {
|
||||||
|
MatrixClear();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void MatrixRefresh() // Every second
|
||||||
|
{
|
||||||
|
if (disp_power) {
|
||||||
|
switch (Settings.display_mode) {
|
||||||
|
case 0:
|
||||||
|
// MatrixScrollLeft(Settings.text, Settings.loop);
|
||||||
|
case 2: {
|
||||||
|
char disp_date[9]; // 24-04-17
|
||||||
|
snprintf_P(disp_date, sizeof(disp_date), PSTR("%02d" D_MONTH_DAY_SEPARATOR "%02d" D_YEAR_MONTH_SEPARATOR "%02d"), RtcTime.day_of_month, RtcTime.month, RtcTime.year -2000);
|
||||||
|
MatrixFixed(disp_date);
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
case 3: {
|
||||||
|
char disp_day[10]; // Mon
|
||||||
|
snprintf_P(disp_day, sizeof(disp_day), PSTR("%d %s"), RtcTime.day_of_month, RtcTime.name_of_month);
|
||||||
|
MatrixCenter(disp_day);
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
case 4:
|
||||||
|
MatrixBufferScroll(0);
|
||||||
|
break;
|
||||||
|
case 1: // Time and user text
|
||||||
|
case 5: // Time, user text and MQTT
|
||||||
|
MatrixBufferScroll(1);
|
||||||
|
break;
|
||||||
|
// case 8:
|
||||||
|
// MatrixAllOn();
|
||||||
|
// break;
|
||||||
|
// case 9:
|
||||||
|
// MatrixAll();
|
||||||
|
// break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/*********************************************************************************************\
|
||||||
|
* Interface
|
||||||
|
\*********************************************************************************************/
|
||||||
|
|
||||||
|
boolean Xdsp03(byte function)
|
||||||
|
{
|
||||||
|
boolean result = false;
|
||||||
|
|
||||||
|
if (i2c_flg) {
|
||||||
|
if (FUNC_DISPLAY_INIT_DRIVER == function) {
|
||||||
|
MatrixInitDriver();
|
||||||
|
}
|
||||||
|
else if (XDSP_03 == Settings.display_model) {
|
||||||
|
switch (function) {
|
||||||
|
case FUNC_DISPLAY_MODEL:
|
||||||
|
result = true;
|
||||||
|
break;
|
||||||
|
case FUNC_DISPLAY_INIT:
|
||||||
|
MatrixInit(dsp_init);
|
||||||
|
break;
|
||||||
|
case FUNC_DISPLAY_EVERY_50_MSECOND:
|
||||||
|
MatrixRefresh();
|
||||||
|
break;
|
||||||
|
case FUNC_DISPLAY_POWER:
|
||||||
|
MatrixOnOff();
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return result;
|
||||||
|
}
|
||||||
|
|
||||||
|
#endif // USE_DISPLAY_MATRIX
|
||||||
|
#endif // USE_DISPLAY
|
||||||
|
#endif // USE_I2C
|
|
@ -0,0 +1,290 @@
|
||||||
|
/*
|
||||||
|
xdsp_04_ili9341.ino - Display Tft Ili9341 support for Sonoff-Tasmota
|
||||||
|
|
||||||
|
Copyright (C) 2018 Theo Arends and Adafruit
|
||||||
|
|
||||||
|
This program is free software: you can redistribute it and/or modify
|
||||||
|
it under the terms of the GNU General Public License as published by
|
||||||
|
the Free Software Foundation, either version 3 of the License, or
|
||||||
|
(at your option) any later version.
|
||||||
|
|
||||||
|
This program is distributed in the hope that it will be useful,
|
||||||
|
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||||
|
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||||
|
GNU General Public License for more details.
|
||||||
|
|
||||||
|
You should have received a copy of the GNU General Public License
|
||||||
|
along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||||
|
*/
|
||||||
|
|
||||||
|
#ifdef USE_SPI
|
||||||
|
#ifdef USE_DISPLAY
|
||||||
|
#ifdef USE_DISPLAY_ILI9341
|
||||||
|
|
||||||
|
#define XDSP_04 4
|
||||||
|
|
||||||
|
#define TFT_TOP 16
|
||||||
|
#define TFT_BOTTOM 16
|
||||||
|
#define TFT_FONT_WIDTH 6
|
||||||
|
#define TFT_FONT_HEIGTH 8 // Adafruit minimal font heigth pixels
|
||||||
|
|
||||||
|
#include <SPI.h>
|
||||||
|
#include <Adafruit_GFX.h>
|
||||||
|
#include <Adafruit_ILI9341.h> // TFT 320x240 and 480x320
|
||||||
|
|
||||||
|
Adafruit_ILI9341 *tft;
|
||||||
|
|
||||||
|
uint16_t tft_scroll;
|
||||||
|
|
||||||
|
/*********************************************************************************************/
|
||||||
|
|
||||||
|
void Ili9341Clear()
|
||||||
|
{
|
||||||
|
tft->fillScreen(ILI9341_BLACK);
|
||||||
|
tft->setCursor(0, 0);
|
||||||
|
}
|
||||||
|
|
||||||
|
void Ili9341DrawStringAt(uint16_t x, uint16_t y, char *str, uint16_t color, uint8_t flag)
|
||||||
|
{
|
||||||
|
uint16_t active_color = ILI9341_WHITE;
|
||||||
|
|
||||||
|
tft->setTextSize(Settings.display_size);
|
||||||
|
if (!flag) {
|
||||||
|
tft->setCursor(x, y);
|
||||||
|
} else {
|
||||||
|
tft->setCursor((x-1) * TFT_FONT_WIDTH * Settings.display_size, (y-1) * TFT_FONT_HEIGTH * Settings.display_size);
|
||||||
|
}
|
||||||
|
if (color) { active_color = color; }
|
||||||
|
tft->setTextColor(active_color, ILI9341_BLACK);
|
||||||
|
tft->println(str);
|
||||||
|
}
|
||||||
|
|
||||||
|
void Ili9341DisplayOnOff(uint8_t on)
|
||||||
|
{
|
||||||
|
// tft->showDisplay(on);
|
||||||
|
// tft->invertDisplay(on);
|
||||||
|
if (pin[GPIO_BACKLIGHT] < 99) {
|
||||||
|
pinMode(pin[GPIO_BACKLIGHT], OUTPUT);
|
||||||
|
digitalWrite(pin[GPIO_BACKLIGHT], on);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/*********************************************************************************************/
|
||||||
|
|
||||||
|
void DisplayTftPrint(byte size, char *txt)
|
||||||
|
{
|
||||||
|
uint16_t theight;
|
||||||
|
|
||||||
|
tft->setCursor(0, tft_scroll);
|
||||||
|
tft->setTextSize(size);
|
||||||
|
theight = size * TFT_FONT_HEIGTH;
|
||||||
|
tft->fillRect(0, tft_scroll, tft->width(), theight, ILI9341_BLACK);
|
||||||
|
|
||||||
|
snprintf_P(log_data, sizeof(log_data), PSTR(D_LOG_APPLICATION "[%s]"), txt);
|
||||||
|
AddLog(LOG_LEVEL_DEBUG);
|
||||||
|
|
||||||
|
tft->print(txt);
|
||||||
|
tft_scroll += theight;
|
||||||
|
if (tft_scroll >= (tft->height() - TFT_BOTTOM)) {
|
||||||
|
tft_scroll = TFT_TOP;
|
||||||
|
}
|
||||||
|
tft->setScrollStart(tft_scroll);
|
||||||
|
}
|
||||||
|
|
||||||
|
/*********************************************************************************************/
|
||||||
|
|
||||||
|
void Ili9341InitMode()
|
||||||
|
{
|
||||||
|
tft->setRotation(0);
|
||||||
|
tft->invertDisplay(0);
|
||||||
|
tft->fillScreen(ILI9341_BLACK);
|
||||||
|
tft->setTextWrap(false); // Allow text to run off edges
|
||||||
|
tft->cp437(true);
|
||||||
|
if (!Settings.display_mode) {
|
||||||
|
tft->setCursor(0, 0);
|
||||||
|
tft->setTextColor(ILI9341_WHITE, ILI9341_BLACK);
|
||||||
|
tft->setTextSize(1);
|
||||||
|
} else {
|
||||||
|
tft->setScrollMargins(TFT_TOP, TFT_BOTTOM);
|
||||||
|
tft->setCursor(0, 0);
|
||||||
|
tft->setTextColor(ILI9341_YELLOW, ILI9341_BLACK);
|
||||||
|
tft->setTextSize(2);
|
||||||
|
tft->println("HEADER");
|
||||||
|
|
||||||
|
tft_scroll = TFT_TOP;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void Ili9341Init(uint8_t mode)
|
||||||
|
{
|
||||||
|
switch(mode) {
|
||||||
|
case DISPLAY_INIT_MODE:
|
||||||
|
Ili9341InitMode();
|
||||||
|
break;
|
||||||
|
case DISPLAY_INIT_PARTIAL:
|
||||||
|
case DISPLAY_INIT_FULL:
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void Ili9341InitDriver()
|
||||||
|
{
|
||||||
|
if (!Settings.display_model) {
|
||||||
|
Settings.display_model = XDSP_04;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (XDSP_04 == Settings.display_model) {
|
||||||
|
tft = new Adafruit_ILI9341(pin[GPIO_SPI_CS], pin[GPIO_SPI_DC]);
|
||||||
|
tft->begin();
|
||||||
|
|
||||||
|
Ili9341InitMode();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void Ili9341PrintLogLine()
|
||||||
|
{
|
||||||
|
tft->setTextColor(ILI9341_CYAN, ILI9341_BLACK); // Add background color to solve flicker
|
||||||
|
tft->setCursor(0, tft_scroll);
|
||||||
|
byte size = Settings.display_size;
|
||||||
|
tft->setTextSize(size);
|
||||||
|
uint16_t theight = size * TFT_FONT_HEIGTH;
|
||||||
|
tft->fillRect(0, tft_scroll, tft->width(), theight, ILI9341_BLACK);
|
||||||
|
|
||||||
|
char *pch = strchr(disp_log_buffer[disp_log_buffer_ptr],'~'); // = 0x7E (~) Replace degrees character (276 octal)
|
||||||
|
if (pch != NULL) {
|
||||||
|
disp_log_buffer[disp_log_buffer_ptr][pch - disp_log_buffer[disp_log_buffer_ptr]] = '\370'; // = 0xF8
|
||||||
|
}
|
||||||
|
|
||||||
|
snprintf_P(log_data, sizeof(log_data), PSTR(D_LOG_APPLICATION "[%s]"), disp_log_buffer[disp_log_buffer_ptr]);
|
||||||
|
AddLog(LOG_LEVEL_DEBUG);
|
||||||
|
|
||||||
|
tft->print(disp_log_buffer[disp_log_buffer_ptr]);
|
||||||
|
tft_scroll += theight;
|
||||||
|
if (tft_scroll >= (tft->height() - TFT_BOTTOM)) {
|
||||||
|
tft_scroll = TFT_TOP;
|
||||||
|
}
|
||||||
|
tft->setScrollStart(tft_scroll);
|
||||||
|
}
|
||||||
|
|
||||||
|
void Ili9341PrintLog()
|
||||||
|
{
|
||||||
|
disp_refresh--;
|
||||||
|
if (!disp_refresh) {
|
||||||
|
disp_refresh = Settings.display_refresh;
|
||||||
|
disp_log_buffer_active = (disp_log_buffer_idx != disp_log_buffer_ptr);
|
||||||
|
if (disp_log_buffer_active) {
|
||||||
|
Ili9341PrintLogLine();
|
||||||
|
DisplayLogBufferPtrInc();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void Ili9341OnOff()
|
||||||
|
{
|
||||||
|
Ili9341DisplayOnOff(disp_power);
|
||||||
|
}
|
||||||
|
|
||||||
|
void Ili9341Refresh() // Every second
|
||||||
|
{
|
||||||
|
if (Settings.display_mode) { // Mode 0 is User text
|
||||||
|
char tftdt[21];
|
||||||
|
char disp_time[9]; // 13:45:43
|
||||||
|
char disp_date4[11]; // 24-04-2017
|
||||||
|
|
||||||
|
snprintf_P(disp_time, sizeof(disp_time), PSTR("%02d" D_HOUR_MINUTE_SEPARATOR "%02d" D_MINUTE_SECOND_SEPARATOR "%02d"), RtcTime.hour, RtcTime.minute, RtcTime.second);
|
||||||
|
snprintf_P(disp_date4, sizeof(disp_date4), PSTR("%02d" D_MONTH_DAY_SEPARATOR "%02d" D_YEAR_MONTH_SEPARATOR "%04d"), RtcTime.day_of_month, RtcTime.month, RtcTime.year);
|
||||||
|
|
||||||
|
tft->setTextSize(2);
|
||||||
|
tft->setTextColor(ILI9341_YELLOW, ILI9341_BLACK); // Add background color to solve flicker
|
||||||
|
tft->setCursor(0, 0);
|
||||||
|
snprintf_P(tftdt, sizeof(tftdt), PSTR("%s %s"), disp_date4, disp_time);
|
||||||
|
tft->print(tftdt);
|
||||||
|
|
||||||
|
switch (Settings.display_mode) {
|
||||||
|
case 2: // Local
|
||||||
|
case 3: // Local
|
||||||
|
case 4: // Mqtt
|
||||||
|
case 5: // Mqtt
|
||||||
|
Ili9341PrintLog();
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/*********************************************************************************************\
|
||||||
|
* Interface
|
||||||
|
\*********************************************************************************************/
|
||||||
|
|
||||||
|
boolean Xdsp04(byte function)
|
||||||
|
{
|
||||||
|
boolean result = false;
|
||||||
|
|
||||||
|
if (spi_flg) {
|
||||||
|
if (FUNC_DISPLAY_INIT_DRIVER == function) {
|
||||||
|
Ili9341InitDriver();
|
||||||
|
}
|
||||||
|
else if (XDSP_04 == Settings.display_model) {
|
||||||
|
|
||||||
|
if (!dsp_color) { dsp_color = ILI9341_WHITE; }
|
||||||
|
|
||||||
|
switch (function) {
|
||||||
|
case FUNC_DISPLAY_MODEL:
|
||||||
|
result = true;
|
||||||
|
break;
|
||||||
|
case FUNC_DISPLAY_INIT:
|
||||||
|
Ili9341Init(dsp_init);
|
||||||
|
break;
|
||||||
|
case FUNC_DISPLAY_EVERY_SECOND:
|
||||||
|
Ili9341Refresh();
|
||||||
|
break;
|
||||||
|
case FUNC_DISPLAY_POWER:
|
||||||
|
Ili9341OnOff();
|
||||||
|
break;
|
||||||
|
case FUNC_DISPLAY_CLEAR:
|
||||||
|
Ili9341Clear();
|
||||||
|
break;
|
||||||
|
case FUNC_DISPLAY_DRAW_HLINE:
|
||||||
|
tft->writeFastHLine(dsp_x, dsp_y, dsp_len, dsp_color);
|
||||||
|
break;
|
||||||
|
case FUNC_DISPLAY_DRAW_VLINE:
|
||||||
|
tft->writeFastVLine(dsp_x, dsp_y, dsp_len, dsp_color);
|
||||||
|
break;
|
||||||
|
case FUNC_DISPLAY_DRAW_LINE:
|
||||||
|
tft->writeLine(dsp_x, dsp_y, dsp_x2, dsp_y2, dsp_color);
|
||||||
|
break;
|
||||||
|
case FUNC_DISPLAY_DRAW_CIRCLE:
|
||||||
|
tft->drawCircle(dsp_x, dsp_y, dsp_rad, dsp_color);
|
||||||
|
break;
|
||||||
|
case FUNC_DISPLAY_FILL_CIRCLE:
|
||||||
|
tft->fillCircle(dsp_x, dsp_y, dsp_rad, dsp_color);
|
||||||
|
break;
|
||||||
|
case FUNC_DISPLAY_DRAW_RECTANGLE:
|
||||||
|
tft->drawRect(dsp_x, dsp_y, dsp_x2, dsp_y2, dsp_color);
|
||||||
|
break;
|
||||||
|
case FUNC_DISPLAY_FILL_RECTANGLE:
|
||||||
|
tft->fillRect(dsp_x, dsp_y, dsp_x2, dsp_y2, dsp_color);
|
||||||
|
break;
|
||||||
|
// case FUNC_DISPLAY_DRAW_FRAME:
|
||||||
|
// oled->display();
|
||||||
|
// break;
|
||||||
|
case FUNC_DISPLAY_FONT_SIZE:
|
||||||
|
tft->setTextSize(Settings.display_size);
|
||||||
|
break;
|
||||||
|
case FUNC_DISPLAY_DRAW_STRING:
|
||||||
|
Ili9341DrawStringAt(dsp_x, dsp_y, dsp_str, dsp_color, dsp_flag);
|
||||||
|
break;
|
||||||
|
case FUNC_DISPLAY_ONOFF:
|
||||||
|
Ili9341DisplayOnOff(dsp_on);
|
||||||
|
break;
|
||||||
|
case FUNC_DISPLAY_ROTATION:
|
||||||
|
tft->setRotation(dsp_rotation);
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return result;
|
||||||
|
}
|
||||||
|
|
||||||
|
#endif // USE_DISPLAY_ILI9341
|
||||||
|
#endif // USE_DISPLAY
|
||||||
|
#endif // USE_SPI
|
|
@ -0,0 +1,250 @@
|
||||||
|
/*
|
||||||
|
xdsp_05_epaper.ino - Display e-paper support for Sonoff-Tasmota
|
||||||
|
|
||||||
|
Copyright (C) 2018 Theo Arends, Gerhard Mutz and Waveshare
|
||||||
|
|
||||||
|
This program is free software: you can redistribute it and/or modify
|
||||||
|
it under the terms of the GNU General Public License as published by
|
||||||
|
the Free Software Foundation, either version 3 of the License, or
|
||||||
|
(at your option) any later version.
|
||||||
|
|
||||||
|
This program is distributed in the hope that it will be useful,
|
||||||
|
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||||
|
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||||
|
GNU General Public License for more details.
|
||||||
|
|
||||||
|
You should have received a copy of the GNU General Public License
|
||||||
|
along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||||
|
*/
|
||||||
|
|
||||||
|
#ifdef USE_SPI
|
||||||
|
#ifdef USE_DISPLAY
|
||||||
|
#ifdef USE_DISPLAY_EPAPER
|
||||||
|
|
||||||
|
#define XDSP_05 5
|
||||||
|
|
||||||
|
#define COLORED 0
|
||||||
|
#define UNCOLORED 1
|
||||||
|
|
||||||
|
// using font 8 is opional (num=3)
|
||||||
|
// very badly readable, but may be useful for graphs
|
||||||
|
#define USE_TINY_FONT
|
||||||
|
|
||||||
|
#include <epd2in9.h>
|
||||||
|
#include <epdpaint.h>
|
||||||
|
|
||||||
|
unsigned char image[(EPD_HEIGHT * EPD_WIDTH) / 8];
|
||||||
|
|
||||||
|
Paint paint(image, EPD_WIDTH, EPD_HEIGHT); // width should be the multiple of 8
|
||||||
|
Epd epd;
|
||||||
|
sFONT *selected_font;
|
||||||
|
|
||||||
|
/*********************************************************************************************/
|
||||||
|
|
||||||
|
void EpdInitMode()
|
||||||
|
{
|
||||||
|
// whiten display with full update
|
||||||
|
epd.Init(lut_full_update);
|
||||||
|
|
||||||
|
epd.ClearFrameMemory(0xFF); // bit set = white, bit reset = black
|
||||||
|
epd.DisplayFrame();
|
||||||
|
delay(3000);
|
||||||
|
|
||||||
|
// switch to partial update
|
||||||
|
epd.Init(lut_partial_update);
|
||||||
|
|
||||||
|
// Clear image memory
|
||||||
|
epd.ClearFrameMemory(0xFF); // bit set = white, bit reset = black
|
||||||
|
epd.DisplayFrame();
|
||||||
|
delay(500);
|
||||||
|
|
||||||
|
selected_font = &Font12;
|
||||||
|
|
||||||
|
/*
|
||||||
|
// Welcome text
|
||||||
|
paint.SetRotate(ROTATE_90);
|
||||||
|
paint.Clear(UNCOLORED);
|
||||||
|
paint.DrawStringAt(50, 50, "Waveshare E-Paper Display!", selected_font, COLORED);
|
||||||
|
epd.SetFrameMemory(paint.GetImage(), 0, 0, paint.GetWidth(), paint.GetHeight());
|
||||||
|
epd.DisplayFrame();
|
||||||
|
delay(1000);
|
||||||
|
*/
|
||||||
|
paint.Clear(UNCOLORED);
|
||||||
|
}
|
||||||
|
|
||||||
|
void EpdInitPartial()
|
||||||
|
{
|
||||||
|
epd.Init(lut_partial_update);
|
||||||
|
//paint.Clear(UNCOLORED);
|
||||||
|
epd.DisplayFrame();
|
||||||
|
delay(500);
|
||||||
|
}
|
||||||
|
|
||||||
|
void EpdInitFull()
|
||||||
|
{
|
||||||
|
epd.Init(lut_full_update);
|
||||||
|
//paint.Clear(UNCOLORED);
|
||||||
|
//epd.ClearFrameMemory(0xFF);
|
||||||
|
epd.DisplayFrame();
|
||||||
|
delay(3000);
|
||||||
|
}
|
||||||
|
|
||||||
|
void EpdInit(uint8_t mode)
|
||||||
|
{
|
||||||
|
switch(mode) {
|
||||||
|
case DISPLAY_INIT_MODE:
|
||||||
|
EpdInitMode();
|
||||||
|
break;
|
||||||
|
case DISPLAY_INIT_PARTIAL:
|
||||||
|
EpdInitPartial();
|
||||||
|
break;
|
||||||
|
case DISPLAY_INIT_FULL:
|
||||||
|
EpdInitFull();
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void EpdInitDriver()
|
||||||
|
{
|
||||||
|
if (!Settings.display_model) {
|
||||||
|
Settings.display_model = XDSP_05;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (XDSP_05 == Settings.display_model) {
|
||||||
|
epd.cs_pin = pin[GPIO_SPI_CS];
|
||||||
|
epd.mosi_pin = pin[GPIO_SPI_MOSI]; // 13
|
||||||
|
epd.sclk_pin = pin[GPIO_SPI_CLK]; // 14
|
||||||
|
|
||||||
|
EpdInitMode();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/*********************************************************************************************/
|
||||||
|
|
||||||
|
void EpdClear()
|
||||||
|
{
|
||||||
|
paint.Clear(UNCOLORED);
|
||||||
|
}
|
||||||
|
|
||||||
|
void EpdSetFontorSize(uint8_t font)
|
||||||
|
{
|
||||||
|
if (1 == font) {
|
||||||
|
selected_font = &Font12;
|
||||||
|
} else {
|
||||||
|
#ifdef USE_TINY_FONT
|
||||||
|
if (2 == font) {
|
||||||
|
selected_font = &Font24;
|
||||||
|
} else {
|
||||||
|
selected_font = &Font8;
|
||||||
|
}
|
||||||
|
#else
|
||||||
|
selected_font = &Font24;
|
||||||
|
#endif
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void EpdDrawStringAt(uint16_t x, uint16_t y, char *str, uint8_t color, uint8_t flag)
|
||||||
|
{
|
||||||
|
if (!flag) {
|
||||||
|
paint.DrawStringAt(x, y, str, selected_font, color);
|
||||||
|
} else {
|
||||||
|
paint.DrawStringAt((x-1) * selected_font->Width, (y-1) * selected_font->Height, str, selected_font, color);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// not needed
|
||||||
|
void EpdDisplayOnOff(uint8_t on)
|
||||||
|
{
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
void EpdOnOff()
|
||||||
|
{
|
||||||
|
EpdDisplayOnOff(disp_power);
|
||||||
|
}
|
||||||
|
|
||||||
|
void EpdRefresh() // Every second
|
||||||
|
{
|
||||||
|
if (Settings.display_mode) { // Mode 0 is User text
|
||||||
|
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/*********************************************************************************************\
|
||||||
|
* Interface
|
||||||
|
\*********************************************************************************************/
|
||||||
|
|
||||||
|
boolean Xdsp05(byte function)
|
||||||
|
{
|
||||||
|
boolean result = false;
|
||||||
|
|
||||||
|
if (spi_flg) {
|
||||||
|
if (FUNC_DISPLAY_INIT_DRIVER == function) {
|
||||||
|
EpdInitDriver();
|
||||||
|
}
|
||||||
|
else if (XDSP_04 == Settings.display_model) {
|
||||||
|
|
||||||
|
if (!dsp_color) { dsp_color = COLORED; }
|
||||||
|
|
||||||
|
switch (function) {
|
||||||
|
case FUNC_DISPLAY_MODEL:
|
||||||
|
result = true;
|
||||||
|
break;
|
||||||
|
case FUNC_DISPLAY_INIT:
|
||||||
|
EpdInit(dsp_init);
|
||||||
|
break;
|
||||||
|
case FUNC_DISPLAY_EVERY_SECOND:
|
||||||
|
EpdRefresh();
|
||||||
|
break;
|
||||||
|
case FUNC_DISPLAY_POWER:
|
||||||
|
EpdOnOff();
|
||||||
|
break;
|
||||||
|
case FUNC_DISPLAY_CLEAR:
|
||||||
|
EpdClear();
|
||||||
|
break;
|
||||||
|
case FUNC_DISPLAY_DRAW_HLINE:
|
||||||
|
paint.DrawHorizontalLine(dsp_x, dsp_y, dsp_len, dsp_color);
|
||||||
|
break;
|
||||||
|
case FUNC_DISPLAY_DRAW_VLINE:
|
||||||
|
paint.DrawVerticalLine(dsp_x, dsp_y, dsp_len, dsp_color);
|
||||||
|
break;
|
||||||
|
case FUNC_DISPLAY_DRAW_LINE:
|
||||||
|
paint.DrawLine(dsp_x, dsp_y, dsp_x2, dsp_y2, dsp_color);
|
||||||
|
break;
|
||||||
|
case FUNC_DISPLAY_DRAW_CIRCLE:
|
||||||
|
paint.DrawCircle(dsp_x, dsp_y, dsp_rad, dsp_color);
|
||||||
|
break;
|
||||||
|
case FUNC_DISPLAY_FILL_CIRCLE:
|
||||||
|
paint.DrawFilledCircle(dsp_x, dsp_y, dsp_rad, dsp_color);
|
||||||
|
break;
|
||||||
|
case FUNC_DISPLAY_DRAW_RECTANGLE:
|
||||||
|
paint.DrawRectangle(dsp_x, dsp_y, dsp_x + dsp_x2, dsp_y + dsp_y2, dsp_color);
|
||||||
|
break;
|
||||||
|
case FUNC_DISPLAY_FILL_RECTANGLE:
|
||||||
|
paint.DrawFilledRectangle(dsp_x, dsp_y, dsp_x + dsp_x2, dsp_y + dsp_y2, dsp_color);
|
||||||
|
break;
|
||||||
|
case FUNC_DISPLAY_DRAW_FRAME:
|
||||||
|
epd.SetFrameMemory(paint.GetImage(), 0, 0, paint.GetWidth(), paint.GetHeight());
|
||||||
|
epd.DisplayFrame();
|
||||||
|
break;
|
||||||
|
case FUNC_DISPLAY_FONT_SIZE:
|
||||||
|
EpdSetFontorSize(Settings.display_size);
|
||||||
|
break;
|
||||||
|
case FUNC_DISPLAY_DRAW_STRING:
|
||||||
|
EpdDrawStringAt(dsp_x, dsp_y, dsp_str, dsp_color, dsp_flag);
|
||||||
|
break;
|
||||||
|
case FUNC_DISPLAY_ONOFF:
|
||||||
|
EpdDisplayOnOff(dsp_on);
|
||||||
|
break;
|
||||||
|
case FUNC_DISPLAY_ROTATION:
|
||||||
|
paint.SetRotate(dsp_rotation);
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return result;
|
||||||
|
}
|
||||||
|
|
||||||
|
#endif // USE_DISPLAY_EPAPER
|
||||||
|
#endif // USE_DISPLAY
|
||||||
|
#endif // USE_SPI
|
|
@ -0,0 +1,125 @@
|
||||||
|
/*
|
||||||
|
xdsp_interface.ino - Display interface support for Sonoff-Tasmota
|
||||||
|
|
||||||
|
Copyright (C) 2018 Theo Arends
|
||||||
|
|
||||||
|
This program is free software: you can redistribute it and/or modify
|
||||||
|
it under the terms of the GNU General Public License as published by
|
||||||
|
the Free Software Foundation, either version 3 of the License, or
|
||||||
|
(at your option) any later version.
|
||||||
|
|
||||||
|
This program is distributed in the hope that it will be useful,
|
||||||
|
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||||
|
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||||
|
GNU General Public License for more details.
|
||||||
|
|
||||||
|
You should have received a copy of the GNU General Public License
|
||||||
|
along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||||
|
*/
|
||||||
|
|
||||||
|
boolean (* const xdsp_func_ptr[])(byte) PROGMEM = { // Display Function Pointers
|
||||||
|
#ifdef XDSP_01
|
||||||
|
&Xdsp01,
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#ifdef XDSP_02
|
||||||
|
&Xdsp02,
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#ifdef XDSP_03
|
||||||
|
&Xdsp03,
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#ifdef XDSP_04
|
||||||
|
&Xdsp04,
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#ifdef XDSP_05
|
||||||
|
&Xdsp05,
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#ifdef XDSP_06
|
||||||
|
&Xdsp06,
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#ifdef XDSP_07
|
||||||
|
&Xdsp07,
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#ifdef XDSP_08
|
||||||
|
&Xdsp08,
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#ifdef XDSP_09
|
||||||
|
&Xdsp09,
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#ifdef XDSP_10
|
||||||
|
&Xdsp10,
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#ifdef XDSP_11
|
||||||
|
&Xdsp11,
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#ifdef XDSP_12
|
||||||
|
&Xdsp12,
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#ifdef XDSP_13
|
||||||
|
&Xdsp13,
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#ifdef XDSP_14
|
||||||
|
&Xdsp14,
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#ifdef XDSP_15
|
||||||
|
&Xdsp15,
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#ifdef XDSP_16
|
||||||
|
&Xdsp16
|
||||||
|
#endif
|
||||||
|
};
|
||||||
|
|
||||||
|
const uint8_t xdsp_present = sizeof(xdsp_func_ptr) / sizeof(xdsp_func_ptr[0]); // Number of drivers found
|
||||||
|
|
||||||
|
/*********************************************************************************************\
|
||||||
|
* Function call to all xdsp
|
||||||
|
*
|
||||||
|
* FUNC_DISPLAY_INIT_DRIVER
|
||||||
|
* FUNC_DISPLAY_INIT
|
||||||
|
* FUNC_DISPLAY_EVERY_50_MSECOND
|
||||||
|
* FUNC_DISPLAY_EVERY_SECOND
|
||||||
|
* FUNC_DISPLAY_POWER
|
||||||
|
* FUNC_DISPLAY_CLEAR
|
||||||
|
* FUNC_DISPLAY_DRAW_FRAME
|
||||||
|
* FUNC_DISPLAY_DRAW_HLINE
|
||||||
|
* FUNC_DISPLAY_DRAW_VLINE
|
||||||
|
* FUNC_DISPLAY_DRAW_CIRCLE
|
||||||
|
* FUNC_DISPLAY_FILL_CIRCLE
|
||||||
|
* FUNC_DISPLAY_DRAW_RECTANGLE
|
||||||
|
* FUNC_DISPLAY_FILL_RECTANGLE
|
||||||
|
* FUNC_DISPLAY_FONT_SIZE
|
||||||
|
* FUNC_DISPLAY_ROTATION
|
||||||
|
* FUNC_DISPLAY_DRAW_STRING
|
||||||
|
* FUNC_DISPLAY_ONOFF
|
||||||
|
\*********************************************************************************************/
|
||||||
|
|
||||||
|
uint8_t XdspPresent()
|
||||||
|
{
|
||||||
|
return xdsp_present;
|
||||||
|
}
|
||||||
|
|
||||||
|
boolean XdspCall(byte Function)
|
||||||
|
{
|
||||||
|
boolean result = false;
|
||||||
|
|
||||||
|
for (byte x = 0; x < xdsp_present; x++) {
|
||||||
|
result = xdsp_func_ptr[x](Function);
|
||||||
|
if (result) break;
|
||||||
|
}
|
||||||
|
|
||||||
|
return result;
|
||||||
|
}
|
Loading…
Reference in New Issue