mirror of
https://github.com/adafruit/TFTLCD-Library.git
synced 2026-09-11 09:02:53 +00:00
Compare commits
32
Commits
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
167e9364be | ||
|
|
bdcfb20734 | ||
|
|
c542e168f3 | ||
|
|
d5390a973a | ||
|
|
aef2d6d469 | ||
|
|
c69ffb9866 | ||
|
|
b0debeeeef | ||
|
|
8ad1ede59f | ||
|
|
d73bbf1866 | ||
|
|
9535fbf889 | ||
|
|
97a82854c8 | ||
|
|
ecf4cf17b0 | ||
|
|
6c236e25fa | ||
|
|
40266af7ab | ||
|
|
6c41da9750 | ||
|
|
9323b5cdb5 | ||
|
|
87479c7442 | ||
|
|
7a983dcbc5 | ||
|
|
7d70af32ff | ||
|
|
d9b13dbda0 | ||
|
|
318bb8356e | ||
|
|
162103b583 | ||
|
|
879c387a08 | ||
|
|
f775b97d86 | ||
|
|
286f81f96e | ||
|
|
391f1a503f | ||
|
|
7fc3d6fb0a | ||
|
|
6bc43d3e67 | ||
|
|
b9d06458f5 | ||
|
|
1cf75baa9b | ||
|
|
4ccd1148b0 | ||
|
|
c596e1aa7f |
@@ -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.
|
||||
+635
-82
@@ -4,83 +4,79 @@
|
||||
// Graphics library by ladyada/adafruit with init code from Rossum
|
||||
// MIT license
|
||||
|
||||
#if defined(__SAM3X8E__)
|
||||
#include <include/pio.h>
|
||||
#define PROGMEM
|
||||
#define pgm_read_byte(addr) (*(const unsigned char *)(addr))
|
||||
#define pgm_read_word(addr) (*(const unsigned short *)(addr))
|
||||
#endif
|
||||
#ifdef __AVR__
|
||||
#include <avr/pgmspace.h>
|
||||
#include <avr/pgmspace.h>
|
||||
#endif
|
||||
#include "pins_arduino.h"
|
||||
#include "wiring_private.h"
|
||||
#include "Adafruit_TFTLCD.h"
|
||||
#include "pin_magic.h"
|
||||
|
||||
//#define TFTWIDTH 320
|
||||
//#define TFTHEIGHT 480
|
||||
|
||||
#define TFTWIDTH 240
|
||||
#define TFTHEIGHT 320
|
||||
|
||||
// LCD controller chip identifiers
|
||||
#define ID_932X 0
|
||||
#define ID_7575 1
|
||||
#define ID_9341 2
|
||||
#define ID_HX8357D 3
|
||||
#define ID_UNKNOWN 0xFF
|
||||
|
||||
// Register names from Peter Barrett's Microtouch code
|
||||
#define ILI932X_START_OSC 0x00
|
||||
#define ILI932X_DRIV_OUT_CTRL 0x01
|
||||
#define ILI932X_DRIV_WAV_CTRL 0x02
|
||||
#define ILI932X_ENTRY_MOD 0x03
|
||||
#define ILI932X_RESIZE_CTRL 0x04
|
||||
#define ILI932X_DISP_CTRL1 0x07
|
||||
#define ILI932X_DISP_CTRL2 0x08
|
||||
#define ILI932X_DISP_CTRL3 0x09
|
||||
#define ILI932X_DISP_CTRL4 0x0A
|
||||
#define ILI932X_RGB_DISP_IF_CTRL1 0x0C
|
||||
#define ILI932X_FRM_MARKER_POS 0x0D
|
||||
#define ILI932X_RGB_DISP_IF_CTRL2 0x0F
|
||||
#define ILI932X_POW_CTRL1 0x10
|
||||
#define ILI932X_POW_CTRL2 0x11
|
||||
#define ILI932X_POW_CTRL3 0x12
|
||||
#define ILI932X_POW_CTRL4 0x13
|
||||
#define ILI932X_GRAM_HOR_AD 0x20
|
||||
#define ILI932X_GRAM_VER_AD 0x21
|
||||
#define ILI932X_RW_GRAM 0x22
|
||||
#define ILI932X_POW_CTRL7 0x29
|
||||
#define ILI932X_FRM_RATE_COL_CTRL 0x2B
|
||||
#define ILI932X_GAMMA_CTRL1 0x30
|
||||
#define ILI932X_GAMMA_CTRL2 0x31
|
||||
#define ILI932X_GAMMA_CTRL3 0x32
|
||||
#define ILI932X_GAMMA_CTRL4 0x35
|
||||
#define ILI932X_GAMMA_CTRL5 0x36
|
||||
#define ILI932X_GAMMA_CTRL6 0x37
|
||||
#define ILI932X_GAMMA_CTRL7 0x38
|
||||
#define ILI932X_GAMMA_CTRL8 0x39
|
||||
#define ILI932X_GAMMA_CTRL9 0x3C
|
||||
#define ILI932X_GAMMA_CTRL10 0x3D
|
||||
#define ILI932X_HOR_START_AD 0x50
|
||||
#define ILI932X_HOR_END_AD 0x51
|
||||
#define ILI932X_VER_START_AD 0x52
|
||||
#define ILI932X_VER_END_AD 0x53
|
||||
#define ILI932X_GATE_SCAN_CTRL1 0x60
|
||||
#define ILI932X_GATE_SCAN_CTRL2 0x61
|
||||
#define ILI932X_GATE_SCAN_CTRL3 0x6A
|
||||
#define ILI932X_PART_IMG1_DISP_POS 0x80
|
||||
#define ILI932X_PART_IMG1_START_AD 0x81
|
||||
#define ILI932X_PART_IMG1_END_AD 0x82
|
||||
#define ILI932X_PART_IMG2_DISP_POS 0x83
|
||||
#define ILI932X_PART_IMG2_START_AD 0x84
|
||||
#define ILI932X_PART_IMG2_END_AD 0x85
|
||||
#define ILI932X_PANEL_IF_CTRL1 0x90
|
||||
#define ILI932X_PANEL_IF_CTRL2 0x92
|
||||
#define ILI932X_PANEL_IF_CTRL3 0x93
|
||||
#define ILI932X_PANEL_IF_CTRL4 0x95
|
||||
#define ILI932X_PANEL_IF_CTRL5 0x97
|
||||
#define ILI932X_PANEL_IF_CTRL6 0x98
|
||||
#include "registers.h"
|
||||
|
||||
#define HX8347G_COLADDRSTART_HI 0x02
|
||||
#define HX8347G_COLADDRSTART_LO 0x03
|
||||
#define HX8347G_COLADDREND_HI 0x04
|
||||
#define HX8347G_COLADDREND_LO 0x05
|
||||
#define HX8347G_ROWADDRSTART_HI 0x06
|
||||
#define HX8347G_ROWADDRSTART_LO 0x07
|
||||
#define HX8347G_ROWADDREND_HI 0x08
|
||||
#define HX8347G_ROWADDREND_LO 0x09
|
||||
#define HX8347G_MEMACCESS 0x16
|
||||
#if defined(__SAMD51__)
|
||||
#include <Adafruit_ZeroDMA.h>
|
||||
#include "utility/dma.h"
|
||||
|
||||
#define TIMERNUM 3
|
||||
|
||||
#if TIMERNUM == 0
|
||||
#define TIMER TC0
|
||||
#define IRQN TC0_IRQn
|
||||
#define IRQ_HANDLER TC0_Handler
|
||||
#define TIMER_GCLK_ID TC0_GCLK_ID
|
||||
#define TIMER_EVU EVSYS_ID_USER_TC0_EVU
|
||||
#elif TIMERNUM == 1
|
||||
#define TIMER TC1
|
||||
#define IRQN TC1_IRQn
|
||||
#define IRQ_HANDLER TC1_Handler
|
||||
#define TIMER_GCLK_ID TC1_GCLK_ID
|
||||
#define TIMER_EVU EVSYS_ID_USER_TC1_EVU
|
||||
#elif TIMERNUM == 2
|
||||
#define TIMER TC2
|
||||
#define IRQN TC2_IRQn
|
||||
#define IRQ_HANDLER TC2_Handler
|
||||
#define TIMER_GCLK_ID TC2_GCLK_ID
|
||||
#define TIMER_EVU EVSYS_ID_USER_TC2_EVU
|
||||
#elif TIMERNUM == 3
|
||||
#define TIMER TC3
|
||||
#define IRQN TC3_IRQn
|
||||
#define IRQ_HANDLER TC3_Handler
|
||||
#define TIMER_GCLK_ID TC3_GCLK_ID
|
||||
#define TIMER_EVU EVSYS_ID_USER_TC3_EVU
|
||||
#endif
|
||||
|
||||
#define clockpin 4 // ItsyBitsy M4
|
||||
|
||||
static Adafruit_ZeroDMA myDMA;
|
||||
static ZeroDMAstatus stat;
|
||||
static DmacDescriptor *desc;
|
||||
|
||||
static volatile bool transfer_is_done = true;
|
||||
|
||||
static void dma_callback(Adafruit_ZeroDMA *dma) {
|
||||
transfer_is_done = true;
|
||||
}
|
||||
#endif
|
||||
|
||||
// Constructor for breakout board (configurable LCD control lines).
|
||||
// Can still use this w/shield, but parameters are ignored.
|
||||
@@ -91,10 +87,41 @@ Adafruit_TFTLCD::Adafruit_TFTLCD(
|
||||
#ifndef USE_ADAFRUIT_SHIELD_PINOUT
|
||||
// Convert pin numbers to registers and bitmasks
|
||||
_reset = reset;
|
||||
#ifdef __AVR__
|
||||
csPort = portOutputRegister(digitalPinToPort(cs));
|
||||
cdPort = portOutputRegister(digitalPinToPort(cd));
|
||||
wrPort = portOutputRegister(digitalPinToPort(wr));
|
||||
rdPort = portOutputRegister(digitalPinToPort(rd));
|
||||
#elif defined(__SAM3X8E__)
|
||||
csPort = digitalPinToPort(cs);
|
||||
cdPort = digitalPinToPort(cd);
|
||||
wrPort = digitalPinToPort(wr);
|
||||
rdPort = digitalPinToPort(rd);
|
||||
#elif defined(__SAMD51__)
|
||||
csPortSet = &(PORT->Group[g_APinDescription[cs].ulPort].OUTSET.reg);
|
||||
csPortClr = &(PORT->Group[g_APinDescription[cs].ulPort].OUTCLR.reg);
|
||||
cdPortSet = &(PORT->Group[g_APinDescription[cd].ulPort].OUTSET.reg);
|
||||
cdPortClr = &(PORT->Group[g_APinDescription[cd].ulPort].OUTCLR.reg);
|
||||
wrPortSet = &(PORT->Group[g_APinDescription[wr].ulPort].OUTSET.reg);
|
||||
wrPortClr = &(PORT->Group[g_APinDescription[wr].ulPort].OUTCLR.reg);
|
||||
rdPortSet = &(PORT->Group[g_APinDescription[rd].ulPort].OUTSET.reg);
|
||||
rdPortClr = &(PORT->Group[g_APinDescription[rd].ulPort].OUTCLR.reg);
|
||||
// Temporary - pin 0 determines which PORT register to use
|
||||
volatile uint32_t *r = &(PORT->Group[g_APinDescription[0].ulPort].OUT.reg);
|
||||
writePort = (volatile uint8_t *)r + 2;
|
||||
r = &(PORT->Group[g_APinDescription[0].ulPort].IN.reg);
|
||||
readPort = (volatile uint8_t *)r + 2;
|
||||
r = &(PORT->Group[g_APinDescription[0].ulPort].DIRSET.reg);
|
||||
dirSet = (volatile uint8_t *)r + 2;
|
||||
r = &(PORT->Group[g_APinDescription[0].ulPort].DIRCLR.reg);
|
||||
dirClr = (volatile uint8_t *)r + 2;
|
||||
#endif
|
||||
#if defined(__SAMD51__)
|
||||
csPinMask = digitalPinToBitMask(cs);
|
||||
cdPinMask = digitalPinToBitMask(cd);
|
||||
wrPinMask = digitalPinToBitMask(wr);
|
||||
rdPinMask = digitalPinToBitMask(rd);
|
||||
#else
|
||||
csPinSet = digitalPinToBitMask(cs);
|
||||
cdPinSet = digitalPinToBitMask(cd);
|
||||
wrPinSet = digitalPinToBitMask(wr);
|
||||
@@ -103,14 +130,28 @@ Adafruit_TFTLCD::Adafruit_TFTLCD(
|
||||
cdPinUnset = ~cdPinSet;
|
||||
wrPinUnset = ~wrPinSet;
|
||||
rdPinUnset = ~rdPinSet;
|
||||
*csPort |= csPinSet; // Set all control bits to HIGH (idle)
|
||||
*cdPort |= cdPinSet; // Signals are ACTIVE LOW
|
||||
*wrPort |= wrPinSet;
|
||||
*rdPort |= rdPinSet;
|
||||
#endif
|
||||
#ifdef __AVR__
|
||||
*csPort |= csPinSet; // Set all control bits to HIGH (idle)
|
||||
*cdPort |= cdPinSet; // Signals are ACTIVE LOW
|
||||
*wrPort |= wrPinSet;
|
||||
*rdPort |= rdPinSet;
|
||||
#elif defined(__SAM3X8E__)
|
||||
csPort->PIO_SODR |= csPinSet; // Set all control bits to HIGH (idle)
|
||||
cdPort->PIO_SODR |= cdPinSet; // Signals are ACTIVE LOW
|
||||
wrPort->PIO_SODR |= wrPinSet;
|
||||
rdPort->PIO_SODR |= rdPinSet;
|
||||
#elif defined(__SAMD51__)
|
||||
*csPortSet = csPinMask; // Set all control bits to HIGH (idle)
|
||||
*cdPortSet = cdPinMask; // Signals are ACTIVE LOW
|
||||
*wrPortSet = wrPinMask;
|
||||
// *wrPortClr = wrPinMask;
|
||||
*rdPortSet = rdPinMask;
|
||||
#endif
|
||||
pinMode(cs, OUTPUT); // Enable outputs
|
||||
pinMode(cd, OUTPUT);
|
||||
pinMode(wr, OUTPUT);
|
||||
pinMode(rd, OUTPUT);
|
||||
pinMode(cd, OUTPUT);
|
||||
if(reset) {
|
||||
digitalWrite(reset, HIGH);
|
||||
pinMode(reset, OUTPUT);
|
||||
@@ -205,6 +246,28 @@ static const uint8_t HX8347G_regValues[] PROGMEM = {
|
||||
0x09 , 0x3F
|
||||
};
|
||||
|
||||
static const uint8_t HX8357D_regValues[] PROGMEM = {
|
||||
HX8357_SWRESET, 0,
|
||||
HX8357D_SETC, 3, 0xFF, 0x83, 0x57,
|
||||
TFTLCD_DELAY, 250,
|
||||
HX8357_SETRGB, 4, 0x00, 0x00, 0x06, 0x06,
|
||||
HX8357D_SETCOM, 1, 0x25, // -1.52V
|
||||
HX8357_SETOSC, 1, 0x68, // Normal mode 70Hz, Idle mode 55 Hz
|
||||
HX8357_SETPANEL, 1, 0x05, // BGR, Gate direction swapped
|
||||
HX8357_SETPWR1, 6, 0x00, 0x15, 0x1C, 0x1C, 0x83, 0xAA,
|
||||
HX8357D_SETSTBA, 6, 0x50, 0x50, 0x01, 0x3C, 0x1E, 0x08,
|
||||
// MEME GAMMA HERE
|
||||
HX8357D_SETCYC, 7, 0x02, 0x40, 0x00, 0x2A, 0x2A, 0x0D, 0x78,
|
||||
HX8357_COLMOD, 1, 0x55,
|
||||
HX8357_MADCTL, 1, 0xC0,
|
||||
HX8357_TEON, 1, 0x00,
|
||||
HX8357_TEARLINE, 2, 0x00, 0x02,
|
||||
HX8357_SLPOUT, 0,
|
||||
TFTLCD_DELAY, 150,
|
||||
HX8357_DISPON, 0,
|
||||
TFTLCD_DELAY, 50,
|
||||
};
|
||||
|
||||
static const uint16_t ILI932x_regValues[] PROGMEM = {
|
||||
ILI932X_START_OSC , 0x0001, // Start oscillator
|
||||
TFTLCD_DELAY , 50, // 50 millisecond delay
|
||||
@@ -264,6 +327,8 @@ void Adafruit_TFTLCD::begin(uint16_t id) {
|
||||
|
||||
reset();
|
||||
|
||||
delay(200);
|
||||
|
||||
if((id == 0x9325) || (id == 0x9328)) {
|
||||
|
||||
uint16_t a, d;
|
||||
@@ -278,6 +343,60 @@ void Adafruit_TFTLCD::begin(uint16_t id) {
|
||||
setRotation(rotation);
|
||||
setAddrWindow(0, 0, TFTWIDTH-1, TFTHEIGHT-1);
|
||||
|
||||
} else if (id == 0x9341) {
|
||||
|
||||
uint16_t a, d;
|
||||
driver = ID_9341;
|
||||
CS_ACTIVE;
|
||||
writeRegister8(ILI9341_SOFTRESET, 0);
|
||||
delay(50);
|
||||
writeRegister8(ILI9341_DISPLAYOFF, 0);
|
||||
|
||||
writeRegister8(ILI9341_POWERCONTROL1, 0x23);
|
||||
writeRegister8(ILI9341_POWERCONTROL2, 0x10);
|
||||
writeRegister16(ILI9341_VCOMCONTROL1, 0x2B2B);
|
||||
writeRegister8(ILI9341_VCOMCONTROL2, 0xC0);
|
||||
writeRegister8(ILI9341_MEMCONTROL, ILI9341_MADCTL_MY | ILI9341_MADCTL_BGR);
|
||||
writeRegister8(ILI9341_PIXELFORMAT, 0x55);
|
||||
writeRegister16(ILI9341_FRAMECONTROL, 0x001B);
|
||||
|
||||
writeRegister8(ILI9341_ENTRYMODE, 0x07);
|
||||
/* writeRegister32(ILI9341_DISPLAYFUNC, 0x0A822700);*/
|
||||
|
||||
writeRegister8(ILI9341_SLEEPOUT, 0);
|
||||
delay(150);
|
||||
writeRegister8(ILI9341_DISPLAYON, 0);
|
||||
delay(500);
|
||||
setAddrWindow(0, 0, TFTWIDTH-1, TFTHEIGHT-1);
|
||||
// return;
|
||||
|
||||
} else if (id == 0x8357) {
|
||||
// HX8357D
|
||||
driver = ID_HX8357D;
|
||||
CS_ACTIVE;
|
||||
while(i < sizeof(HX8357D_regValues)) {
|
||||
uint8_t r = pgm_read_byte(&HX8357D_regValues[i++]);
|
||||
uint8_t len = pgm_read_byte(&HX8357D_regValues[i++]);
|
||||
if(r == TFTLCD_DELAY) {
|
||||
delay(len);
|
||||
} else {
|
||||
//Serial.print("Register $"); Serial.print(r, HEX);
|
||||
//Serial.print(" datalen "); Serial.println(len);
|
||||
|
||||
CS_ACTIVE;
|
||||
CD_COMMAND;
|
||||
write8(r);
|
||||
CD_DATA;
|
||||
for (uint8_t d=0; d<len; d++) {
|
||||
uint8_t x = pgm_read_byte(&HX8357D_regValues[i++]);
|
||||
write8(x);
|
||||
}
|
||||
CS_IDLE;
|
||||
|
||||
}
|
||||
}
|
||||
// return;
|
||||
|
||||
} else if(id == 0x7575) {
|
||||
|
||||
uint8_t a, d;
|
||||
@@ -294,13 +413,158 @@ void Adafruit_TFTLCD::begin(uint16_t id) {
|
||||
|
||||
} else {
|
||||
driver = ID_UNKNOWN;
|
||||
return;
|
||||
// return;
|
||||
}
|
||||
|
||||
#if defined(__SAMD51__)
|
||||
// Do insane timer/PWM/DMA init here
|
||||
// Write-strobe pin will NEED to be on a PWM-suitable output!
|
||||
|
||||
// TIMER STUFF
|
||||
|
||||
// Set up generic clock gen 2 as source for TC4
|
||||
// Datasheet recommends setting GENCTRL register in a single write,
|
||||
// so a temp value is used here to more easily construct a value.
|
||||
|
||||
GCLK_GENCTRL_Type genctrl;
|
||||
genctrl.bit.SRC = GCLK_GENCTRL_SRC_DPLL0_Val; // 120 MHz source
|
||||
genctrl.bit.GENEN = 1; // Enable
|
||||
genctrl.bit.OE = 1;
|
||||
genctrl.bit.DIVSEL = 0; // Do not divide clock source
|
||||
genctrl.bit.DIV = 0;
|
||||
GCLK->GENCTRL[2].reg = genctrl.reg;
|
||||
while(GCLK->SYNCBUSY.bit.GENCTRL1 == 1);
|
||||
|
||||
GCLK->PCHCTRL[TIMER_GCLK_ID].bit.CHEN = 0;
|
||||
while(GCLK->PCHCTRL[TIMER_GCLK_ID].bit.CHEN); // Wait for disable
|
||||
GCLK_PCHCTRL_Type pchctrl;
|
||||
pchctrl.bit.GEN = GCLK_PCHCTRL_GEN_GCLK2_Val;
|
||||
pchctrl.bit.CHEN = 1;
|
||||
GCLK->PCHCTRL[TIMER_GCLK_ID].reg = pchctrl.reg;
|
||||
while(!GCLK->PCHCTRL[TIMER_GCLK_ID].bit.CHEN); // Wait for enable
|
||||
|
||||
// Set up event system off same clock
|
||||
GCLK->PCHCTRL[EVSYS_GCLK_ID_0].bit.CHEN = 0;
|
||||
while(GCLK->PCHCTRL[EVSYS_GCLK_ID_0].bit.CHEN); // Wait for disable
|
||||
pchctrl.bit.GEN = GCLK_PCHCTRL_GEN_GCLK2_Val;
|
||||
pchctrl.bit.CHEN = 1;
|
||||
GCLK->PCHCTRL[EVSYS_GCLK_ID_0].reg = pchctrl.reg;
|
||||
while(!GCLK->PCHCTRL[EVSYS_GCLK_ID_0].bit.CHEN); // Wait for enable
|
||||
MCLK->APBBMASK.bit.EVSYS_ = 1; // Enable event system clock
|
||||
|
||||
// Configure timer for 8-bit normal PWM mode
|
||||
|
||||
// Counter must first be disabled to configure it
|
||||
TIMER->COUNT8.CTRLA.bit.ENABLE = 0;
|
||||
while(TIMER->COUNT8.SYNCBUSY.bit.STATUS);
|
||||
|
||||
TIMER->COUNT8.WAVE.bit.WAVEGEN = 2; // Normal PWM mode (NPWM)
|
||||
|
||||
TIMER->COUNT8.CTRLA.bit.MODE = 1; // 8-bit counter mode
|
||||
TIMER->COUNT8.CTRLA.bit.PRESCALER = 0; // 1:1 clock prescale
|
||||
while(TIMER->COUNT8.SYNCBUSY.bit.STATUS);
|
||||
|
||||
//TIMER->COUNT8.CTRLBSET.bit.DIR = 1; // Count DOWN
|
||||
TIMER->COUNT8.CTRLBCLR.bit.DIR = 1; // Count UP
|
||||
while(TIMER->COUNT8.SYNCBUSY.bit.CTRLB);
|
||||
TIMER->COUNT8.CTRLBSET.bit.ONESHOT = 1; // One-shot operation
|
||||
while(TIMER->COUNT8.SYNCBUSY.bit.CTRLB);
|
||||
|
||||
TIMER->COUNT8.PER.reg = 3; // PWM top value
|
||||
while(TIMER->COUNT8.SYNCBUSY.bit.PER);
|
||||
|
||||
TIMER->COUNT8.CC[0].reg = 2; // Compare value for channel 0
|
||||
while(TIMER->COUNT8.SYNCBUSY.bit.CC0);
|
||||
|
||||
TIMER->COUNT8.EVCTRL.bit.TCEI = 1; // Enable async input events
|
||||
TIMER->COUNT8.EVCTRL.bit.EVACT = 1; // Event action = start/restart/retrigger
|
||||
|
||||
//TIMER->COUNT8.DRVCTRL.bit.INVEN0 = 1; // Invert output
|
||||
|
||||
// Enable TCx
|
||||
TIMER->COUNT8.CTRLA.reg |= TC_CTRLA_ENABLE;
|
||||
while(TIMER->COUNT8.SYNCBUSY.bit.STATUS);
|
||||
|
||||
// CCL STUFF
|
||||
// Enable CCL bus clock (CLK_CCL_APB)
|
||||
MCLK->APBCMASK.bit.CCL_ = 1; // Enable CCL clock
|
||||
// Generic clock (GCLK_CCL) is needed for input events, filter,
|
||||
// edge detection or sequential logic (i.e. not needed here?)
|
||||
GCLK->PCHCTRL[CCL_GCLK_ID].bit.CHEN = 0;
|
||||
while(GCLK->PCHCTRL[CCL_GCLK_ID].bit.CHEN); // Wait for disable
|
||||
pchctrl.bit.GEN = GCLK_PCHCTRL_GEN_GCLK2_Val;
|
||||
pchctrl.bit.CHEN = 1;
|
||||
GCLK->PCHCTRL[CCL_GCLK_ID].reg = pchctrl.reg;
|
||||
while(!GCLK->PCHCTRL[CCL_GCLK_ID].bit.CHEN); // Wait for enable
|
||||
|
||||
// CCL/OUT[0] = PA07 (D2), PA19 (D9), PB02 (NA), PB23 (MISO)
|
||||
// CCL/OUT[1] = PA11 (NA), PA31 (SWDIO), PB11 (NA)
|
||||
// CCL/OUT[2] = PB09 (A3), PA25 (NA)
|
||||
// CCL/OUT[3] = PB17 (NA)
|
||||
|
||||
CCL->CTRL.bit.SWRST = 1; // Reset CCL registers to defaults
|
||||
CCL->CTRL.bit.ENABLE = 1; // Enable CCL
|
||||
|
||||
// LUT control X register can only be written when disabled
|
||||
CCL->LUTCTRL[TIMERNUM].bit.ENABLE = 0;
|
||||
|
||||
//CCL->LUTCTRL[TIMERNUM].bit.FILTSEL = 2; // Filter enabled
|
||||
CCL->LUTCTRL[TIMERNUM].bit.FILTSEL = 0; // No filter
|
||||
|
||||
CCL->LUTCTRL[TIMERNUM].bit.INSEL0 = 6; // TC input source
|
||||
CCL->LUTCTRL[TIMERNUM].bit.INSEL1 = 0; // MASK
|
||||
CCL->LUTCTRL[TIMERNUM].bit.INSEL2 = 0; // MASK
|
||||
CCL->LUTCTRL[TIMERNUM].bit.TRUTH = 0b01010101; // Invert
|
||||
CCL->LUTCTRL[TIMERNUM].bit.ENABLE = 1;
|
||||
|
||||
#if TIMERNUM == 0
|
||||
pinMode(2, OUTPUT);
|
||||
pinPeripheral(2, PIO_CCL);
|
||||
#elif TIMERNUM == 2
|
||||
pinMode(A3, OUTPUT);
|
||||
pinPeripheral(A3, PIO_CCL);
|
||||
#endif
|
||||
|
||||
// EVENTS STUFF
|
||||
|
||||
EVSYS->USER[TIMER_EVU].reg = 1; // Connect Timer EVU to ch 0 (value is +1)
|
||||
// Datasheet recommends single write operation; reg instead of bit
|
||||
// Also datasheet: PATH bits must be zero when using async!
|
||||
EVSYS_CHANNEL_Type ev;
|
||||
ev.reg = 0;
|
||||
ev.bit.PATH = 2; // Asynchronous
|
||||
ev.bit.EVGEN = 0x22; // DMA channel 0
|
||||
EVSYS->Channel[0].CHANNEL.reg = ev.reg;
|
||||
|
||||
// DMA STUFF
|
||||
|
||||
stat = myDMA.allocate();
|
||||
myDMA.printStatus(stat);
|
||||
|
||||
uint8_t foo;
|
||||
desc = myDMA.addDescriptor(
|
||||
(void *)&foo, // move data from here
|
||||
(void *)writePort, // to here
|
||||
256, // this many...
|
||||
DMA_BEAT_SIZE_BYTE, // bytes/hword/words
|
||||
false, // increment source addr?
|
||||
false); // increment dest addr?
|
||||
desc->BTCTRL.bit.EVOSEL = 0x3; // Event strobe on beat transfer
|
||||
|
||||
DMAC->Channel[0].CHEVCTRL.bit.EVOE = 1; // Enable event output
|
||||
DMAC->Channel[0].CHEVCTRL.bit.EVOMODE = 0; // Use EVOSEL output selection
|
||||
|
||||
myDMA.setCallback(dma_callback);
|
||||
|
||||
#endif
|
||||
|
||||
|
||||
}
|
||||
|
||||
void Adafruit_TFTLCD::reset(void) {
|
||||
|
||||
CS_IDLE;
|
||||
// CD_DATA;
|
||||
WR_IDLE;
|
||||
RD_IDLE;
|
||||
|
||||
@@ -328,7 +592,6 @@ void Adafruit_TFTLCD::reset(void) {
|
||||
// Relevant to rect/screen fills and H/V lines. Input coordinates are
|
||||
// assumed pre-sorted (e.g. x2 >= x1).
|
||||
void Adafruit_TFTLCD::setAddrWindow(int x1, int y1, int x2, int y2) {
|
||||
|
||||
CS_ACTIVE;
|
||||
if(driver == ID_932X) {
|
||||
|
||||
@@ -388,6 +651,18 @@ void Adafruit_TFTLCD::setAddrWindow(int x1, int y1, int x2, int y2) {
|
||||
writeRegisterPair(HX8347G_COLADDREND_HI , HX8347G_COLADDREND_LO , x2);
|
||||
writeRegisterPair(HX8347G_ROWADDREND_HI , HX8347G_ROWADDREND_LO , y2);
|
||||
|
||||
} else if ((driver == ID_9341) || (driver == ID_HX8357D)){
|
||||
uint32_t t;
|
||||
|
||||
t = x1;
|
||||
t <<= 16;
|
||||
t |= x2;
|
||||
writeRegister32(ILI9341_COLADDRSET, t); // HX8357D uses same registers!
|
||||
t = y1;
|
||||
t <<= 16;
|
||||
t |= y2;
|
||||
writeRegister32(ILI9341_PAGEADDRSET, t); // HX8357D uses same registers!
|
||||
|
||||
}
|
||||
CS_IDLE;
|
||||
}
|
||||
@@ -415,11 +690,42 @@ void Adafruit_TFTLCD::flood(uint16_t color, uint32_t len) {
|
||||
|
||||
CS_ACTIVE;
|
||||
CD_COMMAND;
|
||||
if(driver == ID_932X) write8(0x00); // High byte of GRAM register...
|
||||
write8(0x22); // Write data to GRAM
|
||||
if (driver == ID_9341) {
|
||||
write8(0x2C);
|
||||
} else if (driver == ID_932X) {
|
||||
write8(0x00); // High byte of GRAM register...
|
||||
write8(0x22); // Write data to GRAM
|
||||
} else if (driver == ID_HX8357D) {
|
||||
write8(HX8357_RAMWR);
|
||||
} else {
|
||||
write8(0x22); // Write data to GRAM
|
||||
}
|
||||
CD_DATA;
|
||||
|
||||
#if defined(__SAMD51__)
|
||||
if(hi == lo) {
|
||||
pinPeripheral(clockpin, PIO_TIMER);
|
||||
desc->SRCADDR.reg = (uint32_t)&lo;
|
||||
desc->BTCTRL.bit.SRCINC = 0;
|
||||
uint32_t bytesToGo = len * 2;
|
||||
uint16_t bytesThisPass;
|
||||
// BTCNT is a 16-bit value, so large fills may require multiple DMA xfers
|
||||
while(bytesToGo > 0) {
|
||||
if(bytesToGo > 65535) bytesThisPass = 65535;
|
||||
else bytesThisPass = bytesToGo;
|
||||
desc->BTCNT.reg = bytesThisPass;
|
||||
transfer_is_done = false;
|
||||
stat = myDMA.startJob();
|
||||
myDMA.trigger();
|
||||
while(!transfer_is_done);
|
||||
bytesToGo -= bytesThisPass;
|
||||
}
|
||||
pinPeripheral(clockpin, PIO_OUTPUT);
|
||||
} else {
|
||||
#endif
|
||||
|
||||
// Write first pixel normally, decrement counter by 1
|
||||
CD_DATA;
|
||||
//CD_DATA;
|
||||
write8(hi);
|
||||
write8(lo);
|
||||
len--;
|
||||
@@ -430,7 +736,7 @@ void Adafruit_TFTLCD::flood(uint16_t color, uint32_t len) {
|
||||
// on the port(s) and just toggle the write strobe.
|
||||
while(blocks--) {
|
||||
i = 16; // 64 pixels/block / 4 pixels/pass
|
||||
do {
|
||||
do {
|
||||
WR_STROBE; WR_STROBE; WR_STROBE; WR_STROBE; // 2 bytes/pixel
|
||||
WR_STROBE; WR_STROBE; WR_STROBE; WR_STROBE; // x 4 pixels
|
||||
} while(--i);
|
||||
@@ -453,6 +759,11 @@ void Adafruit_TFTLCD::flood(uint16_t color, uint32_t len) {
|
||||
write8(lo);
|
||||
}
|
||||
}
|
||||
|
||||
#if defined(__SAMD51__)
|
||||
}
|
||||
#endif
|
||||
|
||||
CS_IDLE;
|
||||
}
|
||||
|
||||
@@ -556,14 +867,12 @@ void Adafruit_TFTLCD::fillScreen(uint16_t color) {
|
||||
writeRegister16(0x0020, x);
|
||||
writeRegister16(0x0021, y);
|
||||
|
||||
} else if(driver == ID_7575) {
|
||||
|
||||
// For the 7575, there is no settable address pointer, instead the
|
||||
} else if ((driver == ID_9341) || (driver == ID_7575) || (driver == ID_HX8357D)) {
|
||||
// For these, there is no settable address pointer, instead the
|
||||
// address window must be set for each drawing operation. However,
|
||||
// this display takes rotation into account for the parameters, no
|
||||
// need to do extra rotation math here.
|
||||
setAddrWindow(0, 0, _width - 1, _height - 1);
|
||||
|
||||
}
|
||||
flood(color, (long)TFTWIDTH * (long)TFTHEIGHT);
|
||||
}
|
||||
@@ -612,7 +921,15 @@ void Adafruit_TFTLCD::drawPixel(int16_t x, int16_t y, uint16_t color) {
|
||||
hi = color >> 8; lo = color;
|
||||
CD_COMMAND; write8(0x22); CD_DATA; write8(hi); write8(lo);
|
||||
|
||||
} else if ((driver == ID_9341) || (driver == ID_HX8357D)) {
|
||||
setAddrWindow(x, y, _width-1, _height-1);
|
||||
CS_ACTIVE;
|
||||
CD_COMMAND;
|
||||
write8(0x2C);
|
||||
CD_DATA;
|
||||
write8(color >> 8); write8(color);
|
||||
}
|
||||
|
||||
CS_IDLE;
|
||||
}
|
||||
|
||||
@@ -620,16 +937,50 @@ void Adafruit_TFTLCD::drawPixel(int16_t x, int16_t y, uint16_t color) {
|
||||
// externally by BMP examples. Assumes that setWindowAddr() has
|
||||
// previously been set to define the bounds. Max 255 pixels at
|
||||
// a time (BMP examples read in small chunks due to limited RAM).
|
||||
#if defined(__SAMD51__)
|
||||
void Adafruit_TFTLCD::pushColors(uint16_t *data, uint16_t len, boolean first) {
|
||||
#else
|
||||
void Adafruit_TFTLCD::pushColors(uint16_t *data, uint8_t len, boolean first) {
|
||||
#endif
|
||||
uint16_t color;
|
||||
uint8_t hi, lo;
|
||||
CS_ACTIVE;
|
||||
if(first == true) { // Issue GRAM write command only on first call
|
||||
CD_COMMAND;
|
||||
if(driver == ID_932X) write8(0x00);
|
||||
write8(0x22);
|
||||
if (driver == ID_9341) {
|
||||
write8(0x2C);
|
||||
} else if (driver == ID_932X) {
|
||||
write8(0x00); // High byte of GRAM register...
|
||||
write8(0x22); // Write data to GRAM
|
||||
} else if (driver == ID_HX8357D) {
|
||||
write8(HX8357_RAMWR);
|
||||
} else {
|
||||
write8(0x22); // Write data to GRAM
|
||||
}
|
||||
}
|
||||
CD_DATA;
|
||||
|
||||
#if defined(__SAMD51__)
|
||||
pinPeripheral(clockpin, PIO_TIMER);
|
||||
desc->BTCTRL.bit.SRCINC = 1;
|
||||
uint8_t *dataPtr = (uint8_t *)data; // -> 1st byte of data
|
||||
uint32_t bytesToGo = len * 2;
|
||||
uint16_t bytesThisPass;
|
||||
// BTCNT is a 16-bit value, so large fills may require multiple DMA xfers
|
||||
while(bytesToGo > 0) {
|
||||
if(bytesToGo > 65535) bytesThisPass = 65535;
|
||||
else bytesThisPass = bytesToGo;
|
||||
desc->SRCADDR.reg = (uint32_t)dataPtr + bytesThisPass;
|
||||
desc->BTCNT.reg = bytesThisPass;
|
||||
transfer_is_done = false;
|
||||
stat = myDMA.startJob();
|
||||
myDMA.trigger();
|
||||
while(!transfer_is_done);
|
||||
bytesToGo -= bytesThisPass;
|
||||
dataPtr += bytesThisPass;
|
||||
}
|
||||
pinPeripheral(clockpin, PIO_OUTPUT);
|
||||
#else
|
||||
while(len--) {
|
||||
color = *data++;
|
||||
hi = color >> 8; // Don't simplify or merge these
|
||||
@@ -637,6 +988,66 @@ void Adafruit_TFTLCD::pushColors(uint16_t *data, uint8_t len, boolean first) {
|
||||
write8(hi); // going on.
|
||||
write8(lo);
|
||||
}
|
||||
#endif
|
||||
CS_IDLE;
|
||||
}
|
||||
|
||||
void Adafruit_TFTLCD::pushColorsDMA(
|
||||
uint32_t bytesToGo,
|
||||
uint8_t *buffer,
|
||||
uint16_t bufSize,
|
||||
void (*callback)(uint8_t *dest, uint16_t len)) {
|
||||
CS_ACTIVE;
|
||||
CD_COMMAND;
|
||||
if(driver == ID_9341) {
|
||||
write8(0x2C);
|
||||
} else if(driver == ID_932X) {
|
||||
write8(0x00); // High byte of GRAM register...
|
||||
write8(0x22); // Write data to GRAM
|
||||
} else if (driver == ID_HX8357D) {
|
||||
write8(HX8357_RAMWR);
|
||||
} else {
|
||||
write8(0x22); // Write data to GRAM
|
||||
}
|
||||
CD_DATA;
|
||||
|
||||
// Buffer passed in should be 2X bufSize bytes...
|
||||
uint8_t *buf[2];
|
||||
buf[0] = buffer; // First half of buffer
|
||||
buf[1] = buf[0] + bufSize; // Second half
|
||||
uint8_t idx = 2; // Active buffer 0/1 (2 = first pass; no xfer)
|
||||
|
||||
pinPeripheral(clockpin, PIO_TIMER);
|
||||
desc->BTCTRL.bit.SRCINC = 1;
|
||||
|
||||
uint16_t bytesThisPass;
|
||||
while(bytesToGo > 0) {
|
||||
if(idx < 2) {
|
||||
// Wait for prior transfer to finish
|
||||
while(!transfer_is_done);
|
||||
// Send from buf[idx]
|
||||
desc->SRCADDR.reg = (uint32_t)buf[idx] + bytesThisPass;
|
||||
desc->BTCNT.reg = bytesThisPass;
|
||||
transfer_is_done = false;
|
||||
stat = myDMA.startJob();
|
||||
myDMA.trigger();
|
||||
bytesToGo -= bytesThisPass; // Data sent
|
||||
idx = 1 - idx; // Toggle idx so data is loaded into alt buffer
|
||||
} else {
|
||||
// First pass, no xfer, just load...
|
||||
idx = 0;
|
||||
}
|
||||
// Load next data (if needed)
|
||||
if(bytesToGo) {
|
||||
if(bytesToGo > bufSize) bytesThisPass = bufSize;
|
||||
else bytesThisPass = bytesToGo;
|
||||
(*callback)(buf[idx], bytesThisPass);
|
||||
}
|
||||
}
|
||||
// Wait for last transfer to finish
|
||||
while(!transfer_is_done);
|
||||
pinPeripheral(clockpin, PIO_OUTPUT);
|
||||
|
||||
CS_IDLE;
|
||||
}
|
||||
|
||||
@@ -660,7 +1071,8 @@ void Adafruit_TFTLCD::setRotation(uint8_t x) {
|
||||
// For 932X, init default full-screen address window:
|
||||
setAddrWindow(0, 0, _width - 1, _height - 1); // CS_IDLE happens here
|
||||
|
||||
} if(driver == ID_7575) {
|
||||
}
|
||||
if(driver == ID_7575) {
|
||||
|
||||
uint8_t t;
|
||||
switch(rotation) {
|
||||
@@ -674,9 +1086,53 @@ void Adafruit_TFTLCD::setRotation(uint8_t x) {
|
||||
// drawPixel() cheats by setting only the top left...by default,
|
||||
// the lower right is always reset to the corner.
|
||||
setLR(); // CS_IDLE happens here
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
if (driver == ID_9341) {
|
||||
// MEME, HX8357D uses same registers as 9341 but different values
|
||||
uint16_t t;
|
||||
|
||||
switch (rotation) {
|
||||
case 2:
|
||||
t = ILI9341_MADCTL_MX | ILI9341_MADCTL_BGR;
|
||||
break;
|
||||
case 3:
|
||||
t = ILI9341_MADCTL_MV | ILI9341_MADCTL_BGR;
|
||||
break;
|
||||
case 0:
|
||||
t = ILI9341_MADCTL_MY | ILI9341_MADCTL_BGR;
|
||||
break;
|
||||
case 1:
|
||||
t = ILI9341_MADCTL_MX | ILI9341_MADCTL_MY | ILI9341_MADCTL_MV | ILI9341_MADCTL_BGR;
|
||||
break;
|
||||
}
|
||||
writeRegister8(ILI9341_MADCTL, t ); // MADCTL
|
||||
// For 9341, init default full-screen address window:
|
||||
setAddrWindow(0, 0, _width - 1, _height - 1); // CS_IDLE happens here
|
||||
}
|
||||
|
||||
if (driver == ID_HX8357D) {
|
||||
// MEME, HX8357D uses same registers as 9341 but different values
|
||||
uint16_t t;
|
||||
|
||||
switch (rotation) {
|
||||
case 2:
|
||||
t = HX8357B_MADCTL_RGB;
|
||||
break;
|
||||
case 3:
|
||||
t = HX8357B_MADCTL_MX | HX8357B_MADCTL_MV | HX8357B_MADCTL_RGB;
|
||||
break;
|
||||
case 0:
|
||||
t = HX8357B_MADCTL_MX | HX8357B_MADCTL_MY | HX8357B_MADCTL_RGB;
|
||||
break;
|
||||
case 1:
|
||||
t = HX8357B_MADCTL_MY | HX8357B_MADCTL_MV | HX8357B_MADCTL_RGB;
|
||||
break;
|
||||
}
|
||||
writeRegister8(ILI9341_MADCTL, t ); // MADCTL
|
||||
// For 8357, init default full-screen address window:
|
||||
setAddrWindow(0, 0, _width - 1, _height - 1); // CS_IDLE happens here
|
||||
}}
|
||||
|
||||
#ifdef read8isFunctionalized
|
||||
#define read8(x) x=read8fn()
|
||||
@@ -751,9 +1207,42 @@ uint16_t Adafruit_TFTLCD::readPixel(int16_t x, int16_t y) {
|
||||
|
||||
// Ditto with the read/write port directions, as above.
|
||||
uint16_t Adafruit_TFTLCD::readID(void) {
|
||||
uint16_t id;
|
||||
|
||||
// retry a bunch!
|
||||
for (int i = 0; i<5; i++) {
|
||||
id = readReg(0xD3);
|
||||
if (id == 0x9341) {
|
||||
return id;
|
||||
}
|
||||
}
|
||||
|
||||
uint8_t hi, lo;
|
||||
|
||||
/*
|
||||
for (uint8_t i=0; i<128; i++) {
|
||||
Serial.print("$"); Serial.print(i, HEX);
|
||||
Serial.print(" = 0x"); Serial.println(readReg(i), HEX);
|
||||
}
|
||||
*/
|
||||
|
||||
if (readReg(0x04) == 0x8000) { // eh close enough
|
||||
// setc!
|
||||
/*
|
||||
Serial.println("!");
|
||||
for (uint8_t i=0; i<254; i++) {
|
||||
Serial.print("$"); Serial.print(i, HEX);
|
||||
Serial.print(" = 0x"); Serial.println(readReg(i), HEX);
|
||||
}
|
||||
*/
|
||||
writeRegister24(HX8357D_SETC, 0xFF8357);
|
||||
delay(300);
|
||||
//Serial.println(readReg(0xD0), HEX);
|
||||
if (readReg(0xD0) == 0x990000) {
|
||||
return 0x8357;
|
||||
}
|
||||
}
|
||||
|
||||
CS_ACTIVE;
|
||||
CD_COMMAND;
|
||||
write8(0x00);
|
||||
@@ -765,7 +1254,38 @@ uint16_t Adafruit_TFTLCD::readID(void) {
|
||||
setWriteDir(); // Restore LCD data port(s) to WRITE configuration
|
||||
CS_IDLE;
|
||||
|
||||
return (hi << 8) | lo;
|
||||
id = hi; id <<= 8; id |= lo;
|
||||
return id;
|
||||
}
|
||||
|
||||
uint32_t Adafruit_TFTLCD::readReg(uint8_t r) {
|
||||
uint32_t id;
|
||||
uint8_t x;
|
||||
|
||||
// try reading register #4
|
||||
CS_ACTIVE;
|
||||
CD_COMMAND;
|
||||
write8(r);
|
||||
setReadDir(); // Set up LCD data port(s) for READ operations
|
||||
CD_DATA;
|
||||
delayMicroseconds(50);
|
||||
read8(x);
|
||||
id = x; // Do not merge or otherwise simplify
|
||||
id <<= 8; // these lines. It's an unfortunate
|
||||
read8(x);
|
||||
id |= x; // shenanigans that are going on.
|
||||
id <<= 8; // these lines. It's an unfortunate
|
||||
read8(x);
|
||||
id |= x; // shenanigans that are going on.
|
||||
id <<= 8; // these lines. It's an unfortunate
|
||||
read8(x);
|
||||
id |= x; // shenanigans that are going on.
|
||||
CS_IDLE;
|
||||
setWriteDir(); // Restore LCD data port(s) to WRITE configuration
|
||||
|
||||
//Serial.print("Read $"); Serial.print(r, HEX);
|
||||
//Serial.print(":\t0x"); Serial.println(id, HEX);
|
||||
return id;
|
||||
}
|
||||
|
||||
// Pass 8-bit (each) R,G,B, get back 16-bit packed color
|
||||
@@ -820,3 +1340,36 @@ void Adafruit_TFTLCD::writeRegisterPair(uint8_t aH, uint8_t aL, uint16_t d) {
|
||||
}
|
||||
#endif
|
||||
|
||||
|
||||
void Adafruit_TFTLCD::writeRegister24(uint8_t r, uint32_t d) {
|
||||
CS_ACTIVE;
|
||||
CD_COMMAND;
|
||||
write8(r);
|
||||
CD_DATA;
|
||||
delayMicroseconds(10);
|
||||
write8(d >> 16);
|
||||
delayMicroseconds(10);
|
||||
write8(d >> 8);
|
||||
delayMicroseconds(10);
|
||||
write8(d);
|
||||
CS_IDLE;
|
||||
|
||||
}
|
||||
|
||||
|
||||
void Adafruit_TFTLCD::writeRegister32(uint8_t r, uint32_t d) {
|
||||
CS_ACTIVE;
|
||||
CD_COMMAND;
|
||||
write8(r);
|
||||
CD_DATA;
|
||||
delayMicroseconds(10);
|
||||
write8(d >> 24);
|
||||
delayMicroseconds(10);
|
||||
write8(d >> 16);
|
||||
delayMicroseconds(10);
|
||||
write8(d >> 8);
|
||||
delayMicroseconds(10);
|
||||
write8(d);
|
||||
CS_IDLE;
|
||||
|
||||
}
|
||||
|
||||
+48
-18
@@ -11,11 +11,13 @@
|
||||
#else
|
||||
#include "WProgram.h"
|
||||
#endif
|
||||
|
||||
#include <Adafruit_GFX.h>
|
||||
|
||||
// **** IF USING THE LCD BREAKOUT BOARD, COMMENT OUT THIS NEXT LINE. ****
|
||||
// **** IF USING THE LCD SHIELD, LEAVE THE LINE ENABLED: ****
|
||||
#define USE_ADAFRUIT_SHIELD_PINOUT
|
||||
|
||||
//#define USE_ADAFRUIT_SHIELD_PINOUT 1
|
||||
|
||||
class Adafruit_TFTLCD : public Adafruit_GFX {
|
||||
|
||||
@@ -24,23 +26,31 @@ class Adafruit_TFTLCD : public Adafruit_GFX {
|
||||
Adafruit_TFTLCD(uint8_t cs, uint8_t cd, uint8_t wr, uint8_t rd, uint8_t rst);
|
||||
Adafruit_TFTLCD(void);
|
||||
|
||||
void begin(uint16_t id = 0x9325),
|
||||
drawPixel(int16_t x, int16_t y, uint16_t color),
|
||||
drawFastHLine(int16_t x0, int16_t y0, int16_t w, uint16_t color),
|
||||
drawFastVLine(int16_t x0, int16_t y0, int16_t h, uint16_t color),
|
||||
fillRect(int16_t x, int16_t y, int16_t w, int16_t h, uint16_t c),
|
||||
fillScreen(uint16_t color),
|
||||
reset(void),
|
||||
setRegisters8(uint8_t *ptr, uint8_t n),
|
||||
setRegisters16(uint16_t *ptr, uint8_t n),
|
||||
setRotation(uint8_t x),
|
||||
// These methods are public in order for BMP examples to work:
|
||||
setAddrWindow(int x1, int y1, int x2, int y2),
|
||||
pushColors(uint16_t *data, uint8_t len, boolean first);
|
||||
void begin(uint16_t id = 0x9325);
|
||||
void drawPixel(int16_t x, int16_t y, uint16_t color);
|
||||
void drawFastHLine(int16_t x0, int16_t y0, int16_t w, uint16_t color);
|
||||
void drawFastVLine(int16_t x0, int16_t y0, int16_t h, uint16_t color);
|
||||
void fillRect(int16_t x, int16_t y, int16_t w, int16_t h, uint16_t c);
|
||||
void fillScreen(uint16_t color);
|
||||
void reset(void);
|
||||
void setRegisters8(uint8_t *ptr, uint8_t n);
|
||||
void setRegisters16(uint16_t *ptr, uint8_t n);
|
||||
void setRotation(uint8_t x);
|
||||
// These methods are public in order for BMP examples to work:
|
||||
void setAddrWindow(int x1, int y1, int x2, int y2);
|
||||
#if defined(__SAMD51__)
|
||||
void pushColors(uint16_t *data, uint16_t len, boolean first);
|
||||
#else
|
||||
void pushColors(uint16_t *data, uint8_t len, boolean first);
|
||||
#endif
|
||||
void pushColorsDMA(uint32_t totalBytes, uint8_t *buffer,
|
||||
uint16_t bufSize, void (*callback)(uint8_t *dest, uint16_t len));
|
||||
|
||||
|
||||
uint16_t color565(uint8_t r, uint8_t g, uint8_t b),
|
||||
readPixel(int16_t x, int16_t y),
|
||||
readID(void);
|
||||
uint32_t readReg(uint8_t r);
|
||||
|
||||
private:
|
||||
|
||||
@@ -62,21 +72,41 @@ class Adafruit_TFTLCD : public Adafruit_GFX {
|
||||
#ifndef writeRegister16
|
||||
writeRegister16(uint16_t a, uint16_t d),
|
||||
#endif
|
||||
writeRegister24(uint8_t a, uint32_t d),
|
||||
writeRegister32(uint8_t a, uint32_t d),
|
||||
#ifndef writeRegisterPair
|
||||
writeRegisterPair(uint8_t aH, uint8_t aL, uint16_t d),
|
||||
#endif
|
||||
setLR(void),
|
||||
flood(uint16_t color, uint32_t len);
|
||||
uint8_t driver;
|
||||
|
||||
#ifndef read8
|
||||
uint8_t read8fn(void);
|
||||
#define read8isFunctionalized
|
||||
#endif
|
||||
|
||||
#ifndef USE_ADAFRUIT_SHIELD_PINOUT
|
||||
volatile uint8_t *csPort , *cdPort , *wrPort , *rdPort;
|
||||
uint8_t csPinSet , cdPinSet , wrPinSet , rdPinSet ,
|
||||
csPinUnset, cdPinUnset, wrPinUnset, rdPinUnset,
|
||||
_reset;
|
||||
|
||||
#ifdef __AVR__
|
||||
volatile uint8_t *csPort , *cdPort , *wrPort , *rdPort;
|
||||
uint8_t csPinSet , cdPinSet , wrPinSet , rdPinSet ,
|
||||
csPinUnset, cdPinUnset, wrPinUnset, rdPinUnset,
|
||||
_reset;
|
||||
#elif defined(__SAM3X8E__)
|
||||
Pio *csPort , *cdPort , *wrPort , *rdPort;
|
||||
uint32_t csPinSet , cdPinSet , wrPinSet , rdPinSet ,
|
||||
csPinUnset, cdPinUnset, wrPinUnset, rdPinUnset,
|
||||
_reset;
|
||||
#elif defined(__SAMD51__)
|
||||
volatile uint32_t *csPortSet , *cdPortSet , *wrPortSet , *rdPortSet,
|
||||
*csPortClr , *cdPortClr , *wrPortClr , *rdPortClr;
|
||||
uint32_t csPinMask , cdPinMask , wrPinMask , rdPinMask,
|
||||
_reset;
|
||||
volatile uint8_t *writePort, *readPort, *dirSet, *dirClr;
|
||||
|
||||
#endif
|
||||
|
||||
#endif
|
||||
};
|
||||
|
||||
|
||||
@@ -1,32 +1,39 @@
|
||||
// IMPORTANT: Adafruit_TFTLCD LIBRARY MUST BE SPECIFICALLY
|
||||
// CONFIGURED FOR EITHER THE TFT SHIELD OR THE BREAKOUT BOARD.
|
||||
// SEE RELEVANT COMMENTS IN Adafruit_TFTLCD.h FOR SETUP.
|
||||
// Graphics test rigged specifically for the SAMD21 branch
|
||||
// of TFTLCD and the ItsyBitsy M4 board. TFTLCD lib MUST be
|
||||
// configured for the breakout board option, plus there's
|
||||
// some wiring shenanigans...
|
||||
|
||||
// LCD_WR MUST go to pin D4, because we're using a specific
|
||||
// timer/counter for PWM output. The pin # could be changed
|
||||
// IF a corresponding timer change is made in the SAMD21 TFTLIB.
|
||||
|
||||
// One of two additional wiring changes MUST be made. Either:
|
||||
// LCD_WR MUST go through an inverter (e.g. 74HC04)
|
||||
// -or-
|
||||
// The TFT 'CS' pin MUST be tied HIGH (ignoring LCD_CS setting)
|
||||
// If you opt for this latter arrangement, you CANNOT read the
|
||||
// device ID from the display (or anything else) -- see setup()
|
||||
// where 'identifier' is hardcoded;
|
||||
|
||||
// Data pins are as follows:
|
||||
// D0 connects to digital pin 0 (Notice these are
|
||||
// D1 connects to digital pin 1 NOT in order!)
|
||||
// D2 connects to digital pin 7
|
||||
// D3 connects to digital pin 9
|
||||
// D4 connects to digital pin 10
|
||||
// D5 connects to digital pin 11
|
||||
// D6 connects to digital pin 13
|
||||
// D7 connects to digital pin 12
|
||||
|
||||
#include <Adafruit_GFX.h> // Core graphics library
|
||||
#include <Adafruit_TFTLCD.h> // Hardware-specific library
|
||||
|
||||
// The control pins for the LCD can be assigned to any digital or
|
||||
// analog pins...but we'll use the analog pins as this allows us to
|
||||
// double up the pins with the touch screen (see the TFT paint example).
|
||||
#define LCD_CS A3 // Chip Select goes to Analog 3
|
||||
#define LCD_CD A2 // Command/Data goes to Analog 2
|
||||
#define LCD_WR A1 // LCD Write goes to Analog 1
|
||||
#define LCD_RD A0 // LCD Read goes to Analog 0
|
||||
#define LCD_CS A3 // Chip Select (see notes above)
|
||||
#define LCD_CD A2 // Command/Data
|
||||
#define LCD_RD A0 // LCD Read strobe
|
||||
#define LCD_WR 4 // LCD Write strobe (see notes above)
|
||||
|
||||
#define LCD_RESET A4 // Can alternately just connect to Arduino's reset pin
|
||||
|
||||
// When using the BREAKOUT BOARD only, use these 8 data lines to the LCD:
|
||||
// For the Arduino Uno, Duemilanove, Diecimila, etc.:
|
||||
// D0 connects to digital pin 8 (Notice these are
|
||||
// D1 connects to digital pin 9 NOT in order!)
|
||||
// D2 connects to digital pin 2
|
||||
// D3 connects to digital pin 3
|
||||
// D4 connects to digital pin 4
|
||||
// D5 connects to digital pin 5
|
||||
// D6 connects to digital pin 6
|
||||
// D7 connects to digital pin 7
|
||||
// For the Arduino Mega, use digital pins 22 through 29
|
||||
// (on the 2-row header at the end of the board).
|
||||
#define LCD_RESET A4 // Alternately just connect to Arduino's reset pin
|
||||
|
||||
// Assign human-readable names to some common 16-bit color values:
|
||||
#define BLACK 0x0000
|
||||
@@ -39,30 +46,36 @@
|
||||
#define WHITE 0xFFFF
|
||||
|
||||
Adafruit_TFTLCD tft(LCD_CS, LCD_CD, LCD_WR, LCD_RD, LCD_RESET);
|
||||
// If using the shield, all control and data lines are fixed, and
|
||||
// a simpler declaration can optionally be used:
|
||||
// Adafruit_TFTLCD tft;
|
||||
|
||||
void setup(void) {
|
||||
Serial.begin(9600);
|
||||
Serial.println(F("TFT LCD test"));
|
||||
|
||||
#ifdef USE_ADAFRUIT_SHIELD_PINOUT
|
||||
Serial.println(F("Using Adafruit 2.8\" TFT Arduino Shield Pinout"));
|
||||
#else
|
||||
Serial.println(F("Using Adafruit 2.8\" TFT Breakout Board Pinout"));
|
||||
#endif
|
||||
|
||||
Serial.print("TFT size is "); Serial.print(tft.width()); Serial.print("x"); Serial.println(tft.height());
|
||||
|
||||
tft.reset();
|
||||
|
||||
uint16_t identifier = tft.readID();
|
||||
|
||||
// SEE NOTES ABOVE - this is necessary IF using the
|
||||
// hard-wired CS (and no inverter) option.
|
||||
identifier = 0x9341;
|
||||
|
||||
if(identifier == 0x9325) {
|
||||
Serial.println(F("Found ILI9325 LCD driver"));
|
||||
} else if(identifier == 0x9328) {
|
||||
Serial.println(F("Found ILI9328 LCD driver"));
|
||||
} else if(identifier == 0x7575) {
|
||||
Serial.println(F("Found HX8347G LCD driver"));
|
||||
} else if(identifier == 0x9341) {
|
||||
Serial.println(F("Found ILI9341 LCD driver"));
|
||||
} else if(identifier == 0x8357) {
|
||||
Serial.println(F("Found HX8357D LCD driver"));
|
||||
} else {
|
||||
Serial.print(F("Unknown LCD driver chip: "));
|
||||
Serial.println(identifier, HEX);
|
||||
@@ -72,11 +85,30 @@ void setup(void) {
|
||||
Serial.println(F("If using the breakout board, it should NOT be #defined!"));
|
||||
Serial.println(F("Also if using the breakout, double-check that all wiring"));
|
||||
Serial.println(F("matches the tutorial."));
|
||||
return;
|
||||
}
|
||||
|
||||
tft.begin(identifier);
|
||||
|
||||
#if 0
|
||||
// Test frame rate:
|
||||
uint32_t startTime = millis();
|
||||
uint32_t frames = 0;
|
||||
for(;;) {
|
||||
tft.fillScreen(0x0000);
|
||||
frames++;
|
||||
// delay(500);
|
||||
tft.fillScreen(0xFFFF);
|
||||
frames++;
|
||||
// delay(500);
|
||||
if(!(frames & 0xFF)) {
|
||||
uint32_t elapsed = (millis() - startTime) / 1000;
|
||||
if(elapsed > 0) {
|
||||
Serial.println(frames / elapsed);
|
||||
}
|
||||
}
|
||||
}
|
||||
#endif
|
||||
|
||||
Serial.println(F("Benchmark Time (microseconds)"));
|
||||
|
||||
Serial.print(F("Screen fill "));
|
||||
@@ -377,4 +409,3 @@ unsigned long testFilledRoundRects() {
|
||||
|
||||
return micros() - start;
|
||||
}
|
||||
|
||||
|
||||
@@ -1,219 +0,0 @@
|
||||
// IMPORTANT: Adafruit_TFTLCD LIBRARY MUST BE SPECIFICALLY
|
||||
// CONFIGURED FOR EITHER THE TFT SHIELD OR THE BREAKOUT BOARD.
|
||||
// SEE RELEVANT COMMENTS IN Adafruit_TFTLCD.h FOR SETUP.
|
||||
|
||||
#include <Adafruit_GFX.h> // Core graphics library
|
||||
#include <Adafruit_TFTLCD.h> // Hardware-specific library
|
||||
|
||||
// The control pins for the LCD can be assigned to any digital or
|
||||
// analog pins...but we'll use the analog pins as this allows us to
|
||||
// double up the pins with the touch screen (see the TFT paint example).
|
||||
#define LCD_CS A3 // Chip Select goes to Analog 3
|
||||
#define LCD_CD A2 // Command/Data goes to Analog 2
|
||||
#define LCD_WR A1 // LCD Write goes to Analog 1
|
||||
#define LCD_RD A0 // LCD Read goes to Analog 0
|
||||
|
||||
#define LCD_RESET A4 // Can alternately just connect to Arduino's reset pin
|
||||
|
||||
// When using the BREAKOUT BOARD only, use these 8 data lines to the LCD:
|
||||
// For the Arduino Uno, Duemilanove, Diecimila, etc.:
|
||||
// D0 connects to digital pin 8 (Notice these are
|
||||
// D1 connects to digital pin 9 NOT in order!)
|
||||
// D2 connects to digital pin 2
|
||||
// D3 connects to digital pin 3
|
||||
// D4 connects to digital pin 4
|
||||
// D5 connects to digital pin 5
|
||||
// D6 connects to digital pin 6
|
||||
// D7 connects to digital pin 7
|
||||
// For the Arduino Mega, use digital pins 22 through 29
|
||||
// (on the 2-row header at the end of the board).
|
||||
|
||||
// Assign human-readable names to some common 16-bit color values:
|
||||
#define BLACK 0x0000
|
||||
#define BLUE 0x001F
|
||||
#define RED 0xF800
|
||||
#define GREEN 0x07E0
|
||||
#define CYAN 0x07FF
|
||||
#define MAGENTA 0xF81F
|
||||
#define YELLOW 0xFFE0
|
||||
#define WHITE 0xFFFF
|
||||
|
||||
Adafruit_TFTLCD tft(LCD_CS, LCD_CD, LCD_WR, LCD_RD, LCD_RESET);
|
||||
// If using the shield, all control and data lines are fixed, and
|
||||
// a simpler declaration can optionally be used:
|
||||
// Adafruit_TFTLCD tft;
|
||||
|
||||
void setup(void) {
|
||||
Serial.begin(9600);
|
||||
Serial.println(F("TFT LCD test"));
|
||||
|
||||
#ifdef USE_ADAFRUIT_SHIELD_PINOUT
|
||||
Serial.println(F("Using Adafruit 2.8\" TFT Arduino Shield Pinout"));
|
||||
#else
|
||||
Serial.println(F("Using Adafruit 2.8\" TFT Breakout Board Pinout"));
|
||||
#endif
|
||||
|
||||
tft.reset();
|
||||
|
||||
uint16_t identifier = tft.readID();
|
||||
|
||||
if(identifier == 0x9325) {
|
||||
Serial.println(F("Found ILI9325 LCD driver"));
|
||||
} else if(identifier == 0x9328) {
|
||||
Serial.println(F("Found ILI9328 LCD driver"));
|
||||
} else if(identifier == 0x7575) {
|
||||
Serial.println(F("Found HX8347G LCD driver"));
|
||||
} else {
|
||||
Serial.print(F("Unknown LCD driver chip: "));
|
||||
Serial.println(identifier, HEX);
|
||||
Serial.println(F("If using the Adafruit 2.8\" TFT Arduino shield, the line:"));
|
||||
Serial.println(F(" #define USE_ADAFRUIT_SHIELD_PINOUT"));
|
||||
Serial.println(F("should appear in the library header (Adafruit_TFT.h)."));
|
||||
Serial.println(F("If using the breakout board, it should NOT be #defined!"));
|
||||
Serial.println(F("Also if using the breakout, double-check that all wiring"));
|
||||
Serial.println(F("matches the tutorial."));
|
||||
return;
|
||||
}
|
||||
|
||||
tft.begin(identifier);
|
||||
|
||||
tft.fillScreen(BLACK);
|
||||
|
||||
Serial.println(F("This is a test of the rotation capabilities of the TFT library!"));
|
||||
Serial.println(F("Press <SEND> (or type a character) to advance"));
|
||||
}
|
||||
|
||||
void loop(void) {
|
||||
rotatePixel();
|
||||
rotateLine();
|
||||
rotateFastline();
|
||||
rotateDrawrect();
|
||||
rotateFillrect();
|
||||
rotateDrawcircle();
|
||||
rotateFillcircle();
|
||||
rotateText();
|
||||
}
|
||||
|
||||
void rotateText() {
|
||||
for (uint8_t i=0; i<4; i++) {
|
||||
tft.fillScreen(BLACK);
|
||||
Serial.println(tft.getRotation(), DEC);
|
||||
|
||||
tft.setCursor(0, 30);
|
||||
tft.setTextColor(RED);
|
||||
tft.setTextSize(1);
|
||||
tft.println("Hello World!");
|
||||
tft.setTextColor(YELLOW);
|
||||
tft.setTextSize(2);
|
||||
tft.println("Hello World!");
|
||||
tft.setTextColor(GREEN);
|
||||
tft.setTextSize(3);
|
||||
tft.println("Hello World!");
|
||||
tft.setTextColor(BLUE);
|
||||
tft.setTextSize(4);
|
||||
tft.print(1234.567);
|
||||
|
||||
while (!Serial.available());
|
||||
Serial.read(); Serial.read(); Serial.read();
|
||||
|
||||
tft.setRotation(tft.getRotation()+1);
|
||||
}
|
||||
}
|
||||
|
||||
void rotateFillcircle(void) {
|
||||
for (uint8_t i=0; i<4; i++) {
|
||||
tft.fillScreen(BLACK);
|
||||
Serial.println(tft.getRotation(), DEC);
|
||||
|
||||
tft.fillCircle(10, 30, 10, YELLOW);
|
||||
|
||||
while (!Serial.available());
|
||||
Serial.read(); Serial.read(); Serial.read();
|
||||
|
||||
tft.setRotation(tft.getRotation()+1);
|
||||
}
|
||||
}
|
||||
|
||||
void rotateDrawcircle(void) {
|
||||
for (uint8_t i=0; i<4; i++) {
|
||||
tft.fillScreen(BLACK);
|
||||
Serial.println(tft.getRotation(), DEC);
|
||||
|
||||
tft.drawCircle(10, 30, 10, YELLOW);
|
||||
|
||||
while (!Serial.available());
|
||||
Serial.read(); Serial.read(); Serial.read();
|
||||
|
||||
tft.setRotation(tft.getRotation()+1);
|
||||
}
|
||||
}
|
||||
|
||||
void rotateFillrect(void) {
|
||||
for (uint8_t i=0; i<4; i++) {
|
||||
tft.fillScreen(BLACK);
|
||||
Serial.println(tft.getRotation(), DEC);
|
||||
|
||||
tft.fillRect(10, 20, 10, 20, GREEN);
|
||||
|
||||
while (!Serial.available());
|
||||
Serial.read(); Serial.read(); Serial.read();
|
||||
|
||||
tft.setRotation(tft.getRotation()+1);
|
||||
}
|
||||
}
|
||||
|
||||
void rotateDrawrect(void) {
|
||||
for (uint8_t i=0; i<4; i++) {
|
||||
tft.fillScreen(BLACK);
|
||||
Serial.println(tft.getRotation(), DEC);
|
||||
|
||||
tft.drawRect(10, 20, 10, 20, GREEN);
|
||||
|
||||
while (!Serial.available());
|
||||
Serial.read(); Serial.read(); Serial.read();
|
||||
|
||||
tft.setRotation(tft.getRotation()+1);
|
||||
}
|
||||
}
|
||||
|
||||
void rotateFastline(void) {
|
||||
for (uint8_t i=0; i<4; i++) {
|
||||
tft.fillScreen(BLACK);
|
||||
Serial.println(tft.getRotation(), DEC);
|
||||
|
||||
tft.drawFastHLine(0, 20, tft.width(), RED);
|
||||
tft.drawFastVLine(20, 0, tft.height(), BLUE);
|
||||
|
||||
while (!Serial.available());
|
||||
Serial.read(); Serial.read(); Serial.read();
|
||||
|
||||
tft.setRotation(tft.getRotation()+1);
|
||||
}
|
||||
}
|
||||
|
||||
void rotateLine(void) {
|
||||
for (uint8_t i=0; i<4; i++) {
|
||||
tft.fillScreen(BLACK);
|
||||
Serial.println(tft.getRotation(), DEC);
|
||||
|
||||
tft.drawLine(tft.width()/2, tft.height()/2, 0, 0, RED);
|
||||
while (!Serial.available());
|
||||
Serial.read(); Serial.read(); Serial.read();
|
||||
|
||||
tft.setRotation(tft.getRotation()+1);
|
||||
}
|
||||
}
|
||||
|
||||
void rotatePixel(void) {
|
||||
for (uint8_t i=0; i<4; i++) {
|
||||
tft.fillScreen(BLACK);
|
||||
Serial.println(tft.getRotation(), DEC);
|
||||
|
||||
tft.drawPixel(10,20, RED);
|
||||
while (!Serial.available());
|
||||
Serial.read(); Serial.read(); Serial.read();
|
||||
|
||||
tft.setRotation(tft.getRotation()+1);
|
||||
}
|
||||
}
|
||||
|
||||
+229
-53
@@ -1,58 +1,86 @@
|
||||
// BMP-loading example specifically for the TFTLCD breakout board.
|
||||
// If using the Arduino shield, use the tftbmp_shield.pde sketch instead!
|
||||
// If using an Arduino Mega, make sure the SD library is configured for
|
||||
// 'soft' SPI in the file Sd2Card.h.
|
||||
// BMP-loading demo rigged specifically for the SAMD21 branch
|
||||
// of TFTLCD and the ItsyBitsy M4 board. TFTLCD lib MUST be
|
||||
// configured for the breakout board option, plus there's
|
||||
// some wiring shenanigans...
|
||||
|
||||
// LCD_WR MUST go to pin D4, because we're using a specific
|
||||
// timer/counter for PWM output. The pin # could be changed
|
||||
// IF a corresponding timer change is made in the SAMD21 TFTLIB.
|
||||
|
||||
// One of two additional wiring changes MUST be made. Either:
|
||||
// LCD_WR MUST go through an inverter (e.g. 74HC04)
|
||||
// -or-
|
||||
// The TFT 'CS' pin MUST be tied HIGH (ignoring LCD_CS setting)
|
||||
// If you opt for this latter arrangement, you CANNOT read the
|
||||
// device ID from the display (or anything else) -- see setup()
|
||||
// where 'identifier' is hardcoded;
|
||||
|
||||
// Data pins are as follows:
|
||||
// D0 connects to digital pin 0 (Notice these are
|
||||
// D1 connects to digital pin 1 NOT in order!)
|
||||
// D2 connects to digital pin 7
|
||||
// D3 connects to digital pin 9
|
||||
// D4 connects to digital pin 10
|
||||
// D5 connects to digital pin 11
|
||||
// D6 connects to digital pin 13
|
||||
// D7 connects to digital pin 12
|
||||
|
||||
#include <SD.h>
|
||||
#include <Adafruit_GFX.h> // Core graphics library
|
||||
#include <Adafruit_TFTLCD.h> // Hardware-specific library
|
||||
#include <SD.h>
|
||||
|
||||
// The control pins for the LCD can be assigned to any digital or
|
||||
// analog pins...but we'll use the analog pins as this allows us to
|
||||
// double up the pins with the touch screen (see the TFT paint example).
|
||||
#define LCD_CS A3 // Chip Select goes to Analog 3
|
||||
#define LCD_CD A2 // Command/Data goes to Analog 2
|
||||
#define LCD_WR A1 // LCD Write goes to Analog 1
|
||||
#define LCD_RD A0 // LCD Read goes to Analog 0
|
||||
#define LCD_CS A3 // Chip Select (see notes above)
|
||||
#define LCD_CD A2 // Command/Data
|
||||
#define LCD_RD A0 // LCD Read strobe
|
||||
#define LCD_WR 4 // LCD Write strobe (see notes above)
|
||||
|
||||
// When using the BREAKOUT BOARD only, use these 8 data lines to the LCD:
|
||||
// For the Arduino Uno, Duemilanove, Diecimila, etc.:
|
||||
// D0 connects to digital pin 8 (Notice these are
|
||||
// D1 connects to digital pin 9 NOT in order!)
|
||||
// D2 connects to digital pin 2
|
||||
// D3 connects to digital pin 3
|
||||
// D4 connects to digital pin 4
|
||||
// D5 connects to digital pin 5
|
||||
// D6 connects to digital pin 6
|
||||
// D7 connects to digital pin 7
|
||||
// For the Arduino Mega, use digital pins 22 through 29
|
||||
// (on the 2-row header at the end of the board).
|
||||
#define LCD_RESET A4 // Alternately just connect to Arduino's reset pin
|
||||
|
||||
// For Arduino Uno/Duemilanove, etc
|
||||
// connect the SD card with DI going to pin 11, DO going to pin 12 and SCK going to pin 13 (standard)
|
||||
// Then pin 10 goes to CS (or whatever you have set up)
|
||||
#define SD_CS 10 // Set the chip select line to whatever you use (10 doesnt conflict with the library)
|
||||
// DO NOT use the SD card slot on the TFT breakout -- it doesn't
|
||||
// appear to work when using the parallel interface. Instead, a
|
||||
// separate SD breakout is needed.
|
||||
|
||||
#define SD_CS A5 // SD card delect
|
||||
|
||||
// A switch or jumper on A1 selects DMA vs non-DMA BMP loading.
|
||||
// There's really not a huge performance difference in this case
|
||||
// just because the bottleneck is in the SD card access and color
|
||||
// conversion operations...BUT...it does demonstrate how the
|
||||
// pushColorsDMA() function works, and how to use a callback to
|
||||
// load the next block of data while the current block is sent.
|
||||
#define DMA_SELECT A1 // Hi/lo chooses DMA vs non-DMA DMA loader
|
||||
|
||||
// In the SD card, place 24 bit color BMP files (be sure they are 24-bit!)
|
||||
// There are examples in the sketch folder
|
||||
|
||||
// our TFT wiring
|
||||
Adafruit_TFTLCD tft(LCD_CS, LCD_CD, LCD_WR, LCD_RD, A4);
|
||||
Adafruit_TFTLCD tft(LCD_CS, LCD_CD, LCD_WR, LCD_RD, LCD_RESET);
|
||||
|
||||
void setup()
|
||||
{
|
||||
Serial.begin(9600);
|
||||
while(!Serial);
|
||||
|
||||
pinMode(DMA_SELECT, INPUT_PULLUP);
|
||||
|
||||
tft.reset();
|
||||
|
||||
uint16_t identifier = tft.readID();
|
||||
|
||||
// SEE NOTES ABOVE - this is necessary IF using the
|
||||
// hard-wired CS (and no inverter) option.
|
||||
identifier = 0x9341;
|
||||
|
||||
if(identifier == 0x9325) {
|
||||
Serial.println(F("Found ILI9325 LCD driver"));
|
||||
} else if(identifier == 0x9328) {
|
||||
Serial.println(F("Found ILI9328 LCD driver"));
|
||||
} else if(identifier == 0x7575) {
|
||||
Serial.println(F("Found HX8347G LCD driver"));
|
||||
} else if(identifier == 0x9341) {
|
||||
Serial.println(F("Found ILI9341 LCD driver"));
|
||||
} else if(identifier == 0x8357) {
|
||||
Serial.println(F("Found HX8357D LCD driver"));
|
||||
} else {
|
||||
Serial.print(F("Unknown LCD driver chip: "));
|
||||
Serial.println(identifier, HEX);
|
||||
@@ -66,16 +94,23 @@ void setup()
|
||||
}
|
||||
|
||||
tft.begin(identifier);
|
||||
tft.fillScreen(0);
|
||||
|
||||
Serial.print(F("Initializing SD card..."));
|
||||
if (!SD.begin(SD_CS)) {
|
||||
Serial.println(F("failed!"));
|
||||
return;
|
||||
tft.fillScreen(0xF800);
|
||||
for(;;);
|
||||
}
|
||||
Serial.println(F("OK!"));
|
||||
|
||||
bmpDraw("woof.bmp", 0, 0);
|
||||
delay(1000);
|
||||
Serial.println(F("OK!"));
|
||||
tft.fillScreen(0x001F);
|
||||
|
||||
if(digitalRead(DMA_SELECT))
|
||||
bmpDrawDMA("woof.bmp", 0, 0);
|
||||
else
|
||||
bmpDraw("woof.bmp", 0, 0);
|
||||
// delay(1000);
|
||||
}
|
||||
|
||||
void loop()
|
||||
@@ -84,12 +119,39 @@ void loop()
|
||||
tft.setRotation(i);
|
||||
tft.fillScreen(0);
|
||||
for(int j=0; j <= 200; j += 50) {
|
||||
bmpDraw("miniwoof.bmp", j, j);
|
||||
if(digitalRead(DMA_SELECT))
|
||||
bmpDrawDMA("miniwoof.bmp", j, j);
|
||||
else
|
||||
bmpDraw("miniwoof.bmp", j, j);
|
||||
}
|
||||
delay(1000);
|
||||
// delay(1000);
|
||||
}
|
||||
}
|
||||
|
||||
// Common functions/vars for both BMP loaders ------------------------------
|
||||
|
||||
// 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;
|
||||
}
|
||||
|
||||
// "Vanilla" (non-DMA) BMP Loader ------------------------------------------
|
||||
|
||||
// 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
|
||||
@@ -98,10 +160,9 @@ void loop()
|
||||
// makes loading a little faster. 20 pixels seems a
|
||||
// good balance.
|
||||
|
||||
#define BUFFPIXEL 20
|
||||
#define BUFFPIXEL 64
|
||||
|
||||
void bmpDraw(char *filename, int x, int y) {
|
||||
|
||||
File bmpFile;
|
||||
int bmpWidth, bmpHeight; // W+H in pixels
|
||||
uint8_t bmpDepth; // Bit depth (currently must be 24)
|
||||
@@ -117,6 +178,7 @@ void bmpDraw(char *filename, int x, int y) {
|
||||
uint32_t pos = 0, startTime = millis();
|
||||
uint8_t lcdidx = 0;
|
||||
boolean first = true;
|
||||
uint16_t col16;
|
||||
|
||||
if((x >= tft.width()) || (y >= tft.height())) return;
|
||||
|
||||
@@ -203,7 +265,8 @@ void bmpDraw(char *filename, int x, int y) {
|
||||
b = sdbuffer[buffidx++];
|
||||
g = sdbuffer[buffidx++];
|
||||
r = sdbuffer[buffidx++];
|
||||
lcdbuffer[lcdidx++] = tft.color565(r,g,b);
|
||||
col16 = tft.color565(r,g,b);
|
||||
lcdbuffer[lcdidx++] = (col16 * 0x00010001) >> 8; // Flip hi/lo bytes
|
||||
} // end pixel
|
||||
} // end scanline
|
||||
// Write any remaining data to LCD
|
||||
@@ -216,28 +279,141 @@ void bmpDraw(char *filename, int x, int y) {
|
||||
} // end goodBmp
|
||||
}
|
||||
}
|
||||
tft.setAddrWindow(0, 0, tft.width() - 1, tft.height() - 1);
|
||||
|
||||
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.
|
||||
// DMA BMP Loader ----------------------------------------------------------
|
||||
|
||||
uint16_t read16(File f) {
|
||||
uint16_t result;
|
||||
((uint8_t *)&result)[0] = f.read(); // LSB
|
||||
((uint8_t *)&result)[1] = f.read(); // MSB
|
||||
return result;
|
||||
// DMA buffer: 320 pixels max width, DMALINES height, 2 bytes/pixel, 2 bufs
|
||||
// SD buffer: 320 pixels max width, one scanline
|
||||
#define DMALINES 16
|
||||
uint8_t dmabuf[DMALINES * 320 * 2 * 2];
|
||||
uint8_t sdbuf[320 * 3];
|
||||
|
||||
File bmpFile;
|
||||
uint32_t bmpImageoffset; // Start of image data in file
|
||||
int lineNum, linesToGo; // Current, remaining lines to load
|
||||
boolean flip; // BMP is stored bottom-to-top
|
||||
int bmpHeight; // Uncropped height in pixels
|
||||
int croppedWidth; // Cropped width in pixels
|
||||
uint32_t rowSize; // Not always bmpWidth; may have padding
|
||||
|
||||
void bmpCallback(uint8_t *dest, uint16_t len) {
|
||||
int row, col, linesThisPass;
|
||||
uint8_t r, g, b, *ptr;
|
||||
uint16_t col16;
|
||||
uint32_t pos;
|
||||
|
||||
linesThisPass = (linesToGo > DMALINES) ? DMALINES : linesToGo;
|
||||
|
||||
for(row=0; row<linesThisPass; row++, lineNum++) { // 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 - lineNum) * rowSize;
|
||||
else // Bitmap is stored top-to-bottom
|
||||
pos = bmpImageoffset + lineNum * rowSize;
|
||||
if(bmpFile.position() != pos) { // Need seek?
|
||||
bmpFile.seek(pos);
|
||||
}
|
||||
|
||||
bmpFile.read(sdbuf, croppedWidth * 3); // Read scanline
|
||||
ptr = sdbuf;
|
||||
for(col=0; col<croppedWidth; col++) { // For each column...
|
||||
// Convert pixel from BMP to TFT format
|
||||
b = *ptr++;
|
||||
g = *ptr++;
|
||||
r = *ptr++;
|
||||
col16 = tft.color565(r,g,b);
|
||||
*dest++ = col16 >> 8; // High byte
|
||||
*dest++ = col16; // Low byte
|
||||
} // end pixel
|
||||
} // end scanline
|
||||
|
||||
linesToGo -= linesThisPass;
|
||||
}
|
||||
|
||||
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;
|
||||
void bmpDrawDMA(char *filename, int x, int y) {
|
||||
int bmpWidth; // Image width in pixels
|
||||
uint8_t bmpDepth; // Bit depth (currently must be 24)
|
||||
boolean goodBmp = false; // Set to true on valid header parse
|
||||
int w, h;
|
||||
uint32_t 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.println(F("File not found"));
|
||||
return;
|
||||
}
|
||||
|
||||
// Parse BMP header
|
||||
if(read16(bmpFile) == 0x4D42) { // BMP signature
|
||||
Serial.println(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;
|
||||
} else {
|
||||
flip = true;
|
||||
}
|
||||
|
||||
// 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);
|
||||
croppedWidth = w;
|
||||
lineNum = 0;
|
||||
linesToGo = h;
|
||||
tft.pushColorsDMA(w * h * 2, dmabuf, w * DMALINES * 2, bmpCallback);
|
||||
|
||||
Serial.print(F("Loaded in "));
|
||||
Serial.print(millis() - startTime);
|
||||
Serial.println(" ms");
|
||||
} // end goodBmp
|
||||
}
|
||||
}
|
||||
tft.setAddrWindow(0, 0, tft.width() - 1, tft.height() - 1);
|
||||
|
||||
bmpFile.close();
|
||||
if(!goodBmp) Serial.println(F("BMP format not recognized."));
|
||||
}
|
||||
|
||||
|
||||
@@ -1,225 +0,0 @@
|
||||
// BMP-loading example specifically for the TFTLCD Arduino shield.
|
||||
// If using the breakout board, use the tftbmp.pde sketch instead!
|
||||
// If using an Arduino Mega, make sure the SD library is configured for
|
||||
// 'soft' SPI in the file Sd2Card.h.
|
||||
|
||||
#include <Adafruit_GFX.h> // Core graphics library
|
||||
#include <Adafruit_TFTLCD.h> // Hardware-specific library
|
||||
#include <SD.h>
|
||||
|
||||
// In the SD card, place 24 bit color BMP files (be sure they are 24-bit!)
|
||||
// There are examples in the sketch folder
|
||||
|
||||
#define SD_CS 5 // Card select for shield use
|
||||
|
||||
Adafruit_TFTLCD tft;
|
||||
uint8_t spi_save;
|
||||
|
||||
void setup()
|
||||
{
|
||||
Serial.begin(9600);
|
||||
|
||||
tft.reset();
|
||||
|
||||
uint16_t identifier = tft.readID();
|
||||
|
||||
if(identifier == 0x9325) {
|
||||
Serial.println(F("Found ILI9325 LCD driver"));
|
||||
} else if(identifier == 0x9328) {
|
||||
Serial.println(F("Found ILI9328 LCD driver"));
|
||||
} else if(identifier == 0x7575) {
|
||||
Serial.println(F("Found HX8347G LCD driver"));
|
||||
} else {
|
||||
Serial.print(F("Unknown LCD driver chip: "));
|
||||
Serial.println(identifier, HEX);
|
||||
Serial.println(F("If using the Adafruit 2.8\" TFT Arduino shield, the line:"));
|
||||
Serial.println(F(" #define USE_ADAFRUIT_SHIELD_PINOUT"));
|
||||
Serial.println(F("should appear in the library header (Adafruit_TFT.h)."));
|
||||
Serial.println(F("If using the breakout board, it should NOT be #defined!"));
|
||||
Serial.println(F("Also if using the breakout, double-check that all wiring"));
|
||||
Serial.println(F("matches the tutorial."));
|
||||
return;
|
||||
}
|
||||
|
||||
tft.begin(identifier);
|
||||
|
||||
Serial.print(F("Initializing SD card..."));
|
||||
if (!SD.begin(SD_CS)) {
|
||||
Serial.println(F("failed!"));
|
||||
return;
|
||||
}
|
||||
Serial.println(F("OK!"));
|
||||
spi_save = SPCR;
|
||||
|
||||
bmpDraw("woof.bmp", 0, 0);
|
||||
delay(1000);
|
||||
}
|
||||
|
||||
void loop()
|
||||
{
|
||||
for(int i = 0; i<4; i++) {
|
||||
tft.setRotation(i);
|
||||
tft.fillScreen(0);
|
||||
for(int j=0; j <= 200; j += 50) {
|
||||
bmpDraw("miniwoof.bmp", j, j);
|
||||
}
|
||||
delay(1000);
|
||||
}
|
||||
}
|
||||
|
||||
// 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, int x, int 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 in buffer (R+G+B per pixel)
|
||||
uint16_t lcdbuffer[BUFFPIXEL]; // pixel out buffer (16-bit 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();
|
||||
uint8_t lcdidx = 0;
|
||||
boolean first = true;
|
||||
|
||||
if((x >= tft.width()) || (y >= tft.height())) return;
|
||||
|
||||
Serial.println();
|
||||
Serial.print("Loading image '");
|
||||
Serial.print(filename);
|
||||
Serial.println('\'');
|
||||
// Open requested file on SD card
|
||||
SPCR = spi_save;
|
||||
if ((bmpFile = SD.open(filename)) == NULL) {
|
||||
Serial.print("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
|
||||
SPCR = 0;
|
||||
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;
|
||||
SPCR = spi_save;
|
||||
if(bmpFile.position() != pos) { // Need seek?
|
||||
bmpFile.seek(pos);
|
||||
buffidx = sizeof(sdbuffer); // Force buffer reload
|
||||
}
|
||||
|
||||
for (col=0; col<w; col++) { // For each column...
|
||||
// Time to read more pixel data?
|
||||
if (buffidx >= sizeof(sdbuffer)) { // Indeed
|
||||
// Push LCD buffer to the display first
|
||||
if(lcdidx > 0) {
|
||||
SPCR = 0;
|
||||
tft.pushColors(lcdbuffer, lcdidx, first);
|
||||
lcdidx = 0;
|
||||
first = false;
|
||||
}
|
||||
SPCR = spi_save;
|
||||
bmpFile.read(sdbuffer, sizeof(sdbuffer));
|
||||
buffidx = 0; // Set index to beginning
|
||||
}
|
||||
|
||||
// Convert pixel from BMP to TFT format
|
||||
b = sdbuffer[buffidx++];
|
||||
g = sdbuffer[buffidx++];
|
||||
r = sdbuffer[buffidx++];
|
||||
lcdbuffer[lcdidx++] = tft.color565(r,g,b);
|
||||
} // end pixel
|
||||
} // end scanline
|
||||
// Write any remaining data to LCD
|
||||
if(lcdidx > 0) {
|
||||
SPCR = 0;
|
||||
tft.pushColors(lcdbuffer, lcdidx, first);
|
||||
}
|
||||
Serial.print(F("Loaded in "));
|
||||
Serial.print(millis() - startTime);
|
||||
Serial.println(" ms");
|
||||
} // end goodBmp
|
||||
}
|
||||
}
|
||||
|
||||
bmpFile.close();
|
||||
if(!goodBmp) Serial.println("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;
|
||||
}
|
||||
|
||||
@@ -1,174 +0,0 @@
|
||||
// Paint example specifically for the TFTLCD breakout board.
|
||||
// If using the Arduino shield, use the tftpaint_shield.pde sketch instead!
|
||||
// DOES NOT CURRENTLY WORK ON ARDUINO LEONARDO
|
||||
|
||||
#include <Adafruit_GFX.h> // Core graphics library
|
||||
#include <Adafruit_TFTLCD.h> // Hardware-specific library
|
||||
#include <TouchScreen.h>
|
||||
|
||||
// When using the BREAKOUT BOARD only, use these 8 data lines to the LCD:
|
||||
// For the Arduino Uno, Duemilanove, Diecimila, etc.:
|
||||
// D0 connects to digital pin 8 (Notice these are
|
||||
// D1 connects to digital pin 9 NOT in order!)
|
||||
// D2 connects to digital pin 2
|
||||
// D3 connects to digital pin 3
|
||||
// D4 connects to digital pin 4
|
||||
// D5 connects to digital pin 5
|
||||
// D6 connects to digital pin 6
|
||||
// D7 connects to digital pin 7
|
||||
// For the Arduino Mega, use digital pins 22 through 29
|
||||
// (on the 2-row header at the end of the board).
|
||||
|
||||
#define YP A3 // must be an analog pin, use "An" notation!
|
||||
#define XM A2 // must be an analog pin, use "An" notation!
|
||||
#define YM 9 // can be a digital pin
|
||||
#define XP 8 // can be a digital pin
|
||||
|
||||
#define TS_MINX 150
|
||||
#define TS_MINY 120
|
||||
#define TS_MAXX 920
|
||||
#define TS_MAXY 940
|
||||
|
||||
// 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 LCD_CS A3
|
||||
#define LCD_CD A2
|
||||
#define LCD_WR A1
|
||||
#define LCD_RD A0
|
||||
// optional
|
||||
#define LCD_RESET A4
|
||||
|
||||
// Assign human-readable names to some common 16-bit color values:
|
||||
#define BLACK 0x0000
|
||||
#define BLUE 0x001F
|
||||
#define RED 0xF800
|
||||
#define GREEN 0x07E0
|
||||
#define CYAN 0x07FF
|
||||
#define MAGENTA 0xF81F
|
||||
#define YELLOW 0xFFE0
|
||||
#define WHITE 0xFFFF
|
||||
|
||||
|
||||
Adafruit_TFTLCD tft(LCD_CS, LCD_CD, LCD_WR, LCD_RD, LCD_RESET);
|
||||
|
||||
#define BOXSIZE 40
|
||||
#define PENRADIUS 3
|
||||
int oldcolor, currentcolor;
|
||||
|
||||
void setup(void) {
|
||||
Serial.begin(9600);
|
||||
Serial.println(F("Paint!"));
|
||||
|
||||
tft.reset();
|
||||
|
||||
uint16_t identifier = tft.readID();
|
||||
|
||||
if(identifier == 0x9325) {
|
||||
Serial.println(F("Found ILI9325 LCD driver"));
|
||||
} else if(identifier == 0x9328) {
|
||||
Serial.println(F("Found ILI9328 LCD driver"));
|
||||
} else if(identifier == 0x7575) {
|
||||
Serial.println(F("Found HX8347G LCD driver"));
|
||||
} else {
|
||||
Serial.print(F("Unknown LCD driver chip: "));
|
||||
Serial.println(identifier, HEX);
|
||||
return;
|
||||
}
|
||||
|
||||
tft.begin(identifier);
|
||||
|
||||
tft.fillScreen(BLACK);
|
||||
|
||||
tft.fillRect(0, 0, BOXSIZE, BOXSIZE, RED);
|
||||
tft.fillRect(BOXSIZE, 0, BOXSIZE, BOXSIZE, YELLOW);
|
||||
tft.fillRect(BOXSIZE*2, 0, BOXSIZE, BOXSIZE, GREEN);
|
||||
tft.fillRect(BOXSIZE*3, 0, BOXSIZE, BOXSIZE, CYAN);
|
||||
tft.fillRect(BOXSIZE*4, 0, BOXSIZE, BOXSIZE, BLUE);
|
||||
tft.fillRect(BOXSIZE*5, 0, BOXSIZE, BOXSIZE, MAGENTA);
|
||||
// tft.fillRect(BOXSIZE*6, 0, BOXSIZE, BOXSIZE, WHITE);
|
||||
|
||||
tft.drawRect(0, 0, BOXSIZE, BOXSIZE, WHITE);
|
||||
currentcolor = RED;
|
||||
|
||||
pinMode(13, OUTPUT);
|
||||
}
|
||||
|
||||
#define MINPRESSURE 10
|
||||
#define MAXPRESSURE 1000
|
||||
|
||||
void loop()
|
||||
{
|
||||
digitalWrite(13, HIGH);
|
||||
Point p = ts.getPoint();
|
||||
digitalWrite(13, LOW);
|
||||
|
||||
// if sharing pins, you'll need to fix the directions of the touchscreen pins
|
||||
//pinMode(XP, OUTPUT);
|
||||
pinMode(XM, OUTPUT);
|
||||
pinMode(YP, OUTPUT);
|
||||
//pinMode(YM, OUTPUT);
|
||||
|
||||
// we have some minimum pressure we consider 'valid'
|
||||
// pressure of 0 means no pressing!
|
||||
|
||||
if (p.z > MINPRESSURE && p.z < MAXPRESSURE) {
|
||||
/*
|
||||
Serial.print("X = "); Serial.print(p.x);
|
||||
Serial.print("\tY = "); Serial.print(p.y);
|
||||
Serial.print("\tPressure = "); Serial.println(p.z);
|
||||
*/
|
||||
|
||||
if (p.y < (TS_MINY-5)) {
|
||||
Serial.println("erase");
|
||||
// press the bottom of the screen to erase
|
||||
tft.fillRect(0, BOXSIZE, tft.width(), tft.height()-BOXSIZE, BLACK);
|
||||
}
|
||||
// scale from 0->1023 to tft.width
|
||||
p.x = map(p.x, TS_MINX, TS_MAXX, tft.width(), 0);
|
||||
p.y = map(p.y, TS_MINY, TS_MAXY, tft.height(), 0);
|
||||
/*
|
||||
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 = RED;
|
||||
tft.drawRect(0, 0, BOXSIZE, BOXSIZE, WHITE);
|
||||
} else if (p.x < BOXSIZE*2) {
|
||||
currentcolor = YELLOW;
|
||||
tft.drawRect(BOXSIZE, 0, BOXSIZE, BOXSIZE, WHITE);
|
||||
} else if (p.x < BOXSIZE*3) {
|
||||
currentcolor = GREEN;
|
||||
tft.drawRect(BOXSIZE*2, 0, BOXSIZE, BOXSIZE, WHITE);
|
||||
} else if (p.x < BOXSIZE*4) {
|
||||
currentcolor = CYAN;
|
||||
tft.drawRect(BOXSIZE*3, 0, BOXSIZE, BOXSIZE, WHITE);
|
||||
} else if (p.x < BOXSIZE*5) {
|
||||
currentcolor = BLUE;
|
||||
tft.drawRect(BOXSIZE*4, 0, BOXSIZE, BOXSIZE, WHITE);
|
||||
} else if (p.x < BOXSIZE*6) {
|
||||
currentcolor = MAGENTA;
|
||||
tft.drawRect(BOXSIZE*5, 0, BOXSIZE, BOXSIZE, WHITE);
|
||||
}
|
||||
|
||||
if (oldcolor != currentcolor) {
|
||||
if (oldcolor == RED) tft.fillRect(0, 0, BOXSIZE, BOXSIZE, RED);
|
||||
if (oldcolor == YELLOW) tft.fillRect(BOXSIZE, 0, BOXSIZE, BOXSIZE, YELLOW);
|
||||
if (oldcolor == GREEN) tft.fillRect(BOXSIZE*2, 0, BOXSIZE, BOXSIZE, GREEN);
|
||||
if (oldcolor == CYAN) tft.fillRect(BOXSIZE*3, 0, BOXSIZE, BOXSIZE, CYAN);
|
||||
if (oldcolor == BLUE) tft.fillRect(BOXSIZE*4, 0, BOXSIZE, BOXSIZE, BLUE);
|
||||
if (oldcolor == MAGENTA) tft.fillRect(BOXSIZE*5, 0, BOXSIZE, BOXSIZE, MAGENTA);
|
||||
}
|
||||
}
|
||||
if (((p.y-PENRADIUS) > BOXSIZE) && ((p.y+PENRADIUS) < tft.height())) {
|
||||
tft.fillCircle(p.x, p.y, PENRADIUS, currentcolor);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1,163 +0,0 @@
|
||||
// Paint example specifically for the TFTLCD Arduino shield.
|
||||
// If using the breakout board, use the tftpaint.pde sketch instead!
|
||||
|
||||
#include <Adafruit_GFX.h> // Core graphics library
|
||||
#include <Adafruit_TFTLCD.h> // Hardware-specific library
|
||||
#include <TouchScreen.h>
|
||||
|
||||
#ifndef USE_ADAFRUIT_SHIELD_PINOUT
|
||||
#error "This sketch is intended for use with the TFT LCD Shield. Make sure that USE_ADAFRUIT_SHIELD_PINOUT is #defined in the Adafruit_TFTLCD.h library file."
|
||||
#endif
|
||||
|
||||
// These are the pins for the shield!
|
||||
#define YP A1 // must be an analog pin, use "An" notation!
|
||||
#define XM A2 // must be an analog pin, use "An" notation!
|
||||
#define YM 7 // can be a digital pin
|
||||
#define XP 6 // can be a digital pin
|
||||
|
||||
#define TS_MINX 150
|
||||
#define TS_MINY 120
|
||||
#define TS_MAXX 920
|
||||
#define TS_MAXY 940
|
||||
|
||||
// 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 LCD_CS A3
|
||||
#define LCD_CD A2
|
||||
#define LCD_WR A1
|
||||
#define LCD_RD A0
|
||||
|
||||
// Assign human-readable names to some common 16-bit color values:
|
||||
#define BLACK 0x0000
|
||||
#define BLUE 0x001F
|
||||
#define RED 0xF800
|
||||
#define GREEN 0x07E0
|
||||
#define CYAN 0x07FF
|
||||
#define MAGENTA 0xF81F
|
||||
#define YELLOW 0xFFE0
|
||||
#define WHITE 0xFFFF
|
||||
|
||||
|
||||
Adafruit_TFTLCD tft;
|
||||
|
||||
#define BOXSIZE 40
|
||||
#define PENRADIUS 4
|
||||
int oldcolor, currentcolor;
|
||||
|
||||
void setup(void) {
|
||||
Serial.begin(9600);
|
||||
Serial.println(F("Paint!"));
|
||||
|
||||
tft.reset();
|
||||
|
||||
uint16_t identifier = tft.readID();
|
||||
|
||||
if(identifier == 0x9325) {
|
||||
Serial.println(F("Found ILI9325 LCD driver"));
|
||||
} else if(identifier == 0x9328) {
|
||||
Serial.println(F("Found ILI9328 LCD driver"));
|
||||
} else if(identifier == 0x7575) {
|
||||
Serial.println(F("Found HX8347G LCD driver"));
|
||||
} else {
|
||||
Serial.print(F("Unknown LCD driver chip: "));
|
||||
Serial.println(identifier, HEX);
|
||||
return;
|
||||
}
|
||||
|
||||
tft.begin(identifier);
|
||||
|
||||
tft.fillScreen(BLACK);
|
||||
|
||||
tft.fillRect(0, 0, BOXSIZE, BOXSIZE, RED);
|
||||
tft.fillRect(BOXSIZE, 0, BOXSIZE, BOXSIZE, YELLOW);
|
||||
tft.fillRect(BOXSIZE*2, 0, BOXSIZE, BOXSIZE, GREEN);
|
||||
tft.fillRect(BOXSIZE*3, 0, BOXSIZE, BOXSIZE, CYAN);
|
||||
tft.fillRect(BOXSIZE*4, 0, BOXSIZE, BOXSIZE, BLUE);
|
||||
tft.fillRect(BOXSIZE*5, 0, BOXSIZE, BOXSIZE, MAGENTA);
|
||||
// tft.fillRect(BOXSIZE*6, 0, BOXSIZE, BOXSIZE, WHITE);
|
||||
|
||||
tft.drawRect(0, 0, BOXSIZE, BOXSIZE, WHITE);
|
||||
currentcolor = RED;
|
||||
|
||||
pinMode(13, OUTPUT);
|
||||
}
|
||||
|
||||
#define MINPRESSURE 10
|
||||
#define MAXPRESSURE 1000
|
||||
|
||||
void loop()
|
||||
{
|
||||
digitalWrite(13, HIGH);
|
||||
Point p = ts.getPoint();
|
||||
digitalWrite(13, LOW);
|
||||
|
||||
// if sharing pins, you'll need to fix the directions of the touchscreen pins
|
||||
//pinMode(XP, OUTPUT);
|
||||
pinMode(XM, OUTPUT);
|
||||
pinMode(YP, OUTPUT);
|
||||
//pinMode(YM, OUTPUT);
|
||||
|
||||
// we have some minimum pressure we consider 'valid'
|
||||
// pressure of 0 means no pressing!
|
||||
|
||||
if (p.z > MINPRESSURE && p.z < MAXPRESSURE) {
|
||||
/*
|
||||
Serial.print("X = "); Serial.print(p.x);
|
||||
Serial.print("\tY = "); Serial.print(p.y);
|
||||
Serial.print("\tPressure = "); Serial.println(p.z);
|
||||
*/
|
||||
|
||||
if (p.y < (TS_MINY-5)) {
|
||||
Serial.println("erase");
|
||||
// press the bottom of the screen to erase
|
||||
tft.fillRect(0, BOXSIZE, tft.width(), tft.height()-BOXSIZE, BLACK);
|
||||
}
|
||||
// scale from 0->1023 to tft.width
|
||||
p.x = map(p.x, TS_MINX, TS_MAXX, tft.width(), 0);
|
||||
p.y = map(p.y, TS_MINY, TS_MAXY, tft.height(), 0);
|
||||
/*
|
||||
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 = RED;
|
||||
tft.drawRect(0, 0, BOXSIZE, BOXSIZE, WHITE);
|
||||
} else if (p.x < BOXSIZE*2) {
|
||||
currentcolor = YELLOW;
|
||||
tft.drawRect(BOXSIZE, 0, BOXSIZE, BOXSIZE, WHITE);
|
||||
} else if (p.x < BOXSIZE*3) {
|
||||
currentcolor = GREEN;
|
||||
tft.drawRect(BOXSIZE*2, 0, BOXSIZE, BOXSIZE, WHITE);
|
||||
} else if (p.x < BOXSIZE*4) {
|
||||
currentcolor = CYAN;
|
||||
tft.drawRect(BOXSIZE*3, 0, BOXSIZE, BOXSIZE, WHITE);
|
||||
} else if (p.x < BOXSIZE*5) {
|
||||
currentcolor = BLUE;
|
||||
tft.drawRect(BOXSIZE*4, 0, BOXSIZE, BOXSIZE, WHITE);
|
||||
} else if (p.x < BOXSIZE*6) {
|
||||
currentcolor = MAGENTA;
|
||||
tft.drawRect(BOXSIZE*5, 0, BOXSIZE, BOXSIZE, WHITE);
|
||||
}
|
||||
|
||||
if (oldcolor != currentcolor) {
|
||||
if (oldcolor == RED) tft.fillRect(0, 0, BOXSIZE, BOXSIZE, RED);
|
||||
if (oldcolor == YELLOW) tft.fillRect(BOXSIZE, 0, BOXSIZE, BOXSIZE, YELLOW);
|
||||
if (oldcolor == GREEN) tft.fillRect(BOXSIZE*2, 0, BOXSIZE, BOXSIZE, GREEN);
|
||||
if (oldcolor == CYAN) tft.fillRect(BOXSIZE*3, 0, BOXSIZE, BOXSIZE, CYAN);
|
||||
if (oldcolor == BLUE) tft.fillRect(BOXSIZE*4, 0, BOXSIZE, BOXSIZE, BLUE);
|
||||
if (oldcolor == MAGENTA) tft.fillRect(BOXSIZE*5, 0, BOXSIZE, BOXSIZE, MAGENTA);
|
||||
}
|
||||
}
|
||||
if (((p.y-PENRADIUS) > BOXSIZE) && ((p.y+PENRADIUS) < tft.height())) {
|
||||
tft.fillCircle(p.x, p.y, PENRADIUS, currentcolor);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -0,0 +1,105 @@
|
||||
#include <SD.h>
|
||||
#include <Adafruit_GFX.h> // Core graphics library
|
||||
#include <Adafruit_TFTLCD.h> // Hardware-specific library
|
||||
|
||||
#define LCD_CS A3 // Chip Select (see notes above)
|
||||
#define LCD_CD A2 // Command/Data
|
||||
#define LCD_RD A0 // LCD Read strobe
|
||||
#define LCD_WR 4 // LCD Write strobe (see notes above)
|
||||
|
||||
#define LCD_RESET A4 // Alternately just connect to Arduino's reset pin
|
||||
|
||||
#define DMA_SELECT A1 // Hi/lo chooses DMA vs non-DMA effect
|
||||
|
||||
Adafruit_TFTLCD tft(LCD_CS, LCD_CD, LCD_WR, LCD_RD, LCD_RESET);
|
||||
|
||||
#define DMALINES 16
|
||||
// DMA buffer is 320 pixels * DMALINES * 2 bytes/pixel * 2 buffers
|
||||
uint8_t dmabuf[320 * DMALINES * 2 * 2];
|
||||
// Pixel buffer is slightly wider than screen, for X-scrolling
|
||||
uint16_t pixels[320 + 64];
|
||||
uint32_t startTime;
|
||||
|
||||
void setup()
|
||||
{
|
||||
Serial.begin(9600);
|
||||
while(!Serial);
|
||||
|
||||
pinMode(DMA_SELECT, INPUT_PULLUP);
|
||||
|
||||
// Initialize pixel buffer with alternating red and white bands,
|
||||
// 32 pixels wide. 0x00F8 is 16-bit red (0xF800) endian-swapped
|
||||
// so bytes can be copied directly to screen.
|
||||
for(int i=0; i<320+64; i++)
|
||||
pixels[i] = (i & 32) ? 0x00F8 : 0xFFFF;
|
||||
|
||||
tft.reset();
|
||||
|
||||
uint16_t identifier = tft.readID();
|
||||
|
||||
// SEE NOTES ABOVE - this is necessary IF using the
|
||||
// hard-wired CS (and no inverter) option.
|
||||
identifier = 0x9341;
|
||||
|
||||
if(identifier == 0x9325) {
|
||||
Serial.println(F("Found ILI9325 LCD driver"));
|
||||
} else if(identifier == 0x9328) {
|
||||
Serial.println(F("Found ILI9328 LCD driver"));
|
||||
} else if(identifier == 0x7575) {
|
||||
Serial.println(F("Found HX8347G LCD driver"));
|
||||
} else if(identifier == 0x9341) {
|
||||
Serial.println(F("Found ILI9341 LCD driver"));
|
||||
} else if(identifier == 0x8357) {
|
||||
Serial.println(F("Found HX8357D LCD driver"));
|
||||
} else {
|
||||
Serial.print(F("Unknown LCD driver chip: "));
|
||||
Serial.println(identifier, HEX);
|
||||
return;
|
||||
}
|
||||
|
||||
tft.begin(identifier);
|
||||
tft.setRotation(1);
|
||||
tft.fillScreen(0);
|
||||
startTime = millis();
|
||||
}
|
||||
|
||||
int lineNum;
|
||||
int frame = 0;
|
||||
|
||||
// pushColorsDMA() callback function -- fills DMALINES scanlines with
|
||||
// data from pixels[] array.
|
||||
void myCallback(uint8_t *dest, uint16_t len) {
|
||||
for(int i=0; i<DMALINES; i++) {
|
||||
// Wave up to 64 pixels horizontally (extra width in pixels[] array)
|
||||
int offset = (int)((sin((float)(lineNum + frame) / 40.0) + 1.0) * 31.5);
|
||||
// Change offset every 32 lines for checkerboard effect
|
||||
if((lineNum + frame/8) & 32) offset = (offset + 32) % 63;
|
||||
memcpy(dest, &pixels[offset], len / DMALINES);
|
||||
lineNum++;
|
||||
dest += 320 * 2; // Offset to next scanline (2 bytes/pixel)
|
||||
}
|
||||
}
|
||||
|
||||
void loop() {
|
||||
tft.setAddrWindow(0, 0, tft.width() - 1, tft.height() - 1);
|
||||
lineNum = 0;
|
||||
if(digitalRead(DMA_SELECT)) {
|
||||
tft.pushColorsDMA(tft.width() * tft.height() * 2, dmabuf, tft.width() * DMALINES * 2, myCallback);
|
||||
} else {
|
||||
bool first = true;
|
||||
while(lineNum < tft.height()) {
|
||||
// Fill the DMA buffer, but don't issue it
|
||||
myCallback(dmabuf, tft.width() * DMALINES * 2);
|
||||
// Then send it using non-DMA function:
|
||||
tft.pushColors((uint16_t *)dmabuf, tft.width() * DMALINES, first);
|
||||
first = false;
|
||||
}
|
||||
}
|
||||
frame++;
|
||||
uint32_t elapsed = (millis() - startTime) / 1000;
|
||||
if(elapsed > 0) {
|
||||
Serial.print(frame / elapsed);
|
||||
Serial.println(" fps");
|
||||
}
|
||||
}
|
||||
|
||||
+144
-10
@@ -32,11 +32,12 @@
|
||||
// given for each supported board.
|
||||
|
||||
// Shield pin usage:
|
||||
// LCD Data Bit : 7 6 5 4 3 2 1 0
|
||||
// Digital pin #: 7 6 13 4 11 10 9 8
|
||||
// Uno port/pin : PD7 PD6 PB5 PD4 PB3 PB2 PB1 PB0
|
||||
// Mega port/pin: PH4 PH3 PB7 PG5 PB5 PB4 PH6 PH5
|
||||
// Leo port/pin : PE6 PD7 PC7 PD4 PB7 PB6 PB5 PB4
|
||||
// LCD Data Bit : 7 6 5 4 3 2 1 0
|
||||
// Digital pin #: 7 6 13 4 11 10 9 8
|
||||
// Uno port/pin : PD7 PD6 PB5 PD4 PB3 PB2 PB1 PB0
|
||||
// Mega port/pin: PH4 PH3 PB7 PG5 PB5 PB4 PH6 PH5
|
||||
// Leo port/pin : PE6 PD7 PC7 PD4 PB7 PB6 PB5 PB4
|
||||
// Due port/pin : PC23 PC24 PB27 PC26 PD7 PC29 PC21 PC22
|
||||
// Breakout pin usage:
|
||||
// LCD Data Bit : 7 6 5 4 3 2 1 0
|
||||
// Uno dig. pin : 7 6 5 4 3 2 9 8
|
||||
@@ -45,6 +46,8 @@
|
||||
// Mega port/pin: PA7 PA6 PA5 PA4 PA3 PA2 PA1 PA0 (one contiguous PORT)
|
||||
// Leo dig. pin : 7 6 5 4 3 2 9 8
|
||||
// Leo port/pin : PE6 PD7 PC6 PD4 PD0 PD1 PB5 PB4
|
||||
// Due dig. pin : 40 39 38 37 36 35 34 33
|
||||
// Due port/pin : PC8 PC7 PC6 PC5 PC4 PC3 PC2 PC1 (one contiguous PORT. -ish…)
|
||||
|
||||
// Pixel read operations require a minimum 400 nS delay from RD_ACTIVE
|
||||
// to polling the input pins. At 16 MHz, one machine cycle is 62.5 nS.
|
||||
@@ -67,10 +70,10 @@
|
||||
|
||||
// LCD control lines:
|
||||
// RD (read), WR (write), CD (command/data), CS (chip select)
|
||||
#define RD_PORT PORTC
|
||||
#define WR_PORT PORTC
|
||||
#define CD_PORT PORTC
|
||||
#define CS_PORT PORTC
|
||||
#define RD_PORT PORTC /*pin A0 */
|
||||
#define WR_PORT PORTC /*pin A1 */
|
||||
#define CD_PORT PORTC /*pin A2 */
|
||||
#define CS_PORT PORTC /*pin A3 */
|
||||
#define RD_MASK B00000001
|
||||
#define WR_MASK B00000010
|
||||
#define CD_MASK B00000100
|
||||
@@ -252,13 +255,143 @@
|
||||
// program to compile.
|
||||
#define write8 write8inline
|
||||
|
||||
#elif defined(__SAM3X8E__)
|
||||
|
||||
// Arduino Due
|
||||
|
||||
#ifdef USE_ADAFRUIT_SHIELD_PINOUT
|
||||
|
||||
#define RD_PORT PIOA /*pin A0 */
|
||||
#define WR_PORT PIOA /*pin A1 */
|
||||
#define CD_PORT PIOA /*pin A2 */
|
||||
#define CS_PORT PIOA /*pin A3 */
|
||||
#define RD_MASK 0x00010000
|
||||
#define WR_MASK 0x01000000
|
||||
#define CD_MASK 0x00800000
|
||||
#define CS_MASK 0x00400000
|
||||
|
||||
#define write8inline(d) { \
|
||||
PIO_Set(PIOD, (((d) & 0x08)<<(7-3))); \
|
||||
PIO_Clear(PIOD, (((~d) & 0x08)<<(7-3))); \
|
||||
PIO_Set(PIOC, (((d) & 0x01)<<(22-0)) | (((d) & 0x02)<<(21-1))| (((d) & 0x04)<<(29-2))| (((d) & 0x10)<<(26-4))| (((d) & 0x40)<<(24-6))| (((d) & 0x80)<<(23-7))); \
|
||||
PIO_Clear(PIOC, (((~d) & 0x01)<<(22-0)) | (((~d) & 0x02)<<(21-1))| (((~d) & 0x04)<<(29-2))| (((~d) & 0x10)<<(26-4))| (((~d) & 0x40)<<(24-6))| (((~d) & 0x80)<<(23-7))); \
|
||||
PIO_Set(PIOB, (((d) & 0x20)<<(27-5))); \
|
||||
PIO_Clear(PIOB, (((~d) & 0x20)<<(27-5))); \
|
||||
WR_STROBE; }
|
||||
|
||||
#define read8inline(result) { \
|
||||
RD_ACTIVE; \
|
||||
delayMicroseconds(1); \
|
||||
result = (((PIOC->PIO_PDSR & (1<<23)) >> (23-7)) | ((PIOC->PIO_PDSR & (1<<24)) >> (24-6)) | \
|
||||
((PIOB->PIO_PDSR & (1<<27)) >> (27-5)) | ((PIOC->PIO_PDSR & (1<<26)) >> (26-4)) | \
|
||||
((PIOD->PIO_PDSR & (1<< 7)) >> ( 7-3)) | ((PIOC->PIO_PDSR & (1<<29)) >> (29-2)) | \
|
||||
((PIOC->PIO_PDSR & (1<<21)) >> (21-1)) | ((PIOC->PIO_PDSR & (1<<22)) >> (22-0))); \
|
||||
RD_IDLE;}
|
||||
|
||||
#define setWriteDirInline() { \
|
||||
PIOD->PIO_MDDR |= 0x00000080; /*PIOD->PIO_SODR = 0x00000080;*/ PIOD->PIO_OER |= 0x00000080; PIOD->PIO_PER |= 0x00000080; \
|
||||
PIOC->PIO_MDDR |= 0x25E00000; /*PIOC->PIO_SODR = 0x25E00000;*/ PIOC->PIO_OER |= 0x25E00000; PIOC->PIO_PER |= 0x25E00000; \
|
||||
PIOB->PIO_MDDR |= 0x08000000; /*PIOB->PIO_SODR = 0x08000000;*/ PIOB->PIO_OER |= 0x08000000; PIOB->PIO_PER |= 0x08000000; }
|
||||
|
||||
#define setReadDirInline() { \
|
||||
pmc_enable_periph_clk(ID_PIOD); pmc_enable_periph_clk(ID_PIOC); pmc_enable_periph_clk(ID_PIOB) ; \
|
||||
PI OD->PIO_PUDR |= 0x00000080; PIOD->PIO_IFDR |= 0x00000080; PIOD->PIO_ODR |= 0x00000080; PIOD->PIO_PER |= 0x00000080; \
|
||||
PIOC->PIO_PUDR |= 0x25E00000; PIOC->PIO_IFDR |= 0x25E00000; PIOC->PIO_ODR |= 0x25E00000; PIOC->PIO_PER |= 0x25E00000; \
|
||||
PIOB->PIO_PUDR |= 0x08000000; PIOB->PIO_IFDR |= 0x08000000; PIOB->PIO_ODR |= 0x08000000; PIOB->PIO_PER |= 0x08000000; }
|
||||
|
||||
// Control signals are ACTIVE LOW (idle is HIGH)
|
||||
// Command/Data: LOW = command, HIGH = data
|
||||
// These are single-instruction operations and always inline
|
||||
#define RD_ACTIVE RD_PORT->PIO_CODR |= RD_MASK
|
||||
#define RD_IDLE RD_PORT->PIO_SODR |= RD_MASK
|
||||
#define WR_ACTIVE WR_PORT->PIO_CODR |= WR_MASK
|
||||
#define WR_IDLE WR_PORT->PIO_SODR |= WR_MASK
|
||||
#define CD_COMMAND CD_PORT->PIO_CODR |= CD_MASK
|
||||
#define CD_DATA CD_PORT->PIO_SODR |= CD_MASK
|
||||
#define CS_ACTIVE CS_PORT->PIO_CODR |= CS_MASK
|
||||
#define CS_IDLE CS_PORT->PIO_SODR |= CS_MASK
|
||||
|
||||
#else // Due w/Breakout board
|
||||
|
||||
#define write8inline(d) { \
|
||||
PIO_Set(PIOC, (((d) & 0xFF)<<1)); \
|
||||
PIO_Clear(PIOC, (((~d) & 0xFF)<<1)); \
|
||||
WR_STROBE; }
|
||||
|
||||
#define read8inline(result) { \
|
||||
RD_ACTIVE; \
|
||||
delayMicroseconds(1); \
|
||||
result = ((PIOC->PIO_PDSR & 0x1FE) >> 1); \
|
||||
RD_IDLE;}
|
||||
|
||||
#define setWriteDirInline() { \
|
||||
PIOC->PIO_MDDR |= 0x000001FE; \
|
||||
PIOC->PIO_OER |= 0x000001FE; \
|
||||
PIOC->PIO_PER |= 0x000001FE; }
|
||||
|
||||
#define setReadDirInline() { \
|
||||
pmc_enable_periph_clk( ID_PIOC ) ; \
|
||||
PIOC->PIO_PUDR |= 0x000001FE; \
|
||||
PIOC->PIO_IFDR |= 0x000001FE; \
|
||||
PIOC->PIO_ODR |= 0x000001FE; \
|
||||
PIOC->PIO_PER |= 0x000001FE; }
|
||||
|
||||
// When using the TFT breakout board, control pins are configurable.
|
||||
#define RD_ACTIVE rdPort->PIO_CODR |= rdPinSet //PIO_Clear(rdPort, rdPinSet)
|
||||
#define RD_IDLE rdPort->PIO_SODR |= rdPinSet //PIO_Set(rdPort, rdPinSet)
|
||||
#define WR_ACTIVE wrPort->PIO_CODR |= wrPinSet //PIO_Clear(wrPort, wrPinSet)
|
||||
#define WR_IDLE wrPort->PIO_SODR |= wrPinSet //PIO_Set(wrPort, wrPinSet)
|
||||
#define CD_COMMAND cdPort->PIO_CODR |= cdPinSet //PIO_Clear(cdPort, cdPinSet)
|
||||
#define CD_DATA cdPort->PIO_SODR |= cdPinSet //PIO_Set(cdPort, cdPinSet)
|
||||
#define CS_ACTIVE csPort->PIO_CODR |= csPinSet //PIO_Clear(csPort, csPinSet)
|
||||
#define CS_IDLE csPort->PIO_SODR |= csPinSet //PIO_Set(csPort, csPinSet)
|
||||
|
||||
#endif
|
||||
|
||||
#elif defined(__SAMD51__) // Metro / Feather / ItsyBitsy M4
|
||||
|
||||
#ifdef USE_ADAFRUIT_SHIELD_PINOUT
|
||||
|
||||
// M4 w/shield: TBD
|
||||
|
||||
#else // M4 w/breakout
|
||||
|
||||
#define write8inline(d) { \
|
||||
*writePort = d; \
|
||||
WR_STROBE; }
|
||||
|
||||
#define read8inline(result) { \
|
||||
RD_ACTIVE; \
|
||||
delayMicroseconds(1); \
|
||||
result = *readPort; \
|
||||
RD_IDLE; }
|
||||
|
||||
#define setWriteDirInline() { *dirSet = 0xFF; }
|
||||
#define setReadDirInline() { *dirClr = 0xFF; }
|
||||
|
||||
#define RD_ACTIVE *rdPortClr = rdPinMask
|
||||
#define RD_IDLE *rdPortSet = rdPinMask
|
||||
/*
|
||||
#define WR_ACTIVE *wrPortClr = wrPinMask
|
||||
#define WR_IDLE *wrPortSet = wrPinMask
|
||||
*/
|
||||
#define WR_ACTIVE *wrPortSet = wrPinMask
|
||||
#define WR_IDLE *wrPortClr = wrPinMask
|
||||
#define CD_COMMAND *cdPortClr = cdPinMask
|
||||
#define CD_DATA *cdPortSet = cdPinMask
|
||||
#define CS_ACTIVE *csPortClr = csPinMask
|
||||
#define CS_IDLE *csPortSet = csPinMask
|
||||
|
||||
#endif
|
||||
|
||||
#else
|
||||
|
||||
#error "Board type unsupported / not recognized"
|
||||
|
||||
#endif
|
||||
|
||||
// Stuff common to all Arduino board types:
|
||||
#if defined(__AVR__)
|
||||
// Stuff common to all Arduino AVR board types:
|
||||
|
||||
#ifdef USE_ADAFRUIT_SHIELD_PINOUT
|
||||
|
||||
@@ -287,6 +420,7 @@
|
||||
#define CS_IDLE *csPort |= csPinSet
|
||||
|
||||
#endif
|
||||
#endif
|
||||
|
||||
// Data write strobe, ~2 instructions and always inline
|
||||
#define WR_STROBE { WR_ACTIVE; WR_IDLE; }
|
||||
|
||||
+172
@@ -0,0 +1,172 @@
|
||||
// Register names from Peter Barrett's Microtouch code
|
||||
#define ILI932X_START_OSC 0x00
|
||||
#define ILI932X_DRIV_OUT_CTRL 0x01
|
||||
#define ILI932X_DRIV_WAV_CTRL 0x02
|
||||
#define ILI932X_ENTRY_MOD 0x03
|
||||
#define ILI932X_RESIZE_CTRL 0x04
|
||||
#define ILI932X_DISP_CTRL1 0x07
|
||||
#define ILI932X_DISP_CTRL2 0x08
|
||||
#define ILI932X_DISP_CTRL3 0x09
|
||||
#define ILI932X_DISP_CTRL4 0x0A
|
||||
#define ILI932X_RGB_DISP_IF_CTRL1 0x0C
|
||||
#define ILI932X_FRM_MARKER_POS 0x0D
|
||||
#define ILI932X_RGB_DISP_IF_CTRL2 0x0F
|
||||
#define ILI932X_POW_CTRL1 0x10
|
||||
#define ILI932X_POW_CTRL2 0x11
|
||||
#define ILI932X_POW_CTRL3 0x12
|
||||
#define ILI932X_POW_CTRL4 0x13
|
||||
#define ILI932X_GRAM_HOR_AD 0x20
|
||||
#define ILI932X_GRAM_VER_AD 0x21
|
||||
#define ILI932X_RW_GRAM 0x22
|
||||
#define ILI932X_POW_CTRL7 0x29
|
||||
#define ILI932X_FRM_RATE_COL_CTRL 0x2B
|
||||
#define ILI932X_GAMMA_CTRL1 0x30
|
||||
#define ILI932X_GAMMA_CTRL2 0x31
|
||||
#define ILI932X_GAMMA_CTRL3 0x32
|
||||
#define ILI932X_GAMMA_CTRL4 0x35
|
||||
#define ILI932X_GAMMA_CTRL5 0x36
|
||||
#define ILI932X_GAMMA_CTRL6 0x37
|
||||
#define ILI932X_GAMMA_CTRL7 0x38
|
||||
#define ILI932X_GAMMA_CTRL8 0x39
|
||||
#define ILI932X_GAMMA_CTRL9 0x3C
|
||||
#define ILI932X_GAMMA_CTRL10 0x3D
|
||||
#define ILI932X_HOR_START_AD 0x50
|
||||
#define ILI932X_HOR_END_AD 0x51
|
||||
#define ILI932X_VER_START_AD 0x52
|
||||
#define ILI932X_VER_END_AD 0x53
|
||||
#define ILI932X_GATE_SCAN_CTRL1 0x60
|
||||
#define ILI932X_GATE_SCAN_CTRL2 0x61
|
||||
#define ILI932X_GATE_SCAN_CTRL3 0x6A
|
||||
#define ILI932X_PART_IMG1_DISP_POS 0x80
|
||||
#define ILI932X_PART_IMG1_START_AD 0x81
|
||||
#define ILI932X_PART_IMG1_END_AD 0x82
|
||||
#define ILI932X_PART_IMG2_DISP_POS 0x83
|
||||
#define ILI932X_PART_IMG2_START_AD 0x84
|
||||
#define ILI932X_PART_IMG2_END_AD 0x85
|
||||
#define ILI932X_PANEL_IF_CTRL1 0x90
|
||||
#define ILI932X_PANEL_IF_CTRL2 0x92
|
||||
#define ILI932X_PANEL_IF_CTRL3 0x93
|
||||
#define ILI932X_PANEL_IF_CTRL4 0x95
|
||||
#define ILI932X_PANEL_IF_CTRL5 0x97
|
||||
#define ILI932X_PANEL_IF_CTRL6 0x98
|
||||
|
||||
#define HX8347G_COLADDRSTART_HI 0x02
|
||||
#define HX8347G_COLADDRSTART_LO 0x03
|
||||
#define HX8347G_COLADDREND_HI 0x04
|
||||
#define HX8347G_COLADDREND_LO 0x05
|
||||
#define HX8347G_ROWADDRSTART_HI 0x06
|
||||
#define HX8347G_ROWADDRSTART_LO 0x07
|
||||
#define HX8347G_ROWADDREND_HI 0x08
|
||||
#define HX8347G_ROWADDREND_LO 0x09
|
||||
#define HX8347G_MEMACCESS 0x16
|
||||
|
||||
|
||||
|
||||
#define ILI9341_SOFTRESET 0x01
|
||||
#define ILI9341_SLEEPIN 0x10
|
||||
#define ILI9341_SLEEPOUT 0x11
|
||||
#define ILI9341_NORMALDISP 0x13
|
||||
#define ILI9341_INVERTOFF 0x20
|
||||
#define ILI9341_INVERTON 0x21
|
||||
#define ILI9341_GAMMASET 0x26
|
||||
#define ILI9341_DISPLAYOFF 0x28
|
||||
#define ILI9341_DISPLAYON 0x29
|
||||
#define ILI9341_COLADDRSET 0x2A
|
||||
#define ILI9341_PAGEADDRSET 0x2B
|
||||
#define ILI9341_MEMORYWRITE 0x2C
|
||||
#define ILI9341_PIXELFORMAT 0x3A
|
||||
#define ILI9341_FRAMECONTROL 0xB1
|
||||
#define ILI9341_DISPLAYFUNC 0xB6
|
||||
#define ILI9341_ENTRYMODE 0xB7
|
||||
#define ILI9341_POWERCONTROL1 0xC0
|
||||
#define ILI9341_POWERCONTROL2 0xC1
|
||||
#define ILI9341_VCOMCONTROL1 0xC5
|
||||
#define ILI9341_VCOMCONTROL2 0xC7
|
||||
#define ILI9341_MEMCONTROL 0x36
|
||||
#define ILI9341_MADCTL 0x36
|
||||
|
||||
#define ILI9341_MADCTL_MY 0x80
|
||||
#define ILI9341_MADCTL_MX 0x40
|
||||
#define ILI9341_MADCTL_MV 0x20
|
||||
#define ILI9341_MADCTL_ML 0x10
|
||||
#define ILI9341_MADCTL_RGB 0x00
|
||||
#define ILI9341_MADCTL_BGR 0x08
|
||||
#define ILI9341_MADCTL_MH 0x04
|
||||
|
||||
|
||||
|
||||
#define HX8357_NOP 0x00
|
||||
#define HX8357_SWRESET 0x01
|
||||
#define HX8357_RDDID 0x04
|
||||
#define HX8357_RDDST 0x09
|
||||
|
||||
#define HX8357B_RDPOWMODE 0x0A
|
||||
#define HX8357B_RDMADCTL 0x0B
|
||||
#define HX8357B_RDCOLMOD 0x0C
|
||||
#define HX8357B_RDDIM 0x0D
|
||||
#define HX8357B_RDDSDR 0x0F
|
||||
|
||||
#define HX8357_SLPIN 0x10
|
||||
#define HX8357_SLPOUT 0x11
|
||||
#define HX8357B_PTLON 0x12
|
||||
#define HX8357B_NORON 0x13
|
||||
|
||||
#define HX8357_INVOFF 0x20
|
||||
#define HX8357_INVON 0x21
|
||||
#define HX8357_DISPOFF 0x28
|
||||
#define HX8357_DISPON 0x29
|
||||
|
||||
#define HX8357_CASET 0x2A
|
||||
#define HX8357_PASET 0x2B
|
||||
#define HX8357_RAMWR 0x2C
|
||||
#define HX8357_RAMRD 0x2E
|
||||
|
||||
#define HX8357B_PTLAR 0x30
|
||||
#define HX8357_TEON 0x35
|
||||
#define HX8357_TEARLINE 0x44
|
||||
#define HX8357_MADCTL 0x36
|
||||
#define HX8357_COLMOD 0x3A
|
||||
|
||||
#define HX8357_SETOSC 0xB0
|
||||
#define HX8357_SETPWR1 0xB1
|
||||
#define HX8357B_SETDISPLAY 0xB2
|
||||
#define HX8357_SETRGB 0xB3
|
||||
#define HX8357D_SETCOM 0xB6
|
||||
|
||||
#define HX8357B_SETDISPMODE 0xB4
|
||||
#define HX8357D_SETCYC 0xB4
|
||||
#define HX8357B_SETOTP 0xB7
|
||||
#define HX8357D_SETC 0xB9
|
||||
|
||||
#define HX8357B_SET_PANEL_DRIVING 0xC0
|
||||
#define HX8357D_SETSTBA 0xC0
|
||||
#define HX8357B_SETDGC 0xC1
|
||||
#define HX8357B_SETID 0xC3
|
||||
#define HX8357B_SETDDB 0xC4
|
||||
#define HX8357B_SETDISPLAYFRAME 0xC5
|
||||
#define HX8357B_GAMMASET 0xC8
|
||||
#define HX8357B_SETCABC 0xC9
|
||||
#define HX8357_SETPANEL 0xCC
|
||||
|
||||
|
||||
#define HX8357B_SETPOWER 0xD0
|
||||
#define HX8357B_SETVCOM 0xD1
|
||||
#define HX8357B_SETPWRNORMAL 0xD2
|
||||
|
||||
#define HX8357B_RDID1 0xDA
|
||||
#define HX8357B_RDID2 0xDB
|
||||
#define HX8357B_RDID3 0xDC
|
||||
#define HX8357B_RDID4 0xDD
|
||||
|
||||
#define HX8357D_SETGAMMA 0xE0
|
||||
|
||||
#define HX8357B_SETGAMMA 0xC8
|
||||
#define HX8357B_SETPANELRELATED 0xE9
|
||||
|
||||
#define HX8357B_MADCTL_MY 0x80
|
||||
#define HX8357B_MADCTL_MX 0x40
|
||||
#define HX8357B_MADCTL_MV 0x20
|
||||
#define HX8357B_MADCTL_ML 0x10
|
||||
#define HX8357B_MADCTL_RGB 0x00
|
||||
#define HX8357B_MADCTL_BGR 0x08
|
||||
#define HX8357B_MADCTL_MH 0x04
|
||||
Reference in New Issue
Block a user