
Добавил:
ohpetya
Опубликованный материал нарушает ваши авторские права? Сообщите нам.
Вуз:
Предмет:
Файл:SimpleILI9341
.cpp/***************************************************
Arduino TFT graphics library for the ILI9341
Derived from the TFT_ILI9341 library which was
derived from the Adafruit_GFX library and the
associated driver library.
****************************************************/
#include "SimpleILI9341.h"
#include <avr/pgmspace.h>
#include <SPI.h>
int16_t Cursorx, Cursory, win_xe, win_ye;
uint16_t tft_width = 320;
uint16_t tft_height = 240;
uint8_t pen_width = 1; // if pen_width > 1 then draws with a disc of radius pen_width-1 // the overall width is pen_width*2-1
uint8_t letter_gap = 1;
uint16_t addr_row, addr_col;
uint8_t mySPCR;
bool execDrawChar = true;
bool ILI9341fast = false;
uint8_t tft_CS = 10; // Chip select control pin
uint8_t tft_DC = 8; // Data Command control pin
uint8_t tft_RST = 7; // Reset pin (could connect to Arduino RESET pin)
int touch_xmin = 340;
int touch_ymin = 340;
int touch_xmax = 3800;
int touch_ymax = 3800;
uint8_t touch_Rotation = 1;
uint8_t touch_CS = 2; // Chip select control pin
static inline void spiWait17(void) __attribute__((always_inline));
static inline void spiWait15(void) __attribute__((always_inline));
static inline void spiWait14(void) __attribute__((always_inline));
static inline void spiWait12(void) __attribute__((always_inline));
static inline void spiWrite16(uint16_t data, int16_t count) __attribute__((always_inline));
void tft_fastSetup(void);
void tft_fastPixel(uint16_t x, uint16_t y, uint16_t color);
void tft_setAddrWindow(int16_t x0, int16_t y0, int16_t x1, int16_t y1);
#define ILI9341_INIT_DELAY 0x80
// ILI9341 control registers
#define ILI9341_NOP 0x00
#define ILI9341_SWRESET 0x01
#define ILI9341_RDDID 0x04
#define ILI9341_RDDST 0x09
#define ILI9341_RDIMGFMT 0x0A
#define ILI9341_RDMADCTL 0x0B
#define ILI9341_RDPIXFMT 0x0C
#define ILI9341_RD_DISP_IMG_FMT 0x0D
#define ILI9341_RD_DISP_SIG_MODE 0x0E
#define ILI9341_RDSELFDIAG 0x0F
#define ILI9341_SLPIN 0x10
#define ILI9341_SLPOUT 0x11
#define ILI9341_PTLON 0x12
#define ILI9341_NORON 0x13
#define ILI9341_INVOFF 0x20
#define ILI9341_INVON 0x21
#define ILI9341_GAMMASET 0x26
#define ILI9341_DISPOFF 0x28
#define ILI9341_DISPON 0x29
#define ILI9341_CASET 0x2A
#define ILI9341_PASET 0x2B
#define ILI9341_RAMWR 0x2C
#define ILI9341_COLOR_SET 0x2D
#define ILI9341_RAMRD 0x2E
#define ILI9341_PTLAR 0x30
#define ILI9341_VSCRDEF 0x33
#define ILI9341_TEAR_EFF_OFF 0x34
#define ILI9341_TEAR_EFF_ON 0x35
#define ILI9341_MADCTL 0x36
#define ILI9341_VSCRSADD 0x37
#define ILI9341_IDLE_MODE_OFF 0x38
#define ILI9341_IDLE_MODE_ON 0x39
#define ILI9341_PIXFMT 0x3A
#define ILI9341_WRT_MEM_CTRL 0x3C
#define ILI9341_RD_MEM_CTRL 0x3E
#define ILI9341_SET_TEAR_SCANLINE 0x44
#define ILI9341_GET_SCANLINE 0x45
#define ILI9341_WRT_DISP_BRIGHT 0x51
#define ILI9341_RD_DISP_BRIGHT 0x52
#define ILI9341_WRT_CTRL_DISP 0x53
#define ILI9341_RD_CTRL_DISP 0x54
#define ILI9341_WRT_ADAPT_BRIGHT_CTRL 0x55
#define ILI9341_RD_ADAPT_BRIGHT_CTRL 0x56
#define ILI9341_WRT_CABC_MIN_BRIGHT 0x5E
#define ILI9341_RD_CABC_MIN_BRIGHT 0x5F
#define ILI9341_RGB_INTF_SIG_CTRL 0xB0
#define ILI9341_FRMCTR1 0xB1
#define ILI9341_FRMCTR2 0xB2
#define ILI9341_FRMCTR3 0xB3
#define ILI9341_INVCTR 0xB4
#define ILI9341_BLANKING_PORCH_CTRL 0xB5
#define ILI9341_DFUNCTR 0xB6
#define ILI9341_ENTRY_MODE_SET 0xB7
#define ILI9341_BKLGT_CTRL_1 0xB8
#define ILI9341_BKLGT_CTRL_2 0xB9
#define ILI9341_BKLGT_CTRL_3 0xBA
#define ILI9341_BKLGT_CTRL_4 0xBB
#define ILI9341_BKLGT_CTRL_5 0xBC
#define ILI9341_BKLGT_CTRL_7 0xBE
#define ILI9341_BKLGT_CTRL_8 0xBF
#define ILI9341_PWCTR1 0xC0
#define ILI9341_PWCTR2 0xC1
#define ILI9341_PWCTR3 0xC2
#define ILI9341_PWCTR4 0xC3
#define ILI9341_PWCTR5 0xC4
#define ILI9341_VMCTR1 0xC5
#define ILI9341_VMCTR2 0xC7
#define ILI9341_NV_MEM_WRT 0xD0
#define ILI9341_NV_MEM_PROT_KEY 0xD1
#define ILI9341_NV_MEM_STAT_RD 0xD2
#define ILI9341_RD_ID4 0xD3
#define ILI9341_RDID1 0xDA
#define ILI9341_RDID2 0xDB
#define ILI9341_RDID3 0xDC
#define ILI9341_RDID4 0xDD
#define ILI9341_GMCTRP1 0xE0
#define ILI9341_GMCTRN1 0xE1
#define ILI9341_GAMMA_CTRL_1 0xE2
#define ILI9341_GAMMA_CTRL_2 0xE3
#define ILI9341_INTF_CTRL 0xF6
/***************************************************************************************
** Function name: tft_spiwrite
** Description: Write 8 bits to SPI port
***************************************************************************************/
static void tft_spiwrite(uint8_t c)
{
if (ILI9341fast) {
uint8_t backupSPCR = SPCR;
SPCR = mySPCR;
SPDR = c;
asm volatile( "nop\n\t" ::); // Sync SPIF and some commands need this delay otherwise they get lost!
while (!(SPSR & _BV(SPIF)));
SPCR = backupSPCR;
} else
SPI.transfer(c);
}
/***************************************************************************************
** Function name: tft_writecommand
** Description: Send an 8 bit command to the TFT
***************************************************************************************/
static void tft_writecommand(uint8_t c)
{
digitalWrite(tft_DC, LOW);
digitalWrite(tft_CS, LOW);
tft_spiwrite(c);
digitalWrite(tft_CS, HIGH);
}
/***************************************************************************************
** Function name: tft_writedata
** Description: Send a 8 bit data value to the TFT
***************************************************************************************/
static void tft_writedata(uint8_t c)
{
digitalWrite(tft_DC, HIGH);
digitalWrite(tft_CS, LOW);
tft_spiwrite(c);
digitalWrite(tft_CS, HIGH);
}
/***************************************************************************************
** Function name: spi_begin
** Description: Prepare for SPI communication to TFT
***************************************************************************************/
// If the SPI library has transaction support, these functions
// establish settings and protect from interference from other
// libraries. Otherwise, they simply do nothing.
#ifdef SPI_HAS_TRANSACTION
#ifdef SUPPORT_TRANSACTIONS
static inline void spi_begin(void) __attribute__((always_inline));
static inline void spi_begin(void) {
SPI.beginTransaction(SPISettings(8000000, MSBFIRST, SPI_MODE0));
}
static inline void spi_end(void) __attribute__((always_inline));
static inline void spi_end(void) {
while (!(SPSR & _BV(SPIF))); // wait for everything SPI to finish before freeing up the bus
SPI.endTransaction();
}
#else // we do not want to SUPPORT_TRANSACTIONS
#define spi_begin()
#define spi_end()
#endif // SUPPORT_TRANSACTIONS
#else
#define spi_begin()
#define spi_end()
#endif
/***************************************************************************************
** Description: Get initialisation commands from FLASH and send to TFT
***************************************************************************************/
void tft_commandList (const uint8_t *addr)
{
uint8_t numCommands, numArgs;
uint8_t ms;
spi_begin();
numCommands = pgm_read_byte(addr++); // Number of commands to follow
while (numCommands--) // For each command...
{
tft_writecommand(pgm_read_byte(addr++)); // Read, issue command
numArgs = pgm_read_byte(addr++); // Number of args to follow
ms = numArgs & ILI9341_INIT_DELAY; // If hibit set, delay follows args
numArgs &= ~ILI9341_INIT_DELAY; // Mask out delay bit
while (numArgs--) // For each argument...
{
tft_writedata(pgm_read_byte(addr++)); // Read, issue argument
}
if (ms)
{
ms = pgm_read_byte(addr++); // Read post-command delay time (ms)
delay( (ms==255 ? 500 : ms) );
}
}
spi_end();
}
/***************************************************************************************
** Function name: DrawBitmap
** Description: Draw an image stored in an array on the TFT
***************************************************************************************/
void DrawBitmap(int16_t x, int16_t y, const unsigned short *bitmap) {
int16_t i, j, w,h;
w = pgm_read_word(bitmap++);
h = pgm_read_word(bitmap++);
tft_fastSetup();
for (j = 0; j < h; j++) {
for (i = 0; i < w; i++ ) {
tft_fastPixel(x + i, y + j, pgm_read_word(bitmap++));
}
}
}
/***************************************************************************************
** Function name: DrawBitmapMonoBits
** Description: Draw a black and white image stored as an array of bits
***************************************************************************************/
void DrawBitmapMonoBits(int16_t x, int16_t y, const uint8_t *bitmap, uint16_t color) {
int16_t i, j, bits, n, w,h;
w = pgm_read_byte(bitmap++);
w = w | (pgm_read_byte(bitmap++) << 8);
h = pgm_read_byte(bitmap++);
h = h | (pgm_read_byte(bitmap++) << 8);
tft_fastSetup();
n = 0;
for (j = 0; j < h; j++) {
for (i = 0; i < w; i++ ) {
if (n % 8 == 0)
bits = pgm_read_byte(bitmap++);
if ((bits & 0x80) == 0)
tft_fastPixel(x + i, y + j, color);
bits = bits << 1;
n++;
}
}
}
/***************************************************************************************
** Function name: DrawBitmapMonoRLE
** Description: Draw a black and white image stored as RLE
***************************************************************************************/
void DrawBitmapMonoRLE(int16_t x, int16_t y, const uint8_t *bitmap, uint16_t color) {
int16_t i,j,nb, w,h;
bool CurIsBlack;
w = pgm_read_byte(bitmap++);
w = w | (pgm_read_byte(bitmap++) << 8);
w = w & 0x7FFF;
h = pgm_read_byte(bitmap++);
h = h | (pgm_read_byte(bitmap++) << 8);
tft_fastSetup();
nb = 0;
CurIsBlack = true;
j = 0;
i = 0;
for (j = 0; j < h; j++) {
for (i = 0; i < w; i++ ) {
while (nb == 0) {
nb = pgm_read_byte(bitmap++);
CurIsBlack = !CurIsBlack;
}
if (!CurIsBlack)
tft_fastPixel(x + i, y + j, color);
nb--;
}
}
}
/***************************************************************************************
** Function name: DrawBitmapMono
** Description: Draw a black and white image stored in an array on the TFT
***************************************************************************************/
void DrawBitmapMono(int16_t x, int16_t y, const uint8_t *bitmap, uint16_t color) {
uint8_t *bmp;
int16_t w;
bmp = bitmap;
w = pgm_read_byte(bmp++);
w = pgm_read_byte(bmp++);
if ((w & 0x80) > 0)
DrawBitmapMonoRLE(x, y, bitmap, color);
else
DrawBitmapMonoBits(x, y, bitmap, color);
}
/***************************************************************************************
** Function name: setCursor
** Description: Set the text cursor x,y position
***************************************************************************************/
void tft_setCursor(int16_t x, int16_t y)
{
Cursorx = x;
Cursory = y;
}
/***************************************************************************************
** Function name: tft_setAddrWindow
** Description: define an area to receive a stream of pixels
***************************************************************************************/
// Chip select stays low, use setWindow() from sketches
static void tft_setAddrWindow(int16_t x0, int16_t y0, int16_t x1, int16_t y1)
{
if (ILI9341fast) {
// Column addr set
digitalWrite(tft_DC, LOW);
digitalWrite(tft_CS, LOW);
SPDR = ILI9341_CASET;
spiWait15();
digitalWrite(tft_DC, HIGH);
SPDR = x0 >> 8;; spiWait12();
addr_col = 0xFFFF;
SPDR = x0; spiWait12();
if(x1!=win_xe) {
SPDR = x1 >> 8; spiWait12();
asm volatile( "nop\n\t" ::);
win_xe=x1;
SPDR = x1; spiWait14();
}
// Row addr set
digitalWrite(tft_DC, LOW);
SPDR = ILI9341_PASET; spiWait15();
digitalWrite(tft_DC, HIGH);
SPDR = y0 >> 8; spiWait12();
addr_row = 0xFFFF;
SPDR = y0; spiWait12();
if(y1!=win_ye) {
SPDR = y1 >> 8; spiWait12();
asm volatile( "nop\n\t" ::);
win_ye=y1;
SPDR = y1; spiWait14();
}
// write to RAM
digitalWrite(tft_DC, LOW);
SPDR = ILI9341_RAMWR; spiWait14();
//CS, HIGH;
//digitalWrite(tft_CS, HIGH);
digitalWrite(tft_DC, HIGH);
} else {
tft_writecommand(ILI9341_CASET); // Column addr set
tft_writedata(x0 >> 8);
tft_writedata(x0); // XSTART
tft_writedata(x1 >> 8);
tft_writedata(x1); // XEND
tft_writecommand(ILI9341_PASET); // Row addr set
tft_writedata(y0 >> 8);
tft_writedata(y0); // YSTART
tft_writedata(y1 >> 8);
tft_writedata(y1); // YEND
tft_writecommand(ILI9341_RAMWR); // write to RAM
digitalWrite(tft_CS, LOW);
digitalWrite(tft_DC, HIGH);
}
}
/***************************************************************************************
** Function name: DrawPixel
** Description: push a single pixel at an arbitrary position
***************************************************************************************/
void DrawPixel(uint16_t x, uint16_t y, uint16_t color)
{
// Faster range checking, possible because x and y are unsigned
if ((x >= tft_width) || (y >= tft_height)) return;
spi_begin();
digitalWrite(tft_CS, LOW);
if (ILI9341fast) {
if (addr_col != x) {
digitalWrite(tft_DC, LOW);
SPDR = ILI9341_CASET;
spiWait12();
addr_col = x;
digitalWrite(tft_DC, HIGH);
SPDR = x >> 8; spiWait17();
SPDR = x; spiWait17();
SPDR = x >> 8; spiWait17();
SPDR = x; spiWait12();
}
if (addr_row != y) {
digitalWrite(tft_DC, LOW);
SPDR = ILI9341_PASET;
spiWait12();
addr_row = y;
digitalWrite(tft_DC, HIGH);
SPDR = y >> 8; spiWait17();
SPDR = y; spiWait17();
SPDR = y >> 8; spiWait17();
SPDR = y; spiWait14();
}
digitalWrite(tft_DC, LOW);
SPDR = ILI9341_RAMWR; spiWait15();
digitalWrite(tft_DC, HIGH);
SPDR = color >> 8; spiWait15();
win_xe=x;
SPDR = color; spiWait12();
win_ye=y;
} else {
tft_setAddrWindow(x, y, x, y);
spiWrite16(color, 1);
}
digitalWrite(tft_CS, HIGH);
spi_end();
}
/***************************************************************************************
** Function name: tft_fastPixel
***************************************************************************************/
static void tft_fastPixel(uint16_t x, uint16_t y, uint16_t color)
{
if (ILI9341fast) {
// Faster range checking, possible because x and y are unsigned
if ((x >= tft_width) || (y >= tft_height)) return;
spi_begin();
digitalWrite(tft_CS, LOW);
if (addr_col != x) {
digitalWrite(tft_DC, LOW);
SPDR = ILI9341_CASET;
spiWait14();
addr_col = x;
digitalWrite(tft_DC, HIGH);
SPDR = x >> 8;; spiWait17();
SPDR = x; spiWait12();
}
if (addr_row != y) {
digitalWrite(tft_DC, LOW);
SPDR = ILI9341_PASET;
spiWait14();
addr_row = y;
digitalWrite(tft_DC, HIGH);
SPDR = y >> 8; spiWait17();
SPDR = y; spiWait14();
}
digitalWrite(tft_DC, LOW);
SPDR = ILI9341_RAMWR; spiWait15();
digitalWrite(tft_DC, HIGH);
SPDR = color >> 8; spiWait17();
SPDR = color; spiWait14();
digitalWrite(tft_CS, HIGH);
spi_end();
} else {
DrawPixel(x, y, color);
}
}
/***************************************************************************************
** Function name: tft_fastSetup
***************************************************************************************/
static void tft_fastSetup(void)
{
if (ILI9341fast) {
spi_begin();
digitalWrite(tft_DC, LOW);
digitalWrite(tft_CS, LOW);
SPDR = ILI9341_CASET;
spiWait15();
digitalWrite(tft_DC, HIGH);
SPDR = 0; spiWait14();
addr_col = 0;
SPDR = 0; spiWait12();
win_xe=tft_width-1;
SPDR = win_xe >> 8; spiWait15();
SPDR = win_xe; spiWait14();
digitalWrite(tft_DC, LOW);
SPDR = ILI9341_PASET;
spiWait15();
digitalWrite(tft_DC, HIGH);
SPDR = 0; spiWait14();
addr_row = 0;
SPDR = 0; spiWait12();
win_ye=tft_height-1;
SPDR = win_ye >> 8; spiWait15();
SPDR = win_ye; spiWait14();
digitalWrite(tft_CS, HIGH);
spi_end();
}
}
/***************************************************************************************
** Function name: DrawVLine
** Description: draw a vertical line
***************************************************************************************/
void DrawVLine(uint16_t x, uint16_t y, uint16_t h, uint16_t color)
{
#ifdef CLIP_CHECK
// Rudimentary clipping
if ((x >= tft_width) || (y >= tft_height)) return;
if ((y + h - 1) >= tft_height) h = tft_height - y;
#endif
if (pen_width > 1) {
DrawLine(x, y, x, y+h-1, color);
} else {
spi_begin();
tft_setAddrWindow(x, y, x, y + h - 1);
spiWrite16(color, h);
digitalWrite(tft_CS, HIGH);
spi_end();
}
}
/***************************************************************************************
** Function name: DrawHLineSingle
** Description: draw a horizontal line with pen width 1
***************************************************************************************/
void DrawHLineSingle(uint16_t x, uint16_t y, uint16_t w, uint16_t color)
{
#ifdef CLIP_CHECK
// Rudimentary clipping
if ((x >= tft_width) || (y >= tft_height)) return;
if ((x + w - 1) >= tft_width) w = tft_width - x;
#endif
spi_begin();
tft_setAddrWindow(x, y, x + w - 1, y);
spiWrite16(color, w);
digitalWrite(tft_CS, HIGH);
spi_end();
}
/***************************************************************************************
** Function name: DrawHLine
** Description: draw a horizontal line
***************************************************************************************/
void DrawHLine(uint16_t x, uint16_t y, uint16_t w, uint16_t color)
{
if (pen_width > 1)
DrawLine(x, y, x+w-1, y, color);
else
DrawHLineSingle(x, y, w, color);
}
/***************************************************************************************
** Function name: DrawBox
** Description: draw a filled rectangle
***************************************************************************************/
void DrawBox(uint16_t x, uint16_t y, uint16_t w, uint16_t h, uint16_t color)
{
#ifdef CLIP_CHECK
if ((x > tft_width) || (y > tft_height) || (w==0) || (h==0)) return;
if ((x + w - 1) > tft_width) w = tft_width - x;
if ((y + h - 1) > tft_height) h = tft_height - y;
#endif
spi_begin();
tft_setAddrWindow(x, y, x + w - 1, y + h - 1);
while (h--) spiWrite16(color, w);
digitalWrite(tft_CS, HIGH);
spi_end();
}
/***************************************************************************************
** Function name: DrawRoundRect
** Description: draw a filled rectangle with round corners
***************************************************************************************/
void DrawRoundRect(uint16_t x, uint16_t y, uint16_t w, uint16_t h, uint16_t rad, uint16_t color) {
DrawBox(x, y+rad+1, w, h-rad*2-2, color);
DrawDisc(x+rad, y+rad, rad, color);
DrawDisc(x+w-rad-1, y+rad, rad, color);
DrawDisc(x+rad, y+h-rad-1, rad, color);
DrawDisc(x+w-rad-1, y+h-rad-1, rad, color);
DrawBox(x+rad+1, y, w-rad*2-2, rad*2, color);
DrawBox(x+rad+1, y+h-rad*2, w-rad*2-2, rad*2, color);
}
/***************************************************************************************
** Function name: invertDisplay
** Description: invert the display colours i = 1 invert, i = 0 normal
***************************************************************************************/
void InvertDisplay(boolean i)
{
spi_begin();
// Send the command twice as otherwise it does not always work!
tft_writecommand(i ? ILI9341_INVON : ILI9341_INVOFF);
tft_writecommand(i ? ILI9341_INVON : ILI9341_INVOFF);
spi_end();
}
/***************************************************************************************
** Function name: drawFloat
** Descriptions: drawFloat, prints 7 non zero digits maximum
***************************************************************************************/
void DrawFloat(float floatNumber, int dp, word Font, uint16_t color)
{
char str[14]; // Array to contain decimal string
uint8_t ptr = 0; // Initialise pointer for array
int8_t digits = 1; // Count the digits to avoid array overflow
float rounding = 0.5; // Round up down delta
if (dp > 7) dp = 7; // Limit the size of decimal portion
// Adjust the rounding value
for (uint8_t i = 0; i < dp; ++i) rounding /= 10.0;
if (floatNumber < -rounding) // add sign, avoid adding - sign to 0.0!
{
str[ptr++] = '-'; // Negative number
str[ptr] = 0; // Put a null in the array as a precaution
digits = 0; // Set digits to 0 to compensate so pointer value can be used later
floatNumber = -floatNumber; // Make positive
}
floatNumber += rounding; // Round up or down
// For error put ... in string and return (all TFT_ILI9341 library fonts contain . character)
if (floatNumber >= 2147483647) {
strcpy(str, "...");
DrawString(str, Font, color);
return;
}
// No chance of overflow from here on
// Get integer part
unsigned long temp = (unsigned long)floatNumber;
// Put integer part into array
ltoa(temp, str + ptr, 10);
// Find out where the null is to get the digit count loaded
while ((uint8_t)str[ptr] != 0) ptr++; // Move the pointer along
digits += ptr; // Count the digits
str[ptr++] = '.'; // Add decimal point
str[ptr] = '0'; // Add a dummy zero
str[ptr + 1] = 0; // Add a null but don't increment pointer so it can be overwritten
// Get the decimal portion
floatNumber = floatNumber - temp;
// Get decimal digits one by one and put in array
// Limit digit count so we don't get a false sense of resolution
uint8_t i = 0;
while ((i < dp) && (digits < 9)) // while (i < dp) for no limit but array size must be increased
{
i++;
floatNumber *= 10; // for the next decimal
temp = floatNumber; // get the decimal
ltoa(temp, str + ptr, 10);
ptr++; digits++; // Increment pointer and digits count
floatNumber -= temp; // Remove that digit
}
// Finally we can plot the string and return pixel length
DrawString(str, Font, color);
}
/***************************************************************************************
** Function name: spiWrite16
** Descriptions: Delay based assembler loop for fast SPI write
***************************************************************************************/
static inline void spiWrite16(uint16_t data, int16_t count)
{
// We can enter this loop with 0 pixels to draw, so we need to check this
if (ILI9341fast) {
uint8_t temp;
asm volatile
(
" sbiw %[count],0\n" // test count
//" brmi 2f\n" // if < 0 then done
" breq 2f\n" // if == 0 then done
"1: out %[spi],%[hi]\n" // write SPI data
" rcall 3f \n" // 7
" rcall 3f \n" // 14
" rjmp 4f \n" // 16
"3: ret \n" //
"4: nop \n" // 17
" out %[spi],%[lo]\n" // write SPI data
" adiw r24,0 \n" // 2
" adiw r24,0 \n" // 4
" rcall 5f \n" // 11
" rjmp 6f \n" // 13
"5: ret \n" //
"6: \n"
" sbiw %[count],1 \n" // 15 decrement count
" brne 1b \n" // 17 if != 0 then loop
"2:\n"
: [temp] "=d" (temp), [count] "+w" (count)
: [spi] "i" (_SFR_IO_ADDR(SPDR)), [lo] "r" ((uint8_t)data), [hi] "r" ((uint8_t)(data>>8))
:
);
} else {
for (;count > 0; count--)
SPI.transfer16(data);
}
}
/***************************************************************************************
** Function name: spiWait
** Descriptions: 17 cycle delay
***************************************************************************************/
static inline void spiWait17(void)
{
asm volatile
(
" rcall 1f \n" // 7
" rcall 1f \n" // 14
" rjmp 2f \n" // 16
"1: ret \n" //
"2: nop \n" // 17
);
}
/***************************************************************************************
** Function name: spiWait
** Descriptions: 15 cycle delay
***************************************************************************************/
static inline void spiWait15(void)
{
asm volatile
(
" adiw r24,0 \n" // 2
" adiw r24,0 \n" // 4
" adiw r24,0 \n" // 6
" rcall 1f \n" // 13
" rjmp 2f \n" // 15
"1: ret \n" //
"2: \n" //
);
}
/***************************************************************************************
** Function name: spiWait
** Descriptions: 14 cycle delay
***************************************************************************************/
static inline void spiWait14(void)
{
asm volatile
(
" nop \n" // 1
" adiw r24,0 \n" // 3
" adiw r24,0 \n" // 5
" rcall 1f \n" // 12
" rjmp 2f \n" // 14
"1: ret \n" //
"2: \n" //
);
}
/***************************************************************************************
** Function name: spiWait
** Descriptions: 12 cycle delay
***************************************************************************************/
static inline void spiWait12(void)
{
asm volatile
(
" nop \n" // 1
" adiw r24,0 \n" // 3
" rcall 1f \n" // 10
" rjmp 2f \n" // 12
"1: ret \n" //
"2: \n" //
);
}
/***************************************************************************************
** Function name: ILI9341Begin
** Descriptions: initialise ILI9341
***************************************************************************************/
void ILI9341Begin(uint8_t CS = 10, uint8_t CD = 8, uint8_t RST = 7, uint16_t w = 320, uint16_t h = 240, uint8_t Rotation = ILI9341_Rotation1) {
tft_CS = CS;
tft_DC = CD;
tft_RST = RST;
SPI.begin();
if (tft_RST > 0) {
digitalWrite(tft_RST, LOW);
pinMode(tft_RST, OUTPUT);
}
digitalWrite(tft_DC, HIGH);
pinMode(tft_DC, OUTPUT);
digitalWrite(tft_CS, HIGH);
pinMode(tft_CS, OUTPUT);
tft_width = w;
tft_height = h;
Cursory = Cursorx = 0;
addr_row = 0xFFFF;
addr_col = 0xFFFF;
win_xe = 0xFFFF;
win_ye = 0xFFFF;
SPI.setClockDivider(SPI_CLOCK_DIV2); // 8 MHz (full! speed!)
SPI.setBitOrder(MSBFIRST);
SPI.setDataMode(SPI_MODE0);
mySPCR = SPCR;
// toggle RST low to reset
if (tft_RST > 0) {
digitalWrite(tft_RST, HIGH);
delay(5);
digitalWrite(tft_RST, LOW);
delay(20);
digitalWrite(tft_RST, HIGH);
delay(150);
}
if (tft_RST <= 0) {
spi_begin();
tft_writecommand(ILI9341_SWRESET);
delay(10);
spi_end();
};
// Initialization commands for ILI9341 screens
static const uint8_t ILI9341_cmds[] PROGMEM =
{
21, /* num commands */
0xEF, /* */ 3, 0x03, 0x80, 0x02,
0xCF, /* */ 3, 0x00, 0xC1, 0x30,
0xED, /* */ 4, 0x64, 0x03, 0x12, 0x81,
0xE8, /* */ 3, 0x85, 0x00, 0x78,
0xCB, /* */ 5, 0x39, 0x2C, 0x00, 0x34, 0x02,
0xF7, /* */ 1, 0x20,
0xEA, /* */ 2, 0x00, 0x00,
ILI9341_PWCTR1, /* power control */ 1, 0x23, // VRH[5:0]
ILI9341_PWCTR2, /* power control */ 1, 0x10, // SAP[2:0];BT[3:0]
ILI9341_VMCTR1, /* VCM control */ 2, 0x3e, 0x28,
ILI9341_VMCTR2, /* VCM control2 */ 1, 0x86, // --
ILI9341_MADCTL, /* */ 1, (ILI9341_MADCTL_MX | ILI9341_MADCTL_BGR),
ILI9341_PIXFMT, /* */ 1, 0x55,
ILI9341_FRMCTR1, /* */ 2, 0x00, 0x18,
ILI9341_DFUNCTR, /* */ 3, 0x08, 0x82, 0x27,
0xF2, /* 3Gamma Function Disable */ 1, 0x00,
ILI9341_GAMMASET, /* Gamma curve selected */ 1, 0x01,
ILI9341_GMCTRP1, /* Set Gamma */ 15,0x0F, 0x31, 0x2B, 0x0C, 0x0E, 0x08, 0x4E, 0xF1, 0x37, 0x07, 0x10, 0x03, 0x0E, 0x09, 0x00,
ILI9341_GMCTRN1, /* */ 15,0x00, 0x0E, 0x14, 0x03, 0x11, 0x07, 0x31, 0xC1, 0x48, 0x08, 0x0F, 0x0C, 0x31, 0x36, 0x0F,
ILI9341_SLPOUT, /* */ ILI9341_INIT_DELAY, 120,
ILI9341_DISPON, /* */ 0,
};
tft_commandList(ILI9341_cmds);
spi_begin();
tft_writecommand(ILI9341_MADCTL);
tft_writedata(Rotation);
spi_end();
}
void ILI9341SetCursor(uint16_t x, uint16_t y) {
tft_setCursor(x, y);
}
void ClearDisplay(uint16_t color) {
DrawBox(0, 0, tft_width, tft_height, color);
}
void DrawLine(uint16_t x1, uint16_t y1, uint16_t x2, uint16_t y2, uint16_t color) {
int tmp, x, y, dx, dy, err, ystep, swapxy;
swapxy = 0;
if (x1 > x2) dx = x1 - x2;
else dx = x2 - x1;
if (y1 > y2) dy = y1 - y2;
else dy = y2 - y1;
if (dy > dx) {
swapxy = 1;
tmp = dx;
dx = dy;
dy = tmp;
tmp = x1;
x1 = y1;
y1 = tmp;
tmp = x2;
x2 = y2;
y2 = tmp;
}
if ((x1 > x2)) {
tmp = x1;
x1 = x2;
x2 = tmp;
tmp = y1;
y1 = y2;
y2 = tmp;
}
err = dx >> 1;
if ((y2 > y1)) ystep = 1;
else ystep = -1;
y = y1;
for (x = x1; x <= x2; x++) {
if (pen_width > 1) {
if ((swapxy == 0))
DrawDisc(x, y, pen_width-1, color);
else
DrawDisc(y, x, pen_width-1, color);
} else{
if ((swapxy == 0)) {
DrawPixel(x, y, color);
} else {
DrawPixel(y, x, color);
}
}
err -= dy;
if (err < 0) {
y += ystep;
err += dx;
}
}
}
void DrawFrame(uint16_t x, uint16_t y, uint16_t w, uint16_t h, uint16_t color) {
DrawHLine(x, y, w, color);
DrawHLine(x, y + h - 1, w, color);
DrawVLine(x, y, h, color);
DrawVLine(x + w - 1, y, h, color);
}
void DrawCircle(uint16_t x0, uint16_t y0, uint16_t rad, uint16_t color) {
DrawEllipse(x0, y0, rad, rad, color);
}
void DrawDisc(uint16_t x0, uint16_t y0, uint16_t rad, uint16_t color) {
DrawFilledEllipse(x0, y0, rad, rad, color);
}
void DrawFilledEllipse(int x0, int y0, int rx, int ry, uint16_t color) {
// the overall width is rad*2+1
if (rx < 1) return;
if (ry < 1) return;
int16_t x, y;
int32_t rx2 = rx * rx;
int32_t ry2 = ry * ry;
int32_t fx2 = 4 * rx2;
int32_t fy2 = 4 * ry2;
int32_t s;
for (x = 0, y = ry, s = 2*ry2+rx2*(1-2*ry); ry2*x <= rx2*y; x++)
{
DrawHLineSingle(x0 - x, y0 - y, x + x + 1, color);
DrawHLineSingle(x0 - x, y0 + y, x + x + 1, color);
if (s >= 0)
{
s += fx2 * (1 - y);
y--;
}
s += ry2 * ((4 * x) + 6);
}
for (x = rx, y = 0, s = 2*rx2+ry2*(1-2*rx); rx2*y <= ry2*x; y++)
{
DrawHLineSingle(x0 - x, y0 - y, x + x + 1, color);
DrawHLineSingle(x0 - x, y0 + y, x + x + 1, color);
if (s >= 0)
{
s += fy2 * (1 - x);
x--;
}
s += rx2 * ((4 * y) + 6);
}
}
void DrawEllipse(int x0, int y0, int rx, int ry, uint16_t color) {
if (rx<2) return;
if (ry<2) return;
int16_t x, y;
int32_t rx2 = rx * rx;
int32_t ry2 = ry * ry;
int32_t fx2 = 4 * rx2;
int32_t fy2 = 4 * ry2;
int32_t s;
tft_fastSetup();
for (x = 0, y = ry, s = 2*ry2+rx2*(1-2*ry); ry2*x <= rx2*y; x++)
{
tft_fastPixel(x0 + x, y0 + y, color);
tft_fastPixel(x0 - x, y0 + y, color);
tft_fastPixel(x0 - x, y0 - y, color);
tft_fastPixel(x0 + x, y0 - y, color);
if (s >= 0)
{
s += fx2 * (1 - y);
y--;
}
s += ry2 * ((4 * x) + 6);
}
for (x = rx, y = 0, s = 2*rx2+ry2*(1-2*rx); rx2*y <= ry2*x; y++)
{
tft_fastPixel(x0 + x, y0 + y, color);
tft_fastPixel(x0 - x, y0 + y, color);
tft_fastPixel(x0 - x, y0 - y, color);
tft_fastPixel(x0 + x, y0 - y, color);
if (s >= 0)
{
s += fy2 * (1 - x);
x--;
}
s += rx2 * ((4 * y) + 6);
}
}
static void swap(uint16_t *a, uint16_t *b) {
uint16_t c;
c = *a;
*a = *b;
*b = c;
}
void DrawTriangle(uint16_t x0, uint16_t y0, uint16_t x1, uint16_t y1, uint16_t x2, uint16_t y2, uint16_t color) {
int16_t a, b, y, last;
// Sort coordinates by Y order (y2 >= y1 >= y0)
if (y0 > y1) {
swap(&y0, &y1); swap(&x0, &x1);
}
if (y1 > y2) {
swap(&y2, &y1); swap(&x2, &x1);
}
if (y0 > y1) {
swap(&y0, &y1); swap(&x0, &x1);
}
if (y0 == y2) { // Handle awkward all-on-same-line case as its own thing
a = b = x0;
if (x1 < a) a = x1;
else if (x1 > b) b = x1;
if (x2 < a) a = x2;
else if (x2 > b) b = x2;
DrawHLineSingle(a, y0, b - a + 1, color);
return;
}
int16_t
dx01 = x1 - x0,
dy01 = y1 - y0,
dx02 = x2 - x0,
dy02 = y2 - y0,
dx12 = x2 - x1,
dy12 = y2 - y1,
sa = 0,
sb = 0;
// For upper part of triangle, find scanline crossings for segments
// 0-1 and 0-2. If y1=y2 (flat-bottomed triangle), the scanline y1
// is included here (and second loop will be skipped, avoiding a /0
// error there), otherwise scanline y1 is skipped here and handled
// in the second loop...which also avoids a /0 error here if y0=y1
// (flat-topped triangle).
if (y1 == y2) last = y1; // Include y1 scanline
else last = y1 - 1; // Skip it
for (y = y0; y <= last; y++) {
a = x0 + sa / dy01;
b = x0 + sb / dy02;
sa += dx01;
sb += dx02;
if (a > b) swap(&a, &b);
DrawHLineSingle(a, y, b - a + 1, color);
}
// For lower part of triangle, find scanline crossings for segments
// 0-2 and 1-2. This loop is skipped if y1=y2.
sa = dx12 * (y - y1);
sb = dx02 * (y - y0);
for (; y <= y2; y++) {
a = x1 + sa / dy12;
b = x0 + sb / dy02;
sa += dx12;
sb += dx02;
if (a > b) swap(&a, &b);
DrawHLineSingle(a, y, b - a + 1, color);
}
}
void DrawChar(uint8_t c, word Font, uint16_t color) {
word n, j, px;
byte ymax, desc;
unsigned long b,d;
ymax = pgm_read_byte_near(Font);
Font++;
desc = pgm_read_byte_near(Font);
Font++;
j = pgm_read_byte_near(Font); // first char
Font++;
if (c < j) return;
while (c > j) {
b = pgm_read_byte_near(Font);
if (b == 0)
return;
if (ymax > 15)
Font += b * 3 + 1;
else if (ymax > 7)
Font += b * 2 + 1;
else
Font += b + 1;
c--;
}
px = Cursorx;
n = pgm_read_byte_near(Font);
Font++;
while (n > 0) {
b = pgm_read_byte_near(Font);
b &= 0xFF;
Font++;
if (ymax > 7) {
d = pgm_read_byte_near(Font);
d &= 0xFF;
b |= d << 8;
Font++;
}
if (ymax > 15) {
d = pgm_read_byte_near(Font);
d &= 0xFF;
b |= d << 16;
Font++;
}
if (execDrawChar) {
for (j = 0; j <= ymax; j++) {
if (b & 1)
DrawPixel(Cursorx, Cursory + desc - j, color);
b = b >> 1;
}
}
Cursorx++;
n--;
}
Cursorx += letter_gap;
}
void DrawString(char * s, word Font, uint16_t color) {
for (char * t = s; * t; t++) {
DrawChar( * t, Font, color);
}
}
void DrawStringAt(int16_t x, int16_t y, char * s, word Font, uint16_t color) {
ILI9341SetCursor(x, y);
DrawString(s, Font, color);
}
void DrawInt(int i, word Font, uint16_t color) {
if (i < 0) {
i=-i;
DrawChar('-',Font, color);
}
bool HasDigit = false;
int n = 10000;
if (i == 0) {
DrawChar('0',Font, color);
} else {
while (n > 0) {
if ((i >= n) or HasDigit) {
DrawChar('0' + (i / n),Font, color);
HasDigit = true;
}
i %= n;
n /= 10;
}
}
}
/***************************************************************************************
** Function name: rgb
** Description: convert three 8 bit RGB levels to a 16 bit colour value
***************************************************************************************/
uint16_t rgb(uint8_t r, uint8_t g, uint8_t b)
{
return ((r & 0xF8) << 8) | ((g & 0xFC) << 3) | (b >> 3);
}
/***************************************************************************************
** Function name: cmp_swap
** Description: if a > b then swap a and b
***************************************************************************************/
static inline void cmp_swap(int16_t *a, int16_t *b)
{
if (*a > *b) {
int16_t c = *a;
*a = *b;
*b = c;
}
}
/***************************************************************************************
** Function name: median_filter
** Description: return median value of five
***************************************************************************************/
static int median_filter(int16_t t[]) {
cmp_swap(&t[0],&t[4]);
cmp_swap(&t[2],&t[4]);
cmp_swap(&t[1],&t[3]);
cmp_swap(&t[0],&t[2]);
cmp_swap(&t[3],&t[4]);
cmp_swap(&t[1],&t[2]);
cmp_swap(&t[0],&t[3]);
cmp_swap(&t[2],&t[3]);
return t[2];
}
/***************************************************************************************
** Function name: GetTouch
** Description: get touch coordinates
** return true if touched
***************************************************************************************/
bool GetTouch(int *x, int *y) {
int16_t z,z1,z2,ax[5],ay[5];
//SPI.beginTransaction(SPISettings(2000000, MSBFIRST, SPI_MODE0));
SPI.beginTransaction(SPISettings(500000, MSBFIRST, SPI_MODE0));
digitalWrite(touch_CS, LOW);
delayMicroseconds(100);
// z = SPI.transfer(0xB1);
// z1 = SPI.transfer16(0xC1) >> 3;
// z2 = SPI.transfer16(0x91) >> 3;
z = SPI.transfer16(0xB4) >> 3;
z1 = SPI.transfer16(0xB4) >> 3;
z2 = SPI.transfer16(0xC4) >> 3;
SPI.transfer16(0x91); // switch on drivers
ax[0] = SPI.transfer16(0x91) >> 3;
ax[1] = SPI.transfer16(0x91) >> 3;
ax[2] = SPI.transfer16(0x91) >> 3;
ax[3] = SPI.transfer16(0x91) >> 3;
ax[4] = SPI.transfer16(0x91) >> 3;
SPI.transfer16(0xD1); // switch on drivers
ay[0] = SPI.transfer16(0xD1) >> 3;
ay[1] = SPI.transfer16(0xD1) >> 3;
ay[2] = SPI.transfer16(0xD1) >> 3;
ay[3] = SPI.transfer16(0xD1) >> 3;
ay[4] = SPI.transfer16(0xD1) >> 3;
// data[4] = SPI.transfer16(0xD0) >> 3; // Last Y touch power down
// data[5] = SPI.transfer16(0) >> 3;
SPI.transfer16(0); // power down
digitalWrite(touch_CS, HIGH);
delayMicroseconds(100);
SPI.endTransaction();
SPI.beginTransaction(SPISettings(8000000, MSBFIRST, SPI_MODE0));
SPI.endTransaction();
if (z1+z2 > 0x80) {
switch (touch_Rotation) {
case 1:
*x = round(long(touch_xmax-median_filter(ax))*tft_width / long(touch_xmax-touch_xmin));
*y = round(long(touch_ymax-median_filter(ay))*tft_height / long(touch_ymax-touch_ymin));
break;
case 2:
*x = round(long(touch_xmax-median_filter(ay))*tft_width / long(touch_xmax-touch_xmin));
*y = tft_height-round(long(touch_ymax-median_filter(ax))*tft_height / long(touch_ymax-touch_ymin));
break;
case 3:
*x = round(long(median_filter(ax)-touch_xmin)*tft_width / long(touch_xmax-touch_xmin));
*y = round(long(median_filter(ay)-touch_ymin)*tft_height / long(touch_ymax-touch_ymin));
break;
default:
*x = round(long(median_filter(ay)-touch_xmin)*tft_width / long(touch_xmax-touch_xmin));
*y = tft_height-round(long(median_filter(ax)-touch_ymin)*tft_height / long(touch_ymax-touch_ymin));
break;
}
return true;
} else {
*x = 0;
*y = 0;
return false;
}
}
/***************************************************************************************
** Function name: BeginTouch
** Descriptions: initialise ILI9341
***************************************************************************************/
void BeginTouch(uint8_t CS = 2, uint8_t Rotation = 1, int xmin = 320, int ymin = 320, int xmax = 3900, int ymax = 3900) {
int x,y;
touch_xmin = xmin;
touch_xmax = xmax;
touch_ymin = ymin;
touch_ymax = ymax;
touch_Rotation = Rotation % 4;
touch_CS = CS;
if (touch_CS > 0) {
pinMode(touch_CS, OUTPUT);
digitalWrite(touch_CS, LOW);
}
GetTouch(&x, &y);
}
Соседние файлы в предмете Электроника и схемотехника