Closed Donziboy2 closed 4 years ago
I updated the master branch to use the newer SPIN method call.
The function to get the kinetisk_spi object changed names.
I should be able to test it in the next week or 2, tackling my 18bit ADC and how to work it into code without getting in the way of other things.
Most of my saved examples use Async and framebuffer so they fall flat on their faces. The oldest test code I have that does not use Async also fails.
Here is the error I get and the test file I used.
Closing now as it is over 2 years old
Let me know if there is something that still should be looked at.
Managed to get the Async branch to compile with the Latest Teensyduino 1.39, Arduino IDE and SPIN that comes with 1.39. Compiler kept getting stuck on the 2 below calls in a few places. Not idea if it changes anything still trying to get dma working.
``// https://github.com/PaulStoffregen/ILI9341_t3n // http://forum.pjrc.com/threads/26305-Highly-optimized-ILI9341-(320x240-TFT-color-display)-library
/*** This is our library for the Adafruit ILI9341 Breakout and Shield ----> http://www.adafruit.com/products/1651
Check out the links above for our tutorials and wiring diagrams These displays use SPI to communicate, 4 or 5 pins are required to interface (RST is optional) Adafruit invests time and resources providing this open source code, please support Adafruit and open-source hardware by purchasing products from Adafruit!
Written by Limor Fried/Ladyada for Adafruit Industries. MIT license, all text above must be included in any redistribution ****/ //
//Additional graphics routines by Tim Trzepacz, SoftEgg LLC added December 2015 //(And then accidentally deleted and rewritten March 2016. Oops!) //Gradient support //---------------- // fillRectVGradient - fills area with vertical gradient // fillRectHGradient - fills area with horizontal gradient // fillScreenVGradient - fills screen with vertical gradient // fillScreenHGradient - fills screen with horizontal gradient
//Additional Color Support //------------------------ // color565toRGB - converts 565 format 16 bit color to RGB // color565toRGB14 - converts 16 bit 565 format color to 14 bit RGB (2 bits clear for math and sign) // RGB14tocolor565 - converts 14 bit RGB back to 16 bit 565 format color
//Low Memory Bitmap Support //------------------------- // writeRect8BPP - write 8 bit per pixel paletted bitmap // writeRect4BPP - write 4 bit per pixel paletted bitmap // writeRect2BPP - write 2 bit per pixel paletted bitmap // writeRect1BPP - write 1 bit per pixel paletted bitmap
//TODO: transparent bitmap writing routines for sprites
//String Pixel Length support //--------------------------- // strPixelLen - gets pixel length of given ASCII string
// <\SoftEgg>
include "ILI9341_t3n.h"
include
include
//#define DEBUG_ASYNC_UPDATE // Enable to print out dma info
ifdef ENABLE_ILI9341_FRAMEBUFFER
DMASetting ILI9341_t3n::_dmasettings[4]; DMAChannel ILI9341_t3n::_dmatx;
DMAChannel _dmatx; ILI9341_t3n *ILI9341_t3n::_dmaActiveDisplay = 0; volatile uint8_t ILI9341_t3n::_dma_state = 0; // Use pointer to this as a way to get back to object... volatile uint32_t ILI9341_t3n::_dma_frame_count = 0; // Can return a frame count...
void ILI9341_t3n::dmaInterrupt(void) { //Serial.println("DMA Interrupt"); /// digitalWriteFast(1,!digitalReadFast(1)); _dma_frame_count++; _dmatx.clearInterrupt();
}
endif
// Teensy 3.1 can only generate 30 MHz SPI when running at 120 MHz (overclock)
define WIDTH ILI9341_TFTWIDTH
define HEIGHT ILI9341_TFTHEIGHT
// Constructor when using hardware ILI9241_KINETISK__pspi-> Faster, but must use SPI pins // specific to each board type (e.g. 11,13 for Uno, 51,52 for Mega, etc.) ILI9341_t3n::ILI9341_t3n(uint8_t cs, uint8_t dc, uint8_t rst, uint8_t mosi, uint8_t sclk, uint8_t miso, SPINClass *pspin ) { _cs = cs; _dc = dc; _rst = rst; _mosi = mosi; _sclk = sclk; _miso = miso; _width = WIDTH; _height = HEIGHT; _pspin = pspin;
ifdef KINETISK
else
endif
}
//======================================================================= // Add optinal support for using frame buffer to speed up complex outputs //=======================================================================
define CBALLOC (ILI9341_TFTHEIGHTILI9341_TFTWIDTH2)
void ILI9341_t3n::setFrameBuffer(uint16_t *frame_buffer) {
ifdef ENABLE_ILI9341_FRAMEBUFFER
}
uint8_t ILI9341_t3n::useFrameBuffer(boolean b) // use the frame buffer? First call will allocate {
ifdef ENABLE_ILI9341_FRAMEBUFFER
}
void ILI9341_t3n::freeFrameBuffer(void) // explicit call to release the buffer {
ifdef ENABLE_ILI9341_FRAMEBUFFER
} void ILI9341_t3n::updateScreen(void) // call to say update the screen now. { // Not sure if better here to check flag or check existence of buffer. // Will go by buffer as maybe can do interesting things?
ifdef ENABLE_ILI9341_FRAMEBUFFER
}
ifdef DEBUG_ASYNC_UPDATE
void dumpDMA_TCD(DMABaseClass *dmabc) { Serial.printf("%x %x:", (uint32_t)dmabc, (uint32_t)dmabc->TCD);
}
endif
void ILI9341_t3n::initDMASettings(void) { // Serial.printf("initDMASettings called %d\n", ili9341_t3n_dma_has_been_init); if (_dma_state) { // should test for init, but... return; // we already init this. }
// uint16_t *fbtft_start_dma_addr = _pfbtft; uint32_t count_words_write = (CBALLOC/SCREEN_DMA_NUM_SETTINGS)/2; // Note I know the divide will give whole number
}
bool ILI9341_t3n::updateScreenAsync(bool update_cont) // call to say update the screen now. { // Not sure if better here to check flag or check existence of buffer. // Will go by buffer as maybe can do interesting things? // BUGBUG:: only handles full screen so bail on the rest of it...
ifdef ENABLE_ILI9341_FRAMEBUFFER
ifdef DEBUG_ASYNC_UPDATE
endif
// volatile uint16_t biter = _dmatx.TCD->BITER; //DMA_CDNE_CDNE(_dmatx.channel); // _dmatx = _dmasettings[0]; // _dmatx.TCD->BITER = biter; _dma_frame_count = 0; // Set frame count back to zero. _pkinetisk_spi->RSER |= SPI_RSER_TFFF_DIRS | SPI_RSER_TFFF_RE; // Set DMA Interrupt Request Select and Enable register _pkinetisk_spi->MCR &= ~SPI_MCR_HALT; //Start transfers. _dmatx.enable(); _dmaActiveDisplay = this; _dma_state |= ILI9341_DMA_ACTIVE; return true;
else
}
void ILI9341_t3n::endUpdateAsync() { // make sure it is on
ifdef ENABLE_ILI9341_FRAMEBUFFER
}
void ILI9341_t3n::waitUpdateAsyncComplete(void) {
ifdef ENABLE_ILI9341_FRAMEBUFFER
}
//=======================================================================
void ILI9341_t3n::setAddrWindow(uint16_t x0, uint16_t y0, uint16_t x1, uint16_t y1) { beginSPITransaction(); setAddr(x0, y0, x1, y1); writecommand_last(ILI9341_RAMWR); // write to RAM endSPITransaction(); }
void ILI9341_t3n::pushColor(uint16_t color) { beginSPITransaction(); writedata16_last(color); endSPITransaction(); }
void ILI9341_t3n::drawPixel(int16_t x, int16_t y, uint16_t color) { x += _originx; y += _originy; if((x < _displayclipx1) ||(x >= _displayclipx2) || (y < _displayclipy1) || (y >= _displayclipy2)) return;
}
void ILI9341_t3n::drawFastVLine(int16_t x, int16_t y, int16_t h, uint16_t color) { x+=_originx; y+=_originy; // Rectangular clipping if((x < _displayclipx1) || (x >= _displayclipx2) || (y >= _displayclipy2)) return; if(y < _displayclipy1) { h = h - (_displayclipy1 - y); y = _displayclipy1;} if((y+h-1) >= _displayclipy2) h = _displayclipy2-y; if(h<1) return;
}
void ILI9341_t3n::drawFastHLine(int16_t x, int16_t y, int16_t w, uint16_t color) { x+=_originx; y+=_originy;
}
void ILI9341_t3n::fillScreen(uint16_t color) {
ifdef ENABLE_ILI9341_FRAMEBUFFER
}
// fill a rectangle void ILI9341_t3n::fillRect(int16_t x, int16_t y, int16_t w, int16_t h, uint16_t color) { x+=_originx; y+=_originy;
}
// fillRectVGradient - fills area with vertical gradient void ILI9341_t3n::fillRectVGradient(int16_t x, int16_t y, int16_t w, int16_t h, uint16_t color1, uint16_t color2) { x+=_originx; y+=_originy;
}
// fillRectHGradient - fills area with horizontal gradient void ILI9341_t3n::fillRectHGradient(int16_t x, int16_t y, int16_t w, int16_t h, uint16_t color1, uint16_t color2) { x+=_originx; y+=_originy;
}
// fillScreenVGradient - fills screen with vertical gradient void ILI9341_t3n::fillScreenVGradient(uint16_t color1, uint16_t color2) { fillRectVGradient(0,0,_width,_height,color1,color2); }
// fillScreenHGradient - fills screen with horizontal gradient void ILI9341_t3n::fillScreenHGradient(uint16_t color1, uint16_t color2) { fillRectHGradient(0,0,_width,_height,color1,color2); }
define MADCTL_MY 0x80
define MADCTL_MX 0x40
define MADCTL_MV 0x20
define MADCTL_ML 0x10
define MADCTL_RGB 0x00
define MADCTL_BGR 0x08
define MADCTL_MH 0x04
void ILI9341_t3n::setRotation(uint8_t m) { rotation = m % 4; // can't be higher than 3 beginSPITransaction(); writecommand_cont(ILI9341_MADCTL); switch (rotation) { case 0: writedata8_last(MADCTL_MX | MADCTL_BGR); _width = ILI9341_TFTWIDTH; _height = ILI9341_TFTHEIGHT; break; case 1: writedata8_last(MADCTL_MV | MADCTL_BGR); _width = ILI9341_TFTHEIGHT; _height = ILI9341_TFTWIDTH; break; case 2: writedata8_last(MADCTL_MY | MADCTL_BGR); _width = ILI9341_TFTWIDTH; _height = ILI9341_TFTHEIGHT; break; case 3: writedata8_last(MADCTL_MX | MADCTL_MY | MADCTL_MV | MADCTL_BGR); _width = ILI9341_TFTHEIGHT; _height = ILI9341_TFTWIDTH; break; } endSPITransaction(); setClipRect(); setOrigin();
}
void ILI9341_t3n::setScroll(uint16_t offset) { beginSPITransaction(); writecommand_cont(ILI9341_VSCRSADD); writedata16_last(offset); endSPITransaction(); }
void ILI9341_t3n::invertDisplay(boolean i) { beginSPITransaction(); writecommand_last(i ? ILI9341_INVON : ILI9341_INVOFF); endSPITransaction(); }
/* uint8_t ILI9341_t3n::readdata(void) { uint8_t r; // Try to work directly with SPI registers... // First wait until output queue is empty uint16_t wTimeout = 0xffff; while (((_pkinetisk_spi->SR) & (15 << 12)) && (--wTimeout)) ; // wait until empty
// _pkinetisk_spi->MCR |= SPI_MCR_CLR_RXF; // discard any received data // _pkinetisk_spi->SR = SPI_SR_TCF;
} */
uint8_t ILI9341_t3n::readcommand8(uint8_t c, uint8_t index) { // Bail if not valid miso if (_miso == 0xff) return 0;
ifdef KINETISK
else
endif
}
// Read Pixel at x,y and get back 16-bit packed color
define READ_PIXEL_PUSH_BYTE 0x3f
uint16_t ILI9341_t3n::readPixel(int16_t x, int16_t y) {
ifdef KINETISK
if (_miso == 0xff) return 0xffff; // bail if not valid miso
else
endif
}
// Now lets see if we can read in multiple pixels
ifdef KINETISK
void ILI9341_t3n::readRect(int16_t x, int16_t y, int16_t w, int16_t h, uint16_t *pcolors) { // Use our Origin. x+=_originx; y+=_originy; //BUGBUG:: Should add some validation of X and Y
if (_miso == 0xff) return; // bail if not valid miso
}
else
// Teensy LC version void ILI9341_t3n::readRect(int16_t x, int16_t y, int16_t w, int16_t h, uint16_t *pcolors) { // Use our Origin. x+=_originx; y+=_originy; //BUGBUG:: Should add some validation of X and Y
if (_miso == 0xff) return; // bail if not valid miso
define RRECT_TIMEOUT 0xffff
undef READ_PIXEL_PUSH_BYTE
define READ_PIXEL_PUSH_BYTE 0 // try with zero to see...
/ if (timeout_countdown == 0) { Serial.print("RRect Timeout "); Serial.println(rxCount, DEC); } / endSPITransaction(); }
endif
// Now lets see if we can writemultiple pixels void ILI9341_t3n::writeRect(int16_t x, int16_t y, int16_t w, int16_t h, const uint16_t *pcolors) {
}
// writeRect8BPP - write 8 bit per pixel paletted bitmap // bitmap data in array at pixels, one byte per pixel // color palette data in array at palette void ILI9341_t3n::writeRect8BPP(int16_t x, int16_t y, int16_t w, int16_t h, const uint8_t pixels, const uint16_t palette ) { //Serial.printf("\nWR8: %d %d %d %d %x\n", x, y, w, h, (uint32_t)pixels); x+=_originx; y+=_originy;
}
// writeRect4BPP - write 4 bit per pixel paletted bitmap // bitmap data in array at pixels, 4 bits per pixel // color palette data in array at palette // width must be at least 2 pixels void ILI9341_t3n::writeRect4BPP(int16_t x, int16_t y, int16_t w, int16_t h, const uint8_t pixels, const uint16_t palette ) { // Simply call through our helper writeRectNBPP(x, y, w, h, 4, pixels, palette ); }
// writeRect2BPP - write 2 bit per pixel paletted bitmap // bitmap data in array at pixels, 4 bits per pixel // color palette data in array at palette // width must be at least 4 pixels void ILI9341_t3n::writeRect2BPP(int16_t x, int16_t y, int16_t w, int16_t h, const uint8_t pixels, const uint16_t palette ) { // Simply call through our helper writeRectNBPP(x, y, w, h, 2, pixels, palette );
}
///============================================================================ // writeRect1BPP - write 1 bit per pixel paletted bitmap // bitmap data in array at pixels, 4 bits per pixel // color palette data in array at palette // width must be at least 8 pixels void ILI9341_t3n::writeRect1BPP(int16_t x, int16_t y, int16_t w, int16_t h, const uint8_t pixels, const uint16_t palette ) { // Simply call through our helper writeRectNBPP(x, y, w, h, 1, pixels, palette ); }
///============================================================================ // writeRectNBPP - write N(1, 2, 4, 8) bit per pixel paletted bitmap // bitmap data in array at pixels // Currently writeRect1BPP, writeRect2BPP, writeRect4BPP use this to do all of the work. void ILI9341_t3n::writeRectNBPP(int16_t x, int16_t y, int16_t w, int16_t h, uint8_t bits_per_pixel, const uint8_t pixels, const uint16_t palette ) { //Serial.printf("\nWR8: %d %d %d %d %x\n", x, y, w, h, (uint32_t)pixels); x+=_originx; y+=_originy; uint8_t pixels_per_byte = 8/ bits_per_pixel; uint16_t count_of_bytes_per_row = (w + pixels_per_byte -1)/pixels_per_byte; // Round up to handle non multiples uint8_t row_shift_init = 8 - bits_per_pixel; // We shift down 6 bits by default uint8_t pixel_bit_mask = (1 << bits_per_pixel) - 1; // get mask to use below // Rectangular clipping
}
static const uint8_t init_commands[] = { 4, 0xEF, 0x03, 0x80, 0x02, 4, 0xCF, 0x00, 0XC1, 0X30, 5, 0xED, 0x64, 0x03, 0X12, 0X81, 4, 0xE8, 0x85, 0x00, 0x78, 6, 0xCB, 0x39, 0x2C, 0x00, 0x34, 0x02, 2, 0xF7, 0x20, 3, 0xEA, 0x00, 0x00, 2, ILI9341_PWCTR1, 0x23, // Power control 2, ILI9341_PWCTR2, 0x10, // Power control 3, ILI9341_VMCTR1, 0x3e, 0x28, // VCM control 2, ILI9341_VMCTR2, 0x86, // VCM control2 2, ILI9341_MADCTL, 0x48, // Memory Access Control 2, ILI9341_PIXFMT, 0x55, 3, ILI9341_FRMCTR1, 0x00, 0x18, 4, ILI9341_DFUNCTR, 0x08, 0x82, 0x27, // Display Function Control 2, 0xF2, 0x00, // Gamma Function Disable 2, ILI9341_GAMMASET, 0x01, // Gamma curve selected 16, ILI9341_GMCTRP1, 0x0F, 0x31, 0x2B, 0x0C, 0x0E, 0x08, 0x4E, 0xF1, 0x37, 0x07, 0x10, 0x03, 0x0E, 0x09, 0x00, // Set Gamma 16, ILI9341_GMCTRN1, 0x00, 0x0E, 0x14, 0x03, 0x11, 0x07, 0x31, 0xC1, 0x48, 0x08, 0x0F, 0x0C, 0x31, 0x36, 0x0F, // Set Gamma 0 };
void ILI9341_t3n::begin(void) { // verify SPI pins are valid; // allow user to say use current ones...
ifdef DEBUG_ASYNC_UPDATE
endif
ifdef KINETISK
else
endif
ifdef KINETISK
else
endif
/ uint8_t x = readcommand8(ILI9341_RDMODE); Serial.print("\nDisplay Power Mode: 0x"); Serial.println(x, HEX); x = readcommand8(ILI9341_RDMADCTL); Serial.print("\nMADCTL Mode: 0x"); Serial.println(x, HEX); x = readcommand8(ILI9341_RDPIXFMT); Serial.print("\nPixel Format: 0x"); Serial.println(x, HEX); x = readcommand8(ILI9341_RDIMGFMT); Serial.print("\nImage Format: 0x"); Serial.println(x, HEX); x = readcommand8(ILI9341_RDSELFDIAG); Serial.print("\nSelf Diagnostic: 0x"); Serial.println(x, HEX); /
beginSPITransaction(); const uint8_t addr = init_commands; while (1) { uint8_t count = addr++; if (count-- == 0) break; writecommand_cont(addr++); while (count-- > 0) { writedata8_cont(addr++); } } writecommand_last(ILI9341_SLPOUT); // Exit Sleep endSPITransaction(); delay(120);
beginSPITransaction(); writecommand_last(ILI9341_DISPON); // Display on endSPITransaction(); }
/* This is the core graphics library for all our displays, providing a common set of graphics primitives (points, lines, circles, etc.). It needs to be paired with a hardware-specific library for each display device we carry (to handle the lower-level functions).
Adafruit invests time and resources providing this open source code, please support Adafruit & open-source hardware by purchasing products from Adafruit!
Copyright (c) 2013 Adafruit Industries. All rights reserved.
Redistribution and use in source and binary forms, with or without modification, are permitted provided that the following conditions are met:
THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. */
//#include "glcdfont.c" extern "C" const unsigned char glcdfont[];
// Draw a circle outline void ILI9341_t3n::drawCircle(int16_t x0, int16_t y0, int16_t r, uint16_t color) { int16_t f = 1 - r; int16_t ddF_x = 1; int16_t ddF_y = -2 * r; int16_t x = 0; int16_t y = r;
drawPixel(x0 , y0+r, color); drawPixel(x0 , y0-r, color); drawPixel(x0+r, y0 , color); drawPixel(x0-r, y0 , color);
while (x<y) { if (f >= 0) { y--; ddF_y += 2; f += ddF_y; } x++; ddF_x += 2; f += ddF_x;
} }
void ILI9341_t3n::drawCircleHelper( int16_t x0, int16_t y0, int16_t r, uint8_t cornername, uint16_t color) { int16_t f = 1 - r; int16_t ddF_x = 1; int16_t ddF_y = -2 * r; int16_t x = 0; int16_t y = r;
while (x<y) { if (f >= 0) { y--; ddF_y += 2; f += ddF_y; } x++; ddF_x += 2; f += ddF_x; if (cornername & 0x4) { drawPixel(x0 + x, y0 + y, color); drawPixel(x0 + y, y0 + x, color); } if (cornername & 0x2) { drawPixel(x0 + x, y0 - y, color); drawPixel(x0 + y, y0 - x, color); } if (cornername & 0x8) { drawPixel(x0 - y, y0 + x, color); drawPixel(x0 - x, y0 + y, color); } if (cornername & 0x1) { drawPixel(x0 - y, y0 - x, color); drawPixel(x0 - x, y0 - y, color); } } }
void ILI9341_t3n::fillCircle(int16_t x0, int16_t y0, int16_t r, uint16_t color) { drawFastVLine(x0, y0-r, 2*r+1, color); fillCircleHelper(x0, y0, r, 3, 0, color); }
// Used to do circles and roundrects void ILI9341_t3n::fillCircleHelper(int16_t x0, int16_t y0, int16_t r, uint8_t cornername, int16_t delta, uint16_t color) {
int16_t f = 1 - r; int16_t ddF_x = 1; int16_t ddF_y = -2 * r; int16_t x = 0; int16_t y = r;
while (x<y) { if (f >= 0) { y--; ddF_y += 2; f += ddF_y; } x++; ddF_x += 2; f += ddF_x;
} }
// Bresenham's algorithm - thx wikpedia void ILI9341_t3n::drawLine(int16_t x0, int16_t y0, int16_t x1, int16_t y1, uint16_t color) { if (y0 == y1) { if (x1 > x0) { drawFastHLine(x0, y0, x1 - x0 + 1, color); } else if (x1 < x0) { drawFastHLine(x1, y0, x0 - x1 + 1, color); } else { drawPixel(x0, y0, color); } return; } else if (x0 == x1) { if (y1 > y0) { drawFastVLine(x0, y0, y1 - y0 + 1, color); } else { drawFastVLine(x0, y1, y0 - y1 + 1, color); } return; }
}
// Draw a rectangle void ILI9341_t3n::drawRect(int16_t x, int16_t y, int16_t w, int16_t h, uint16_t color) {
ifdef ENABLE_ILI9341_FRAMEBUFFER
}
// Draw a rounded rectangle void ILI9341_t3n::drawRoundRect(int16_t x, int16_t y, int16_t w, int16_t h, int16_t r, uint16_t color) { // smarter version drawFastHLine(x+r , y , w-2r, color); // Top drawFastHLine(x+r , y+h-1, w-2r, color); // Bottom drawFastVLine(x , y+r , h-2r, color); // Left drawFastVLine(x+w-1, y+r , h-2r, color); // Right // draw four corners drawCircleHelper(x+r , y+r , r, 1, color); drawCircleHelper(x+w-r-1, y+r , r, 2, color); drawCircleHelper(x+w-r-1, y+h-r-1, r, 4, color); drawCircleHelper(x+r , y+h-r-1, r, 8, color); }
// Fill a rounded rectangle void ILI9341_t3n::fillRoundRect(int16_t x, int16_t y, int16_t w, int16_t h, int16_t r, uint16_t color) { // smarter version fillRect(x+r, y, w-2*r, h, color);
// draw four corners fillCircleHelper(x+w-r-1, y+r, r, 1, h-2r-1, color); fillCircleHelper(x+r , y+r, r, 2, h-2r-1, color); }
// Draw a triangle void ILI9341_t3n::drawTriangle(int16_t x0, int16_t y0, int16_t x1, int16_t y1, int16_t x2, int16_t y2, uint16_t color) { drawLine(x0, y0, x1, y1, color); drawLine(x1, y1, x2, y2, color); drawLine(x2, y2, x0, y0, color); }
// Fill a triangle void ILI9341_t3n::fillTriangle ( int16_t x0, int16_t y0, int16_t x1, int16_t y1, int16_t x2, int16_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; drawFastHLine(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; / longhand: a = x0 + (x1 - x0) (y - y0) / (y1 - y0); b = x0 + (x2 - x0) (y - y0) / (y2 - y0); / if(a > b) swap(a,b); drawFastHLine(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; / longhand: a = x1 + (x2 - x1) (y - y1) / (y2 - y1); b = x0 + (x2 - x0) (y - y0) / (y2 - y0); / if(a > b) swap(a,b); drawFastHLine(a, y, b-a+1, color); } }
void ILI9341_t3n::drawBitmap(int16_t x, int16_t y, const uint8_t *bitmap, int16_t w, int16_t h, uint16_t color) {
int16_t i, j, byteWidth = (w + 7) / 8;
for(j=0; j<h; j++) { for(i=0; i<w; i++ ) { if(pgm_read_byte(bitmap + j * byteWidth + i / 8) & (128 >> (i & 7))) { drawPixel(x+i, y+j, color); } } } }
size_t ILI9341_t3n::write(uint8_t c) { if (font) { if (c == '\n') { cursor_y += font->line_space; // Fix linefeed. Added by T.T., SoftEgg cursor_x = 0; } else { drawFontChar(c); } } else { if (c == '\n') { cursor_y += textsize8; cursor_x = 0; } else if (c == '\r') { // skip em } else { drawChar(cursor_x, cursor_y, c, textcolor, textbgcolor, textsize); cursor_x += textsize6; if (wrap && (cursor_x > (_width - textsize6))) { cursor_y += textsize8; cursor_x = 0; } } } return 1; }
// Draw a character void ILI9341_t3n::drawChar(int16_t x, int16_t y, unsigned char c, uint16_t fgcolor, uint16_t bgcolor, uint8_t size) { if((x >= _width) || // Clip right (y >= _height) || // Clip bottom ((x + 6 size - 1) < 0) || // Clip left TODO: is this correct? ((y + 8 size - 1) < 0)) // Clip top TODO: is this correct? return;
}
static uint32_t fetchbit(const uint8_t *p, uint32_t index) { if (p[index >> 3] & (1 << (7 - (index & 7)))) return 1; return 0; }
static uint32_t fetchbits_unsigned(const uint8_t *p, uint32_t index, uint32_t required) { uint32_t val = 0; do { uint8_t b = p[index >> 3]; uint32_t avail = 8 - (index & 7); if (avail <= required) { val <<= avail; val |= b & ((1 << avail) - 1); index += avail; required -= avail; } else { b >>= avail - required; val <<= required; val |= b & ((1 << required) - 1); break; } } while (required); return val; }
static uint32_t fetchbits_signed(const uint8_t *p, uint32_t index, uint32_t required) { uint32_t val = fetchbits_unsigned(p, index, required); if (val & (1 << (required - 1))) { return (int32_t)val - (1 << required); } return (int32_t)val; }
void ILI9341_t3n::drawFontChar(unsigned int c) { uint32_t bitoffset; const uint8_t *data;
/* Serial.printf("drawFontChar(%c) %d\n", c, c); Serial.printf(" size = %d,%d\n", width, height); Serial.printf(" line space = %d\n", font->line_space); Serial.printf(" offset = %d,%d\n", xoffset, yoffset); Serial.printf(" delta = %d\n", delta); Serial.printf(" cursor = %d,%d\n", cursor_x, cursor_y); Serial.printf(" origin = %d,%d\n", origin_x, origin_y);
*/
ifdef ENABLE_ILI9341_FRAMEBUFFER
}
//strPixelLen - gets pixel length of given ASCII string int16_t ILI9341_t3n::strPixelLen(char str) { // //Serial.printf("strPixelLen %s\n", str); if (!str) return(0); uint16_t len=0, maxlen=0; while (str) { if (str=='\n') { if ( len > maxlen ) { maxlen=len; len=0; } } else { if (!font) { len+=textsize6; } else {
// //Serial.printf("char %c(%d)\n", c,c);
// uint32_t width = fetchbits_unsigned(data, 3, font->bits_width); // //Serial.printf(" width = %d\n", width); bitoffset = font->bits_width + 3; bitoffset += font->bits_height;
// int32_t xoffset = fetchbits_signed(data, bitoffset, font->bits_xoffset); // //Serial.printf(" xoffset = %d\n", xoffset); bitoffset += font->bits_xoffset; bitoffset += font->bits_yoffset;
// //Serial.printf(" delta = %d\n", delta);
// //Serial.printf(" len = %d\n", len); if ( len > maxlen ) { maxlen=len; // //Serial.printf(" maxlen = %d\n", maxlen); }
// //Serial.printf("Return maxlen = %d\n", maxlen); return( maxlen ); } void ILI9341_t3n::drawFontBits(bool opaque, uint32_t bits, uint32_t numbits, int32_t x, int32_t y, uint32_t repeat) { if (bits == 0) { if (opaque) { fillRect(x, y, numbits, repeat, textbgcolor); } } else { int32_t x1 = x; uint32_t n = numbits; int w; int bgw;
}
void ILI9341_t3n::setCursor(int16_t x, int16_t y) { if (x < 0) x = 0; else if (x >= _width) x = _width - 1; cursor_x = x; if (y < 0) y = 0; else if (y >= _height) y = _height - 1; cursor_y = y; } void ILI9341_t3n::getCursor(int16_t x, int16_t y) { x = cursor_x; y = cursor_y; }
void ILI9341_t3n::setTextSize(uint8_t s) { textsize = (s > 0) ? s : 1; }
uint8_t ILI9341_t3n::getTextSize() { return textsize; }
void ILI9341_t3n::setTextColor(uint16_t c) { // For 'transparent' background, we'll set the bg // to the same as fg instead of using a flag textcolor = textbgcolor = c; }
void ILI9341_t3n::setTextColor(uint16_t c, uint16_t b) { textcolor = c; textbgcolor = b; }
void ILI9341_t3n::setTextWrap(boolean w) { wrap = w; }
boolean ILI9341_t3n::getTextWrap() { return wrap; }
uint8_t ILI9341_t3n::getRotation(void) { return rotation; }
void ILI9341_t3n::sleep(bool enable) { beginSPITransaction(); if (enable) { writecommand_cont(ILI9341_DISPOFF);
writecommand_last(ILI9341_SLPIN);
endSPITransaction(); } else { writecommand_cont(ILI9341_DISPON); writecommand_last(ILI9341_SLPOUT); endSPITransaction(); delay(5); } }
void Adafruit_GFX_Button::initButton(ILI9341_t3n gfx, int16_t x, int16_t y, uint8_t w, uint8_t h, uint16_t outline, uint16_t fill, uint16_t textcolor, const char label, uint8_t textsize) { _x = x; _y = y; _w = w; _h = h; _outlinecolor = outline; _fillcolor = fill; _textcolor = textcolor; _textsize = textsize; _gfx = gfx; strncpy(_label, label, 9); _label[9] = 0; }
void Adafruit_GFX_Button::drawButton(bool inverted) { uint16_t fill, outline, text;
}
bool Adafruit_GFX_Button::contains(int16_t x, int16_t y) { if ((x < (_x - _w/2)) || (x > (_x + _w/2))) return false; if ((y < (_y - _h/2)) || (y > (_y + _h/2))) return false; return true; }
``